From 0c84dde85b0a5b89bf8fab402002ca1ac5f3f3a2 Mon Sep 17 00:00:00 2001 From: gongzhiyong Date: Thu, 30 Apr 2026 00:33:20 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20Heicode=20=E6=84=BF=E6=99=AF=E8=8C=83?= =?UTF-8?q?=E5=BC=8F=E3=80=81=E7=80=91=E5=B8=83/=E6=95=8F=E6=8D=B7?= =?UTF-8?q?=E5=AD=90=20Agnet=20=E8=A7=92=E8=89=B2=E4=B8=8E=E8=A7=84?= =?UTF-8?q?=E6=A8=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 docs/vision-heicode-full-stack-agentic-dev.md(完整范式与 W1-W9 / A1-A8 角色) - 新增根 README.md 与 .gitignore(排除 node_modules、target 等) Made-with: Cursor --- .gitignore | 31 + README.md | 32 + _all-in-one-upload/cc-haha/adapters/README.md | 87 + .../src-tauri/gen/schemas/acl-manifests.json | 1 + .../src-tauri/icons/Square30x30Logo.png | Bin 0 -> 1340 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 24100 bytes .../cc-haha/desktop/src-tauri/src/lib.rs | 1106 +++++ .../cc-haha/desktop/src-tauri/tauri.conf.json | 76 + .../cc-haha/desktop/src/api/skills.ts | 22 + .../cc-haha/desktop/src/api/websocket.test.ts | 92 + .../src/components/shared/UpdateChecker.tsx | 106 + .../src/components/tasks/DayOfWeekPicker.tsx | 57 + .../desktop/src/pages/ActiveSession.tsx | 219 + .../desktop/src/pages/ScheduledTasksList.tsx | 416 ++ .../cc-haha/desktop/src/stores/agentStore.ts | 45 + .../cc-haha/desktop/src/types/task.ts | 56 + .../.syncthing.12-agent-core-loop.png.tmp | Bin 0 -> 715131 bytes .../docs/agent/images/06-context-passing.png | Bin 0 -> 118908 bytes .../docs/channel/images/03-access-control.png | Bin 0 -> 560390 bytes .../cc-haha/docs/en/guide/faq.md | 34 + .../images/05-architecture-overview.png | Bin 0 -> 440671 bytes .../cc-haha/docs/guide/quick-start.md | 64 + .../images/desktop_ui/09_slash_command.png | Bin 0 -> 474485 bytes .../docs/images/im/feishu/03-dev-console.png | Bin 0 -> 233228 bytes .../docs/images/im/feishu/07-menu-clear.png | Bin 0 -> 130582 bytes .../docs/images/im/telegram/03-bot-token.png | Bin 0 -> 727105 bytes .../cc-haha/docs/images/logo-horizontal.png | Bin 0 -> 120093 bytes .../cc-haha/docs/memory/03-autodream.md | 316 ++ .../active_session/code.html | 288 ++ .../cc-haha/release-notes/v0.1.7.md | 35 + .../cc-haha/src/bridge/replBridgeHandle.ts | 36 + .../cc-haha/src/bridge/sessionRunner.ts | 550 +++ .../src/buddy/useBuddyNotification.tsx | 93 + .../cc-haha/src/commands/break-cache/index.js | 1 + .../cc-haha/src/commands/compact/index.ts | 15 + .../cc-haha/src/commands/diff/index.ts | 8 + .../cc-haha/src/commands/fast/fast.tsx | 269 ++ .../src/commands/install-github-app/index.ts | 13 + .../cc-haha/src/commands/login/index.ts | 14 + .../cc-haha/src/commands/mobile/index.ts | 11 + .../cc-haha/src/commands/passes/passes.tsx | 24 + .../src/commands/plugin/DiscoverPlugins.tsx | 781 +++ .../src/commands/plugin/unifiedTypes.ts | 34 + .../src/commands/remoteControlServer/index.ts | 34 + .../commands/rename/generateSessionName.ts | 67 + .../cc-haha/src/commands/rename/rename.ts | 87 + .../cc-haha/src/commands/skills/skills.tsx | 8 + .../cc-haha/src/commands/statusline.tsx | 24 + .../cc-haha/src/commands/subscribe-pr.ts | 34 + .../cc-haha/src/commands/tasks/tasks.tsx | 8 + .../commands/terminalSetup/terminalSetup.tsx | 531 +++ .../cc-haha/src/commands/upgrade/upgrade.tsx | 38 + .../cc-haha/src/commands/voice/index.ts | 20 + .../CustomSelect/select-input-option.tsx | 488 ++ .../CustomSelect/use-select-navigation.ts | 653 +++ .../src/components/DevChannelsDialog.tsx | 105 + .../cc-haha/src/components/LanguagePicker.tsx | 86 + .../LspRecommendationMenu.tsx | 88 + .../components/Spinner/teammateSelectHint.ts | 1 + .../components/Spinner/useShimmerAnimation.ts | 31 + .../new-agent-creation/CreateAgentWizard.tsx | 97 + .../wizard-steps/ConfirmStepWrapper.tsx | 74 + .../wizard-steps/MemoryStep.tsx | 113 + .../cc-haha/src/components/agents/types.ts | 27 + .../src/components/hooks/SelectHookMode.tsx | 112 + .../components/hooks/SelectMatcherMode.tsx | 144 + .../src/components/mcp/ElicitationDialog.tsx | 1169 +++++ .../src/components/mcp/McpParsingWarnings.tsx | 213 + .../cc-haha/src/components/mcp/index.ts | 9 + .../AssistantRedactedThinkingMessage.tsx | 31 + .../messages/UserCommandMessage.tsx | 108 + .../messages/UserTeammateMessage.tsx | 206 + .../BashPermissionRequest.tsx | 482 ++ .../useFilePermissionDialog.ts | 212 + .../FilesystemPermissionRequest.tsx | 115 + .../permissions/PermissionExplanation.tsx | 272 ++ .../permissions/rules/PermissionRuleInput.tsx | 138 + .../sandbox/SandboxDependenciesTab.tsx | 120 + .../src/components/scheduled-tasks/types.ts | 12 + .../shell/ExpandShellOutputContext.tsx | 36 + .../cc-haha/src/components/wizard/index.ts | 9 + .../cc-haha/src/constants/github-app.ts | 144 + .../cc-haha/src/context/voice.tsx | 88 + .../entrypoints/sdk/coreTypes.generated.ts | 3 + ...thing.usePromptsFromClaudeInChrome.tsx.tmp | Bin 0 -> 11623 bytes .../src/hooks/notifs/useSettingsErrors.tsx | 69 + .../hooks/notifs/useStartupNotification.ts | 41 + .../cc-haha/src/hooks/renderPlaceholder.ts | 51 + .../hooks/toolPermission/PermissionContext.ts | 388 ++ .../cc-haha/src/hooks/useCanUseTool.tsx | 204 + .../src/hooks/useClipboardImageHint.ts | 77 + .../cc-haha/src/hooks/useDiffData.ts | 110 + .../hooks/useExitOnCtrlCDWithKeybindings.ts | 24 + .../src/hooks/useIdeConnectionStatus.ts | 33 + .../cc-haha/src/hooks/useIssueFlagBanner.ts | 133 + .../src/hooks/usePluginRecommendationBase.tsx | 105 + .../cc-haha/src/hooks/useTerminalSize.ts | 15 + .../src/hooks/useUpdateNotification.ts | 34 + .../cc-haha/src/hooks/useVoiceEnabled.ts | 25 + .../cc-haha/src/ink/clearTerminal.ts | 74 + .../cc-haha/src/ink/components/RawAnsi.tsx | 57 + .../cc-haha/src/ink/events/dispatcher.ts | 233 + .../cc-haha/src/ink/events/terminal-event.ts | 107 + .../src/ink/hooks/use-terminal-title.ts | 31 + .../cc-haha/src/ink/layout/engine.ts | 6 + .../cc-haha/src/ink/measure-element.ts | 23 + .../cc-haha/src/ink/render-node-to-output.ts | 1462 ++++++ .../cc-haha/src/keybindings/shortcutFormat.ts | 63 + .../src/memdir/memoryShapeTelemetry.ts | 34 + .../src/migrations/resetProToOpusDefault.ts | 51 + .../cc-haha/src/query/transitions.ts | 34 + .../.syncthing.providers-real.test.ts.tmp | Bin 0 -> 8915 bytes .../server/__tests__/fixtures/mock-sdk-cli.ts | 274 ++ .../server/__tests__/scheduled-tasks.test.ts | 371 ++ .../cc-haha/src/server/api/agents.ts | 234 + .../cc-haha/src/server/index.ts | 271 ++ .../src/server/middleware/cors.test.ts | 20 + .../streaming/openaiChatStreamToAnthropic.ts | 542 +++ .../src/services/autoDream/autoDream.ts | 324 ++ .../cc-haha/src/services/autoDream/config.ts | 21 + .../src/services/compact/apiMicrocompact.ts | 153 + .../cc-haha/src/services/compact/compact.ts | 1705 +++++++ .../remoteManagedSettings/syncCacheState.ts | 96 + .../src/services/teamMemorySync/types.ts | 156 + .../src/services/tools/toolExecution.ts | 1745 +++++++ .../bundled/claude-api/go/claude-api.md | 2 + .../cc-haha/src/skills/bundled/remember.ts | 82 + .../cc-haha/src/tools/AgentTool/UI.tsx | 872 ++++ .../src/tools/AgentTool/forkSubagent.ts | 210 + .../cc-haha/src/tools/AgentTool/runAgent.ts | 973 ++++ .../src/tools/BashTool/bashPermissions.ts | 2621 +++++++++++ .../src/tools/BashTool/commentLabel.ts | 13 + .../src/tools/EnterPlanModeTool/UI.tsx | 33 + .../cc-haha/src/tools/MCPTool/UI.tsx | 403 ++ .../cc-haha/src/tools/NotebookEditTool/UI.tsx | 93 + .../OverflowTestTool/OverflowTestTool.ts | 34 + .../src/tools/PowerShellTool/clmTypes.ts | 211 + .../tools/PowerShellTool/commandSemantics.ts | 142 + .../destructiveCommandWarning.ts | 109 + .../PowerShellTool/powershellSecurity.ts | 1090 +++++ .../tools/SubscribePRTool/SubscribePRTool.ts | 34 + .../src/tools/TaskUpdateTool/constants.ts | 1 + .../tools/ToolSearchTool/ToolSearchTool.ts | 471 ++ .../cc-haha/src/types/statusLine.ts | 34 + .../cc-haha/src/utils/advisor.ts | 145 + .../cc-haha/src/utils/attachments.ts | 3993 ++++++++++++++++ .../cc-haha/src/utils/codeIndexing.ts | 206 + .../cc-haha/src/utils/configConstants.ts | 21 + .../cc-haha/src/utils/context.ts | 221 + .../cc-haha/src/utils/contextAnalysis.ts | 272 ++ .../cc-haha/src/utils/conversationRecovery.ts | 597 +++ .../cc-haha/src/utils/crypto.ts | 13 + _all-in-one-upload/cc-haha/src/utils/debug.ts | 268 ++ .../cc-haha/src/utils/directMemberMessage.ts | 69 + .../cc-haha/src/utils/errors.ts | 238 + .../cc-haha/src/utils/exampleCommands.ts | 184 + .../cc-haha/src/utils/forkedAgent.ts | 689 +++ .../cc-haha/src/utils/generatedFiles.ts | 136 + .../cc-haha/src/utils/gitSettings.ts | 18 + .../cc-haha/src/utils/headlessProfiler.ts | 178 + .../src/utils/hooks/fileChangedWatcher.ts | 191 + .../src/utils/hooks/hooksConfigManager.ts | 400 ++ .../cc-haha/src/utils/iTermBackup.ts | 73 + .../cc-haha/src/utils/model/deprecation.ts | 101 + .../cc-haha/src/utils/model/modelAllowlist.ts | 170 + .../cc-haha/src/utils/model/modelOptions.ts | 540 +++ .../cc-haha/src/utils/modifiers.ts | 40 + .../src/utils/nativeInstaller/download.ts | 523 +++ _all-in-one-upload/cc-haha/src/utils/pdf.ts | 300 ++ .../permissions/PermissionUpdateSchema.ts | 78 + .../src/utils/permissions/denialTracking.ts | 45 + .../utils/permissions/permissionsLoader.ts | 296 ++ .../src/utils/permissions/yoloClassifier.ts | 1495 ++++++ .../.syncthing.hintRecommendation.ts.tmp | Bin 0 -> 5431 bytes .../plugins/pluginInstallationHelpers.ts | 595 +++ .../cc-haha/src/utils/plugins/pluginPolicy.ts | 20 + .../processUserInput/processBashCommand.tsx | 140 + .../cc-haha/src/utils/queryHelpers.ts | 552 +++ .../utils/secureStorage/keychainPrefetch.ts | 116 + .../src/utils/sessionFileAccessHooks.ts | 250 + .../cc-haha/src/utils/settings/settings.ts | 1015 ++++ .../src/utils/shell/powershellDetection.ts | 107 + _all-in-one-upload/cc-haha/src/utils/sinks.ts | 16 + .../cc-haha/src/utils/staticRender.tsx | 116 + .../cc-haha/src/utils/subprocessEnv.ts | 99 + .../src/utils/swarm/backends/TmuxBackend.ts | 764 +++ .../cc-haha/src/utils/swarm/permissionSync.ts | 928 ++++ .../cc-haha/src/utils/windowsPaths.ts | 199 + .../src/vendor/computer-use-mcp/tools.ts | 706 +++ _all-in-one-upload/cc-haha/src/vim/types.ts | 199 + _all-in-one-upload/new-api/LICENSE | 661 +++ .../new-api/bin/migration_v0.3-v0.4.sql | 17 + .../new-api/common/endpoint_type.go | 45 + .../new-api/common/go-channel.go | 53 + _all-in-one-upload/new-api/common/str.go | 254 + .../new-api/common/system_monitor_windows.go | 50 + .../new-api/constant/context_key.go | 69 + .../controller/channel_affinity_cache.go | 88 + .../new-api/controller/codex_oauth.go | 247 + .../new-api/controller/custom_oauth.go | 584 +++ .../controller/subscription_payment_epay.go | 217 + .../new-api/docker-compose.local.yml | 4 + .../new-api/docs/images/aliyun.png | Bin 0 -> 5102 bytes _all-in-one-upload/new-api/dto/video.go | 47 + _all-in-one-upload/new-api/i18n/i18n.go | 231 + .../new-api/middleware/cache.go | 17 + .../new-api/middleware/distributor.go | 435 ++ .../new-api/middleware/kling_adapter.go | 52 + _all-in-one-upload/new-api/model/setup.go | 16 + .../new-api/model/user_cache.go | 239 + .../pkg/billingexpr/billingexpr_test.go | 1094 +++++ .../new-api/pkg/ionet/jsonutil.go | 96 + .../new-api/relay/channel/ali/constants.go | 14 + .../relay/channel/gemini/relay-gemini.go | 1725 +++++++ .../new-api/relay/channel/openai/constant.go | 76 + .../new-api/relay/channel/replicate/dto.go | 19 + .../relay/channel/task/hailuo/adaptor.go | 302 ++ .../relay/channel/task/suno/adaptor.go | 167 + .../relay/channel/task/vertex/adaptor.go | 424 ++ .../relay/channel/volcengine/constants.go | 19 + .../relay/channel/xinference/constant.go | 8 + .../relay/channel/zhipu_4v/relay-zhipu_v4.go | 60 + .../new-api/relay/helper/price.go | 308 ++ .../new-api/service/codex_oauth.go | 317 ++ _all-in-one-upload/new-api/service/quota.go | 544 +++ .../new-api/service/text_quota_test.go | 441 ++ .../new-api/service/violation_fee.go | 164 + .../setting/model_setting/claude_test.go | 60 + .../channel_affinity_setting.go | 121 + .../new-api/setting/payment_stripe.go | 8 + .../new-api/types/price_data.go | 42 + .../new-api/web/classic/package.json | 96 + .../src/components/common/logo/OIDCIcon.jsx | 57 + .../src/components/common/logo/WeChatIcon.jsx | 55 + .../src/components/layout/NoticeModal.jsx | 255 + .../components/playground/configStorage.js | 234 + .../components/settings/PersonalSetting.jsx | 668 +++ .../classic/src/components/setup/index.jsx | 29 + .../src/components/table/channels/index.jsx | 116 + .../channels/modals/EditChannelModal.jsx | 3951 ++++++++++++++++ .../model-deployments/DeploymentsTable.jsx | 247 + .../model-pricing/filter/PricingTags.jsx | 109 + .../modal/ModelDetailSideSheet.jsx | 132 + .../table/tokens/TokensDescription.jsx | 44 + .../table/usage-logs/UsageLogsColumnDefs.jsx | 936 ++++ .../table/users/UsersColumnDefs.jsx | 390 ++ .../users/modals/UserSubscriptionsModal.jsx | 433 ++ .../classic/src/components/topup/index.jsx | 1003 ++++ .../new-api/web/classic/src/helpers/data.js | 61 + .../new-api/web/classic/src/helpers/index.js | 32 + .../new-api/web/classic/src/helpers/quota.js | 47 + .../classic/src/helpers/statusCodeRules.js | 118 + .../src/hooks/channels/useChannelsData.jsx | 1257 +++++ .../src/hooks/common/useNotifications.js | 94 + .../hooks/common/useSecureVerification.jsx | 274 ++ .../src/hooks/common/useSidebarCollapsed.js | 43 + .../hooks/dashboard/useDashboardCharts.jsx | 628 +++ .../src/hooks/playground/useDataLoader.js | 95 + .../Setting/Dashboard/SettingsAPIInfo.jsx | 514 ++ .../Dashboard/SettingsDataDashboard.jsx | 170 + .../Payment/SettingsPaymentGateway.jsx | 185 + .../classic/src/pages/UserAgreement/index.jsx | 37 + .../components/data-table/bulk-actions.tsx | 212 + .../default/src/components/status-badge.tsx | 174 + .../default/src/components/ui/accordion.tsx | 65 + .../web/default/src/components/ui/drawer.tsx | 132 + .../default/src/components/ui/input-group.tsx | 169 + .../default/src/components/ui/separator.tsx | 25 + .../features/auth/hooks/use-auth-redirect.ts | 86 + .../auth/sign-up/components/sign-up-form.tsx | 412 ++ .../channels/components/channels-table.tsx | 449 ++ .../chat/hooks/use-active-chat-key.ts | 31 + .../src/features/dashboard/lib/text.ts | 16 + .../features/home/components/sections/cta.tsx | 65 + .../dialogs/vendor-mutate-dialog.tsx | 197 + .../models/components/models-dialogs.tsx | 74 + .../models/components/models-table.tsx | 326 ++ .../components/message-action-button.tsx | 51 + .../components/playground-input.tsx | 222 + .../components/dynamic-pricing-breakdown.tsx | 334 ++ .../default/src/features/pricing/lib/index.ts | 9 + .../components/tabs/account-bindings-tab.tsx | 407 ++ .../default/src/features/profile/constants.ts | 18 + .../web/default/src/features/profile/types.ts | 214 + .../src/features/redemption-codes/types.ts | 67 + .../dialogs/subscription-purchase-dialog.tsx | 304 ++ .../content/section-registry.tsx | 125 + .../general/channel-affinity/index.tsx | 696 +++ .../integrations/amount-discount-dialog.tsx | 198 + .../waffo-pancake-settings-section.tsx | 290 ++ .../models/global-settings-card.tsx | 395 ++ .../models/group-ratio-form.tsx | 278 ++ .../models/upstream-ratio-sync-helpers.ts | 84 + .../request-limits/rate-limit-dialog.tsx | 212 + .../web/default/src/hooks/use-countdown.ts | 56 + .../default/src/hooks/use-sidebar-config.ts | 273 ++ .../i18n/locales/_reports/_sync-report.json | 41 + .../new-api/web/default/src/lib/format.ts | 218 + .../default/src/lib/http-status-code-rules.ts | 118 + .../new-api/web/default/src/lib/vchart.ts | 4 + .../web/default/src/routes/(auth)/sign-in.tsx | 23 + .../default/src/routes/(auth)/user/reset.tsx | 17 + .../routes/_authenticated/dashboard/index.tsx | 11 + .../system-settings/content/$section.tsx | 21 + .../common/__tests__/message-buffer.test.ts | 84 + .../__tests__/attachment-limits.test.ts | 52 + cc-haha/adapters/common/http-client.ts | 146 + cc-haha/adapters/feishu/extract-payload.ts | 95 + .../fonts/material-symbols-outlined.woff2 | Bin 0 -> 1109584 bytes cc-haha/desktop/src-tauri/app-icon-macos.svg | 42 + .../icons/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2550 bytes cc-haha/desktop/src-tauri/src/lib.rs | 1106 +++++ .../src-tauri/windows-installer-hooks.nsh | 25 + cc-haha/desktop/src/api/agents.ts | 36 + cc-haha/desktop/src/api/websocket.test.ts | 92 + .../src/components/controls/ModelSelector.tsx | 420 ++ .../components/layout/StartupErrorView.tsx | 99 + .../desktop/src/components/shared/Spinner.tsx | 30 + .../components/shared/UpdateChecker.test.tsx | 65 + .../src/components/tasks/TaskRunsPanel.tsx | 195 + cc-haha/desktop/src/pages/McpSettings.tsx | 1024 ++++ cc-haha/desktop/src/pages/Settings.tsx | 1765 +++++++ cc-haha/desktop/src/stores/agentStore.ts | 45 + cc-haha/desktop/src/stores/mcpStore.ts | 169 + .../desktop/src/stores/sessionRuntimeStore.ts | 69 + cc-haha/desktop/src/theme/globals.css | 684 +++ cc-haha/desktop/src/types/session.ts | 27 + cc-haha/docs/agent/images/07-tool-pool.png | Bin 0 -> 1592815 bytes .../docs/en/agent/images/04-agent-teams.png | Bin 0 -> 105744 bytes cc-haha/docs/en/memory/03-autodream.md | 316 ++ .../docs/en/reference/project-structure.md | 22 + .../images/02-computer-use-security-gates.jpg | Bin 0 -> 535600 bytes cc-haha/docs/images/banner.png | Bin 0 -> 341486 bytes .../docs/images/desktop_ui/02_edit_code.png | Bin 0 -> 548303 bytes .../images/im/feishu/01-create-app-entry.png | Bin 0 -> 147517 bytes .../images/sponsors/shengsuanyun-logo.svg | 4 + cc-haha/docs/skills/02-implementation.md | 897 ++++ .../agent_teams/code.html | 294 ++ .../antique_codex/DESIGN.md | 90 + cc-haha/runtime/mac_helper.py | 775 +++ cc-haha/runtime/requirements.txt | 6 + cc-haha/src/bridge/sessionRunner.ts | 550 +++ cc-haha/src/cli/bg.ts | 34 + .../src/cli/transports/WorkerStateUploader.ts | 131 + cc-haha/src/commands/add-dir/add-dir.tsx | 126 + cc-haha/src/commands/agents-platform/index.ts | 34 + .../src/commands/backfill-sessions/index.js | 1 + cc-haha/src/commands/chrome/chrome.tsx | 285 ++ .../src/commands/extra-usage/extra-usage.tsx | 17 + cc-haha/src/commands/good-claude/index.js | 1 + .../ExistingWorkflowStep.tsx | 103 + cc-haha/src/commands/model/index.ts | 16 + .../commands/output-style/output-style.tsx | 7 + .../privacy-settings/privacy-settings.tsx | 58 + .../commands/release-notes/release-notes.ts | 50 + cc-haha/src/commands/summary/index.js | 1 + cc-haha/src/commands/tasks/index.ts | 11 + .../.syncthing.InvalidConfigDialog.tsx.tmp | Bin 0 -> 15252 bytes .../src/components/AntModelSwitchCallout.ts | 34 + cc-haha/src/components/BridgeDialog.tsx | 401 ++ .../src/components/ChannelDowngradeDialog.tsx | 102 + cc-haha/src/components/CtrlOToExpand.tsx | 51 + .../components/CustomSelect/SelectMulti.tsx | 213 + .../CustomSelect/select-input-option.tsx | 488 ++ cc-haha/src/components/DevChannelsDialog.tsx | 105 + cc-haha/src/components/DiagnosticsDisplay.tsx | 95 + .../components/FileEditToolUpdatedMessage.tsx | 124 + .../src/components/InvalidSettingsDialog.tsx | 89 + .../components/LogoV2/AnimatedAsterisk.tsx | 50 + cc-haha/src/components/Markdown.tsx | 236 + cc-haha/src/components/Message.tsx | 627 +++ .../components/PromptInput/useSwarmBanner.ts | 155 + .../src/components/Spinner/GlimmerMessage.tsx | 328 ++ cc-haha/src/components/TokenWarning.tsx | 179 + .../src/components/agents/agentFileUtils.ts | 272 ++ .../wizard-steps/ColorStep.tsx | 84 + .../wizard-steps/ConfirmStep.tsx | 378 ++ .../src/components/mcp/MCPStdioServerMenu.tsx | 177 + .../components/messages/AdvisorMessage.tsx | 158 + .../components/messages/AttachmentMessage.tsx | 536 +++ .../messages/GroupedToolUseContent.tsx | 58 + .../messages/UserBashOutputMessage.tsx | 54 + .../messages/UserGitHubWebhookMessage.ts | 34 + .../UserToolRejectMessage.tsx | 95 + .../messages/nullRenderingAttachments.ts | 70 + .../SubmitQuestionsView.tsx | 144 + .../NotebookEditToolDiff.tsx | 235 + .../rules/PermissionRuleDescription.tsx | 76 + .../sandbox/SandboxDoctorSection.tsx | 46 + .../scheduled-tasks/steps/NameStep.tsx | 51 + .../scheduled-tasks/steps/PermissionStep.tsx | 55 + .../components/tasks/DreamDetailDialog.tsx | 251 + .../src/components/tasks/ShellProgress.tsx | 87 + cc-haha/src/constants/betas.ts | 52 + cc-haha/src/constants/keys.ts | 11 + cc-haha/src/constants/turnCompletionVerbs.ts | 12 + cc-haha/src/context/notifications.tsx | 240 + .../hooks/notifs/useIDEStatusIndicator.tsx | 186 + cc-haha/src/hooks/useExitOnCtrlCD.ts | 95 + .../src/hooks/useLspPluginRecommendation.tsx | 194 + cc-haha/src/hooks/useManagePlugins.ts | 304 ++ cc-haha/src/hooks/usePasteHandler.ts | 285 ++ cc-haha/src/ink/.syncthing.renderer.ts.tmp | Bin 0 -> 7665 bytes cc-haha/src/ink/Ansi.tsx | 292 ++ cc-haha/src/ink/clearTerminal.ts | 74 + cc-haha/src/ink/components/NoSelect.tsx | 68 + cc-haha/src/ink/devtools.ts | 34 + cc-haha/src/ink/root.ts | 184 + cc-haha/src/ink/searchHighlight.ts | 93 + cc-haha/src/ink/stringWidth.ts | 222 + cc-haha/src/interactiveHelpers.tsx | 366 ++ cc-haha/src/memdir/findRelevantMemories.ts | 141 + cc-haha/src/plugins/builtinPlugins.ts | 159 + cc-haha/src/self-hosted-runner/main.ts | 34 + cc-haha/src/server/api/filesystem.ts | 180 + cc-haha/src/server/connectHeadless.ts | 34 + cc-haha/src/server/lockfile.ts | 34 + cc-haha/src/server/middleware/errorHandler.ts | 45 + cc-haha/src/server/router.ts | 103 + .../services/desktopCliLauncherService.ts | 476 ++ .../src/server/services/hahaOAuthService.ts | 256 + cc-haha/src/server/services/searchService.ts | 348 ++ .../PromptSuggestion/promptSuggestion.ts | 523 +++ cc-haha/src/services/analytics/config.ts | 38 + cc-haha/src/services/api/client.ts | 389 ++ cc-haha/src/services/api/emptyUsage.ts | 22 + cc-haha/src/services/api/withRetry.ts | 822 ++++ .../src/services/compact/cachedMCConfig.ts | 34 + cc-haha/src/services/contextCollapse/index.ts | 34 + cc-haha/src/services/lsp/types.ts | 34 + .../src/services/mcp/channelNotification.ts | 316 ++ .../bundled/claude-api/java/claude-api.md | 2 + .../claude-api/python/agent-sdk/patterns.md | 2 + cc-haha/src/skills/bundled/loremIpsum.ts | 282 ++ cc-haha/src/skills/bundled/skillify.ts | 197 + cc-haha/src/skills/bundled/stuck.ts | 79 + cc-haha/src/tasks/stopTask.ts | 100 + .../built-in/claudeCodeGuideAgent.ts | 205 + .../AgentTool/built-in/verificationAgent.ts | 152 + cc-haha/src/tools/AgentTool/constants.ts | 12 + cc-haha/src/tools/BashTool/commentLabel.ts | 13 + cc-haha/src/tools/EnterPlanModeTool/prompt.ts | 170 + cc-haha/src/tools/FileReadTool/limits.ts | 92 + cc-haha/src/tools/FileReadTool/prompt.ts | 49 + .../tools/PowerShellTool/commonParameters.ts | 30 + .../src/tools/TaskListTool/TaskListTool.ts | 116 + cc-haha/src/tools/ToolSearchTool/constants.ts | 1 + cc-haha/src/tools/ToolSearchTool/prompt.ts | 121 + cc-haha/src/types/fileSuggestion.ts | 34 + cc-haha/src/types/hooks.ts | 290 ++ cc-haha/src/utils/Shell.ts | 474 ++ cc-haha/src/utils/auth.ts | 2002 ++++++++ cc-haha/src/utils/awsAuthStatusManager.ts | 81 + .../utils/background/remote/preconditions.ts | 235 + cc-haha/src/utils/bash/heredoc.ts | 733 +++ cc-haha/src/utils/betas.ts | 439 ++ cc-haha/src/utils/completionCache.ts | 166 + cc-haha/src/utils/computerUse/common.test.ts | 28 + cc-haha/src/utils/computerUse/inputLoader.ts | 3 + cc-haha/src/utils/computerUse/mcpServer.ts | 106 + cc-haha/src/utils/computerUse/pythonBridge.ts | 166 + cc-haha/src/utils/deepLink/protocolHandler.ts | 136 + cc-haha/src/utils/embeddedTools.ts | 29 + cc-haha/src/utils/envDynamic.ts | 151 + cc-haha/src/utils/fileHistory.ts | 1115 +++++ cc-haha/src/utils/format.ts | 308 ++ cc-haha/src/utils/formatBriefTimestamp.ts | 81 + .../src/utils/hooks/hooksConfigSnapshot.ts | 133 + cc-haha/src/utils/hooks/postSamplingHooks.ts | 70 + cc-haha/src/utils/model/modelAllowlist.ts | 170 + .../src/utils/permissions/yoloClassifier.ts | 1495 ++++++ cc-haha/src/utils/plugins/gitAvailability.ts | 69 + .../src/utils/plugins/officialMarketplace.ts | 25 + .../src/utils/plugins/pluginDirectories.ts | 178 + .../src/utils/plugins/pluginStartupCheck.ts | 341 ++ cc-haha/src/utils/plugins/zipCache.ts | 406 ++ cc-haha/src/utils/powershell/staticPrefix.ts | 316 ++ cc-haha/src/utils/promptCategory.ts | 49 + cc-haha/src/utils/screenshotClipboard.ts | 121 + cc-haha/src/utils/sessionEnvironment.ts | 166 + cc-haha/src/utils/settings/constants.ts | 202 + cc-haha/src/utils/settings/mdm/rawRead.ts | 130 + .../src/utils/settings/validateEditTool.ts | 45 + cc-haha/src/utils/sideQuery.ts | 222 + cc-haha/src/utils/statusNoticeHelpers.ts | 20 + cc-haha/src/utils/subprocessEnv.ts | 99 + cc-haha/src/utils/swarm/teammateInit.ts | 129 + .../src/utils/swarm/teammateLayoutManager.ts | 107 + cc-haha/src/utils/tasks.ts | 862 ++++ cc-haha/src/utils/teamMemoryOps.ts | 88 + .../src/utils/telemetry/perfettoTracing.ts | 1120 +++++ cc-haha/src/utils/truncate.ts | 179 + cc-haha/src/utils/warningHandler.ts | 121 + cc-haha/src/utils/xml.ts | 16 + docs/vision-heicode-full-stack-agentic-dev.md | 268 ++ new-api/README.zh_CN.md | 476 ++ new-api/README.zh_TW.md | 476 ++ new-api/bin/migration_v0.3-v0.4.sql | 17 + new-api/common/crypto.go | 32 + new-api/common/custom-event.go | 87 + new-api/common/endpoint_defaults.go | 34 + new-api/common/hash.go | 34 + new-api/common/limiter/limiter.go | 90 + new-api/common/pprof.go | 45 + new-api/common/redis.go | 327 ++ new-api/constant/README.md | 26 + new-api/constant/env.go | 26 + new-api/controller/channel_affinity_cache.go | 88 + new-api/controller/subscription.go | 383 ++ new-api/controller/task_video.go | 313 ++ new-api/controller/token.go | 359 ++ new-api/controller/vendor_meta.go | 124 + new-api/docker-compose.local.yml | 4 + new-api/dto/gemini_isstream_test.go | 73 + new-api/logger/logger.go | 181 + new-api/middleware/cache.go | 17 + new-api/model/model_meta.go | 160 + new-api/model/subscription.go | 1206 +++++ new-api/model/twofa.go | 321 ++ new-api/model/usedata.go | 138 + new-api/relay/channel/ai360/constants.go | 14 + new-api/relay/channel/ali/constants.go | 14 + new-api/relay/channel/cohere/constant.go | 12 + new-api/relay/channel/coze/dto.go | 78 + new-api/relay/channel/deepseek/constants.go | 9 + .../relay/channel/lingyiwanwu/constrants.go | 9 + new-api/relay/channel/mistral/constants.go | 12 + new-api/relay/channel/openai/helper.go | 261 + new-api/relay/channel/replicate/constants.go | 12 + new-api/relay/channel/replicate/dto.go | 19 + new-api/relay/channel/task/kling/adaptor.go | 416 ++ new-api/relay/channel/vertex/dto.go | 42 + new-api/router/dashboard.go | 23 + new-api/service/audio.go | 48 + new-api/service/billing.go | 78 + new-api/service/billing_session.go | 434 ++ new-api/service/channel.go | 78 + new-api/service/channel_affinity.go | 966 ++++ .../service/channel_affinity_template_test.go | 247 + .../channel_affinity_usage_cache_test.go | 105 + new-api/service/channel_select.go | 162 + new-api/service/codex_credential_refresh.go | 104 + .../service/codex_credential_refresh_task.go | 148 + new-api/service/codex_oauth.go | 317 ++ new-api/service/codex_wham_usage.go | 56 + new-api/service/convert.go | 1007 ++++ new-api/service/download.go | 70 + new-api/service/epay.go | 13 + new-api/service/error.go | 221 + new-api/service/error_test.go | 57 + new-api/service/file_decoder.go | 212 + new-api/service/file_service.go | 607 +++ new-api/service/funding_source.go | 139 + new-api/service/group.go | 65 + new-api/service/http.go | 61 + new-api/service/http_client.go | 169 + new-api/service/image.go | 194 + new-api/service/log_info_generate.go | 284 ++ new-api/service/midjourney.go | 259 + new-api/service/notify-limit.go | 118 + .../service/openai_chat_responses_compat.go | 18 + new-api/service/openai_chat_responses_mode.go | 14 + .../service/openaicompat/chat_to_responses.go | 402 ++ new-api/service/openaicompat/policy.go | 19 + new-api/service/openaicompat/regex.go | 33 + .../service/openaicompat/responses_to_chat.go | 133 + new-api/service/passkey/service.go | 177 + new-api/service/passkey/session.go | 50 + new-api/service/passkey/user.go | 71 + new-api/service/pre_consume_quota.go | 79 + new-api/service/quota.go | 544 +++ new-api/service/sensitive.go | 77 + new-api/service/str.go | 152 + new-api/service/subscription_reset_task.go | 93 + new-api/service/task.go | 11 + new-api/service/task_billing.go | 301 ++ new-api/service/task_billing_test.go | 716 +++ new-api/service/task_polling.go | 560 +++ new-api/service/text_quota.go | 474 ++ new-api/service/text_quota_test.go | 441 ++ new-api/service/tiered_settle.go | 116 + new-api/service/tiered_settle_test.go | 830 ++++ new-api/service/token_counter.go | 408 ++ new-api/service/token_estimator.go | 230 + new-api/service/tokenizer.go | 63 + new-api/service/tool_billing.go | 88 + new-api/service/usage_helpr.go | 33 + new-api/service/user_notify.go | 281 ++ new-api/service/violation_fee.go | 164 + new-api/service/waffo_pancake.go | 398 ++ new-api/service/waffo_pancake_test.go | 157 + new-api/service/webhook.go | 126 + new-api/setting/system_setting/oidc.go | 25 + new-api/setting/user_usable_group.go | 54 + new-api/types/price_data.go | 42 + new-api/types/set.go | 42 + new-api/web/classic/public/pay-apple.png | Bin 0 -> 1597 bytes new-api/web/classic/src/App.jsx | 386 ++ .../src/components/dashboard/index.jsx | 286 ++ .../layout/headerbar/NewYearButton.jsx | 62 + .../src/components/playground/ChatArea.jsx | 129 + .../components/settings/PersonalSetting.jsx | 668 +++ .../personal/modals/AccountDeleteModal.jsx | 94 + .../table/channels/modals/BatchTagModal.jsx | 63 + .../model-deployments/DeploymentsFilters.jsx | 130 + .../model-pricing/view/table/PricingTable.jsx | 147 + .../table/models/ModelsColumnDefs.jsx | 380 ++ .../table/redemptions/RedemptionsActions.jsx | 71 + .../table/tokens/modals/EditTokenModal.jsx | 653 +++ .../topup/modals/PaymentConfirmModal.jsx | 221 + .../src/constants/dashboard.constants.js | 149 + new-api/web/classic/src/i18n/locales/en.json | 3792 +++++++++++++++ new-api/web/classic/src/i18n/locales/vi.json | 4181 +++++++++++++++++ .../Setting/Ratio/ModelRationNotSetEditor.jsx | 64 + new-api/web/default/components.json | 26 + new-api/web/default/postcss.config.mjs | 5 + .../src/assets/brand-icons/icon-discord.tsx | 28 + .../src/assets/brand-icons/icon-docker.tsx | 33 + .../src/assets/brand-icons/icon-facebook.tsx | 25 + .../src/assets/brand-icons/icon-figma.tsx | 27 + .../src/assets/brand-icons/icon-github.tsx | 25 + .../src/assets/brand-icons/icon-gitlab.tsx | 25 + .../src/assets/brand-icons/icon-gmail.tsx | 28 + .../src/assets/brand-icons/icon-linuxdo.tsx | 50 + .../src/assets/brand-icons/icon-medium.tsx | 30 + .../src/assets/brand-icons/icon-notion.tsx | 28 + .../src/assets/brand-icons/icon-skype.tsx | 26 + .../src/assets/brand-icons/icon-slack.tsx | 28 + .../src/assets/brand-icons/icon-stripe.tsx | 25 + .../src/assets/brand-icons/icon-telegram.tsx | 25 + .../src/assets/brand-icons/icon-trello.tsx | 27 + .../src/assets/brand-icons/icon-wechat.tsx | 38 + .../src/assets/brand-icons/icon-whatsapp.tsx | 26 + .../src/assets/brand-icons/icon-zoom.tsx | 26 + .../default/src/assets/brand-icons/index.ts | 18 + .../default/src/assets/clerk-full-logo.tsx | 41 + new-api/web/default/src/assets/clerk-logo.tsx | 23 + .../default/src/assets/custom/icon-dir.tsx | 110 + .../src/assets/custom/icon-layout-compact.tsx | 131 + .../src/assets/custom/icon-layout-default.tsx | 124 + .../src/assets/custom/icon-layout-full.tsx | 100 + .../assets/custom/icon-sidebar-floating.tsx | 82 + .../src/assets/custom/icon-sidebar-inset.tsx | 58 + .../assets/custom/icon-sidebar-sidebar.tsx | 53 + .../src/assets/custom/icon-theme-dark.tsx | 79 + .../src/assets/custom/icon-theme-light.tsx | 78 + .../src/assets/custom/icon-theme-system.tsx | 116 + new-api/web/default/src/assets/logo.tsx | 24 + .../src/components/ai-elements/actions.tsx | 65 + .../src/components/ai-elements/artifact.tsx | 151 + .../src/components/ai-elements/branch.tsx | 227 + .../src/components/ai-elements/canvas.tsx | 24 + .../ai-elements/chain-of-thought.tsx | 233 + .../src/components/ai-elements/code-block.tsx | 170 + .../components/ai-elements/confirmation.tsx | 154 + .../src/components/ai-elements/connection.tsx | 28 + .../src/components/ai-elements/context.tsx | 415 ++ .../src/components/ai-elements/controls.tsx | 18 + .../components/ai-elements/conversation.tsx | 107 + .../src/components/ai-elements/edge.tsx | 141 + .../src/components/ai-elements/image.tsx | 24 + .../ai-elements/inline-citation.tsx | 297 ++ .../src/components/ai-elements/loader.tsx | 100 + .../src/components/ai-elements/message.tsx | 76 + .../src/components/ai-elements/node.tsx | 71 + .../components/ai-elements/open-in-chat.tsx | 367 ++ .../src/components/ai-elements/panel.tsx | 15 + .../src/components/ai-elements/plan.tsx | 145 + .../components/ai-elements/prompt-input.tsx | 1386 ++++++ .../src/components/ai-elements/queue.tsx | 273 ++ .../src/components/ai-elements/reasoning.tsx | 186 + .../src/components/ai-elements/response.tsx | 42 + .../src/components/ai-elements/shimmer.tsx | 55 + .../src/components/ai-elements/sources.tsx | 83 + .../src/components/ai-elements/suggestion.tsx | 53 + .../src/components/ai-elements/task.tsx | 87 + .../src/components/ai-elements/tool.tsx | 173 + .../src/components/ai-elements/toolbar.tsx | 16 + .../components/ai-elements/web-preview.tsx | 274 ++ .../src/components/animate-in-view.tsx | 66 + .../default/src/components/auto-skeleton.tsx | 62 + .../default/src/components/coming-soon.tsx | 20 + .../default/src/components/command-menu.tsx | 99 + .../default/src/components/config-drawer.tsx | 363 ++ .../default/src/components/confirm-dialog.tsx | 69 + .../default/src/components/copy-button.tsx | 73 + .../components/data-table/bulk-actions.tsx | 212 + .../components/data-table/column-header.tsx | 76 + .../components/data-table/faceted-filter.tsx | 176 + .../src/components/data-table/index.ts | 9 + .../data-table/mobile-card-list.tsx | 294 ++ .../src/components/data-table/pagination.tsx | 137 + .../src/components/data-table/table-empty.tsx | 69 + .../components/data-table/table-skeleton.tsx | 70 + .../src/components/data-table/toolbar.tsx | 153 + .../components/data-table/view-options.tsx | 58 + .../default/src/components/date-picker.tsx | 67 + .../src/components/datetime-picker.tsx | 141 + .../default/src/components/empty-state.tsx | 50 + .../default/src/components/error-state.tsx | 54 + .../default/src/components/json-editor.tsx | 281 ++ .../src/components/language-switcher.tsx | 66 + .../layout/components/app-header.tsx | 133 + .../layout/components/app-sidebar.tsx | 66 + .../components/authenticated-layout.tsx | 39 + .../layout/components/chat-presets-item.tsx | 257 + .../components/layout/components/footer.tsx | 202 + .../src/components/layout/components/glow.tsx | 46 + .../layout/components/header-logo.tsx | 33 + .../components/layout/components/header.tsx | 20 + .../src/components/layout/components/logo.tsx | 43 + .../src/components/layout/components/main.tsx | 19 + .../layout/components/mobile-drawer.tsx | 273 ++ .../components/layout/components/mockup.tsx | 63 + .../layout/components/nav-group.tsx | 229 + .../layout/components/nav-link-item.tsx | 68 + .../components/layout/components/navbar.tsx | 51 + .../layout/components/page-footer.tsx | 23 + .../layout/components/public-header.tsx | 301 ++ .../layout/components/public-layout.tsx | 40 + .../layout/components/public-navigation.tsx | 68 + .../layout/components/section-page-layout.tsx | 109 + .../components/layout/components/section.tsx | 18 + .../components/layout/components/top-nav.tsx | 107 + .../layout/components/workspace-switcher.tsx | 207 + .../layout/config/system-settings.config.ts | 70 + .../layout/config/top-nav.config.ts | 12 + .../src/components/layout/constants.ts | 47 + .../layout/context/workspace-context.tsx | 44 + .../default/src/components/layout/index.ts | 56 + .../src/components/layout/lib/url-utils.ts | 103 + .../layout/lib/workspace-registry.example.ts | 101 + .../layout/lib/workspace-registry.ts | 110 + .../default/src/components/layout/types.ts | 83 + .../web/default/src/components/learn-more.tsx | 46 + .../default/src/components/loading-state.tsx | 48 + .../web/default/src/components/long-text.tsx | 86 + .../src/components/masked-value-display.tsx | 58 + .../src/components/model-group-selector.tsx | 567 +++ .../default/src/components/multi-select.tsx | 132 + .../src/components/navigation-progress.tsx | 25 + .../src/components/notification-button.tsx | 45 + .../src/components/notification-dialog.tsx | 272 ++ .../src/components/page-transition.tsx | 188 + .../default/src/components/password-input.tsx | 47 + .../src/components/profile-dropdown.tsx | 133 + new-api/web/default/src/components/search.tsx | 39 + .../src/components/select-dropdown.tsx | 65 + .../src/components/sign-out-dialog.tsx | 50 + .../default/src/components/skip-to-main.tsx | 13 + .../default/src/components/status-badge.tsx | 174 + .../web/default/src/components/tag-input.tsx | 96 + .../src/components/theme-quick-switcher.tsx | 111 + .../default/src/components/theme-switch.tsx | 60 + .../web/default/src/components/turnstile.tsx | 58 + .../default/src/components/ui/accordion.tsx | 65 + .../src/components/ui/alert-dialog.tsx | 154 + .../web/default/src/components/ui/alert.tsx | 65 + .../web/default/src/components/ui/avatar.tsx | 50 + .../web/default/src/components/ui/badge.tsx | 45 + .../web/default/src/components/ui/button.tsx | 59 + .../default/src/components/ui/calendar.tsx | 308 ++ .../web/default/src/components/ui/card.tsx | 91 + .../default/src/components/ui/carousel.tsx | 240 + .../default/src/components/ui/checkbox.tsx | 29 + .../default/src/components/ui/collapsible.tsx | 33 + .../src/components/ui/combobox-input.tsx | 197 + .../default/src/components/ui/combobox.tsx | 148 + .../web/default/src/components/ui/command.tsx | 181 + .../web/default/src/components/ui/dialog.tsx | 140 + .../web/default/src/components/ui/drawer.tsx | 132 + .../src/components/ui/dropdown-menu.tsx | 256 + .../web/default/src/components/ui/empty.tsx | 103 + .../web/default/src/components/ui/form.tsx | 164 + .../default/src/components/ui/hover-card.tsx | 41 + .../default/src/components/ui/input-group.tsx | 169 + .../default/src/components/ui/input-otp.tsx | 74 + .../web/default/src/components/ui/input.tsx | 20 + .../web/default/src/components/ui/label.tsx | 23 + .../default/src/components/ui/markdown.tsx | 46 + .../web/default/src/components/ui/popover.tsx | 45 + .../default/src/components/ui/progress.tsx | 30 + .../default/src/components/ui/radio-group.tsx | 42 + .../default/src/components/ui/scroll-area.tsx | 55 + .../web/default/src/components/ui/select.tsx | 186 + .../default/src/components/ui/separator.tsx | 25 + .../web/default/src/components/ui/sheet.tsx | 136 + .../web/default/src/components/ui/sidebar.tsx | 732 +++ .../default/src/components/ui/skeleton.tsx | 13 + .../web/default/src/components/ui/sonner.tsx | 21 + .../web/default/src/components/ui/switch.tsx | 28 + .../web/default/src/components/ui/table.tsx | 113 + .../web/default/src/components/ui/tabs.tsx | 63 + .../default/src/components/ui/textarea.tsx | 17 + .../web/default/src/components/ui/tooltip.tsx | 58 + new-api/web/default/src/config/fonts.ts | 19 + .../src/context/direction-provider.tsx | 61 + .../web/default/src/context/font-provider.tsx | 58 + .../default/src/context/layout-provider.tsx | 85 + .../default/src/context/search-provider.tsx | 46 + .../default/src/context/theme-provider.tsx | 110 + new-api/web/default/src/env.d.ts | 9 + new-api/web/default/src/features/about/api.ts | 7 + .../web/default/src/features/about/index.tsx | 168 + .../web/default/src/features/about/types.ts | 5 + .../sign-in/components/user-auth-form.tsx | 435 ++ .../web/default/src/features/channels/api.ts | 548 +++ .../channels/components/channels-columns.tsx | 1043 ++++ .../channels/components/channels-dialogs.tsx | 85 + .../components/channels-primary-buttons.tsx | 218 + .../channels/components/channels-provider.tsx | 101 + .../channels/components/channels-table.tsx | 449 ++ .../components/data-table-bulk-actions.tsx | 228 + .../components/data-table-row-actions.tsx | 246 + .../components/data-table-tag-row-actions.tsx | 96 + .../dialogs/balance-query-dialog.tsx | 195 + .../dialogs/channel-test-dialog.tsx | 611 +++ .../components/dialogs/codex-oauth-dialog.tsx | 204 + .../components/dialogs/codex-usage-dialog.tsx | 581 +++ .../dialogs/copy-channel-dialog.tsx | 113 + .../components/dialogs/edit-tag-dialog.tsx | 420 ++ .../dialogs/fetch-models-dialog.tsx | 473 ++ .../missing-models-confirmation-dialog.tsx | 84 + .../dialogs/multi-key-manage-dialog.tsx | 423 ++ .../dialogs/multi-key-statistics-card.tsx | 24 + .../dialogs/multi-key-table-row-actions.tsx | 47 + .../dialogs/ollama-models-dialog.tsx | 588 +++ .../dialogs/status-code-risk-dialog.tsx | 150 + .../dialogs/tag-batch-edit-dialog.tsx | 286 ++ .../dialogs/upstream-update-dialog.tsx | 289 ++ .../drawers/channel-mutate-drawer.tsx | 3016 ++++++++++++ .../components/model-mapping-editor.tsx | 244 + .../components/numeric-spinner-input.tsx | 177 + .../src/features/channels/constants.ts | 368 ++ .../hooks/use-channel-upstream-updates.ts | 281 ++ .../default/src/features/channels/index.tsx | 28 + .../features/channels/lib/channel-actions.ts | 577 +++ .../src/features/channels/lib/channel-form.ts | 502 ++ .../channels/lib/channel-type-config.ts | 180 + .../features/channels/lib/channel-utils.ts | 643 +++ .../src/features/channels/lib/index.ts | 7 + .../channels/lib/model-mapping-validation.ts | 229 + .../features/channels/lib/multi-key-utils.ts | 57 + .../src/features/channels/lib/ollama-utils.ts | 143 + .../channels/lib/status-code-risk-guard.ts | 85 + .../channels/lib/upstream-update-utils.ts | 38 + .../default/src/features/channels/types.ts | 295 ++ .../chat/hooks/use-active-chat-key.ts | 31 + .../features/chat/hooks/use-chat-presets.ts | 64 + .../src/features/chat/lib/chat-links.ts | 166 + .../src/features/chat/lib/send-to-fluent.ts | 24 + .../dashboard/hooks/use-dashboard-config.tsx | 107 + .../default/src/features/errors/forbidden.tsx | 29 + .../src/features/errors/general-error.tsx | 43 + .../src/features/errors/maintenance-error.tsx | 23 + .../src/features/errors/not-found-error.tsx | 29 + .../features/errors/unauthorized-error.tsx | 29 + new-api/web/default/src/features/home/api.ts | 15 + .../home/components/connection-line.tsx | 21 + .../features/home/components/feature-item.tsx | 29 + .../features/home/components/gateway-card.tsx | 55 + .../features/home/components/hero-buttons.tsx | 38 + .../home/components/hero-terminal-demo.tsx | 289 ++ .../features/home/components/icon-card.tsx | 29 + .../src/features/home/components/index.ts | 5 + .../home/components/scrolling-icons.tsx | 44 + .../features/home/components/sections/cta.tsx | 65 + .../home/components/sections/features.tsx | 222 + .../home/components/sections/hero.tsx | 96 + .../home/components/sections/how-it-works.tsx | 77 + .../home/components/sections/stats.tsx | 103 + .../features/home/components/stat-item.tsx | 42 + .../default/src/features/home/constants.ts | 129 + .../default/src/features/home/hooks/index.ts | 1 + .../home/hooks/use-home-page-content.ts | 69 + .../web/default/src/features/home/index.tsx | 55 + .../src/features/home/lib/icon-mapper.tsx | 41 + .../web/default/src/features/home/types.ts | 21 + new-api/web/default/src/features/keys/api.ts | 99 + .../components/api-key-group-combobox.tsx | 173 + .../keys/components/api-keys-cells.tsx | 197 + .../keys/components/api-keys-columns.tsx | 359 ++ .../components/api-keys-delete-dialog.tsx | 72 + .../keys/components/api-keys-dialogs.tsx | 39 + .../api-keys-multi-delete-dialog.tsx | 70 + .../components/api-keys-mutate-drawer.tsx | 589 +++ .../components/api-keys-primary-buttons.tsx | 17 + .../keys/components/api-keys-provider.tsx | 170 + .../keys/components/api-keys-table.tsx | 257 + .../components/data-table-bulk-actions.tsx | 114 + .../components/data-table-row-actions.tsx | 259 + .../components/dialogs/cc-switch-dialog.tsx | 207 + .../default/src/features/keys/constants.ts | 86 + .../web/default/src/features/keys/index.tsx | 24 + .../src/features/keys/lib/api-key-form.ts | 89 + .../default/src/features/keys/lib/index.ts | 10 + .../web/default/src/features/keys/types.ts | 88 + .../web/default/src/features/models/api.ts | 614 +++ .../components/data-table-bulk-actions.tsx | 189 + .../components/data-table-row-actions.tsx | 118 + .../components/deployment-access-guard.tsx | 181 + .../models/components/deployments-columns.tsx | 303 ++ .../models/components/deployments-table.tsx | 400 ++ .../models/components/description-cell.tsx | 35 + .../dialogs/create-deployment-drawer.tsx | 747 +++ .../dialogs/extend-deployment-dialog.tsx | 218 + .../dialogs/missing-models-dialog.tsx | 233 + .../prefill-group-management-dialog.tsx | 509 ++ .../dialogs/prefill-group-management.tsx | 62 + .../dialogs/vendor-mutate-dialog.tsx | 197 + .../dialogs/view-details-dialog.tsx | 262 ++ .../drawers/model-mutate-drawer.tsx | 1249 +++++ .../drawers/prefill-group-form-drawer.tsx | 364 ++ .../models/components/models-columns.tsx | 599 +++ .../models/components/models-dialogs.tsx | 74 + .../components/models-primary-buttons.tsx | 95 + .../models/components/models-provider.tsx | 118 + .../models/components/models-table.tsx | 326 ++ .../models/components/prefill-group-shared.ts | 110 + .../hooks/use-model-deployment-settings.ts | 174 + .../web/default/src/features/models/index.tsx | 171 + .../features/models/lib/deployments-utils.ts | 24 + .../default/src/features/models/lib/index.ts | 12 + .../src/features/models/lib/model-actions.ts | 253 + .../src/features/models/lib/model-form.ts | 122 + .../src/features/models/lib/model-utils.ts | 177 + .../src/features/models/lib/query-keys.ts | 49 + .../src/features/models/lib/vendor-actions.ts | 34 + .../src/features/models/section-registry.tsx | 36 + .../components/message-action-button.tsx | 51 + .../playground/components/message-error.tsx | 61 + .../playground/components/playground-chat.tsx | 273 ++ .../default/src/features/playground/index.tsx | 191 + .../web/default/src/features/pricing/api.ts | 12 + .../features/pricing/components/model-row.tsx | 274 ++ .../components/tabs/notification-tab.tsx | 368 ++ .../profile/hooks/use-access-token.ts | 46 + .../features/redemption-codes/lib/index.ts | 15 + new-api/web/default/src/features/setup/api.ts | 40 + .../features/setup/components/admin-step.tsx | 105 + .../setup/components/complete-step.tsx | 90 + .../setup/components/database-step.tsx | 146 + .../setup/components/step-navigation.tsx | 61 + .../setup/components/usage-mode-step.tsx | 113 + .../web/default/src/features/setup/index.ts | 1 + .../src/features/setup/setup-wizard.tsx | 382 ++ .../web/default/src/features/setup/types.ts | 23 + .../subscriptions-mutate-drawer.tsx | 526 +++ .../src/features/system-settings/api.ts | 49 + .../auth/basic-auth-section.tsx | 259 + .../auth/bot-protection-section.tsx | 141 + .../system-settings/auth/custom-oauth/api.ts | 61 + .../components/discovery-button.tsx | 77 + .../components/preset-selector.tsx | 115 + .../components/provider-form-dialog.tsx | 583 +++ .../components/provider-table.tsx | 132 + .../custom-oauth/custom-oauth-section.tsx | 68 + .../hooks/use-custom-oauth-mutations.ts | 94 + .../hooks/use-custom-oauth-providers.ts | 12 + .../auth/custom-oauth/types.ts | 206 + .../features/system-settings/auth/index.tsx | 61 + .../system-settings/auth/oauth-section.tsx | 763 +++ .../system-settings/auth/passkey-section.tsx | 335 ++ .../system-settings/auth/section-registry.tsx | 127 + .../components/form-dirty-indicator.tsx | 36 + .../components/form-navigation-guard.tsx | 85 + .../components/settings-accordion.tsx | 35 + .../components/settings-card.tsx | 32 + .../components/settings-page.tsx | 62 + .../components/settings-section.tsx | 41 + .../content/announcements-section.tsx | 599 +++ .../content/api-info-section.tsx | 528 +++ .../system-settings/content/chat-dialog.tsx | 152 + .../content/chat-settings-section.tsx | 179 + .../content/chat-settings-visual-editor.tsx | 192 + .../content/dashboard-section.tsx | 167 + .../content/drawing-settings-section.tsx | 149 + .../system-settings/content/faq-section.tsx | 433 ++ .../system-settings/content/index.tsx | 112 + .../content/json-toggle-section.tsx | 196 + .../content/section-registry.tsx | 125 + .../content/uptime-kuma-section.tsx | 461 ++ .../features/system-settings/content/utils.ts | 19 + .../general/channel-affinity/api.ts | 45 + .../channel-affinity/cache-stats-dialog.tsx | 154 + .../general/channel-affinity/constants.ts | 89 + .../general/channel-affinity/index.tsx | 696 +++ .../channel-affinity/rule-editor-dialog.tsx | 429 ++ .../general/channel-affinity/types.ts | 38 + .../general/checkin-settings-section.tsx | 186 + .../system-settings/general/index.tsx | 89 + .../general/pricing-section.tsx | 362 ++ .../general/quota-settings-section.tsx | 245 + .../general/section-registry.tsx | 148 + .../general/system-behavior-section.tsx | 166 + .../general/system-info-section.tsx | 395 ++ .../hooks/use-accordion-state.ts | 85 + .../hooks/use-form-dirty-guard.ts | 56 + .../system-settings/hooks/use-reset-form.ts | 26 + .../hooks/use-safe-json-state.ts | 40 + .../hooks/use-settings-form.ts | 268 ++ .../hooks/use-system-options.ts | 113 + .../hooks/use-update-option.ts | 47 + .../src/features/system-settings/index.tsx | 17 + .../integrations/amount-discount-dialog.tsx | 198 + .../amount-discount-visual-editor.tsx | 264 ++ .../amount-options-visual-editor.tsx | 148 + .../integrations/creem-product-dialog.tsx | 241 + .../creem-products-visual-editor.tsx | 304 ++ .../integrations/email-settings-section.tsx | 300 ++ .../system-settings/integrations/index.tsx | 88 + .../ionet-deployment-settings-section.tsx | 251 + .../monitoring-settings-section.tsx | 487 ++ .../integrations/payment-method-dialog.tsx | 284 ++ .../payment-methods-visual-editor.tsx | 438 ++ .../integrations/payment-settings-section.tsx | 1297 +++++ .../integrations/section-registry.tsx | 160 + .../system-settings/integrations/utils.ts | 110 + .../waffo-pancake-settings-section.tsx | 290 ++ .../integrations/waffo-settings-section.tsx | 510 ++ .../integrations/worker-settings-section.tsx | 182 + .../system-settings/maintenance/config.ts | 218 + .../maintenance/header-navigation-section.tsx | 238 + .../system-settings/maintenance/index.tsx | 54 + .../maintenance/log-settings-section.tsx | 243 + .../maintenance/notice-section.tsx | 90 + .../maintenance/performance-section.tsx | 781 +++ .../maintenance/section-registry.tsx | 129 + .../maintenance/sidebar-modules-section.tsx | 259 + .../maintenance/update-checker-section.tsx | 178 + .../models/channel-selector-dialog.tsx | 388 ++ .../models/claude-settings-card.tsx | 261 + .../models/conflict-confirm-dialog.tsx | 102 + .../system-settings/models/constants.ts | 59 + .../models/gemini-settings-card.tsx | 397 ++ .../models/global-settings-card.tsx | 395 ++ .../models/grok-settings-card.tsx | 132 + .../models/group-ratio-form.tsx | 278 ++ .../models/group-ratio-visual-editor.tsx | 1115 +++++ .../models/group-special-usable-editor.tsx | 394 ++ .../features/system-settings/models/index.tsx | 57 + .../models/model-ratio-dialog.tsx | 654 +++ .../models/model-ratio-form.tsx | 342 ++ .../models/model-ratio-visual-editor.tsx | 786 ++++ .../models/ratio-settings-card.tsx | 488 ++ .../models/section-registry.tsx | 155 + .../models/tiered-pricing-editor.tsx | 1609 +++++++ .../models/tool-price-settings.tsx | 337 ++ .../models/upstream-ratio-sync-columns.tsx | 338 ++ .../models/upstream-ratio-sync-helpers.ts | 84 + .../models/upstream-ratio-sync-table.tsx | 284 ++ .../models/upstream-ratio-sync.tsx | 552 +++ .../features/system-settings/models/utils.ts | 123 + .../system-settings/request-limits/index.tsx | 36 + .../request-limits/rate-limit-dialog.tsx | 212 + .../request-limits/rate-limit-section.tsx | 299 ++ .../rate-limit-visual-editor.tsx | 199 + .../request-limits/section-registry.tsx | 86 + .../sensitive-words-section.tsx | 149 + .../request-limits/ssrf-section.tsx | 396 ++ .../src/features/system-settings/types.ts | 340 ++ .../system-settings/utils/json-parser.ts | 167 + .../system-settings/utils/json-validators.ts | 35 + .../system-settings/utils/route-config.ts | 92 + .../system-settings/utils/section-registry.ts | 78 + .../columns/common-logs-columns.tsx | 779 +++ .../components/dialogs/fail-reason-dialog.tsx | 69 + .../web/default/src/features/wallet/api.ts | 217 + .../components/affiliate-rewards-card.tsx | 156 + .../components/creem-products-section.tsx | 56 + .../dialogs/billing-history-dialog.tsx | 322 ++ .../dialogs/creem-confirm-dialog.tsx | 78 + .../dialogs/payment-confirm-dialog.tsx | 136 + .../components/dialogs/transfer-dialog.tsx | 111 + .../wallet/components/recharge-form-card.tsx | 494 ++ .../components/subscription-plans-card.tsx | 600 +++ .../wallet/components/wallet-stats-card.tsx | 74 + .../default/src/features/wallet/constants.ts | 53 + .../src/features/wallet/hooks/index.ts | 11 + .../features/wallet/hooks/use-affiliate.ts | 79 + .../wallet/hooks/use-billing-history.ts | 144 + .../wallet/hooks/use-creem-payment.ts | 37 + .../src/features/wallet/hooks/use-payment.ts | 120 + .../features/wallet/hooks/use-redemption.ts | 50 + .../features/wallet/hooks/use-topup-info.ts | 208 + .../wallet/hooks/use-waffo-pancake-payment.ts | 89 + .../wallet/hooks/use-waffo-payment.ts | 65 + .../web/default/src/features/wallet/index.tsx | 330 ++ .../src/features/wallet/lib/affiliate.ts | 11 + .../src/features/wallet/lib/billing.ts | 61 + .../default/src/features/wallet/lib/format.ts | 79 + .../default/src/features/wallet/lib/index.ts | 8 + .../src/features/wallet/lib/payment.ts | 150 + .../default/src/features/wallet/lib/ui.tsx | 115 + .../web/default/src/features/wallet/types.ts | 260 + new-api/web/default/src/hooks/index.ts | 14 + new-api/web/default/src/hooks/use-admin.ts | 13 + .../src/hooks/use-copy-to-clipboard.ts | 77 + .../web/default/src/hooks/use-countdown.ts | 56 + new-api/web/default/src/hooks/use-debounce.ts | 23 + new-api/web/default/src/hooks/use-dialog.ts | 168 + .../src/hooks/use-hidden-click-unlock.ts | 48 + .../web/default/src/hooks/use-media-query.ts | 32 + .../src/hooks/use-minimum-loading-time.ts | 33 + new-api/web/default/src/hooks/use-mobile.tsx | 19 + .../default/src/hooks/use-notifications.ts | 161 + .../default/src/hooks/use-sidebar-config.ts | 273 ++ .../web/default/src/hooks/use-sidebar-data.ts | 127 + new-api/web/default/src/hooks/use-status.ts | 62 + .../default/src/hooks/use-system-config.ts | 185 + .../src/hooks/use-table-compact-mode.ts | 63 + .../default/src/hooks/use-table-url-state.ts | 225 + .../default/src/hooks/use-top-nav-links.ts | 92 + .../web/default/src/hooks/use-user-display.ts | 56 + new-api/web/default/src/i18n/config.ts | 39 + .../i18n/locales/_reports/_sync-report.json | 41 + .../locales/_reports/fr.untranslated.json | 5 + .../locales/_reports/ja.untranslated.json | 86 + .../locales/_reports/ru.untranslated.json | 90 + .../locales/_reports/vi.untranslated.json | 5 + .../locales/_reports/zh.untranslated.json | 98 + new-api/web/default/src/i18n/locales/en.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/locales/fr.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/locales/ja.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/locales/ru.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/locales/vi.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/locales/zh.json | 3683 +++++++++++++++ new-api/web/default/src/i18n/static-keys.ts | 472 ++ new-api/web/default/src/lib/api.ts | 236 + new-api/web/default/src/lib/colors.ts | 164 + new-api/web/default/src/lib/constants.ts | 14 + new-api/web/default/src/lib/cookies.ts | 43 + .../web/default/src/lib/copy-to-clipboard.ts | 85 + new-api/web/default/src/lib/currency.ts | 555 +++ new-api/web/default/src/lib/dayjs.ts | 6 + new-api/web/default/src/lib/dom-utils.ts | 16 + new-api/web/default/src/lib/format.ts | 218 + .../default/src/lib/handle-server-error.ts | 25 + .../default/src/lib/http-status-code-rules.ts | 118 + new-api/web/default/src/lib/lobe-icon.tsx | 146 + new-api/web/default/src/lib/motion.ts | 104 + new-api/web/default/src/lib/oauth.ts | 126 + new-api/web/default/src/lib/passkey.ts | 271 ++ new-api/web/default/src/lib/roles.ts | 27 + .../default/src/lib/secure-verification.ts | 48 + .../default/src/lib/show-submitted-data.tsx | 15 + new-api/web/default/src/lib/time.ts | 171 + new-api/web/default/src/lib/utils.ts | 95 + new-api/web/default/src/lib/vchart.ts | 4 + new-api/web/default/src/routeTree.gen.ts | 1262 +++++ .../web/default/src/routes/about/index.tsx | 6 + new-api/web/default/src/stores/auth-store.ts | 87 + .../default/src/stores/notification-store.ts | 70 + .../default/src/stores/system-config-store.ts | 94 + new-api/web/default/src/styles/index.css | 566 +++ new-api/web/default/src/styles/theme.css | 124 + new-api/web/default/src/tanstack-table.d.ts | 15 + new-api/web/default/tsconfig.app.json | 33 + 1158 files changed, 257958 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 _all-in-one-upload/cc-haha/adapters/README.md create mode 100644 _all-in-one-upload/cc-haha/desktop/src-tauri/gen/schemas/acl-manifests.json create mode 100644 _all-in-one-upload/cc-haha/desktop/src-tauri/icons/Square30x30Logo.png create mode 100644 _all-in-one-upload/cc-haha/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 _all-in-one-upload/cc-haha/desktop/src-tauri/src/lib.rs create mode 100644 _all-in-one-upload/cc-haha/desktop/src-tauri/tauri.conf.json create mode 100644 _all-in-one-upload/cc-haha/desktop/src/api/skills.ts create mode 100644 _all-in-one-upload/cc-haha/desktop/src/api/websocket.test.ts create mode 100644 _all-in-one-upload/cc-haha/desktop/src/components/shared/UpdateChecker.tsx create mode 100644 _all-in-one-upload/cc-haha/desktop/src/components/tasks/DayOfWeekPicker.tsx create mode 100644 _all-in-one-upload/cc-haha/desktop/src/pages/ActiveSession.tsx create mode 100644 _all-in-one-upload/cc-haha/desktop/src/pages/ScheduledTasksList.tsx create mode 100644 _all-in-one-upload/cc-haha/desktop/src/stores/agentStore.ts create mode 100644 _all-in-one-upload/cc-haha/desktop/src/types/task.ts create mode 100644 _all-in-one-upload/cc-haha/docs/agent/images/.syncthing.12-agent-core-loop.png.tmp create mode 100644 _all-in-one-upload/cc-haha/docs/agent/images/06-context-passing.png create mode 100644 _all-in-one-upload/cc-haha/docs/channel/images/03-access-control.png create mode 100644 _all-in-one-upload/cc-haha/docs/en/guide/faq.md create mode 100644 _all-in-one-upload/cc-haha/docs/en/memory/images/05-architecture-overview.png create mode 100644 _all-in-one-upload/cc-haha/docs/guide/quick-start.md create mode 100644 _all-in-one-upload/cc-haha/docs/images/desktop_ui/09_slash_command.png create mode 100644 _all-in-one-upload/cc-haha/docs/images/im/feishu/03-dev-console.png create mode 100644 _all-in-one-upload/cc-haha/docs/images/im/feishu/07-menu-clear.png create mode 100644 _all-in-one-upload/cc-haha/docs/images/im/telegram/03-bot-token.png create mode 100644 _all-in-one-upload/cc-haha/docs/images/logo-horizontal.png create mode 100644 _all-in-one-upload/cc-haha/docs/memory/03-autodream.md create mode 100644 _all-in-one-upload/cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/active_session/code.html create mode 100644 _all-in-one-upload/cc-haha/release-notes/v0.1.7.md create mode 100644 _all-in-one-upload/cc-haha/src/bridge/replBridgeHandle.ts create mode 100644 _all-in-one-upload/cc-haha/src/bridge/sessionRunner.ts create mode 100644 _all-in-one-upload/cc-haha/src/buddy/useBuddyNotification.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/break-cache/index.js create mode 100644 _all-in-one-upload/cc-haha/src/commands/compact/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/diff/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/fast/fast.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/install-github-app/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/login/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/mobile/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/passes/passes.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/plugin/DiscoverPlugins.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/plugin/unifiedTypes.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/remoteControlServer/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/rename/generateSessionName.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/rename/rename.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/skills/skills.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/statusline.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/subscribe-pr.ts create mode 100644 _all-in-one-upload/cc-haha/src/commands/tasks/tasks.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/terminalSetup/terminalSetup.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/upgrade/upgrade.tsx create mode 100644 _all-in-one-upload/cc-haha/src/commands/voice/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/CustomSelect/select-input-option.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/CustomSelect/use-select-navigation.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/DevChannelsDialog.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/LanguagePicker.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/LspRecommendation/LspRecommendationMenu.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/Spinner/teammateSelectHint.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/Spinner/useShimmerAnimation.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/CreateAgentWizard.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/agents/types.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/hooks/SelectHookMode.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/hooks/SelectMatcherMode.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/mcp/ElicitationDialog.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/mcp/McpParsingWarnings.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/mcp/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/messages/AssistantRedactedThinkingMessage.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/messages/UserCommandMessage.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/messages/UserTeammateMessage.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/permissions/PermissionExplanation.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/permissions/rules/PermissionRuleInput.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/sandbox/SandboxDependenciesTab.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/scheduled-tasks/types.ts create mode 100644 _all-in-one-upload/cc-haha/src/components/shell/ExpandShellOutputContext.tsx create mode 100644 _all-in-one-upload/cc-haha/src/components/wizard/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/constants/github-app.ts create mode 100644 _all-in-one-upload/cc-haha/src/context/voice.tsx create mode 100644 _all-in-one-upload/cc-haha/src/entrypoints/sdk/coreTypes.generated.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/.syncthing.usePromptsFromClaudeInChrome.tsx.tmp create mode 100644 _all-in-one-upload/cc-haha/src/hooks/notifs/useSettingsErrors.tsx create mode 100644 _all-in-one-upload/cc-haha/src/hooks/notifs/useStartupNotification.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/renderPlaceholder.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/toolPermission/PermissionContext.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useCanUseTool.tsx create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useClipboardImageHint.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useDiffData.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useExitOnCtrlCDWithKeybindings.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useIdeConnectionStatus.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useIssueFlagBanner.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/usePluginRecommendationBase.tsx create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useTerminalSize.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useUpdateNotification.ts create mode 100644 _all-in-one-upload/cc-haha/src/hooks/useVoiceEnabled.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/clearTerminal.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/components/RawAnsi.tsx create mode 100644 _all-in-one-upload/cc-haha/src/ink/events/dispatcher.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/events/terminal-event.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/hooks/use-terminal-title.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/layout/engine.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/measure-element.ts create mode 100644 _all-in-one-upload/cc-haha/src/ink/render-node-to-output.ts create mode 100644 _all-in-one-upload/cc-haha/src/keybindings/shortcutFormat.ts create mode 100644 _all-in-one-upload/cc-haha/src/memdir/memoryShapeTelemetry.ts create mode 100644 _all-in-one-upload/cc-haha/src/migrations/resetProToOpusDefault.ts create mode 100644 _all-in-one-upload/cc-haha/src/query/transitions.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/__tests__/.syncthing.providers-real.test.ts.tmp create mode 100644 _all-in-one-upload/cc-haha/src/server/__tests__/fixtures/mock-sdk-cli.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/__tests__/scheduled-tasks.test.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/api/agents.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/index.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/middleware/cors.test.ts create mode 100644 _all-in-one-upload/cc-haha/src/server/proxy/streaming/openaiChatStreamToAnthropic.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/autoDream/autoDream.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/autoDream/config.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/compact/apiMicrocompact.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/compact/compact.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/remoteManagedSettings/syncCacheState.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/teamMemorySync/types.ts create mode 100644 _all-in-one-upload/cc-haha/src/services/tools/toolExecution.ts create mode 100644 _all-in-one-upload/cc-haha/src/skills/bundled/claude-api/go/claude-api.md create mode 100644 _all-in-one-upload/cc-haha/src/skills/bundled/remember.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/AgentTool/UI.tsx create mode 100644 _all-in-one-upload/cc-haha/src/tools/AgentTool/forkSubagent.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/AgentTool/runAgent.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/BashTool/bashPermissions.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/BashTool/commentLabel.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/EnterPlanModeTool/UI.tsx create mode 100644 _all-in-one-upload/cc-haha/src/tools/MCPTool/UI.tsx create mode 100644 _all-in-one-upload/cc-haha/src/tools/NotebookEditTool/UI.tsx create mode 100644 _all-in-one-upload/cc-haha/src/tools/OverflowTestTool/OverflowTestTool.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/PowerShellTool/clmTypes.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/PowerShellTool/commandSemantics.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/PowerShellTool/destructiveCommandWarning.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/PowerShellTool/powershellSecurity.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/SubscribePRTool/SubscribePRTool.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/TaskUpdateTool/constants.ts create mode 100644 _all-in-one-upload/cc-haha/src/tools/ToolSearchTool/ToolSearchTool.ts create mode 100644 _all-in-one-upload/cc-haha/src/types/statusLine.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/advisor.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/attachments.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/codeIndexing.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/configConstants.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/context.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/contextAnalysis.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/conversationRecovery.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/crypto.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/debug.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/directMemberMessage.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/errors.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/exampleCommands.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/forkedAgent.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/generatedFiles.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/gitSettings.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/headlessProfiler.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/hooks/fileChangedWatcher.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/hooks/hooksConfigManager.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/iTermBackup.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/model/deprecation.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/model/modelAllowlist.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/model/modelOptions.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/modifiers.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/nativeInstaller/download.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/pdf.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/permissions/PermissionUpdateSchema.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/permissions/denialTracking.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/permissions/permissionsLoader.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/permissions/yoloClassifier.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/plugins/.syncthing.hintRecommendation.ts.tmp create mode 100644 _all-in-one-upload/cc-haha/src/utils/plugins/pluginInstallationHelpers.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/plugins/pluginPolicy.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/processUserInput/processBashCommand.tsx create mode 100644 _all-in-one-upload/cc-haha/src/utils/queryHelpers.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/secureStorage/keychainPrefetch.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/sessionFileAccessHooks.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/settings/settings.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/shell/powershellDetection.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/sinks.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/staticRender.tsx create mode 100644 _all-in-one-upload/cc-haha/src/utils/subprocessEnv.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/swarm/backends/TmuxBackend.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/swarm/permissionSync.ts create mode 100644 _all-in-one-upload/cc-haha/src/utils/windowsPaths.ts create mode 100644 _all-in-one-upload/cc-haha/src/vendor/computer-use-mcp/tools.ts create mode 100644 _all-in-one-upload/cc-haha/src/vim/types.ts create mode 100644 _all-in-one-upload/new-api/LICENSE create mode 100644 _all-in-one-upload/new-api/bin/migration_v0.3-v0.4.sql create mode 100644 _all-in-one-upload/new-api/common/endpoint_type.go create mode 100644 _all-in-one-upload/new-api/common/go-channel.go create mode 100644 _all-in-one-upload/new-api/common/str.go create mode 100644 _all-in-one-upload/new-api/common/system_monitor_windows.go create mode 100644 _all-in-one-upload/new-api/constant/context_key.go create mode 100644 _all-in-one-upload/new-api/controller/channel_affinity_cache.go create mode 100644 _all-in-one-upload/new-api/controller/codex_oauth.go create mode 100644 _all-in-one-upload/new-api/controller/custom_oauth.go create mode 100644 _all-in-one-upload/new-api/controller/subscription_payment_epay.go create mode 100644 _all-in-one-upload/new-api/docker-compose.local.yml create mode 100644 _all-in-one-upload/new-api/docs/images/aliyun.png create mode 100644 _all-in-one-upload/new-api/dto/video.go create mode 100644 _all-in-one-upload/new-api/i18n/i18n.go create mode 100644 _all-in-one-upload/new-api/middleware/cache.go create mode 100644 _all-in-one-upload/new-api/middleware/distributor.go create mode 100644 _all-in-one-upload/new-api/middleware/kling_adapter.go create mode 100644 _all-in-one-upload/new-api/model/setup.go create mode 100644 _all-in-one-upload/new-api/model/user_cache.go create mode 100644 _all-in-one-upload/new-api/pkg/billingexpr/billingexpr_test.go create mode 100644 _all-in-one-upload/new-api/pkg/ionet/jsonutil.go create mode 100644 _all-in-one-upload/new-api/relay/channel/ali/constants.go create mode 100644 _all-in-one-upload/new-api/relay/channel/gemini/relay-gemini.go create mode 100644 _all-in-one-upload/new-api/relay/channel/openai/constant.go create mode 100644 _all-in-one-upload/new-api/relay/channel/replicate/dto.go create mode 100644 _all-in-one-upload/new-api/relay/channel/task/hailuo/adaptor.go create mode 100644 _all-in-one-upload/new-api/relay/channel/task/suno/adaptor.go create mode 100644 _all-in-one-upload/new-api/relay/channel/task/vertex/adaptor.go create mode 100644 _all-in-one-upload/new-api/relay/channel/volcengine/constants.go create mode 100644 _all-in-one-upload/new-api/relay/channel/xinference/constant.go create mode 100644 _all-in-one-upload/new-api/relay/channel/zhipu_4v/relay-zhipu_v4.go create mode 100644 _all-in-one-upload/new-api/relay/helper/price.go create mode 100644 _all-in-one-upload/new-api/service/codex_oauth.go create mode 100644 _all-in-one-upload/new-api/service/quota.go create mode 100644 _all-in-one-upload/new-api/service/text_quota_test.go create mode 100644 _all-in-one-upload/new-api/service/violation_fee.go create mode 100644 _all-in-one-upload/new-api/setting/model_setting/claude_test.go create mode 100644 _all-in-one-upload/new-api/setting/operation_setting/channel_affinity_setting.go create mode 100644 _all-in-one-upload/new-api/setting/payment_stripe.go create mode 100644 _all-in-one-upload/new-api/types/price_data.go create mode 100644 _all-in-one-upload/new-api/web/classic/package.json create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/common/logo/OIDCIcon.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/common/logo/WeChatIcon.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/layout/NoticeModal.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/playground/configStorage.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/settings/PersonalSetting.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/setup/index.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/channels/index.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/channels/modals/EditChannelModal.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/model-deployments/DeploymentsTable.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/filter/PricingTags.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/modal/ModelDetailSideSheet.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/tokens/TokensDescription.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/usage-logs/UsageLogsColumnDefs.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/users/UsersColumnDefs.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/table/users/modals/UserSubscriptionsModal.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/components/topup/index.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/helpers/data.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/helpers/index.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/helpers/quota.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/helpers/statusCodeRules.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/channels/useChannelsData.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/common/useNotifications.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/common/useSecureVerification.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/common/useSidebarCollapsed.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/dashboard/useDashboardCharts.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/hooks/playground/useDataLoader.js create mode 100644 _all-in-one-upload/new-api/web/classic/src/pages/Setting/Dashboard/SettingsAPIInfo.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/pages/Setting/Dashboard/SettingsDataDashboard.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/pages/Setting/Payment/SettingsPaymentGateway.jsx create mode 100644 _all-in-one-upload/new-api/web/classic/src/pages/UserAgreement/index.jsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/data-table/bulk-actions.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/status-badge.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/ui/accordion.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/ui/drawer.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/ui/input-group.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/components/ui/separator.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/auth/hooks/use-auth-redirect.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/auth/sign-up/components/sign-up-form.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/channels/components/channels-table.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/chat/hooks/use-active-chat-key.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/dashboard/lib/text.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/home/components/sections/cta.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/models/components/dialogs/vendor-mutate-dialog.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/models/components/models-dialogs.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/models/components/models-table.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/playground/components/message-action-button.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/playground/components/playground-input.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/pricing/components/dynamic-pricing-breakdown.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/pricing/lib/index.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/profile/components/tabs/account-bindings-tab.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/profile/constants.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/profile/types.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/redemption-codes/types.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/subscriptions/components/dialogs/subscription-purchase-dialog.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/content/section-registry.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/general/channel-affinity/index.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/integrations/amount-discount-dialog.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/integrations/waffo-pancake-settings-section.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/models/global-settings-card.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/models/group-ratio-form.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/models/upstream-ratio-sync-helpers.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/features/system-settings/request-limits/rate-limit-dialog.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/hooks/use-countdown.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/hooks/use-sidebar-config.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/i18n/locales/_reports/_sync-report.json create mode 100644 _all-in-one-upload/new-api/web/default/src/lib/format.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/lib/http-status-code-rules.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/lib/vchart.ts create mode 100644 _all-in-one-upload/new-api/web/default/src/routes/(auth)/sign-in.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/routes/(auth)/user/reset.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/routes/_authenticated/dashboard/index.tsx create mode 100644 _all-in-one-upload/new-api/web/default/src/routes/_authenticated/system-settings/content/$section.tsx create mode 100644 cc-haha/adapters/common/__tests__/message-buffer.test.ts create mode 100644 cc-haha/adapters/common/attachment/__tests__/attachment-limits.test.ts create mode 100644 cc-haha/adapters/common/http-client.ts create mode 100644 cc-haha/adapters/feishu/extract-payload.ts create mode 100644 cc-haha/desktop/public/fonts/material-symbols-outlined.woff2 create mode 100644 cc-haha/desktop/src-tauri/app-icon-macos.svg create mode 100644 cc-haha/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png create mode 100644 cc-haha/desktop/src-tauri/src/lib.rs create mode 100644 cc-haha/desktop/src-tauri/windows-installer-hooks.nsh create mode 100644 cc-haha/desktop/src/api/agents.ts create mode 100644 cc-haha/desktop/src/api/websocket.test.ts create mode 100644 cc-haha/desktop/src/components/controls/ModelSelector.tsx create mode 100644 cc-haha/desktop/src/components/layout/StartupErrorView.tsx create mode 100644 cc-haha/desktop/src/components/shared/Spinner.tsx create mode 100644 cc-haha/desktop/src/components/shared/UpdateChecker.test.tsx create mode 100644 cc-haha/desktop/src/components/tasks/TaskRunsPanel.tsx create mode 100644 cc-haha/desktop/src/pages/McpSettings.tsx create mode 100644 cc-haha/desktop/src/pages/Settings.tsx create mode 100644 cc-haha/desktop/src/stores/agentStore.ts create mode 100644 cc-haha/desktop/src/stores/mcpStore.ts create mode 100644 cc-haha/desktop/src/stores/sessionRuntimeStore.ts create mode 100644 cc-haha/desktop/src/theme/globals.css create mode 100644 cc-haha/desktop/src/types/session.ts create mode 100644 cc-haha/docs/agent/images/07-tool-pool.png create mode 100644 cc-haha/docs/en/agent/images/04-agent-teams.png create mode 100644 cc-haha/docs/en/memory/03-autodream.md create mode 100644 cc-haha/docs/en/reference/project-structure.md create mode 100644 cc-haha/docs/features/images/02-computer-use-security-gates.jpg create mode 100644 cc-haha/docs/images/banner.png create mode 100644 cc-haha/docs/images/desktop_ui/02_edit_code.png create mode 100644 cc-haha/docs/images/im/feishu/01-create-app-entry.png create mode 100644 cc-haha/docs/images/sponsors/shengsuanyun-logo.svg create mode 100644 cc-haha/docs/skills/02-implementation.md create mode 100644 cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/agent_teams/code.html create mode 100644 cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/antique_codex/DESIGN.md create mode 100644 cc-haha/runtime/mac_helper.py create mode 100644 cc-haha/runtime/requirements.txt create mode 100644 cc-haha/src/bridge/sessionRunner.ts create mode 100644 cc-haha/src/cli/bg.ts create mode 100644 cc-haha/src/cli/transports/WorkerStateUploader.ts create mode 100644 cc-haha/src/commands/add-dir/add-dir.tsx create mode 100644 cc-haha/src/commands/agents-platform/index.ts create mode 100644 cc-haha/src/commands/backfill-sessions/index.js create mode 100644 cc-haha/src/commands/chrome/chrome.tsx create mode 100644 cc-haha/src/commands/extra-usage/extra-usage.tsx create mode 100644 cc-haha/src/commands/good-claude/index.js create mode 100644 cc-haha/src/commands/install-github-app/ExistingWorkflowStep.tsx create mode 100644 cc-haha/src/commands/model/index.ts create mode 100644 cc-haha/src/commands/output-style/output-style.tsx create mode 100644 cc-haha/src/commands/privacy-settings/privacy-settings.tsx create mode 100644 cc-haha/src/commands/release-notes/release-notes.ts create mode 100644 cc-haha/src/commands/summary/index.js create mode 100644 cc-haha/src/commands/tasks/index.ts create mode 100644 cc-haha/src/components/.syncthing.InvalidConfigDialog.tsx.tmp create mode 100644 cc-haha/src/components/AntModelSwitchCallout.ts create mode 100644 cc-haha/src/components/BridgeDialog.tsx create mode 100644 cc-haha/src/components/ChannelDowngradeDialog.tsx create mode 100644 cc-haha/src/components/CtrlOToExpand.tsx create mode 100644 cc-haha/src/components/CustomSelect/SelectMulti.tsx create mode 100644 cc-haha/src/components/CustomSelect/select-input-option.tsx create mode 100644 cc-haha/src/components/DevChannelsDialog.tsx create mode 100644 cc-haha/src/components/DiagnosticsDisplay.tsx create mode 100644 cc-haha/src/components/FileEditToolUpdatedMessage.tsx create mode 100644 cc-haha/src/components/InvalidSettingsDialog.tsx create mode 100644 cc-haha/src/components/LogoV2/AnimatedAsterisk.tsx create mode 100644 cc-haha/src/components/Markdown.tsx create mode 100644 cc-haha/src/components/Message.tsx create mode 100644 cc-haha/src/components/PromptInput/useSwarmBanner.ts create mode 100644 cc-haha/src/components/Spinner/GlimmerMessage.tsx create mode 100644 cc-haha/src/components/TokenWarning.tsx create mode 100644 cc-haha/src/components/agents/agentFileUtils.ts create mode 100644 cc-haha/src/components/agents/new-agent-creation/wizard-steps/ColorStep.tsx create mode 100644 cc-haha/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsx create mode 100644 cc-haha/src/components/mcp/MCPStdioServerMenu.tsx create mode 100644 cc-haha/src/components/messages/AdvisorMessage.tsx create mode 100644 cc-haha/src/components/messages/AttachmentMessage.tsx create mode 100644 cc-haha/src/components/messages/GroupedToolUseContent.tsx create mode 100644 cc-haha/src/components/messages/UserBashOutputMessage.tsx create mode 100644 cc-haha/src/components/messages/UserGitHubWebhookMessage.ts create mode 100644 cc-haha/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx create mode 100644 cc-haha/src/components/messages/nullRenderingAttachments.ts create mode 100644 cc-haha/src/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.tsx create mode 100644 cc-haha/src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx create mode 100644 cc-haha/src/components/permissions/rules/PermissionRuleDescription.tsx create mode 100644 cc-haha/src/components/sandbox/SandboxDoctorSection.tsx create mode 100644 cc-haha/src/components/scheduled-tasks/steps/NameStep.tsx create mode 100644 cc-haha/src/components/scheduled-tasks/steps/PermissionStep.tsx create mode 100644 cc-haha/src/components/tasks/DreamDetailDialog.tsx create mode 100644 cc-haha/src/components/tasks/ShellProgress.tsx create mode 100644 cc-haha/src/constants/betas.ts create mode 100644 cc-haha/src/constants/keys.ts create mode 100644 cc-haha/src/constants/turnCompletionVerbs.ts create mode 100644 cc-haha/src/context/notifications.tsx create mode 100644 cc-haha/src/hooks/notifs/useIDEStatusIndicator.tsx create mode 100644 cc-haha/src/hooks/useExitOnCtrlCD.ts create mode 100644 cc-haha/src/hooks/useLspPluginRecommendation.tsx create mode 100644 cc-haha/src/hooks/useManagePlugins.ts create mode 100644 cc-haha/src/hooks/usePasteHandler.ts create mode 100644 cc-haha/src/ink/.syncthing.renderer.ts.tmp create mode 100644 cc-haha/src/ink/Ansi.tsx create mode 100644 cc-haha/src/ink/clearTerminal.ts create mode 100644 cc-haha/src/ink/components/NoSelect.tsx create mode 100644 cc-haha/src/ink/devtools.ts create mode 100644 cc-haha/src/ink/root.ts create mode 100644 cc-haha/src/ink/searchHighlight.ts create mode 100644 cc-haha/src/ink/stringWidth.ts create mode 100644 cc-haha/src/interactiveHelpers.tsx create mode 100644 cc-haha/src/memdir/findRelevantMemories.ts create mode 100644 cc-haha/src/plugins/builtinPlugins.ts create mode 100644 cc-haha/src/self-hosted-runner/main.ts create mode 100644 cc-haha/src/server/api/filesystem.ts create mode 100644 cc-haha/src/server/connectHeadless.ts create mode 100644 cc-haha/src/server/lockfile.ts create mode 100644 cc-haha/src/server/middleware/errorHandler.ts create mode 100644 cc-haha/src/server/router.ts create mode 100644 cc-haha/src/server/services/desktopCliLauncherService.ts create mode 100644 cc-haha/src/server/services/hahaOAuthService.ts create mode 100644 cc-haha/src/server/services/searchService.ts create mode 100644 cc-haha/src/services/PromptSuggestion/promptSuggestion.ts create mode 100644 cc-haha/src/services/analytics/config.ts create mode 100644 cc-haha/src/services/api/client.ts create mode 100644 cc-haha/src/services/api/emptyUsage.ts create mode 100644 cc-haha/src/services/api/withRetry.ts create mode 100644 cc-haha/src/services/compact/cachedMCConfig.ts create mode 100644 cc-haha/src/services/contextCollapse/index.ts create mode 100644 cc-haha/src/services/lsp/types.ts create mode 100644 cc-haha/src/services/mcp/channelNotification.ts create mode 100644 cc-haha/src/skills/bundled/claude-api/java/claude-api.md create mode 100644 cc-haha/src/skills/bundled/claude-api/python/agent-sdk/patterns.md create mode 100644 cc-haha/src/skills/bundled/loremIpsum.ts create mode 100644 cc-haha/src/skills/bundled/skillify.ts create mode 100644 cc-haha/src/skills/bundled/stuck.ts create mode 100644 cc-haha/src/tasks/stopTask.ts create mode 100644 cc-haha/src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts create mode 100644 cc-haha/src/tools/AgentTool/built-in/verificationAgent.ts create mode 100644 cc-haha/src/tools/AgentTool/constants.ts create mode 100644 cc-haha/src/tools/BashTool/commentLabel.ts create mode 100644 cc-haha/src/tools/EnterPlanModeTool/prompt.ts create mode 100644 cc-haha/src/tools/FileReadTool/limits.ts create mode 100644 cc-haha/src/tools/FileReadTool/prompt.ts create mode 100644 cc-haha/src/tools/PowerShellTool/commonParameters.ts create mode 100644 cc-haha/src/tools/TaskListTool/TaskListTool.ts create mode 100644 cc-haha/src/tools/ToolSearchTool/constants.ts create mode 100644 cc-haha/src/tools/ToolSearchTool/prompt.ts create mode 100644 cc-haha/src/types/fileSuggestion.ts create mode 100644 cc-haha/src/types/hooks.ts create mode 100644 cc-haha/src/utils/Shell.ts create mode 100644 cc-haha/src/utils/auth.ts create mode 100644 cc-haha/src/utils/awsAuthStatusManager.ts create mode 100644 cc-haha/src/utils/background/remote/preconditions.ts create mode 100644 cc-haha/src/utils/bash/heredoc.ts create mode 100644 cc-haha/src/utils/betas.ts create mode 100644 cc-haha/src/utils/completionCache.ts create mode 100644 cc-haha/src/utils/computerUse/common.test.ts create mode 100644 cc-haha/src/utils/computerUse/inputLoader.ts create mode 100644 cc-haha/src/utils/computerUse/mcpServer.ts create mode 100644 cc-haha/src/utils/computerUse/pythonBridge.ts create mode 100644 cc-haha/src/utils/deepLink/protocolHandler.ts create mode 100644 cc-haha/src/utils/embeddedTools.ts create mode 100644 cc-haha/src/utils/envDynamic.ts create mode 100644 cc-haha/src/utils/fileHistory.ts create mode 100644 cc-haha/src/utils/format.ts create mode 100644 cc-haha/src/utils/formatBriefTimestamp.ts create mode 100644 cc-haha/src/utils/hooks/hooksConfigSnapshot.ts create mode 100644 cc-haha/src/utils/hooks/postSamplingHooks.ts create mode 100644 cc-haha/src/utils/model/modelAllowlist.ts create mode 100644 cc-haha/src/utils/permissions/yoloClassifier.ts create mode 100644 cc-haha/src/utils/plugins/gitAvailability.ts create mode 100644 cc-haha/src/utils/plugins/officialMarketplace.ts create mode 100644 cc-haha/src/utils/plugins/pluginDirectories.ts create mode 100644 cc-haha/src/utils/plugins/pluginStartupCheck.ts create mode 100644 cc-haha/src/utils/plugins/zipCache.ts create mode 100644 cc-haha/src/utils/powershell/staticPrefix.ts create mode 100644 cc-haha/src/utils/promptCategory.ts create mode 100644 cc-haha/src/utils/screenshotClipboard.ts create mode 100644 cc-haha/src/utils/sessionEnvironment.ts create mode 100644 cc-haha/src/utils/settings/constants.ts create mode 100644 cc-haha/src/utils/settings/mdm/rawRead.ts create mode 100644 cc-haha/src/utils/settings/validateEditTool.ts create mode 100644 cc-haha/src/utils/sideQuery.ts create mode 100644 cc-haha/src/utils/statusNoticeHelpers.ts create mode 100644 cc-haha/src/utils/subprocessEnv.ts create mode 100644 cc-haha/src/utils/swarm/teammateInit.ts create mode 100644 cc-haha/src/utils/swarm/teammateLayoutManager.ts create mode 100644 cc-haha/src/utils/tasks.ts create mode 100644 cc-haha/src/utils/teamMemoryOps.ts create mode 100644 cc-haha/src/utils/telemetry/perfettoTracing.ts create mode 100644 cc-haha/src/utils/truncate.ts create mode 100644 cc-haha/src/utils/warningHandler.ts create mode 100644 cc-haha/src/utils/xml.ts create mode 100644 docs/vision-heicode-full-stack-agentic-dev.md create mode 100644 new-api/README.zh_CN.md create mode 100644 new-api/README.zh_TW.md create mode 100644 new-api/bin/migration_v0.3-v0.4.sql create mode 100644 new-api/common/crypto.go create mode 100644 new-api/common/custom-event.go create mode 100644 new-api/common/endpoint_defaults.go create mode 100644 new-api/common/hash.go create mode 100644 new-api/common/limiter/limiter.go create mode 100644 new-api/common/pprof.go create mode 100644 new-api/common/redis.go create mode 100644 new-api/constant/README.md create mode 100644 new-api/constant/env.go create mode 100644 new-api/controller/channel_affinity_cache.go create mode 100644 new-api/controller/subscription.go create mode 100644 new-api/controller/task_video.go create mode 100644 new-api/controller/token.go create mode 100644 new-api/controller/vendor_meta.go create mode 100644 new-api/docker-compose.local.yml create mode 100644 new-api/dto/gemini_isstream_test.go create mode 100644 new-api/logger/logger.go create mode 100644 new-api/middleware/cache.go create mode 100644 new-api/model/model_meta.go create mode 100644 new-api/model/subscription.go create mode 100644 new-api/model/twofa.go create mode 100644 new-api/model/usedata.go create mode 100644 new-api/relay/channel/ai360/constants.go create mode 100644 new-api/relay/channel/ali/constants.go create mode 100644 new-api/relay/channel/cohere/constant.go create mode 100644 new-api/relay/channel/coze/dto.go create mode 100644 new-api/relay/channel/deepseek/constants.go create mode 100644 new-api/relay/channel/lingyiwanwu/constrants.go create mode 100644 new-api/relay/channel/mistral/constants.go create mode 100644 new-api/relay/channel/openai/helper.go create mode 100644 new-api/relay/channel/replicate/constants.go create mode 100644 new-api/relay/channel/replicate/dto.go create mode 100644 new-api/relay/channel/task/kling/adaptor.go create mode 100644 new-api/relay/channel/vertex/dto.go create mode 100644 new-api/router/dashboard.go create mode 100644 new-api/service/audio.go create mode 100644 new-api/service/billing.go create mode 100644 new-api/service/billing_session.go create mode 100644 new-api/service/channel.go create mode 100644 new-api/service/channel_affinity.go create mode 100644 new-api/service/channel_affinity_template_test.go create mode 100644 new-api/service/channel_affinity_usage_cache_test.go create mode 100644 new-api/service/channel_select.go create mode 100644 new-api/service/codex_credential_refresh.go create mode 100644 new-api/service/codex_credential_refresh_task.go create mode 100644 new-api/service/codex_oauth.go create mode 100644 new-api/service/codex_wham_usage.go create mode 100644 new-api/service/convert.go create mode 100644 new-api/service/download.go create mode 100644 new-api/service/epay.go create mode 100644 new-api/service/error.go create mode 100644 new-api/service/error_test.go create mode 100644 new-api/service/file_decoder.go create mode 100644 new-api/service/file_service.go create mode 100644 new-api/service/funding_source.go create mode 100644 new-api/service/group.go create mode 100644 new-api/service/http.go create mode 100644 new-api/service/http_client.go create mode 100644 new-api/service/image.go create mode 100644 new-api/service/log_info_generate.go create mode 100644 new-api/service/midjourney.go create mode 100644 new-api/service/notify-limit.go create mode 100644 new-api/service/openai_chat_responses_compat.go create mode 100644 new-api/service/openai_chat_responses_mode.go create mode 100644 new-api/service/openaicompat/chat_to_responses.go create mode 100644 new-api/service/openaicompat/policy.go create mode 100644 new-api/service/openaicompat/regex.go create mode 100644 new-api/service/openaicompat/responses_to_chat.go create mode 100644 new-api/service/passkey/service.go create mode 100644 new-api/service/passkey/session.go create mode 100644 new-api/service/passkey/user.go create mode 100644 new-api/service/pre_consume_quota.go create mode 100644 new-api/service/quota.go create mode 100644 new-api/service/sensitive.go create mode 100644 new-api/service/str.go create mode 100644 new-api/service/subscription_reset_task.go create mode 100644 new-api/service/task.go create mode 100644 new-api/service/task_billing.go create mode 100644 new-api/service/task_billing_test.go create mode 100644 new-api/service/task_polling.go create mode 100644 new-api/service/text_quota.go create mode 100644 new-api/service/text_quota_test.go create mode 100644 new-api/service/tiered_settle.go create mode 100644 new-api/service/tiered_settle_test.go create mode 100644 new-api/service/token_counter.go create mode 100644 new-api/service/token_estimator.go create mode 100644 new-api/service/tokenizer.go create mode 100644 new-api/service/tool_billing.go create mode 100644 new-api/service/usage_helpr.go create mode 100644 new-api/service/user_notify.go create mode 100644 new-api/service/violation_fee.go create mode 100644 new-api/service/waffo_pancake.go create mode 100644 new-api/service/waffo_pancake_test.go create mode 100644 new-api/service/webhook.go create mode 100644 new-api/setting/system_setting/oidc.go create mode 100644 new-api/setting/user_usable_group.go create mode 100644 new-api/types/price_data.go create mode 100644 new-api/types/set.go create mode 100644 new-api/web/classic/public/pay-apple.png create mode 100644 new-api/web/classic/src/App.jsx create mode 100644 new-api/web/classic/src/components/dashboard/index.jsx create mode 100644 new-api/web/classic/src/components/layout/headerbar/NewYearButton.jsx create mode 100644 new-api/web/classic/src/components/playground/ChatArea.jsx create mode 100644 new-api/web/classic/src/components/settings/PersonalSetting.jsx create mode 100644 new-api/web/classic/src/components/settings/personal/modals/AccountDeleteModal.jsx create mode 100644 new-api/web/classic/src/components/table/channels/modals/BatchTagModal.jsx create mode 100644 new-api/web/classic/src/components/table/model-deployments/DeploymentsFilters.jsx create mode 100644 new-api/web/classic/src/components/table/model-pricing/view/table/PricingTable.jsx create mode 100644 new-api/web/classic/src/components/table/models/ModelsColumnDefs.jsx create mode 100644 new-api/web/classic/src/components/table/redemptions/RedemptionsActions.jsx create mode 100644 new-api/web/classic/src/components/table/tokens/modals/EditTokenModal.jsx create mode 100644 new-api/web/classic/src/components/topup/modals/PaymentConfirmModal.jsx create mode 100644 new-api/web/classic/src/constants/dashboard.constants.js create mode 100644 new-api/web/classic/src/i18n/locales/en.json create mode 100644 new-api/web/classic/src/i18n/locales/vi.json create mode 100644 new-api/web/classic/src/pages/Setting/Ratio/ModelRationNotSetEditor.jsx create mode 100644 new-api/web/default/components.json create mode 100644 new-api/web/default/postcss.config.mjs create mode 100644 new-api/web/default/src/assets/brand-icons/icon-discord.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-docker.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-facebook.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-figma.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-github.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-gitlab.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-gmail.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-linuxdo.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-medium.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-notion.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-skype.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-slack.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-stripe.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-telegram.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-trello.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-wechat.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-whatsapp.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/icon-zoom.tsx create mode 100644 new-api/web/default/src/assets/brand-icons/index.ts create mode 100644 new-api/web/default/src/assets/clerk-full-logo.tsx create mode 100644 new-api/web/default/src/assets/clerk-logo.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-dir.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-layout-compact.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-layout-default.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-layout-full.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-sidebar-floating.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-sidebar-inset.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-sidebar-sidebar.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-theme-dark.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-theme-light.tsx create mode 100644 new-api/web/default/src/assets/custom/icon-theme-system.tsx create mode 100644 new-api/web/default/src/assets/logo.tsx create mode 100644 new-api/web/default/src/components/ai-elements/actions.tsx create mode 100644 new-api/web/default/src/components/ai-elements/artifact.tsx create mode 100644 new-api/web/default/src/components/ai-elements/branch.tsx create mode 100644 new-api/web/default/src/components/ai-elements/canvas.tsx create mode 100644 new-api/web/default/src/components/ai-elements/chain-of-thought.tsx create mode 100644 new-api/web/default/src/components/ai-elements/code-block.tsx create mode 100644 new-api/web/default/src/components/ai-elements/confirmation.tsx create mode 100644 new-api/web/default/src/components/ai-elements/connection.tsx create mode 100644 new-api/web/default/src/components/ai-elements/context.tsx create mode 100644 new-api/web/default/src/components/ai-elements/controls.tsx create mode 100644 new-api/web/default/src/components/ai-elements/conversation.tsx create mode 100644 new-api/web/default/src/components/ai-elements/edge.tsx create mode 100644 new-api/web/default/src/components/ai-elements/image.tsx create mode 100644 new-api/web/default/src/components/ai-elements/inline-citation.tsx create mode 100644 new-api/web/default/src/components/ai-elements/loader.tsx create mode 100644 new-api/web/default/src/components/ai-elements/message.tsx create mode 100644 new-api/web/default/src/components/ai-elements/node.tsx create mode 100644 new-api/web/default/src/components/ai-elements/open-in-chat.tsx create mode 100644 new-api/web/default/src/components/ai-elements/panel.tsx create mode 100644 new-api/web/default/src/components/ai-elements/plan.tsx create mode 100644 new-api/web/default/src/components/ai-elements/prompt-input.tsx create mode 100644 new-api/web/default/src/components/ai-elements/queue.tsx create mode 100644 new-api/web/default/src/components/ai-elements/reasoning.tsx create mode 100644 new-api/web/default/src/components/ai-elements/response.tsx create mode 100644 new-api/web/default/src/components/ai-elements/shimmer.tsx create mode 100644 new-api/web/default/src/components/ai-elements/sources.tsx create mode 100644 new-api/web/default/src/components/ai-elements/suggestion.tsx create mode 100644 new-api/web/default/src/components/ai-elements/task.tsx create mode 100644 new-api/web/default/src/components/ai-elements/tool.tsx create mode 100644 new-api/web/default/src/components/ai-elements/toolbar.tsx create mode 100644 new-api/web/default/src/components/ai-elements/web-preview.tsx create mode 100644 new-api/web/default/src/components/animate-in-view.tsx create mode 100644 new-api/web/default/src/components/auto-skeleton.tsx create mode 100644 new-api/web/default/src/components/coming-soon.tsx create mode 100644 new-api/web/default/src/components/command-menu.tsx create mode 100644 new-api/web/default/src/components/config-drawer.tsx create mode 100644 new-api/web/default/src/components/confirm-dialog.tsx create mode 100644 new-api/web/default/src/components/copy-button.tsx create mode 100644 new-api/web/default/src/components/data-table/bulk-actions.tsx create mode 100644 new-api/web/default/src/components/data-table/column-header.tsx create mode 100644 new-api/web/default/src/components/data-table/faceted-filter.tsx create mode 100644 new-api/web/default/src/components/data-table/index.ts create mode 100644 new-api/web/default/src/components/data-table/mobile-card-list.tsx create mode 100644 new-api/web/default/src/components/data-table/pagination.tsx create mode 100644 new-api/web/default/src/components/data-table/table-empty.tsx create mode 100644 new-api/web/default/src/components/data-table/table-skeleton.tsx create mode 100644 new-api/web/default/src/components/data-table/toolbar.tsx create mode 100644 new-api/web/default/src/components/data-table/view-options.tsx create mode 100644 new-api/web/default/src/components/date-picker.tsx create mode 100644 new-api/web/default/src/components/datetime-picker.tsx create mode 100644 new-api/web/default/src/components/empty-state.tsx create mode 100644 new-api/web/default/src/components/error-state.tsx create mode 100644 new-api/web/default/src/components/json-editor.tsx create mode 100644 new-api/web/default/src/components/language-switcher.tsx create mode 100644 new-api/web/default/src/components/layout/components/app-header.tsx create mode 100644 new-api/web/default/src/components/layout/components/app-sidebar.tsx create mode 100644 new-api/web/default/src/components/layout/components/authenticated-layout.tsx create mode 100644 new-api/web/default/src/components/layout/components/chat-presets-item.tsx create mode 100644 new-api/web/default/src/components/layout/components/footer.tsx create mode 100644 new-api/web/default/src/components/layout/components/glow.tsx create mode 100644 new-api/web/default/src/components/layout/components/header-logo.tsx create mode 100644 new-api/web/default/src/components/layout/components/header.tsx create mode 100644 new-api/web/default/src/components/layout/components/logo.tsx create mode 100644 new-api/web/default/src/components/layout/components/main.tsx create mode 100644 new-api/web/default/src/components/layout/components/mobile-drawer.tsx create mode 100644 new-api/web/default/src/components/layout/components/mockup.tsx create mode 100644 new-api/web/default/src/components/layout/components/nav-group.tsx create mode 100644 new-api/web/default/src/components/layout/components/nav-link-item.tsx create mode 100644 new-api/web/default/src/components/layout/components/navbar.tsx create mode 100644 new-api/web/default/src/components/layout/components/page-footer.tsx create mode 100644 new-api/web/default/src/components/layout/components/public-header.tsx create mode 100644 new-api/web/default/src/components/layout/components/public-layout.tsx create mode 100644 new-api/web/default/src/components/layout/components/public-navigation.tsx create mode 100644 new-api/web/default/src/components/layout/components/section-page-layout.tsx create mode 100644 new-api/web/default/src/components/layout/components/section.tsx create mode 100644 new-api/web/default/src/components/layout/components/top-nav.tsx create mode 100644 new-api/web/default/src/components/layout/components/workspace-switcher.tsx create mode 100644 new-api/web/default/src/components/layout/config/system-settings.config.ts create mode 100644 new-api/web/default/src/components/layout/config/top-nav.config.ts create mode 100644 new-api/web/default/src/components/layout/constants.ts create mode 100644 new-api/web/default/src/components/layout/context/workspace-context.tsx create mode 100644 new-api/web/default/src/components/layout/index.ts create mode 100644 new-api/web/default/src/components/layout/lib/url-utils.ts create mode 100644 new-api/web/default/src/components/layout/lib/workspace-registry.example.ts create mode 100644 new-api/web/default/src/components/layout/lib/workspace-registry.ts create mode 100644 new-api/web/default/src/components/layout/types.ts create mode 100644 new-api/web/default/src/components/learn-more.tsx create mode 100644 new-api/web/default/src/components/loading-state.tsx create mode 100644 new-api/web/default/src/components/long-text.tsx create mode 100644 new-api/web/default/src/components/masked-value-display.tsx create mode 100644 new-api/web/default/src/components/model-group-selector.tsx create mode 100644 new-api/web/default/src/components/multi-select.tsx create mode 100644 new-api/web/default/src/components/navigation-progress.tsx create mode 100644 new-api/web/default/src/components/notification-button.tsx create mode 100644 new-api/web/default/src/components/notification-dialog.tsx create mode 100644 new-api/web/default/src/components/page-transition.tsx create mode 100644 new-api/web/default/src/components/password-input.tsx create mode 100644 new-api/web/default/src/components/profile-dropdown.tsx create mode 100644 new-api/web/default/src/components/search.tsx create mode 100644 new-api/web/default/src/components/select-dropdown.tsx create mode 100644 new-api/web/default/src/components/sign-out-dialog.tsx create mode 100644 new-api/web/default/src/components/skip-to-main.tsx create mode 100644 new-api/web/default/src/components/status-badge.tsx create mode 100644 new-api/web/default/src/components/tag-input.tsx create mode 100644 new-api/web/default/src/components/theme-quick-switcher.tsx create mode 100644 new-api/web/default/src/components/theme-switch.tsx create mode 100644 new-api/web/default/src/components/turnstile.tsx create mode 100644 new-api/web/default/src/components/ui/accordion.tsx create mode 100644 new-api/web/default/src/components/ui/alert-dialog.tsx create mode 100644 new-api/web/default/src/components/ui/alert.tsx create mode 100644 new-api/web/default/src/components/ui/avatar.tsx create mode 100644 new-api/web/default/src/components/ui/badge.tsx create mode 100644 new-api/web/default/src/components/ui/button.tsx create mode 100644 new-api/web/default/src/components/ui/calendar.tsx create mode 100644 new-api/web/default/src/components/ui/card.tsx create mode 100644 new-api/web/default/src/components/ui/carousel.tsx create mode 100644 new-api/web/default/src/components/ui/checkbox.tsx create mode 100644 new-api/web/default/src/components/ui/collapsible.tsx create mode 100644 new-api/web/default/src/components/ui/combobox-input.tsx create mode 100644 new-api/web/default/src/components/ui/combobox.tsx create mode 100644 new-api/web/default/src/components/ui/command.tsx create mode 100644 new-api/web/default/src/components/ui/dialog.tsx create mode 100644 new-api/web/default/src/components/ui/drawer.tsx create mode 100644 new-api/web/default/src/components/ui/dropdown-menu.tsx create mode 100644 new-api/web/default/src/components/ui/empty.tsx create mode 100644 new-api/web/default/src/components/ui/form.tsx create mode 100644 new-api/web/default/src/components/ui/hover-card.tsx create mode 100644 new-api/web/default/src/components/ui/input-group.tsx create mode 100644 new-api/web/default/src/components/ui/input-otp.tsx create mode 100644 new-api/web/default/src/components/ui/input.tsx create mode 100644 new-api/web/default/src/components/ui/label.tsx create mode 100644 new-api/web/default/src/components/ui/markdown.tsx create mode 100644 new-api/web/default/src/components/ui/popover.tsx create mode 100644 new-api/web/default/src/components/ui/progress.tsx create mode 100644 new-api/web/default/src/components/ui/radio-group.tsx create mode 100644 new-api/web/default/src/components/ui/scroll-area.tsx create mode 100644 new-api/web/default/src/components/ui/select.tsx create mode 100644 new-api/web/default/src/components/ui/separator.tsx create mode 100644 new-api/web/default/src/components/ui/sheet.tsx create mode 100644 new-api/web/default/src/components/ui/sidebar.tsx create mode 100644 new-api/web/default/src/components/ui/skeleton.tsx create mode 100644 new-api/web/default/src/components/ui/sonner.tsx create mode 100644 new-api/web/default/src/components/ui/switch.tsx create mode 100644 new-api/web/default/src/components/ui/table.tsx create mode 100644 new-api/web/default/src/components/ui/tabs.tsx create mode 100644 new-api/web/default/src/components/ui/textarea.tsx create mode 100644 new-api/web/default/src/components/ui/tooltip.tsx create mode 100644 new-api/web/default/src/config/fonts.ts create mode 100644 new-api/web/default/src/context/direction-provider.tsx create mode 100644 new-api/web/default/src/context/font-provider.tsx create mode 100644 new-api/web/default/src/context/layout-provider.tsx create mode 100644 new-api/web/default/src/context/search-provider.tsx create mode 100644 new-api/web/default/src/context/theme-provider.tsx create mode 100644 new-api/web/default/src/env.d.ts create mode 100644 new-api/web/default/src/features/about/api.ts create mode 100644 new-api/web/default/src/features/about/index.tsx create mode 100644 new-api/web/default/src/features/about/types.ts create mode 100644 new-api/web/default/src/features/auth/sign-in/components/user-auth-form.tsx create mode 100644 new-api/web/default/src/features/channels/api.ts create mode 100644 new-api/web/default/src/features/channels/components/channels-columns.tsx create mode 100644 new-api/web/default/src/features/channels/components/channels-dialogs.tsx create mode 100644 new-api/web/default/src/features/channels/components/channels-primary-buttons.tsx create mode 100644 new-api/web/default/src/features/channels/components/channels-provider.tsx create mode 100644 new-api/web/default/src/features/channels/components/channels-table.tsx create mode 100644 new-api/web/default/src/features/channels/components/data-table-bulk-actions.tsx create mode 100644 new-api/web/default/src/features/channels/components/data-table-row-actions.tsx create mode 100644 new-api/web/default/src/features/channels/components/data-table-tag-row-actions.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/balance-query-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/codex-oauth-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/codex-usage-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/copy-channel-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/edit-tag-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/fetch-models-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/missing-models-confirmation-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/multi-key-manage-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/multi-key-statistics-card.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/multi-key-table-row-actions.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/ollama-models-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/status-code-risk-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/tag-batch-edit-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/dialogs/upstream-update-dialog.tsx create mode 100644 new-api/web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx create mode 100644 new-api/web/default/src/features/channels/components/model-mapping-editor.tsx create mode 100644 new-api/web/default/src/features/channels/components/numeric-spinner-input.tsx create mode 100644 new-api/web/default/src/features/channels/constants.ts create mode 100644 new-api/web/default/src/features/channels/hooks/use-channel-upstream-updates.ts create mode 100644 new-api/web/default/src/features/channels/index.tsx create mode 100644 new-api/web/default/src/features/channels/lib/channel-actions.ts create mode 100644 new-api/web/default/src/features/channels/lib/channel-form.ts create mode 100644 new-api/web/default/src/features/channels/lib/channel-type-config.ts create mode 100644 new-api/web/default/src/features/channels/lib/channel-utils.ts create mode 100644 new-api/web/default/src/features/channels/lib/index.ts create mode 100644 new-api/web/default/src/features/channels/lib/model-mapping-validation.ts create mode 100644 new-api/web/default/src/features/channels/lib/multi-key-utils.ts create mode 100644 new-api/web/default/src/features/channels/lib/ollama-utils.ts create mode 100644 new-api/web/default/src/features/channels/lib/status-code-risk-guard.ts create mode 100644 new-api/web/default/src/features/channels/lib/upstream-update-utils.ts create mode 100644 new-api/web/default/src/features/channels/types.ts create mode 100644 new-api/web/default/src/features/chat/hooks/use-active-chat-key.ts create mode 100644 new-api/web/default/src/features/chat/hooks/use-chat-presets.ts create mode 100644 new-api/web/default/src/features/chat/lib/chat-links.ts create mode 100644 new-api/web/default/src/features/chat/lib/send-to-fluent.ts create mode 100644 new-api/web/default/src/features/dashboard/hooks/use-dashboard-config.tsx create mode 100644 new-api/web/default/src/features/errors/forbidden.tsx create mode 100644 new-api/web/default/src/features/errors/general-error.tsx create mode 100644 new-api/web/default/src/features/errors/maintenance-error.tsx create mode 100644 new-api/web/default/src/features/errors/not-found-error.tsx create mode 100644 new-api/web/default/src/features/errors/unauthorized-error.tsx create mode 100644 new-api/web/default/src/features/home/api.ts create mode 100644 new-api/web/default/src/features/home/components/connection-line.tsx create mode 100644 new-api/web/default/src/features/home/components/feature-item.tsx create mode 100644 new-api/web/default/src/features/home/components/gateway-card.tsx create mode 100644 new-api/web/default/src/features/home/components/hero-buttons.tsx create mode 100644 new-api/web/default/src/features/home/components/hero-terminal-demo.tsx create mode 100644 new-api/web/default/src/features/home/components/icon-card.tsx create mode 100644 new-api/web/default/src/features/home/components/index.ts create mode 100644 new-api/web/default/src/features/home/components/scrolling-icons.tsx create mode 100644 new-api/web/default/src/features/home/components/sections/cta.tsx create mode 100644 new-api/web/default/src/features/home/components/sections/features.tsx create mode 100644 new-api/web/default/src/features/home/components/sections/hero.tsx create mode 100644 new-api/web/default/src/features/home/components/sections/how-it-works.tsx create mode 100644 new-api/web/default/src/features/home/components/sections/stats.tsx create mode 100644 new-api/web/default/src/features/home/components/stat-item.tsx create mode 100644 new-api/web/default/src/features/home/constants.ts create mode 100644 new-api/web/default/src/features/home/hooks/index.ts create mode 100644 new-api/web/default/src/features/home/hooks/use-home-page-content.ts create mode 100644 new-api/web/default/src/features/home/index.tsx create mode 100644 new-api/web/default/src/features/home/lib/icon-mapper.tsx create mode 100644 new-api/web/default/src/features/home/types.ts create mode 100644 new-api/web/default/src/features/keys/api.ts create mode 100644 new-api/web/default/src/features/keys/components/api-key-group-combobox.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-cells.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-columns.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-delete-dialog.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-dialogs.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-multi-delete-dialog.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-mutate-drawer.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-primary-buttons.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-provider.tsx create mode 100644 new-api/web/default/src/features/keys/components/api-keys-table.tsx create mode 100644 new-api/web/default/src/features/keys/components/data-table-bulk-actions.tsx create mode 100644 new-api/web/default/src/features/keys/components/data-table-row-actions.tsx create mode 100644 new-api/web/default/src/features/keys/components/dialogs/cc-switch-dialog.tsx create mode 100644 new-api/web/default/src/features/keys/constants.ts create mode 100644 new-api/web/default/src/features/keys/index.tsx create mode 100644 new-api/web/default/src/features/keys/lib/api-key-form.ts create mode 100644 new-api/web/default/src/features/keys/lib/index.ts create mode 100644 new-api/web/default/src/features/keys/types.ts create mode 100644 new-api/web/default/src/features/models/api.ts create mode 100644 new-api/web/default/src/features/models/components/data-table-bulk-actions.tsx create mode 100644 new-api/web/default/src/features/models/components/data-table-row-actions.tsx create mode 100644 new-api/web/default/src/features/models/components/deployment-access-guard.tsx create mode 100644 new-api/web/default/src/features/models/components/deployments-columns.tsx create mode 100644 new-api/web/default/src/features/models/components/deployments-table.tsx create mode 100644 new-api/web/default/src/features/models/components/description-cell.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/create-deployment-drawer.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/extend-deployment-dialog.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/missing-models-dialog.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/prefill-group-management-dialog.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/prefill-group-management.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/vendor-mutate-dialog.tsx create mode 100644 new-api/web/default/src/features/models/components/dialogs/view-details-dialog.tsx create mode 100644 new-api/web/default/src/features/models/components/drawers/model-mutate-drawer.tsx create mode 100644 new-api/web/default/src/features/models/components/drawers/prefill-group-form-drawer.tsx create mode 100644 new-api/web/default/src/features/models/components/models-columns.tsx create mode 100644 new-api/web/default/src/features/models/components/models-dialogs.tsx create mode 100644 new-api/web/default/src/features/models/components/models-primary-buttons.tsx create mode 100644 new-api/web/default/src/features/models/components/models-provider.tsx create mode 100644 new-api/web/default/src/features/models/components/models-table.tsx create mode 100644 new-api/web/default/src/features/models/components/prefill-group-shared.ts create mode 100644 new-api/web/default/src/features/models/hooks/use-model-deployment-settings.ts create mode 100644 new-api/web/default/src/features/models/index.tsx create mode 100644 new-api/web/default/src/features/models/lib/deployments-utils.ts create mode 100644 new-api/web/default/src/features/models/lib/index.ts create mode 100644 new-api/web/default/src/features/models/lib/model-actions.ts create mode 100644 new-api/web/default/src/features/models/lib/model-form.ts create mode 100644 new-api/web/default/src/features/models/lib/model-utils.ts create mode 100644 new-api/web/default/src/features/models/lib/query-keys.ts create mode 100644 new-api/web/default/src/features/models/lib/vendor-actions.ts create mode 100644 new-api/web/default/src/features/models/section-registry.tsx create mode 100644 new-api/web/default/src/features/playground/components/message-action-button.tsx create mode 100644 new-api/web/default/src/features/playground/components/message-error.tsx create mode 100644 new-api/web/default/src/features/playground/components/playground-chat.tsx create mode 100644 new-api/web/default/src/features/playground/index.tsx create mode 100644 new-api/web/default/src/features/pricing/api.ts create mode 100644 new-api/web/default/src/features/pricing/components/model-row.tsx create mode 100644 new-api/web/default/src/features/profile/components/tabs/notification-tab.tsx create mode 100644 new-api/web/default/src/features/profile/hooks/use-access-token.ts create mode 100644 new-api/web/default/src/features/redemption-codes/lib/index.ts create mode 100644 new-api/web/default/src/features/setup/api.ts create mode 100644 new-api/web/default/src/features/setup/components/admin-step.tsx create mode 100644 new-api/web/default/src/features/setup/components/complete-step.tsx create mode 100644 new-api/web/default/src/features/setup/components/database-step.tsx create mode 100644 new-api/web/default/src/features/setup/components/step-navigation.tsx create mode 100644 new-api/web/default/src/features/setup/components/usage-mode-step.tsx create mode 100644 new-api/web/default/src/features/setup/index.ts create mode 100644 new-api/web/default/src/features/setup/setup-wizard.tsx create mode 100644 new-api/web/default/src/features/setup/types.ts create mode 100644 new-api/web/default/src/features/subscriptions/components/subscriptions-mutate-drawer.tsx create mode 100644 new-api/web/default/src/features/system-settings/api.ts create mode 100644 new-api/web/default/src/features/system-settings/auth/basic-auth-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/bot-protection-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/api.ts create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/components/discovery-button.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/components/preset-selector.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/components/provider-form-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/components/provider-table.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/custom-oauth-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/hooks/use-custom-oauth-mutations.ts create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/hooks/use-custom-oauth-providers.ts create mode 100644 new-api/web/default/src/features/system-settings/auth/custom-oauth/types.ts create mode 100644 new-api/web/default/src/features/system-settings/auth/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/oauth-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/passkey-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/auth/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/form-dirty-indicator.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/form-navigation-guard.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/settings-accordion.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/settings-page.tsx create mode 100644 new-api/web/default/src/features/system-settings/components/settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/announcements-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/api-info-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/chat-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/chat-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/chat-settings-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/dashboard-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/drawing-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/faq-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/json-toggle-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/uptime-kuma-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/content/utils.ts create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/api.ts create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/cache-stats-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/constants.ts create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/rule-editor-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/channel-affinity/types.ts create mode 100644 new-api/web/default/src/features/system-settings/general/checkin-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/pricing-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/quota-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/system-behavior-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/general/system-info-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-accordion-state.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-form-dirty-guard.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-reset-form.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-safe-json-state.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-settings-form.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-system-options.ts create mode 100644 new-api/web/default/src/features/system-settings/hooks/use-update-option.ts create mode 100644 new-api/web/default/src/features/system-settings/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/amount-discount-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/amount-discount-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/amount-options-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/creem-product-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/creem-products-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/email-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/ionet-deployment-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/monitoring-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/payment-method-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/payment-methods-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/payment-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/utils.ts create mode 100644 new-api/web/default/src/features/system-settings/integrations/waffo-pancake-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/waffo-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/integrations/worker-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/config.ts create mode 100644 new-api/web/default/src/features/system-settings/maintenance/header-navigation-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/log-settings-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/notice-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/performance-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/sidebar-modules-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/maintenance/update-checker-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/channel-selector-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/claude-settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/conflict-confirm-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/constants.ts create mode 100644 new-api/web/default/src/features/system-settings/models/gemini-settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/global-settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/grok-settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/group-ratio-form.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/group-ratio-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/group-special-usable-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/model-ratio-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/model-ratio-form.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/model-ratio-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/ratio-settings-card.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/tiered-pricing-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/tool-price-settings.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/upstream-ratio-sync-columns.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/upstream-ratio-sync-helpers.ts create mode 100644 new-api/web/default/src/features/system-settings/models/upstream-ratio-sync-table.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/upstream-ratio-sync.tsx create mode 100644 new-api/web/default/src/features/system-settings/models/utils.ts create mode 100644 new-api/web/default/src/features/system-settings/request-limits/index.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/rate-limit-dialog.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/rate-limit-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/rate-limit-visual-editor.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/section-registry.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/sensitive-words-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/request-limits/ssrf-section.tsx create mode 100644 new-api/web/default/src/features/system-settings/types.ts create mode 100644 new-api/web/default/src/features/system-settings/utils/json-parser.ts create mode 100644 new-api/web/default/src/features/system-settings/utils/json-validators.ts create mode 100644 new-api/web/default/src/features/system-settings/utils/route-config.ts create mode 100644 new-api/web/default/src/features/system-settings/utils/section-registry.ts create mode 100644 new-api/web/default/src/features/usage-logs/components/columns/common-logs-columns.tsx create mode 100644 new-api/web/default/src/features/usage-logs/components/dialogs/fail-reason-dialog.tsx create mode 100644 new-api/web/default/src/features/wallet/api.ts create mode 100644 new-api/web/default/src/features/wallet/components/affiliate-rewards-card.tsx create mode 100644 new-api/web/default/src/features/wallet/components/creem-products-section.tsx create mode 100644 new-api/web/default/src/features/wallet/components/dialogs/billing-history-dialog.tsx create mode 100644 new-api/web/default/src/features/wallet/components/dialogs/creem-confirm-dialog.tsx create mode 100644 new-api/web/default/src/features/wallet/components/dialogs/payment-confirm-dialog.tsx create mode 100644 new-api/web/default/src/features/wallet/components/dialogs/transfer-dialog.tsx create mode 100644 new-api/web/default/src/features/wallet/components/recharge-form-card.tsx create mode 100644 new-api/web/default/src/features/wallet/components/subscription-plans-card.tsx create mode 100644 new-api/web/default/src/features/wallet/components/wallet-stats-card.tsx create mode 100644 new-api/web/default/src/features/wallet/constants.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/index.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-affiliate.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-billing-history.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-creem-payment.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-payment.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-redemption.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-topup-info.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-waffo-pancake-payment.ts create mode 100644 new-api/web/default/src/features/wallet/hooks/use-waffo-payment.ts create mode 100644 new-api/web/default/src/features/wallet/index.tsx create mode 100644 new-api/web/default/src/features/wallet/lib/affiliate.ts create mode 100644 new-api/web/default/src/features/wallet/lib/billing.ts create mode 100644 new-api/web/default/src/features/wallet/lib/format.ts create mode 100644 new-api/web/default/src/features/wallet/lib/index.ts create mode 100644 new-api/web/default/src/features/wallet/lib/payment.ts create mode 100644 new-api/web/default/src/features/wallet/lib/ui.tsx create mode 100644 new-api/web/default/src/features/wallet/types.ts create mode 100644 new-api/web/default/src/hooks/index.ts create mode 100644 new-api/web/default/src/hooks/use-admin.ts create mode 100644 new-api/web/default/src/hooks/use-copy-to-clipboard.ts create mode 100644 new-api/web/default/src/hooks/use-countdown.ts create mode 100644 new-api/web/default/src/hooks/use-debounce.ts create mode 100644 new-api/web/default/src/hooks/use-dialog.ts create mode 100644 new-api/web/default/src/hooks/use-hidden-click-unlock.ts create mode 100644 new-api/web/default/src/hooks/use-media-query.ts create mode 100644 new-api/web/default/src/hooks/use-minimum-loading-time.ts create mode 100644 new-api/web/default/src/hooks/use-mobile.tsx create mode 100644 new-api/web/default/src/hooks/use-notifications.ts create mode 100644 new-api/web/default/src/hooks/use-sidebar-config.ts create mode 100644 new-api/web/default/src/hooks/use-sidebar-data.ts create mode 100644 new-api/web/default/src/hooks/use-status.ts create mode 100644 new-api/web/default/src/hooks/use-system-config.ts create mode 100644 new-api/web/default/src/hooks/use-table-compact-mode.ts create mode 100644 new-api/web/default/src/hooks/use-table-url-state.ts create mode 100644 new-api/web/default/src/hooks/use-top-nav-links.ts create mode 100644 new-api/web/default/src/hooks/use-user-display.ts create mode 100644 new-api/web/default/src/i18n/config.ts create mode 100644 new-api/web/default/src/i18n/locales/_reports/_sync-report.json create mode 100644 new-api/web/default/src/i18n/locales/_reports/fr.untranslated.json create mode 100644 new-api/web/default/src/i18n/locales/_reports/ja.untranslated.json create mode 100644 new-api/web/default/src/i18n/locales/_reports/ru.untranslated.json create mode 100644 new-api/web/default/src/i18n/locales/_reports/vi.untranslated.json create mode 100644 new-api/web/default/src/i18n/locales/_reports/zh.untranslated.json create mode 100644 new-api/web/default/src/i18n/locales/en.json create mode 100644 new-api/web/default/src/i18n/locales/fr.json create mode 100644 new-api/web/default/src/i18n/locales/ja.json create mode 100644 new-api/web/default/src/i18n/locales/ru.json create mode 100644 new-api/web/default/src/i18n/locales/vi.json create mode 100644 new-api/web/default/src/i18n/locales/zh.json create mode 100644 new-api/web/default/src/i18n/static-keys.ts create mode 100644 new-api/web/default/src/lib/api.ts create mode 100644 new-api/web/default/src/lib/colors.ts create mode 100644 new-api/web/default/src/lib/constants.ts create mode 100644 new-api/web/default/src/lib/cookies.ts create mode 100644 new-api/web/default/src/lib/copy-to-clipboard.ts create mode 100644 new-api/web/default/src/lib/currency.ts create mode 100644 new-api/web/default/src/lib/dayjs.ts create mode 100644 new-api/web/default/src/lib/dom-utils.ts create mode 100644 new-api/web/default/src/lib/format.ts create mode 100644 new-api/web/default/src/lib/handle-server-error.ts create mode 100644 new-api/web/default/src/lib/http-status-code-rules.ts create mode 100644 new-api/web/default/src/lib/lobe-icon.tsx create mode 100644 new-api/web/default/src/lib/motion.ts create mode 100644 new-api/web/default/src/lib/oauth.ts create mode 100644 new-api/web/default/src/lib/passkey.ts create mode 100644 new-api/web/default/src/lib/roles.ts create mode 100644 new-api/web/default/src/lib/secure-verification.ts create mode 100644 new-api/web/default/src/lib/show-submitted-data.tsx create mode 100644 new-api/web/default/src/lib/time.ts create mode 100644 new-api/web/default/src/lib/utils.ts create mode 100644 new-api/web/default/src/lib/vchart.ts create mode 100644 new-api/web/default/src/routeTree.gen.ts create mode 100644 new-api/web/default/src/routes/about/index.tsx create mode 100644 new-api/web/default/src/stores/auth-store.ts create mode 100644 new-api/web/default/src/stores/notification-store.ts create mode 100644 new-api/web/default/src/stores/system-config-store.ts create mode 100644 new-api/web/default/src/styles/index.css create mode 100644 new-api/web/default/src/styles/theme.css create mode 100644 new-api/web/default/src/tanstack-table.d.ts create mode 100644 new-api/web/default/tsconfig.app.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d5dd4c --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Dependencies +node_modules/ + +# Build / cache +**/target/ +dist/ +build/ +.turbo/ +.next/ +*.tsbuildinfo + +# Environment +.env +.env.* +!.env.example + +# OS / IDE +.DS_Store +.idea/ +.vscode/ +*.swp +*.swo + +# Logs +*.log +logs/ + +# Go +*.exe +*.test +*.out diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ffee0a --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# Heicode + +Heicode 是一个**面向团队的智能体驱动软件交付**工作区:把 **改造后的大模型网关(New API)**、**终端与桌面上的智能体编程客户端(cc-haha)**,以及 **Agnet 平台上的子智能体团队** 串成一条从想法到上线、再到运维迭代的闭环。 + +## 这个仓库里有什么 + +| 目录 | 作用 | +|------|------| +| `new-api/` | 基于 New API 生态的 **网关与运营能力**(模型渠道、计费、鉴权、多协议中继等),经深度改造后作为用户登录后看到的 **后台与 API 能力层**。 | +| `cc-haha/` | **CLI / 本地服务 / Desktop(Tauri)** 相关代码,提供类 **Claude Code** 的编程与协作体验,并与 New API 对齐登录与接口。 | +| `_all-in-one-upload/` | 历史或打包上传相关目录(按需维护)。 | + +## 产品在解决什么问题 + +- **自动化开发范式**:不止「写代码」,而是覆盖需求、实现、测试、**多云部署**、运维与迭代的 **标准化团队模式**(瀑布 / 敏捷模板 + 子智能体规模可配置)。 +- **平台整合**:用户从官网进入 → 使用改造后的 **New API** 控制台 → 下载 **CLI** 与 **Desktop** → 与 **Agnet** 上已部署的 **子智能体团队** 协同;子智能体可具备 Git 与云资源(GCP / AWS / Azure)的**策略化**自动化能力。 +- **可审计交付**:多智能体协作记录、产品文档、开发日志等与版本和发布关联。 + +## 详细愿景与范式说明 + +完整的产品叙事、三问回答、架构分层、用户旅程、**瀑布(5~9)与敏捷(3~8)子 Agnet 角色清单**、风险与路线图见: + +**[docs/vision-heicode-full-stack-agentic-dev.md](./docs/vision-heicode-full-stack-agentic-dev.md)** + +## 相关外部参考(概念) + +- [oh-my-claudecode](https://ohmyclaudecode.com/) — 高效使用 Claude Code 类工具的实践与脚手架方向。 +- Agnet 平台文档(部署与编排由平台侧提供)— 集成时以平台当前 API 与权限模型为准。 + +## 许可证 + +各子项目可能沿用不同开源许可证(例如 `new-api` 侧常见为 AGPLv3),请以各子目录内 `LICENSE` 为准。 diff --git a/_all-in-one-upload/cc-haha/adapters/README.md b/_all-in-one-upload/cc-haha/adapters/README.md new file mode 100644 index 0000000..fbc41f7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/adapters/README.md @@ -0,0 +1,87 @@ +# Claude Code IM Adapters + +当前目录只放 IM Adapter 运行时代码。 + +用户文档已经迁移到 `docs/`,并且以 Desktop Webapp 配置流程为准: + +- `docs/im/index.md` +- `docs/im/telegram.md` +- `docs/im/feishu.md` + +## 当前方案摘要 + +当前真实链路是: + +```text +Desktop Webapp Settings + -> /api/adapters + -> ~/.claude/adapters.json + -> adapters//index.ts + -> /api/sessions + /ws/:sessionId + -> Claude Code session +``` + +注意两点: + +- IM 配置和配对都在 Desktop Webapp 的 `Settings -> IM 接入` +- Webapp 不会自动启动 Adapter 进程,仍需手动运行 `bun run telegram` 或 `bun run feishu` + +## 快速启动 + +```bash +cd adapters +bun install +bun run telegram +# 或 +bun run feishu +``` + +## 开发 + +### 运行测试 + +```bash +cd adapters +bun test +bun test common/ +bun test telegram/ +bun test feishu/ +``` + +### 目录结构 + +```text +adapters/ +├── common/ +│ └── attachment/ # 跨平台附件工具(types / limits / store / image-watcher) +├── telegram/ +│ └── media.ts # TelegramMediaService(grammy Bot API 封装) +├── feishu/ +│ ├── media.ts # FeishuMediaService(@larksuiteoapi/node-sdk 封装) +│ └── extract-payload.ts # 入站 im.message.receive_v1 事件解析 +├── package.json +├── tsconfig.json +└── README.md +``` + +## 附件收发 + +两个 Adapter 都支持双向图片/文件,和 Desktop 端走同一套 `AttachmentRef` 协议透传给主进程。 + +**入站(用户 → Claude):** + +- 飞书: 图片(jpg/png/gif/webp/heic)、文档(doc/xls/ppt/pdf 等)、post 富文本里的 img/file 元素 +- Telegram: photo、document、video、audio、voice + +下载落地到 `~/.claude/im-downloads/{platform}/{sessionId}/`,24 小时后自动 GC(`.part` 孤文件 10 分钟超时)。大小限制:单张图 ≤10 MB、单个文件 ≤30 MB,超限直接拒收并在 IM 里提示。 + +**出站(Claude → 用户):** + +Agent 流式文本里的 markdown 图片引用 `![alt](path|url|data:)` 会被 `ImageBlockWatcher` 识别、上传到 IM 平台,作为独立图片消息发出: + +- 飞书: `im.message.create(msg_type='image')` 单发(card 内嵌是后续优化) +- Telegram: `bot.api.sendPhoto(InputFile)` 单发 + +非图片类出站(Agent 产的 pdf/zip 等)暂不支持。 + +设计细节: `docs/superpowers/specs/2026-04-11-im-attachment-support-design.md`。 diff --git a/_all-in-one-upload/cc-haha/desktop/src-tauri/gen/schemas/acl-manifests.json b/_all-in-one-upload/cc-haha/desktop/src-tauri/gen/schemas/acl-manifests.json new file mode 100644 index 0000000..ff2a40c --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src-tauri/gen/schemas/acl-manifests.json @@ -0,0 +1 @@ +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"process":{"default_permission":{"identifier":"default","description":"This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n","permissions":["allow-exit","allow-restart"]},"permissions":{"allow-exit":{"identifier":"allow-exit","description":"Enables the exit command without any pre-configured scope.","commands":{"allow":["exit"],"deny":[]}},"allow-restart":{"identifier":"allow-restart","description":"Enables the restart command without any pre-configured scope.","commands":{"allow":["restart"],"deny":[]}},"deny-exit":{"identifier":"deny-exit","description":"Denies the exit command without any pre-configured scope.","commands":{"allow":[],"deny":["exit"]}},"deny-restart":{"identifier":"deny-restart","description":"Denies the restart command without any pre-configured scope.","commands":{"allow":[],"deny":["restart"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/desktop/src-tauri/icons/Square30x30Logo.png b/_all-in-one-upload/cc-haha/desktop/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..330ee2136669f689cd9ec032943f13b7cef987cd GIT binary patch literal 1340 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 EKT}%K-T(jq literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/desktop/src-tauri/src/lib.rs b/_all-in-one-upload/cc-haha/desktop/src-tauri/src/lib.rs new file mode 100644 index 0000000..c6a33d0 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src-tauri/src/lib.rs @@ -0,0 +1,1106 @@ +use std::{ + collections::{HashMap, VecDeque}, + io::{Error as IoError, ErrorKind, Read, Write}, + net::{SocketAddr, TcpListener, TcpStream}, + path::PathBuf, + process::{Command as StdCommand, Stdio}, + str, + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, Mutex, + }, + thread, + time::{Duration, Instant}, +}; + +use portable_pty::{native_pty_system, ChildKiller, CommandBuilder, MasterPty, PtySize}; +use serde::Serialize; +use tauri::menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder}; +use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}; +use tauri::Emitter; +use tauri::{AppHandle, Manager, RunEvent, State, WindowEvent}; +use tauri_plugin_shell::{ + process::{CommandChild, CommandEvent}, + ShellExt, +}; + +const SERVER_STARTUP_LOG_LIMIT: usize = 80; +const MAIN_WINDOW_LABEL: &str = "main"; +const TRAY_SHOW_ID: &str = "tray_show"; +const TRAY_QUIT_ID: &str = "tray_quit"; + +#[derive(Default)] +struct ServerState(Mutex); + +struct ServerRuntime { + url: String, + child: CommandChild, +} + +#[derive(Default)] +struct ServerStatus { + runtime: Option, + startup_error: Option, +} + +#[derive(Default)] +struct AppExitState { + is_quitting: Mutex, +} + +/// 与 ServerState 平级的 adapter 子进程状态。 +/// +/// adapter sidecar(claude-sidecar adapters --feishu --telegram)的生命周期 +/// 跟 server 不同:它没有 HTTP 端口可探活,没配凭据时会自己干净退出, +/// 而且需要支持运行时热重启 —— 用户在设置页保存飞书 / Telegram 凭据后, +/// 前端会通过 invoke('restart_adapters_sidecar') 来重启它,让新凭据生效。 +#[derive(Default)] +struct AdapterState(Mutex>); + +#[derive(Default)] +struct TerminalState { + next_id: AtomicU32, + sessions: Mutex>, +} + +struct TerminalSession { + master: Box, + writer: Mutex>, + killer: Mutex>, +} + +#[derive(Serialize, Clone)] +struct TerminalSpawnResult { + session_id: u32, + shell: String, + cwd: String, +} + +#[derive(Serialize, Clone)] +struct TerminalOutputPayload { + session_id: u32, + data: String, +} + +#[derive(Serialize, Clone)] +struct TerminalExitPayload { + session_id: u32, + code: u32, + signal: Option, +} + +#[tauri::command] +fn get_server_url(state: State<'_, ServerState>) -> Result { + let guard = state + .0 + .lock() + .map_err(|_| "desktop server state is unavailable".to_string())?; + + if let Some(runtime) = guard.runtime.as_ref() { + return Ok(runtime.url.clone()); + } + + Err(guard + .startup_error + .clone() + .unwrap_or_else(|| "desktop server did not start".to_string())) +} + +/// 前端在设置页保存飞书 / Telegram 凭据后调用,触发 adapter sidecar 热重启。 +/// +/// 流程: +/// 1. kill 当前 adapter 子进程(如果在跑) +/// 2. spawn 新的 adapter 子进程 +/// 3. 新 sidecar 内部的 loadConfig() 会读到最新的 ~/.claude/adapters.json +/// 并重新建立 WebSocket 连接到飞书 / Telegram +/// +/// 凭据缺失时 sidecar 自己会 warn + skip + 退出,所以这里不需要前置检查。 +#[tauri::command] +fn restart_adapters_sidecar(app: AppHandle) -> Result<(), String> { + stop_adapters_sidecar(&app); + spawn_and_track_adapters_sidecar(&app); + Ok(()) +} + +#[tauri::command] +fn prepare_for_update_install(app: AppHandle) -> Result<(), String> { + mark_app_quitting(&app); + stop_server_sidecar(&app); + stop_adapters_sidecar(&app); + + #[cfg(target_os = "windows")] + { + kill_windows_sidecars(); + } + + // Give Windows a short moment to release executable file handles before the + // updater starts replacing bundled sidecars in the install directory. + std::thread::sleep(Duration::from_millis(750)); + Ok(()) +} + +fn mark_app_quitting(app: &AppHandle) { + if let Some(state) = app.try_state::() { + if let Ok(mut is_quitting) = state.is_quitting.lock() { + *is_quitting = true; + } + } +} + +fn should_hide_to_tray(app: &AppHandle, label: &str) -> bool { + if label != MAIN_WINDOW_LABEL { + return false; + } + + app.try_state::() + .and_then(|state| state.is_quitting.lock().ok().map(|value| !*value)) + .unwrap_or(true) +} + +fn show_main_window(app: &AppHandle) { + if let Some(window) = app.get_webview_window(MAIN_WINDOW_LABEL) { + let _ = window.unminimize(); + let _ = window.show(); + let _ = window.set_focus(); + } +} + +fn setup_system_tray(app: &mut tauri::App) -> tauri::Result<()> { + let menu = MenuBuilder::new(app) + .text(TRAY_SHOW_ID, "Show Claude Code Haha") + .separator() + .text(TRAY_QUIT_ID, "Quit Claude Code Haha") + .build()?; + + let mut tray = TrayIconBuilder::with_id("main-tray") + .tooltip("Claude Code Haha") + .menu(&menu) + .show_menu_on_left_click(false) + .on_menu_event(|app, event| match event.id().as_ref() { + TRAY_SHOW_ID => show_main_window(app), + TRAY_QUIT_ID => { + mark_app_quitting(app); + app.exit(0); + } + _ => {} + }) + .on_tray_icon_event(|tray, event| { + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Up, + .. + } = event + { + show_main_window(tray.app_handle()); + } + }); + + if let Some(icon) = app.default_window_icon() { + tray = tray.icon(icon.clone()); + } + + tray.build(app)?; + + Ok(()) +} + +#[tauri::command] +fn terminal_spawn( + app: AppHandle, + state: State<'_, TerminalState>, + cols: u16, + rows: u16, + cwd: Option, +) -> Result { + let cwd_path = resolve_terminal_cwd(cwd)?; + let shell = default_shell(); + let pty_system = native_pty_system(); + let pair = pty_system + .openpty(PtySize { + rows: rows.max(8), + cols: cols.max(20), + pixel_width: 0, + pixel_height: 0, + }) + .map_err(|err| format!("open terminal pty: {err}"))?; + + let mut cmd = CommandBuilder::new(&shell); + cmd.cwd(cwd_path.as_os_str()); + for (key, value) in terminal_environment(&shell) { + cmd.env(key, value); + } + cmd.env("TERM", "xterm-256color"); + cmd.env("COLORTERM", "truecolor"); + + let mut child = pair + .slave + .spawn_command(cmd) + .map_err(|err| format!("spawn terminal shell: {err}"))?; + drop(pair.slave); + + let mut reader = pair + .master + .try_clone_reader() + .map_err(|err| format!("clone terminal reader: {err}"))?; + let writer = pair + .master + .take_writer() + .map_err(|err| format!("open terminal writer: {err}"))?; + let killer = child.clone_killer(); + let session_id = state.next_id.fetch_add(1, Ordering::Relaxed) + 1; + + { + let mut sessions = state + .sessions + .lock() + .map_err(|_| "terminal state is unavailable".to_string())?; + sessions.insert( + session_id, + TerminalSession { + master: pair.master, + writer: Mutex::new(writer), + killer: Mutex::new(killer), + }, + ); + } + + let output_app = app.clone(); + thread::spawn(move || { + let mut buffer = [0_u8; 8192]; + let mut pending_utf8 = Vec::new(); + loop { + match reader.read(&mut buffer) { + Ok(0) => break, + Ok(n) => { + let data = decode_terminal_output(&mut pending_utf8, &buffer[..n]); + if !data.is_empty() { + let _ = output_app.emit( + "terminal-output", + TerminalOutputPayload { session_id, data }, + ); + } + } + Err(err) => { + let _ = output_app.emit( + "terminal-output", + TerminalOutputPayload { + session_id, + data: format!("\r\n[terminal read error: {err}]\r\n"), + }, + ); + break; + } + } + } + if !pending_utf8.is_empty() { + let data = String::from_utf8_lossy(&pending_utf8).to_string(); + let _ = output_app.emit( + "terminal-output", + TerminalOutputPayload { session_id, data }, + ); + } + }); + + let exit_app = app.clone(); + thread::spawn(move || { + let status = child.wait(); + if let Some(state) = exit_app.try_state::() { + if let Ok(mut sessions) = state.sessions.lock() { + sessions.remove(&session_id); + } + } + match status { + Ok(status) => { + let _ = exit_app.emit( + "terminal-exit", + TerminalExitPayload { + session_id, + code: status.exit_code(), + signal: status.signal().map(ToString::to_string), + }, + ); + } + Err(err) => { + let _ = exit_app.emit( + "terminal-output", + TerminalOutputPayload { + session_id, + data: format!("\r\n[terminal wait error: {err}]\r\n"), + }, + ); + } + } + }); + + Ok(TerminalSpawnResult { + session_id, + shell, + cwd: cwd_path.to_string_lossy().to_string(), + }) +} + +#[tauri::command] +fn terminal_write( + state: State<'_, TerminalState>, + session_id: u32, + data: String, +) -> Result<(), String> { + let sessions = state + .sessions + .lock() + .map_err(|_| "terminal state is unavailable".to_string())?; + let session = sessions + .get(&session_id) + .ok_or_else(|| "terminal session is not running".to_string())?; + let mut writer = session + .writer + .lock() + .map_err(|_| "terminal writer is unavailable".to_string())?; + writer + .write_all(data.as_bytes()) + .map_err(|err| format!("write terminal input: {err}"))?; + writer + .flush() + .map_err(|err| format!("flush terminal input: {err}"))?; + Ok(()) +} + +#[tauri::command] +fn terminal_resize( + state: State<'_, TerminalState>, + session_id: u32, + cols: u16, + rows: u16, +) -> Result<(), String> { + let sessions = state + .sessions + .lock() + .map_err(|_| "terminal state is unavailable".to_string())?; + let session = sessions + .get(&session_id) + .ok_or_else(|| "terminal session is not running".to_string())?; + session + .master + .resize(PtySize { + rows: rows.max(8), + cols: cols.max(20), + pixel_width: 0, + pixel_height: 0, + }) + .map_err(|err| format!("resize terminal: {err}"))?; + Ok(()) +} + +#[tauri::command] +fn terminal_kill(state: State<'_, TerminalState>, session_id: u32) -> Result<(), String> { + let session = { + let mut sessions = state + .sessions + .lock() + .map_err(|_| "terminal state is unavailable".to_string())?; + sessions.remove(&session_id) + }; + + if let Some(session) = session { + let mut killer = session + .killer + .lock() + .map_err(|_| "terminal killer is unavailable".to_string())?; + killer + .kill() + .map_err(|err| format!("kill terminal shell: {err}"))?; + } + Ok(()) +} + +fn decode_terminal_output(pending: &mut Vec, chunk: &[u8]) -> String { + pending.extend_from_slice(chunk); + let mut output = String::new(); + + loop { + match str::from_utf8(pending) { + Ok(text) => { + output.push_str(text); + pending.clear(); + break; + } + Err(err) => { + let valid_up_to = err.valid_up_to(); + if valid_up_to > 0 { + let text = str::from_utf8(&pending[..valid_up_to]) + .expect("valid_up_to marks a valid UTF-8 prefix"); + output.push_str(text); + pending.drain(..valid_up_to); + continue; + } + + match err.error_len() { + Some(error_len) => { + output.push('\u{fffd}'); + pending.drain(..error_len); + } + None => break, + } + } + } + } + + output +} + +fn terminal_environment(shell: &str) -> HashMap { + let mut env: HashMap = std::env::vars().collect(); + env.extend(login_shell_environment(shell)); + ensure_utf8_locale(&mut env); + env +} + +fn ensure_utf8_locale(env: &mut HashMap) { + let fallback = default_utf8_locale(); + for key in ["LANG", "LC_CTYPE", "LC_ALL"] { + let needs_fallback = env + .get(key) + .map(|value| !is_utf8_locale(value)) + .unwrap_or(true); + if needs_fallback { + env.insert(key.to_string(), fallback.to_string()); + } + } +} + +fn is_utf8_locale(value: &str) -> bool { + let normalized = value.trim().to_ascii_lowercase().replace('-', ""); + normalized.contains("utf8") +} + +fn default_utf8_locale() -> &'static str { + #[cfg(target_os = "macos")] + { + "en_US.UTF-8" + } + #[cfg(all(unix, not(target_os = "macos")))] + { + "C.UTF-8" + } + #[cfg(not(unix))] + { + "C.UTF-8" + } +} + +#[cfg(not(target_os = "windows"))] +fn login_shell_environment(shell: &str) -> HashMap { + let Ok(mut child) = StdCommand::new(shell) + .args(["-l", "-c", "env -0"]) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .spawn() + else { + return HashMap::new(); + }; + + let deadline = Instant::now() + Duration::from_secs(2); + loop { + match child.try_wait() { + Ok(Some(status)) => { + if !status.success() { + return HashMap::new(); + } + let mut stdout = Vec::new(); + if let Some(mut pipe) = child.stdout.take() { + let _ = pipe.read_to_end(&mut stdout); + } + return parse_env_block(&stdout); + } + Ok(None) if Instant::now() < deadline => { + thread::sleep(Duration::from_millis(25)); + } + Ok(None) => { + let _ = child.kill(); + let _ = child.wait(); + return HashMap::new(); + } + Err(_) => return HashMap::new(), + } + } +} + +#[cfg(target_os = "windows")] +fn login_shell_environment(_shell: &str) -> HashMap { + HashMap::new() +} + +fn parse_env_block(bytes: &[u8]) -> HashMap { + bytes + .split(|byte| *byte == 0) + .filter_map(|entry| { + if entry.is_empty() { + return None; + } + let equals = entry.iter().position(|byte| *byte == b'=')?; + if equals == 0 { + return None; + } + let key = String::from_utf8_lossy(&entry[..equals]).to_string(); + let value = String::from_utf8_lossy(&entry[equals + 1..]).to_string(); + Some((key, value)) + }) + .collect() +} + +fn resolve_terminal_cwd(cwd: Option) -> Result { + let path = match cwd.and_then(|value| { + let trimmed = value.trim(); + if trimmed.is_empty() { + None + } else { + Some(PathBuf::from(trimmed)) + } + }) { + Some(path) => path, + None => home_dir().unwrap_or( + std::env::current_dir().map_err(|err| format!("resolve current directory: {err}"))?, + ), + }; + + if path.is_dir() { + Ok(path) + } else { + Err(format!("terminal cwd does not exist: {}", path.display())) + } +} + +fn home_dir() -> Option { + std::env::var_os("HOME") + .or_else(|| std::env::var_os("USERPROFILE")) + .map(PathBuf::from) +} + +fn default_shell() -> String { + #[cfg(target_os = "windows")] + { + std::env::var("COMSPEC").unwrap_or_else(|_| "powershell.exe".to_string()) + } + #[cfg(not(target_os = "windows"))] + { + std::env::var("SHELL").unwrap_or_else(|_| { + if PathBuf::from("/bin/zsh").exists() { + "/bin/zsh".to_string() + } else { + "/bin/bash".to_string() + } + }) + } +} + +fn reserve_local_port() -> Result { + let listener = + TcpListener::bind("127.0.0.1:0").map_err(|err| format!("bind local port: {err}"))?; + let port = listener + .local_addr() + .map_err(|err| format!("read local port: {err}"))? + .port(); + drop(listener); + Ok(port) +} + +fn wait_for_server(url_host: &str, port: u16) -> Result<(), String> { + let addr: SocketAddr = format!("{url_host}:{port}") + .parse() + .map_err(|err| format!("parse server address: {err}"))?; + let deadline = Instant::now() + Duration::from_secs(10); + + while Instant::now() < deadline { + if TcpStream::connect_timeout(&addr, Duration::from_millis(200)).is_ok() { + return Ok(()); + } + std::thread::sleep(Duration::from_millis(150)); + } + + Err(format!( + "desktop server did not start listening on {url_host}:{port} within 10 seconds" + )) +} + +fn push_server_startup_log(logs: &Arc>>, line: String) { + let line = line.trim_end().to_string(); + if line.is_empty() { + return; + } + + let Ok(mut guard) = logs.lock() else { + return; + }; + if guard.len() >= SERVER_STARTUP_LOG_LIMIT { + guard.pop_front(); + } + guard.push_back(line); +} + +fn format_server_startup_error(message: &str, logs: &Arc>>) -> String { + let log_text = logs + .lock() + .ok() + .map(|guard| guard.iter().cloned().collect::>().join("\n")) + .filter(|text| !text.trim().is_empty()) + .unwrap_or_else(|| "No server stdout/stderr was captured before the timeout.".to_string()); + + format!("{message}\n\nRecent server logs:\n{log_text}") +} + +fn resolve_app_root(_app: &AppHandle) -> Result { + // 历史用途:此前 sidecar launcher 用 dynamic file:// import 加载磁盘上 + // 的 src/server/index.ts 和 preload.ts,所以 Tauri 必须把整个 src/ + + // node_modules/ 当 Resource 一起 ship 到 .app/Contents/Resources/app/。 + // + // 现在 launcher 改成静态 import + bun build --compile 整棵静态打进二进制, + // sidecar 不再读磁盘上的 src/ 或 node_modules/。CLAUDE_APP_ROOT 现在 + // 只剩一个名义上的"app 安装根目录"作用,给 conversationService 在 + // spawn CLI 子进程时通过 --app-root 透传。 + // + // 我们直接用当前可执行文件所在目录作为 app_root: + // Dev: desktop/src-tauri/target// (rust 跑出来的 binary 那一层) + // Prod: .app/Contents/MacOS/ (sidecar 二进制的同级目录) + let exe = std::env::current_exe().map_err(|err| format!("resolve current exe path: {err}"))?; + let dir = exe + .parent() + .ok_or_else(|| "current exe has no parent dir".to_string())? + .to_path_buf(); + Ok(dir) +} + +fn start_server_sidecar(app: &AppHandle) -> Result { + let host = "127.0.0.1"; + let port = reserve_local_port()?; + let url = format!("http://{host}:{port}"); + let app_root = resolve_app_root(app)?; + let app_root_arg = app_root.to_string_lossy().to_string(); + + // 单一合并 sidecar:第一个参数选 server / cli / adapters 模式。 + let mut sidecar = app + .shell() + .sidecar("claude-sidecar") + .map_err(|err| format!("resolve sidecar: {err}"))?; + for (key, value) in terminal_environment(&default_shell()) { + sidecar = sidecar.env(key, value); + } + let sidecar = sidecar.args([ + "server", + "--app-root", + &app_root_arg, + "--host", + host, + "--port", + &port.to_string(), + ]); + + let startup_logs = Arc::new(Mutex::new(VecDeque::new())); + let logs_for_task = Arc::clone(&startup_logs); + + let (mut rx, child) = sidecar + .spawn() + .map_err(|err| format!("spawn server sidecar: {err}"))?; + + tauri::async_runtime::spawn(async move { + while let Some(event) = rx.recv().await { + match event { + CommandEvent::Stdout(line) => { + let line = String::from_utf8_lossy(&line); + let line = line.trim_end(); + println!("[claude-server] {line}"); + push_server_startup_log(&logs_for_task, format!("[stdout] {line}")); + } + CommandEvent::Stderr(line) => { + let line = String::from_utf8_lossy(&line); + let line = line.trim_end(); + eprintln!("[claude-server] {line}"); + push_server_startup_log(&logs_for_task, format!("[stderr] {line}")); + } + CommandEvent::Terminated(payload) => { + let line = format!( + "sidecar exited (code={:?}, signal={:?})", + payload.code, payload.signal + ); + eprintln!("[claude-server] {line}"); + push_server_startup_log(&logs_for_task, format!("[exit] {line}")); + } + _ => {} + } + } + }); + + if let Err(err) = wait_for_server(host, port) { + let _ = child.kill(); + return Err(format_server_startup_error(&err, &startup_logs)); + } + + Ok(ServerRuntime { url, child }) +} + +fn stop_server_sidecar(app: &AppHandle) { + let Some(state) = app.try_state::() else { + return; + }; + + let Ok(mut guard) = state.0.lock() else { + return; + }; + + if let Some(runtime) = guard.runtime.take() { + let _ = runtime.child.kill(); + } +} + +/// 启动 adapter sidecar。返回 Result 主要为了把"无法 spawn"和"spawn 后立刻 +/// 退出(凭据缺失)"区分开 —— 后者不算错误,是正常 default 状态。 +fn start_adapters_sidecar(app: &AppHandle) -> Result { + let app_root = resolve_app_root(app)?; + let app_root_arg = app_root.to_string_lossy().to_string(); + + // adapter 内部的 WsBridge 默认连 ws://127.0.0.1:3456,但桌面端的 server + // 用的是 reserve_local_port() 拿到的动态端口。这里把实际端口通过 + // ADAPTER_SERVER_URL env var 传过去 —— adapters/common/config.ts 的 + // loadConfig() 会读它。 + // + // 如果 server 还没起来 / 没拿到 URL,回退到 3456 作为最后兜底(adapter + // 自己有重连逻辑,等 server 上线就能连上)。 + let server_http_url = app + .try_state::() + .and_then(|state| { + state + .0 + .lock() + .ok() + .and_then(|guard| guard.runtime.as_ref().map(|r| r.url.clone())) + }) + .unwrap_or_else(|| "http://127.0.0.1:3456".to_string()); + // WsBridge 直接 `new WebSocket('${serverUrl}/ws/...')`,必须传 ws://; + // 不会自动从 http 转。 + let server_ws_url = if let Some(rest) = server_http_url.strip_prefix("http://") { + format!("ws://{rest}") + } else if let Some(rest) = server_http_url.strip_prefix("https://") { + format!("wss://{rest}") + } else { + server_http_url.clone() + }; + + let mut sidecar = app + .shell() + .sidecar("claude-sidecar") + .map_err(|err| format!("resolve sidecar: {err}"))?; + for (key, value) in terminal_environment(&default_shell()) { + sidecar = sidecar.env(key, value); + } + let sidecar = sidecar.env("ADAPTER_SERVER_URL", &server_ws_url).args([ + "adapters", + "--app-root", + &app_root_arg, + "--feishu", + "--telegram", + ]); + + let (mut rx, child) = sidecar + .spawn() + .map_err(|err| format!("spawn adapter sidecar: {err}"))?; + + // 用一个 async task 把 sidecar 的 stdout/stderr 转发出来。它退出时 + // 整个 task 也会自然结束。 + tauri::async_runtime::spawn(async move { + while let Some(event) = rx.recv().await { + match event { + CommandEvent::Stdout(line) => { + let line = String::from_utf8_lossy(&line); + println!("[claude-adapters] {}", line.trim_end()); + } + CommandEvent::Stderr(line) => { + let line = String::from_utf8_lossy(&line); + eprintln!("[claude-adapters] {}", line.trim_end()); + } + CommandEvent::Terminated(payload) => { + // exit code != 0 是常态:用户没配凭据时 sidecar 内部会 + // warn + skip + process.exit(1)。这里只 info 一行, + // 不要当错误冒泡。 + println!( + "[claude-adapters] sidecar exited (code={:?}, signal={:?})", + payload.code, payload.signal + ); + } + _ => {} + } + } + }); + + Ok(child) +} + +/// spawn adapter sidecar 并把 child handle 存进 AdapterState。 +/// 在启动 + 重启路径里复用,集中处理"无法 spawn"的日志。 +fn spawn_and_track_adapters_sidecar(app: &AppHandle) { + match start_adapters_sidecar(app) { + Ok(child) => { + if let Some(state) = app.try_state::() { + if let Ok(mut guard) = state.0.lock() { + *guard = Some(child); + } + } + } + Err(err) => { + eprintln!("[desktop] failed to start adapter sidecar: {err}"); + } + } +} + +fn stop_adapters_sidecar(app: &AppHandle) { + let Some(state) = app.try_state::() else { + return; + }; + let Ok(mut guard) = state.0.lock() else { + return; + }; + if let Some(child) = guard.take() { + let _ = child.kill(); + } +} + +#[cfg(target_os = "windows")] +fn kill_windows_sidecars() { + for image_name in [ + "claude-sidecar-x86_64-pc-windows-msvc.exe", + "claude-sidecar-aarch64-pc-windows-msvc.exe", + "claude-sidecar.exe", + ] { + let _ = StdCommand::new("taskkill") + .args(["/F", "/T", "/IM", image_name]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); + } +} + +#[cfg(test)] +mod tests { + use super::{decode_terminal_output, default_utf8_locale, ensure_utf8_locale, parse_env_block}; + use std::collections::HashMap; + + #[test] + fn terminal_output_decoder_preserves_split_chinese_characters() { + let mut pending = Vec::new(); + let bytes = "安装 Skills 成功\n".as_bytes(); + + assert_eq!(decode_terminal_output(&mut pending, &bytes[..2]), ""); + assert_eq!(decode_terminal_output(&mut pending, &bytes[2..4]), "安"); + assert_eq!( + decode_terminal_output(&mut pending, &bytes[4..]), + "装 Skills 成功\n" + ); + assert!(pending.is_empty()); + } + + #[test] + fn terminal_output_decoder_keeps_incomplete_suffix_pending() { + let mut pending = Vec::new(); + let bytes = "中文".as_bytes(); + + assert_eq!(decode_terminal_output(&mut pending, &bytes[..4]), "中"); + assert_eq!(pending, bytes[3..4]); + assert_eq!(decode_terminal_output(&mut pending, &bytes[4..]), "文"); + assert!(pending.is_empty()); + } + + #[test] + fn parse_env_block_reads_nul_delimited_values() { + let env = + parse_env_block(b"PATH=/opt/homebrew/bin:/usr/bin\0NODE_PATH=/tmp/node\0EMPTY=\0"); + + assert_eq!( + env.get("PATH").map(String::as_str), + Some("/opt/homebrew/bin:/usr/bin") + ); + assert_eq!(env.get("NODE_PATH").map(String::as_str), Some("/tmp/node")); + assert_eq!(env.get("EMPTY").map(String::as_str), Some("")); + } + + #[test] + fn terminal_environment_forces_utf8_locale_when_shell_uses_c_locale() { + let mut env = HashMap::from([ + ("LANG".to_string(), "C".to_string()), + ("LC_CTYPE".to_string(), "POSIX".to_string()), + ("LC_ALL".to_string(), "C".to_string()), + ]); + + ensure_utf8_locale(&mut env); + + assert_eq!( + env.get("LANG").map(String::as_str), + Some(default_utf8_locale()) + ); + assert_eq!( + env.get("LC_CTYPE").map(String::as_str), + Some(default_utf8_locale()) + ); + assert_eq!( + env.get("LC_ALL").map(String::as_str), + Some(default_utf8_locale()) + ); + } + + #[test] + fn terminal_environment_keeps_existing_utf8_locale() { + let mut env = HashMap::from([ + ("LANG".to_string(), "zh_CN.UTF-8".to_string()), + ("LC_CTYPE".to_string(), "en_US.UTF8".to_string()), + ("LC_ALL".to_string(), "C.UTF-8".to_string()), + ]); + + ensure_utf8_locale(&mut env); + + assert_eq!(env.get("LANG").map(String::as_str), Some("zh_CN.UTF-8")); + assert_eq!(env.get("LC_CTYPE").map(String::as_str), Some("en_US.UTF8")); + assert_eq!(env.get("LC_ALL").map(String::as_str), Some("C.UTF-8")); + } +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + let builder = tauri::Builder::default() + .manage(ServerState::default()) + .manage(AdapterState::default()) + .manage(TerminalState::default()) + .manage(AppExitState::default()) + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_process::init()) + .plugin(tauri_plugin_updater::Builder::new().build()) + .invoke_handler(tauri::generate_handler![ + get_server_url, + restart_adapters_sidecar, + prepare_for_update_install, + terminal_spawn, + terminal_write, + terminal_resize, + terminal_kill + ]); + + // macOS: native menu bar (traffic-light overlay style) + #[cfg(target_os = "macos")] + let builder = builder + .menu(|app| { + let about_item = + MenuItemBuilder::with_id("nav_about", "关于 Claude Code Haha").build(app)?; + let settings_item = MenuItemBuilder::with_id("nav_settings", "设置...") + .accelerator("CmdOrCtrl+,") + .build(app)?; + + let app_submenu = SubmenuBuilder::new(app, "Claude Code Haha") + .item(&about_item) + .separator() + .item(&settings_item) + .separator() + .services() + .separator() + .hide() + .hide_others() + .show_all() + .separator() + .quit() + .build()?; + + let edit_submenu = SubmenuBuilder::new(app, "Edit") + .undo() + .redo() + .separator() + .cut() + .copy() + .paste() + .select_all() + .build()?; + + let view_submenu = SubmenuBuilder::new(app, "View").fullscreen().build()?; + + let window_submenu = SubmenuBuilder::new(app, "Window") + .minimize() + .maximize() + .close_window() + .build()?; + + MenuBuilder::new(app) + .item(&app_submenu) + .item(&edit_submenu) + .item(&view_submenu) + .item(&window_submenu) + .build() + }) + .on_menu_event(|app, event| match event.id().as_ref() { + "nav_about" => { + let _ = app.emit("native-menu-navigate", "about"); + } + "nav_settings" => { + let _ = app.emit("native-menu-navigate", "settings"); + } + _ => {} + }); + + let app = builder + .setup(|app| { + setup_system_tray(app)?; + + let state = app.state::(); + let mut guard = state + .0 + .lock() + .map_err(|_| IoError::new(ErrorKind::Other, "server state lock poisoned"))?; + + match start_server_sidecar(&app.handle()) { + Ok(runtime) => { + guard.runtime = Some(runtime); + guard.startup_error = None; + } + Err(err) => { + eprintln!("[desktop] failed to start local server: {err}"); + guard.runtime = None; + guard.startup_error = Some(err); + } + } + drop(guard); + + // server 起来之后再起 adapter sidecar —— start_adapters_sidecar + // 内部会从 ServerState 读 server URL 注入 ADAPTER_SERVER_URL env, + // 让 adapter 连上动态端口。 + spawn_and_track_adapters_sidecar(&app.handle()); + + Ok(()) + }) + .build(tauri::generate_context!()) + .expect("error while building tauri application"); + + app.run(|app_handle, event| match event { + RunEvent::WindowEvent { + label, + event: WindowEvent::CloseRequested { api, .. }, + .. + } if should_hide_to_tray(app_handle, &label) => { + api.prevent_close(); + if let Some(window) = app_handle.get_webview_window(&label) { + let _ = window.hide(); + } + } + #[cfg(target_os = "macos")] + RunEvent::Reopen { + has_visible_windows: false, + .. + } => { + show_main_window(app_handle); + } + RunEvent::ExitRequested { .. } => { + mark_app_quitting(app_handle); + stop_server_sidecar(app_handle); + stop_adapters_sidecar(app_handle); + } + RunEvent::Exit => { + mark_app_quitting(app_handle); + stop_server_sidecar(app_handle); + stop_adapters_sidecar(app_handle); + } + _ => {} + }); +} diff --git a/_all-in-one-upload/cc-haha/desktop/src-tauri/tauri.conf.json b/_all-in-one-upload/cc-haha/desktop/src-tauri/tauri.conf.json new file mode 100644 index 0000000..c9330e6 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-schema-v2.json", + "productName": "HeiCode", + "version": "0.1.0", + "identifier": "com.heicode.desktop", + "build": { + "frontendDist": "../dist", + "devUrl": "http://localhost:1420", + "beforeDevCommand": "bun run build:sidecars && bun run dev", + "beforeBuildCommand": "bun run build && bun run build:sidecars" + }, + "app": { + "windows": [ + { + "title": "HeiCode", + "width": 1440, + "height": 960, + "minWidth": 960, + "minHeight": 640, + "decorations": true, + "transparent": false, + "acceptFirstMouse": true + } + ], + "security": { + "dangerousDisableAssetCspModification": ["style-src"], + "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: asset: https://asset.localhost; font-src 'self' data:; connect-src 'self' ws://127.0.0.1:* http://127.0.0.1:* ws://localhost:* http://localhost:*; media-src 'self' blob:" + } + }, + "plugins": { + "updater": { + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDlCOUIwRDExQTc5RTFGMzYKUldRMkg1Nm5FUTJibTJ2cGlHY0pkL0dGemxXMUlzc01pVTVMM1U3WGpmWUtrUC8wK2ErSXhLKzEK", + "endpoints": [], + "windows": { + "installMode": "passive" + } + } + }, + "bundle": { + "active": true, + "targets": "all", + "createUpdaterArtifacts": true, + "windows": { + "nsis": { + "installerHooks": "windows-installer-hooks.nsh" + } + }, + "externalBin": [ + "binaries/claude-sidecar" + ], + "resources": [], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "macOS": { + "dmg": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "width": 660, + "height": 400 + } + } + } + } +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/api/skills.ts b/_all-in-one-upload/cc-haha/desktop/src/api/skills.ts new file mode 100644 index 0000000..c081699 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/api/skills.ts @@ -0,0 +1,22 @@ +import { api } from './client' +import type { SkillMeta, SkillDetail } from '../types/skill' + +export const skillsApi = { + list: (cwd?: string) => { + const query = cwd ? `?cwd=${encodeURIComponent(cwd)}` : '' + return api.get<{ skills: SkillMeta[] }>(`/api/skills${query}`, { timeout: 120_000 }) + }, + + detail: (source: string, name: string, cwd?: string) => { + const query = new URLSearchParams({ + source, + name, + }) + if (cwd) query.set('cwd', cwd) + + return api.get<{ detail: SkillDetail }>( + `/api/skills/detail?${query.toString()}`, + { timeout: 120_000 }, + ) + }, +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/api/websocket.test.ts b/_all-in-one-upload/cc-haha/desktop/src/api/websocket.test.ts new file mode 100644 index 0000000..7481319 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/api/websocket.test.ts @@ -0,0 +1,92 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' + +vi.mock('./client', () => ({ + getBaseUrl: () => 'http://127.0.0.1:3456', +})) + +import { wsManager } from './websocket' + +type SocketHandler = (() => void) | ((event: { data: string }) => void) + +class FakeWebSocket { + static readonly CONNECTING = 0 + static readonly OPEN = 1 + static readonly CLOSING = 2 + static readonly CLOSED = 3 + static instances: FakeWebSocket[] = [] + + readonly url: string + readyState = FakeWebSocket.CONNECTING + onopen: SocketHandler | null = null + onmessage: SocketHandler | null = null + onclose: SocketHandler | null = null + onerror: SocketHandler | null = null + sent: string[] = [] + + constructor(url: string) { + this.url = url + FakeWebSocket.instances.push(this) + } + + send(data: string) { + this.sent.push(data) + } + + close() { + this.readyState = FakeWebSocket.CLOSED + ;(this.onclose as (() => void) | null)?.() + } + + open() { + this.readyState = FakeWebSocket.OPEN + ;(this.onopen as (() => void) | null)?.() + } + + fail() { + this.readyState = FakeWebSocket.CLOSED + ;(this.onclose as (() => void) | null)?.() + } +} + +describe('wsManager reconnect buffering', () => { + const originalWebSocket = globalThis.WebSocket + + beforeEach(() => { + vi.useFakeTimers() + FakeWebSocket.instances = [] + globalThis.WebSocket = FakeWebSocket as unknown as typeof WebSocket + wsManager.disconnectAll() + }) + + afterEach(() => { + wsManager.disconnectAll() + globalThis.WebSocket = originalWebSocket + vi.useRealTimers() + }) + + it('replays queued messages after an unexpected reconnect', async () => { + wsManager.connect('session-reconnect') + + const firstSocket = FakeWebSocket.instances[0] + expect(firstSocket?.url).toContain('/ws/session-reconnect') + + firstSocket!.open() + wsManager.send('session-reconnect', { type: 'user_message', content: 'first' }) + expect(firstSocket!.sent).toEqual([ + JSON.stringify({ type: 'user_message', content: 'first' }), + ]) + + firstSocket!.fail() + wsManager.send('session-reconnect', { type: 'user_message', content: 'queued while offline' }) + + await vi.advanceTimersByTimeAsync(1000) + + const secondSocket = FakeWebSocket.instances[1] + expect(secondSocket).toBeDefined() + secondSocket!.open() + + expect(secondSocket!.sent).toEqual([ + JSON.stringify({ type: 'user_message', content: 'queued while offline' }), + ]) + }) +}) diff --git a/_all-in-one-upload/cc-haha/desktop/src/components/shared/UpdateChecker.tsx b/_all-in-one-upload/cc-haha/desktop/src/components/shared/UpdateChecker.tsx new file mode 100644 index 0000000..d9bec6a --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/components/shared/UpdateChecker.tsx @@ -0,0 +1,106 @@ +import { useEffect } from 'react' +import { useTranslation } from '../../i18n' +import { MarkdownRenderer } from '../markdown/MarkdownRenderer' +import { isTauriRuntime } from '../../lib/desktopRuntime' +import { useUpdateStore } from '../../stores/updateStore' +import { formatBytes } from '../../lib/formatBytes' + +export function UpdateChecker() { + const t = useTranslation() + const status = useUpdateStore((s) => s.status) + const availableVersion = useUpdateStore((s) => s.availableVersion) + const releaseNotes = useUpdateStore((s) => s.releaseNotes) + const progressPercent = useUpdateStore((s) => s.progressPercent) + const downloadedBytes = useUpdateStore((s) => s.downloadedBytes) + const totalBytes = useUpdateStore((s) => s.totalBytes) + const error = useUpdateStore((s) => s.error) + const shouldPrompt = useUpdateStore((s) => s.shouldPrompt) + const initialize = useUpdateStore((s) => s.initialize) + const installUpdate = useUpdateStore((s) => s.installUpdate) + const dismissPrompt = useUpdateStore((s) => s.dismissPrompt) + + useEffect(() => { + void initialize() + }, [initialize]) + + if (!isTauriRuntime()) return null + + const showPopup = + shouldPrompt && !!availableVersion && ['available', 'downloading', 'restarting'].includes(status) + + if (!showPopup) return null + + const hasKnownProgress = typeof totalBytes === 'number' && totalBytes > 0 + const downloadedText = formatBytes(downloadedBytes) + const statusText = + status === 'restarting' + ? t('update.restarting') + : status === 'downloading' + ? hasKnownProgress + ? t('update.downloading') + : t('update.progressBytes', { downloaded: downloadedText }) + : null + + return ( +
+
+

+ {t('update.available', { version: availableVersion })} +

+ + {releaseNotes && ( +
+ +
+ )} + + {(status === 'downloading' || status === 'restarting') && ( +
+
+ {hasKnownProgress || status === 'restarting' ? ( +
+ ) : ( +
+ )} +
+ {statusText && ( +

+ {statusText} + {status === 'downloading' && hasKnownProgress ? ` ${progressPercent}%` : ''} +

+ )} +
+ )} + + {error && ( +

+ {t('update.failed', { error })} +

+ )} + + {status === 'available' && ( +
+ + +
+ )} +
+
+ ) +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/components/tasks/DayOfWeekPicker.tsx b/_all-in-one-upload/cc-haha/desktop/src/components/tasks/DayOfWeekPicker.tsx new file mode 100644 index 0000000..577b848 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/components/tasks/DayOfWeekPicker.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from '../../i18n' + +type Props = { + selected: number[] + onChange: (days: number[]) => void +} + +// Display order: Mon(1) → Sun(0), matching Chinese convention +const DAY_ORDER = [1, 2, 3, 4, 5, 6, 0] + +const DAY_KEYS = [ + 'newTask.daySun', + 'newTask.dayMon', + 'newTask.dayTue', + 'newTask.dayWed', + 'newTask.dayThu', + 'newTask.dayFri', + 'newTask.daySat', +] as const + +export function DayOfWeekPicker({ selected, onChange }: Props) { + const t = useTranslation() + + const toggle = (day: number) => { + if (selected.includes(day)) { + // Don't allow deselecting the last day + if (selected.length <= 1) return + onChange(selected.filter((d) => d !== day)) + } else { + onChange([...selected, day]) + } + } + + return ( +
+ {DAY_ORDER.map((day) => { + const isActive = selected.includes(day) + return ( + + ) + })} +
+ ) +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/pages/ActiveSession.tsx b/_all-in-one-upload/cc-haha/desktop/src/pages/ActiveSession.tsx new file mode 100644 index 0000000..0cc18ec --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/pages/ActiveSession.tsx @@ -0,0 +1,219 @@ +import { useEffect, useMemo } from 'react' +import { useTabStore } from '../stores/tabStore' +import { useSessionStore } from '../stores/sessionStore' +import { useChatStore } from '../stores/chatStore' +import { useCLITaskStore } from '../stores/cliTaskStore' +import { useTeamStore } from '../stores/teamStore' +import { useTranslation } from '../i18n' +import { MessageList } from '../components/chat/MessageList' +import { ChatInput } from '../components/chat/ChatInput' +import { ComputerUsePermissionModal } from '../components/chat/ComputerUsePermissionModal' +import { TeamStatusBar } from '../components/teams/TeamStatusBar' +import { SessionTaskBar } from '../components/chat/SessionTaskBar' + +const TASK_POLL_INTERVAL_MS = 1000 + +export function ActiveSession() { + const activeTabId = useTabStore((s) => s.activeTabId) + const sessions = useSessionStore((s) => s.sessions) + const connectToSession = useChatStore((s) => s.connectToSession) + const sessionState = useChatStore((s) => activeTabId ? s.sessions[activeTabId] : undefined) + const pendingComputerUsePermission = sessionState?.pendingComputerUsePermission ?? null + const fetchSessionTasks = useCLITaskStore((s) => s.fetchSessionTasks) + const trackedTaskSessionId = useCLITaskStore((s) => s.sessionId) + const hasIncompleteTasks = useCLITaskStore((s) => s.tasks.some((task) => task.status !== 'completed')) + const chatState = sessionState?.chatState ?? 'idle' + const tokenUsage = sessionState?.tokenUsage ?? { input_tokens: 0, output_tokens: 0 } + + const session = sessions.find((s) => s.id === activeTabId) + const memberInfo = useTeamStore((s) => activeTabId ? s.getMemberBySessionId(activeTabId) : null) + const activeTeam = useTeamStore((s) => s.activeTeam) + const isMemberSession = !!memberInfo + + useEffect(() => { + if (activeTabId && !isMemberSession) { + connectToSession(activeTabId) + } + }, [activeTabId, isMemberSession, connectToSession]) + + useEffect(() => { + if (!activeTabId || isMemberSession) return + + const shouldPollTasks = + chatState !== 'idle' || + (trackedTaskSessionId === activeTabId && hasIncompleteTasks) + + if (!shouldPollTasks) return + + void fetchSessionTasks(activeTabId) + + const timer = setInterval(() => { + void fetchSessionTasks(activeTabId) + }, TASK_POLL_INTERVAL_MS) + + return () => clearInterval(timer) + }, [ + activeTabId, + isMemberSession, + chatState, + trackedTaskSessionId, + hasIncompleteTasks, + fetchSessionTasks, + ]) + + const t = useTranslation() + const messages = sessionState?.messages ?? [] + const streamingText = sessionState?.streamingText ?? '' + const isEmpty = messages.length === 0 && !streamingText + + const isActive = chatState !== 'idle' + const totalTokens = tokenUsage.input_tokens + tokenUsage.output_tokens + + const lastUpdated = useMemo(() => { + if (!session?.modifiedAt) return '' + const diff = Date.now() - new Date(session.modifiedAt).getTime() + if (diff < 60000) return t('session.timeJustNow') + if (diff < 3600000) return t('session.timeMinutes', { n: Math.floor(diff / 60000) }) + if (diff < 86400000) return t('session.timeHours', { n: Math.floor(diff / 3600000) }) + return t('session.timeDays', { n: Math.floor(diff / 86400000) }) + }, [session?.modifiedAt, t]) + + if (!activeTabId) return null + + return ( +
+ {isMemberSession && ( +
+
+
+
+ {memberInfo?.status === 'running' && ( + + )} + {memberInfo?.status === 'completed' && ( + check_circle + )} + smart_toy + + {memberInfo?.role} + + {activeTeam && ( + + @ {activeTeam.name} + + )} +
+

+ {t('teams.memberSessionHint')} +

+
+ +
+
+ )} + + {isEmpty ? ( +
+
+ {isMemberSession ? ( + <> + smart_toy +

+ {memberInfo?.status === 'running' + ? `${memberInfo.role} ${t('teams.working')}` + : t('teams.noMessages')} +

+ + ) : ( + <> + Claude Code Haha +

+ {t('empty.title')} +

+

+ {t('empty.subtitle')} +

+ + )} +
+
+ ) : ( + <> + {!isMemberSession && ( +
+
+

+ {session?.title || t('session.untitled')} +

+
+ {isActive && ( + + + {t('session.active')} + + )} + {totalTokens > 0 && ( + <> + · + {totalTokens.toLocaleString()} t + + )} + {lastUpdated && ( + <> + · + {t('session.lastUpdated', { time: lastUpdated })} + + )} + {session?.messageCount !== undefined && session.messageCount > 0 && ( + <> + · + {t('session.messages', { count: session.messageCount })} + + )} +
+ {session?.workDirExists === false && ( +
+ warning + + {t('session.workspaceUnavailable', { dir: session.workDir || 'directory no longer exists' })} + +
+ )} +
+
+ )} + + + + )} + + {!isMemberSession && } + + + + + + {!isMemberSession && activeTabId ? ( + + ) : null} +
+ ) +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/pages/ScheduledTasksList.tsx b/_all-in-one-upload/cc-haha/desktop/src/pages/ScheduledTasksList.tsx new file mode 100644 index 0000000..7c7c87b --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/pages/ScheduledTasksList.tsx @@ -0,0 +1,416 @@ +import { useTranslation } from '../i18n' +import { mockScheduledTasks, mockStatusBar } from '../mocks/data' + +export function ScheduledTasksList() { + const t = useTranslation() + const { stats, tasks } = mockScheduledTasks + const task0 = tasks[0]! + const task1 = tasks[1]! + const task2 = tasks[2]! + + return ( +
+ {/* SideNavBar */} + + + {/* Main Content Area */} +
+ {/* TopAppBar */} +
+ +
+
+ + +
+ +
+
+ + {/* Separation Line */} +
+ + {/* Scrollable Content */} +
+
+ {/* Page Header */} +
+
+

{t('scheduledPage.title')}

+

{t('scheduledPage.subtitle')}

+
+ +
+ + {/* Bento-style Summary Cards */} +
+ {/* Total Tasks */} +
+
+ {t('tasks.totalTasks')} + analytics +
+
{stats.totalTasks}
+
+ trending_up + {t('scheduledPage.thisMonth', { count: '+2' })} +
+
+ + {/* Next Run */} +
+
+ {t('scheduledPage.nextRun')} + schedule +
+
{stats.nextRun.name}
+

{stats.nextRun.time}

+
+ + {/* System Health */} +
+
+ {t('scheduledPage.systemHealth')} + check_circle +
+
{stats.systemHealth}%
+

{stats.healthPeriod}

+
+
+ + {/* Operational Tasks Table */} +
+ + + + + + + + + + + + {/* Task Row 1 - Nightly linting */} + + + + + + + + + {/* Task Row 2 - Clean up temp files */} + + + + + + + + + {/* Task Row 3 - Database Vacuum */} + + + + + + + + +
{t('scheduledPage.colTaskName')}{t('scheduledPage.colFrequency')}{t('scheduledPage.colLastResult')}{t('scheduledPage.colNextExecution')}{t('scheduledPage.colActions')}
+
+
+ code_blocks +
+
+
{task0.name}
+
Root: /projects/companion/src
+
+
+
+ {task0.frequency} + +
+ + check_circle + + {task0.lastResult} +
+
+
{task0.nextExecution}
+
+
+ + + +
+
+
+
+ cleaning_services +
+
+
{task1.name}
+
{task1.description}
+
+
+
+ {task1.frequency} + +
+ + check_circle + + {task1.lastResult} +
+
+
{task1.nextExecution}
+
+
+ + + +
+
+
+
+ database +
+
+
{task2.name}
+
{task2.description}
+
+
+
+ Monthly + +
+ + error + + {task2.lastResult} +
+
+
{task2.nextExecution}
+
+
+ + + +
+
+ + {/* End of list placeholder */} +
+
+ history_toggle_off +
+

{t('scheduledPage.endOfList')}

+

{t('scheduledPage.pausedTasks')}

+
+
+ + {/* System Logs / Details Panel */} +
+ {/* Recent Output Logs */} +
+

{t('scheduledPage.recentLogs')}

+
+
+ 2023-11-10 23:01 + [INFO] + Nightly linting started for repository: companion-main +
+
+ 2023-11-10 23:04 + [INFO] + Processed 1,422 files. No critical issues found. +
+
+ 2023-11-10 23:04 + [WARN] + Found 12 deprecated calls in /legacy/utils.js +
+
+ 2023-11-10 23:05 + [INFO] + Task completed successfully in 242.4s. +
+
+ Log stream: active + +
+
+
+ + {/* Resource Allocation Panel */} +
+
+

{t('scheduledPage.resourceAllocation')}

+
+
+
+ {t('scheduledPage.cpuCapacity')} + 42% +
+
+
+
+
+
+
+ {t('scheduledPage.memoryLoad')} + 68% +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + {/* Footer */} +
+
+ {mockStatusBar.user} • {mockStatusBar.username} • {mockStatusBar.plan} +
+
+ + fiber_manual_record + + {t('scheduledPage.connectedLocal')} +
+
+
+ + + +
+
+
+
+ ) +} diff --git a/_all-in-one-upload/cc-haha/desktop/src/stores/agentStore.ts b/_all-in-one-upload/cc-haha/desktop/src/stores/agentStore.ts new file mode 100644 index 0000000..580bda1 --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/stores/agentStore.ts @@ -0,0 +1,45 @@ +import { create } from 'zustand' +import { agentsApi, type AgentDefinition } from '../api/agents' + +export type AgentDetailReturnTab = 'agents' | 'plugins' + +type AgentStore = { + activeAgents: AgentDefinition[] + allAgents: AgentDefinition[] + isLoading: boolean + error: string | null + selectedAgent: AgentDefinition | null + selectedAgentReturnTab: AgentDetailReturnTab + + fetchAgents: (cwd?: string) => Promise + selectAgent: ( + agent: AgentDefinition | null, + returnTab?: AgentDetailReturnTab, + ) => void +} + +export const useAgentStore = create((set) => ({ + activeAgents: [], + allAgents: [], + isLoading: false, + error: null, + selectedAgent: null, + selectedAgentReturnTab: 'agents', + + fetchAgents: async (cwd) => { + set({ isLoading: true, error: null }) + try { + const { activeAgents, allAgents } = await agentsApi.list(cwd) + set({ activeAgents, allAgents, isLoading: false }) + } catch (error) { + const message = error instanceof Error ? error.message : 'Failed to load agents' + set({ isLoading: false, error: message }) + } + }, + + selectAgent: (agent, returnTab = 'agents') => + set({ + selectedAgent: agent, + selectedAgentReturnTab: agent ? returnTab : 'agents', + }), +})) diff --git a/_all-in-one-upload/cc-haha/desktop/src/types/task.ts b/_all-in-one-upload/cc-haha/desktop/src/types/task.ts new file mode 100644 index 0000000..9ccbbba --- /dev/null +++ b/_all-in-one-upload/cc-haha/desktop/src/types/task.ts @@ -0,0 +1,56 @@ +// Source: src/server/services/cronService.ts + +export type TaskNotificationConfig = { + enabled: boolean + channels: ('telegram' | 'feishu')[] +} + +export type CronTask = { + id: string + name: string + description?: string + cron: string + prompt: string + enabled: boolean + recurring?: boolean + permanent?: boolean + createdAt: number + lastRunAt?: number + lastFiredAt?: string + nextRunAt?: number + permissionMode?: string + model?: string + folderPath?: string + useWorktree?: boolean + notification?: TaskNotificationConfig +} + +export type CreateTaskInput = { + name: string + description?: string + cron: string + prompt: string + enabled?: boolean + recurring?: boolean + permanent?: boolean + permissionMode?: string + model?: string + folderPath?: string + useWorktree?: boolean + notification?: TaskNotificationConfig +} + +export type TaskRun = { + id: string + taskId: string + taskName: string + startedAt: string + completedAt?: string + status: 'running' | 'completed' | 'failed' | 'timeout' + prompt: string + output?: string + error?: string + exitCode?: number + durationMs?: number + sessionId?: string +} diff --git a/_all-in-one-upload/cc-haha/docs/agent/images/.syncthing.12-agent-core-loop.png.tmp b/_all-in-one-upload/cc-haha/docs/agent/images/.syncthing.12-agent-core-loop.png.tmp new file mode 100644 index 0000000000000000000000000000000000000000..9ba8cb653338df4b4051e0335d2cb4c0ba6a2d42 GIT binary patch literal 715131 zcmeIu0Sy2E0K%a6Pi+qe5hx58Fkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd U0RsjM7%*VKfB^#r3>Y{Z80rxK0RR91 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/agent/images/06-context-passing.png b/_all-in-one-upload/cc-haha/docs/agent/images/06-context-passing.png new file mode 100644 index 0000000000000000000000000000000000000000..26d4d45db8b9576a659fe111329578e957fdb5fe GIT binary patch literal 118908 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 z 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 z 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 z zqWl|th3KFG*VqT%Z(1D`=y1H7*wxkK&^$w0OM*MF!9650Ri@5KKtoOKM!X$Z@clEZ zr;lUOq#%32qs(d0XB;4`rFnsmuXwO}0=f}>0-%fvpf&h-b;YM<=>h=+ckCP;neaM$ zd;e{3>n-Gv=K6-eE$IAHh)Qi5-kqr%>Zr{8FoMnPQ(90^W*scWbgN?x)>ymHgl@kC3?du?~{KXjr zKF=Ks5>H0U)?PVOZQ_HUqd4c6SrsKE;rH(?NlAO)vY3MDV$Rh`ujbcss+GoneR-#* zR+rT+9(%};*kfs4s9tj{U-f5n)L?>Bl~yUw=4kT`+@r9((PWhlFxoH9otD3kKxJP` z3rn<2DpvrkQ)mBh5D~2d8n?I7(h_Aewc>lkT~!e=ux5CVx71vQjl5uNl0S^xugJY4V8W(M8j$KVxe zJFcG`8QBUVz`s-&$mU0iN*LAtaC32qMKcGdWM+t`f>Knm)ygV!*-Z(W+l9G};1VY<-c#b?0om6&*=W74%uX>MU5 zAtC?Fi)oq^$M0a$b`O{C_yZJ3PnJT8wDfvkb4wq%9h77*ha>SKHbZ8onQ%7z?pMiU zB5J+`rOXJPq{y=ZK?k_zFd56LmV--_@^p)QQAXi`0-715Jx1Hwc507WqR}+623O;V zlB=tY$q4+0@O z?stQhI-|>->{l2y8AlTrI))h(n53U#;sNVmzZc%WrJ0;v{~r**dJopDkE9O|ZNR(X zGcrXSAZt1hb>K`gn7F;2K}Oa<^kAvM{hjmKA(J&;we41^)d~SgPrAvtgtLB|e)6l| zS4)X+1T`7Fo1%g48&0d$8bDa-dWHP;>(B4sr>a$@9G1oYa;X3Fe9h`F4i1J(fDiEw z6`Pp2-fqWYZ((E1vorqe2HD%Ilv+|3g@gGIVOghFr$%Q>iB}*{F6;3F497@a&qEo8 z^;w}2Iay<0slt#!Ww!qGF z>z07t*XhL(ZP$MNKx&ccWDmdsXlQi7f>rl)ul}mma(5`Ti~%fLoI zKR^F!NorvUw-=e?%Q8kv(zDneo`QZWrnZ*2R!K!A#ofL3lF5*jAel)%6}h}5Q{;3P z?ul2kkx-OEYj4qY84-bO!XvpX1$AR+2Y~Bpx{GqECr!A+#IIm06r9NqUthhlrC?`& z{o-+dj^Y&Bt1Qgl*(mNP*sfWLGBnDC|5`(gVrc3ekC4YZLS~yK9xD0Ai-dC=lo?{G z{MM@$MS{_yYD3?9e6VoE;(F6ol=`kdztb2gJVJM^aXJ|SNG9D%k1sZ3s4wh_>gyHc zYd4H^%OF6e$ZL?(ymS${o5w_cjpN42lk50gv}`XhvYvA1G^^5u_>@m9{ZA`p?V*wx ze`1E5(Y!_I9&6hITI!0}e(8=1gZBW{ojaeM7nKGfH-dh6n$%kAd*O$3qa~5h@Eea3S6P*yH8o`yF&;GHdnb~le(OrisT1Urf zn++v;u8dherV;*usl!IThxMm=t=tETq)m7A-RQ_2jcpfo7+yX>m7 z_#b9yONhUCye3aeg&AHZD18B*7%#}eqMQC|FbM||f%>2iw5dB|*ksjZ+XSoP^6Mp2 zU%}fo?%$!Fj7GsYCnj2NA3*z``i7yLG?)#RVgI-HP=kZ`>5%m6d2v%~|;sLM@$9 zXJSN~v_#O;(E%FBs#k%}YU(u_I>GWOdh`%faj+=-@tKk;psUszE*wN+v)p^HNWo%5 zX(Z{jGl(<2L4Aa_2Nqx~4*N_FftDk`}r_PinZ zPfVPHMQ)m04xo691{buTq}NB`*b!vVvXM1Ly6Ax8Si(NC>Xn^67F2 zx`yqYdt|a&rpgU5dZ<5cC}gcP7#gACkvZJaAYU%>C^O@ybEw~CG|k)$bbIvGjG-`Z zxKtte1vRrxk2p538oh3wcx55|(N1{r;p-f*i)6MWiNoTr(sp@MVRLJ89K%hGP14*L{w-CGCw>mbLyGHr$}?g8rV$)VPgkyU4DKy zjH+Uh;8C$-ru%;_EHSJb6o^cA(1TKV2%P=0A3u46E|%`*tlV;^FSIq8?5Vh_Rto23 zyvbs4v&K-h%4&HatLyYYXbaOLMu@62mVINgk!w+1x8;V+v+HA?!&A6P6U?S>+(A+w z?=$CU;UB1#&WGUz4!8LL6(SJeDPj?#uaHn5FVS-_4HdS68H=9Y?F| zV|ALeD4Lik&lzWRPs^M=QetYZSccm|G5aj07S|p1`WQBH&HW&ZN}&CBXM*xkWyHU^ zA@dz_TbkJ#oWn41aO%w83O|XSs%;%Ty-iM}mfYD(ZI0qNU_LWb@%HD3lmNiuYANWhM25g|*7AfakDMo_N zVTHwhh7r|?!&x(O7$D40^kwIs!xE1t6aCRjS!O^YcI>U333@1=yLn!ZocvuMc?8?d z&kEb^Bd6@9TxKPjZJ|1$D|hllqFr=2$o{l6cjQ@LEydQ$ph{btMFu&BxmXv7Cw}M~ zz(a9w)3&4zPzsI>wqJXHF)W~apJ=%zV#Vw)(gtvU-k<|K+8Rc5x8+Xxmjg0Uid22`)6_5=mK zQC~j}6dOn>jX|?<>#8tgHF%jeIL}`hLyAq&A&TlW$HKBEUn2x>$MojNEoYUknlhdw zH@}Ypk(7%Gu(bPWi3-Aub{GkM?kEL#LX!L6=$-?FZ>YfMQa(TLj4k%C`s4eaMV8_J z7IcC*Z#jiwQwBQwaI$7j`>LDj#Uhbo#bgI}{-;mUB-<@W;=1Z=Tgqew6qQ6@cfNu0d`0=K7}py1 zv&+%ak36(FlGlUkIWvd#c{dW8H*WUu*sz);Jx)t=WBNAE{Rp$GpCdGch#bX>8U=I! zm>}n&b%_1H+VE5+Dec~vH(yP9EMvc-4~4p)7uI!8>6P_sFvO;TQu6=WgdG*EL}aI-T7gCT=8czS>7iV#s{nU)5hS4+WsceH)2kCVXx4H{PKypJ50E$E14M z5awdSoR%l@3PI|q1tC!~Qi!K+y{BZymG|x7Hm8MNx#e?oueVtz^mMf9$uG+m z`|9}jx-&wukCc)wq7{NK-{H9Ln126g$w4UiK3`?8b#nb?e|+iBMqlF&UFNC#Uknyo zo_p|iL|hRw!J2myU z##cTq?YlzO$8h@?@}Lgs2+?w8m4t!D%793>wx=KS^|U_>9uRSomfOq~;Xe^7=Wlb4 zqkiu3>;B07Y6nAV3(8Mp4a!VsDrjVX`Xl&qYI%a1lTc6Q#B4r)%}*wEv={jMqwEN0 z@j?3UxFqNlFjYJlO2!JrwA%xO;nymURF(vd;+wf9`);;8+RT zm@JLNogqI;bG>yo>`tVB-m-c&Dqd`LX5@=xIsU}Kn5;s)tljjq3M-yoI+lj6O}`=_ z!8!Hp=63cih5vv!O$tJY9HxrABnvIk_cb>&=RouuQHb)KkcWguv_AW|ux>-#qJDGJ znpVhyT=KK-`BUOAzhW824_{Pd(VFS^~pvqUDlZD?@M*%3L$y$lOri#UlMFi_|D70f40X!@{mPa zKI9MlX}0lgermYUVU_S4Sw(zR7`~SNuJOCEJqyRwz)=3QYDZy>VCsdUHKU{2-5~WQ zW_2Tts|_~QBasb%k&i|9TRF2zWzuCf$Tajs28o@G3n)K|mN9QRt*+j1u~A8{>y`=5 z)+UReew(P?WZGl6Rk!FOrX5%V_v5yr#q%?`Db6zM=7W-q`n(f3S+I=!jXrDYs`CZqX5xY}fY9okZeH?k!1*Ai;kx%MsjfAFrIumKMQNPH~wD2({Z>VyS3 z5tAThou1-_WRe;#;t57dUq*`WpYoz9hu=O)XB1leyHQE!P&m@r*hwJxouyz|w?CmH zMcy%nz9$q{=+DjgU-!8kdpk}w!W6Qcqmuoiv^xgSz49M-aP9dj`TUKj-d5>Q(rmk& zZ)3~&d_Ur7@8ndZ>h-TqDco5hzKe}R;YI61taE$DaT!_VRVTF-~9F6NlM>$ba+x@0|M@kYP&rX(?Q*dy;@K zE+Sjw_K|u5WvycH28vn^Mh{mRX;0C6>JTb~djIR%!j@ki7N4zm}z%2iq0I zBfnkxpC?C~&y zlc}Fv9H2YzXIB!MDGI3Ly5K+7o-$pT)lXHPZcWI0*ox_EF}GGsD#&|mbCo{Mxu@_+ z)w*saIz zJBd_%T~FEwyW*A?G&t0*8fSDXcT?nIs>V=1c0M<)gE{?Ww#eaZyo)Q6xvY$K{Hdf~FZe{Pj6x=@ zT#Z8oQ{gQciPIi70iU}UWmVGl+gO^?AILckD|H0ArXdZ2iUmUYZ>notnF8TEl8))G zO~YNC+6Lb>k4kFp#PcoVbronTTFsPGR(^DF@Ch4pTKg46EoRp(fzTN zzqS}RcKG6`RgIs99y@{TBNlF6`K;;T@Fee`(j;ahoq?pjK~qy)CGq4mn$3{JKzp^& z^L0@!g7_;VQqr`DF}(cPh1I`%-;M-TBCr?lF0>EOqH$cUX$G1;wgpZ8vgLP5N@@RBdRb0J0)s;c4v@~(cqv_sh$mhK6(N1!{ zT6kIzr{6A84GDB2F-TbD-lHlGOm+bHB;!X&O%1)vWaQc3yOfKbgnS zgaFD?tLv61@{#yE%>rMzaF0g1%p}L}%cddIeW#6dh~>Td$;cA3>w$dfH%1R4*;vSIX zY+|Qb0fZmh3-hL1+V!g}{K-ojSph<77yit0zN9<-U(~RQFiYMKmpcU{pdtGE8LWm^ z(LWOvykzLE^OQ`w>(1E9_3!S!{-6E^&7JFX1PyK_>Dl#e07n4;u-r#K=E0?p)vK$<^dpXzTG44~}#Ka0sGQZ|3>yN|ul$7r}lzG2=?%19wz`wxu zYv#4mclY*=T_}S*azGzGtJ{a`JJ5NJo`a%TvAN`isK1A$TW-Ljf4JVv=U}B$zHao{ zIfCKBu;Cj%c}H!{#I%cJXG=i!3MnqV(p09T?S*TJUZjAV4p+DcAJBQ5LK66RxHzNy zZbbmpcJkLwVx^@(<{xf&zg&D62#r4z&t?!N?%RceB-8D`!~FZ11z6EhGh=mWC;grt2V&w3ks@X`MhXG={?w- zJQ*vyb&BD5uDryc-x* z>{OXI_(aW)w}*lKg^O*SHNtQ$^n8A@rhABNZQUCw>H;-)Zaeb}Xfx1_W^O)?ZUgJN z-GjBe&z>>F@l+VCk7%BDWqgXYyEwhk)Ex#ua$<(a@j7R!i`0@5EwCyEYEY^=xWi}- zW|M=lg#G#PdJLODZ?!n80l0b$<<$!~J6xU~+#+>i5+l9IGWH=&3LEDTYHybj@yduy zB2kJG$0ITLuEc&fvtzplCAZP-2Hyd$y>+sxk=GwuM5fetO~uM{C*=C5UzLrC>)Ox^ zc%J|xy#}5;6xw`KI?XsW8^3c|;@B=T8TY48t_@#JqzGZ@>9u0h)?KXTs5>4wz?&e! zs@n?hZ;My8bHasS7UeT&ghPp}1_NhXu6#+TD{;;i%$;ooIWNUmCMVx=Io2G6KG!nkiQ!ZY z^afclc%(ywQ=z`L4^wW1RNb}q3ef-keatJQCdR*@2`ZB_2pp*8@gw>o1>h*sko0)< zEP?GUGXq1GUJu8Vot6X8JZ|1v!xHo-!LQ2B5Kpw-nyR}=NtDEVa&poc&0^9WXYeu7 zHKqcu+dM>DQJxpb!KZdW{y$>xNC zbh>D1*&tujLxTz;AUFt^PHeAk+=7g28||r=&VpEc6)?k=cjg4ZyP~GPzGtjVV12S$ z_$j#FuC|h1f%8`7`xm1nOCyz*!xUmf;jyvPKR@(rZ==3@ch=jh!Na3`s+Or9GYheL>7C!l#N|iu{=XRr~P(Ftm;`#9j z3Wo1ygMYUAw0xf2eNTJXi!3!jGWrz7qCcGvO4HYF>21RBB)}ZAb?#spiR|ycX!Klr z{hCios_($j@PpprmcUEUYB>EBfX`xgb%}MVez4L%h(u~Od?RIHE@o!2tUI2?cczV%KUB|l}>dRk$2nV6ZdxS?sWYtsO$+Q90fAG#zt#itAA$$3< zQj`sf@b)LWWq0m8``j!;GdNZIE=)wW%vg;d&9fL*#y+@-gN>y9OsE?;>KKj|mvuzs zVcf44a46lxfAjjQKK$;-$o#2_t!3zJsq0YQ5NW1h8vB#tMcWKILBLIS1QiHqC`b`s z??mzx7k`)w8Z52%OdclW1nGTc)1RvOqLFlkOkLWXxL0pU>C_ct0?Q75k;i7e5Q~z5 zAm4zq0gDW*4khc)&+Sz}+(3bDF;{V`{?frUO9lrk^l9*ufDcD|dm- ze)YD6wib`(g6YQjZU@0>1&$2`1qB(f>OuSG(IZAD=h~ixS^_+UCkEN_Jv`LZvJCRQ z0>EqngI$LMCm9-9DXDA`Su17QNZMt0t?W=AA8M(r&e73^kc&H+!uk0Op%k^?B`-?@ z>@P>pMipsKVe9pga=o5zQ3}hgspr6f)iHEf9jLgE_O`CBs^S~;yWQ(LZN7W~iqn(G zj$|rW+F$qgMQv?|eXyp@%?ly02rhMRz!gCWU$6W8RhA3|MLMeq!4up_yX}8pxZnBr zEOBv;FshyBoRARE(^Xa?=eCjWq*GF${Su3M`y2}Be6A$Y4RcR%KCW+UK)?gbof0l9 zb7(r~0%iQCyxsY6v`ZKVJvBAt2NUbw#U}6o4*aq#=sLyM_W63?DhSg`>IRO z;!UDj9WBXZ-e4XOVdHd5lQWufShIFUtOam*(L526QU)B#F<3eqmcCmSn0MP?YyUmEhD)8mtq<#PZ|g zU*!yX#_jKcQSB3qtWX6-yg;%Cp)hi-Hrh1d`J3)9ZdVLG#zc=_-bjc)30(3*E z$_gV$ufN+ zi^%);K(#Fn4V`n`3P`=BfX(&5hwYS1nn!=ep3DQJ;w`4@Qg?Q$*m!JPzOPi}qdX*g;`0aGc`wz> zz)l=o1ncWhoThB2yQb@1!4cl5{_0YiyFO;9+@wRbTFzwpvUS>(@nCO{S>4pktlDZt zUb&nO4A`yxa6awRj*pIBLgopn(e(?J&1&;WljQ@0#|~J z=dfQqV~x~t_oN2AAkKe(wLUv4ID@_C#EC@JWx3Z2>|#wPPtOFd&MUQAeStuPTmW^I ze({dgWqlw-QtVxjGXLEAA4J#_0)iToaZ<;_+-OzY3{9CQIs($1V)tXB*GDBRxN}$>%udl!?TUGi@C;KY>)L`}3#`IO>rO9h} zlHLz-`Sz3Ixh&I^D-4gT{g<(UiUf(jAW%X7si_FZX2t^w>+>l{lXa+B;YdK)`slvwmDos5>K4EoMtV! zlE`5rFS!Nw=!$d^3wz~J`e832$70d5VbzxiYW^&eX5rh%CO_nEzdlk4Sd+#bcS?*7 z5SyfU{K4gThQ-zv7e4z|U2K6&Hkj#HT%KEd3Z86K?17vhAMXSXW5T<;bE4KEn6oo8 zF=1g!LxDGHK0_P-%a^JbU7+K2_pT$0r?98Dz{YTa_p9HGIGROoUw@4)^%fuvLb~$bym=1u<$;hSC@G!I`UMFb|C1K{3!5=4fLiD3 z&9c`8wL^0wMSFlffGlXPwI`9k*7?u(VSad_bCsiF(0B+r?J|B=OVHJbc|DAo`bbW_ zAMw}X%}DC<@^48=Zno3$%Er#p8!=;y(ia?q;?k`qSC^rXNsN~oaPVy&^d|Rvm8GTW zI5;}~kiU z{1r>4!0kn?M0Y&aY&HEI(l86)T%dVS0#KU!L+2<)@g7i=#v^Q(=1k9Lgcqz)c@EWJB}Zg{**4g>!GB@})8R z+2-UsKrAtZZdxsfj2un7GV69~G}%w|_m@E8=GuX3+M+w~Kx$i|d2-P5G0Kw?@| z6(Y~Z8qfwX87&sSLhTj2b7vMDZP-l4sCdt#H7ix}qnKvq0LNoJ^KH}N-(uIOSN|sUTkGpIsgHmr70DZ1O}|NZzLqyg*@Sb+ zXK=c2@PhAdgls&n+t`nPr-uaU z_s(3^KQR@RkeNMzAB-7KWLA$o^)MbS4oW~Pb=rt&&|unkRn&)5?08WsmH$NtqY+@V zL>U1S=W=nH@<-x@-UtesahZy@$n6D?;259^M21HfwA<0Cw0wQPRgDYFaWa#P@ zF5=(d8c!&~FzLEJS^oR|!E(vv>}cAN+X@df2%Nb)&bl}< zz^^nzzJOzHE|l80{qNu8)^-q_P^`9jqg+P7snebTM-afW1rS*GbmR09|FYZBtuRep zUVt@LVaQfEqKtZv?Cg+uYrKN6cA|36{4_Z}`Olv);ee|C8_!b%`sP6E!bK;N;dulL8C`SbhWF7z4`_+?RVW{3IVdusN06f1YY-;X$v&ni}d3 znL(<0<-l;B($pL2NrtR%tqr?xBsn7%=6B|VY+XHmfUVWRmb#S|9-czIbVhlE%;$6g zd;2^4M&yuJv;-1s>fWUnU<7Gnmx~lOVxo3e+k0hiy1IY&>6hyDsHv8(=Y&!+u3Sxw zjG>hq+j9};YL+j>arse-lbmf}=( z=R0`+&hvZEIqR%vJ@5P1JIm$FFxOmjUEkR8*?WJsM?c`PxqmM!GvnFQ3j1+0qpRxO3aHFdcf#ZXE-`^(V|O`r=b!SE*ZNa2yIUcjju^s{*tJnbJm+s zU2ZgSWKo<|5S=dlTt;5revVI>MeA{hcSFN%YDLE2I&6tIZU{I-NZZ}*9B9@r%RqNJ zOj7MLup`cP1wp^3I;X`xu-~^@^gW7^4qI3y!XM!IhGkR);xvG=OyS^RmR#oV7n z9T*DAt2Jaa-H|N7KQGNcQOzDc6Dw1%d7vHq z5pae83d3JDg8?JS=2oac5ZkA?Lz0uVUeJzlIgkQ+W>i}F6zc-NgQW)0(kT8@X?pbW z_b2ebT)24B%d+(2J4`ptxK>|Je&~#$5*JSgIdn!wxtg}Xi6M(zbmH@CK^I;p0L>G3 zFom0fy#dP<8COxgemS4d@hX)d=XD{~0(F*j!X}tI{?n4`giXKH{lekpInq}eL!8{eRwq}lHLLo5rCmUzwCgkgF)HS z*6bI+b!wqko7b)S*7fQh6l4os{c3+g?q6HkD0tuaRn=Q#kcI^^LQAFuBvB{J7}JcV zhB_iASq!g~x4n zv#pZz!Xgh(*NZMqcJ0K z2Rx?8P#SB!^%5XT_qe`*pUwNm8#(~ddUdY0X#sk0T8}!Op4Pbqi;2oKq`F*i_ko4N z@kx`7X{Qa~Q~AjNvO>S!j_;i*_Xe#92}S(gm~?}C{}Dx^$U2xM>i+djuH7Jz<}J53 zddG(=-HwKUvtg_Uu=C8+SakwI$PuEOwM$1?ofr~@vI#HmO+#AsVwWAQe73+A+0$0i zYcy2fp<)dufPa=7GK&az{#tyX`00x>(d9iPWhxUs6Ef#@#osCHqiH~7<@de^9al#& zdrCm6^G*qTm{9=Y_x(NnF_rimfv(wE0Ic}Tn>pA!(Pi%y9S~_#m+3;!YX%GU=V58N zMa|9cKm)z(UT)(4OkpWrM?;q6Uit{#=HH%2tF70klfe5(l(o<*54JGJjjEvvzPdWv zqLvfk_w&kAXApGXio1d5TG&rEgS!POcNBC*FWuZo4Gu5&Nm?&t&nSg3!u;04( zdnEp5V`IQIYhB&d8zj-j8*u$ZoGnZX0g2%dkN&KRxIYF~l;Rgy;4QlZ9{C_4?%3Da zS#i;H5+soCU=6>Al&xN(rHA{u95w!(o)=xItN|aZG9ICb2!+O(O%3;;jmaCJ&@y9V z*^isNbn6}1&3??TExglm0BA~EThw3{ZyXH@H*tLT94L^vI+r`T6vAkr|wp9%l@SmDpd_U}#bE6OsGA$%DCvv&ts|ps+#NrHemb-D&W)75KywTm! z_@1~yIKlY(F-Rhf4MI{*Pax&o;P%>Ml}dTKNwHaA`#yhAO7Gd#PY7vRyPTKWG7Ce{*y}#A8R_)HH&6brl~=c@PlM z0-WS4orFhFRw2SQL2)GH|CCT3;=CO~Ji|(5o1af= zUnJ#oqNJx!G+c0N`fG07<6mF?}_rKPKb&Up7_ z@lj5Y*Kc{#1=2l1s_n|+VvlJRSWnT8(s`h$;-SYHbP4MN2Kh&2pFWX- z%yz97#6TdSB4UM11_a<`HqBo(5&ip_fzIN1P+LbwUUO-qh+J?eZLG8$Gb=J^Zt1x< z1{@9mm<>}?Nuni4e+JeIMey;~xWwN-v-q410U4W7pWltp8bHVZ&j||=w+)CF@Vl;Y zP<#gXHE59z7}7aLm+BV=T3x6=L=PPA&VqK$&I>KeA>k5a9j4tt`2t^h!N>M{1Re=` zJ;QW4Bmj_=BlvbQ1U(aTi)a*xPj{xh;f=c&J|eeQdE|lm7K?2}?54&J4)Y-6`7s5+ z66EE2o87ltQVm#aM+-dOc9{BK9r)f}xoYPqE2eQ>42sr+uF!|O_tjB5=haG`uwkHx zkn!6A3Mj|DqdK7rgV@kIBQ~3t1uHevx#72B8tm}f^YvfARs`J6@KPOR$m;44uxWti zJ{e{dlLnv?Dna>ZFL2gTFm9Bt@88?s8fWvz4aWlAaPxrIG~5f!QdX!at^|u=^GjBv zX0JRzk#~GJUSa|$cqxLx~yu7 z-lbvA$sgKCNB!AQI198et(tBuk$Ri$g;Zh=;7*7#9ol8~xQ&cAdn%g0262=m&1lNP zYBi7jnzEI-xs??vh$w&*=+!+@a535#cjRV88ip3f#R2}UZ9$i>UNr;gZ#Q%pOKsKS zn=u=(lv^B)4*nvKmA+cfN>|V*QD=zkCkNf`b(ruCp2S1+cotYTqP3rjftb(+ z=oK0KO-QWk-9z%kney`hO_V6fl6{8AjwKgTOT1%MfS6`;h-=WH+6NK`=Jbit)S6+%KWRiyHwnSR?rw|YenK&r)d`3!qYa<&lp4K$?R4%jt&Uiq-R3RlYugB_C)j0Ix+BK26W{7Q zkakFwSRghI9zDz8Mgh-gQgZS*X!220?Xqz;Jq&_$^zq%m4?Vuvt^fhg5G+~BSTa84 zV~=m3$OCNolf%Po-svyS$?6PL!2sxWINqQDm21p?teJa>ervP9Isn4$bcf!KN05`# z_iQiE?R+@Ts!%CVFGm?nPS+so&>h%!&9x88gg~tGWsY(|K|%7&IPg~hQRMIC7}}cY z#(J#K5aHkTan-xkkOGBWM5L2k*e5B2`FU_~h%g~f=>qURd+QNZipCU(YF40F%8CO} zP0E6kH(r*7)nna9QYZWK0pfO%w&?oaBJLlF6||3GAVp}uN}fC2g!m)ijX=cx|9O=D zQHOW$jK@L3#xNWZ|+Wxc&CYew<_5NVD7g+Jp*0~Z0gky ziQtJ!_S5)>JwQhsvf9qF?g5^aXB$F}edwyEC`J>JO`jd-$XG0>oP!5}97D&&JVPWH6Tr{1b%Ia6$t>)9+ z4iqq<84Pnaop39j@HoojaUXZmHQcf2{(3o~OV5{AIHYGifX4l6_RB_neoV~Cik1t! zFaoCI%|cGVHO-9ygts>TA3gnLuBa0Hvy5+voH|WxQD%_`&l*Q(ffh%0=)KoIN*@GU zbag(qyE~PM8p|HfX9>?V<5#W9B}ILu{!$|HrlZO=uAnnNjBItLiHnpS`5u#8t@UWN zUOfh`1Uun}60P=ULTm&lh+@&z9);kKgQB-ZYXJpK?%PhgGxqIqz`TTmHN4yzdmIA* z7*cMVp>H9r>T1XcP3waongi_szg90=%?Vm)Q~pAG&F9AhlUJGf_Ir}7Lb2VI%F&Xz z6p|E|OyI zQMzmb=6iqy$l-TK@-sx8&5@ih(V1QBPjSYel1f*%dmHi}TeS;%1L}wBDL?`%T zZ94MwedJ_IgE_Iw=SFic32v-PblEGC0Q7uuTn`E_l2cMlWxRDjy`(kJQYay+1Se_? zz|#c+_hVNV!O^;sAZV#k??5(Xm!w$&ZeH5bGCI`e0Uwd4H4r|An{ z;MIY-n6!`28n8;-Ab~FY@!f9j?gQQ3C%>E$d+|6@KkYFj_X5S4ot4Eap#q9cfmc4+ zS$F@zHJ~gk99JcdvOL?P5;Mt6brH$pwd_;&_0_`&Loif-{;cj}@oW&#;Z6e78}x4m zK{!xic)T1_(lhChiUEb(B)GTApTu|8cpvqfWM=Mx7DJ%PFTNikSO>-AclN6?KDDV* zM6-OMr2UcM-13w_WBpdL&-DvffFo_jLfXkMznbt!+k-aHVSWbW3WT9;&NjHt0yszJ zx$4oX#p=e!#|-AN+m!hD?VrXKa^5(0*Yj=h4R8eJ$3ayz^D8?7}y{7Qz#3@{90XKuqpif; zHopKZAjqjPG~5H7;DrO`^u3!rasZYOx?_EBZ$Bxkmn_xJ*#-zaAWM{!kpVy$E5+x# zEP&Rz-K0(B^erU-re_x{=7e9`a09(OC>jQe zS_G{}HZ1$!$uhIz(A4~XAt$*wBu5kPz4*=D=e?=A`iIEK_;Vj%D$f;bxcW3`l&pE~ z1*aQjOC1V~fc7f}9c2J++>VLXA<4$wD4lGW&olR+z>cGjosi|<~Up8f_x z?+|s#vuVF;Nnw9tP&k|&6{QgL=mZq_j3*-_^R_rG3c&nUd&++POb*kfjJ>$BBxYbdQ1-H#Y~2*}j{GQ?DkC z+C+xoZM+B)%Ncsj^{50-LPI`BTpGBX42il-NeO9BX_9+SPHdr|^`t13qy~d~)ze7a zd~SWC)>6z!-0ht6i>MJBD4<(txjx+hC=ZdOo}JwnPRr)J+u>i80EMmxGYm?!8R)P; z6M1%4)&+TQkRbq~5N0**1V8S#^}bPAoNwMKenrXX*(8}NfLm~(HgSzWlP`h9HSYhT z73m5uPOd@gc$}vPh`LsiP;2?bWSM|~x9RDT0k}E9^%9QJ;Gb)BZ}q>_l+9;g+Ia~9 z@h2htNC{-V6nPpl$ze5y#13o^LbQU#3nu&$%9C`Lqcu3lcG#Ws?y6LNjtxv?%RDJ< zP=^_gxc_*XDBXrbN6uA5vIW>0$IU9J_|1M{W_MQ$0$`p^7XRg9*+9onutJ4s6@$=ex31&RMvqSTLwTpF#v!A$OP!TSdc6% zqz?q&nIlf0^(f77(EexDR1r4w0)5CBdW0R|GjQsfk0fxuC>>Qr-f%h}j-~Y)n3qA4m_8v+EdryvG99`3i#`VvjCnzBt+}yCSV#WVr7;>$rX_ml1>GkoZBQUKaC@;^F zRRfMUrh)IPNrwwkL=KNok52%z0YbEko|`v{-IPAN1zx;W0oML)3JqrXE^V%94Kj}6Bc$o-e|jj&nRzLIv>&F z{pW9Rm^#7T;V;TUK<9G0Cx{Ks&HeyYjptvM;{W&NBw{F#DsBF&#hQ(el6GvLVT16u zZFoK0J@1bE@M}*vbANI03@yRpdrwWA8mnCeYFIadPc3Y{thiWq2eg_+N+9{i8E9{? zz!W0{zJLZOwySCiRK+*%*t>y5zXH6KEM*tkdK!sS)Zhzrynn_iVVfbsYSy^#3ebX? zZ#pL>XeCMF5Lkqexmu5hwVC3S@vQDxN;ov`RXtDMpWP=T(Q+&kOS-*^4)CW5+lJec z4(5sE&>7H7cI+nTN<6my^`mg1&>$C`&2@;tmJOBgzmLI&Yx z@zLdFKC^tjps;Xr+8!;wzdN!y@#yC#h|jzEYZ0HLL`2HC6 zJyhER-Jp6;xG9Q;+1FBkwjwFKFIfv8e=uo#39tT4ON_4Rq95iP6)E~fp8&dfP#{Fh zzxiEP?7d#oTc)?duokOHm7aH>5^D6^R_&3!+(?t0uaOWXgnFNTah+z7Kc?8*MfP?N zq&m6c0Y!0|O$A#rO<&@p(ZR5HALcEN`ifn>wXm^%8&wkH`hM?CI;01pll(3v>|Di! zXTY$fLLnMnHVfzo1Jt#_zvZ(4H=7Cm#h)%^x-!YhP`LsOdT=}Hq##`yG0*Y3x*uKE z92fKC0)h%>kZYNs&8mR=Vn>knNzP-6rQkwRWUa=ziB_FcxZ1JHz;#XVNZE_WRgPE} z)mLr&myakU@Kn@KVWY>UphC{$rfqGqqSQlSTusC#_5C{FaZ_3OJOYS-T%KhP#-NOr zeM%pwUL?3=jRv-WcAQEHAbH{Q)~wv!I7jHZM+1x4$>*7M)N< z7d>BPJDJ<%39N5rii?o*c6IC4p+uzzZE}(|UB9(@hFeAH{5hG?_Jl*WUi#$NQZwMc zQ>V;HO+3%MmkF2ToF)~}*Vw7og{o4Fp<6QXs)4d{fXFb6;BO#kkn#WsO7O>NP*wz# zWP{~-uMT3CFZewGE1{PlW;G~H1o5MzR7kNHkzjn}{!!Q%)<{M1dm!0C2Wg}tIDqVL6<3~syHRdJ)R0z5 z6#NCd^gmu>HQGEc+GXPZ{McB7toMQTv5vH8)d%hPJA|&kKm8GiqV%Czur|?_MWnIc znF`<}Knwi?1GqmOsc@18>cIxo zG)Nm)( z4{IJ@55KMzwQHrXTuhk(&g)mYe{RU;LzRD8cS0H_O1r$U*ml2v9&C8L8g)fdT*ZH8 zEJhkPl;_Y3E8}JI`_vw@u0i%9RSyB7HJ1!V?yhny4pOHt|)R=Gg7d@wdzv`~k z>IT2{3i@YxPOtp;;qztJ zC)B2?vIXjwjkD-~YCLFaGUups@J%a0tt3^L+>h4>#-A*tdwBomt|f!>Zwbq9akcy6K=IN9|* zm%otX=rgW_P{u<`hUPONDj}K@dz=bZT6Ym&+MDAHJ~dln`w)zxCw5b+AwKh21Ps=! zAk2h;D5eFE>>op~Ywd!bmzFd8F)!44+6F=;XIl+kh#S#DlSYsM|Int}upEpewa#)LiSr&)UfIw+ZW0XJj=lg&$jG4xz#)eI!KaGY%Y#9PH2b^&r_s7n zjJOeVcckkZ`tEQ2RMqRvG`V1`M?qKo>)h=N1*p`dJiXC_?9lVtNj>HTUs|QoqV+{% zzR)W9GCK7%sVW_~*i|`R!E3PQ|G`+1-VmD&c61R@&D#BT`}6@w|`QhOw)$Zmqjw*EPxlW9J5Oi!8eO}1eBUh^NUz087mG15Zpcg%0_H< zK75Vuhk=`So4BudpaT&3;w^4%?L9<#A<=)gi>Wo<=-?&(%M=4tB>&B>{S{&Sf)N9V zz68uW=m0S>NXFy8@Wl`>-e_e6hfL2go_XCzi0VI}-`A4RN-%*hQjI~K@IR0L00Fbh zvymMOva~hfWcQHXRR1&8h@<|IBFeVIGWaRXBuJ&A*EZ9_n|;cC%4kU3vwg~^)xIMP z#iW0hGvXWnNRSuyq0gC+DsPS%iQ@n-gk-u-;-*$G7J}t>d>nya8lwZtIG^B-2BQV( zYe@mQlwJQY~@6VA7s*8D5al@lCUqc0McR5#jN8aS^aGT~y7U%{xJk5w+ALrkxq>egQQ5rS0GdPg&+*{T zh+CY$1HSLx`~!d9z5X9$;lGdi|0Tlu|J$E1(=r$bCCkO-E_b&G{;T8x;n0#?UBu*T zjNOS5#7D~Xe>~f}!~UhN5O4mkQR}-i{XeJ8thMI{ST4;yYhXWOgX*oa?=!!mz>m8w zk^liwyhPH*a9{g4swcwfq{JF5%;F7J?~c~oyJJT0j$t?>X~RY%&-z&G061Oli2+;$ z+73uCC0erXj^xJLo?RhL$ICHqGWwDz7|<+5_5h^vGCx4I{a@ov1z>M(F1sTLudb z+EigLtVr;K%w@+Xu)UORb^k_&oPc*<+ZYmX@3dy7={kURTQee| z?QeV7Up2E$^`|R?Lg}Uf?f!Z9J%sv&2@{QAoj&qvg}iC}QNn~uw_Sg)#4A4Ag*~(- zUkT1HP{Xy}Y|EPe0S(N)K341Y#``Uu`@jp*?JlJ9*_O0s+ayT^6;ysXct|#eTiK`l{+p z`={A9;jghISrw(uozBu!Vc>2@6{$Pc@Z4`SBc6*GHF&>I zo&q`xxu82lR11L@s2_7xB+xg* zTKaB=?zqF(1Z$GdhkaD8Mdhw7L5%iKs6QTDU@`hZ56V5J%J=AzfXdsHlPEMqEB-r2 zV%-aqs0VwpCz_Q{xNn3e z7Bd>q>Xb6CUaC`0bGU04AA=Dmz8FVC(kzi&KvfO~<>2Y$Pkb+D-Ak;jLhhAvxI_K4 zHu0M4DsuH`=bT^Y0FjTc^1A5r{qc{I7=9Q>exEj+lk^KFA`)lh!X*MVA`SXu9QTC2 zT3UNTScC^jT1`UFapfeZsRANmfxYV!T zv2%0|OjgtH>FU%Ef{+o>JWjhwW}AlbYetqi+my6t6BOb z-J;eVKfY>!(sQL}eCBeq8j4vR!eQIma_^0exkikMt!(bwn;hZmdV#KxrlO|gWai5w zIqPvaH&T)K*?l9=BNV3F%kpz(yK8VJAZ_~RyudyW ztrw#9tfMr5B|SgSjimKYblB4D=+g{(K!zr`%wn7_;2i3IP_wS>vc1w{F3yKas*FwbRB)7rf>FdKLsiLUcBUQl3^M6SZnGruh>KZ!ahRZvA|JHI;Ap6UH9J zv#TseOUZQxUGGD{)9<-h#dq7nW;Mgy1ehLp4HhWmE-aoTbPi0@wl65_v!aOk3IPIG)rs7$=~7=Utb|Z$0puVg0<+EJTNnC8DgG?f3Z?KSV0TQy@bywkT6aabQ%XY1QH0E`h!dxn7cB`bp738#|4M7NhP zuU`cE^4#t(U!OnZqzG==GCcd+ssp~mV|eA*=K4lJyQ*4;QIbfYfBn_CM2?JPCDtgpwm32d%kVS`d6aiDd(Q>=K@jN z9%*i7UIS9QbDl!u+|Ha5E;O2F$gu%*V;xEaJFKBCjOY6>8D}76DWXUNV2R$sI%1E# z)0l5>B!A4j4S-+SZCWWLahVsC2xhL;Ij#H8cW_F4#$|-IrvHA>&o(PFAnA#aixC)213OD97Qu(e%YzFv!q zQ*;m@pe;ZiHIRz~v(e+SSt6+y?+k(VzY zP6ZBkj4r%g-tV$tcT4*+#YWhu9Uj2g4p>B<1-<0KfM}KCVZPlvBDG@U(aXvCy%Shd zhh{G0{*)KfEKmSQ3lIH?Jb9guHRwSfeXUimD@swW&Bwi-&#X-8J2-*C^(sT&rrcIV{NkR@;OA9eiYTotxx>4M((9G2E; z#;NCh7{=wscPwP2#>bOKDpQ^GY1C9!WGf3k56g@B8Ag&C%YSIhI}c0=9=ji>v<=cT z4~sg^?gN!e19dZW6$L|c@o0+NSLMZ~!#$?Pzqtb2Ft5%#dJHp49l^{$z#T1IkF9c&(==!`DgH zBVhB@apfj?t&c%M8SsJHgi{A;n z?WU?Q8ep>oW3a{KJTk#GHq&yO{!Z#;(YlAbk(Gwc6&C>ZERBO!W5gfxa* zfX!gfFMkwM+Iu_)b-^)KSk144G7)@@`@HNTWHlj*#v5<@)4G=@@mP0D+;`^O%NbIp zzVaz8cR`TccOd&k*nWB8=ou#f4^l zOmR#sHCuW)mdE`@s!2Wux*~t(fN?~?zgO+0BuehX=KEFeTJe)MO5zhGJ z!9pAMW8=3H-(~HKkXzHU$`;AFA5r-6P*F;qDT_gJ(9Gn~Gj8L1W@qAC2aR9*$axyd zo4khsy>9R|;7r?8c5xK%5k+0dsQ&P@Bs2UR5bWgg*u&gwG>3CTP$E7mV~Y5PfW8Lv zQ_g;sM|xq*{)u=JvEqYA3l57TL(?=gS~;waOQxgWJ1ln}z~>@ZUEIrR50_NX!$iq{no8G>~7@hqRJw=dAni2S1U?F61=D_EApyfV5dTdD51_$-LfAx!2vy8fG zi6_P(*>bT$<-2p%;-h;HKIybd{n=A_Vw5TR}PGJOe9S1DRHuP1ZdiIv)U|n*n1BD+;^Ae|qYg!Vc8clN&{tr{d}2{Rp=LlG>^DEnDOE6ks9iLn zn&D?Jy1T=^YwqH)7<6rF04Ir^oa$HuMyl=JdT_ohm+r_&5HBoBFZ303=BF@Cp{c}z z+ZlGxSfDVS>>9_oPwKpTx_Y(%31iyughuYjs};H{GPlmRc{T=YB8_|IzVyn#BVlsRzkA`69q>fXd_!{U$zq@?F$$;zDUMgn2$^EFN`gTh-_e)h||3%x0o%RPnA=g(!@5V9Qjy4VGs@_DAJZ2It6Huh?Kqp{qzP-hnwypSY9cZaSJ99K1LlVa-Rb3SY5lv54J{l?*)gyk z(a1ds-FXcJ8X?QE?C2OGll}Om6RJjriX_igeoLwq@{27ivwkTP1?kLpspzMOPB z-|hQcpvXD%rSZwsL)qQczYYqd8oks~i8*G*!PRY2rGFei9KxW zUS7id(;YI(3jsW^TXIL4#ZU>?9%b zWFm~fM4I?9c63BSAE!#Llf2(xn=gdMo0e>2!tw$V{-_{j!RR_8B~||cr%VODPi*1N z1{IxAT+w&<~E~g;?Lw) z*iH6$_8X0e4juwltL;bU2UGIxdYPtzdgE}OK!{N_C$*BkOwybHk;R(F{zR*|JrWau zk+o$ZInlU=o5a`l#o8Kn&-Aa|TT|(uJfYAdN39o`P|z!>zcIlG>)zP1Y7*rz%97{$ zd&m%yb8PgHI3m|*MXR)q!q*f%aPFMTbG>!@bA327(!LAej2wo<-pjURKe?KVlbTq|YD)8=G|<6pms`u%O(C_B$$hJ0 zc{=&=pYdc+ey#7-D5KRA``q@XD_sdX5!pYwsvI~rv1_HVhMJQb&giJ`TG&4Pke(7T zs%yUY(vm3MZd4!y!AbgTB(SZ3^{GIXIMJrpS2nIU-tk&F)D^zWt!umsjp}6v9)cw+ zw#agZv&l^*p<0{3NeN)g%b@pOlH~~8HeXxo+SoO$GEAK&{R;R+jibhJx%tPaHA)Sg zX&I#oFg%uF1WPW@1#ZWmV?RK8lbO1{o-b0(b2~TQhqEc`O=!r$I)1n^q>6+7fdkq) zh;E6NliJPA7JqCL&IC#8wB+$z7w(QrrjnWHi{*{CG3dkO<(PL^Jk-!qLQenYL3MbF zTNjBC77_jCm4u)3kr!s8&2HW@YU6$4D{{W8BvL=Q3sbC>A0hSq!m1Rt+nwo&ckH!T z>*7kr{;u~7HPK7(;hXUkq8>w!!4Z?3JJ_@1SCn$+G@#_fJkYX%SeWRXjcjiuJiU~B zxZ{=P%hsbGng(qP53;$Hq+>KUew)~nP~6J+=>(DL1Tgs|z@fODo$vUdqU;B0k+&2Q zErtzgb2}pKc)2p8L?e)qR5f*$_`Dwb+O>pPbK>iU)V4zDd;CuxhgudV6A2Y}(3 zJD~RtsO|Xg0wmx!{|_P7|96SlRV8=rb$^sOEQg6d&~*55y%HA!%BmQ@jZ^o|`bEZY zX*XROk(^6|(3$oFL}cizthkn_grugY6q0OJqk@{6Noib8Nf-BT=^&`>QQ00<6bRTO zY3C5L1%K@RTbzWylJLXU9*9mg3xMWx%$M1eJ`cI?ixdIW9a>8Fz;+btR^MBt1!(cj zmM$S5&^;CSu+#Fn!zpv8v(F6cNDDY)gwMTlhw%asbhLgpiN_>2B{?0cQsZLWiF5DA6ZOt@o4Y=_AAszS+%wfi&mjMwU^x*}N)aRu<3l|i0 zNZisZXG|u)BVK>BN&1kD2^&XBfDCwP+p6&_Z2T`uX2u_DTl+BxM z{1>Y%ufhdN6PhGw2P*-GwKRW{e7sndYUFXyN*#=MTyjj=T0|r(|=*5z%Znvw{Sg&u38_^_- zYJpR`YSt-(S0ZqUQcf+maVR-3NA9pDVQ$6izS?iIe>$G%hN{G(UhXk}Utr2yy;z$2 zKd4ki>NF1Lo{EXstu}7PvQg^I_eJqSq1yntdrTot%-_eK%IuLy4tN1|1XA9-5&E04^m6>=sgF14yjC9Ug5X+&Dd7UuVCA=yIyIt z02VnD)NwN@*T;!9aEsn)VCn^zwInKl9|VSywaLIuResSmMJgBdSTsqR3Tv|KDzSTmX#_y9fyXXQkC`MD}8nJ;w=?IT=RX8>Su-W;JA~;@U6H7c<-4Fhv zuZX)X2bx+Il=H;$H@d24k7)L^yf8gtzDLH=$OQOKpP;P|k3VA>fSd0(#W=_4e% zwVf}a+ybE%yZ1`L+T3aA`@>~y-peIAKcoPuSu`1#i{5j5C}>M(vkJFUD=GUD53MXI zOru;Rsy2@;ZuETE)xdX<_27DfxLJ)ut$2^b_}0Xh*N4(6kCwo&%3jGO`S=){9(p#C zPlOE@B^60;_*|$3Fh^^ntS-`yi!gr4K{AS!iZK30nYmQ7{3KoCBnYbS(>Q943ZkEd zBdW-`hbLt}Uj;!o7k95E+e2SQM-QK$Uz(Y*<`?i()@Mx?Yb-8fjmMnruQMjv(YV^w zShlgS1b-|PTWqu%3kaWIxx;*-gxqE2RKRIC_3EAn4=G@YX@a&E ziOKbOMxr^*uN}US5D_)y<~^ZsqsYK$;H6n}v7z7WKGK8EkO0mw>{uI%Ek5W_;p$F9OL*3FsyXb-J0cIvqD7^Bl3X_zOu;oeCpw>ME z9|{$re5kAA;G7&$lBfewGi$zNXJskf8w)q}>|y?9&it*11fxtk_G>yqzE!z6TlRze z?p5XlVsRv&tK^6Qt;plhH0VP#@ZzPVUY?YG+6`X%=1&_f6~M z46FMdZ)p(QF}+Fr8ykFLIWX|FK^o3nIOHk5U)o4DnApVQf&Pr-%Bfvk&Gw@9tUGeh z)p{omC*Sw;%g3?n-J8ZyunPak1Lki@VMO>_n{rb^9!j97 zJc?I&V?y(%DeCNbWeMDGETj_{Mv7|(&@)`kew~-2E1Mkrn~#>Z zj?Jn#GI^4g*Kwp3esOiqnjx5uX$*C7y*%oUH@SCjkza!M+=5!8BsnZ>5CfeX=PU8f zejuNS;q7u923atQgg7$tBZ`H&hIoyX`BiGHK1}r0s%cz_Yy4-Ke`B9d&jd^~LQ!Mt zug{O#Zf;PbEN@zyG)KProJc-;R89B+54720m?LOs`?PrItB_vj>S@J6XtdA}PaQuT zu5xQTuRqB}kxoguA-*`U9yr?qOUnJm!71qN)kpW?Nz%^B2#djz5l9_+#KJtkq5i1%i_^iXD~K3NOD&@o&Yr1IQ8yE#}l3aEQRk+J4(dNeIW zJKu1=ejH*TvK@EA)l2m~$hOzNdD;1t6At(^f{1;fr%N-=z)K4ef=hSur^B{`8*Jx7Q}! zD4TP&r{wj8wd!kB2E^4lpG#y;e8;7bN@Nk-a_$kD5QSNMy=e4a+;*4U)hIC4{J>XJ z{L$?9gbY3YU{asYQ+eAyIzo3Or~TykSPla5MuA5<>!5|o>K$XCBx?5ZcrCw_8Q|fe zOk^;8epp|_S(Anu11uRgMD}iRemz3J@jNMJ zPKVDAt+uT%4D?+Ia;Q$ay{3cL3WwEzOl~*GSZK#Zj#;NSufxX8o8ZuLpTiZ1 z^3=Bui}$UfFz;?fpTl#Nh6W%T;oi*^v(To%-I@HcF>q%EKNwoN1|3&^8V4AC{ZJI7 zLT2eH-I|r@BdDR0ec5;P$;+)P)UbfSj?_*aJCRPpeBErNW_O}bA&q|AF?ZprBb;FK z?Dps&X|?MM#+t}1#tG>m&Ml5q6IA^yXJk@lx#`f=%r!4Y;^>q2?#<-hOpPs1G|&0L zIXkV{F?BGOK%qQM!hykWiv8eVX3ThV>2l_V30oP~Xy#5fwNi6NNWGexVv|PPcd5P~yizi*U(wm^ zuAR!1XcDNZ4$u;ymqC?19UTSiw>w@+WnA=Noc{AaWB0yT2Skv^^}ckIpljrd*~8R{a%11mYpfZxvwFO5cN$99}1IAPM_fH#Waz9Zu!|~ zjQ$kZTpmt)n-IN)SjI>Kt1S6NKG*H*3Yi^FxRY2#)xA7&^Zgmz4reHYx50X+qLH2$ zet9l@d%+_2)nji*2D$Rk!D0>GW7k}?dnCbXWVE!6A4-0w`{USR zb;)*fu@JE=HOn6Z8?U8U>gy}^jYR_Cobd5D6Ta|v^R#IX$w>T#g{EW!zPN+IJ$Ub! z%!M+E|I=a>G_gMShq6>oIMOxwsWF^2nHKKX&9;XM%P;lzJ?0Za4|i9#f3Cl;pA$N_$i`1kfD}yQ(IHCR5_sXlDN$k`Wev!)%rze=^(WHZs91_Ogj3&u>M>7SCsI+G`wl z9Ibv!qx@up~>80ve^_-5KYJ5w426A$q#;5bRGm$o}TUkkU7CU?{jKM_74HV3A zUbeNSS>QA2UF_mcdsy$l+~~TVakQRJ(DJ2{^tavV&c}}rERQlxQBjDAKcu@Z9;ERL zj>b2w6AUco`?kGPpPBBBd^W`gabB*L46&?zO`!^jrhQ)P;y#|-L{Ojxv}VmE?{rV) z=DWajOMDuW%}~vT#>T0sp^%3RcrZ&>0s?>CB#0vMCU%gCTFQt9Vy~pUTQVDOb5ZEz zTAkSzIr7N#C@2V8eauH3vNkcI=czf*-}-q^35()sfvtzNF8yIzqnWIYXMV%54afb_5TY=g>cK+3 z;4i;F*uI7qBHz`=H3ma?iFrO-Auo`V_|kK`OSv5bJ8AfB9QodM%M9lC4h8!OI}H=! zVa^<<*;Z%jcJIaG8F;u9-KJHo83wu9`iCz_9DJ#$%(UEUO(=re z_^?QPMHzehhy+qo_yB`jVoYRauZ48}gRSw)A_-IG6U>yno+qP)1zUxWyW_ffj<@nhY|gF(t*;kiV?{mpm{cKq=9ZSY ziWBAOdAdw{TdOCn_{>uwfbyw~2oG8-N06_1`M02;hAtQPNcFE@`vPvtwos+uZ+(Hh ztkW`T7(Y6$hoL2^CD+^2oIZ4v_8+V2ao(-w#z@wu4+F1Y?zUvZrH-&-!jNe3wk0Nn zatW;}qdtRgchySp)Xr{p(|(gZG}P7DLa1*@LG8rxNl@E+VUqNdu{kTj0~^!p%oFs5 z|3%qbM^)Lb+ryY3D4a?fpmBG@8aF( z?6dbi=a26jgW+JH3)i}z=eh3dnseTB-X3`;B^pfcpD3Z3NZW9_sM&tFv7Dcg$8Su; zO822}WkDmu+c;st(Z+0H$U>)L;>$!vO=7GS`G&d1Fk_9W;+WAT&%=7`sNB!k4=x;? zPGi=o??s-|jc*k$Eu?O4Bst+Gb(_AWkP*H#-Que)dxBzmr%Z+3*qAZs{+-98B}9_- z^1?CXA$t#cZrnwl9Ho$O`a|R&(-m-fb7I8 zYa9)W={6Rj`{FlHGCd4VYUQt`6DeYZo{r?60p+8INpL_+yFLtMrsEe>!E{T{rS8zQ@01 zQNJIk;T>Y^N%_j zy+lbdk6)QyW;9Cy)qNm4(Idv>i~5MV(di`TXff0=ZQWQ-^F7=s3Dafr>tbleai2a= zKIGLeBKu4+v=%^B8KJO8bsZ&J@XyaEKOr$w!W~*J=v>IMvRbbz7@tx-rJ`&2RlRAr7@HbYzr<= z3j?qh^Am}^&&$LuR=V)Rmd@JF0VFiLL#Wt0OaOCyp0cKFoK5>@anH38*}TE*(y@8N z@I1O`(g%Z;vnXlV0{2OFUuS(&D`8|4juAnNqQ*7b_pa4rs*d9Y)y7!k!fJm0@`L>< zpSA||)AXF2*J+y8oCvDn+gvsarMCHy8h8@hs{G?ITZ6Z4zDCWqtU>)t3D2A6oE=Z^ zS@19a38QOs3pMJUbHr7^t-0~`eD6M$Zee^O&$qc)FOh>gh@>nG1r0}H{_kA_<=Ib~ zPKWz1M-?MfrQ3Nzzc~MVlWx7Sf49*|X}=f*p#Zih#P4Tl_ZCpcd(4a5A6`fKDmb9F zB2~?!nR`&0ccxCmsIG*;u@R4J=(DU%ho^RZ}x&^X0*A!KRz8w zIr?d#1c=c`WQ3&qZ#I-WyNSEtQ40v6#4_o`h37-1kHCyGwkU27cn9 zK&BpoBaX-SV6){o8bL_>reUx{^Sj!>p#Adtgz9>H82Ug1veh2HFx`)47^#e}nF47jD?l?z z5679_Y8p;RYxR_xz%}?9|L|?3-R0_BdjEFlZ8>$y@5Su6&UIhO$GeQzUpM^P`tv4< zk-J7iB7!{7u2mG1y`!7EDz`d`<5>TMyQN>#spGGE=Hss0B5dWSJEjLqLME$?yZn}` zb5GyC`|^pzwK5IC8Xla{UGrsd#CO*+aE5UL1U&ry^W_Jnqf8yA-510pW$#QEo8)oo zA0F!GrUo)j`K4hzVM1Hh3h|`S(k)FsluFlr6S3jRKwQq>q>w^)J0+3#wCuJQW4^vL zXXLb5%SDm@c;cJw5i*mEnddCyT>abBDL0=qf1z-&bQ|)P;EcOU7L&kyr*Zniv+10N zA#mGPnxiaAf;WL_UcpZx?Yu0SJG!Ybm6O6-cIq#d+|YID3ZL0vsC{^z{ex+tEG^cK zZSDcrzKZ;fdFS5ORgr1u%Y=Bkp!Zm&SxWrB32PY*w(28vPUQ`gx>x>my7K=D#g_Zp zgNaOfK&~+ME=E$L@;ZC}s2{bwJUg9;I%6Vj5^fX)Niie2eD?C6&JrCacHTC8+OpPX z`?09UHy)4JVBC=N%g^{d$r-vmnzlwO#>}XGpscA8b?|Pnt+><)79f3r_E%6>7S0 z917<%__XML_U@he@FY!6$bN5O)HbGl6G$3X!K#H2S7&&i(LedrM<)EXyzrfAK8m|? zN!idU^5rI5vXh`>&i*ZF&&5pWF0Q^8ru2O*rn{~$Wmk3VAK3ll1Xsl$dpX6J&j)1Y zobz{7J~=s&)!0uTOWckjSnFxmhCsH57z4~@mT&&d(ly~L7o)Obf4W<&$3hStp61EV zuvKhOg`v`NIj*S8M=N=@lcy9E|I*`N4Ix%cIT`?8$k1;mnDGYg699ek643KKWL#hE zZit{-pYP_!XB?DkCS-mRWt=VRLe$%^Yid&ZI{m^ihQ{E*VVJH>v`bR_a5ubh+{<>zcKU_ z>sIdgu@xu0V`s^E0bvNi414Gy#W?Wg^Z9mgyj68Iy1^Ju5tnf4#h=ou3YS6KKOLs4 zI7(mCgrlG1WbVv8<`a$nYDb~PT%MIdm^3&T&3~vHmF0IJ@^KG0U5r(P(0+c^FfyBN z$1_DHMh>#$nhcnh2=L%WF4yaS*r%SEctbSl^#a)MUswr(EJhLzLT$BO4l>1n3%f4! zYEJ{7*|>q(D%MreWy6~qvK>IZ$9G&;OrwweVCnaxv7Q6DY1TzIOrh*=uf;X_WD994 z>Z0!jwi5L9I3Q7^wO!f6lQA}AaC&71kaoyVva{anM3oZP{F$<<8np|Y@dz^&6E?Y@nI7`U9e&bnYP`J1dQi9%q&q-*r!p?Z^*L2Av_p@7??#`6Dl zwRrBzq>C;$)lG636C6gZYPY%SKF7z4qk#*)ite|x?)VHz*XV!d4Cov~Xo#E)X7C$dlQBiTOE+cEzMA_%_nc`z zt7J=F|9By?z8%;6F>rLje~xcg-%I>#>%chNS>vVHX}r#wQueSep1vRI@J8@}rljVZ z&*l4b=e)lmdNHU|e#434@%X^Sg2iZp-ElWB@=0Zfo9}^5*xGN5k7@|_cWkGPGA;Hu zU>izYpu(H_P0g+$ou6J`8@6jGUvn!VUh|l)NRBWuE#8xwc7IC8k5Z3Z+wtA`zC&*f znskep``Sp;<7Yk-?Vr2NXD9f-JB(aJ$Pwnf7QeSYI-hHj7tfBlr~l%OQ~FFvyQ&SF zL3>fDUnAr5UGB;w$Z<)FO=`4B(x(kvmx|mcLdjL8zw`DHn?V4>^)gpS=Z!6Z>7+z| zee!Dt95j}JlQXiukx~1*@%mWjUU^d+1WJ&bjTakm5VbrV$_9&F2>PI@$$0Z= z<|mw1|=R$Zc8M1Sg#9PDxkb~|!0hqM<09SSL&%t6!f+U=Wo!oQaG5mKmzD`*iK zobuV!4zK9UgS(1cK0oCrqGT%JMv*~P1;TE481h{B7I&R-gx!zlr5Uw;-4`sk)O>e- zlAu+`#m&X#c8J{Muv)R)eawDWrP4a;)prP3Ki;v2SO@eJ0+K6lz$V?!FGZyE^d%B` zM@LQ<$BQA4gBEt?)eT+1D!03!!J}#31{b~Q?070IH8qBY)f7Cyz?MU&L^TkfvBq}s zX_lUbrY41?3*4+Z3fUIp2k5?4>F7CuI=>_v&i;4Oh7j622M3qS^E)`gkbIFgHPO@r z;YhNO2>$JNz9wpIEf091EzHgew+#RMxiMAwZd{@5Q?F8h;+MoklkDXH1fspL43_|T zzZw}#H2x1SjSZyha|()j`_(8g;()+}WFbm$LHQIUY3=Bk@N)YeD(Wd%XWDH{Xr;-4 z18VO812;E!5MhRyaLype-KogP+Km%LTvzAknM?<;8I(Dq7mM_av}->Yl#D{~cAd*U zg&UH~VPfE4goTAQ&yMD5U#hE&wD9pIg6Yi3`Qd(^dWA}{ zK6ul1)63IBsL!8qt7u-QtyKF}Jg~Ot7%0cU?}Dp32p)k@jpl#)mZVE-zs>H+yz@{b z=+W+9b#?1K$>*zYQOx$1lCM@R5Mkc)9Wo!1SBI@w6pa-%G~yxe0D@oE=H`wjU1yhi z`YPX%frHg!k|YA`KT}nFig0ON;<+7lx)WcJB#m9W<{nMoULYPeXF&I>k2-p;Np49>m0uKY zhlPR4-ON9O5=j3BT>9f1C=vF|=x^C9C#I(p59=72!@BcJu4^sapLpHPwt$Y zRY{(FjlI3H*giChwL6q46dA8yzn(mPTk@$)@Y< zE+*a2Q)A?kcTt7`~^N5 z$W`qWA2zfdyy$#)`-&zbzP7){)x6I(ufK2MeQ$qyV6kg1@9eDBU;e||F<{Mg^OjT+ z9|RP6wvK%MtVnJ(KMj#E32@;KHxf|qE^#_;^ojPNs^|nfnQwTZ;HdrB<-CsE6(g;f z<|>6^L~Mp!om$LSxa}_kE33<9LdbM0$txwqI|vL6w9QfKJUg3kTpu$k>yk*=_>pfr zQL#zOe})|&6~%z|GtNp12ctmaTJs;!wQErR?wL%+MjEoy)-*_?hI?WZF4dWwx^1vUeSI~QxE>U607*)#=hAYmlDX5mm&c!8Vjwsgj73?k0J{+$o2_`x%5%8`~zk!SH zTjxGqrl0G7EWsLU2Ty?)X=P0f{Q4G`1Yar~^gMR{Qq2YrP37Sl{2#`w6y(S?SfS-( z0fg(=n;jJhPVE2C+16HUQ@K9-<18ZZT(`(B1N>9n-bhW#au}P=uTw3bvqdI?h{BnB$Y>(JvJLJPYZG#8y!^yYm~HN*ROdIsXxQ^uwTVc zq&!m5b}O38DVPMOSs$%}B(_yrIEk*dhXg0y-JKn&_#1)3>eJDvJv{WbPwevH~QTxEGg+~p$p}vEisPWf`r8|Q>&oCXp`u4jYtX;8=J*K2Q^p1#@6(d zgeZ8)xvdNgm#O7_iOUkaG|jNOW!)MJb0g-IH^{5WCzC)ZoSrRTc4YYuwP}5%WwT~-C3GA|s>a`(M0GxB=jtNS`hgs!(Q{Hd$ArnEAP3QJVjpF24;@eAwZ}^!{OeaW)T| zAD!A>LM66LG8d%;fycJ4U5d#5plJpX_km_LPX9MwD}PK2vw=*9{S|uwY==$Ez#z%O zfjzT=dk%JXcDA<1Yb8zTg1cNv&gsJNFC)a~%Pky-WunZ5cev2JUO4Y8kt24z-`}d( z%ykX-WN@i_`dmMx!cno+5^>OThWExn9sA~P;*F4xcO>oFyO43;ONSep5rn%XFZjnC zeVBP}U=#{6AM7<^{m@`V!3vVgGM}pNgwQeB+EhYvo+ocLt_cT;j1n{#^BPpjWzl`9 z-m93ps4UsD9`5P!hI@yPuMAo@$fDeWQiO=gbzaTeHZ2RMmg`RuU6hP-FlAjPCbqn| zKsKCq&9J(asS!PR5F7TbsG@>|oBi!*@fpex7{69nP2m&9ZT)&!CV5A!V>MT$mzVEi zC0VGU3aSaohUcDBqj{r-Bc z9$JeT1=i9AmltI4?kp|yHLH0@9u$ifkB9NHHrxtB;@$jFyNJ?ul~VuSW+^3PQcAj8 zh9(kBj;V}oe`H7oc6N2;tCi8vL~3d!PEV5rx5U3pZCYnB>H@d5fxgPe;5Qx~o)Q zd9AKabX=OV6EhDVghGl)nNH(blf~+kzH!;uwHrH&&psY=GzpfCiJ6mAEKJG`EZ7?w zEq(}%EiK*iqQ!~yaZU&gy{z5(SpsYE@hQ(Lx+W?Dtgo9MN=SF3-KmQE`0aVcs~tI< ztVNVLaIz)F=ix`=QTip!eoG)zF-N4qgI6hELwSd*Ol>`izJ_>k+NmSPZ_mADaA$rh zj<}97TfqAySL<9)P0aKh*yimt16!UPG?7eR>D{c-!GOhQIw?;-ru|5#>>215n zpgP7$Mpp924jjTY)E8cTv<(G^;i#x6l9EJbgHMsXovU<}1f@ZU)rn~51b@u)g|%GE z(H&|mtO~e+hOijzh&qNYJY=dy$Qgx0T`*r+UiqK3g{9@01`s}M+{NFnEb#HkNwcv^&Sz|_s&lH%Zo-2k8W5)t9n%;f+IC8EiJdRK`=ds zt|yT8!J95qlksxS~YD)D3=s@Lli+Z#+yw_E%uEUN-jiD@6Ted67!QvL5{O zMM%c-WI-#4eC)D4gNwlZHetNKjeJUUkt``xO-e|q9uwk*aD5!q484>9cD}|(+}*BB zg>10qX4H(myfgaahtAqa@{B{W&S7G5|e!u6%}}i%WXik?h~Sr;fsaFeHgNtg8h^ zs%W8e@=L0~MM|$Igm+Pd3!8lU&u4=sR#uGpg&KnBzTcD!7$Ao0<-2ERK^!8J6}VY1 zV|$TEdV2ag4|ftuO3I=)DXrMjJ$q=$>&S9D4D(IS_so9*+WvJ-xZszCx~>ZNhf7FF zonJnAgd8fs>NW1$&<|KI(QU%wu%cj8DRgW8^r}qFB6f0SWo2hRI?$-w1AL(iAZ7Kf zff5325f?hu7nW3#?N=Ald&2aSkEhR153!>Y-DWtv-G8t2)pj&dsS_Hy*x1o4Ra2+HSPt zI-hT6f)%G%7ZeR4P90v=(|y1i%UaZPzy&G1A!6Yo@YawuySBorV-_7>P|C)#M1oA= zH%lQ9+7%4H+(=S-Gka436S|oo1@Sj6d8N;siEavvRBT2MYm>xAMxJ-`N6X7^=AYM@ z4PRsWSkwE(vpA}nepF~zowQZF`&z`ED@C&bql^6%K@?P>Qj^(8@idWeLzlbRhLW4G zgdMvfFS(Q;?&ZsJlB(*cOC29M2oi@^?S`V-xZJt2Z5OXr5mNLfT#`AJmBFjni7D=5 zTwG3;36pVJZ)!|pVPTPA#PZUhyPnF-XS@oi&U*8^8Jq~Rsfjd1Z*T8ANC76|sq}O@ zifOpuB1ik#8t%z|ZWoy3!8MSp8cyOlp_HmaJzBcX$n?tc?(N16q>e8-Od1Wxh891< zCMI}xGj7St_ear}EIS{xN9!$iYpZ7Vv}7!_MG`WzSh>2mz^_5dCEOaPuOuQSend>{ zJe96o5cP)MN^3EctR>`0sM9*W>EBzR^|tQbur?!Z1s3s{;zW;epHi-hRh=N>s@g{} z_@*V^pn7;!Qi!8{1YoWTQ}yZVXTdORE7VjOVPs(Ff~jP8*LJGREGbfu5VzxjuFJx= z=kUNUelPY-3$^Nkq%(2xmE+xL28~K)gSMAU?{Nv^deYi4AiIz&fsc|h<4t4VLHae7 z=-AkUF*9#_t~#v(M$=$h6e^O4kZO?B@;q;CrIzL$REa+yfI*X7!Zt^S3es*pP927d z^gP*(WroF*Q$Kx@fG1cN54V5ChQ0iHMB8tU;S^DPe0(DT>}-WBg%|OU@uPcEM5DL1 z`iK0}zT~AlN!}no>}#ey)U+*J3kXDL6uyQ0WHX2hpKcCP4*@5#w!*p#Hm$KQ{PPVR zI$(^i6z5XNpO;`;J`Im~V%k)A|owxEoKN>|F9`R9Kc|oz1mwJz}|DVR^5Nk1m9m zm(PA>RV`1cW0T_e+YRE(Xm+hT7@5jy)Z^E_o{g#-rYIk4M>@N5xV}=9w#w6Ti>(Dq zH@;i!%AJ?otJ4i+IQF=Lf2J|a^NZcTN9*JM^iTIVuLgJf$?~9#DAEGQn+OOidG+*R z>{3*MJg?7^V(8@kfb970@5LqZ(B&aZO+>fD;v%-JBc7$njn=!z0YuyAaxjW&_fq`L z#cinWb#tR_djqE_f$e_)oNS@}kamgG_Wf_bMl$lvo2$pcRy%=lVPKeVah z_)eDA_xA3>j`V`S%Zq)gI#OQ74+;8H#`3k?vt|*{N2%Q;$mf{gG<8&Ep3tP^aSP!U~OJ( zFf7E!!?dlv{W<_&My3ADbz4Osip#-`orA;i;>hc&W{&SBegPoDmI@wJ-@M* z9C|DR#?w><*W(sFXDG@rWhSqy&?>pP&x+X0Htz#6Nodtk>v5h=ipFNDaCx>H0}rD} z%J%tTL#-QUb4$jMvUX>-T+`~fRRhV3uSQZ*8z1ifMab?J7a8e(u*TobJ52FxW^FNv zv79wB%ky%h(eF4%!NGQ+<8rrKUJ1Put3a{cbz=hS$&)8Gwzg9)tKm7y1xT@X)klz7 zxi-++jYO`8OXCsqUqq)pjNs8IE}VGtrgCLv<(Z|ci_#OG$|OJm{{QwVcOuCbLrN{i ztMx?r)8wiQ+Vg3Zb@OmyNjB!^IpGn5GCyeQ?Ny$dnu_lA!lZ8m1D}D-WG7W^z0}@p zsVNX|wm-}tf!C%A4{*b|Ls?~=)zmZ$dgo`mRuFy-4>N#o_iz6A@xud>?4das&lq0q z+)S9eS7vugqqIlBV)&ugn8$I$E33!t^P2-Vc*XKEq_HUA-_+S(x%XHycKrt3Wj9(0 zlhVo!2^*dfzV9~$pnt)XjAM6jQ1bU#!#m7X$`fz!KoUK9a#H~9-n|+(PBohzaV-_G za&4xoGZRj8`Z(Wr_T6occU14+4~4dUf7FNt!ixY!so9i*e9(TgVM~PqErYK3ik2W( zZgzH^p0C3~Lc=f$#4d0+J1ah6(rpVR8|QLZ!+%iR*QSvEROsaRv|(XoWg?{ok**SX z)oGL%N2Fz!CpU$I4&pc}YBTT}+xswg$e-QM!dZ=GnZDA5DPg0FLbL1DPna z+qYU9$uZ_7vJ_$yg9exFV2Yj*G0kr7?TD|$b zF*4!=C=2wuDyG84i)E(H1**Gx5)v0hf5VTblLyx*IGe@Y--`vKj-!6b$wBDOH27m( zs#!~yjhXbP6G4v))oHdRM5XvS|9bz=sbn zSEr{b@Yw$crqp^yV`Q{wzbYtk2~jyc%XS|>4%=~QTILUl)1qQNc?8ni$vS^8FTq^= z*c^q{-Ah*j)vDrX6~OSRZ|6bOGay?5E|vN^s*4K?Toz+aX>wV;soXKuI#%cbd902Wk`$KZ=AV7(~%+?qRz;=2#*`XCeg!( zz&x9ps(r#SW;KDXH}mS63VU8W>djW%1$dd&Y@x<^SBkcxpr@`x&KR-`sM*;sZJL^! zA#O&^q)7uhY^N*$KnG3B_VqeX^=1iZTT#NFV3lLNXyq+a(|q+x``zuRNC8@B9r96+ zrmMU7PiVL-3Zf4(mdX3yAgd#D2h}hXREyn?xum5-AaoT9wC%=3ni9H2M6_c8A+QAm znlzpgoQ3FZt*w#q{h^78snJV5d>sG41^cI|d%T8}wcm{2%+u@U`8fB&b+S`Z6E* z1>m4JL6SK%`QF}+WoE-|(37ZF$Vu?lIF*Z_ z!_#gx)df#uHw5Scz8vu{s3VjQVGGTjtp`KLTf!oVp37-cGY-)Vj4(P&O|U->5)&7JTzYQY=v>iYyofAt#II?$VR zCw`rnsAV%_52z8t6DPh{&cImgI{!X7$;ZL5xn8l!H)71)+SrNFIgZ=r3!5nBqnW9) zRSammUpo1dqT$lK{I|Xed$$bnn8UKNq@)_!b(8*PGgcF*co5T^m1V+WB-OiY=Z`g| z$t_(hvjdolkpDeGn71?fm%Y5oarQNyV{tIDS}A`HCld|cUm28?xQ_eqVT09_PJf70 z;$7gb&vI3h)T`aY4!ip9Mb={eCxFH65|PZ=qZjH#N~7bSisvt4+h7-b{66)oqb@M!FVU_8{l%vu2$P@1CGU?ErG5y(AnI^jS*-i6HxwHKD+1(bgx3YX>5!0e* zSKe|cRH$fb*XB9jH|^1)l)pW}z4{rCCF~I3`1dLl(lIcJ#;7BA&I6?`cyGQ(^$}Bf zRV4|zcCWHBp<;Z0uQekA1x{D({OIU4Ar{HMLNj@rqu-k38Ed!VN7^72n)v>G)l`pi zv%|fQ4?S_0v3bh>Mv^sG2X~ns2f=*`3xyx8Q&v)vqm&mQZV(-9MAg@GvXoNM#3py| zc4G*?rMoraDSnMViVP-X=!xG4ea9>3@GnONN0}zuauhs528cUeJun>AyVn$GCpG-c`nx$&X7W>Vaq)X;3H`-bh1Fps?J)1x zIN3Gg>*PPKTcgNa;Kf|Idr~2y%Co60CGJ+(i$s2mj$SO(xuHN4sg!dMeGDi<)2zbh z5OL-@{WFb1GEpHXq1^Ibozr#zDVoK2`Nl}Ebe4kUXz^-WDpcFX1AoK>? z2T+oX45NWeSxs!8!5j{#+F^`OT7MY2Vs+ByYK%fG-ZjAOAXnyK*Ht8EkU{&RvGQGG zG=nA?nwPhC<4BQElf~E1fb$wG9(}oiawuW^P2E8Xccj+58-0$0`ycSd`nTr7lf%s- z_>4e*{m(wEN<()CYIJ4gufjqyV&aVyky{_O)8RJjjH~GAEfQQE>I5Dq=);FkA3m@q zRj2)LK2SZo@c-ZrZwf5^@9rU4riPq{ji+)cveJUwFHM1F-=%Ij$sdy_GM?Vp#8|br zPzQt`a=$EgpFT$ugrH!vp)&&5&t~PhNxyCu8%!bUt)HXDt@E-LZ2em!!VP1mLjIcl zuAvPyI*`L@Hp@9vBnW|sbkwU%FoJ+VEq)!1*4_5OL2?QTEo>hc@;Nw^X?@8P`K0d)xa~|WoQ<<%av@(hd(1}j zYJ#2MZh1wZC~;l2)!lYuRzT<|gR^Cl1zV%_?f;V|G(kf;kGzm~3;NaEoHJ;OV2po& z$&M&^{onih?i?7fc~mz^^Aka8b1OVxv_EdWI(`iwqV3(?z$?{fTGk)dNAf*S>DFKl zUR279JwC4594qVYEBcSk?lmp0IP9$SI0J=6n!l5Ny!{)|)miQ<14J*$%={85z^fQ%Nun!A<40F!u`nYOK@cHOh0i@SF^i{qG1E%ml4isn)4-PhoCp?y{ z4w1GHz@9)NVQ(b+C&R{!0ESJ?6yHErf9|*|Aql@?bs#G;^xb${*Md;{gFGcdA|gsm zLbxmNs;jELXpznI`7bcWf5T+oC027Gk43eZoq6E0xAcJ6V=U?+OiJ^&Sqf49Je8%1 zgqGy^{E%M)YvJn~3O`Cbmw>`d&O)dMMC|78L69Vsfq_1zn+0gv-=lqN=|4t$1a7(U z_5cPW59P*jJ7a_B>(}BNhOCdFQ84U^|JJ{ZNpjJt0HGh-S@PP$re(S-Bm&r=p?PW2 zrvhLAV5IVD&&2-0AYphFn)EyTJ5dFcq)wLR@7MnT21>(jto{zwgKU~QmThrZTxvcJ zQK4_?uYO? zGXo;|9rnyX`$6ynRZaURdvxBjkjiGRa@a3zM1^y_+cD*FIvau0*=T|v#&>SF;5cRR zA*l1xwN$6krO_WNo^2I_ut4!Yk^S^Ct1k$oC`nyHVq$1~e6c0cP=5Mv4r`8`@a6 z*pX{qt*(8u6JUo1FsHo*R0Ms6m zFFJqo9c=_lagcgze@S<_$#DK)w&E&@y{Js{+J1qK){*${LD61(lvkrzZ!Jc)ER>WE zMoTVv4mILFd?-ostXILlX|VAgu}{IIFJ&w3&IJP zIspmi(_!rlNE0en(FuAy*rXREGJCq|>3nSSDMUK2pgvYHEnv7}%7g#ytM2&tiTh;N zVN6xZKXaM;4aomXPEH2(gS1M`CF=w!BagKN#iSZ6!i564(aso_%Wi&Y-jy6GjF^}T zO-)VMd*!kevert9cjOzDa+jX+t?L3}+hgA#!U|x_`zm zu|1>Af{^kp&)48I-iH3@Rw1yf!30e6ze6pcLB_bFN{!d`g~@q)W^j5sR54p2mdAMy zmBfu6&8uKDygj-*;KK*=(VeVrzBo?9j=iS92KAzuRc};JWX++Bjm-t+D*^0DcgLAe zkCL=%98z5NX>1p2c`YZ#f${UcT}S-5x(kW4@A+Eu&~#^K=i;2Bb-ZS*;Zn~OvBDtfbB$I#~*il?u2(8te>{kyZe7j znS}~oZSN}Ekt>@Mbr{RW-~8*>>Cpft+ER`A=pkrro^V*IKrP?eVo9eQ146Xi!~KIu z_`>uwpRr65F0DtUGmG;NuXz^3o7sb={Uk$N2@GtCv&+k&Vc)j*E$m%_wS(uZrF6LvQNe89lKM7Q<^SfZe~*G*{FDmCj!FA3os#9p3HNd9C51yoVDkU0o~Cp!)j}tCg*YZvW*y+v4bP zx{d{6v2Y&i@9#Gt{%*G6QnSeIxQ^OKR@Q&gb@M7p`HOg>d-;B~JqGOa{vzQHXGdLa zk-SazZ~FU~pFQi!*EpWl_Dr~c$a-G-^<V)6)9m1#RxDxo;Ng7E%3&`?QY`#hxld3mz>2_!j;^-heetmeb{XWAA) zgd7@`TMxIfy{9LQVDP%aJJ8wd^jhkPdASNSsxH!^6EBxiYMg^%65~Jk{ukM7^S!J4 zQl{rJf`36OA>awK{(HHsql;5XU6l4KLDZ}0s3^-ej5vTn(k+96f|PRxy+}2xL3&0s zT&RPDNLzpZq~q0sGcgOmc0(THk`l|kI4w)j^97s(*Zi=XpG>XH)MM*Us9~oY$PTDs z3bpiD(|faHikPHUR>t3!YWiE;B|gcGh#qTg6?3C`!OqSHv}`6>OZ>lbMCV1Kgx%x- ztlWKIas`$MPDsL-d6QhdDAd`Aj?MkVPGPaD8{Q5zP7`24O&FTEW1~?olu8VPyuI)& z#}DKSv{Kk&_Y6B9LsDd1o;n8++e+tYeh>58S0O+Ju~@$i!KG#Y!dPI^x;Bb2R4@f` zoAB`0pO_YW{p#DF;knZ<&5wVUwI#!IZdX!fw&?4#wmfKNCmxXgZuTU}<3y?@c>Ok3 zBD`y58p*kN69n=58#2MIRPPlZ01(;WvOflt9*@Ua!9BvLfNQzq6;}B1GzK=SO2w6L zs#=pg6CZQhd_5}tYBFyKLwShie=5LGt!)g#lychJ+WJiGg*7cY{};cL8WtW-%c)4i z%PXHzgCC1S;tS2$d4fUJr_s@4tQJ+SiL;TG&vSzecMy)*BV;XaUyO{7#!%=SpRfl6 zoQN_js*2&n&l#L}%M};SQL3z6`1qdB%*;TjAqzkMp=Qki?-C!NZGwQeL~D1U-Q#67 z>JluP3*nc7dvCTUIf#g>l+$L;Cz4jFKq~=O+J56nq35L^G(zz_k7QHZ%~&5>A;pgu z;x-c!21z_#?tlL)<<_N|6WZEZgzaK|gT=UXx-Gx^$yrW8{e8T0ou58B82C|AT$mu> z${v)LmBqKUu|cE>qRfAi`&=l;xp@C#= zeLYXvSkDLt{of%iysYjkP$Gc!yzL<6F-QIsJhNJ0}()brwa1QbF(Gh^lJ8Bpzj{dwEo1!5wo<@IL6!Khf40I_c!PIc#KPZ_O`IYYS& zelpsZ(&G6GndtOw2+C#3H_Y>k)AC_0j2E3344D?=QGoO^sz)WQexEy7&)r|GI6ZX) z+QU&f|Ex{nq6vS~<3RNSwIW-Q7LGAwgof&X6n8NtBwZ=<59z{7%zNkc@N|t=6r3E4 zOG}PJs63sktD^Om95hx+F662ia#?rpJ~=<#9PdivciZ~YEa2^ecZz=FGfP$X_miD= z@^p!n5<{fB&(^;|Your(s8_Gt(i0UGg&o<&EVyzUUz_fDCFhV*>PhnOs!?a#W#r0Q zu2zYmK#fD5m$z~}9})S&M||i$9d{QZJs=Qf6qie5M$kI z3!mllg7Ue9v1&HEk-}>L#KT5HWgIy7cSA)E4b|Z4K0c$Cn0U2fYN#y;?X>EuC6o9B zG|2h}NC-!r7|O$W1X`7TebR*9KY!4)iB1`I1xG+UVvuaHrDbLuW0Q~mgFO{qVL?F& ziJTEGkZ4hJ{#*!>j5;k6!Z?}Cvy=TZMcrIz?c7ft9xgJhPr8GY42%E5Nk>hsw_f<+ z$D9p?EIF~W#kJ9X!|p`GljViZu$3-Vc%V3^*OD)W)iNK+Ebnk%<1^V>K zn!_!}Dfjj1>Ga-IQ2Iw}xp+)eIubougZ+S*@9fmJdw+K)`=#SXZpEa_c}aH^$Y5^Y zbA$HmCuI_yxODeK$)f8!ZlFE0)PSFC)l$ta(Q7G(HC>sy+&?uos0#agLn}=gn^Jx>nm{x@PrCOyMxLsDpNx`XL`q7EN!a$L00EP(OjE$| z?kOIF#`YUmN=BO+N2jCfaXAZ@?v6W1GB;5aeX7E$fNLQw0TPq<;V*#ujeP#zfcK%& z=A>r*#mPB^q*m$PQDWNj4JZjGC##2JrLEd66R;q2t;pTQ0(A5-Q^bQqL0ou{uyO5; z_m(OEC^6wRs(q=td^lBMzs|MS7I~(hu)E;?IXard*3iQz#}YY)ifL{#FIMW{VBBDmDNfgeGr{FP(N9}RtR{0T-8hNdLs{Wdu*S&hecCtNeUak^9z;FE)t88p}ZPYtG3~EHc zHM%;jO;Gs!>6&37Pfw-tWi{UNIhy#kZloW(lGeY>!m{a+&6?(wr&T8|__HDXc>}yf zD3TqtRd&?ry26K0u_(#UyPxMa2dz?)BY{^MDK?PqPE6pi7#plR4OFkVc%IL$Rp%0k zhz`b^XfPdYn-TeOtaPg)@32iS!Sn2$>Csl!4b%eyUYF0}1{Fr#(*+G$N@`j2*M9p? z*uE9hJyERsfsV#uG$&LL0x$%FU=bhA0HdztX^CWq@z~V15hohs8Q~3Hi)sA zDRCIA=gRy@Htbwks7c^)reWGX@wp>}ftNifCFFmAET{Lhh*=*$EHgh=0IZL(egq<< z&%)ptfP?MnC3u%CzLUkp8~No5#^WvpxdYBS`oH3=Ja#5*&qadcC#!aC$wV=!@(?#) z@wMsyBWTRrXmLhKZ{U+!L3jS~80tZyV!*rQJ(osQl8*J^f^n!1z;)&-ar0ifjW-1@ znomA)0nQyE3UuiMA|mY7@9r{q)oo%-xW_N}zk4#hwW-sYP zp1#ILB%BXg8DKg+EQp36bJqg8K~DWQNjFg0dA48Eb8{OgDFydBSp__LzvJ@{CLzLB z@ieHW%F$g*?we4Wsp4sUROLyDuENf0foJW>N-E4T7klz>hrk7^blFe8N4Sx{s+*{I z4x2X6D5HhRTQsbIU%Ac(-B0qokbLuda$sPuNKZR~)g;y1+uhuJ2Kw1wk0fr<0#ox? z@?^?W6l4(1F)WMpY?Nq%;S`5>YvsZY4qbnKg!7;8ttWX-#z#gHJ*i!d)|S%Of75Zv z<;?ue^YR^N!O-t%uCC=?98RV3x?(~YF&{U#=!8yt6fdo^2d6=s`F0ZQf{p&t32d}m ze*`=u#UZxas5uC{y14#Cxfo=1{rLlqKWc>RblZD&(qg@9lkQvoB!U5UL?{t=446N1 zU-6S-ZIdlA|CICUydWU9*CsuDz7eu$?99`B^3FpP%{+f)^tJ9S-q77}dQ0t>)yWGb$QFR1B<_0-KxfEhu@c-B5Qu{|70!_CjQBfnt&j1#&-~K%MgJEy%l35b*+bOq zN|0n60~#;PrD2&OZ1V=cFI|#0Qrv!Rgk**vw6#QBd#gc&m*KCf6}raUG?D*?M;t7W z+NLi>s;>segi;b;MdJ!X)&NL*sW>FR4}~c z;j!+-O z;h^wSSNEo7*)0b-uy~prO(acZUFA>NE4{|CVOgb+{#;c6E)s({?6dVC0LXH_VJ$BI zA2q72g3{dq-l&H#8*}_OxFm$_^EZpLg8|2Rtha(wQ{(8>+2M?ednaf%jg}L*Jp+P+ zOIU?|)$)fW{F_2nIsaGGn%~z{HFr11H~yX~a|TTvn+4)&z+4{nrJ3Cnu(mEF;dU5- z?>j^haPmmV9}_@OWW!})(i95_xt>gxV=aIGJ`4cN%xuAxAfAE(${lZ*(Ab#@LTF6G z!68^M+1lFrcYAw|e1?*Qga=PGOzh_;_Kw!p*f*cDvaapS8zUB<9Y1E`*Pz>+JWm5X zFBML}X1#hrZ>rdV=*~@Nw$@JCr^<&X!-aeD{^Emm7yX-4B=~otSeUlYNKt;{U2$}y zfm$EOhxAlHKEP%+^b2^~XEPn17rV7b1Yfm0tyI6kl#M^p00>HJ>oLhNxft+AN0^az?V*vcVY2Qbtg$$yX=;FEGKIX zpeazRu#`eUP=MlfT>Nf(XXl_@4HglX%R&cd>pR#&<>c8C6N#y*A8SvEz()`Zj*8<5 z$EQ=_(-ZlsmdEh2)SRRb&Uk5iR5=~2IU06fxSZ_W@gjYLX|k(Ff6qirR`!zBq;G2= ztE4mT)XzWZ{!M{AhcVE*0b*EJcYd@@7De~5+>Rlv;Qnr7)A#KvTl|ByJGvEa6b$4cpK7B&5Ghebit{%NwS-(sQgEaE ztxsikF+kjf!TI-7q1#lE0hZF|=o?8T1+PpTU%_p@f=*68 zy*a1Nh0jTzM$|U^Z`}uxwOy|D-cpe+mPwsfQdn5_@TxsmLfTV$=iK$H-_ySsDWB0b zls#Vu0K8)&`oOK5d$<`gF)mcj3}Mf)y5WpkHy1m*R-TeNm(tZe7nv-kGUzW+X8Z1t z*v7H5-Y1d-L2OpHb2x29vg?=GoFa3w&y z!-cGCy>5VJcKaF?E?jw9T13uZ44>)aySL%!LH}zSxIy4zk9<*slU1#}7*YewdH9xE zU&6!H!y-i3!`3AJUGTa(sk=^P`+Rfr-=!tsk`)Cf%*J*yy!2@op8J;uwWx)KhJqR% znoeOiE$R5QD@NddWG0D$X^j?7oxN&f+hp$2>Kw0~65CJ3_V=?y)3tiOu7GX`U?ufB z7d_e2s4q_R0MNg2+(thJk?H;Jf&RZP?mK8629fB3_^a3@g47B6q)?% zDmQNLjTDoYI<;J!+5QI9pC%GWtShng>}&yFsTBJ^X&ozntA_J;pp@^sQbV1cyDr&P zfBq~ZPafv`Peo=s{dMXb2y*;PJgzqsd{M5~h0lHtf_V;};lq1|eM^uXr zZp=>X`s)E+adUcdgwJ+i0>NkxNB#;)(d<`;fWs(DBaPr})nj312Hk#BGX($_%z4;G zDgO}2xE-uHgRb*nef$HP8S63}k^y~@WC(TuH!TjjtE+3Cl3AUU`bi4tfDhaaP7msU zMTDKd^4b0)1Fv3V3GwRDEP2=MV}VsyJR0i#rxqWBgw(Ko5YgXGfz$T9>`uSYl(I5h zp#H)nA!t)K%pZ<+{y+BqGA_!sd*jB(KoL|>L`)C~X+#mE1qGy$Zj_J)>1Gr~q(o^! zKtwu*?vN5`X_4-(p_u`mHQ@g3y}j@M=l{HU-rc;}Yy)Smxvuj(*RhV{yTY2e85tYa zNya)??@CCPOpF8wXrtt4TAn}WH#cW_@zp&%SjhPK^JuTL$$&TP54R^eNg2C*w$QLxQ$q%+R%D_-qy&rwl3_QoBQ;YZ zelsbZ(mZx^#ZUmi=^MHTiYP5x5R&Yl21IdNUe~ai0BC4$;-i;f90%9LWlr-9!&ZCY zLJLHF9-8DUdSg*_4$%cS0!aOClb6?S7&L`*gZN)rH8XZ2y5zPa8UtnpP@K1T7E9Q4 zzZrzQogXa6JU=u_z_-h+3eN+NK{KzQo2jbR!`F;7!4}MF>{1UOrYg5gqQ@`9%$*Fd zYR7&0I={Wrvs@WR1;007q95E4eS2lLGbJJnb%T#jw>^G7FQ3J6?vGrbw+%PEyQ{aV z%T2n;R-H=eWpiCIT3|%FhL2Zl|91z~?YbZ_T=0dt)bqEW9C(0oG6nt!?s<0@1f?$# zkr46;8|t1;%{FN9^thTS2awg__5^c4PsGOkw|3|T6YjRzdY3l_i!hkHZvqP8 z504LcLE8!+mWebHksYO^pH>1>5ZKb67#M8y+s`szHF1MydQ9@8v_4Ht@m8~NTjHag zpdhTvUcPx8lWNvPT0ZpkrANk?9zivI|2~oTi&jX&rE6XW1qpSWXjjdULEfJnSIL3R z&)K113pA^RVr)fMigM@<#=rU-EwsJtrqM1BzemX@d;}=dum< z92W{X&YUrTpDOT?;!26o$;T($;nArd+`9wkb|`sL#7R-GSh;-pe)#Mc zj)MiKu&~ggbgiy4rJG5yK&Pgg)0~>qTthoXwq*HRBZ#$XGawbSK%P@gS~~q2J|q~R zB}r%}(zoy{w|%PhP`qxwS?}d5CGuIa#IF|1BETgn2W?M6*3F3Yd1!uSJ{zuwim%9K z`X>mP;MHN|eK^604hy*=E{W~V8GARDB^Y3GOe`Ha2Hh*WIoa6O3#7Ic-5Yg|Dty5~W zco7#Rzz){FmA$;XiZQPi@oBU@h#g*mj$=x(M5F3K{LV{s?d{_MKmADpBp-6{g3|lX z%JEmA5i}jaF@J9Fb-6tMIG7peHyh`I=yjz6U&c#b%r7PK<4Z4j+j` z^W&Q?7_;3=hhMyiC1VZ2S0MFXeAAvqu#jOp8-?7Hx-}@D6%6gDjwJaN2-8BttQ>x0 zZtjYNvv{7lG$aeVpZv<{KF_4GwkPVRTH=r!OiMs|J~iVpA0jp4#{=ah&aqdtMaMT% zey;CFE=|6_bKBiT6&7)COf3go_*&o4An|ZBUpg`zlm^z)RV*$@S~v-2TCi9s++3h? z+UWPX{nW*2{+HiOXA0cud3RCu4JjjU&d7sw3?Y*8ckhBdwtr;C4#Iu2sJAS6fqiQ2 z#}C_uh4gr1SRc1Ll_jA0r=DlZZPFEVg5;@6@(=h##~Td#dscq;S#2aDHA*&%Ng2!d z9hSOForzS%j}#*JSfOJoH>FZ11k2T1S9xC-QYP$DRiX7{v(riw*X}MKt)zpp!`DXT zvG*EQ53PEx)!lhX-7P=>tx?>foe@HoZ+cpWqsHT+ zRFS^d7HRguO~c64CayJp0%tg=PJ1qT2NH`UD4g#WPyD6JSpH znFekofjyVvy_V2WdGzkj^v6+wo`E%o?`>U+MRdJ5A_^;Xk^N%Kr%%N4!(D04a2FKm z)y;se7tOU|&FCC%0zR5bkLWkO$Ex}V1O8}1I>x|bJ~Twi5Zu2u%Q@(}AuoTbxw(0^ ztKZ}^Y|L-oV2$L#0}n-{YSL0y+SuOUN-7+7gQcVHp4o+xAB$B(F4s86#5{pG8Zr5E zI9m)2X;My&rJLkGTa|1lAPrfLn)OenTeki2eB$5{WLnoSCsi;=SbYvt; zl%T$S^$II6+SX2UUiTJjj%zMG7|4G9EUrDjCM}lksgFtIaYQdBM4Kbq$6XckPL^he|*-v8bjT33=%e5>n`; zgQ@m3A&=AKV&X|i>$i-M(mQ@+PV1`+wV&OZ?8P;QauWQgi_J!DGl2S$rxF9s40o?3 z1n+5ZeX9M@t?RF?!0ie*pS%JmJ7hYaPME4oC=H1)a~2T!_yOLvmB zOP%JswPhfa(f#_Ag#A4CCxroZy&@qGEIVDCP@Ek7IRfZY3|BC=dGqEmT~?^Pj=n3h(s(dN+5GG!$sZDf>&(KvSPHuQgrDFA()2>?KK5?S3$`c6)gp>GFn!eRC$Ex;R4wu_9 z#t9P+!fp)6iBiYgJ@qf3bM;|eQc5bjtqvN2uIoLYgU(5T6}>v?yhyBUn%X$*NqJxw z-wq<_b#!!GpXsa_+{+dA;fLTz_}T|58a;hs@;VDY@2eBv>+8>UpLBwn+T7e_M@|ny zJ0Nt8+%_Tb&_R!7PWZ6(mqqF){aEje&&tk*;*pdr6glU*s1PHlGwP(GB%-OIA>>c4 zSy?5cKG^Q^?7R^dvvojdCN-g(n375Wt1g(n9(@qd3XO=kvDK()WtBXZKm^9Yz34Ad ztiVI)$+GoW2ZMX{okN5ti2ToGPpM@(3pHwT_vO#Ay7KZX%45Rs+0B04WtefFPVX=Ippk1l4l2?=Y(i z_Mr2V3d+9n7)J@e84;6`a-Pqv;EvQnbw`k=A6*K2*UIoJ1Oif7kYE+Sn7)^_3!79D zO)}|B?g7&}E;tI|pj*|*Wu1^~^j8DKDjLk=m*7OpVbbN$o9DT+A(f=fc5&eFhg2@S zpfyGO7gqQ97x4oK&m2b3o>TEys$dq}ypSeDXY}LKzz)WqtQ&KLKwPZVmqGw79Wpy2 z`L1Gg=&$e}gO}JQ@Yb-ZE^1^yHLktJLxk}DnCg6~bnGdFP4yn~59S}SsyfNUYd*IA z_A4(F;@!s=Ys8U!8A`f7)bS>66{6sfd|m~_&348j8Uq0KUXo2-}7 zVzA5%8o+B#kitMl95a|Mdj=MWll#)>eOOGuQo1rZi8QqMl_R#d%h#PocwX;Yi_CS7 zFP+Burag*kQYSBU7_7}uw70c^V;>jPdVNYgjor-o2IUH6|7YR$SFfs_)?8S$-)82> zfC7D?)5<3Grm@0v=>#8NUJHhxm43x0Pr`U==)#eoH#3&<8ZIXOJRFm|Ik55mxJc1JnT(TeV{b3^g@ zN3YvRA- zbJoy@Igo2XBZd^-WOFoZ@zDDGXVO7xQU~&3S|t!9_Z88FP4yZ+{498uz+Vr3e}MQT zdWN!!s{d-o$^{L~yI#rN-duQhdN1Sq{a*oK{50>)OK`<-Kpc)1iV@&o9XmZoa?x>M z-Te5mvXIbFG74law2r|>4-Jwel~&!xFiHqp_7xI#`7^IK$fwyk4SP(Ml%_~UZbL5g zhRkaUo^{VSvbW$s1GB!Lh^|5hp7!94$tHDUOwXZvCrHKnwD`|IKSIuRSmoW-zw@?_ zhv=VYO%C_*AFI=Kwv;?jL?x0GAOO}b02yHxd?C0w>=v-}w6wckH;gwH2X#A>uPr}G z`KO(qNhO2#4{x2y{l$Ub1Or~)zT@C^{exkk`K(R+Uq-liLUOF;T*2*jp^s?6L6w2SND1% zcG^e`gjz`C!^Q!mqMmOO(E*<=ZEc|p2i2Dyd-_22WlVF~8XxJ&9{j+EnVoLGf&aJf zuLRuW0_6s&?8*V5lMpg7a~VDg;pHM*dr3(b_)nB;ml_iBse_q6O?O%FQ%CR?Lh0EO zTJYuWh@c!^;;*uk7o0NB%nc>;w9Q>$)zHByNCKeS%DlaG3 z5?yXHTp3I+|4sG8x9*J1HWB|OH#he}yUd_w!81jzC=Pa;{*{)EofafF zL`OhuJq_+3Fv5Fip#-ePs$&=KP=`$--%EbE{()cQmY;`SGMSZnkgT|P_$KKFM04Ht zc3L1Cg%ocpx-pC~aw;($Q;D5vD*p6p4mW`it2)n&RHqZT8( z3ie&F5BXokSl0(x;x*J6fk7#t`0kqNSNv@+z3_(B>QBiSwd)^k6j-LK&a+sw?p+jS`* z!M!-*yoYXBR8m8!=L3ljm8w-Lc+yh59(Y2~;L_08y$2Z?`kBHYy^j*W_&UpopFUs23d@L@8 z+mH3w@x^zIXx&j;Nd7{G7OGY_5cWZ$4Z0_4++-^Rw%nRxR?I!S1OX+!`fPr!)l1bv zGH28r-IgHi0gO%(`4wm^;Cx*B*n)os8&!;Efd}!MFqWkEPsSNUM=0IqfZk^F@|bOc z)McI<*`k8~$)bp_+W1ErB^Vc~s)W9t4D3j-(bm4chX31;bw<&T)(mtM;hDU` zBgfsyxo&-}pxm2x>o01Gw_1s(ai%Lw*owQi{0bR{17$F_5Q(3jcBfAP`bUZVVnw{v zWl`b&Q;L`UzCjxf9)~NJoW2g0E5qRiPq4spH018fPMcIA$}3z}*h-HE4+dW6br*o! zSoYS`#6f$LlwnNZiE&-LR4-^_(20U=J0QrWp+1Vn#W6h4Wf-o`Xm0oGnYGtbQ$ITt zq~0?eeJ)o)&Gf17SO!=*&XSYU?;5Q^3WCu6*^Gh$EIsq{inCp2MqR05;3)}Z5%xi9 z3O^V_iu=B~8}ZR)(ckp@E4^JZiN^NYut3Qdg62MFw>Jhs#a2#JN~?cyM1a#&1qDGp zkhZgfJgTwM5RZa9JTU*@vHo)09^)PKsK$j!?CH$%(le4tmAJS#^{qK5-wQ~lH!;%* z>e$tGaJ+m#NN|+l9_EWux(YX6>+@lPD<1#M)U}AI92+~ga_%vnZfN{G z97>zRmc=UiK{k*GaZ%2o=H!$?ixq+MVtz7u(Ifoq9L$8A?e<@DRA zAM553#cn&_I0vyZ`OJ5KiBred#EK_Qv;Xgmy<@rCEw@@raRzU%&~mh2Tl_M|tG*2t z2@m@TN#W9!=F$^h@sE_3_Mmzxv@XxIBIs(VS+_LjAEME|3jslANQ;4#T3W);m8@75 z^7hcZBq|K4EdLRe2{=|>n5q?Xpa&NDtXR$w>(EsC$$!Jz=Oeyal43EgQyy%{zO8V-&a ziBPiY+Gw1}prC%jnz?6_fWg4X*E=Zp>bvp)12fMr5LJRc?c!LNLGsY(8@wUJe*7_u z{88{D#4LcYfTBPOwsrtHwHkI9+ls_K!`La+c#|6$*^^v9z(qp3!5Z2&O37nui9Dw( zLa?kMS*7QAKI3i(SfP^Ca^*}-q4lJ|KpH=l5ywRBv7i7fv+8OjAX={8&Bz~99*ncX zn6@Nd=L(^|y=M52u9o;|X;|CoSXg32{aJ>G6VhyCvMK|{)UxCZ8}zCD&OApmb8zgI z@9nHV+Bobl^4PjF%lg(fL^u8WKo`}YRCv+Uu%3GF;?7f8KWTK%+Q+tn!=yW&>#&&E z*0gP3za|kyS%lUq;62oeR;|;N>_@5xM`G{2Ba+zCZX`*181MgHQkT-J?>tR{0z-`_ z1`gy9-1PF8P<=?f7&HYPE6BOV_kE3X!%*K&4$Id`@(lRklxH!>NNY(pn;$fu@UVOM zZy=3TE_0kcyrGW1HS1mQ$RR(zFJd=mSsDzSSyG`tF2DNX*7n)m`ZnNByhjfKP>nK|9q{Mkynmi9mL^@PyN$P- zfS#hMGm;Cje^A08Jh!~kk`H@#rWJ@i65`$yd-_00=agPdr`)aY8<@Cc|0q zF8oJ4nAhjgOF#q2(V#|h%^Os}I5`v9UHJ;Q%|!)w$)LNxsUZt+-bFWrKwr-H>Sf>!vqIWCO>HZ} zf*(E<%q)tJ!j(N&2=BNcG4LV!;8X5Sze+^j=djQ>yjUKs4EpA;+!gqwuX1I@iTdxU z%tUNHot)Ra!@i0E$0n5ZGv#}cieS&QDBD_X{BQ)U=M5pQa8&L5M*A_c(|Kd}ro*%7 zm&ZAy1dtAcWuG8u{pJ)YuMg0!BBf#L5nx4mkH~-?+VZriNKda1$cyOlhVpPX)zT&R zL5uS77BbjmY{3I?fjcL96RQjH6seDQvDIFY?$_S<6PIm{WP=gjdS$||W@8zQ#YC68 z$}iZH+$(&5AiUQTtH8ixV+e}^MT#}OjKR*c9K%+2O3F+vzUa2(A1$b*T1f2tj_1Si z8waHVDndwxP%pFg?v6WN1K1cA)Zd^fq2CKa$jSussS`c@C~be8j(6{#t^J6Jtug5j z$>fHRS7!?HqX4q!#gTG|Po_Pr4RJD9y2~gg%{W_YH}})7F-(w3MABlQWOgzdxiXz# z(Vh6ntUX>+v)InY%IaL~LsSWRWTMHLdSkA`=xcN2@iL70XrPRp)w2vD0ySu(EP~Ve z^4(`bkoO*Nngv!UkTRedbo=qWjWbm7JCg#aZ3v_hsO6Zd{%Du6hhx)DkHO+Otdhvs z$O!hA$sura@4^bIz@Yf@82@4!&oBUtT(QfQ6i5vS_-Z*BeFsyNF|7H1m&+|}QXfl@ zh{t_?QdI<&zldAou^eVj>8d0p#+}MCd~0KooMp}i??Xb^fOfDxAI)W{V_-P7L4m|R zh5QcSi~U4m<4iWu4OKwggP5cG&i2)r?!{+ILl)ruH0e&yH}b6V^iR{e%8T6fgmhV< z_2Ay9e>;dQKCbr<1>GK}JgyW-drDw?N=lFzpd8*rZpiKF%J1J-{EM{d-U2oQ_=6u! zHl9HQ4z^WjDT{tYLdYQx@Wf+w%e}eI+tps>1dv|p!P!>gvKkt0^A;$Hcf;ccJ=^|1 zjmgG3nN?X|>-T*tl&c!%zxfI>Ib{ZL&V&|fJ3znyO(*HmUtA8Xf+HS6%g_}Ef07_E z;OgP<3R482`UL1156}1?%FYg`NdIu!T}eN1+7$<8#4d9Vrk*!>>&vU0`MKE9baT;>{x3FTO;RNL97 z6VB&XD+ybm26bEOyak~LxJe9}-68!2u@i#j1Z|h)w9V_=n8n-BEdc+vIPoi2jN1qP zojU*q=;`6Iw|XoU!RH))4IkPY{D2b~*usMK7L4wI!%@$EYVEMu1Iukif4|u`UsfC` zTk;eJjh!jFPV=I7c!eRdIT|HXA^_;+ShbmTYO62Dk3sbh969!bvUq>&}G%=P9E^{cO> z5^9sCh&+WDzyA_N&FCN?H(M3&%cFS>2-m8yv5xDf!gesof%3gcp>p>|T(Jarg)ED~ zn5n6|_V)Sa{aPm>zi+e@fisXmF8MkYE+SahSYkHqA^+tJT@Qsiw{8+?UABm$9GV6X zXU7a`+JQjZDGGkup|9kzqC|2@bL(?l*tKq4PbAN@r#(TYTeG;*X??E5tXHda;IWa6 zyds30AiXl)7Pt4|oNBJIzGZYyPBDp*Ew}5_iGEfxAS>#fwYS#kfUNnjkynW@9`~f=#o?#`I^#0zBfu(EaC?=v!Y-TI*EK zPF7fksRfgZK~lgLYRU{uO@vI`C4k6bHz z*xP$#e5MM9pDUof!Q`5K=?}6kY`>ybZbxt9lfToEA@_OM`Uc=&bvC)$LjH;yjXN5vY2wbu#(lgu>$D&HUf;A1XS46zA~Ny&o%< zy=!0M*d9RoEAfC=iW`A2&{rDp@f!Jq)tNFjCV&{i0uL5&DAj>OKtpjeK(`8#v{%H1^{PHN)3CMwt zqugetJ}(6xs*{&ioeZbA?d`kWt#iSZ^l!$U z4&q;Cle33XuhX-)eyyLx*%RT=4e|s}wgHmQb^EBq3RRfk((@oa^us?WbeYF`7Zv{h z%j1z_obv(lA55q7#$Gl|l%Gt~va2QJpx@7?*26gmU~oX@+YsfwM}ac<|pA=9o<#`O}AtDR1jD+vzy zCXxxKcu6raKICp2ST@1dW5D-Ze_-DIg=TQFA@Y+NcUMWUoPbFXC4+rS^3FGUg?0C9 zeZTVAZVX#JGJ)WK%bPPtz{Vs3km%IZE3wN9L2_-aZZHi?#7k?Wry^75b<}V3e2ctZ%jmAc5vve&>QOn75p?q97O^ zn}-XHwuJaDpZoG^s&7gwY9*^}9(! z!%Q`5H&~{L+@u_aq zeFF|9#OZ_OwYu5_;)}rgIS<+;wB~%lfg*s-C;%g_&J!yu@n=ivFdhS@BB-EP(fJ1Z zh7^x;Oc3HY_fiSAbp?jS-BUJ0U*7|#si?RZ4{xWXxq!9z#w9&{{n@o`XovvdwtbqZ z$)C8K6()mVLFtdLMSp;M=jUC=v4d^^v}$0^2XKYFoe~br+KvD<_YL>T!SVD4;qjIU zXaCloJ@RtOuI@v$L{h%aZqdC*TwGie6BEqp>pL@@m!a_51qQn;Qe#bo5S?2YMK9Vo|i=G|%P3DD^aVF=RGg1HEJ%7!o(YCI_c z-EC!MYYW&qVaBviz6|Tn-(R`B&*#~lt%0+|k5BwvwZ@cuPBv%AC{pF(7ms~^;OMxqYjm^Eb@D%kugG!7)Vhy7 zcp2c5U4PR3_!sIxQ6Q)P-^dggx8mcJP+93_X=!QRnfxI-8UrrF>Ppa|w}w53fI|ft zV;5_kI+-8qT&y%({N>bXe=&}Jw5_~^?(JLeqQ^z_pbjXfsd3RyKb31si|D-&IA=$wKH~BqzjfmTO#c?ajtWYvzuL>{fDy-u`cZ$8 zH2H@dY+%0!c<|p(ZvB#`S^OyLU&A@bqQ7QYxjTHX6p&E^`#`D&k( z6hF9iFG?Va`IMXW@zdDfIcC;Im~ElX4af0~Ij*~wBZ=UbgRXV_7sJ%m+LGH7wQ7L9 zPF)TwxL73JCtK(+C1*hzdkk3OJq8l|7*nq;e-JCBAV!(LNH*)d&|_`b5_NyX4i-Ag zQ33&R5Sz2zc2375%Pb+kj zTpcCB?go~lBIsHQR#168CW_|=k$Ny+Asz`ph`<6i>j~xfO80(~U#m2N#Jk(Gjh}_> zNi;5;d`)>Dy;2GR9Q?=h!31n;k9+f&85PlI2}?_Oo!4eY7WaOA7LNA4bf>B9Bwp+z zXnmu>CWmwEK1)xff1vO2Z$p#FXXUu-d%chRXw!b=$9lY3p#p9fK{IX@!VNtEhZsx* zf{{)x`6BLkG*r^$XHW@u9jO^+D3(*4m(Qzg%?$jrZPdFM1Prg<4IpN1kn^lh2GNfa zg!oj9gI~m3zFlfChm3$bB0IA;^ z_h@#R1ZSQH;UWu`I&1Y+DqheVPa5@3`U#Y-qykADAi%=e? zd}CWw)s6A|c|pH+(s%3jW`7L9Doab2yJ8(Krugpf!jsQfUmCDq!l~Y`$0QoRS-K5Z z!i>st%taMRE{i0AiNESJzgkf|i|Az6+T=c7k`SbVn(eRNUYJ}3eS08m(1*oeMJ)Zq z%Q(-x4fDWipz^vQjlD{N+#o6@68N}29x4G!{AJFCuv_|#C60_R1l@T4mj@VWMg61B zO{Q}5q;#jM{z%tMfxQGmNM4R3G#CB8fsYfSLiJ5e>e;k=CT2nJ#yC?Zs3%2lz8pG4 zKRot6@J1C*`!eY&WnC~Wk^jTnF6p`W&ml8lDp%Q#*R&e(n(q%$2v}S((;Id9aQ&+J zXwDm}Z{mFfbUxnfv&jz7>l&TcRE&|G>)jBTbwA`E(TCI>Esu;d|B>3(@DjCCkf<=T zx}3B%>MxZ?Z(^{@V#sKOrOwNSCc zkhgO+=Hv}ah#4cEACDQaM%`7YL+W(Lh)Zd{u1Prbm~L3M^Y z!tK@0p`~jF+OTZ1uF7^}PKrrch8qm$A;0+vLnL4-Cee_no^J;;mS7H=yhF#Y97py; zOpsSmQ^~kzpvI(CQuM={Gr&27yDpyM2@=7Jj}t+`zqNbv7bOeg+-fn~*e^2s| z9kdO3xAZiDW^HGdArh$d*RY(&7VHF&l3ju5k^431iTGW*^ZoHn(9fW8bIj-bI4WRz zdYbLoW0~WgSUy1BL;#q zl0Kj{f;t2Pg&^ceLMZC*c87|py|*~|8eQ3*o3)x+QCvJ9&J9w}+A({IlF}Kv25SKD z2PXm?IQTJh3!hbhAP@LVl+#)=Og}t(bQmaLk$2Cq;Ja@{LH#mdwvxgOQx0}6a#;

omlUi~I$Gutz;OW)b+tn6`cFA>2DoMJ#@qgH*SxEV;HW2f`zR0hURWt733yrYqj}orZ}N^AFkSA)%51FWdQp+oqCj_ z>EQ0Pu#XZCw~`@DVUec>Dar*7I%STkqcS zr6}#tee;);`W>}^g$G>mLcPUi(pg5mm~1e_L(T|tu@>#|$GY zXZ2N=lQiXF4C8ySdxFwm>A?s!9Yil4vOQP4`SFWfk1BT_TpoC*Fq4w_=o9z>N@{g= zb$6l_Agn3X>k+{H;f-}xV*}CE?WP{p{;Y9%;AqCg9QXOP8hgFR>@v#keV^)kS;}wc z4}HIw;t8Nz1YL{P2_WZcv&}eejgtY?2Sobxxuouh>*6Bd;{+!}_lBia5l=8ACgUI_ z0EEdTc^n?wx5O})8-BZU#nQHv=LpUP)7Mm+5R!CrpCG;@P16i$I&LkO5{)zQYGV7j(WQIaBK-cE;i zY-bloa^}d=^P5L-mkF`3I8>qSNwkptGBs|s~b`}ArkYc15t-o<86k2|ei1Mmq+;HTCvULOCNyP}@=N^P+X zax!d2Z4V=*VSJ=u9rc1p?4wvQ=op-U;bfuOZzJjfQW@n|q#DhySwp>`6g~h0T*9pT z4I6P`J>73d6Fa4Kb~j;w5|F%@Y-OxuRtU@%^Ts;!A{~+2t8iRh$iU6Cqu473&<3E~ zSd1ePHMy$lM~L-VgQ*Jmh_8!_Uso%Dv5yqIAi())~oh7qi~8qaz1= zx2f&ZYfi37W1`2OTlwPLi6u$@z#Q9$JR$J&mkH`~gt2Xe=b2b*x`J`j@PJ{QVr}3W z*9b_#{xZ!rRLrjf`CB~cC0!u@uERG-X@dpvNy8`R{zJMLlWKTzk@kln_f#$S+Gyy7 z+P;UCPCYPVWaKPFi`O28Kiwu>`We3THC~&~kQ(;1AWko@Jr)@G1A=7yDT&sU<1s*A z0>mTCID_MD+mNz%O5kP)Z{s@8Km)-@qDQg$l>^soox-7cIcLs*fQ2A z81kQNJT4i*k+!~Ys@-@E_Kq0fC15{_AizNAb+GI{H02i-;5=G-0X$;+Z~wlh9rW0&ZBl;}*;=z{=xZHT@qPm1 zz~n*DgU3Nq1m#Uu1!cUKmls49X=w+VniQFGva`o42Ez{Zj zCkecLB$n1(+n{KiY8{19T&rmGxtFpb-@a@S-$MF5G#=>Vymd=}9pcPjqPYZAO|S~% z+%YHPj7#wT<*j$4CTAI<;Nr5) zSGa9fYsh%|>@S?N+1d6xeH9DCN&tTWA9u~681@0b#eu?b!lk| z2yJZ7^?B-GtRbeRrlwFa<*A$70z6lNOotF$gr-q@=e18CKK}g5yK1Nz3ci2;4u@$P ze0Rv{z+{@to3~f&0J*N7|N8WmpXy9v($X-=@!QC`VCWJs88iNYSTl>6E|xdC#GW`i zHfC5V?IHBU!a_TvTJDDGPMV8^SZksJL;Leg_LBssFT}PQ-W)sr1sXb<8Xv)5npSd! z+VkC(N%hCTKwTK32{de!R_SoN%p~0JW|dLBa2Z;ajw>p-SALn}D==yj+VSwr=r?0QHHXKa53GEU!Y{*dRC+OjsxK=7^cbWVrzoV`K@t- zro(?Q!bnn$8sFXV2Fw);`@^&r^?CgYk?L;-a?}xt)s>d=?QMQ~bM;Fp9>*lLqLe;z zfmP_-RabldPg`L*{I3Wgoa@{PO!dS>!jU|fM*y=J0D%PgW|+yvIAKC|R1il^y{2mD z#_~sbMJ)k`nbG^h^Zj#&6!}VX!;=CKvRZ#nObXH?6}tD@h}KjCf|S`1q(pqD@FyOz zY;PO9b#tqSeFWGt$6v1wwm*>5@_i%^6*K@i11q2Sn zzkh$}6LHI7alGGQ1#uEV#!nqMpa1@!O#S`cry#ZygmjvzLXamzAnr|5y~Yc={`;^T z{B^>m@zC?VGe0#HyQq?}PjMBMtQ$=7Wag=@y@Dt(5F+W%vW8TIzO&LbuKnsGh~xnZ z@il;lE%nxw!5asG3f^l@c!=@4ufZ{c`!_y_;=tne2VimBzpCfA?|}LDcWILR8~d+` zMp;2d|bKHKkbL>V2*XrVXX2=aWUbWNCR2kOH&= z$hI);Fe)_k#`mwsDI@_-4YDtl`$^!VIj->anGt9_a-0rV8uy%kwhLj0*JAHr}^z;<&7i=4|8&)vLl#~F{ zkBsX13sO>2kX85qbt#N<-(H=b86Jj-rT}TS*D7}#1ri}7Nbuc%0O>5pC>!Q%Y;Pdr zpwxpS++umlTwkGfO6S%#KhS)6{PO zXaqvfVB)*)>Bi%RU3BN$+8o6Ldnfn|W>Zk>AXVl%+yAVkC`to=Mws>J&!1Va z*p*Bu-O6{Jdfrj)fK0lx)*T4{hc1)Bsv75r1s;RR7IWAwMnEi?btDe_%zVkJQ6QIb z1KjHn_bh}1dvD%OP}n9)EiEK9?DX%AP(jj3N3wg`Ug<%3KEUWdgeeQ~+QB7YvZ#PM=eAS^jXf_Xo_D>P|lb83(wzA;~*B*qyM6U2w-YW4|U7w5lB{uoSwDLyeD;S92EtdpCBp5;ctw3`Qy6k|6X=A4ZaaZG9 zwMa}WY_xK!4yRv)DhtB|N)N)xb4)h&_Qi0xdwlbX!0rZo zEP(ub)RB9->2j$H*Ltr7a%sh+KdC(%IxWkTUVYURAkAeHZ z+`oiQHpB#HW_lvXWqyk!{AbVZN{O}N2DnCW^hcafOptB@5-GTTv%!51NS*a{2DV>1 zfE^wm2htqF!c$kTO89x^eGhl%vV|uEtnBS)d-K%|rz+Ald4z>Ev6Imad4o6VL|C=o z7P@eW?6cBQr5rFVbrcFT!uh}mXU?B`?3WfA>x#(o&vLf4wJ|E$D8sep2*>!z*Ik>baGWVV}r`?$@C(-{+h|e4ui$ zyx7xI9a^Not-SyW$nq!>GPpZn)_~Rps_a*9Q&UZ6rz4O=oJtoOKOj>T61y*d{CEXV z@Gf#UKwKX>H8%_laGYahEyv~34O(EM#L02#yxN1KV^!r_82V}WGh-KKf#4A_B~M0~ ztn6Z5C?-3A@2#W+OBbwVksw^B=y;42cV#|LjQ#0meCL%mHwy+$GTMchvCZfv+)*t$<=#9AG@(lTD-(`_^V z%jlagOh>Pe;FO0R+D|A#De>KvQZ%#lq{`h;E=v^(g0jGHhAAuIU#>9+AA zpnjwyI56M|SnOUL2P6=jPJQ0KRWG!9*=jh~HIE0H3;C*IXYEU9tM;`E(l;8=eeomX@0+1g`hQukjmcTo+HUlP9|$3?Y!wH5##cp za$?J~P5VCBALUg7s=_7-zCY=Q5-Qkf*G%PV+hl@IlO~@EU$yvAg6Y!LrxZfawG*9X z!R#Tr{>B-69yxH0j(-%zgx;xLhkg(YZTBx?MJ(YnF^;yQ4t7qu$sp2?3<{_~Tbh|i z_D2!qFZA^VY-n(Y44gOhYg;=~n%{4(gQfGhOcK9?_x;Xr`0f#RvX8`H>kF~-eZTcKO*p__AVlUrGMk(>k|IBOwIVt9TFGSrT9Rf5UAfm(m1rzunCHwa6 zTY&sTyXO5=*sAuTLZfq_UI#Q1sD)2pK_1C=14gFJJ{xYI>C+!H7pCXo!3{nN-)s1h zJobjL3In0WKE$*J=F|Q7^qclm3wr5Tp$fNMN8$^(w$Vry_3|$sY9P~wz=H*nAJCYT zQhEz4K`awNYd~r|w^RTym4Hf`gkU(FmJ=cM06LHaIpMvi{d*xOz9zv|Lw2b3Y=Zne z41mBi3(J-7lGN2DDcL3dG5EV&uPz)cxCF0@9^eGX*QEsKi;9Y{8|4jP?nO^0_#8g6 zxSRMNDrmn*ogED$Q^!TN=eB>bXbkF<;258U++w2Xs_`d{Qus5Q|le@TetEMY2eVh?Fh0Q~b?a*tdto{zU@GT$zc>%;BuQO9-WG186iD`&5#EZvUdlSB znIPhbn?4*FNp=4G$=EQtgowj3?$;pe8&eGhnGc`D_x0wWFTnvGE#8_DN-2JD;nvJH_wYc%%;#w#-M-7!FXc-k79;z! zm+ZDV1kul^17_51I&RWOS!`LY)$kTb)Q$#+!&AzU_Q3sfG_|vnp8vJgS_QIrQPDu8 zFil-aFc^n3zkmihJ>B)xqGx~t=3&EJAQrV%O_Y`KH~^$j{y z_P6s3RNnsDTca3flO^x6q_=x1wk-X$Th!Yvui?4iQP;l1vqduLvkOamfggT3B@a4g z)%%Jl&J-$uc{0wkJ?C|>33rc-iHf6IRlRNG)uUXvQM&MTt^!c>SGaSK`(z+kfXCOm zJ;CGzGepNbIQ&HF9y72Dkk#oz2%67o>|W`>vn{Je5M{a|SUT##=ncVbpwCa+ zY>D-yZS;NHU7cP*!?fjm3xlfyyY^t_hFBDnBa`gw)%1lcPCIs{A8Y#-Y#+O*5ZhiD39>0 z_YC8Q!ZYD>_)_a|UC1bDYT~k;2IFH9OD&=T{b7}=#rn{W&kIy~jNDNCV zkJxTfH*;Ye0ed2=qOBsstEG;)h{6rG+o9CY6~92mI-<;r`&f9jpc4W#}@i>2SZ6I0j!Oi@MdwU2mD^5)J6z+z<4}q>Od$MvqbBUnCHmQm=Bwbmr*ho68u<_9!F>5zhq^q+Qqu zAo*SN9??+&HyCFys2}#07`b@6LBG_;u~gOa6q6db`V7%-jGXA&73(nJi|xZGrqr*!*}BD|D|~UZw3ATe(k>t9sj#7 z|GO^m9Q{`j?0@&h|E|mb?hUvC|9d|EcMbM$ga54u|MgkGYCCUiU#_wJW{Le+IKSyO zY^FCF8z@oBITRjmfmgj{h)s;Dr3-JR?p0C!?F2ecEDspb}iz$B-QWZ-@W)V z2hAwNwRZgd1`vpNMo0IRVBll1AKpi7!P9%`(0-+cK-}^>7?^=Td=S|$enEBm|Nh4f z`CNH?^>QLoF7n_m`XrJTEtq*=p!t9GO75k-le;qT)X*v$^E`2F+By8&VZ_%!L3js= zw&CYk=Wls#&&Rl73}u=*#!^ZPWB4)iFYVSWc15()>z|T~279xsq76J}IhI5)L+3{= zyRXjpMDu8R+o`KZT>4^4D;CU()br1i=J+xngmT4v;_EOd@1(%y)8w-?+~9WYbeJqG zdiy$f@RdF1^dhfvKBbANJiLN?%-7(9=qQ@ZzZk{(S`=MHwI#FQG&prjMvLX7{{&gT zBs&#H@2=9$M8IHA!ISdaUnK8wl%x|^uGAEss9j++r!_gG6g)e2;;4#G`UUbP3W~bu z2pg@1tm@GZWyS@VEDvYi63-`f(SGP9 z;Lj61zT+KkR98pUAHous&@r9T{4q8;RqlN{?GE;fvtbHb?hvo6y+yX03w5-@_S#P2 zG8az% zmZdJ?)<1JB^CwYjwz@BCXqlwFdF2Oj2WoEDm?=bHh+#+8jhRzP4Uc&uScEG`rVRv) z{DhBR=zTJ$q9eK!yTjE@#u0NqjlZhq*Q)u&|q&w zL>TMa=A(OEBD~YH&F4Fo40mgfo2nD#tp`PKt!Z}E%vRJG-5mG1I?=OyZ9bW^CXHsT zqDiPQhj>IUDFw}09uV$zRU${cK9f2(l3leSYMTl5(Q{m=)fT-opked=OSJn>x8}Dz zqU$ON>D1=*kyd3o8$&O3ZvzIxW$u5SEwax28$2$>x8JCnX7lx;?EAI< z?ws^?tO|{^PZPM1VWd&}Yu4s-?JqvlDyNxwM#CH4Pq z-E(SPas^x1EdGo3c{@tm-eh0qkNUJeIPZ;efAXTkdo~Jd%yfPKPg-xw*?(L3{wXWjMk_SWQC`)HS^;DM&ahty4Ge2P9FQWH_JW#)~IDxsbGY(W0< z+m$r8_txycWtH5aze%nye!GV9WwFSN_O1&}qymW2cZt1T} z+_i*uyG)LmQS{I3t=+9R%ViS0Li?l`8kWmh1FOTW?+)L-cirl2!R{lAR-fy!wtsOJ znD+Qr#})jwkK^2DQu1-v?_d970$JlZc7;dW3@a?WRht{H7awx{*`E(LaukouEL68~ zu1eZx5nT1`r{;5y?OzZ1T@HWsW=C|O@xjyTbGJS(4v$w|I#2BHsaKpI9~S!MZVOvy zy*FS^Jg=9Q*58M@-+S$De-5ok3qG}ryYK%kyWOijrC)8%*STwd_Sarbb(@6UCBE0R zWv$m<1eSl3LR5bN%fFVDoxtL6UBq0)+qs#UNgoxje>hm0^ipY;$0dKq9DDuuX8Jx> zz+8P^_Wf$vG>I=ZCBLo-{#J}CxZ=-uW1i6eT~F0)Cz;f4Oq!k{^!>B)ii~f;du(014f~M(zHV;K4BHKw5sMfY zY8-*Jv~3OhwT+Fxz8v+~&A?Ex>#X&w_TNRW@gh^Lj1Pthrto=-Ff_bbp%J_)iyhj; r*s#+AvL1%0njO?2z~5wXnf6yc@@KBlgtu$mK&m}m{an^LB{Ts5)64c3 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/channel/images/03-access-control.png b/_all-in-one-upload/cc-haha/docs/channel/images/03-access-control.png new file mode 100644 index 0000000000000000000000000000000000000000..c97b20ff20f29e85740fd7a33ad1ca57e45ff182 GIT binary patch literal 560390 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�YQ#)M_0I!ZWYF~+}c#zO{UEdB@QojoaY@i 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 my0YU9qWwD3t~x&RbV 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

NS)O{TgQI+ItD+SA^W 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 z zdcSt5RTlELPt5Af?^8Hr{Z}53d&O3?t9#E+z92t3amSnS9RUH++t4aBMZx<5VD`Jw zE{+~yDuTe^yq5n!kO6<SpZl%`X}HZW-&XqD95-PwPRZyF2+@ zeBLs^KHgm?;kJ;ZL}3j(jp#1lic!AEl?jnAR^I$GP)+L-nfii;t+KPx)r(Z^15$f< zw|jphzf!~b;jolp$kua65->v@tb3q}#T-qA= zMwd#LuW9Ss)&D>|yly@Ab)FvloHopbD*L~yZuWo4L`IJEZXLUsaN4+5>=)0cSoRdi zt&V-1XP(@=4-=H$S;xBp&f?qc$2~V(VM{NE)jYwe(S3o%6Eb2(%L%08OHl%bEWsIN2dI-Jt%YDWWB-aK8d}z#dH1FNyM+F zTOgD{I%+r@Bzk^tb=GpXy7hlzvFL6eO=CzM0AOR2J-@@pVXq&J{*KELH}c39kK1MU zznKzqq4dI`q%}HRkfbcipKYCyyM03q52CKN7eIhfqQ8Azu~(uDTU=S_zoZogdRHv zlRTR2=ZPIQ89P=xH#iS>FVC8{#9`}S5fbtnRTrssy}tHSYGMBvDH9d+kM=AcYL?|B zZ{Osf<`4Z6d$7upvqOvIas^68p9|^}b1fj>HV*9Fa2l}F@1~ymCr&vcznnn#ye(;N z*?W#Mpqadk7ZY{!Xs{LbVchVo4k(a&W@3BhOxtbTpUqV?+U2E(*^C+@-Z>69{|%VI z|3G-=1ph9Ow@-8UK3Sl`OBNyz}nhdaJeB z+RcP40aP=IthtoB#oeukg?_mknw>!wC_Z;5z2yFAtd@-Fxs-oN!m1MAIG2-}k0jedt>|1+Z~>CkyU1%LKtsS$F` z-SyFQn8TGiQXK5^(sLiGsaxYJYYeP+&zxxW7?3mGAE9FFj2Fy!i*i2q=b0e<>r2Ta z;2m7<*8rBZWwQ*~L&t-BA1lWmZOiMyb=@o79VvFkzYM4lm+lDOyz}&rq~rd|E+QQd za+4{fMA%)gzh=#&38F|D(nsXB_d3sS?M#({$skdm0P2dd{NCC+>N&^6)h!>E9ar)W zr;ng5fvS@Jt*X3|<5n{qKU>L2*q+4G>v_)0sIJL&T2pRdHZ394+wd6hPFLE4Wcoim zO^bg%-Diomf150JO?r6!)phhnq@d_+)<7o_L*OkN#?}si+2f6NaM@A$HMZw$CSnCw zWli_%ok{||H~u8_kt{{)VWj8*zHDEY&)dAd0m`P}Nqh$1s|Mi{z(plBC-Z$s|M;Y2 zvR`n>jSnlXB%#};+WN%kS!*5lWUk4z8?89Zlc?!Rud}lv1gN&RbzD(_w9Gx{Dl-Z! zp&754mnaxh+rKHDFiJrr$=MNq>}sK z@6ofm#y{u19Zv4@I^tR5Rp;3s&U@bo;oncFzQAnt2p3%~eR-U^fCXvqD` zE6e=UJT5nV!>4-=U-J=?lS|*2d(|eSt6NRq{;J)lL-Tb{tXH1Z8kbb<+?#ngcoOhg zAd{YiMYm+M@$N6_4R>2RF_B0~w%4{Y0?jn9AvQJNtwQ_dC^(94ss5

ecXkbvn@Z zIX+p=c__KMJfij9C87S)fwYNHUS&Uju=_o%Pk3b8k~Ix`?_O7Yq_sWqe}zJ{3f+sT zvgmr2o$fU0>Afelx6No*SChG&Q}Nm6foHNquGg0wqrEaVG=KY#cn2hVTj_oZ)M@Z97<0){PJcD@e%uh%7 z)&=9ar&!!BX?xw~=~dLaDIH%fQA8-~-|1_0TbbkBCo3XvJ=6d&9)6zC(uNqdP(nb^ z@qe5FZq<`UK*E!McVqr(I`w}01&H|Iv&+-u;xpg|kNB>!;w9!h>iRe|d3e3|>lJXP z$O!I4h5{+YP|)``Z&;S!0WE4-K+-4R4J}<7zkpdMuRp7t%TUiZ2%i`VXX_XSrXqE(nl^ zCcK+V4*OA3jLR+j-5FUy*5LxqFaj)ReT>BBwjs^=nr4O0>GZ3%#) z$^7%nR~S+qkQfNTzgcZ3=}=nz5rZ1sI)MX7pO0HU)I{IADVebVp2)zavKthsIuxt#}$8P`ssk2+!G__GJA z3NF&P&UBW$6_{_R&*nt`(>N~8^D12ep9W&i%-KaVdZ=N~h8EX1R5l&}Og+>6{bki} z)g{3XJ`j7a<=y^H1qR4x!viFv0>Ic|y|KhVoSbX<$Lcqm$CAHgk7OmFtLDNF%uH6a z(Aym0Ug#_4JW>{+od*jV&!s8)$^gg9Ur`#Mb(E#@ssvNq1L!L6ZKiM|_bcXHqlnPd znM1(JEEP@dPQDoVvUMd9Y|+(x>l1_mR29+c$@fl$sv)`I*8KCf1=_^G-5FQva3c@5 zfvt7T(f<7f4Kj0~<_}?tJ?7Bw$<1`%Af}`};l$ zRN2L680P`3%1j zc?zo6zAr zh1QPM%YYwrIN5qq-o5<4D&szhWyNBw0+s5kZ~nb> z94KAO@$7ersxRO`_`t5O?+LZ6Kr-$FX1bBjeHt^srMceouRXl@Ka)Or(1F^6JcG`j zHE71{=Jc1;Vs9wqeE|%ya<8xZ`^|RtQ|G^=)3J7L007f7yh7_nmN>0YuB{5pDB$QG z$M9VN^Ya78wG83Qcrk;zb1GUHKOg-E5~F|igT_U(7114t7S>;ojch8JUF#THFTf(F zi|*_BezRWV2z;Zc;GgJ9R){k0y`5O6!tK4Cv3%?LfwcV5=ndo6NG2%Qlwuxzp6`?i ze4~~T=Z$fvCj=7wn4+x9vb+NG73h#4^Wr!r1lUDIQl?Vr9a5LY#K8UO!!JG4IMpOe zfHQ@}yLn6jbNml$&`VsRR$<6yk3RQx{>TVFnpwB@eUQJz-kFA0t3=F3}QlODV{M3@WVHy7tq zcdj0QQ79z~BduUQF=Ax?iF_t6yw`pJ#A>Fu-j@K|!q(HXLfMx|m3+&Qo%$~P*!R(} z|I(KIc#%Wzx|L&SMTq17d}c(!owGy`Mhr;H2LLrc-hG5v;AH(WOZ-q@!fUk-(dwh4QBIqUJ0I$F0OPBBHXhYE06urNQ>p0H>XEMnOUKPr9UMtxrikNwD_OJd725NE4s#rwfb_5$iMcaf6u=$3 z>l#4I0b!tuo&)X^lIRgD03i^s!Pb374~W7&9rG8F1w`B6jVokVY`GNPT~O!i%G3Bu z=387s@75|7h+c-JWqZP@bf}`6bXp{n7|%V&=goQ2(Athdy{uk}T# zF3`yL^If#FCKn!=Ln3A}h{$1yW~b(s^F?B)T$^<4m33pYr~3KIX5a6&;Q~wSLlc?A zXkEcX>w~mqW}=xY;9VDdCFd;{b!0A3iA3mgvkE5{sYYlMaHv8v16-)c$q+47;xBOS z(aW{DoaqmMlZ5H7t0(cvJm87?NuhxyAuK`pfbYVUP1%v*(Q4e}h+lG_Flg~% zW?RRM$kwUQ%@Hr~vSlHBQ%RcF>D|-T2|w_( z^&e>e4^!zpfZI&=;v(ZHz~@ZY{oI$>i^8rHYAs=NUpxGJE??WZtYCPdIb7+xLzu#= z<|=@>6XfUxze2$y?MTUYcXF@$(2eAe;P?Sjv4J2k zwqhy0|2hwCg)1{Z9#Bw9K*6X=)reBzR~Jhrr&hd>K=^1T4>?sSZDjad2u3cc6v~tH zaCQ~(qgh|RgP-dYo9f3R+if0ZIj(~o2~7o~)040!i^=qb@23u1fRSKItZyk$D7KZR zud2!JsGZG^7!7o3xCaHEk32lN7#Y)U16D=8fGLS7CIqshF!;1fP#acZHO_Sqns+Ce z+$1gq1W{{`VUMCm1Xj2KZ@qFJAjfg+4Yltntw`$`2_%6x*;|4Z@^k&yp04hm)yyoI4vEnr`x=+-OfCyu{IFyl zKVkQeE*q9gDo#xMGul$DNpDS4#g;iYR_AYuT2X%}lDWH72?Bz2gocH!5;^Z4p`nTa z#f_l-aTzrN`tJ;rt2$Ums0~vjCKK88Ziw)&+FraHMhi(M%u%ffWheI5)8-%u=TAT| z0Gv&oNj*&$1Vr|JUEX#&2ezlEo&I1D+ zAv*$8a0)(7(<3A&(62Pg4#6AmE4LGax=+b>$eBr=$sdOW$rc5{9qn*}5NP2x$_o|Y z@I1Y{((apo0oQz?*f zg8JK7Kaq-)b-1#7`ln=Yl%Ul*x{WqOr{=kT?=!|{Z;x36X-|Jexb+taKB7}fO|JM# z6Z#(rf9ivjWn1o#rx+J91=E*kKUCM>sT0qFJz=Jvf?^=aeOLUhNJbjU(X7rzQ~7B~ z+)H62=UlhU=~aeO|9Zf`r?b+xij4&;=w#}ck4o~=rjFGO@oVDMQ6@h=vMFK>?D|%A zCbPe_b)eUb;9X-qHSko-E~O}cEqzZE+iVuD5rs3XL5VJhhtq00<;okwV1pda&yah% z?yl4&B+8I=TCPPs`(ki1+?`K`_J@J<wD0pi)yP0wSkhPiCFyyg#@k@_n{m z(Ia{tnPrI8L{LFbZ{GHe7PBA^RsUCll|&G)Lsp&gqR)_c1Mc`O@~TJ=t;Dp&E` zQu3)ah51&i_v?@X@N=!I_~wpsCT@>!Q@@+60e~>ALWYOQ#5pY`bA+33>4fqQU)nF$ zuzm_ON$%I#-qCg66+fk|%e;+P;_bEWS$K6_?wm=b_Q`q>s!Fv+ohV4%^g%Ek(w4rG zB4uQrXL^tEI~$W&itt&UvdGg;?kAH0?FF4Y&9`-n&I~;&el2^#H0z$^LAPwwt|1!? z0v)uU1`?Osp3Nuza^DD);!XK091=P-Zf7z zP0Rz}E&nvv{bU4wGz8Tg%}I%7d`KLLxC|#(xcW8r&?N`{ewLi{lJV!ZrKcZD?03hMGO8-_9Yf`v&GJ&k($}+u|V>TCU0?F+&1Us z+t3j`N%Qv_1wCCM4-(6zuPcJ8KIf1<)x8@34FoD4pXlDQvwcyeA${7(lY3jUIF!$@ zWJtZO_eYlNT6XRFn z6RPU=x6_$EbYZLTwtPwY$FmDLT8-advM2f{uiQ6KKhVoxwr@#-`qAfEKT(c*uwmTfRhEb9cv^kFIPb&r8qHkwn-1+;-d7xTlw#b>wrq0dT*&Jj3wMxG<(8y6dUi zJkQ+F%|JD{`=Vl@Av^Li+V9J>eZPSt6-$D<^H9yQlb4_rgUF5Q9V4ScRJ|F`!^<^Q zuWARj7dlA=n(l>BFt&a)DZe?hqG!(GGEVrBqEIncJ<+F;oaJxCx6YRp^Uc1GgQa?q zDd)hL^gKw~h(e0R=z5C7-jwb4dp0X1+;V@)^>N07N9{1n=QKAZ7EY%(A;aI=1gpFM zx~vT3R2vAq$08qUtx@IYyVz^4{$TiILgOc5ikCjt>yWs?`Q*Nu=W35ZJgA_-KykV! zoad8%^IyL%shwLq2YVR^!RdD} z0$T-jBfCUVlc}fN*l67Zgzn{D)=umuji&@cGnGx*hfuy(%|LX3OIqD4uuN(bbgp}} z`9_U?Olo4X5E~N*{vxiJPzJ?UC*xJ$>W>}*l81VvCIfm|<9zf4l6iR@J=HL(mOAdj ziVNA(VQKkQYI`~aVQ3K{Y;dvKIM^YVQ8f!&lY?DEJ-{2qp+x)S-f)s)@ejo^VFWC# zp;9+OwvpG#WV4-=r9!`@-2=_4H2Lg4wi$>17f#K4ZWG-2AMzcK&pB^nl4SbzY2B&KVk;2CsgB>s5FltlNZpJeX~QSs+XGB;DL)*Dk8Mp>=WNX zsdJC50j(oZjn!zSTr8DtFAgGz`EG98^i4&zgK?fOa%B23_dS2?x8H+}@;x8SDHpkq zlPkBHao|j$%Hocg$Z^ZNm&}fT4MYmf@6(nUfmpla_?|q}0nw!j_-^J&=IkO z+^2hO%V~e#Pq3bv`eo&OnzOE_^KP4i95oOCm;0bu5Mrz+`q2llLL)FJ<}qr#{(u{Jh6GU3xn6-G6)-vD%QDIG6NU zd0x$7wB_w(=dn;b&~4lOXUTJ8(aqEL99UyZmCa?teUyMvCaD{4#aXVb#<}sKRK$mo4!~Ze)L&+>UPN zk~p?kgxY200D|J3F+q1Bu^FXiF-JB?E~$B9*KZ@&WVhUo#ad8aYBDlFT|9^}rU{7w zWwOGtCb>L(xjbG+*{p%QH8jwy-4bbGQa9<(4DW*q8u1o;y_ay%U6bDh@ky}4auZ4v zpK&F;FdU--UZfiN`MhKUB}m&V21SsGBrylMild4@hf0xDgvJ@n9xFNo3-Wp}0^~TL z&&(bwjoD_yV|HTRa6NSnlj0UE1F`iQ1Q3TYB5xgm#4_p+RsG2wK=rlha!fnuC?1Ae zpHO&re5dtiWx_sENbiVnGL5)*xfHeJyx#6` zx(&(v%O=obn#MYE=*cw0&~c^LHTiMstp$V1iVC0@tt{2IjDMnI6LK|WrkXxayP0qt zyIVG#NB-)ZLgxhm&@Y#n7>8Sd8+9pjwBNV2=7N7}xPiAqkch0A)lwrT>nD*TN$p~# zN8a4b$KO3S>MG99*dVtDHL9#+Mxo?+M-?5R%xh`?NSg}wQN7mG3`B&aVx5_4yT07W zwmKRqMT?QGpIKxF8Mg&1ypZ_Q-Z$Rq`R10+$$AF$M<jT?vbkPMb}YFaggQJBKA_a^Nx!??8q- zt8prkK6l1J{-?@)RLA1@Z=vDXxeJdf)b5vI`?%$!tAf^!>XF^;ocp2oaiP5dHF-?XQSg+MsvKmqAHuRb6fBQzLwY6U)%A z2GVX=Gf^okHZ##imKr36;;}kajGVv4JEh*Vlqm=H&z6Dia}1K(qaWbHd$;j~)kF>Q zP9#{rdoyS!mdeE(v`aOKmj#as%ot0JOHY}cn@q<}s`-jBXa)jB9F@X@kdzw!sr)Cw z0ykBSf(t`SI&Y-O1PDJ+lBwFotYt~nR{}i)zlDk?);*D$EB_D+^`OF1k0Gs|lX|t1 z#_i_74}S5OnErtvPi;_oAUXGtZ=ZpO2ewu_XBbf!M{&C6JqyS#(_8K0>3s2=ucO!} z5-L5uD&I#%V@^QQj5K{&Q~P<|f3x-S8f0 zpV^Egr-SG?s?*vn?|}Nt2ZzosURLi`rJcg4aVKosi4ql-sF{E&Lp=PAhVE9HH*n4c z%x5>P)E3>tPN$i|i85)zmbx@CV?}2a}!ImPo{u zIFNsPW=)Q?=G`Za7u%ITsz@f^{GO@Y2p%qf2LhiDt zcw@9t209KNP4RfdEp+cdIwo!}avWPeP9r=SF{tQR{pc&f&O2(Cu=nAE0N#B3cPhmK z@;4v3@FBSom{fd(eqb_5r5W8NUaP?YmV51tk?^8z$i!w@upjP9KF$Xnn;ejVtHb*G#E2CS2pU9VSD$c_SdA?2Rxa7?0%zED*QuGh7|Rs5uGsa)MpD=%IA2D31j#2+9PCwzkO<@Im(~3V z>DMHCEMI}%Ma%OY>c#SwF$pthqcDSMfe})_;rL1BTxV%vh&`qVIDRozetORHno!3QG`qpBgsKW6xmaLx80CBy%1ajo+B+pf@Ikk>iMw)G5YM zEifIV7b;3*HA=EuP*VERn}o-kdm%StK=%wkSZIzjio_T7BPAHrq7hYmiJq7Dz`}FW zp`Lh zWA)WGO7jtn;Zj5C@xP!?ooQwzo@0>!(-N0TeD!wKO%ZtQ3D${s3DyVyfzET$wV~cfMR^}JS7ipxh}5Vg z9H1vcmP~S?)*_$4@bec%zkfdv*8hzDY%Ug)_-wi|4oAj>yRAt^5N$oZm(1$Cd0Slv zW6QC9dLG}%t|D!qsgr#Kf(3moA1$9A3j8!%V=McC>;eAI;*b7ubDX4WK@O>Ly~J#y ziE3(_t8|_?e;&sfuy?+VYJQ#cG{yvv^zW#lEcZ zJ=>siO{u{%f;HmtORJvtp^%IT`wE9!u)dv`&Vz~@@R;>7?}V+{wCC8@UBR4O1bb~J zfGGFj(|(+$m$}C3{ml-~mXKEjzh$B+PZ^WHZ68+rMfv>-*}47?G`IP@2=yO`X)br6 zd8#089`LX4X2TJ@Z1PJkHw!`T0!nz(N(c+c*nVi4&OCu-5izA1E2PJ$Js)u-E-_O&l>DrUv z`wD(`ll}VQGewVvOjW9ARASs))DhI< z1HTEv)|pG@o-vr_*>QS=Rp1uh)YsjdYPu zvlr9rqG4@o+#Iop=`pP0O!9yz7-v{yK~RtMd#-n}53TxwD3wwj+pssvi+fm=*7-Iv zJ;_;nCVi0}7~h=9S?;+Iiu<`XIpKq+H-^@j0IcRWlkqC|4|o%FB0A?P<@NkxJ2S-6>sG}Mt;((^1=_{PO;WIaV)(MQq%kak@u2D8Xra+?1Mu)4kelMJ7A(6w|?4nNOqaeZ=z23MASNiuXb0QPz?f@b<^_h2s+o zR1-+Ue9LR)!f7k0vb1ylo_o>}A%;jXS+)o<1{ z!&Zo#;^(P;g=xatB1zM1WtS-oW34>#*$7j6pzB&>Q%IGi=%a(HuI~Bug5i187}cm zPkb)1afYW}KmP{aM&#Sx(pr?YjuFj|Evyf49QO8*{9L2j{z`EL(|S~P5}_6@_$b}c z)s{Mio$^-7$-T7REori zu=iN?^OyVTKX}1O5*IoMgAxvxi0JT`{bw?9ylttC5W=3 zH;}DY&VU#{wHoCDE9?71$&4aE5gX&ts{U|bxrj)F(n6nCet*KoCXV=_gnmV$dYRVN zJ=rT6QM;foR$Kj~o2ZT8sFb8FvaGN#q555t64J^c_Y_O1zCeTvV##V;2o*tY5+VsO zZE|*5utP(`mIyP|FcDTB69+^k#Ab&X=cD5*6=g&?gn6?=VeurmS)ex}G+73m-KIf>A?#k21f1Az)byv`qO zw0xqrWL9eBI6bQm5~7cWW1c31A_aXlI!TzZ7$;54U-yj0MKNk8iGk+%_~VJeFb{0d z4^i4>WR$14Di2hR)*%C5R5anao**i>R+3vk40taE!JQH~C!HeUNp4S#m0l51P#+aC z-51N*c^L5{V4F>m(IdYrsf0C^^($-mEyjCF=%NUBp8@|*+O4$&Tpgi}f1-9-IO^65 z!_#5(DujY}ohwM0a-k4?3+3wYZ-e<7GqAEc8efq8!9w<^#PI{0`Tn!okG$q z;*tk7wR|;V9Npz&aD$JB6P8sD2JI!Kq8FV;fg2+N_f>!?%jI7axbN$#EXDYBYzJy%@!VN_{fhqp$w2x$eOqW${J&&Q zm0?b+9{UEFDb=G?yuFl*n&%SNG)$@!*HFEgeQJ#_XmNnq0O$|wUs6urN+-#JQu-`~ zV(J(%hp0VwyNV}4_x-EPEi#*`8jdf2tmj;wWjOM&dM1Kb;zV_VAE6bIkq;1LE{0(Ql;XqB9x!Yc(T7kHjDT_*cilFZ_*n z@L#d|9ismL@fdGee&?9VsY#>IRhT3}>CsXS>FrghpXBwA6c0XjUus$(n~6;E6u3z< ztek~pmb+?IgDKqraQ&;$m6P5JxM;)9}M z37={NN(}nW22$n@q-YZ7atTeb#0Z>7yzt#UMaQ*7NFYEUsahA;&nj;^Mpt-dG4IgQkn}9h#;Bhfg#cyAd7^^2}Q$+ z(OZFzfZ08DDG5d8G6SANR057#gfi*JLndoHWxaS9V~)Ogy2~b2$+pT>-~t~?WMl`teFQ67Xsof)lQj*UUdW|^F=)J2#}@DCT%uKKoU_G zvHH~FQeLVjM1cB{=BX?w9FrDCkb!kIU)|gbrMG@^oJg5U zz^Cm|zk$n)*Vn~jOhK@-@9&kIV1lYNmOb`TK=moK0n1s7*4^wo-?h@7#zJ)|UxD&5L zBcV>+5CcF(k|^^=14-gDIwD&z4biC^;E$065jWyjZxu zImk$HcjT%`J$+T9@{t+lR%|03hd2KKtZLo9D?NPMA$0!$im73s`aIXh#($_${Lj$r z`}kHP)<3zSTnICG0XALj;&cfYL6Bt(jyC@QrO|zbq3|WDDq{HlFi8_2M?Ol3bT-{! zg;y0moPsX{x}|&Hk|MoE(nH%Vm~iE)t&9X$HaBS3@1ml?6&V_mBI>p}4S1i;3g0qW z?y`V0WDX}etpl7u=95}=g9R|}SY9CN6?r2IQ`ee6bpj9O@;%pzO7~{hbq#)r(Dz;l za3phCr|cW5zMCpB!-=4k)Sdx-eYe_@=9^`-oFEf^Gt7H^-IpvkP`aDI4M5Ge+P6pq zWt6yhjB8No?_WD?{fd8=?vJnip37)M^Zl95IobZ{Gl?4GYk%Kzr<1e{=K}yp#Zu&d zO}!Lz%AegPZ!!J-RwMm4C6m5$j0uLj`At8ir_*ZpXV`v6&0lH!{{Wevc!c$~{{RT` zZ0x#`)??Os)|Cd9TQ9^RjlaQyOOMI4wGke(xh-nrr&Y%R_IP?8ov-%Vo~1atb|F1V z01McB;YT2xc1%W~qQjoIL7E^W8BP-y)TQQB1fU2==wNb34YdfjTOcE8iC)Z?CB|(g zcb07CT~d`iR&9!>grfSU7}q_(0#8e?6iuaN8?E(srLo5U0O6c2pXr6q5jReZryWvf zd@VTDuL^R}w2puN;1_pKft#?;}a z#)gpw1@&JK1%X)FQN&`T<$f2){T9&LFK1Vl8wCi#M=RRz=4{=t@f*I~zGLWSdt-~j zVI2)POuBHipmIDOv$+eBt$Q`TE$;5$gA*r3W`!f*rLV7rq{FX2M(|pEff}!P*zX8C=*6;* z$mbZHm(MZI;H88dRCwy!)onL%FwNjJj(tL~_@Uee!0xAH@@=8n6OX5g#^c+DtSi+o zZAKbp+(1C#GTu@k_gaHM3R-o}%M&WDxk8NC5DuyaJ zEPP{9?JL_n{vzKF?H{@wxx{R1vv=lRikmAoyQumn7P~-OCib0qtUMXF+P7znfE~Wd zuMIx72M-e1>mP5}w4bP7Gy%%UoekHq z-p7Fj^hLGioc2iSq5xAGLP_h%ULwI_G(-fs*%FHP76?o>{z$k;oSixqcc=Efne!&i15vtGxvfx`BdyXc2p8;c%k0y(YoQ2S2p{OqDvuB`9Aampt1*2!s+G*#Pszf!&h--97Q*{T!y$43PIsw;HVrVUsYc&%kwPd@1>LFnTBOjnEb8HQ(t!ZxdNe4Vtg)NoV}(0yu#&2xYx0vz%o#wJf0)p2{N zU7Ar^pC2-R zZJzF1fy_n`*q7xwv8RbXHK%mcWe24GwF|MA_DtM;uptG;=DO;Hy677t=*<~nPyllCL0*)`F;|E=$2M&whNxp z2mUehX=rROo>eh4Fz)nq@f4}NShT!K>k5i$D5QWmbpNdtSq%fsm>` zwF&{gnzI?jrxSpmCD9orbXqUXI&Y;}f~6{~dk5z=z>ew+#9=BB#$stWodaGBrHV)e zD7aC6BMV6I)x=V18iMc&oj10lL+Q9ZzogO#Dyt9~Mx{bUDsFjec%8x~2U4Tx+(*$e zIddJzTRX#s#BA2{H|ek&1GV%kSIRbnKBa=kVd&O%8nr07h0q+>AQA_CeVr%pj`&*K zpNBeoy>{t#dlQt^&v7{FSohY~Q;q*yk+ykOPg9aeNQyQG((GBG44|pK`;cz+hq%L)E?UFB9>!XaVV~vYh^r1L{teGY^TMLtdRo7Y%SKaW%bT(rN~an@UEZi%ielsxox3 zBwZ&sgL8R--yKo#}tcK#pyHuw_Vhv5@>)pFcsd52{&kJ=1w zAJbQ>i*tXVz)~QZZPYc40npwj8(Wm>Ze&!Ck{M?1_miCEb+fFecAH<1%jh^ZrY{YW zVk%K>z`KJZpH*Xh8r1PMuvMtlqlv@2hOQpHGft}=7X_yCs`__~_+$1D4V?N6pK^Oe zi^`hkAB|SbXwj_j4V)=y8cpln~ zlI9W|Mcqx@FhqzMRizx{vKG1VgftPv49(Ilg|T<@x?P~$X7clm+HGlLvrM9>;l)y> zSw}I!ym3&)(+5r=X8~Z~Mxo1Hakqv`z#PoLUYIo{bDJZ6K{z~>A(&tWxY{4r3((g! z@xkj mcO<3cTCoIq*ANU_m$h$y1Us!xCw=;MH@F&~FR_5EnUAN?WX{Jx)a6BSb+}>>a@P4vr|ET~#Wz@brJCtxccl zJO$CkSk3bx1{6%R*;J)p4~ci9!`7!!Se)N3%rN=ZL5#)V^9;JP zE8+1tI_8ynH9_@XO~8U24up9u$vb2gxt#^#{{X>0+IU{gDQ4JQUMD`-Tzi>E2c0>A zl`!?lAIb48Y=#m;xE?Iw(8yZXa2t!-{{Rs?!@=&?V)G2UFU&DGEJi=m=020qHk}aC z;CLELo*)IH`mWvGhr%_xeX;QIwHp)Sr!H=Hp5=Le#YPddI8M{y-V0g7ZW>sIk~rNh z0D)1rkiLIxPWN`#bsI>{tKFW|Vs>viqe{LNn2bF@`i;X@Ehe0~r=v!b>aH-9oLpX} znn~R3W_%GIAzC5Z#MnXq0A~_^{aUKuf+xfy;0@vIA4}83{{RB#&&T7%yU8Dn25D>D zQ$PN#dMJD#9xZ8+8~*^z9X!q+k^5<^-mjTbkCEu{G2tg~yenficMG>WNs(rb+7Vs! zTa~t`^kR`^2pX>sE=E#|vin zhMw`MxlZ%c&93r2-Vgi^?I((yyJ@zDuF%%mtcxY5@k|C`@ljY~b4U*KTqL$>F|b}i zpIx9{V+hH-B=0wBxBHs-aoK#^XEEDPk~ig2<~t#_SXy|j6@Qm76IiyZo9Rhyb`b6&8hEdy%HavlZM4eLTATIX1iy;0 z0oks=GtU`Z$GVcD?}BH=N9N~yzcJSrh#&r`VvqPr{ACjddbvse0P{{8_An|B_)0uv zNh5k$MeY6w!=L_w*ZAV_F<%ir40pxhizCT)hk1F1%;GS)<~`U74a%`KYCW%QJ~Ca$ zO`tXbxSOmCb{mi12Kj5|*j>}?7C&jgEroSa{2L zK@A3E{TPLXT2Xe9cT+w^imVR$ZMMF*HPikB{4s22ijBP5EtuOqpw6<)E=iP9%qY7m zt3|J=QT0POU+EbC09FN{Yt3}f_#SZb(0oSbqDUroZh^mF=@$F&nc#Mhg^j1rcA|## zvD;Am?*QDt&{xXo;aNyFpm==KaV|E9(h5%yoNS7rXLIETi4E7~+n3*V*Y3k0$78YC zZq4Gw96l!+8|msZ(Nlk~!UJYrM1VBVD|YEODZE|#?UVKsb~!B^%QmNkb~)5*Vp&10 zqRs&4aXf*m#ink%`^C?}-%B~gZ$HF|-u^w9m*FwnLUNOnu+#jN4k1I*`bpr5U~zDm zFkr&@`?@XsZyRxYS5t2{U!T#+GmKVVFcqs-!c)Yx^juo!0NSk~x2DU1HeG4dl%Z(q zWu%Sn&w}^HFBz`QjoIL2z^R>K$d4&J)aiT}elh7(^p$o8W-$$i4@T_k4jNs<0oHIf zJ=W*&J>#pyj`{pUWLpEg9kdprETrUsdrqe2#~sL>s|t&P4d{BJjZneG#6H?6dc&a*tb2J8k7 zt1wh>!j%(H)Gdl_XeWup$-1Msz0l_y_}->Lx}1+S!sWQ!`Sse&UMiESQlcqPePT;n zb0V1@WG`CYP~NC>$vY!*cqs5?vHmFEn_~8dd(6t8lku{y&tx^MU9{Vw+r6OO-qm5n9OGtjCl89I(+sUd!Ka9(NtZFqEp*0@Z+QAk z;j7^3@eAS8dl^>pvd!)6rFt|Y3z*{*N<7dEb(s-HM zT$67$8)AFTx!5kVb@b3(MQudgOH7$oV(AP1|i2 z_xAq)X7_uu6e>R-w3(GW6C4Go&=Bg?&+0LO&L%7xS4Q~k@Q1pu3wXVpr?C5Pp5w8b zM^>#tlx8iZP+_o?+R$qHb_SA5%Rp&u{bN3=?Oz1G0CNuvn_--7=G^Cb7SQJvu)_nB zRKQZI!GNOTO>gM{^`GiC!p&=ho+7a?5nl(6{d_`iQ$OAgX}%4Zp@PQ&hstmjuo#+$ zFTv9w(xe|YGSXgKXF2XMb(dQ8E}li*$oW&~!~&p1a#`;BH&>eOS9+U4y1e%|!Dd*! zpTyC_*2Upzx}7?vr3TfOwcfCfATBipU}idn?M+Et9LU?MKVl8}B@-7*v>Aqo*Z08_31%^Fg30O@(abZe#<{Y>1=ac?Uimq;0L00LloJSGGy!@5xW40q{w)Zj_PRV62#?~Lw);_HY zBdh9YJheQ5T|>Js4cjfTeup>Ochk?ahQo)XWMQz*{YD?8N9j8K08<~eu=p6-PV(|K zvi2S;X~{S%N6qMSQ+HXmtk}Bye~ik$C6mzfWsk)>(bcXV-~pz{k~^3kC1SiT0`}&+ zOT@iWH$j-RpQVVyi5mSdxW+AWFs8}JPajFulD1~H?#!pM>&A^Ye6IaT;X(9<2j-Zy z)e3>UZUDfNSEmZus6f=TsxN3Y9U6jp%KCqKpBwI?o56ts0F64S;rNCjw}|V}M}@>5 z5eisvMNk?{^81x+P9v_?`d0@1x6wtQ&5R#%GTNZmSesXfRmwr_6?l+I1F+f%ib+SXE{$ZMSL85G!DVEK@_ z@}*N=wOm7h2DL|2K5jC)3wqgx2X%Y0z;3fAst!Lgr^k$_53bsCFDIuN<DAB;JV6*jP3uJUvsEDCe&NCo$(?vnv`}>u85-3(DSP~@l zUuJqAosLB}Mwc9t5=?$-Zio{clz2=F!HFmA3uH>7Xk&lLaAm63xHI3iIEz0 zPl$$qS|t`X=7Yc2tv?B8jPy~_HKWIu}N0>r_2W0tN{b@v=X}8Htt#NUk zP(|#30YNr`70{Z7q9h_n0GpH(7l}h**9K?nO*W33+bDtg$95TFmMbtYQ#5JD|Y6fOv~^-^r8>DK1yg{+wwE}EneCN71UWKl)zVsE(1+`(XTW}NSzf+FcIEU1SpPS zNHl7?aj^x(*)VS<96scwM-`~J=ehyCk`bbI0LH5iB7%0;M7woFBLQnjPstvywGALC z!sYZ7lmv5#PC)i1NsuE>z0<_Vf>V7FHbu~*0tBXYx(B@y2DelZw4elmY)fQy0Hg77toyLCHQQz=cvH%yHcl)fy!> zQ-KEq+L!`tq8ym$6iYA{yd=`%F4O|kByvE4e3i=MF@icLBUn%qspy}z8qA2D&Wbao zktTIS-8dBwNCgABh?Mj|1a&DoAdX4#1dlOvVIsaHA45V!dc74L0gkKDh@VGF7$=6- zUST(Z%bLV=I#1d?xl2LLa=;J#Hi!N8t>5B>q4|zPMbDwD>uWzp@9tVdDlHklTy6dN zM8y8PR`Ky4O1?KU*~~Q-8kK6&sLFKOWRgp4IL*|Bojn24=gkM3xP zQwCMD-DrCN8lO3+k5se~f~6pPkv*sX03Vqowk`hu0Lbyv+^+N*;l;A`Z0IM_v)j*2 zRcub>ccWUXO)ZywKmY@Vs|Xr%o9e1j-`@6xMh~47Pbm16EhkMErx(A??qO^GOKO-J zS^)<-xMj@fM{D{3+d*>yVkZ8lSNSAZPw{TfG2ealFX5j*3i?j~(b z34#amDtaGc-#!mFo3{IVwYx=w+N|21F}OUwlc6G%DX4oxEVrl8G(h51qBWSZ> zGyJlz{qmkq#qz!i8VUH#GA7@gIj_I`AISW=`%mZm&4c0(g}Z-+;eg+hXx<+0z2cj?eo%Jr7pb`(;m1CiX~NqnsuP=Dml_OmI|m zPDd`No)1V<-c3T-o1GalRj;`(+RC7!--r{T;DmF^<;+5#hd>QD% zOLq|oKQ;TCi^iaE-(RFI;}tU8IT7aJ$!PXCio9UxU@iIMS1)^afsyS4Dbe`0VU@O> zH?Y~ojx+T*81A$!5X!^~OqdW?i)6_>91o$lAlA^S>->qo6O5t4>NuA+2!PWNvaN>O zjN2{Fuy}VDRR*&`cN2j(1OwMaiqvgZM-wEG8fvb44VGf_jk3ye+!Z%euU{0_wV~WH zPbuWRSeR3lDLF0&j|oV`*x$GwLMfOiuqHT-c@juQ71sfO5j ztQ&Kb%lF5!Mvxw^Wk*h+nOjGEo1)t+7R}Sos^#oBd<`*(uG&v&ET=KW%0!>2tP8`A zR{Y<5n>;Df;-!PC>}^*NOfifmee337r%7z-?r4)f&N7{8ZEAg@cWx#_;`9oe<0YY^ z`34?COx`-JGUf)r5Nx)$iJaP&bG~fd^x%vgI#_8AnJi$N`K?^>#Q-)SFQKxbY#lrK zA2V#rdmmN&N*p2~07jMyQD8=d!d8p_0JVFMm;o+cN${ATVlJhCNSK64Jk64~MC?q; zfL~eyEhw829koBurO4CjS8p4mmF)!Z6uMF-OAvIK1=CGz~%|fcf!!` z@tH^c+(P-BYFfl;)qO7b94a(s`{NU(Y^WRd#Qx>v#Xq2Rr>V;xJm|-ZUFe>YkB|4jOu{ zBHFGslHU4E)LusV-F|=YeR#dZ;`eiw?sq85vyq3YY2fj>4J^AB_B4R^;p<_{xy?8A zUK{|DBI}2DOh(2MJ75 zFE6WA;grL9O#9`1ZSYaFcyAN_2eVDi?It>%Tz*r4#O$6S#BtPS8T3iPR_AuH)Y=bP zCKnEP7~KXpZ2VO0*3V~IHC8iZa~wu-n>M8zG1+`If#jPXjT&MP?^~xm*toJadmXRh zk8=Bg@ZsRU6O+;1p2=c1uMw7EHd`;uD&@3(If~3`wXLm+6&yIdAZses4w(g@Xu0#? z{_rKUJNC)(8{ywAJWF;rFT_6!mgSCns5dfwAL(%wYJv!&(l}rdE)NnoZ|eA5x2pX6 zdD}a>93C#I!t9<=Q#i&kjyyjd#aV&f+eM&*AjNL$wYPh_ADn&!c4u{4KefL#8J}!U z2Mtp=r9?c?7@BRVh<6ElLyP$80!xR}CS`KFj5X9-Gg9VWCH@U<-Dk8nf0pjoB*x_q zsQOiNY`}J(-Ciej=X+Q^w7^!(E8?h^nlyz9RhrQH4P$D&7MF29U0&-cbqhGW!n@S@ zr|@v>7Q^o+#Fif+-WJK_+5THoW^uU2VKWLMwE(2IXE-m=3Q-InGzL9B`nsl*EYhc_TSBBv~g{wZyao!|yjhe+`sy{Bt_D+^73xz+? zGZ9+7UrASl$l@WC!95t>i*mf`S#b*_Sw0X=@OV+)hR^Ia55t}pBW5!##p5bwZp-pV zW%ViH-A0(C$GFmGqy^GIlN=|i;^4vnE&~3=>NFV;c%%Iz3OO~TNYVgUo{v&sTLuB?(4d^iR zIBMp(y-Iv|Y@&f6hd-06xB?kZtP`Ov%#wrNWm&5mx8SbbKGkgph$?%?!qBNlB-t#t z6;Cm(C9O5_Ea9bw((d6ds9VSZHz6;DH*0c@w(&`qY~E3fq~~njL5It8Dx6{&UZq#p zG-me{-oYG;qmf-v;sbrVwD>8Da#=AY44 zK8E}sehj=l@5^zRt>AAjB>BgkW;vcK0%^A&T8PToPBSmc)l>_)uBo7(&z!Cw(TXL2?hWQ%d&gQ-af$La~uxC zZv$wycMqGhgC9#P%xdA8iEf^_VE~vUPOw%zdlF5$nZG$a&vn+FIYv#kWw2{_LGmlU z{s-XmzRkA%5wbW@{{Y|F`_}?`P7vT*#VsIqwyV8<2inXV>f4hy`KyH!{{XIM?o$)& zmO7gE;X-p;;{#|18(8OL8C*$;{F3DiJsfUxi^Js^H3#DJEOkaDug>R7=6 zW4{O&fc@E1-Og#^2Xa|f3n0bhv>A@gvdp=no?n?@K^%2yv7W6ut!WPqWHs#$kVyr6 zz^XXkievblOj0amGxS>x1VeNYC*D`t{fQMbe}d}_%xzcJbGKuOVRb{qVVG)xqu3e; zv2LUt7Mf&P>T?Id!@VC1nGIZzVK%>HC{*6AWwg~9l4ftoJv~M;qZ{Z*#L4tg`9{Eq zndd9Bd|q!q!xrsw?VPFNUt?+Q4GhM%C7DBCkvB0kp4PP0aN_=qkmhJ_9hb>p1{D1# zi+$3(1M6p4H&{SEqt|DAGZ)$I*YNVk=44x#rAjQMp?ZmVm1%RE+m75;^}Kd$XW*A( zu$XP$=G#M(;oFo~%LW>Q{YHxHb{*0o&kiIT8JJto;bq-^?6-fi+p@)MCctDHIae2) zV`<_Ym1WehzM7b&OoqSFv~dB-W;rfJ@TN>knl8{QXls@tl~Jr2}ocwQ+g$C1^bTQ2IR9X>~3Em$g;hm%W}78nO_Koc(wokJ-Y!(y{EHOBz zKBI?2IChB%`^e5speFK-VU*-VZa zH0Shq8~L*1E7g_k{{VoG9(gV+X7*bk!Q~rChr@hglW_TSa;)PAOmMZe8W`RhtQPeN zdvzppR__$P1L=5+-wr!@na_x7c_iU5_zWIY{Jx!Elj&1n^&0nL8gBPJ=hYW^UQZ9d z2Yy$%jqq%~^=SB$r<_#T+(YVoLAiYzO~g~FNz|WAxMCf`2!H6G+PS8!d*)ovoxUJ9 z5w!jtx1X8r(`oAbZP-S$6@knfOtHB96aN6CtQtw-HZ5~+4r_#%ldX6<4`TW;@VsQX z2-|(w?PeFzRmA2wc4wB?H0nroI!>nge@5P^uJa4$V;T#aBn>3!z0_sD3$qPboulwi z>>dMX{6*t-lNjGfc2j0+<1p=WWK+drs|q5ZBEb3}@qf}@--V}nnXY@jEGFwH)r_BH z^4vBer4cvA;|rYXk)a}sX|xlk6aN57WM2c;WrLx<9k|LW3PTZ&*-R~J7l#(m#W|G# z9Pd%H3s`(7xf#lQS#5?UwjQH?R?2dW%7sdTL)hAFq~gxpOmIKwmFHR2vo*lv0ZNbu z`9o=rC>%h?)#spFOT(7`0CuCpKJ)OK%h_>)%$#twa9I4ZzB$w>W9U7jg|!G4EqG(W zf@QtR$UGozZs)cieR+1#Z_g~jW4213UyY?+jx#Ly{Xb6j4?=wx3$HplEj*Xd9fjVX z!K1v*yUDkEvOA^OtY&$%IKhU&Q+C9Lu+$*B?sYh502`YKTCF=h)`=YRI0MCBi9E~2 z9^2&`dzN7>oV=!>?TFC zPQ}yBYhv4#Wwfx3s>Ztx0jO!TaR$qxW+bga;rqaUh`$hfErrZ*x%F+F*qW{nz}L>P z6`xBI+5VFcgm2PhxzOiugUFSe-U`e;PRPl8R{R-m&8qBu9fR5YHd~6sa8=DK>}@9H z&f#!x(=_;lC-neR9{>}DN z4UQPhE=QK+xI88*7zQDQh7dz{}(QRL#}lf^-?{;J-7FE`oYH+B0(l4M>ZH+0>n%yS&Nt|u>l&FWc! zrG{l#b9mlCXRmSvtt;mr!M@X1#(u=q0`0=)FCr~`6=VBW<@jOD?|)!GBmV#uaim9l zNea4Y)ZMuhvboLJ&E4gGBs@;zc1Oe3P%t?r*Jo8LWi6?LIC^<*U&F;!@1t+gBT@&&crmso?P-cMc!1YFQvHNNJmSP+0B*sKKx|h^Bvsm=EGp} zEvLZYO<+z?GJM|-(m)ldxvdSV8bFqwHi)}m%K5Y6W5dqU_-@{wWxJf~6fxLp6q%08 zvjX2o@$3WL!%nXWHh3Y;coq(6i4a$P?kC{w$@ewA?UmlX3&kcIGOM$g&rWd8!_o%5 zCpFBeM~~wU;SX!v34^YS5BOj*+>bNOH)FNARyPfc#8jo4WmS$J655A^3RP)>)|~-! z@7-E*-Jj87ODxZu53sNumq7R{@WZlxC-(0**}b*e>~2GV%JPAj(yM}X9y+y7A+)$j zs0acK={j{<4a_71)l;U*be1v=S+4EE5NrT>0U9#W#gL)o!Z?vRmrhZC$X>>E@W6 zW3vWim^@Hr3fvB3IP1JU#iT#g&_In>K>QrFakcyy?~aBi7hbbzV>5PA^tB840m~U- zJeSQq+ive@x1qOr7Q*bV3Z^GD&udV@VQChg0_T`D9b*h&m$>q49CXRm8xIi|{3s_w*= z*QtP_{yar@bNsb;0o)pclIEX-7kik^gYg@H$tyndfp%RbF|w7yT6Om`NSyJp^nA5)ecdJ4J@sQqfR&rpHGB()&`qh z1jsp`!b`ZC8?5mL{ie!t(T2!(g-WJu$G1v(i(CdRf_aw~)sOS0G*>@^i^G2CH^H4} z`@-I?dqW#XVV_45{hq|MQ^Puwm|om&Dxom?Ei~Re9h)un$pkd@QHN)}sg~XBZjXbP z!oF{u=a2DizcF3zc&UxZ&TR7P*qWwG^J>m{n2s(2?xpqtr2DGx7sB_9-w-=vns4W5 zGK{-oHa9H8WVCw6&G;7hJ~qQ;@tb3^xi$kh$gm!iVsk7W(qgMn zqv)6&Q;F@WKrL(&&=v8pGMk(aqh-zgRrOEc_YNKb_mt76#&&>+{{YeK{mRv+DoXb( zT9J$G_UV2K3^v4Pxt7drw$0VeaQSX7u3t`$)nZ=yn2|-slUmEHK+bbN;_{>7Hi-k9L zaweO|&30$t=-w{N_`YX|r|rJZ*4f5wjxT6im$9|RFjBAS2xrmYE(V|PihwL4#xJ3h<)QNfx! zM_#LVTHq>DackkVY0G$-cn)csu9x^FHot6kkA53th1xx|&-0u$4VZ08RI?n$wjqsi z#8dUdUg80ZOli*RrncWC*{_5v!Uh*N$SF{zw3v3BepJ%$TLqj^X>D8`Qa+73gN~V# z95pGskX*I!MCJ9c9w0Y?gRO$AhN*?w!A7Mj%`K@#&Bd@fn};Vfg3=E#wY;SVb(s~@ zG=GilwcG4BiT&v8z8i1$j-E?XIrI+8Tbtqr6w`egZZ!Q6cLxNYqY$vI&iGc}&i-;N zM$zu0VNP+DV6lG?tzG#1J{&T*V_sSXM*=`=ft@eaWF9)0TjJw+#DWOU*kI}X1vG9S z#{0w+0 z@g2FJ5cxLnH<7UTe5WJ8<@nq+O6<*W_=h$1DR8&crt(aZMT7+azCc00aq;!x3&d9a zckNqiH*K(u%r-=xYidb>#9&D=W!0Yu_lC{#_=(Im629rSYL075A)$_LHTAL7aNGu= zq-lUExDz6qrYGxMy}N&e&&7_>?+0aeUpm??ovnh-v%DS)6T^~IW5pVksj=at8yGHw z1$76)G2*v;-Ws#Lhs!rhndNvoS@jHMOmD|B_F_w&P1M69iXzT*!b`MsP3jer$l-0^ z_!aRXx}A&7cZ0Uu2Z6(6c{2rkZEAVG8nfxsFKc8mj^c5bjVG@qsJ3G{+HH%?@EcvR zdsZ?W+YDU%7BdZ)3_dRn#LgE%2Z^M$rh<1n~`dckL#j^z$*guaT=8;)}%$y`PM>)whO!`(du_7gqclo9^FU@jOJ=*}c2p zF3{~>Q$uF)c;{g;Sl8kx3W4+**B&t-jxz*xS>+!RzXdZ0Z{XJ`k~nX%PddQ;19j4V z7AyE*+ia5?y#D|Wo4d<$Tp6!ZCaIXw$VOjR5y8OvjA;$$>oJ}K8ywxVRZM$P} zUlWKv5w8$?-`KAb)izgm`}5CsTQ0$5xF^-i@OZkksW!XZ@?8xVCARey@wT;V=)G;YTONL7+m9X4GkVZD=8&*2aUbycs1MojoF+RhMknl^6cjeoEq7U zTs}clFL}ax2Z%2%0mF>4*NBzJ%%4QwFiW*3vi3q(jnc8r>NJmHmGlYCiqx-QgcGs= z8laFlAP*v(pdbl0D!o97zNn2Pr*3K5ESJoJiROX^p&gMC2vK_x6KO(cQ7sY9IiM6t zkaQAlWC3DG=X)XnfhIt*U=3z2uf&fr@lEyRqL0#%q1JmR0PC#BngntKqHCcRL1CkH z@1igDpod0;7@0sfCx%3FDl}V%J0=2Gm@#000Wb(bVU)oZQ8UOJ08`|lN6jecl*RkR zqn4-wQZW*oBG!dL81`Nxs$rvqddIp6Onz*M^X9Js#CH!oK=e|8G%6OJ!0HtJs2NG1 zg9O@E$?)d`di2Q>ej{2edJbz_vd+5MUL1t)U4gA1-W9JJ4_8Iu+COEVq4ah=`}IFl zUuV*D{J_a0)4NsYzz!_m1P}RYV(#Jm;mvxp_WuAs7{ceh+(1AYlQveZ*!Wt{bKyri z-Z-t3WriHwy@oNEjX$J6;+t(gmuBj(K0PZ|!tX;PuR^U_73k38ruICw?02d|ffocB zy0`Af#V%=<`W%yaO@3pA9-}jAZJPAQ`PTmcj1l?5{%i9o;}*?_bY6G!*Ma)`Z0EKo z-`nADEf%LpWSJgEviW5!muE7(K3##J0Bsr#f#&0@oz#;jn)UHXnU0IWmghNMd4Qvv zWZ8`jZVM1Nsn?+XCb)jX*x#zJ>7?C$Hhb=GwAbQ)MTX*nRIR(h+88GP0CEiXY4>f2 z$~J#3ua3pk#ZYjgMhmz>xxYospMeeRhTmZ^@u~V6b^1%FH`BLS{=n=lO`zGgVVjJn ziKR|!)AWoDalNEpMWBa@t?oc~q{!{eV2#K1m+E#j@zKNo0G5ngZ^ZmZ_JSKSShVqy zl9iU0wTym_-3XmtX zL|c@r+HGDjkIc_wuvU|wL{B5|-@H8A9M)#^aM?~CeR`E@wxi%g@U^=8!p-Yv+q2v* zS5pJCjisG!79yDrcMyAnxf-sIQLui1KfP)Vrry5rc9@(tZ?yIO2#_gZqKiBI80N6| zINa(Eu?pT~%yWIYdk~891EDigF9``i0UWmAD7JZs+HgSp1bDUAHip4*P?m7X< ztsI&KfL6IK;xVUHBf?G6C+|Gh+ouIiDlt|^=W5iIS-H*KvM>aC&<)q44L=pHX@-Lk zs2G@zdaqU(pNm)j07qH!_p4FlW;&i%M}1UIod;g%Cy2M+#TDcM z(J?0Rtbl+$P;{FGMq}a7N1Ac#7&nB4v;dTYMad^#s6lrJ%}5*HPM@(52o|{4x*7!V zi=VMVfB@=Gk^^jD>ZT+MTFN8RaEkzXBO(|P0P1<5Fh{Or#;K9?Z+@LpiPX&Kp+Gdr zaCE5)cSvh7$vdrB&A>=UbO{{wM0HRErf#B5(IOx!z|SO1rFoPKa!?LYF>sZM(GohV zzz*KjSlJ*EpzO224H3~Rlq+J5E1qaDPhAlpNHb*+2#80Klm|`7JK!4zfMVUbcBnH0~XR{L>VwryoeS{^Y}p1R03uR1uO)7 z=c-!RJL^NZTto-}+@jJ6KkQVx57u`eC#N*YfC&@SLO^jqkO%BeH3B$CTd0vQnBqhT z>VOD>F(tE0js}PZ^fhmrt7PKKrXb|+~lVs|cN)EkIX?6fw$)qES2C3?G zMy#$ib_u#>}iza&=FJF&s~)WE&WsEuw% znrBPMw4!!ELL-`N26g+{Au;O(HUbUChoW%@p7J=fOzR+dsLQMk=E_$*m3c51M0WE; z_D)t_Wds}D0UZjdU0sk+MddzliGcwjI+djqg~oaWYs<+9i!2}<(G$rUr>d>wQV>Cj zQl6Geg%NuNrJK7l0(6lmAsQWJI~`SS*?~fR&_`3*AUdo)3KL|(p0-HeSWZTrQGn;C zxfZZMjztp?QouFjjSLio^9U~NqST{=cL_;OPNh&s>p;EGP5LJzqM8CR9Q00X5q^l0 zIVS)zo`DnD6Kkgc9i=2jhy;xS5NNVQN;rF^^8w92G`)z?P(E@HMdbkXvJado#0okT z4P=|89SAyNsrIS^)xO07GIy1ockjK_b=)+=K{pi5Eo1zS}7lkOb<3#7G^rRJ=qkM2}Pn zQXDO_e>dW$1uNuG>LS}9VPo)zae0@2gD^x{eM6hs)|UTz{Af3adZ9co!f z_2uN8*Do9=`|gkZ@Vb|I6z~~kTo&18U^%%?4xph-pYg9C0|aYtd0e%X-#N;}{{X{i z5B~VozkE&O4Gga)z;O_2yt&b#4IjL(fwds&;^{-q=jt{cRYL(@qgq?914rli{y%85 zD%q}MSB|YxOih^HKn_4FeK&zorqME>;_13{i``X#0WtuPzTG$|M|LYDer~NvRhyjM z+bZL&R_B$MpII@WgPj37cy*p3d0H@=x$Mos zXu^VKTl<%X(hyHo@6JSgRs?#UeHFUbS*PryrEhJM4nL*Ks_BmbqIU0U{c_RrT`2}& z{#UZ*R_hYFcfd#oZ#Jv+j#*2FbpDf7^R~;j4u6;KkE{Kk{{T>@`Tor34C#aC9&f@8 zv6X-Cxh$Qn8O{reU}9;D0#DKkzI?(qpE?e3C*$>mkNU?Yk~Ey_0mB3NO*@b+>kg~k zfABve=cWE<{@={byh4cH78YjtZ7=)ITG_%zu(oH2V9~rxG!OinPnEu#^jgjHB3B)s z_IP?8ov-%Fo}g?@sO!tgGGwG3JeRQf!-*PQ1u%5DNS;9mM*O;#fUtWa^P*C zonatM`h>KNC1tCij+d{79wK}_VJqQl`dzHp;lk=9o;utj9MCnFumUGnG_GpP>-ro| z1|peh9-(Qs2_1SYt94t<&i6~TboPfT9-9SPDdreXRjKQ5)&}79TZekPoXGdBmJRIg zZlyd$Y+HRUGXT$2*MH|0jTuxOThCG7;!~H0Rdi~7T(o{q$o&;ac)b|crJYzSNqMEk z8Y-n4Pm#rLE817LXEQ8T&1aZA`z)tL*sKLlOGDCAmX}0aa|*{#7mUMKc3+Rf)T3UF zLduk?w6X0Yks5-k*2gq7L4#l}Z|q+|!OlCcG|!P5o03vlNq*+u+g}r#&D#8izR%{B zvfMTk7faDrsX~K;+{hBybBqHTLdyI<^@5&h952wKW^H+jzm2?EV?Pos7gwJvah*oun{FVsz3<@Ndt1)VAjvM`iX|#*WNo zPT;4)IDR)#w&NgvX#Cq~zAWKRw7ZrOeILBmo`>lu&ZZU~C69NNzJhxCn(H{t@j3Qy zj?ZzACbnaUeR`5K;xiu4*t{+rLs$@zcx(p5d1#R`P0p~tO-?EiP>zWFjY^KJoaFOt z9VDG~g%~q)01bMl$bd&%q+DlBO_r?837|!ta&%0Oa)=TMB7JR9V048T8AzsF5ELl9 zxh1Wm+L4+&l|wwuCzO{{KByUZ@rJ8ElTYrWO6ufvKW zkEE~-Yq+FUJtKv3tp_ONZVuX;KgM^4e-RsR;$wI_PqEvY+C1kb&2v09Ckc(iPzIHD zGYL(kw8)Xf91k%IOt-<`it<4o9yYLZF-U(Gn(4Y<3~uoxwzr4OppbtzIjTO|Ytr9_ zH*a-shpeth=bcpl0P5E`&a@Sh4Mmuj!S%ZA?{~g2@_n7(KEva7b3A56jK^g7EX|&c z{+O^dJ%PsL({3Y%1&dwM+biKk+5Z3#InMJk=Ve(&)Z?}emPt*x2ITC-zX$RE07&y& z;}qygH6w$BxC;RXRmhv_@lCh8^=^bT~7myHBJ(x35tz-nk-A4 zOJWFd1Q9E!b|>L{-ab#1VY2OYEGiYQl(e&j;0$? z&MzZYfC-WX+u?-6@NZ{!j%!E`$g#|uMe$7K?N~O}d?y>++WqG2rrYB7O96w~{glUi zpf+OMoptY}oH=`k3Hmlko$8X5yl%SzQgEBsmQ4~osJ*}bIBwi5}n-#4(8u(avn zu}`jQijQl{oLtcyCA^i4Cg;4%bd`;*@KWzhn+w0JM(;7$vrhrHd1J8j!-x$S>^B`s zM)s3T)@am{LhjAZczva~{q}FqeA(R`4htmOd{sPtTZwCj6)Yd4b|)NO2hbjw#?hrP zdM}ZF9dJ8UneV@M_$}K$wOym9w0J7mI+SUbdH^al)hajuPorx%i=7Y~GihH`z7xIg zehvIQSJ-T)Hf9q#-UVl6OeNv27zQ*y7~yRT18E=nq_j-mcc~ zH#L6+U9HS<7>YFA>pG4YLvZv=@@pAQm*{%0sNNrOS$~VKgW|5}vYhUQ4{0*oi{{QD zuXH~Pio;(B`hliH9@bJbp#}Qz!ubop&{}D-16mq6Td$hW_cy-{-vN_}SS3TXX)L}Cm z4M4}?=xqILP^jQFrB#i4Dzw0d2M||5ZvOz_)Zf0*ZqpUK&AZzimv^DGt72;4GrSv_ zT9y`*IL&&_r5=T(G|Nw{13>u6DztOZcv#2Bjx&Hu& z^0kYRm;4n)v^-qksZpvb)2Xu=jZQEC2aD0na|6``PgQ;RS(s^fromOP6*e;q+DOD# z_pWmA$G_~~!!Gow??)@yYCA<%mS2g>{v}@+>^pdB@WZ&nU8exF6?5@L;#W2CN4(lQ z#?7`mhR#&OWc2ce;b`MdBs?~w-^avS(|$c7EVsD(Tksdi)XlhpG(-|$1FDN08>^)C zQVxS6LF9UOUZj=G8$-j!;5N&|HuEqWzu7Jt4|4`DGsjeC6+Ev8Ee5-VrR1I#H}r^@ z5=Yg&u-VO}@NKw!F7Lc3?o&0|{i4Q)#wnCrQH-s_>*I0HC8n)M6YA3zTZzZJ4e@_M_c#zkUBn&4WLn@A(k}R9w}9wq+y+De z0Q%YWU;e3h>cXVuq0uysVcPEv9y2z}XtN!u+bzv))@z#PmCh?0i^O5W>ei}xk_oWT zG*}A&7Ps3?)o)XFxSS3PcpJRV_IDAP@q9{_XM=SEhz%_dG|Bp0CC!)?kh__`436*z z(%cS0KA*wo+7gqs~!PL93_368X?T|=tksysh8tS^s!v6rm zHMQOxcW;W_mMdUz+gF$2YS+YMRo|E#EAURL;`dUkEq|n^#`ic!3x^YgkrB&#!Q1_z z-gemMdwI1d4O2GS49d1^jjKYB14UYq3}7U~8X=%wz+A1#X3uX2)xtKVPgf0{Qf`1~(ORFY-OZ#ru6OY*zl>*z9qr?{t&Q1Q zTR&GDmtk`AgQtx+kUa<^kBqUJgVNBowq2NGvW!(6$1B9u!eg+N>0{cHx#?Zn!!;Y&dy0to$8`J{&bJLBh4cq?!g!eGs z#_021)9)K_cr3z}b(I_rFCT}`3lGLP2L>gS-9+#f)eWi#5rWVqat`meg|>UE+RUeK zwi`REmF)&hXAg^{ID?u*8g*E0QG`oe(;^7y2+D-zPjW*erM!LkUf%A{@BaX7_WKL5 zS;l9xTUnVmH^AnZW)7w*lQ`JXQjKQQ1k-qT6i9*qAen*EKL#I$y|UdFX_;?Nc{pd} z8J5^(Ov|!-hZX~IpA@87R<0tWHE1W%fYLac47d&^g@k1v40hPzvUXv1i*Y$-H#DZe z9f`qbPNRpY=n~;g^xo!!dvO(~a!-VJd$=9?;`imB?4C`Y)v1%eBg=9};;LcrxkehL zW>u(Z5hc|eX*Y@Pl4pCf%(jM(&t`bHW>|c>fv;Yb zD%9D){{TkNT;|O((pn601ETpQfyd@KP9rSG<@l=Dd~RGRx|Smj{u-1kG5kz>95gK; z863jzo!k5`8_U`KoxEPmk?(jBysuYiZ*zn`HzL6i>01nbD@y@amJg?8cb&it-~_z0OIZ)Nw+1M z_`C77o%poC?7mx=Zqo^})V6OEUlc1+%?>H`jaIN0$D?lu1+zT;h~qg)NuhL=j`#RA z=?C~C!GUHVYKXhkN7&U z<=zAGriuDF==ayJ``5-CB?8lisEG7W|pAyFrP=;jo)|lYEy#wL%&OK8;gSg(nhqdrfAv zb90zEs(X$2M7E!C`-!Evj27rJ+~WyCjy{OY>Sphv_xxq`9$abqH$)n-99IL9CqwQl!LI(d-L&{jpDo#q zq1k+ik8jF5L7rji)577K7ZmB#Z8ukZhz)Gq+_YV8J=FXwo9)flCd- z%2|lSoEACEYys(9*144oPpnwi6LLvdUH&0=e?`aH)o#=9K) zB*(1Ud=%J7GxURpR+SWLMOwvH*5^I=sqp^*nRsd242xm&t?J;mpEAW@YGxRWHV+L} znak;Ma8u$BsQC1uq`={@(1?UY(@cU7_0?`yaJ?U!G#~toJppaTxr=7gLU< zXTT9BkkA1D000007lDpCFHJP!tYN#njnUy>eieK_Z?9&zmPKm0eg?Hn7IR9RxzEb+ z01B>aLG_(Yz*Ga9gICh;8(tTwc)i$dp5D&pvrM-gwAo$--w>MZ_^x-BRvdnV(`X1K z&ZbEXmp!iGnI9Y3h>u~w)b}%TZ7*o__C@wMSPxxaggNoMLM|FSFcZkrY8{g$Y%>2 z<~Ed)3yC}=0BmjeW$;xp??sOA^O)1e29iAv(9<-%AQm9HfOJgQh0pu`_(}KezYLP5 z$>el!n+1_#shU{oIaVe0G1$s(06CAu5I7odA&qR@5~0)nlrdDH%&$<@564wwrtP1}hYJx(d9R_KFEX9#<9seZE%44UY{dFJ z5a7t4=Zp z`Ib|F+nt-hv{S-ivkLB^jlohHQl*FhhcF2Z4{L}J0RRA#q|#OjMy1%#41OT@ueJ`^ z47XyowfO8#C(&YYS&bDnQV>}itWhq zoR

I)fS}=@B78@g&Y-CUm-R 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%0D13?Mjy4+%O!E4DC)0f)t9 zIEt=lk?5Z0uvBmam?6Z*g>hGmZwT4%h26Np;P9EABRSbz{8g)zW|i9&Sn67W94tqm^I$C9SZ-P$% z`y;$vgQdUC{N{CVn<9X*}!A|2;+}C z65Ow12z6#s_}xr4Fwx?W&;~GwXrIpG;juEb>!p%IboqN$jY<_g6=oJZ-+{zQ9eb^# z;g58=Ci{2kvOBKYe9s$~Wt%};6HgIe0_ttVH__02R)+dOKrSo;Lt?dwHoU$-?NVW^?zCPYN3k;bUpGGbq@7 zqRw+HHqqg+HE~BatwqjbsZ^%cmU=ce#5|KDQDez#zY1IAq2cd*nO5?%Et##H;4s*F z_#8tp#lDD#JyK+&C#$xD) z;l)O}uk<7bL%2ScoR`m?#O~j5d&u$CTX%V8Q-aR7ZI8_Jft6vIimqr@!cxPz^jyct zsA0_pOQynCIMv>RQZ>8eFCQK(HdDn0ce2M~Hg7e{a($S?V!_1bjHgb%D!wSvC5>Yo z_+terlIbPdSWhN~9w624ywroiL^u|b z2NQ^J1+m1sLU4pGj6B_rCpB6c_i?Zaa33#d;hiK(fqdvku*&+unC!2?OS@g6tGis+ zBH3E_=Hk97i^Nno+{cP z?(P139NrypJ7JM+eR}y;?e}Mr;3_|8s?){2m2tR_N<9rQ`p$D`jsQV(W$v&IB*@dR zxa`ZjbLEXDx}`H#kmIHt7+%r~LysvO`zoyj>NHCQd>0&Mk=fmn<7;Qt*;=2QZAC7l>RZ=nHz&H>>%zF)c0YKSmTXJ%>KSp` zFOJakucJ<@3tVfF=!q_9ZjoqQygm*u2{jz*$HcyL9l$8Koc{m>92)>Z^+!?3Vm9Ji znPdDw{1%mkLi~edT;K$QvQ^x9f0?)TFPoktbA8=sTkhKY-*nh)zJ|wQvmkP2;Bc?Q zQ1k+oFnB3A2Q$|WkpkyHy3fT&!TGt}$@qWIx4*GF!`htZ5tp|MQvmAN$`vq`1zbfM zWVy^>E(Nb77Q0y0bC-k-sqp)=d*Z}qJ|u8CZZ~BPQHrBRmOCw}j-=ditxVEBj+k){ z;PjB<*!P9$rD&%#?q$9Qd3+jphcm%8)|a%!Jlj0yr}9=Fetj3pJ)7DL%Vx8Tn`yFV z(`I9nRm0|ZV)mCcwW!wgw9A?H9?*9OAxE-F^ou?YFilA58+$!XPsm4Sq??9+aZq4akYIN8aRBX7W$Zn zx!$8GuvV861-#dJ?vr^t^VtpAVz-^+BWN~1W$Bs?tTNmd7|?EAPHyZ?cT}hyQNVyH zQx-OtIKaAYE5a7(yf$SOAG_V1qmSBCMa=nYHhki1n?no3PoZS~Z8nM2g1M{24}sqo zz9e>-=KI6nmc`J^XcFuOM}x!S#s>#`I52_6@X`T$q?_n0vfL!>vMI@)I=ow9JW_4G zRLz^oU4hwsmTn=Lb$m@Q++I4RUI6;l0QwAuG%=ciB;3H&JAvM&@^?YJY%b95n-PJb zw0WH)kzt>W!-~uw8mmpVYpfl_8wAV%Y;;{!nfwtu+{?1uW@_#3Y^_6wqf-!R)64M% z&n<5dZ?+_t7;N_8G<0 ztXsh_C9D%5%muZ)LuA{I-cOBvjM)wQXPA5*O|v^EQ#s4<$acRGQ0$fm6-}Y14$5AQ*f((i9qA}=)Zqi^ zdS1b2J4@pO!rt5MZZC5?MYXN1vKX8`J1@*XE-7G|X*Gd@m0UZx-$tW&+8QnD_W@zJ zJmcV@+5FEe%rF_IQGv(hhM&Z76#iGIR*Qjam|FM*YTNfcN|KiIZc8zt!yYm`Fz22c z_p4teqlK+oWiyvQ7qghs31`LluZ458^t5C&j&0y~=R(kp;*%|OXl!MDqp7_Q3LZ3e ze{1(2iq2_cvTdBBhN* z-uBpK_??i*okoVuW;u>%GRNa*5mkb);d^+?n95|%oI=-LnplRTY49-PeGQA?!{H10 zv68cMJ|S`L#$;y<{5D&kW4Nk{RLcWK8yHA&bvUzL0Ws>jMaGG5i9xtu5u0aX2=umT@Ij=2oYuY3mY6|&zxoop3+CAv(7D2SQ3VDuMnQb0fg~wrP zmj>b})vne(jx8X7TWcBBVk$FkOG3A8PL#y_D?Tt=K8c&ZAVd~rZX}C!#4hH?_>bOa z`=8XjN8zjGOxsGEKSMKf+k$hjg0ry=Vf=|R94AgKR~LLJJ|1@~xa>~A)!k0R;P!5& zXHPQt=)=^iSy)pP%`$x>odu+w0Mt&4qAO)vQ?-8u9#4^Mu1Ss0^L%E?U};dnVDPTQ zR;~Q0oLnq#(jlS8OGL*t&8W1R7iTWe_*wi_P_0^(N?QY6l0^_qe&ldrHkS4-b3z$|&PA499ZYbA`fT{VpQ4df5&k zjHO9{xzBrxA)q!%B-jG5T1Bs5drX2XSFW5QpV2WXHchQPlz{4iCz6m0vbmp78mHb< zAvli4%Xz6{dD0V78-gvEv7`c~kKL zj*7UNo~|B%>i3&_1e3@W;MrASO9L6r*?;W%TVjms?J3iyuG?R-F|S1cIm9#{f4ObV z+W3FkovC9pTpO3)@tVy1 zg$I9{rg@Ljbe^0mWIVc|E_o%#n)w??`$4^Wcy7PY{SL|g%5K`OGpF@5_VjiiW%eU- zx&8xY@}|%aZX43papJ92!m}>-o1Y%p- zBGDBYZj0!DXX?tP9#g39@BI&#{i~xISg1mjY?M}>tYE+z8%>gMb4~4gBpkvCZAL&E zPwY#LpvN07zU|TZjn+yCmJb)`Ls~U=T z(5s-a1F2Oo*nCDe5k~`ppz7G1L&YjI+S|S4h+f=-Wp3vXp3Lli$nGC18)>&#>NxEFr6)HFhNR$4Hxcw{j%N3H(~|JwvCyEmVVvHHA5R0b zDq^1fPoqt1C!terE708D<#782hIKb)+2aq!OI|~o_fMpBYCs;S<)=cq$*gTQHG=VJ zSIx89{M&9eg1*sa&fs-Z!$yNi;Gs{G8~4>&3DO%8tbMC{I}0p5Hs|e2HchRLjxMTH zvV>Km>Hh$+z_k0ICi07{>FKqpme9C^>Bbl^}!w^5t z73RA1W;e_+5KMYPyz5Z*QJRf8v){Aj&Cc*;nu@Jnov{RMJ~$nCn>U}$3(d2jocjbO zKPua=PS}v`r^gWk)^42a7Z>&G(DW~|zhC58(I^5!2P;^v=a%4vaK|sL9>RlA<_cq? zBx%(iNuUBWl(giX?POU10|+;=BqU040FHJ-Xaxv@0yRO-@oK!7l1)&{{BD1uCI`kulXiR!KXcxQx!I9`496HBVFoZOEo206|S2qTq|f zAt-i;yv2v9m`Axi64e_5x{=W&jFYEzK;lfoY9e%vbWVEmPz@s-)8v#Mu%{3NheYWq z5@el3>tw*_E}}>`<}|v|G8}*a2IPZpu}De2kf7oXjjlb3fdbZ7&=Tc;VmY8*QK7P2 zi4K0WbFv3ibFf9`8sHNGVJ&o&&Zz(u_ywTTAf+*6?o<{Z4f;xOIS`^XPm7cw9Kk)% zERd7V$-yI73h0Hi0%A|ngf=*=dGbgDJo;Hmn?WtHSO+ijBgFSC45(zf6C6Es*@+g~#9@y0)G>|W(DKxd$j>u3E5<2RHL}*hA5D^G4 zl7&Oj0y&`;gaPJIfyowEL0}}15o2zA(PPgd3A($=z%>D z0toJnQV>$*96^$SsyU<8i6sCKG$>JmgFMVCkQy&A1fWD(EQpaDypxCkCz$Gyonu0R zNfw)%sb53ngs`B20uM3dn2EXs`w${~DSV0?IuL>kC#BJTh(TQ!>B#^dYDZBhE<_G! zl9@NvFJb`+PW;g^VWM)3AsOajKywiXspzCh7DSPziI@Tm=mFI(a}pz}XItGO0q$ZF z;n;BieW^hm)9)GxuugduQA7fL(v(L~g2S=qp9s}P-1ScJWd>mYB!qdPKp{O)fWPc4 zjiILwgXrG|dn-O@3v*0hag*ua&Uvf8!`o;n_onq|%*^JP%iPy};yJDn`$P0SQu{Q0 zS?7i5%j9F|7VE|P7o17ZS$ZLy=UW{IGnq#T@99}k~*{N*6K5?q^x^lCObZ4no zr*%0ebb0Yreld!zhyv9rIpfHgOAbFTPGCcZzG|2^l~RZFtdkzFy6+u z_}xRUpJMY#jTL-rxUp3aarP<%^;S7W5?RTF#rdF?$$_c&Bg}i#1Pek7h+j~g2m&uU zq!+SjNsj-+6Kczjt>su$dN7|X<8U-ZcAr)ciL)OJG{IdEKNqT zhHXXI7rDd+weu_|+iz<5yH*aa4r)F}*w{5=M`%)%^uO|nn ze@Ir>@cMUAnqaZ}6}CAgBbw&kk*&pI91CmHFj~rPH>T#n`Y=kcc!Swm`!&4Gb|6sT z!siiQZM@$h`9_=Jt5}Ygk&}Mk`n5eSX(v?Bwy- zcfC1#F@JUOzo!Gsy$$2%o6g!7=J}(I93>)Kg24moP-jv(xbrIv^iHTtS}sHnGC&_$ zUZ-4HWjm?Z{7%|!-dUB?r1#LJS-7lIfq=?PA=mRD1@`3%SR6Z1$}vag<0{)n7Mz{s zCT&j@Wus;G5{*O0UYjZjCJzszWY05ks^>1ZkYR-v5M&yz zAd&1GA!)EJC3!YPTrjb6)95jF&UR(0y0sxX>8F@94F+P*+teBRj0m_ZyyX zuLHHUGCjiPyGw-HZ2JsodJK-KZCp(@mX`7I4Qs9*OfboA@?gO<#Dl^kmwZxqu<<=td;3eWIp)~syCBS$H^ktEPnF`Gm*MdEX1oef z=;75km>TXk5)Tx%0SnIMDNU%GvP(1Q7l024`^fOekJ|jhZT6ok%qeXJJUuEDFfOZ9 z@z5`tj&)WxWwihVcU%eMFBy*6PZ}G@&hjBfo?(~gSX|=+Qk!H`#ZjS05FSZ3Fe;mB zO6$*pw;_n|9v^BCU^_Xf|An88uCyA>%W>NLa9?|&NX%e+PS5X*PRvvgaGt&~&Cwz{9A zAbK|a3|kC-iz?LwPx!veoxTc<(PA?V^=%g4<}_Sz8y}Wb!(gfkjdKn&8sa1k2^e~A z1`LicwtvBiwpo7lw-dL%8TPLc>G1heE78MJv)t^r9?Fbx1kcf{=?ugJQL8NQ^^s=2 z47?8Q&fRTZRZ}b4R$?ex5^NRSfvRg@8XEx_6+gw9xW3l-zV}#9U zkV$oV^f3&s`v{j*A>&JuzPtF^*)6l*?}se6cpHb>4C=Nbl?qw*5}r|*RigY}4y7{Z zG&Y$6qrDsWgGsZg#1dfctXy1CBJXpO-S9c@P`Z;Hz1^2&`pd=>^;8R z_TS<>4(I!z-i~>K+FbiB*{nqqnPEjhD~uxzY&A!5g6=RWQfr92ohO-J9iO%P(hp&N z@b;IOhi6r|+fbjO!^JajBdXqc=Y}5_8$Y=0ZvFQAZ1bFlXE4}mb?aq$rhAL0m{y@t z^y#MQ^&KuJ=ax8n-{`eiBr<=Hmaco^Ajlg)5VuYk=k znZ8$;VZ(^@t*MK|wyOySK`nGmjn^l5pZG$zjj{W2j@=K3Tt;89+as{g`3{yMmIjSl z)$3u1W7$j62Qr-&7H|LrkkU!@fE!!jmftp0o^IPe+_ogqrJL;5Wm`AHQEOZsUjvDF zbDz`Ht;7xVsLrc~JY8;YX!ldUeXZI2W?m>$$LAQl*C=Tu9Cia0QPru{rsrCrY`UAk z^_p3s7hXDWi>TDjjoD;&*MSco8)?1Gx5MsVeKl~Iwl6oMSmk-kF!b>6t5vkiorlCz z5XVh6ytT~&;DQR~&xC7mn=`pB_tM2|Z5%!iB-;!vOxq2Y(QgRBS8Yxj^w_=n|b0_XEWSBSnN($vDKZM=D2|83V2cIoZ1X8ZMfY~k5+C2j)1MH z@V9O5Q=4y7Wp*nrtB0+L*{q_zBQoG?n^v7%T}JvkPdvzFFzD#;wPjAVqD)?m!X0-b&B+Md8aFIt^^Qn2wsS|Z#~^i zyW27(%&(xo1NkF)o5%&?K1R!}GIcBGxO+&R%jhq`0sjEmJ9ykJG4eKEFJdlMF+WyV zYGpeey{7J~;XU3CM~tgW4U+A~YeOc-7u9HB#ZEX|-^_Wohtc^)>$hhb%Q82_68m-ST7TF`53>QaQF6kE}zTR}uvbxsY!FI-OG3 zk;d{CNAPG-t6#zn(qgK;_3C1_gFdSF)OQ=6??%R#INC|!l6$RD@T+et0fEJAABSz6 zrACHblhdW1QmO^g{Edi%8$X1vRfgv{wT8dZB`1N zCaztPVsl)ko7x`HjHgkdui@tAweN5sOGpk7S_<8N37-A;@4Ic`VfT5m`$wB>?#*K| z8aSLKT)4LhS09OU_-hl0Y2yNzV+RXkUg30<-u~(*0$vmT53TlYM}CEl2WcUs292A-cm{ zZ2+vt;dk_m-nQ>t;Y>5;)@0E$#A2!G(pFW~OERaC)ti*sT+3qq4g9leG8|CCW?4q> zF`0%F5Ew|MTAeEHrt#c52<{igoPIg@(s3Ao+W3rEZZ8vxulZ{A>pDxG>W`ChW(0SW zb@lUM9`E-rnkg2tH(ib%r~O4)f>&&lXVWi%&CNNM_#4Ix zOY(nGbf1jG0p_}Yc778!b9bBQ-VcbJ{+%5E0BSaeH^yceMLHA*^L7=$O*&!Lb$WmR zUuX~oi;3kAfzuipoNsM{?kvh5>JSZ^Us*qUr?ehCHs^ExH}=CS+uZ)HKX+Jc+-&_! z8$)<*5^Nht#PMNrCFLM?`!OTP1?cH<`BEX^VSmVzNw&4Ti#wAPWvI zwMSGj8j*)+p69C0z7ih{SZ(3#z8}Q~>9Dl1*sK-?om}OZ0mjVBD=n5|8NxkhQ)!ZQ zH1GL>bq~Qgyu71lciEckRxQ|kJNCCB7+gLf*n-1b7lo?otftn@%c#_-K-Bs(&2^LB zrD&0AZ?6^7&jZ=BHuj@pZH^TUjv5THo|Q+95)6l zFv+pFYSjw|uFO4FI+!-R8iZYRcZ9}N!~7i>H#k!qdnuh7V7;w2_|@RaKGpMg#SZ5; zv$-9w!EAo_w#t@!n_@5(ahOgF>k*F>FvaDZP8EPOxSYcSm|sgg7+`B=-v_1_3xTB5 zQoco<;alkDqpDQn#WW9E%`)IE%}Fak6+F+26lnpLvCRRbVOZe+YF!he`%&w8SUVx#^?!S-qRY0odV>o^KNr(cNw>s?cHtGQ&TO)<&__Y!&RyaXydTK=h5P5 zxY_jF(hQ9Zg9H#ebKs@i9@TvP#&6p>$uSr`p21|ba=fDvh@|Em!xLTYH7d~tIH@(P zE#lCZz$Akjsk-5iigz{t0Kze|xDB82vrjO~snVu1{60aNVp~ctTw;X>Jb)rdqS^k{ z*uM(3LVPFEHzAu(loEP=QR|63e(mN>w%#?dRPxu;sY_-mW*QJ3kY4c@TM@;@SIN=rNgwDLx?5;{IiF%RmtSyX&*N{KW9E9K5=9ABg39|wRlX^ zHK^Q1KMRsq^h_;doYq&Y=R+y9agoGGi3@e*e+BP~yz>yu*EiZNp3AWrg-V%*G~#oo z)T`+Y-0F{|MchTkZ^Tzjd>Ao9%8zls2Z)V>6t>mSa%2h}Nq}k3mfFN2nVX zADvO%O#JxXzl*OEdFI#VR5pitn_ZOFrBbaNW?O~Dzb>JIad~T~Hia?>4FC^Y*0Gzd zsY%JGlF4d)VDKa1hip7A>~7KIJ7Kh0R%>5B%<1M7j$X>Gr%X1BSm1ptK_r+m2Svkv z8Fm9E+AoA&z5^G7qA)u-p6wob%0q;-)x%=34Wj7%N4<_8=!Mk(00q9y?>8je_Ib2B z$2rqkwArgMnLRw$6;`cNf@LPKRcmT`&12k84xB-=%oE2ug5HK-yI+JZu6dkdTTcO+ zZHCe8-Y&go@UoA_u~h{kdJjtKb3CrG8{S2_GjD~5d3m01z3rCW!zu>lc@{{_?etqz z7SzVqs_-f~fRNxR(`anmalfkJ{GU3`HhVh3Z5~CL;xHMeU5Rcl35&zjEU8AbPY`=Z zxVZhAFQNYc3l`+_3YqTCZ|5w^pI0myYqonk#nPhZ3>8MyH87Rx$I+(Z_tGvR0pZk; zxIcB|a|p>vJ1tw7wVc zo0r`V(_uDq7l_F48A!+CeJK<$Vw(kK4@72O!du&jmGcwDr-OXM!lql1{I$JIyJ+#7 zMTo6O3zp&X*Ws!PRH=tLxhA0np~bD`^t{*5jqGJRN#cjV{!^T8e?HA9=da2zInD~6 zQ;mHJ*qZouMQj;!93;9bGAHS_n7ZLn#oKd3QNI(Es(cRH&|@hwj`ucTHl;@}50h~M zDeEp1cmqQw_R)6M;5MKrD8gc}jjO({~K_V;RVxQZ@wD`D|Dwk4HlRG2Jt2@Vbx5N@~b!}wS6gSC67 z#_yzW4>#F-hXsVKj&I8u<~I#iz7~})NNcx;Mi3#T+&o0uLe%2dw8)>5Igc~K)XVW_ z0a5%_FvH^23>&(WjWTckg7Swr1za|*R<^Do+;tu}oavJ$_a{?(q-c|6=}Dw>x!2zY z7WZiG`@}6Rmdx=F8Gha1&Q4lx#^dP&TL$tpk{e!-nIyO@hv8z~%XVLVnO^bm)T%ay z+ht(l31NYa!4}eVnBfya)I9h~wdjy; zM7o~^u0zP?zQ*tGbGc8AEy(WoI@!z)TULfMG0F4x*R1o#GTOp%w8co_}iXJplOs~?7_9Ol==VuWD_3xI1C^VT@7f?D!t;XtbM=)1m{45*H!tBn( zY*yj&CQ!rE%uR}T1I+x(+;yZ7Dx+~=5vQ^MtY zQG|9Vz1$+68nY@|xGv*kM|zlTQzZ#8jn+qf8qyjblZGNit<_FM}?%O8zf$9yf`nvze_i3~N9Ef*=4o zu6N#jel5P*M;3s7UdCTH4o>EFwXP(F?Oj&4)fW7PAHT6^zlF+9 z{{Z$izyAPb;s%lb00_jb?eIc__#4{cr}tN1-{`0=FX~aOu6)JYSDM?%+GAD3@$GIg z#y}*Ki>Whj)@u5n@KVp>otnM%9O3fzVXRHC^k?l~EOyPlk9oUF*BB#fao<)keOUM@ zDVF$6&A3Izf0*hy{9cOPW%LsZQ;@z7&5Xe9SBxB~xt$VQkk{Hw@{?RddUigY79JC+ zYv05=7K6!V9}7nCbIiki8#%isV;xT?+5DECYw=*|Yw?xpJbG6)V3AIn0G&9U8mtSz z_VMz~-*~skahbhpEW+pcrg^iqu~oLLvX>A8AKYj-2VVd;|+V5A_Vb+HX(MLsova3 zu32|Iy1y8^``FiPHtjPVq^+Y8xw=2j(_E7iuG$60yub~v;>$YADxuM z#t#7C*3`tbAEZHp#6gZS<6$f0qc^$YH+p+Rg~)RKDZZ_r+D(o4JGP%@HqReZ z8=qyH5^&j_dYF@lbMYWIj%pvJ1jO_MRr8;~C0-8}8@Xo*aBg>s2VGs2)*QT&59mmb zRB!(Ph4@o`@wZG|1Bc1kjI@A39-fVjmWcQ|>Ob+p-P3_LW^4`MALNxkdf$Hx9UM(9 zv)x8(h@kp8doX#O2V)+?=-X7jlYgJs)mD+B2j~z!^{7#-rlfD<=DsP8j=$3~U>~=T-ulym$PhnkSoih*PBfv1B zu{dlNCpXSEZw|~p9-s~sb4(`*b{|+{y)7585^Np`v@TECjr1w;rmY4&$A*(60t<^l zbId_=iPWBcYwHKWHMQBU((a#ZwhuSOSH)%fHJM?Zms5K^Og(3vo4x&jA}8m5N&f)#Y+p-07s183O^R`7pPfVkb^iCPtz4?B2tBQ%OTXOB+CUrV+})hoaMuAcf0h|Kuaj7O-!g6roMxEtSwPeU zxXPj)8X$;uy`2};ZwJ-E_%rsOhk$=``%c#Zb1{tl>*T&2#Nk=qgNOQ(ymWo3Tvrtfnz>ba_>3Im zGhankm0CnJwd@RWY}}5b{S>6)lX491PZIct4}#Yt9CPV5Yi8TTbu#)M{{W&F$;wq9 zOA^}5bUl?go98R*e~sOn#qQtW>A-9zcT$V99IFqr*)>x|<<#F^l}cganIIPrQO7}H zE9A~ul;)YvV^1u}^1N(;3n@Ufti7xybeB*e2mv3wboh9AL3(UUGM z&2zFKaT{UUZ*}sLwQNom*;QOC>rlkf%ji|5QI6rMN$q={*EPUPVkSlOUtYcsJ=bps zWjrJ82FC4f%Vs+_oaWh{ZSh<#X+ijUjuo)%WjckVaRwJpAZ)q6Ydj0?@527h>>lzw zMr{@=Xma|yL4(QmlPbzMnT4Z;bqc&Mr%>?Ks2NeMbwJQKm|Oq{UU8a?oyyim>i9f! z4fyAKEwmf{--h#ciyN}z3096(M>xm1_2Ufc!0(=f}31yVxc^i!|-9ejji7f z&~IaZyGfhlDC~ASF{Ost+`6_ej*bflLZ2I|dOaBDQ#4-a=I0fsx6{AeUyIyETj4js z-d-u}<$5%koM)}VI}L)Pm(zG}qNE|Fo*V(|aR&NGZ8ifgoP)+D@OCr7=Z0Lb!w&2* z?xmgQnR&z1c(qzMCp-COHldkos*_QTAFS>hFfL7RJhf#^%e)Y8M?2nT;zR-_*4ZNCU-stMBEmRGx+ z>nz_-!GpA0H=p9gJVwgpc+9=ED&hq{M_&T}0E}UnT;gHHf|Fp}$pezcGhOg*d&CEY zjm+*>9kdM1w)VDbl4X=KTqY_103E~Br%=$XR<{cX4H$WJ9YeL&3AFtQsdV1f>i0>p zKL-xW=lSlzWz0P$=4tu>5Um?VT8duC(c-oDtRrD*= zrYi!lFb4@LBc;cwnP3k_R$`){Cf^eiKD78Q#nflPskSiYF#K0)Lm`$V(yDncn;U_1o4$SC zhqib&qa`kM+xz9K=}&-suQJ+?gY#(iPbtHCY{NJ^M}oo9bImbUy+#^rZyB(cJY92U z@jM>T@THvif6Q}DrG8dihpMOFG2t_Re9R%nl;G zN-e9!iS%YjYlwjPu;jFd!z}i?zU~<2U(jYycnqJ);raAg-qq6-J_r22g_M{dve|r> zGUjoNxC5Sx3eF1VnWgs6;cDBBu-M%5WF5I2n+DwLF2!Z8ukzd8X*RVdQ!d~%#F585 zC!`g@beZVb+Fyodl|>8Suv zS6kS~h((cfpbb^M$~Xq{lmJj5=#5rgfVJj{o=AXzdX&CEBu`)a#raUz=)el z6Q8L~UCE&C3_>LrK1qNCCB?{r*&a#EXqLRJg5tV~E(5xhTHy!nL~e4 z7!nV~YH~f6wZ4XIL@kx!#!mL|azy-AqVVk>vro|aTOt1dou}$xyHp9rtbTYYAW(noQ`A#shUQz&AaI9=H5nhrj6Ro45VCt|=Rz!_5Bx#pr3*Mb4y|7e4g3 z?*y4YtiH#CVYpwbKRf;6#(&53ujq6O_xHN->y6G}i4*=Jh>L6VRDT#f+_BAW6LeT6 zyfj0_8X$u_p{t*`taZAc6gbxeNF*4AUdO|w$Ey+k&|@1~ewFknA#$)EwrYE0KS%`@y{^DO5ut&PQ0H>p|E?&!R)1U!goZxK3bqGXUwr$y?+ z;Hcrgt~NYay`_o9Wm;{oE*%L2CP4us06^4h-4i278hNG!kFk4nK6StX4B8j3C~p>F zNJn0Mmy@NTdh(KfKT6~YJi9DU*=FhGG%RsH9j`j^mFI=%%micc0wdQdgex54jLrQf zdvX%toZ!n_C(^e?>Du$fwAk3W4sT!49aonmBjs!yk^rjNjaRE{2>Hj2A|SYOjzMy_ z_{-4rC;nObmYeAb0%uP&$}cOvr0^<>Vy#kSRG*n#co>YkFrvU7m><3 zsR1_xkF74Rm>4F&=z=dNRUsfrj?j?S_SB*y6cBX!k`f1QN#93%5E^8=pj!0=M-+>T zngApoZ;r@)L?2$V@jnijx_1r{O@ zN(3S=s$c+RAv1L03u^)mwYmsMNhkml2-Xm0(14f7XadOOh)qpE4(Nml=ASimAPz~) zXc1&In=EU-Vt=+(bj*x@^NzVc(M?D_Q%GGk3Kryn z+#xMt2s?y%paeivpn!l8?NFKt!pWHt9Z*n(3v)+1BwYv>L1I88a1ryl-M?@t( zP-Z49g&YD>7Q81t0st@_8uwLvMTAM^rzEeaGMOe~Q)#w}0tQXMI>K==eMemqlgR)Z zT~JDWGwo1n5zznel@4*r;;VdNT+(+R$g#{fo|QkZK4(Rz&?F=8nZ$j}!gy`yZsKz_cmiPvz=) z`6@zGOCrlsR-ZKO%&5W!x~*hFM4`I2dZb0}n`Aw(M98`@itn#C_*>08@m>FQTa_y;AsceZ2$>gBj%2nYPB=(&!Z$+eeHcm#Q7+wHJy z$;+^|XJ0nOA6sAPT&0nJhqB24{{Sna zskhP!Inf7b^TG%}&X}u>KcsS&Nk1-Sut+}}rE&h4UfBIdE06!V0#YRuAZF6imZryaBYBK8Hj4sVL5h1!g%oI;?n z4+1?P8o7>$Ba-L6tJy7}*sR*7O|+SN@VJH(z~g##hv_le5WIO#bD88hjSSl+$5p~& z@Xq3=R+)l39;2~azbW7L$!%^_%!7LSJxZVu-;A=4q@?2q*N>#bL%rlX0L@7!}MJ#UA=8W}Y^XhUSYALo#vF4lm*iDPdosn*z zX6e1;e|*%Z!AY*Q%=*thYe#3hL7eS2Wmh)OarJR{s;2LGvqwgc%^iaCI(VI{CECYw zlHtXksMW%3I6lH%rDv7ak@WLrzaL){m}7Am{AFiW#A2$twQ7zxbKP=RnA26rl>!R; zsxgXDS|6E{b9>U%pw^J~o`f#{0Pwr;l5WRwn}^w5)oljEX8DdcA*WjpUbP%{7L_*_ z*Qrnzwxff9;dll{x=36KN4-;hO3i2jv-nzNql&?EsZW0*saX1)?}giOp~QX(b2kts zPCo;F+NxE47k$Xors_j;`H2qoTn=G^xFQc(*G2Nn(pQ_*d7Wgb2i4*(^p2kEk9S4i zH?M~87MoGw!*~@oi)8Z3c)W`+4WpQ3_?qrxG5BWGsQN#YkIB}i9m3b}kU`-hB0CQ~ z_)2^pZH-(G&~FEDdA2`juqC_<$K<(oDy|%XFv`^)4UbSX7GE(q8>DKg2UI$}#^9Oi zG+UJgEXbsN72Ws3wU)PfdFIh=#>-}yU6ietQ^90eK2}*(_(CfZ>iCB_&1;_K@Q81! z(9qBY$>Sdrd(g^v&AyGW-hM%X$6+%4qRc4bFqAQ^YiqWfaO|h+HKdJLbSB)^ws#Q( z7r4%{bza?{sgcmn@~lqOP{d+#dO3y~re#8lqOEKosNYLXjwEoB&L9kgjWtd0A${Yj zehf_OZSX!SGJ1O}mcJQ+$K{y3HqbMOv{B256&YRJj}2zh17D>a<#gx5;l1I5*?pDV zh61e@zdFPm`!@ot)MgV7OK7yWK-bkSaPLGaIUkPS1AZU&V;@&=8y$+oW|^x+Q86X^jFIuQcPLGRmd^4;lgUu?I5l;AOV zEGE+J4l6ao;qhP!)ag6`1H*k@D{>`aEviI@xx#gVM5s7kLBBrhYLbliiFa!ra?+v! zmPiVWzy2x;JXisqC`4{R!^+Q4o8>-5I`g7 zb_3xo@V&iUiz~}~L~er-OB;u(Dms=gDWRL->D3LFRi<6*fKM(N-pYcDeodv7W!QRzz^LHE$5O_4LqRYu z7tUR~+ij!XM%Ly#Z?-t`nCCgZFynFfuSVKq5m!ON!2yhGM+;lXdzGE$rB`uPd!FvD zGE_}7tRyKYW`mPwb$BoF_q(4Co0`Y&<8F3SJg}yhsjk z2T%=?;2`Lcq@wPLyiKpQmri&b@maB+7PiZ3bIr8KGmOs`@?jX`yCxn;;>Mpm3g8u*=m=6sb9hvMd*KD43pXGJ&-yF-|mT)=Pb5KQA z9x?!u*14o}bLM7O90!wfNj=JQ+~2yAr5Q(bDOs8R`!~6q@4I_DMZIkGkHg|K+;FW+ z3g_{BR|`#|oeDDocxknuo@5ivbpHT^{{SC*yW9rgF}tDKeUsV@US#ZMV^*Fk1j>Gf zF&ss=bEZLwwZRa$fI_I+)fr|~a2k*frDjx@-L%B*uFdDUwJoQifMy)! zVv~(CM~pbXjqS1YmX2+Ms9Jk}`_0R@wY^QS-X=$Y$6zq~O`VL-3x~!u3e>5Fx(ma7 zS<^yC+OQDV1P2?~-5fmcIuj)n8h01IM{jsb_(gELl-WE^>-UGT`PR^E-2&(2$1M!2 zTL(?{p51 z*;d9m!IZHW%)0|e8Gy!yxB5q6s}NX86AdmCq-edF*TRLkZQ1OJ+3yV7n5#z>SO-&X zCoZ9t<@Ddh9Cbw}7t|xAiPMV9=4Bd{DV{2IUeggF(dMO6qw4@Fz0cvW<1-#hJ%nyI zjI(+h&)WU(?bcS3>FAjo@XNcJx^T6>YQHy3icR9Ah8?}0b0j*sx8<6msN zGH2PA3}mNiHbXeZ99}aj6@49QHFP!b?;wEU(GF=4?iT1ouA|zIgloZ$Yls_tS8&;e zb+$C=)2&bA+dG2z$E1^EiE(ipGdxh^VF7&1B1Cme@tK#t3wVB!)1u3wo4HhvqdTAY zS+H14<7)Fg^lWB+{{WBT@c#fIV6q%LD&g=LMlsEGGU~M$_f#+S%Z!6C13&?AX7hHx z3ATH|+Ks8pC}L<}Gu@!a=J7gXqnPaO&SCZw#0JD-Hm?Crkiv}fF7$82R-hXZiJ?%2R&)a{4rwzbr&X|V z9||9a9p2>lirbFdZevR|%qkOBg*>MRl+h%?4y#g$d!NieY0|}fx@Qwfb6n<~Bp52c z6WqYpy~GUxb%)+oULGynyX@Ip^xwAK_=DaKFL>L)#85cuw1yW6fx_{8S1-d0id4gi zI+96}ONk`Tn{&b+jyaVIS}zd?w>S8?^9hIs@4;|0tj2@(rT zlglI<2G~vfl%7ElJiUvfrxv$ao3wpU#C#(j3HF;CLu@vya~aKDr=h`9j}fyt98M;i z+SnX5{U<39Ng6J1@m=tR?Z=2*hY_$lC6qH`_BRv*ahP{j^tp~@O|B5ij$q)WOu#0a zW?~6&vg8wpsQN<==aWgNiLE@3Zknjiv0+e*UCX@mCj**R3KJeuf=5-@#g9fG5d1BA zSeh;^eHXT?NYoaPLhkDQ#@q2>;sE%U-xg=QtUd=BfXkhR!{ym#6Bkjh zt49k-q@FU*R$o!o9{`w`zN<`@G>0~$Lzv)N=Jf}X^i`|{8twAuU~9k@&mHjPj-3^fs9POl%UU9D(*@Vqn&tRtdu5&~PC*Agy z&CrX?*73ajOZdFrM~Tg%!Dd@kOAVFe*+o-REXeS69Qrf~Aez-4<29=gIC!82i46iw z?XLyiJa#j~9_}`SVYatoHjg-~nQaYx+J+}B6pcSeQj;3yxV^xK4@V*a26-+r3@G6+ zKqLdGn-yIo)q-WqYIEVVdqJ9KO`_^e%rhKbI5FC{(^W6wJfs2#n%W)_x8;)fcHfRy zyxpP5vmDz4hRgAo7vZw;PtzCHXlqF0a1c4(V@0P0Fu}qA0BDhA!G*UA$907Gof+e6 z#Qw*4oZgm8w!0yb=J{p|D9CE%H7RCHV`@I5s?~oJLmcl`Dh*87*=!#KemZs^!q)G$ zhh=uRV)lnP#b!Ce1IDlor&7NXc&#peB%|0^QfA)m{H8~>h9t#ZCY|TT+tHOwdJH3u_8jS7Rz`XNf8i9jd~@*1>*WG zDqE?eE=SXBFT%OG9jMtHCL4RZlg?}AEOQ-S2}civ$Kbsv02-8ycQoou0@)F%)pCBo zc$(NPiSd(*@fS;E^9(l19Mdty;PQMuIy5m9=;AQ$qRtjtlSnsk209hbR#KNpadU}| zWUQ(wXlr=r&l}z+_D{sl^EPK|b}K5(Fj#z>B&(KHqmOkW^7@rtONXL!fM9FJretWX z-V{7wZx6!$VOI~9QKg;i-aexrkI3uQG}`wF9+rhjK8C4i4JHV14Uu3*gbj;z>1k78 z04v!mZn8FgO0Dpacr@CKUJq?H%X2xcZK=Q(x|8u6KZ3>LDL6KNCx|c6rea|8g{6E} z{3QEDzTJ++Zr^tsFI#0ce>TIKIi4#USU)htQYQ3iHksj~#{mzLNo=-2CU}XpUfOP? z%8zRvL!8#S0U;p(%F3Y>?l+q@*N08-!U(w+ zT(!hz&Tzcglot~2B1tEiGEcR1?9-n63RzgbY=+YO&)V&u+S7$NrsO%!2Q_sD>s7QX zHlb+lcw^eS~}y*-g##FJ}ngbB`AlPbdqD z_=)V3p63xRagL=OH7Rc~y=7o=v`V1k2HJ&D#FY*Zx@t`g)4Trw7+dMxmgjRl$85!X zknGNBM;C{G#;~;?h^I>u*NV++gTOQC3~>Sk+nUl04W&=fx9GB)nbxLLTVIi%MEO0Aq-P=;pFt2ix?^JUnm10lb{|C&y+vb28j+2N6R6)|%wiXe{94 zaBT50pvlm=X;!gTU;spFy1Gkt#NM&=Lwf%J3nt!U@VJb#b$hwWwrrYSjhNi$9^7Un zuC#$dfejJ*#E&)0&EAgDc$40?&tSYt?~gLWZ00jDZ46dm`c%dnET;C6=_%puN|-L; zX?bbk2Z+oqD8L#afC1T6Ysk~<60sT)ipx;u+4b{m_ru{s;Qrn7wr6zsY!-L4xt#%t z!ezKTTQL=}j&prXMmG@Iib5vmOEIx=pf^Y14yTWthZW){cpLP_V77-g%<*}4XMm@b z)2_@hr2hcO(xOdK!of(ewXp(u#I6EiV@WM*K_CJ{K%G9N=%bnAaJ4-y7Z-`4Qb8`G ziK$GIIr^?0O3K5uvU!($`qkodYIjxO>%tXH!)%6l>|S%5U@K(#W*PPAyA@s4!T8QD zvl=~CMM|!c01qu_oma^kc-&SJo0)~i)}qInZK@er%wG4RjXC? zA5i-5sPgx_pe}JFiz<9#Woi_66Hih(-1-T)Z-VP(ce%SAmflWlzHE5IZ604o8tf(u zDxz6Sj1DSdqn<;HV6eI-Lxfru^6_PuZZmkBce*eJ zA*#_>)_)yCSelM;h`Wu-<=9QTwrhDK>lHr*9sqE8ZX+k9zYIe#n6F;89Buv`l&U*` zH;L55F~$z06@A>7haUpFgWe7kc{>@tOs^H3U}@FEVMb@QxEl1R`bKa$?O@^c_#^^N zq_2-362TV}@eDbU{!Jecz{Gq@57+uN9SOc8eIx9y`ga51i+|g9iQYEw_s@Z;n_{rE zaABBDwZYJ#PK74JSxu67LAf$@aVz8Y(qQt84%6pY9D@?7epFlrmvfC&H^z8hPx9x`$Hmi#p``b5J+FBI&vcXMwJYYk>9O;~1d*%>AA2a& z!r}1`Yq1!5bzIhl@jhgM?b$!e>55rD*;olA6qZz%-tn8i_F2iN5uS;m~ZN{23DmJ4Dsq|-w zqJ2x=%i#-h+zHhX3BFO)KDt31Zwvg}`_ZC_7?r&-OU{xXlu~^_2>jOjbmCG)`$V3A$O$-!QM{hWbdHl3n=*%7?XWc20E_H&6vnY znbkh&8S_9IXb_&F==FN4E+j;RPel18fV`9QD3l}A3vCb2AEoxpCzrpl6`3Qt(D=_ zPW3Q`WBDyze1h?97yep)htt_PV=4NW9@8`psm`KL^M!ev{&`d~hXI}CPK`16b8q^< zy<1BT+I;JUpaGcTAb;x$@#TPw<18azk754+{3BOHuS4=UzqNnc`JD;l(dFCC*)hjs zleqAXUzIDI+%F~5-E?1%6C2CfA;Q!A%5?t#tt*_4zgqF^f3d^=0JxsryY~8@m+Xl) zM37=^RztCSOSD@pnN`hpYczfn6HS~&pGuWs`Y&dLEN~Ml=aLX#hz>9XF3aCu5vd0m ztE1;(s!okXC_6K4?WX;*z2I)k8IWcfd+-_C>QH!NeQGthY69ZNYTE;2?<-63ays*c zO|lM8L=u34Ps<=W$cE{N=q_ky@sHIV-jmPzkxhQa%i5|kL)d$iz zNItR9DDaSAg;5*KjC2ZoBt_GU%%Z@=s*I7hFuhq}KOUq+OrNoNj4w`GY;7+y_AJjv zY97)SJcEv|Mx1tDbJ2P;5AW*cXV*9Cyv5M0bVQf5&vr%+%NR1)B-U=cm#b@Uw0OI7 zZ(f6{@#Lfo+X?>wTG?LBuWvNnY?LaBLEH0bP!Splp=Hr6lhC`bw#yRX>tw*v3^O0lXGr* zBZ>uz8bQ8^VsIHTuaa6=I3gNMliev10TyFT01ig>LR*Opt&1`cz!)!2z9;)SJy#&tlg8H^4>=BD38)9S5S^sd z6B`zcw+jb+IuIqKgyMf!A#54)^9@r@qlRVg`m`oCW#cNDBIVKmWNG*0ivZ559mo%~ zRQL%2#9sjz7F<#|E?ts%08mbn7&FtmX;FSx^&rATepgw{YkoITtb?IlT$dU*DN{T! zj%jwJ6ExF@hBr>;Aqh6R4m`uPcTaK%w7o9qqBY;^=TdG289ABz=Ibsm;U4daPQT{r zh{L5a6M!sVr^P}*gKFFtM2+`gWApc1=AatAzd6%Ce+m$DgrMUMfZRmQ1Cz)ir_wM6r$#Ve(&M$}+U!nQ~P zf^$*T7nnSxNo1f7RALcZ7K->HR*u#W%9u+8H6&ku5TL=(W&l8t2Le4uL4dzHFh@Z1 zU3eN5Up7P*e=0qnS@{(((b@(_)`n;}GZ+rBg1H9bcn0pe%tJh_B@`nsP797f1Aw z*p?^p*-Y@IIAsWuvd=s#+Dh?IzVXOA_ydx7<)qih_n-ub%#4))Mda{EJ(xqPASM2% z^lYe#t|kBpw(2C8F&$i1T;AkF5|m zco(z(7m!pr0_Z^dxC%{(kydI7!8eRItr(}W%LY;{NI_nMwQ%v4-X)=kR<+;u%GUwa zyc4j3KWo?w`0*L{NNugyKgga{{iWcwBs`su0prT29G2h3KRfj6m;V*^GHH%Q#hqH^b zp}a3R_!q@Buy5r_=t;nk3i^Q%X-SEs-Ol0;m$(us3DxAwsDA)yY6h)@UX&>DoR08m zu>zs5Hk#?;ms{B(Ff>9Hi%2G|_d4ITX(Qj{alhH7WP=1;=Ziv{gRQqiB>IKuCfD)@ zFU7yt1@gWB=82l$?Kcfif~hf}S#(J4`YVmLpZq-*q5LhHv#+0R2G6&_Aq!z}kX6&b zl-@^nZiEIJ7oLEq6PDjRgDGa3J8C8u={eKIjSIuRn9-JJ_D!O zE>CtIqmffi(@%KZbo+6Ali*i?1@B7L9Yyea#`|iNdiSe;Bwk80`~$QsWt9DV7+-iw zu7FM5#@Oqsq4?!GN2b`%{Jrkz}%%xHx;I?uf6XK9biS)dGL`!M$h% z{fxueRoi0ga+;Noa7|HSHR@-)u-LSS87VYB)LgkZl#?QxcZb5ZjZCNeC2NVKQ7m3YX=XN*$l4oP)|7rkoxq+ruE)rBr+b~V3t=8J5vn9kI$N<~ z)|5Hab>2$dxqCu`eW_lyLTHC^KDtP}+p$_rXv$&Hrdkzo?%<;if#IVZz9_y3)sfKP z3t0`^`jX#imS3A@rEcoUm0#Dwh{RegwS%-UPH0&onEIdbf8m zqrNa3&ul4SD+9vba8#slpg?et#KJ=&k**OKlK_Hma!+V|tmexScDS=Ch6duNC0)x2 zmsjaIIJ3GD6qykCz!GVk53h8D$VaUBG<4EG{MqT8K3<{EK;Z{kF0$rpO5=anI2l&1Ucrk|t;dS0&c+}ni%OiqT(?{iF$1}X z8M>l10yr7o?sV8B=T#W(S|KuBVoiBq{n=Co3rQv+NO(N$>o20rQzbs@Y0BGaQmXicTVEhyiy7M1Fb=bK;Sh6^VB7Tu$lIE^o+D0)1ey9ey0l6#c35VK%M}uUey>luwv|zWNeunE;^yf6o#zV;07|~{6VX52AV$;Lds~%n|c0L8U89fu_c^_ zl)vU-Rg&LJM5hr`>LFUJFs^J%7nJY`X^G*t;-)EBkbYQ$v@RANE$%G$zA9FO{wHbD zDGR~51EL8GbMa7VRe+OH$f=N+X$Pw+W3g{E4}kA95kenVSZ}C?-hQKfYz0+b(LQ?je`2A^`c@3M zU@*aoz{25`hg!1Y}x1aJs+e6;4eBfN~xKyQP@S>?;F5d3JU);Pz48$PKO27$Z*!cJdcamhQ!Ni#DO6 z*EfE+{lVxjiGgq0f64skZ-yWNOJqm`qtfdhPdcT!w26yX>5r)}Z0K7Z`|clFyLGXg zi==8u4t&hW$0h112opV0jYa#Kqy2Vy*4)29(wNBd&A@}{KI7Dm*%~V-tFG@kfn1AF z_54!C{FmcOx3M>@=h&7hh@{s1J+(iG2gCWH08N&(sM4SBn^i_yebF8SgoC<-?+j?j zKr?M9Te z|6^IZ)6PeIFw?_^7kfeM%4b66!dZ$0cF)&K*a_q}!ujN<+Z8D5I}}>EvsL;+i3C+~ zjYo@4s{QKqDgLcP4V$A8Uk9mt@WM52CqH!4U|-hWDm=YeCmheJ9!ry>&+C{E-vnK4 zh`NLf2Ryv~;VOLf3p0$3xaY5ITp(<|Iu7De6%8VbefM$Q6e7{dUBfWPcXg|=qjyL6)u*m8iEUkjeWQB z=OE6zrg}Lxo(u>dEQ zsPLRi<4Tp&a8iQD(ZTZs@9gn-HdW*4#=a9*9V+xBJ!$a-2V1@i;2;!Z49mpd1x99{ z4g>6GQ2JzP#1aT#xjV3c5U3vECLTL%*cpmz?jiQxkr?^NuM*a;b!-GLd?RZTAB~Ha zjE)s{lRtiptHd5atyA_pOdViK1?J1+D^ zO(^kbbyoG$5BCIoh zl1qhy4S{!D;T}vBzKsJ;35!#Pkh$X8q|8ch7yLF>IG9l{_=Loe6zx-5fX9lHm4Gy` zyT_y01w5a@HC1A^04rRfselmqlK{v8$h>&3_$~auqb@{JLf=CmR#fT*l(sVLkyKzY z+z=p@vOh@HRY6BbnKUlg>ovk=F52W?uEZ7qX@b})?p%>C2L*5Q>m8LWAd>nzSH&F) zOsPtdMec z!~_77w8C$%qHtA=Ee^IzimNpR3U{Jj37`>iXQuCm08FrKyh)y zNheAx{$fLCz@NTz&F~_@+KdPEr`^yb5;jRGaXle9qU16LV(Hp{plrC5^t;KN09o92 z8&QXaSGrV>*ny@JwHoC^^O=k=3Ae?CAI-RaO~k@Aof2xbD;oyBV`%8` z<@y*F=wA6M38+oUr1kDxanKPcEoLq@Rr;0hGCFAZU08;C3AA_$@YgDeNw(p)v4KUy z!yEL84?S`F$B@X*>Vo|)#(1+bVhciv2;9)g309~B^M0V$Zv5JD4aPSw+CpN9Ry2(X zp*K^!mOiB9^m)^+!swYM33a;j&P9i5Wk*#g_a0?^eYW}nhS&A%1LT-(a2gk4wjFmof%b4*B!hc@|L#2ef#A@ z%IeTye~nS?hee&%AnA z5pN^$LOX)_Q%q#`66j`1*TdnjczPR{bxFm9DX|-K$0##GkK8kp*Y0y_LADeW`k zVEOCoDarO8(d|tA14v4Gi`n|&IkQKlTZpt?A_`nf-v%#I*?u)cRKklOefkGb?IUaQ zIjrelEwd3_$D-a8R4jV#N?uL$QutN>p$?7;maRNZe!GKyL<-d{ zW?Ilhx^vPdtHc)3qkuo}hm1u5%G}X>Pg^F;OTyPs;BlFaM2E<*d)BJdYL*w}U*;u^ zImPx>L8a68OI0G+ImXvnkMQ0G#=@|wn3><&sf|BF_bel?XQ#V=`i2DBLA-GE#2CQjeA2M z5`CuM;A3-f#^X`ErA5aUlvg)`Fw5r~-|hS5el&+A{khKA$I$Sde*mKoB)Ka{MWHT> z#^P{v8sJFLm9c`@(iC%1W5A>IMA&b?XhXVp8}rd5`(;?9e4CAWZ3r}&jLv*8Vf*D- zfn=wl1Q}DdNoOeW=d@IlBIEMML0*r_Zc25;js`S6mQNo(VB(+ef2v=gIN#N4$0jk> z)qiK^pAvs&L}71+)2;u9cP!_3Yl@@oo4ixG)`5S3L$x{r2TKa7buN+X58{naCjmZF zN1@cu$d!*mGlx~yze|$UEQIYsx=(-C8YW|MYs=t0p=1so7PotO$zD68GaG;^bIy;8 z$wuwNvvE3U=axmznLOIQttl*iUjb?VX?AHgMyh!>tF*t;sAsi~*#G23vBey`)GCzc z6$vk>#WNYJvRxwLktVkH81qUx{F1>SVCmGM<{7=NkIe6s%S&HGs?;E$^^AbKXf@Hs zT^BtozHAP|H=?e~<42+2n1@`B#A43^s_rjz!G8dnr_$8L!_%h2uItByt7nv(flp6+ zpS#3^r0EoEwKp?|G#ve~v)?_P%6a@A zzKA)!5`;7Ttn|GB-b>Hq>e1wpKa;bz)WB6Ozpqu+s*d+0>S~&G4c#N?TW>p- zfB#d%y20s+ICkV+j=70b+71);;~QIE`)J$>A-cJ zR%rjGl=Ps)D~3j-%m;qE%esL57hYrZnH=hBr4@oZP*MNboMq|(WWIINt2WVhz@6?1 zl}<;hAoHa2%o}Zr*$BU}&k03BG^5uF`}^ZgcQ(GMqUb8Pv!g+KrG1|sYxpEGC<;!m z+ueQaoKRlgr>k{8lz(5~3*Ay%R1ec|zW3oTjz-&a&N#P^HP2;8OOGM51otPoVSn3h z3m?iB9QQ*F5RWi@Hh#jz+tHJ9?5SL9i|P&@`|eDr6}xKSO_`Z^s#VkBaF*K9ByRg~ zd8n?q?bd}9S+7&m!IraghtU=uyOQe$7qa+RGwbs`2i_l8UemDTR{dblEY_^;I~H1m zPP_pn0joqewl+cszgD}+XO)63hfkvA%Y)0s&Oh=R)>{{Mhs9JU%vJ(gPrjTzV_e5! zV+*Vf1hAbPX03km27YTwc|>NNx5VZ0Z}SssU{_WD$#*4_KG zZNv2NoEzKmd@a{4g0d)1vz;RHnuq$@P4T4}*>Ajod!iI!>6Gp2pG{1Myofy3HR9nd z#twD_4Yp?bDrk5-GfL(BE>+)pg=FV*|eLW6!oqNZnD6e#OOaK+(e2e zzfQ@~K|!wmGtlF152J#9x4TO;e^$FhHopq}7bRdI!|%{yI*=^!)-c8$w|hiGygSBP zKcZx9ez_PMWNRkd@+Up=9|JHkKVR_!PdFRlZ2csS&52er?adwCVKU7E3yn|A0FO-o}8E%Cf1?a&5`y0ysKJsuzXf@rC+9Zru=&b7u4he z4On(EjMYRdY++uFgAV^wg#@YIlxu~PL!VIBk4|{{XzzkKuW_A^LTpGno`GX||CSro zu7}X(i>))#9ba2kD_fO-GnU&3<^nu#wln?W{}^!+4vEqqsBZJ_TFix#P<~%(F<9P# zed(~BSbN^Mu-AdI?i{=*1bZjU&+(E`HHJCjerd&ajmcu}aPExg`G!8)f3X@VrhofS z)-Bs%rF+3}sB`7OJpp+0_sqkoTm7Ht$dO@dBIgOp=8<-~&}|Jz2oC(iB73>iH-;}` zXq3u9f8NyYi^Kg4u~Bp$^-CmIp?}8Vesomq*%2;?Jy%=2DS;~jE*yN;i*+8!>uMQ{ z9^V84=!~38Al$+Xt_%uGqo+$x~+35kE&wIwcGnmeIi zu=@uPzW1hBj`?##=bkqlQKcCpHQv{+ekV34g1k7g)qHqwNOYSs3AgOxJbEqr>B!A( zW3lw~xrBXIDyT~OXgwyp7wP;qA>ZKVky4fD zArbz+W(M6pn1Y1_`aC?XQ{B(k0#XN@{I}GG^0Z5%_O5F&BvlI{Lza(G3unH`YAq8x zdUAgqS#Is~STE4dwcJ+i;n{P1F}V}q^*;jzb5(B1mN!H*=8nj|ll#SIpaXoG-Y*x! z*ImQnu5IN*;cWJ&$HaT8Ebk923jf z4`tsMi22WLL-J_}4Bfce0B~sDX*bzn;X#4V0qkE$g`*j5E1pw>nqRWKc|auv{(VrZ z3fyZu^_&&nbKtP6Ci__p$86mUEV*gbtUyH`dgk*39$XHU-B{ZAECk9IjJU8^P6&M{ z9|VeC;6-Ai@y8bwgc?s4FZj)HY3L-rKiIC`@>Ap&Y_!P5o1Ct@Y9E5#MsdswVa4(cR_?&p2e>#d87X2w#1o2^Gb>or1meW&2 zh62x}=czUEKSmvU9_lAj9OWcZMV!304Lt-(7Gl-D_{9la)W{#pd2dW|9+z1T7P{*Z zp}w6`Y$|&3ZZR**@a-3f$)Gv&-^_c!x4PPK5p36Kx0mTSEJ!Y$NI+aZc1qJ`xIWdCQ5-kQ@fa|Hi_>;b*_^Z@&gmk4%d>iNbHLgD zbMTO)2S;+8e4|T}v*M-{+fAVg9&U=ukq`gRvF>eu*rWIus8~Jop|Opo!hgZnn@8*I z-@4nm9kz$Ug=O$+7s?0qzp)SjXMr_~a6Zb=BQ||7Fg{0; zPEjU#Jb(J2Y%6Ry|3!J~@q5cJxZ3>yc6)UV_o7VCmK6_iaC{{qzBjt}xjiT}##g3{ zjV<3*t+u>oqYIv<5 zXFk^N->8r7xV6#0S_$;|vFhwzv>7o4A|w@3tLd&iVlGf;^RCQUC2>wevf|a^e^yFv zRodBhl8N9IKyJ?~cUrE;HVRMPs!y7N^#Wm+N(7Rm&iz1E5Zy$TlzzO}He z4A&kiJ$)s#3-ucQxgzaOVPeN|{B5Pt9BKfL8d?A#d zcq8g0M+?Vv0_&;vczD9Wiw7ERc8OjA6?Cp7#t1Jv>z03jxep>p&Fj;4$u`+Bl#l)4 zQ}>a~F*s|}3l*_zt>aC;q};9fjSYh3(qWebTke^I8Mn5M7N2_ANAa*J;zZCw#!8VZIAH%mdk9)jfKT}{s9mb;jxO6C!v`m z{~hmG&?DNeVH=t3PXP&M7j}y7*||(+MidRDCz+?Gq;{M|le-4Ya;0)Vh;Oo*HGrI9qTDo8FRmLv2%N{sC}@!ncLc z!)~%q9&92bzaTLncN>TnH0l|{i%yX35+q~I+qxhDqY^=jR|2I$t|WgT0Zm7htnk5j6wWVt-+rgC9X=~<%34>98l(%N*{o0@-st?^4+f=li{mb>Y+ zB0R37@BOWdjY9LRL&XV&Cx2@APhjB^z<7*W-&zP%FHH0?Dk_9MBfAXT(6lM!c)k5* z*KH9?u>;>Abl0GVGnaIsUccE5(PbtVk(6N>IG@go?p3^q%71zr;*V9d(B#!6e9W5q zhV*w2_A;j-yI?Ga`l{6|UY}vaR~`P2Z#-q`CK75UkM9nzJ6BWd$*Jp_nTFW^a!%WQ zl*42GAsOww=r+=-ZJ4P_fWD5@Bcylei4{AKi6x(C*(5!1&`o2M)lUwXWv)%ri=Llm-y79_~ zq`_8xZ8iHi3yW(;kB-QW51Fg-@$Tw_@fe3wfd$BDyRl=lB@8oUGFBJ#x)!bTLRtE- zXZdp)_W_R4H~n<>7>-=&s2G+9?q5IU&_77Dr0F3pgfOewFDDI*lSm~@3@al9ekwJ@ zHtdJ^@8_GM!Js?t#Sn?*VTsJ9YYjt#=H*dbehn9y%BxE3;sY$%Fb9-Q{$#IM zTpoTbby%!b3udd#6259XCj%qZ$1+AoqJ5fQ@S>CPp4GoicGG;AedXB4r`Z!kW3ysE z*6&o(hc{hrqu%*=h-9`*jpD-(5!w=k=5e1rIsvZbGY1Rj*b~O9yE>3N?6SdMs{;I; zoKF<;^J$eDfB1?lema29I57^4ynZP7MYZCq zXX%SG2t>Xa9yIMef}h4I%DZ3p1XA_Pk-_NwZ4 zb3-@7(Y8!CjLv}m#7Uy^d!-@NU7ShHvW~u%`pWnh*HohX=$mSY3k4_YL9(iuVSt2h zXr{6s(Q}|uI)#{#K$t#0@jRod7-}upG%k{eJ`i;=H@EA`G#=l^BRg{tiei{ImVgab z=ny;(M0FWNP0*Om#^Osl-Y_Lni3h%UB^?$h-P$|O6^X<376{MfXbjvtQ4hYN;-a5Z zmB&8t_1;(HsRQ05k3g9~WTBv4pa{WHQ2=Fpm(9YhOO(a|ed* zY=+w;m^!I(b5hxXDLhHCBhi9KgKETpZ?OqKuqWW5>)L1bG1AZq?*&mTH z?4T4Ej5o;H3??5y08Jnb;u*Qn^lv5z6{AJqOB}|Lsa?|{Nk|ODNVkB|6vP0i-=Q6C z;ho`|adGGfs^xviKf))OIi;oJy;5O#bc>~qNR%)Lh!z_xg8(9K5jBDfE+(x-7d2<1_F&o#Y$erP4WdX=1_Q-%0r90U-guyrqGf~3y~?C4j9Vf+ z#_31Us<0YTPVoAQT(Wvp0FS&Qygu$nu{d@B|DBU+K&e_jP6fV49>BFxl*~0r1}%}} z)$#y@V4c=*EWr?oiU}Ev{r#faobN_;?bU=`SXFB4x;pGHzI^oS;Jd(RQ-C$;ICJ=6 z0Qkx3wZ%0!?iHsPCj3q#6)2bxC@lpO^QS=*Lja>G!EylD1LtD6jFH>Dgwff##LxJe zXTrT!!};c#%@lhpCC5K>$ZWH_$E18B7E=?P8MQc`1g=cQ_uaSlKO z(6D;Y;;2)SXb-8k=i8vS)1ZTwWJ3Q~vH>pe{WEDgW*t$?S#tB4Umx&W^Jcar(JAgb z;BYH4ek;aiO&Y?*xdtPEh<6hc3DfpVheLiNL=+|4{lQ^Y*UP-%fGF^(t*Br}2Jc zB91#pEk4*?tR5U>@44r*YYj2eKw3vrud-5wsqm)&!hYdLwWpo%K|s|2cC>+dd5X(41Tfta466a#I7RP zK=CM-wedCH;*~o$PCUt3i(ktpCw(FMzx@MfS>RdI^}ceK z1jXYJ_dWEvpr5U@p96VlfF$!bWWot#8{IwVkbp!{!u!wne}p~s)s63wH3qtzKz)vt zw^6%i8w& zKT~MmE!giGewfaFuM#kuIp5o!#}GTc6n!?|zDoAyJk&Sp=e?hnI=O(`6C@&)r<`S9 zxc~mQMj!`X2^$(Ef*KWWy=6|h-T5EvXS=nIH_p{}2mwKb#ug4mG?h$c)#lgEQGLnCQ z4afC?jx=A1e}JAEq~P5Eh@K!d`hegklF<=(hosF9?o>{cy}&H7=k`5_x6{dOVwV#o z4@H7c?A5nmEYitqhB`@5TqZ~Kj`_o*hc`4Obn~Ogrop3(ub@5{oo;f|koO-T-Zj)9 zzlKr!aa=0FT@ml8>vohUBW>qwY2_l|`#jMG=n13Zxmxk8xqV8I>s*u>@lvlyPvZ+{ zg15#$6BN9Gut5YLIQx&c^DB!XXIk&p+5M=F^`~Q_ZJ!cOw%*e8-x2B@XhQ}SQ9`V{ z9MS`9qpThdm$PE}o(Cz0oK&c1A0v-e)G0_v?wK5jqLTDcH_71rM^3P+pQh7+&(iH% z%&&yGdCu3EDiZ>CbUg_zPvqgW)*PcW6tMpR*bjWHVI)a9xi7rKC((-g$jR-o{b}88 z)Hhuz!cDy*j#9sv?dRLE^Qa_Lzf_l?6Kx97f{9n|ia2rZqddzT-o66OPmF*+g9wmh zUx}4gI`_qu#jK}`L{9h+Ko5v6wCQ9bbD1lH*Z9z`Uvx7KC%;kCXS&)TBOE>}eEA}3 zyp5tF&g<~}103Hni3i3QKP#rh{}#ZG`GqhSn#<~sa@QS!*sD*mjXJxgnacnBQ- zOuy1TVzG=Hd65}*tpSRwwAt{OZ&}(<@>8tpH^WLB%l+KSr7X-@f6;TYl`1a^@T7j2 zjg9e9y$Tx96vh=8y~$mJFdo$VGxFruXJ0rlMNq5Og8sKuN=AMiHb`+j>?`3eBy?T)p7 zC~#K@Rln6`>4Fn#33G4bNM91~(|8)mh#GpbHBNoneRSg4*FPukWdYuI z)FIt_n){iA!E1=Oeef10eUgu>I5B2{+NSp$CMR-deJk;hD18lp4Z`k7te*GmHzr62 zVYmtwtu*?YyCO``;O(g0uMLo|3Ra()zeH>vH}}bQuD6kW=hn(l^*C1O=16k|OV`?O z<#fKnb-tpIH9kCV6QZ`eMn96Jn+DIh;rj4dx6NUx6BW0})+?c@v-G;72F}q|jkG{2 z$tEyYpELpSS8ooCf$$BY5x0>pZ|#$cj!_P#WCXg2G#~iEun395r4nHu`(hm0Di4N| z=#~pglO3~*5=Pf~&id`BvqN+5w|lZa6c(0d8+WYccUc4i+s@w==~x0pQe5FFa53^C zFcA@1yey3=1z*U#w6XK$YTjmwjW%1GFxfrye4dVtXgy63VM^`{v@s=bs*vf%UWMr7 z@=E_Ce-2-B*M}Jp^%?+b*idM%W%D=rg{(CypG6t))k#G#9X0@V3>7L(oZtCHkR3EM1o>Z8|^uZo))I#DR(UiZ0BWvEfpTUPbgaAzZQsEYU5dp4GHQH!V_`A1zgK_T?Vhw;;a?Ku&)L?h z@e`p3AJ|t+IraG<*WHdVDf5N>urs#SFpwIuUEi9#dnO!V-pga+ksf+heC*gT1Yxm( zHLZ*Uc`$~^|MWShDZ6Jc?-KMFcE{u^tt9wG6Wjz?5=FhKMNvxCE(#8dFXbh*byDkQ z{TtMKmcBhB{I0$k$FeNos_}mIe(KTEt;Gt}aqE6;$NJBQQfNv5dosp0hLZZ}Fbfqq zOVkc`$C*+aZSBU?s##YLDio=vgr`^kHpt&r7XW~g*TJDf5~@pPF~`*Y3yCoII*yDq z8}}b8oS?IG%m&eW6>_!hqT9KXINtb=2zW*ZnpZPcxRbzhanr$A&eIkaNp%y3?gM!~F}X-p$x$qeDFEp4XMOVbEkR zLVgh z-iX1gu5&p54}Er({dB%(6ePcEC<>giHd5OSSADs@WtwZlS$dB$`v+!FSn94%7{~Mz z4)&J(V(gvj^ z@jFpE8((RleQyTUXFP!0HcHaTk6l$QL4A%bhsy>rna|?VL{UF(;>d3H3vLhW|5EHZ zHDCpN@|umtlBJGQ``@Q+XKDRsvnx9|H=|l~2I_xly>0BzmCmDnkTUbWnkWv3TVp56 z|Fp1qLPB!qPB~NEoSNc91_zh0=JR>Y48{Wr&xvd$$hu-!od#i?dmnuIwYbl${N=gR z&_+uzl$o-J zL-S1qff#@~f$3}TCWZ|h8uD~|+nt=EaaAWsU&UfnUKQP*+Mh&a$t1;(*RHf$Sis*w zz<~f|t%&~tmJ4oAPgZ&R2MNh2;4?E=@im-0rS~V|_OOw2ZwLFU zzXsoiLh(>KS6VqXV*S>|t<2aeC;U#d3Dyw$bK%f#lN^p5c~&-lx3BZcReK#^`DyLL z0X)2@QCQqzE)Fx{!HG7oU)06FMSG|sF=&%6%H-qO+jglK+kb#Br)Q@3);Ldl_5F(f z0IifRo2N>?rZQBYyY?=r<~ZCxMO1jUkSU zmDPM`nnW#carJh$UpjWkKFsGfB;?MIKhfsk9hr|_?Oe5t;AJ2$BLX_QG0em3V;faF zjPXHhx%(JcK6CgM!MA2!k0M!#Z$vV_KgB!J7;EGa{ZlrxPMpyteO)f(=*x z^1+eyGDr4U%+fyq|H=sQNCW(7x_Cdl%361Hb>y;;myfS?mb+@pP$tfc#F}vZ1PSxk zKk9&z0-=y+H3Ltnet2{UC|(^69w<4vm&-B(ygv1&dI)Rdih*ymPR>T!>w~!19Yso? z=#=skTb%57cby!W0G366Q1m+eO62Ji8kw{2t_etwXSl0^Mg2a(%^M|Ym9-pguzPc^^x zJtmwT7a2NfCA63I^|JRoJR$LV^wJd)R>l|^$UhP(FTd-LjKzIB@H(wFsd^R$3eFzi zSk|M}$hD3j$g8f3cT<+6sXeP6oHqL{xImV@Q110hp?Hj~v5qzMvY~0TSSo36lQ2qT z{zx5-PPNDZOh(wm7De6s#?v9n6-oDr3o})nwHwpgXs~Xy}mGvuyfovE6cql*iu@$Fi3;|8e2h(}W2? zBpoFf3zeq#$>~xEaK6t(pM8sH53JKYceJ2$!X$gq|l{a>pB`8`|@Q-YjqA5<;C z@`+=E!j2=lacKMpGxVDt=c4)vY}zJo>Y6q5L6crh(AA=D8r0YFP@kV{0~s8 zl8q=&JwhOh8x9X!L1<-2Cx&(bvadM_mBI=L8==*~q()6Ka3U^TYh-(U1o6@0s(_RXn4#nJRj(+swRe)Rs_jG&%zH2qaWNf z_ROX-(ubh6c43O?ivHPo0PPg<%KtXzV1*R|=Ta0U6T;bMm=O)13V?|6LGU+w;Wyb9 zB^=XesNzU+v`A7F6H=KGYJdTiuOT6oKFrCO3GNY2Kt!ol=5@O;5ilYEzd%UcSQ@;< z0q&tN)(ulZ03c-hhY4zsw&nNGMEvlF)A#vJz{cOts)-w2&DV_n7_ekumi;&Hfu=K;Xi zy0o!i7(OK+72Tif8Y~3^EBezo=28lA(L2y{Dmd+D*qop*+d zXgTRbUqzz>j91a3RdG${0xXb$ibV%7T)K$Uh@N%CrK!fq;y{-PT!sGWO58(fM1^tK z5~4>!iX1MuOXZM$SYh%iU^;sk04WsZ*Sw-fG^HD&dBtH149-gjhZAQfdbGo|{Ym4L zX*oq*oKiG;Nb!M0qNE#&7AP=ksC-&j2r53lxfpORS(-<&PX$Q=!x2#keuJ6UFaZrb z>?~iSq=g31^_@0hr{X6;+bR_bko)NKE?|Tb;$P5@2N13QKqopgF{%tmNd?W&AsQ+@ zyje#?j|}iF2>_>}d-jZ0gP7_oCjW?4z(jFXjA2sgG$`OCeweddqz+}LzYO8HGZa-* zmXuRzHiaS1AucJ5CouAywXk4Sb{jb!=&aHLM3jLcw4!pZ4`OF)p~@Yg&5b+YqHo78 z1o9VjKzStm<+bRMkvni*-pNbB@?Dg{WGY8W)r`!_y41y#1gvxHvJQL~(mnE^LF@OC zQ6c0G1s;u=B{*hDbtbH26X-HiFlr5YpShf;38M~26jA_^8u1&e;hyc3fj?92M;{d; zV$(T!vpZaHK229>r8WGL*TO?-9%=c5e04H@`TOwfO0Y+^BFO$c!dohxfl%-%q75T# zoro55;h=el@j^_Z6;ZagFFcFZ#I(J0@5*9})Bk&C5L; zQ5{P6-4-a+^!Hp%wL(hc3Y}K|N@a4u10~O&JJSq^SK21pGKiZD4L|hv8GyaZP@_8I zAgE?Bq}mHIrlLz$M{u$yrrLlx$zvOjM~Z1S8U9T1cEw9JudJ$N=vgXi)EE405cYc? zMT1n{ZM>M%LEoZAH2fnet=+!*GgI{cA?d5*qHNx;m+tQFlF!SHmImo=q(Nfo zW~IATSh_nzkdRnHTGHp;@9+J8;+oGr_r#fVol|*TBt&NbPVuqW^7@#xs%l_Vs`q0U z&2M#m!Tq;sh<9Kz4Y@gAjaP`U$m~1l_j~D%3&LOHwy*1YGwzwjF|nIz?~cSWHWP7r z|5SV!b|1i)xu$Cfl%9U~gO}B6^r@-3P>tl=M#P{?%PuKHg(=~MP>kkt=~Wk7^TIkz zYcq&{qkGh!tGX=%Srzkn8+Woxz1>0|x`7(7uE-F%@gLynJqb{Rp|I2^t?ecZv*qI2 zQX_PxUN&kf6aSH_SvJG79w@*N~`0c_Hv*+B?Hm#W>Y z8+qzf9VQtcaDCw_$F=_}t@VGU>2D7c>5AI8M(kbnhKt78$3*!?I@Dv(nihZ0+AX2C zwrz7NRXnqC=2WY0Def}N*IUQjoG+EuPJelBu2Fave?7W0xSfgHR4+&w{<{48{(qRN z_ECRdCuw57@j!xfZH(Q`_S*l-r;+g`ah2Hk=2(h;#haxm7hAC`)}H)qL%qju-4t{w zZ_MWFP5l1!O8AdbzlY4C)G8#T>AJA6Ps|{;?5`;YdM?FL{;gRM1x+So4&N!mkDxNBZ>mLG;1`TJ^y{-OD`$ zq^pDoqcc!2d~_UWU1VYTM6)R0xrvre)l6m|G4*LxGSYaw?FW8o^h{6XrK!!{CogSW<>(CUf@Wg995;dbSC52L(_WV>o zFfeulw9Wnol%UnE-N9$iW>g?*R=m6;OB(7@UqG}=Ui)neo&b+0E;Fl2bsR>iUhuKX zc4s{#!NSfI~rGWVdlyiSX5F)Z!V5f!-t92BUs&S}i z36t70lqUEARIS@Bg4WDowJ3k5(gKT;J3_y2Zc6q%6wLx!#iq)x5#8y+`dFD?@>+YG z5Sn?MvQR0723Vh|jz29jUlZa~1u=A_1SPFdEVuo|mXW6(eWJIivH7O$w<|kw9ZXOw z2HxaVkWo9ntt|YD4NNy~NaSS0-N?XL&gj*I-z|24wz-FjjWqhi6Zw3a=~)lYh~jSE zE6Af*&>!+g;KN<+e`)lYHiQzjC!dt@i)D)u|6-Ds*ltzvUHQ|1O4K}4Z@;+^l|@Qr zl~(wLG5AVb=5^>K0(MPL^2?N>e_;&f?#hQ=722tEd}DUmr2RCLfk0iUGdO}rNQIme zjL(Qp-MPXsAUcm;b;4**&i0pSQ7myqv3P;^N9Vn4c~GVli{wIn6j}Z% zZL;EwFL<}@p-6mzz@t_tJ!O(nfePyc{96wwo#yEb#!a?LBor%VYh4T;1q3|^=o8Z} z`wG}wiY|)IlU3AN=V3WZ#0HCY*&M8`ZSj6ATksB|(9lI$W@P;PLKH?8coocMwm-I9 zj*+aOic(qdmF0pwkkm_XS0Rnsgbd5sLGw;DbD!7(8J&K2qqLl%3W?q&ByzAMvg9M! zk~a3nD|;7a97Ys)9V{rLvSGGW3FnbD(1U4Heq8%bM4_%LmoXmg+ZpI7?gHb%Q48vR zh->KB+&v-zUm=4fF}I3SDChz|e3>fXlk5Q~9lt2y99$XCL(QsK9ukItbaFP|ZSao= zL(mytRpQG~{L?-*ZFd9O#SN%tLDqLr_Xo_XH6e;9Tuz@@HlSkokqAxxJ|l4Zz#@p;C}Q+e)2z(v0x)Na%bpKI%-g+di0Tf)ORLSj`jX zr9@lF@s~Eo5uwobjw5cFkJZ?MpUG1Yz0FL%pQwVqeBkvnnc^hBb$-<^<>o-@hQaul zGWD`lUB9JZifr*5(O%x`|KBPuj@ryZxWS#_)081Pjp6 zZ>Q8f6M3Ph%33WZFfMyGqTwER$nZ>gmJbCEk|&7*BM`_%q~p9c`!b5v8hEwidYI6IQehYAoFATyZT5FDo&>^5Lg&&acfoa zoeoU;`!B36V^MG=(M;>NMm4i*M$Co2SGHpk4YA6e7XhVN5Tw9^2z4UMR&W1eQ<`DY zJV(l^E`OB+u))gHfv74_Qg6w>!dZZb#}^gCY=5hGV2CNk5hb-^8&q*z=!%8};hkW7 zBaqQc5!kSTmVpyxQLl<$us-6wx&&5rSrwPQQOiJFCku|dVc;1x~+DOF|1&v`sG|z52z`v zqOmX!bf232SKUsvGC5j{q2Rzp{+KAwbp10m3YKuiPImA4r$5pjQjODB*mq)>(qG7b zc>m>`^|8zPjXvcW9+4$E=Uvk;5do&4FJ>U5$F(7)vw!yw%^oI$&i^#TpO2{(z3?KI zV(Fi&vTU3=Rm`yxp-4*LRm2r@c#&=w=6;5MOINrPemG{?8i{{?Mgqkt|11$;@e=qX z9lu6tyz0-t6kc^mB{zX<*&5X%_(@gdE8c^19#n*jK)j1NT1Hv^(zx47yF8@*7Jf{~ zK@c&%joO&VF4*r=aNAWFVrl)}HQQ=LcJI&eqnT}?_~)trN-IIgje=J4)3s*CK7Zjp z2ps%%qw-oR7bmmOmNi28g{aF)BLHvKpR08Z#!}lhM9n&7@mia-GXCW)nT~K190fMc zoR4{5Z?zgku$Wf}GgZm(;D)5$bKYM|6-I{}GzG&O%>3@Ytb#LhR*(dw3{&0WW!U&C zywVPEBwDbvOe1qb_h6y+CV_j%zVM!0}*8@S0H5BzD$r2=DV#4@N1Bw;Fe zSVq#R*o*umhfb%5Z}wB9mllf5{ys}S^C+KE%|1?r1BFbz&@KxHpt?#aM+lfg$;VKH zB99m1cT*FG5cY_IvS-mz9r%{?dXJ)j3%C-Dd#FL|BYkz|SxE|VdWmd>fS3;i;SPY3 z`Z5gkfhu4&a?C0`KcB4)P89N2?x|F8tEi-BCYa>qNy^B~r*$Q^E*9418Bl4nrpjlg zpKemTTh!sx_zpUk zg_Yopc2F-PNX_E7F%#+3cTp3G8jvoKiHodCAkvoO%b8*JQ<@ur zFwzfWQ&8^QjA~dc;epMrfjAR?&?tRLuU2R2HldqKkV{QbB^aHj2BfX^_Os z-e+KM7MTrk9G+r)mdh(_z>n4+ie+P<=k?EoG8I+P6G@P;0}^$KYU*au?8`K~-|OY) znc%td@M2uE6Cf2L!+8-|ksEw$s0dam-O-w4x@rwu=AB85u({S}e?-fE`KS{$p$q z<8L{8dQU&NtfSRwK4lpW7e4ExnyobxBJzzE7YpJ-njSI2oW24@pActx8RK;bt_tZ& z#j%!Jj=h9pIZ`|{lg`r~2LVY_pKPGf$w!Et&m8!h@uLGNEyYiJ1Zei=2 zEl^k_&m=L@EQL(%ReKr)Hx4FD$8h)6>jpX~6?+h~65vFmANDuQa|TF}Pg#%z7CJQd zFe%Cf@oHk;?P~9D6!TnojCFP64zOpm@Q=fC(@?Z3bc`SAwAAQf>-ESySxX6l!>L4CTuU1k5J_16>klZW+ z(*AOoe6$neETd%{>-AkU`0AF|NrvgWt-UJsGU;Xa zx3J}7PrYC8l)WS3^~}HQ7_aOuPjNtI zv^M~HjeJ4>7^em=5lpOVOa~S}>7JZtrdz^%FVg;v`4G4^uyT$3qfJst8*ehb^e#GJ<#plQ)jNgjnp3u=NozB;%=#d}*dP&% z?`MUXbEZ@0V(UDVEBnQ2hY(WaP{~{_21}&<&R#6%y}%}AsDx)_2tH_Y*Y`HzjB5#V zq^r1Ihzp**`6Ln)6R_m|#vVAti~dvg=qT!e%TfH+YNlCa)c&z+|7u?3S>ts*EzY}M zv-_*|`|UeDNaNOV_wZ4VYE6U+uSig);UuK3o$j>7@Q+-J08{y8V{Cx& zOo~jUQcByWi})c+6R&O6s^GXOZ@-;a86p2#vDI`Z{TqiY+lltYrG#YTU8F^Ckih$z`6*b!)DG2~n= z64)``8@@A#1ZN(yD@!L;?5z5uo0Z{C*7^fd`>Q0_&^hWJkrgwW>gdx{{n!EIhmqR! zG4?e0MT#QJ=JXmf=IV9dc?Wa$Z}F8GW*s&}ZQ@hKDwf}p+bK1&n3244B|I`vpsC`# zh9XF1gxtp~4I;iiDkPe7=NqazN@L|ms;siL0t zF2m?u-be=_gS92Uq>oxLty21E*jUmwGeJE0hs?uy6l34RwDh|g2Kp9F_et19=$){rVZ`L{?H6Iz+)`PsB4h{Zf` zAxC^oY>5apRZRO$&ddbIn4Y)`U9Tq2s0lk!a;hzeud53-G$;dtsEc)=VIt{F+CyxjxEK`~+hqCB4oZ}+VmO}zm8K7YETicF zS({PvUVUG>A^t~$rR7=LLMJvKpN3MqM9wUtlr`&{pRs46Ok!}nS{{@WBRS$d^A1h9 zqnLAMm6ZcxtZM29!e%tYeWuv)!lZ9st*|n{&?CoQE}LG3s%b)TqyJhi?M@9;XCo5v#+ zC;eshy0LZ@`pV+#f%A+Ch69{EWMZbVAlU!9Q5m^K)0dVNgx?YySGTQcQ3_~0sk4|&-i2TCiq5u4Efw@-z;mV{!MdG`*Mha_^d z*8$%rtJ}Ydtgm+G<;t&>Ev|@GHTNIl8f<_`pf;-94&H-nc0d5W8LVW7NQ+JF*Xo?xRT)x)$fKqS$c10TR2;Hlv1T7*Oy!r z2|y!WW?h5DWil6R7hjJrqbHFw4umP+ZA^VO{zZ>qV}^6^HuU4Fr8J{Ea&%0zuTr+Bk0)7Z=QF+soRzLsrFb|gYAhcU z`mF=kL1FJbwGLD9a-iquZrvoH1bM0f^)TxLZ9S}MZdhVAn%iS4&O)-ssrtCDf2@1j zLCwM}F~&iz67CWgBT`_D`N`Kp!J8&DulORvlk~`_l1WW*s1h~H-JVd$pcs%(D!?`9 z?_x1m^UO(NW=}}zN$_H9(qC*lFInBX^9;jZ!fmNKf-wi3lxY+&GH%IjeU#v3w8nKl z&)J0k(u-)+%PnmLVThsX-Uz_O3(y+AllE4b{6j?$OZ9L>r;$!ZB6_T{b|;81_E&09 zrKTYn$uek(FvaCu??C}ih@4#^NuBU76AQPHMow>yO7DBVGzfi(?Id`3;QZe_^+rEU zs&{$b-kWPKP7gdSy3^KI$9(2gs|Ye3z$`!=U*mpk`vv~o?`#E!0C3Yl|5kywKo9YT z>9(V1Y!p1hRMLY>gWK1)o~!MCo*H(CJ2WhE?s4jQ2YXf_$|kQA@Gd+Rdb!A@X|D7L zDvLUq1;~m*{14#MR#eJ5Y~Q1FfxFPYwvH7ikv)<5BF>XtSJredu2%)?_rk7ZAGR0M z?VtjEb0rXS7dYD zsSe=m1BvlZhuValXtloAAa6tcD$`Qi{|IQi{@;BYbNSXbb+G$G<=Pj z+6yLtGDIS9uVxw1_CU7%_%Z1WttG6)bEiY|?+gU17Sf)_IR62nUF^<~<7L6x7{lX| z18gpM{F~YnS5#p75}m;VhFO1d599l2Cx+Sh9=8|*D9`_w!DZaF@BNZ6A>I%Xf)(DQ za%kH4HS3KR9;5QiV9skgc9ra6NW5~P`ID$;4dD}+K$bLbdCXZ{h{{uTTVCcqvdOJx zq<7310A}2Os4=b$!sEchWMi8_Mgm!kFH=_L&=Ep>hZ54vNy$pO;%I$T@CR$(jY0d0 zcJLaAEpu(h8tB$A21(%S@C~p%s94YHYnFFtKK8#B<;nbZ57PetCLy`{>G|7vnTHu# zkRgiZ=khy# z%qMk-!nicq`y#J<(ks8V^Uc&Y$vrNQ`x)Gi#pr1fgu$%FwXRjikCmgW<}-A&m>~?& z0q-O$9vSkj-Nf#qJR1YsKY_*^dj{n3AkR%PD_A_ztDX~gM=ej+PO$?PRt|uq82iio z4*Y(>89+?nzm;C7bMaFxFu7Y0Dz6%=LBqn2q4-Vjq~0C0wW$zQuU$^V(7Ap3Me{mUks*`$yXeWpin^%$21h~HNM>` zXEC1W(4(JZu#WNxWknrwu73@k82=bvXG z`+_DhS}{}s=zXk2(wT&+uW2$ zjVKmCVt(3Z<*wU5$^y|#ik~cbcmz%emfNiJyNm8s070zQCi%w9lOZWqr*O{;WYnlS z)%8{LDnS-R;EFBwY+r>n^g)Y7+1m!~fB8s}MEnh~)FU|o&2Jb0l;{k=ZlMnAiKR&p z6^k|eRY1jjtBRXU2T2x?^c!Q+-QrG`P&O-t^PGoI4FN{jZJ?RdYLE=g$o8C+BJP>m z7tx+YAT8GWJ;6xGJoA7+=zwaAk4;2_npkXusETThl=t4PO*9>xh8d<1$N{adw%sQa2o<_&}?rwZ%r z517`Ym3=7|mbSd_On=Bitta4K^BC`C1LZyI5kJ&G(8|7}?(flS9&8nLNxTrcck3k< zeDXcYWP|vqfPd&!3aCD3gT(w&SSb~22w52sJzCR(VM%cTVhdBe6G^(@VGI@n(#pYK zWt9(Q+V5Sh_RxjOVu_O^81fJKs<_ILcl3`LaQNSn6mB&rfE*+o7(Lkjug_&Nj(BtMEMG=qb3g}FEu zbaob$R-ae~o%p_b;aZ5XyjD>LVXBatP@n2JW2`))L>UPEq1tx>)Mj=RxnU9(n!RG$ zinNo*Ub5p%L`L(u3H6LBsfu`>z_+pUie9Beel#unTGfP^AzEF?L59FbzO)xwcC-nugaYI$#6yjBjyrKo3 z4<)sY4TqL!op|PIGml8VT&qBy(C(7M3w!e+Z%n7WDwBdS%nqIRF)$8Mra2X4ht6N8 zu$ng+AxVi6jhkn9>PpkK#PcY_djf%X(vIPotHEQk#RFN}?fBN?i$_%g)PLf`)uGB( zB%-HJ<(n%vPU*|G9e4NKGDZ3%*B}to0O^f!kY}R3&v*Q@Ei$<@TsT0vC=rbds=B;7 z@a3!aESXPjHgK0>4AFw$P+==@DuQ|}YM9?26fIp~m7dYwKW3Z+l!4?;1a0ORW}jUdP19yKh;3Y`10e1jV7@RfOAl`;*5%>7@G ztxu5x0sYmDCM?|9!|=udFNeP@?~{WIBL)d>;^RLdbn?Ef`MWq{3e=#p2w~d~cCfeS znt%|XGs>nBJz5x@A$5HyR-Y|3mp*T=0ParDz)=n`zK={n zmm~6S;jMW7w0%j2eKdZYq<#j^wwp>a?t;D!+`^Q_VOF)Q0SD_A@=RWGUQXtYpC{XWL?Xoq%~VZzlKS@C7ZJxF*Zyhf9rKtdNrGQ0oyN)aPfOp1Y`pwEnhr2`IdZaDyH(J zz3G}}+&H|65b4bd&*TxjYQ^mtKa-P~ATmpiSp#G7m6}tTsL%=DEdzFVs|hvJXTd`) z*(&!~lf{SrKFPDbmZx61&2W4N{UqdzH&TJ|OrAv578~1~a`m@We2m_zApBq+y_8z+ z$8hH}49Ma+%L%D~nFq27@bfqc!=1aCvz~}nGNcbXL5cEeyh+jwBaO>xC*a#QB{qX05IQ?I zFmsM8U5W(3i&2k$W_I~76S&fY@4|uaWSXP8;F>eJ#tU&pUAsHB4d$Gw6+ylJV*o}| zR+b9Sw1Uuo2HzK)w6fZ2jjH(_7@M)m*xm_%kki%-ww6F-q-}Tl_y{aju0gq@{YB<% zs%aSjmL*Dh3JDYL4pPREd}pF@+E zc^}6kUe<>(b5l?>@&FHMyynjWYhcRe)v7nrG@b)}Pnocnph1fd#*R&>p~j=L%fp*2+1c|IBEPx62Zl|8Pki7089a{i z{ZYLR*o#rX7s{hCZu)%i%5UgwC;B&y3@|xjy7u|Bd8OAACl=Zp%vZ)+ZRs5tZ>{}E^Jn|S-z zbIYeIo5t$Sb(qDtUbbw@5G3sPI((S zNh|f(8xa1CevOclhag=;?x%f)v{ygt{3>G`)m4e}fvY!GqJXqk>u9HTtqO}9reAs& z#PJjMGUn7{NA{BNth?N}jTfJdC;2kE^Wn8{OSw}aFyd-WOnL7Qu@G|v>&2!o9~WD~ zqCQbbr-3I*VztURtoGxVKNOPjg4cKz5}N%{SKAjKpOOY^_#Q;M{lF6MK(GCcE z;Z@|j&_vsY;1c9QDA9;{HOUZ)Lr)(~kvx;SKc4(#(NS|6G zC-_gj)(C1cA;+-rWb|M5KKy^rzqGEz$O>)P8J~_P3~=7n z;#46LZh7nHytta&`+X?p2_~6IYL36~tmq&LBUVNdrxCxif@oKZxP|9wg@tzL4mV3O zjo6W0?<#mETamp=O8|CB*(VF`Hr!mEA^kw^z%W0g!Pocy0SFQlIrhGjygciDpe;7(U#@L4vE(FziTk z=KY}KzEe!`cSD@ibGylv2=aEM@ZO{w}hY8h`7*m=;k$LUkFl3p_MUhWQU3wNM}BCpn7KPP;zSuF2}s$^ycKd_ z|3b7p)t2<8D)@cRdhcNykU!_^9nK(`+a7`5J9GASn=n*bSGrHtOOO4BNSsD_tmOf& z|LD?Q&>V{OX`GSNa1!r)|0~5? z^YcIATl3;@;kb+ECnr?mw z(7W%=*Bk4;FJ*F;{2soyWp~wGu)X`FMAi+1;9hz681T;PI9qp5VyuflO(4P9WJ`B(1Dr5q2q{!vwyp670tAG!B zV=@QQ@p~WR=J6^3yR;(v5jF5BW@*T@7c=s^HZ<@%pWU)ezqw+K>(J*SoZbSa!rK-9 zcj-#P8J+!xZx4P3{3UO9N|&#uKq+#%c%UEnKY(g{S8~fDZ$9xl(sRrUDONVP{7pSUvTc+SUGn5j0T5ywxttK{sWA@j35=Vg`1Qx!DE5l{k^0;Zi(ieQ}(Eg?~ysZqYu=sle!!A$?tZaG5sn6OAA@blZF zIX2N(cg=&8CoRgcT}ai>?~g{GgwRIiD8?S}GbZ>iRCqDs_lDJO z{j5)RftvQAiT#gN9bXPY8788K`lf04eQW_nj|*shf-?sbA}8FWqId-V(3%8HzZwi{>gOf62aYQqFu zZW;g2N$TD}DH_%E#thc&&s?ZY*E~CpFxJfxsqM!6l92s%`g6C~gTd(0ESOQvIU^C|^f^-g1dU4VSRT@dBRp7xot!^^XIGve>M%ba<5$(5?yVm-p~ zFw9+k95PS1HyQhpCZ21(Za9VSPy41lNt>L@q$QOrGy9Z?hz?Ihvh@;Xq4YJ?QqS5G z7$D!`E_WC19iGlc6;}CWpEDTy zD_-#ZY*eb*^7^@9SAw&PUH$S@TcKRq`vinWfNcHtL+Oq&#_Z&S*XwTPX{{Dtx|^{U z*36x)$QPW?@MH#e6i)09X$-UbArrT6kX2(B!L8jT$DTye_A=#G^V)p$$Zkr$bnH1_ zs6im zE&9QEg~Gk&lO_6T0(LFF z!dQ&KZq;LjhtZ7__+T@Vk-ziE=~*6P$2X%eCel*6{%-Zw&DktaOFNO(P8OoIx%~WQKSyoy~Fsr{BG%@WPZa^T#M24u7Rs`_WV^y z?6+7X9xU!-eNg%T0`yF?vxmbdpHBj3vmST&qIXk`qCL-YVNd;~30|+ciKTaP@K=X( zG-^l>nmSg^y^N6N|A&Z9_r<25P;Cm81O6JB+_kQf-nP4<1S#A-aV18L8;sDH5?Z>W z2IWR?*#9btay|*pUpLrC^BdYzJUh@)kEs?Jn!^I8?n2{=w?lK2KIcnA7oOxh-pU4~=1<9ARuIz^dG!7MSjOLc=Y zc;$5w-ibiM*tG<EBd&RjC^Q18B{eAM?YeF%i?9|z`La8w*Cd&z-(R6jQJv*IaW$uX5GU?WHoz$u(+a9cU~Hr6*iR>?|3eNuE% z4df`0gxm!BBL7d?;4+1u=+sjGst{JmkO9gaWk?^o zk@T{Dqj!t=C<{`a=82$n2wFaf`aeJ`0jhd6;_a4rm4vTi-Hg0xlEP@k382JUwv`tGx;?JEb?DWwgD)VLb%Ii28I%3;)4rfJ5g6Gq!5 zq83C%1uMs&L@|(VQWda9BB#NnSs4PS#^>IepoZ%ncE;^RKZV>c@zK_sl&;Y!T#;Ee zWTgg3G;(?ftAJ=b6_~K0q(CGXbg9p(jcsnAk)b1W9&2B&a0^K5*7GZtGlThGLIN6wU_jO2xc5MvQ_aL4`jH>88Z}gr55c9afdsTx< zR47~u?Rmrm0}*+Xda_uf!XAUJ*cu$ilFdb?M zE26|ZGU5!CG-p<=LSpX#8hmSuBy=uuQa(NZt&PM|F=d)#h*-J;cjQ)rtP0va~a4h1yM(QcF&U;({rFITcgSK2f0drvg<5TZM($4CSMA zcNPMxDmpSnH+#-#FH;NdZ?YsDI4k%oo)FTR=G`g};XX$OTBo>R2r`kM3MKnJ9tc=l zQ%@#KnpxhalK$7z~7pp&c*Pm?aTFzLpfnpmBp?>FiUDws%rRlV>vPV+$6Sm3UQ7r8 zsbD1;5CIgk_#uR8)gZy?3(!ZtqI6~)jU7YI1qAODEMHiZOQuIPk-fUTnXU-Zghi$K zod%V227S(o*|$XHOf{y$NT-||#g69%55oLbgGi7llj3Q4p`(fSh&+vDYGUM#a&ORK zj)p6-_op^zh?WEyQAf}ozOPyf_KA#-vUB@5S%mn?Js6cz#-}UW&w}fL??!lQz95gc z$n=-@$EnU5#&2*>xIkIYDSyAcXC_6@eO0X~TKUdWK^`XO_C72z&Ld`VhVS{>A99QjLs!4vw+Nx1P0U4*XJ zoY`4Vil{XqQ~?)P@Er!bjTg0|C#!kC4DvDp75p&Tnc5g#mmwY#;Os z^0bS7$O5RhzCu(|5&s_lZMHL*3Vz9LH}?bK>$fIkhPW2Z^u8W%5sip^_;tT^d1aGZdBZA}=68ZNK4aMq$>z$^X7CEx}U&vb##1Ef_Wj0~3G0 zSyX9E`X-S*r@76zODHXjXKFxM8lYTlTKt>(y`1{VWD3eAUR_mZW5wI#=5b(6w(MEGK zM}NBfxhVVTX9u+Z>8NMFHB!c>Lz_osS*O`f^NMEB%F*idL)Xeu3H4EZe#TKp4DG0I z`KRfwouqF^AFAW#$g%47^LGdg&W1rRcP5ci*>2mzbef}0sIsK=O+MwMLuneP*c!_n zw^oW4R(J%FqXysYI4J#3X~~4%D(eia(NP>WER2Xgczu`_q--n)>!R&HM$;S6RRq6H zL9fL^mC%Uvky6WGhNt8qG!JRzW`@*5pE?y9)%`t3#9B?Z>n2pdn>;*j^~WvuiKeKs zC41%x;ffuARd}9eqjzuFpCvTIw0Y)xEWzlyhPfPwgmw@a*I!2Hp;)@94)q5c?$7U)NudmOM;JGQv9N9mKs6c7)TyR)5qKhZpojZ%wfBgFeJ`$>o+1by?c|l-{myI{u zBFtsLTj&Mz=yZxVxKzH%Rmm-&Ss!Zl09yhMhmvqViT(#L_;MTYgLcX46&2_3zUGTy zplP-$6Zd!c8Odl$eC_ZlSFds`f{E(R-yMarI6O&3p#DDqk^XbF{Xr1L7mSaS8{#6* zz-+3?S^39*n&0QO$m2xMd_rdfOu{2FQ{q?h?}XXj5Hs*3^y=UA+G_srin;X+X@1Ys zz%$N@h@Dw8`;*n;gZ)OM-_baEOY@m-C-jpMc7)R9zj_cZ0Zc~qnZ>~=sJ8)Mpn)-96twkb%_JPeNHj}+~T#mQxW*^eC z_*gaHEDgS5nwAn5Wg}WBIR9Uj^Z%;?l33I{Qg|b>$7RF#6&g`tWbyOls1Yd7_HC|I zIZJcrv&S+M$G0SbFe{g>^~0yMalAj$O04EOAfXbxfE+J_uZKk+A`CVicH_7XGiW|r zTZa*Ruh80w_d9_4oD;)?sdce@o6kRQfyZa_iYMYm>-bEeqF*nw*mFiIV(Rv>xTxb= zl>6I6%e^>~y*Agf)A%EVyQx zWkU)au<{{IzTFeo4Q^$F7gu-kIzCvw3!D0)9T@cU=d}j)=^MpE!-(&Tdco0;?TtQ@ zLO+w`Vw?H8jjW!PdSm|`5$SM#y;>#T*vq9*oZN#D7nsoxuI!IJqL`)uih1oMClrps zW?57pq|Dr%X~dG3`mx$#Tm&f-@R#^ZSQFM#yov5ifWNXgNLpUs=Nasdd8~`Z3Zg_g z^Lt4lMFbgql!>DgYPV1!{A<^vp4P&VzGF=3*MFK#6pR4N9^1N zretVzjwEGDcd=n{GCg6rMCc-H8Sv_j5`>(p9)2vl;eQ1YnyHel22nd4IsOju{`}`~ z0FR|fkVpXCa^BvLGlsT3tqV28+29A!$S6@zF$rl8-?$#D!ASLDty~bqC|zEKETBvl zL=Rv+mJ^3qWufW65XXUzp1V@$gt;ab4L`Rq{*wz_%=%Jlu_U_76o6q)Oa zruhjLi1x0kMxR$Cz*ek=N^2jP%42`_Qe%zqOJU>4HO<(KA0zr18LdZp+FAz~DlrO+ zE*s_{;i3=ekCSdw47g#o3!?M$IRe+Du6w$PeK#~>uj*`RvljM9;Xd|Uiakr#*Bhli`Qu|vT~Q9p zf*X}Q9_~tM1d#mM9d}pXZsEk&ux}&jp2E8MHvpimlc6YfANq8>$7u;4iPF&}8HvIS z7tk&--MlNgYzBR0N55U*go)R~>*)WHbj{&$bzgVlq_Le$CTeWkwr$(CZQE*WH*V}S zwi~l)lk}VS_x(3B&pGFw``mf%*=y~+*ZK_Nj$p}4ab#h`J#B_aigUS`!-_OjI#c@E zQ;^5DvzYbXbUW*DT=6gx9-@|mh|W_G!&IoYNJ=A}`qyS9f{)e9-J*&YsD!2TRqiAU z3OO)xO*^a=T}WClTbU>0GyQWZ7MH#0qLl@IBkWh=B{h%B`#tofCV?A)CM0 zyy426HKnIlDg;nwRUR_G%iOMLH?K4feYB^_uhfl1rB)g)+U2`?(FxGmEF_*kLOl%O zOyzyf)lopF91FV|(n}#X+@bQR5?3`nH54AJ-Vr_pyhgc}^*xE(u}kv3Rpo1k7lO}F zs*mU(X+y8In8QIzT=k{bJjw)$*aj~fIBE5+4>bpR3*mu@{=Rg%U^du2-3|`>Np3j! zmv9V_aNAG>95)m!Q`MDEh|iJ(EQB&+m>-%chKJ-N0UGefs_=ja?0fs7 z>IMe1JTXGd#c97f9^&S{Rz$?mu5V)?5#&o-iiP~N=zZ4GA^A#1)`>O&UM7+tZ5-{A zcNE8WG@tWk`|dtPn=rQN+*wzGpmcjkM*hC6+%l`k-j?phmn{q8mbZGANV`N-oTWd| z^L3Lmw>U3oJ*eL!*Mi))WO|V{4hOXIPj1IskyZNSpAtX?$`GB63WvUTFb%JR;no}Z ztypV-Q`2dRm}ZmCm4-khT1~5H{)Rk!$Ofat%3H0+0IbikxiSss>j5}=`Al*M8YT5X zGx_Ve8I29(rcLBDhU%l#)2{sf2H>OxZ=#)2dsB0jY8~78w!LD6qrsci@2j!^La(S1 zlds%J{{R^O0Qxepe)Pm!K6%YU;H2Zw>^E%-&nn)$n(_dDCJWVc3m%=eE<6ccjd5lxZ~oJLh}9fb)h4#RvP`L~vAT=RMe%{q@CeT?N74 z)2I%TJ2$~6Q$YrikkF5j5jw-KD=dE^ND|wVN@|F`WvBJ}?LRv4h|pYcpOMGX-sv4s z-=$!1iqs$eqN_JfKGIf1y%v#UJb8peMb!nZ(!gp^t_B5x<1K6QFsfH)!M=Hs4XJF^H7nh1B}E}&7Qs}e@GA%e2BLE0}KxY!hbpq=`M~; z!uf7ocwx3&p;JHGW43{35hoIY;}GF59VD@pX-~2MpHLe0&l(*wud+f2A?p1znS&Yory>Dmnup*(iQ^cOM*YhB%M|RR+juk{5%Kkt zj~)Cwl~ul~GagUZA1X3~Kj3Me-rztfor#>b^im0@%q(tt3Yyp1fP` z(O*nKjf%0XVp7LZB6+{14|h(W99^L-4mAq&OguU2_FzD(uD-fk#mioytEuY~M>ffv zqltP(wa~g^ozIB(LEW2HR+QRmrL)GyH=b|EumBP3KJ=`;8^V9fH+I%F5<5zQgYfj< zPuP8Pb!e5hn@UFO7rHH-R!SQmlM?MJT@n#PQrtv81C&^Qh@*0NY`ljycxXJ=4lbPh z4$?!{-`pz&Q`AaU9ljj_`rY&F&g@P`XcAF^=zCX&31#!=rq;`ouC@*(Stk8TYVS4# zX)6JJKmSKu|BQPOP_L0>xwgF+@=4xA`p7N#WZf|-C^vEWuV#mh77n=0%k%%#Le8h z-*FR2R@g>DTQB~RDn?|SIORr;`p!o=Ic;aDp^ZX~AX`!^T z^Yj|~A7D+i{y}nh(cueHMbhl9fLC5eR%`Ngji&6DQCmjg8PQr9RJd~!0PspDb~(^5 zrTOhluxygiEk0GX(3nOsRA-)(*0lVgDwPS!_9bCtZO(3|j~9%HrEEJg9#C9#U(gnv zYILcSd!XVQ`V)l6vz)YYvclT^B!eDiU8cUqrcm}(@O=ps z>#UoZuHLLKeU_P{OI=b7eXQo}`44nc&M>+iubN>~G_HWcH zqI!G*I!G>9v*|X8kVitdj%oB2x_OwzC zb1L22uD9;`h*@YfcQzx? zKePwr7-pUP-emvakf+<6YbuN2sFhHwqhGeFJHzo5{&cN#fQFa8hIM0mh>+>?Eqi5x zV8t?@QRv>VYmG|b(|OB+C_1A8%-D(tMt|%qK8Eq8Dq5(mu|4Vi&FDi6m3UHGFUaSQ z*_@v(ye~R4kD00Ude#f7A!R&MglU+m#Yg8SS8~0ZA;w@_!)yWbA+|oPi$*LHhw?wi zH3EtgzoK6m8m|qBKajEd+P33WpPMR7a}GnC7D=G_jFybq#Q?tJd__}*u91?!7v(9o zb561)6Nal&kC<4`)jAG=NR)nn$B{_3=1KPq7e&+86oyKXPhd=jrUkgTE50wiR0YcF zfB6Cl(Sx9jBqGZbJ|wGH4we+iHN~JVg|jK@NShN{) z5a)-%Q0Siw(FHlWA~^5h{}U~Th3SdVK^rMu z-2K7qL4buJl1&Mx0%d?DERF)?-8K+3`EJM|Yo0QUc}Si)uqqMk9Fu61h?S&bSDej4 zw0tOP$>5+Y40+QMo+{Z=js)G*1#og9&r%IRX?6_7=npv!+d(u=BMCeECLH%Ot? zF9QCAwN|a!<_0G~3eqz?!{^CC=6vB9!~Aro#SAsHMJWUIAMOds5ZBfMN| zOlcf?1oZeR4kxvUA!G|(G3=8VfDY38;esYm6G{Mp>R&OQ9UEAAlRj>DT~B{PKv>{F zLyCOBl{&L!{~N&y)ZSc*;)bAFw3f9}xgh|)E`CYF0~WAfCA*xbP-|z4V{DYe1BihuXh{C!cRu`xfBAvWIotqA2j&3YU2Z5pR z4UL#H91oXL;`-!P4#@0>65UKpE_0eb-XEF~C7>4Fi@gtp5xRR$5siVG3g_O9y%2yO z#wFcjFHS@3(V~l3lg1g&1OF#2f-p{RJ*h?&PW%mCrmEI|0p3Xbjly)a7+zctwKSSQ zL~#g*_bWhum|R>I5&*&OQ|b$TvJ?msky)o<-eTUmlp4kYiYcp9Bf@L~7+h#T{51}F z2%Ix-2|E-X2x#{5SrA8@8A-6heFM$;b(1U2xd7G>1@ zd6xydhNqpw&B^0r{0N0%pChDg<4F%OHDPl{Q-D#1>iE`e`2jNo>S*1sz`L9Lm@6~w zeiQSpnA_-;&e={1n9gY)+~YVub2Nyedc2)*FGN&qJd%XATrGdB2r0>jVs-v!SX#5o zu^3udC>Lv|hr3D*YjTCE9pd zTp!K*syoK^Pxv6IHQYZ}&7ZJoWM$jg#yQBu>fqJ6E?nPdqV3bV28Y+VA3fpW@%4nW||VIK*aN_e&? zvpB1zNG?mP0#hps-9kR1)EE0DDyz;C<1g|Qkqw^nLk4%f^NRgvO4T z?9^**5J_0~f2&fC!t4Wi6_Z=`a<@q2%Iu@+s;U{)_^6xr^&ALC9mztmZkc~S(GIN! z8mL64qI3P>{Wf@7Iic_WY(LvC;=osYl{k?Jm(XTSVe@@&x8RhNB;Jd65T$w)fq;sL zzU82Wk9ZWYWeK|}W8Aq`G|P|}CAr1vFv38b)-QInn0TV`<{?RJX@57^!$A? z+yvjJab%}`6c(gXnLXyMb|!7nM9Fw13iv`SvRFinzb5r?U9@%faK<=~YXMy!g&UiE2kSo%!2RB_VO*tpO2NLzP`i8AhPJDR`%43bQqvO$ zRRoyn^{M_^DMsV4I9&GyIpAJZV`Gm`#WCXfh0jAbE%A`-p1nUEbe-|C0H-4!1^{O0 z5V(R_dG&1jnP**pXB#AG?s4`;#l-71()i;I_aA^vX%Q!&xRN`6Ifx_tlp*z+$+>m5 z#Ki7LVjav(c@~;Eq?Roc`Ks84q(EGXGl;>%(R~IIL{We}Pv{1;DeYLnFw3{w@lEn~ z2M(KxoH5tJ8HH!SJ_7A(eJ?edm&TN&?JtN0V(!COO&Lr6f>*dOvCH5d2|fyFPf+hC zgEdF|u15)2Jt!$>tPtjvB`;FHgf+f@y3yJUvHZ{CpX>>b5bH#=4pRmto^u zZUMDftGpOolP4g;|v0P%I^)9sW?+A@e4xA@KaNt(D^JEMq)k4CJTLss-ss!4zd-92vXqW!Sy6@H-N zB(XzM>xgaEk6_@BDqVACQW}^^u(4db14bDI4!!wlrK$1tLw>3fpf2#OK+k566eCs{OQv+o_cP ziloTT%W^B={3&6o2!(+{SIY%pS9EhrW&dv=A6J;C5Mss&pO{Rrz}4iv zj1M-{#k!iERYPkv;iHT7QS~CH8M+!ZxgIoqwiE0zHbg@`YW0e>{{YC_J6~2@XrC-A z&J7|Nm&Y7XZ&e*xAE^#UYM<;m#~m~u*oIp3NHe*Jvwh(X6}U7lm}ywK3z&dz#5euD zLA?sSI|25{$eojfS%a)kQOG0FRa!}lnNc5*rreRW-C};OZy9r`H5=Uww~Um{T@Aj; zChC?9!yf1LShgDV8tGqKDs(dpX_mk!@iLJDuohCoE37wY?hm?cv~hNSL{c=!IA$;0 zWs=G>)!*C~5508XJe;Q%A^NUUqglY@uznU@FNM^oE90A6)71$zlhSyr=E$%H64ndj zzjGL*FM_`^M1@GTaxfE1poeAeXpOR5wSy1{(X}EDnPL4F;9tk_-PBndT#HY4(9E8| zn_jRu>zo2UA8l4&i09nx7Dofr(*($IB;wpxNeQ1F6=uG@n)vhFnt5;WL~Zt`PrLSP zc+#xmD?Hy1r%hJg;L4f)gfWx~R{%Rej(R##uK`cLb?$ziL`9e3T2Z>CH+x&ljH}5s z#?%_bvf-kk-_N272w!%j^-(x|r0}t&nT@9$Cn|mMQ z&+kWU4AIkf+_m@~o(FaLk}PdX8!XW5ZqH2c+E4-xx7Z&VODF=z%!kUBih#LG&HZw*F@vV+{Kj{H)qxH6 zgN#K#g_VL3Obf9-998wJV@s2C5UGKuTvDv)eC zvdOCWunhD`r!{sfb9X2d?s%KU6%6`n=>Ga;QhW2U?&#+NmYPV&+T3YeCob|!l#?RP zw&b1>(wyE?+40$3(`Ugxii&mB>OPw=tGW73Gsm#AMIIK&4%HPvF0$s`CT-ePGWNLe z@Y-1N7q@p1(a+~T%UteB@z3V^eEwI zg3BzT9EZplb2|@g#B$+aK+|RMWhLlmcjsCeGkHymcw5dXd9FV)**$w@oS%;8p(Igy9fLiawCqqd-ms)Ik>gXLa?MueB!`6=kr^p;}wTe);&oh zfHPU!IwH|MXIxuQ=$fSyv*`^*B6END;-gIDWirrJE zzs2p=tcTJtcg15Z#8(7FAW7&Hh`m?eaEMqwE9f|fwSW*-O3PJFBa$G^z{bk4ghU$Wh^&imJ*;yi=2^~vgPJJUsiv_(EN>S=2 zC(I($wbPMP_HIe=Tg?0y9ecVd8w^RI2OYtfPf}%0w~Eh7M~i7a>fmsn6hz6gXi3Tr zmY2V~t_BH-l)gw`RgOcE3Lp>-QthbyFDO4#J6OewD4sGB-?p0s4}RfODoprAnecJp zzqYwf=*`AqSQonZ-2@ z6E#Va@4uazf-qs~82IR#U%=z0-?gv8TJp$$Np7@#CRJnq2Q!H0s=$FakCS-FIpnmU z9oX*-d5hL_d4;r}l*3bA#B-f_u4%~pmim44wa@!}tT z1@{hJ?NVFQb>F&_g_M8``s-)wZ(qLJzliAxj-eTyJG%$iOSqLu_5nXrK38uy1uDvP z!&vEK!oUp<6A=4rH3X^tAHU{RUDK{EevQ46)T)=kzqGsW_f0x5E}9gH^a`|IVXe$kMOW9iiQ>~7pjPj9o`WlhInda@?^&^qpgo>i=38AuT`p(G@th#&j{<^F_KccSqboCbS!-WT;5P9fXQvD?zKUQK;_kKGEQdN&Xs z)xNo9mmzx1A!)z(Re>T3S*{7v2l_bE^EZE%sz*^6&d=!oxSYL;$w#Im^BoGLpNN++ z)X_#wJuw?mk!cT^Si#az@kYN|n(jJ97gyyXBHux3uK!J#eq@TWuw_p=<0r#}zK^Re z$nn!7XBkebCNdq;;ih@CRtm|z`;W6y_~TFh$V6=gFLXf90(C*c(r8!RYo)(9>W0Lg z4RlH1+tHcE{{yTV-r*MQZRd&n;CcnS7)qN^UX+Fc|kjiT5oi?-R( z=aC~Ul?1(HbI!bCXgg^!wrSm@3? zYww$L{W6pn^vZ5UTUPC^o#=vNjzjZxS9g848S0*OgSt>hdzo18x35oC4jQLX^UFtS zFDE3mJv?0Yn>zF0tLV8lo6iHkoQPhQt&yEk0Ir5q*{s<53SNhG1HEHA)5YgCjQ5(d zXSuG5ilajzFf^cJP+%J-?}J`<$i1gZYA_$QwdxfD4Mwh-qiZzEzG(bh%`ekX_?xUB zh;c2Rr?R@mAxjsTnlxkxiXjYWjOq*_I8x0l!x0!D6>~B;ba>&La0qnwU_~Hw`Nga% zGE}ngD$xpla1SIsBTu>cWXQ&|nDHGhw?@WU4rz z+m!eNLI|7BRt_U$w_%$E>&=D0H_5&)I>vHhm>wRc3`;CHxT?pX&zHt9Q=CVL!Ij#$ zouK8rAPTol>FZm*@DHcBKPdMlO4^spi+1AllEk_{J7&37qDrXd^pZDTtAx#3L#MHZ zu(8|-TU-BB|4yVT8NH4xSf*qPO(@x)0#&t^NHU_{Man8HZm6Uf6D)8d9*i8mp)Lux z8Z14iu75!+B2iB+n)9G~;)zZ{4DGiNBb6H=0tq;q1y|2dPpLq_mcmIRM9cD0!YNjZ z%T5}gmxDIzJYk`u5yVA=67j#OhQ+3+9^A-5V+Qt=!l#k@!g-7iOT^NY`^e9A1W-~FQE2uQ~pq6(7u$~ z*9_U@Lw3o&WTeX&XnYA*B-r%GtZwOGX^JWqLN=Rc7kV1oUr_@S>Wql&~D~ zp@wE5HPUQYpZhZZ$199e@|<`YQx_M1cydSLWmzsDX`JxSWDkU4 z)!=hEgAg>UQka!kT`J$=P##fz*8B-2Cw4mzb;;1B%`!zzrAS`z-qO>cP6=1YPwg4WHCpp6y8+Jqx;<_Ubw>x=m@2QU? zn55?uoYcXFx!2abMCFP|nq2j5xmw1}IMj<7?jho^SsW=r%-`SIO{}tYlW|lMn?efq zNLKbk7qQic=-id1R#I@FgJnDV<(f1%@a6RzuQV@hdYwk`%Uba(YZ+4eEVGDqjZzRe zL2$l$^^n?USWTzg7}4;~NE=t9S$>1tyxCT5XOY8o*y|IDm2a~!-!#LI8tq6{_89nw zUbLOI%eQglkcKzI_P^u+u&qY1;U8czQ-PpfM(je0y9MByfNnO)7cP70i~%Ow&fs#4 z2OO@+Cr7~6hg74Ozm$V$1aMebiWMCY3#4gdXD(#xDsPfJozjn3`R$s#*SxBf0|>w- z!*S8rDJMEFaI8Z}aW=bW%1%#sMRVmoGHclUo};JhfwaF#rILp8S}Ld!$h))?4ED;j zsQ(sNi3MFO&HDJ@AmDub$Z&bN;Yqp%48VvV1t1B+>-6q;$rrJh#S z!End1yG`xG;0u4rkQ&O|#XDx&U_=Kyu=n`?+>|-s;Rvc>Y3Y@ffue4-IWH*3#p0t) zx@lPhoTCx&(N)bVRH7ii;q*PVpiEtV?VhZ=;BQlFkIH2-Q_INgB8KZm;|RIYGRn#dTUco0&yQwinJO+F}{RxVHA z{>Uh{wJ)d_VmBOaq+=jr_!+?`4jT-1;q55?2RN4faEE^@X{Y`N0GWcHtZkrme}ti? zE&yc->msvl(pn&6#y)XHM2PIL-l?>5CwVi+{#d&PBvl;?UQrReB7ZtkGDG=!0~T3% zH0)(Pa>k}MX3F88e*mfJ+^&NcBkPeaMY%YX_I|KL{|Q(!QYyECps%q+4jC@o)1_x) zm(=X;XR|mmn=Tj843F^&rIP`q>;PFwRPXW&w-{E(~(K)FTPX!SI-Z()VGkZAplqq1Z`Extz%t(8=}GT7HqOP zrZrCA8TdAVGl(%H^$&ouqrouO`!{lShy_2bZ?M$#zT(p$P-@P`I{-{yyd;z*43$1K z5zRo10TV^6{z@+B9~2kuHWAGh^DOZ^8=UtgX&|E~nnm2eG1{&_5S`z?ez{1p#&zu& zpqR`#@3%P)z|$Re80`{Kgjl4Cu}?u5{q!WK~$V&o`T1fv} z>|i*Qx}&Ri4uX~ZTKbznJ(GRsu6+Iq1FGfEsAYq>TP2FUj-j73<0_KLx!FX^jEy52 z-~1s@dBu4WZBod^;3S6rzOU<}TzeI?5wfJWE}qm^Zd*b`yc@uyYa$<-`ViwhHn*BrOnu5H$zqLUTtA=Cv6ta@OVsIChSuL# ze0rJWC`4$eZ79F8tbhOAvTSch89hEu2uc?+>M~$!Qm;MoVr%^k@Ky*Y z8d*JARlYZg!Q0(9nbVJ zdSsIo6nGhGB+`S*%!c^hN^s{RoqY!5W@!;S!#QGe&mGT+x@7hU?uVu^xyU(eG^{zO z+#P5wactdp3Q#Cf?R^x;$ZT6Vz^fh2#&nwWq$9dZNm1D({&RIPu9oZLK(A=N)+POv zUXwgRTzFb!`bXK@7p*{-2>tcE4;Cju_O~2orj@BL)=v7GH{DG_6^9(u{lKw~!X#?Hdo&Sv_DnG7Q{fMlA95ek(^-oSQa z`^^s*Le5%Jd&X$V;hs;(Wq?U?+W{FlaTiuCe98^UZG@ToiadH`wH~MPbU=>C2Tht{ zEapp5{Pm&*&)VeL?zl#%BO%YE9AOR)Ckh+FD4yJr)-q)|pCJj*9sS3*A8Z|HFZQ4A z%hI7lGcd}!2hjM)$x<50XL=_6+au(o7CA3|9qq2QGvt_ZnD=E8GtK<|qTKe#KOIj9 zJThciWn841?W>i?CeXujV-FkbNud+04)U<{jgbq-xNSZ)qji2JdA2RCqwVV?xy zOFO}kUu#>1>Z%RMyVbO1CghEx!F;n_)Tv66Bv9vsMhhBrIi%YE19l7oTL8~j`~z%~ z_=|x*iTDep(RdT>bZ8~;R6ae*3-C))L&d(a(b|1?F1?rMZC7SLifXRskHXbR{~d8} zl;?P4ducB@dcsYxzKzW5!G>hX(cnj;?k1L}P;Wyd6&@-hRDf152-_Kv@*a`nI6@p( z6*UXX+F%i8mM=A4y<#Rd!sOM|BE3eu{%tuh5Zkr?;>^Qy+NvY?Sm#;Rp(>WK*v`bo zAClm#4eeAA;DnY30le&crbhYwcP<|lg{p!SJ1hDx5&r;bO5>~EkrSV1K;+bGUY5lk z_2DIF@(k;xW2JKg1>meH3$De~6n^a&?|oGA%`4~nX0Jr9<%Xd_yN@&+fH>NE^ay{H z8bw>csx8We{nLhE$o=ti@i*U|=X^&49dhc4pYV9k5#xB0^l4#yHC{ld?6OWFCULr@ z#~uEhnh`{{vKO*1UXP=NCkEUS>T^`LUrAJnYH0z2?yl5oS*x>0Gy14;Ev19%(FgM1 zo*;Ds~;ABz|GXd3!(M!6^@k{h*k0a45Cp0w%|% z6X%Cj>O~ag*ruC39dXek5_FS$=lS2~qVA+Wkx#9#a*r;L72&c!b8~kD$vgi6+6dFf zkJVlE!=SP|xh%Z84r}`(3gcUVojNF|Z9hXcCH~INqatsm%jDBG#_&}DQC-!q! zf}7C~E)X}pOmZv?d=9@28;xAPjk0v!V#u?% z?M=Q{E^oiVG8&XcEc6;^hp-!Y0G5Yx`)xmn-Qn(fA2m}u5CLcWD=U!`AkDf6iQInL z-)6Jlxm;yeWQ3?>Uc2b+=j1%Iw+p3z-;$@RtI(>e!W$&aM;<6h`*Q2aH#>1_D*qy^dkLatq-ka`xb?uN1ACm5=1M2 zb`(GZDMzv(V$*h4AbK#n<+x?fmDTPOD3ffy-m?-3%8<9DUvjfPa6SNQfD|48#=}%i zaTf&c&bSpab|hD=@Rr6^%hFA2TH|+~4M!9bh~@H6qt&p#c>CU6v04$=h$g}jN_C%5 zJ<7Z*<)*uo)^loF2j3Afl-Cv!+3D&l!N;(=f7uY`Eg*2;M#a=7yjDv+&FpSrCkuF* z-@Kui-D=$>eyz&CIYRB1kAr=9(R_MheQ{A6??qV$zeQ!(DA-BJF{q}O+djW`jCk{r zr`W@8s+8$Lh0Henjt9re<(e~1D~3y(O2)zP-5wL@kP`8yh2R#o)k#=XufOvXbGlI0 z790Iya0tlA7Q7RAfM8M#c2-7~d4ewDZHvEtA){AaSe|jDGV3!pnWRyNyD^LBwS5wG zyvKLz9Yl`i@2kEUe|hhptVY7Cv~YLs-EZsSv!DV{aRdno?#HtFcbo0>Sz$N&5(_eY zdJKNwB>CVMa#8Ml5O6Rlz^NS~rwVsxN!b`NN!mn)!V1Pv3<3Fmb$Top zLfp%bI>Fi6s`$~eKu!E}<({i22$J#t8kvMTY)C+#*@$z|-kiFtJ z=b0pKC^QW9Zww$VzFQnoJ{=m4_Yd@uFsVn>yq+B*x@gXgoKjjNH)}rQ%E)_DcxS#)y+O+JcqbZUIK|A^f;H+A-%{0wZj*NYp^b98axal=v zR^KL5y?J9>Y<&@clg$V?^P{fO7>Pzh4PwCcS0~$rAEHP3JOm9t(7YUX>p5>ldw#On zAJM+8xT>TdR3Ac(;~v2dmiySFkFNtb1E#w#Zo)fV<+ryU&v@!510_ApxA}2VFkqCV z#+DcaR|`sXQB)!xmDmdR##G&^6!?!Q_DYHaQ7`GsVzy${N8q3E%|;-qX@ ztdbbYk-y0q#Lf&sbOj5iX0TUU^gCjRzBA8d?H@*mUZQOsxg27{{U>YHHU=5 z(R-O2CLPUr?pHbBKeNRI3bSB7+Ry%Xe|?9Q0T7N~n_lI}HO|RS_n(a&T_jJn$f-Hg zO^A7_XsZ)$guXijOq*3p?O4Z*uX_se>JtZl2M7?(U>h@|X2>+YBkn?|Jtcb9Svvg# zxR|-*`c$xK-X@o~E!F)0ZNhmm`ao5UtFI~oo`7YDNFsE3j>PQ-zGb44GWQc=cE{Ixy} zwJlCl+so9-l=*lE#6Q0KVs~2bf5|X#Td~b}E`# zm~n<7Iv4NgsaAf=_m1avdl=vPH$O~9J8*ea=HqUO+UjRHw_-fBN%N=~Sql#j2(WE((YJ8;apfmC@K#+!~hKYm9 zj&j}9v^v5cwkzR~w-SS`=D(`)NJ*GC()O9lMei}uYwU`fV4RQbqhpi83q53$V@-Se z$Y(1Lk*byEVvd}+IlxGoLN}vCab0p6Wuo!1rZZy$^$LO$Za6aMtQ7k09hbeFD`@Q? z%r6AeT5<;)D9qyiht1^?MS1oF_M?6#i$3JX{b|++S$_25R zGF8QJ5{nC zwalIRzqX2auLMM0DVc)shoPj|m<73*|s4$KHBQd^}ohOSWbtyP}1 z^KbE$e%4f%F8}cSt3}Z6B^d8!|D;@6^;D6rS#Gy7Y)=B%Z%V3)o?~H%T@Cq+cPA!% zxon!spw+DX(_Y(s>%-`lZ{Ag<+b%DmwN|g(|BTc!HD0z>!D~% zcyM>7>VqM8_iZE5EM}I45$u~v@qv?o#|v$#lS#)h#)lo_@ejaJCYcz_M8o2d>+H3g zS$V0hxgA;5WmGL6tU_@feEwjdYlWT%#E5Ad7A};N(Z@({C_?WM{uUgXjt$&T&siuI znKC^m5C`I~P?a&3z+b_&V`LWDb^@Q`KtE!5FQXNKE}Y`J7z;XR9G8{fpe3WzR-q}0 z8IuGcXaJBY0;wG>iI-kMdJs-3b zcwuVsuKCkP`9*cnN8=d&VdF;#Y9)~+jH}X4bBR>D(z_h4RXJD~oIC@Jqhj$FEehqE z=q7|m@l7&O#OYjPti}?A#K<48{EJZP#Z!U)D?st;0t&1j$6)n+c0e99Ls-#TMmK(o zMOl_mJsGJuVKJqEV~R5@ds}fBzcS1TIWbQ~13FC@bdoQ7g1V#AEG9vbDGGUZ$RY;S z7pf&DTM|-a@+TB3%?X*>I2FCcIKAtd)&WfF;vK zK_e3f#G2sqkk&o+RCFjQVn1c?O00JP=M#BH}d<4PmC z7qAO66F~PWE(9B=>Qz<%hEmngnE|Wf@NK)g9xZTnfl~RGp*zCx#DIloscMoQC>j~- zr65yh5w5gGar}>1qY$+p2!Kc8Gz?>1tKBRlVzA1Kuy3MmG6b<-sV-cufR(l@udBrK ziPgl38BQe++L`VlhtRYEJ<| zIiQ1ne;_&+Nv`clz^=YF<16rabW8s7^G=yRY)g+q$J;OvW4GCp7SkK#6v7;c%JPsuDI-_3a*pMW8u8 zF2eTYd6H=lX!8m{pztgiZls>pUpl4Vox*_QoRjVvL-q2Yh?1N|=|QXd%#X!{t*bWyPy=gu}!QO_+HoseFp@ z3awLP(q&PVg}YX9S4Rr^dP*U1d1+e!_8eVZiZT?b!PF^NXmAY5p^4x!3&&g_A?DIK zaS37y8ZgFLT!}k0r14r+uz8?D6CVR9)WG8_|AGiQ|Bc#0O(67wIi?NUakN~I1;9DX zC;HFgmAFqSsze|eCnOIgQ5qQ#3&7C>Cmg&)kB&*EB+3$(eV!kj46w!+L_;?x2q`oV zV-5R-sy^ZF`Y0;`0%xga=*LBPiB*B$`IY@@e99$GWw~6p;Zu?F^nt+=JH$&%AIrdX z7~wcQM+%%DP|?}p!ha-xcA69JrFPC}i+-02p>FXn5l57FQ+=tJbwN}pXrw?hA6nKc zCxq2aPL<(2t}Jhla&ZLtB<>_bm72hMH=<8>$^HZMe_?M? z+(XM#$Yl4GIzgVm12&kmXfWY1YavPys-g2Mt|Y7J`N-4B;9(%G)}t|GR-)w*B%;`7 z&;ifngW|>8S=cm}7#e_;()}S}+#K;@#J{2-+xx1PvNZlE!vp8x1Bl8#lIXv$1U(jcwbu)!0dY^Z7pO`E%Bqd+xnw)||8V+57!^ z%SqgUok$-^NtofHPri)7e-FYli~haA280M!->Q(li;bKY%O!KnX2T%UAz(^Hd90QPNo?t zyg&0V1;v8w`3%%jzI*CPrI%0-(0bK|bz7Xfw|AvX1XT+~qwz%5nJ1EExuN%q39=1> zt({=QT)*jxiC_aK+U)qGzF}KM=zvOy(#xGp;aMw#u$_k-D`D4Xe%QC&tA zs`(1Bij$wkXU^ul!54M`bKDqE&Z$2Oz%?kWq3e(=#5=_4vH4dr;OvaEy0?XD?Sqa8 zx+Hk8{`6gF4C+PYF%34F*^AFa$A}r_3F2&HVOy3Qpbjz?ewc10gK6pxW5BRl9#070 zaH~7C#a9ooU7DJ)?BFKL)n@IQ%lcvYmT?|yla_)e>^M6y4q>jEJAvY*_8X0@dO^v5 zqSnABPbEoM?lRAW9(MWT>;>tVag>BlD_X87c!}!=xuF~ys{fR<)7fuILYW7#yRf&i zAERE6Yhai$AF8E~WOu6u{UTacl7NaOSeyHrlGpU6^5b^AG2w+NWm>14WD;lG&sEA= zO#^;dsm4$~3B9?z>+VeV)63e7{JrUh6y=~#Ze6F+(alH8J2GZ8*tnV8ti(_{39Cc( z$Xj}K-MYeg%IOW~73!CRh;>sXSBt4L`S}^jMrBjClYg|uqsohd>e-z@(Y1BgViREM zOpt|NFl{}mia0P!fLjEzZiEAxbkiy;imFo4)1za$%=_h`@o>Xt+5&HS2KABZ?$~m7 zKAX?pC%0QpY5>tuYBTY|{6|};TNU_S{sD5@^>8&=$6`&q1p}Mg^#n5?a~Dt)d=B;E z7SVXhR+J7!I+l*SWde_{R_t%^AHj@+-0h7*jwdTg=IjOZn$qo!I!}+Q7;}bq&dLOwA?_r8!_B{sL_pSe1GsFHJ7FW)TY(IDfVs?w#tlJu(WOXH$BYpG+KorkBA5+r6L zw3{(LReXxQ6TsIY`IZ`Ob!nVqL(9-x3(cUPvsknwPTk0nmTN;O>fu5WfPP!SZGP5j zH}E0TiE}jMo$V9zC=g(aWy|5~qQxGzj#TRHqQ?|dJe>Y5N_>0+cLtC1A!@AO)pSqU zS!-$y)2e#fu|Bv~m zPf@!N(d;8F#w_Cu#RRpTVPoucw+=SEaX3C0ZdBsvpqkL2UU5`mr9B@J6RUE!3-U9a zGM%Ese1YKS+%1Ont7exHGZ$LAJk^IAx;_K@MoGIKj$D$)K(b|unHgDs(jk4Xi%EO+ zN^3qFTB6@oVFPTq!FM9o9KSeMB9D1i-XCL-f6#c#&|3TRTeF@x$pxC4DdY&TdWy#&Vlb zNik>PXE8}nedpI(X|51N<*$T1kP_f?tzIeJOkPztk0p@n z?0!2oUiKskD2v{>l1x@~vpm1J{A$$!_IvV^aY%3;Sm?mAz06D83|O^Q5WQoF^UdvW zV-HO{USHpJJg`dLF;%JNPO8R5WJt^`TGhL=}*yJsH>J9p28oL zY^yFyAJ`k_mUIkgKhbeXb3*Aev24O3Zspu1OaE86*`B35rD*tyQB&KvbzSaTd^yuL zZ9;dUn9_|Dj=Wz$tpalu!?GKqH#y_CYWz_!|BJ$8)yD$oRDdF);5X8T0Bqyz17mRp zS;IP3_vUJ*vbn;baqAH3iuN${-y)$YRHcZ$OGlYludstw6k9&@zgnhunv*LY*xp5B zNb(2ME;Lz)svNQzs*MPm67%7Of#^`82dmGiih+5mD=%6oc+x0R>U`3h=AE*2kvDgB z>LzVPNKw=0_Gm|JONDc`6H{#;()PBd?1Rnr89y`k%+&f9D*j-Dm1C{*C))4a$y|5D zZ78wY`>j8|w5v*6)M`n0f2O>Gjyvd|9G4Ht~M=Q(+ej?(?QjfTG3@~ z&P%#@>{;9#LIDn&^2!ZyG%}sf^fc~Hm;RkaCiBldLx`a`%Hol0&<~xSxK``eFN!P@ zfy#EZd1CVo;33J_8S-2CJhGH8mqC#fG9eTwlf%*jpvke~%T^7ZoQ@6gp-FCY7^$!B zuC`snepo{+nh^5qE-S7OlFnmK^dxKt#4_=X-A~hb`M&wzSI}Orc=%GehgJ#!R9%i(!$!Q@zVHo6+vin z*Tpie_izp!rd=4CuTfnXz+y?DPVpFkgdj(*D0!E-OqOq#oi?Sb(y1IW!RAR*Qw`aB zC||0OpA9o#U@vSP7J@3xK{8V=(Ir?sz7`;)NybBpF50bsl|4#m6R=e-rBO20*Lw`z zFz3{2@2&XKw?axiA+aTbaT?uj1ae8fAmF(FmG$F})UqAc!w$66JNZ8yto`>Ol%W$}#&}ts&`gF-~XsOCB`lF$% z75M_DlPz-1fC+=jJG%jW?0X$mv^&`f!Zz7G>xmV+(_P5%I%sht@E7ov3a zWn-(qO~?)H1%7jlbGca=c|^aa1fs8YxIVY}p1g1^3Tx@mflHZxPb^&A&bJ(8kdjv& zzT8*xcgxo=zwK;4F8-~6N-};EN-|cbahJ77I`xw2NWp4g3mlMvz;CNq@4$KXGow1V z%wQtVNd(kAx>x>k6CipjX`6`8p0&=_N}3-1?`0u%Z!6~?pz#X7$k^!7_mww7zJTVt$V ztAWmk_+i?ddll|@-VI>%lNIv3lF85Hi$}KKINn%j%z*Hs@bdi+5_&s&RHVHqqso%r z?0dP1%PQ;bBe&u|jB7%JL5wWahUuHIABM0fuIv%|Zfl#0Q@8k(kM-J2F0`bkgN_PA zz_V4)oU_H4J9$deJKZZ;tpX`*8Qp_>4^}Qswnv-!i?fQ73vhjIJFdTx8fe2#^CjrN z<6uvVxm|m6(xoh81#cEuR?nKwxHq=hV{4k0(64OY+p463luKl*;*Ze)X7~p^TH9Wq z7>-q|HisF#C5@3oKM+KabkkvgOETOnl0PdT@ zlO?ozkDYcySX0?HHG+@*<4VuBTF%E+j|O-2zbch=Ov5a!+?(qkYsmflh2O~exNSRb zmqFE-T9vkLu|k%)`-M3S!@<-5foo-%3F{i?L4s%1+!nQcXCr#uX67KHyUdTfZlZS4 zuOKm#b&&GLo{*&%atE|&VT+N8bc57bYk-W@O!i4DHLmt*5;AH>xZSO~4j&K@L}M#} zcyF~CBgS@W@Ga{iyA?-n^m1z1iXFVN8a74XB`golf2(6>O5!3=jN%g{?Ade;(Qo3_ ziE~pbX~tmnl2`+~`-))QyhbBeoSwn-Pv+*RGv;XVC+$7v@Qy#)G89_u{qa(z!@z`Z zFX!U$Y0Zx4;M3Ty9`H(-5%fyMr^2`kQJ{+n_F34rC39OH zj+8Ch+~TybSABG(=UV>5;D~p!GBj@rAgp|?w&U3}%z@oBiJZ38ota`3Pxb@%FNihe ztBJI1Bv2l5Sx66_GYUNF8pP|!(b9qutBsP@= z$=W&%%)hWb*SAdi|B_}))~y>xk6nw97X4;p+5lRlC&A(;Cos)U$FFJGHu0(^xvBBm zC!2Ep=6>Tag^GB-{!E$YZ)n-F0;Tb_R$JbrW$rpgy_&jNv5RpTrvZy6z3)8`Q)v z^04QlFEHXs&`=4!nry^ES5-#k^Cy_`4Ld=2CiXDH$Iq|`5_pfWjuc2sk*?*ULw8Z= zFc~gmGM6-JQ3vvfekST@*OJ@IDemzXgk~@WtoBdG1+p*cRc%L?1yp6k=-x7oFhYB;-(n({=eO}8X-en88E)# ze#oJcn)9elc%WXy$qKmIXlaHUR87vq=03w0Fc#0IS+gHQMJS@l`+QL>6CYz4>SUKz zB??Z9FbODl)K<<` zbx|<8Me7Joi@|?30>`uMMO>0~$HoDnX&SK{L0aPIGKsSied#0&14~DicaFc7FULs? zzJgSD=awVjhQ6*NA3rq&=ht~?gitE**RcM}a;2Z9H*3kKJZ^rJu75~Ib*|k?;_L^V zzi?Fgz*>^6!8T&x%3tOE@2>v<$5+cY=(qdBiYI;H>)us%tl50iXGj>o#TEa`Z7SCl zjfJ{bO^pAYj;g{vj+uW?6`zi(jP=p7BaxS2 ztu^?>c`I07Av7TH6Pi^n%pG#i|9hF)b)7QuDOZK*Gia~-wSvL-2POHlFUEX45>i?t z!Jhvct_D0@m%Fu$-FvgzlR&P5&(bBopyvBgS%xYDr< z+^=hSy4kmPw&Z=tvUT|#$_2Lv*54mB#Y@v8TetF#5IcgL#2cB9H{tEIH>I+8lFI9& zzS@+j6$GjeMYP<@MbWIJPxkMc^HlvzwZtV)N}eh5U&$mM-18=+;u>JRwOUYw{p$l} zg=D0OtGN`2H%w`WT8u^7pzAXc#(l=1W*MZJv3w7F6WFE*GhoKJao!FeSag>6G@H%u$r9B9@#C2ojnH7(y~pY=7=DG~ zY`JW!*4jNgR&0*M%{nC}VyuP5F-1v-HT}A^If5kP0^(r6tpH{Qp`? z;7P3$yoq};E$1M<8pZPL|IFQWS^1LnVZC3@EQ&x&2W%h16wEWZY=aZUARXr&2P8U3 z1@~|8nBN2FX$OE;;?5Sn@EU_3%#X-X$|KsneLV9gf ziTSdzaI@%GxaK-&xd7$Zc(#KwAQk>DiPJ@(BJraT31CdSf<)6kVj>7^ z5Wqs%oERLF+^Gy)&p()E$rU+(MdfGACk9#t*g7PtYx2;Z2yJhnp>wcKkw~w_0m6uf zMQx9up&g`T2B=W;GDru0t(5fS<64%(b=Z5xFFeX%;owRY2>E%OE>fR_k>ik0m0BSm zkqAOcE_lxKOl%avn0%nI@|4rD5DXXv{mTC(E-4gCCs*zTK?@=b+XYDQWbsm*TP}B# zJ7jB;VG?~mJP7lzPJv+1n|vu22X+QkoY5bMb_nmtl);2EN!sv8$A3jfu$tNmL0b?JW=XG)%kia}{ZF1VGa5diu`i9RZ}AJ+62Il8Wu{8a zPsdfNmVnSmq7OkV65=Wkr2OTaawz0uJ0L=0N|aV6EkFQ|MgB?7r4mFNkV;i*m=uzY zwOr>V@vXF;we&b1B$*wSc+V0%gX*I_!#4wy63ilepqKKiD1mq&aFYsf>G1&4#$jcV zvS7iEJ;B9$p`<#6n1m=%C!V0vr_z;r1&Ylehl-MX<;bw0Q;F&cgpZvtRJ3%Yaq>d} z_c3wN*df;$E2YfarYfsx5!%h55PZ@iZM&w7YY?4DNI?3ZZZ>PFr!B` zfKNzz=s+GS!UI9f#0w|UViVYrAIzPeIw0C)D_%O7&E>g;plYL7f_R28?AE>rNk+- zQHx%}a@)_k6JN&vIz=+M?=MKFO5AbFJR7=VNUI06IU6lw`4CWYsiam<$VO9Nx(`!j>qX5_jS0HWbv7*GLN*!ZDr z&ykmU#HbEJxWaI8==NnGpfNM$nC|K~-Np&QgLJB}5i7?#LFg4EoAg*Am^IQnco2lG z!8g}%QWTKuSs*iDyX_}H7c7dRla801KsGJc9TdyuA%{H`3vMOg%@-#ZCZ_Z=S0|+aVl?(h zz^Y&$sTiF45zEdCN^L5TqWRClaF;4k@|2h<){6cvO>VsycjOcM8TLFxFgI^H|DQhr z!g}hVo0S~)F*g%s_-A@Zb)kC>g~_gNM>ETyv3gv1KdL>7VfAu!5S@@@TL>J!vGsW?-bRO)I z#j*m~gDez@%rL`y663wZ*cTRbb#vz}y;XG3hNC{o0f+_n#NdJ%51Ci76HS0HZWuay zE*}>^$EDjkg{5MH(ars%*XRcZ)tNCE(^^4$UgE)tVL0c4xHS1g`t59zTTCWtKl8mA z=S72B@C5V1y>u0Hj3+sMg zROZeQqP8*bI)~8Yi^-*JLd0=iZpglQpF)s53u8S?kB~*MD*lj1TvUXdI z0#o}SdjLM6(|OH8?ekTXayx_Rf@`Zob%-9T^|~aiNnLg+liLITRnFLY!$as~q*)x< zZSk50SN4*zk#(h*bJEkWi^(bbV zOI%&IwI6g}@yruo<=L)g@4O|q4#(PX3LItETT;9>hQnh?%LK$v8Ab7@U9-#Zc%y2= z?n`vrDoGQkD{AD%w}XLJj6`;=(#R=T3%knLFF!@t3sS96u%1z{P4r&nT?NMZHbPj9 z3A*SbZL|{izAxc)GGKL;013;$>;_MIZb6`+Ef=kU4e%eJn`7{Lgp8vItVN-jlgj+# z;hw`vpfioaZd|Z?&6YjM~Hk8iy8pIxVL ziG3-0BxFDWetggQPn^@M)joVHAk#g6>Oq?Abu4|ksE-rJBAE(4xIT4v z%ooazfS-^|ff<~Ns3Jgq_D1x@C7MF4z}R2j@|0pt$Y>?T&OHrvTAyEzZ=xyh>;tZD^^Mr-$DTQ z*8P2?=6f!Y|Ja-%n_}jFTCzw<4xUWNiWO=b7jQg2dMR1^JU;%ws7oszHCjOwpsd1; z9?(BqWXC(%!UrIeYe!U3t{LG$$~@>cD?;}skU&O8cvpNY6OMG%tBiK@_+~e=QCJyO z(}sfXY1?|4RaKwnGJV*3q!1^EgDZeduRQB?NwqUhPdNGHX9^&=5`&J}F-cduR!6R=GxM zGzyAbvn}?Te0X;~BktSK2n$~~Y5#@p#8N@>uGy}J;)CT4my(&8eJCiF+gW$%`D{zI zr3uS;zoe+6xg)a3SA@|!8b}(4(Y}{%8Iq4x1Pfslz>0}Z@Wh%0w zz`eSQHsyInWT5z~8oWBUuCZU>=3f0}MJH|5E6{Xnmk75a%!Q{yT&+2{GL9&d;GlJx zbLvhfcjAV7$vwls5#NXTGXeGYpvqpE>ZT-LupcgR#0bu4C4mW$x@Chc?2u-*Un%c` zmVjx6PXPT)-;i~a%06~J44wARV=Jn~W zVf`G3Yx1(z9hIZz%M~epa~L5cW($l5e1hO_nX~ctiQT> z=dDI%OiPPbX{-1k7qrK6r7_RuIga*DKi7h`#;kf8Qt6=EZUvR9ag)4`s!dS?`whC< z;Il}w+#c57)qr!OF0dxIXM-K2U1S8x=zZ2cFd=f8)18i2%a_?pwy@kTzD*h*R?7r^ z8nS;O8cLNvzRCcXkl3(}X~*RurzZ=y>hUI3ZBQi5PjRWGk;Fpm!ZQUB5Q1FupmWl| zzCw5qQ1O$^vdu5ir;no!Q>29B2GUI!tuPl)j;J!K@N*E7+JK z(u(c_ye`$=(-B?PKW1{XLMb}oGvh~RZ+hLr6dC>E8`!8*_PH@cR zLb-fj0h_od|b#nrwhD1`9r4|Sa^uy+ALhA&j8{-fifD=<>jTD-YVUEr}p z+FI?YNjG`S|4I2)I_^B{IBZ|s!&?2a&{>DhvUpQk6W$)t-fYA98b5qxW zIRAaXC@s3js*5z57V%wxT%|0GzH)hf$E(QzX&S|Ox+)iRUZYA93f+76Sfu&wob9N_ z5aYUmnVzSvvw^QNA4j$li7H5ZOYubLhuF{3S$l}5!|&fR*=>P`M2#-9gu!GD9TbL~ zw)MQZLq}{bF;L1Z@71Oa#45WL!ImO{>N~c5OB@^Fj=5V{TvpYdf3)Ur033hZ@9m~W z94~B0t4UJFj*@WMv?TkHm%D^QuIH^>G}nq?(kS93cAZD!_#3}cRPXL0nj**b8t;Xm zxHx7%I=m1GBu__iFIIFtl??yp^}Kf8$?h)LGa2?LMQ{vl`sk@RywbqzQ@XBb*LI<0 zU8#ICai|ny3F|kYQJx$hKZS*at-do4w23(0Evj&%{$QNtA)8&{ot>`*1R%XtE3IBh zJ1@BKC9Kq!5v=}95O=?Hk=}*1<_N@Sc#{RM{hS;_nD}C(#a2S4nz&0NmOZgc{zbbQ zVtsBTrj>Vf{?$y^j;^Uddcrt+0x77Ibf+T|H>taB6slJqJJHDp&1gtPHC2Kr5rZ)f zsgBC1jNNYT74MYoF0Gg~v9@gZhZ}6G65y{FIu42}x&p<+wP-X=6w;$?XJlW9 znYMiQvd#uSM?{ zifGRx?a-TX%r4che$q6B8gszfVQ|_957ebb`rsiY8mEdV2$c2D(ec@wLE%6@kl0b8 zRWkx~Zs^pgkhQtA&)8+TtuNdR#`0>k(4=piE7aVYF*J*=PAgJ=25glU9^R{k{pF86 z`xzyvVuR|ccuToAw@(T?8!e>l2Fce|L{bzaFBoSPfP3N++V+Z*W6b+46Bj;PTqRf6 zo%$M0^nwljp-_`N1v51jb-J8PYor8;9MZRuWhLw=%`%-l99l@C9^x2QMTW|b85oNO z`&VffYZvl$lU_9JYx9xT3UyF@si#wzaJ?%~MS)@aequpB=OgsbCwNb*w~wt4A*J>avQMSqd=d5C`wwZpsG z0{pl=w6)1;wZs<+r^+aF&^c973UKvcpjzzxX`lDSIDhw=(RSG8uCIkRYaxXM=l=@=RSk_@Wh) zx0;Ypt0^{-nipZ~zioJ#HbdIK{&0<_qAIL7FX{_=n@5SGC&^`&jP{ z?(vh~zBED0ZUR`#xGIVu>s!MMsTBb5mH6 zr{aIP=^Z1*%-E;O=Cf_ppOx0V0InD3MIvgOS8W(@Vmn+@;;lxb^;ZgoGy;W)b0O=$ zG%u-{bp-+a&q^Is!pqwXEB!XW)bz&HB_OZ%sZxzTAMo|b?Y}fk0G#t`rCuNcE&{Rc zt3~b!?}vfEQ&%zk}u1r|iLW`P97zqjg( z>-lV$Kig|K7hKZ>5b_dvEm=0cP|dHtM9tI5yHS zFMjD%+m-rurVQ zzW9unpQV>wwX>G+%B6|c%NoFc5F;J{+?9?&r0u>S!3gmaxoP5d^ zJ>m~0E9sB9-T_4i^LEl5O7i(zqM!K`$)q{ zVbksMg;JHnuu+W&l;=V1-xk9C$j!bQSer>q=AtjxlgF?zA;eI=WeJ|80n!>?Xn>ltM4gaqWGZGx(Bc9>6(Rrg zF;OuMb6B3#swE*tr8;$zmjtXSBO$Z81?7r{lFRK7G9a4gJ3zJMze*`0qfvrR{QI0> z^E&`LnsoWj1Ofx_*109-0dN8Sh@(G##@m}66i^AmY9%q-UmVmx*gfV8|2*+4dX9s3 zlKF;wvaG63@LP94_I;MZI6v2aawZd|=YU=>xh>;KG?(oT-N+r{IzV=?%Em0b8BJRZ z#5NT7bgM*>yP};cM`DB-D=z_`N-UpUhI*7K1cLo^dE6ynk3$x@ZF zADVLqMtv)kfIMSjq|TpbsW9vN=0qYo!a(fzrTByuU!gc8n6(_f<3WhU3iT_*db~a; zBCn2_+90OkAHYDdFkB8|{v2et5>BpFU!nAi7Y?|sa?X?*zQ`o$H2i%Qb&4;sO?U@V zvOPk9f>_%$OkCPQI8-1EF3vJHzyJt{mLQ0S9H|GwlMtJ%5h%EY;e&ZoXCTcFUyGs{ zxC}{n^({&|-Y2;`>S&TY0Z9kSur!+j5wz3t~B*LG{gri0=ne*c=DF`YVQ-QK`kf=n!AiE#M*(U?@%QR;Vt{{S}&OBO(so$1ZNlw~iB=SeV>Tf^e`J;C00< zBsEV3I@%k8k3yeU#jXP~zzQ5PQL+>4jj&>3!6o2+N5`r}O1DaZ!%P5A-;yvywA2v; zF}tM`m=(4gj)npn00Dr8kKeZp6~!y@ogtVIiN(VBmHqKr{Gx!O1A_^EqGJjuY>k^e z6L6_da;)ShU(;LuJvj|B#%Y2OmeF7rKtxgz5H z7%sWVkv6DSvLZTlwfEEET)GV^NN=zKY``l=8cygfqZP23G63C1DK)P2BGXEc918Mr zk;*AHJC4bNoPi=ACPdLf0si(@0&0#CH=n`NQ5qr-PN4wW33LxvPd^GrJ`;Xc4lPg{ z2!Dg5RJUk^s9vCJ7S@q}b|yqEc$N>h_*ET|%6(CMy*RcIIZw+SBLFRdQgOi65=m(i znwwaI&_%47diCcuJZwCBn|>Q{xIzk=C@!T!K3w*QIJ?4v5HLBI$)f<1ur#~09vTCn z9!M>iK`BTrm}GnOCEsKZ6{;p(3SD_Q*+jjv28|ip)Ws2H7VPZXraE?8d6KE799a}p zz01z@5D9<$wSQdRfK-hF;p2NdYbA|M)hccNs|zE$SweU(=pP_?k<&`oWGRIg&mSt~ zuu+X{d|BW&j_N-AvGQv1=mmGX08D8tG5EtY^EX{`b*>EF4-mo(Uk%;|{G{T2f99N7nQ4q8@6N$iO)k-jpOEKYmOM+%Z; zr$p{QU1~T-emk}L7{6c08Np%=*8*jHWjBdfSgGlsA0dSx`8iefQqB+>v!s-+)cC^!}JMVjUtLH!A+urWc@Hn?F3xV(8 zEmLxBpBd8dUX(m~c=|RBioSAmBR6q3f`(rqWcaeG`2RV6Og{GiMl6BKmr*d`M%ZXmrSZ)`_FHxVddEpJH&*I#&Cu z_TLH=%RX~YQ3V~j>n8lbKC~GVaaryC($6{;mh(KEbg$lw9u7OlvrJeg+oAkH7RuXF zd}w1EdujI`Qao>iE)8-FLMk9c0#QqPPc^B`ZP~#+yor4(w`P7mcYy7cG`?&fdC~OjRq| zvS!YFeyO}+xy+@q++*}U-78Y(Jq=1QVw1zw%pof`_tZx#D)0A_seeySsqo!GiDGZX z^{s#lGZ<-P7euh;CEL7@fS{Q1IH}|EI~5e7#MG7+-`nQ9{^{{bY#xz7IZt)qty zDPngJcsQ4KcF1}n2EHYurnaQ;R$a9#>6&`rs@ED!Ai(1?A_VU^wmt5Ra$<(*ehm@* z2axor^oBcu=oz6T9--08)@@wm4ul<{$+cw7r!ch9HLxU(W5yDYQtY=U#~Zwe-Sc-e z`)Zwn^N3fJfz?I^Eg~PwFPtD&2;`3Ap=NI4xNA$b`anfv5RSsJ{`UN(pfrgLl%uXG z_oq}fb*P0UlhTTEhQ%s1u8x9Il~ z3EbzUX(IbA0Dy%2mPoExa`UehcKPo*6w>*&m`nPFa`o;O<;`$HA#wfuY(F`6{UdH) z7lneBgl1*WaUAJ=F=C+|2^T)UOAtelj$Ld}^O%=j6f@OB5D$fSfQ^vyf;h>#DM$h{ z;J)5YpbCs@sMvxajS7sbhF6J(xWzR_|+C@x)@)hY>F8i|MYSVGJvJ$Vj8VeEVWxfjhW(C3?i$Q_IZ)mj=9O(I zRI?D15DCFdRUJXktw1)0TnN;#@@OS)Z29}F&k@N613_xgKK1P&si=Ll*fl%0UY3w?_Mrp{iqCz==4&8O-Qp-# zCkSpxzN=GwF3n*3;^l%e;nY@mfsOQq42 z_Ic4&n2R%W26*d=l=A}{MvjPS)B0oSiF~ABg3zI|`byiE`NYCnnBZF!=;wymlCIdK zo%oU%#rsWKQaQj4CE4PM;G`v{<5t0LZz0Yd__K6AiXKbRk^Hr!sk~Ta^%57M? zC0pxUG3DZUe;H=qMIV4$=zG-9K6sSymJ*cU~yVjT^g}a@lv|4M7j4_aS=rwYo7H zZth`G^8sOg#ZWrO2si4kT#7tauw$5qHp7S57WB{aTqn2!xf9-CDP{y% zp0bMTqv4-|T0!*0W}) zyNR==&%asN%y!2YXBsOUh>1c#_$6vsrFt#sS!3wX;Y^@7eA*%EzsISw|8-+L@1A<0 z-#+lnNPe^0Y0m8rel;%nKLGXNmEt?zF-hJr%h+Gox8pZVhO;CSZwkpQuHWI_a;ij* zKP0N#lUh?m>dQjGn``aWI*+ADh;cGb1fpP;VZOL4caOf?#BKd*gu#zGgPtymk9`6s;%Z;Q1Mmv8?8R_e^$ zV#ZYBUXMnQ%YMuW{FwXSbyWYmuJr0J2PRIkwtH&T;i~9*=R^;=Nt!*N=Qmg%gq^a! z>}#u@%iZ(A`46C8wz_omf;<;WH8GmizOh+}@*>XQT>ZtG@gUR+#tc{IHd#||;Oo|4 zWqG;?%}7Snnb7 zzZj5WEv3!tzew-}>6Ndh%-3be!~tSp=K?WD`hnt(lhx8~iV7Mj(nFu7{~Xno_jM2} zZO^rn{^z6<<$sZ5tk=YZAJJH?>jF3qj9a;wfF+93izHNaR>QG_T5|2k#qvq$Jmj>v zV+dCMk7wS^`iE5Tc?lUY{Js>AB(*bXKS55ks}Ob1fh988shy9%Kb##exFV~pPgB!J4oG3SE( zahFoOG<4hkhA8u@f)fv&r^9xpooZE z@+`TXc-kRC;%`3L63~eyGnTI2Pn?x`>YELUGp$@H^g~(M$p9sSekGX7WCV?c1DzIV4#yK9#T44-7Eb(j5f>oD7sqtM8Am->=m>&_ zAcrTM3!{XdEcPr2`QR=_@Xs+R%g2J%j@F@5YH*kbjmA?zJHII%rONn!A%Ph3ko3>j zOB9_~GeY6ba9Kokn_DYcAXM+^@wI+)VMS*NKSK`pUzCnT9BFJNMZ|`DQX=Ihn;`tX`HKm} z0Rk4y=o*YPlSd9nMb#6N<82V5LBtjP)|n_Vd!$J=YX<1pPf%b9)VL?Y@x`(w@l`^K z9u{wYC65QmJjvHHvQTa=j>4v)FJ}&?L&V!+$)J&=kUMrH*&3$;<3R!RJZIqq`#Q?b zvD{EcMHi4J1F_J|1({)ia+kFD0HXmN#-38Yx&4i- zV(!m@11L_abn*Z=N;aABG`uZF&bjMU@+jiKWfd-D50YlHC*fvl<_!wwF}hT8a;G~D zdAWVUec44;7@g|Qz#=^o= zsIaYD1<7bKI}{xiH4=KbkcqHVr32#cuLB#J3@VWkfC^V5;a$it^N_N8oAF0E{Kh)6 zXiR$76XwoJnfCB!WpG)lnl_t%$P0u=*V^Rp#@MRJ z+||?FQ(OSBmz2nF;e*WW4eDzw{n7iN@9O194UqqvFK9v~%CqZMr9VKdY(XiuH|35~ zbMe?pP0eS18U@Bjb388$iWAaZQB8Or&5 zZqqQ#`A~$A3Plc+kQydiqHV}2r#UM^6iY>^D9RioItU@@onz_n`R)7o{k{9T?|ZNN zy080ny`In4^Vy{zETWwUx}fWcqXjukAW^@^D5^o20m{CvwL*h>(pSFMEc5KDhN_Zg zRN=_(wq0$n_Dfb60hl!i*3-=^QWjttY-)ssM(j}_$5Ugs(vA%4muEUH#PqRcnCp&a z0m6K+pupjr@B9NZXj?hkoDRX9aN-hS|D7ZU5!M(=K{dvth8X>S)_rCBI}fJ4MeW3SmH2OA^0m)V=zz^h*uVPh5-m9 z>C%`4<$i&6_;u`^hiD=)au_4GqVn>Kt3XPVj8M0%(1?${e)N8aauC;^M3J;}5A5sY z4qVyU%_BW~a_QNH)KYiw(tWQ@)j)tyvoHjZAg&lMUl9EclJSWB+Y`&Xe{wH(LVk)Q zt04H7Y>|r`q}j`Ym!EXQ^;D|^wF}WpH#vqppB;P!mJ8CiHyqrM$1I-J3ZCJHj@gm1 z6>TI3j&nwC5s>VrLw%T4B5fS%Uje#Z3zW$zxxefcgTsLp<~&p66D;P^SRywW>va$d zB7+80B8AylmYd`#^j?N6y*hWRk@${l}?8ppfLuK^MDvE~V$O2Ck$OcSK`D?`)*$v{v5?Bl#8X$kn zYfQ|DXYUg1bWG+=xmU%`I2@yS)35)NU{NRP204NfYXL%P7%_(dgX0IH>D6TpX*7aK zv1XQ|@FytJ43EyE@lA)(a3PN6FbFy>LI7-87TkWft&1a8xiDX#uWWgrxf+zggCBm+ zv~N}JQ=hMM{mPWD4D>sC<4$>?`dqjm zfk5s6B)OmyIr;l8U3ZUq<$dm0tU?U$X1vd0QKbJXoc2H0lHi71=OO$|(yqz#%84b% z@l8ENh^h4+e`q=+K{)E~ho6n_mHR&~pY(nF>|TNP8DTvqdGhUvOV_JqF^9-|H)`yt zpSrtc@0zY+T(srt?g%FOHEv zg6+Gqupz7HlGr&Y*Qd}mSe1G4LFp^|_<%=fOKXv|p_ij!LN{bGu6G5#uX}L%Nc)+X zrw?|k3K~yHkYnOpZCytOCLC94f2PmCukVxwfw!N!-+#YyxKH^b<;PlNMK&fwpow_r zLc`kN!>Z#m)^+NcfY$33;yPjOVKcAw5&AxObY(5F)~Hze?DgkDPj{r12HWk*Sv5N= zrE_)Y9|!(~-OYdIMj8x^_uNb!T0S}UIP-(lXXiKiX4i>M$2&a~{{8n4syzz@YyA>) zcz+<)Kv~82al>h?t7(FdO>s#?d;VB@pKRtf>kx$UKVZgFaC6Q-ggdn^Lk#<3H>JnE zt;Fhm`1-qGY+-v0F7bEep?Nlb=TOMIOe?C)=-CS$P%B?T>CkmyV215^dN* z-(l~@=R?15efZCJ=vuU{)yoIUqo_LvwK?Y)51;DNOgvtN|0yf~z$v+Cx3)hk<6TW1 z_VACSlc&4A=kP>IqASHIGu}J3I_rbSk;5i^i=U_MC6||%54~^C%e<;J zU@Y~qGX2#a#}5}gJ8t!#eiUN$%4{n;81kZx>iu?tWmtCW^5_rGF27Kh72h**Px!os zpOb6B_Z8~Hgk0yxB6l(@9J{Y5>mb&AD;qvd6P8~UZ;n1?a&W)2R^Q0{E)N1dXb!ut zX|&h+OtT^+bq?TrHuE!+1YF160zKX@@_ zjdyc@Z*unLru6N`yDv_yE*B~^#R!#GR&(RKDBGRo=Z7o@+oRK$W|A1HM@}8VU2=YL zGdjO>`RDFzsp7i&PdtI_hOr0y^3q+94b z%Sz$PU*!G6mk<)~T6$(voX-3@5Ycpqe(d}=<$GUOQb+loZ4WvuGrm6V98z63({(ma z|2NQf99xv>k@DSAN?NPhyFZl>R?#Dwf zj>i}8ogxS=m7F*Bn$44pq&{!)*}eQk_JP{bwU>`C_X|w8|4UtaUYQy78O8eb^1ve?$8|yn{-K$y-}-_IgbCDQZ8Roo-)f@5lG`K zwqH)F{w|kXhL`->C}8{-^Y4|8Y#o_3Zryi>It1Qzp6H_nCX9q-rGFcz%KgafY9p;Z z{QN)Q1ebd;Fe+feqB%aJPT2l^$F%ptfxfwOTa+(HS|mf%X6mgA^|X;Z%L|<|dEjs3 z?KzpkwmQ#8V`_RV;>E2m9MCuP`xbGhGydppd){dyv!>QL@J3_pCzsG0Y3G`=Y7Z$$ zJmtVa<>1;k!-{TZiwNXQHN#Z=zml0l$?>*&nTo}-slYJT5%@XW<7@b9si zyR1?smtdV=5zDLo;|#W6C{DT6V$ZxI5%l!FUS{h50KIB~z`}{X$t$@DQAeb(tRDBj z?;~#8x}JY=xoOS!#Uc4Bk%)Ve1$^SqMx4|uUBv8py&ndjDp`lXZ%<7Ak~o;+@K67d z+_jjfK>8l3dBexCnzpuojKd@4U;WhleB9aj>F#-$L8Dy_IB4?ZgXVr~RZ9ay(9eAp z$$#wfAKfv`WV(uvYR^1`M$&`A{w*YryVxB^-dgj0&TUdKos4YfHO_b&7ww%^dz95O zJ7@pY6n#lVT|ieVLGfy4`_WS$~~;FBebud?uviVZFeD5KFW@neTe1u_+jG8h1!|(Uc!-OGcNm%oWA|S zLMpTFN#vj*D+}Q{+tySSuuLpI60eZ{?%TH$Enh%4j=a*h`5*9Vv6E-p{xoq{H)uS8 zeBVQ6;s>m|G;enC$?$()c)XtA|5l|py1h*@tS2>f>{I2-lN5X1ze%K@$JR#W%I=TGtURe|gjMh92 zeK7fUP8#aFeQbHF=>m5&F-@h?kc6+0#-L!7N@2(n0%VAm#sef*90UNMGTY|xT1&o0*24`fcy&TzGwkT7Hn%JYCisaN9y`MkU_#Iij{Fly zZY3cz=(HEKEL;lrlM?23(LS^}QkGE25yKq?3IGB;Yfu92p>Ia=)rS8@Y^jb6&?rKy zl($O^9TieG;`LL`Y0~F{Rxufa2{aXo#8Wm&_Bf$Q5_TA*2QT9-(KOv_MqfTfs}=j# zq5wznK%@YZ@n>q6WZ8C)bgh*#TPDlVG&D?X27hpy$sR`xA))QhS+rA@V_MHpF-jP? z0$8}W(<)cs9`o9wiXLxZ?8JhC|5~7-IPf{k+*I5P9AQrBc?+|GR;qLHF0?HDR`Y(U{0 zrWzv0v8cX~%7ok7s^eZ!6ynHPJuP&;Bt}b~tQ>|XV9QB^Lz!a?G->8Q5pv&LN#7Gw z=6&n1^u_dNFaHO0Ir~;aN|L&pLSb1Ou6a{v2jKZb@4?i#rkA48CxsYUJ@oJR_wVb= zf>+cvnD~Bq|614zH&TKCYIH+f#yPXnVQ(3jm*%mA*89^{XH{rZt9eiwij6`RXzlHU z!!M4e1Fpp+8WZQjDY_p7i6fsUKz2y*WHji`WnAL*5YZb9p?dlCr3S%9CXYN^L-nJQ z)`3&591oZBki2*dvYQP*h0+VMWah_7_1^d0}pbe34UPLGjr4RW8q*QiBvCQ>p^QQdpw0W{a#=9%d;f z3zQh_BKDgp1u09$iFKuinK+}iEzhE+8czD zhx#;wvOU?5Jj2*5Iw}mDG=*wGUuc@VsR2D_Xd|8#QM6Z=07VwTaR=HlV|I3oFT#3i zUfdmCYvNQMZciQ7OCksoZ`V`_#&Wdexl2lTp9``C23bzy*~s+uD5rgWmo6j@b zUg zJEM{9j*fGhdP^tLQm4SGdWui{Rzd14$7r??_w^B-`d$wE&~(lcT$^}gs#Vw^5+zGa z9wMOj~$DF7;@e@$VdY5S`hkB8H=NwBgOsN4L}uI!+3W+2B%VWy=O6f=_;+!8DF@ zSQs0v0n$dR?R@GY?ItF2MH{O)4CE|7uc!L~3-UOek|zLKWEf2CT_b*QA3_%{Sh6q2 z7Pq8@SdRs&n5w9oPkA{lD!F-}>7T5eDrjF;U0?^$a!WN|_lKw!Cb1Q##kuGTqYYKS z>^Q;f5d&Ks<{oN<4Z11RK*9#>y>|^HONt|`xkKW~E!s&c5*pJdokC67Oarda1rlY0 zBDrIm+U5PAtuoF-3qrKw&?wusy!ty8odm!}Dp-9%bj6j)KdDVXjr4zmcDYFD-*k$$ z|7ORl5#>Baihp1`U5WBchXR`(n$=3rtZ&io)sRteFqZ2U1y(H*MLN*5qLz=jm4741 zj!hktwL$gQic&l6Xt`ggJ#1Y!$a4l{!|sMtUImN~q;f+f86Yv4d1RL^_+qm_?3D)s z7+FARR|O&_(Pt<}b`K3%q>iI-XPYbGRa{gdv`yO0jmV^&nKJlBpldb8Od$-Wgc!+i z(Yq`5vY`|L{!5#i*G~kbjKRs1?m3VR_*#%KVgeNbAwE#Xl++G?-!CeYg$B!?f=>aE zpS)W7Pk~18!Z4bOx{VLo8ZmOZLdKPv*Nl$o(B{oPc21u=sk>w_+~f6>3lqAneA1yd zAh=JW|GSvJ0pGDwxxUo4>T6)5YsZx9;~; zg)RjrX-uG<-^6-1byO7L;3wYR(!WK4pWAMBQ8U@EzdGny@-+r!>@A}4Wd6N(Lr0JK z%83E5NO$Xo9QQriY9$-tKr2ajH1&nME~`CrO|`Obz?Uo|{K z31uA~Ft~aFV%_u3*XIu9^fE}MEAO4}Q~Ru)`PyX*{lyqH7c`cfL;m@yLlSv0|L$m^ zatr3k7mg%4>jwoT>!deTKxCr##iV(;s4-HX$*{cdjCS3dgS-hqZ9YG7?Q+C}u7bPT zCuA{{9Z1z@oJH2vd6x>|Ge%_&Do;*nd+ue3D2i%0kErV}|7bHz{LZzPCg?gK6K@6G z{;X>cw|s+3^3YTsPCV{4t8lIBCNU=07zvM2^O%F>T+DBuK&H>w8brCVKe1v#>=DU&+={(I_J<5+NoFDhnQcv9b)`V|F=q`n}19`gOl>er6pbQ zre*&29i#i&w3Tf?dq-@}_s_`(Its_h#GQV_@mrWVIUI7E5Z7Iep37X`XCf;$afSoT zL0kg^_{)Q{PmcwzL}fo&(mTBzBWM1BV=qHw&Ea>Knoiwiwx0dk7}EUcZhW@)tWt^g z;k`&x#+OE=EVYR_lXJ%(=C^q1fu1(k?*)chz9? zDZiA1bl{VDM0t(5sIe4vR;h@(?@=Io*s#<71qG@6H8*^|>G-}i3kSZA%RiS##kC(- zr>Lg&f4-37$#a9b&rg}JG?kUklGx_eXDt1@?wh~C{ogr$&R#Qp&Z~|&UuGcs_(Nky z@#|r;HYqQ$7t1lmJ2?Y93uFIBhSa&3gmP7ER#v9zzQX)7o5R8{%1IB6n3CWh$dVet zb$(7RW?DEfiG6Q(`_dCj!S}?5$&xabuN!t_44y;s{x7zNW0DZC+7?53^rfftX-NpIr-V;?9)MZ@=|IR*6|8Hp4TC^Xw;n(Ud)db=+^(=5yK(Z z$Z-|3LNd#r=Fo_7zZ`V7KW^W+o>$StHSYAO@_y<8S*9kP zsDmpWely_A?+mzPRPx&G!n>9w=Qofz_ekFb7-VCj^Z92PXM6d0DSH1Sf$e6};pL&>e zdmz=;kH!;dc%$SSwb5C}3y~fB-Y)M;U!#JpPEsxOJ!%2;sI&k_OYjP)S);aDZkoZJv2w)Eg3n{hJb3vx&>jV}E;-R{ zKLJaO7?QNi-d|`3x+J5MFLp)Lkjgt!2xanNK_c2Vo~rU?^}rdFB4lcdD3{e$BpBo2%@%mI( zU=?gX1?^Sm33s6d*{RgI4glw=g#OUxM&wXCSm?6|6D1Vb_9~=&x+Lzq(k^>zmi`3TN`sqxu3W`pOT9UjVF6^-_34@<9M9 zB2rvcZln(HI8D{mSS`Sfv=z~a>i50&yv^6_u}`kBEB6S&FWsv&02jKP)qE;Le6}u|zy+$P3G^Y-CS4h^U-$pwYMN2UDR4j9WhdedWw)-tfSEahN`Hgu> zs#@5_tRWi8+<`QUh!aMS@D=kPBj~QD)B*U_aW|oj~wW+1*k3WaKA-nzESt zf%h+$Di?1`8Fmu&9nn)zl{FpQb8q#$Jyr z{EUO~ygzogYLMZ^$ilq8m@6OAG`j&(;?T<9=67k#yMu!Q^r$u#wdZUgwjZl4a~Gg3 zD-4lT)VMB}v{Iadr4@qIWuWM6#|XDCp~rayc%gQoU*aNhQ&rUIWkM>IruMdGtzSM5 zHV+4ZQ15JIOSF3Y_=>qO;$phx_;IjQ=@V7V#dZQtBBdduy2mj#b(DLA?vxJ3{}?xG z!z9;mCl-$gmDm{ZH1nzhZO1Ixf(C4gI)~t{r;ch+XX{Gv!J)nTJDl3Gocu0sxon$= z;61id%g`qt<6f6F2u;_LgfR1@9nY@L#~fxjPNvXc3x6z3X8tDmTkr;p_U;46Z1CBp z?SP+ezBmCV3yMTliz<*d#LU6K#K1_IacK~}l?;f~7h(+UZf=pvoJ`b^mPBBBnQ4Mn z1FL9u!jBZvS&@w=hK?mlt5_v+MH-xc-Rg-j&0|pd>V}S`0_j$swDfpW7I_3k=1@sZ zA@rA)T{wkR7qdJcK+K5r9@XkIF$mp9RL61y#(f?N%8M19HE#y=P~01~a=5&>QV%`z zIw4N>TVeKVH&!?1yzd@KNBp*9ybOCldCZjoqvN6T>CiHQE$E>0)l;Ch249dI#aAZ; z6IIbN8;KN2#F6D|jrhRl!g-qbS5;*Gf(+pX53M4bFIqpASew1~F$?b6Ua35;914jg z=Pc!{(=_ z#xH@yloN;~395^VGprtCW9SslQ5H6iWE{O{CoPa_H#|_b zmNqFHIpvZwqP z3=DJtx?0AxH@tTesz-HR)P}piUM?JSDU!jd#=PROWy@00p|uqxIhk=0zbN=e2Y85h zEtReV#u&mjl-HI%AqB=s!guu3aftrEj`%2o$HYKM82suyq-I)&@93b;7_Lez7`rA% zB62iq0od`Yqw%Pph`_maY%vRI6_zLS6%P2_3z<(`su8NL2&W=uoqov5@X%T5C|I2= zX&@mMe<3LRfc`g~lcuW$lJtn0pRKj@&?yq9CMYCwoRrlVe!3o9qX9w80-IxXR*vqk zJ%wDS8#Ku=@SyN5F5>loAzb^UZHO>GDk#|#l2{#7)7%plS^YP{1ZU#mQaWlrgDp#+ zh7TJ)4H3TXdUvLFa;T3yb|9wzJ@wlGe>csq>{r}kx$u|+KN7&B173U4Nl#naHZlRL z<2n&RyWNDGD?5~;Oog&mA91kSv23qrZmwF|!GhYdfct_!jtQN)-C1RE-|9)LNr}jE zc!tW+xQ4ouAC1J*P9@bnpSzU*>^t9iBx+{6c+rTJ?)&11kcg;-4p9G%sK<95;el|e z73y3Qso=)tUAI%1Y4o^x%r6~TK`lqke!UyC z1=WY8!**@Vww-$)#LXNiwC-eV*DWv3gvh3kQqobH5eq{3juwq^+^hJG*fZ!*?#9RQ&rmL5Vtu z`rl5j=WyvW&Z)MFueuhK|LXnK6LkthZu0eirpwCTfj90*NDNZY*5c`Uqa1ZMX*=mO z%+mdGnCl3~DuQL^dm(F97xUacI^F$g9=W5d_IqDc*$0Y4raANxWAiog)VahxPa?V% z(t%$4+6xcAkY*J!yM3bhqnC=+mbq(}(vJp8IW9h{DsOelo=I(s`qH4Not%;ImQeyp ziWO-CEvjCyJ(4il%rH{?0*916%uUeaB|p>~hDYw?Wrwq%+jrpgK?*Cmjb-ZSG@GbD zP7jLKHm7^X!ew1Y`T-uc@SM@d&E|wqK%kcJF3f}FZRJB5B9BG zS9{dPjj*80>B;b-1V4X|LU)ocN>Ina4;akCcKf&8*7?srn!`%nBDx-)i~j!)_%YdB zs#rK`+kB}TUv-V#X|KT4wGbqyf|)f!N`J$((wI25=f$!EFazxv4*a47#X6-#tbM6> zZ(ZH%Pdr4H+r~va(&>NlW7mc%V)RvguY>U!`ZQSmj}7zNCY@uJZpleG?XXqFZrRg! zz;wMl=@NU#WJM6&2X*&H3W0T*zYL?B&a(#fdfx-l>mb?3Z*%muVvUsYXYij^H*@g# zkIRurqtaa;#_0ExpLL>XAPiM~E~Z4e(&UortW{Z2pR4pQn~+;w-2oS}?NPUn*WvzR zJB*c7oj)*5d{_3C%V51#ymu4{LY9+R*?rCnwWz&1tNZ{yZ!PKX!G6)K!zv~|_&?5N zZQX%vejkW+fod<8jyjQCyA*x8V|<92a1J+gx+t7FZTacKUu^9OZ)JTmrL!f~Ggj|! zvMqgvTYV;!CCOF!Cn?6Ir$Yq^l9m5dhBcU&&8#9Qq`3wee|W^_cC-G50Rx_ zf1B^VDDXxd3%gFXtNnP3XCifC1?-Agcw29MH>1}|Y{P7A?jCQ2T~7eA$w=2pG4;2N zX8Fz@Ah7edDbM8W&yBQb%&=DFN>v|r+Jb*2}$cE0VSVLr6wMSvSI~d6- z4kqhHaV^RDSvv`CAw9Rd(tNgn%n%9j6zM@F@~xF4^k(w3tE*F@b2JbFcNs|UWZ)7b zO?Zr405eIS)mTh>kBvQ>rjyJLJs@Pjy;!;5V=q`f74n)n1Dxn28+G?J9F28LE0W(> z${OSpKt%>v?r3uOEZDr-TpBbe?GH#KRg?PmxelnPd1Jtk8G(}P*TBmF2Ox9Z}542;bNM_OWz;r&EPPMQ5#dOxZ${m z%D}Mn!$yLmpSt_HEx(UQ&~Iw00HL-qC~`g$D54?%)*sPTH;07ZG5lOeG``n(uw7H7 zI@@!*;tj5L#48CkmKX1~96Eq?AR-$_o)N@O55ZMoT#yEb>aHB&eqg%iaD|J&B@D%7 zNWFuhzB#%B`Dba1hU5wW@y)hK#ISX{+Vyf1?vo~)fV|1bM(+2x+2S6lkEd)(NZi=?3iT=eLcQLefm@r}-NzDihI$b{w+~7j`)eqn`QSfw-A}4*- z={Oo-mD}XgR?AzD0qqrg{8Pe}`*%lXoPzs#p2%Pzjzq%rr$TmIL=BZx53UQkDjZq_ zeRgp!>uHdgCZpgOU)@X99o?0uegQ3l78XYYT7e_VIm{>oZ@?=FEz?Sis2tm2h%HA8 zl|aT1^kuy{v*9t1=bM)~uoH7@OTEsW*?9O1e=JcFfl_hp;_CcI5OSkb?+i1UNAE# zwdTV6SuGDBBs7~3*-+O+=H}{X@mXWGy>heTJaCtN0vm+i{;6O5n zvFMJ8q%r^p%;y5H_IA|%keo>fUzdxEP-{ao!GAXA>sv7yax8S#v)8FEhZCXK&(;@r zLGm`~yxdDyeYy{_5LRoka7>FzcQgf%f7AB=zw& z`ugg3LKVP<#FZP5JHmZIAGk2U!Ex8Y)uZM{g*){(2D(_>d_*1$mX4wf zuA}&&;w7_SGYl9eRM=Ur8b#YjdTBS!epgrQ3GUf*CVrnPmQA9U2AKvOXD!UCx0d|t zof4t2tx&S=-RZy!3~B@ME6u;sV=wt8`k^y~U{J{fd7K!ffx3|*py2Iz%m zj|r{8S(4)xm&Uzmdp7LDU5B)XQ=zoPnx~kTv4(9VsDKZ1hv@=^dPo$a{x--Q(9VSQ zT08u9Z*a;Du!SG$0J89gbilkmBcq-~iFFZe1&VSSbBAq~=syXHFWuFTUBy*@;EKYx zV?A{-j!;of1Zf?iPn;`%&t$~J_vC$y1DVQWY#)(M`wVS%jVqD@noEcpSK3jL9x5bF z-BUf;R?D&qA`kM{^7icW03i25hxeqHs!o<5;UoATm+G|?IiL2oA~$4Y;p~{(FWL1c zCd}WxEf6OPk+`19a5?7d~G@Y)|MBxc4W2${n^s`iZ zs64%spo_Bkfje%AW$e2i68svVeGJ-i|A;Mik4Fwh49Kz}(Ts6Yp^TPg&zJd|U@id< z^}e0Q`cfEham~{W^EA=zddM<_g?q4JiQHN%I5vW zc3uk$v8!juIL?gqOO2S4p>yG3XH(^m75gl3-HiBJeMbxAKAFSrU$EaN;t;-+cYa)5 znI&V`TNy8IS6}op3;H(vT2TY-1lQU^Q;32kj zRS4$K%LbJ*xqCIK-BVc4I*D(yDz$A~f$!w2W00#?8ZdJ|pgJhDe^yzIjXB0FA9#KMHPZXUJz|v-j`5uiyG+1V=l`B={ zQ5SDYG8I&BT=T!g>Ug-jO-Md`Ry>a`mq(CYDbhcB(T677Ri7q58e_mWW!)&?;ck03 zXyacv`6`~Er{M;3URs)ihIHSqUG0<9g_-b#`bucd?emOMBrVa=*IzZnInH0rWkB{R z8GYPgVG2%F6~TxfC;$bE%4HJ_^y0NK)>(DML@uR7)yjtHU!hFga`pPj1e29SZ4m~w z4Oh~Zon-p5`f)L7QfBUw29^ZCYMCGpsmLK06vz5)yg!z|*)A{a)zrI}RGA^WG!K<#ut@2ilivy?GRtj|P$a%xhl7>Y*VpSLYo1SsT{tPML_1AcQLDQ)vW-`urA@tv+~&pIN+FEcZr-jbed^v5I%0ov||*> z9Q; zI$nMm_w2EGhwT;_=2H4ih)HPO9Obm6e4JIKnK`gpwPb5;Ljc ziX-}^;{-Eb*>-FuC&3fHFZK76(C5W9vbJgClK>0sekpvgTD<@0!%dKqnXmjh9)S;q zT46aph)L3Wbcv6CUgu6eJRpXd~HN93OpI8&lcPw3L&#lUw z-m3!rrcMXDFdfD)4{V3eyLXyTnW^gy84l94^EX|KnWd+v#2(xa(nHN+$6zk&L>Y4o zt}wh~BChk14NbCJpvrMjmO|M_2%Doxd>4Ek5`V=X_!s1les9))uOT)1<2yEzfo3Q7 zuB$JG`uoaMB6i&Xu=w8v5qVg5NnZn;I&akrF`N$h7jaR9%&?yKAB0O$5wRD@4{5)* zT{J03%W+#on40IbW(hqtQk)EpPCt~mlos^fP}YQZTvt8-tZlF5!Gad5Ipl=*Sk9N& zQ=@vc?nqY6q`h;#Z63jr=#uY)*SsoZW&a@%AnC!)Evyzsp_&(+bT1P4Rf}dK&7{ws zB8%Lc;UZ%s;h~^yE+{hlQS}>f)CFOkgjnbgnE5(6^{GmW%OgiSKj2dB=oA1--n3w&s* zYvssN%P0KlH^&b(m_WPcPu#8s&hl z9b=<&tFsYXn2$5W^3%l<^t?{x1{-v`ZjzeF36GnO83^uS4;O|(c%fA-5?c*zKNxd{ z*0SsVhV-Jz*cj=-(2c^2y0I1Uq<$+SPev;mcm6LU3=HVQMfJtkALDu^1}*_H>I4~^ zZh$OHkGO7lG#r);*rr&g4$RdZZ3`0Dt5GpSYMUoV@4&T8g`nnEQ5VVn$XFNw6O3~s?q-&6;(w2$R_@5rG zU_Q6F;ves`6T}iKHZmc{lQ<}vTnisdbz$U0&}>w6T19(Q5r{Q` zMwIw(k6#Gz3GOw=V7phrFXL9p$sW2!e0!E0Xo4?7MTUm+)y>JdiK@!CdzO<|yxTfk z_QhAforXKeyB^1p_L+z}p$9eJ?+P-g!9ouD-=>t;*XB$wU_`P&9qfRF{k?koC8Vdt zO0vOT<{tJdNl5hO`w0qDhGWR2qzNU65)XOhqeZn7uw0*qn^w}P**;h373#fkBlc}I zgPO4@(orQhzd1y#L@!VQkJlR#F+H{Om;;n+2i%B)rit%Muf`K3%Ft}cOn;~BVqrW} z*{|`fA|V}Fn#PO^xlrX)7RJ!yd+mD}(hpJ^BgC>%Q?N9*ql7>dW)g}K3(Zp%JZ-ev zYvdQczzj><5h9(4(QNjSk@x2}Gt$SM&}qx0IweU0z9|;3l$3Y$bhXV60Lg`)#cyW zx)b~sbU}`=apUF2;xyxNh_5Mc@35Zzv0AB6yxI^k7y?=>gwsha+$CC~+G~$i{+^(1 zJm>u44S}Ff5fKqm&e5vOFoe3Hv_!oUF_MjyA*%Nu<6c~Dbs}BiWT~;^F+fQiDM90{ zT09&;wovRn*lA~*NzxcKPTtXc6qfBKi56^oU*C6;DQs1in^^AiB}3xiUXYM@M>C+> zkOZRsY*DuqxB?gZkB^Dm4khXL*laj-r z2L>@w_09t4VA=z&4zQG?PzQBCpQZK$N(#`merD7Ut9qLbC7nN#s)^w5?|_?QGmBhl zU{NYT@eljSP4&_YIv_(73Jl*SrgJN>ZKhVi^r{X@W)&NH zOn|qOJ%!4>_Km{{PH=)GqlK?Wjm{9*gZPCZB}Bc^7B#RQ2&kH?T?ip`ZC82DH?}~X zj_p;y9^nYlImt&-U5mlpnnLt5jc%n^G01^anz+rPMLKVS?gu-23f~yiV zMiAz{eJC-Oh=C$LfAb9oj`gDYT=YdDFLuvQ49C)+za#zgIp6*`4Kb$YsJ<|gz%V~2;ShaEQ3 z#Rx*WA(N>?kievk@AEZJ2Cs{oX3Yv$@20PM0H#Q@Czzq2bb?J7L1;S9fAD-7v-?f5^!)ylf5sz!XweBA5{oLz z!5>?lK;ZUd$J=&=bBnS<^{qnYBAe?)_~V#F7U(Nicwj;&w6o<~=x%+kh{bQdDhQ`O zP}sE{L0c{~76vxAYt7ZuHI|29!5;+BV>1Pv;3WZbyfhAAFrOgnc`5||*zIcPKe^^| zP?3)hT&?zYO2@l1TdBe-eM!=!K(+hc!hPh4`B=!3n{a;@#I*y9eqI}&=a=+el~@me z*k8{dCZG~?&Cw3>h*v|pX6rt4Pjkp6q$L%E3jAasniSt=Bz!m0i#zEK#AB(FfPd=z9FNh{3|I_%p60hVvmTG--!20Q52^+>XghKL+F#!m^&HH@Ynkf3PXS z#p;U(=tR>+?u~5{)tuhimH(ffi9w8In%kbvb7maS3@)W;kPBupU!h4s8YPA@wYz7!e-}O0?Icv^29| zxfuM1kozr4i`2)4@$%e_%T|eKBA6o8>a{8w*6P|_|0;2RgI;opx@aXa{eshUA$^QS zx6x5AA~DLsf4fI#!)-w05TOLr+ggE*j{B7Y+rfkJ7hj!8&5`>w*3U~)a7h2YmWF#H zZGKXFpZRuMFH*`UX!&;aF@u#7Ia!LxK*3R0+)v^c6xYg@!J3pwgQWv6Zw3xC6iEXz zq&o<*-wiHYZvx}e)?!gMfJAu{LVHcr`{26$-nryP8yU$@b6_2i;+JuK=^m5x zg-{yP09lmB0F&V%o)DM;MumJ78+gwR0bJtvd)U7C?u{-&o(rYvqGx=)QYm{7)7y(h zGWxb_+J(FLkl9CLwF)6RcU1THi0LRdx9;x%L(yj{DTrN?pUx2ERVX}U_u$#5*suw+ zz#WPmJ#`G8V>5>zQPKDwwvr*F!d-W`-k|6Q2ZqDaPF56-g&Ddy$mmKIP}YnPXZPgH zCDrb6$h|Yd6MnbC5}!2#M9FmUjnqDfV~FWBhUJL9=rR%7-su|dg2h?b^B)`1_vtC7 zc>pHu8iVa}@_X{(B0c*_loy73!pt^FvY8ti$`WlcfFqj7;uN z)L3F$+N4Q)I0fQMb_E$`S@oR+A;!Dn@Cs>((_abLtIr)VpL(CiD~B1JCap8_HHF4o z!F_g(YFB^+t3yd_obgB0AkJY|Uo@VIfzCk+&Ya1Iqtk5Pn0YcM$?kYFnltaW_i%;E zJ^7^qIHFI=Yp53mOsQ0-N2-vByH$Y+d8tUXqmy?+`vDfYOe^VEMWs*r7#Jp6I-=L# zKhlpD!VNuY|Bf3#uV+N|X)*@iPA@@Vp!>$FH3*~~M@4-(DDuvsF53pkdsH$Y!n(r3 zxtcCzk#c-gP}c5BQCAnpL8VZQ`rd@alA~&93D7)yfc7=F}p^2wv%01J;be) zFsnP<05B;#_~0PYYPZ6Vlz84T^hpfV|f>JNPx5c@84h(*4Jh#_LTBIWAQquKO(s6BpSo%)c zHG+oemDS6U4sEefN!xy1gncDk*kTs;=Ce_iitLZ5m_!2F{KAPF4Q1V3IPKtCNxHgz zOX^vGsMh5oMBB0$=;TkS8R3qs9`D zb0mY_Yb{~O*o;2s059;fTKud@0*D*I12l+rH~uu#udpFdDL$)OE1d=u^dHJl0QD1) zst*!O23szsqK?8tM_kb!pJ+zb1t-2wyR}$SFFc~nPbg`8Czv-K5!Ft-^9#>_tlA@NmjN7B8Gh^-C#9W(pAy#~--=e|ItI$6>2>Y1L zac!kUB!ajOw^KvNdOBoEd@PezfP|@1WI8~Fn*Q)-@@^4b+z%|E703WzhIJ5Nh8s6a zvSkC>@ws|sR74*lf?S0g%+`Sdnw@JB5}hZ*M4~7X@m&$sQ&Mja5maX!*aDoWVTyyM zrvX?R5-|mE7Rzm%BmI!&odGcBckrM|`Bh#%bl86#nZq5_MrJW)g$pRyBpnvg>L)?! zW=`STG~Is#hu|jdoFT%$S_^ojNP06{x;q?Cm`Hhf-Y*)n?FIvk0?xxc(SikMChmK# z;n-CpWFrjvTNgy$OGC2CK}ajZ<2;E%|NDrqiQI8I`~#2tWEeHNvLVd;DfXW!Gp9bc zN5-kyXbR!)_?}Oy@b>TJB(jj{adbZ}kUFuvw^%hZaOe;+T=v}R4jUQKNi5G(*jC=< z0}`5mesD1x1jy~v!9MDW*vL5i?AA2Ai3b6rbh(7DY6}R-sH4ZWnv$un9n3-*Uac`1fU{UQ?DAewc|2sVQhB#;*%Uq;obt@-R#R zlkh@zA+MBN40w;z3=V{i8aqYPP%^}19~!3E|28s}YVR9(=tymR^SQzObn!Kk@eTch zGb>WJQilJ@EXddT*r8k99D%c^0{{RG8v8yKL>T*cvIF307=CMw4x(#ywaxc^UyPHK zY;9dchAi8G)Qj6z+Zo?eFW9gA03~zb|D|2t(2U^D#O7;19i+ zBlIsKS0iy>13TYlZub52=Njxx(Wfh`_J8msA&t+cp~lJnJ(eu#PjSd{2vf(Di!=)8 zbDNlJ%1U1&Y45%HunBT09iN^UW_JpA6|Qe@@SnDSypV@%bx8%t}1R8 zS$e@BKxbFa&DH^n*e&=vo|n4oiwLkuEX1jugLlo)~oS>i1%FQ9i-Pz6~@4OtF9b3*U3GZF|`*=#ypXL@K`g@0=MvHv@PrRp5W z%!X+?{Aee^Z&GUKXV0;pN4V)dn5!N_SJ!sRVG4j7Q z1Jv?(C?qmb&uZi6;Y8ibphh%gDec7%ys^@12XU>qX^5Xw3O&To@D4UJ}Z zI-;)$xxs?_p~BUpKmCd`27T~fx@OAhBq1uZV+MRrYtO@{b{oq;MDg9bnPzxp&*7NI z5hUvZe#<8_Bmbp8Al{D~vF_^AK7$3_|=&m|1*=8sF0R*X!sy zZS(=}H{9}g2=vEDQ>(TlkVao7ZCe>v-aZx>8=4}Vb!fU)@k>ACQ?Z!D(D|M7p$Hiw zeQW3ZF9lCX9;R113glIlka&eSkZCz%RRAgwCb~*Nx3lG}?Eu*xsSk zQ6dKa^l%4sV00D{>9AKp{1ZP}Ore_4=7aHImro5MWb(xM=Hu=_{5!#r1+*bsaNjKn zf_bZRu$Iu0TEq)>OxLrc{!3UC@a|6^r!jW89ppfV)BUy;L$j4s)JNtmQQm4aVxMY% zQ2Tm>9FJ!g^1x>vMrdS-Jr|C_UVGrk^KGqNJH7_Fa6)$Bp}KIQyLAmvFlh@yeL!MpMC_h^&FZ2CK8yDdGe z<`@B@GcP7?tG9%IxZq7nysgK)Kb#+hHD*D;6z>YRuzvxn)bFTmAAKU^UpdkU)LVWg z)TIT;iv#N%>}&rwrtWlXV}a>jllwa`-c0(@`3O7j=)wyAyPQsO%i8c}H zgvd^;vnKK>)Ln3cTzzfb`!o<-K($SXq7XkT>(oi7L&~`&-tS9~rUfYghN3Qo#|uJH z!yZLoW-kmE%o2`yKde1cThGxO^s2%i-Dq{XQ2(hB5r`KQ3%^+Ks&%a?4+{rzP#jMA z)&5Necs|!-lRUt@9usuk8$F2IGr)Qm0->*`Oz88 zv3P;ov4ogf@F#{q*IbLUblTigo_|l^yrte{I+&C4`x^`U<)>VC_~PYx2~DAjdy5Z_4y_!7V4z!wrE8u_ZuuM9E$+3a}d( z>Fo;TFB_p%Gp`Bmuv=e~k3LqtI+XS!Zl#}Av;5J!w>vHIDvGp3#jdfTtn#<1wL>GW z9Ddk*l$u+GLfHf|mE-emfN?Woo5NJT`?K%55#&s0%y4Y{4f97SwI{{Pi`kgUD(F#sfGRzpUz$XsdNZ0y^L9QEg}A!# z%{0{0xzZueGLXG+Vsz)>#NbU{WPGacB+61=9v{S~96HG0Kai5xivxgczN)~BnzAJF zHuwRT0kw!{<&jaGW`^L~H^k>*pQh+5$;!5mRFab_%P|<)sOm6caKB(i zfgg2i5y>KJ-({GeXu5cX9Bgsa#;FVz9DTFZedw^JbVtWR*%iNw2EU(0X2IjZT$)YTxY4e+sn`@b*xvCwDfu$qO>GpHfQ+R`y(9Q*dbd`Y(Z`8a zhvL2o&L$0O{PkC}6*6f`OLf%ILMqy?pD_;6=v6=nb0mit^ZBRvv%!mD zpHPNw1@g)DB3z=eXSwAii7zbyJNo|!NTXwJdM=E}@<)3MXm}Yi#NM%Zn~=6ID6-&< z+qApW?T6khDK=CSBL&C(g)z!kU^MWgEM5N*^NMb(^}N@hK_cOBpV%tH^OYNPPC;#D zzx-ly4KDm)HA3T~FkgRndg5eDT|q^Vq80GyWYuqRR$U|bp|KBowe-|CSHmOzF~CPAue6ZUiLtlt#t!DK${GV?G)ZAT;NI7-4g1{{nLN+I!$sG#_hMou7As`zP06$x+S3 zhKk-r8+FikHE@@tDShB1UkAx`bI^&MB-;dv%u$!Aexv6E>nqX-G**poP^WnP%|>~#=yU7IY9c-E2!zZ z3E}S=N3ImNZKr)1B1z8{j5-UySkmb5cgnWE6w;;IN_T7aF}}TH2R={wVOn?M!6(E4 z^$lMZ23?Gy@-w=V4V=lHNXfnGr9<13LZF_{3*4xgK zO1EUTj%{T?tVV`(O*36(I3mq3p0#RA{~5x(2Y1&6nvh6K8H)BNaNkFgB++a4T$O6H z9Z!Ax)@tg0uF>#W&&N1R*Af$RIt)SZ{IC<7k%J}`(P!zBYVhP?rlX&6AB_l5QvtK! zx#)#`&Bxh@W7@_76A_-(Q9cOskDg|AsqeSFkQ?F_81OAp#kJnnZewCO17;f*G*v}D zc4sQ|+fvKOb7q9(^rE|>MdI1mO#i_uZz`|s5v^_*yPK_zJ(SSq%v;WwoB9jOJYexpDBDnCD9!Um@wjy}@8^UNtPy~!soTyqXN5c=9m zyj;fKad+@LLhnc4RmCSh{z8F^y-AjZxQ6>8>~B2p#KfB}vt9r%WiDze;_ENlm-2j5 zL69=$Yr>$JeJEe6 zs%UkK_$POe=YSV2Cna#A7?1L8a(mK?t+Lt2P#+ihVVw1@qp-x6F3Zu&#P?&Q84J?`L72>~#+1r={``4aLJxwm1l@1WDZukNjn#YnmdrG20OJ=Ky)H?V~q) zu1T+6gw{2Q^XvY!tr!3RZ{AUp90`l&%#FV1DpK5JO96X9Vb}6m3484eZ7eX<6TU>} z_lkah!E}43laXP+J!2&4Fi}$aiR3dH%uilEI>#^k-hVp{Q2<%GFXJP%eDqXSdfg8q zd&hip3!1VLcHi{)drpTtRRCX|#*q-Rbf9g;#0guBa)*;?y6QfOIXQy$=ejb2a+kv)%pE=VnTjoSheN*)&mpfD z4e*NzQ_b?K;JP7Gh`Y;|Glzc|3?QXPFHq*92nXc@pn3YHHkwa}a4Bij#TTq_?^tZ_ zTBSeE7OfNq)U>rm@ZMuapVvl3*MAZH19_r0FILUhAc#+Q+?u54-4-Ku-xMjc9kk+o z_qyd6j+s@+X;iX7yf7OgFO7K+p zL970H$bQ)057CKL0%C=;sr9J;YW?1I#NV2Dq|&~>5q#xc*`>V3@!e|&9wKdAgJmt| w>0slTYBc9i8XE8Uq`v>swR|75Wv?jU4249IKh8oqrnGSN!t^em`uErW1A72XumAu6 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/en/guide/faq.md b/_all-in-one-upload/cc-haha/docs/en/guide/faq.md new file mode 100644 index 0000000..46be288 --- /dev/null +++ b/_all-in-one-upload/cc-haha/docs/en/guide/faq.md @@ -0,0 +1,34 @@ +# FAQ + + +## Q: `undefined is not an object (evaluating 'usage.input_tokens')` + +**Cause**: `ANTHROPIC_BASE_URL` is misconfigured. The API endpoint is returning HTML or another non-JSON format instead of a valid Anthropic protocol response. + +This project uses the **Anthropic Messages API protocol**. `ANTHROPIC_BASE_URL` must point to an endpoint compatible with Anthropic's `/v1/messages` interface. The Anthropic SDK automatically appends `/v1/messages` to the base URL, so: + +- MiniMax: `ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic` ✅ +- OpenRouter: `ANTHROPIC_BASE_URL=https://openrouter.ai/api` ✅ +- OpenRouter (wrong): `ANTHROPIC_BASE_URL=https://openrouter.ai/anthropic` ❌ (returns HTML) + +If your model provider only supports the OpenAI protocol, you need a proxy like LiteLLM for protocol translation. See the [Third-Party Models Guide](./third-party-models.md). + +## Q: `Cannot find package 'bundle'` + +``` +error: Cannot find package 'bundle' from '.../claude-code-haha/src/entrypoints/cli.tsx' +``` + +**Cause**: Your Bun version is too old and doesn't support the required `bun:bundle` built-in module. + +**Fix**: Upgrade Bun to the latest version: + +```bash +bun upgrade +``` + +## Q: How to use OpenAI / DeepSeek / Ollama or other non-Anthropic models? + +This project only supports the Anthropic protocol. If your model provider doesn't natively support the Anthropic protocol, you need a proxy like [LiteLLM](https://github.com/BerriAI/litellm) for protocol translation (OpenAI → Anthropic). + +See the [Third-Party Models Guide](./third-party-models.md) for detailed setup instructions. diff --git a/_all-in-one-upload/cc-haha/docs/en/memory/images/05-architecture-overview.png b/_all-in-one-upload/cc-haha/docs/en/memory/images/05-architecture-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..a4dca2bc43e6a08e2687468e5370f68b216cb72b GIT binary patch literal 440671 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

2J+TNFGYW%C@2WQT|*u{cyCNeA(IfACSp2S^!J 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 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/guide/quick-start.md b/_all-in-one-upload/cc-haha/docs/guide/quick-start.md new file mode 100644 index 0000000..fb262d6 --- /dev/null +++ b/_all-in-one-upload/cc-haha/docs/guide/quick-start.md @@ -0,0 +1,64 @@ +# 快速开始 + +## 1. 安装 Bun + +```bash +# macOS / Linux +curl -fsSL https://bun.sh/install | bash + +# macOS (Homebrew) +brew install bun + +# Windows (PowerShell) +powershell -c "irm bun.sh/install.ps1 | iex" +``` + +> 精简版 Linux 如提示 `unzip is required`,先运行 `apt update && apt install -y unzip` + +## 2. 安装依赖并配置 + +```bash +bun install +cp .env.example .env +# 编辑 .env 填入你的 API Key,详见「环境变量」文档 +``` + +环境变量的完整说明请参考 [环境变量配置](./env-vars.md)。 + +## 3. 启动 + +### macOS / Linux + +```bash +./bin/claude-haha # 交互 TUI 模式 +./bin/claude-haha -p "your prompt here" # 无头模式 +./bin/claude-haha --help # 查看所有选项 +``` + +### Windows + +> **前置要求**:必须安装 [Git for Windows](https://git-scm.com/download/win) + +```powershell +# PowerShell / cmd 直接调用 Bun +bun --env-file=.env ./src/entrypoints/cli.tsx + +# 或在 Git Bash 中运行 +./bin/claude-haha +``` + +## 4. 全局使用(可选) + +将 `bin/` 加入 PATH 后可在任意目录启动,详见 [全局使用指南](./global-usage.md): + +```bash +export PATH="$HOME/path/to/claude-code-haha/bin:$PATH" +``` + +## 5. 降级模式 + +如果 Ink TUI 出现问题,可以使用降级 Recovery CLI 模式: + +```bash +CLAUDE_CODE_FORCE_RECOVERY_CLI=1 ./bin/claude-haha +``` diff --git a/_all-in-one-upload/cc-haha/docs/images/desktop_ui/09_slash_command.png b/_all-in-one-upload/cc-haha/docs/images/desktop_ui/09_slash_command.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf3824640e16dbc6e3e745de0cea42a7a8a1e55 GIT binary patch literal 474485 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 z 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

UQawukGl2r$`EOi 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


%{|bnZpJY1?|!Q{EU9j=v-mi?P)1#6BwS) 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
    t0?=VyFvDCnE`6D&_~dfo)z(b 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

    |= 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 JK;c&4{{a&m3X1>$ literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/images/im/feishu/03-dev-console.png b/_all-in-one-upload/cc-haha/docs/images/im/feishu/03-dev-console.png new file mode 100644 index 0000000000000000000000000000000000000000..8e08efa1feef329b53ae9f285da599e8873209a9 GIT binary patch literal 233228 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

    `Qr4@Joz9 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

    Ulm&9EY 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

    qU(_CwBu*xfH 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 GkN*p7eeSLR literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/images/im/feishu/07-menu-clear.png b/_all-in-one-upload/cc-haha/docs/images/im/feishu/07-menu-clear.png new file mode 100644 index 0000000000000000000000000000000000000000..3e24c63072ef06fe64109accf4c638c959e82925 GIT binary patch literal 130582 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⋙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 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/images/im/telegram/03-bot-token.png b/_all-in-one-upload/cc-haha/docs/images/im/telegram/03-bot-token.png new file mode 100644 index 0000000000000000000000000000000000000000..c07e983face6f67b6bb4e96b0e8d50688509bb60 GIT binary patch literal 727105 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 z%0A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%0AWnAj#OIE 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৘HdbZWcsh+ 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 t+ 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�-%_k5exjR#BUH(VIQ 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 z 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%0Awgn8_Qcg}a(l`0mbeL#0D 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 Z_^MLVQ%L;{=Re>9QPfbVlCuo`e*i^%MB@Me literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/images/logo-horizontal.png b/_all-in-one-upload/cc-haha/docs/images/logo-horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..e1cc11e19fb124bd5475b73587a86aa31bd4d864 GIT binary patch literal 120093 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 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/docs/memory/03-autodream.md b/_all-in-one-upload/cc-haha/docs/memory/03-autodream.md new file mode 100644 index 0000000..c58f817 --- /dev/null +++ b/_all-in-one-upload/cc-haha/docs/memory/03-autodream.md @@ -0,0 +1,316 @@ +# Claude Code 记忆系统 — AutoDream 记忆整合 + +> Claude 会"做梦"——在后台静默回顾近期会话,整合、更新、修剪记忆,就像人类睡眠中整理白天的记忆一样。 + +

    +AutoDream · 触发条件 · 整合流程 · 安全限制 · UI 展示 · 配置开关 · 对比 · 源码导航 +

    + +![AutoDream 概览](./images/11-autodream-overview.png) + +--- + +## 一、什么是 AutoDream? + +AutoDream 是 Claude Code 的 **后台记忆整合机制**,内部代号 **"Dream: Memory Consolidation"**。 + +核心隐喻: + +| 人类 | Claude Code | +|------|-------------| +| 白天随手记笔记 | `extractMemories` — 每次对话后提取新记忆 | +| 晚上睡觉时整理笔记本 | `autoDream` — 定期回顾多个会话,整合全部记忆 | + +当你不活跃时(默认间隔 24 小时、积累 5 个会话后),Claude 会在后台静默启动一个 **"做梦"子智能体**(forked subagent),回顾所有近期会话记录,将零散的记忆整合为结构化的、去重的、去过时的持久化知识。 + +**关键源码**:`src/services/autoDream/autoDream.ts` + +```typescript +// Background memory consolidation. Fires the /dream prompt as a forked +// subagent when time-gate passes AND enough sessions have accumulated. +``` + +--- + +## 二、触发条件 + +![AutoDream 触发流程](./images/12-autodream-trigger.png) + +AutoDream 采用 **五重门控** 机制,按开销从低到高逐级检查: + +### 门控链 + +| 序号 | 门控 | 说明 | 开销 | +|------|------|------|------| +| 1 | **功能开关** | `isAutoDreamEnabled()` + 非 KAIROS + 非远程模式 + autoMemory 已启用 | 内存读取 | +| 2 | **时间门控** | 距上次整合 >= `minHours`(默认 24h) | 1 次 stat | +| 3 | **扫描节流** | 上次扫描后至少等 10 分钟再重新扫描 | 时间戳比较 | +| 4 | **会话门控** | 自上次整合后至少 `minSessions` 个新会话(默认 5 个,排除当前) | 目录扫描 | +| 5 | **锁门控** | 没有其他进程正在做梦(PID 锁文件) | stat + read | + +**关键源码** `src/services/autoDream/autoDream.ts:63-66`: + +```typescript +const DEFAULTS: AutoDreamConfig = { + minHours: 24, // 距离上次整合至少 24 小时 + minSessions: 5, // 期间至少积累了 5 个会话 +} +``` + +### 扫描节流 + +当时间门控通过但会话门控未通过时,锁文件的 mtime 不会更新,导致时间门控在后续每个 turn 都会通过。为避免频繁的目录扫描,设有 **10 分钟的扫描节流**: + +```typescript +const SESSION_SCAN_INTERVAL_MS = 10 * 60 * 1000 +``` + +### 执行入口 + +AutoDream 在每次 AI 回复完成后的 stop hook 阶段被触发(fire-and-forget,不阻塞主线程): + +**关键源码** `src/query/stopHooks.ts:154-156`: + +```typescript +if (!toolUseContext.agentId) { + void executeAutoDream(stopHookContext, toolUseContext.appendSystemMessage) +} +``` + +### 阻止条件 + +以下情况不会触发 AutoDream: + +- **KAIROS 模式**:使用独立的 disk-skill dream +- **远程模式**:`getIsRemoteMode() === true` +- **autoMemory 未启用** +- **`--bare` / SIMPLE 模式** +- **子代理内**:只有主代理才触发 + +--- + +## 三、四阶段整合流程 + +![AutoDream 四阶段流程](./images/13-autodream-phases.png) + +一旦所有门控通过,AutoDream 启动一个 **分叉子智能体**,按照 `consolidationPrompt.ts` 定义的 4 阶段提示词工作: + +### Phase 1 — Orient(定向) + +``` +- ls 记忆目录,查看已有文件 +- 读取 MEMORY.md 索引,理解当前知识结构 +- 浏览现有主题文件,避免创建重复 +- 如存在 logs/ 或 sessions/ 子目录,检查最近条目 +``` + +### Phase 2 — Gather recent signal(收集近期信号) + +按优先级从高到低搜集信息: + +1. **Daily logs** — `logs/YYYY/MM/YYYY-MM-DD.md`(追加流日志) +2. **漂移的记忆** — 与代码库现状矛盾的旧事实 +3. **会话记录搜索** — 用 `grep` 在 JSONL 转录文件中窄范围检索 + +``` +不要穷尽读取转录文件。只查找你已经怀疑重要的内容。 +``` + +### Phase 3 — Consolidate(整合) + +- **合并**新信号到已有主题文件(而非创建新的近似文件) +- **转换**相对日期为绝对日期("昨天" → "2026-04-03") +- **删除**被推翻的旧事实 + +### Phase 4 — Prune and index(修剪与索引) + +- 更新 `MEMORY.md`,保持 ≤ 规定行数且 ≤ 25KB +- 删除指向过时记忆的指针 +- 压缩冗长条目(>200 字符的索引行,将内容移入主题文件) +- 新增指向重要记忆的指针 +- 解决矛盾(两个文件意见不一致时,修复错误的那个) + +**关键源码** `src/services/autoDream/consolidationPrompt.ts:10-64` + +--- + +## 四、安全限制 + +AutoDream 子智能体受到严格的工具权限限制: + +### Bash 仅限只读 + +``` +允许:ls, find, grep, cat, stat, wc, head, tail +拒绝:所有写入、重定向、修改状态的命令 +``` + +### 文件操作仅限记忆目录 + +`createAutoMemCanUseTool()` 是 `extractMemories` 和 `autoDream` 共享的权限函数: + +``` +允许 Read / Grep / Glob — 无限制 +允许 Edit / Write — 仅 auto-memory 目录内 +拒绝 MCP / Agent / 非只读 Bash / 其他写操作 +``` + +**关键源码** `src/services/extractMemories/extractMemories.ts:167-171` + +### 锁文件机制 + +使用 `.consolidate-lock` 文件实现进程级互斥: + +| 机制 | 说明 | +|------|------| +| **锁内容** | 持有者 PID | +| **时间戳** | 锁文件 mtime = 上次整合时间 | +| **过期** | 持有超过 1 小时视为过期(防 PID 复用) | +| **竞争** | 两个进程同时写入 → 最后写入者获胜,失败者在 re-read 时退出 | +| **回滚** | 失败时回退 mtime 到获取前的值,让下次尝试不受影响 | +| **崩溃恢复** | mtime 卡住 + 死 PID → 下个进程回收锁 | + +**关键源码** `src/services/autoDream/consolidationLock.ts` + +--- + +## 五、UI 展示 + +### 底部状态栏 + +当 AutoDream 运行时,底部状态栏会显示 **"dreaming"** 标签: + +```typescript +// src/tasks/pillLabel.ts:61-62 +case 'dream': + return 'dreaming' +``` + +### 任务详情对话框 + +用户按 `Shift+Down` 可打开后台任务对话框,查看梦境的实时进度: + +- **DreamDetailDialog** 组件展示: + - 正在回顾的会话数量 + - 当前阶段:`starting`(正在分析)→ `updating`(正在修改记忆文件) + - 最近的助手文本响应和工具调用次数 + - 已触碰的文件路径列表 + +- **用户可按 `x` 键终止**正在进行的梦境(触发 abort + 锁回滚) + +### 完成通知 + +梦境完成后,如果有文件被修改,会在主会话中显示内联通知: + +```typescript +appendSystemMessage({ + ...createMemorySavedMessage(dreamState.filesTouched), + verb: 'Improved', +}) +``` + +**关键源码**: +- `src/tasks/DreamTask/DreamTask.ts` — 任务状态管理 +- `src/components/tasks/DreamDetailDialog.tsx` — UI 组件 + +--- + +## 六、配置与开关 + +### settings.json + +```json +{ + "autoDreamEnabled": true +} +``` + +- **显式设置时**:直接使用用户的值 +- **未设置时**:由远程 GrowthBook feature flag `tengu_onyx_plover` 控制 + +**关键源码** `src/services/autoDream/config.ts:13-21`: + +```typescript +export function isAutoDreamEnabled(): boolean { + const setting = getInitialSettings().autoDreamEnabled + if (setting !== undefined) return setting + const gb = getFeatureValue_CACHED_MAY_BE_STALE<{ enabled?: unknown } | null>( + 'tengu_onyx_plover', null, + ) + return gb?.enabled === true +} +``` + +### 远程配置参数 + +`tengu_onyx_plover` feature flag 可配置: + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `enabled` | boolean | — | 功能总开关 | +| `minHours` | number | 24 | 最小间隔(小时) | +| `minSessions` | number | 5 | 最小会话数 | + +### 手动触发 `/dream` + +除了自动触发,用户可以通过 `/dream` 命令手动触发记忆整合。手动触发会调用 `recordConsolidation()` 更新锁文件时间戳。 + +--- + +## 七、与 extractMemories 的关系 + +| 维度 | extractMemories | autoDream | +|------|----------------|-----------| +| **触发频率** | 每次对话回合结束 | 每 24h + 5 个会话 | +| **触发位置** | `stopHooks.ts` L149 | `stopHooks.ts` L155 | +| **处理范围** | 当前对话最近的消息 | 多个会话的历史记录 | +| **目标** | 提取新记忆 | 整合/去重/修剪已有记忆 | +| **人类类比** | 白天随手记笔记 | 睡觉时整理笔记本 | +| **共享组件** | `createAutoMemCanUseTool` | `createAutoMemCanUseTool` | +| **分叉代理** | 最多 5 turns | 无 turn 限制 | +| **转录** | 不记录(`skipTranscript`) | 不记录(`skipTranscript`) | + +### 协作流 + +``` +每次对话结束 + ↓ +extractMemories → 提取新记忆片段 → 写入 *.md + MEMORY.md + ↓ +(积累 24h + 5个会话后) + ↓ +autoDream → 回顾所有记忆 + 会话记录 + ↓ +合并重复 / 修正过时 / 删除矛盾 / 压缩索引 + ↓ +MEMORY.md 和主题文件焕然一新 +``` + +--- + +## 八、源码导航 + +| 文件 | 职责 | +|------|------| +| `src/services/autoDream/autoDream.ts` | 主逻辑:门控检查、启动分叉代理、进度监控 | +| `src/services/autoDream/config.ts` | 开关控制:settings.json 或 GrowthBook | +| `src/services/autoDream/consolidationPrompt.ts` | 梦境提示词:4 阶段整合工作流 | +| `src/services/autoDream/consolidationLock.ts` | 锁文件机制:防并发、时间戳、回滚 | +| `src/tasks/DreamTask/DreamTask.ts` | UI 任务注册:状态管理、终止、回滚 | +| `src/tasks/pillLabel.ts` | 底部状态栏标签:"dreaming" | +| `src/components/tasks/DreamDetailDialog.tsx` | 梦境详情对话框 UI | +| `src/query/stopHooks.ts` | 执行入口:每次回复后触发 | +| `src/utils/backgroundHousekeeping.ts` | 初始化入口:`initAutoDream()` | +| `src/services/extractMemories/extractMemories.ts` | 共享的 `createAutoMemCanUseTool` | + +--- + +## 九、分析事件 + +AutoDream 通过以下事件记录运行状态: + +| 事件 | 时机 | 附带数据 | +|------|------|----------| +| `tengu_auto_dream_fired` | 梦境启动 | `hours_since`, `sessions_since` | +| `tengu_auto_dream_completed` | 梦境完成 | `cache_read`, `cache_created`, `output`, `sessions_reviewed` | +| `tengu_auto_dream_failed` | 梦境失败 | — | diff --git a/_all-in-one-upload/cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/active_session/code.html b/_all-in-one-upload/cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/active_session/code.html new file mode 100644 index 0000000..61c5619 --- /dev/null +++ b/_all-in-one-upload/cc-haha/docs/ui-clone/stitch_claudecode_haha_frontend_design/active_session/code.html @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + +
    + +
    +
    +Claude Code Companion + +
    +
    +
    + + +
    + +
    +
    + +
    + +
    +
    + +
    session-active-042 • last updated 2m ago
    +
    + +
    + +
    + +
    +
    +

    + I need to refactor the login flow in auth.ts. Let's move the JWT signing logic to a separate helper and add validation for the user payload. +

    +
    +
    + +
    +
    +smart_toy +
    +
    +
    +

    Understood. I will begin by analyzing the current implementation of auth.ts. I'll extract the JWT logic into a new utility function and implement the validation layer as requested.

    +
    + +
    + +
    + +
    +
    +
    +edit_document +edit_file: auth.ts +
    +Modified +
    +
    ++ const validatePayload = (user) => { ... }
    ++ export const signToken = (payload) => jwt.sign(payload, SECRET);
    +- // OLD LOGIC REMOVED +
    +
    + +
    +
    +
    +Crafting... + +00:42 +1.2k tokens +
    + +
    +
    +
    +
    + +
    +
    +
    + + + +
    +
    + + +
    +Claude 3.5 Sonnet +
    +
    +
    +
    + +
    +
    +User Avatar • username • Pro Plan +
    +
    + + + +
    +
    +
    + \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/release-notes/v0.1.7.md b/_all-in-one-upload/cc-haha/release-notes/v0.1.7.md new file mode 100644 index 0000000..4666c10 --- /dev/null +++ b/_all-in-one-upload/cc-haha/release-notes/v0.1.7.md @@ -0,0 +1,35 @@ +# Claude Code Haha v0.1.7 + +这是一个以 Windows 桌面端在线更新稳定性和聊天展示体验修复为主的补丁版本。 + +相比 `v0.1.6`,这次重点修复了 Windows 桌面端自动更新后本地服务启动失败的问题,并补齐了 Windows 开发环境 WebUI 启动 CLI 时的宏预加载逻辑。同时修复了 Mermaid 渲染错误提示和聊天手动滚动被打断的问题。 + +## 主要更新 + +- 修复 Windows 桌面端在线自动更新流程:安装新版本前会先停止本地 server sidecar 和 adapter sidecar,避免升级后重启时出现 `os error 32`、`另一个程序正在使用此文件` 或“本地服务启动失败”。 +- Windows 发布产物改为优先使用 NSIS 安装包,并在安装器 hook 中处理 sidecar 进程清理,降低从旧版本自动升级时被文件锁卡住的概率。 +- 修复 Windows 开发环境中 WebUI 启动 CLI 失败的问题,源码 fallback 启动 CLI 时会正确加载 `preload.ts`,避免 `MACRO is not defined` 导致进程启动失败。 +- 优化聊天列表手动滚动体验:用户向上查看历史消息时,流式输出不会强制把视图拉回底部;当用户仍停留在底部附近时,会继续保持自动跟随最新回复。 + +## 问题修复 + +- 修复 Mermaid 图表渲染失败时可能出现开发错误覆盖层的问题,让错误状态保持在聊天消息内部展示。 +- 修复聊天流式输出期间手动滚动位置被覆盖的问题,并补充相关回归测试。 +- 修复 Windows updater 安装阶段没有提前释放 sidecar 文件句柄的问题。 +- 修复 Windows dev WebUI 会话启动时 CLI 进程直接以 code 1 退出的问题。 + +## 其他说明 + +- 已安装 `v0.1.5` 或 `v0.1.6` 的 Windows 用户正常情况下可以直接升级到 `v0.1.7`,不需要先卸载旧版本。 +- 如果某台机器已经卡在旧版本升级后的“本地服务启动失败”页面,可以先完全退出桌面端和残留的 `claude-sidecar.exe` 进程,再安装 `v0.1.7`。 +- GitHub Release 正文继续以 `release-notes/v0.1.7.md` 作为来源,发布时无需再手动复制 Markdown。 + +## 安装说明 + +### macOS + +首次打开如果提示“已损坏”或“无法验证开发者”,请执行: + +```bash +xattr -cr /Applications/Claude\ Code\ Haha.app +``` diff --git a/_all-in-one-upload/cc-haha/src/bridge/replBridgeHandle.ts b/_all-in-one-upload/cc-haha/src/bridge/replBridgeHandle.ts new file mode 100644 index 0000000..f04d745 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/bridge/replBridgeHandle.ts @@ -0,0 +1,36 @@ +import { updateSessionBridgeId } from '../utils/concurrentSessions.js' +import type { ReplBridgeHandle } from './replBridge.js' +import { toCompatSessionId } from './sessionIdCompat.js' + +/** + * Global pointer to the active REPL bridge handle, so callers outside + * useReplBridge's React tree (tools, slash commands) can invoke handle methods + * like subscribePR. Same one-bridge-per-process justification as bridgeDebug.ts + * — the handle's closure captures the sessionId and getAccessToken that created + * the session, and re-deriving those independently (BriefTool/upload.ts pattern) + * risks staging/prod token divergence. + * + * Set from useReplBridge.tsx when init completes; cleared on teardown. + */ + +let handle: ReplBridgeHandle | null = null + +export function setReplBridgeHandle(h: ReplBridgeHandle | null): void { + handle = h + // Publish (or clear) our bridge session ID in the session record so other + // local peers can dedup us out of their bridge list — local is preferred. + void updateSessionBridgeId(getSelfBridgeCompatId() ?? null).catch(() => {}) +} + +export function getReplBridgeHandle(): ReplBridgeHandle | null { + return handle +} + +/** + * Our own bridge session ID in the session_* compat format the API returns + * in /v1/sessions responses — or undefined if bridge isn't connected. + */ +export function getSelfBridgeCompatId(): string | undefined { + const h = getReplBridgeHandle() + return h ? toCompatSessionId(h.bridgeSessionId) : undefined +} diff --git a/_all-in-one-upload/cc-haha/src/bridge/sessionRunner.ts b/_all-in-one-upload/cc-haha/src/bridge/sessionRunner.ts new file mode 100644 index 0000000..bc232bc --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/bridge/sessionRunner.ts @@ -0,0 +1,550 @@ +import { type ChildProcess, spawn } from 'child_process' +import { createWriteStream, type WriteStream } from 'fs' +import { tmpdir } from 'os' +import { dirname, join } from 'path' +import { createInterface } from 'readline' +import { jsonParse, jsonStringify } from '../utils/slowOperations.js' +import { debugTruncate } from './debugUtils.js' +import type { + SessionActivity, + SessionDoneStatus, + SessionHandle, + SessionSpawner, + SessionSpawnOpts, +} from './types.js' + +const MAX_ACTIVITIES = 10 +const MAX_STDERR_LINES = 10 + +/** + * Sanitize a session ID for use in file names. + * Strips any characters that could cause path traversal (e.g. `../`, `/`) + * or other filesystem issues, replacing them with underscores. + */ +export function safeFilenameId(id: string): string { + return id.replace(/[^a-zA-Z0-9_-]/g, '_') +} + +/** + * A control_request emitted by the child CLI when it needs permission to + * execute a **specific** tool invocation (not a general capability check). + * The bridge forwards this to the server so the user can approve/deny. + */ +export type PermissionRequest = { + type: 'control_request' + request_id: string + request: { + /** Per-invocation permission check — "may I run this tool with these inputs?" */ + subtype: 'can_use_tool' + tool_name: string + input: Record + tool_use_id: string + } +} + +type SessionSpawnerDeps = { + execPath: string + /** + * Arguments that must precede the CLI flags when spawning. Empty for + * compiled binaries (where execPath is the claude binary itself); contains + * the script path (process.argv[1]) for npm installs where execPath is the + * node runtime. Without this, node sees --sdk-url as a node option and + * exits with "bad option: --sdk-url" (see anthropics/claude-code#28334). + */ + scriptArgs: string[] + env: NodeJS.ProcessEnv + verbose: boolean + sandbox: boolean + debugFile?: string + permissionMode?: string + onDebug: (msg: string) => void + onActivity?: (sessionId: string, activity: SessionActivity) => void + onPermissionRequest?: ( + sessionId: string, + request: PermissionRequest, + accessToken: string, + ) => void +} + +/** Map tool names to human-readable verbs for the status display. */ +const TOOL_VERBS: Record = { + Read: 'Reading', + Write: 'Writing', + Edit: 'Editing', + MultiEdit: 'Editing', + Bash: 'Running', + Glob: 'Searching', + Grep: 'Searching', + WebFetch: 'Fetching', + WebSearch: 'Searching', + Task: 'Running task', + FileReadTool: 'Reading', + FileWriteTool: 'Writing', + FileEditTool: 'Editing', + GlobTool: 'Searching', + GrepTool: 'Searching', + BashTool: 'Running', + NotebookEditTool: 'Editing notebook', + LSP: 'LSP', +} + +function toolSummary(name: string, input: Record): string { + const verb = TOOL_VERBS[name] ?? name + const target = + (input.file_path as string) ?? + (input.filePath as string) ?? + (input.pattern as string) ?? + (input.command as string | undefined)?.slice(0, 60) ?? + (input.url as string) ?? + (input.query as string) ?? + '' + if (target) { + return `${verb} ${target}` + } + return verb +} + +function extractActivities( + line: string, + sessionId: string, + onDebug: (msg: string) => void, +): SessionActivity[] { + let parsed: unknown + try { + parsed = jsonParse(line) + } catch { + return [] + } + + if (!parsed || typeof parsed !== 'object') { + return [] + } + + const msg = parsed as Record + const activities: SessionActivity[] = [] + const now = Date.now() + + switch (msg.type) { + case 'assistant': { + const message = msg.message as Record | undefined + if (!message) break + const content = message.content + if (!Array.isArray(content)) break + + for (const block of content) { + if (!block || typeof block !== 'object') continue + const b = block as Record + + if (b.type === 'tool_use') { + const name = (b.name as string) ?? 'Tool' + const input = (b.input as Record) ?? {} + const summary = toolSummary(name, input) + activities.push({ + type: 'tool_start', + summary, + timestamp: now, + }) + onDebug( + `[bridge:activity] sessionId=${sessionId} tool_use name=${name} ${inputPreview(input)}`, + ) + } else if (b.type === 'text') { + const text = (b.text as string) ?? '' + if (text.length > 0) { + activities.push({ + type: 'text', + summary: text.slice(0, 80), + timestamp: now, + }) + onDebug( + `[bridge:activity] sessionId=${sessionId} text "${text.slice(0, 100)}"`, + ) + } + } + } + break + } + case 'result': { + const subtype = msg.subtype as string | undefined + if (subtype === 'success') { + activities.push({ + type: 'result', + summary: 'Session completed', + timestamp: now, + }) + onDebug( + `[bridge:activity] sessionId=${sessionId} result subtype=success`, + ) + } else if (subtype) { + const errors = msg.errors as string[] | undefined + const errorSummary = errors?.[0] ?? `Error: ${subtype}` + activities.push({ + type: 'error', + summary: errorSummary, + timestamp: now, + }) + onDebug( + `[bridge:activity] sessionId=${sessionId} result subtype=${subtype} error="${errorSummary}"`, + ) + } else { + onDebug( + `[bridge:activity] sessionId=${sessionId} result subtype=undefined`, + ) + } + break + } + default: + break + } + + return activities +} + +/** + * Extract plain text from a replayed SDKUserMessage NDJSON line. Returns the + * trimmed text if this looks like a real human-authored message, otherwise + * undefined so the caller keeps waiting for the first real message. + */ +function extractUserMessageText( + msg: Record, +): string | undefined { + // Skip tool-result user messages (wrapped subagent results) and synthetic + // caveat messages — neither is human-authored. + if (msg.parent_tool_use_id != null || msg.isSynthetic || msg.isReplay) + return undefined + + const message = msg.message as Record | undefined + const content = message?.content + let text: string | undefined + if (typeof content === 'string') { + text = content + } else if (Array.isArray(content)) { + for (const block of content) { + if ( + block && + typeof block === 'object' && + (block as Record).type === 'text' + ) { + text = (block as Record).text as string | undefined + break + } + } + } + text = text?.trim() + return text ? text : undefined +} + +/** Build a short preview of tool input for debug logging. */ +function inputPreview(input: Record): string { + const parts: string[] = [] + for (const [key, val] of Object.entries(input)) { + if (typeof val === 'string') { + parts.push(`${key}="${val.slice(0, 100)}"`) + } + if (parts.length >= 3) break + } + return parts.join(' ') +} + +export function createSessionSpawner(deps: SessionSpawnerDeps): SessionSpawner { + return { + spawn(opts: SessionSpawnOpts, dir: string): SessionHandle { + // Debug file resolution: + // 1. If deps.debugFile is provided, use it with session ID suffix for uniqueness + // 2. If verbose or ant build, auto-generate a temp file path + // 3. Otherwise, no debug file + const safeId = safeFilenameId(opts.sessionId) + let debugFile: string | undefined + if (deps.debugFile) { + const ext = deps.debugFile.lastIndexOf('.') + if (ext > 0) { + debugFile = `${deps.debugFile.slice(0, ext)}-${safeId}${deps.debugFile.slice(ext)}` + } else { + debugFile = `${deps.debugFile}-${safeId}` + } + } else if (deps.verbose || process.env.USER_TYPE === 'ant') { + debugFile = join(tmpdir(), 'claude', `bridge-session-${safeId}.log`) + } + + // Transcript file: write raw NDJSON lines for post-hoc analysis. + // Placed alongside the debug file when one is configured. + let transcriptStream: WriteStream | null = null + let transcriptPath: string | undefined + if (deps.debugFile) { + transcriptPath = join( + dirname(deps.debugFile), + `bridge-transcript-${safeId}.jsonl`, + ) + transcriptStream = createWriteStream(transcriptPath, { flags: 'a' }) + transcriptStream.on('error', err => { + deps.onDebug( + `[bridge:session] Transcript write error: ${err.message}`, + ) + transcriptStream = null + }) + deps.onDebug(`[bridge:session] Transcript log: ${transcriptPath}`) + } + + const args = [ + ...deps.scriptArgs, + '--print', + '--sdk-url', + opts.sdkUrl, + '--session-id', + opts.sessionId, + '--input-format', + 'stream-json', + '--output-format', + 'stream-json', + '--replay-user-messages', + ...(deps.verbose ? ['--verbose'] : []), + ...(debugFile ? ['--debug-file', debugFile] : []), + ...(deps.permissionMode + ? ['--permission-mode', deps.permissionMode] + : []), + ] + + const env: NodeJS.ProcessEnv = { + ...deps.env, + // Strip the bridge's OAuth token so the child CC process uses + // the session access token for inference instead. + CLAUDE_CODE_OAUTH_TOKEN: undefined, + CLAUDE_CODE_ENVIRONMENT_KIND: 'bridge', + ...(deps.sandbox && { CLAUDE_CODE_FORCE_SANDBOX: '1' }), + CLAUDE_CODE_SESSION_ACCESS_TOKEN: opts.accessToken, + // v1: HybridTransport (WS reads + POST writes) to Session-Ingress. + // Harmless in v2 mode — transportUtils checks CLAUDE_CODE_USE_CCR_V2 first. + CLAUDE_CODE_POST_FOR_SESSION_INGRESS_V2: '1', + // v2: SSETransport + CCRClient to CCR's /v1/code/sessions/* endpoints. + // Same env vars environment-manager sets in the container path. + ...(opts.useCcrV2 && { + CLAUDE_CODE_USE_CCR_V2: '1', + CLAUDE_CODE_WORKER_EPOCH: String(opts.workerEpoch), + }), + } + + deps.onDebug( + `[bridge:session] Spawning sessionId=${opts.sessionId} sdkUrl=${opts.sdkUrl} accessToken=${opts.accessToken ? 'present' : 'MISSING'}`, + ) + deps.onDebug(`[bridge:session] Child args: ${args.join(' ')}`) + if (debugFile) { + deps.onDebug(`[bridge:session] Debug log: ${debugFile}`) + } + + // Pipe all three streams: stdin for control, stdout for NDJSON parsing, + // stderr for error capture and diagnostics. + const child: ChildProcess = spawn(deps.execPath, args, { + cwd: dir, + stdio: ['pipe', 'pipe', 'pipe'], + env, + windowsHide: true, + }) + + deps.onDebug( + `[bridge:session] sessionId=${opts.sessionId} pid=${child.pid}`, + ) + + const activities: SessionActivity[] = [] + let currentActivity: SessionActivity | null = null + const lastStderr: string[] = [] + let sigkillSent = false + let firstUserMessageSeen = false + + // Buffer stderr for error diagnostics + if (child.stderr) { + const stderrRl = createInterface({ input: child.stderr }) + stderrRl.on('line', line => { + // Forward stderr to bridge's stderr in verbose mode + if (deps.verbose) { + process.stderr.write(line + '\n') + } + // Ring buffer of last N lines + if (lastStderr.length >= MAX_STDERR_LINES) { + lastStderr.shift() + } + lastStderr.push(line) + }) + } + + // Parse NDJSON from child stdout + if (child.stdout) { + const rl = createInterface({ input: child.stdout }) + rl.on('line', line => { + // Write raw NDJSON to transcript file + if (transcriptStream) { + transcriptStream.write(line + '\n') + } + + // Log all messages flowing from the child CLI to the bridge + deps.onDebug( + `[bridge:ws] sessionId=${opts.sessionId} <<< ${debugTruncate(line)}`, + ) + + // In verbose mode, forward raw output to stderr + if (deps.verbose) { + process.stderr.write(line + '\n') + } + + const extracted = extractActivities( + line, + opts.sessionId, + deps.onDebug, + ) + for (const activity of extracted) { + // Maintain ring buffer + if (activities.length >= MAX_ACTIVITIES) { + activities.shift() + } + activities.push(activity) + currentActivity = activity + + deps.onActivity?.(opts.sessionId, activity) + } + + // Detect control_request and replayed user messages. + // extractActivities parses the same line but swallows parse errors + // and skips 'user' type — re-parse here is cheap (NDJSON lines are + // small) and keeps each path self-contained. + { + let parsed: unknown + try { + parsed = jsonParse(line) + } catch { + // Non-JSON line, skip detection + } + if (parsed && typeof parsed === 'object') { + const msg = parsed as Record + + if (msg.type === 'control_request') { + const request = msg.request as + | Record + | undefined + if ( + request?.subtype === 'can_use_tool' && + deps.onPermissionRequest + ) { + deps.onPermissionRequest( + opts.sessionId, + parsed as PermissionRequest, + opts.accessToken, + ) + } + // interrupt is turn-level; the child handles it internally (print.ts) + } else if ( + msg.type === 'user' && + !firstUserMessageSeen && + opts.onFirstUserMessage + ) { + const text = extractUserMessageText(msg) + if (text) { + firstUserMessageSeen = true + opts.onFirstUserMessage(text) + } + } + } + } + }) + } + + const done = new Promise(resolve => { + child.on('close', (code, signal) => { + // Close transcript stream on exit + if (transcriptStream) { + transcriptStream.end() + transcriptStream = null + } + + if (signal === 'SIGTERM' || signal === 'SIGINT') { + deps.onDebug( + `[bridge:session] sessionId=${opts.sessionId} interrupted signal=${signal} pid=${child.pid}`, + ) + resolve('interrupted') + } else if (code === 0) { + deps.onDebug( + `[bridge:session] sessionId=${opts.sessionId} completed exit_code=0 pid=${child.pid}`, + ) + resolve('completed') + } else { + deps.onDebug( + `[bridge:session] sessionId=${opts.sessionId} failed exit_code=${code} pid=${child.pid}`, + ) + resolve('failed') + } + }) + + child.on('error', err => { + deps.onDebug( + `[bridge:session] sessionId=${opts.sessionId} spawn error: ${err.message}`, + ) + resolve('failed') + }) + }) + + const handle: SessionHandle = { + sessionId: opts.sessionId, + done, + activities, + accessToken: opts.accessToken, + lastStderr, + get currentActivity(): SessionActivity | null { + return currentActivity + }, + kill(): void { + if (!child.killed) { + deps.onDebug( + `[bridge:session] Sending SIGTERM to sessionId=${opts.sessionId} pid=${child.pid}`, + ) + // On Windows, child.kill('SIGTERM') throws; use default signal. + if (process.platform === 'win32') { + child.kill() + } else { + child.kill('SIGTERM') + } + } + }, + forceKill(): void { + // Use separate flag because child.killed is set when kill() is called, + // not when the process exits. We need to send SIGKILL even after SIGTERM. + if (!sigkillSent && child.pid) { + sigkillSent = true + deps.onDebug( + `[bridge:session] Sending SIGKILL to sessionId=${opts.sessionId} pid=${child.pid}`, + ) + if (process.platform === 'win32') { + child.kill() + } else { + child.kill('SIGKILL') + } + } + }, + writeStdin(data: string): void { + if (child.stdin && !child.stdin.destroyed) { + deps.onDebug( + `[bridge:ws] sessionId=${opts.sessionId} >>> ${debugTruncate(data)}`, + ) + child.stdin.write(data) + } + }, + updateAccessToken(token: string): void { + handle.accessToken = token + // Send the fresh token to the child process via stdin. The child's + // StructuredIO handles update_environment_variables messages by + // setting process.env directly, so getSessionIngressAuthToken() + // picks up the new token on the next refreshHeaders call. + handle.writeStdin( + jsonStringify({ + type: 'update_environment_variables', + variables: { CLAUDE_CODE_SESSION_ACCESS_TOKEN: token }, + }) + '\n', + ) + deps.onDebug( + `[bridge:session] Sent token refresh via stdin for sessionId=${opts.sessionId}`, + ) + }, + } + + return handle + }, + } +} + +export { extractActivities as _extractActivitiesForTesting } diff --git a/_all-in-one-upload/cc-haha/src/buddy/useBuddyNotification.tsx b/_all-in-one-upload/cc-haha/src/buddy/useBuddyNotification.tsx new file mode 100644 index 0000000..fddcb70 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/buddy/useBuddyNotification.tsx @@ -0,0 +1,93 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { useEffect } from 'react'; +import { useNotifications } from '../context/notifications.js'; +import { Text } from '../ink.js'; +import { getGlobalConfig } from '../utils/config.js'; +import { getRainbowColor } from '../utils/thinking.js'; + +// Local date, not UTC — 24h rolling wave across timezones. Sustained Twitter +// buzz instead of a single UTC-midnight spike, gentler on soul-gen load. +// Teaser window: April 1-7, 2026 only. Command stays live forever after. +export function isBuddyTeaserWindow(): boolean { + if ("external" === 'ant') return true; + const d = new Date(); + return d.getFullYear() === 2026 && d.getMonth() === 3 && d.getDate() <= 7; +} +export function isBuddyLive(): boolean { + if ("external" === 'ant') return true; + const d = new Date(); + return d.getFullYear() > 2026 || d.getFullYear() === 2026 && d.getMonth() >= 3; +} +function RainbowText(t0) { + const $ = _c(2); + const { + text + } = t0; + let t1; + if ($[0] !== text) { + t1 = <>{[...text].map(_temp)}; + $[0] = text; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} + +// Rainbow /buddy teaser shown on startup when no companion hatched yet. +// Idle presence and reactions are handled by CompanionSprite directly. +function _temp(ch, i) { + return {ch}; +} +export function useBuddyNotification() { + const $ = _c(4); + const { + addNotification, + removeNotification + } = useNotifications(); + let t0; + let t1; + if ($[0] !== addNotification || $[1] !== removeNotification) { + t0 = () => { + const config = getGlobalConfig(); + if (config.companion || !isBuddyTeaserWindow()) { + return; + } + addNotification({ + key: "buddy-teaser", + jsx: , + priority: "immediate", + timeoutMs: 15000 + }); + return () => removeNotification("buddy-teaser"); + }; + t1 = [addNotification, removeNotification]; + $[0] = addNotification; + $[1] = removeNotification; + $[2] = t0; + $[3] = t1; + } else { + t0 = $[2]; + t1 = $[3]; + } + useEffect(t0, t1); +} +export function findBuddyTriggerPositions(text: string): Array<{ + start: number; + end: number; +}> { + const triggers: Array<{ + start: number; + end: number; + }> = []; + const re = /\/buddy\b/g; + let m: RegExpExecArray | null; + while ((m = re.exec(text)) !== null) { + triggers.push({ + start: m.index, + end: m.index + m[0].length + }); + } + return triggers; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiUmVhY3QiLCJ1c2VFZmZlY3QiLCJ1c2VOb3RpZmljYXRpb25zIiwiVGV4dCIsImdldEdsb2JhbENvbmZpZyIsImdldFJhaW5ib3dDb2xvciIsImlzQnVkZHlUZWFzZXJXaW5kb3ciLCJkIiwiRGF0ZSIsImdldEZ1bGxZZWFyIiwiZ2V0TW9udGgiLCJnZXREYXRlIiwiaXNCdWRkeUxpdmUiLCJSYWluYm93VGV4dCIsInQwIiwiJCIsIl9jIiwidGV4dCIsInQxIiwibWFwIiwiX3RlbXAiLCJjaCIsImkiLCJ1c2VCdWRkeU5vdGlmaWNhdGlvbiIsImFkZE5vdGlmaWNhdGlvbiIsInJlbW92ZU5vdGlmaWNhdGlvbiIsImNvbmZpZyIsImNvbXBhbmlvbiIsImtleSIsImpzeCIsInByaW9yaXR5IiwidGltZW91dE1zIiwiZmluZEJ1ZGR5VHJpZ2dlclBvc2l0aW9ucyIsIkFycmF5Iiwic3RhcnQiLCJlbmQiLCJ0cmlnZ2VycyIsInJlIiwibSIsIlJlZ0V4cEV4ZWNBcnJheSIsImV4ZWMiLCJwdXNoIiwiaW5kZXgiLCJsZW5ndGgiXSwic291cmNlcyI6WyJ1c2VCdWRkeU5vdGlmaWNhdGlvbi50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZmVhdHVyZSB9IGZyb20gJ2J1bjpidW5kbGUnXG5pbXBvcnQgUmVhY3QsIHsgdXNlRWZmZWN0IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyB1c2VOb3RpZmljYXRpb25zIH0gZnJvbSAnLi4vY29udGV4dC9ub3RpZmljYXRpb25zLmpzJ1xuaW1wb3J0IHsgVGV4dCB9IGZyb20gJy4uL2luay5qcydcbmltcG9ydCB7IGdldEdsb2JhbENvbmZpZyB9IGZyb20gJy4uL3V0aWxzL2NvbmZpZy5qcydcbmltcG9ydCB7IGdldFJhaW5ib3dDb2xvciB9IGZyb20gJy4uL3V0aWxzL3RoaW5raW5nLmpzJ1xuXG4vLyBMb2NhbCBkYXRlLCBub3QgVVRDIOKAlCAyNGggcm9sbGluZyB3YXZlIGFjcm9zcyB0aW1lem9uZXMuIFN1c3RhaW5lZCBUd2l0dGVyXG4vLyBidXp6IGluc3RlYWQgb2YgYSBzaW5nbGUgVVRDLW1pZG5pZ2h0IHNwaWtlLCBnZW50bGVyIG9uIHNvdWwtZ2VuIGxvYWQuXG4vLyBUZWFzZXIgd2luZG93OiBBcHJpbCAxLTcsIDIwMjYgb25seS4gQ29tbWFuZCBzdGF5cyBsaXZlIGZvcmV2ZXIgYWZ0ZXIuXG5leHBvcnQgZnVuY3Rpb24gaXNCdWRkeVRlYXNlcldpbmRvdygpOiBib29sZWFuIHtcbiAgaWYgKFwiZXh0ZXJuYWxcIiA9PT0gJ2FudCcpIHJldHVybiB0cnVlXG4gIGNvbnN0IGQgPSBuZXcgRGF0ZSgpXG4gIHJldHVybiBkLmdldEZ1bGxZZWFyKCkgPT09IDIwMjYgJiYgZC5nZXRNb250aCgpID09PSAzICYmIGQuZ2V0RGF0ZSgpIDw9IDdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQnVkZHlMaXZlKCk6IGJvb2xlYW4ge1xuICBpZiAoXCJleHRlcm5hbFwiID09PSAnYW50JykgcmV0dXJuIHRydWVcbiAgY29uc3QgZCA9IG5ldyBEYXRlKClcbiAgcmV0dXJuIChcbiAgICBkLmdldEZ1bGxZZWFyKCkgPiAyMDI2IHx8IChkLmdldEZ1bGxZZWFyKCkgPT09IDIwMjYgJiYgZC5nZXRNb250aCgpID49IDMpXG4gIClcbn1cblxuZnVuY3Rpb24gUmFpbmJvd1RleHQoeyB0ZXh0IH06IHsgdGV4dDogc3RyaW5nIH0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICB7Wy4uLnRleHRdLm1hcCgoY2gsIGkpID0+IChcbiAgICAgICAgPFRleHQga2V5PXtpfSBjb2xvcj17Z2V0UmFpbmJvd0NvbG9yKGkpfT5cbiAgICAgICAgICB7Y2h9XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICkpfVxuICAgIDwvPlxuICApXG59XG5cbi8vIFJhaW5ib3cgL2J1ZGR5IHRlYXNlciBzaG93biBvbiBzdGFydHVwIHdoZW4gbm8gY29tcGFuaW9uIGhhdGNoZWQgeWV0LlxuLy8gSWRsZSBwcmVzZW5jZSBhbmQgcmVhY3Rpb25zIGFyZSBoYW5kbGVkIGJ5IENvbXBhbmlvblNwcml0ZSBkaXJlY3RseS5cbmV4cG9ydCBmdW5jdGlvbiB1c2VCdWRkeU5vdGlmaWNhdGlvbigpOiB2b2lkIHtcbiAgY29uc3QgeyBhZGROb3RpZmljYXRpb24sIHJlbW92ZU5vdGlmaWNhdGlvbiB9ID0gdXNlTm90aWZpY2F0aW9ucygpXG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIWZlYXR1cmUoJ0JVRERZJykpIHJldHVyblxuICAgIGNvbnN0IGNvbmZpZyA9IGdldEdsb2JhbENvbmZpZygpXG4gICAgaWYgKGNvbmZpZy5jb21wYW5pb24gfHwgIWlzQnVkZHlUZWFzZXJXaW5kb3coKSkgcmV0dXJuXG4gICAgYWRkTm90aWZpY2F0aW9uKHtcbiAgICAgIGtleTogJ2J1ZGR5LXRlYXNlcicsXG4gICAgICBqc3g6IDxSYWluYm93VGV4dCB0ZXh0PVwiL2J1ZGR5XCIgLz4sXG4gICAgICBwcmlvcml0eTogJ2ltbWVkaWF0ZScsXG4gICAgICB0aW1lb3V0TXM6IDE1XzAwMCxcbiAgICB9KVxuICAgIHJldHVybiAoKSA9PiByZW1vdmVOb3RpZmljYXRpb24oJ2J1ZGR5LXRlYXNlcicpXG4gIH0sIFthZGROb3RpZmljYXRpb24sIHJlbW92ZU5vdGlmaWNhdGlvbl0pXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kQnVkZHlUcmlnZ2VyUG9zaXRpb25zKFxuICB0ZXh0OiBzdHJpbmcsXG4pOiBBcnJheTx7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH0+IHtcbiAgaWYgKCFmZWF0dXJlKCdCVUREWScpKSByZXR1cm4gW11cbiAgY29uc3QgdHJpZ2dlcnM6IEFycmF5PHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXIgfT4gPSBbXVxuICBjb25zdCByZSA9IC9cXC9idWRkeVxcYi9nXG4gIGxldCBtOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsXG4gIHdoaWxlICgobSA9IHJlLmV4ZWModGV4dCkpICE9PSBudWxsKSB7XG4gICAgdHJpZ2dlcnMucHVzaCh7IHN0YXJ0OiBtLmluZGV4LCBlbmQ6IG0uaW5kZXggKyBtWzBdLmxlbmd0aCB9KVxuICB9XG4gIHJldHVybiB0cmlnZ2Vyc1xufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsU0FBU0EsT0FBTyxRQUFRLFlBQVk7QUFDcEMsT0FBT0MsS0FBSyxJQUFJQyxTQUFTLFFBQVEsT0FBTztBQUN4QyxTQUFTQyxnQkFBZ0IsUUFBUSw2QkFBNkI7QUFDOUQsU0FBU0MsSUFBSSxRQUFRLFdBQVc7QUFDaEMsU0FBU0MsZUFBZSxRQUFRLG9CQUFvQjtBQUNwRCxTQUFTQyxlQUFlLFFBQVEsc0JBQXNCOztBQUV0RDtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQVNDLG1CQUFtQkEsQ0FBQSxDQUFFLEVBQUUsT0FBTyxDQUFDO0VBQzdDLElBQUksVUFBVSxLQUFLLEtBQUssRUFBRSxPQUFPLElBQUk7RUFDckMsTUFBTUMsQ0FBQyxHQUFHLElBQUlDLElBQUksQ0FBQyxDQUFDO0VBQ3BCLE9BQU9ELENBQUMsQ0FBQ0UsV0FBVyxDQUFDLENBQUMsS0FBSyxJQUFJLElBQUlGLENBQUMsQ0FBQ0csUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUlILENBQUMsQ0FBQ0ksT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQzNFO0FBRUEsT0FBTyxTQUFTQyxXQUFXQSxDQUFBLENBQUUsRUFBRSxPQUFPLENBQUM7RUFDckMsSUFBSSxVQUFVLEtBQUssS0FBSyxFQUFFLE9BQU8sSUFBSTtFQUNyQyxNQUFNTCxDQUFDLEdBQUcsSUFBSUMsSUFBSSxDQUFDLENBQUM7RUFDcEIsT0FDRUQsQ0FBQyxDQUFDRSxXQUFXLENBQUMsQ0FBQyxHQUFHLElBQUksSUFBS0YsQ0FBQyxDQUFDRSxXQUFXLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSUYsQ0FBQyxDQUFDRyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUU7QUFFN0U7QUFFQSxTQUFBRyxZQUFBQyxFQUFBO0VBQUEsTUFBQUMsQ0FBQSxH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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/break-cache/index.js b/_all-in-one-upload/cc-haha/src/commands/break-cache/index.js new file mode 100644 index 0000000..e1a619d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/break-cache/index.js @@ -0,0 +1 @@ +export default { isEnabled: () => false, isHidden: true, name: 'stub' }; diff --git a/_all-in-one-upload/cc-haha/src/commands/compact/index.ts b/_all-in-one-upload/cc-haha/src/commands/compact/index.ts new file mode 100644 index 0000000..6db38d4 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/compact/index.ts @@ -0,0 +1,15 @@ +import type { Command } from '../../commands.js' +import { isEnvTruthy } from '../../utils/envUtils.js' + +const compact = { + type: 'local', + name: 'compact', + description: + 'Clear conversation history but keep a summary in context. Optional: /compact [instructions for summarization]', + isEnabled: () => !isEnvTruthy(process.env.DISABLE_COMPACT), + supportsNonInteractive: true, + argumentHint: '', + load: () => import('./compact.js'), +} satisfies Command + +export default compact diff --git a/_all-in-one-upload/cc-haha/src/commands/diff/index.ts b/_all-in-one-upload/cc-haha/src/commands/diff/index.ts new file mode 100644 index 0000000..a15b819 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/diff/index.ts @@ -0,0 +1,8 @@ +import type { Command } from '../../commands.js' + +export default { + type: 'local-jsx', + name: 'diff', + description: 'View uncommitted changes and per-turn diffs', + load: () => import('./diff.js'), +} satisfies Command diff --git a/_all-in-one-upload/cc-haha/src/commands/fast/fast.tsx b/_all-in-one-upload/cc-haha/src/commands/fast/fast.tsx new file mode 100644 index 0000000..398c3c3 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/fast/fast.tsx @@ -0,0 +1,269 @@ +import { c as _c } from "react/compiler-runtime"; +import * as React from 'react'; +import { useState } from 'react'; +import type { CommandResultDisplay, LocalJSXCommandContext } from '../../commands.js'; +import { Dialog } from '../../components/design-system/Dialog.js'; +import { FastIcon, getFastIconString } from '../../components/FastIcon.js'; +import { Box, Link, Text } from '../../ink.js'; +import { useKeybindings } from '../../keybindings/useKeybinding.js'; +import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from '../../services/analytics/index.js'; +import { type AppState, useAppState, useSetAppState } from '../../state/AppState.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; +import { clearFastModeCooldown, FAST_MODE_MODEL_DISPLAY, getFastModeModel, getFastModeRuntimeState, getFastModeUnavailableReason, isFastModeEnabled, isFastModeSupportedByModel, prefetchFastModeStatus } from '../../utils/fastMode.js'; +import { formatDuration } from '../../utils/format.js'; +import { formatModelPricing, getOpus46CostTier } from '../../utils/modelCost.js'; +import { updateSettingsForSource } from '../../utils/settings/settings.js'; +function applyFastMode(enable: boolean, setAppState: (f: (prev: AppState) => AppState) => void): void { + clearFastModeCooldown(); + updateSettingsForSource('userSettings', { + fastMode: enable ? true : undefined + }); + if (enable) { + setAppState(prev => { + // Only switch model if current model doesn't support fast mode + const needsModelSwitch = !isFastModeSupportedByModel(prev.mainLoopModel); + return { + ...prev, + ...(needsModelSwitch ? { + mainLoopModel: getFastModeModel(), + mainLoopModelForSession: null + } : {}), + fastMode: true + }; + }); + } else { + setAppState(prev => ({ + ...prev, + fastMode: false + })); + } +} +export function FastModePicker(t0) { + const $ = _c(30); + const { + onDone, + unavailableReason + } = t0; + const model = useAppState(_temp); + const initialFastMode = useAppState(_temp2); + const setAppState = useSetAppState(); + const [enableFastMode, setEnableFastMode] = useState(initialFastMode ?? false); + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = getFastModeRuntimeState(); + $[0] = t1; + } else { + t1 = $[0]; + } + const runtimeState = t1; + const isCooldown = runtimeState.status === "cooldown"; + const isUnavailable = unavailableReason !== null; + let t2; + if ($[1] === Symbol.for("react.memo_cache_sentinel")) { + t2 = formatModelPricing(getOpus46CostTier(true)); + $[1] = t2; + } else { + t2 = $[1]; + } + const pricing = t2; + let t3; + if ($[2] !== enableFastMode || $[3] !== isUnavailable || $[4] !== model || $[5] !== onDone || $[6] !== setAppState) { + t3 = function handleConfirm() { + if (isUnavailable) { + return; + } + applyFastMode(enableFastMode, setAppState); + logEvent("tengu_fast_mode_toggled", { + enabled: enableFastMode, + source: "picker" as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS + }); + if (enableFastMode) { + const fastIcon = getFastIconString(enableFastMode); + const modelUpdated = !isFastModeSupportedByModel(model) ? ` · model set to ${FAST_MODE_MODEL_DISPLAY}` : ""; + onDone(`${fastIcon} Fast mode ON${modelUpdated} · ${pricing}`); + } else { + setAppState(_temp3); + onDone("Fast mode OFF"); + } + }; + $[2] = enableFastMode; + $[3] = isUnavailable; + $[4] = model; + $[5] = onDone; + $[6] = setAppState; + $[7] = t3; + } else { + t3 = $[7]; + } + const handleConfirm = t3; + let t4; + if ($[8] !== initialFastMode || $[9] !== isUnavailable || $[10] !== onDone || $[11] !== setAppState) { + t4 = function handleCancel() { + if (isUnavailable) { + if (initialFastMode) { + applyFastMode(false, setAppState); + } + onDone("Fast mode OFF", { + display: "system" + }); + return; + } + const message = initialFastMode ? `${getFastIconString()} Kept Fast mode ON` : "Kept Fast mode OFF"; + onDone(message, { + display: "system" + }); + }; + $[8] = initialFastMode; + $[9] = isUnavailable; + $[10] = onDone; + $[11] = setAppState; + $[12] = t4; + } else { + t4 = $[12]; + } + const handleCancel = t4; + let t5; + if ($[13] !== isUnavailable) { + t5 = function handleToggle() { + if (isUnavailable) { + return; + } + setEnableFastMode(_temp4); + }; + $[13] = isUnavailable; + $[14] = t5; + } else { + t5 = $[14]; + } + const handleToggle = t5; + let t6; + if ($[15] !== handleConfirm || $[16] !== handleToggle) { + t6 = { + "confirm:yes": handleConfirm, + "confirm:nextField": handleToggle, + "confirm:next": handleToggle, + "confirm:previous": handleToggle, + "confirm:cycleMode": handleToggle, + "confirm:toggle": handleToggle + }; + $[15] = handleConfirm; + $[16] = handleToggle; + $[17] = t6; + } else { + t6 = $[17]; + } + let t7; + if ($[18] === Symbol.for("react.memo_cache_sentinel")) { + t7 = { + context: "Confirmation" + }; + $[18] = t7; + } else { + t7 = $[18]; + } + useKeybindings(t6, t7); + let t8; + if ($[19] === Symbol.for("react.memo_cache_sentinel")) { + t8 = Fast mode (research preview); + $[19] = t8; + } else { + t8 = $[19]; + } + const title = t8; + let t9; + if ($[20] !== isUnavailable) { + t9 = exitState => exitState.pending ? Press {exitState.keyName} again to exit : isUnavailable ? Esc to cancel : Tab to toggle · Enter to confirm · Esc to cancel; + $[20] = isUnavailable; + $[21] = t9; + } else { + t9 = $[21]; + } + let t10; + if ($[22] !== enableFastMode || $[23] !== unavailableReason) { + t10 = unavailableReason ? {unavailableReason} : <>Fast mode{enableFastMode ? "ON " : "OFF"}{pricing}{isCooldown && runtimeState.status === "cooldown" && {runtimeState.reason === "overloaded" ? "Fast mode overloaded and is temporarily unavailable" : "You've hit your fast limit"}{" \xB7 resets in "}{formatDuration(runtimeState.resetAt - Date.now(), { + hideTrailingZeros: true + })}}; + $[22] = enableFastMode; + $[23] = unavailableReason; + $[24] = t10; + } else { + t10 = $[24]; + } + let t11; + if ($[25] === Symbol.for("react.memo_cache_sentinel")) { + t11 = Learn more:{" "}https://code.claude.com/docs/en/fast-mode; + $[25] = t11; + } else { + t11 = $[25]; + } + let t12; + if ($[26] !== handleCancel || $[27] !== t10 || $[28] !== t9) { + t12 = {t10}{t11}; + $[26] = handleCancel; + $[27] = t10; + $[28] = t9; + $[29] = t12; + } else { + t12 = $[29]; + } + return t12; +} +function _temp4(prev_0) { + return !prev_0; +} +function _temp3(prev) { + return { + ...prev, + fastMode: false + }; +} +function _temp2(s_0) { + return s_0.fastMode; +} +function _temp(s) { + return s.mainLoopModel; +} +async function handleFastModeShortcut(enable: boolean, getAppState: () => AppState, setAppState: (f: (prev: AppState) => AppState) => void): Promise { + const unavailableReason = getFastModeUnavailableReason(); + if (unavailableReason) { + return `Fast mode unavailable: ${unavailableReason}`; + } + const { + mainLoopModel + } = getAppState(); + applyFastMode(enable, setAppState); + logEvent('tengu_fast_mode_toggled', { + enabled: enable, + source: 'shortcut' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS + }); + if (enable) { + const fastIcon = getFastIconString(true); + const modelUpdated = !isFastModeSupportedByModel(mainLoopModel) ? ` · model set to ${FAST_MODE_MODEL_DISPLAY}` : ''; + const pricing = formatModelPricing(getOpus46CostTier(true)); + return `${fastIcon} Fast mode ON${modelUpdated} · ${pricing}`; + } else { + return `Fast mode OFF`; + } +} +export async function call(onDone: LocalJSXCommandOnDone, context: LocalJSXCommandContext, args?: string): Promise { + if (!isFastModeEnabled()) { + return null; + } + + // Fetch org fast mode status before showing the picker. We must know + // whether the org has disabled fast mode before allowing any toggle. + // If a startup prefetch is already in flight, this awaits it. + await prefetchFastModeStatus(); + const arg = args?.trim().toLowerCase(); + if (arg === 'on' || arg === 'off') { + const result = await handleFastModeShortcut(arg === 'on', context.getAppState, context.setAppState); + onDone(result); + return null; + } + const unavailableReason = getFastModeUnavailableReason(); + logEvent('tengu_fast_mode_picker_shown', { + unavailable_reason: (unavailableReason ?? '') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS + }); + return ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZVN0YXRlIiwiQ29tbWFuZFJlc3VsdERpc3BsYXkiLCJMb2NhbEpTWENvbW1hbmRDb250ZXh0IiwiRGlhbG9nIiwiRmFzdEljb24iLCJnZXRGYXN0SWNvblN0cmluZyIsIkJveCIsIkxpbmsiLCJUZXh0IiwidXNlS2V5YmluZGluZ3MiLCJBbmFseXRpY3NNZXRhZGF0YV9JX1ZFUklGSUVEX1RISVNfSVNfTk9UX0NPREVfT1JfRklMRVBBVEhTIiwibG9nRXZlbnQiLCJBcHBTdGF0ZSIsInVzZUFwcFN0YXRlIiwidXNlU2V0QXBwU3RhdGUiLCJMb2NhbEpTWENvbW1hbmRPbkRvbmUiLCJjbGVhckZhc3RNb2RlQ29vbGRvd24iLCJGQVNUX01PREVfTU9ERUxfRElTUExBWSIsImdldEZhc3RNb2RlTW9kZWwiLCJnZXRGYXN0TW9kZVJ1bnRpbWVTdGF0ZSIsImdldEZhc3RNb2RlVW5hdmFpbGFibGVSZWFzb24iLCJpc0Zhc3RNb2RlRW5hYmxlZCIsImlzRmFzdE1vZGVTdXBwb3J0ZWRCeU1vZGVsIiwicHJlZmV0Y2hGYXN0TW9kZVN0YXR1cyIsImZvcm1hdER1cmF0aW9uIiwiZm9ybWF0TW9kZWxQcmljaW5nIiwiZ2V0T3B1czQ2Q29zdFRpZXIiLCJ1cGRhdGVTZXR0aW5nc0ZvclNvdXJjZSIsImFwcGx5RmFzdE1vZGUiLCJlbmFibGUiLCJzZXRBcHBTdGF0ZSIsImYiLCJwcmV2IiwiZmFzdE1vZGUiLCJ1bmRlZmluZWQiLCJuZWVkc01vZGVsU3dpdGNoIiwibWFpbkxvb3BNb2RlbCIsIm1haW5Mb29wTW9kZWxGb3JTZXNzaW9uIiwiRmFzdE1vZGVQaWNrZXIiLCJ0MCIsIiQiLCJfYyIsIm9uRG9uZSIsInVuYXZhaWxhYmxlUmVhc29uIiwibW9kZWwiLCJfdGVtcCIsImluaXRpYWxGYXN0TW9kZSIsIl90ZW1wMiIsImVuYWJsZUZhc3RNb2RlIiwic2V0RW5hYmxlRmFzdE1vZGUiLCJ0MSIsIlN5bWJvbCIsImZvciIsInJ1bnRpbWVTdGF0ZSIsImlzQ29vbGRvd24iLCJzdGF0dXMiLCJpc1VuYXZhaWxhYmxlIiwidDIiLCJwcmljaW5nIiwidDMiLCJoYW5kbGVDb25maXJtIiwiZW5hYmxlZCIsInNvdXJjZSIsImZhc3RJY29uIiwibW9kZWxVcGRhdGVkIiwiX3RlbXAzIiwidDQiLCJoYW5kbGVDYW5jZWwiLCJkaXNwbGF5IiwibWVzc2FnZSIsInQ1IiwiaGFuZGxlVG9nZ2xlIiwiX3RlbXA0IiwidDYiLCJ0NyIsImNvbnRleHQiLCJ0OCIsInRpdGxlIiwidDkiLCJleGl0U3RhdGUiLCJwZW5kaW5nIiwia2V5TmFtZSIsInQxMCIsInJlYXNvbiIsInJlc2V0QXQiLCJEYXRlIiwibm93IiwiaGlkZVRyYWlsaW5nWmVyb3MiLCJ0MTEiLCJ0MTIiLCJwcmV2XzAiLCJzXzAiLCJzIiwiaGFuZGxlRmFzdE1vZGVTaG9ydGN1dCIsImdldEFwcFN0YXRlIiwiUHJvbWlzZSIsImNhbGwiLCJhcmdzIiwiUmVhY3ROb2RlIiwiYXJnIiwidHJpbSIsInRvTG93ZXJDYXNlIiwicmVzdWx0IiwidW5hdmFpbGFibGVfcmVhc29uIl0sInNvdXJjZXMiOlsiZmFzdC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHR5cGUge1xuICBDb21tYW5kUmVzdWx0RGlzcGxheSxcbiAgTG9jYWxKU1hDb21tYW5kQ29udGV4dCxcbn0gZnJvbSAnLi4vLi4vY29tbWFuZHMuanMnXG5pbXBvcnQgeyBEaWFsb2cgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL2Rlc2lnbi1zeXN0ZW0vRGlhbG9nLmpzJ1xuaW1wb3J0IHsgRmFzdEljb24sIGdldEZhc3RJY29uU3RyaW5nIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9GYXN0SWNvbi5qcydcbmltcG9ydCB7IEJveCwgTGluaywgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB7IHVzZUtleWJpbmRpbmdzIH0gZnJvbSAnLi4vLi4va2V5YmluZGluZ3MvdXNlS2V5YmluZGluZy5qcydcbmltcG9ydCB7XG4gIHR5cGUgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyxcbiAgbG9nRXZlbnQsXG59IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB7XG4gIHR5cGUgQXBwU3RhdGUsXG4gIHVzZUFwcFN0YXRlLFxuICB1c2VTZXRBcHBTdGF0ZSxcbn0gZnJvbSAnLi4vLi4vc3RhdGUvQXBwU3RhdGUuanMnXG5pbXBvcnQgdHlwZSB7IExvY2FsSlNYQ29tbWFuZE9uRG9uZSB9IGZyb20gJy4uLy4uL3R5cGVzL2NvbW1hbmQuanMnXG5pbXBvcnQge1xuICBjbGVhckZhc3RNb2RlQ29vbGRvd24sXG4gIEZBU1RfTU9ERV9NT0RFTF9ESVNQTEFZLFxuICBnZXRGYXN0TW9kZU1vZGVsLFxuICBnZXRGYXN0TW9kZVJ1bnRpbWVTdGF0ZSxcbiAgZ2V0RmFzdE1vZGVVbmF2YWlsYWJsZVJlYXNvbixcbiAgaXNGYXN0TW9kZUVuYWJsZWQsXG4gIGlzRmFzdE1vZGVTdXBwb3J0ZWRCeU1vZGVsLFxuICBwcmVmZXRjaEZhc3RNb2RlU3RhdHVzLFxufSBmcm9tICcuLi8uLi91dGlscy9mYXN0TW9kZS5qcydcbmltcG9ydCB7IGZvcm1hdER1cmF0aW9uIH0gZnJvbSAnLi4vLi4vdXRpbHMvZm9ybWF0LmpzJ1xuaW1wb3J0IHsgZm9ybWF0TW9kZWxQcmljaW5nLCBnZXRPcHVzNDZDb3N0VGllciB9IGZyb20gJy4uLy4uL3V0aWxzL21vZGVsQ29zdC5qcydcbmltcG9ydCB7IHVwZGF0ZVNldHRpbmdzRm9yU291cmNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvc2V0dGluZ3Mvc2V0dGluZ3MuanMnXG5cbmZ1bmN0aW9uIGFwcGx5RmFzdE1vZGUoXG4gIGVuYWJsZTogYm9vbGVhbixcbiAgc2V0QXBwU3RhdGU6IChmOiAocHJldjogQXBwU3RhdGUpID0+IEFwcFN0YXRlKSA9PiB2b2lkLFxuKTogdm9pZCB7XG4gIGNsZWFyRmFzdE1vZGVDb29sZG93bigpXG4gIHVwZGF0ZVNldHRpbmdzRm9yU291cmNlKCd1c2VyU2V0dGluZ3MnLCB7XG4gICAgZmFzdE1vZGU6IGVuYWJsZSA/IHRydWUgOiB1bmRlZmluZWQsXG4gIH0pXG4gIGlmIChlbmFibGUpIHtcbiAgICBzZXRBcHBTdGF0ZShwcmV2ID0+IHtcbiAgICAgIC8vIE9ubHkgc3dpdGNoIG1vZGVsIGlmIGN1cnJlbnQgbW9kZWwgZG9lc24ndCBzdXBwb3J0IGZhc3QgbW9kZVxuICAgICAgY29uc3QgbmVlZHNNb2RlbFN3aXRjaCA9ICFpc0Zhc3RNb2RlU3VwcG9ydGVkQnlNb2RlbChwcmV2Lm1haW5Mb29wTW9kZWwpXG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5wcmV2LFxuICAgICAgICAuLi4obmVlZHNNb2RlbFN3aXRjaFxuICAgICAgICAgID8geyBtYWluTG9vcE1vZGVsOiBnZXRGYXN0TW9kZU1vZGVsKCksIG1haW5Mb29wTW9kZWxGb3JTZXNzaW9uOiBudWxsIH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgICAgZmFzdE1vZGU6IHRydWUsXG4gICAgICB9XG4gICAgfSlcbiAgfSBlbHNlIHtcbiAgICBzZXRBcHBTdGF0ZShwcmV2ID0+ICh7IC4uLnByZXYsIGZhc3RNb2RlOiBmYWxzZSB9KSlcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gRmFzdE1vZGVQaWNrZXIoe1xuICBvbkRvbmUsXG4gIHVuYXZhaWxhYmxlUmVhc29uLFxufToge1xuICBvbkRvbmU6IChcbiAgICByZXN1bHQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHsgZGlzcGxheT86IENvbW1hbmRSZXN1bHREaXNwbGF5IH0sXG4gICkgPT4gdm9pZFxuICB1bmF2YWlsYWJsZVJlYXNvbjogc3RyaW5nIHwgbnVsbFxufSk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IG1vZGVsID0gdXNlQXBwU3RhdGUocyA9PiBzLm1haW5Mb29wTW9kZWwpXG4gIGNvbnN0IGluaXRpYWxGYXN0TW9kZSA9IHVzZUFwcFN0YXRlKHMgPT4gcy5mYXN0TW9kZSlcbiAgY29uc3Qgc2V0QXBwU3RhdGUgPSB1c2VTZXRBcHBTdGF0ZSgpXG4gIGNvbnN0IFtlbmFibGVGYXN0TW9kZSwgc2V0RW5hYmxlRmFzdE1vZGVdID0gdXNlU3RhdGUoaW5pdGlhbEZhc3RNb2RlID8/IGZhbHNlKVxuICBjb25zdCBydW50aW1lU3RhdGUgPSBnZXRGYXN0TW9kZVJ1bnRpbWVTdGF0ZSgpXG4gIGNvbnN0IGlzQ29vbGRvd24gPSBydW50aW1lU3RhdGUuc3RhdHVzID09PSAnY29vbGRvd24nXG4gIGNvbnN0IGlzVW5hdmFpbGFibGUgPSB1bmF2YWlsYWJsZVJlYXNvbiAhPT0gbnVsbFxuICBjb25zdCBwcmljaW5nID0gZm9ybWF0TW9kZWxQcmljaW5nKGdldE9wdXM0NkNvc3RUaWVyKHRydWUpKVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUNvbmZpcm0oKTogdm9pZCB7XG4gICAgaWYgKGlzVW5hdmFpbGFibGUpIHJldHVyblxuICAgIGFwcGx5RmFzdE1vZGUoZW5hYmxlRmFzdE1vZGUsIHNldEFwcFN0YXRlKVxuICAgIGxvZ0V2ZW50KCd0ZW5ndV9mYXN0X21vZGVfdG9nZ2xlZCcsIHtcbiAgICAgIGVuYWJsZWQ6IGVuYWJsZUZhc3RNb2RlLFxuICAgICAgc291cmNlOlxuICAgICAgICAncGlja2VyJyBhcyBBbmFseXRpY3NNZXRhZGF0YV9JX1ZFUklGSUVEX1RISVNfSVNfTk9UX0NPREVfT1JfRklMRVBBVEhTLFxuICAgIH0pXG4gICAgaWYgKGVuYWJsZUZhc3RNb2RlKSB7XG4gICAgICBjb25zdCBmYXN0SWNvbiA9IGdldEZhc3RJY29uU3RyaW5nKGVuYWJsZUZhc3RNb2RlKVxuICAgICAgY29uc3QgbW9kZWxVcGRhdGVkID0gIWlzRmFzdE1vZGVTdXBwb3J0ZWRCeU1vZGVsKG1vZGVsKVxuICAgICAgICA/IGAgwrcgbW9kZWwgc2V0IHRvICR7RkFTVF9NT0RFX01PREVMX0RJU1BMQVl9YFxuICAgICAgICA6ICcnXG4gICAgICBvbkRvbmUoYCR7ZmFzdEljb259IEZhc3QgbW9kZSBPTiR7bW9kZWxVcGRhdGVkfSDCtyAke3ByaWNpbmd9YClcbiAgICB9IGVsc2Uge1xuICAgICAgc2V0QXBwU3RhdGUocHJldiA9PiAoeyAuLi5wcmV2LCBmYXN0TW9kZTogZmFsc2UgfSkpXG4gICAgICBvbkRvbmUoYEZhc3QgbW9kZSBPRkZgKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUNhbmNlbCgpOiB2b2lkIHtcbiAgICBpZiAoaXNVbmF2YWlsYWJsZSkge1xuICAgICAgLy8gRW5zdXJlIGZhc3QgbW9kZSBpcyBvZmYgaWYgdGhlIG9yZyBoYXMgZGlzYWJsZWQgaXRcbiAgICAgIGlmIChpbml0aWFsRmFzdE1vZGUpIHtcbiAgICAgICAgYXBwbHlGYXN0TW9kZShmYWxzZSwgc2V0QXBwU3RhdGUpXG4gICAgICB9XG4gICAgICBvbkRvbmUoJ0Zhc3QgbW9kZSBPRkYnLCB7IGRpc3BsYXk6ICdzeXN0ZW0nIH0pXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgY29uc3QgbWVzc2FnZSA9IGluaXRpYWxGYXN0TW9kZVxuICAgICAgPyBgJHtnZXRGYXN0SWNvblN0cmluZygpfSBLZXB0IEZhc3QgbW9kZSBPTmBcbiAgICAgIDogYEtlcHQgRmFzdCBtb2RlIE9GRmBcbiAgICBvbkRvbmUobWVzc2FnZSwgeyBkaXNwbGF5OiAnc3lzdGVtJyB9KVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlVG9nZ2xlKCk6IHZvaWQge1xuICAgIGlmIChpc1VuYXZhaWxhYmxlKSByZXR1cm5cbiAgICBzZXRFbmFibGVGYXN0TW9kZShwcmV2ID0+ICFwcmV2KVxuICB9XG5cbiAgdXNlS2V5YmluZGluZ3MoXG4gICAge1xuICAgICAgJ2NvbmZpcm06eWVzJzogaGFuZGxlQ29uZmlybSxcbiAgICAgICdjb25maXJtOm5leHRGaWVsZCc6IGhhbmRsZVRvZ2dsZSxcbiAgICAgICdjb25maXJtOm5leHQnOiBoYW5kbGVUb2dnbGUsXG4gICAgICAnY29uZmlybTpwcmV2aW91cyc6IGhhbmRsZVRvZ2dsZSxcbiAgICAgICdjb25maXJtOmN5Y2xlTW9kZSc6IGhhbmRsZVRvZ2dsZSxcbiAgICAgICdjb25maXJtOnRvZ2dsZSc6IGhhbmRsZVRvZ2dsZSxcbiAgICB9LFxuICAgIHsgY29udGV4dDogJ0NvbmZpcm1hdGlvbicgfSxcbiAgKVxuXG4gIGNvbnN0IHRpdGxlID0gKFxuICAgIDxUZXh0PlxuICAgICAgPEZhc3RJY29uIGNvb2xkb3duPXtpc0Nvb2xkb3dufSAvPiBGYXN0IG1vZGUgKHJlc2VhcmNoIHByZXZpZXcpXG4gICAgPC9UZXh0PlxuICApXG5cbiAgcmV0dXJuIChcbiAgICA8RGlhbG9nXG4gICAgICB0aXRsZT17dGl0bGV9XG4gICAgICBzdWJ0aXRsZT17YEhpZ2gtc3BlZWQgbW9kZSBmb3IgJHtGQVNUX01PREVfTU9ERUxfRElTUExBWX0uIEJpbGxlZCBhcyBleHRyYSB1c2FnZSBhdCBhIHByZW1pdW0gcmF0ZS4gU2VwYXJhdGUgcmF0ZSBsaW1pdHMgYXBwbHkuYH1cbiAgICAgIG9uQ2FuY2VsPXtoYW5kbGVDYW5jZWx9XG4gICAgICBjb2xvcj1cImZhc3RNb2RlXCJcbiAgICAgIGlucHV0R3VpZGU9e2V4aXRTdGF0ZSA9PlxuICAgICAgICBleGl0U3RhdGUucGVuZGluZyA/IChcbiAgICAgICAgICA8VGV4dD5QcmVzcyB7ZXhpdFN0YXRlLmtleU5hbWV9IGFnYWluIHRvIGV4aXQ8L1RleHQ+XG4gICAgICAgICkgOiBpc1VuYXZhaWxhYmxlID8gKFxuICAgICAgICAgIDxUZXh0PkVzYyB0byBjYW5jZWw8L1RleHQ+XG4gICAgICAgICkgOiAoXG4gICAgICAgICAgPFRleHQ+VGFiIHRvIHRvZ2dsZSDCtyBFbnRlciB0byBjb25maXJtIMK3IEVzYyB0byBjYW5jZWw8L1RleHQ+XG4gICAgICAgIClcbiAgICAgIH1cbiAgICA+XG4gICAgICB7dW5hdmFpbGFibGVSZWFzb24gPyAoXG4gICAgICAgIDxCb3ggbWFyZ2luTGVmdD17Mn0+XG4gICAgICAgICAgPFRleHQgY29sb3I9XCJlcnJvclwiPnt1bmF2YWlsYWJsZVJlYXNvbn08L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgKSA6IChcbiAgICAgICAgPD5cbiAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBnYXA9ezB9IG1hcmdpbkxlZnQ9ezJ9PlxuICAgICAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwicm93XCIgZ2FwPXsyfT5cbiAgICAgICAgICAgICAgPFRleHQgYm9sZD5GYXN0IG1vZGU8L1RleHQ+XG4gICAgICAgICAgICAgIDxUZXh0XG4gICAgICAgICAgICAgICAgY29sb3I9e2VuYWJsZUZhc3RNb2RlID8gJ2Zhc3RNb2RlJyA6IHVuZGVmaW5lZH1cbiAgICAgICAgICAgICAgICBib2xkPXtlbmFibGVGYXN0TW9kZX1cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtlbmFibGVGYXN0TW9kZSA/ICdPTiAnIDogJ09GRid9XG4gICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+e3ByaWNpbmd9PC9UZXh0PlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgPC9Cb3g+XG5cbiAgICAgICAgICB7aXNDb29sZG93biAmJiBydW50aW1lU3RhdGUuc3RhdHVzID09PSAnY29vbGRvd24nICYmIChcbiAgICAgICAgICAgIDxCb3ggbWFyZ2luTGVmdD17Mn0+XG4gICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwid2FybmluZ1wiPlxuICAgICAgICAgICAgICAgIHtydW50aW1lU3RhdGUucmVhc29uID09PSAnb3ZlcmxvYWRlZCdcbiAgICAgICAgICAgICAgICAgID8gJ0Zhc3QgbW9kZSBvdmVybG9hZGVkIGFuZCBpcyB0ZW1wb3JhcmlseSB1bmF2YWlsYWJsZSdcbiAgICAgICAgICAgICAgICAgIDogXCJZb3UndmUgaGl0IHlvdXIgZmFzdCBsaW1pdFwifVxuICAgICAgICAgICAgICAgIHsnIMK3IHJlc2V0cyBpbiAnfVxuICAgICAgICAgICAgICAgIHtmb3JtYXREdXJhdGlvbihydW50aW1lU3RhdGUucmVzZXRBdCAtIERhdGUubm93KCksIHtcbiAgICAgICAgICAgICAgICAgIGhpZGVUcmFpbGluZ1plcm9zOiB0cnVlLFxuICAgICAgICAgICAgICAgIH0pfVxuICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICA8L0JveD5cbiAgICAgICAgICApfVxuICAgICAgICA8Lz5cbiAgICAgICl9XG4gICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgTGVhcm4gbW9yZTp7JyAnfVxuICAgICAgICA8TGluayB1cmw9XCJodHRwczovL2NvZGUuY2xhdWRlLmNvbS9kb2NzL2VuL2Zhc3QtbW9kZVwiPlxuICAgICAgICAgIGh0dHBzOi8vY29kZS5jbGF1ZGUuY29tL2RvY3MvZW4vZmFzdC1tb2RlXG4gICAgICAgIDwvTGluaz5cbiAgICAgIDwvVGV4dD5cbiAgICA8L0RpYWxvZz5cbiAgKVxufVxuXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVGYXN0TW9kZVNob3J0Y3V0KFxuICBlbmFibGU6IGJvb2xlYW4sXG4gIGdldEFwcFN0YXRlOiAoKSA9PiBBcHBTdGF0ZSxcbiAgc2V0QXBwU3RhdGU6IChmOiAocHJldjogQXBwU3RhdGUpID0+IEFwcFN0YXRlKSA9PiB2b2lkLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdW5hdmFpbGFibGVSZWFzb24gPSBnZXRGYXN0TW9kZVVuYXZhaWxhYmxlUmVhc29uKClcbiAgaWYgKHVuYXZhaWxhYmxlUmVhc29uKSB7XG4gICAgcmV0dXJuIGBGYXN0IG1vZGUgdW5hdmFpbGFibGU6ICR7dW5hdmFpbGFibGVSZWFzb259YFxuICB9XG5cbiAgY29uc3QgeyBtYWluTG9vcE1vZGVsIH0gPSBnZXRBcHBTdGF0ZSgpXG4gIGFwcGx5RmFzdE1vZGUoZW5hYmxlLCBzZXRBcHBTdGF0ZSlcbiAgbG9nRXZlbnQoJ3Rlbmd1X2Zhc3RfbW9kZV90b2dnbGVkJywge1xuICAgIGVuYWJsZWQ6IGVuYWJsZSxcbiAgICBzb3VyY2U6XG4gICAgICAnc2hvcnRjdXQnIGFzIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMsXG4gIH0pXG5cbiAgaWYgKGVuYWJsZSkge1xuICAgIGNvbnN0IGZhc3RJY29uID0gZ2V0RmFzdEljb25TdHJpbmcodHJ1ZSlcbiAgICBjb25zdCBtb2RlbFVwZGF0ZWQgPSAhaXNGYXN0TW9kZVN1cHBvcnRlZEJ5TW9kZWwobWFpbkxvb3BNb2RlbClcbiAgICAgID8gYCDCtyBtb2RlbCBzZXQgdG8gJHtGQVNUX01PREVfTU9ERUxfRElTUExBWX1gXG4gICAgICA6ICcnXG4gICAgY29uc3QgcHJpY2luZyA9IGZvcm1hdE1vZGVsUHJpY2luZyhnZXRPcHVzNDZDb3N0VGllcih0cnVlKSlcbiAgICByZXR1cm4gYCR7ZmFzdEljb259IEZhc3QgbW9kZSBPTiR7bW9kZWxVcGRhdGVkfSDCtyAke3ByaWNpbmd9YFxuICB9IGVsc2Uge1xuICAgIHJldHVybiBgRmFzdCBtb2RlIE9GRmBcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2FsbChcbiAgb25Eb25lOiBMb2NhbEpTWENvbW1hbmRPbkRvbmUsXG4gIGNvbnRleHQ6IExvY2FsSlNYQ29tbWFuZENvbnRleHQsXG4gIGFyZ3M/OiBzdHJpbmcsXG4pOiBQcm9taXNlPFJlYWN0LlJlYWN0Tm9kZSB8IG51bGw+IHtcbiAgaWYgKCFpc0Zhc3RNb2RlRW5hYmxlZCgpKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vIEZldGNoIG9yZyBmYXN0IG1vZGUgc3RhdHVzIGJlZm9yZSBzaG93aW5nIHRoZSBwaWNrZXIuIFdlIG11c3Qga25vd1xuICAvLyB3aGV0aGVyIHRoZSBvcmcgaGFzIGRpc2FibGVkIGZhc3QgbW9kZSBiZWZvcmUgYWxsb3dpbmcgYW55IHRvZ2dsZS5cbiAgLy8gSWYgYSBzdGFydHVwIHByZWZldGNoIGlzIGFscmVhZHkgaW4gZmxpZ2h0LCB0aGlzIGF3YWl0cyBpdC5cbiAgYXdhaXQgcHJlZmV0Y2hGYXN0TW9kZVN0YXR1cygpXG5cbiAgY29uc3QgYXJnID0gYXJncz8udHJpbSgpLnRvTG93ZXJDYXNlKClcbiAgaWYgKGFyZyA9PT0gJ29uJyB8fCBhcmcgPT09ICdvZmYnKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaGFuZGxlRmFzdE1vZGVTaG9ydGN1dChcbiAgICAgIGFyZyA9PT0gJ29uJyxcbiAgICAgIGNvbnRleHQuZ2V0QXBwU3RhdGUsXG4gICAgICBjb250ZXh0LnNldEFwcFN0YXRlLFxuICAgIClcbiAgICBvbkRvbmUocmVzdWx0KVxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICBjb25zdCB1bmF2YWlsYWJsZVJlYXNvbiA9IGdldEZhc3RNb2RlVW5hdmFpbGFibGVSZWFzb24oKVxuICBsb2dFdmVudCgndGVuZ3VfZmFzdF9tb2RlX3BpY2tlcl9zaG93bicsIHtcbiAgICB1bmF2YWlsYWJsZV9yZWFzb246ICh1bmF2YWlsYWJsZVJlYXNvbiA/P1xuICAgICAgJycpIGFzIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMsXG4gIH0pXG4gIHJldHVybiAoXG4gICAgPEZhc3RNb2RlUGlja2VyIG9uRG9uZT17b25Eb25lfSB1bmF2YWlsYWJsZVJlYXNvbj17dW5hdmFpbGFibGVSZWFzb259IC8+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsUUFBUSxRQUFRLE9BQU87QUFDaEMsY0FDRUMsb0JBQW9CLEVBQ3BCQyxzQkFBc0IsUUFDakIsbUJBQW1CO0FBQzFCLFNBQVNDLE1BQU0sUUFBUSwwQ0FBMEM7QUFDakUsU0FBU0MsUUFBUSxFQUFFQyxpQkFBaUIsUUFBUSw4QkFBOEI7QUFDMUUsU0FBU0Ms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QUltQixNQUFNLEVBQUU7SUFDVixNQUFNa0MsUUFBUSxHQUFHMUQsaUJBQWlCLENBQUMsSUFBSSxDQUFDO0lBQ3hDLE1BQU0yRCxZQUFZLEdBQUcsQ0FBQzFDLDBCQUEwQixDQUFDYyxhQUFhLENBQUMsR0FDM0QsbUJBQW1CbkIsdUJBQXVCLEVBQUUsR0FDNUMsRUFBRTtJQUNOLE1BQU15QyxPQUFPLEdBQUdqQyxrQkFBa0IsQ0FBQ0MsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0QsT0FBTyxHQUFHcUMsUUFBUSxnQkFBZ0JDLFlBQVksTUFBTU4sT0FBTyxFQUFFO0VBQy9ELENBQUMsTUFBTTtJQUNMLE9BQU8sZUFBZTtFQUN4QjtBQUNGO0FBRUEsT0FBTyxlQUFlc0MsSUFBSUEsQ0FDeEJ0RCxNQUFNLEVBQUUzQixxQkFBcUIsRUFDN0I0RCxPQUFPLEVBQUV6RSxzQkFBc0IsRUFDL0IrRixJQUFhLENBQVIsRUFBRSxNQUFNLENBQ2QsRUFBRUYsT0FBTyxDQUFDaEcsS0FBSyxDQUFDbUcsU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDO0VBQ2pDLElBQUksQ0FBQzdFLGlCQUFpQixDQUFDLENBQUMsRUFBRTtJQUN4QixPQUFPLElBQUk7RUFDYjs7RUFFQTtFQUNBO0VBQ0E7RUFDQSxNQUFNRSxzQkFBc0IsQ0FBQyxDQUFDO0VBRTlCLE1BQU00RSxHQUFHLEdBQUdGLElBQUksRUFBRUcsSUFBSSxDQUFDLENBQUMsQ0FBQ0MsV0FBVyxDQUFDLENBQUM7RUFDdEMsSUFBSUYsR0FBRyxLQUFLLElBQUksSUFBSUEsR0FBRyxLQUFLLEtBQUssRUFBRTtJQUNqQyxNQUFNRyxNQUFNLEdBQUcsTUFBTVQsc0JBQXNCLENBQ3pDTSxHQUFHLEtBQUssSUFBSSxFQUNaeEIsT0FBTyxDQUFDbUIsV0FBVyxFQUNuQm5CLE9BQU8sQ0FBQzdDLFdBQ1YsQ0FBQztJQUNEWSxNQUFNLENBQUM0RCxNQUFNLENBQUM7SUFDZCxPQUFPLElBQUk7RUFDYjtFQUVBLE1BQU0zRCxpQkFBaUIsR0FBR3ZCLDRCQUE0QixDQUFDLENBQUM7RUFDeERULFFBQVEsQ0FBQyw4QkFBOEIsRUFBRTtJQUN2QzRGLGtCQUFrQixFQUFFLENBQUM1RCxpQkFBaUIsSUFDcEMsRUFBRSxLQUFLakM7RUFDWCxDQUFDLENBQUM7RUFDRixPQUNFLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDZ0MsTUFBTSxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQ0MsaUJBQWlCLENBQUMsR0FBRztBQUU1RSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/install-github-app/index.ts b/_all-in-one-upload/cc-haha/src/commands/install-github-app/index.ts new file mode 100644 index 0000000..9b5b882 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/install-github-app/index.ts @@ -0,0 +1,13 @@ +import type { Command } from '../../commands.js' +import { isEnvTruthy } from '../../utils/envUtils.js' + +const installGitHubApp = { + type: 'local-jsx', + name: 'install-github-app', + description: 'Set up Claude GitHub Actions for a repository', + availability: ['claude-ai', 'console'], + isEnabled: () => !isEnvTruthy(process.env.DISABLE_INSTALL_GITHUB_APP_COMMAND), + load: () => import('./install-github-app.js'), +} satisfies Command + +export default installGitHubApp diff --git a/_all-in-one-upload/cc-haha/src/commands/login/index.ts b/_all-in-one-upload/cc-haha/src/commands/login/index.ts new file mode 100644 index 0000000..f9bc5a2 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/login/index.ts @@ -0,0 +1,14 @@ +import type { Command } from '../../commands.js' +import { hasAnthropicApiKeyAuth } from '../../utils/auth.js' +import { isEnvTruthy } from '../../utils/envUtils.js' + +export default () => + ({ + type: 'local-jsx', + name: 'login', + description: hasAnthropicApiKeyAuth() + ? 'Switch Anthropic accounts' + : 'Sign in with your Anthropic account', + isEnabled: () => !isEnvTruthy(process.env.DISABLE_LOGIN_COMMAND), + load: () => import('./login.js'), + }) satisfies Command diff --git a/_all-in-one-upload/cc-haha/src/commands/mobile/index.ts b/_all-in-one-upload/cc-haha/src/commands/mobile/index.ts new file mode 100644 index 0000000..2657aa8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/mobile/index.ts @@ -0,0 +1,11 @@ +import type { Command } from '../../commands.js' + +const mobile = { + type: 'local-jsx', + name: 'mobile', + aliases: ['ios', 'android'], + description: 'Show QR code to download the Claude mobile app', + load: () => import('./mobile.js'), +} satisfies Command + +export default mobile diff --git a/_all-in-one-upload/cc-haha/src/commands/passes/passes.tsx b/_all-in-one-upload/cc-haha/src/commands/passes/passes.tsx new file mode 100644 index 0000000..c17cb59 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/passes/passes.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { Passes } from '../../components/Passes/Passes.js'; +import { logEvent } from '../../services/analytics/index.js'; +import { getCachedRemainingPasses } from '../../services/api/referral.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; +import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js'; +export async function call(onDone: LocalJSXCommandOnDone): Promise { + // Mark that user has visited /passes so we stop showing the upsell + const config = getGlobalConfig(); + const isFirstVisit = !config.hasVisitedPasses; + if (isFirstVisit) { + const remaining = getCachedRemainingPasses(); + saveGlobalConfig(current => ({ + ...current, + hasVisitedPasses: true, + passesLastSeenRemaining: remaining ?? current.passesLastSeenRemaining + })); + } + logEvent('tengu_guest_passes_visited', { + is_first_visit: isFirstVisit + }); + return ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlBhc3NlcyIsImxvZ0V2ZW50IiwiZ2V0Q2FjaGVkUmVtYWluaW5nUGFzc2VzIiwiTG9jYWxKU1hDb21tYW5kT25Eb25lIiwiZ2V0R2xvYmFsQ29uZmlnIiwic2F2ZUdsb2JhbENvbmZpZyIsImNhbGwiLCJvbkRvbmUiLCJQcm9taXNlIiwiUmVhY3ROb2RlIiwiY29uZmlnIiwiaXNGaXJzdFZpc2l0IiwiaGFzVmlzaXRlZFBhc3NlcyIsInJlbWFpbmluZyIsImN1cnJlbnQiLCJwYXNzZXNMYXN0U2VlblJlbWFpbmluZyIsImlzX2ZpcnN0X3Zpc2l0Il0sInNvdXJjZXMiOlsicGFzc2VzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IFBhc3NlcyB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvUGFzc2VzL1Bhc3Nlcy5qcydcbmltcG9ydCB7IGxvZ0V2ZW50IH0gZnJvbSAnLi4vLi4vc2VydmljZXMvYW5hbHl0aWNzL2luZGV4LmpzJ1xuaW1wb3J0IHsgZ2V0Q2FjaGVkUmVtYWluaW5nUGFzc2VzIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvYXBpL3JlZmVycmFsLmpzJ1xuaW1wb3J0IHR5cGUgeyBMb2NhbEpTWENvbW1hbmRPbkRvbmUgfSBmcm9tICcuLi8uLi90eXBlcy9jb21tYW5kLmpzJ1xuaW1wb3J0IHsgZ2V0R2xvYmFsQ29uZmlnLCBzYXZlR2xvYmFsQ29uZmlnIH0gZnJvbSAnLi4vLi4vdXRpbHMvY29uZmlnLmpzJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2FsbChcbiAgb25Eb25lOiBMb2NhbEpTWENvbW1hbmRPbkRvbmUsXG4pOiBQcm9taXNlPFJlYWN0LlJlYWN0Tm9kZT4ge1xuICAvLyBNYXJrIHRoYXQgdXNlciBoYXMgdmlzaXRlZCAvcGFzc2VzIHNvIHdlIHN0b3Agc2hvd2luZyB0aGUgdXBzZWxsXG4gIGNvbnN0IGNvbmZpZyA9IGdldEdsb2JhbENvbmZpZygpXG4gIGNvbnN0IGlzRmlyc3RWaXNpdCA9ICFjb25maWcuaGFzVmlzaXRlZFBhc3Nlc1xuICBpZiAoaXNGaXJzdFZpc2l0KSB7XG4gICAgY29uc3QgcmVtYWluaW5nID0gZ2V0Q2FjaGVkUmVtYWluaW5nUGFzc2VzKClcbiAgICBzYXZlR2xvYmFsQ29uZmlnKGN1cnJlbnQgPT4gKHtcbiAgICAgIC4uLmN1cnJlbnQsXG4gICAgICBoYXNWaXNpdGVkUGFzc2VzOiB0cnVlLFxuICAgICAgcGFzc2VzTGFzdFNlZW5SZW1haW5pbmc6IHJlbWFpbmluZyA/PyBjdXJyZW50LnBhc3Nlc0xhc3RTZWVuUmVtYWluaW5nLFxuICAgIH0pKVxuICB9XG4gIGxvZ0V2ZW50KCd0ZW5ndV9ndWVzdF9wYXNzZXNfdmlzaXRlZCcsIHsgaXNfZmlyc3RfdmlzaXQ6IGlzRmlyc3RWaXNpdCB9KVxuICByZXR1cm4gPFBhc3NlcyBvbkRvbmU9e29uRG9uZX0gLz5cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLQSxLQUFLLE1BQU0sT0FBTztBQUM5QixTQUFTQyxNQUFNLFFBQVEsbUNBQW1DO0FBQzFELFNBQVNDLFFBQVEsUUFBUSxtQ0FBbUM7QUFDNUQsU0FBU0Msd0JBQXdCLFFBQVEsZ0NBQWdDO0FBQ3pFLGNBQWNDLHFCQUFxQixRQUFRLHdCQUF3QjtBQUNuRSxTQUFTQyxlQUFlLEVBQUVDLGdCQUFnQixRQUFRLHVCQUF1QjtBQUV6RSxPQUFPLGVBQWVDLElBQUlBLENBQ3hCQyxNQUFNLEVBQUVKLHFCQUFxQixDQUM5QixFQUFFSyxPQUFPLENBQUNULEtBQUssQ0FBQ1UsU0FBUyxDQUFDLENBQUM7RUFDMUI7RUFDQSxNQUFNQyxNQUFNLEdBQUdOLGVBQWUsQ0FBQyxDQUFDO0VBQ2hDLE1BQU1PLFlBQVksR0FBRyxDQUFDRCxNQUFNLENBQUNFLGdCQUFnQjtFQUM3QyxJQUFJRCxZQUFZLEVBQUU7SUFDaEIsTUFBTUUsU0FBUyxHQUFHWCx3QkFBd0IsQ0FBQyxDQUFDO0lBQzVDRyxnQkFBZ0IsQ0FBQ1MsT0FBTyxLQUFLO01BQzNCLEdBQUdBLE9BQU87TUFDVkYsZ0JBQWdCLEVBQUUsSUFBSTtNQUN0QkcsdUJBQXVCLEVBQUVGLFNBQVMsSUFBSUMsT0FBTyxDQUFDQztJQUNoRCxDQUFDLENBQUMsQ0FBQztFQUNMO0VBQ0FkLFFBQVEsQ0FBQyw0QkFBNEIsRUFBRTtJQUFFZSxjQUFjLEVBQUVMO0VBQWEsQ0FBQyxDQUFDO0VBQ3hFLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUNKLE1BQU0sQ0FBQyxHQUFHO0FBQ25DIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/plugin/DiscoverPlugins.tsx b/_all-in-one-upload/cc-haha/src/commands/plugin/DiscoverPlugins.tsx new file mode 100644 index 0000000..d62a8db --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/plugin/DiscoverPlugins.tsx @@ -0,0 +1,781 @@ +import { c as _c } from "react/compiler-runtime"; +import figures from 'figures'; +import * as React from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { ConfigurableShortcutHint } from '../../components/ConfigurableShortcutHint.js'; +import { Byline } from '../../components/design-system/Byline.js'; +import { SearchBox } from '../../components/SearchBox.js'; +import { useSearchInput } from '../../hooks/useSearchInput.js'; +import { useTerminalSize } from '../../hooks/useTerminalSize.js'; +// eslint-disable-next-line custom-rules/prefer-use-keybindings -- useInput needed for raw search mode text input +import { Box, Text, useInput, useTerminalFocus } from '../../ink.js'; +import { useKeybinding, useKeybindings } from '../../keybindings/useKeybinding.js'; +import type { LoadedPlugin } from '../../types/plugin.js'; +import { count } from '../../utils/array.js'; +import { openBrowser } from '../../utils/browser.js'; +import { logForDebugging } from '../../utils/debug.js'; +import { errorMessage } from '../../utils/errors.js'; +import { clearAllCaches } from '../../utils/plugins/cacheUtils.js'; +import { formatInstallCount, getInstallCounts } from '../../utils/plugins/installCounts.js'; +import { isPluginGloballyInstalled } from '../../utils/plugins/installedPluginsManager.js'; +import { createPluginId, detectEmptyMarketplaceReason, type EmptyMarketplaceReason, formatFailureDetails, formatMarketplaceLoadingErrors, loadMarketplacesWithGracefulDegradation } from '../../utils/plugins/marketplaceHelpers.js'; +import { loadKnownMarketplacesConfig } from '../../utils/plugins/marketplaceManager.js'; +import { OFFICIAL_MARKETPLACE_NAME } from '../../utils/plugins/officialMarketplace.js'; +import { installPluginFromMarketplace } from '../../utils/plugins/pluginInstallationHelpers.js'; +import { isPluginBlockedByPolicy } from '../../utils/plugins/pluginPolicy.js'; +import { plural } from '../../utils/stringUtils.js'; +import { truncateToWidth } from '../../utils/truncate.js'; +import { findPluginOptionsTarget, PluginOptionsFlow } from './PluginOptionsFlow.js'; +import { PluginTrustWarning } from './PluginTrustWarning.js'; +import { buildPluginDetailsMenuOptions, extractGitHubRepo, type InstallablePlugin } from './pluginDetailsHelpers.js'; +import type { ViewState as ParentViewState } from './types.js'; +import { usePagination } from './usePagination.js'; +type Props = { + error: string | null; + setError: (error: string | null) => void; + result: string | null; + setResult: (result: string | null) => void; + setViewState: (state: ParentViewState) => void; + onInstallComplete?: () => void | Promise; + onSearchModeChange?: (isActive: boolean) => void; + targetPlugin?: string; +}; +type ViewState = 'plugin-list' | 'plugin-details' | { + type: 'plugin-options'; + plugin: LoadedPlugin; + pluginId: string; +}; +export function DiscoverPlugins({ + error, + setError, + result: _result, + setResult, + setViewState: setParentViewState, + onInstallComplete, + onSearchModeChange, + targetPlugin +}: Props): React.ReactNode { + // View state + const [viewState, setViewState] = useState('plugin-list'); + const [selectedPlugin, setSelectedPlugin] = useState(null); + + // Data state + const [availablePlugins, setAvailablePlugins] = useState([]); + const [loading, setLoading] = useState(true); + const [installCounts, setInstallCounts] = useState | null>(null); + + // Search state + const [isSearchMode, setIsSearchModeRaw] = useState(false); + const setIsSearchMode = useCallback((active: boolean) => { + setIsSearchModeRaw(active); + onSearchModeChange?.(active); + }, [onSearchModeChange]); + const { + query: searchQuery, + setQuery: setSearchQuery, + cursorOffset: searchCursorOffset + } = useSearchInput({ + isActive: viewState === 'plugin-list' && isSearchMode && !loading, + onExit: () => { + setIsSearchMode(false); + } + }); + const isTerminalFocused = useTerminalFocus(); + const { + columns: terminalWidth + } = useTerminalSize(); + + // Filter plugins based on search query + const filteredPlugins = useMemo(() => { + if (!searchQuery) return availablePlugins; + const lowerQuery = searchQuery.toLowerCase(); + return availablePlugins.filter(plugin => plugin.entry.name.toLowerCase().includes(lowerQuery) || plugin.entry.description?.toLowerCase().includes(lowerQuery) || plugin.marketplaceName.toLowerCase().includes(lowerQuery)); + }, [availablePlugins, searchQuery]); + + // Selection state + const [selectedIndex, setSelectedIndex] = useState(0); + const [selectedForInstall, setSelectedForInstall] = useState>(new Set()); + const [installingPlugins, setInstallingPlugins] = useState>(new Set()); + + // Pagination for plugin list (continuous scrolling) + const pagination = usePagination({ + totalItems: filteredPlugins.length, + selectedIndex + }); + + // Reset selection when search query changes + useEffect(() => { + setSelectedIndex(0); + }, [searchQuery]); + + // Details view state + const [detailsMenuIndex, setDetailsMenuIndex] = useState(0); + const [isInstalling, setIsInstalling] = useState(false); + const [installError, setInstallError] = useState(null); + + // Warning state for non-critical errors + const [warning, setWarning] = useState(null); + + // Empty state reason + const [emptyReason, setEmptyReason] = useState(null); + + // Load all plugins from all marketplaces + useEffect(() => { + async function loadAllPlugins() { + try { + const config = await loadKnownMarketplacesConfig(); + + // Load marketplaces with graceful degradation + const { + marketplaces, + failures + } = await loadMarketplacesWithGracefulDegradation(config); + + // Collect all plugins from all marketplaces + const allPlugins: InstallablePlugin[] = []; + for (const { + name, + data: marketplace + } of marketplaces) { + if (marketplace) { + for (const entry of marketplace.plugins) { + const pluginId = createPluginId(entry.name, name); + allPlugins.push({ + entry, + marketplaceName: name, + pluginId, + // Only block when globally installed (user/managed scope). + // Project/local-scope installs don't block — user may want to + // promote to user scope so it's available everywhere (gh-29997). + isInstalled: isPluginGloballyInstalled(pluginId) + }); + } + } + } + + // Filter out installed and policy-blocked plugins + const uninstalledPlugins = allPlugins.filter(p => !p.isInstalled && !isPluginBlockedByPolicy(p.pluginId)); + + // Fetch install counts and sort by popularity + try { + const counts = await getInstallCounts(); + setInstallCounts(counts); + if (counts) { + // Sort by install count (descending), then alphabetically + uninstalledPlugins.sort((a_0, b_0) => { + const countA = counts.get(a_0.pluginId) ?? 0; + const countB = counts.get(b_0.pluginId) ?? 0; + if (countA !== countB) return countB - countA; + return a_0.entry.name.localeCompare(b_0.entry.name); + }); + } else { + // No counts available - sort alphabetically + uninstalledPlugins.sort((a_1, b_1) => a_1.entry.name.localeCompare(b_1.entry.name)); + } + } catch (error_0) { + // Log the error, then gracefully degrade to alphabetical sort + logForDebugging(`Failed to fetch install counts: ${errorMessage(error_0)}`); + uninstalledPlugins.sort((a, b) => a.entry.name.localeCompare(b.entry.name)); + } + setAvailablePlugins(uninstalledPlugins); + + // Detect empty reason if no plugins available + const configuredCount = Object.keys(config).length; + if (uninstalledPlugins.length === 0) { + const reason = await detectEmptyMarketplaceReason({ + configuredMarketplaceCount: configuredCount, + failedMarketplaceCount: failures.length + }); + setEmptyReason(reason); + } + + // Handle marketplace loading errors/warnings + const successCount = count(marketplaces, m => m.data !== null); + const errorResult = formatMarketplaceLoadingErrors(failures, successCount); + if (errorResult) { + if (errorResult.type === 'warning') { + setWarning(errorResult.message + '. Showing available plugins.'); + } else { + throw new Error(errorResult.message); + } + } + + // Handle targetPlugin - navigate directly to plugin details + // Search in allPlugins (before filtering) to handle installed plugins gracefully + if (targetPlugin) { + const foundPlugin = allPlugins.find(p_0 => p_0.entry.name === targetPlugin); + if (foundPlugin) { + if (foundPlugin.isInstalled) { + setError(`Plugin '${foundPlugin.pluginId}' is already installed. Use '/plugin' to manage existing plugins.`); + } else { + setSelectedPlugin(foundPlugin); + setViewState('plugin-details'); + } + } else { + setError(`Plugin "${targetPlugin}" not found in any marketplace`); + } + } + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to load plugins'); + } finally { + setLoading(false); + } + } + void loadAllPlugins(); + }, [setError, targetPlugin]); + + // Install selected plugins + const installSelectedPlugins = async () => { + if (selectedForInstall.size === 0) return; + const pluginsToInstall = availablePlugins.filter(p_1 => selectedForInstall.has(p_1.pluginId)); + setInstallingPlugins(new Set(pluginsToInstall.map(p_2 => p_2.pluginId))); + let successCount_0 = 0; + let failureCount = 0; + const newFailedPlugins: Array<{ + name: string; + reason: string; + }> = []; + for (const plugin_0 of pluginsToInstall) { + const result = await installPluginFromMarketplace({ + pluginId: plugin_0.pluginId, + entry: plugin_0.entry, + marketplaceName: plugin_0.marketplaceName, + scope: 'user' + }); + if (result.success) { + successCount_0++; + } else { + failureCount++; + newFailedPlugins.push({ + name: plugin_0.entry.name, + reason: result.error + }); + } + } + setInstallingPlugins(new Set()); + setSelectedForInstall(new Set()); + clearAllCaches(); + + // Handle installation results + if (failureCount === 0) { + const message = `✓ Installed ${successCount_0} ${plural(successCount_0, 'plugin')}. ` + `Run /reload-plugins to activate.`; + setResult(message); + } else if (successCount_0 === 0) { + setError(`Failed to install: ${formatFailureDetails(newFailedPlugins, true)}`); + } else { + const message_0 = `✓ Installed ${successCount_0} of ${successCount_0 + failureCount} plugins. ` + `Failed: ${formatFailureDetails(newFailedPlugins, false)}. ` + `Run /reload-plugins to activate successfully installed plugins.`; + setResult(message_0); + } + if (successCount_0 > 0) { + if (onInstallComplete) { + await onInstallComplete(); + } + } + setParentViewState({ + type: 'menu' + }); + }; + + // Install single plugin from details view + const handleSinglePluginInstall = async (plugin_1: InstallablePlugin, scope: 'user' | 'project' | 'local' = 'user') => { + setIsInstalling(true); + setInstallError(null); + const result_0 = await installPluginFromMarketplace({ + pluginId: plugin_1.pluginId, + entry: plugin_1.entry, + marketplaceName: plugin_1.marketplaceName, + scope + }); + if (result_0.success) { + const loaded = await findPluginOptionsTarget(plugin_1.pluginId); + if (loaded) { + setIsInstalling(false); + setViewState({ + type: 'plugin-options', + plugin: loaded, + pluginId: plugin_1.pluginId + }); + return; + } + setResult(result_0.message); + if (onInstallComplete) { + await onInstallComplete(); + } + setParentViewState({ + type: 'menu' + }); + } else { + setIsInstalling(false); + setInstallError(result_0.error); + } + }; + + // Handle error state + useEffect(() => { + if (error) { + setResult(error); + } + }, [error, setResult]); + + // Escape in plugin-details view - go back to plugin-list + useKeybinding('confirm:no', () => { + setViewState('plugin-list'); + setSelectedPlugin(null); + }, { + context: 'Confirmation', + isActive: viewState === 'plugin-details' + }); + + // Escape in plugin-list view (not search mode) - exit to parent menu + useKeybinding('confirm:no', () => { + setParentViewState({ + type: 'menu' + }); + }, { + context: 'Confirmation', + isActive: viewState === 'plugin-list' && !isSearchMode + }); + + // Handle entering search mode (non-escape keys) + useInput((input, _key) => { + const keyIsNotCtrlOrMeta = !_key.ctrl && !_key.meta; + if (!isSearchMode) { + // Enter search mode with '/' or any printable character + if (input === '/' && keyIsNotCtrlOrMeta) { + setIsSearchMode(true); + setSearchQuery(''); + } else if (keyIsNotCtrlOrMeta && input.length > 0 && !/^\s+$/.test(input) && + // Don't enter search mode for navigation keys + input !== 'j' && input !== 'k' && input !== 'i') { + setIsSearchMode(true); + setSearchQuery(input); + } + } + }, { + isActive: viewState === 'plugin-list' && !loading + }); + + // Plugin-list navigation (non-search mode) + useKeybindings({ + 'select:previous': () => { + if (selectedIndex === 0) { + setIsSearchMode(true); + } else { + pagination.handleSelectionChange(selectedIndex - 1, setSelectedIndex); + } + }, + 'select:next': () => { + if (selectedIndex < filteredPlugins.length - 1) { + pagination.handleSelectionChange(selectedIndex + 1, setSelectedIndex); + } + }, + 'select:accept': () => { + if (selectedIndex === filteredPlugins.length && selectedForInstall.size > 0) { + void installSelectedPlugins(); + } else if (selectedIndex < filteredPlugins.length) { + const plugin_2 = filteredPlugins[selectedIndex]; + if (plugin_2) { + if (plugin_2.isInstalled) { + setParentViewState({ + type: 'manage-plugins', + targetPlugin: plugin_2.entry.name, + targetMarketplace: plugin_2.marketplaceName + }); + } else { + setSelectedPlugin(plugin_2); + setViewState('plugin-details'); + setDetailsMenuIndex(0); + setInstallError(null); + } + } + } + } + }, { + context: 'Select', + isActive: viewState === 'plugin-list' && !isSearchMode + }); + useKeybindings({ + 'plugin:toggle': () => { + if (selectedIndex < filteredPlugins.length) { + const plugin_3 = filteredPlugins[selectedIndex]; + if (plugin_3 && !plugin_3.isInstalled) { + const newSelection = new Set(selectedForInstall); + if (newSelection.has(plugin_3.pluginId)) { + newSelection.delete(plugin_3.pluginId); + } else { + newSelection.add(plugin_3.pluginId); + } + setSelectedForInstall(newSelection); + } + } + }, + 'plugin:install': () => { + if (selectedForInstall.size > 0) { + void installSelectedPlugins(); + } + } + }, { + context: 'Plugin', + isActive: viewState === 'plugin-list' && !isSearchMode + }); + + // Plugin-details navigation + const detailsMenuOptions = React.useMemo(() => { + if (!selectedPlugin) return []; + const hasHomepage = selectedPlugin.entry.homepage; + const githubRepo = extractGitHubRepo(selectedPlugin); + return buildPluginDetailsMenuOptions(hasHomepage, githubRepo); + }, [selectedPlugin]); + useKeybindings({ + 'select:previous': () => { + if (detailsMenuIndex > 0) { + setDetailsMenuIndex(detailsMenuIndex - 1); + } + }, + 'select:next': () => { + if (detailsMenuIndex < detailsMenuOptions.length - 1) { + setDetailsMenuIndex(detailsMenuIndex + 1); + } + }, + 'select:accept': () => { + if (!selectedPlugin) return; + const action = detailsMenuOptions[detailsMenuIndex]?.action; + const hasHomepage_0 = selectedPlugin.entry.homepage; + const githubRepo_0 = extractGitHubRepo(selectedPlugin); + if (action === 'install-user') { + void handleSinglePluginInstall(selectedPlugin, 'user'); + } else if (action === 'install-project') { + void handleSinglePluginInstall(selectedPlugin, 'project'); + } else if (action === 'install-local') { + void handleSinglePluginInstall(selectedPlugin, 'local'); + } else if (action === 'homepage' && hasHomepage_0) { + void openBrowser(hasHomepage_0); + } else if (action === 'github' && githubRepo_0) { + void openBrowser(`https://github.com/${githubRepo_0}`); + } else if (action === 'back') { + setViewState('plugin-list'); + setSelectedPlugin(null); + } + } + }, { + context: 'Select', + isActive: viewState === 'plugin-details' && !!selectedPlugin + }); + if (typeof viewState === 'object' && viewState.type === 'plugin-options') { + const { + plugin: plugin_4, + pluginId: pluginId_0 + } = viewState; + function finish(msg: string): void { + setResult(msg); + if (onInstallComplete) { + void onInstallComplete(); + } + setParentViewState({ + type: 'menu' + }); + } + return { + switch (outcome) { + case 'configured': + finish(`✓ Installed and configured ${plugin_4.name}. Run /reload-plugins to apply.`); + break; + case 'skipped': + finish(`✓ Installed ${plugin_4.name}. Run /reload-plugins to apply.`); + break; + case 'error': + finish(`Installed but failed to save config: ${detail}`); + break; + } + }} />; + } + + // Loading state + if (loading) { + return Loading…; + } + + // Error state + if (error) { + return {error}; + } + + // Plugin details view + if (viewState === 'plugin-details' && selectedPlugin) { + const hasHomepage_1 = selectedPlugin.entry.homepage; + const githubRepo_1 = extractGitHubRepo(selectedPlugin); + const menuOptions = buildPluginDetailsMenuOptions(hasHomepage_1, githubRepo_1); + return + + Plugin details + + + + {selectedPlugin.entry.name} + from {selectedPlugin.marketplaceName} + {selectedPlugin.entry.version && Version: {selectedPlugin.entry.version}} + {selectedPlugin.entry.description && + {selectedPlugin.entry.description} + } + {selectedPlugin.entry.author && + + By:{' '} + {typeof selectedPlugin.entry.author === 'string' ? selectedPlugin.entry.author : selectedPlugin.entry.author.name} + + } + + + + + {installError && + Error: {installError} + } + + + {menuOptions.map((option, index) => + {detailsMenuIndex === index && {'> '}} + {detailsMenuIndex !== index && {' '}} + + {isInstalling && option.action.startsWith('install-') ? 'Installing…' : option.label} + + )} + + + + + + + + + + + ; + } + + // Empty state + if (availablePlugins.length === 0) { + return + + Discover plugins + + + + + Esc to go back + + + ; + } + + // Get visible plugins from pagination + const visiblePlugins = pagination.getVisibleItems(filteredPlugins); + return + + Discover plugins + {pagination.needsPagination && + {' '} + ({pagination.scrollPosition.current}/ + {pagination.scrollPosition.total}) + } + + + {/* Search box */} + + + + + {/* Warning banner */} + {warning && + + {figures.warning} {warning} + + } + + {/* No search results */} + {filteredPlugins.length === 0 && searchQuery && + No plugins match "{searchQuery}" + } + + {/* Scroll up indicator */} + {pagination.scrollPosition.canScrollUp && + {figures.arrowUp} more above + } + + {/* Plugin list - use startIndex in key to force re-render on scroll */} + {visiblePlugins.map((plugin_5, visibleIndex) => { + const actualIndex = pagination.toActualIndex(visibleIndex); + const isSelected = selectedIndex === actualIndex; + const isSelectedForInstall = selectedForInstall.has(plugin_5.pluginId); + const isInstallingThis = installingPlugins.has(plugin_5.pluginId); + const isLast = visibleIndex === visiblePlugins.length - 1; + return + + + {isSelected && !isSearchMode ? figures.pointer : ' '}{' '} + + + {isInstallingThis ? figures.ellipsis : isSelectedForInstall ? figures.radioOn : figures.radioOff}{' '} + {plugin_5.entry.name} + · {plugin_5.marketplaceName} + {plugin_5.entry.tags?.includes('community-managed') && [Community Managed]} + {installCounts && plugin_5.marketplaceName === OFFICIAL_MARKETPLACE_NAME && + {' · '} + {formatInstallCount(installCounts.get(plugin_5.pluginId) ?? 0)}{' '} + installs + } + + + {plugin_5.entry.description && + + {truncateToWidth(plugin_5.entry.description, 60)} + + } + ; + })} + + {/* Scroll down indicator */} + {pagination.scrollPosition.canScrollDown && + {figures.arrowDown} more below + } + + {/* Error messages */} + {error && + + {figures.cross} {error} + + } + + 0} canToggle={selectedIndex < filteredPlugins.length && !filteredPlugins[selectedIndex]?.isInstalled} /> + ; +} +function DiscoverPluginsKeyHint(t0) { + const $ = _c(10); + const { + hasSelection, + canToggle + } = t0; + let t1; + if ($[0] !== hasSelection) { + t1 = hasSelection && ; + $[0] = hasSelection; + $[1] = t1; + } else { + t1 = $[1]; + } + let t2; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t2 = type to search; + $[2] = t2; + } else { + t2 = $[2]; + } + let t3; + if ($[3] !== canToggle) { + t3 = canToggle && ; + $[3] = canToggle; + $[4] = t3; + } else { + t3 = $[4]; + } + let t4; + let t5; + if ($[5] === Symbol.for("react.memo_cache_sentinel")) { + t4 = ; + t5 = ; + $[5] = t4; + $[6] = t5; + } else { + t4 = $[5]; + t5 = $[6]; + } + let t6; + if ($[7] !== t1 || $[8] !== t3) { + t6 = {t1}{t2}{t3}{t4}{t5}; + $[7] = t1; + $[8] = t3; + $[9] = t6; + } else { + t6 = $[9]; + } + return t6; +} + +/** + * Context-aware empty state message for the Discover screen + */ +function EmptyStateMessage(t0) { + const $ = _c(6); + const { + reason + } = t0; + switch (reason) { + case "git-not-installed": + { + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>Git is required to install marketplaces.Please install git and restart Claude Code.; + $[0] = t1; + } else { + t1 = $[0]; + } + return t1; + } + case "all-blocked-by-policy": + { + let t1; + if ($[1] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>Your organization policy does not allow any external marketplaces.Contact your administrator.; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; + } + case "policy-restricts-sources": + { + let t1; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>Your organization restricts which marketplaces can be added.Switch to the Marketplaces tab to view allowed sources.; + $[2] = t1; + } else { + t1 = $[2]; + } + return t1; + } + case "all-marketplaces-failed": + { + let t1; + if ($[3] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>Failed to load marketplace data.Check your network connection.; + $[3] = t1; + } else { + t1 = $[3]; + } + return t1; + } + case "all-plugins-installed": + { + let t1; + if ($[4] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>All available plugins are already installed.Check for new plugins later or add more marketplaces.; + $[4] = t1; + } else { + t1 = $[4]; + } + return t1; + } + case "no-marketplaces-configured": + default: + { + let t1; + if ($[5] === Symbol.for("react.memo_cache_sentinel")) { + t1 = <>No plugins available.Add a marketplace first using the Marketplaces tab.; + $[5] = t1; + } else { + t1 = $[5]; + } + return t1; + } + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmaWd1cmVzIiwiUmVhY3QiLCJ1c2VDYWxsYmFjayIsInVzZUVmZmVjdCIsInVzZU1lbW8iLCJ1c2VTdGF0ZSIsIkNvbmZpZ3VyYWJsZVNob3J0Y3V0SGludCIsIkJ5bGluZSIsIlNlYXJjaEJveCIsInVzZVNlYXJjaElucHV0IiwidXNlVGVybWluYWxTaXplIiwiQm94IiwiVGV4dCIsInVzZUlucHV0IiwidXNlVGVybWluYWxGb2N1cyIsInVzZUtleWJpbmRpbmciLCJ1c2VLZXliaW5kaW5ncyIsIkxvYWRlZFBsdWdpbiIsImNvdW50Iiwib3BlbkJyb3dzZXIiLCJsb2dGb3JEZWJ1Z2dpbmciLCJlcnJvck1lc3NhZ2UiLCJjbGVhckFsbENhY2hlcyIsImZvcm1hdEluc3RhbGxDb3VudCIsImdldEluc3RhbGxDb3VudHMiLCJpc1BsdWdpbkdsb2JhbGx5SW5zdGFsbGVkIiwiY3JlYXRlUGx1Z2luSWQiLCJkZXRlY3RFbXB0eU1hcmtldHBsYWNlUmVhc29uIiwiRW1wdHlNYXJrZXRwbGFjZVJlYXNvbiIsImZvcm1hdEZhaWx1cmVEZXRhaWxzIiwiZm9ybWF0TWFya2V0cGxhY2VMb2FkaW5nRXJyb3JzIiwibG9hZE1hcmtldHBsYWNlc1dpdGhHcmFjZWZ1bERlZ3JhZGF0aW9uIiwibG9hZEtub3duTWFya2V0cGxhY2VzQ29uZmlnIiwiT0ZGSUNJQUxfTUFSS0VUUExBQ0VfTkFNRSIsImluc3RhbGxQbHVnaW5Gcm9tTWFya2V0cGxhY2UiLCJpc1BsdWdpbkJsb2NrZWRCeVBvbGljeSIsInBsdXJhbCIsInRydW5jYXRlVG9XaWR0aCIsImZpbmRQbHVnaW5PcHRpb25zVGFyZ2V0IiwiUGx1Z2luT3B0aW9uc0Zsb3ciLCJQbHVnaW5UcnVzdFdhcm5pbmciLCJidWlsZFBsdWdpbkRldGFpbHNNZW51T3B0aW9ucyIsImV4dHJhY3RHaXRIdWJSZXBvIiwiSW5zdGFsbGFibGVQbHVnaW4iLCJWaWV3U3RhdGUiLCJQYXJlbnRWaWV3U3RhdGUiLCJ1c2VQYWdpbmF0aW9uIiwiUHJvcHMiLCJlcnJvciIsInNldEVycm9yIiwicmVzdWx0Iiwic2V0UmVzdWx0Iiwic2V0Vmlld1N0YXRlIiwic3RhdGUiLCJvbkluc3RhbGxDb21wbGV0ZSIsIlByb21pc2UiLCJvblNlYXJjaE1vZGVDaGFuZ2UiLCJpc0FjdGl2ZSIsInRhcmdldFBsdWdpbiIsInR5cGUiLCJwbHVnaW4iLCJwbHVnaW5JZCIsIkRpc2NvdmVyUGx1Z2lucyIsIl9yZXN1bHQiLCJzZXRQYXJlbnRWaWV3U3RhdGUiLCJSZWFjdE5vZGUiLCJ2aWV3U3RhdGUiLCJzZWxlY3RlZFBsdWdpbiIsInNldFNlbGVjdGVkUGx1Z2luIiwiYXZhaWxhYmxlUGx1Z2lucyIsInNldEF2YWlsYWJsZVBsdWdpbnMiLCJsb2FkaW5nIiwic2V0TG9hZGluZyIsImluc3RhbGxDb3VudHMiLCJzZXRJbnN0YWxsQ291bnRzIiwiTWFwIiwiaXNTZWFyY2hNb2RlIiwic2V0SXNTZWFyY2hNb2RlUmF3Iiwic2V0SXNTZWFyY2hNb2RlIiwiYWN0aXZlIiwicXVlcnkiLCJzZWFyY2hRdWVyeSIsInNldFF1ZXJ5Iiwic2V0U2VhcmNoUXVlcnkiLCJjdXJzb3JPZmZzZXQiLCJzZWFyY2hDdXJzb3JPZmZzZXQiLCJvbkV4aXQiLCJpc1Rlcm1pbmFsRm9jdXNlZCIsImNvbHVtbnMiLCJ0ZXJtaW5hbFdpZHRoIiwiZmlsdGVyZWRQbHVnaW5zIiwibG93ZXJRdWVyeSIsInRvTG93ZXJDYXNlIiwiZmlsdGVyIiwiZW50cnkiLCJuYW1lIiwiaW5jbHVkZXMiLCJkZXNjcmlwdGlvbiIsIm1hcmtldHBsYWNlTmFtZSIsInNlbGVjdGVkSW5kZXgiLCJzZXRTZWxlY3RlZEluZGV4Iiwic2VsZWN0ZWRGb3JJbnN0YWxsIiwic2V0U2VsZWN0ZWRGb3JJbnN0YWxsIiwiU2V0IiwiaW5zdGFsbGluZ1BsdWdpbnMiLCJzZXRJbnN0YWxsaW5nUGx1Z2lucyIsInBhZ2luYXRpb24iLCJ0b3RhbEl0ZW1zIiwibGVuZ3RoIiwiZGV0YWlsc01lbnVJbmRleCIsInNldERldGFpbHNNZW51SW5kZXgiLCJpc0luc3RhbGxpbmciLCJzZXRJc0luc3RhbGxpbmciLCJpbnN0YWxsRXJyb3IiLCJzZXRJbnN0YWxsRXJyb3IiLCJ3YXJuaW5nIiwic2V0V2FybmluZyIsImVtcHR5UmVhc29uIiwic2V0RW1wdHlSZWFzb24iLCJsb2FkQWxsUGx1Z2lucyIsImNvbmZpZyIsIm1hcmtldHBsYWNlcyIsImZhaWx1cmVzIiwiYWxsUGx1Z2lucyIsImRhdGEiLCJtYXJrZXRwbGFjZSIsInBsdWdpbnMiLCJwdXNoIiwiaXNJbnN0YWxsZWQiLCJ1bmluc3RhbGxlZFBsdWdpbnMiLCJwIiwiY291bnRzIiwic29ydCIsImEiLCJiIiwiY291bnRBIiwiZ2V0IiwiY291bnRCIiwibG9jYWxlQ29tcGFyZSIsImNvbmZpZ3VyZWRDb3VudCIsIk9iamVjdCIsImtleXMiLCJyZWFzb24iLCJjb25maWd1cmVkTWFya2V0cGxhY2VDb3VudCIsImZhaWxlZE1hcmtldHBsYWNlQ291bnQiLCJzdWNjZXNzQ291bnQiLCJtIiwiZXJyb3JSZXN1bHQiLCJtZXNzYWdlIiwiRXJyb3IiLCJmb3VuZFBsdWdpbiIsImZpbmQiLCJlcnIiLCJpbnN0YWxsU2VsZWN0ZWRQbHVnaW5zIiwic2l6ZSIsInBsdWdpbnNUb0luc3RhbGwiLCJoYXMiLCJtYXAiLCJmYWlsdXJlQ291bnQiLCJuZXdGYWlsZWRQbHVnaW5zIiwiQXJyYXkiLCJzY29wZSIsInN1Y2Nlc3MiLCJoYW5kbGVTaW5nbGVQbHVnaW5JbnN0YWxsIiwibG9hZGVkIiwiY29udGV4dCIsImlucHV0IiwiX2tleSIsImtleUlzTm90Q3RybE9yTWV0YSIsImN0cmwiLCJtZXRhIiwidGVzdCIsInNlbGVjdDpwcmV2aW91cyIsImhhbmRsZVNlbGVjdGlvbkNoYW5nZSIsInNlbGVjdDpuZXh0Iiwic2VsZWN0OmFjY2VwdCIsInRhcmdldE1hcmtldHBsYWNlIiwicGx1Z2luOnRvZ2dsZSIsIm5ld1NlbGVjdGlvbiIsImRlbGV0ZSIsImFkZCIsInBsdWdpbjppbnN0YWxsIiwiZGV0YWlsc01lbnVPcHRpb25zIiwiaGFzSG9tZXBhZ2UiLCJob21lcGFnZSIsImdpdGh1YlJlcG8iLCJhY3Rpb24iLCJmaW5pc2giLCJtc2ciLCJvdXRjb21lIiwiZGV0YWlsIiwibWVudU9wdGlvbnMiLCJ2ZXJzaW9uIiwiYXV0aG9yIiwib3B0aW9uIiwiaW5kZXgiLCJzdGFydHNXaXRoIiwibGFiZWwiLCJ2aXNpYmxlUGx1Z2lucyIsImdldFZpc2libGVJdGVtcyIsIm5lZWRzUGFnaW5hdGlvbiIsInNjcm9sbFBvc2l0aW9uIiwiY3VycmVudCIsInRvdGFsIiwiY2FuU2Nyb2xsVXAiLCJhcnJvd1VwIiwidmlzaWJsZUluZGV4IiwiYWN0dWFsSW5kZXgiLCJ0b0FjdHVhbEluZGV4IiwiaXNTZWxlY3RlZCIsImlzU2VsZWN0ZWRGb3JJbnN0YWxsIiwiaXNJbnN0YWxsaW5nVGhpcyIsImlzTGFzdCIsInN0YXJ0SW5kZXgiLCJ1bmRlZmluZWQiLCJwb2ludGVyIiwiZWxsaXBzaXMiLCJyYWRpb09uIiwicmFkaW9PZmYiLCJ0YWdzIiwiY2FuU2Nyb2xsRG93biIsImFycm93RG93biIsImNyb3NzIiwiRGlzY292ZXJQbHVnaW5zS2V5SGludCIsInQwIiwiJCIsIl9jIiwiaGFzU2VsZWN0aW9uIiwiY2FuVG9nZ2xlIiwidDEiLCJ0MiIsIlN5bWJvbCIsImZvciIsInQzIiwidDQiLCJ0NSIsInQ2IiwiRW1wdHlTdGF0ZU1lc3NhZ2UiXSwic291cmNlcyI6WyJEaXNjb3ZlclBsdWdpbnMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmaWd1cmVzIGZyb20gJ2ZpZ3VyZXMnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZU1lbW8sIHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBDb25maWd1cmFibGVTaG9ydGN1dEhpbnQgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL0NvbmZpZ3VyYWJsZVNob3J0Y3V0SGludC5qcydcbmltcG9ydCB7IEJ5bGluZSB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvZGVzaWduLXN5c3RlbS9CeWxpbmUuanMnXG5pbXBvcnQgeyBTZWFyY2hCb3ggfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL1NlYXJjaEJveC5qcydcbmltcG9ydCB7IHVzZVNlYXJjaElucHV0IH0gZnJvbSAnLi4vLi4vaG9va3MvdXNlU2VhcmNoSW5wdXQuanMnXG5pbXBvcnQgeyB1c2VUZXJtaW5hbFNpemUgfSBmcm9tICcuLi8uLi9ob29rcy91c2VUZXJtaW5hbFNpemUuanMnXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY3VzdG9tLXJ1bGVzL3ByZWZlci11c2Uta2V5YmluZGluZ3MgLS0gdXNlSW5wdXQgbmVlZGVkIGZvciByYXcgc2VhcmNoIG1vZGUgdGV4dCBpbnB1dFxuaW1wb3J0IHsgQm94LCBUZXh0LCB1c2VJbnB1dCwgdXNlVGVybWluYWxGb2N1cyB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB7XG4gIHVzZUtleWJpbmRpbmcsXG4gIHVzZUtleWJpbmRpbmdzLFxufSBmcm9tICcuLi8uLi9rZXliaW5kaW5ncy91c2VLZXliaW5kaW5nLmpzJ1xuaW1wb3J0IHR5cGUgeyBMb2FkZWRQbHVnaW4gfSBmcm9tICcuLi8uLi90eXBlcy9wbHVnaW4uanMnXG5pbXBvcnQgeyBjb3VudCB9IGZyb20gJy4uLy4uL3V0aWxzL2FycmF5LmpzJ1xuaW1wb3J0IHsgb3BlbkJyb3dzZXIgfSBmcm9tICcuLi8uLi91dGlscy9icm93c2VyLmpzJ1xuaW1wb3J0IHsgbG9nRm9yRGVidWdnaW5nIH0gZnJvbSAnLi4vLi4vdXRpbHMvZGVidWcuanMnXG5pbXBvcnQgeyBlcnJvck1lc3NhZ2UgfSBmcm9tICcuLi8uLi91dGlscy9lcnJvcnMuanMnXG5pbXBvcnQgeyBjbGVhckFsbENhY2hlcyB9IGZyb20gJy4uLy4uL3V0aWxzL3BsdWdpbnMvY2FjaGVVdGlscy5qcydcbmltcG9ydCB7XG4gIGZvcm1hdEluc3RhbGxDb3VudCxcbiAgZ2V0SW5zdGFsbENvdW50cyxcbn0gZnJvbSAnLi4vLi4vdXRpbHMvcGx1Z2lucy9pbnN0YWxsQ291bnRzLmpzJ1xuaW1wb3J0IHsgaXNQbHVnaW5HbG9iYWxseUluc3RhbGxlZCB9IGZyb20gJy4uLy4uL3V0aWxzL3BsdWdpbnMvaW5zdGFsbGVkUGx1Z2luc01hbmFnZXIuanMnXG5pbXBvcnQge1xuICBjcmVhdGVQbHVnaW5JZCxcbiAgZGV0ZWN0RW1wdHlNYXJrZXRwbGFjZVJlYXNvbixcbiAgdHlwZSBFbXB0eU1hcmtldHBsYWNlUmVhc29uLFxuICBmb3JtYXRGYWlsdXJlRGV0YWlscyxcbiAgZm9ybWF0TWFya2V0cGxhY2VMb2FkaW5nRXJyb3JzLFxuICBsb2FkTWFya2V0cGxhY2VzV2l0aEdyYWNlZnVsRGVncmFkYXRpb24sXG59IGZyb20gJy4uLy4uL3V0aWxzL3BsdWdpbnMvbWFya2V0cGxhY2VIZWxwZXJzLmpzJ1xuaW1wb3J0IHsgbG9hZEtub3duTWFya2V0cGxhY2VzQ29uZmlnIH0gZnJvbSAnLi4vLi4vdXRpbHMvcGx1Z2lucy9tYXJrZXRwbGFjZU1hbmFnZXIuanMnXG5pbXBvcnQgeyBPRkZJQ0lBTF9NQVJLRVRQTEFDRV9OQU1FIH0gZnJvbSAnLi4vLi4vdXRpbHMvcGx1Z2lucy9vZmZpY2lhbE1hcmtldHBsYWNlLmpzJ1xuaW1wb3J0IHsgaW5zdGFsbFBsdWdpbkZyb21NYXJrZXRwbGFjZSB9IGZyb20gJy4uLy4uL3V0aWxzL3BsdWdpbnMvcGx1Z2luSW5zdGFsbGF0aW9uSGVscGVycy5qcydcbmltcG9ydCB7IGlzUGx1Z2luQmxvY2tlZEJ5UG9saWN5IH0gZnJvbSAnLi4vLi4vdXRpbHMvcGx1Z2lucy9wbHVnaW5Qb2xpY3kuanMnXG5pbXBvcnQgeyBwbHVyYWwgfSBmcm9tICcuLi8uLi91dGlscy9zdHJpbmdVdGlscy5qcydcbmltcG9ydCB7IHRydW5jYXRlVG9XaWR0aCB9IGZyb20gJy4uLy4uL3V0aWxzL3RydW5jYXRlLmpzJ1xuaW1wb3J0IHtcbiAgZmluZFBsdWdpbk9wdGlvbnNUYXJnZXQsXG4gIFBsdWdpbk9wdGlvbnNGbG93LFxufSBmcm9tICcuL1BsdWdpbk9wdGlvbnNGbG93LmpzJ1xuaW1wb3J0IHsgUGx1Z2luVHJ1c3RXYXJuaW5nIH0gZnJvbSAnLi9QbHVnaW5UcnVzdFdhcm5pbmcuanMnXG5pbXBvcnQge1xuICBidWlsZFBsdWdpbkRldGFpbHNNZW51T3B0aW9ucyxcbiAgZXh0cmFjdEdpdEh1YlJlcG8sXG4gIHR5cGUgSW5zdGFsbGFibGVQbHVnaW4sXG59IGZyb20gJy4vcGx1Z2luRGV0YWlsc0hlbHBlcnMuanMnXG5pbXBvcnQgdHlwZSB7IFZpZXdTdGF0ZSBhcyBQYXJlbnRWaWV3U3RhdGUgfSBmcm9tICcuL3R5cGVzLmpzJ1xuaW1wb3J0IHsgdXNlUGFnaW5hdGlvbiB9IGZyb20gJy4vdXNlUGFnaW5hdGlvbi5qcydcblxudHlwZSBQcm9wcyA9IHtcbiAgZXJyb3I6IHN0cmluZyB8IG51bGxcbiAgc2V0RXJyb3I6IChlcnJvcjogc3RyaW5nIHwgbnVsbCkgPT4gdm9pZFxuICByZXN1bHQ6IHN0cmluZyB8IG51bGxcbiAgc2V0UmVzdWx0OiAocmVzdWx0OiBzdHJpbmcgfCBudWxsKSA9PiB2b2lkXG4gIHNldFZpZXdTdGF0ZTogKHN0YXRlOiBQYXJlbnRWaWV3U3RhdGUpID0+IHZvaWRcbiAgb25JbnN0YWxsQ29tcGxldGU/OiAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICBvblNlYXJjaE1vZGVDaGFuZ2U/OiAoaXNBY3RpdmU6IGJvb2xlYW4pID0+IHZvaWRcbiAgdGFyZ2V0UGx1Z2luPzogc3RyaW5nXG59XG5cbnR5cGUgVmlld1N0YXRlID1cbiAgfCAncGx1Z2luLWxpc3QnXG4gIHwgJ3BsdWdpbi1kZXRhaWxzJ1xuICB8IHsgdHlwZTogJ3BsdWdpbi1vcHRpb25zJzsgcGx1Z2luOiBMb2FkZWRQbHVnaW47IHBsdWdpbklkOiBzdHJpbmcgfVxuXG5leHBvcnQgZnVuY3Rpb24gRGlzY292ZXJQbHVnaW5zKHtcbiAgZXJyb3IsXG4gIHNldEVycm9yLFxuICByZXN1bHQ6IF9yZXN1bHQsXG4gIHNldFJlc3VsdCxcbiAgc2V0Vmlld1N0YXRlOiBzZXRQYXJlbnRWaWV3U3RhdGUsXG4gIG9uSW5zdGFsbENvbXBsZXRlLFxuICBvblNlYXJjaE1vZGVDaGFuZ2UsXG4gIHRhcmdldFBsdWdpbixcbn06IFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgLy8gVmlldyBzdGF0ZVxuICBjb25zdCBbdmlld1N0YXRlLCBzZXRWaWV3U3RhdGVdID0gdXNlU3RhdGU8Vmlld1N0YXRlPigncGx1Z2luLWxpc3QnKVxuICBjb25zdCBbc2VsZWN0ZWRQbHVnaW4sIHNldFNlbGVjdGVkUGx1Z2luXSA9XG4gICAgdXNlU3RhdGU8SW5zdGFsbGFibGVQbHVnaW4gfCBudWxsPihudWxsKVxuXG4gIC8vIERhdGEgc3RhdGVcbiAgY29uc3QgW2F2YWlsYWJsZVBsdWdpbnMsIHNldEF2YWlsYWJsZVBsdWdpbnNdID0gdXNlU3RhdGU8SW5zdGFsbGFibGVQbHVnaW5bXT4oXG4gICAgW10sXG4gIClcbiAgY29uc3QgW2xvYWRpbmcsIHNldExvYWRpbmddID0gdXNlU3RhdGUodHJ1ZSlcbiAgY29uc3QgW2luc3RhbGxDb3VudHMsIHNldEluc3RhbGxDb3VudHNdID0gdXNlU3RhdGU8TWFwPFxuICAgIHN0cmluZyxcbiAgICBudW1iZXJcbiAgPiB8IG51bGw+KG51bGwpXG5cbiAgLy8gU2VhcmNoIHN0YXRlXG4gIGNvbnN0IFtpc1NlYXJjaE1vZGUsIHNldElzU2VhcmNoTW9kZVJhd10gPSB1c2VTdGF0ZShmYWxzZSlcbiAgY29uc3Qgc2V0SXNTZWFyY2hNb2RlID0gdXNlQ2FsbGJhY2soXG4gICAgKGFjdGl2ZTogYm9vbGVhbikgPT4ge1xuICAgICAgc2V0SXNTZWFyY2hNb2RlUmF3KGFjdGl2ZSlcbiAgICAgIG9uU2VhcmNoTW9kZUNoYW5nZT8uKGFjdGl2ZSlcbiAgICB9LFxuICAgIFtvblNlYXJjaE1vZGVDaGFuZ2VdLFxuICApXG4gIGNvbnN0IHtcbiAgICBxdWVyeTogc2VhcmNoUXVlcnksXG4gICAgc2V0UXVlcnk6IHNldFNlYXJjaFF1ZXJ5LFxuICAgIGN1cnNvck9mZnNldDogc2VhcmNoQ3Vyc29yT2Zmc2V0LFxuICB9ID0gdXNlU2VhcmNoSW5wdXQoe1xuICAgIGlzQWN0aXZlOiB2aWV3U3RhdGUgPT09ICdwbHVnaW4tbGlzdCcgJiYgaXNTZWFyY2hNb2RlICYmICFsb2FkaW5nLFxuICAgIG9uRXhpdDogKCkgPT4ge1xuICAgICAgc2V0SXNTZWFyY2hNb2RlKGZhbHNlKVxuICAgIH0sXG4gIH0pXG4gIGNvbnN0IGlzVGVybWluYWxGb2N1c2VkID0gdXNlVGVybWluYWxGb2N1cygpXG4gIGNvbnN0IHsgY29sdW1uczogdGVybWluYWxXaWR0aCB9ID0gdXNlVGVybWluYWxTaXplKClcblxuICAvLyBGaWx0ZXIgcGx1Z2lucyBiYXNlZCBvbiBzZWFyY2ggcXVlcnlcbiAgY29uc3QgZmlsdGVyZWRQbHVnaW5zID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFzZWFyY2hRdWVyeSkgcmV0dXJuIGF2YWlsYWJsZVBsdWdpbnNcbiAgICBjb25zdCBsb3dlclF1ZXJ5ID0gc2VhcmNoUXVlcnkudG9Mb3dlckNhc2UoKVxuICAgIHJldHVybiBhdmFpbGFibGVQbHVnaW5zLmZpbHRlcihcbiAgICAgIHBsdWdpbiA9PlxuICAgICAgICBwbHVnaW4uZW50cnkubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKGxvd2VyUXVlcnkpIHx8XG4gICAgICAgIHBsdWdpbi5lbnRyeS5kZXNjcmlwdGlvbj8udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhsb3dlclF1ZXJ5KSB8fFxuICAgICAgICBwbHVnaW4ubWFya2V0cGxhY2VOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMobG93ZXJRdWVyeSksXG4gICAgKVxuICB9LCBbYXZhaWxhYmxlUGx1Z2lucywgc2VhcmNoUXVlcnldKVxuXG4gIC8vIFNlbGVjdGlvbiBzdGF0ZVxuICBjb25zdCBbc2VsZWN0ZWRJbmRleCwgc2V0U2VsZWN0ZWRJbmRleF0gPSB1c2VTdGF0ZSgwKVxuICBjb25zdCBbc2VsZWN0ZWRGb3JJbnN0YWxsLCBzZXRTZWxlY3RlZEZvckluc3RhbGxdID0gdXNlU3RhdGU8U2V0PHN0cmluZz4+KFxuICAgIG5ldyBTZXQoKSxcbiAgKVxuICBjb25zdCBbaW5zdGFsbGluZ1BsdWdpbnMsIHNldEluc3RhbGxpbmdQbHVnaW5zXSA9IHVzZVN0YXRlPFNldDxzdHJpbmc+PihcbiAgICBuZXcgU2V0KCksXG4gIClcblxuICAvLyBQYWdpbmF0aW9uIGZvciBwbHVnaW4gbGlzdCAoY29udGludW91cyBzY3JvbGxpbmcpXG4gIGNvbnN0IHBhZ2luYXRpb24gPSB1c2VQYWdpbmF0aW9uPEluc3RhbGxhYmxlUGx1Z2luPih7XG4gICAgdG90YWxJdGVtczogZmlsdGVyZWRQbHVnaW5zLmxlbmd0aCxcbiAgICBzZWxlY3RlZEluZGV4LFxuICB9KVxuXG4gIC8vIFJlc2V0IHNlbGVjdGlvbiB3aGVuIHNlYXJjaCBxdWVyeSBjaGFuZ2VzXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgc2V0U2VsZWN0ZWRJbmRleCgwKVxuICB9LCBbc2VhcmNoUXVlcnldKVxuXG4gIC8vIERldGFpbHMgdmlldyBzdGF0ZVxuICBjb25zdCBbZGV0YWlsc01lbnVJbmRleCwgc2V0RGV0YWlsc01lbnVJbmRleF0gPSB1c2VTdGF0ZSgwKVxuICBjb25zdCBbaXNJbnN0YWxsaW5nLCBzZXRJc0luc3RhbGxpbmddID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFtpbnN0YWxsRXJyb3IsIHNldEluc3RhbGxFcnJvcl0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPihudWxsKVxuXG4gIC8vIFdhcm5pbmcgc3RhdGUgZm9yIG5vbi1jcml0aWNhbCBlcnJvcnNcbiAgY29uc3QgW3dhcm5pbmcsIHNldFdhcm5pbmddID0gdXNlU3RhdGU8c3RyaW5nIHwgbnVsbD4obnVsbClcblxuICAvLyBFbXB0eSBzdGF0ZSByZWFzb25cbiAgY29uc3QgW2VtcHR5UmVhc29uLCBzZXRFbXB0eVJlYXNvbl0gPSB1c2VTdGF0ZTxFbXB0eU1hcmtldHBsYWNlUmVhc29uIHwgbnVsbD4oXG4gICAgbnVsbCxcbiAgKVxuXG4gIC8vIExvYWQgYWxsIHBsdWdpbnMgZnJvbSBhbGwgbWFya2V0cGxhY2VzXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgYXN5bmMgZnVuY3Rpb24gbG9hZEFsbFBsdWdpbnMoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb25maWcgPSBhd2FpdCBsb2FkS25vd25NYXJrZXRwbGFjZXNDb25maWcoKVxuXG4gICAgICAgIC8vIExvYWQgbWFya2V0cGxhY2VzIHdpdGggZ3JhY2VmdWwgZGVncmFkYXRpb25cbiAgICAgICAgY29uc3QgeyBtYXJrZXRwbGFjZXMsIGZhaWx1cmVzIH0gPVxuICAgICAgICAgIGF3YWl0IGxvYWRNYXJrZXRwbGFjZXNXaXRoR3JhY2VmdWxEZWdyYWRhdGlvbihjb25maWcpXG5cbiAgICAgICAgLy8gQ29sbGVjdCBhbGwgcGx1Z2lucyBmcm9tIGFsbCBtYXJrZXRwbGFjZXNcbiAgICAgICAgY29uc3QgYWxsUGx1Z2luczogSW5zdGFsbGFibGVQbHVnaW5bXSA9IFtdXG5cbiAgICAgICAgZm9yIChjb25zdCB7IG5hbWUsIGRhdGE6IG1hcmtldHBsYWNlIH0gb2YgbWFya2V0cGxhY2VzKSB7XG4gICAgICAgICAgaWYgKG1hcmtldHBsYWNlKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIG1hcmtldHBsYWNlLnBsdWdpbnMpIHtcbiAgICAgICAgICAgICAgY29uc3QgcGx1Z2luSWQgPSBjcmVhdGVQbHVnaW5JZChlbnRyeS5uYW1lLCBuYW1lKVxuICAgICAgICAgICAgICBhbGxQbHVnaW5zLnB1c2goe1xuICAgICAgICAgICAgICAgIGVudHJ5LFxuICAgICAgICAgICAgICAgIG1hcmtldHBsYWNlTmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICBwbHVnaW5JZCxcbiAgICAgICAgICAgICAgICAvLyBPbmx5IGJsb2NrIHdoZW4gZ2xvYmFsbHkgaW5zdGFsbGVkICh1c2VyL21hbmFnZWQgc2NvcGUpLlxuICAgICAgICAgICAgICAgIC8vIFByb2plY3QvbG9jYWwtc2NvcGUgaW5zdGFsbHMgZG9uJ3QgYmxvY2sg4oCUIHVzZXIgbWF5IHdhbnQgdG9cbiAgICAgICAgICAgICAgICAvLyBwcm9tb3RlIHRvIHVzZXIgc2NvcGUgc28gaXQncyBhdmFpbGFibGUgZXZlcnl3aGVyZSAoZ2gtMjk5OTcpLlxuICAgICAgICAgICAgICAgIGlzSW5zdGFsbGVkOiBpc1BsdWdpbkdsb2JhbGx5SW5zdGFsbGVkKHBsdWdpbklkKSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaWx0ZXIgb3V0IGluc3RhbGxlZCBhbmQgcG9saWN5LWJsb2NrZWQgcGx1Z2luc1xuICAgICAgICBjb25zdCB1bmluc3RhbGxlZFBsdWdpbnMgPSBhbGxQbHVnaW5zLmZpbHRlcihcbiAgICAgICAgICBwID0+ICFwLmlzSW5zdGFsbGVkICYmICFpc1BsdWdpbkJsb2NrZWRCeVBvbGljeShwLnBsdWdpbklkKSxcbiAgICAgICAgKVxuXG4gICAgICAgIC8vIEZldGNoIGluc3RhbGwgY291bnRzIGFuZCBzb3J0IGJ5IHBvcHVsYXJpdHlcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBjb3VudHMgPSBhd2FpdCBnZXRJbnN0YWxsQ291bnRzKClcbiAgICAgICAgICBzZXRJbnN0YWxsQ291bnRzKGNvdW50cylcblxuICAgICAgICAgIGlmIChjb3VudHMpIHtcbiAgICAgICAgICAgIC8vIFNvcnQgYnkgaW5zdGFsbCBjb3VudCAoZGVzY2VuZGluZyksIHRoZW4gYWxwaGFiZXRpY2FsbHlcbiAgICAgICAgICAgIHVuaW5zdGFsbGVkUGx1Z2lucy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGNvdW50QSA9IGNvdW50cy5nZXQoYS5wbHVnaW5JZCkgPz8gMFxuICAgICAgICAgICAgICBjb25zdCBjb3VudEIgPSBjb3VudHMuZ2V0KGIucGx1Z2luSWQpID8/IDBcbiAgICAgICAgICAgICAgaWYgKGNvdW50QSAhPT0gY291bnRCKSByZXR1cm4gY291bnRCIC0gY291bnRBXG4gICAgICAgICAgICAgIHJldHVybiBhLmVudHJ5Lm5hbWUubG9jYWxlQ29tcGFyZShiLmVudHJ5Lm5hbWUpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBObyBjb3VudHMgYXZhaWxhYmxlIC0gc29ydCBhbHBoYWJldGljYWxseVxuICAgICAgICAgICAgdW5pbnN0YWxsZWRQbHVnaW5zLnNvcnQoKGEsIGIpID0+XG4gICAgICAgICAgICAgIGEuZW50cnkubmFtZS5sb2NhbGVDb21wYXJlKGIuZW50cnkubmFtZSksXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIC8vIExvZyB0aGUgZXJyb3IsIHRoZW4gZ3JhY2VmdWxseSBkZWdyYWRlIHRvIGFscGhhYmV0aWNhbCBzb3J0XG4gICAgICAgICAgbG9nRm9yRGVidWdnaW5nKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBmZXRjaCBpbnN0YWxsIGNvdW50czogJHtlcnJvck1lc3NhZ2UoZXJyb3IpfWAsXG4gICAgICAgICAgKVxuICAgICAgICAgIHVuaW5zdGFsbGVkUGx1Z2lucy5zb3J0KChhLCBiKSA9PlxuICAgICAgICAgICAgYS5lbnRyeS5uYW1lLmxvY2FsZUNvbXBhcmUoYi5lbnRyeS5uYW1lKSxcbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBzZXRBdmFpbGFibGVQbHVnaW5zKHVuaW5zdGFsbGVkUGx1Z2lucylcblxuICAgICAgICAvLyBEZXRlY3QgZW1wdHkgcmVhc29uIGlmIG5vIHBsdWdpbnMgYXZhaWxhYmxlXG4gICAgICAgIGNvbnN0IGNvbmZpZ3VyZWRDb3VudCA9IE9iamVjdC5rZXlzKGNvbmZpZykubGVuZ3RoXG4gICAgICAgIGlmICh1bmluc3RhbGxlZFBsdWdpbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY29uc3QgcmVhc29uID0gYXdhaXQgZGV0ZWN0RW1wdHlNYXJrZXRwbGFjZVJlYXNvbih7XG4gICAgICAgICAgICBjb25maWd1cmVkTWFya2V0cGxhY2VDb3VudDogY29uZmlndXJlZENvdW50LFxuICAgICAgICAgICAgZmFpbGVkTWFya2V0cGxhY2VDb3VudDogZmFpbHVyZXMubGVuZ3RoLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgc2V0RW1wdHlSZWFzb24ocmVhc29uKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIG1hcmtldHBsYWNlIGxvYWRpbmcgZXJyb3JzL3dhcm5pbmdzXG4gICAgICAgIGNvbnN0IHN1Y2Nlc3NDb3VudCA9IGNvdW50KG1hcmtldHBsYWNlcywgbSA9PiBtLmRhdGEgIT09IG51bGwpXG4gICAgICAgIGNvbnN0IGVycm9yUmVzdWx0ID0gZm9ybWF0TWFya2V0cGxhY2VMb2FkaW5nRXJyb3JzKFxuICAgICAgICAgIGZhaWx1cmVzLFxuICAgICAgICAgIHN1Y2Nlc3NDb3VudCxcbiAgICAgICAgKVxuICAgICAgICBpZiAoZXJyb3JSZXN1bHQpIHtcbiAgICAgICAgICBpZiAoZXJyb3JSZXN1bHQudHlwZSA9PT0gJ3dhcm5pbmcnKSB7XG4gICAgICAgICAgICBzZXRXYXJuaW5nKGVycm9yUmVzdWx0Lm1lc3NhZ2UgKyAnLiBTaG93aW5nIGF2YWlsYWJsZSBwbHVnaW5zLicpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclJlc3VsdC5tZXNzYWdlKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSB0YXJnZXRQbHVnaW4gLSBuYXZpZ2F0ZSBkaXJlY3RseSB0byBwbHVnaW4gZGV0YWlsc1xuICAgICAgICAvLyBTZWFyY2ggaW4gYWxsUGx1Z2lucyAoYmVmb3JlIGZpbHRlcmluZykgdG8gaGFuZGxlIGluc3RhbGxlZCBwbHVnaW5zIGdyYWNlZnVsbHlcbiAgICAgICAgaWYgKHRhcmdldFBsdWdpbikge1xuICAgICAgICAgIGNvbnN0IGZvdW5kUGx1Z2luID0gYWxsUGx1Z2lucy5maW5kKFxuICAgICAgICAgICAgcCA9PiBwLmVudHJ5Lm5hbWUgPT09IHRhcmdldFBsdWdpbixcbiAgICAgICAgICApXG5cbiAgICAgICAgICBpZiAoZm91bmRQbHVnaW4pIHtcbiAgICAgICAgICAgIGlmIChmb3VuZFBsdWdpbi5pc0luc3RhbGxlZCkge1xuICAgICAgICAgICAgICBzZXRFcnJvcihcbiAgICAgICAgICAgICAgICBgUGx1Z2luICcke2ZvdW5kUGx1Z2luLnBsdWdpbklkfScgaXMgYWxyZWFkeSBpbnN0YWxsZWQuIFVzZSAnL3BsdWdpbicgdG8gbWFuYWdlIGV4aXN0aW5nIHBsdWdpbnMuYCxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgc2V0U2VsZWN0ZWRQbHVnaW4oZm91bmRQbHVnaW4pXG4gICAgICAgICAgICAgIHNldFZpZXdTdGF0ZSgncGx1Z2luLWRldGFpbHMnKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRFcnJvcihgUGx1Z2luIFwiJHt0YXJnZXRQbHVnaW59XCIgbm90IGZvdW5kIGluIGFueSBtYXJrZXRwbGFjZWApXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2V0RXJyb3IoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6ICdGYWlsZWQgdG8gbG9hZCBwbHVnaW5zJylcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHNldExvYWRpbmcoZmFsc2UpXG4gICAgICB9XG4gICAgfVxuICAgIHZvaWQgbG9hZEFsbFBsdWdpbnMoKVxuICB9LCBbc2V0RXJyb3IsIHRhcmdldFBsdWdpbl0pXG5cbiAgLy8gSW5zdGFsbCBzZWxlY3RlZCBwbHVnaW5zXG4gIGNvbnN0IGluc3RhbGxTZWxlY3RlZFBsdWdpbnMgPSBhc3luYyAoKSA9PiB7XG4gICAgaWYgKHNlbGVjdGVkRm9ySW5zdGFsbC5zaXplID09PSAwKSByZXR1cm5cblxuICAgIGNvbnN0IHBsdWdpbnNUb0luc3RhbGwgPSBhdmFpbGFibGVQbHVnaW5zLmZpbHRlcihwID0+XG4gICAgICBzZWxlY3RlZEZvckluc3RhbGwuaGFzKHAucGx1Z2luSWQpLFxuICAgIClcblxuICAgIHNldEluc3RhbGxpbmdQbHVnaW5zKG5ldyBTZXQocGx1Z2luc1RvSW5zdGFsbC5tYXAocCA9PiBwLnBsdWdpbklkKSkpXG5cbiAgICBsZXQgc3VjY2Vzc0NvdW50ID0gMFxuICAgIGxldCBmYWlsdXJlQ291bnQgPSAwXG4gICAgY29uc3QgbmV3RmFpbGVkUGx1Z2luczogQXJyYXk8eyBuYW1lOiBzdHJpbmc7IHJlYXNvbjogc3RyaW5nIH0+ID0gW11cblxuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHBsdWdpbnNUb0luc3RhbGwpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGluc3RhbGxQbHVnaW5Gcm9tTWFya2V0cGxhY2Uoe1xuICAgICAgICBwbHVnaW5JZDogcGx1Z2luLnBsdWdpbklkLFxuICAgICAgICBlbnRyeTogcGx1Z2luLmVudHJ5LFxuICAgICAgICBtYXJrZXRwbGFjZU5hbWU6IHBsdWdpbi5tYXJrZXRwbGFjZU5hbWUsXG4gICAgICAgIHNjb3BlOiAndXNlcicsXG4gICAgICB9KVxuXG4gICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgc3VjY2Vzc0NvdW50KytcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZhaWx1cmVDb3VudCsrXG4gICAgICAgIG5ld0ZhaWxlZFBsdWdpbnMucHVzaCh7XG4gICAgICAgICAgbmFtZTogcGx1Z2luLmVudHJ5Lm5hbWUsXG4gICAgICAgICAgcmVhc29uOiByZXN1bHQuZXJyb3IsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgc2V0SW5zdGFsbGluZ1BsdWdpbnMobmV3IFNldCgpKVxuICAgIHNldFNlbGVjdGVkRm9ySW5zdGFsbChuZXcgU2V0KCkpXG4gICAgY2xlYXJBbGxDYWNoZXMoKVxuXG4gICAgLy8gSGFuZGxlIGluc3RhbGxhdGlvbiByZXN1bHRzXG4gICAgaWYgKGZhaWx1cmVDb3VudCA9PT0gMCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9XG4gICAgICAgIGDinJMgSW5zdGFsbGVkICR7c3VjY2Vzc0NvdW50fSAke3BsdXJhbChzdWNjZXNzQ291bnQsICdwbHVnaW4nKX0uIGAgK1xuICAgICAgICBgUnVuIC9yZWxvYWQtcGx1Z2lucyB0byBhY3RpdmF0ZS5gXG4gICAgICBzZXRSZXN1bHQobWVzc2FnZSlcbiAgICB9IGVsc2UgaWYgKHN1Y2Nlc3NDb3VudCA9PT0gMCkge1xuICAgICAgc2V0RXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gaW5zdGFsbDogJHtmb3JtYXRGYWlsdXJlRGV0YWlscyhuZXdGYWlsZWRQbHVnaW5zLCB0cnVlKX1gLFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgICAgYOKckyBJbnN0YWxsZWQgJHtzdWNjZXNzQ291bnR9IG9mICR7c3VjY2Vzc0NvdW50ICsgZmFpbHVyZUNvdW50fSBwbHVnaW5zLiBgICtcbiAgICAgICAgYEZhaWxlZDogJHtmb3JtYXRGYWlsdXJlRGV0YWlscyhuZXdGYWlsZWRQbHVnaW5zLCBmYWxzZSl9LiBgICtcbiAgICAgICAgYFJ1biAvcmVsb2FkLXBsdWdpbnMgdG8gYWN0aXZhdGUgc3VjY2Vzc2Z1bGx5IGluc3RhbGxlZCBwbHVnaW5zLmBcbiAgICAgIHNldFJlc3VsdChtZXNzYWdlKVxuICAgIH1cblxuICAgIGlmIChzdWNjZXNzQ291bnQgPiAwKSB7XG4gICAgICBpZiAob25JbnN0YWxsQ29tcGxldGUpIHtcbiAgICAgICAgYXdhaXQgb25JbnN0YWxsQ29tcGxldGUoKVxuICAgICAgfVxuICAgIH1cblxuICAgIHNldFBhcmVudFZpZXdTdGF0ZSh7IHR5cGU6ICdtZW51JyB9KVxuICB9XG5cbiAgLy8gSW5zdGFsbCBzaW5nbGUgcGx1Z2luIGZyb20gZGV0YWlscyB2aWV3XG4gIGNvbnN0IGhhbmRsZVNpbmdsZVBsdWdpbkluc3RhbGwgPSBhc3luYyAoXG4gICAgcGx1Z2luOiBJbnN0YWxsYWJsZVBsdWdpbixcbiAgICBzY29wZTogJ3VzZXInIHwgJ3Byb2plY3QnIHwgJ2xvY2FsJyA9ICd1c2VyJyxcbiAgKSA9PiB7XG4gICAgc2V0SXNJbnN0YWxsaW5nKHRydWUpXG4gICAgc2V0SW5zdGFsbEVycm9yKG51bGwpXG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBpbnN0YWxsUGx1Z2luRnJvbU1hcmtldHBsYWNlKHtcbiAgICAgIHBsdWdpbklkOiBwbHVnaW4ucGx1Z2luSWQsXG4gICAgICBlbnRyeTogcGx1Z2luLmVudHJ5LFxuICAgICAgbWFya2V0cGxhY2VOYW1lOiBwbHVnaW4ubWFya2V0cGxhY2VOYW1lLFxuICAgICAgc2NvcGUsXG4gICAgfSlcblxuICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgZmluZFBsdWdpbk9wdGlvbnNUYXJnZXQocGx1Z2luLnBsdWdpbklkKVxuICAgICAgaWYgKGxvYWRlZCkge1xuICAgICAgICBzZXRJc0luc3RhbGxpbmcoZmFsc2UpXG4gICAgICAgIHNldFZpZXdTdGF0ZSh7XG4gICAgICAgICAgdHlwZTogJ3BsdWdpbi1vcHRpb25zJyxcbiAgICAgICAgICBwbHVnaW46IGxvYWRlZCxcbiAgICAgICAgICBwbHVnaW5JZDogcGx1Z2luLnBsdWdpbklkLFxuICAgICAgICB9KVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIHNldFJlc3VsdChyZXN1bHQubWVzc2FnZSlcbiAgICAgIGlmIChvbkluc3RhbGxDb21wbGV0ZSkge1xuICAgICAgICBhd2FpdCBvbkluc3RhbGxDb21wbGV0ZSgpXG4gICAgICB9XG4gICAgICBzZXRQYXJlbnRWaWV3U3RhdGUoeyB0eXBlOiAnbWVudScgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgc2V0SXNJbnN0YWxsaW5nKGZhbHNlKVxuICAgICAgc2V0SW5zdGFsbEVycm9yKHJlc3VsdC5lcnJvcilcbiAgICB9XG4gIH1cblxuICAvLyBIYW5kbGUgZXJyb3Igc3RhdGVcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgIHNldFJlc3VsdChlcnJvcilcbiAgICB9XG4gIH0sIFtlcnJvciwgc2V0UmVzdWx0XSlcblxuICAvLyBFc2NhcGUgaW4gcGx1Z2luLWRldGFpbHMgdmlldyAtIGdvIGJhY2sgdG8gcGx1Z2luLWxpc3RcbiAgdXNlS2V5YmluZGluZyhcbiAgICAnY29uZmlybTpubycsXG4gICAgKCkgPT4ge1xuICAgICAgc2V0Vmlld1N0YXRlKCdwbHVnaW4tbGlzdCcpXG4gICAgICBzZXRTZWxlY3RlZFBsdWdpbihudWxsKVxuICAgIH0sXG4gICAge1xuICAgICAgY29udGV4dDogJ0NvbmZpcm1hdGlvbicsXG4gICAgICBpc0FjdGl2ZTogdmlld1N0YXRlID09PSAncGx1Z2luLWRldGFpbHMnLFxuICAgIH0sXG4gIClcblxuICAvLyBFc2NhcGUgaW4gcGx1Z2luLWxpc3QgdmlldyAobm90IHNlYXJjaCBtb2RlKSAtIGV4aXQgdG8gcGFyZW50IG1lbnVcbiAgdXNlS2V5YmluZGluZyhcbiAgICAnY29uZmlybTpubycsXG4gICAgKCkgPT4ge1xuICAgICAgc2V0UGFyZW50Vmlld1N0YXRlKHsgdHlwZTogJ21lbnUnIH0pXG4gICAgfSxcbiAgICB7XG4gICAgICBjb250ZXh0OiAnQ29uZmlybWF0aW9uJyxcbiAgICAgIGlzQWN0aXZlOiB2aWV3U3RhdGUgPT09ICdwbHVnaW4tbGlzdCcgJiYgIWlzU2VhcmNoTW9kZSxcbiAgICB9LFxuICApXG5cbiAgLy8gSGFuZGxlIGVudGVyaW5nIHNlYXJjaCBtb2RlIChub24tZXNjYXBlIGtleXMpXG4gIHVzZUlucHV0KFxuICAgIChpbnB1dCwgX2tleSkgPT4ge1xuICAgICAgY29uc3Qga2V5SXNOb3RDdHJsT3JNZXRhID0gIV9rZXkuY3RybCAmJiAhX2tleS5tZXRhXG4gICAgICBpZiAoIWlzU2VhcmNoTW9kZSkge1xuICAgICAgICAvLyBFbnRlciBzZWFyY2ggbW9kZSB3aXRoICcvJyBvciBhbnkgcHJpbnRhYmxlIGNoYXJhY3RlclxuICAgICAgICBpZiAoaW5wdXQgPT09ICcvJyAmJiBrZXlJc05vdEN0cmxPck1ldGEpIHtcbiAgICAgICAgICBzZXRJc1NlYXJjaE1vZGUodHJ1ZSlcbiAgICAgICAgICBzZXRTZWFyY2hRdWVyeSgnJylcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBrZXlJc05vdEN0cmxPck1ldGEgJiZcbiAgICAgICAgICBpbnB1dC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgIS9eXFxzKyQvLnRlc3QoaW5wdXQpICYmXG4gICAgICAgICAgLy8gRG9uJ3QgZW50ZXIgc2VhcmNoIG1vZGUgZm9yIG5hdmlnYXRpb24ga2V5c1xuICAgICAgICAgIGlucHV0ICE9PSAnaicgJiZcbiAgICAgICAgICBpbnB1dCAhPT0gJ2snICYmXG4gICAgICAgICAgaW5wdXQgIT09ICdpJ1xuICAgICAgICApIHtcbiAgICAgICAgICBzZXRJc1NlYXJjaE1vZGUodHJ1ZSlcbiAgICAgICAgICBzZXRTZWFyY2hRdWVyeShpbnB1dClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgeyBpc0FjdGl2ZTogdmlld1N0YXRlID09PSAncGx1Z2luLWxpc3QnICYmICFsb2FkaW5nIH0sXG4gIClcblxuICAvLyBQbHVnaW4tbGlzdCBuYXZpZ2F0aW9uIChub24tc2VhcmNoIG1vZGUpXG4gIHVzZUtleWJpbmRpbmdzKFxuICAgIHtcbiAgICAgICdzZWxlY3Q6cHJldmlvdXMnOiAoKSA9PiB7XG4gICAgICAgIGlmIChzZWxlY3RlZEluZGV4ID09PSAwKSB7XG4gICAgICAgICAgc2V0SXNTZWFyY2hNb2RlKHRydWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFnaW5hdGlvbi5oYW5kbGVTZWxlY3Rpb25DaGFuZ2Uoc2VsZWN0ZWRJbmRleCAtIDEsIHNldFNlbGVjdGVkSW5kZXgpXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAnc2VsZWN0Om5leHQnOiAoKSA9PiB7XG4gICAgICAgIGlmIChzZWxlY3RlZEluZGV4IDwgZmlsdGVyZWRQbHVnaW5zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICBwYWdpbmF0aW9uLmhhbmRsZVNlbGVjdGlvbkNoYW5nZShzZWxlY3RlZEluZGV4ICsgMSwgc2V0U2VsZWN0ZWRJbmRleClcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgICdzZWxlY3Q6YWNjZXB0JzogKCkgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgc2VsZWN0ZWRJbmRleCA9PT0gZmlsdGVyZWRQbHVnaW5zLmxlbmd0aCAmJlxuICAgICAgICAgIHNlbGVjdGVkRm9ySW5zdGFsbC5zaXplID4gMFxuICAgICAgICApIHtcbiAgICAgICAgICB2b2lkIGluc3RhbGxTZWxlY3RlZFBsdWdpbnMoKVxuICAgICAgICB9IGVsc2UgaWYgKHNlbGVjdGVkSW5kZXggPCBmaWx0ZXJlZFBsdWdpbnMubGVuZ3RoKSB7XG4gICAgICAgICAgY29uc3QgcGx1Z2luID0gZmlsdGVyZWRQbHVnaW5zW3NlbGVjdGVkSW5kZXhdXG4gICAgICAgICAgaWYgKHBsdWdpbikge1xuICAgICAgICAgICAgaWYgKHBsdWdpbi5pc0luc3RhbGxlZCkge1xuICAgICAgICAgICAgICBzZXRQYXJlbnRWaWV3U3RhdGUoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdtYW5hZ2UtcGx1Z2lucycsXG4gICAgICAgICAgICAgICAgdGFyZ2V0UGx1Z2luOiBwbHVnaW4uZW50cnkubmFtZSxcbiAgICAgICAgICAgICAgICB0YXJnZXRNYXJrZXRwbGFjZTogcGx1Z2luLm1hcmtldHBsYWNlTmFtZSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNldFNlbGVjdGVkUGx1Z2luKHBsdWdpbilcbiAgICAgICAgICAgICAgc2V0Vmlld1N0YXRlKCdwbHVnaW4tZGV0YWlscycpXG4gICAgICAgICAgICAgIHNldERldGFpbHNNZW51SW5kZXgoMClcbiAgICAgICAgICAgICAgc2V0SW5zdGFsbEVycm9yKG51bGwpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgY29udGV4dDogJ1NlbGVjdCcsXG4gICAgICBpc0FjdGl2ZTogdmlld1N0YXRlID09PSAncGx1Z2luLWxpc3QnICYmICFpc1NlYXJjaE1vZGUsXG4gICAgfSxcbiAgKVxuXG4gIHVzZUtleWJpbmRpbmdzKFxuICAgIHtcbiAgICAgICdwbHVnaW46dG9nZ2xlJzogKCkgPT4ge1xuICAgICAgICBpZiAoc2VsZWN0ZWRJbmRleCA8IGZpbHRlcmVkUGx1Z2lucy5sZW5ndGgpIHtcbiAgICAgICAgICBjb25zdCBwbHVnaW4gPSBmaWx0ZXJlZFBsdWdpbnNbc2VsZWN0ZWRJbmRleF1cbiAgICAgICAgICBpZiAocGx1Z2luICYmICFwbHVnaW4uaXNJbnN0YWxsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NlbGVjdGlvbiA9IG5ldyBTZXQoc2VsZWN0ZWRGb3JJbnN0YWxsKVxuICAgICAgICAgICAgaWYgKG5ld1NlbGVjdGlvbi5oYXMocGx1Z2luLnBsdWdpbklkKSkge1xuICAgICAgICAgICAgICBuZXdTZWxlY3Rpb24uZGVsZXRlKHBsdWdpbi5wbHVnaW5JZClcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG5ld1NlbGVjdGlvbi5hZGQocGx1Z2luLnBsdWdpbklkKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0U2VsZWN0ZWRGb3JJbnN0YWxsKG5ld1NlbGVjdGlvbilcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAncGx1Z2luOmluc3RhbGwnOiAoKSA9PiB7XG4gICAgICAgIGlmIChzZWxlY3RlZEZvckluc3RhbGwuc2l6ZSA+IDApIHtcbiAgICAgICAgICB2b2lkIGluc3RhbGxTZWxlY3RlZFBsdWdpbnMoKVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgY29udGV4dDogJ1BsdWdpbicsXG4gICAgICBpc0FjdGl2ZTogdmlld1N0YXRlID09PSAncGx1Z2luLWxpc3QnICYmICFpc1NlYXJjaE1vZGUsXG4gICAgfSxcbiAgKVxuXG4gIC8vIFBsdWdpbi1kZXRhaWxzIG5hdmlnYXRpb25cbiAgY29uc3QgZGV0YWlsc01lbnVPcHRpb25zID0gUmVhY3QudXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFzZWxlY3RlZFBsdWdpbikgcmV0dXJuIFtdXG4gICAgY29uc3QgaGFzSG9tZXBhZ2UgPSBzZWxlY3RlZFBsdWdpbi5lbnRyeS5ob21lcGFnZVxuICAgIGNvbnN0IGdpdGh1YlJlcG8gPSBleHRyYWN0R2l0SHViUmVwbyhzZWxlY3RlZFBsdWdpbilcbiAgICByZXR1cm4gYnVpbGRQbHVnaW5EZXRhaWxzTWVudU9wdGlvbnMoaGFzSG9tZXBhZ2UsIGdpdGh1YlJlcG8pXG4gIH0sIFtzZWxlY3RlZFBsdWdpbl0pXG5cbiAgdXNlS2V5YmluZGluZ3MoXG4gICAge1xuICAgICAgJ3NlbGVjdDpwcmV2aW91cyc6ICgpID0+IHtcbiAgICAgICAgaWYgKGRldGFpbHNNZW51SW5kZXggPiAwKSB7XG4gICAgICAgICAgc2V0RGV0YWlsc01lbnVJbmRleChkZXRhaWxzTWVudUluZGV4IC0gMSlcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgICdzZWxlY3Q6bmV4dCc6ICgpID0+IHtcbiAgICAgICAgaWYgKGRldGFpbHNNZW51SW5kZXggPCBkZXRhaWxzTWVudU9wdGlvbnMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgIHNldERldGFpbHNNZW51SW5kZXgoZGV0YWlsc01lbnVJbmRleCArIDEpXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAnc2VsZWN0OmFjY2VwdCc6ICgpID0+IHtcbiAgICAgICAgaWYgKCFzZWxlY3RlZFBsdWdpbikgcmV0dXJuXG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IGRldGFpbHNNZW51T3B0aW9uc1tkZXRhaWxzTWVudUluZGV4XT8uYWN0aW9uXG4gICAgICAgIGNvbnN0IGhhc0hvbWVwYWdlID0gc2VsZWN0ZWRQbHVnaW4uZW50cnkuaG9tZXBhZ2VcbiAgICAgICAgY29uc3QgZ2l0aHViUmVwbyA9IGV4dHJhY3RHaXRIdWJSZXBvKHNlbGVjdGVkUGx1Z2luKVxuICAgICAgICBpZiAoYWN0aW9uID09PSAnaW5zdGFsbC11c2VyJykge1xuICAgICAgICAgIHZvaWQgaGFuZGxlU2luZ2xlUGx1Z2luSW5zdGFsbChzZWxlY3RlZFBsdWdpbiwgJ3VzZXInKVxuICAgICAgICB9IGVsc2UgaWYgKGFjdGlvbiA9PT0gJ2luc3RhbGwtcHJvamVjdCcpIHtcbiAgICAgICAgICB2b2lkIGhhbmRsZVNpbmdsZVBsdWdpbkluc3RhbGwoc2VsZWN0ZWRQbHVnaW4sICdwcm9qZWN0JylcbiAgICAgICAgfSBlbHNlIGlmIChhY3Rpb24gPT09ICdpbnN0YWxsLWxvY2FsJykge1xuICAgICAgICAgIHZvaWQgaGFuZGxlU2luZ2xlUGx1Z2luSW5zdGFsbChzZWxlY3RlZFBsdWdpbiwgJ2xvY2FsJylcbiAgICAgICAgfSBlbHNlIGlmIChhY3Rpb24gPT09ICdob21lcGFnZScgJiYgaGFzSG9tZXBhZ2UpIHtcbiAgICAgICAgICB2b2lkIG9wZW5Ccm93c2VyKGhhc0hvbWVwYWdlKVxuICAgICAgICB9IGVsc2UgaWYgKGFjdGlvbiA9PT0gJ2dpdGh1YicgJiYgZ2l0aHViUmVwbykge1xuICAgICAgICAgIHZvaWQgb3BlbkJyb3dzZXIoYGh0dHBzOi8vZ2l0aHViLmNvbS8ke2dpdGh1YlJlcG99YClcbiAgICAgICAgfSBlbHNlIGlmIChhY3Rpb24gPT09ICdiYWNrJykge1xuICAgICAgICAgIHNldFZpZXdTdGF0ZSgncGx1Z2luLWxpc3QnKVxuICAgICAgICAgIHNldFNlbGVjdGVkUGx1Z2luKG51bGwpXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBjb250ZXh0OiAnU2VsZWN0JyxcbiAgICAgIGlzQWN0aXZlOiB2aWV3U3RhdGUgPT09ICdwbHVnaW4tZGV0YWlscycgJiYgISFzZWxlY3RlZFBsdWdpbixcbiAgICB9LFxuICApXG5cbiAgaWYgKHR5cGVvZiB2aWV3U3RhdGUgPT09ICdvYmplY3QnICYmIHZpZXdTdGF0ZS50eXBlID09PSAncGx1Z2luLW9wdGlvbnMnKSB7XG4gICAgY29uc3QgeyBwbHVnaW4sIHBsdWdpbklkIH0gPSB2aWV3U3RhdGVcbiAgICBmdW5jdGlvbiBmaW5pc2gobXNnOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgIHNldFJlc3VsdChtc2cpXG4gICAgICBpZiAob25JbnN0YWxsQ29tcGxldGUpIHtcbiAgICAgICAgdm9pZCBvbkluc3RhbGxDb21wbGV0ZSgpXG4gICAgICB9XG4gICAgICBzZXRQYXJlbnRWaWV3U3RhdGUoeyB0eXBlOiAnbWVudScgfSlcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgIDxQbHVnaW5PcHRpb25zRmxvd1xuICAgICAgICBwbHVnaW49e3BsdWdpbn1cbiAgICAgICAgcGx1Z2luSWQ9e3BsdWdpbklkfVxuICAgICAgICBvbkRvbmU9eyhvdXRjb21lLCBkZXRhaWwpID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKG91dGNvbWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2NvbmZpZ3VyZWQnOlxuICAgICAgICAgICAgICBmaW5pc2goXG4gICAgICAgICAgICAgICAgYOKckyBJbnN0YWxsZWQgYW5kIGNvbmZpZ3VyZWQgJHtwbHVnaW4ubmFtZX0uIFJ1biAvcmVsb2FkLXBsdWdpbnMgdG8gYXBwbHkuYCxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgY2FzZSAnc2tpcHBlZCc6XG4gICAgICAgICAgICAgIGZpbmlzaChcbiAgICAgICAgICAgICAgICBg4pyTIEluc3RhbGxlZCAke3BsdWdpbi5uYW1lfS4gUnVuIC9yZWxvYWQtcGx1Z2lucyB0byBhcHBseS5gLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgICAgICAgIGZpbmlzaChgSW5zdGFsbGVkIGJ1dCBmYWlsZWQgdG8gc2F2ZSBjb25maWc6ICR7ZGV0YWlsfWApXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9fVxuICAgICAgLz5cbiAgICApXG4gIH1cblxuICAvLyBMb2FkaW5nIHN0YXRlXG4gIGlmIChsb2FkaW5nKSB7XG4gICAgcmV0dXJuIDxUZXh0PkxvYWRpbmfigKY8L1RleHQ+XG4gIH1cblxuICAvLyBFcnJvciBzdGF0ZVxuICBpZiAoZXJyb3IpIHtcbiAgICByZXR1cm4gPFRleHQgY29sb3I9XCJlcnJvclwiPntlcnJvcn08L1RleHQ+XG4gIH1cblxuICAvLyBQbHVnaW4gZGV0YWlscyB2aWV3XG4gIGlmICh2aWV3U3RhdGUgPT09ICdwbHVnaW4tZGV0YWlscycgJiYgc2VsZWN0ZWRQbHVnaW4pIHtcbiAgICBjb25zdCBoYXNIb21lcGFnZSA9IHNlbGVjdGVkUGx1Z2luLmVudHJ5LmhvbWVwYWdlXG4gICAgY29uc3QgZ2l0aHViUmVwbyA9IGV4dHJhY3RHaXRIdWJSZXBvKHNlbGVjdGVkUGx1Z2luKVxuXG4gICAgY29uc3QgbWVudU9wdGlvbnMgPSBidWlsZFBsdWdpbkRldGFpbHNNZW51T3B0aW9ucyhoYXNIb21lcGFnZSwgZ2l0aHViUmVwbylcblxuICAgIHJldHVybiAoXG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgPEJveCBtYXJnaW5Cb3R0b209ezF9PlxuICAgICAgICAgIDxUZXh0IGJvbGQ+UGx1Z2luIGRldGFpbHM8L1RleHQ+XG4gICAgICAgIDwvQm94PlxuXG4gICAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiIG1hcmdpbkJvdHRvbT17MX0+XG4gICAgICAgICAgPFRleHQgYm9sZD57c2VsZWN0ZWRQbHVnaW4uZW50cnkubmFtZX08L1RleHQ+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+ZnJvbSB7c2VsZWN0ZWRQbHVnaW4ubWFya2V0cGxhY2VOYW1lfTwvVGV4dD5cbiAgICAgICAgICB7c2VsZWN0ZWRQbHVnaW4uZW50cnkudmVyc2lvbiAmJiAoXG4gICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5WZXJzaW9uOiB7c2VsZWN0ZWRQbHVnaW4uZW50cnkudmVyc2lvbn08L1RleHQ+XG4gICAgICAgICAgKX1cbiAgICAgICAgICB7c2VsZWN0ZWRQbHVnaW4uZW50cnkuZGVzY3JpcHRpb24gJiYgKFxuICAgICAgICAgICAgPEJveCBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICAgICAgICA8VGV4dD57c2VsZWN0ZWRQbHVnaW4uZW50cnkuZGVzY3JpcHRpb259PC9UZXh0PlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKX1cbiAgICAgICAgICB7c2VsZWN0ZWRQbHVnaW4uZW50cnkuYXV0aG9yICYmIChcbiAgICAgICAgICAgIDxCb3ggbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgICAgQnk6eycgJ31cbiAgICAgICAgICAgICAgICB7dHlwZW9mIHNlbGVjdGVkUGx1Z2luLmVudHJ5LmF1dGhvciA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgICAgICAgID8gc2VsZWN0ZWRQbHVnaW4uZW50cnkuYXV0aG9yXG4gICAgICAgICAgICAgICAgICA6IHNlbGVjdGVkUGx1Z2luLmVudHJ5LmF1dGhvci5uYW1lfVxuICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICA8L0JveD5cbiAgICAgICAgICApfVxuICAgICAgICA8L0JveD5cblxuICAgICAgICA8UGx1Z2luVHJ1c3RXYXJuaW5nIC8+XG5cbiAgICAgICAge2luc3RhbGxFcnJvciAmJiAoXG4gICAgICAgICAgPEJveCBtYXJnaW5Cb3R0b209ezF9PlxuICAgICAgICAgICAgPFRleHQgY29sb3I9XCJlcnJvclwiPkVycm9yOiB7aW5zdGFsbEVycm9yfTwvVGV4dD5cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgKX1cblxuICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICB7bWVudU9wdGlvbnMubWFwKChvcHRpb24sIGluZGV4KSA9PiAoXG4gICAgICAgICAgICA8Qm94IGtleT17b3B0aW9uLmFjdGlvbn0+XG4gICAgICAgICAgICAgIHtkZXRhaWxzTWVudUluZGV4ID09PSBpbmRleCAmJiA8VGV4dD57Jz4gJ308L1RleHQ+fVxuICAgICAgICAgICAgICB7ZGV0YWlsc01lbnVJbmRleCAhPT0gaW5kZXggJiYgPFRleHQ+eycgICd9PC9UZXh0Pn1cbiAgICAgICAgICAgICAgPFRleHQgYm9sZD17ZGV0YWlsc01lbnVJbmRleCA9PT0gaW5kZXh9PlxuICAgICAgICAgICAgICAgIHtpc0luc3RhbGxpbmcgJiYgb3B0aW9uLmFjdGlvbi5zdGFydHNXaXRoKCdpbnN0YWxsLScpXG4gICAgICAgICAgICAgICAgICA/ICdJbnN0YWxsaW5n4oCmJ1xuICAgICAgICAgICAgICAgICAgOiBvcHRpb24ubGFiZWx9XG4gICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgIDwvQm94PlxuICAgICAgICAgICkpfVxuICAgICAgICA8L0JveD5cblxuICAgICAgICA8Qm94IG1hcmdpblRvcD17MX0+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICA8QnlsaW5lPlxuICAgICAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICAgICAgYWN0aW9uPVwic2VsZWN0OmFjY2VwdFwiXG4gICAgICAgICAgICAgICAgY29udGV4dD1cIlNlbGVjdFwiXG4gICAgICAgICAgICAgICAgZmFsbGJhY2s9XCJFbnRlclwiXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJzZWxlY3RcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICAgICAgYWN0aW9uPVwiY29uZmlybTpub1wiXG4gICAgICAgICAgICAgICAgY29udGV4dD1cIkNvbmZpcm1hdGlvblwiXG4gICAgICAgICAgICAgICAgZmFsbGJhY2s9XCJFc2NcIlxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uPVwiYmFja1wiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L0J5bGluZT5cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgPC9Cb3g+XG4gICAgKVxuICB9XG5cbiAgLy8gRW1wdHkgc3RhdGVcbiAgaWYgKGF2YWlsYWJsZVBsdWdpbnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8Qm94IG1hcmdpbkJvdHRvbT17MX0+XG4gICAgICAgICAgPFRleHQgYm9sZD5EaXNjb3ZlciBwbHVnaW5zPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICAgPEVtcHR5U3RhdGVNZXNzYWdlIHJlYXNvbj17ZW1wdHlSZWFzb259IC8+XG4gICAgICAgIDxCb3ggbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvciBpdGFsaWM+XG4gICAgICAgICAgICBFc2MgdG8gZ28gYmFja1xuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICA8L0JveD5cbiAgICApXG4gIH1cblxuICAvLyBHZXQgdmlzaWJsZSBwbHVnaW5zIGZyb20gcGFnaW5hdGlvblxuICBjb25zdCB2aXNpYmxlUGx1Z2lucyA9IHBhZ2luYXRpb24uZ2V0VmlzaWJsZUl0ZW1zKGZpbHRlcmVkUGx1Z2lucylcblxuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgPEJveD5cbiAgICAgICAgPFRleHQgYm9sZD5EaXNjb3ZlciBwbHVnaW5zPC9UZXh0PlxuICAgICAgICB7cGFnaW5hdGlvbi5uZWVkc1BhZ2luYXRpb24gJiYgKFxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgeycgJ31cbiAgICAgICAgICAgICh7cGFnaW5hdGlvbi5zY3JvbGxQb3NpdGlvbi5jdXJyZW50fS9cbiAgICAgICAgICAgIHtwYWdpbmF0aW9uLnNjcm9sbFBvc2l0aW9uLnRvdGFsfSlcbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICl9XG4gICAgICA8L0JveD5cblxuICAgICAgey8qIFNlYXJjaCBib3ggKi99XG4gICAgICA8Qm94IG1hcmdpbkJvdHRvbT17MX0+XG4gICAgICAgIDxTZWFyY2hCb3hcbiAgICAgICAgICBxdWVyeT17c2VhcmNoUXVlcnl9XG4gICAgICAgICAgaXNGb2N1c2VkPXtpc1NlYXJjaE1vZGV9XG4gICAgICAgICAgaXNUZXJtaW5hbEZvY3VzZWQ9e2lzVGVybWluYWxGb2N1c2VkfVxuICAgICAgICAgIHdpZHRoPXt0ZXJtaW5hbFdpZHRoIC0gNH1cbiAgICAgICAgICBjdXJzb3JPZmZzZXQ9e3NlYXJjaEN1cnNvck9mZnNldH1cbiAgICAgICAgLz5cbiAgICAgIDwvQm94PlxuXG4gICAgICB7LyogV2FybmluZyBiYW5uZXIgKi99XG4gICAgICB7d2FybmluZyAmJiAoXG4gICAgICAgIDxCb3ggbWFyZ2luQm90dG9tPXsxfT5cbiAgICAgICAgICA8VGV4dCBjb2xvcj1cIndhcm5pbmdcIj5cbiAgICAgICAgICAgIHtmaWd1cmVzLndhcm5pbmd9IHt3YXJuaW5nfVxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICApfVxuXG4gICAgICB7LyogTm8gc2VhcmNoIHJlc3VsdHMgKi99XG4gICAgICB7ZmlsdGVyZWRQbHVnaW5zLmxlbmd0aCA9PT0gMCAmJiBzZWFyY2hRdWVyeSAmJiAoXG4gICAgICAgIDxCb3ggbWFyZ2luQm90dG9tPXsxfT5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5ObyBwbHVnaW5zIG1hdGNoICZxdW90O3tzZWFyY2hRdWVyeX0mcXVvdDs8L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgKX1cblxuICAgICAgey8qIFNjcm9sbCB1cCBpbmRpY2F0b3IgKi99XG4gICAgICB7cGFnaW5hdGlvbi5zY3JvbGxQb3NpdGlvbi5jYW5TY3JvbGxVcCAmJiAoXG4gICAgICAgIDxCb3g+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+IHtmaWd1cmVzLmFycm93VXB9IG1vcmUgYWJvdmU8L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgKX1cblxuICAgICAgey8qIFBsdWdpbiBsaXN0IC0gdXNlIHN0YXJ0SW5kZXggaW4ga2V5IHRvIGZvcmNlIHJlLXJlbmRlciBvbiBzY3JvbGwgKi99XG4gICAgICB7dmlzaWJsZVBsdWdpbnMubWFwKChwbHVnaW4sIHZpc2libGVJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBhY3R1YWxJbmRleCA9IHBhZ2luYXRpb24udG9BY3R1YWxJbmRleCh2aXNpYmxlSW5kZXgpXG4gICAgICAgIGNvbnN0IGlzU2VsZWN0ZWQgPSBzZWxlY3RlZEluZGV4ID09PSBhY3R1YWxJbmRleFxuICAgICAgICBjb25zdCBpc1NlbGVjdGVkRm9ySW5zdGFsbCA9IHNlbGVjdGVkRm9ySW5zdGFsbC5oYXMocGx1Z2luLnBsdWdpbklkKVxuICAgICAgICBjb25zdCBpc0luc3RhbGxpbmdUaGlzID0gaW5zdGFsbGluZ1BsdWdpbnMuaGFzKHBsdWdpbi5wbHVnaW5JZClcbiAgICAgICAgY29uc3QgaXNMYXN0ID0gdmlzaWJsZUluZGV4ID09PSB2aXNpYmxlUGx1Z2lucy5sZW5ndGggLSAxXG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICA8Qm94XG4gICAgICAgICAgICBrZXk9e2Ake3BhZ2luYXRpb24uc3RhcnRJbmRleH0tJHtwbHVnaW4ucGx1Z2luSWR9YH1cbiAgICAgICAgICAgIGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIlxuICAgICAgICAgICAgbWFyZ2luQm90dG9tPXtpc0xhc3QgJiYgIWVycm9yID8gMCA6IDF9XG4gICAgICAgICAgPlxuICAgICAgICAgICAgPEJveD5cbiAgICAgICAgICAgICAgPFRleHRcbiAgICAgICAgICAgICAgICBjb2xvcj17aXNTZWxlY3RlZCAmJiAhaXNTZWFyY2hNb2RlID8gJ3N1Z2dlc3Rpb24nIDogdW5kZWZpbmVkfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAge2lzU2VsZWN0ZWQgJiYgIWlzU2VhcmNoTW9kZSA/IGZpZ3VyZXMucG9pbnRlciA6ICcgJ317JyAnfVxuICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgICAgIHtpc0luc3RhbGxpbmdUaGlzXG4gICAgICAgICAgICAgICAgICA/IGZpZ3VyZXMuZWxsaXBzaXNcbiAgICAgICAgICAgICAgICAgIDogaXNTZWxlY3RlZEZvckluc3RhbGxcbiAgICAgICAgICAgICAgICAgICAgPyBmaWd1cmVzLnJhZGlvT25cbiAgICAgICAgICAgICAgICAgICAgOiBmaWd1cmVzLnJhZGlvT2ZmfXsnICd9XG4gICAgICAgICAgICAgICAge3BsdWdpbi5lbnRyeS5uYW1lfVxuICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPiDCtyB7cGx1Z2luLm1hcmtldHBsYWNlTmFtZX08L1RleHQ+XG4gICAgICAgICAgICAgICAge3BsdWdpbi5lbnRyeS50YWdzPy5pbmNsdWRlcygnY29tbXVuaXR5LW1hbmFnZWQnKSAmJiAoXG4gICAgICAgICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj4gW0NvbW11bml0eSBNYW5hZ2VkXTwvVGV4dD5cbiAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgIHtpbnN0YWxsQ291bnRzICYmXG4gICAgICAgICAgICAgICAgICBwbHVnaW4ubWFya2V0cGxhY2VOYW1lID09PSBPRkZJQ0lBTF9NQVJLRVRQTEFDRV9OQU1FICYmIChcbiAgICAgICAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgICAgICAgICAgeycgwrcgJ31cbiAgICAgICAgICAgICAgICAgICAgICB7Zm9ybWF0SW5zdGFsbENvdW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFsbENvdW50cy5nZXQocGx1Z2luLnBsdWdpbklkKSA/PyAwLFxuICAgICAgICAgICAgICAgICAgICAgICl9eycgJ31cbiAgICAgICAgICAgICAgICAgICAgICBpbnN0YWxsc1xuICAgICAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICA8L0JveD5cbiAgICAgICAgICAgIHtwbHVnaW4uZW50cnkuZGVzY3JpcHRpb24gJiYgKFxuICAgICAgICAgICAgICA8Qm94IG1hcmdpbkxlZnQ9ezR9PlxuICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICAgICAge3RydW5jYXRlVG9XaWR0aChwbHVnaW4uZW50cnkuZGVzY3JpcHRpb24sIDYwKX1cbiAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIDwvQm94PlxuICAgICAgICAgICAgKX1cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgKVxuICAgICAgfSl9XG5cbiAgICAgIHsvKiBTY3JvbGwgZG93biBpbmRpY2F0b3IgKi99XG4gICAgICB7cGFnaW5hdGlvbi5zY3JvbGxQb3NpdGlvbi5jYW5TY3JvbGxEb3duICYmIChcbiAgICAgICAgPEJveD5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj4ge2ZpZ3VyZXMuYXJyb3dEb3dufSBtb3JlIGJlbG93PC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICl9XG5cbiAgICAgIHsvKiBFcnJvciBtZXNzYWdlcyAqL31cbiAgICAgIHtlcnJvciAmJiAoXG4gICAgICAgIDxCb3ggbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICA8VGV4dCBjb2xvcj1cImVycm9yXCI+XG4gICAgICAgICAgICB7ZmlndXJlcy5jcm9zc30ge2Vycm9yfVxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICApfVxuXG4gICAgICA8RGlzY292ZXJQbHVnaW5zS2V5SGludFxuICAgICAgICBoYXNTZWxlY3Rpb249e3NlbGVjdGVkRm9ySW5zdGFsbC5zaXplID4gMH1cbiAgICAgICAgY2FuVG9nZ2xlPXtcbiAgICAgICAgICBzZWxlY3RlZEluZGV4IDwgZmlsdGVyZWRQbHVnaW5zLmxlbmd0aCAmJlxuICAgICAgICAgICFmaWx0ZXJlZFBsdWdpbnNbc2VsZWN0ZWRJbmRleF0/LmlzSW5zdGFsbGVkXG4gICAgICAgIH1cbiAgICAgIC8+XG4gICAgPC9Cb3g+XG4gIClcbn1cblxuZnVuY3Rpb24gRGlzY292ZXJQbHVnaW5zS2V5SGludCh7XG4gIGhhc1NlbGVjdGlvbixcbiAgY2FuVG9nZ2xlLFxufToge1xuICBoYXNTZWxlY3Rpb246IGJvb2xlYW5cbiAgY2FuVG9nZ2xlOiBib29sZWFuXG59KTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgcmV0dXJuIChcbiAgICA8Qm94IG1hcmdpblRvcD17MX0+XG4gICAgICA8VGV4dCBkaW1Db2xvciBpdGFsaWM+XG4gICAgICAgIDxCeWxpbmU+XG4gICAgICAgICAge2hhc1NlbGVjdGlvbiAmJiAoXG4gICAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICAgIGFjdGlvbj1cInBsdWdpbjppbnN0YWxsXCJcbiAgICAgICAgICAgICAgY29udGV4dD1cIlBsdWdpblwiXG4gICAgICAgICAgICAgIGZhbGxiYWNrPVwiaVwiXG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uPVwiaW5zdGFsbFwiXG4gICAgICAgICAgICAgIGJvbGRcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgKX1cbiAgICAgICAgICA8VGV4dD50eXBlIHRvIHNlYXJjaDwvVGV4dD5cbiAgICAgICAgICB7Y2FuVG9nZ2xlICYmIChcbiAgICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgICAgYWN0aW9uPVwicGx1Z2luOnRvZ2dsZVwiXG4gICAgICAgICAgICAgIGNvbnRleHQ9XCJQbHVnaW5cIlxuICAgICAgICAgICAgICBmYWxsYmFjaz1cIlNwYWNlXCJcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJ0b2dnbGVcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICApfVxuICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgIGFjdGlvbj1cInNlbGVjdDphY2NlcHRcIlxuICAgICAgICAgICAgY29udGV4dD1cIlNlbGVjdFwiXG4gICAgICAgICAgICBmYWxsYmFjaz1cIkVudGVyXCJcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uPVwiZGV0YWlsc1wiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICBhY3Rpb249XCJjb25maXJtOm5vXCJcbiAgICAgICAgICAgIGNvbnRleHQ9XCJDb25maXJtYXRpb25cIlxuICAgICAgICAgICAgZmFsbGJhY2s9XCJFc2NcIlxuICAgICAgICAgICAgZGVzY3JpcHRpb249XCJiYWNrXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L0J5bGluZT5cbiAgICAgIDwvVGV4dD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG4vKipcbiAqIENvbnRleHQtYXdhcmUgZW1wdHkgc3RhdGUgbWVzc2FnZSBmb3IgdGhlIERpc2NvdmVyIHNjcmVlblxuICovXG5mdW5jdGlvbiBFbXB0eVN0YXRlTWVzc2FnZSh7XG4gIHJlYXNvbixcbn06IHtcbiAgcmVhc29uOiBFbXB0eU1hcmtldHBsYWNlUmVhc29uIHwgbnVsbFxufSk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIHN3aXRjaCAocmVhc29uKSB7XG4gICAgY2FzZSAnZ2l0LW5vdC1pbnN0YWxsZWQnOlxuICAgICAgcmV0dXJuIChcbiAgICAgICAgPD5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5HaXQgaXMgcmVxdWlyZWQgdG8gaW5zdGFsbCBtYXJrZXRwbGFjZXMuPC9UZXh0PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlBsZWFzZSBpbnN0YWxsIGdpdCBhbmQgcmVzdGFydCBDbGF1ZGUgQ29kZS48L1RleHQ+XG4gICAgICAgIDwvPlxuICAgICAgKVxuICAgIGNhc2UgJ2FsbC1ibG9ja2VkLWJ5LXBvbGljeSc6XG4gICAgICByZXR1cm4gKFxuICAgICAgICA8PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgWW91ciBvcmdhbml6YXRpb24gcG9saWN5IGRvZXMgbm90IGFsbG93IGFueSBleHRlcm5hbCBtYXJrZXRwbGFjZXMuXG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPkNvbnRhY3QgeW91ciBhZG1pbmlzdHJhdG9yLjwvVGV4dD5cbiAgICAgICAgPC8+XG4gICAgICApXG4gICAgY2FzZSAncG9saWN5LXJlc3RyaWN0cy1zb3VyY2VzJzpcbiAgICAgIHJldHVybiAoXG4gICAgICAgIDw+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICBZb3VyIG9yZ2FuaXphdGlvbiByZXN0cmljdHMgd2hpY2ggbWFya2V0cGxhY2VzIGNhbiBiZSBhZGRlZC5cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICBTd2l0Y2ggdG8gdGhlIE1hcmtldHBsYWNlcyB0YWIgdG8gdmlldyBhbGxvd2VkIHNvdXJjZXMuXG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8Lz5cbiAgICAgIClcbiAgICBjYXNlICdhbGwtbWFya2V0cGxhY2VzLWZhaWxlZCc6XG4gICAgICByZXR1cm4gKFxuICAgICAgICA8PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPkZhaWxlZCB0byBsb2FkIG1hcmtldHBsYWNlIGRhdGEuPC9UZXh0PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPkNoZWNrIHlvdXIgbmV0d29yayBjb25uZWN0aW9uLjwvVGV4dD5cbiAgICAgICAgPC8+XG4gICAgICApXG4gICAgY2FzZSAnYWxsLXBsdWdpbnMtaW5zdGFsbGVkJzpcbiAgICAgIHJldHVybiAoXG4gICAgICAgIDw+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+QWxsIGF2YWlsYWJsZSBwbHVnaW5zIGFyZSBhbHJlYWR5IGluc3RhbGxlZC48L1RleHQ+XG4gICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICBDaGVjayBmb3IgbmV3IHBsdWdpbnMgbGF0ZXIgb3IgYWRkIG1vcmUgbWFya2V0cGxhY2VzLlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC8+XG4gICAgICApXG4gICAgY2FzZSAnbm8tbWFya2V0cGxhY2VzLWNvbmZpZ3VyZWQnOlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gKFxuICAgICAgICA8PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPk5vIHBsdWdpbnMgYXZhaWxhYmxlLjwvVGV4dD5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgIEFkZCBhIG1hcmtldHBsYWNlIGZpcnN0IHVzaW5nIHRoZSBNYXJrZXRwbGFjZXMgdGFiLlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC8+XG4gICAgICApXG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU9BLE9BQU8sTUFBTSxTQUFTO0FBQzdCLE9BQU8sS0FB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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/plugin/unifiedTypes.ts b/_all-in-one-upload/cc-haha/src/commands/plugin/unifiedTypes.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/plugin/unifiedTypes.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/commands/remoteControlServer/index.ts b/_all-in-one-upload/cc-haha/src/commands/remoteControlServer/index.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/remoteControlServer/index.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/commands/rename/generateSessionName.ts b/_all-in-one-upload/cc-haha/src/commands/rename/generateSessionName.ts new file mode 100644 index 0000000..2ebd786 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/rename/generateSessionName.ts @@ -0,0 +1,67 @@ +import { queryHaiku } from '../../services/api/claude.js' +import type { Message } from '../../types/message.js' +import { logForDebugging } from '../../utils/debug.js' +import { errorMessage } from '../../utils/errors.js' +import { safeParseJSON } from '../../utils/json.js' +import { extractTextContent } from '../../utils/messages.js' +import { extractConversationText } from '../../utils/sessionTitle.js' +import { asSystemPrompt } from '../../utils/systemPromptType.js' + +export async function generateSessionName( + messages: Message[], + signal: AbortSignal, +): Promise { + const conversationText = extractConversationText(messages) + if (!conversationText) { + return null + } + + try { + const result = await queryHaiku({ + systemPrompt: asSystemPrompt([ + 'Generate a short kebab-case name (2-4 words) that captures the main topic of this conversation. Use lowercase words separated by hyphens. Examples: "fix-login-bug", "add-auth-feature", "refactor-api-client", "debug-test-failures". Return JSON with a "name" field.', + ]), + userPrompt: conversationText, + outputFormat: { + type: 'json_schema', + schema: { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: ['name'], + additionalProperties: false, + }, + }, + signal, + options: { + querySource: 'rename_generate_name', + agents: [], + isNonInteractiveSession: false, + hasAppendSystemPrompt: false, + mcpTools: [], + }, + }) + + const content = extractTextContent(result.message.content) + + const response = safeParseJSON(content) + if ( + response && + typeof response === 'object' && + 'name' in response && + typeof (response as { name: unknown }).name === 'string' + ) { + return (response as { name: string }).name + } + return null + } catch (error) { + // Haiku timeout/rate-limit/network are expected operational failures — + // logForDebugging, not logError. Called automatically on every 3rd bridge + // message (initReplBridge.ts), so errors here would flood the error file. + logForDebugging(`generateSessionName failed: ${errorMessage(error)}`, { + level: 'error', + }) + return null + } +} diff --git a/_all-in-one-upload/cc-haha/src/commands/rename/rename.ts b/_all-in-one-upload/cc-haha/src/commands/rename/rename.ts new file mode 100644 index 0000000..014d7eb --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/rename/rename.ts @@ -0,0 +1,87 @@ +import type { UUID } from 'crypto' +import { getSessionId } from '../../bootstrap/state.js' +import { + getBridgeBaseUrlOverride, + getBridgeTokenOverride, +} from '../../bridge/bridgeConfig.js' +import type { ToolUseContext } from '../../Tool.js' +import type { + LocalJSXCommandContext, + LocalJSXCommandOnDone, +} from '../../types/command.js' +import { getMessagesAfterCompactBoundary } from '../../utils/messages.js' +import { + getTranscriptPath, + saveAgentName, + saveCustomTitle, +} from '../../utils/sessionStorage.js' +import { isTeammate } from '../../utils/teammate.js' +import { generateSessionName } from './generateSessionName.js' + +export async function call( + onDone: LocalJSXCommandOnDone, + context: ToolUseContext & LocalJSXCommandContext, + args: string, +): Promise { + // Prevent teammates from renaming - their names are set by team leader + if (isTeammate()) { + onDone( + 'Cannot rename: This session is a swarm teammate. Teammate names are set by the team leader.', + { display: 'system' }, + ) + return null + } + + let newName: string + if (!args || args.trim() === '') { + const generated = await generateSessionName( + getMessagesAfterCompactBoundary(context.messages), + context.abortController.signal, + ) + if (!generated) { + onDone( + 'Could not generate a name: no conversation context yet. Usage: /rename ', + { display: 'system' }, + ) + return null + } + newName = generated + } else { + newName = args.trim() + } + + const sessionId = getSessionId() as UUID + const fullPath = getTranscriptPath() + + // Always save the custom title (session name) + await saveCustomTitle(sessionId, newName, fullPath) + + // Sync title to bridge session on claude.ai/code (best-effort, non-blocking). + // v2 env-less bridge stores cse_* in replBridgeSessionId — + // updateBridgeSessionTitle retags internally for the compat endpoint. + const appState = context.getAppState() + const bridgeSessionId = appState.replBridgeSessionId + if (bridgeSessionId) { + const tokenOverride = getBridgeTokenOverride() + void import('../../bridge/createSession.js').then( + ({ updateBridgeSessionTitle }) => + updateBridgeSessionTitle(bridgeSessionId, newName, { + baseUrl: getBridgeBaseUrlOverride(), + getAccessToken: tokenOverride ? () => tokenOverride : undefined, + }).catch(() => {}), + ) + } + + // Also persist as the session's agent name for prompt-bar display + await saveAgentName(sessionId, newName, fullPath) + context.setAppState(prev => ({ + ...prev, + standaloneAgentContext: { + ...prev.standaloneAgentContext, + name: newName, + }, + })) + + onDone(`Session renamed to: ${newName}`, { display: 'system' }) + return null +} diff --git a/_all-in-one-upload/cc-haha/src/commands/skills/skills.tsx b/_all-in-one-upload/cc-haha/src/commands/skills/skills.tsx new file mode 100644 index 0000000..c9bf0e6 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/skills/skills.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import type { LocalJSXCommandContext } from '../../commands.js'; +import { SkillsMenu } from '../../components/skills/SkillsMenu.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; +export async function call(onDone: LocalJSXCommandOnDone, context: LocalJSXCommandContext): Promise { + return ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkxvY2FsSlNYQ29tbWFuZENvbnRleHQiLCJTa2lsbHNNZW51IiwiTG9jYWxKU1hDb21tYW5kT25Eb25lIiwiY2FsbCIsIm9uRG9uZSIsImNvbnRleHQiLCJQcm9taXNlIiwiUmVhY3ROb2RlIiwib3B0aW9ucyIsImNvbW1hbmRzIl0sInNvdXJjZXMiOlsic2tpbGxzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgTG9jYWxKU1hDb21tYW5kQ29udGV4dCB9IGZyb20gJy4uLy4uL2NvbW1hbmRzLmpzJ1xuaW1wb3J0IHsgU2tpbGxzTWVudSB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvc2tpbGxzL1NraWxsc01lbnUuanMnXG5pbXBvcnQgdHlwZSB7IExvY2FsSlNYQ29tbWFuZE9uRG9uZSB9IGZyb20gJy4uLy4uL3R5cGVzL2NvbW1hbmQuanMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjYWxsKFxuICBvbkRvbmU6IExvY2FsSlNYQ29tbWFuZE9uRG9uZSxcbiAgY29udGV4dDogTG9jYWxKU1hDb21tYW5kQ29udGV4dCxcbik6IFByb21pc2U8UmVhY3QuUmVhY3ROb2RlPiB7XG4gIHJldHVybiA8U2tpbGxzTWVudSBvbkV4aXQ9e29uRG9uZX0gY29tbWFuZHM9e2NvbnRleHQub3B0aW9ucy5jb21tYW5kc30gLz5cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLQSxLQUFLLE1BQU0sT0FBTztBQUM5QixjQUFjQyxzQkFBc0IsUUFBUSxtQkFBbUI7QUFDL0QsU0FBU0MsVUFBVSxRQUFRLHVDQUF1QztBQUNsRSxjQUFjQyxxQkFBcUIsUUFBUSx3QkFBd0I7QUFFbkUsT0FBTyxlQUFlQyxJQUFJQSxDQUN4QkMsTUFBTSxFQUFFRixxQkFBcUIsRUFDN0JHLE9BQU8sRUFBRUwsc0JBQXNCLENBQ2hDLEVBQUVNLE9BQU8sQ0FBQ1AsS0FBSyxDQUFDUSxTQUFTLENBQUMsQ0FBQztFQUMxQixPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDSCxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQ0MsT0FBTyxDQUFDRyxPQUFPLENBQUNDLFFBQVEsQ0FBQyxHQUFHO0FBQzNFIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/statusline.tsx b/_all-in-one-upload/cc-haha/src/commands/statusline.tsx new file mode 100644 index 0000000..02c7f0b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/statusline.tsx @@ -0,0 +1,24 @@ +import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'; +import type { Command } from '../commands.js'; +import { AGENT_TOOL_NAME } from '../tools/AgentTool/constants.js'; +const statusline = { + type: 'prompt', + description: "Set up Claude Code's status line UI", + contentLength: 0, + // Dynamic content + aliases: [], + name: 'statusline', + progressMessage: 'setting up statusLine', + allowedTools: [AGENT_TOOL_NAME, 'Read(~/**)', 'Edit(~/.claude/settings.json)'], + source: 'builtin', + disableNonInteractive: true, + async getPromptForCommand(args): Promise { + const prompt = args.trim() || 'Configure my statusLine from my shell PS1 configuration'; + return [{ + type: 'text', + text: `Create an ${AGENT_TOOL_NAME} with subagent_type "statusline-setup" and the prompt "${prompt}"` + }]; + } +} satisfies Command; +export default statusline; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJDb250ZW50QmxvY2tQYXJhbSIsIkNvbW1hbmQiLCJBR0VOVF9UT09MX05BTUUiLCJzdGF0dXNsaW5lIiwidHlwZSIsImRlc2NyaXB0aW9uIiwiY29udGVudExlbmd0aCIsImFsaWFzZXMiLCJuYW1lIiwicHJvZ3Jlc3NNZXNzYWdlIiwiYWxsb3dlZFRvb2xzIiwic291cmNlIiwiZGlzYWJsZU5vbkludGVyYWN0aXZlIiwiZ2V0UHJvbXB0Rm9yQ29tbWFuZCIsImFyZ3MiLCJQcm9taXNlIiwicHJvbXB0IiwidHJpbSIsInRleHQiXSwic291cmNlcyI6WyJzdGF0dXNsaW5lLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbnRlbnRCbG9ja1BhcmFtIH0gZnJvbSAnQGFudGhyb3BpYy1haS9zZGsvcmVzb3VyY2VzL2luZGV4Lm1qcydcbmltcG9ydCB0eXBlIHsgQ29tbWFuZCB9IGZyb20gJy4uL2NvbW1hbmRzLmpzJ1xuaW1wb3J0IHsgQUdFTlRfVE9PTF9OQU1FIH0gZnJvbSAnLi4vdG9vbHMvQWdlbnRUb29sL2NvbnN0YW50cy5qcydcblxuY29uc3Qgc3RhdHVzbGluZSA9IHtcbiAgdHlwZTogJ3Byb21wdCcsXG4gIGRlc2NyaXB0aW9uOiBcIlNldCB1cCBDbGF1ZGUgQ29kZSdzIHN0YXR1cyBsaW5lIFVJXCIsXG4gIGNvbnRlbnRMZW5ndGg6IDAsIC8vIER5bmFtaWMgY29udGVudFxuICBhbGlhc2VzOiBbXSxcbiAgbmFtZTogJ3N0YXR1c2xpbmUnLFxuICBwcm9ncmVzc01lc3NhZ2U6ICdzZXR0aW5nIHVwIHN0YXR1c0xpbmUnLFxuICBhbGxvd2VkVG9vbHM6IFtcbiAgICBBR0VOVF9UT09MX05BTUUsXG4gICAgJ1JlYWQofi8qKiknLFxuICAgICdFZGl0KH4vLmNsYXVkZS9zZXR0aW5ncy5qc29uKScsXG4gIF0sXG4gIHNvdXJjZTogJ2J1aWx0aW4nLFxuICBkaXNhYmxlTm9uSW50ZXJhY3RpdmU6IHRydWUsXG4gIGFzeW5jIGdldFByb21wdEZvckNvbW1hbmQoYXJncyk6IFByb21pc2U8Q29udGVudEJsb2NrUGFyYW1bXT4ge1xuICAgIGNvbnN0IHByb21wdCA9XG4gICAgICBhcmdzLnRyaW0oKSB8fCAnQ29uZmlndXJlIG15IHN0YXR1c0xpbmUgZnJvbSBteSBzaGVsbCBQUzEgY29uZmlndXJhdGlvbidcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgICAgIHRleHQ6IGBDcmVhdGUgYW4gJHtBR0VOVF9UT09MX05BTUV9IHdpdGggc3ViYWdlbnRfdHlwZSBcInN0YXR1c2xpbmUtc2V0dXBcIiBhbmQgdGhlIHByb21wdCBcIiR7cHJvbXB0fVwiYCxcbiAgICAgIH0sXG4gICAgXVxuICB9LFxufSBzYXRpc2ZpZXMgQ29tbWFuZFxuXG5leHBvcnQgZGVmYXVsdCBzdGF0dXNsaW5lXG4iXSwibWFwcGluZ3MiOiJBQUFBLGNBQWNBLGlCQUFpQixRQUFRLHVDQUF1QztBQUM5RSxjQUFjQyxPQUFPLFFBQVEsZ0JBQWdCO0FBQzdDLFNBQVNDLGVBQWUsUUFBUSxpQ0FBaUM7QUFFakUsTUFBTUMsVUFBVSxHQUFHO0VBQ2pCQyxJQUFJLEVBQUUsUUFBUTtFQUNkQyxXQUFXLEVBQUUscUNBQXFDO0VBQ2xEQyxhQUFhLEVBQUUsQ0FBQztFQUFFO0VBQ2xCQyxPQUFPLEVBQUUsRUFBRTtFQUNYQyxJQUFJLEVBQUUsWUFBWTtFQUNsQkMsZUFBZSxFQUFFLHVCQUF1QjtFQUN4Q0MsWUFBWSxFQUFFLENBQ1pSLGVBQWUsRUFDZixZQUFZLEVBQ1osK0JBQStCLENBQ2hDO0VBQ0RTLE1BQU0sRUFBRSxTQUFTO0VBQ2pCQyxxQkFBcUIsRUFBRSxJQUFJO0VBQzNCLE1BQU1DLG1CQUFtQkEsQ0FBQ0MsSUFBSSxDQUFDLEVBQUVDLE9BQU8sQ0FBQ2YsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO0lBQzVELE1BQU1nQixNQUFNLEdBQ1ZGLElBQUksQ0FBQ0csSUFBSSxDQUFDLENBQUMsSUFBSSx5REFBeUQ7SUFDMUUsT0FBTyxDQUNMO01BQ0ViLElBQUksRUFBRSxNQUFNO01BQ1pjLElBQUksRUFBRSxhQUFhaEIsZUFBZSwwREFBMERjLE1BQU07SUFDcEcsQ0FBQyxDQUNGO0VBQ0g7QUFDRixDQUFDLFdBQVdmLE9BQU87QUFFbkIsZUFBZUUsVUFBVSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/subscribe-pr.ts b/_all-in-one-upload/cc-haha/src/commands/subscribe-pr.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/subscribe-pr.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/commands/tasks/tasks.tsx b/_all-in-one-upload/cc-haha/src/commands/tasks/tasks.tsx new file mode 100644 index 0000000..1215af7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/tasks/tasks.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import type { LocalJSXCommandContext } from '../../commands.js'; +import { BackgroundTasksDialog } from '../../components/tasks/BackgroundTasksDialog.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; +export async function call(onDone: LocalJSXCommandOnDone, context: LocalJSXCommandContext): Promise { + return ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkxvY2FsSlNYQ29tbWFuZENvbnRleHQiLCJCYWNrZ3JvdW5kVGFza3NEaWFsb2ciLCJMb2NhbEpTWENvbW1hbmRPbkRvbmUiLCJjYWxsIiwib25Eb25lIiwiY29udGV4dCIsIlByb21pc2UiLCJSZWFjdE5vZGUiXSwic291cmNlcyI6WyJ0YXNrcy50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IExvY2FsSlNYQ29tbWFuZENvbnRleHQgfSBmcm9tICcuLi8uLi9jb21tYW5kcy5qcydcbmltcG9ydCB7IEJhY2tncm91bmRUYXNrc0RpYWxvZyB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvdGFza3MvQmFja2dyb3VuZFRhc2tzRGlhbG9nLmpzJ1xuaW1wb3J0IHR5cGUgeyBMb2NhbEpTWENvbW1hbmRPbkRvbmUgfSBmcm9tICcuLi8uLi90eXBlcy9jb21tYW5kLmpzJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2FsbChcbiAgb25Eb25lOiBMb2NhbEpTWENvbW1hbmRPbkRvbmUsXG4gIGNvbnRleHQ6IExvY2FsSlNYQ29tbWFuZENvbnRleHQsXG4pOiBQcm9taXNlPFJlYWN0LlJlYWN0Tm9kZT4ge1xuICByZXR1cm4gPEJhY2tncm91bmRUYXNrc0RpYWxvZyB0b29sVXNlQ29udGV4dD17Y29udGV4dH0gb25Eb25lPXtvbkRvbmV9IC8+XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsY0FBY0Msc0JBQXNCLFFBQVEsbUJBQW1CO0FBQy9ELFNBQVNDLHFCQUFxQixRQUFRLGlEQUFpRDtBQUN2RixjQUFjQyxxQkFBcUIsUUFBUSx3QkFBd0I7QUFFbkUsT0FBTyxlQUFlQyxJQUFJQSxDQUN4QkMsTUFBTSxFQUFFRixxQkFBcUIsRUFDN0JHLE9BQU8sRUFBRUwsc0JBQXNCLENBQ2hDLEVBQUVNLE9BQU8sQ0FBQ1AsS0FBSyxDQUFDUSxTQUFTLENBQUMsQ0FBQztFQUMxQixPQUFPLENBQUMscUJBQXFCLENBQUMsY0FBYyxDQUFDLENBQUNGLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDRCxNQUFNLENBQUMsR0FBRztBQUMzRSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/terminalSetup/terminalSetup.tsx b/_all-in-one-upload/cc-haha/src/commands/terminalSetup/terminalSetup.tsx new file mode 100644 index 0000000..4e7ef5e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/terminalSetup/terminalSetup.tsx @@ -0,0 +1,531 @@ +import chalk from 'chalk'; +import { randomBytes } from 'crypto'; +import { copyFile, mkdir, readFile, writeFile } from 'fs/promises'; +import { homedir, platform } from 'os'; +import { dirname, join } from 'path'; +import type { ThemeName } from 'src/utils/theme.js'; +import { pathToFileURL } from 'url'; +import { supportsHyperlinks } from '../../ink/supports-hyperlinks.js'; +import { color } from '../../ink.js'; +import { maybeMarkProjectOnboardingComplete } from '../../projectOnboardingState.js'; +import type { ToolUseContext } from '../../Tool.js'; +import type { LocalJSXCommandContext, LocalJSXCommandOnDone } from '../../types/command.js'; +import { backupTerminalPreferences, checkAndRestoreTerminalBackup, getTerminalPlistPath, markTerminalSetupComplete } from '../../utils/appleTerminalBackup.js'; +import { setupShellCompletion } from '../../utils/completionCache.js'; +import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js'; +import { env } from '../../utils/env.js'; +import { isFsInaccessible } from '../../utils/errors.js'; +import { execFileNoThrow } from '../../utils/execFileNoThrow.js'; +import { addItemToJSONCArray, safeParseJSONC } from '../../utils/json.js'; +import { logError } from '../../utils/log.js'; +import { getPlatform } from '../../utils/platform.js'; +import { jsonParse, jsonStringify } from '../../utils/slowOperations.js'; +const EOL = '\n'; + +// Terminals that natively support CSI u / Kitty keyboard protocol +const NATIVE_CSIU_TERMINALS: Record = { + ghostty: 'Ghostty', + kitty: 'Kitty', + 'iTerm.app': 'iTerm2', + WezTerm: 'WezTerm', + WarpTerminal: 'Warp' +}; + +/** + * Detect if we're running in a VSCode Remote SSH session. + * In this case, keybindings need to be installed on the LOCAL machine, + * not the remote server where Claude is running. + */ +function isVSCodeRemoteSSH(): boolean { + const askpassMain = process.env.VSCODE_GIT_ASKPASS_MAIN ?? ''; + const path = process.env.PATH ?? ''; + + // Check both env vars - VSCODE_GIT_ASKPASS_MAIN is more reliable when git extension + // is active, and PATH is a fallback. Omit path separator for Windows compatibility. + return askpassMain.includes('.vscode-server') || askpassMain.includes('.cursor-server') || askpassMain.includes('.windsurf-server') || path.includes('.vscode-server') || path.includes('.cursor-server') || path.includes('.windsurf-server'); +} +export function getNativeCSIuTerminalDisplayName(): string | null { + if (!env.terminal || !(env.terminal in NATIVE_CSIU_TERMINALS)) { + return null; + } + return NATIVE_CSIU_TERMINALS[env.terminal] ?? null; +} + +/** + * Format a file path as a clickable hyperlink. + * + * Paths containing spaces (e.g., "Application Support") are not clickable + * in most terminals - they get split at the space. OSC 8 hyperlinks solve + * this by embedding a file:// URL that the terminal can open on click, + * while displaying the clean path to the user. + * + * Unlike createHyperlink(), this doesn't apply any color styling so the + * path inherits the parent's styling (e.g., chalk.dim). + */ +function formatPathLink(filePath: string): string { + if (!supportsHyperlinks()) { + return filePath; + } + const fileUrl = pathToFileURL(filePath).href; + // OSC 8 hyperlink: \e]8;;URL\a TEXT \e]8;;\a + return `\x1b]8;;${fileUrl}\x07${filePath}\x1b]8;;\x07`; +} +export function shouldOfferTerminalSetup(): boolean { + // iTerm2, WezTerm, Ghostty, Kitty, and Warp natively support CSI u / Kitty + // keyboard protocol, which Claude Code already parses. No setup needed for + // these terminals. + return platform() === 'darwin' && env.terminal === 'Apple_Terminal' || env.terminal === 'vscode' || env.terminal === 'cursor' || env.terminal === 'windsurf' || env.terminal === 'alacritty' || env.terminal === 'zed'; +} +export async function setupTerminal(theme: ThemeName): Promise { + let result = ''; + switch (env.terminal) { + case 'Apple_Terminal': + result = await enableOptionAsMetaForTerminal(theme); + break; + case 'vscode': + result = await installBindingsForVSCodeTerminal('VSCode', theme); + break; + case 'cursor': + result = await installBindingsForVSCodeTerminal('Cursor', theme); + break; + case 'windsurf': + result = await installBindingsForVSCodeTerminal('Windsurf', theme); + break; + case 'alacritty': + result = await installBindingsForAlacritty(theme); + break; + case 'zed': + result = await installBindingsForZed(theme); + break; + case null: + break; + } + saveGlobalConfig(current => { + if (['vscode', 'cursor', 'windsurf', 'alacritty', 'zed'].includes(env.terminal ?? '')) { + if (current.shiftEnterKeyBindingInstalled === true) return current; + return { + ...current, + shiftEnterKeyBindingInstalled: true + }; + } else if (env.terminal === 'Apple_Terminal') { + if (current.optionAsMetaKeyInstalled === true) return current; + return { + ...current, + optionAsMetaKeyInstalled: true + }; + } + return current; + }); + maybeMarkProjectOnboardingComplete(); + + // Install shell completions (ant-only, since the completion command is ant-only) + if ("external" === 'ant') { + result += await setupShellCompletion(theme); + } + return result; +} +export function isShiftEnterKeyBindingInstalled(): boolean { + return getGlobalConfig().shiftEnterKeyBindingInstalled === true; +} +export function hasUsedBackslashReturn(): boolean { + return getGlobalConfig().hasUsedBackslashReturn === true; +} +export function markBackslashReturnUsed(): void { + const config = getGlobalConfig(); + if (!config.hasUsedBackslashReturn) { + saveGlobalConfig(current => ({ + ...current, + hasUsedBackslashReturn: true + })); + } +} +export async function call(onDone: LocalJSXCommandOnDone, context: ToolUseContext & LocalJSXCommandContext, _args: string): Promise { + if (env.terminal && env.terminal in NATIVE_CSIU_TERMINALS) { + const message = `Shift+Enter is natively supported in ${NATIVE_CSIU_TERMINALS[env.terminal]}. + +No configuration needed. Just use Shift+Enter to add newlines.`; + onDone(message); + return null; + } + + // Check if terminal is supported + if (!shouldOfferTerminalSetup()) { + const terminalName = env.terminal || 'your current terminal'; + const currentPlatform = getPlatform(); + + // Build platform-specific terminal suggestions + let platformTerminals = ''; + if (currentPlatform === 'macos') { + platformTerminals = ' • macOS: Apple Terminal\n'; + } else if (currentPlatform === 'windows') { + platformTerminals = ' • Windows: Windows Terminal\n'; + } + // For Linux and other platforms, we don't show native terminal options + // since they're not currently supported + + const message = `Terminal setup cannot be run from ${terminalName}. + +This command configures a convenient Shift+Enter shortcut for multi-line prompts. +${chalk.dim('Note: You can already use backslash (\\\\) + return to add newlines.')} + +To set up the shortcut (optional): +1. Exit tmux/screen temporarily +2. Run /terminal-setup directly in one of these terminals: +${platformTerminals} • IDE: VSCode, Cursor, Windsurf, Zed + • Other: Alacritty +3. Return to tmux/screen - settings will persist + +${chalk.dim('Note: iTerm2, WezTerm, Ghostty, Kitty, and Warp support Shift+Enter natively.')}`; + onDone(message); + return null; + } + const result = await setupTerminal(context.options.theme); + onDone(result); + return null; +} +type VSCodeKeybinding = { + key: string; + command: string; + args: { + text: string; + }; + when: string; +}; +async function installBindingsForVSCodeTerminal(editor: 'VSCode' | 'Cursor' | 'Windsurf' = 'VSCode', theme: ThemeName): Promise { + // Check if we're running in a VSCode Remote SSH session + // In this case, keybindings need to be installed on the LOCAL machine + if (isVSCodeRemoteSSH()) { + return `${color('warning', theme)(`Cannot install keybindings from a remote ${editor} session.`)}${EOL}${EOL}${editor} keybindings must be installed on your local machine, not the remote server.${EOL}${EOL}To install the Shift+Enter keybinding:${EOL}1. Open ${editor} on your local machine (not connected to remote)${EOL}2. Open the Command Palette (Cmd/Ctrl+Shift+P) → "Preferences: Open Keyboard Shortcuts (JSON)"${EOL}3. Add this keybinding (the file must be a JSON array):${EOL}${EOL}${chalk.dim(`[ + { + "key": "shift+enter", + "command": "workbench.action.terminal.sendSequence", + "args": { "text": "\\u001b\\r" }, + "when": "terminalFocus" + } +]`)}${EOL}`; + } + const editorDir = editor === 'VSCode' ? 'Code' : editor; + const userDirPath = join(homedir(), platform() === 'win32' ? join('AppData', 'Roaming', editorDir, 'User') : platform() === 'darwin' ? join('Library', 'Application Support', editorDir, 'User') : join('.config', editorDir, 'User')); + const keybindingsPath = join(userDirPath, 'keybindings.json'); + try { + // Ensure user directory exists (idempotent with recursive) + await mkdir(userDirPath, { + recursive: true + }); + + // Read existing keybindings file, or default to empty array if it doesn't exist + let content = '[]'; + let keybindings: VSCodeKeybinding[] = []; + let fileExists = false; + try { + content = await readFile(keybindingsPath, { + encoding: 'utf-8' + }); + fileExists = true; + keybindings = safeParseJSONC(content) as VSCodeKeybinding[] ?? []; + } catch (e: unknown) { + if (!isFsInaccessible(e)) throw e; + } + + // Backup the existing file before modifying it + if (fileExists) { + const randomSha = randomBytes(4).toString('hex'); + const backupPath = `${keybindingsPath}.${randomSha}.bak`; + try { + await copyFile(keybindingsPath, backupPath); + } catch { + return `${color('warning', theme)(`Error backing up existing ${editor} terminal keybindings. Bailing out.`)}${EOL}${chalk.dim(`See ${formatPathLink(keybindingsPath)}`)}${EOL}${chalk.dim(`Backup path: ${formatPathLink(backupPath)}`)}${EOL}`; + } + } + + // Check if keybinding already exists + const existingBinding = keybindings.find(binding => binding.key === 'shift+enter' && binding.command === 'workbench.action.terminal.sendSequence' && binding.when === 'terminalFocus'); + if (existingBinding) { + return `${color('warning', theme)(`Found existing ${editor} terminal Shift+Enter key binding. Remove it to continue.`)}${EOL}${chalk.dim(`See ${formatPathLink(keybindingsPath)}`)}${EOL}`; + } + + // Create the new keybinding + const newKeybinding: VSCodeKeybinding = { + key: 'shift+enter', + command: 'workbench.action.terminal.sendSequence', + args: { + text: '\u001b\r' + }, + when: 'terminalFocus' + }; + + // Modify the content by adding the new keybinding while preserving comments and formatting + const updatedContent = addItemToJSONCArray(content, newKeybinding); + + // Write the updated content back to the file + await writeFile(keybindingsPath, updatedContent, { + encoding: 'utf-8' + }); + return `${color('success', theme)(`Installed ${editor} terminal Shift+Enter key binding`)}${EOL}${chalk.dim(`See ${formatPathLink(keybindingsPath)}`)}${EOL}`; + } catch (error) { + logError(error); + throw new Error(`Failed to install ${editor} terminal Shift+Enter key binding`); + } +} +async function enableOptionAsMetaForProfile(profileName: string): Promise { + // First try to add the property (in case it doesn't exist) + // Quote the profile name to handle names with spaces (e.g., "Man Page", "Red Sands") + const { + code: addCode + } = await execFileNoThrow('/usr/libexec/PlistBuddy', ['-c', `Add :'Window Settings':'${profileName}':useOptionAsMetaKey bool true`, getTerminalPlistPath()]); + + // If adding fails (likely because it already exists), try setting it instead + if (addCode !== 0) { + const { + code: setCode + } = await execFileNoThrow('/usr/libexec/PlistBuddy', ['-c', `Set :'Window Settings':'${profileName}':useOptionAsMetaKey true`, getTerminalPlistPath()]); + if (setCode !== 0) { + logError(new Error(`Failed to enable Option as Meta key for Terminal.app profile: ${profileName}`)); + return false; + } + } + return true; +} +async function disableAudioBellForProfile(profileName: string): Promise { + // First try to add the property (in case it doesn't exist) + // Quote the profile name to handle names with spaces (e.g., "Man Page", "Red Sands") + const { + code: addCode + } = await execFileNoThrow('/usr/libexec/PlistBuddy', ['-c', `Add :'Window Settings':'${profileName}':Bell bool false`, getTerminalPlistPath()]); + + // If adding fails (likely because it already exists), try setting it instead + if (addCode !== 0) { + const { + code: setCode + } = await execFileNoThrow('/usr/libexec/PlistBuddy', ['-c', `Set :'Window Settings':'${profileName}':Bell false`, getTerminalPlistPath()]); + if (setCode !== 0) { + logError(new Error(`Failed to disable audio bell for Terminal.app profile: ${profileName}`)); + return false; + } + } + return true; +} + +// Enable Option as Meta key for Terminal.app +async function enableOptionAsMetaForTerminal(theme: ThemeName): Promise { + try { + // Create a backup of the current plist file + const backupPath = await backupTerminalPreferences(); + if (!backupPath) { + throw new Error('Failed to create backup of Terminal.app preferences, bailing out'); + } + + // Read the current default profile from the plist + const { + stdout: defaultProfile, + code: readCode + } = await execFileNoThrow('defaults', ['read', 'com.apple.Terminal', 'Default Window Settings']); + if (readCode !== 0 || !defaultProfile.trim()) { + throw new Error('Failed to read default Terminal.app profile'); + } + const { + stdout: startupProfile, + code: startupCode + } = await execFileNoThrow('defaults', ['read', 'com.apple.Terminal', 'Startup Window Settings']); + if (startupCode !== 0 || !startupProfile.trim()) { + throw new Error('Failed to read startup Terminal.app profile'); + } + let wasAnyProfileUpdated = false; + const defaultProfileName = defaultProfile.trim(); + const optionAsMetaEnabled = await enableOptionAsMetaForProfile(defaultProfileName); + const audioBellDisabled = await disableAudioBellForProfile(defaultProfileName); + if (optionAsMetaEnabled || audioBellDisabled) { + wasAnyProfileUpdated = true; + } + const startupProfileName = startupProfile.trim(); + + // Only proceed if the startup profile is different from the default profile + if (startupProfileName !== defaultProfileName) { + const startupOptionAsMetaEnabled = await enableOptionAsMetaForProfile(startupProfileName); + const startupAudioBellDisabled = await disableAudioBellForProfile(startupProfileName); + if (startupOptionAsMetaEnabled || startupAudioBellDisabled) { + wasAnyProfileUpdated = true; + } + } + if (!wasAnyProfileUpdated) { + throw new Error('Failed to enable Option as Meta key or disable audio bell for any Terminal.app profile'); + } + + // Flush the preferences cache + await execFileNoThrow('killall', ['cfprefsd']); + markTerminalSetupComplete(); + return `${color('success', theme)(`Configured Terminal.app settings:`)}${EOL}${color('success', theme)('- Enabled "Use Option as Meta key"')}${EOL}${color('success', theme)('- Switched to visual bell')}${EOL}${chalk.dim('Option+Enter will now enter a newline.')}${EOL}${chalk.dim('You must restart Terminal.app for changes to take effect.', theme)}${EOL}`; + } catch (error) { + logError(error); + + // Attempt to restore from backup + const restoreResult = await checkAndRestoreTerminalBackup(); + const errorMessage = 'Failed to enable Option as Meta key for Terminal.app.'; + if (restoreResult.status === 'restored') { + throw new Error(`${errorMessage} Your settings have been restored from backup.`); + } else if (restoreResult.status === 'failed') { + throw new Error(`${errorMessage} Restoring from backup failed, try manually with: defaults import com.apple.Terminal ${restoreResult.backupPath}`); + } else { + throw new Error(`${errorMessage} No backup was available to restore from.`); + } + } +} +async function installBindingsForAlacritty(theme: ThemeName): Promise { + const ALACRITTY_KEYBINDING = `[[keyboard.bindings]] +key = "Return" +mods = "Shift" +chars = "\\u001B\\r"`; + + // Get Alacritty config file paths in order of preference + const configPaths: string[] = []; + + // XDG config path (Linux and macOS) + const xdgConfigHome = process.env.XDG_CONFIG_HOME; + if (xdgConfigHome) { + configPaths.push(join(xdgConfigHome, 'alacritty', 'alacritty.toml')); + } else { + configPaths.push(join(homedir(), '.config', 'alacritty', 'alacritty.toml')); + } + + // Windows-specific path + if (platform() === 'win32') { + const appData = process.env.APPDATA; + if (appData) { + configPaths.push(join(appData, 'alacritty', 'alacritty.toml')); + } + } + + // Find existing config file by attempting to read it, or use first preferred path + let configPath: string | null = null; + let configContent = ''; + let configExists = false; + for (const path of configPaths) { + try { + configContent = await readFile(path, { + encoding: 'utf-8' + }); + configPath = path; + configExists = true; + break; + } catch (e: unknown) { + if (!isFsInaccessible(e)) throw e; + // File missing or inaccessible — try next config path + } + } + + // If no config exists, use the first path (XDG/default location) + if (!configPath) { + configPath = configPaths[0] ?? null; + } + if (!configPath) { + throw new Error('No valid config path found for Alacritty'); + } + try { + if (configExists) { + // Check if keybinding already exists (look for Shift+Return binding) + if (configContent.includes('mods = "Shift"') && configContent.includes('key = "Return"')) { + return `${color('warning', theme)('Found existing Alacritty Shift+Enter key binding. Remove it to continue.')}${EOL}${chalk.dim(`See ${formatPathLink(configPath)}`)}${EOL}`; + } + + // Create backup + const randomSha = randomBytes(4).toString('hex'); + const backupPath = `${configPath}.${randomSha}.bak`; + try { + await copyFile(configPath, backupPath); + } catch { + return `${color('warning', theme)('Error backing up existing Alacritty config. Bailing out.')}${EOL}${chalk.dim(`See ${formatPathLink(configPath)}`)}${EOL}${chalk.dim(`Backup path: ${formatPathLink(backupPath)}`)}${EOL}`; + } + } else { + // Ensure config directory exists (idempotent with recursive) + await mkdir(dirname(configPath), { + recursive: true + }); + } + + // Add the keybinding to the config + let updatedContent = configContent; + if (configContent && !configContent.endsWith('\n')) { + updatedContent += '\n'; + } + updatedContent += '\n' + ALACRITTY_KEYBINDING + '\n'; + + // Write the updated config + await writeFile(configPath, updatedContent, { + encoding: 'utf-8' + }); + return `${color('success', theme)('Installed Alacritty Shift+Enter key binding')}${EOL}${color('success', theme)('You may need to restart Alacritty for changes to take effect')}${EOL}${chalk.dim(`See ${formatPathLink(configPath)}`)}${EOL}`; + } catch (error) { + logError(error); + throw new Error('Failed to install Alacritty Shift+Enter key binding'); + } +} +async function installBindingsForZed(theme: ThemeName): Promise { + // Zed uses JSON keybindings similar to VSCode + const zedDir = join(homedir(), '.config', 'zed'); + const keymapPath = join(zedDir, 'keymap.json'); + try { + // Ensure zed directory exists (idempotent with recursive) + await mkdir(zedDir, { + recursive: true + }); + + // Read existing keymap file, or default to empty array if it doesn't exist + let keymapContent = '[]'; + let fileExists = false; + try { + keymapContent = await readFile(keymapPath, { + encoding: 'utf-8' + }); + fileExists = true; + } catch (e: unknown) { + if (!isFsInaccessible(e)) throw e; + } + if (fileExists) { + // Check if keybinding already exists + if (keymapContent.includes('shift-enter')) { + return `${color('warning', theme)('Found existing Zed Shift+Enter key binding. Remove it to continue.')}${EOL}${chalk.dim(`See ${formatPathLink(keymapPath)}`)}${EOL}`; + } + + // Create backup + const randomSha = randomBytes(4).toString('hex'); + const backupPath = `${keymapPath}.${randomSha}.bak`; + try { + await copyFile(keymapPath, backupPath); + } catch { + return `${color('warning', theme)('Error backing up existing Zed keymap. Bailing out.')}${EOL}${chalk.dim(`See ${formatPathLink(keymapPath)}`)}${EOL}${chalk.dim(`Backup path: ${formatPathLink(backupPath)}`)}${EOL}`; + } + } + + // Parse and modify the keymap + let keymap: Array<{ + context?: string; + bindings: Record; + }>; + try { + keymap = jsonParse(keymapContent); + if (!Array.isArray(keymap)) { + keymap = []; + } + } catch { + keymap = []; + } + + // Add the new keybinding for terminal context + keymap.push({ + context: 'Terminal', + bindings: { + 'shift-enter': ['terminal::SendText', '\u001b\r'] + } + }); + + // Write the updated keymap + await writeFile(keymapPath, jsonStringify(keymap, null, 2) + '\n', { + encoding: 'utf-8' + }); + return `${color('success', theme)('Installed Zed Shift+Enter key binding')}${EOL}${chalk.dim(`See ${formatPathLink(keymapPath)}`)}${EOL}`; + } catch (error) { + logError(error); + throw new Error('Failed to install Zed Shift+Enter key binding'); + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjaGFsayIsInJhbmRvbUJ5dGVzIiwiY29weUZpbGUiLCJta2RpciIsInJlYWRGaWxlIiwid3JpdGVGaWxlIiwiaG9tZWRpciIsInBsYXRmb3JtIiwiZGlybmFtZSIsImpvaW4iLCJUaGVtZU5hbWUiLCJwYXRoVG9GaWxlVVJMIiwic3VwcG9ydHNIeXBlcmxpbmtzIiwiY29sb3IiLCJtYXliZU1hcmtQcm9qZWN0T25ib2FyZGluZ0NvbXBsZXRlIiwiVG9vbFVzZUNvbnRleHQiLCJMb2NhbEpTWENvbW1hbmRDb250ZXh0IiwiTG9jYWxKU1hDb21tYW5kT25Eb25lIiwiYmFja3VwVGVybWluYWxQcmVmZXJlbmNlcyIsImNoZWNrQW5kUmVzdG9yZVRlcm1pbmFsQmFja3VwIiwiZ2V0VGVybWluYWxQbGlzdFBhdGgiLCJtYXJrVGVybWluYWxTZXR1cENvbXBsZXRlIiwic2V0dXBTaGVsbENvbXBsZXRpb24iLCJnZXRHbG9iYWxDb25maWciLCJzYXZlR2xvYmFsQ29uZmlnIiwiZW52IiwiaXNGc0luYWNjZXNzaWJsZSIsImV4ZWNGaWxlTm9UaHJvdyIsImFkZEl0ZW1Ub0pTT05DQXJyYXkiLCJzYWZlUGFyc2VKU09OQyIsImxvZ0Vycm9yIiwiZ2V0UGxhdGZvcm0iLCJqc29uUGFyc2UiLCJqc29uU3RyaW5naWZ5IiwiRU9MIiwiTkFUSVZFX0NTSVVfVEVSTUlOQUxTIiwiUmVjb3JkIiwiZ2hvc3R0eSIsImtpdHR5IiwiV2V6VGVybSIsIldhcnBUZXJtaW5hbCIsImlzVlNDb2RlUmVtb3RlU1NIIiwiYXNrcGFzc01haW4iLCJwcm9jZXNzIiwiVlNDT0RFX0dJVF9BU0tQQVNTX01BSU4iLCJwYXRoIiwiUEFUSCIsImluY2x1ZGVzIiwiZ2V0TmF0aXZlQ1NJdVRlcm1pbmFsRGlzcGxheU5hbWUiLCJ0ZXJtaW5hbCIsImZvcm1hdFBhdGhMaW5rIiwiZmlsZVBhdGgiLCJmaWxlVXJsIiwiaHJlZiIsInNob3VsZE9mZmVyVGVybWluYWxTZXR1cCIsInNldHVwVGVybWluYWwiLCJ0aGVtZSIsIlByb21pc2UiLCJyZXN1bHQiLCJlbmFibGVPcHRpb25Bc01ldGFGb3JUZXJtaW5hbCIsImluc3RhbGxCaW5kaW5nc0ZvclZTQ29kZVRlcm1pbmFsIiwiaW5zdGFsbEJpbmRpbmdzRm9yQWxhY3JpdHR5IiwiaW5zdGFsbEJpbmRpbmdzRm9yWmVkIiwiY3VycmVudCIsInNoaWZ0RW50ZXJLZXlCaW5kaW5nSW5zdGFsbGVkIiwib3B0aW9uQXNNZXRhS2V5SW5zdGFsbGVkIiwiaXNTaGlmdEVudGVyS2V5QmluZGluZ0luc3RhbGxlZCIsImhhc1VzZWRCYWNrc2xhc2hSZXR1cm4iLCJtYXJrQmFja3NsYXNoUmV0dXJuVXNlZCIsImNvbmZpZyIsImNhbGwiLCJvbkRvbmUiLCJjb250ZXh0IiwiX2FyZ3MiLCJtZXNzYWdlIiwidGVybWluYWxOYW1lIiwiY3VycmVudFBsYXRmb3JtIiwicGxhdGZvcm1UZXJtaW5hbHMiLCJkaW0iLCJvcHRpb25zIiwiVlNDb2RlS2V5YmluZGluZyIsImtleSIsImNvbW1hbmQiLCJhcmdzIiwidGV4dCIsIndoZW4iLCJlZGl0b3IiLCJlZGl0b3JEaXIiLCJ1c2VyRGlyUGF0aCIsImtleWJpbmRpbmdzUGF0aCIsInJlY3Vyc2l2ZSIsImNvbnRlbnQiLCJrZXliaW5kaW5ncyIsImZpbGVFeGlzdHMiLCJlbmNvZGluZyIsImUiLCJyYW5kb21TaGEiLCJ0b1N0cmluZyIsImJhY2t1cFBhdGgiLCJleGlzdGluZ0JpbmRpbmciLCJmaW5kIiwiYmluZGluZyIsIm5ld0tleWJpbmRpbmciLCJ1cGRhdGVkQ29udGVudCIsImVycm9yIiwiRXJyb3IiLCJlbmFibGVPcHRpb25Bc01ldGFGb3JQcm9maWxlIiwicHJvZmlsZU5hbWUiLCJjb2RlIiwiYWRkQ29kZSIsInNldENvZGUiLCJkaXNhYmxlQXVkaW9CZWxsRm9yUHJvZmlsZSIsInN0ZG91dCIsImRlZmF1bHRQcm9maWxlIiwicmVhZENvZGUiLCJ0cmltIiwic3RhcnR1cFByb2ZpbGUiLCJzdGFydHVwQ29kZSIsIndhc0FueVByb2ZpbGVVcGRhdGVkIiwiZGVmYXVsdFByb2ZpbGVOYW1lIiwib3B0aW9uQXNNZXRhRW5hYmxlZCIsImF1ZGlvQmVsbERpc2FibGVkIiwic3RhcnR1cFByb2ZpbGVOYW1lIiwic3RhcnR1cE9wdGlvbkFzTWV0YUVuYWJsZWQiLCJzdGFydHVwQXVkaW9CZWxsRGlzYWJsZWQiLCJyZXN0b3JlUmVzdWx0IiwiZXJyb3JNZXNzYWdlIiwic3RhdHVzIiwiQUxBQ1JJVFRZX0tFWUJJTkRJTkciLCJjb25maWdQYXRocyIsInhkZ0NvbmZpZ0hvbWUiLCJYREdfQ09ORklHX0hPTUUiLCJwdXNoIiwiYXBwRGF0YSIsIkFQUERBVEEiLCJjb25maWdQYXRoIiwiY29uZmlnQ29udGVudCIsImNvbmZpZ0V4aXN0cyIsImVuZHNXaXRoIiwiemVkRGlyIiwia2V5bWFwUGF0aCIsImtleW1hcENvbnRlbnQiLCJrZXltYXAiLCJBcnJheSIsImJpbmRpbmdzIiwiaXNBcnJheSJdLCJzb3VyY2VzIjpbInRlcm1pbmFsU2V0dXAudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjaGFsayBmcm9tICdjaGFsaydcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0IHsgY29weUZpbGUsIG1rZGlyLCByZWFkRmlsZSwgd3JpdGVGaWxlIH0gZnJvbSAnZnMvcHJvbWlzZXMnXG5pbXBvcnQgeyBob21lZGlyLCBwbGF0Zm9ybSB9IGZyb20gJ29zJ1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiB9IGZyb20gJ3BhdGgnXG5pbXBvcnQgdHlwZSB7IFRoZW1lTmFtZSB9IGZyb20gJ3NyYy91dGlscy90aGVtZS5qcydcbmltcG9ydCB7IHBhdGhUb0ZpbGVVUkwgfSBmcm9tICd1cmwnXG5pbXBvcnQgeyBzdXBwb3J0c0h5cGVybGlua3MgfSBmcm9tICcuLi8uLi9pbmsvc3VwcG9ydHMtaHlwZXJsaW5rcy5qcydcbmltcG9ydCB7IGNvbG9yIH0gZnJvbSAnLi4vLi4vaW5rLmpzJ1xuaW1wb3J0IHsgbWF5YmVNYXJrUHJvamVjdE9uYm9hcmRpbmdDb21wbGV0ZSB9IGZyb20gJy4uLy4uL3Byb2plY3RPbmJvYXJkaW5nU3RhdGUuanMnXG5pbXBvcnQgdHlwZSB7IFRvb2xVc2VDb250ZXh0IH0gZnJvbSAnLi4vLi4vVG9vbC5qcydcbmltcG9ydCB0eXBlIHtcbiAgTG9jYWxKU1hDb21tYW5kQ29udGV4dCxcbiAgTG9jYWxKU1hDb21tYW5kT25Eb25lLFxufSBmcm9tICcuLi8uLi90eXBlcy9jb21tYW5kLmpzJ1xuaW1wb3J0IHtcbiAgYmFja3VwVGVybWluYWxQcmVmZXJlbmNlcyxcbiAgY2hlY2tBbmRSZXN0b3JlVGVybWluYWxCYWNrdXAsXG4gIGdldFRlcm1pbmFsUGxpc3RQYXRoLFxuICBtYXJrVGVybWluYWxTZXR1cENvbXBsZXRlLFxufSBmcm9tICcuLi8uLi91dGlscy9hcHBsZVRlcm1pbmFsQmFja3VwLmpzJ1xuaW1wb3J0IHsgc2V0dXBTaGVsbENvbXBsZXRpb24gfSBmcm9tICcuLi8uLi91dGlscy9jb21wbGV0aW9uQ2FjaGUuanMnXG5pbXBvcnQgeyBnZXRHbG9iYWxDb25maWcsIHNhdmVHbG9iYWxDb25maWcgfSBmcm9tICcuLi8uLi91dGlscy9jb25maWcuanMnXG5pbXBvcnQgeyBlbnYgfSBmcm9tICcuLi8uLi91dGlscy9lbnYuanMnXG5pbXBvcnQgeyBpc0ZzSW5hY2Nlc3NpYmxlIH0gZnJvbSAnLi4vLi4vdXRpbHMvZXJyb3JzLmpzJ1xuaW1wb3J0IHsgZXhlY0ZpbGVOb1Rocm93IH0gZnJvbSAnLi4vLi4vdXRpbHMvZXhlY0ZpbGVOb1Rocm93LmpzJ1xuaW1wb3J0IHsgYWRkSXRlbVRvSlNPTkNBcnJheSwgc2FmZVBhcnNlSlNPTkMgfSBmcm9tICcuLi8uLi91dGlscy9qc29uLmpzJ1xuaW1wb3J0IHsgbG9nRXJyb3IgfSBmcm9tICcuLi8uLi91dGlscy9sb2cuanMnXG5pbXBvcnQgeyBnZXRQbGF0Zm9ybSB9IGZyb20gJy4uLy4uL3V0aWxzL3BsYXRmb3JtLmpzJ1xuaW1wb3J0IHsganNvblBhcnNlLCBqc29uU3RyaW5naWZ5IH0gZnJvbSAnLi4vLi4vdXRpbHMvc2xvd09wZXJhdGlvbnMuanMnXG5cbmNvbnN0IEVPTCA9ICdcXG4nXG5cbi8vIFRlcm1pbmFscyB0aGF0IG5hdGl2ZWx5IHN1cHBvcnQgQ1NJIHUgLyBLaXR0eSBrZXlib2FyZCBwcm90b2NvbFxuY29uc3QgTkFUSVZFX0NTSVVfVEVSTUlOQUxTOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBnaG9zdHR5OiAnR2hvc3R0eScsXG4gIGtpdHR5OiAnS2l0dHknLFxuICAnaVRlcm0uYXBwJzogJ2lUZXJtMicsXG4gIFdlelRlcm06ICdXZXpUZXJtJyxcbiAgV2FycFRlcm1pbmFsOiAnV2FycCcsXG59XG5cbi8qKlxuICogRGV0ZWN0IGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSBWU0NvZGUgUmVtb3RlIFNTSCBzZXNzaW9uLlxuICogSW4gdGhpcyBjYXNlLCBrZXliaW5kaW5ncyBuZWVkIHRvIGJlIGluc3RhbGxlZCBvbiB0aGUgTE9DQUwgbWFjaGluZSxcbiAqIG5vdCB0aGUgcmVtb3RlIHNlcnZlciB3aGVyZSBDbGF1ZGUgaXMgcnVubmluZy5cbiAqL1xuZnVuY3Rpb24gaXNWU0NvZGVSZW1vdGVTU0goKTogYm9vbGVhbiB7XG4gIGNvbnN0IGFza3Bhc3NNYWluID0gcHJvY2Vzcy5lbnYuVlNDT0RFX0dJVF9BU0tQQVNTX01BSU4gPz8gJydcbiAgY29uc3QgcGF0aCA9IHByb2Nlc3MuZW52LlBBVEggPz8gJydcblxuICAvLyBDaGVjayBib3RoIGVudiB2YXJzIC0gVlNDT0RFX0dJVF9BU0tQQVNTX01BSU4gaXMgbW9yZSByZWxpYWJsZSB3aGVuIGdpdCBleHRlbnNpb25cbiAgLy8gaXMgYWN0aXZlLCBhbmQgUEFUSCBpcyBhIGZhbGxiYWNrLiBPbWl0IHBhdGggc2VwYXJhdG9yIGZvciBXaW5kb3dzIGNvbXBhdGliaWxpdHkuXG4gIHJldHVybiAoXG4gICAgYXNrcGFzc01haW4uaW5jbHVkZXMoJy52c2NvZGUtc2VydmVyJykgfHxcbiAgICBhc2twYXNzTWFpbi5pbmNsdWRlcygnLmN1cnNvci1zZXJ2ZXInKSB8fFxuICAgIGFza3Bhc3NNYWluLmluY2x1ZGVzKCcud2luZHN1cmYtc2VydmVyJykgfHxcbiAgICBwYXRoLmluY2x1ZGVzKCcudnNjb2RlLXNlcnZlcicpIHx8XG4gICAgcGF0aC5pbmNsdWRlcygnLmN1cnNvci1zZXJ2ZXInKSB8fFxuICAgIHBhdGguaW5jbHVkZXMoJy53aW5kc3VyZi1zZXJ2ZXInKVxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXROYXRpdmVDU0l1VGVybWluYWxEaXNwbGF5TmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKCFlbnYudGVybWluYWwgfHwgIShlbnYudGVybWluYWwgaW4gTkFUSVZFX0NTSVVfVEVSTUlOQUxTKSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgcmV0dXJuIE5BVElWRV9DU0lVX1RFUk1JTkFMU1tlbnYudGVybWluYWxdID8/IG51bGxcbn1cblxuLyoqXG4gKiBGb3JtYXQgYSBmaWxlIHBhdGggYXMgYSBjbGlja2FibGUgaHlwZXJsaW5rLlxuICpcbiAqIFBhdGhzIGNvbnRhaW5pbmcgc3BhY2VzIChlLmcuLCBcIkFwcGxpY2F0aW9uIFN1cHBvcnRcIikgYXJlIG5vdCBjbGlja2FibGVcbiAqIGluIG1vc3QgdGVybWluYWxzIC0gdGhleSBnZXQgc3BsaXQgYXQgdGhlIHNwYWNlLiBPU0MgOCBoeXBlcmxpbmtzIHNvbHZlXG4gKiB0aGlzIGJ5IGVtYmVkZGluZyBhIGZpbGU6Ly8gVVJMIHRoYXQgdGhlIHRlcm1pbmFsIGNhbiBvcGVuIG9uIGNsaWNrLFxuICogd2hpbGUgZGlzcGxheWluZyB0aGUgY2xlYW4gcGF0aCB0byB0aGUgdXNlci5cbiAqXG4gKiBVbmxpa2UgY3JlYXRlSHlwZXJsaW5rKCksIHRoaXMgZG9lc24ndCBhcHBseSBhbnkgY29sb3Igc3R5bGluZyBzbyB0aGVcbiAqIHBhdGggaW5oZXJpdHMgdGhlIHBhcmVudCdzIHN0eWxpbmcgKGUuZy4sIGNoYWxrLmRpbSkuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdFBhdGhMaW5rKGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIXN1cHBvcnRzSHlwZXJsaW5rcygpKSB7XG4gICAgcmV0dXJuIGZpbGVQYXRoXG4gIH1cbiAgY29uc3QgZmlsZVVybCA9IHBhdGhUb0ZpbGVVUkwoZmlsZVBhdGgpLmhyZWZcbiAgLy8gT1NDIDggaHlwZXJsaW5rOiBcXGVdODs7VVJMXFxhIFRFWFQgXFxlXTg7O1xcYVxuICByZXR1cm4gYFxceDFiXTg7OyR7ZmlsZVVybH1cXHgwNyR7ZmlsZVBhdGh9XFx4MWJdODs7XFx4MDdgXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaG91bGRPZmZlclRlcm1pbmFsU2V0dXAoKTogYm9vbGVhbiB7XG4gIC8vIGlUZXJtMiwgV2V6VGVybSwgR2hvc3R0eSwgS2l0dHksIGFuZCBXYXJwIG5hdGl2ZWx5IHN1cHBvcnQgQ1NJIHUgLyBLaXR0eVxuICAvLyBrZXlib2FyZCBwcm90b2NvbCwgd2hpY2ggQ2xhdWRlIENvZGUgYWxyZWFkeSBwYXJzZXMuIE5vIHNldHVwIG5lZWRlZCBmb3JcbiAgLy8gdGhlc2UgdGVybWluYWxzLlxuICByZXR1cm4gKFxuICAgIChwbGF0Zm9ybSgpID09PSAnZGFyd2luJyAmJiBlbnYudGVybWluYWwgPT09ICdBcHBsZV9UZXJtaW5hbCcpIHx8XG4gICAgZW52LnRlcm1pbmFsID09PSAndnNjb2RlJyB8fFxuICAgIGVudi50ZXJtaW5hbCA9PT0gJ2N1cnNvcicgfHxcbiAgICBlbnYudGVybWluYWwgPT09ICd3aW5kc3VyZicgfHxcbiAgICBlbnYudGVybWluYWwgPT09ICdhbGFjcml0dHknIHx8XG4gICAgZW52LnRlcm1pbmFsID09PSAnemVkJ1xuICApXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXR1cFRlcm1pbmFsKHRoZW1lOiBUaGVtZU5hbWUpOiBQcm9taXNlPHN0cmluZz4ge1xuICBsZXQgcmVzdWx0ID0gJydcblxuICBzd2l0Y2ggKGVudi50ZXJtaW5hbCkge1xuICAgIGNhc2UgJ0FwcGxlX1Rlcm1pbmFsJzpcbiAgICAgIHJlc3VsdCA9IGF3YWl0IGVuYWJsZU9wdGlvbkFzTWV0YUZvclRlcm1pbmFsKHRoZW1lKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd2c2NvZGUnOlxuICAgICAgcmVzdWx0ID0gYXdhaXQgaW5zdGFsbEJpbmRpbmdzRm9yVlNDb2RlVGVybWluYWwoJ1ZTQ29kZScsIHRoZW1lKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdjdXJzb3InOlxuICAgICAgcmVzdWx0ID0gYXdhaXQgaW5zdGFsbEJpbmRpbmdzRm9yVlNDb2RlVGVybWluYWwoJ0N1cnNvcicsIHRoZW1lKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd3aW5kc3VyZic6XG4gICAgICByZXN1bHQgPSBhd2FpdCBpbnN0YWxsQmluZGluZ3NGb3JWU0NvZGVUZXJtaW5hbCgnV2luZHN1cmYnLCB0aGVtZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYWxhY3JpdHR5JzpcbiAgICAgIHJlc3VsdCA9IGF3YWl0IGluc3RhbGxCaW5kaW5nc0ZvckFsYWNyaXR0eSh0aGVtZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnemVkJzpcbiAgICAgIHJlc3VsdCA9IGF3YWl0IGluc3RhbGxCaW5kaW5nc0ZvclplZCh0aGVtZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBudWxsOlxuICAgICAgYnJlYWtcbiAgfVxuXG4gIHNhdmVHbG9iYWxDb25maWcoY3VycmVudCA9PiB7XG4gICAgaWYgKFxuICAgICAgWyd2c2NvZGUnLCAnY3Vyc29yJywgJ3dpbmRzdXJmJywgJ2FsYWNyaXR0eScsICd6ZWQnXS5pbmNsdWRlcyhcbiAgICAgICAgZW52LnRlcm1pbmFsID8/ICcnLFxuICAgICAgKVxuICAgICkge1xuICAgICAgaWYgKGN1cnJlbnQuc2hpZnRFbnRlcktleUJpbmRpbmdJbnN0YWxsZWQgPT09IHRydWUpIHJldHVybiBjdXJyZW50XG4gICAgICByZXR1cm4geyAuLi5jdXJyZW50LCBzaGlmdEVudGVyS2V5QmluZGluZ0luc3RhbGxlZDogdHJ1ZSB9XG4gICAgfSBlbHNlIGlmIChlbnYudGVybWluYWwgPT09ICdBcHBsZV9UZXJtaW5hbCcpIHtcbiAgICAgIGlmIChjdXJyZW50Lm9wdGlvbkFzTWV0YUtleUluc3RhbGxlZCA9PT0gdHJ1ZSkgcmV0dXJuIGN1cnJlbnRcbiAgICAgIHJldHVybiB7IC4uLmN1cnJlbnQsIG9wdGlvbkFzTWV0YUtleUluc3RhbGxlZDogdHJ1ZSB9XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50XG4gIH0pXG5cbiAgbWF5YmVNYXJrUHJvamVjdE9uYm9hcmRpbmdDb21wbGV0ZSgpXG5cbiAgLy8gSW5zdGFsbCBzaGVsbCBjb21wbGV0aW9ucyAoYW50LW9ubHksIHNpbmNlIHRoZSBjb21wbGV0aW9uIGNvbW1hbmQgaXMgYW50LW9ubHkpXG4gIGlmIChcImV4dGVybmFsXCIgPT09ICdhbnQnKSB7XG4gICAgcmVzdWx0ICs9IGF3YWl0IHNldHVwU2hlbGxDb21wbGV0aW9uKHRoZW1lKVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTaGlmdEVudGVyS2V5QmluZGluZ0luc3RhbGxlZCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldEdsb2JhbENvbmZpZygpLnNoaWZ0RW50ZXJLZXlCaW5kaW5nSW5zdGFsbGVkID09PSB0cnVlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNVc2VkQmFja3NsYXNoUmV0dXJuKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0R2xvYmFsQ29uZmlnKCkuaGFzVXNlZEJhY2tzbGFzaFJldHVybiA9PT0gdHJ1ZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFya0JhY2tzbGFzaFJldHVyblVzZWQoKTogdm9pZCB7XG4gIGNvbnN0IGNvbmZpZyA9IGdldEdsb2JhbENvbmZpZygpXG4gIGlmICghY29uZmlnLmhhc1VzZWRCYWNrc2xhc2hSZXR1cm4pIHtcbiAgICBzYXZlR2xvYmFsQ29uZmlnKGN1cnJlbnQgPT4gKHtcbiAgICAgIC4uLmN1cnJlbnQsXG4gICAgICBoYXNVc2VkQmFja3NsYXNoUmV0dXJuOiB0cnVlLFxuICAgIH0pKVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjYWxsKFxuICBvbkRvbmU6IExvY2FsSlNYQ29tbWFuZE9uRG9uZSxcbiAgY29udGV4dDogVG9vbFVzZUNvbnRleHQgJiBMb2NhbEpTWENvbW1hbmRDb250ZXh0LFxuICBfYXJnczogc3RyaW5nLFxuKTogUHJvbWlzZTxudWxsPiB7XG4gIGlmIChlbnYudGVybWluYWwgJiYgZW52LnRlcm1pbmFsIGluIE5BVElWRV9DU0lVX1RFUk1JTkFMUykge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBgU2hpZnQrRW50ZXIgaXMgbmF0aXZlbHkgc3VwcG9ydGVkIGluICR7TkFUSVZFX0NTSVVfVEVSTUlOQUxTW2Vudi50ZXJtaW5hbF19LlxuXG5ObyBjb25maWd1cmF0aW9uIG5lZWRlZC4gSnVzdCB1c2UgU2hpZnQrRW50ZXIgdG8gYWRkIG5ld2xpbmVzLmBcbiAgICBvbkRvbmUobWVzc2FnZSlcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgLy8gQ2hlY2sgaWYgdGVybWluYWwgaXMgc3VwcG9ydGVkXG4gIGlmICghc2hvdWxkT2ZmZXJUZXJtaW5hbFNldHVwKCkpIHtcbiAgICBjb25zdCB0ZXJtaW5hbE5hbWUgPSBlbnYudGVybWluYWwgfHwgJ3lvdXIgY3VycmVudCB0ZXJtaW5hbCdcbiAgICBjb25zdCBjdXJyZW50UGxhdGZvcm0gPSBnZXRQbGF0Zm9ybSgpXG5cbiAgICAvLyBCdWlsZCBwbGF0Zm9ybS1zcGVjaWZpYyB0ZXJtaW5hbCBzdWdnZXN0aW9uc1xuICAgIGxldCBwbGF0Zm9ybVRlcm1pbmFscyA9ICcnXG4gICAgaWYgKGN1cnJlbnRQbGF0Zm9ybSA9PT0gJ21hY29zJykge1xuICAgICAgcGxhdGZvcm1UZXJtaW5hbHMgPSAnICAg4oCiIG1hY09TOiBBcHBsZSBUZXJtaW5hbFxcbidcbiAgICB9IGVsc2UgaWYgKGN1cnJlbnRQbGF0Zm9ybSA9PT0gJ3dpbmRvd3MnKSB7XG4gICAgICBwbGF0Zm9ybVRlcm1pbmFscyA9ICcgICDigKIgV2luZG93czogV2luZG93cyBUZXJtaW5hbFxcbidcbiAgICB9XG4gICAgLy8gRm9yIExpbnV4IGFuZCBvdGhlciBwbGF0Zm9ybXMsIHdlIGRvbid0IHNob3cgbmF0aXZlIHRlcm1pbmFsIG9wdGlvbnNcbiAgICAvLyBzaW5jZSB0aGV5J3JlIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkXG5cbiAgICBjb25zdCBtZXNzYWdlID0gYFRlcm1pbmFsIHNldHVwIGNhbm5vdCBiZSBydW4gZnJvbSAke3Rlcm1pbmFsTmFtZX0uXG5cblRoaXMgY29tbWFuZCBjb25maWd1cmVzIGEgY29udmVuaWVudCBTaGlmdCtFbnRlciBzaG9ydGN1dCBmb3IgbXVsdGktbGluZSBwcm9tcHRzLlxuJHtjaGFsay5kaW0oJ05vdGU6IFlvdSBjYW4gYWxyZWFkeSB1c2UgYmFja3NsYXNoIChcXFxcXFxcXCkgKyByZXR1cm4gdG8gYWRkIG5ld2xpbmVzLicpfVxuXG5UbyBzZXQgdXAgdGhlIHNob3J0Y3V0IChvcHRpb25hbCk6XG4xLiBFeGl0IHRtdXgvc2NyZWVuIHRlbXBvcmFyaWx5XG4yLiBSdW4gL3Rlcm1pbmFsLXNldHVwIGRpcmVjdGx5IGluIG9uZSBvZiB0aGVzZSB0ZXJtaW5hbHM6XG4ke3BsYXRmb3JtVGVybWluYWxzfSAgIOKAoiBJREU6IFZTQ29kZSwgQ3Vyc29yLCBXaW5kc3VyZiwgWmVkXG4gICDigKIgT3RoZXI6IEFsYWNyaXR0eVxuMy4gUmV0dXJuIHRvIHRtdXgvc2NyZWVuIC0gc2V0dGluZ3Mgd2lsbCBwZXJzaXN0XG5cbiR7Y2hhbGsuZGltKCdOb3RlOiBpVGVybTIsIFdlelRlcm0sIEdob3N0dHksIEtpdHR5LCBhbmQgV2FycCBzdXBwb3J0IFNoaWZ0K0VudGVyIG5hdGl2ZWx5LicpfWBcbiAgICBvbkRvbmUobWVzc2FnZSlcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2V0dXBUZXJtaW5hbChjb250ZXh0Lm9wdGlvbnMudGhlbWUpXG4gIG9uRG9uZShyZXN1bHQpXG4gIHJldHVybiBudWxsXG59XG5cbnR5cGUgVlNDb2RlS2V5YmluZGluZyA9IHtcbiAga2V5OiBzdHJpbmdcbiAgY29tbWFuZDogc3RyaW5nXG4gIGFyZ3M6IHsgdGV4dDogc3RyaW5nIH1cbiAgd2hlbjogc3RyaW5nXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxCaW5kaW5nc0ZvclZTQ29kZVRlcm1pbmFsKFxuICBlZGl0b3I6ICdWU0NvZGUnIHwgJ0N1cnNvcicgfCAnV2luZHN1cmYnID0gJ1ZTQ29kZScsXG4gIHRoZW1lOiBUaGVtZU5hbWUsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICAvLyBDaGVjayBpZiB3ZSdyZSBydW5uaW5nIGluIGEgVlNDb2RlIFJlbW90ZSBTU0ggc2Vzc2lvblxuICAvLyBJbiB0aGlzIGNhc2UsIGtleWJpbmRpbmdzIG5lZWQgdG8gYmUgaW5zdGFsbGVkIG9uIHRoZSBMT0NBTCBtYWNoaW5lXG4gIGlmIChpc1ZTQ29kZVJlbW90ZVNTSCgpKSB7XG4gICAgcmV0dXJuIGAke2NvbG9yKFxuICAgICAgJ3dhcm5pbmcnLFxuICAgICAgdGhlbWUsXG4gICAgKShcbiAgICAgIGBDYW5ub3QgaW5zdGFsbCBrZXliaW5kaW5ncyBmcm9tIGEgcmVtb3RlICR7ZWRpdG9yfSBzZXNzaW9uLmAsXG4gICAgKX0ke0VPTH0ke0VPTH0ke2VkaXRvcn0ga2V5YmluZGluZ3MgbXVzdCBiZSBpbnN0YWxsZWQgb24geW91ciBsb2NhbCBtYWNoaW5lLCBub3QgdGhlIHJlbW90ZSBzZXJ2ZXIuJHtFT0x9JHtFT0x9VG8gaW5zdGFsbCB0aGUgU2hpZnQrRW50ZXIga2V5YmluZGluZzoke0VPTH0xLiBPcGVuICR7ZWRpdG9yfSBvbiB5b3VyIGxvY2FsIG1hY2hpbmUgKG5vdCBjb25uZWN0ZWQgdG8gcmVtb3RlKSR7RU9MfTIuIE9wZW4gdGhlIENvbW1hbmQgUGFsZXR0ZSAoQ21kL0N0cmwrU2hpZnQrUCkg4oaSIFwiUHJlZmVyZW5jZXM6IE9wZW4gS2V5Ym9hcmQgU2hvcnRjdXRzIChKU09OKVwiJHtFT0x9My4gQWRkIHRoaXMga2V5YmluZGluZyAodGhlIGZpbGUgbXVzdCBiZSBhIEpTT04gYXJyYXkpOiR7RU9MfSR7RU9MfSR7Y2hhbGsuZGltKGBbXG4gIHtcbiAgICBcImtleVwiOiBcInNoaWZ0K2VudGVyXCIsXG4gICAgXCJjb21tYW5kXCI6IFwid29ya2JlbmNoLmFjdGlvbi50ZXJtaW5hbC5zZW5kU2VxdWVuY2VcIixcbiAgICBcImFyZ3NcIjogeyBcInRleHRcIjogXCJcXFxcdTAwMWJcXFxcclwiIH0sXG4gICAgXCJ3aGVuXCI6IFwidGVybWluYWxGb2N1c1wiXG4gIH1cbl1gKX0ke0VPTH1gXG4gIH1cblxuICBjb25zdCBlZGl0b3JEaXIgPSBlZGl0b3IgPT09ICdWU0NvZGUnID8gJ0NvZGUnIDogZWRpdG9yXG4gIGNvbnN0IHVzZXJEaXJQYXRoID0gam9pbihcbiAgICBob21lZGlyKCksXG4gICAgcGxhdGZvcm0oKSA9PT0gJ3dpbjMyJ1xuICAgICAgPyBqb2luKCdBcHBEYXRhJywgJ1JvYW1pbmcnLCBlZGl0b3JEaXIsICdVc2VyJylcbiAgICAgIDogcGxhdGZvcm0oKSA9PT0gJ2RhcndpbidcbiAgICAgICAgPyBqb2luKCdMaWJyYXJ5JywgJ0FwcGxpY2F0aW9uIFN1cHBvcnQnLCBlZGl0b3JEaXIsICdVc2VyJylcbiAgICAgICAgOiBqb2luKCcuY29uZmlnJywgZWRpdG9yRGlyLCAnVXNlcicpLFxuICApXG4gIGNvbnN0IGtleWJpbmRpbmdzUGF0aCA9IGpvaW4odXNlckRpclBhdGgsICdrZXliaW5kaW5ncy5qc29uJylcblxuICB0cnkge1xuICAgIC8vIEVuc3VyZSB1c2VyIGRpcmVjdG9yeSBleGlzdHMgKGlkZW1wb3RlbnQgd2l0aCByZWN1cnNpdmUpXG4gICAgYXdhaXQgbWtkaXIodXNlckRpclBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAvLyBSZWFkIGV4aXN0aW5nIGtleWJpbmRpbmdzIGZpbGUsIG9yIGRlZmF1bHQgdG8gZW1wdHkgYXJyYXkgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgIGxldCBjb250ZW50ID0gJ1tdJ1xuICAgIGxldCBrZXliaW5kaW5nczogVlNDb2RlS2V5YmluZGluZ1tdID0gW11cbiAgICBsZXQgZmlsZUV4aXN0cyA9IGZhbHNlXG4gICAgdHJ5IHtcbiAgICAgIGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShrZXliaW5kaW5nc1BhdGgsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSlcbiAgICAgIGZpbGVFeGlzdHMgPSB0cnVlXG4gICAgICBrZXliaW5kaW5ncyA9IChzYWZlUGFyc2VKU09OQyhjb250ZW50KSBhcyBWU0NvZGVLZXliaW5kaW5nW10pID8/IFtdXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKCFpc0ZzSW5hY2Nlc3NpYmxlKGUpKSB0aHJvdyBlXG4gICAgfVxuXG4gICAgLy8gQmFja3VwIHRoZSBleGlzdGluZyBmaWxlIGJlZm9yZSBtb2RpZnlpbmcgaXRcbiAgICBpZiAoZmlsZUV4aXN0cykge1xuICAgICAgY29uc3QgcmFuZG9tU2hhID0gcmFuZG9tQnl0ZXMoNCkudG9TdHJpbmcoJ2hleCcpXG4gICAgICBjb25zdCBiYWNrdXBQYXRoID0gYCR7a2V5YmluZGluZ3NQYXRofS4ke3JhbmRvbVNoYX0uYmFrYFxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgY29weUZpbGUoa2V5YmluZGluZ3NQYXRoLCBiYWNrdXBQYXRoKVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBgJHtjb2xvcihcbiAgICAgICAgICAnd2FybmluZycsXG4gICAgICAgICAgdGhlbWUsXG4gICAgICAgICkoXG4gICAgICAgICAgYEVycm9yIGJhY2tpbmcgdXAgZXhpc3RpbmcgJHtlZGl0b3J9IHRlcm1pbmFsIGtleWJpbmRpbmdzLiBCYWlsaW5nIG91dC5gLFxuICAgICAgICApfSR7RU9MfSR7Y2hhbGsuZGltKGBTZWUgJHtmb3JtYXRQYXRoTGluayhrZXliaW5kaW5nc1BhdGgpfWApfSR7RU9MfSR7Y2hhbGsuZGltKGBCYWNrdXAgcGF0aDogJHtmb3JtYXRQYXRoTGluayhiYWNrdXBQYXRoKX1gKX0ke0VPTH1gXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYga2V5YmluZGluZyBhbHJlYWR5IGV4aXN0c1xuICAgIGNvbnN0IGV4aXN0aW5nQmluZGluZyA9IGtleWJpbmRpbmdzLmZpbmQoXG4gICAgICBiaW5kaW5nID0+XG4gICAgICAgIGJpbmRpbmcua2V5ID09PSAnc2hpZnQrZW50ZXInICYmXG4gICAgICAgIGJpbmRpbmcuY29tbWFuZCA9PT0gJ3dvcmtiZW5jaC5hY3Rpb24udGVybWluYWwuc2VuZFNlcXVlbmNlJyAmJlxuICAgICAgICBiaW5kaW5nLndoZW4gPT09ICd0ZXJtaW5hbEZvY3VzJyxcbiAgICApXG4gICAgaWYgKGV4aXN0aW5nQmluZGluZykge1xuICAgICAgcmV0dXJuIGAke2NvbG9yKFxuICAgICAgICAnd2FybmluZycsXG4gICAgICAgIHRoZW1lLFxuICAgICAgKShcbiAgICAgICAgYEZvdW5kIGV4aXN0aW5nICR7ZWRpdG9yfSB0ZXJtaW5hbCBTaGlmdCtFbnRlciBrZXkgYmluZGluZy4gUmVtb3ZlIGl0IHRvIGNvbnRpbnVlLmAsXG4gICAgICApfSR7RU9MfSR7Y2hhbGsuZGltKGBTZWUgJHtmb3JtYXRQYXRoTGluayhrZXliaW5kaW5nc1BhdGgpfWApfSR7RU9MfWBcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgdGhlIG5ldyBrZXliaW5kaW5nXG4gICAgY29uc3QgbmV3S2V5YmluZGluZzogVlNDb2RlS2V5YmluZGluZyA9IHtcbiAgICAgIGtleTogJ3NoaWZ0K2VudGVyJyxcbiAgICAgIGNvbW1hbmQ6ICd3b3JrYmVuY2guYWN0aW9uLnRlcm1pbmFsLnNlbmRTZXF1ZW5jZScsXG4gICAgICBhcmdzOiB7IHRleHQ6ICdcXHUwMDFiXFxyJyB9LFxuICAgICAgd2hlbjogJ3Rlcm1pbmFsRm9jdXMnLFxuICAgIH1cblxuICAgIC8vIE1vZGlmeSB0aGUgY29udGVudCBieSBhZGRpbmcgdGhlIG5ldyBrZXliaW5kaW5nIHdoaWxlIHByZXNlcnZpbmcgY29tbWVudHMgYW5kIGZvcm1hdHRpbmdcbiAgICBjb25zdCB1cGRhdGVkQ29udGVudCA9IGFkZEl0ZW1Ub0pTT05DQXJyYXkoY29udGVudCwgbmV3S2V5YmluZGluZylcblxuICAgIC8vIFdyaXRlIHRoZSB1cGRhdGVkIGNvbnRlbnQgYmFjayB0byB0aGUgZmlsZVxuICAgIGF3YWl0IHdyaXRlRmlsZShrZXliaW5kaW5nc1BhdGgsIHVwZGF0ZWRDb250ZW50LCB7IGVuY29kaW5nOiAndXRmLTgnIH0pXG5cbiAgICByZXR1cm4gYCR7Y29sb3IoXG4gICAgICAnc3VjY2VzcycsXG4gICAgICB0aGVtZSxcbiAgICApKFxuICAgICAgYEluc3RhbGxlZCAke2VkaXRvcn0gdGVybWluYWwgU2hpZnQrRW50ZXIga2V5IGJpbmRpbmdgLFxuICAgICl9JHtFT0x9JHtjaGFsay5kaW0oYFNlZSAke2Zvcm1hdFBhdGhMaW5rKGtleWJpbmRpbmdzUGF0aCl9YCl9JHtFT0x9YFxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ0Vycm9yKGVycm9yKVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gaW5zdGFsbCAke2VkaXRvcn0gdGVybWluYWwgU2hpZnQrRW50ZXIga2V5IGJpbmRpbmdgLFxuICAgIClcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBlbmFibGVPcHRpb25Bc01ldGFGb3JQcm9maWxlKFxuICBwcm9maWxlTmFtZTogc3RyaW5nLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIC8vIEZpcnN0IHRyeSB0byBhZGQgdGhlIHByb3BlcnR5IChpbiBjYXNlIGl0IGRvZXNuJ3QgZXhpc3QpXG4gIC8vIFF1b3RlIHRoZSBwcm9maWxlIG5hbWUgdG8gaGFuZGxlIG5hbWVzIHdpdGggc3BhY2VzIChlLmcuLCBcIk1hbiBQYWdlXCIsIFwiUmVkIFNhbmRzXCIpXG4gIGNvbnN0IHsgY29kZTogYWRkQ29kZSB9ID0gYXdhaXQgZXhlY0ZpbGVOb1Rocm93KCcvdXNyL2xpYmV4ZWMvUGxpc3RCdWRkeScsIFtcbiAgICAnLWMnLFxuICAgIGBBZGQgOidXaW5kb3cgU2V0dGluZ3MnOicke3Byb2ZpbGVOYW1lfSc6dXNlT3B0aW9uQXNNZXRhS2V5IGJvb2wgdHJ1ZWAsXG4gICAgZ2V0VGVybWluYWxQbGlzdFBhdGgoKSxcbiAgXSlcblxuICAvLyBJZiBhZGRpbmcgZmFpbHMgKGxpa2VseSBiZWNhdXNlIGl0IGFscmVhZHkgZXhpc3RzKSwgdHJ5IHNldHRpbmcgaXQgaW5zdGVhZFxuICBpZiAoYWRkQ29kZSAhPT0gMCkge1xuICAgIGNvbnN0IHsgY29kZTogc2V0Q29kZSB9ID0gYXdhaXQgZXhlY0ZpbGVOb1Rocm93KCcvdXNyL2xpYmV4ZWMvUGxpc3RCdWRkeScsIFtcbiAgICAgICctYycsXG4gICAgICBgU2V0IDonV2luZG93IFNldHRpbmdzJzonJHtwcm9maWxlTmFtZX0nOnVzZU9wdGlvbkFzTWV0YUtleSB0cnVlYCxcbiAgICAgIGdldFRlcm1pbmFsUGxpc3RQYXRoKCksXG4gICAgXSlcblxuICAgIGlmIChzZXRDb2RlICE9PSAwKSB7XG4gICAgICBsb2dFcnJvcihcbiAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgIGBGYWlsZWQgdG8gZW5hYmxlIE9wdGlvbiBhcyBNZXRhIGtleSBmb3IgVGVybWluYWwuYXBwIHByb2ZpbGU6ICR7cHJvZmlsZU5hbWV9YCxcbiAgICAgICAgKSxcbiAgICAgIClcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc2FibGVBdWRpb0JlbGxGb3JQcm9maWxlKFxuICBwcm9maWxlTmFtZTogc3RyaW5nLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIC8vIEZpcnN0IHRyeSB0byBhZGQgdGhlIHByb3BlcnR5IChpbiBjYXNlIGl0IGRvZXNuJ3QgZXhpc3QpXG4gIC8vIFF1b3RlIHRoZSBwcm9maWxlIG5hbWUgdG8gaGFuZGxlIG5hbWVzIHdpdGggc3BhY2VzIChlLmcuLCBcIk1hbiBQYWdlXCIsIFwiUmVkIFNhbmRzXCIpXG4gIGNvbnN0IHsgY29kZTogYWRkQ29kZSB9ID0gYXdhaXQgZXhlY0ZpbGVOb1Rocm93KCcvdXNyL2xpYmV4ZWMvUGxpc3RCdWRkeScsIFtcbiAgICAnLWMnLFxuICAgIGBBZGQgOidXaW5kb3cgU2V0dGluZ3MnOicke3Byb2ZpbGVOYW1lfSc6QmVsbCBib29sIGZhbHNlYCxcbiAgICBnZXRUZXJtaW5hbFBsaXN0UGF0aCgpLFxuICBdKVxuXG4gIC8vIElmIGFkZGluZyBmYWlscyAobGlrZWx5IGJlY2F1c2UgaXQgYWxyZWFkeSBleGlzdHMpLCB0cnkgc2V0dGluZyBpdCBpbnN0ZWFkXG4gIGlmIChhZGRDb2RlICE9PSAwKSB7XG4gICAgY29uc3QgeyBjb2RlOiBzZXRDb2RlIH0gPSBhd2FpdCBleGVjRmlsZU5vVGhyb3coJy91c3IvbGliZXhlYy9QbGlzdEJ1ZGR5JywgW1xuICAgICAgJy1jJyxcbiAgICAgIGBTZXQgOidXaW5kb3cgU2V0dGluZ3MnOicke3Byb2ZpbGVOYW1lfSc6QmVsbCBmYWxzZWAsXG4gICAgICBnZXRUZXJtaW5hbFBsaXN0UGF0aCgpLFxuICAgIF0pXG5cbiAgICBpZiAoc2V0Q29kZSAhPT0gMCkge1xuICAgICAgbG9nRXJyb3IoXG4gICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICBgRmFpbGVkIHRvIGRpc2FibGUgYXVkaW8gYmVsbCBmb3IgVGVybWluYWwuYXBwIHByb2ZpbGU6ICR7cHJvZmlsZU5hbWV9YCxcbiAgICAgICAgKSxcbiAgICAgIClcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlXG59XG5cbi8vIEVuYWJsZSBPcHRpb24gYXMgTWV0YSBrZXkgZm9yIFRlcm1pbmFsLmFwcFxuYXN5bmMgZnVuY3Rpb24gZW5hYmxlT3B0aW9uQXNNZXRhRm9yVGVybWluYWwoXG4gIHRoZW1lOiBUaGVtZU5hbWUsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICB0cnkge1xuICAgIC8vIENyZWF0ZSBhIGJhY2t1cCBvZiB0aGUgY3VycmVudCBwbGlzdCBmaWxlXG4gICAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IGJhY2t1cFRlcm1pbmFsUHJlZmVyZW5jZXMoKVxuICAgIGlmICghYmFja3VwUGF0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnRmFpbGVkIHRvIGNyZWF0ZSBiYWNrdXAgb2YgVGVybWluYWwuYXBwIHByZWZlcmVuY2VzLCBiYWlsaW5nIG91dCcsXG4gICAgICApXG4gICAgfVxuXG4gICAgLy8gUmVhZCB0aGUgY3VycmVudCBkZWZhdWx0IHByb2ZpbGUgZnJvbSB0aGUgcGxpc3RcbiAgICBjb25zdCB7IHN0ZG91dDogZGVmYXVsdFByb2ZpbGUsIGNvZGU6IHJlYWRDb2RlIH0gPSBhd2FpdCBleGVjRmlsZU5vVGhyb3coXG4gICAgICAnZGVmYXVsdHMnLFxuICAgICAgWydyZWFkJywgJ2NvbS5hcHBsZS5UZXJtaW5hbCcsICdEZWZhdWx0IFdpbmRvdyBTZXR0aW5ncyddLFxuICAgIClcblxuICAgIGlmIChyZWFkQ29kZSAhPT0gMCB8fCAhZGVmYXVsdFByb2ZpbGUudHJpbSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byByZWFkIGRlZmF1bHQgVGVybWluYWwuYXBwIHByb2ZpbGUnKVxuICAgIH1cblxuICAgIGNvbnN0IHsgc3Rkb3V0OiBzdGFydHVwUHJvZmlsZSwgY29kZTogc3RhcnR1cENvZGUgfSA9IGF3YWl0IGV4ZWNGaWxlTm9UaHJvdyhcbiAgICAgICdkZWZhdWx0cycsXG4gICAgICBbJ3JlYWQnLCAnY29tLmFwcGxlLlRlcm1pbmFsJywgJ1N0YXJ0dXAgV2luZG93IFNldHRpbmdzJ10sXG4gICAgKVxuICAgIGlmIChzdGFydHVwQ29kZSAhPT0gMCB8fCAhc3RhcnR1cFByb2ZpbGUudHJpbSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byByZWFkIHN0YXJ0dXAgVGVybWluYWwuYXBwIHByb2ZpbGUnKVxuICAgIH1cblxuICAgIGxldCB3YXNBbnlQcm9maWxlVXBkYXRlZCA9IGZhbHNlXG5cbiAgICBjb25zdCBkZWZhdWx0UHJvZmlsZU5hbWUgPSBkZWZhdWx0UHJvZmlsZS50cmltKClcbiAgICBjb25zdCBvcHRpb25Bc01ldGFFbmFibGVkID1cbiAgICAgIGF3YWl0IGVuYWJsZU9wdGlvbkFzTWV0YUZvclByb2ZpbGUoZGVmYXVsdFByb2ZpbGVOYW1lKVxuICAgIGNvbnN0IGF1ZGlvQmVsbERpc2FibGVkID1cbiAgICAgIGF3YWl0IGRpc2FibGVBdWRpb0JlbGxGb3JQcm9maWxlKGRlZmF1bHRQcm9maWxlTmFtZSlcblxuICAgIGlmIChvcHRpb25Bc01ldGFFbmFibGVkIHx8IGF1ZGlvQmVsbERpc2FibGVkKSB7XG4gICAgICB3YXNBbnlQcm9maWxlVXBkYXRlZCA9IHRydWVcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydHVwUHJvZmlsZU5hbWUgPSBzdGFydHVwUHJvZmlsZS50cmltKClcblxuICAgIC8vIE9ubHkgcHJvY2VlZCBpZiB0aGUgc3RhcnR1cCBwcm9maWxlIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBkZWZhdWx0IHByb2ZpbGVcbiAgICBpZiAoc3RhcnR1cFByb2ZpbGVOYW1lICE9PSBkZWZhdWx0UHJvZmlsZU5hbWUpIHtcbiAgICAgIGNvbnN0IHN0YXJ0dXBPcHRpb25Bc01ldGFFbmFibGVkID1cbiAgICAgICAgYXdhaXQgZW5hYmxlT3B0aW9uQXNNZXRhRm9yUHJvZmlsZShzdGFydHVwUHJvZmlsZU5hbWUpXG4gICAgICBjb25zdCBzdGFydHVwQXVkaW9CZWxsRGlzYWJsZWQgPVxuICAgICAgICBhd2FpdCBkaXNhYmxlQXVkaW9CZWxsRm9yUHJvZmlsZShzdGFydHVwUHJvZmlsZU5hbWUpXG5cbiAgICAgIGlmIChzdGFydHVwT3B0aW9uQXNNZXRhRW5hYmxlZCB8fCBzdGFydHVwQXVkaW9CZWxsRGlzYWJsZWQpIHtcbiAgICAgICAgd2FzQW55UHJvZmlsZVVwZGF0ZWQgPSB0cnVlXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCF3YXNBbnlQcm9maWxlVXBkYXRlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnRmFpbGVkIHRvIGVuYWJsZSBPcHRpb24gYXMgTWV0YSBrZXkgb3IgZGlzYWJsZSBhdWRpbyBiZWxsIGZvciBhbnkgVGVybWluYWwuYXBwIHByb2ZpbGUnLFxuICAgICAgKVxuICAgIH1cblxuICAgIC8vIEZsdXNoIHRoZSBwcmVmZXJlbmNlcyBjYWNoZVxuICAgIGF3YWl0IGV4ZWNGaWxlTm9UaHJvdygna2lsbGFsbCcsIFsnY2ZwcmVmc2QnXSlcblxuICAgIG1hcmtUZXJtaW5hbFNldHVwQ29tcGxldGUoKVxuXG4gICAgcmV0dXJuIGAke2NvbG9yKFxuICAgICAgJ3N1Y2Nlc3MnLFxuICAgICAgdGhlbWUsXG4gICAgKShcbiAgICAgIGBDb25maWd1cmVkIFRlcm1pbmFsLmFwcCBzZXR0aW5nczpgLFxuICAgICl9JHtFT0x9JHtjb2xvcignc3VjY2VzcycsIHRoZW1lKSgnLSBFbmFibGVkIFwiVXNlIE9wdGlvbiBhcyBNZXRhIGtleVwiJyl9JHtFT0x9JHtjb2xvcignc3VjY2VzcycsIHRoZW1lKSgnLSBTd2l0Y2hlZCB0byB2aXN1YWwgYmVsbCcpfSR7RU9MfSR7Y2hhbGsuZGltKCdPcHRpb24rRW50ZXIgd2lsbCBub3cgZW50ZXIgYSBuZXdsaW5lLicpfSR7RU9MfSR7Y2hhbGsuZGltKCdZb3UgbXVzdCByZXN0YXJ0IFRlcm1pbmFsLmFwcCBmb3IgY2hhbmdlcyB0byB0YWtlIGVmZmVjdC4nLCB0aGVtZSl9JHtFT0x9YFxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ0Vycm9yKGVycm9yKVxuXG4gICAgLy8gQXR0ZW1wdCB0byByZXN0b3JlIGZyb20gYmFja3VwXG4gICAgY29uc3QgcmVzdG9yZVJlc3VsdCA9IGF3YWl0IGNoZWNrQW5kUmVzdG9yZVRlcm1pbmFsQmFja3VwKClcblxuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9ICdGYWlsZWQgdG8gZW5hYmxlIE9wdGlvbiBhcyBNZXRhIGtleSBmb3IgVGVybWluYWwuYXBwLidcbiAgICBpZiAocmVzdG9yZVJlc3VsdC5zdGF0dXMgPT09ICdyZXN0b3JlZCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7ZXJyb3JNZXNzYWdlfSBZb3VyIHNldHRpbmdzIGhhdmUgYmVlbiByZXN0b3JlZCBmcm9tIGJhY2t1cC5gLFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAocmVzdG9yZVJlc3VsdC5zdGF0dXMgPT09ICdmYWlsZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2Vycm9yTWVzc2FnZX0gUmVzdG9yaW5nIGZyb20gYmFja3VwIGZhaWxlZCwgdHJ5IG1hbnVhbGx5IHdpdGg6IGRlZmF1bHRzIGltcG9ydCBjb20uYXBwbGUuVGVybWluYWwgJHtyZXN0b3JlUmVzdWx0LmJhY2t1cFBhdGh9YCxcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtlcnJvck1lc3NhZ2V9IE5vIGJhY2t1cCB3YXMgYXZhaWxhYmxlIHRvIHJlc3RvcmUgZnJvbS5gLFxuICAgICAgKVxuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsQmluZGluZ3NGb3JBbGFjcml0dHkodGhlbWU6IFRoZW1lTmFtZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IEFMQUNSSVRUWV9LRVlCSU5ESU5HID0gYFtba2V5Ym9hcmQuYmluZGluZ3NdXVxua2V5ID0gXCJSZXR1cm5cIlxubW9kcyA9IFwiU2hpZnRcIlxuY2hhcnMgPSBcIlxcXFx1MDAxQlxcXFxyXCJgXG5cbiAgLy8gR2V0IEFsYWNyaXR0eSBjb25maWcgZmlsZSBwYXRocyBpbiBvcmRlciBvZiBwcmVmZXJlbmNlXG4gIGNvbnN0IGNvbmZpZ1BhdGhzOiBzdHJpbmdbXSA9IFtdXG5cbiAgLy8gWERHIGNvbmZpZyBwYXRoIChMaW51eCBhbmQgbWFjT1MpXG4gIGNvbnN0IHhkZ0NvbmZpZ0hvbWUgPSBwcm9jZXNzLmVudi5YREdfQ09ORklHX0hPTUVcbiAgaWYgKHhkZ0NvbmZpZ0hvbWUpIHtcbiAgICBjb25maWdQYXRocy5wdXNoKGpvaW4oeGRnQ29uZmlnSG9tZSwgJ2FsYWNyaXR0eScsICdhbGFjcml0dHkudG9tbCcpKVxuICB9IGVsc2Uge1xuICAgIGNvbmZpZ1BhdGhzLnB1c2goam9pbihob21lZGlyKCksICcuY29uZmlnJywgJ2FsYWNyaXR0eScsICdhbGFjcml0dHkudG9tbCcpKVxuICB9XG5cbiAgLy8gV2luZG93cy1zcGVjaWZpYyBwYXRoXG4gIGlmIChwbGF0Zm9ybSgpID09PSAnd2luMzInKSB7XG4gICAgY29uc3QgYXBwRGF0YSA9IHByb2Nlc3MuZW52LkFQUERBVEFcbiAgICBpZiAoYXBwRGF0YSkge1xuICAgICAgY29uZmlnUGF0aHMucHVzaChqb2luKGFwcERhdGEsICdhbGFjcml0dHknLCAnYWxhY3JpdHR5LnRvbWwnKSlcbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIGV4aXN0aW5nIGNvbmZpZyBmaWxlIGJ5IGF0dGVtcHRpbmcgdG8gcmVhZCBpdCwgb3IgdXNlIGZpcnN0IHByZWZlcnJlZCBwYXRoXG4gIGxldCBjb25maWdQYXRoOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICBsZXQgY29uZmlnQ29udGVudCA9ICcnXG4gIGxldCBjb25maWdFeGlzdHMgPSBmYWxzZVxuXG4gIGZvciAoY29uc3QgcGF0aCBvZiBjb25maWdQYXRocykge1xuICAgIHRyeSB7XG4gICAgICBjb25maWdDb250ZW50ID0gYXdhaXQgcmVhZEZpbGUocGF0aCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KVxuICAgICAgY29uZmlnUGF0aCA9IHBhdGhcbiAgICAgIGNvbmZpZ0V4aXN0cyA9IHRydWVcbiAgICAgIGJyZWFrXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKCFpc0ZzSW5hY2Nlc3NpYmxlKGUpKSB0aHJvdyBlXG4gICAgICAvLyBGaWxlIG1pc3Npbmcgb3IgaW5hY2Nlc3NpYmxlIOKAlCB0cnkgbmV4dCBjb25maWcgcGF0aFxuICAgIH1cbiAgfVxuXG4gIC8vIElmIG5vIGNvbmZpZyBleGlzdHMsIHVzZSB0aGUgZmlyc3QgcGF0aCAoWERHL2RlZmF1bHQgbG9jYXRpb24pXG4gIGlmICghY29uZmlnUGF0aCkge1xuICAgIGNvbmZpZ1BhdGggPSBjb25maWdQYXRoc1swXSA/PyBudWxsXG4gIH1cblxuICBpZiAoIWNvbmZpZ1BhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHZhbGlkIGNvbmZpZyBwYXRoIGZvdW5kIGZvciBBbGFjcml0dHknKVxuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAoY29uZmlnRXhpc3RzKSB7XG4gICAgICAvLyBDaGVjayBpZiBrZXliaW5kaW5nIGFscmVhZHkgZXhpc3RzIChsb29rIGZvciBTaGlmdCtSZXR1cm4gYmluZGluZylcbiAgICAgIGlmIChcbiAgICAgICAgY29uZmlnQ29udGVudC5pbmNsdWRlcygnbW9kcyA9IFwiU2hpZnRcIicpICYmXG4gICAgICAgIGNvbmZpZ0NvbnRlbnQuaW5jbHVkZXMoJ2tleSA9IFwiUmV0dXJuXCInKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBgJHtjb2xvcihcbiAgICAgICAgICAnd2FybmluZycsXG4gICAgICAgICAgdGhlbWUsXG4gICAgICAgICkoXG4gICAgICAgICAgJ0ZvdW5kIGV4aXN0aW5nIEFsYWNyaXR0eSBTaGlmdCtFbnRlciBrZXkgYmluZGluZy4gUmVtb3ZlIGl0IHRvIGNvbnRpbnVlLicsXG4gICAgICAgICl9JHtFT0x9JHtjaGFsay5kaW0oYFNlZSAke2Zvcm1hdFBhdGhMaW5rKGNvbmZpZ1BhdGgpfWApfSR7RU9MfWBcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIGJhY2t1cFxuICAgICAgY29uc3QgcmFuZG9tU2hhID0gcmFuZG9tQnl0ZXMoNCkudG9TdHJpbmcoJ2hleCcpXG4gICAgICBjb25zdCBiYWNrdXBQYXRoID0gYCR7Y29uZmlnUGF0aH0uJHtyYW5kb21TaGF9LmJha2BcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNvcHlGaWxlKGNvbmZpZ1BhdGgsIGJhY2t1cFBhdGgpXG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGAke2NvbG9yKFxuICAgICAgICAgICd3YXJuaW5nJyxcbiAgICAgICAgICB0aGVtZSxcbiAgICAgICAgKShcbiAgICAgICAgICAnRXJyb3IgYmFja2luZyB1cCBleGlzdGluZyBBbGFjcml0dHkgY29uZmlnLiBCYWlsaW5nIG91dC4nLFxuICAgICAgICApfSR7RU9MfSR7Y2hhbGsuZGltKGBTZWUgJHtmb3JtYXRQYXRoTGluayhjb25maWdQYXRoKX1gKX0ke0VPTH0ke2NoYWxrLmRpbShgQmFja3VwIHBhdGg6ICR7Zm9ybWF0UGF0aExpbmsoYmFja3VwUGF0aCl9YCl9JHtFT0x9YFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFbnN1cmUgY29uZmlnIGRpcmVjdG9yeSBleGlzdHMgKGlkZW1wb3RlbnQgd2l0aCByZWN1cnNpdmUpXG4gICAgICBhd2FpdCBta2RpcihkaXJuYW1lKGNvbmZpZ1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICAgIH1cblxuICAgIC8vIEFkZCB0aGUga2V5YmluZGluZyB0byB0aGUgY29uZmlnXG4gICAgbGV0IHVwZGF0ZWRDb250ZW50ID0gY29uZmlnQ29udGVudFxuICAgIGlmIChjb25maWdDb250ZW50ICYmICFjb25maWdDb250ZW50LmVuZHNXaXRoKCdcXG4nKSkge1xuICAgICAgdXBkYXRlZENvbnRlbnQgKz0gJ1xcbidcbiAgICB9XG4gICAgdXBkYXRlZENvbnRlbnQgKz0gJ1xcbicgKyBBTEFDUklUVFlfS0VZQklORElORyArICdcXG4nXG5cbiAgICAvLyBXcml0ZSB0aGUgdXBkYXRlZCBjb25maWdcbiAgICBhd2FpdCB3cml0ZUZpbGUoY29uZmlnUGF0aCwgdXBkYXRlZENvbnRlbnQsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSlcblxuICAgIHJldHVybiBgJHtjb2xvcihcbiAgICAgICdzdWNjZXNzJyxcbiAgICAgIHRoZW1lLFxuICAgICkoJ0luc3RhbGxlZCBBbGFjcml0dHkgU2hpZnQrRW50ZXIga2V5IGJpbmRpbmcnKX0ke0VPTH0ke2NvbG9yKFxuICAgICAgJ3N1Y2Nlc3MnLFxuICAgICAgdGhlbWUsXG4gICAgKShcbiAgICAgICdZb3UgbWF5IG5lZWQgdG8gcmVzdGFydCBBbGFjcml0dHkgZm9yIGNoYW5nZXMgdG8gdGFrZSBlZmZlY3QnLFxuICAgICl9JHtFT0x9JHtjaGFsay5kaW0oYFNlZSAke2Zvcm1hdFBhdGhMaW5rKGNvbmZpZ1BhdGgpfWApfSR7RU9MfWBcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dFcnJvcihlcnJvcilcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbnN0YWxsIEFsYWNyaXR0eSBTaGlmdCtFbnRlciBrZXkgYmluZGluZycpXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEJpbmRpbmdzRm9yWmVkKHRoZW1lOiBUaGVtZU5hbWUpOiBQcm9taXNlPHN0cmluZz4ge1xuICAvLyBaZWQgdXNlcyBKU09OIGtleWJpbmRpbmdzIHNpbWlsYXIgdG8gVlNDb2RlXG4gIGNvbnN0IHplZERpciA9IGpvaW4oaG9tZWRpcigpLCAnLmNvbmZpZycsICd6ZWQnKVxuICBjb25zdCBrZXltYXBQYXRoID0gam9pbih6ZWREaXIsICdrZXltYXAuanNvbicpXG5cbiAgdHJ5IHtcbiAgICAvLyBFbnN1cmUgemVkIGRpcmVjdG9yeSBleGlzdHMgKGlkZW1wb3RlbnQgd2l0aCByZWN1cnNpdmUpXG4gICAgYXdhaXQgbWtkaXIoemVkRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuXG4gICAgLy8gUmVhZCBleGlzdGluZyBrZXltYXAgZmlsZSwgb3IgZGVmYXVsdCB0byBlbXB0eSBhcnJheSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgbGV0IGtleW1hcENvbnRlbnQgPSAnW10nXG4gICAgbGV0IGZpbGVFeGlzdHMgPSBmYWxzZVxuICAgIHRyeSB7XG4gICAgICBrZXltYXBDb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoa2V5bWFwUGF0aCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KVxuICAgICAgZmlsZUV4aXN0cyA9IHRydWVcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoIWlzRnNJbmFjY2Vzc2libGUoZSkpIHRocm93IGVcbiAgICB9XG5cbiAgICBpZiAoZmlsZUV4aXN0cykge1xuICAgICAgLy8gQ2hlY2sgaWYga2V5YmluZGluZyBhbHJlYWR5IGV4aXN0c1xuICAgICAgaWYgKGtleW1hcENvbnRlbnQuaW5jbHVkZXMoJ3NoaWZ0LWVudGVyJykpIHtcbiAgICAgICAgcmV0dXJuIGAke2NvbG9yKFxuICAgICAgICAgICd3YXJuaW5nJyxcbiAgICAgICAgICB0aGVtZSxcbiAgICAgICAgKShcbiAgICAgICAgICAnRm91bmQgZXhpc3RpbmcgWmVkIFNoaWZ0K0VudGVyIGtleSBiaW5kaW5nLiBSZW1vdmUgaXQgdG8gY29udGludWUuJyxcbiAgICAgICAgKX0ke0VPTH0ke2NoYWxrLmRpbShgU2VlICR7Zm9ybWF0UGF0aExpbmsoa2V5bWFwUGF0aCl9YCl9JHtFT0x9YFxuICAgICAgfVxuXG4gICAgICAvLyBDcmVhdGUgYmFja3VwXG4gICAgICBjb25zdCByYW5kb21TaGEgPSByYW5kb21CeXRlcyg0KS50b1N0cmluZygnaGV4JylcbiAgICAgIGNvbnN0IGJhY2t1cFBhdGggPSBgJHtrZXltYXBQYXRofS4ke3JhbmRvbVNoYX0uYmFrYFxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgY29weUZpbGUoa2V5bWFwUGF0aCwgYmFja3VwUGF0aClcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gYCR7Y29sb3IoXG4gICAgICAgICAgJ3dhcm5pbmcnLFxuICAgICAgICAgIHRoZW1lLFxuICAgICAgICApKFxuICAgICAgICAgICdFcnJvciBiYWNraW5nIHVwIGV4aXN0aW5nIFplZCBrZXltYXAuIEJhaWxpbmcgb3V0LicsXG4gICAgICAgICl9JHtFT0x9JHtjaGFsay5kaW0oYFNlZSAke2Zvcm1hdFBhdGhMaW5rKGtleW1hcFBhdGgpfWApfSR7RU9MfSR7Y2hhbGsuZGltKGBCYWNrdXAgcGF0aDogJHtmb3JtYXRQYXRoTGluayhiYWNrdXBQYXRoKX1gKX0ke0VPTH1gXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgYW5kIG1vZGlmeSB0aGUga2V5bWFwXG4gICAgbGV0IGtleW1hcDogQXJyYXk8e1xuICAgICAgY29udGV4dD86IHN0cmluZ1xuICAgICAgYmluZGluZ3M6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHN0cmluZ1tdPlxuICAgIH0+XG4gICAgdHJ5IHtcbiAgICAgIGtleW1hcCA9IGpzb25QYXJzZShrZXltYXBDb250ZW50KVxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGtleW1hcCkpIHtcbiAgICAgICAga2V5bWFwID0gW11cbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIGtleW1hcCA9IFtdXG4gICAgfVxuXG4gICAgLy8gQWRkIHRoZSBuZXcga2V5YmluZGluZyBmb3IgdGVybWluYWwgY29udGV4dFxuICAgIGtleW1hcC5wdXNoKHtcbiAgICAgIGNvbnRleHQ6ICdUZXJtaW5hbCcsXG4gICAgICBiaW5kaW5nczoge1xuICAgICAgICAnc2hpZnQtZW50ZXInOiBbJ3Rlcm1pbmFsOjpTZW5kVGV4dCcsICdcXHUwMDFiXFxyJ10sXG4gICAgICB9LFxuICAgIH0pXG5cbiAgICAvLyBXcml0ZSB0aGUgdXBkYXRlZCBrZXltYXBcbiAgICBhd2FpdCB3cml0ZUZpbGUoa2V5bWFwUGF0aCwganNvblN0cmluZ2lmeShrZXltYXAsIG51bGwsIDIpICsgJ1xcbicsIHtcbiAgICAgIGVuY29kaW5nOiAndXRmLTgnLFxuICAgIH0pXG5cbiAgICByZXR1cm4gYCR7Y29sb3IoXG4gICAgICAnc3VjY2VzcycsXG4gICAgICB0aGVtZSxcbiAgICApKFxuICAgICAgJ0luc3RhbGxlZCBaZWQgU2hpZnQrRW50ZXIga2V5IGJpbmRpbmcnLFxuICAgICl9JHtFT0x9JHtjaGFsay5kaW0oYFNlZSAke2Zvcm1hdFBhdGhMaW5rKGtleW1hcFBhdGgpfWApfSR7RU9MfWBcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dFcnJvcihlcnJvcilcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbnN0YWxsIFplZCBTaGlmdCtFbnRlciBrZXkgYmluZGluZycpXG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsS0FBSyxNQUFNLE9BQU87QUFDekIsU0FBU0MsV0FBVyxRQUFRLFFBQVE7QUFDcEMsU0FBU0MsUUFBUSxFQUFFQyxLQUFLLEVBQUVDLFFBQVEsRUFBRUMsU0FBUyxRQUFRLGFBQWE7QUFDbEUsU0FBU0MsT0FBTyxFQUFFQyxRQUFRLFFBQVEsSUFBSTtBQUN0QyxTQUFTQyxPQUFPLEVBQUVDLElBQUksUUFBUSxNQUFNO0FBQ3BDLGNBQWNDLFNBQVMsUUFBUSxvQkFBb0I7QUFDbkQsU0FBU0MsYUFBYSxRQUFRLEtBQUs7QUFDbkMsU0FBU0Msa0JBQWtCLFFBQVEsa0NBQWtDO0FBQ3JFLFNBQVNDLEtBQUssUUFBUSxjQUFjO0FBQ3BDLFNBQVNDLGtDQUFrQyxRQUFRLGlDQUFpQztBQUNwRixjQUFjQyxjQUFjLFFBQVEsZUFBZTtBQUNuRCxjQUNFQyxzQkFBc0IsRUFDdEJDLHFCQUFxQixRQUNoQix3QkFBd0I7QUFDL0IsU0FDRUMseUJBQXlCLEVBQ3pCQyw2QkFBNkIsRUFDN0JDLG9CQUFvQixFQUNwQkMseUJBQXlCLFFBQ3BCLG9DQUFvQztBQUMzQyxTQUFTQyxvQkFBb0IsUUFBUSxnQ0FB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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/upgrade/upgrade.tsx b/_all-in-one-upload/cc-haha/src/commands/upgrade/upgrade.tsx new file mode 100644 index 0000000..1daf73d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/upgrade/upgrade.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import type { LocalJSXCommandContext } from '../../commands.js'; +import { getOauthProfileFromOauthToken } from '../../services/oauth/getOauthProfile.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; +import { getClaudeAIOAuthTokens, isClaudeAISubscriber } from '../../utils/auth.js'; +import { openBrowser } from '../../utils/browser.js'; +import { logError } from '../../utils/log.js'; +import { Login } from '../login/login.js'; +export async function call(onDone: LocalJSXCommandOnDone, context: LocalJSXCommandContext): Promise { + try { + // Check if user is already on the highest Max plan (20x) + if (isClaudeAISubscriber()) { + const tokens = getClaudeAIOAuthTokens(); + let isMax20x = false; + if (tokens?.subscriptionType && tokens?.rateLimitTier) { + isMax20x = tokens.subscriptionType === 'max' && tokens.rateLimitTier === 'default_claude_max_20x'; + } else if (tokens?.accessToken) { + const profile = await getOauthProfileFromOauthToken(tokens.accessToken); + isMax20x = profile?.organization?.organization_type === 'claude_max' && profile?.organization?.rate_limit_tier === 'default_claude_max_20x'; + } + if (isMax20x) { + setTimeout(onDone, 0, 'You are already on the highest Max subscription plan. For additional usage, run /login to switch to an API usage-billed account.'); + return null; + } + } + const url = 'https://claude.ai/upgrade/max'; + await openBrowser(url); + return { + context.onChangeAPIKey(); + onDone(success ? 'Login successful' : 'Login interrupted'); + }} />; + } catch (error) { + logError(error as Error); + setTimeout(onDone, 0, 'Failed to open browser. Please visit https://claude.ai/upgrade/max to upgrade.'); + } + return null; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkxvY2FsSlNYQ29tbWFuZENvbnRleHQiLCJnZXRPYXV0aFByb2ZpbGVGcm9tT2F1dGhUb2tlbiIsIkxvY2FsSlNYQ29tbWFuZE9uRG9uZSIsImdldENsYXVkZUFJT0F1dGhUb2tlbnMiLCJpc0NsYXVkZUFJU3Vic2NyaWJlciIsIm9wZW5Ccm93c2VyIiwibG9nRXJyb3IiLCJMb2dpbiIsImNhbGwiLCJvbkRvbmUiLCJjb250ZXh0IiwiUHJvbWlzZSIsIlJlYWN0Tm9kZSIsInRva2VucyIsImlzTWF4MjB4Iiwic3Vic2NyaXB0aW9uVHlwZSIsInJhdGVMaW1pdFRpZXIiLCJhY2Nlc3NUb2tlbiIsInByb2ZpbGUiLCJvcmdhbml6YXRpb24iLCJvcmdhbml6YXRpb25fdHlwZSIsInJhdGVfbGltaXRfdGllciIsInNldFRpbWVvdXQiLCJ1cmwiLCJzdWNjZXNzIiwib25DaGFuZ2VBUElLZXkiLCJlcnJvciIsIkVycm9yIl0sInNvdXJjZXMiOlsidXBncmFkZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IExvY2FsSlNYQ29tbWFuZENvbnRleHQgfSBmcm9tICcuLi8uLi9jb21tYW5kcy5qcydcbmltcG9ydCB7IGdldE9hdXRoUHJvZmlsZUZyb21PYXV0aFRva2VuIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvb2F1dGgvZ2V0T2F1dGhQcm9maWxlLmpzJ1xuaW1wb3J0IHR5cGUgeyBMb2NhbEpTWENvbW1hbmRPbkRvbmUgfSBmcm9tICcuLi8uLi90eXBlcy9jb21tYW5kLmpzJ1xuaW1wb3J0IHtcbiAgZ2V0Q2xhdWRlQUlPQXV0aFRva2VucyxcbiAgaXNDbGF1ZGVBSVN1YnNjcmliZXIsXG59IGZyb20gJy4uLy4uL3V0aWxzL2F1dGguanMnXG5pbXBvcnQgeyBvcGVuQnJvd3NlciB9IGZyb20gJy4uLy4uL3V0aWxzL2Jyb3dzZXIuanMnXG5pbXBvcnQgeyBsb2dFcnJvciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcydcbmltcG9ydCB7IExvZ2luIH0gZnJvbSAnLi4vbG9naW4vbG9naW4uanMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjYWxsKFxuICBvbkRvbmU6IExvY2FsSlNYQ29tbWFuZE9uRG9uZSxcbiAgY29udGV4dDogTG9jYWxKU1hDb21tYW5kQ29udGV4dCxcbik6IFByb21pc2U8UmVhY3QuUmVhY3ROb2RlIHwgbnVsbD4ge1xuICB0cnkge1xuICAgIC8vIENoZWNrIGlmIHVzZXIgaXMgYWxyZWFkeSBvbiB0aGUgaGlnaGVzdCBNYXggcGxhbiAoMjB4KVxuICAgIGlmIChpc0NsYXVkZUFJU3Vic2NyaWJlcigpKSB7XG4gICAgICBjb25zdCB0b2tlbnMgPSBnZXRDbGF1ZGVBSU9BdXRoVG9rZW5zKClcbiAgICAgIGxldCBpc01heDIweCA9IGZhbHNlXG5cbiAgICAgIGlmICh0b2tlbnM/LnN1YnNjcmlwdGlvblR5cGUgJiYgdG9rZW5zPy5yYXRlTGltaXRUaWVyKSB7XG4gICAgICAgIGlzTWF4MjB4ID1cbiAgICAgICAgICB0b2tlbnMuc3Vic2NyaXB0aW9uVHlwZSA9PT0gJ21heCcgJiZcbiAgICAgICAgICB0b2tlbnMucmF0ZUxpbWl0VGllciA9PT0gJ2RlZmF1bHRfY2xhdWRlX21heF8yMHgnXG4gICAgICB9IGVsc2UgaWYgKHRva2Vucz8uYWNjZXNzVG9rZW4pIHtcbiAgICAgICAgY29uc3QgcHJvZmlsZSA9IGF3YWl0IGdldE9hdXRoUHJvZmlsZUZyb21PYXV0aFRva2VuKHRva2Vucy5hY2Nlc3NUb2tlbilcbiAgICAgICAgaXNNYXgyMHggPVxuICAgICAgICAgIHByb2ZpbGU/Lm9yZ2FuaXphdGlvbj8ub3JnYW5pemF0aW9uX3R5cGUgPT09ICdjbGF1ZGVfbWF4JyAmJlxuICAgICAgICAgIHByb2ZpbGU/Lm9yZ2FuaXphdGlvbj8ucmF0ZV9saW1pdF90aWVyID09PSAnZGVmYXVsdF9jbGF1ZGVfbWF4XzIweCdcbiAgICAgIH1cblxuICAgICAgaWYgKGlzTWF4MjB4KSB7XG4gICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgb25Eb25lLFxuICAgICAgICAgIDAsXG4gICAgICAgICAgJ1lvdSBhcmUgYWxyZWFkeSBvbiB0aGUgaGlnaGVzdCBNYXggc3Vic2NyaXB0aW9uIHBsYW4uIEZvciBhZGRpdGlvbmFsIHVzYWdlLCBydW4gL2xvZ2luIHRvIHN3aXRjaCB0byBhbiBBUEkgdXNhZ2UtYmlsbGVkIGFjY291bnQuJyxcbiAgICAgICAgKVxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHVybCA9ICdodHRwczovL2NsYXVkZS5haS91cGdyYWRlL21heCdcbiAgICBhd2FpdCBvcGVuQnJvd3Nlcih1cmwpXG5cbiAgICByZXR1cm4gKFxuICAgICAgPExvZ2luXG4gICAgICAgIHN0YXJ0aW5nTWVzc2FnZT17XG4gICAgICAgICAgJ1N0YXJ0aW5nIG5ldyBsb2dpbiBmb2xsb3dpbmcgL3VwZ3JhZGUuIEV4aXQgd2l0aCBDdHJsLUMgdG8gdXNlIGV4aXN0aW5nIGFjY291bnQuJ1xuICAgICAgICB9XG4gICAgICAgIG9uRG9uZT17c3VjY2VzcyA9PiB7XG4gICAgICAgICAgY29udGV4dC5vbkNoYW5nZUFQSUtleSgpXG4gICAgICAgICAgb25Eb25lKHN1Y2Nlc3MgPyAnTG9naW4gc3VjY2Vzc2Z1bCcgOiAnTG9naW4gaW50ZXJydXB0ZWQnKVxuICAgICAgICB9fVxuICAgICAgLz5cbiAgICApXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nRXJyb3IoZXJyb3IgYXMgRXJyb3IpXG4gICAgc2V0VGltZW91dChcbiAgICAgIG9uRG9uZSxcbiAgICAgIDAsXG4gICAgICAnRmFpbGVkIHRvIG9wZW4gYnJvd3Nlci4gUGxlYXNlIHZpc2l0IGh0dHBzOi8vY2xhdWRlLmFpL3VwZ3JhZGUvbWF4IHRvIHVwZ3JhZGUuJyxcbiAgICApXG4gIH1cbiAgcmV0dXJuIG51bGxcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLQSxLQUFLLE1BQU0sT0FBTztBQUM5QixjQUFjQyxzQkFBc0IsUUFBUSxtQkFBbUI7QUFDL0QsU0FBU0MsNkJBQTZCLFFBQVEseUNBQXlDO0FBQ3ZGLGNBQWNDLHFCQUFxQixRQUFRLHdCQUF3QjtBQUNuRSxTQUNFQyxzQkFBc0IsRUFDdEJDLG9CQUFvQixRQUNmLHFCQUFxQjtBQUM1QixTQUFTQyxXQUFXLFFBQVEsd0JBQXdCO0FBQ3BELFNBQVNDLFFBQVEsUUFBUSxvQkFBb0I7QUFDN0MsU0FBU0MsS0FBSyxRQUFRLG1CQUFtQjtBQUV6QyxPQUFPLGVBQWVDLElBQUlBLENBQ3hCQyxNQUFNLEVBQUVQLHFCQUFxQixFQUM3QlEsT0FBTyxFQUFFVixzQkFBc0IsQ0FDaEMsRUFBRVcsT0FBTyxDQUFDWixLQUFLLENBQUNhLFNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQztFQUNqQyxJQUFJO0lBQ0Y7SUFDQSxJQUFJUixvQkFBb0IsQ0FBQyxDQUFDLEVBQUU7TUFDMUIsTUFBTVMsTUFBTSxHQUFHVixzQkFBc0IsQ0FBQyxDQUFDO01BQ3ZDLElBQUlXLFFBQVEsR0FBRyxLQUFLO01BRXBCLElBQUlELE1BQU0sRUFBRUUsZ0JBQWdCLElBQUlGLE1BQU0sRUFBRUcsYUFBYSxFQUFFO1FBQ3JERixRQUFRLEdBQ05ELE1BQU0sQ0FBQ0UsZ0JBQWdCLEtBQUssS0FBSyxJQUNqQ0YsTUFBTSxDQUFDRyxhQUFhLEtBQUssd0JBQXdCO01BQ3JELENBQUMsTUFBTSxJQUFJSCxNQUFNLEVBQUVJLFdBQVcsRUFBRTtRQUM5QixNQUFNQyxPQUFPLEdBQUcsTUFBTWpCLDZCQUE2QixDQUFDWSxNQUFNLENBQUNJLFdBQVcsQ0FBQztRQUN2RUgsUUFBUSxHQUNOSSxPQUFPLEVBQUVDLFlBQVksRUFBRUMsaUJBQWlCLEtBQUssWUFBWSxJQUN6REYsT0FBTyxFQUFFQyxZQUFZLEVBQUVFLGVBQWUsS0FBSyx3QkFBd0I7TUFDdkU7TUFFQSxJQUFJUCxRQUFRLEVBQUU7UUFDWlEsVUFBVSxDQUNSYixNQUFNLEVBQ04sQ0FBQyxFQUNELGtJQUNGLENBQUM7UUFDRCxPQUFPLElBQUk7TUFDYjtJQUNGO0lBRUEsTUFBTWMsR0FBRyxHQUFHLCtCQUErQjtJQUMzQyxNQUFNbEIsV0FBVyxDQUFDa0IsR0FBRyxDQUFDO0lBRXRCLE9BQ0UsQ0FBQyxLQUFLLENBQ0osZUFBZSxDQUFDLENBQ2Qsa0ZBQ0YsQ0FBQyxDQUNELE1BQU0sQ0FBQyxDQUFDQyxPQUFPLElBQUk7TUFDakJkLE9BQU8sQ0FBQ2UsY0FBYyxDQUFDLENBQUM7TUFDeEJoQixNQUFNLENBQUNlLE9BQU8sR0FBRyxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztJQUM1RCxDQUFDLENBQUMsR0FDRjtFQUVOLENBQUMsQ0FBQyxPQUFPRSxLQUFLLEVBQUU7SUFDZHBCLFFBQVEsQ0FBQ29CLEtBQUssSUFBSUMsS0FBSyxDQUFDO0lBQ3hCTCxVQUFVLENBQ1JiLE1BQU0sRUFDTixDQUFDLEVBQ0QsZ0ZBQ0YsQ0FBQztFQUNIO0VBQ0EsT0FBTyxJQUFJO0FBQ2IiLCJpZ25vcmVMaXN0IjpbXX0= \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/commands/voice/index.ts b/_all-in-one-upload/cc-haha/src/commands/voice/index.ts new file mode 100644 index 0000000..61540d3 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/commands/voice/index.ts @@ -0,0 +1,20 @@ +import type { Command } from '../../commands.js' +import { + isVoiceGrowthBookEnabled, + isVoiceModeEnabled, +} from '../../voice/voiceModeEnabled.js' + +const voice = { + type: 'local', + name: 'voice', + description: 'Toggle voice mode', + availability: ['claude-ai'], + isEnabled: () => isVoiceGrowthBookEnabled(), + get isHidden() { + return !isVoiceModeEnabled() + }, + supportsNonInteractive: false, + load: () => import('./voice.js'), +} satisfies Command + +export default voice diff --git a/_all-in-one-upload/cc-haha/src/components/CustomSelect/select-input-option.tsx b/_all-in-one-upload/cc-haha/src/components/CustomSelect/select-input-option.tsx new file mode 100644 index 0000000..51e60ce --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/CustomSelect/select-input-option.tsx @@ -0,0 +1,488 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { type ReactNode, useEffect, useRef, useState } from 'react'; +// eslint-disable-next-line custom-rules/prefer-use-keybindings -- UP arrow exit not in Attachments bindings +import { Box, Text, useInput } from '../../ink.js'; +import { useKeybinding, useKeybindings } from '../../keybindings/useKeybinding.js'; +import type { PastedContent } from '../../utils/config.js'; +import { getImageFromClipboard } from '../../utils/imagePaste.js'; +import type { ImageDimensions } from '../../utils/imageResizer.js'; +import { ClickableImageRef } from '../ClickableImageRef.js'; +import { ConfigurableShortcutHint } from '../ConfigurableShortcutHint.js'; +import { Byline } from '../design-system/Byline.js'; +import TextInput from '../TextInput.js'; +import type { OptionWithDescription } from './select.js'; +import { SelectOption } from './select-option.js'; +type Props = { + option: Extract, { + type: 'input'; + }>; + isFocused: boolean; + isSelected: boolean; + shouldShowDownArrow: boolean; + shouldShowUpArrow: boolean; + maxIndexWidth: number; + index: number; + inputValue: string; + onInputChange: (value: string) => void; + onSubmit: (value: string) => void; + onExit?: () => void; + layout: 'compact' | 'expanded'; + children?: ReactNode; + /** + * When true, shows the label before the input field. + * When false (default), uses the label as the placeholder. + */ + showLabel?: boolean; + /** + * Callback to open external editor for editing the input value. + * When provided, ctrl+g will trigger this callback with the current value + * and a setter function to update the internal state. + */ + onOpenEditor?: (currentValue: string, setValue: (value: string) => void) => void; + /** + * When true, automatically reset cursor to end of line when: + * - Option becomes focused + * - Input value changes + * This prevents cursor position bugs when the input value updates asynchronously. + */ + resetCursorOnUpdate?: boolean; + /** + * Optional callback when an image is pasted into the input. + */ + onImagePaste?: (base64Image: string, mediaType?: string, filename?: string, dimensions?: ImageDimensions, sourcePath?: string) => void; + /** + * Pasted content to display inline above the input when focused. + */ + pastedContents?: Record; + /** + * Callback to remove a pasted image by its ID. + */ + onRemoveImage?: (id: number) => void; + /** + * Whether image selection mode is active. + */ + imagesSelected?: boolean; + /** + * Currently selected image index within the image attachments array. + */ + selectedImageIndex?: number; + /** + * Callback to set image selection mode on/off. + */ + onImagesSelectedChange?: (selected: boolean) => void; + /** + * Callback to change the selected image index. + */ + onSelectedImageIndexChange?: (index: number) => void; +}; +export function SelectInputOption(t0) { + const $ = _c(100); + const { + option, + isFocused, + isSelected, + shouldShowDownArrow, + shouldShowUpArrow, + maxIndexWidth, + index, + inputValue, + onInputChange, + onSubmit, + onExit, + layout, + children, + showLabel: t1, + onOpenEditor, + resetCursorOnUpdate: t2, + onImagePaste, + pastedContents, + onRemoveImage, + imagesSelected, + selectedImageIndex: t3, + onImagesSelectedChange, + onSelectedImageIndexChange + } = t0; + const showLabelProp = t1 === undefined ? false : t1; + const resetCursorOnUpdate = t2 === undefined ? false : t2; + const selectedImageIndex = t3 === undefined ? 0 : t3; + let t4; + if ($[0] !== pastedContents) { + t4 = pastedContents ? Object.values(pastedContents).filter(_temp) : []; + $[0] = pastedContents; + $[1] = t4; + } else { + t4 = $[1]; + } + const imageAttachments = t4; + const showLabel = showLabelProp || option.showLabelWithValue === true; + const [cursorOffset, setCursorOffset] = useState(inputValue.length); + const isUserEditing = useRef(false); + let t5; + if ($[2] !== inputValue.length || $[3] !== isFocused || $[4] !== resetCursorOnUpdate) { + t5 = () => { + if (resetCursorOnUpdate && isFocused) { + if (isUserEditing.current) { + isUserEditing.current = false; + } else { + setCursorOffset(inputValue.length); + } + } + }; + $[2] = inputValue.length; + $[3] = isFocused; + $[4] = resetCursorOnUpdate; + $[5] = t5; + } else { + t5 = $[5]; + } + let t6; + if ($[6] !== inputValue || $[7] !== isFocused || $[8] !== resetCursorOnUpdate) { + t6 = [resetCursorOnUpdate, isFocused, inputValue]; + $[6] = inputValue; + $[7] = isFocused; + $[8] = resetCursorOnUpdate; + $[9] = t6; + } else { + t6 = $[9]; + } + useEffect(t5, t6); + let t7; + if ($[10] !== inputValue || $[11] !== onInputChange || $[12] !== onOpenEditor) { + t7 = () => { + onOpenEditor?.(inputValue, onInputChange); + }; + $[10] = inputValue; + $[11] = onInputChange; + $[12] = onOpenEditor; + $[13] = t7; + } else { + t7 = $[13]; + } + const t8 = isFocused && !!onOpenEditor; + let t9; + if ($[14] !== t8) { + t9 = { + context: "Chat", + isActive: t8 + }; + $[14] = t8; + $[15] = t9; + } else { + t9 = $[15]; + } + useKeybinding("chat:externalEditor", t7, t9); + let t10; + if ($[16] !== onImagePaste) { + t10 = () => { + if (!onImagePaste) { + return; + } + getImageFromClipboard().then(imageData => { + if (imageData) { + onImagePaste(imageData.base64, imageData.mediaType, undefined, imageData.dimensions); + } + }); + }; + $[16] = onImagePaste; + $[17] = t10; + } else { + t10 = $[17]; + } + const t11 = isFocused && !!onImagePaste; + let t12; + if ($[18] !== t11) { + t12 = { + context: "Chat", + isActive: t11 + }; + $[18] = t11; + $[19] = t12; + } else { + t12 = $[19]; + } + useKeybinding("chat:imagePaste", t10, t12); + let t13; + if ($[20] !== imageAttachments || $[21] !== onRemoveImage) { + t13 = () => { + if (imageAttachments.length > 0 && onRemoveImage) { + onRemoveImage(imageAttachments.at(-1).id); + } + }; + $[20] = imageAttachments; + $[21] = onRemoveImage; + $[22] = t13; + } else { + t13 = $[22]; + } + const t14 = isFocused && !imagesSelected && inputValue === "" && imageAttachments.length > 0 && !!onRemoveImage; + let t15; + if ($[23] !== t14) { + t15 = { + context: "Attachments", + isActive: t14 + }; + $[23] = t14; + $[24] = t15; + } else { + t15 = $[24]; + } + useKeybinding("attachments:remove", t13, t15); + let t16; + let t17; + if ($[25] !== imageAttachments.length || $[26] !== onSelectedImageIndexChange || $[27] !== selectedImageIndex) { + t16 = () => { + if (imageAttachments.length > 1) { + onSelectedImageIndexChange?.((selectedImageIndex + 1) % imageAttachments.length); + } + }; + t17 = () => { + if (imageAttachments.length > 1) { + onSelectedImageIndexChange?.((selectedImageIndex - 1 + imageAttachments.length) % imageAttachments.length); + } + }; + $[25] = imageAttachments.length; + $[26] = onSelectedImageIndexChange; + $[27] = selectedImageIndex; + $[28] = t16; + $[29] = t17; + } else { + t16 = $[28]; + t17 = $[29]; + } + let t18; + if ($[30] !== imageAttachments || $[31] !== onImagesSelectedChange || $[32] !== onRemoveImage || $[33] !== onSelectedImageIndexChange || $[34] !== selectedImageIndex) { + t18 = () => { + const img = imageAttachments[selectedImageIndex]; + if (img && onRemoveImage) { + onRemoveImage(img.id); + if (imageAttachments.length <= 1) { + onImagesSelectedChange?.(false); + } else { + onSelectedImageIndexChange?.(Math.min(selectedImageIndex, imageAttachments.length - 2)); + } + } + }; + $[30] = imageAttachments; + $[31] = onImagesSelectedChange; + $[32] = onRemoveImage; + $[33] = onSelectedImageIndexChange; + $[34] = selectedImageIndex; + $[35] = t18; + } else { + t18 = $[35]; + } + let t19; + if ($[36] !== onImagesSelectedChange) { + t19 = () => { + onImagesSelectedChange?.(false); + }; + $[36] = onImagesSelectedChange; + $[37] = t19; + } else { + t19 = $[37]; + } + let t20; + if ($[38] !== t16 || $[39] !== t17 || $[40] !== t18 || $[41] !== t19) { + t20 = { + "attachments:next": t16, + "attachments:previous": t17, + "attachments:remove": t18, + "attachments:exit": t19 + }; + $[38] = t16; + $[39] = t17; + $[40] = t18; + $[41] = t19; + $[42] = t20; + } else { + t20 = $[42]; + } + const t21 = isFocused && !!imagesSelected; + let t22; + if ($[43] !== t21) { + t22 = { + context: "Attachments", + isActive: t21 + }; + $[43] = t21; + $[44] = t22; + } else { + t22 = $[44]; + } + useKeybindings(t20, t22); + let t23; + if ($[45] !== onImagesSelectedChange) { + t23 = (_input, key) => { + if (key.upArrow) { + onImagesSelectedChange?.(false); + } + }; + $[45] = onImagesSelectedChange; + $[46] = t23; + } else { + t23 = $[46]; + } + const t24 = isFocused && !!imagesSelected; + let t25; + if ($[47] !== t24) { + t25 = { + isActive: t24 + }; + $[47] = t24; + $[48] = t25; + } else { + t25 = $[48]; + } + useInput(t23, t25); + let t26; + let t27; + if ($[49] !== imagesSelected || $[50] !== isFocused || $[51] !== onImagesSelectedChange) { + t26 = () => { + if (!isFocused && imagesSelected) { + onImagesSelectedChange?.(false); + } + }; + t27 = [isFocused, imagesSelected, onImagesSelectedChange]; + $[49] = imagesSelected; + $[50] = isFocused; + $[51] = onImagesSelectedChange; + $[52] = t26; + $[53] = t27; + } else { + t26 = $[52]; + t27 = $[53]; + } + useEffect(t26, t27); + const descriptionPaddingLeft = layout === "expanded" ? maxIndexWidth + 3 : maxIndexWidth + 4; + const t28 = layout === "compact" ? 0 : undefined; + const t29 = `${index}.`; + let t30; + if ($[54] !== maxIndexWidth || $[55] !== t29) { + t30 = t29.padEnd(maxIndexWidth + 2); + $[54] = maxIndexWidth; + $[55] = t29; + $[56] = t30; + } else { + t30 = $[56]; + } + let t31; + if ($[57] !== t30) { + t31 = {t30}; + $[57] = t30; + $[58] = t31; + } else { + t31 = $[58]; + } + let t32; + if ($[59] !== cursorOffset || $[60] !== imagesSelected || $[61] !== inputValue || $[62] !== isFocused || $[63] !== onExit || $[64] !== onImagePaste || $[65] !== onInputChange || $[66] !== onSubmit || $[67] !== option || $[68] !== showLabel) { + t32 = showLabel ? <>{option.label}{isFocused ? <>{option.labelValueSeparator ?? ", "} { + isUserEditing.current = true; + onInputChange(value); + option.onChange(value); + }} onSubmit={onSubmit} onExit={onExit} placeholder={option.placeholder} focus={!imagesSelected} showCursor={true} multiline={true} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} columns={80} onImagePaste={onImagePaste} onPaste={pastedText => { + isUserEditing.current = true; + const before = inputValue.slice(0, cursorOffset); + const after = inputValue.slice(cursorOffset); + const newValue = before + pastedText + after; + onInputChange(newValue); + option.onChange(newValue); + setCursorOffset(before.length + pastedText.length); + }} /> : inputValue && {option.labelValueSeparator ?? ", "}{inputValue}} : isFocused ? { + isUserEditing.current = true; + onInputChange(value_0); + option.onChange(value_0); + }} onSubmit={onSubmit} onExit={onExit} placeholder={option.placeholder || (typeof option.label === "string" ? option.label : undefined)} focus={!imagesSelected} showCursor={true} multiline={true} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} columns={80} onImagePaste={onImagePaste} onPaste={pastedText_0 => { + isUserEditing.current = true; + const before_0 = inputValue.slice(0, cursorOffset); + const after_0 = inputValue.slice(cursorOffset); + const newValue_0 = before_0 + pastedText_0 + after_0; + onInputChange(newValue_0); + option.onChange(newValue_0); + setCursorOffset(before_0.length + pastedText_0.length); + }} /> : {inputValue || option.placeholder || option.label}; + $[59] = cursorOffset; + $[60] = imagesSelected; + $[61] = inputValue; + $[62] = isFocused; + $[63] = onExit; + $[64] = onImagePaste; + $[65] = onInputChange; + $[66] = onSubmit; + $[67] = option; + $[68] = showLabel; + $[69] = t32; + } else { + t32 = $[69]; + } + let t33; + if ($[70] !== children || $[71] !== t28 || $[72] !== t31 || $[73] !== t32) { + t33 = {t31}{children}{t32}; + $[70] = children; + $[71] = t28; + $[72] = t31; + $[73] = t32; + $[74] = t33; + } else { + t33 = $[74]; + } + let t34; + if ($[75] !== isFocused || $[76] !== isSelected || $[77] !== shouldShowDownArrow || $[78] !== shouldShowUpArrow || $[79] !== t33) { + t34 = {t33}; + $[75] = isFocused; + $[76] = isSelected; + $[77] = shouldShowDownArrow; + $[78] = shouldShowUpArrow; + $[79] = t33; + $[80] = t34; + } else { + t34 = $[80]; + } + let t35; + if ($[81] !== descriptionPaddingLeft || $[82] !== isFocused || $[83] !== isSelected || $[84] !== option.description || $[85] !== option.dimDescription) { + t35 = option.description && {option.description}; + $[81] = descriptionPaddingLeft; + $[82] = isFocused; + $[83] = isSelected; + $[84] = option.description; + $[85] = option.dimDescription; + $[86] = t35; + } else { + t35 = $[86]; + } + let t36; + if ($[87] !== descriptionPaddingLeft || $[88] !== imageAttachments || $[89] !== imagesSelected || $[90] !== isFocused || $[91] !== selectedImageIndex) { + t36 = imageAttachments.length > 0 && {imageAttachments.map((img_0, idx) => )}{imagesSelected ? {imageAttachments.length > 1 && <>} : isFocused ? "(\u2193 to select)" : null}; + $[87] = descriptionPaddingLeft; + $[88] = imageAttachments; + $[89] = imagesSelected; + $[90] = isFocused; + $[91] = selectedImageIndex; + $[92] = t36; + } else { + t36 = $[92]; + } + let t37; + if ($[93] !== layout) { + t37 = layout === "expanded" && ; + $[93] = layout; + $[94] = t37; + } else { + t37 = $[94]; + } + let t38; + if ($[95] !== t34 || $[96] !== t35 || $[97] !== t36 || $[98] !== t37) { + t38 = {t34}{t35}{t36}{t37}; + $[95] = t34; + $[96] = t35; + $[97] = t36; + $[98] = t37; + $[99] = t38; + } else { + t38 = $[99]; + } + return t38; +} +function _temp(c) { + return c.type === "image"; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlJlYWN0Tm9kZSIsInVzZUVmZmVjdCIsInVzZVJlZiIsInVzZVN0YXRlIiwiQm94IiwiVGV4dCIsInVzZUlucHV0IiwidXNlS2V5YmluZGluZyIsInVzZUtleWJpbmRpbmdzIiwiUGFzdGVkQ29udGVudCIsImdldEltYWdlRnJvbUNsaXBib2FyZCIsIkltYWdlRGltZW5zaW9ucyIsIkNsaWNrYWJsZUltYWdlUmVmIiwiQ29uZmlndXJhYmxlU2hvcnRjdXRIaW50IiwiQnlsaW5lIiwiVGV4dElucHV0IiwiT3B0aW9uV2l0aERlc2NyaXB0aW9uIiwiU2VsZWN0T3B0aW9uIiwiUHJvcHMiLCJvcHRpb24iLCJFeHRyYWN0IiwiVCIsInR5cGUiLCJpc0ZvY3VzZWQiLCJpc1NlbGVjdGVkIiwic2hvdWxkU2hvd0Rvd25BcnJvdyIsInNob3VsZFNob3dVcEFycm93IiwibWF4SW5kZXhXaWR0aCIsImluZGV4IiwiaW5wdXRWYWx1ZSIsIm9uSW5wdXRDaGFuZ2UiLCJ2YWx1ZSIsIm9uU3VibWl0Iiwib25FeGl0IiwibGF5b3V0IiwiY2hpbGRyZW4iLCJzaG93TGFiZWwiLCJvbk9wZW5FZGl0b3IiLCJjdXJyZW50VmFsdWUiLCJzZXRWYWx1ZSIsInJlc2V0Q3Vyc29yT25VcGRhdGUiLCJvbkltYWdlUGFzdGUiLCJiYXNlNjRJbWFnZSIsIm1lZGlhVHlwZSIsImZpbGVuYW1lIiwiZGltZW5zaW9ucyIsInNvdXJjZVBhdGgiLCJwYXN0ZWRDb250ZW50cyIsIlJlY29yZCIsIm9uUmVtb3ZlSW1hZ2UiLCJpZCIsImltYWdlc1NlbGVjdGVkIiwic2VsZWN0ZWRJbWFnZUluZGV4Iiwib25JbWFnZXNTZWxlY3RlZENoYW5nZSIsInNlbGVjdGVkIiwib25TZWxlY3RlZEltYWdlSW5kZXhDaGFuZ2UiLCJTZWxlY3RJbnB1dE9wdGlvbiIsInQwIiwiJCIsIl9jIiwidDEiLCJ0MiIsInQzIiwic2hvd0xhYmVsUHJvcCIsInVuZGVmaW5lZCIsInQ0IiwiT2JqZWN0IiwidmFsdWVzIiwiZmlsdGVyIiwiX3RlbXAiLCJpbWFnZUF0dGFjaG1lbnRzIiwic2hvd0xhYmVsV2l0aFZhbHVlIiwiY3Vyc29yT2Zmc2V0Iiwic2V0Q3Vyc29yT2Zmc2V0IiwibGVuZ3RoIiwiaXNVc2VyRWRpdGluZyIsInQ1IiwiY3VycmVudCIsInQ2IiwidDciLCJ0OCIsInQ5IiwiY29udGV4dCIsImlzQWN0aXZlIiwidDEwIiwidGhlbiIsImltYWdlRGF0YSIsImJhc2U2NCIsInQxMSIsInQxMiIsInQxMyIsImF0IiwidDE0IiwidDE1IiwidDE2IiwidDE3IiwidDE4IiwiaW1nIiwiTWF0aCIsIm1pbiIsInQxOSIsInQyMCIsInQyMSIsInQyMiIsInQyMyIsIl9pbnB1dCIsImtleSIsInVwQXJyb3ciLCJ0MjQiLCJ0MjUiLCJ0MjYiLCJ0MjciLCJkZXNjcmlwdGlvblBhZGRpbmdMZWZ0IiwidDI4IiwidDI5IiwidDMwIiwicGFkRW5kIiwidDMxIiwidDMyIiwibGFiZWwiLCJsYWJlbFZhbHVlU2VwYXJhdG9yIiwib25DaGFuZ2UiLCJwbGFjZWhvbGRlciIsInBhc3RlZFRleHQiLCJiZWZvcmUiLCJzbGljZSIsImFmdGVyIiwibmV3VmFsdWUiLCJ2YWx1ZV8wIiwicGFzdGVkVGV4dF8wIiwiYmVmb3JlXzAiLCJhZnRlcl8wIiwibmV3VmFsdWVfMCIsInQzMyIsInQzNCIsInQzNSIsImRlc2NyaXB0aW9uIiwiZGltRGVzY3JpcHRpb24iLCJ0MzYiLCJtYXAiLCJpbWdfMCIsImlkeCIsInQzNyIsInQzOCIsImMiXSwic291cmNlcyI6WyJzZWxlY3QtaW5wdXQtb3B0aW9uLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgdHlwZSBSZWFjdE5vZGUsIHVzZUVmZmVjdCwgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGN1c3RvbS1ydWxlcy9wcmVmZXItdXNlLWtleWJpbmRpbmdzIC0tIFVQIGFycm93IGV4aXQgbm90IGluIEF0dGFjaG1lbnRzIGJpbmRpbmdzXG5pbXBvcnQgeyBCb3gsIFRleHQsIHVzZUlucHV0IH0gZnJvbSAnLi4vLi4vaW5rLmpzJ1xuaW1wb3J0IHtcbiAgdXNlS2V5YmluZGluZyxcbiAgdXNlS2V5YmluZGluZ3MsXG59IGZyb20gJy4uLy4uL2tleWJpbmRpbmdzL3VzZUtleWJpbmRpbmcuanMnXG5pbXBvcnQgdHlwZSB7IFBhc3RlZENvbnRlbnQgfSBmcm9tICcuLi8uLi91dGlscy9jb25maWcuanMnXG5pbXBvcnQgeyBnZXRJbWFnZUZyb21DbGlwYm9hcmQgfSBmcm9tICcuLi8uLi91dGlscy9pbWFnZVBhc3RlLmpzJ1xuaW1wb3J0IHR5cGUgeyBJbWFnZURpbWVuc2lvbnMgfSBmcm9tICcuLi8uLi91dGlscy9pbWFnZVJlc2l6ZXIuanMnXG5pbXBvcnQgeyBDbGlja2FibGVJbWFnZVJlZiB9IGZyb20gJy4uL0NsaWNrYWJsZUltYWdlUmVmLmpzJ1xuaW1wb3J0IHsgQ29uZmlndXJhYmxlU2hvcnRjdXRIaW50IH0gZnJvbSAnLi4vQ29uZmlndXJhYmxlU2hvcnRjdXRIaW50LmpzJ1xuaW1wb3J0IHsgQnlsaW5lIH0gZnJvbSAnLi4vZGVzaWduLXN5c3RlbS9CeWxpbmUuanMnXG5pbXBvcnQgVGV4dElucHV0IGZyb20gJy4uL1RleHRJbnB1dC5qcydcbmltcG9ydCB0eXBlIHsgT3B0aW9uV2l0aERlc2NyaXB0aW9uIH0gZnJvbSAnLi9zZWxlY3QuanMnXG5pbXBvcnQgeyBTZWxlY3RPcHRpb24gfSBmcm9tICcuL3NlbGVjdC1vcHRpb24uanMnXG5cbnR5cGUgUHJvcHM8VD4gPSB7XG4gIG9wdGlvbjogRXh0cmFjdDxPcHRpb25XaXRoRGVzY3JpcHRpb248VD4sIHsgdHlwZTogJ2lucHV0JyB9PlxuICBpc0ZvY3VzZWQ6IGJvb2xlYW5cbiAgaXNTZWxlY3RlZDogYm9vbGVhblxuICBzaG91bGRTaG93RG93bkFycm93OiBib29sZWFuXG4gIHNob3VsZFNob3dVcEFycm93OiBib29sZWFuXG4gIG1heEluZGV4V2lkdGg6IG51bWJlclxuICBpbmRleDogbnVtYmVyXG4gIGlucHV0VmFsdWU6IHN0cmluZ1xuICBvbklucHV0Q2hhbmdlOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZFxuICBvblN1Ym1pdDogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWRcbiAgb25FeGl0PzogKCkgPT4gdm9pZFxuICBsYXlvdXQ6ICdjb21wYWN0JyB8ICdleHBhbmRlZCdcbiAgY2hpbGRyZW4/OiBSZWFjdE5vZGVcbiAgLyoqXG4gICAqIFdoZW4gdHJ1ZSwgc2hvd3MgdGhlIGxhYmVsIGJlZm9yZSB0aGUgaW5wdXQgZmllbGQuXG4gICAqIFdoZW4gZmFsc2UgKGRlZmF1bHQpLCB1c2VzIHRoZSBsYWJlbCBhcyB0aGUgcGxhY2Vob2xkZXIuXG4gICAqL1xuICBzaG93TGFiZWw/OiBib29sZWFuXG4gIC8qKlxuICAgKiBDYWxsYmFjayB0byBvcGVuIGV4dGVybmFsIGVkaXRvciBmb3IgZWRpdGluZyB0aGUgaW5wdXQgdmFsdWUuXG4gICAqIFdoZW4gcHJvdmlkZWQsIGN0cmwrZyB3aWxsIHRyaWdnZXIgdGhpcyBjYWxsYmFjayB3aXRoIHRoZSBjdXJyZW50IHZhbHVlXG4gICAqIGFuZCBhIHNldHRlciBmdW5jdGlvbiB0byB1cGRhdGUgdGhlIGludGVybmFsIHN0YXRlLlxuICAgKi9cbiAgb25PcGVuRWRpdG9yPzogKFxuICAgIGN1cnJlbnRWYWx1ZTogc3RyaW5nLFxuICAgIHNldFZhbHVlOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZCxcbiAgKSA9PiB2b2lkXG4gIC8qKlxuICAgKiBXaGVuIHRydWUsIGF1dG9tYXRpY2FsbHkgcmVzZXQgY3Vyc29yIHRvIGVuZCBvZiBsaW5lIHdoZW46XG4gICAqIC0gT3B0aW9uIGJlY29tZXMgZm9jdXNlZFxuICAgKiAtIElucHV0IHZhbHVlIGNoYW5nZXNcbiAgICogVGhpcyBwcmV2ZW50cyBjdXJzb3IgcG9zaXRpb24gYnVncyB3aGVuIHRoZSBpbnB1dCB2YWx1ZSB1cGRhdGVzIGFzeW5jaHJvbm91c2x5LlxuICAgKi9cbiAgcmVzZXRDdXJzb3JPblVwZGF0ZT86IGJvb2xlYW5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGNhbGxiYWNrIHdoZW4gYW4gaW1hZ2UgaXMgcGFzdGVkIGludG8gdGhlIGlucHV0LlxuICAgKi9cbiAgb25JbWFnZVBhc3RlPzogKFxuICAgIGJhc2U2NEltYWdlOiBzdHJpbmcsXG4gICAgbWVkaWFUeXBlPzogc3RyaW5nLFxuICAgIGZpbGVuYW1lPzogc3RyaW5nLFxuICAgIGRpbWVuc2lvbnM/OiBJbWFnZURpbWVuc2lvbnMsXG4gICAgc291cmNlUGF0aD86IHN0cmluZyxcbiAgKSA9PiB2b2lkXG4gIC8qKlxuICAgKiBQYXN0ZWQgY29udGVudCB0byBkaXNwbGF5IGlubGluZSBhYm92ZSB0aGUgaW5wdXQgd2hlbiBmb2N1c2VkLlxuICAgKi9cbiAgcGFzdGVkQ29udGVudHM/OiBSZWNvcmQ8bnVtYmVyLCBQYXN0ZWRDb250ZW50PlxuICAvKipcbiAgICogQ2FsbGJhY2sgdG8gcmVtb3ZlIGEgcGFzdGVkIGltYWdlIGJ5IGl0cyBJRC5cbiAgICovXG4gIG9uUmVtb3ZlSW1hZ2U/OiAoaWQ6IG51bWJlcikgPT4gdm9pZFxuICAvKipcbiAgICogV2hldGhlciBpbWFnZSBzZWxlY3Rpb24gbW9kZSBpcyBhY3RpdmUuXG4gICAqL1xuICBpbWFnZXNTZWxlY3RlZD86IGJvb2xlYW5cbiAgLyoqXG4gICAqIEN1cnJlbnRseSBzZWxlY3RlZCBpbWFnZSBpbmRleCB3aXRoaW4gdGhlIGltYWdlIGF0dGFjaG1lbnRzIGFycmF5LlxuICAgKi9cbiAgc2VsZWN0ZWRJbWFnZUluZGV4PzogbnVtYmVyXG4gIC8qKlxuICAgKiBDYWxsYmFjayB0byBzZXQgaW1hZ2Ugc2VsZWN0aW9uIG1vZGUgb24vb2ZmLlxuICAgKi9cbiAgb25JbWFnZXNTZWxlY3RlZENoYW5nZT86IChzZWxlY3RlZDogYm9vbGVhbikgPT4gdm9pZFxuICAvKipcbiAgICogQ2FsbGJhY2sgdG8gY2hhbmdlIHRoZSBzZWxlY3RlZCBpbWFnZSBpbmRleC5cbiAgICovXG4gIG9uU2VsZWN0ZWRJbWFnZUluZGV4Q2hhbmdlPzogKGluZGV4OiBudW1iZXIpID0+IHZvaWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNlbGVjdElucHV0T3B0aW9uPFQ+KHtcbiAgb3B0aW9uLFxuICBpc0ZvY3VzZWQsXG4gIGlzU2VsZWN0ZWQsXG4gIHNob3VsZFNob3dEb3duQXJyb3csXG4gIHNob3VsZFNob3dVcEFycm93LFxuICBtYXhJbmRleFdpZHRoLFxuICBpbmRleCxcbiAgaW5wdXRWYWx1ZSxcbiAgb25JbnB1dENoYW5nZSxcbiAgb25TdWJtaXQsXG4gIG9uRXhpdCxcbiAgbGF5b3V0LFxuICBjaGlsZHJlbixcbiAgc2hvd0xhYmVsOiBzaG93TGFiZWxQcm9wID0gZmFsc2UsXG4gIG9uT3BlbkVkaXRvcixcbiAgcmVzZXRDdXJzb3JPblVwZGF0ZSA9IGZhbHNlLFxuICBvbkltYWdlUGFzdGUsXG4gIHBhc3RlZENvbnRlbnRzLFxuICBvblJlbW92ZUltYWdlLFxuICBpbWFnZXNTZWxlY3RlZCxcbiAgc2VsZWN0ZWRJbWFnZUluZGV4ID0gMCxcbiAgb25JbWFnZXNTZWxlY3RlZENoYW5nZSxcbiAgb25TZWxlY3RlZEltYWdlSW5kZXhDaGFuZ2UsXG59OiBQcm9wczxUPik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IGltYWdlQXR0YWNobWVudHMgPSBwYXN0ZWRDb250ZW50c1xuICAgID8gT2JqZWN0LnZhbHVlcyhwYXN0ZWRDb250ZW50cykuZmlsdGVyKGMgPT4gYy50eXBlID09PSAnaW1hZ2UnKVxuICAgIDogW11cblxuICAvLyBBbGxvdyBpbmRpdmlkdWFsIG9wdGlvbnMgdG8gZm9yY2Ugc2hvd2luZyB0aGUgbGFiZWwgdmlhIHNob3dMYWJlbFdpdGhWYWx1ZVxuICBjb25zdCBzaG93TGFiZWwgPSBzaG93TGFiZWxQcm9wIHx8IG9wdGlvbi5zaG93TGFiZWxXaXRoVmFsdWUgPT09IHRydWVcbiAgY29uc3QgW2N1cnNvck9mZnNldCwgc2V0Q3Vyc29yT2Zmc2V0XSA9IHVzZVN0YXRlKGlucHV0VmFsdWUubGVuZ3RoKVxuXG4gIC8vIFRyYWNrIHdoZXRoZXIgdGhlIGxhdGVzdCBpbnB1dFZhbHVlIGNoYW5nZSB3YXMgZnJvbSB1c2VyIHR5cGluZy9wYXN0aW5nLFxuICAvLyBzbyB3ZSBjYW4gc2tpcCByZXNldHRpbmcgY3Vyc29yIHRvIGVuZCBvbiB1c2VyLWluaXRpYXRlZCBjaGFuZ2VzLlxuICBjb25zdCBpc1VzZXJFZGl0aW5nID0gdXNlUmVmKGZhbHNlKVxuXG4gIC8vIFJlc2V0IGN1cnNvciB0byBlbmQgb2YgbGluZSB3aGVuOlxuICAvLyAxLiBPcHRpb24gYmVjb21lcyBmb2N1c2VkICh1c2VyIG5hdmlnYXRlcyB0byBpdClcbiAgLy8gMi4gSW5wdXQgdmFsdWUgY2hhbmdlcyBleHRlcm5hbGx5IChlLmcuLCBhc3luYyBjbGFzc2lmaWVyIGRlc2NyaXB0aW9uIHVwZGF0ZXMpXG4gIC8vIFNraXAgcmVzZXQgd2hlbiB0aGUgY2hhbmdlIHdhcyBmcm9tIHVzZXIgdHlwaW5nICh3aGljaCBzZXRzIGlzVXNlckVkaXRpbmcgcmVmKVxuICAvLyBPbmx5IGVuYWJsZWQgd2hlbiByZXNldEN1cnNvck9uVXBkYXRlIHByb3AgaXMgdHJ1ZVxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChyZXNldEN1cnNvck9uVXBkYXRlICYmIGlzRm9jdXNlZCkge1xuICAgICAgaWYgKGlzVXNlckVkaXRpbmcuY3VycmVudCkge1xuICAgICAgICBpc1VzZXJFZGl0aW5nLmN1cnJlbnQgPSBmYWxzZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2V0Q3Vyc29yT2Zmc2V0KGlucHV0VmFsdWUubGVuZ3RoKVxuICAgICAgfVxuICAgIH1cbiAgfSwgW3Jlc2V0Q3Vyc29yT25VcGRhdGUsIGlzRm9jdXNlZCwgaW5wdXRWYWx1ZV0pXG5cbiAgLy8gY3RybCtnIHRvIG9wZW4gZXh0ZXJuYWwgZWRpdG9yIChyZXVzZXMgY2hhdDpleHRlcm5hbEVkaXRvciBrZXliaW5kaW5nKVxuICB1c2VLZXliaW5kaW5nKFxuICAgICdjaGF0OmV4dGVybmFsRWRpdG9yJyxcbiAgICAoKSA9PiB7XG4gICAgICBvbk9wZW5FZGl0b3I/LihpbnB1dFZhbHVlLCBvbklucHV0Q2hhbmdlKVxuICAgIH0sXG4gICAgeyBjb250ZXh0OiAnQ2hhdCcsIGlzQWN0aXZlOiBpc0ZvY3VzZWQgJiYgISFvbk9wZW5FZGl0b3IgfSxcbiAgKVxuXG4gIC8vIGN0cmwrdiB0byBwYXN0ZSBpbWFnZSBmcm9tIGNsaXBib2FyZCAoc2FtZSBhcyBQcm9tcHRJbnB1dClcbiAgdXNlS2V5YmluZGluZyhcbiAgICAnY2hhdDppbWFnZVBhc3RlJyxcbiAgICAoKSA9PiB7XG4gICAgICBpZiAoIW9uSW1hZ2VQYXN0ZSkgcmV0dXJuXG4gICAgICB2b2lkIGdldEltYWdlRnJvbUNsaXBib2FyZCgpLnRoZW4oaW1hZ2VEYXRhID0+IHtcbiAgICAgICAgaWYgKGltYWdlRGF0YSkge1xuICAgICAgICAgIG9uSW1hZ2VQYXN0ZShcbiAgICAgICAgICAgIGltYWdlRGF0YS5iYXNlNjQsXG4gICAgICAgICAgICBpbWFnZURhdGEubWVkaWFUeXBlLFxuICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgaW1hZ2VEYXRhLmRpbWVuc2lvbnMsXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0sXG4gICAgeyBjb250ZXh0OiAnQ2hhdCcsIGlzQWN0aXZlOiBpc0ZvY3VzZWQgJiYgISFvbkltYWdlUGFzdGUgfSxcbiAgKVxuXG4gIC8vIEJhY2tzcGFjZSB3aXRoIGVtcHR5IGlucHV0IHJlbW92ZXMgdGhlIGxhc3QgcGFzdGVkIGltYWdlIChub24taW1hZ2Utc2VsZWN0aW9uIG1vZGUpXG4gIHVzZUtleWJpbmRpbmcoXG4gICAgJ2F0dGFjaG1lbnRzOnJlbW92ZScsXG4gICAgKCkgPT4ge1xuICAgICAgaWYgKGltYWdlQXR0YWNobWVudHMubGVuZ3RoID4gMCAmJiBvblJlbW92ZUltYWdlKSB7XG4gICAgICAgIG9uUmVtb3ZlSW1hZ2UoaW1hZ2VBdHRhY2htZW50cy5hdCgtMSkhLmlkKVxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgY29udGV4dDogJ0F0dGFjaG1lbnRzJyxcbiAgICAgIGlzQWN0aXZlOlxuICAgICAgICBpc0ZvY3VzZWQgJiZcbiAgICAgICAgIWltYWdlc1NlbGVjdGVkICYmXG4gICAgICAgIGlucHV0VmFsdWUgPT09ICcnICYmXG4gICAgICAgIGltYWdlQXR0YWNobWVudHMubGVuZ3RoID4gMCAmJlxuICAgICAgICAhIW9uUmVtb3ZlSW1hZ2UsXG4gICAgfSxcbiAgKVxuXG4gIC8vIEltYWdlIHNlbGVjdGlvbiBtb2RlIGtleWJpbmRpbmdzIOKAlCByZXVzZXMgZXhpc3RpbmcgQXR0YWNobWVudHMgYWN0aW9uc1xuICB1c2VLZXliaW5kaW5ncyhcbiAgICB7XG4gICAgICAnYXR0YWNobWVudHM6bmV4dCc6ICgpID0+IHtcbiAgICAgICAgaWYgKGltYWdlQXR0YWNobWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIG9uU2VsZWN0ZWRJbWFnZUluZGV4Q2hhbmdlPy4oXG4gICAgICAgICAgICAoc2VsZWN0ZWRJbWFnZUluZGV4ICsgMSkgJSBpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAnYXR0YWNobWVudHM6cHJldmlvdXMnOiAoKSA9PiB7XG4gICAgICAgIGlmIChpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBvblNlbGVjdGVkSW1hZ2VJbmRleENoYW5nZT8uKFxuICAgICAgICAgICAgKHNlbGVjdGVkSW1hZ2VJbmRleCAtIDEgKyBpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCkgJVxuICAgICAgICAgICAgICBpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAnYXR0YWNobWVudHM6cmVtb3ZlJzogKCkgPT4ge1xuICAgICAgICBjb25zdCBpbWcgPSBpbWFnZUF0dGFjaG1lbnRzW3NlbGVjdGVkSW1hZ2VJbmRleF1cbiAgICAgICAgaWYgKGltZyAmJiBvblJlbW92ZUltYWdlKSB7XG4gICAgICAgICAgb25SZW1vdmVJbWFnZShpbWcuaWQpXG4gICAgICAgICAgLy8gSWYgbm8gaW1hZ2VzIGxlZnQgYWZ0ZXIgcmVtb3ZhbCwgZXhpdCBpbWFnZSBzZWxlY3Rpb25cbiAgICAgICAgICBpZiAoaW1hZ2VBdHRhY2htZW50cy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgb25JbWFnZXNTZWxlY3RlZENoYW5nZT8uKGZhbHNlKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBZGp1c3QgaW5kZXggaWYgd2UgZGVsZXRlZCB0aGUgbGFzdCBpbWFnZVxuICAgICAgICAgICAgb25TZWxlY3RlZEltYWdlSW5kZXhDaGFuZ2U/LihcbiAgICAgICAgICAgICAgTWF0aC5taW4oc2VsZWN0ZWRJbWFnZUluZGV4LCBpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCAtIDIpLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgICdhdHRhY2htZW50czpleGl0JzogKCkgPT4ge1xuICAgICAgICBvbkltYWdlc1NlbGVjdGVkQ2hhbmdlPy4oZmFsc2UpXG4gICAgICB9LFxuICAgIH0sXG4gICAgeyBjb250ZXh0OiAnQXR0YWNobWVudHMnLCBpc0FjdGl2ZTogaXNGb2N1c2VkICYmICEhaW1hZ2VzU2VsZWN0ZWQgfSxcbiAgKVxuXG4gIC8vIFVQIGFycm93IGV4aXRzIGltYWdlIHNlbGVjdGlvbiBtb2RlIChVUCBpc24ndCBib3VuZCB0byBhdHRhY2htZW50czpleGl0KVxuICB1c2VJbnB1dChcbiAgICAoX2lucHV0LCBrZXkpID0+IHtcbiAgICAgIGlmIChrZXkudXBBcnJvdykge1xuICAgICAgICBvbkltYWdlc1NlbGVjdGVkQ2hhbmdlPy4oZmFsc2UpXG4gICAgICB9XG4gICAgfSxcbiAgICB7IGlzQWN0aXZlOiBpc0ZvY3VzZWQgJiYgISFpbWFnZXNTZWxlY3RlZCB9LFxuICApXG5cbiAgLy8gRXhpdCBpbWFnZSBtb2RlIHdoZW4gb3B0aW9uIGxvc2VzIGZvY3VzXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFpc0ZvY3VzZWQgJiYgaW1hZ2VzU2VsZWN0ZWQpIHtcbiAgICAgIG9uSW1hZ2VzU2VsZWN0ZWRDaGFuZ2U/LihmYWxzZSlcbiAgICB9XG4gIH0sIFtpc0ZvY3VzZWQsIGltYWdlc1NlbGVjdGVkLCBvbkltYWdlc1NlbGVjdGVkQ2hhbmdlXSlcblxuICBjb25zdCBkZXNjcmlwdGlvblBhZGRpbmdMZWZ0ID1cbiAgICBsYXlvdXQgPT09ICdleHBhbmRlZCcgPyBtYXhJbmRleFdpZHRoICsgMyA6IG1heEluZGV4V2lkdGggKyA0XG5cbiAgcmV0dXJuIChcbiAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBmbGV4U2hyaW5rPXswfT5cbiAgICAgIDxTZWxlY3RPcHRpb25cbiAgICAgICAgaXNGb2N1c2VkPXtpc0ZvY3VzZWR9XG4gICAgICAgIGlzU2VsZWN0ZWQ9e2lzU2VsZWN0ZWR9XG4gICAgICAgIHNob3VsZFNob3dEb3duQXJyb3c9e3Nob3VsZFNob3dEb3duQXJyb3d9XG4gICAgICAgIHNob3VsZFNob3dVcEFycm93PXtzaG91bGRTaG93VXBBcnJvd31cbiAgICAgICAgZGVjbGFyZUN1cnNvcj17ZmFsc2V9XG4gICAgICA+XG4gICAgICAgIDxCb3hcbiAgICAgICAgICBmbGV4RGlyZWN0aW9uPVwicm93XCJcbiAgICAgICAgICBmbGV4U2hyaW5rPXtsYXlvdXQgPT09ICdjb21wYWN0JyA/IDAgOiB1bmRlZmluZWR9XG4gICAgICAgID5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj57YCR7aW5kZXh9LmAucGFkRW5kKG1heEluZGV4V2lkdGggKyAyKX08L1RleHQ+XG4gICAgICAgICAge2NoaWxkcmVufVxuICAgICAgICAgIHtzaG93TGFiZWwgPyAoXG4gICAgICAgICAgICA8PlxuICAgICAgICAgICAgICA8VGV4dCBjb2xvcj17aXNGb2N1c2VkID8gJ3N1Z2dlc3Rpb24nIDogdW5kZWZpbmVkfT5cbiAgICAgICAgICAgICAgICB7b3B0aW9uLmxhYmVsfVxuICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIHtpc0ZvY3VzZWQgPyAoXG4gICAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwic3VnZ2VzdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICB7b3B0aW9uLmxhYmVsVmFsdWVTZXBhcmF0b3IgPz8gJywgJ31cbiAgICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgICAgIDxUZXh0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e2lucHV0VmFsdWV9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt2YWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgaXNVc2VyRWRpdGluZy5jdXJyZW50ID0gdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgIG9uSW5wdXRDaGFuZ2UodmFsdWUpXG4gICAgICAgICAgICAgICAgICAgICAgb3B0aW9uLm9uQ2hhbmdlKHZhbHVlKVxuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICBvblN1Ym1pdD17b25TdWJtaXR9XG4gICAgICAgICAgICAgICAgICAgIG9uRXhpdD17b25FeGl0fVxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj17b3B0aW9uLnBsYWNlaG9sZGVyfVxuICAgICAgICAgICAgICAgICAgICBmb2N1cz17IWltYWdlc1NlbGVjdGVkfVxuICAgICAgICAgICAgICAgICAgICBzaG93Q3Vyc29yPXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICBtdWx0aWxpbmU9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvck9mZnNldD17Y3Vyc29yT2Zmc2V0fVxuICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZUN1cnNvck9mZnNldD17c2V0Q3Vyc29yT2Zmc2V0fVxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5zPXs4MH1cbiAgICAgICAgICAgICAgICAgICAgb25JbWFnZVBhc3RlPXtvbkltYWdlUGFzdGV9XG4gICAgICAgICAgICAgICAgICAgIG9uUGFzdGU9eyhwYXN0ZWRUZXh0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBpc1VzZXJFZGl0aW5nLmN1cnJlbnQgPSB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVmb3JlID0gaW5wdXRWYWx1ZS5zbGljZSgwLCBjdXJzb3JPZmZzZXQpXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWZ0ZXIgPSBpbnB1dFZhbHVlLnNsaWNlKGN1cnNvck9mZnNldClcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IGJlZm9yZSArIHBhc3RlZFRleHQgKyBhZnRlclxuICAgICAgICAgICAgICAgICAgICAgIG9uSW5wdXRDaGFuZ2UobmV3VmFsdWUpXG4gICAgICAgICAgICAgICAgICAgICAgb3B0aW9uLm9uQ2hhbmdlKG5ld1ZhbHVlKVxuICAgICAgICAgICAgICAgICAgICAgIHNldEN1cnNvck9mZnNldChiZWZvcmUubGVuZ3RoICsgcGFzdGVkVGV4dC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgICApIDogKFxuICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgJiYgKFxuICAgICAgICAgICAgICAgICAgPFRleHQ+XG4gICAgICAgICAgICAgICAgICAgIHtvcHRpb24ubGFiZWxWYWx1ZVNlcGFyYXRvciA/PyAnLCAnfVxuICAgICAgICAgICAgICAgICAgICB7aW5wdXRWYWx1ZX1cbiAgICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8Lz5cbiAgICAgICAgICApIDogaXNGb2N1c2VkID8gKFxuICAgICAgICAgICAgPFRleHRJbnB1dFxuICAgICAgICAgICAgICB2YWx1ZT17aW5wdXRWYWx1ZX1cbiAgICAgICAgICAgICAgb25DaGFuZ2U9e3ZhbHVlID0+IHtcbiAgICAgICAgICAgICAgICBpc1VzZXJFZGl0aW5nLmN1cnJlbnQgPSB0cnVlXG4gICAgICAgICAgICAgICAgb25JbnB1dENoYW5nZSh2YWx1ZSlcbiAgICAgICAgICAgICAgICBvcHRpb24ub25DaGFuZ2UodmFsdWUpXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgIG9uU3VibWl0PXtvblN1Ym1pdH1cbiAgICAgICAgICAgICAgb25FeGl0PXtvbkV4aXR9XG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPXtcbiAgICAgICAgICAgICAgICBvcHRpb24ucGxhY2Vob2xkZXIgfHxcbiAgICAgICAgICAgICAgICAodHlwZW9mIG9wdGlvbi5sYWJlbCA9PT0gJ3N0cmluZycgPyBvcHRpb24ubGFiZWwgOiB1bmRlZmluZWQpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZm9jdXM9eyFpbWFnZXNTZWxlY3RlZH1cbiAgICAgICAgICAgICAgc2hvd0N1cnNvcj17dHJ1ZX1cbiAgICAgICAgICAgICAgbXVsdGlsaW5lPXt0cnVlfVxuICAgICAgICAgICAgICBjdXJzb3JPZmZzZXQ9e2N1cnNvck9mZnNldH1cbiAgICAgICAgICAgICAgb25DaGFuZ2VDdXJzb3JPZmZzZXQ9e3NldEN1cnNvck9mZnNldH1cbiAgICAgICAgICAgICAgY29sdW1ucz17ODB9XG4gICAgICAgICAgICAgIG9uSW1hZ2VQYXN0ZT17b25JbWFnZVBhc3RlfVxuICAgICAgICAgICAgICBvblBhc3RlPXsocGFzdGVkVGV4dDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgaXNVc2VyRWRpdGluZy5jdXJyZW50ID0gdHJ1ZVxuICAgICAgICAgICAgICAgIGNvbnN0IGJlZm9yZSA9IGlucHV0VmFsdWUuc2xpY2UoMCwgY3Vyc29yT2Zmc2V0KVxuICAgICAgICAgICAgICAgIGNvbnN0IGFmdGVyID0gaW5wdXRWYWx1ZS5zbGljZShjdXJzb3JPZmZzZXQpXG4gICAgICAgICAgICAgICAgY29uc3QgbmV3VmFsdWUgPSBiZWZvcmUgKyBwYXN0ZWRUZXh0ICsgYWZ0ZXJcbiAgICAgICAgICAgICAgICBvbklucHV0Q2hhbmdlKG5ld1ZhbHVlKVxuICAgICAgICAgICAgICAgIG9wdGlvbi5vbkNoYW5nZShuZXdWYWx1ZSlcbiAgICAgICAgICAgICAgICBzZXRDdXJzb3JPZmZzZXQoYmVmb3JlLmxlbmd0aCArIHBhc3RlZFRleHQubGVuZ3RoKVxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICApIDogKFxuICAgICAgICAgICAgPFRleHQgY29sb3I9e2lucHV0VmFsdWUgPyB1bmRlZmluZWQgOiAnaW5hY3RpdmUnfT5cbiAgICAgICAgICAgICAge2lucHV0VmFsdWUgfHwgb3B0aW9uLnBsYWNlaG9sZGVyIHx8IG9wdGlvbi5sYWJlbH1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICApfVxuICAgICAgICA8L0JveD5cbiAgICAgIDwvU2VsZWN0T3B0aW9uPlxuICAgICAge29wdGlvbi5kZXNjcmlwdGlvbiAmJiAoXG4gICAgICAgIDxCb3ggcGFkZGluZ0xlZnQ9e2Rlc2NyaXB0aW9uUGFkZGluZ0xlZnR9PlxuICAgICAgICAgIDxUZXh0XG4gICAgICAgICAgICBkaW1Db2xvcj17b3B0aW9uLmRpbURlc2NyaXB0aW9uICE9PSBmYWxzZX1cbiAgICAgICAgICAgIGNvbG9yPXtcbiAgICAgICAgICAgICAgaXNTZWxlY3RlZCA/ICdzdWNjZXNzJyA6IGlzRm9jdXNlZCA/ICdzdWdnZXN0aW9uJyA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfVxuICAgICAgICAgID5cbiAgICAgICAgICAgIHtvcHRpb24uZGVzY3JpcHRpb259XG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICl9XG4gICAgICB7aW1hZ2VBdHRhY2htZW50cy5sZW5ndGggPiAwICYmIChcbiAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwicm93XCIgZ2FwPXsxfSBwYWRkaW5nTGVmdD17ZGVzY3JpcHRpb25QYWRkaW5nTGVmdH0+XG4gICAgICAgICAge2ltYWdlQXR0YWNobWVudHMubWFwKChpbWcsIGlkeCkgPT4gKFxuICAgICAgICAgICAgPENsaWNrYWJsZUltYWdlUmVmXG4gICAgICAgICAgICAgIGtleT17aW1nLmlkfVxuICAgICAgICAgICAgICBpbWFnZUlkPXtpbWcuaWR9XG4gICAgICAgICAgICAgIGlzU2VsZWN0ZWQ9eyEhaW1hZ2VzU2VsZWN0ZWQgJiYgaWR4ID09PSBzZWxlY3RlZEltYWdlSW5kZXh9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICkpfVxuICAgICAgICAgIDxCb3ggZmxleEdyb3c9ezF9IGp1c3RpZnlDb250ZW50PVwiZmxleC1zdGFydFwiIGZsZXhEaXJlY3Rpb249XCJyb3dcIj5cbiAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICB7aW1hZ2VzU2VsZWN0ZWQgPyAoXG4gICAgICAgICAgICAgICAgPEJ5bGluZT5cbiAgICAgICAgICAgICAgICAgIHtpbWFnZUF0dGFjaG1lbnRzLmxlbmd0aCA+IDEgJiYgKFxuICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbj1cImF0dGFjaG1lbnRzOm5leHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dD1cIkF0dGFjaG1lbnRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhbGxiYWNrPVwi4oaSXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uPVwibmV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb249XCJhdHRhY2htZW50czpwcmV2aW91c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0PVwiQXR0YWNobWVudHNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2s9XCLihpBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJwcmV2XCJcbiAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8Lz5cbiAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICA8Q29uZmlndXJhYmxlU2hvcnRjdXRIaW50XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbj1cImF0dGFjaG1lbnRzOnJlbW92ZVwiXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ9XCJBdHRhY2htZW50c1wiXG4gICAgICAgICAgICAgICAgICAgIGZhbGxiYWNrPVwiYmFja3NwYWNlXCJcbiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJyZW1vdmVcIlxuICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uPVwiYXR0YWNobWVudHM6ZXhpdFwiXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ9XCJBdHRhY2htZW50c1wiXG4gICAgICAgICAgICAgICAgICAgIGZhbGxiYWNrPVwiZXNjXCJcbiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb249XCJjYW5jZWxcIlxuICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8L0J5bGluZT5cbiAgICAgICAgICAgICAgKSA6IGlzRm9jdXNlZCA/IChcbiAgICAgICAgICAgICAgICAnKOKGkyB0byBzZWxlY3QpJ1xuICAgICAgICAgICAgICApIDogbnVsbH1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICApfVxuICAgICAge2xheW91dCA9PT0gJ2V4cGFuZGVkJyAmJiA8VGV4dD4gPC9UZXh0Pn1cbiAgICA8L0JveD5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUFJLEtBQUtDLFNBQVMsRUFBRUMsU0FBUyxFQUFFQyxNQUFNLEVBQUVDLFFBQVEsUUFBUSxPQUFPO0FBQzFFO0FBQ0EsU0FBU0MsR0FBRyxFQUFFQyxJQUFJLEVBQUVDLFFBQVEsUUFBUSxjQUFjO0FBQ2xELFNBQ0VDLGFBQWEsRUFDYkMsY0FBYyxRQUNULG9DQUFvQztBQUMzQyxjQUFjQyxhQUFhLFFBQVEsdUJBQXVCO0FBQzFELFNBQVNDLHFCQUFxQixRQUFRLDJCQUEyQjtBQUNqRSxjQUFjQyxlQUFlLFFBQVEsNkJBQTZCO0FBQ2xFLFNBQVNDLGlCQUFpQixRQUFRLHlCQUF5QjtBQUMzRCxTQUFTQyx3QkFBd0IsUUFBUSxnQ0FBZ0M7QUFDekUsU0FBU0MsTUFBTSxRQUFRLDRCQUE0QjtBQUNuRCxPQUFPQyxTQUFTLE1BQU0saUJBQWlCO0FBQ3ZDLGNBQWNDLHFCQUFxQixRQUFRLGFBQWE7QUFDeEQsU0FBU0MsWUFBWSxRQUFRLG9CQUFvQjtBQUVqRCxLQUFLQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUc7RUFDZEMsTUFBTSxFQUFFQyxPQUFPLENBQUNKLHFCQUFxQixDQUFDSyxDQUFDLENBQUMsRUFBRTtJQUFFQyxJQUFJLEVBQUUsT0FBTztFQUFDLENBQUMsQ0FBQztFQUM1REMsU0FBUyxFQUFFLE9BQU87RUFDbEJDLFVBQVUsRUFBRSxPQUFPO0VBQ25CQyxtQkFBbUIsRUFBRSxPQUFPO0VBQzVCQyxp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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/CustomSelect/use-select-navigation.ts b/_all-in-one-upload/cc-haha/src/components/CustomSelect/use-select-navigation.ts new file mode 100644 index 0000000..7ecb4e7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/CustomSelect/use-select-navigation.ts @@ -0,0 +1,653 @@ +import { + useCallback, + useEffect, + useMemo, + useReducer, + useRef, + useState, +} from 'react' +import { isDeepStrictEqual } from 'util' +import OptionMap from './option-map.js' +import type { OptionWithDescription } from './select.js' + +type State = { + /** + * Map where key is option's value and value is option's index. + */ + optionMap: OptionMap + + /** + * Number of visible options. + */ + visibleOptionCount: number + + /** + * Value of the currently focused option. + */ + focusedValue: T | undefined + + /** + * Index of the first visible option. + */ + visibleFromIndex: number + + /** + * Index of the last visible option. + */ + visibleToIndex: number +} + +type Action = + | FocusNextOptionAction + | FocusPreviousOptionAction + | FocusNextPageAction + | FocusPreviousPageAction + | SetFocusAction + | ResetAction + +type SetFocusAction = { + type: 'set-focus' + value: T +} + +type FocusNextOptionAction = { + type: 'focus-next-option' +} + +type FocusPreviousOptionAction = { + type: 'focus-previous-option' +} + +type FocusNextPageAction = { + type: 'focus-next-page' +} + +type FocusPreviousPageAction = { + type: 'focus-previous-page' +} + +type ResetAction = { + type: 'reset' + state: State +} + +const reducer = (state: State, action: Action): State => { + switch (action.type) { + case 'focus-next-option': { + if (state.focusedValue === undefined) { + return state + } + + const item = state.optionMap.get(state.focusedValue) + + if (!item) { + return state + } + + // Wrap to first item if at the end + const next = item.next || state.optionMap.first + + if (!next) { + return state + } + + // When wrapping to first, reset viewport to start + if (!item.next && next === state.optionMap.first) { + return { + ...state, + focusedValue: next.value, + visibleFromIndex: 0, + visibleToIndex: state.visibleOptionCount, + } + } + + const needsToScroll = next.index >= state.visibleToIndex + + if (!needsToScroll) { + return { + ...state, + focusedValue: next.value, + } + } + + const nextVisibleToIndex = Math.min( + state.optionMap.size, + state.visibleToIndex + 1, + ) + + const nextVisibleFromIndex = nextVisibleToIndex - state.visibleOptionCount + + return { + ...state, + focusedValue: next.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + + case 'focus-previous-option': { + if (state.focusedValue === undefined) { + return state + } + + const item = state.optionMap.get(state.focusedValue) + + if (!item) { + return state + } + + // Wrap to last item if at the beginning + const previous = item.previous || state.optionMap.last + + if (!previous) { + return state + } + + // When wrapping to last, reset viewport to end + if (!item.previous && previous === state.optionMap.last) { + const nextVisibleToIndex = state.optionMap.size + const nextVisibleFromIndex = Math.max( + 0, + nextVisibleToIndex - state.visibleOptionCount, + ) + return { + ...state, + focusedValue: previous.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + + const needsToScroll = previous.index <= state.visibleFromIndex + + if (!needsToScroll) { + return { + ...state, + focusedValue: previous.value, + } + } + + const nextVisibleFromIndex = Math.max(0, state.visibleFromIndex - 1) + + const nextVisibleToIndex = nextVisibleFromIndex + state.visibleOptionCount + + return { + ...state, + focusedValue: previous.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + + case 'focus-next-page': { + if (state.focusedValue === undefined) { + return state + } + + const item = state.optionMap.get(state.focusedValue) + + if (!item) { + return state + } + + // Move by a full page (visibleOptionCount items) + const targetIndex = Math.min( + state.optionMap.size - 1, + item.index + state.visibleOptionCount, + ) + + // Find the item at the target index + let targetItem = state.optionMap.first + while (targetItem && targetItem.index < targetIndex) { + if (targetItem.next) { + targetItem = targetItem.next + } else { + break + } + } + + if (!targetItem) { + return state + } + + // Update the visible range to include the new focused item + const nextVisibleToIndex = Math.min( + state.optionMap.size, + targetItem.index + 1, + ) + const nextVisibleFromIndex = Math.max( + 0, + nextVisibleToIndex - state.visibleOptionCount, + ) + + return { + ...state, + focusedValue: targetItem.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + + case 'focus-previous-page': { + if (state.focusedValue === undefined) { + return state + } + + const item = state.optionMap.get(state.focusedValue) + + if (!item) { + return state + } + + // Move by a full page (visibleOptionCount items) + const targetIndex = Math.max(0, item.index - state.visibleOptionCount) + + // Find the item at the target index + let targetItem = state.optionMap.first + while (targetItem && targetItem.index < targetIndex) { + if (targetItem.next) { + targetItem = targetItem.next + } else { + break + } + } + + if (!targetItem) { + return state + } + + // Update the visible range to include the new focused item + const nextVisibleFromIndex = Math.max(0, targetItem.index) + const nextVisibleToIndex = Math.min( + state.optionMap.size, + nextVisibleFromIndex + state.visibleOptionCount, + ) + + return { + ...state, + focusedValue: targetItem.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + + case 'reset': { + return action.state + } + + case 'set-focus': { + // Early return if already focused on this value + if (state.focusedValue === action.value) { + return state + } + + const item = state.optionMap.get(action.value) + if (!item) { + return state + } + + // Check if the item is already in view + if ( + item.index >= state.visibleFromIndex && + item.index < state.visibleToIndex + ) { + // Already visible, just update focus + return { + ...state, + focusedValue: action.value, + } + } + + // Need to scroll to make the item visible + // Scroll as little as possible - put item at edge of viewport + let nextVisibleFromIndex: number + let nextVisibleToIndex: number + + if (item.index < state.visibleFromIndex) { + // Item is above viewport - scroll up to put it at the top + nextVisibleFromIndex = item.index + nextVisibleToIndex = Math.min( + state.optionMap.size, + nextVisibleFromIndex + state.visibleOptionCount, + ) + } else { + // Item is below viewport - scroll down to put it at the bottom + nextVisibleToIndex = Math.min(state.optionMap.size, item.index + 1) + nextVisibleFromIndex = Math.max( + 0, + nextVisibleToIndex - state.visibleOptionCount, + ) + } + + return { + ...state, + focusedValue: action.value, + visibleFromIndex: nextVisibleFromIndex, + visibleToIndex: nextVisibleToIndex, + } + } + } +} + +export type UseSelectNavigationProps = { + /** + * Number of items to display. + * + * @default 5 + */ + visibleOptionCount?: number + + /** + * Options. + */ + options: OptionWithDescription[] + + /** + * Initially focused option's value. + */ + initialFocusValue?: T + + /** + * Callback for focusing an option. + */ + onFocus?: (value: T) => void + + /** + * Value to focus + */ + focusValue?: T +} + +export type SelectNavigation = { + /** + * Value of the currently focused option. + */ + focusedValue: T | undefined + + /** + * 1-based index of the focused option in the full list. + * Returns 0 if no option is focused. + */ + focusedIndex: number + + /** + * Index of the first visible option. + */ + visibleFromIndex: number + + /** + * Index of the last visible option. + */ + visibleToIndex: number + + /** + * All options. + */ + options: OptionWithDescription[] + + /** + * Visible options. + */ + visibleOptions: Array & { index: number }> + + /** + * Whether the focused option is an input type. + */ + isInInput: boolean + + /** + * Focus next option and scroll the list down, if needed. + */ + focusNextOption: () => void + + /** + * Focus previous option and scroll the list up, if needed. + */ + focusPreviousOption: () => void + + /** + * Focus next page and scroll the list down by a page. + */ + focusNextPage: () => void + + /** + * Focus previous page and scroll the list up by a page. + */ + focusPreviousPage: () => void + + /** + * Focus a specific option by value. + */ + focusOption: (value: T | undefined) => void +} + +const createDefaultState = ({ + visibleOptionCount: customVisibleOptionCount, + options, + initialFocusValue, + currentViewport, +}: Pick, 'visibleOptionCount' | 'options'> & { + initialFocusValue?: T + currentViewport?: { visibleFromIndex: number; visibleToIndex: number } +}): State => { + const visibleOptionCount = + typeof customVisibleOptionCount === 'number' + ? Math.min(customVisibleOptionCount, options.length) + : options.length + + const optionMap = new OptionMap(options) + const focusedItem = + initialFocusValue !== undefined && optionMap.get(initialFocusValue) + const focusedValue = focusedItem ? initialFocusValue : optionMap.first?.value + + let visibleFromIndex = 0 + let visibleToIndex = visibleOptionCount + + // When there's a valid focused item, adjust viewport to show it + if (focusedItem) { + const focusedIndex = focusedItem.index + + if (currentViewport) { + // If focused item is already in the current viewport range, try to preserve it + if ( + focusedIndex >= currentViewport.visibleFromIndex && + focusedIndex < currentViewport.visibleToIndex + ) { + // Keep the same viewport if it's valid + visibleFromIndex = currentViewport.visibleFromIndex + visibleToIndex = Math.min( + optionMap.size, + currentViewport.visibleToIndex, + ) + } else { + // Need to adjust viewport to show focused item + // Use minimal scrolling - put item at edge of viewport + if (focusedIndex < currentViewport.visibleFromIndex) { + // Item is above current viewport - scroll up to put it at the top + visibleFromIndex = focusedIndex + visibleToIndex = Math.min( + optionMap.size, + visibleFromIndex + visibleOptionCount, + ) + } else { + // Item is below current viewport - scroll down to put it at the bottom + visibleToIndex = Math.min(optionMap.size, focusedIndex + 1) + visibleFromIndex = Math.max(0, visibleToIndex - visibleOptionCount) + } + } + } else if (focusedIndex >= visibleOptionCount) { + // No current viewport but focused item is outside default viewport + // Scroll to show the focused item at the bottom of the viewport + visibleToIndex = Math.min(optionMap.size, focusedIndex + 1) + visibleFromIndex = Math.max(0, visibleToIndex - visibleOptionCount) + } + + // Ensure viewport bounds are valid + visibleFromIndex = Math.max( + 0, + Math.min(visibleFromIndex, optionMap.size - 1), + ) + visibleToIndex = Math.min( + optionMap.size, + Math.max(visibleOptionCount, visibleToIndex), + ) + } + + return { + optionMap, + visibleOptionCount, + focusedValue, + visibleFromIndex, + visibleToIndex, + } +} + +export function useSelectNavigation({ + visibleOptionCount = 5, + options, + initialFocusValue, + onFocus, + focusValue, +}: UseSelectNavigationProps): SelectNavigation { + const [state, dispatch] = useReducer( + reducer, + { + visibleOptionCount, + options, + initialFocusValue: focusValue || initialFocusValue, + } as Parameters>[0], + createDefaultState, + ) + + // Store onFocus in a ref to avoid re-running useEffect when callback changes + const onFocusRef = useRef(onFocus) + onFocusRef.current = onFocus + + const [lastOptions, setLastOptions] = useState(options) + + if (options !== lastOptions && !isDeepStrictEqual(options, lastOptions)) { + dispatch({ + type: 'reset', + state: createDefaultState({ + visibleOptionCount, + options, + initialFocusValue: + focusValue ?? state.focusedValue ?? initialFocusValue, + currentViewport: { + visibleFromIndex: state.visibleFromIndex, + visibleToIndex: state.visibleToIndex, + }, + }), + }) + + setLastOptions(options) + } + + const focusNextOption = useCallback(() => { + dispatch({ + type: 'focus-next-option', + }) + }, []) + + const focusPreviousOption = useCallback(() => { + dispatch({ + type: 'focus-previous-option', + }) + }, []) + + const focusNextPage = useCallback(() => { + dispatch({ + type: 'focus-next-page', + }) + }, []) + + const focusPreviousPage = useCallback(() => { + dispatch({ + type: 'focus-previous-page', + }) + }, []) + + const focusOption = useCallback((value: T | undefined) => { + if (value !== undefined) { + dispatch({ + type: 'set-focus', + value, + }) + } + }, []) + + const visibleOptions = useMemo(() => { + return options + .map((option, index) => ({ + ...option, + index, + })) + .slice(state.visibleFromIndex, state.visibleToIndex) + }, [options, state.visibleFromIndex, state.visibleToIndex]) + + // Validate that focusedValue exists in current options. + // This handles the case where options change during render but the reset + // action hasn't been processed yet - without this, the cursor would disappear + // because focusedValue points to an option that no longer exists. + const validatedFocusedValue = useMemo(() => { + if (state.focusedValue === undefined) { + return undefined + } + const exists = options.some(opt => opt.value === state.focusedValue) + if (exists) { + return state.focusedValue + } + // Fall back to first option if focused value doesn't exist + return options[0]?.value + }, [state.focusedValue, options]) + + const isInInput = useMemo(() => { + const focusedOption = options.find( + opt => opt.value === validatedFocusedValue, + ) + return focusedOption?.type === 'input' + }, [validatedFocusedValue, options]) + + // Call onFocus with the validated value (what's actually displayed), + // not the internal state value which may be stale if options changed. + // Use ref to avoid re-running when callback reference changes. + useEffect(() => { + if (validatedFocusedValue !== undefined) { + onFocusRef.current?.(validatedFocusedValue) + } + }, [validatedFocusedValue]) + + // Allow parent to programmatically set focus via focusValue prop + useEffect(() => { + if (focusValue !== undefined) { + dispatch({ + type: 'set-focus', + value: focusValue, + }) + } + }, [focusValue]) + + // Compute 1-based focused index for scroll position display + const focusedIndex = useMemo(() => { + if (validatedFocusedValue === undefined) { + return 0 + } + const index = options.findIndex(opt => opt.value === validatedFocusedValue) + return index >= 0 ? index + 1 : 0 + }, [validatedFocusedValue, options]) + + return { + focusedValue: validatedFocusedValue, + focusedIndex, + visibleFromIndex: state.visibleFromIndex, + visibleToIndex: state.visibleToIndex, + visibleOptions, + isInInput: isInInput ?? false, + focusNextOption, + focusPreviousOption, + focusNextPage, + focusPreviousPage, + focusOption, + options, + } +} diff --git a/_all-in-one-upload/cc-haha/src/components/DevChannelsDialog.tsx b/_all-in-one-upload/cc-haha/src/components/DevChannelsDialog.tsx new file mode 100644 index 0000000..5e68afb --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/DevChannelsDialog.tsx @@ -0,0 +1,105 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { useCallback } from 'react'; +import type { ChannelEntry } from '../bootstrap/state.js'; +import { Box, Text } from '../ink.js'; +import { gracefulShutdownSync } from '../utils/gracefulShutdown.js'; +import { Select } from './CustomSelect/index.js'; +import { Dialog } from './design-system/Dialog.js'; +type Props = { + channels: ChannelEntry[]; + onAccept(): void; +}; +export function DevChannelsDialog(t0) { + const $ = _c(14); + const { + channels, + onAccept + } = t0; + let t1; + if ($[0] !== onAccept) { + t1 = function onChange(value) { + bb2: switch (value) { + case "accept": + { + onAccept(); + break bb2; + } + case "exit": + { + gracefulShutdownSync(1); + } + } + }; + $[0] = onAccept; + $[1] = t1; + } else { + t1 = $[1]; + } + const onChange = t1; + const handleEscape = _temp; + let t2; + let t3; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t2 = --dangerously-load-development-channels is for local channel development only. Do not use this option to run channels you have downloaded off the internet.; + t3 = Please use --channels to run a list of approved channels.; + $[2] = t2; + $[3] = t3; + } else { + t2 = $[2]; + t3 = $[3]; + } + let t4; + if ($[4] !== channels) { + t4 = channels.map(_temp2).join(", "); + $[4] = channels; + $[5] = t4; + } else { + t4 = $[5]; + } + let t5; + if ($[6] !== t4) { + t5 = {t2}{t3}Channels:{" "}{t4}; + $[6] = t4; + $[7] = t5; + } else { + t5 = $[7]; + } + let t6; + if ($[8] === Symbol.for("react.memo_cache_sentinel")) { + t6 = [{ + label: "I am using this for local development", + value: "accept" + }, { + label: "Exit", + value: "exit" + }]; + $[8] = t6; + } else { + t6 = $[8]; + } + let t7; + if ($[9] !== onChange) { + t7 = onResponse('no')} /> + + + ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJveCIsIlRleHQiLCJTZWxlY3QiLCJQZXJtaXNzaW9uRGlhbG9nIiwiUHJvcHMiLCJwbHVnaW5OYW1lIiwicGx1Z2luRGVzY3JpcHRpb24iLCJmaWxlRXh0ZW5zaW9uIiwib25SZXNwb25zZSIsInJlc3BvbnNlIiwiQVVUT19ESVNNSVNTX01TIiwiTHNwUmVjb21tZW5kYXRpb25NZW51IiwiUmVhY3ROb2RlIiwib25SZXNwb25zZVJlZiIsInVzZVJlZiIsImN1cnJlbnQiLCJ1c2VFZmZlY3QiLCJ0aW1lb3V0SWQiLCJzZXRUaW1lb3V0IiwicmVmIiwiY2xlYXJUaW1lb3V0Iiwib25TZWxlY3QiLCJ2YWx1ZSIsIm9wdGlvbnMiLCJsYWJlbCJdLCJzb3VyY2VzIjpbIkxzcFJlY29tbWVuZGF0aW9uTWVudS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBTZWxlY3QgfSBmcm9tICcuLi9DdXN0b21TZWxlY3Qvc2VsZWN0LmpzJ1xuaW1wb3J0IHsgUGVybWlzc2lvbkRpYWxvZyB9IGZyb20gJy4uL3Blcm1pc3Npb25zL1Blcm1pc3Npb25EaWFsb2cuanMnXG5cbnR5cGUgUHJvcHMgPSB7XG4gIHBsdWdpbk5hbWU6IHN0cmluZ1xuICBwbHVnaW5EZXNjcmlwdGlvbj86IHN0cmluZ1xuICBmaWxlRXh0ZW5zaW9uOiBzdHJpbmdcbiAgb25SZXNwb25zZTogKHJlc3BvbnNlOiAneWVzJyB8ICdubycgfCAnbmV2ZXInIHwgJ2Rpc2FibGUnKSA9PiB2b2lkXG59XG5cbmNvbnN0IEFVVE9fRElTTUlTU19NUyA9IDMwXzAwMFxuXG5leHBvcnQgZnVuY3Rpb24gTHNwUmVjb21tZW5kYXRpb25NZW51KHtcbiAgcGx1Z2luTmFtZSxcbiAgcGx1Z2luRGVzY3JpcHRpb24sXG4gIGZpbGVFeHRlbnNpb24sXG4gIG9uUmVzcG9uc2UsXG59OiBQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIC8vIFVzZSByZWYgdG8gYXZvaWQgdGltZXIgcmVzZXQgd2hlbiBvblJlc3BvbnNlIGNoYW5nZXNcbiAgY29uc3Qgb25SZXNwb25zZVJlZiA9IFJlYWN0LnVzZVJlZihvblJlc3BvbnNlKVxuICBvblJlc3BvbnNlUmVmLmN1cnJlbnQgPSBvblJlc3BvbnNlXG5cbiAgLy8gMzAtc2Vjb25kIGF1dG8tZGlzbWlzcyB0aW1lciAtIGNvdW50cyBhcyBpZ25vcmVkIChubylcbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KFxuICAgICAgcmVmID0+IHJlZi5jdXJyZW50KCdubycpLFxuICAgICAgQVVUT19ESVNNSVNTX01TLFxuICAgICAgb25SZXNwb25zZVJlZixcbiAgICApXG4gICAgcmV0dXJuICgpID0+IGNsZWFyVGltZW91dCh0aW1lb3V0SWQpXG4gIH0sIFtdKVxuXG4gIGZ1bmN0aW9uIG9uU2VsZWN0KHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKHZhbHVlKSB7XG4gICAgICBjYXNlICd5ZXMnOlxuICAgICAgICBvblJlc3BvbnNlKCd5ZXMnKVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAnbm8nOlxuICAgICAgICBvblJlc3BvbnNlKCdubycpXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICduZXZlcic6XG4gICAgICAgIG9uUmVzcG9uc2UoJ25ldmVyJylcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgJ2Rpc2FibGUnOlxuICAgICAgICBvblJlc3BvbnNlKCdkaXNhYmxlJylcbiAgICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBjb25zdCBvcHRpb25zID0gW1xuICAgIHtcbiAgICAgIGxhYmVsOiAoXG4gICAgICAgIDxUZXh0PlxuICAgICAgICAgIFllcywgaW5zdGFsbCA8VGV4dCBib2xkPntwbHVnaW5OYW1lfTwvVGV4dD5cbiAgICAgICAgPC9UZXh0PlxuICAgICAgKSxcbiAgICAgIHZhbHVlOiAneWVzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIGxhYmVsOiAnTm8sIG5vdCBub3cnLFxuICAgICAgdmFsdWU6ICdubycsXG4gICAgfSxcbiAgICB7XG4gICAgICBsYWJlbDogKFxuICAgICAgICA8VGV4dD5cbiAgICAgICAgICBOZXZlciBmb3IgPFRleHQgYm9sZD57cGx1Z2luTmFtZX08L1RleHQ+XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICksXG4gICAgICB2YWx1ZTogJ25ldmVyJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIGxhYmVsOiAnRGlzYWJsZSBhbGwgTFNQIHJlY29tbWVuZGF0aW9ucycsXG4gICAgICB2YWx1ZTogJ2Rpc2FibGUnLFxuICAgIH0sXG4gIF1cblxuICByZXR1cm4gKFxuICAgIDxQZXJtaXNzaW9uRGlhbG9nIHRpdGxlPVwiTFNQIFBsdWdpbiBSZWNvbW1lbmRhdGlvblwiPlxuICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgcGFkZGluZ1g9ezJ9IHBhZGRpbmdZPXsxfT5cbiAgICAgICAgPEJveCBtYXJnaW5Cb3R0b209ezF9PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgTFNQIHByb3ZpZGVzIGNvZGUgaW50ZWxsaWdlbmNlIGxpa2UgZ28tdG8tZGVmaW5pdGlvbiBhbmQgZXJyb3JcbiAgICAgICAgICAgIGNoZWNraW5nXG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICAgPEJveD5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5QbHVnaW46PC9UZXh0PlxuICAgICAgICAgIDxUZXh0PiB7cGx1Z2luTmFtZX08L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgICB7cGx1Z2luRGVzY3JpcHRpb24gJiYgKFxuICAgICAgICAgIDxCb3g+XG4gICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj57cGx1Z2luRGVzY3JpcHRpb259PC9UZXh0PlxuICAgICAgICAgIDwvQm94PlxuICAgICAgICApfVxuICAgICAgICA8Qm94PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlRyaWdnZXJlZCBieTo8L1RleHQ+XG4gICAgICAgICAgPFRleHQ+IHtmaWxlRXh0ZW5zaW9ufSBmaWxlczwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICAgIDxCb3ggbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICA8VGV4dD5Xb3VsZCB5b3UgbGlrZSB0byBpbnN0YWxsIHRoaXMgTFNQIHBsdWdpbj88L1RleHQ+XG4gICAgICAgIDwvQm94PlxuICAgICAgICA8Qm94PlxuICAgICAgICAgIDxTZWxlY3RcbiAgICAgICAgICAgIG9wdGlvbnM9e29wdGlvbnN9XG4gICAgICAgICAgICBvbkNoYW5nZT17b25TZWxlY3R9XG4gICAgICAgICAgICBvbkNhbmNlbD17KCkgPT4gb25SZXNwb25zZSgnbm8nKX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L0JveD5cbiAgICAgIDwvQm94PlxuICAgIDwvUGVybWlzc2lvbkRpYWxvZz5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUtBLEtBQUssTUFBTSxPQUFPO0FBQzlCLFNBQVNDLEdBQUcsRUFBRUMsSUFBSSxRQUFRLGNBQWM7QUFDeEMsU0FBU0MsTUFBTSxRQUFRLDJCQUEyQjtBQUNsRCxTQUFTQyxnQkFBZ0IsUUFBUSxvQ0FBb0M7QUFFckUsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLFVBQVUsRUFBRSxNQUFNO0VBQ2xCQyxpQkFBaUIsQ0FBQyxFQUFFLE1BQU07RUFDMUJDLGFBQWEsRUFBRSxNQUFNO0VBQ3JCQyxVQUFVLEVBQUUsQ0FBQ0MsUUFBUSxFQUFFLEtBQUssR0FBRyxJQUFJLEdBQUcsT0FBTyxHQUFHLFNBQVMsRUFBRSxHQUFHLElBQUk7QUFDcEUsQ0FBQztBQUVELE1BQU1DLGVBQWUsR0FBRyxNQUFNO0FBRTlCLE9BQU8sU0FBU0MscUJBQXFCQSxDQUFDO0VBQ3BDTixVQUFVO0VBQ1ZD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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/Spinner/teammateSelectHint.ts b/_all-in-one-upload/cc-haha/src/components/Spinner/teammateSelectHint.ts new file mode 100644 index 0000000..420f949 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/Spinner/teammateSelectHint.ts @@ -0,0 +1 @@ +export const TEAMMATE_SELECT_HINT = 'shift + ↑/↓ to select' diff --git a/_all-in-one-upload/cc-haha/src/components/Spinner/useShimmerAnimation.ts b/_all-in-one-upload/cc-haha/src/components/Spinner/useShimmerAnimation.ts new file mode 100644 index 0000000..d1d4ea9 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/Spinner/useShimmerAnimation.ts @@ -0,0 +1,31 @@ +import { useMemo } from 'react' +import { stringWidth } from '../../ink/stringWidth.js' +import { type DOMElement, useAnimationFrame } from '../../ink.js' +import type { SpinnerMode } from './types.js' + +export function useShimmerAnimation( + mode: SpinnerMode, + message: string, + isStalled: boolean, +): [ref: (element: DOMElement | null) => void, glimmerIndex: number] { + const glimmerSpeed = mode === 'requesting' ? 50 : 200 + // Pass null when stalled to unsubscribe from the clock — otherwise the + // setInterval keeps firing at 20fps even when the shimmer isn't visible. + // Notably, if the caller never attaches `ref` (e.g. conditional JSX), + // useTerminalViewport stays at its initial isVisible:true and the + // viewport-pause never kicks in, so this is the only stop mechanism. + const [ref, time] = useAnimationFrame(isStalled ? null : glimmerSpeed) + const messageWidth = useMemo(() => stringWidth(message), [message]) + + if (isStalled) { + return [ref, -100] + } + + const cyclePosition = Math.floor(time / glimmerSpeed) + const cycleLength = messageWidth + 20 + + if (mode === 'requesting') { + return [ref, (cyclePosition % cycleLength) - 10] + } + return [ref, messageWidth + 10 - (cyclePosition % cycleLength)] +} diff --git a/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/CreateAgentWizard.tsx b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/CreateAgentWizard.tsx new file mode 100644 index 0000000..4ca9ba3 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/CreateAgentWizard.tsx @@ -0,0 +1,97 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { type ReactNode } from 'react'; +import { isAutoMemoryEnabled } from '../../../memdir/paths.js'; +import type { Tools } from '../../../Tool.js'; +import type { AgentDefinition } from '../../../tools/AgentTool/loadAgentsDir.js'; +import { WizardProvider } from '../../wizard/index.js'; +import type { WizardStepComponent } from '../../wizard/types.js'; +import type { AgentWizardData } from './types.js'; +import { ColorStep } from './wizard-steps/ColorStep.js'; +import { ConfirmStepWrapper } from './wizard-steps/ConfirmStepWrapper.js'; +import { DescriptionStep } from './wizard-steps/DescriptionStep.js'; +import { GenerateStep } from './wizard-steps/GenerateStep.js'; +import { LocationStep } from './wizard-steps/LocationStep.js'; +import { MemoryStep } from './wizard-steps/MemoryStep.js'; +import { MethodStep } from './wizard-steps/MethodStep.js'; +import { ModelStep } from './wizard-steps/ModelStep.js'; +import { PromptStep } from './wizard-steps/PromptStep.js'; +import { ToolsStep } from './wizard-steps/ToolsStep.js'; +import { TypeStep } from './wizard-steps/TypeStep.js'; +type Props = { + tools: Tools; + existingAgents: AgentDefinition[]; + onComplete: (message: string) => void; + onCancel: () => void; +}; +export function CreateAgentWizard(t0) { + const $ = _c(17); + const { + tools, + existingAgents, + onComplete, + onCancel + } = t0; + let t1; + if ($[0] !== existingAgents) { + t1 = () => ; + $[0] = existingAgents; + $[1] = t1; + } else { + t1 = $[1]; + } + let t2; + if ($[2] !== tools) { + t2 = () => ; + $[2] = tools; + $[3] = t2; + } else { + t2 = $[3]; + } + let t3; + if ($[4] === Symbol.for("react.memo_cache_sentinel")) { + t3 = isAutoMemoryEnabled() ? [MemoryStep] : []; + $[4] = t3; + } else { + t3 = $[4]; + } + let t4; + if ($[5] !== existingAgents || $[6] !== onComplete || $[7] !== tools) { + t4 = () => ; + $[5] = existingAgents; + $[6] = onComplete; + $[7] = tools; + $[8] = t4; + } else { + t4 = $[8]; + } + let t5; + if ($[9] !== t1 || $[10] !== t2 || $[11] !== t4) { + t5 = [LocationStep, MethodStep, GenerateStep, t1, PromptStep, DescriptionStep, t2, ModelStep, ColorStep, ...t3, t4]; + $[9] = t1; + $[10] = t2; + $[11] = t4; + $[12] = t5; + } else { + t5 = $[12]; + } + const steps = t5; + let t6; + if ($[13] === Symbol.for("react.memo_cache_sentinel")) { + t6 = {}; + $[13] = t6; + } else { + t6 = $[13]; + } + let t7; + if ($[14] !== onCancel || $[15] !== steps) { + t7 = ; + $[14] = onCancel; + $[15] = steps; + $[16] = t7; + } else { + t7 = $[16]; + } + return t7; +} +function _temp() {} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlJlYWN0Tm9kZSIsImlzQXV0b01lbW9yeUVuYWJsZWQiLCJUb29scyIsIkFnZW50RGVmaW5pdGlvbiIsIldpemFyZFByb3ZpZGVyIiwiV2l6YXJkU3RlcENvbXBvbmVudCIsIkFnZW50V2l6YXJkRGF0YSIsIkNvbG9yU3RlcCIsIkNvbmZpcm1TdGVwV3JhcHBlciIsIkRlc2NyaXB0aW9uU3RlcCIsIkdlbmVyYXRlU3RlcCIsIkxvY2F0aW9uU3RlcCIsIk1lbW9yeVN0ZXAiLCJNZXRob2RTdGVwIiwiTW9kZWxTdGVwIiwiUHJvbXB0U3RlcCIsIlRvb2xzU3RlcCIsIlR5cGVTdGVwIiwiUHJvcHMiLCJ0b29scyIsImV4aXN0aW5nQWdlbnRzIiwib25Db21wbGV0ZSIsIm1lc3NhZ2UiLCJvbkNhbmNlbCIsIkNyZWF0ZUFnZW50V2l6YXJkIiwidDAiLCIkIiwiX2MiLCJ0MSIsInQyIiwidDMiLCJTeW1ib2wiLCJmb3IiLCJ0NCIsInQ1Iiwic3RlcHMiLCJ0NiIsInQ3IiwiX3RlbXAiXSwic291cmNlcyI6WyJDcmVhdGVBZ2VudFdpemFyZC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0LCB7IHR5cGUgUmVhY3ROb2RlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBpc0F1dG9NZW1vcnlFbmFibGVkIH0gZnJvbSAnLi4vLi4vLi4vbWVtZGlyL3BhdGhzLmpzJ1xuaW1wb3J0IHR5cGUgeyBUb29scyB9IGZyb20gJy4uLy4uLy4uL1Rvb2wuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50RGVmaW5pdGlvbiB9IGZyb20gJy4uLy4uLy4uL3Rvb2xzL0FnZW50VG9vbC9sb2FkQWdlbnRzRGlyLmpzJ1xuaW1wb3J0IHsgV2l6YXJkUHJvdmlkZXIgfSBmcm9tICcuLi8uLi93aXphcmQvaW5kZXguanMnXG5pbXBvcnQgdHlwZSB7IFdpemFyZFN0ZXBDb21wb25lbnQgfSBmcm9tICcuLi8uLi93aXphcmQvdHlwZXMuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50V2l6YXJkRGF0YSB9IGZyb20gJy4vdHlwZXMuanMnXG5pbXBvcnQgeyBDb2xvclN0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9Db2xvclN0ZXAuanMnXG5pbXBvcnQgeyBDb25maXJtU3RlcFdyYXBwZXIgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9Db25maXJtU3RlcFdyYXBwZXIuanMnXG5pbXBvcnQgeyBEZXNjcmlwdGlvblN0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9EZXNjcmlwdGlvblN0ZXAuanMnXG5pbXBvcnQgeyBHZW5lcmF0ZVN0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9HZW5lcmF0ZVN0ZXAuanMnXG5pbXBvcnQgeyBMb2NhdGlvblN0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9Mb2NhdGlvblN0ZXAuanMnXG5pbXBvcnQgeyBNZW1vcnlTdGVwIH0gZnJvbSAnLi93aXphcmQtc3RlcHMvTWVtb3J5U3RlcC5qcydcbmltcG9ydCB7IE1ldGhvZFN0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9NZXRob2RTdGVwLmpzJ1xuaW1wb3J0IHsgTW9kZWxTdGVwIH0gZnJvbSAnLi93aXphcmQtc3RlcHMvTW9kZWxTdGVwLmpzJ1xuaW1wb3J0IHsgUHJvbXB0U3RlcCB9IGZyb20gJy4vd2l6YXJkLXN0ZXBzL1Byb21wdFN0ZXAuanMnXG5pbXBvcnQgeyBUb29sc1N0ZXAgfSBmcm9tICcuL3dpemFyZC1zdGVwcy9Ub29sc1N0ZXAuanMnXG5pbXBvcnQgeyBUeXBlU3RlcCB9IGZyb20gJy4vd2l6YXJkLXN0ZXBzL1R5cGVTdGVwLmpzJ1xuXG50eXBlIFByb3BzID0ge1xuICB0b29sczogVG9vbHNcbiAgZXhpc3RpbmdBZ2VudHM6IEFnZW50RGVmaW5pdGlvbltdXG4gIG9uQ29tcGxldGU6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWRcbiAgb25DYW5jZWw6ICgpID0+IHZvaWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIENyZWF0ZUFnZW50V2l6YXJkKHtcbiAgdG9vbHMsXG4gIGV4aXN0aW5nQWdlbnRzLFxuICBvbkNvbXBsZXRlLFxuICBvbkNhbmNlbCxcbn06IFByb3BzKTogUmVhY3ROb2RlIHtcbiAgLy8gQ3JlYXRlIHN0ZXAgY29tcG9uZW50cyB3aXRoIHByb3BzXG4gIGNvbnN0IHN0ZXBzOiBXaXphcmRTdGVwQ29tcG9uZW50PEFnZW50V2l6YXJkRGF0YT5bXSA9IFtcbiAgICBMb2NhdGlvblN0ZXAsIC8vIDBcbiAgICBNZXRob2RTdGVwLCAvLyAxXG4gICAgR2VuZXJhdGVTdGVwLCAvLyAyXG4gICAgKCkgPT4gPFR5cGVTdGVwIGV4aXN0aW5nQWdlbnRzPXtleGlzdGluZ0FnZW50c30gLz4sIC8vIDNcbiAgICBQcm9tcHRTdGVwLCAvLyA0XG4gICAgRGVzY3JpcHRpb25TdGVwLCAvLyA1XG4gICAgKCkgPT4gPFRvb2xzU3RlcCB0b29scz17dG9vbHN9IC8+LCAvLyA2XG4gICAgTW9kZWxTdGVwLCAvLyA3XG4gICAgQ29sb3JTdGVwLCAvLyA4XG4gICAgLy8gTWVtb3J5U3RlcCBpcyBjb25kaXRpb25hbGx5IGluY2x1ZGVkIGJhc2VkIG9uIEdyb3d0aEJvb2sgZ2F0ZVxuICAgIC4uLihpc0F1dG9NZW1vcnlFbmFibGVkKCkgPyBbTWVtb3J5U3RlcF0gOiBbXSksXG4gICAgKCkgPT4gKFxuICAgICAgPENvbmZpcm1TdGVwV3JhcHBlclxuICAgICAgICB0b29scz17dG9vbHN9XG4gICAgICAgIGV4aXN0aW5nQWdlbnRzPXtleGlzdGluZ0FnZW50c31cbiAgICAgICAgb25Db21wbGV0ZT17b25Db21wbGV0ZX1cbiAgICAgIC8+XG4gICAgKSxcbiAgXVxuXG4gIHJldHVybiAoXG4gICAgPFdpemFyZFByb3ZpZGVyPEFnZW50V2l6YXJkRGF0YT5cbiAgICAgIHN0ZXBzPXtzdGVwc31cbiAgICAgIGluaXRpYWxEYXRhPXt7fX1cbiAgICAgIG9uQ29tcGxldGU9eygpID0+IHtcbiAgICAgICAgLy8gV2l6YXJkIGNvbXBsZXRpb24gaXMgaGFuZGxlZCBieSBDb25maXJtU3RlcFdyYXBwZXJcbiAgICAgICAgLy8gd2hpY2ggY2FsbHMgb25Db21wbGV0ZSB3aXRoIHRoZSBhcHByb3ByaWF0ZSBtZXNzYWdlXG4gICAgICB9fVxuICAgICAgb25DYW5jZWw9e29uQ2FuY2VsfVxuICAgICAgdGl0bGU9XCJDcmVhdGUgbmV3IGFnZW50XCJcbiAgICAgIHNob3dTdGVwQ291bnRlcj17ZmFsc2V9XG4gICAgLz5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUFJLEtBQUtDLFNBQVMsUUFBUSxPQUFPO0FBQzdDLFNBQVNDLG1CQUFtQixRQUFRLDBCQUEwQjtBQUM5RCxjQUFjQyxLQUFLLFFBQVEsa0JBQWtCO0FBQzdDLGNBQWNDLGVBQWUsUUFBUSwyQ0FBMkM7QUFDaEYsU0FBU0MsY0FBYyxRQUFRLHVCQUF1QjtBQUN0RCxjQUFjQyxtQkFBbUIsUUFBUSx1QkFBdUI7QUFDaEUsY0FBY0MsZUFBZSxRQUFRLFlBQVk7QUFDakQsU0FBU0MsU0FBUyxRQUFRLDZCQUE2QjtBQUN2RCxTQUFTQyxrQkFBa0IsUUFBUSxzQ0FBc0M7QUFDekUsU0FBU0MsZUFBZSxRQUFRLG1DQUFtQztBQUNuRSxTQUFTQyxZQUFZLFFBQVEsZ0NBQWdDO0FBQzdELFNBQVNDLFlBQVksUUFBUSxnQ0FBZ0M7QUFDN0QsU0FBU0MsVUFBVSxRQUFRLDhCQUE4QjtBQUN6RCxTQUFTQyxVQUFVLFFBQVEsOEJBQThCO0FBQ3pELFNBQVNDLFNBQVMsUUFBUSw2QkFBNkI7QUFDdkQsU0FBU0MsVUFBVSxRQUFRLDhCQUE4QjtBQUN6RCxTQUFTQyxTQUFTLFFBQVEsNkJBQTZCO0FBQ3ZELFNBQVNDLFFBQVEsUUFBUSw0QkFBNEI7QUFFckQsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLEtBQUssRUFBRWpCLEtBQUs7RUFDWmtCLGNBQWMsRUFBRWpCLGVBQWUsRUFBRTtFQUNqQ2tCLFVBQVUsRUFBRSxDQUFDQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSTtFQUNyQ0MsUUFBUSxFQUFFLEdBQUcsR0FBRyxJ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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx new file mode 100644 index 0000000..343eca2 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx @@ -0,0 +1,74 @@ +import chalk from 'chalk'; +import React, { type ReactNode, useCallback, useState } from 'react'; +import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js'; +import { useSetAppState } from 'src/state/AppState.js'; +import type { Tools } from '../../../../Tool.js'; +import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js'; +import { getActiveAgentsFromList } from '../../../../tools/AgentTool/loadAgentsDir.js'; +import { editFileInEditor } from '../../../../utils/promptEditor.js'; +import { useWizard } from '../../../wizard/index.js'; +import { getNewAgentFilePath, saveAgentToFile } from '../../agentFileUtils.js'; +import type { AgentWizardData } from '../types.js'; +import { ConfirmStep } from './ConfirmStep.js'; +type Props = { + tools: Tools; + existingAgents: AgentDefinition[]; + onComplete: (message: string) => void; +}; +export function ConfirmStepWrapper({ + tools, + existingAgents, + onComplete +}: Props): ReactNode { + const { + wizardData + } = useWizard(); + const [saveError, setSaveError] = useState(null); + const setAppState = useSetAppState(); + const saveAgent = useCallback(async (openInEditor: boolean): Promise => { + if (!wizardData?.finalAgent) return; + try { + await saveAgentToFile(wizardData.location!, wizardData.finalAgent.agentType, wizardData.finalAgent.whenToUse, wizardData.finalAgent.tools, wizardData.finalAgent.getSystemPrompt(), true, wizardData.finalAgent.color, wizardData.finalAgent.model, wizardData.finalAgent.memory); + setAppState(state => { + if (!wizardData.finalAgent) return state; + const allAgents = state.agentDefinitions.allAgents.concat(wizardData.finalAgent); + return { + ...state, + agentDefinitions: { + ...state.agentDefinitions, + activeAgents: getActiveAgentsFromList(allAgents), + allAgents + } + }; + }); + if (openInEditor) { + const filePath = getNewAgentFilePath({ + source: wizardData.location!, + agentType: wizardData.finalAgent.agentType + }); + await editFileInEditor(filePath); + } + logEvent('tengu_agent_created', { + agent_type: wizardData.finalAgent.agentType, + generation_method: wizardData.wasGenerated ? 'generated' : 'manual', + source: wizardData.location!, + tool_count: wizardData.finalAgent.tools?.length ?? 'all', + has_custom_model: !!wizardData.finalAgent.model, + has_custom_color: !!wizardData.finalAgent.color, + has_memory: !!wizardData.finalAgent.memory, + memory_scope: wizardData.finalAgent.memory ?? 'none', + ...(openInEditor ? { + opened_in_editor: true + } : {}) + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS); + const message = openInEditor ? `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)} and opened in editor. ` + `If you made edits, restart to load the latest version.` : `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)}`; + onComplete(message); + } catch (err) { + setSaveError(err instanceof Error ? err.message : 'Failed to save agent'); + } + }, [wizardData, onComplete, setAppState]); + const handleSave = useCallback(() => saveAgent(false), [saveAgent]); + const handleSaveAndEdit = useCallback(() => saveAgent(true), [saveAgent]); + return ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjaGFsayIsIlJlYWN0IiwiUmVhY3ROb2RlIiwidXNlQ2FsbGJhY2siLCJ1c2VTdGF0ZSIsIkFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMiLCJsb2dFdmVudCIsInVzZVNldEFwcFN0YXRlIiwiVG9vbHMiLCJBZ2VudERlZmluaXRpb24iLCJnZXRBY3RpdmVBZ2VudHNGcm9tTGlzdCIsImVkaXRGaWxlSW5FZGl0b3IiLCJ1c2VXaXphcmQiLCJnZXROZXdBZ2VudEZpbGVQYXRoIiwic2F2ZUFnZW50VG9GaWxlIiwiQWdlbnRXaXphcmREYXRhIiwiQ29uZmlybVN0ZXAiLCJQcm9wcyIsInRvb2xzIiwiZXhpc3RpbmdBZ2VudHMiLCJvbkNvbXBsZXRlIiwibWVzc2FnZSIsIkNvbmZpcm1TdGVwV3JhcHBlciIsIndpemFyZERhdGEiLCJzYXZlRXJyb3IiLCJzZXRTYXZlRXJyb3IiLCJzZXRBcHBTdGF0ZSIsInNhdmVBZ2VudCIsIm9wZW5JbkVkaXRvciIsIlByb21pc2UiLCJmaW5hbEFnZW50IiwibG9jYXRpb24iLCJhZ2VudFR5cGUiLCJ3aGVuVG9Vc2UiLCJnZXRTeXN0ZW1Qcm9tcHQiLCJjb2xvciIsIm1vZGVsIiwibWVtb3J5Iiwic3RhdGUiLCJhbGxBZ2VudHMiLCJhZ2VudERlZmluaXRpb25zIiwiY29uY2F0IiwiYWN0aXZlQWdlbnRzIiwiZmlsZVBhdGgiLCJzb3VyY2UiLCJhZ2VudF90eXBlIiwiZ2VuZXJhdGlvbl9tZXRob2QiLCJ3YXNHZW5lcmF0ZWQiLCJ0b29sX2NvdW50IiwibGVuZ3RoIiwiaGFzX2N1c3RvbV9tb2RlbCIsImhhc19jdXN0b21fY29sb3IiLCJoYXNfbWVtb3J5IiwibWVtb3J5X3Njb3BlIiwib3BlbmVkX2luX2VkaXRvciIsImJvbGQiLCJlcnIiLCJFcnJvciIsImhhbmRsZVNhdmUiLCJoYW5kbGVTYXZlQW5kRWRpdCJdLCJzb3VyY2VzIjpbIkNvbmZpcm1TdGVwV3JhcHBlci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJ1xuaW1wb3J0IFJlYWN0LCB7IHR5cGUgUmVhY3ROb2RlLCB1c2VDYWxsYmFjaywgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB7XG4gIHR5cGUgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyxcbiAgbG9nRXZlbnQsXG59IGZyb20gJ3NyYy9zZXJ2aWNlcy9hbmFseXRpY3MvaW5kZXguanMnXG5pbXBvcnQgeyB1c2VTZXRBcHBTdGF0ZSB9IGZyb20gJ3NyYy9zdGF0ZS9BcHBTdGF0ZS5qcydcbmltcG9ydCB0eXBlIHsgVG9vbHMgfSBmcm9tICcuLi8uLi8uLi8uLi9Ub29sLmpzJ1xuaW1wb3J0IHR5cGUgeyBBZ2VudERlZmluaXRpb24gfSBmcm9tICcuLi8uLi8uLi8uLi90b29scy9BZ2VudFRvb2wvbG9hZEFnZW50c0Rpci5qcydcbmltcG9ydCB7IGdldEFjdGl2ZUFnZW50c0Zyb21MaXN0IH0gZnJvbSAnLi4vLi4vLi4vLi4vdG9vbHMvQWdlbnRUb29sL2xvYWRBZ2VudHNEaXIuanMnXG5pbXBvcnQgeyBlZGl0RmlsZUluRWRpdG9yIH0gZnJvbSAnLi4vLi4vLi4vLi4vdXRpbHMvcHJvbXB0RWRpdG9yLmpzJ1xuaW1wb3J0IHsgdXNlV2l6YXJkIH0gZnJvbSAnLi4vLi4vLi4vd2l6YXJkL2luZGV4LmpzJ1xuaW1wb3J0IHsgZ2V0TmV3QWdlbnRGaWxlUGF0aCwgc2F2ZUFnZW50VG9GaWxlIH0gZnJvbSAnLi4vLi4vYWdlbnRGaWxlVXRpbHMuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50V2l6YXJkRGF0YSB9IGZyb20gJy4uL3R5cGVzLmpzJ1xuaW1wb3J0IHsgQ29uZmlybVN0ZXAgfSBmcm9tICcuL0NvbmZpcm1TdGVwLmpzJ1xuXG50eXBlIFByb3BzID0ge1xuICB0b29sczogVG9vbHNcbiAgZXhpc3RpbmdBZ2VudHM6IEFnZW50RGVmaW5pdGlvbltdXG4gIG9uQ29tcGxldGU6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIENvbmZpcm1TdGVwV3JhcHBlcih7XG4gIHRvb2xzLFxuICBleGlzdGluZ0FnZW50cyxcbiAgb25Db21wbGV0ZSxcbn06IFByb3BzKTogUmVhY3ROb2RlIHtcbiAgY29uc3QgeyB3aXphcmREYXRhIH0gPSB1c2VXaXphcmQ8QWdlbnRXaXphcmREYXRhPigpXG4gIGNvbnN0IFtzYXZlRXJyb3IsIHNldFNhdmVFcnJvcl0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPihudWxsKVxuICBjb25zdCBzZXRBcHBTdGF0ZSA9IHVzZVNldEFwcFN0YXRlKClcblxuICBjb25zdCBzYXZlQWdlbnQgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAob3BlbkluRWRpdG9yOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICBpZiAoIXdpemFyZERhdGE/LmZpbmFsQWdlbnQpIHJldHVyblxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzYXZlQWdlbnRUb0ZpbGUoXG4gICAgICAgICAgd2l6YXJkRGF0YS5sb2NhdGlvbiEsXG4gICAgICAgICAgd2l6YXJkRGF0YS5maW5hbEFnZW50LmFnZW50VHlwZSxcbiAgICAgICAgICB3aXphcmREYXRhLmZpbmFsQWdlbnQud2hlblRvVXNlLFxuICAgICAgICAgIHdpemFyZERhdGEuZmluYWxBZ2VudC50b29scyxcbiAgICAgICAgICB3aXphcmREYXRhLmZpbmFsQWdlbnQuZ2V0U3lzdGVtUHJvbXB0KCksXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICB3aXphcmREYXRhLmZpbmFsQWdlbnQuY29sb3IsXG4gICAgICAgICAgd2l6YXJkRGF0YS5maW5hbEFnZW50Lm1vZGVsLFxuICAgICAgICAgIHdpemFyZERhdGEuZmluYWxBZ2VudC5tZW1vcnksXG4gICAgICAgIClcblxuICAgICAgICBzZXRBcHBTdGF0ZShzdGF0ZSA9PiB7XG4gICAgICAgICAgaWYgKCF3aXphcmREYXRhLmZpbmFsQWdlbnQpIHJldHVybiBzdGF0ZVxuXG4gICAgICAgICAgY29uc3QgYWxsQWdlbnRzID0gc3RhdGUuYWdlbnREZWZpbml0aW9ucy5hbGxBZ2VudHMuY29uY2F0KFxuICAgICAgICAgICAgd2l6YXJkRGF0YS5maW5hbEFnZW50LFxuICAgICAgICAgIClcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgICAgICBhZ2VudERlZmluaXRpb25zOiB7XG4gICAgICAgICAgICAgIC4uLnN0YXRlLmFnZW50RGVmaW5pdGlvbnMsXG4gICAgICAgICAgICAgIGFjdGl2ZUFnZW50czogZ2V0QWN0aXZlQWdlbnRzRnJvbUxpc3QoYWxsQWdlbnRzKSxcbiAgICAgICAgICAgICAgYWxsQWdlbnRzLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgaWYgKG9wZW5JbkVkaXRvcikge1xuICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gZ2V0TmV3QWdlbnRGaWxlUGF0aCh7XG4gICAgICAgICAgICBzb3VyY2U6IHdpemFyZERhdGEubG9jYXRpb24hLFxuICAgICAgICAgICAgYWdlbnRUeXBlOiB3aXphcmREYXRhLmZpbmFsQWdlbnQuYWdlbnRUeXBlLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgYXdhaXQgZWRpdEZpbGVJbkVkaXRvcihmaWxlUGF0aClcbiAgICAgICAgfVxuXG4gICAgICAgIGxvZ0V2ZW50KCd0ZW5ndV9hZ2VudF9jcmVhdGVkJywge1xuICAgICAgICAgIGFnZW50X3R5cGU6IHdpemFyZERhdGEuZmluYWxBZ2VudC5hZ2VudFR5cGUsXG4gICAgICAgICAgZ2VuZXJhdGlvbl9tZXRob2Q6IHdpemFyZERhdGEud2FzR2VuZXJhdGVkID8gJ2dlbmVyYXRlZCcgOiAnbWFudWFsJyxcbiAgICAgICAgICBzb3VyY2U6IHdpemFyZERhdGEubG9jYXRpb24hLFxuICAgICAgICAgIHRvb2xfY291bnQ6IHdpemFyZERhdGEuZmluYWxBZ2VudC50b29scz8ubGVuZ3RoID8/ICdhbGwnLFxuICAgICAgICAgIGhhc19jdXN0b21fbW9kZWw6ICEhd2l6YXJkRGF0YS5maW5hbEFnZW50Lm1vZGVsLFxuICAgICAgICAgIGhhc19jdXN0b21fY29sb3I6ICEhd2l6YXJkRGF0YS5maW5hbEFnZW50LmNvbG9yLFxuICAgICAgICAgIGhhc19tZW1vcnk6ICEhd2l6YXJkRGF0YS5maW5hbEFnZW50Lm1lbW9yeSxcbiAgICAgICAgICBtZW1vcnlfc2NvcGU6IHdpemFyZERhdGEuZmluYWxBZ2VudC5tZW1vcnkgPz8gJ25vbmUnLFxuICAgICAgICAgIC4uLihvcGVuSW5FZGl0b3IgPyB7IG9wZW5lZF9pbl9lZGl0b3I6IHRydWUgfSA6IHt9KSxcbiAgICAgICAgfSBhcyBBbmFseXRpY3NNZXRhZGF0YV9JX1ZFUklGSUVEX1RISVNfSVNfTk9UX0NPREVfT1JfRklMRVBBVEhTKVxuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBvcGVuSW5FZGl0b3JcbiAgICAgICAgICA/IGBDcmVhdGVkIGFnZW50OiAke2NoYWxrLmJvbGQod2l6YXJkRGF0YS5maW5hbEFnZW50LmFnZW50VHlwZSl9IGFuZCBvcGVuZWQgaW4gZWRpdG9yLiBgICtcbiAgICAgICAgICAgIGBJZiB5b3UgbWFkZSBlZGl0cywgcmVzdGFydCB0byBsb2FkIHRoZSBsYXRlc3QgdmVyc2lvbi5gXG4gICAgICAgICAgOiBgQ3JlYXRlZCBhZ2VudDogJHtjaGFsay5ib2xkKHdpemFyZERhdGEuZmluYWxBZ2VudC5hZ2VudFR5cGUpfWBcbiAgICAgICAgb25Db21wbGV0ZShtZXNzYWdlKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNldFNhdmVFcnJvcihcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogJ0ZhaWxlZCB0byBzYXZlIGFnZW50JyxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH0sXG4gICAgW3dpemFyZERhdGEsIG9uQ29tcGxldGUsIHNldEFwcFN0YXRlXSxcbiAgKVxuXG4gIGNvbnN0IGhhbmRsZVNhdmUgPSB1c2VDYWxsYmFjaygoKSA9PiBzYXZlQWdlbnQoZmFsc2UpLCBbc2F2ZUFnZW50XSlcblxuICBjb25zdCBoYW5kbGVTYXZlQW5kRWRpdCA9IHVzZUNhbGxiYWNrKCgpID0+IHNhdmVBZ2VudCh0cnVlKSwgW3NhdmVBZ2VudF0pXG5cbiAgcmV0dXJuIChcbiAgICA8Q29uZmlybVN0ZXBcbiAgICAgIHRvb2xzPXt0b29sc31cbiAgICAgIGV4aXN0aW5nQWdlbnRzPXtleGlzdGluZ0FnZW50c31cbiAgICAgIG9uU2F2ZT17aGFuZGxlU2F2ZX1cbiAgICAgIG9uU2F2ZUFuZEVkaXQ9e2hhbmRsZVNhdmVBbmRFZGl0fVxuICAgICAgZXJyb3I9e3NhdmVFcnJvcn1cbiAgICAvPlxuICApXG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLEtBQUssTUFBTSxPQUFPO0FBQ3pCLE9BQU9DLEtBQUssSUFBSSxLQUFLQyxTQUFTLEVBQUVDLFdBQVcsRUFBRUMsUUFBUSxRQUFRLE9BQU87QUFDcEUsU0FDRSxLQUFLQywwREFBMEQsRUFDL0RDLFFBQVEsUUFDSCxpQ0FBaUM7QUFDeEMsU0FBU0MsY0FBYyxRQUFRLHVCQUF1QjtBQUN0RCxjQUFjQyxLQUFLLFFBQVEscUJBQXFCO0FBQ2hELGNBQWNDLGVBQWUsUUFBUSw4Q0FBOEM7QUFDbkYsU0FBU0MsdUJBQXVCLFFBQVEsOENBQThDO0FBQ3RGLFNBQVNDLGdCQUFnQixRQUFRLG1DQUFtQztBQUNwRSxTQUFTQyxTQUFTLFFBQVEsMEJBQTBCO0FBQ3BELFNBQVNDLG1CQUFtQixFQUFFQyxlQUFlLFFBQVEseUJBQXlCO0FBQzlFLGNBQWNDLGVBQWUsUUFBUSxhQUFhO0FBQ2xELFNBQVNDLFdBQVcsUUFBUSxrQkFBa0I7QUFFOUMsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLEtBQUssRUFBRVYsS0FBSztFQUNaVyxjQUFjLEVBQUVW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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx new file mode 100644 index 0000000..56c951a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx @@ -0,0 +1,113 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { type ReactNode } from 'react'; +import { Box } from '../../../../ink.js'; +import { useKeybinding } from '../../../../keybindings/useKeybinding.js'; +import { isAutoMemoryEnabled } from '../../../../memdir/paths.js'; +import { type AgentMemoryScope, loadAgentMemoryPrompt } from '../../../../tools/AgentTool/agentMemory.js'; +import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'; +import { Select } from '../../../CustomSelect/select.js'; +import { Byline } from '../../../design-system/Byline.js'; +import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'; +import { useWizard } from '../../../wizard/index.js'; +import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'; +import type { AgentWizardData } from '../types.js'; +type MemoryOption = { + label: string; + value: AgentMemoryScope | 'none'; +}; +export function MemoryStep() { + const $ = _c(13); + const { + goNext, + goBack, + updateWizardData, + wizardData + } = useWizard(); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = { + context: "Confirmation" + }; + $[0] = t0; + } else { + t0 = $[0]; + } + useKeybinding("confirm:no", goBack, t0); + const isUserScope = wizardData.location === "userSettings"; + let t1; + if ($[1] !== isUserScope) { + t1 = isUserScope ? [{ + label: "User scope (~/.claude/agent-memory/) (Recommended)", + value: "user" + }, { + label: "None (no persistent memory)", + value: "none" + }, { + label: "Project scope (.claude/agent-memory/)", + value: "project" + }, { + label: "Local scope (.claude/agent-memory-local/)", + value: "local" + }] : [{ + label: "Project scope (.claude/agent-memory/) (Recommended)", + value: "project" + }, { + label: "None (no persistent memory)", + value: "none" + }, { + label: "User scope (~/.claude/agent-memory/)", + value: "user" + }, { + label: "Local scope (.claude/agent-memory-local/)", + value: "local" + }]; + $[1] = isUserScope; + $[2] = t1; + } else { + t1 = $[2]; + } + const memoryOptions = t1; + let t2; + if ($[3] !== goNext || $[4] !== updateWizardData || $[5] !== wizardData.finalAgent || $[6] !== wizardData.systemPrompt) { + t2 = value => { + const memory = value === "none" ? undefined : value as AgentMemoryScope; + const agentType = wizardData.finalAgent?.agentType; + updateWizardData({ + selectedMemory: memory, + finalAgent: wizardData.finalAgent ? { + ...wizardData.finalAgent, + memory, + getSystemPrompt: isAutoMemoryEnabled() && memory && agentType ? () => wizardData.systemPrompt + "\n\n" + loadAgentMemoryPrompt(agentType, memory) : () => wizardData.systemPrompt + } : undefined + }); + goNext(); + }; + $[3] = goNext; + $[4] = updateWizardData; + $[5] = wizardData.finalAgent; + $[6] = wizardData.systemPrompt; + $[7] = t2; + } else { + t2 = $[7]; + } + const handleSelect = t2; + let t3; + if ($[8] === Symbol.for("react.memo_cache_sentinel")) { + t3 = ; + $[8] = t3; + } else { + t3 = $[8]; + } + let t4; + if ($[9] !== goBack || $[10] !== handleSelect || $[11] !== memoryOptions) { + t4 = ; + $[10] = onCancel; + $[11] = t2; + $[12] = t3; + $[13] = t4; + } else { + t4 = $[13]; + } + let t5; + if ($[14] !== hookEventMetadata.description || $[15] !== onCancel || $[16] !== t4 || $[17] !== title) { + t5 = {t4}; + $[14] = hookEventMetadata.description; + $[15] = onCancel; + $[16] = t4; + $[17] = title; + $[18] = t5; + } else { + t5 = $[18]; + } + return t5; +} +function _temp2(hook, index) { + return { + label: `[${hook.config.type}] ${getHookDisplayText(hook.config)}`, + value: index.toString(), + description: hook.source === "pluginHook" && hook.pluginName ? `${hookSourceHeaderDisplayString(hook.source)} (${hook.pluginName})` : hookSourceHeaderDisplayString(hook.source) + }; +} +function _temp() { + return Esc to go back; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkhvb2tFdmVudCIsIkhvb2tFdmVudE1ldGFkYXRhIiwiQm94IiwiVGV4dCIsImdldEhvb2tEaXNwbGF5VGV4dCIsImhvb2tTb3VyY2VIZWFkZXJEaXNwbGF5U3RyaW5nIiwiSW5kaXZpZHVhbEhvb2tDb25maWciLCJTZWxlY3QiLCJEaWFsb2ciLCJQcm9wcyIsInNlbGVjdGVkRXZlbnQiLCJzZWxlY3RlZE1hdGNoZXIiLCJob29rc0ZvclNlbGVjdGVkTWF0Y2hlciIsImhvb2tFdmVudE1ldGFkYXRhIiwib25TZWxlY3QiLCJob29rIiwib25DYW5jZWwiLCJTZWxlY3RIb29rTW9kZSIsInQwIiwiJCIsIl9jIiwidGl0bGUiLCJtYXRjaGVyTWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJsZW5ndGgiLCJ0MSIsIlN5bWJvbCIsImZvciIsInQyIiwiZGVzY3JpcHRpb24iLCJfdGVtcCIsIm1hcCIsIl90ZW1wMiIsInQzIiwidmFsdWUiLCJpbmRleF8wIiwicGFyc2VJbnQiLCJob29rXzAiLCJpbmRleCIsInQ0IiwidDUiLCJsYWJlbCIsImNvbmZpZyIsInR5cGUiLCJ0b1N0cmluZyIsInNvdXJjZSIsInBsdWdpbk5hbWUiXSwic291cmNlcyI6WyJTZWxlY3RIb29rTW9kZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTZWxlY3RIb29rTW9kZSBzaG93cyBhbGwgaG9va3MgY29uZmlndXJlZCBmb3IgYSBnaXZlbiBldmVudCttYXRjaGVyIHBhaXIuXG4gKlxuICogVGhlIC9ob29rcyBtZW51IGlzIHJlYWQtb25seTogdGhpcyB2aWV3IG5vIGxvbmdlciBvZmZlcnMgXCJhZGQgbmV3IGhvb2tcIlxuICogYW5kIHNlbGVjdGluZyBhIGhvb2sgc2hvd3MgaXRzIHJlYWQtb25seSBkZXRhaWxzIGluc3RlYWQgb2YgYSBkZWxldGVcbiAqIGNvbmZpcm1hdGlvbi5cbiAqL1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IEhvb2tFdmVudCB9IGZyb20gJ3NyYy9lbnRyeXBvaW50cy9hZ2VudFNka1R5cGVzLmpzJ1xuaW1wb3J0IHR5cGUgeyBIb29rRXZlbnRNZXRhZGF0YSB9IGZyb20gJ3NyYy91dGlscy9ob29rcy9ob29rc0NvbmZpZ01hbmFnZXIuanMnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQge1xuICBnZXRIb29rRGlzcGxheVRleHQsXG4gIGhvb2tTb3VyY2VIZWFkZXJEaXNwbGF5U3RyaW5nLFxuICB0eXBlIEluZGl2aWR1YWxIb29rQ29uZmlnLFxufSBmcm9tICcuLi8uLi91dGlscy9ob29rcy9ob29rc1NldHRpbmdzLmpzJ1xuaW1wb3J0IHsgU2VsZWN0IH0gZnJvbSAnLi4vQ3VzdG9tU2VsZWN0L3NlbGVjdC5qcydcbmltcG9ydCB7IERpYWxvZyB9IGZyb20gJy4uL2Rlc2lnbi1zeXN0ZW0vRGlhbG9nLmpzJ1xuXG50eXBlIFByb3BzID0ge1xuICBzZWxlY3RlZEV2ZW50OiBIb29rRXZlbnRcbiAgc2VsZWN0ZWRNYXRjaGVyOiBzdHJpbmcgfCBudWxsXG4gIGhvb2tzRm9yU2VsZWN0ZWRNYXRjaGVyOiBJbmRpdmlkdWFsSG9va0NvbmZpZ1tdXG4gIGhvb2tFdmVudE1ldGFkYXRhOiBIb29rRXZlbnRNZXRhZGF0YVxuICBvblNlbGVjdDogKGhvb2s6IEluZGl2aWR1YWxIb29rQ29uZmlnKSA9PiB2b2lkXG4gIG9uQ2FuY2VsOiAoKSA9PiB2b2lkXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBTZWxlY3RIb29rTW9kZSh7XG4gIHNlbGVjdGVkRXZlbnQsXG4gIHNlbGVjdGVkTWF0Y2hlcixcbiAgaG9va3NGb3JTZWxlY3RlZE1hdGNoZXIsXG4gIGhvb2tFdmVudE1ldGFkYXRhLFxuICBvblNlbGVjdCxcbiAgb25DYW5jZWwsXG59OiBQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IHRpdGxlID1cbiAgICBob29rRXZlbnRNZXRhZGF0YS5tYXRjaGVyTWV0YWRhdGEgIT09IHVuZGVmaW5lZFxuICAgICAgPyBgJHtzZWxlY3RlZEV2ZW50fSAtIE1hdGNoZXI6ICR7c2VsZWN0ZWRNYXRjaGVyIHx8ICcoYWxsKSd9YFxuICAgICAgOiBzZWxlY3RlZEV2ZW50XG5cbiAgaWYgKGhvb2tzRm9yU2VsZWN0ZWRNYXRjaGVyLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiAoXG4gICAgICA8RGlhbG9nXG4gICAgICAgIHRpdGxlPXt0aXRsZX1cbiAgICAgICAgc3VidGl0bGU9e2hvb2tFdmVudE1ldGFkYXRhLmRlc2NyaXB0aW9ufVxuICAgICAgICBvbkNhbmNlbD17b25DYW5jZWx9XG4gICAgICAgIGlucHV0R3VpZGU9eygpID0+IDxUZXh0PkVzYyB0byBnbyBiYWNrPC9UZXh0Pn1cbiAgICAgID5cbiAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgZ2FwPXsxfT5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5ObyBob29rcyBjb25maWd1cmVkIGZvciB0aGlzIGV2ZW50LjwvVGV4dD5cbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgIFRvIGFkZCBob29rcywgZWRpdCBzZXR0aW5ncy5qc29uIGRpcmVjdGx5IG9yIGFzayBDbGF1ZGUuXG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgIDwvRGlhbG9nPlxuICAgIClcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPERpYWxvZ1xuICAgICAgdGl0bGU9e3RpdGxlfVxuICAgICAgc3VidGl0bGU9e2hvb2tFdmVudE1ldGFkYXRhLmRlc2NyaXB0aW9ufVxuICAgICAgb25DYW5jZWw9e29uQ2FuY2VsfVxuICAgID5cbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8U2VsZWN0XG4gICAgICAgICAgb3B0aW9ucz17aG9va3NGb3JTZWxlY3RlZE1hdGNoZXIubWFwKChob29rLCBpbmRleCkgPT4gKHtcbiAgICAgICAgICAgIGxhYmVsOiBgWyR7aG9vay5jb25maWcudHlwZX1dICR7Z2V0SG9va0Rpc3BsYXlUZXh0KGhvb2suY29uZmlnKX1gLFxuICAgICAgICAgICAgdmFsdWU6IGluZGV4LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgaG9vay5zb3VyY2UgPT09ICdwbHVnaW5Ib29rJyAmJiBob29rLnBsdWdpbk5hbWVcbiAgICAgICAgICAgICAgICA/IGAke2hvb2tTb3VyY2VIZWFkZXJEaXNwbGF5U3RyaW5nKGhvb2suc291cmNlKX0gKCR7aG9vay5wbHVnaW5OYW1lfSlgXG4gICAgICAgICAgICAgICAgOiBob29rU291cmNlSGVhZGVyRGlzcGxheVN0cmluZyhob29rLnNvdXJjZSksXG4gICAgICAgICAgfSkpfVxuICAgICAgICAgIG9uQ2hhbmdlPXt2YWx1ZSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHBhcnNlSW50KHZhbHVlLCAxMClcbiAgICAgICAgICAgIGNvbnN0IGhvb2sgPSBob29rc0ZvclNlbGVjdGVkTWF0Y2hlcltpbmRleF1cbiAgICAgICAgICAgIGlmIChob29rKSB7XG4gICAgICAgICAgICAgIG9uU2VsZWN0KGhvb2spXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfX1cbiAgICAgICAgICBvbkNhbmNlbD17b25DYW5jZWx9XG4gICAgICAgIC8+XG4gICAgICA8L0JveD5cbiAgICA8L0RpYWxvZz5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLEtBQUtBLEtBQUssTUFBTSxPQUFPO0FBQzlCLGNBQWNDLFNBQVMsUUFBUSxrQ0FBa0M7QUFDakUsY0FBY0MsaUJBQWlCLFFBQVEsdUNBQXVDO0FBQzlFLFNBQVNDLEdBQUcsRUFBRUMsSUFBSSxRQUFRLGNBQWM7QUFDeEMsU0FDRUMsa0JBQWtCLEVBQ2xCQyw2QkFBNkIsRUFDN0IsS0FBS0Msb0JBQW9CLFFB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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/hooks/SelectMatcherMode.tsx b/_all-in-one-upload/cc-haha/src/components/hooks/SelectMatcherMode.tsx new file mode 100644 index 0000000..d292fc8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/hooks/SelectMatcherMode.tsx @@ -0,0 +1,144 @@ +import { c as _c } from "react/compiler-runtime"; +/** + * SelectMatcherMode shows the configured matchers for a selected hook event. + * + * The /hooks menu is read-only: this view no longer offers "add new matcher" + * and simply lets the user drill into each matcher to see its hooks. + */ +import * as React from 'react'; +import type { HookEvent } from 'src/entrypoints/agentSdkTypes.js'; +import { Box, Text } from '../../ink.js'; +import { type HookSource, hookSourceInlineDisplayString, type IndividualHookConfig } from '../../utils/hooks/hooksSettings.js'; +import { plural } from '../../utils/stringUtils.js'; +import { Select } from '../CustomSelect/select.js'; +import { Dialog } from '../design-system/Dialog.js'; +type MatcherWithSource = { + matcher: string; + sources: HookSource[]; + hookCount: number; +}; +type Props = { + selectedEvent: HookEvent; + matchersForSelectedEvent: string[]; + hooksByEventAndMatcher: Record>; + eventDescription: string; + onSelect: (matcher: string) => void; + onCancel: () => void; +}; +export function SelectMatcherMode(t0) { + const $ = _c(25); + const { + selectedEvent, + matchersForSelectedEvent, + hooksByEventAndMatcher, + eventDescription, + onSelect, + onCancel + } = t0; + let t1; + if ($[0] !== hooksByEventAndMatcher || $[1] !== matchersForSelectedEvent || $[2] !== selectedEvent) { + let t2; + if ($[4] !== hooksByEventAndMatcher || $[5] !== selectedEvent) { + t2 = matcher => { + const hooks = hooksByEventAndMatcher[selectedEvent]?.[matcher] || []; + const sources = Array.from(new Set(hooks.map(_temp))); + return { + matcher, + sources, + hookCount: hooks.length + }; + }; + $[4] = hooksByEventAndMatcher; + $[5] = selectedEvent; + $[6] = t2; + } else { + t2 = $[6]; + } + t1 = matchersForSelectedEvent.map(t2); + $[0] = hooksByEventAndMatcher; + $[1] = matchersForSelectedEvent; + $[2] = selectedEvent; + $[3] = t1; + } else { + t1 = $[3]; + } + const matchersWithSources = t1; + if (matchersForSelectedEvent.length === 0) { + const t2 = `${selectedEvent} - Matchers`; + let t3; + if ($[7] === Symbol.for("react.memo_cache_sentinel")) { + t3 = No hooks configured for this event.To add hooks, edit settings.json directly or ask Claude.; + $[7] = t3; + } else { + t3 = $[7]; + } + let t4; + if ($[8] !== eventDescription || $[9] !== onCancel || $[10] !== t2) { + t4 = {t3}; + $[8] = eventDescription; + $[9] = onCancel; + $[10] = t2; + $[11] = t4; + } else { + t4 = $[11]; + } + return t4; + } + const t2 = `${selectedEvent} - Matchers`; + let t3; + if ($[12] !== matchersWithSources) { + t3 = matchersWithSources.map(_temp3); + $[12] = matchersWithSources; + $[13] = t3; + } else { + t3 = $[13]; + } + let t4; + if ($[14] !== onSelect) { + t4 = value => { + onSelect(value); + }; + $[14] = onSelect; + $[15] = t4; + } else { + t4 = $[15]; + } + let t5; + if ($[16] !== onCancel || $[17] !== t3 || $[18] !== t4) { + t5 = ({ + ...o, + disabled: true + })) : options : options} isDisabled={feature('BASH_CLASSIFIER') ? toolUseConfirm.classifierAutoApproved : false} inlineDescriptions onChange={onSelect} onCancel={() => handleReject()} onFocus={handleFocus} onInputModeToggle={handleInputModeToggle} /> + + + + Esc to cancel + {(focusedOption === 'yes' && !yesInputMode || focusedOption === 'no' && !noInputMode) && ' · Tab to amend'} + {explainerState.enabled && ` · ctrl+e to ${explainerState.visible ? 'hide' : 'explain'}`} + + {toolUseContext.options.debug && Ctrl+d to show debug info} + + } + ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiZmlndXJlcyIsIlJlYWN0IiwidXNlQ2FsbGJhY2siLCJ1c2VFZmZlY3QiLCJ1c2VNZW1vIiwidXNlUmVmIiwidXNlU3RhdGUiLCJCb3giLCJUZXh0IiwidXNlVGhlbWUiLCJ1c2VLZXliaW5kaW5nIiwiZ2V0RmVhdHVyZVZhbHVlX0NBQ0hFRF9NQVlfQkVfU1RBTEUiLCJBbmFseXRpY3NNZXRhZGF0YV9JX1ZFUklGSUVEX1RISVNfSVNfTk9UX0NPREVfT1JfRklMRVBBVEhTIiwibG9nRXZlbnQiLCJzYW5pdGl6ZVRvb2xOYW1lRm9yQW5hbHl0aWNzIiwidXNlQXBwU3RhdGUiLCJCYXNoVG9vbCIsImdldEZpcnN0V29yZFByZWZpeCIsImdldFNpbXBsZUNvbW1hbmRQcmVmaXgiLCJnZXREZXN0cnVjdGl2ZUNvbW1hbmRXYXJuaW5nIiwicGFyc2VTZWRFZGl0Q29tbWFuZCIsInNob3VsZFVzZVNhbmRib3giLCJnZXRDb21wb3VuZENvbW1hbmRQcmVmaXhlc1N0YXRpYyIsImNyZWF0ZVByb21wdFJ1bGVDb250ZW50IiwiZ2VuZXJhdGVHZW5lcmljRGVzY3JpcHRpb24iLCJnZXRCYXNoUHJvbXB0QWxsb3dEZXNjcmlwdGlvbnMiLCJpc0NsYXNzaWZpZXJQZXJtaXNzaW9uc0VuYWJsZWQiLCJleHRyYWN0UnVsZXMiLCJQZXJtaXNzaW9uVXBkYXRlIiwiU2FuZGJveE1hbmFnZXIiLCJTZWxlY3QiLCJTaGltbWVyQ2hhciIsInVzZVNoaW1tZXJBbmltYXRpb24iLCJVbmFyeUV2ZW50IiwidXNlUGVybWlzc2lvblJlcXVlc3RMb2dnaW5nIiwiUGVybWlzc2lvbkRlY2lzaW9uRGVidWdJbmZvIiwiUGVybWlzc2lvbkRpYWxvZyIsIlBlcm1pc3Npb25FeHBsYWluZXJDb250ZW50IiwidXNlUGVybWlzc2lvbkV4cGxhaW5lclVJIiwiUGVybWlzc2lvblJlcXVlc3RQcm9wcyIsIlBlcm1pc3Npb25SdWxlRXhwbGFuYXRpb24iLCJTZWRFZGl0UGVybWlzc2lvblJlcXVlc3QiLCJ1c2VTaGVsbFBlcm1pc3Npb25GZWVkYmFjayIsImxvZ1VuYXJ5UGVybWlzc2lvbkV2ZW50IiwiYmFzaFRvb2xVc2VPcHRpb25zIiwiQ0hFQ0tJTkdfVEVYVCIsIkNsYXNzaWZpZXJDaGVja2luZ1N1YnRpdGxlIiwiJCIsIl9jIiwicmVmIiwiZ2xpbW1lckluZGV4IiwidDAiLCJTeW1ib2wiLCJmb3IiLCJ0MSIsIm1hcCIsImNoYXIiLCJpIiwidDIiLCJCYXNoUGVybWlzc2lvblJlcXVlc3QiLCJwcm9wcyIsInRvb2xVc2VDb25maXJtIiwidG9vbFVzZUNvbnRleHQiLCJvbkRvbmUiLCJvblJlamVjdCIsInZlcmJvc2UiLCJ3b3JrZXJCYWRnZSIsImNvbW1hbmQiLCJkZXNjcmlwdGlvbiIsImlucHV0IiwiaW5wdXRTY2hlbWEiLCJwYXJzZSIsInNlZEluZm8iLCJCYXNoUGVybWlzc2lvblJlcXVlc3RJbm5lciIsIl92ZXJib3NlIiwiUmVhY3ROb2RlIiwidGhlbWUiLCJ0b29sUGVybWlzc2lvbkNvbnRleHQiLCJzIiwiZXhwbGFpbmVyU3RhdGUiLCJ0b29sTmFtZSIsInRvb2wiLCJuYW1lIiwidG9vbElucHV0IiwidG9vbERlc2NyaXB0aW9uIiwibWVzc2FnZXMiLCJ5ZXNJbnB1dE1vZGUiLCJub0lucHV0TW9kZSIsInllc0ZlZWRiYWNrTW9kZUVudGVyZWQiLCJub0ZlZWRiYWNrTW9kZUVudGVyZWQiLCJhY2NlcHRGZWVkYmFjayIsInJlamVjdEZlZWRiYWNrIiwic2V0QWNjZXB0RmVlZGJhY2siLCJzZXRSZWplY3RGZWVkYmFjayIsImZvY3VzZWRPcHRpb24iLCJoYW5kbGVJbnB1dE1vZGVUb2dnbGUiLCJoYW5kbGVSZWplY3QiLCJoYW5kbGVGb2N1cyIsImV4cGxhaW5lclZpc2libGUiLCJ2aXNpYmxlIiwic2hvd1Blcm1pc3Npb25EZWJ1ZyIsInNldFNob3dQZXJtaXNzaW9uRGVidWciLCJjbGFzc2lmaWVyRGVzY3JpcHRpb24iLCJzZXRDbGFzc2lmaWVyRGVzY3JpcHRpb24iLCJpbml0aWFsQ2xhc3NpZmllckRlc2NyaXB0aW9uRW1wdHkiLCJzZXRJbml0aWFsQ2xhc3NpZmllckRlc2NyaXB0aW9uRW1wdHkiLCJ0cmltIiwiYWJvcnRDb250cm9sbGVyIiwiQWJvcnRDb250cm9sbGVyIiwic2lnbmFsIiwidGhlbiIsImdlbmVyaWMiLCJhYm9ydGVkIiwiY2F0Y2giLCJhYm9ydCIsImlzQ29tcG91bmQiLCJwZXJtaXNzaW9uUmVzdWx0IiwiZGVjaXNpb25SZWFzb24iLCJ0eXBlIiwiZWRpdGFibGVQcmVmaXgiLCJzZXRFZGl0YWJsZVByZWZpeCIsImJhY2tlbmRCYXNoUnVsZXMiLCJzdWdnZXN0aW9ucyIsInVuZGVmaW5lZCIsImZpbHRlciIsInIiLCJydWxlQ29udGVudCIsImxlbmd0aCIsInR3byIsIm9uZSIsImhhc1VzZXJFZGl0ZWRQcmVmaXgiLCJvbkVkaXRhYmxlUHJlZml4Q2hhbmdlIiwidmFsdWUiLCJjdXJyZW50IiwiY2FuY2VsbGVkIiwic3ViY21kIiwiaXNSZWFkT25seSIsInByZWZpeGVzIiwiY2xhc3NpZmllcldhc0NoZWNraW5nIiwiY2xhc3NpZmllckNoZWNrSW5Qcm9ncmVzcyIsImRlc3RydWN0aXZlV2FybmluZyIsInNhbmRib3hpbmdFbmFibGVkIiwiaXNTYW5kYm94ZWQiLCJpc1NhbmRib3hpbmdFbmFibGVkIiwidW5hcnlFdmVudCIsImNvbXBsZXRpb25fdHlwZSIsImxhbmd1YWdlX25hbWUiLCJleGlzdGluZ0FsbG93RGVzY3JpcHRpb25zIiwib3B0aW9ucyIsImJlaGF2aW9yIiwib25SZWplY3RGZWVkYmFja0NoYW5nZSIsIm9uQWNjZXB0RmVlZGJhY2tDaGFuZ2UiLCJvbkNsYXNzaWZpZXJEZXNjcmlwdGlvbkNoYW5nZSIsImhhbmRsZVRvZ2dsZURlYnVnIiwicHJldiIsImNvbnRleHQiLCJoYW5kbGVEaXNtaXNzQ2hlY2ttYXJrIiwib25EaXNtaXNzQ2hlY2ttYXJrIiwiaXNBY3RpdmUiLCJjbGFzc2lmaWVyQXV0b0FwcHJvdmVkIiwib25TZWxlY3QiLCJvcHRpb25JbmRleCIsIlJlY29yZCIsInllcyIsIm5vIiwib3B0aW9uX2luZGV4IiwiZXhwbGFpbmVyX3Zpc2libGUiLCJ0b29sTmFtZUZvckFuYWx5dGljcyIsInRyaW1tZWRQcmVmaXgiLCJvbkFsbG93IiwicHJlZml4VXBkYXRlcyIsInJ1bGVzIiwiZGVzdGluYXRpb24iLCJ0cmltbWVkRGVzY3JpcHRpb24iLCJwZXJtaXNzaW9uVXBkYXRlcyIsInRyaW1tZWRGZWVkYmFjayIsImlzTWNwIiwiaGFzX2luc3RydWN0aW9ucyIsImluc3RydWN0aW9uc19sZW5ndGgiLCJlbnRlcmVkX2ZlZWRiYWNrX21vZGUiLCJjbGFzc2lmaWVyU3VidGl0bGUiLCJ0aWNrIiwiY2xhc3NpZmllck1hdGNoZWRSdWxlIiwicmVuZGVyVG9vbFVzZU1lc3NhZ2UiLCJwcm9taXNlIiwiZGVidWciLCJvIiwiZGlzYWJsZWQiLCJlbmFibGVkIl0sInNvdXJjZXMiOlsiQmFzaFBlcm1pc3Npb25SZXF1ZXN0LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmZWF0dXJlIH0gZnJvbSAnYnVuOmJ1bmRsZSdcbmltcG9ydCBmaWd1cmVzIGZyb20gJ2ZpZ3VyZXMnXG5pbXBvcnQgUmVhY3QsIHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQm94LCBUZXh0LCB1c2VUaGVtZSB9IGZyb20gJy4uLy4uLy4uL2luay5qcydcbmltcG9ydCB7IHVzZUtleWJpbmRpbmcgfSBmcm9tICcuLi8uLi8uLi9rZXliaW5kaW5ncy91c2VLZXliaW5kaW5nLmpzJ1xuaW1wb3J0IHsgZ2V0RmVhdHVyZVZhbHVlX0NBQ0hFRF9NQVlfQkVfU1RBTEUgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9hbmFseXRpY3MvZ3Jvd3RoYm9vay5qcydcbmltcG9ydCB7XG4gIHR5cGUgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyxcbiAgbG9nRXZlbnQsXG59IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB7IHNhbml0aXplVG9vbE5hbWVGb3JBbmFseXRpY3MgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9hbmFseXRpY3MvbWV0YWRhdGEuanMnXG5pbXBvcnQgeyB1c2VBcHBTdGF0ZSB9IGZyb20gJy4uLy4uLy4uL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHsgQmFzaFRvb2wgfSBmcm9tICcuLi8uLi8uLi90b29scy9CYXNoVG9vbC9CYXNoVG9vbC5qcydcbmltcG9ydCB7XG4gIGdldEZpcnN0V29yZFByZWZpeCxcbiAgZ2V0U2ltcGxlQ29tbWFuZFByZWZpeCxcbn0gZnJvbSAnLi4vLi4vLi4vdG9vbHMvQmFzaFRvb2wvYmFzaFBlcm1pc3Npb25zLmpzJ1xuaW1wb3J0IHsgZ2V0RGVzdHJ1Y3RpdmVDb21tYW5kV2FybmluZyB9IGZyb20gJy4uLy4uLy4uL3Rvb2xzL0Jhc2hUb29sL2Rlc3RydWN0aXZlQ29tbWFuZFdhcm5pbmcuanMnXG5pbXBvcnQgeyBwYXJzZVNlZEVkaXRDb21tYW5kIH0gZnJvbSAnLi4vLi4vLi4vdG9vbHMvQmFzaFRvb2wvc2VkRWRpdFBhcnNlci5qcydcbmltcG9ydCB7IHNob3VsZFVzZVNhbmRib3ggfSBmcm9tICcuLi8uLi8uLi90b29scy9CYXNoVG9vbC9zaG91bGRVc2VTYW5kYm94LmpzJ1xuaW1wb3J0IHsgZ2V0Q29tcG91bmRDb21tYW5kUHJlZml4ZXNTdGF0aWMgfSBmcm9tICcuLi8uLi8uLi91dGlscy9iYXNoL3ByZWZpeC5qcydcbmltcG9ydCB7XG4gIGNyZWF0ZVByb21wdFJ1bGVDb250ZW50LFxuICBnZW5lcmF0ZUdlbmVyaWNEZXNjcmlwdGlvbixcbiAgZ2V0QmFzaFByb21wdEFsbG93RGVzY3JpcHRpb25zLFxuICBpc0NsYXNzaWZpZXJQZXJtaXNzaW9uc0VuYWJsZWQsXG59IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL2Jhc2hDbGFzc2lmaWVyLmpzJ1xuaW1wb3J0IHsgZXh0cmFjdFJ1bGVzIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvcGVybWlzc2lvbnMvUGVybWlzc2lvblVwZGF0ZS5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvblVwZGF0ZSB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25VcGRhdGVTY2hlbWEuanMnXG5pbXBvcnQgeyBTYW5kYm94TWFuYWdlciB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3NhbmRib3gvc2FuZGJveC1hZGFwdGVyLmpzJ1xuaW1wb3J0IHsgU2VsZWN0IH0gZnJvbSAnLi4vLi4vQ3VzdG9tU2VsZWN0L3NlbGVjdC5qcydcbmltcG9ydCB7IFNoaW1tZXJDaGFyIH0gZnJvbSAnLi4vLi4vU3Bpbm5lci9TaGltbWVyQ2hhci5qcydcbmltcG9ydCB7IHVzZVNoaW1tZXJBbmltYXRpb24gfSBmcm9tICcuLi8uLi9TcGlubmVyL3VzZVNoaW1tZXJBbmltYXRpb24uanMnXG5pbXBvcnQgeyB0eXBlIFVuYXJ5RXZlbnQsIHVzZVBlcm1pc3Npb25SZXF1ZXN0TG9nZ2luZyB9IGZyb20gJy4uL2hvb2tzLmpzJ1xuaW1wb3J0IHsgUGVybWlzc2lvbkRlY2lzaW9uRGVidWdJbmZvIH0gZnJvbSAnLi4vUGVybWlzc2lvbkRlY2lzaW9uRGVidWdJbmZvLmpzJ1xuaW1wb3J0IHsgUGVybWlzc2lvbkRpYWxvZyB9IGZyb20gJy4uL1Blcm1pc3Npb25EaWFsb2cuanMnXG5pbXBvcnQge1xuICBQZXJtaXNzaW9uRXhwbGFpbmVyQ29udGVudCxcbiAgdXNlUGVybWlzc2lvbkV4cGxhaW5lclVJLFxufSBmcm9tICcuLi9QZXJtaXNzaW9uRXhwbGFuYXRpb24uanMnXG5pbXBvcnQgdHlwZSB7IFBlcm1pc3Npb25SZXF1ZXN0UHJvcHMgfSBmcm9tICcuLi9QZXJtaXNzaW9uUmVxdWVzdC5qcydcbmltcG9ydCB7IFBlcm1pc3Npb25SdWxlRXhwbGFuYXRpb24gfSBmcm9tICcuLi9QZXJtaXNzaW9uUnVsZUV4cGxhbmF0aW9uLmpzJ1xuaW1wb3J0IHsgU2VkRWRpdFBlcm1pc3Npb25SZXF1ZXN0IH0gZnJvbSAnLi4vU2VkRWRpdFBlcm1pc3Npb25SZXF1ZXN0L1NlZEVkaXRQZXJtaXNzaW9uUmVxdWVzdC5qcydcbmltcG9ydCB7IHVzZVNoZWxsUGVybWlzc2lvbkZlZWRiYWNrIH0gZnJvbSAnLi4vdXNlU2hlbGxQZXJtaXNzaW9uRmVlZGJhY2suanMnXG5pbXBvcnQgeyBsb2dVbmFyeVBlcm1pc3Npb25FdmVudCB9IGZyb20gJy4uL3V0aWxzLmpzJ1xuaW1wb3J0IHsgYmFzaFRvb2xVc2VPcHRpb25zIH0gZnJvbSAnLi9iYXNoVG9vbFVzZU9wdGlvbnMuanMnXG5cbmNvbnN0IENIRUNLSU5HX1RFWFQgPSAnQXR0ZW1wdGluZyB0byBhdXRvLWFwcHJvdmVcXHUyMDI2J1xuXG4vLyBJc29sYXRlcyB0aGUgMjBmcHMgc2hpbW1lciBjbG9jayBmcm9tIEJhc2hQZXJtaXNzaW9uUmVxdWVzdElubmVyLiBCZWZvcmUgdGhpc1xuLy8gZXh0cmFjdGlvbiwgdXNlU2hpbW1lckFuaW1hdGlvbiBsaXZlZCBpbnNpZGUgdGhlIDUzNS1saW5lIElubmVyIGJvZHksIHNvIGV2ZXJ5XG4vLyA1MG1zIGNsb2NrIHRpY2sgcmUtcmVuZGVyZWQgdGhlIGVudGlyZSBkaWFsb2cgKFBlcm1pc3Npb25EaWFsb2cgKyBTZWxlY3QgK1xuLy8gYWxsIGNoaWxkcmVuKSBmb3IgdGhlIH4xLTMgc2Vjb25kcyB0aGUgY2xhc3NpZmllciB0eXBpY2FsbHkgdGFrZXMuIElubmVyIGFsc29cbi8vIGhhcyBhIENvbXBpbGVyIGJhaWxvdXQgKHNlZSBiZWxvdyksIHNvIG5vdGhpbmcgd2FzIGF1dG8tbWVtb2l6ZWQg4oCUIHRoZSBmdWxsXG4vLyBKU1ggdHJlZSB3YXMgcmVjb25zdHJ1Y3RlZCAyMC02MCB0aW1lcyBwZXIgY2xhc3NpZmllciBjaGVjay5cbmZ1bmN0aW9uIENsYXNzaWZpZXJDaGVja2luZ1N1YnRpdGxlKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IFtyZWYsIGdsaW1tZXJJbmRleF0gPSB1c2VTaGltbWVyQW5pbWF0aW9uKFxuICAgICdyZXF1ZXN0aW5nJyxcbiAgICBDSEVDS0lOR19URVhULFxuICAgIGZhbHNlLFxuICApXG4gIHJldHVybiAoXG4gICAgPEJveCByZWY9e3JlZn0+XG4gICAgICA8VGV4dD5cbiAgICAgICAge1suLi5DSEVDS0lOR19URVhUXS5tYXAoKGNoYXIsIGkpID0+IChcbiAgICAgICAgICA8U2hpbW1lckNoYXJcbiAgICAgICAgICAgIGtleT17aX1cbiAgICAgICAgICAgIGNoYXI9e2NoYXJ9XG4gICAgICAgICAgICBpbmRleD17aX1cbiAgICAgICAgICAgIGdsaW1tZXJJbmRleD17Z2xpbW1lckluZGV4fVxuICAgICAgICAgICAgbWVzc2FnZUNvbG9yPVwiaW5hY3RpdmVcIlxuICAgICAgICAgICAgc2hpbW1lckNvbG9yPVwic3VidGxlXCJcbiAgICAgICAgICAvPlxuICAgICAgICApKX1cbiAgICAgIDwvVGV4dD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gQmFzaFBlcm1pc3Npb25SZXF1ZXN0KFxuICBwcm9wczogUGVybWlzc2lvblJlcXVlc3RQcm9wcyxcbik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IHtcbiAgICB0b29sVXNlQ29uZmlybSxcbiAgICB0b29sVXNlQ29udGV4dCxcbiAgICBvbkRvbmUsXG4gICAgb25SZWplY3QsXG4gICAgdmVyYm9zZSxcbiAgICB3b3JrZXJCYWRnZSxcbiAgfSA9IHByb3BzXG5cbiAgY29uc3QgeyBjb21tYW5kLCBkZXNjcmlwdGlvbiB9ID0gQmFzaFRvb2wuaW5wdXRTY2hlbWEucGFyc2UoXG4gICAgdG9vbFVzZUNvbmZpcm0uaW5wdXQsXG4gIClcblxuICAvLyBEZXRlY3Qgc2VkIGluLXBsYWNlIGVkaXQgY29tbWFuZHMgYW5kIGRlbGVnYXRlIHRvIFNlZEVkaXRQZXJtaXNzaW9uUmVxdWVzdFxuICAvLyBUaGlzIHJlbmRlcnMgc2VkIGVkaXRzIGxpa2UgZmlsZSBlZGl0cyB3aXRoIGEgZGlmZiB2aWV3XG4gIGNvbnN0IHNlZEluZm8gPSBwYXJzZVNlZEVkaXRDb21tYW5kKGNvbW1hbmQpXG5cbiAgaWYgKHNlZEluZm8pIHtcbiAgICByZXR1cm4gKFxuICAgICAgPFNlZEVkaXRQZXJtaXNzaW9uUmVxdWVzdFxuICAgICAgICB0b29sVXNlQ29uZmlybT17dG9vbFVzZUNvbmZpcm19XG4gICAgICAgIHRvb2xVc2VDb250ZXh0PXt0b29sVXNlQ29udGV4dH1cbiAgICAgICAgb25Eb25lPXtvbkRvbmV9XG4gICAgICAgIG9uUmVqZWN0PXtvblJlamVjdH1cbiAgICAgICAgdmVyYm9zZT17dmVyYm9zZX1cbiAgICAgICAgd29ya2VyQmFkZ2U9e3dvcmtlckJhZGdlfVxuICAgICAgICBzZWRJbmZvPXtzZWRJbmZvfVxuICAgICAgLz5cbiAgICApXG4gIH1cblxuICAvLyBSZWd1bGFyIGJhc2ggY29tbWFuZCAtIHJlbmRlciB3aXRoIGhvb2tzXG4gIHJldHVybiAoXG4gICAgPEJhc2hQZXJtaXNzaW9uUmVxdWVzdElubmVyXG4gICAgICB0b29sVXNlQ29uZmlybT17dG9vbFVzZUNvbmZpcm19XG4gICAgICB0b29sVXNlQ29udGV4dD17dG9vbFVzZUNvbnRleHR9XG4gICAgICBvbkRvbmU9e29uRG9uZX1cbiAgICAgIG9uUmVqZWN0PXtvblJlamVjdH1cbiAgICAgIHZlcmJvc2U9e3ZlcmJvc2V9XG4gICAgICB3b3JrZXJCYWRnZT17d29ya2VyQmFkZ2V9XG4gICAgICBjb21tYW5kPXtjb21tYW5kfVxuICAgICAgZGVzY3JpcHRpb249e2Rlc2NyaXB0aW9ufVxuICAgIC8+XG4gIClcbn1cblxuLy8gSW5uZXIgY29tcG9uZW50IHRoYXQgdXNlcyBob29rcyAtIG9ubHkgY2FsbGVkIGZvciBub24tTUNQIENMSSBjb21tYW5kc1xuZnVuY3Rpb24gQmFzaFBlcm1pc3Npb25SZXF1ZXN0SW5uZXIoe1xuICB0b29sVXNlQ29uZmlybSxcbiAgdG9vbFVzZUNvbnRleHQsXG4gIG9uRG9uZSxcbiAgb25SZWplY3QsXG4gIHZlcmJvc2U6IF92ZXJib3NlLFxuICB3b3JrZXJCYWRnZSxcbiAgY29tbWFuZCxcbiAgZGVzY3JpcHRpb24sXG59OiBQZXJtaXNzaW9uUmVxdWVzdFByb3BzICYge1xuICBjb21tYW5kOiBzdHJpbmdcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBbdGhlbWVdID0gdXNlVGhlbWUoKVxuICBjb25zdCB0b29sUGVybWlzc2lvbkNvbnRleHQgPSB1c2VBcHBTdGF0ZShzID0+IHMudG9vbFBlcm1pc3Npb25Db250ZXh0KVxuICBjb25zdCBleHBsYWluZXJTdGF0ZSA9IHVzZVBlcm1pc3Npb25FeHBsYWluZXJVSSh7XG4gICAgdG9vbE5hbWU6IHRvb2xVc2VDb25maXJtLnRvb2wubmFtZSxcbiAgICB0b29sSW5wdXQ6IHRvb2xVc2VDb25maXJtLmlucHV0LFxuICAgIHRvb2xEZXNjcmlwdGlvbjogdG9vbFVzZUNvbmZpcm0uZGVzY3JpcHRpb24sXG4gICAgbWVzc2FnZXM6IHRvb2xVc2VDb250ZXh0Lm1lc3NhZ2VzLFxuICB9KVxuICBjb25zdCB7XG4gICAgeWVzSW5wdXRNb2RlLFxuICAgIG5vSW5wdXRNb2RlLFxuICAgIHllc0ZlZWRiYWNrTW9kZUVudGVyZWQsXG4gICAgbm9GZWVkYmFja01vZGVFbnRlcmVkLFxuICAgIGFjY2VwdEZlZWRiYWNrLFxuICAgIHJlamVjdEZlZWRiYWNrLFxuICAgIHNldEFjY2VwdEZlZWRiYWNrLFxuICAgIHNldFJlamVjdEZlZWRiYWNrLFxuICAgIGZvY3VzZWRPcHRpb24sXG4gICAgaGFuZGxlSW5wdXRNb2RlVG9nZ2xlLFxuICAgIGhhbmRsZVJlamVjdCxcbiAgICBoYW5kbGVGb2N1cyxcbiAgfSA9IHVzZVNoZWxsUGVybWlzc2lvbkZlZWRiYWNrKHtcbiAgICB0b29sVXNlQ29uZmlybSxcbiAgICBvbkRvbmUsXG4gICAgb25SZWplY3QsXG4gICAgZXhwbGFpbmVyVmlzaWJsZTogZXhwbGFpbmVyU3RhdGUudmlzaWJsZSxcbiAgfSlcbiAgY29uc3QgW3Nob3dQZXJtaXNzaW9uRGVidWcsIHNldFNob3dQZXJtaXNzaW9uRGVidWddID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFtjbGFzc2lmaWVyRGVzY3JpcHRpb24sIHNldENsYXNzaWZpZXJEZXNjcmlwdGlvbl0gPSB1c2VTdGF0ZShcbiAgICBkZXNjcmlwdGlvbiB8fCAnJyxcbiAgKVxuICAvLyBUcmFjayB3aGV0aGVyIHRoZSBpbml0aWFsIGRlc2NyaXB0aW9uIChmcm9tIHByb3Agb3IgYXN5bmMgZ2VuZXJhdGlvbikgd2FzIGVtcHR5LlxuICAvLyBPbmNlIHdlIHJlY2VpdmUgYSBub24tZW1wdHkgZGVzY3JpcHRpb24sIHRoaXMgc3RheXMgZmFsc2UuXG4gIGNvbnN0IFtcbiAgICBpbml0aWFsQ2xhc3NpZmllckRlc2NyaXB0aW9uRW1wdHksXG4gICAgc2V0SW5pdGlhbENsYXNzaWZpZXJEZXNjcmlwdGlvbkVtcHR5LFxuICBdID0gdXNlU3RhdGUoIWRlc2NyaXB0aW9uPy50cmltKCkpXG5cbiAgLy8gQXN5bmNocm9ub3VzbHkgZ2VuZXJhdGUgYSBnZW5lcmljIGRlc2NyaXB0aW9uIGZvciB0aGUgY2xhc3NpZmllclxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghaXNDbGFzc2lmaWVyUGVybWlzc2lvbnNFbmFibGVkKCkpIHJldHVyblxuXG4gICAgY29uc3QgYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpXG4gICAgZ2VuZXJhdGVHZW5lcmljRGVzY3JpcHRpb24oY29tbWFuZCwgZGVzY3JpcHRpb24sIGFib3J0Q29udHJvbGxlci5zaWduYWwpXG4gICAgICAudGhlbihnZW5lcmljID0+IHtcbiAgICAgICAgaWYgKGdlbmVyaWMgJiYgIWFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIHNldENsYXNzaWZpZXJEZXNjcmlwdGlvbihnZW5lcmljKVxuICAgICAgICAgIHNldEluaXRpYWxDbGFzc2lmaWVyRGVzY3JpcHRpb25FbXB0eShmYWxzZSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7fSkgLy8gS2VlcCBvcmlnaW5hbCBvbiBlcnJvclxuICAgIHJldHVybiAoKSA9PiBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKVxuICB9LCBbY29tbWFuZCwgZGVzY3JpcHRpb25dKVxuXG4gIC8vIEdIIzExMzgwOiBGb3IgY29tcG91bmQgY29tbWFuZHMgKGNkIHNyYyAmJiBnaXQgc3RhdHVzICYmIG5wbSB0ZXN0KSwgdGhlXG4gIC8vIGJhY2tlbmQgYWxyZWFkeSBjb21wdXRlZCBjb3JyZWN0IHBlci1zdWJjb21tYW5kIHN1Z2dlc3Rpb25zIHZpYSB0cmVlLXNpdHRlclxuICAvLyBzcGxpdCArIHBlci1zdWJjb21tYW5kIHBlcm1pc3Npb24gY2hlY2tzLiBkZWNpc2lvblJlYXNvbi50eXBlID09PVxuICAvLyAnc3ViY29tbWFuZFJlc3VsdHMnIG1hcmtzIHRoaXMgcGF0aC4gVGhlIHN5bmMgcHJlZml4IGhldXJpc3RpY3MgYmVsb3dcbiAgLy8gKGdldFNpbXBsZUNvbW1hbmRQcmVmaXgvZ2V0Rmlyc3RXb3JkUHJlZml4KSBvcGVyYXRlIG9uIHRoZSBGVUxMIGNvbXBvdW5kXG4gIC8vIHN0cmluZyBhbmQgcGljayB0aGUgZmlyc3QgdHdvIHdvcmRzIOKAlCBwcm9kdWNpbmcgZGVhZCBydWxlcyBsaWtlXG4gIC8vIGBCYXNoKGNkIHNyYzoqKWAgb3IgYEJhc2goLi9zY3JpcHQuc2ggJiYgbnBtIHRlc3QpYCB0aGF0IG5ldmVyIG1hdGNoIGFnYWluLlxuICAvLyBVc2VycyBhY2N1bXVsYXRlIDE1MCsgb2YgdGhlc2UgaW4gc2V0dGluZ3MubG9jYWwuanNvbi5cbiAgLy9cbiAgLy8gV2hlbiBjb21wb3VuZCB3aXRoIGV4YWN0bHkgb25lIEJhc2ggcnVsZSAoZS5nLiBgY2Qgc3JjICYmIG5wbSB0ZXN0YCB3aGVyZVxuICAvLyBjZCBpcyByZWFkLW9ubHkg4oaSIG9ubHkgbnBtIHRlc3QgbmVlZHMgYXBwcm92YWwpLCBzZWVkIHRoZSBlZGl0YWJsZSBpbnB1dFxuICAvLyBmcm9tIHRoZSBiYWNrZW5kIHJ1bGUuIFdoZW4gY29tcG91bmQgd2l0aCAyKyBydWxlcywgZWRpdGFibGVQcmVmaXggc3RheXNcbiAgLy8gdW5kZWZpbmVkIHNvIGJhc2hUb29sVXNlT3B0aW9ucyBmYWxscyB0aHJvdWdoIHRvIHllcy1hcHBseS1zdWdnZXN0aW9ucyxcbiAgLy8gd2hpY2ggc2F2ZXMgYWxsIHBlci1zdWJjb21tYW5kIHJ1bGVzIGF0b21pY2FsbHkuXG4gIGNvbnN0IGlzQ29tcG91bmQgPVxuICAgIHRvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHQuZGVjaXNpb25SZWFzb24/LnR5cGUgPT09ICdzdWJjb21tYW5kUmVzdWx0cydcblxuICAvLyBFZGl0YWJsZSBwcmVmaXgg4oCUIGluaXRpYWxpemUgc3luY2hyb25vdXNseSB3aXRoIHRoZSBiZXN0IHByZWZpeCB3ZSBjYW5cbiAgLy8gZXh0cmFjdCB3aXRob3V0IHRyZWUtc2l0dGVyLCB0aGVuIHJlZmluZSB2aWEgdHJlZS1zaXR0ZXIgZm9yIGNvbXBvdW5kXG4gIC8vIGNvbW1hbmRzLiBUaGUgc3luYyBwYXRoIG1hdHRlcnMgYmVjYXVzZSBUUkVFX1NJVFRFUl9CQVNIIGlzIGdhdGVkXG4gIC8vIGFudC1vbmx5OiBpbiBleHRlcm5hbCBidWlsZHMgdGhlIGFzeW5jIHJlZmluZW1lbnQgYmVsb3cgYWx3YXlzIHJlc29sdmVzXG4gIC8vIHRvIFtdIGFuZCB0aGlzIGluaXRpYWwgdmFsdWUgaXMgd2hhdCB0aGUgdXNlciBzZWVzLlxuICAvL1xuICAvLyBMYXp5IGluaXRpYWxpemVyOiB0aGlzIHJ1bnMgcmVnZXggKyBzcGxpdCBvbiBldmVyeSByZW5kZXIgaWYgbGVmdCBpblxuICAvLyB0aGUgcmVuZGVyIGJvZHk7IGl0J3Mgb25seSBuZWVkZWQgZm9yIGluaXRpYWwgc3RhdGUuXG4gIGNvbnN0IFtlZGl0YWJsZVByZWZpeCwgc2V0RWRpdGFibGVQcmVmaXhdID0gdXNlU3RhdGU8c3RyaW5nIHwgdW5kZWZpbmVkPihcbiAgICAoKSA9PiB7XG4gICAgICBpZiAoaXNDb21wb3VuZCkge1xuICAgICAgICAvLyBCYWNrZW5kIHN1Z2dlc3Rpb24gaXMgdGhlIHNvdXJjZSBvZiB0cnV0aCBmb3IgY29tcG91bmQgY29tbWFuZHMuXG4gICAgICAgIC8vIFNpbmdsZSBydWxlIOKGkiBzZWVkIHRoZSBlZGl0YWJsZSBpbnB1dCBzbyB0aGUgdXNlciBjYW4gcmVmaW5lIGl0LlxuICAgICAgICAvLyBNdWx0aXBsZS96ZXJvIHJ1bGVzIOKGkiB1bmRlZmluZWQg4oaSIHllcy1hcHBseS1zdWdnZXN0aW9ucyBoYW5kbGVzIGl0LlxuICAgICAgICBjb25zdCBiYWNrZW5kQmFzaFJ1bGVzID0gZXh0cmFjdFJ1bGVzKFxuICAgICAgICAgICdzdWdnZXN0aW9ucycgaW4gdG9vbFVzZUNvbmZpcm0ucGVybWlzc2lvblJlc3VsdFxuICAgICAgICAgICAgPyB0b29sVXNlQ29uZmlybS5wZXJtaXNzaW9uUmVzdWx0LnN1Z2dlc3Rpb25zXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgKS5maWx0ZXIociA9PiByLnRvb2xOYW1lID09PSBCYXNoVG9vbC5uYW1lICYmIHIucnVsZUNvbnRlbnQpXG4gICAgICAgIHJldHVybiBiYWNrZW5kQmFzaFJ1bGVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgID8gYmFja2VuZEJhc2hSdWxlc1swXSEucnVsZUNvbnRlbnRcbiAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgfVxuICAgICAgY29uc3QgdHdvID0gZ2V0U2ltcGxlQ29tbWFuZFByZWZpeChjb21tYW5kKVxuICAgICAgaWYgKHR3bykgcmV0dXJuIGAke3R3b306KmBcbiAgICAgIGNvbnN0IG9uZSA9IGdldEZpcnN0V29yZFByZWZpeChjb21tYW5kKVxuICAgICAgaWYgKG9uZSkgcmV0dXJuIGAke29uZX06KmBcbiAgICAgIHJldHVybiBjb21tYW5kXG4gICAgfSxcbiAgKVxuICBjb25zdCBoYXNVc2VyRWRpdGVkUHJlZml4ID0gdXNlUmVmKGZhbHNlKVxuICBjb25zdCBvbkVkaXRhYmxlUHJlZml4Q2hhbmdlID0gdXNlQ2FsbGJhY2soKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICBoYXNVc2VyRWRpdGVkUHJlZml4LmN1cnJlbnQgPSB0cnVlXG4gICAgc2V0RWRpdGFibGVQcmVmaXgodmFsdWUpXG4gIH0sIFtdKVxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIFNraXAgYXN5bmMgcmVmaW5lbWVudCBmb3IgY29tcG91bmQgY29tbWFuZHMg4oCUIHRoZSBiYWNrZW5kIGFscmVhZHkgcmFuXG4gICAgLy8gdGhlIGZ1bGwgcGVyLXN1YmNvbW1hbmQgYW5hbHlzaXMgYW5kIGl0cyBzdWdnZXN0aW9uIGlzIGNvcnJlY3QuXG4gICAgaWYgKGlzQ29tcG91bmQpIHJldHVyblxuICAgIGxldCBjYW5jZWxsZWQgPSBmYWxzZVxuICAgIGdldENvbXBvdW5kQ29tbWFuZFByZWZpeGVzU3RhdGljKGNvbW1hbmQsIHN1YmNtZCA9PlxuICAgICAgQmFzaFRvb2wuaXNSZWFkT25seSh7IGNvbW1hbmQ6IHN1YmNtZCB9KSxcbiAgICApXG4gICAgICAudGhlbihwcmVmaXhlcyA9PiB7XG4gICAgICAgIGlmIChjYW5jZWxsZWQgfHwgaGFzVXNlckVkaXRlZFByZWZpeC5jdXJyZW50KSByZXR1cm5cbiAgICAgICAgaWYgKHByZWZpeGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBzZXRFZGl0YWJsZVByZWZpeChgJHtwcmVmaXhlc1swXX06KmApXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKCkgPT4ge30pIC8vIEtlZXAgc3luYyBwcmVmaXggb24gdHJlZS1zaXR0ZXIgZmFpbHVyZVxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjYW5jZWxsZWQgPSB0cnVlXG4gICAgfVxuICB9LCBbY29tbWFuZCwgaXNDb21wb3VuZF0pXG5cbiAgLy8gVHJhY2sgd2hldGhlciBjbGFzc2lmaWVyIGNoZWNrIHdhcyBldmVyIGluIHByb2dyZXNzIChwZXJzaXN0cyBhZnRlciBjb21wbGV0aW9uKS5cbiAgLy8gY2xhc3NpZmllckNoZWNrSW5Qcm9ncmVzcyBpcyBzZXQgb25jZSBhdCBxdWV1ZS1wdXNoIHRpbWUgKGludGVyYWN0aXZlSGFuZGxlcilcbiAgLy8gYW5kIG9ubHkgZXZlciB0cmFuc2l0aW9ucyB0cnVl4oaSZmFsc2UsIHNvIGNhcHR1cmluZyB0aGUgbW91bnQtdGltZSB2YWx1ZSBpc1xuICAvLyBzdWZmaWNpZW50IOKAlCBubyBsYXRjaC9yZWYgbmVlZGVkLiBUaGUgZmVhdHVyZSgpIHRlcm5hcnkga2VlcHMgdGhlIHByb3BlcnR5XG4gIC8vIHJlYWQgb3V0IG9mIGV4dGVybmFsIGJ1aWxkcyAoZm9yYmlkZGVuLXN0cmluZyBjaGVjaykuXG4gIGNvbnN0IFtjbGFzc2lmaWVyV2FzQ2hlY2tpbmddID0gdXNlU3RhdGUoXG4gICAgZmVhdHVyZSgnQkFTSF9DTEFTU0lGSUVSJylcbiAgICAgID8gISF0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyQ2hlY2tJblByb2dyZXNzXG4gICAgICA6IGZhbHNlLFxuICApXG5cbiAgLy8gVGhlc2UgZGVyaXZlIHNvbGVseSBmcm9tIHRoZSB0b29sIGlucHV0IChmaXhlZCBmb3IgdGhlIGRpYWxvZyBsaWZldGltZSkuXG4gIC8vIFRoZSBzaGltbWVyIGNsb2NrIHVzZWQgdG8gbGl2ZSBpbiB0aGlzIGNvbXBvbmVudCBhbmQgcmUtcmVuZGVyIGl0IGF0IDIwZnBzXG4gIC8vIHdoaWxlIHRoZSBjbGFzc2lmaWVyIHJhbiAoc2VlIENsYXNzaWZpZXJDaGVja2luZ1N1YnRpdGxlIGFib3ZlIGZvciB0aGVcbiAgLy8gZXh0cmFjdGlvbikuIFJlYWN0IENvbXBpbGVyIGNhbid0IGF1dG8tbWVtb2l6ZSBpbXBvcnRlZCBmdW5jdGlvbnMgKGNhbid0XG4gIC8vIHByb3ZlIHNpZGUtZWZmZWN0IGZyZWVkb20pLCBzbyB0aGlzIHVzZU1lbW8gc3RpbGwgZ3VhcmRzIGFnYWluc3QgYW55XG4gIC8vIHJlLXJlbmRlciBzb3VyY2UgKGUuZy4gSW5uZXIgc3RhdGUgdXBkYXRlcykuIFNhbWUgcGF0dGVybiBhcyBQUiMyMDczMC5cbiAgY29uc3QgeyBkZXN0cnVjdGl2ZVdhcm5pbmcsIHNhbmRib3hpbmdFbmFibGVkLCBpc1NhbmRib3hlZCB9ID0gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3QgZGVzdHJ1Y3RpdmVXYXJuaW5nID0gZ2V0RmVhdHVyZVZhbHVlX0NBQ0hFRF9NQVlfQkVfU1RBTEUoXG4gICAgICAndGVuZ3VfZGVzdHJ1Y3RpdmVfY29tbWFuZF93YXJuaW5nJyxcbiAgICAgIGZhbHNlLFxuICAgIClcbiAgICAgID8gZ2V0RGVzdHJ1Y3RpdmVDb21tYW5kV2FybmluZyhjb21tYW5kKVxuICAgICAgOiBudWxsXG5cbiAgICBjb25zdCBzYW5kYm94aW5nRW5hYmxlZCA9IFNhbmRib3hNYW5hZ2VyLmlzU2FuZGJveGluZ0VuYWJsZWQoKVxuICAgIGNvbnN0IGlzU2FuZGJveGVkID1cbiAgICAgIHNhbmRib3hpbmdFbmFibGVkICYmIHNob3VsZFVzZVNhbmRib3godG9vbFVzZUNvbmZpcm0uaW5wdXQpXG5cbiAgICByZXR1cm4geyBkZXN0cnVjdGl2ZVdhcm5pbmcsIHNhbmRib3hpbmdFbmFibGVkLCBpc1NhbmRib3hlZCB9XG4gIH0sIFtjb21tYW5kLCB0b29sVXNlQ29uZmlybS5pbnB1dF0pXG5cbiAgY29uc3QgdW5hcnlFdmVudCA9IHVzZU1lbW88VW5hcnlFdmVudD4oXG4gICAgKCkgPT4gKHsgY29tcGxldGlvbl90eXBlOiAndG9vbF91c2Vfc2luZ2xlJywgbGFuZ3VhZ2VfbmFtZTogJ25vbmUnIH0pLFxuICAgIFtdLFxuICApXG5cbiAgdXNlUGVybWlzc2lvblJlcXVlc3RMb2dnaW5nKHRvb2xVc2VDb25maXJtLCB1bmFyeUV2ZW50KVxuXG4gIGNvbnN0IGV4aXN0aW5nQWxsb3dEZXNjcmlwdGlvbnMgPSB1c2VNZW1vKFxuICAgICgpID0+IGdldEJhc2hQcm9tcHRBbGxvd0Rlc2NyaXB0aW9ucyh0b29sUGVybWlzc2lvbkNvbnRleHQpLFxuICAgIFt0b29sUGVybWlzc2lvbkNvbnRleHRdLFxuICApXG5cbiAgY29uc3Qgb3B0aW9ucyA9IHVzZU1lbW8oXG4gICAgKCkgPT5cbiAgICAgIGJhc2hUb29sVXNlT3B0aW9ucyh7XG4gICAgICAgIHN1Z2dlc3Rpb25zOlxuICAgICAgICAgIHRvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHQuYmVoYXZpb3IgPT09ICdhc2snXG4gICAgICAgICAgICA/IHRvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHQuc3VnZ2VzdGlvbnNcbiAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICBkZWNpc2lvblJlYXNvbjogdG9vbFVzZUNvbmZpcm0ucGVybWlzc2lvblJlc3VsdC5kZWNpc2lvblJlYXNvbixcbiAgICAgICAgb25SZWplY3RGZWVkYmFja0NoYW5nZTogc2V0UmVqZWN0RmVlZGJhY2ssXG4gICAgICAgIG9uQWNjZXB0RmVlZGJhY2tDaGFuZ2U6IHNldEFjY2VwdEZlZWRiYWNrLFxuICAgICAgICBvbkNsYXNzaWZpZXJEZXNjcmlwdGlvbkNoYW5nZTogc2V0Q2xhc3NpZmllckRlc2NyaXB0aW9uLFxuICAgICAgICBjbGFzc2lmaWVyRGVzY3JpcHRpb24sXG4gICAgICAgIGluaXRpYWxDbGFzc2lmaWVyRGVzY3JpcHRpb25FbXB0eSxcbiAgICAgICAgZXhpc3RpbmdBbGxvd0Rlc2NyaXB0aW9ucyxcbiAgICAgICAgeWVzSW5wdXRNb2RlLFxuICAgICAgICBub0lucHV0TW9kZSxcbiAgICAgICAgZWRpdGFibGVQcmVmaXgsXG4gICAgICAgIG9uRWRpdGFibGVQcmVmaXhDaGFuZ2UsXG4gICAgICB9KSxcbiAgICBbXG4gICAgICB0b29sVXNlQ29uZmlybSxcbiAgICAgIGNsYXNzaWZpZXJEZXNjcmlwdGlvbixcbiAgICAgIGluaXRpYWxDbGFzc2lmaWVyRGVzY3JpcHRpb25FbXB0eSxcbiAgICAgIGV4aXN0aW5nQWxsb3dEZXNjcmlwdGlvbnMsXG4gICAgICB5ZXNJbnB1dE1vZGUsXG4gICAgICBub0lucHV0TW9kZSxcbiAgICAgIGVkaXRhYmxlUHJlZml4LFxuICAgICAgb25FZGl0YWJsZVByZWZpeENoYW5nZSxcbiAgICBdLFxuICApXG5cbiAgLy8gVG9nZ2xlIHBlcm1pc3Npb24gZGVidWcgaW5mbyB3aXRoIGtleWJpbmRpbmdcbiAgY29uc3QgaGFuZGxlVG9nZ2xlRGVidWcgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0U2hvd1Blcm1pc3Npb25EZWJ1ZyhwcmV2ID0+ICFwcmV2KVxuICB9LCBbXSlcbiAgdXNlS2V5YmluZGluZygncGVybWlzc2lvbjp0b2dnbGVEZWJ1ZycsIGhhbmRsZVRvZ2dsZURlYnVnLCB7XG4gICAgY29udGV4dDogJ0NvbmZpcm1hdGlvbicsXG4gIH0pXG5cbiAgLy8gQWxsb3cgRXNjIHRvIGRpc21pc3MgdGhlIGNoZWNrbWFyayBhZnRlciBhdXRvLWFwcHJvdmFsXG4gIGNvbnN0IGhhbmRsZURpc21pc3NDaGVja21hcmsgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgdG9vbFVzZUNvbmZpcm0ub25EaXNtaXNzQ2hlY2ttYXJrPy4oKVxuICB9LCBbdG9vbFVzZUNvbmZpcm1dKVxuICB1c2VLZXliaW5kaW5nKCdjb25maXJtOm5vJywgaGFuZGxlRGlzbWlzc0NoZWNrbWFyaywge1xuICAgIGNvbnRleHQ6ICdDb25maXJtYXRpb24nLFxuICAgIGlzQWN0aXZlOiBmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKVxuICAgICAgPyAhIXRvb2xVc2VDb25maXJtLmNsYXNzaWZpZXJBdXRvQXBwcm92ZWRcbiAgICAgIDogZmFsc2UsXG4gIH0pXG5cbiAgZnVuY3Rpb24gb25TZWxlY3QodmFsdWU6IHN0cmluZykge1xuICAgIC8vIE1hcCBvcHRpb25zIHRvIG51bWVyaWMgdmFsdWVzIGZvciBhbmFseXRpY3MgKHN0cmluZ3Mgbm90IGFsbG93ZWQgaW4gbG9nRXZlbnQpXG4gICAgbGV0IG9wdGlvbkluZGV4OiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge1xuICAgICAgeWVzOiAxLFxuICAgICAgJ3llcy1hcHBseS1zdWdnZXN0aW9ucyc6IDIsXG4gICAgICAneWVzLXByZWZpeC1lZGl0ZWQnOiAyLFxuICAgICAgbm86IDMsXG4gICAgfVxuICAgIGlmIChmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKSkge1xuICAgICAgb3B0aW9uSW5kZXggPSB7XG4gICAgICAgIHllczogMSxcbiAgICAgICAgJ3llcy1hcHBseS1zdWdnZXN0aW9ucyc6IDIsXG4gICAgICAgICd5ZXMtcHJlZml4LWVkaXRlZCc6IDIsXG4gICAgICAgICd5ZXMtY2xhc3NpZmllci1yZXZpZXdlZCc6IDMsXG4gICAgICAgIG5vOiA0LFxuICAgICAgfVxuICAgIH1cbiAgICBsb2dFdmVudCgndGVuZ3VfcGVybWlzc2lvbl9yZXF1ZXN0X29wdGlvbl9zZWxlY3RlZCcsIHtcbiAgICAgIG9wdGlvbl9pbmRleDogb3B0aW9uSW5kZXhbdmFsdWVdLFxuICAgICAgZXhwbGFpbmVyX3Zpc2libGU6IGV4cGxhaW5lclN0YXRlLnZpc2libGUsXG4gICAgfSlcblxuICAgIGNvbnN0IHRvb2xOYW1lRm9yQW5hbHl0aWNzID0gc2FuaXRpemVUb29sTmFtZUZvckFuYWx5dGljcyhcbiAgICAgIHRvb2xVc2VDb25maXJtLnRvb2wubmFtZSxcbiAgICApIGFzIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFNcblxuICAgIGlmICh2YWx1ZSA9PT0gJ3llcy1wcmVmaXgtZWRpdGVkJykge1xuICAgICAgY29uc3QgdHJpbW1lZFByZWZpeCA9IChlZGl0YWJsZVByZWZpeCA/PyAnJykudHJpbSgpXG4gICAgICBsb2dVbmFyeVBlcm1pc3Npb25FdmVudCgndG9vbF91c2Vfc2luZ2xlJywgdG9vbFVzZUNvbmZpcm0sICdhY2NlcHQnKVxuICAgICAgaWYgKCF0cmltbWVkUHJlZml4KSB7XG4gICAgICAgIHRvb2xVc2VDb25maXJtLm9uQWxsb3codG9vbFVzZUNvbmZpcm0uaW5wdXQsIFtdKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcHJlZml4VXBkYXRlczogUGVybWlzc2lvblVwZGF0ZVtdID0gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdhZGRSdWxlcycsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdG9vbE5hbWU6IEJhc2hUb29sLm5hbWUsXG4gICAgICAgICAgICAgICAgcnVsZUNvbnRlbnQ6IHRyaW1tZWRQcmVmaXgsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgYmVoYXZpb3I6ICdhbGxvdycsXG4gICAgICAgICAgICBkZXN0aW5hdGlvbjogJ2xvY2FsU2V0dGluZ3MnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF1cbiAgICAgICAgdG9vbFVzZUNvbmZpcm0ub25BbGxvdyh0b29sVXNlQ29uZmlybS5pbnB1dCwgcHJlZml4VXBkYXRlcylcbiAgICAgIH1cbiAgICAgIG9uRG9uZSgpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAoZmVhdHVyZSgnQkFTSF9DTEFTU0lGSUVSJykgJiYgdmFsdWUgPT09ICd5ZXMtY2xhc3NpZmllci1yZXZpZXdlZCcpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWREZXNjcmlwdGlvbiA9IGNsYXNzaWZpZXJEZXNjcmlwdGlvbi50cmltKClcbiAgICAgIGxvZ1VuYXJ5UGVybWlzc2lvbkV2ZW50KCd0b29sX3VzZV9zaW5nbGUnLCB0b29sVXNlQ29uZmlybSwgJ2FjY2VwdCcpXG4gICAgICBpZiAoIXRyaW1tZWREZXNjcmlwdGlvbikge1xuICAgICAgICB0b29sVXNlQ29uZmlybS5vbkFsbG93KHRvb2xVc2VDb25maXJtLmlucHV0LCBbXSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHBlcm1pc3Npb25VcGRhdGVzOiBQZXJtaXNzaW9uVXBkYXRlW10gPSBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2FkZFJ1bGVzJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0b29sTmFtZTogQmFzaFRvb2wubmFtZSxcbiAgICAgICAgICAgICAgICBydWxlQ29udGVudDogY3JlYXRlUHJvbXB0UnVsZUNvbnRlbnQodHJpbW1lZERlc2NyaXB0aW9uKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBiZWhhdmlvcjogJ2FsbG93JyxcbiAgICAgICAgICAgIGRlc3RpbmF0aW9uOiAnc2Vzc2lvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgXVxuICAgICAgICB0b29sVXNlQ29uZmlybS5vbkFsbG93KHRvb2xVc2VDb25maXJtLmlucHV0LCBwZXJtaXNzaW9uVXBkYXRlcylcbiAgICAgIH1cbiAgICAgIG9uRG9uZSgpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBzd2l0Y2ggKHZhbHVlKSB7XG4gICAgICBjYXNlICd5ZXMnOiB7XG4gICAgICAgIGNvbnN0IHRyaW1tZWRGZWVkYmFjayA9IGFjY2VwdEZlZWRiYWNrLnRyaW0oKVxuICAgICAgICBsb2dVbmFyeVBlcm1pc3Npb25FdmVudCgndG9vbF91c2Vfc2luZ2xlJywgdG9vbFVzZUNvbmZpcm0sICdhY2NlcHQnKVxuICAgICAgICAvLyBMb2cgYWNjZXB0IHN1Ym1pc3Npb24gd2l0aCBmZWVkYmFjayBjb250ZXh0XG4gICAgICAgIGxvZ0V2ZW50KCd0ZW5ndV9hY2NlcHRfc3VibWl0dGVkJywge1xuICAgICAgICAgIHRvb2xOYW1lOiB0b29sTmFtZUZvckFuYWx5dGljcyxcbiAgICAgICAgICBpc01jcDogdG9vbFVzZUNvbmZpcm0udG9vbC5pc01jcCA/PyBmYWxzZSxcbiAgICAgICAgICBoYXNfaW5zdHJ1Y3Rpb25zOiAhIXRyaW1tZWRGZWVkYmFjayxcbiAgICAgICAgICBpbnN0cnVjdGlvbnNfbGVuZ3RoOiB0cmltbWVkRmVlZGJhY2subGVuZ3RoLFxuICAgICAgICAgIGVudGVyZWRfZmVlZGJhY2tfbW9kZTogeWVzRmVlZGJhY2tNb2RlRW50ZXJlZCxcbiAgICAgICAgfSlcbiAgICAgICAgdG9vbFVzZUNvbmZpcm0ub25BbGxvdyhcbiAgICAgICAgICB0b29sVXNlQ29uZmlybS5pbnB1dCxcbiAgICAgICAgICBbXSxcbiAgICAgICAgICB0cmltbWVkRmVlZGJhY2sgfHwgdW5kZWZpbmVkLFxuICAgICAgICApXG4gICAgICAgIG9uRG9uZSgpXG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBjYXNlICd5ZXMtYXBwbHktc3VnZ2VzdGlvbnMnOiB7XG4gICAgICAgIGxvZ1VuYXJ5UGVybWlzc2lvbkV2ZW50KCd0b29sX3VzZV9zaW5nbGUnLCB0b29sVXNlQ29uZmlybSwgJ2FjY2VwdCcpXG4gICAgICAgIC8vIEV4dHJhY3Qgc3VnZ2VzdGlvbnMgaWYgcHJlc2VudCAod29ya3MgZm9yIGJvdGggJ2FzaycgYW5kICdwYXNzdGhyb3VnaCcgYmVoYXZpb3JzKVxuICAgICAgICBjb25zdCBwZXJtaXNzaW9uVXBkYXRlcyA9XG4gICAgICAgICAgJ3N1Z2dlc3Rpb25zJyBpbiB0b29sVXNlQ29uZmlybS5wZXJtaXNzaW9uUmVzdWx0XG4gICAgICAgICAgICA/IHRvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHQuc3VnZ2VzdGlvbnMgfHwgW11cbiAgICAgICAgICAgIDogW11cbiAgICAgICAgdG9vbFVzZUNvbmZpcm0ub25BbGxvdyh0b29sVXNlQ29uZmlybS5pbnB1dCwgcGVybWlzc2lvblVwZGF0ZXMpXG4gICAgICAgIG9uRG9uZSgpXG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBjYXNlICdubyc6IHtcbiAgICAgICAgY29uc3QgdHJpbW1lZEZlZWRiYWNrID0gcmVqZWN0RmVlZGJhY2sudHJpbSgpXG5cbiAgICAgICAgLy8gTG9nIHJlamVjdCBzdWJtaXNzaW9uIHdpdGggZmVlZGJhY2sgY29udGV4dFxuICAgICAgICBsb2dFdmVudCgndGVuZ3VfcmVqZWN0X3N1Ym1pdHRlZCcsIHtcbiAgICAgICAgICB0b29sTmFtZTogdG9vbE5hbWVGb3JBbmFseXRpY3MsXG4gICAgICAgICAgaXNNY3A6IHRvb2xVc2VDb25maXJtLnRvb2wuaXNNY3AgPz8gZmFsc2UsXG4gICAgICAgICAgaGFzX2luc3RydWN0aW9uczogISF0cmltbWVkRmVlZGJhY2ssXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25zX2xlbmd0aDogdHJpbW1lZEZlZWRiYWNrLmxlbmd0aCxcbiAgICAgICAgICBlbnRlcmVkX2ZlZWRiYWNrX21vZGU6IG5vRmVlZGJhY2tNb2RlRW50ZXJlZCxcbiAgICAgICAgfSlcblxuICAgICAgICAvLyBQcm9jZXNzIHJlamVjdGlvbiAod2l0aCBvciB3aXRob3V0IGZlZWRiYWNrKVxuICAgICAgICBoYW5kbGVSZWplY3QodHJpbW1lZEZlZWRiYWNrIHx8IHVuZGVmaW5lZClcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBjbGFzc2lmaWVyU3VidGl0bGUgPSBmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKSA/IChcbiAgICB0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyQXV0b0FwcHJvdmVkID8gKFxuICAgICAgPFRleHQ+XG4gICAgICAgIDxUZXh0IGNvbG9yPVwic3VjY2Vzc1wiPntmaWd1cmVzLnRpY2t9IEF1dG8tYXBwcm92ZWQ8L1RleHQ+XG4gICAgICAgIHt0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyTWF0Y2hlZFJ1bGUgJiYgKFxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgeycgXFx1MDBiNyBtYXRjaGVkIFwiJ31cbiAgICAgICAgICAgIHt0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyTWF0Y2hlZFJ1bGV9XG4gICAgICAgICAgICB7J1wiJ31cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICl9XG4gICAgICA8L1RleHQ+XG4gICAgKSA6IHRvb2xVc2VDb25maXJtLmNsYXNzaWZpZXJDaGVja0luUHJvZ3Jlc3MgPyAoXG4gICAgICA8Q2xhc3NpZmllckNoZWNraW5nU3VidGl0bGUgLz5cbiAgICApIDogY2xhc3NpZmllcldhc0NoZWNraW5nID8gKFxuICAgICAgPFRleHQgZGltQ29sb3I+UmVxdWlyZXMgbWFudWFsIGFwcHJvdmFsPC9UZXh0PlxuICAgICkgOiB1bmRlZmluZWRcbiAgKSA6IHVuZGVmaW5lZFxuXG4gIHJldHVybiAoXG4gICAgPFBlcm1pc3Npb25EaWFsb2dcbiAgICAgIHdvcmtlckJhZGdlPXt3b3JrZXJCYWRnZX1cbiAgICAgIHRpdGxlPXtcbiAgICAgICAgc2FuZGJveGluZ0VuYWJsZWQgJiYgIWlzU2FuZGJveGVkXG4gICAgICAgICAgPyAnQmFzaCBjb21tYW5kICh1bnNhbmRib3hlZCknXG4gICAgICAgICAgOiAnQmFzaCBjb21tYW5kJ1xuICAgICAgfVxuICAgICAgc3VidGl0bGU9e2NsYXNzaWZpZXJTdWJ0aXRsZX1cbiAgICA+XG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBwYWRkaW5nWD17Mn0gcGFkZGluZ1k9ezF9PlxuICAgICAgICA8VGV4dCBkaW1Db2xvcj17ZXhwbGFpbmVyU3RhdGUudmlzaWJsZX0+XG4gICAgICAgICAge0Jhc2hUb29sLnJlbmRlclRvb2xVc2VNZXNzYWdlKFxuICAgICAgICAgICAgeyBjb21tYW5kLCBkZXNjcmlwdGlvbiB9LFxuICAgICAgICAgICAgeyB0aGVtZSwgdmVyYm9zZTogdHJ1ZSB9LCAvLyBhbHdheXMgc2hvdyB0aGUgZnVsbCBjb21tYW5kXG4gICAgICAgICAgKX1cbiAgICAgICAgPC9UZXh0PlxuICAgICAgICB7IWV4cGxhaW5lclN0YXRlLnZpc2libGUgJiYgKFxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPnt0b29sVXNlQ29uZmlybS5kZXNjcmlwdGlvbn08L1RleHQ+XG4gICAgICAgICl9XG4gICAgICAgIDxQZXJtaXNzaW9uRXhwbGFpbmVyQ29udGVudFxuICAgICAgICAgIHZpc2libGU9e2V4cGxhaW5lclN0YXRlLnZpc2libGV9XG4gICAgICAgICAgcHJvbWlzZT17ZXhwbGFpbmVyU3RhdGUucHJvbWlzZX1cbiAgICAgICAgLz5cbiAgICAgIDwvQm94PlxuICAgICAge3Nob3dQZXJtaXNzaW9uRGVidWcgPyAoXG4gICAgICAgIDw+XG4gICAgICAgICAgPFBlcm1pc3Npb25EZWNpc2lvbkRlYnVnSW5mb1xuICAgICAgICAgICAgcGVybWlzc2lvblJlc3VsdD17dG9vbFVzZUNvbmZpcm0ucGVybWlzc2lvblJlc3VsdH1cbiAgICAgICAgICAgIHRvb2xOYW1lPVwiQmFzaFwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICB7dG9vbFVzZUNvbnRleHQub3B0aW9ucy5kZWJ1ZyAmJiAoXG4gICAgICAgICAgICA8Qm94IGp1c3RpZnlDb250ZW50PVwiZmxleC1lbmRcIiBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5DdHJsLUQgdG8gaGlkZSBkZWJ1ZyBpbmZvPC9UZXh0PlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKX1cbiAgICAgICAgPC8+XG4gICAgICApIDogKFxuICAgICAgICA8PlxuICAgICAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICAgICAgPFBlcm1pc3Npb25SdWxlRXhwbGFuYXRpb25cbiAgICAgICAgICAgICAgcGVybWlzc2lvblJlc3VsdD17dG9vbFVzZUNvbmZpcm0ucGVybWlzc2lvblJlc3VsdH1cbiAgICAgICAgICAgICAgdG9vbFR5cGU9XCJjb21tYW5kXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICB7ZGVzdHJ1Y3RpdmVXYXJuaW5nICYmIChcbiAgICAgICAgICAgICAgPEJveCBtYXJnaW5Cb3R0b209ezF9PlxuICAgICAgICAgICAgICAgIDxUZXh0XG4gICAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5pbmdcIlxuICAgICAgICAgICAgICAgICAgZGltQ29sb3I9e1xuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKVxuICAgICAgICAgICAgICAgICAgICAgID8gdG9vbFVzZUNvbmZpcm0uY2xhc3NpZmllckF1dG9BcHByb3ZlZFxuICAgICAgICAgICAgICAgICAgICAgIDogZmFsc2VcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7ZGVzdHJ1Y3RpdmVXYXJuaW5nfVxuICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgICApfVxuICAgICAgICAgICAgPFRleHRcbiAgICAgICAgICAgICAgZGltQ29sb3I9e1xuICAgICAgICAgICAgICAgIGZlYXR1cmUoJ0JBU0hfQ0xBU1NJRklFUicpXG4gICAgICAgICAgICAgICAgICA/IHRvb2xVc2VDb25maXJtLmNsYXNzaWZpZXJBdXRvQXBwcm92ZWRcbiAgICAgICAgICAgICAgICAgIDogZmFsc2VcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBEbyB5b3Ugd2FudCB0byBwcm9jZWVkP1xuICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgPFNlbGVjdFxuICAgICAgICAgICAgICBvcHRpb25zPXtcbiAgICAgICAgICAgICAgICBmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKVxuICAgICAgICAgICAgICAgICAgPyB0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyQXV0b0FwcHJvdmVkXG4gICAgICAgICAgICAgICAgICAgID8gb3B0aW9ucy5tYXAobyA9PiAoeyAuLi5vLCBkaXNhYmxlZDogdHJ1ZSB9KSlcbiAgICAgICAgICAgICAgICAgICAgOiBvcHRpb25zXG4gICAgICAgICAgICAgICAgICA6IG9wdGlvbnNcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpc0Rpc2FibGVkPXtcbiAgICAgICAgICAgICAgICBmZWF0dXJlKCdCQVNIX0NMQVNTSUZJRVInKVxuICAgICAgICAgICAgICAgICAgPyB0b29sVXNlQ29uZmlybS5jbGFzc2lmaWVyQXV0b0FwcHJvdmVkXG4gICAgICAgICAgICAgICAgICA6IGZhbHNlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaW5saW5lRGVzY3JpcHRpb25zXG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXtvblNlbGVjdH1cbiAgICAgICAgICAgICAgb25DYW5jZWw9eygpID0+IGhhbmRsZVJlamVjdCgpfVxuICAgICAgICAgICAgICBvbkZvY3VzPXtoYW5kbGVGb2N1c31cbiAgICAgICAgICAgICAgb25JbnB1dE1vZGVUb2dnbGU9e2hhbmRsZUlucHV0TW9kZVRvZ2dsZX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgPEJveCBqdXN0aWZ5Q29udGVudD1cInNwYWNlLWJldHdlZW5cIiBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgIEVzYyB0byBjYW5jZWxcbiAgICAgICAgICAgICAgeygoZm9jdXNlZE9wdGlvbiA9PT0gJ3llcycgJiYgIXllc0lucHV0TW9kZSkgfHxcbiAgICAgICAgICAgICAgICAoZm9jdXNlZE9wdGlvbiA9PT0gJ25vJyAmJiAhbm9JbnB1dE1vZGUpKSAmJlxuICAgICAgICAgICAgICAgICcgwrcgVGFiIHRvIGFtZW5kJ31cbiAgICAgICAgICAgICAge2V4cGxhaW5lclN0YXRlLmVuYWJsZWQgJiZcbiAgICAgICAgICAgICAgICBgIMK3IGN0cmwrZSB0byAke2V4cGxhaW5lclN0YXRlLnZpc2libGUgPyAnaGlkZScgOiAnZXhwbGFpbid9YH1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgIHt0b29sVXNlQ29udGV4dC5vcHRpb25zLmRlYnVnICYmIChcbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+Q3RybCtkIHRvIHNob3cgZGVidWcgaW5mbzwvVGV4dD5cbiAgICAgICAgICAgICl9XG4gICAgICAgICAgPC9Cb3g+XG4gICAgICAgIDwvPlxuICAgICAgKX1cbiAgICA8L1Blcm1pc3Npb25EaWFsb2c+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLE9BQU8sUUFBUSxZQUFZO0FBQ3BDLE9BQU9DLE9BQU8sTUFBTSxTQUFTO0FBQzdCLE9BQU9DLEtBQUssSUFBSUMsV0FBVyxFQUFFQyxTQUFTLEVBQUVDLE9BQU8sRUFBRUMsTUFBTSxFQUFFQyxRQUFRLFFBQVEsT0FBTztBQUNoRixTQUFTQyxHQUFHLEVBQUVDLElBQUksRUFBRUMsUUFBUSxRQUFRLGlCQUFpQjtBQUNyRCxTQUFTQyxhQUFhLFFBQVEsdUNBQXVDO0FBQ3JFLFNBQVNDLG1DQUFtQyxRQUFRLDJDQUEyQztBQUMvRixTQUNFLEtBQUtDLDBEQUEwRCxFQUMvREMsUUFBUSxRQUNILHNDQUFzQztBQUM3QyxTQUFTQyw0QkFBNEIsUUFBUSx5Q0FBeUM7QUFDdEYsU0FBU0MsV0FBVyxRQUFRLDRCQUE0QjtBQUN4RCxTQUFTQyxRQUFRLFFBQVEscUNBQXFDO0FBQzlELFNBQ0VDLGtCQUFrQixFQUNsQkMsc0JBQXNCLFFBQ2pCLDRDQUE0QztBQUNuRCxTQUFTQyw0QkFBNEIsUUFBUSxzREFBc0Q7QUFDbkcsU0FBU0MsbUJBQW1CLFFBQVEsMENBQTBDO0FBQzlFLFNBQVNDLGdCQUFnQixRQUFRLDZDQUE2QztBQUM5RSxTQUFTQyxnQ0FBZ0MsUUFBUSwrQkFBK0I7QUFDaEYsU0FDRUMsdUJBQXVCLEVBQ3ZCQywwQkFBMEIsRUFDMUJDLDhCQUE4QixFQUM5QkMsOEJBQThCLFFBQ3pCLDhDQUE4QztBQUNyRCxTQUFTQyxZQUFZLFFBQVEsZ0RBQWdEO0FBQzdFLGNBQWNDLGdCQUFnQixRQUFRLHNEQUFzRDtBQUM1RixTQUFTQyxjQUFjLFFBQVEsMkNBQTJDO0FBQzFFLFNBQVNDLE1BQU0sUUFBUSw4QkFBOEI7QUFDckQsU0FBU0MsV0FBVyxRQUFRLDhCQUE4QjtBQUMxRCxTQUFTQyxtQkFBbUIsUUFBUSxzQ0FBc0M7QUFDMUUsU0FBUyxLQUFLQyxVQUFVLEVBQUVDLDJCQUEyQixRQUFRLGFBQWE7QUFDMUUsU0FBU0MsMkJBQTJCLFFBQVEsbUNBQW1DO0FBQy9FLFNBQVNDLGdCQUFnQixRQUFRLHdCQUF3QjtBQUN6RCxTQUNFQywwQkFBMEIsRUFDMUJDLHdCQUF3QixRQUNuQiw2QkFBNkI7QUFDcEMsY0FBY0Msc0JBQXNCLFFBQVEseUJBQXlCO0FBQ3JFLFNBQVNDLHlCQUF5QixRQUFRLGlDQUFpQztBQUMzRSxTQUFTQyx3QkFBd0IsUUFBUSx5REFBeUQ7QUFDbEcsU0FBU0MsMEJBQTBCLFFBQVEsa0NBQWtDO0FBQzdFLFNBQVNDLHVCQUF1QixRQUFRLGFBQWE7QUFDckQsU0FBU0Msa0JBQWtCLFFBQVEseUJBQXlCO0FBRTVELE1BQU1DLGFBQWEsR0FBRyxrQ0FBa0M7O0FBRXhEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQUFDLDJCQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBQ0UsT0FBQUMsR0FBQSxFQUFBQyxZQUFBLElBQTRCbEIsbUJBQW1CLENBQzdDLFlBQVksRUFDWmEsYUFBYSxFQUNiLEtBQ0YsQ0FBQztFQUFBLElBQUFNLEVBQUE7RUFBQSxJQUFBSixDQUFBLFFBQUFLLE1BQUEsQ0FBQUMsR0FBQTtJQUlNRixFQUFBLE9BQUlOLGFBQWEsQ0FBQztJQUFBRSxDQUFBLE1BQUFJLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFKLENBQUE7RUFBQTtFQUFBLElBQUFPLEVBQUE7RUFBQSxJQUFBUCxDQUFBLFFBQUFHLFlBQUE7SUFEckJJLEVBQUEsSUFBQyxJQUFJLENBQ0YsQ0FBQUgsRUFBa0IsQ0FBQUksR0FBSSxDQUFDLENBQUFDLElBQUEsRUFBQUMsQ0FBQSxLQUN0QixDQUFDLFdBQVcsQ0FDTEEsR0FBQyxDQUFEQSxFQUFBLENBQUMsQ0FDQUQsSUFBSSxDQUFKQSxLQUFHLENBQUMsQ0FDSEMsS0FBQyxDQUFEQSxFQUFBLENBQUMsQ0FDTVAsWUFBWSxDQUFaQSxhQUFXLENBQUMsQ0FDYixZQUFVLENBQVYsVUFBVSxDQUNWLFlBQVEsQ0FBUixRQUFRLEdBRXhCLEVBQ0gsRUFYQyxJQUFJLENBV0U7SUFBQUgsQ0FBQSxNQUFBRyxZQUFBO0lBQUFILENBQUEsTUFBQU8sRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVAsQ0FBQTtFQUFBO0VBQUEsSUFBQVcsRUFBQTtFQUFBLElBQUFYLENBQUEsUUFBQUUsR0FBQSxJQUFBRixDQUFBLFFBQUFPLEVBQUE7SUFaVEksRUFBQSxJQUFDLEdBQUcsQ0FBTVQsR0FBRyxDQUFIQSxJQUFFLENBQUMsQ0FDWCxDQUFBSyxFQVdNLENBQ1IsRUFiQyxHQUFHLENBYUU7SUFBQVAsQ0FBQSxNQUFBRSxHQUFBO0lBQUFGLENBQUEsTUFBQU8sRUFBQTtJQUFBUCxDQUFBLE1BQUFXLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFYLENBQUE7RUFBQTtFQUFBLE9BYk5XLEVBYU07QUFBQTtBQUlWLE9BQU8sU0FBQUMsc0JBQUFDLEtBQUE7RUFBQSxNQUFBYixDQUFBLEdBQUFDLEVBQUE7RUFHTDtJQUFBYSxjQUFBO0lBQUFDLGNBQUE7SUFBQUMsTUFBQTtJQUFBQyxRQUFBO0lBQUFDLE9BQUE7SUFBQUM7RUFBQSxJQU9JTixLQUFLO0VBQUEsSUFBQU8sT0FBQTtFQUFBLElBQUFDLFdBQUE7RUFBQSxJQUFBakIsRUFBQTtFQUFBLElBQUFKLENBQUEsUUFBQWMsY0FBQSxDQUFBUSxLQUFBO0lBRVQ7TUFBQUYsT0FBQTtNQUFBQztJQUFBLElBQWlDcEQsUUFBUSxDQUFBc0QsV0FBWSxDQUFBQyxLQUFNLENBQ3pEVixjQUFjLENBQUFRLEtBQ2hCLENBQUM7SUFJZWxCLEVBQUEsR0FBQS9CLG1CQUFtQixDQUFDK0MsT0FBTyxDQUFDO0lBQUFwQixDQUFBLE1BQUFjLGNBQUEsQ0FBQVEsS0FBQTtJQUFBdEIsQ0FBQSxNQUFBb0IsT0FBQTtJQUFBcEIsQ0FBQSxNQUFBcUIsV0FBQTtJQUFBckIsQ0FBQSxNQUFBSSxFQUFBO0VBQUE7SUFBQWdCLE9BQUEsR0FBQXBCLENBQUE7SUFBQXFCLFdBQUEsR0FBQXJCLENBQUE7SUFBQUksRUFBQSxHQUFBSixDQUFBO0VBQUE7RUFBNUMsTUFBQXlCLE9BQUEsR0FBZ0JyQixFQUE0QjtFQUU1QyxJQUFJcUIsT0FBTztJQUFBLElBQUFsQixFQUFBO0lBQUEsSUFBQVAsQ0FBQSxRQUFBZ0IsTUFBQSxJQUFBaEIsQ0FBQSxRQUFBaUIsUUFBQSxJQUFBakIsQ0FBQSxRQUFBeUIsT0FBQSxJQUFBekIsQ0FBQSxRQUFBYyxjQUFBLElBQUFkLENBQUEsUUFBQWUsY0FBQSxJQUFBZixDQUFBLFFBQUFrQixPQUFBLElBQUFsQixDQUFBLFNBQUFtQixXQUFBO01BRVBaLEVBQUEsSUFBQyx3QkFBd0IsQ0FDUE8sY0FBYyxDQUFkQSxlQUFhLENBQUMsQ0FDZEMsY0FBYyxDQUFkQSxlQUFhLENBQUMsQ0FDdEJDLE1BQU0sQ0FBTkEsT0FBSyxDQUFDLENBQ0pDLFFBQVEsQ0FBUkEsU0FBTyxDQUFDLENBQ1RDLE9BQU8sQ0FBUEEsUUFBTSxDQUFDLENBQ0hDLFdBQVcsQ0FBWEEsWUFBVSxDQUFDLENBQ2ZNLE9BQU8sQ0FBUEEsUUFBTSxDQUFDLEdBQ2hCO01BQUF6QixDQUFBLE1BQUFnQixNQUFBO01BQUFoQixDQUFBLE1BQUFpQixRQUFBO01BQUFqQixDQUFBLE1BQUF5QixPQUFBO01BQUF6QixDQUFBLE1BQUFjLGNBQUE7TUFBQWQsQ0FBQSxNQUFBZSxjQUFBO01BQUFmLENBQUEsTUFBQWtCLE9BQUE7TUFBQWxCLENBQUEsT0FBQW1CLFdBQUE7TUFBQW5CLENBQUEsT0FBQU8sRUFBQTtJQUFBO01BQUFBLEVBQUEsR0FBQVAsQ0FBQTtJQUFBO0lBQUEsT0FSRk8sRUFRRTtFQUFBO0VBRUwsSUFBQUEsRUFBQTtFQUFBLElBQUFQLENBQUEsU0FBQW9CLE9BQUEsSUFBQXBCLENBQUEsU0FBQXFCLFdBQUEsSUFBQXJCLENBQUEsU0FBQWdCLE1BQUEsSUFBQWhCLENBQUEsU0FBQWlCLFFBQUEsSUFBQWpCLENBQUEsU0FBQWMsY0FBQSxJQUFBZCxDQUFBLFNBQUFlLGNBQUEsSUFBQWYsQ0FBQSxTQUFBa0IsT0FBQSxJQUFBbEIsQ0FBQSxTQUFBbUIsV0FBQTtJQUlDWixFQUFBLElBQUMsMEJBQTBCLENBQ1RPLGNBQWMsQ0FBZEEsZUFBYSxDQUFDLENBQ2RDLGNBQWMsQ0FBZEEsZUFBYSxDQUFDLENBQ3RCQyxNQUFNLENBQU5BLE9BQUssQ0FBQyxDQUNKQyxRQUFRLENBQVJBLFNBQU8sQ0FBQyxDQUNUQyxPQUFPLENBQVBBLFFBQU0sQ0FBQyxDQUNIQyxXQUFXLENBQVhBLFlBQVUsQ0FBQyxDQUNmQyxPQUFPLENBQVBBLFFBQU0sQ0FBQyxDQUNIQyxXQUFXLENBQVhBLFlBQVUsQ0FBQyxHQUN4QjtJQUFBckIsQ0FBQSxPQUFBb0IsT0FBQTtJQUFBcEIsQ0FBQSxPQUFBcUIsV0FBQTtJQUFBckIsQ0FBQSxPQUFBZ0IsTUFBQTtJQUFBaEIsQ0FBQSxPQUFBaUIsUUFBQTtJQUFBakIsQ0FBQSxPQUFBYyxjQUFBO0lBQUFkLENBQUEsT0FBQWUsY0FBQTtJQUFBZixDQUFBLE9BQUFrQixPQUFBO0lBQUFsQixDQUFBLE9BQUFtQixXQUFBO0lBQUFuQixDQUFBLE9BQUFPLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFQLENBQUE7RUFBQTtFQUFBLE9BVEZPLEVBU0U7QUFBQTs7QUFJTjtBQUNBLFNBQVNtQiwwQkFBMEJBLENBQUM7RUFDbENaLGNBQWM7RUFDZEMsY0FBYztFQUNkQyxNQUFNO0VBQ05DLFFBQVE7RUFDUkMsT0FBTyxFQUFFUyxRQUFRO0VBQ2pCUixXQUFXO0VBQ1hDLE9BQU87RUFDUEM7QUFJRixDQUhDLEVBQUU3QixzQkFBc0IsR0FBRztFQUMxQjRCLE9BQU8sRUFBRSxNQUFNO0VBQ2ZDLFdBQVcsQ0FBQyxFQUFFLE1BQU07QUFDdEIsQ0FBQyxDQUFDLEVBQUVuRSxLQUFLLENBQUMwRSxTQUFTLENBQUM7RUFDbEIsTUFBTSxDQUFDQyxLQUFLLENBQUMsR0FBR25FLFFBQVEsQ0FBQyxDQUFDO0VBQzFCLE1BQU1vRSxxQkFBcUIsR0FBRzlELFdBQVcsQ0FBQytELENBQUMsSUFBSUEsQ0FBQyxDQUFDRCxxQkFBcUIsQ0FBQztFQUN2RSxNQUFNRSxjQUFjLEdBQUd6Qyx3QkFBd0IsQ0FBQztJQUM5QzBDLFFBQVEsRUFBRW5CLGNBQWMsQ0FBQ29CLElBQUksQ0FBQ0MsSUFBSTtJQUNsQ0MsU0FBUyxFQUFFdEIsY0FBYyxDQUFDUSxLQUFLO0lBQy9CZSxlQUFlLEVBQUV2QixjQUFjLENBQUNPLFdBQVc7SUFDM0NpQixRQUFRLEVBQUV2QixjQUFjLENBQUN1QjtFQUMzQixDQUFDLENBQUM7RUFDRixNQUFNO0lBQ0pDLFlBQVk7SUFDWkMsV0FBVztJQUNYQyxzQkFBc0I7SUFDdEJDLHFCQUFxQjtJQUNyQkMsY0FBYztJQUNkQyxjQUFjO0lBQ2RDLGlCQUFpQjtJQUNqQkMsaUJBQWlCO0lBQ2pCQyxhQUFhO0lBQ2JDLHFCQUFxQjtJQUNyQkMsWUFBWTtJQUNaQztFQUNGLENBQUMsR0FBR3ZELDBCQUEwQixDQUFDO0lBQzdCbUIsY0FBYztJQUNkRSxNQUFNO0lBQ05DLFFBQVE7SUFDUmtDLGdCQUFnQixFQUFFbkIsY0FBYyxDQUFDb0I7RUFDbkMsQ0FBQyxDQUFDO0VBQ0YsTUFBTSxDQUFDQyxtQkFBbUIsRUFBRUMsc0JBQXNCLENBQUMsR0FBRy9GLFFBQVEsQ0FBQyxLQUFLLENBQUM7RUFDckUsTUFBTSxDQUFDZ0cscUJBQXFCLEVBQUVDLHdCQUF3QixDQUFDLEdBQUdqRyxRQUFRLENBQ2hFOEQsV0FBVyxJQUFJLEVBQ2pCLENBQUM7RUFDRDtFQUNBO0VBQ0EsTUFBTSxDQUNKb0MsaUNBQWlDLEVBQ2pDQyxvQ0FBb0MsQ0FDckMsR0FBR25HLFFBQVEsQ0FBQyxDQUFDOEQsV0FBVyxFQUFFc0MsSUFBSSxDQUFDLENBQUMsQ0FBQzs7RUFFbEM7RUFDQXZHLFNBQVMsQ0FBQyxNQUFNO0lBQ2QsSUFBSSxDQUFDdUIsOEJBQThCLENBQUMsQ0FBQyxFQUFFO0lBRXZDLE1BQU1pRixlQUFlLEdBQUcsSUFBSUMsZUFBZSxDQUFDLENBQUM7SUFDN0NwRiwwQkFBMEIsQ0FBQzJDLE9BQU8sRUFBRUMsV0FBVyxFQUFFdUMsZUFBZSxDQUFDRSxNQUFNLENBQUMsQ0FDckVDLElBQUksQ0FBQ0MsT0FBTyxJQUFJO01BQ2YsSUFBSUEsT0FBTyxJQUFJLENBQUNKLGVBQWUsQ0FBQ0UsTUFBTSxDQUFDRyxPQUFPLEVBQUU7UUFDOUNULHdCQUF3QixDQUFDUSxPQUFPLENBQUM7UUFDakNOLG9DQUFvQyxDQUFDLEtBQUssQ0FBQztNQUM3QztJQUNGLENBQUMsQ0FBQyxDQUNEUSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFDO0lBQ25CLE9BQU8sTUFBTU4sZUFBZSxDQUFDTyxLQUFLLENBQUMsQ0FBQztFQUN0QyxDQUFDLEVBQUUsQ0FBQy9DLE9BQU8sRUFBRUMsV0FBVyxDQUFDLENBQUM7O0VBRTFCO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQSxNQUFNK0MsVUFBVSxHQUNkdEQsY0FBYyxDQUFDdUQsZ0JBQWdCLENBQUNDLGNBQWMsRUFBRUMsSUFBSSxLQUFLLG1CQUFtQjs7RUFFOUU7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE1BQU0sQ0FBQ0MsY0FBYyxFQUFFQyxpQkFBaUIsQ0FBQyxHQUFHbEgsUUFBUSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FDdEUsTUFBTTtJQUNKLElBQUk2RyxVQUFVLEVBQUU7TUFDZDtNQUNBO01BQ0E7TUFDQSxNQUFNTSxnQkFBZ0IsR0FBRzlGLFlBQVksQ0FDbkMsYUFBYSxJQUFJa0MsY0FBYyxDQUFDdUQsZ0JBQWdCLEdBQzVDdkQsY0FBYyxDQUFDdUQsZ0JBQWdCLENBQUNNLFdBQVcsR0FDM0NDLFNBQ04sQ0FBQyxDQUFDQyxNQUFNLENBQUNDLENBQUMsSUFBSUEsQ0FBQyxDQUFDN0MsUUFBUSxLQUFLaEUsUUFBUSxDQUFDa0UsSUFBSSxJQUFJMkMsQ0FBQyxDQUFDQyxXQUFXLENBQUM7TUFDNUQsT0FBT0wsZ0JBQWdCLENBQUNNLE1BQU0sS0FBSyxDQUFDLEdBQ2hDTixnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDSyxXQUFXLEdBQ2hDSCxTQUFTO0lBQ2Y7SUFDQSxNQUFNSyxHQUFHLEdBQUc5RyxzQkFBc0IsQ0FBQ2lELE9BQU8sQ0FBQztJQUMzQyxJQUFJNkQsR0FBRyxFQUFFLE9BQU8sR0FBR0EsR0FBRyxJQUFJO0lBQzFCLE1BQU1DLEdBQUcsR0FBR2hILGtCQUFrQixDQUFDa0QsT0FBTyxDQUFDO0lBQ3ZDLElBQUk4RCxHQUFHLEVBQUUsT0FBTyxHQUFHQSxHQUFHLElBQUk7SUFDMUIsT0FBTzlELE9BQU87RUFDaEIsQ0FDRixDQUFDO0VBQ0QsTUFBTStELG1CQUFtQixHQUFHN0gsTUFBTSxDQUFDLEtBQUssQ0FBQztFQUN6QyxNQUFNOEgsc0JBQXNCLEdBQUdqSSxXQUFXLENBQUMsQ0FBQ2tJLEtBQUssRUFBRSxNQUFNLEtBQUs7SUFDNURGLG1CQUFtQixDQUFDRyxPQUFPLEdBQUcsSUFBSTtJQUNsQ2IsaUJBQWlCLENBQUNZLEtBQUssQ0FBQztFQUMxQixDQUFDLEVBQUUsRUFBRSxDQUFDO0VBQ05qSSxTQUFTLENBQUMsTUFBTTtJQUNkO0lBQ0E7SUFDQSxJQUFJZ0gsVUFBVSxFQUFFO0lBQ2hCLElBQUltQixTQUFTLEdBQUcsS0FBSztJQUNyQmhILGdDQUFnQyxDQUFDNkMsT0FBTyxFQUFFb0UsTUFBTSxJQUM5Q3ZILFFBQVEsQ0FBQ3dILFVBQVUsQ0FBQztNQUFFckUsT0FBTyxFQUFFb0U7SUFBTyxDQUFDLENBQ3pDLENBQUMsQ0FDRXpCLElBQUksQ0FBQzJCLFFBQVEsSUFBSTtNQUNoQixJQUFJSCxTQUFTLElBQUlKLG1CQUFtQixDQUFDRyxPQUFPLEVBQUU7TUFDOUMsSUFBSUksUUFBUSxDQUFDVixNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ3ZCUCxpQkFBaUIsQ0FBQyxHQUFHaUIsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7TUFDdkM7SUFDRixDQUFDLENBQUMsQ0FDRHhCLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUM7SUFDbkIsT0FBTyxNQUFNO01BQ1hxQixTQUFTLEdBQUcsSUFBSTtJQUNsQixDQUFDO0VBQ0gsQ0FBQyxFQUFFLENBQUNuRSxPQUFPLEVBQUVnRCxVQUFVLENBQUMsQ0FBQzs7RUFFekI7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE1BQU0sQ0FBQ3VCLHFCQUFxQixDQUFDLEdBQUdwSSxRQUFRLENBQ3RDUCxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FDdEIsQ0FBQyxDQUFDOEQsY0FBYyxDQUFDOEUseUJBQXlCLEdBQzFDLEtBQ04sQ0FBQzs7RUFFRDtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQSxNQUFNO0lBQUVDLGtCQUFrQixFQUFsQkEsb0JBQWtCO0lBQUVDLGlCQUFpQixFQUFqQkEsbUJBQWlCO0lBQUVDLFdBQVcsRUFBWEE7RUFBWSxDQUFDLEdBQUcxSSxPQUFPLENBQUMsTUFBTTtJQUMzRSxNQUFNd0ksa0JBQWtCLEdBQUdqSSxtQ0FBbUMsQ0FDNUQsbUNBQW1DLEVBQ25DLEtBQ0YsQ0FBQyxHQUNHUSw0QkFBNEIsQ0FBQ2dELE9BQU8sQ0FBQyxHQUNyQyxJQUFJO0lBRVIsTUFBTTBFLGlCQUFpQixHQUFHaEgsY0FBYyxDQUFDa0gsbUJBQW1CLENBQUMsQ0FBQztJQUM5RCxNQUFNRCxXQUFXLEdBQ2ZELGlCQUFpQixJQUFJeEgsZ0JBQWdCLENBQUN3QyxjQUFjLENBQUNRLEtBQUssQ0FBQztJQUU3RCxPQUFPO01BQUV1RSxrQkFBa0I7TUFBRUMsaUJBQWlCO01BQUVDO0lBQVksQ0FBQztFQUMvRCxDQUFDLEVBQUUsQ0FBQzNFLE9BQU8sRUFBRU4sY0FBYyxDQUFDUSxLQUFLLENBQUMsQ0FBQztFQUVuQyxNQUFNMkUsVUFBVSxHQUFHNUksT0FBTyxDQUFDNkIsVUFBVSxDQUFDLENBQ3BDLE9BQU87SUFBRWdILGVBQWUsRUFBRSxpQkFBaUI7SUFBRUMsYUFBYSxFQUFFO0VBQU8sQ0FBQyxDQUFDLEVBQ3JFLEVBQ0YsQ0FBQztFQUVEaEgsMkJBQTJCLENBQUMyQixjQUFjLEVBQUVtRixVQUFVLENBQUM7RUFFdkQsTUFBTUcseUJBQXlCLEdBQUcvSSxPQUFPLENBQ3ZDLE1BQU1xQiw4QkFBOEIsQ0FBQ29ELHFCQUFxQixDQUFDLEVBQzNELENBQUNBLHFCQUFxQixDQUN4QixDQUFDO0VBRUQsTUFBTXVFLE9BQU8sR0FBR2hKLE9BQU8sQ0FDckIsTUFDRXdDLGtCQUFrQixDQUFDO0lBQ2pCOEUsV0FBVyxFQUNUN0QsY0FBYyxDQUFDdUQsZ0JBQWdCLENBQUNpQyxRQUFRLEtBQUssS0FBSyxHQUM5Q3hGLGNBQWMsQ0FBQ3VELGdCQUFnQixDQUFDTSxXQUFXLEdBQzNDQyxTQUFTO0lBQ2ZOLGNBQWMsRUFBRXhELGNBQWMsQ0FBQ3VELGdCQUFnQixDQUFDQyxjQUFjO0lBQzlEaUMsc0JBQXNCLEVBQUV6RCxpQkFBaUI7SUFDekMwRCxzQkFBc0IsRUFBRTNELGlCQUFpQjtJQUN6QzRELDZCQUE2QixFQUFFakQsd0JBQXdCO0lBQ3ZERCxxQkFBcUI7SUFDckJFLGlDQUFpQztJQUNqQzJDLHlCQUF5QjtJQUN6QjdELFlBQVk7SUFDWkMsV0FBVztJQUNYZ0MsY0FBYztJQUNkWTtFQUNGLENBQUMsQ0FBQyxFQUNKLENBQ0V0RSxjQUFjLEVBQ2R5QyxxQkFBcUIsRUFDckJFLGlDQUFpQyxFQUNqQzJDLHlCQUF5QixFQUN6QjdELFlBQVksRUFDWkMsV0FBVyxFQUNYZ0MsY0FBYyxFQUNkWSxzQkFBc0IsQ0FFMUIsQ0FBQzs7RUFFRDtFQUNBLE1BQU1zQixpQkFBaUIsR0FBR3ZKLFdBQVcsQ0FBQyxNQUFNO0lBQzFDbUcsc0JBQXNCLENBQUNxRCxJQUFJLElBQUksQ0FBQ0EsSUFBSSxDQUFDO0VBQ3ZDLENBQUMsRUFBRSxFQUFFLENBQUM7RUFDTmhKLGFBQWEsQ0FBQyx3QkFBd0IsRUFBRStJLGlCQUFpQixFQUFFO0lBQ3pERSxPQUFPLEVBQUU7RUFDWCxDQUFDLENBQUM7O0VBRUY7RUFDQSxNQUFNQyxzQkFBc0IsR0FBRzFKLFdBQVcsQ0FBQyxNQUFNO0lBQy9DMkQsY0FBYyxDQUFDZ0csa0JBQWtCLEdBQUcsQ0FBQztFQUN2QyxDQUFDLEVBQUUsQ0FBQ2hHLGNBQWMsQ0FBQyxDQUFDO0VBQ3BCbkQsYUFBYSxDQUFDLFlBQVksRUFBRWtKLHNCQUFzQixFQUFFO0lBQ2xERCxPQUFPLEVBQUUsY0FBYztJQUN2QkcsUUFBUSxFQUFFL0osT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQ2hDLENBQUMsQ0FBQzhELGNBQWMsQ0FBQ2tHLHNCQUFzQixHQUN2QztFQUNOLENBQUMsQ0FBQztFQUVGLFNBQVNDLFFBQVFBLENBQUM1QixPQUFLLEVBQUUsTUFBTSxFQUFFO0lBQy9CO0lBQ0EsSUFBSTZCLFdBQVcsRUFBRUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRztNQUN4Q0MsR0FBRyxFQUFFLENBQUM7TUFDTix1QkFBdUIsRUFBRSxDQUFDO01BQzFCLG1CQUFtQixFQUFFLENBQUM7TUFDdEJDLEVBQUUsRUFBRTtJQUNOLENBQUM7SUFDRCxJQUFJckssT0FBTyxDQUFDLGlCQUFpQixDQUFDLEVBQUU7TUFDOUJrSyxXQUFXLEdBQUc7UUFDWkUsR0FBRyxFQUFFLENBQUM7UUFDTix1QkFBdUIsRUFBRSxDQUFDO1FBQzFCLG1CQUFtQixFQUFFLENBQUM7UUFDdEIseUJBQXlCLEVBQUUsQ0FBQztRQUM1QkMsRUFBRSxFQUFFO01BQ04sQ0FBQztJQUNIO0lBQ0F2SixRQUFRLENBQUMsMENBQTBDLEVBQUU7TUFDbkR3SixZQUFZLEVBQUVKLFdBQVcsQ0FBQzdCLE9BQUssQ0FBQztNQUNoQ2tDLGlCQUFpQixFQUFFdkYsY0FBYyxDQUFDb0I7SUFDcEMsQ0FBQyxDQUFDO0lBRUYsTUFBTW9FLG9CQUFvQixHQUFHekosNEJBQTRCLENBQ3ZEK0MsY0FBYyxDQUFDb0IsSUFBSSxDQUFDQyxJQUN0QixDQUFDLElBQUl0RSwwREFBMEQ7SUFFL0QsSUFBSXdILE9BQUssS0FBSyxtQkFBbUIsRUFBRTtNQUNqQyxNQUFNb0MsYUFBYSxHQUFHLENBQUNqRCxjQUFjLElBQUksRUFBRSxFQUFFYixJQUFJLENBQUMsQ0FBQztNQUNuRC9ELHVCQUF1QixDQUFDLGlCQUFpQixFQUFFa0IsY0FBYyxFQUFFLFFBQVEsQ0FBQztNQUNwRSxJQUFJLENBQUMyRyxhQUFhLEVBQUU7UUFDbEIzRyxjQUFjLENBQUM0RyxPQUFPLENBQUM1RyxjQUFjLENBQUNRLEtBQUssRUFBRSxFQUFFLENBQUM7TUFDbEQsQ0FBQyxNQUFNO1FBQ0wsTUFBTXFHLGFBQWEsRUFBRTlJLGdCQUFnQixFQUFFLEdBQUcsQ0FDeEM7VUFDRTBGLElBQUksRUFBRSxVQUFVO1VBQ2hCcUQsS0FBSyxFQUFFLENBQ0w7WUFDRTNGLFFBQVEsRUFBRWhFLFFBQVEsQ0FBQ2tFLElBQUk7WUFDdkI0QyxXQUFXLEVBQUUwQztVQUNmLENBQUMsQ0FDRjtVQUNEbkIsUUFBUSxFQUFFLE9BQU87VUFDakJ1QixXQUFXLEVBQUU7UUFDZixDQUFDLENBQ0Y7UUFDRC9HLGNBQWMsQ0FBQzRHLE9BQU8sQ0FBQzVHLGNBQWMsQ0FBQ1EsS0FBSyxFQUFFcUcsYUFBYSxDQUFDO01BQzdEO01BQ0EzRyxNQUFNLENBQUMsQ0FBQztNQUNSO0lBQ0Y7SUFFQSxJQUFJaEUsT0FBTyxDQUFDLGlCQUFpQixDQUFDLElBQUlxSSxPQUFLLEtBQUsseUJBQXlCLEVBQUU7TUFDckUsTUFBTXlDLGtCQUFrQixHQUFHdkUscUJBQXFCLENBQUNJLElBQUksQ0FBQyxDQUFDO01BQ3ZEL0QsdUJBQXVCLENBQUMsaUJBQWlCLEVBQUVrQixjQUFjLEVBQUUsUUFBUSxDQUFDO01BQ3BFLElBQUksQ0FBQ2dILGtCQUFrQixFQUFFO1FBQ3ZCaEgsY0FBYyxDQUFDNEcsT0FBTyxDQUFDNUcsY0FBYyxDQUFDUSxLQUFLLEVBQUUsRUFBRSxDQUFDO01BQ2xELENBQUMsTUFBTTtRQUNMLE1BQU15RyxpQkFBaUIsRUFBRWxKLGdCQUFnQixFQUFFLEdBQUcsQ0FDNUM7VUFDRTBGLElBQUksRUFBRSxVQUFVO1VBQ2hCcUQsS0FBSyxFQUFFLENBQ0w7WUFDRTNGLFFBQVEsRUFBRWhFLFFBQVEsQ0FBQ2tFLElBQUk7WUFDdkI0QyxXQUFXLEVBQUV2Ryx1QkFBdUIsQ0FBQ3NKLGtCQUFrQjtVQUN6RCxDQUFDLENBQ0Y7VUFDRHhCLFFBQVEsRUFBRSxPQUFPO1VBQ2pCdUIsV0FBVyxFQUFFO1FBQ2YsQ0FBQyxDQUNGO1FBQ0QvRyxjQUFjLENBQUM0RyxPQUFPLENBQUM1RyxjQUFjLENBQUNRLEtBQUssRUFBRXlHLGlCQUFpQixDQUFDO01BQ2pFO01BQ0EvRyxNQUFNLENBQUMsQ0FBQztNQUNSO0lBQ0Y7SUFFQSxRQUFRcUUsT0FBSztNQUNYLEtBQUssS0FBSztRQUFFO1VBQ1YsTUFBTTJDLGlCQUFlLEdBQUdyRixjQUFjLENBQUNnQixJQUFJLENBQUMsQ0FBQztVQUM3Qy9ELHVCQUF1QixDQUFDLGlCQUFpQixFQUFFa0IsY0FBYyxFQUFFLFFBQVEsQ0FBQztVQUNwRTtVQUNBaEQsUUFBUSxDQUFDLHdCQUF3QixFQUFFO1lBQ2pDbUUsUUFBUSxFQUFFdUYsb0JBQW9CO1lBQzlCUyxLQUFLLEVBQUVuSCxjQUFjLENBQUNvQixJQUFJLENBQUMrRixLQUFLLElBQUksS0FBSztZQUN6Q0MsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDRixpQkFBZTtZQUNuQ0csbUJBQW1CLEVBQUVILGlCQUFlLENBQUNoRCxNQUFNO1lBQzNDb0QscUJBQXFCLEVBQUUzRjtVQUN6QixDQUFDLENBQUM7VUFDRjNCLGNBQWMsQ0FBQzRHLE9BQU8sQ0FDcEI1RyxjQUFjLENBQUNRLEtBQUssRUFDcEIsRUFBRSxFQUNGMEcsaUJBQWUsSUFBSXBELFNBQ3JCLENBQUM7VUFDRDVELE1BQU0sQ0FBQyxDQUFDO1VBQ1I7UUFDRjtNQUNBLEtBQUssdUJBQXVCO1FBQUU7VUFDNUJwQix1QkFBdUIsQ0FBQyxpQkFBaUIsRUFBRWtCLGNBQWMsRUFBRSxRQUFRLENBQUM7VUFDcEU7VUFDQSxNQUFNaUgsbUJBQWlCLEdBQ3JCLGFBQWEsSUFBSWpILGNBQWMsQ0FBQ3VELGdCQUFnQixHQUM1Q3ZELGNBQWMsQ0FBQ3VELGdCQUFnQixDQUFDTSxXQUFXLElBQUksRUFBRSxHQUNqRCxFQUFFO1VBQ1I3RCxjQUFjLENBQUM0RyxPQUFPLENBQUM1RyxjQUFjLENBQUNRLEtBQUssRUFBRXlHLG1CQUFpQixDQUFDO1VBQy9EL0csTUFBTSxDQUFDLENBQUM7VUFDUjtRQUNGO01BQ0EsS0FBSyxJQUFJO1FBQUU7VUFDVCxNQUFNZ0gsZUFBZSxHQUFHcEYsY0FBYyxDQUFDZSxJQUFJLENBQUMsQ0FBQzs7VUFFN0M7VUFDQTdGLFFBQVEsQ0FBQyx3QkFBd0IsRUFBRTtZQUNqQ21FLFFBQVEsRUFBRXVGLG9CQUFvQjtZQUM5QlMsS0FBSyxFQUFFbkgsY0FBYyxDQUFDb0IsSUFBSSxDQUFDK0YsS0FBSyxJQUFJLEtBQUs7WUFDekNDLGdCQUFnQixFQUFFLENBQUMsQ0FBQ0YsZUFBZTtZQUNuQ0csbUJBQW1CLEVBQUVILGVBQWUsQ0FBQ2hELE1BQU07WUFDM0NvRCxxQkFBcUIsRUFBRTFGO1VBQ3pCLENBQUMsQ0FBQzs7VUFFRjtVQUNBTyxZQUFZLENBQUMrRSxlQUFlLElBQUlwRCxTQUFTLENBQUM7VUFDMUM7UUFDRjtJQUNGO0VBQ0Y7RUFFQSxNQUFNeUQsa0JBQWtCLEdBQUdyTCxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FDbkQ4RCxjQUFjLENBQUNrRyxzQkFBc0IsR0FDbkMsQ0FBQyxJQUFJO0FBQ1gsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMvSixPQUFPLENBQUNxTCxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUk7QUFDaEUsUUFBUSxDQUFDeEgsY0FBYyxDQUFDeUgscUJBQXFCLElBQ25DLENBQUMsSUFBSSxDQUFDLFFBQVE7QUFDeEIsWUFBWSxDQUFDLG1CQUFtQjtBQUNoQyxZQUFZLENBQUN6SCxjQUFjLENBQUN5SCxxQkFBcUI7QUFDakQsWUFBWSxDQUFDLEdBQUc7QUFDaEIsVUFBVSxFQUFFLElBQUksQ0FDUDtBQUNULE1BQU0sRUFBRSxJQUFJLENBQUMsR0FDTHpILGNBQWMsQ0FBQzhFLHlCQUF5QixHQUMxQyxDQUFDLDBCQUEwQixHQUFHLEdBQzVCRCxxQkFBcUIsR0FDdkIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLHdCQUF3QixFQUFFLElBQUksQ0FBQyxHQUM1Q2YsU0FBUyxHQUNYQSxTQUFTO0VBRWIsT0FDRSxDQUFDLGdCQUFnQixDQUNmLFdBQVcsQ0FBQyxDQUFDekQsV0FBVyxDQUFDLENBQ3pCLEtBQUssQ0FBQyxDQUNKMkUsbUJBQWlCLElBQUksQ0FBQ0MsYUFBVyxHQUM3Qiw0QkFBNEIsR0FDNUIsY0FDTixDQUFDLENBQ0QsUUFBUSxDQUFDLENBQUNzQyxrQkFBa0IsQ0FBQztBQUVuQyxNQUFNLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzNELFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUNyRyxjQUFjLENBQUNvQixPQUFPLENBQUM7QUFDL0MsVUFBVSxDQUFDbkYsUUFBUSxDQUFDdUssb0JBQW9CLENBQzVCO1VBQUVwSCxPQUFPO1VBQUVDO1FBQVksQ0FBQyxFQUN4QjtVQUFFUSxLQUFLO1VBQUVYLE9BQU8sRUFBRTtRQUFLLENBQUMsQ0FBRTtRQUM1QixDQUFDO0FBQ1gsUUFBUSxFQUFFLElBQUk7QUFDZCxRQUFRLENBQUMsQ0FBQ2MsY0FBYyxDQUFDb0IsT0FBTyxJQUN0QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQ3RDLGNBQWMsQ0FBQ08sV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUNsRDtBQUNULFFBQVEsQ0FBQywwQkFBMEIsQ0FDekIsT0FBTyxDQUFDLENBQUNXLGNBQWMsQ0FBQ29CLE9BQU8sQ0FBQyxDQUNoQyxPQUFPLENBQUMsQ0FBQ3BCLGNBQWMsQ0FBQ3lHLE9BQU8sQ0FBQztBQUUxQyxNQUFNLEVBQUUsR0FBRztBQUNYLE1BQU0sQ0FBQ3BGLG1CQUFtQixHQUNsQjtBQUNSLFVBQVUsQ0FBQywyQkFBMkIsQ0FDMUIsZ0JBQWdCLENBQUMsQ0FBQ3ZDLGNBQWMsQ0FBQ3VELGdCQUFnQixDQUFDLENBQ2xELFFBQVEsQ0FBQyxNQUFNO0FBRTNCLFVBQVUsQ0FBQ3RELGNBQWMsQ0FBQ3NGLE9BQU8sQ0FBQ3FDLEtBQUssSUFDM0IsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEQsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMseUJBQXlCLEVBQUUsSUFBSTtBQUM1RCxZQUFZLEVBQUUsR0FBRyxDQUNOO0FBQ1gsUUFBUSxHQUFHLEdBRUg7QUFDUixVQUFVLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxRQUFRO0FBQ3JDLFlBQVksQ0FBQyx5QkFBeUIsQ0FDeEIsZ0JBQWdCLENBQUMsQ0FBQzVILGNBQWMsQ0FBQ3VELGdCQUFnQixDQUFDLENBQ2xELFFBQVEsQ0FBQyxTQUFTO0FBRWhDLFlBQVksQ0FBQ3dCLG9CQUFrQixJQUNqQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbkMsZ0JBQWdCLENBQUMsSUFBSSxDQUNILEtBQUssQ0FBQyxTQUFTLENBQ2YsUUFBUSxDQUFDLENBQ1A3SSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FDdEI4RCxjQUFjLENBQUNrRyxzQkFBc0IsR0FDckMsS0FDTixDQUFDO0FBRW5CLGtCQUFrQixDQUFDbkIsb0JBQWtCO0FBQ3JDLGdCQUFnQixFQUFFLElBQUk7QUFDdEIsY0FBYyxFQUFFLEdBQUcsQ0FDTjtBQUNiLFlBQVksQ0FBQyxJQUFJLENBQ0gsUUFBUSxDQUFDLENBQ1A3SSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FDdEI4RCxjQUFjLENBQUNrRyxzQkFBc0IsR0FDckMsS0FDTixDQUFDO0FBRWY7QUFDQSxZQUFZLEVBQUUsSUFBSTtBQUNsQixZQUFZLENBQUMsTUFBTSxDQUNMLE9BQU8sQ0FBQyxDQUNOaEssT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQ3RCOEQsY0FBYyxDQUFDa0csc0JBQXNCLEdBQ25DWCxPQUFPLENBQUM3RixHQUFHLENBQUNtSSxDQUFDLEtBQUs7VUFBRSxHQUFHQSxDQUFDO1VBQUVDLFFBQVEsRUFBRTtRQUFLLENBQUMsQ0FBQyxDQUFDLEdBQzVDdkMsT0FBTyxHQUNUQSxPQUNOLENBQUMsQ0FDRCxVQUFVLENBQUMsQ0FDVHJKLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUN0QjhELGNBQWMsQ0FBQ2tHLHNCQUFzQixHQUNyQyxLQUNOLENBQUMsQ0FDRCxrQkFBa0IsQ0FDbEIsUUFBUSxDQUFDLENBQUNDLFFBQVEsQ0FBQyxDQUNuQixRQUFRLENBQUMsQ0FBQyxNQUFNaEUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUMvQixPQUFPLENBQUMsQ0FBQ0MsV0FBVyxDQUFDLENBQ3JCLGlCQUFpQixDQUFDLENBQUNGLHFCQUFxQixDQUFDO0FBRXZELFVBQVUsRUFBRSxHQUFHO0FBQ2YsVUFBVSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMzRCxZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVE7QUFDMUI7QUFDQSxjQUFjLENBQUMsQ0FBRUQsYUFBYSxLQUFLLEtBQUssSUFBSSxDQUFDUixZQUFZLElBQ3hDUSxhQUFhLEtBQUssSUFBSSxJQUFJLENBQUNQLFdBQVksS0FDeEMsaUJBQWlCO0FBQ2pDLGNBQWMsQ0FBQ1IsY0FBYyxDQUFDNkcsT0FBTyxJQUNyQixnQkFBZ0I3RyxjQUFjLENBQUNvQixPQUFPLEdBQUcsTUFBTSxHQUFHLFNBQVMsRUFBRTtBQUM3RSxZQUFZLEVBQUUsSUFBSTtBQUNsQixZQUFZLENBQUNyQyxjQUFjLENBQUNzRixPQUFPLENBQUNxQyxLQUFLLElBQzNCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQy9DO0FBQ2IsVUFBVSxFQUFFLEdBQUc7QUFDZixRQUFRLEdBQ0Q7QUFDUCxJQUFJLEVBQUUsZ0JBQWdCLENBQUM7QUFFdkIiLCJpZ25vcmVMaXN0IjpbXX0= \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts b/_all-in-one-upload/cc-haha/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts new file mode 100644 index 0000000..3272c96 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts @@ -0,0 +1,212 @@ +import { useCallback, useMemo, useState } from 'react' +import { useAppState } from 'src/state/AppState.js' +import { useKeybindings } from '../../../keybindings/useKeybinding.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../../../services/analytics/index.js' +import { sanitizeToolNameForAnalytics } from '../../../services/analytics/metadata.js' +import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js' +import type { CompletionType } from '../../../utils/unaryLogging.js' +import type { ToolUseConfirm } from '../PermissionRequest.js' +import { + type FileOperationType, + getFilePermissionOptions, + type PermissionOption, + type PermissionOptionWithLabel, +} from './permissionOptions.js' +import { + PERMISSION_HANDLERS, + type PermissionHandlerParams, +} from './usePermissionHandler.js' + +export interface ToolInput { + [key: string]: unknown +} + +export type UseFilePermissionDialogProps = { + filePath: string + completionType: CompletionType + languageName: string | Promise + toolUseConfirm: ToolUseConfirm + onDone: () => void + onReject: () => void + parseInput: (input: unknown) => T + operationType?: FileOperationType +} + +export type UseFilePermissionDialogResult = { + options: PermissionOptionWithLabel[] + onChange: (option: PermissionOption, input: T, feedback?: string) => void + acceptFeedback: string + rejectFeedback: string + focusedOption: string + setFocusedOption: (option: string) => void + handleInputModeToggle: (value: string) => void + yesInputMode: boolean + noInputMode: boolean +} + +/** + * Hook for handling file permission dialogs with common logic + */ +export function useFilePermissionDialog({ + filePath, + completionType, + languageName, + toolUseConfirm, + onDone, + onReject, + parseInput, + operationType = 'write', +}: UseFilePermissionDialogProps): UseFilePermissionDialogResult { + const toolPermissionContext = useAppState(s => s.toolPermissionContext) + const [acceptFeedback, setAcceptFeedback] = useState('') + const [rejectFeedback, setRejectFeedback] = useState('') + const [focusedOption, setFocusedOption] = useState('yes') + const [yesInputMode, setYesInputMode] = useState(false) + const [noInputMode, setNoInputMode] = useState(false) + // Track whether user ever entered feedback mode (persists after collapse) + const [yesFeedbackModeEntered, setYesFeedbackModeEntered] = useState(false) + const [noFeedbackModeEntered, setNoFeedbackModeEntered] = useState(false) + + // Generate options based on context + const options = useMemo( + () => + getFilePermissionOptions({ + filePath, + toolPermissionContext, + operationType, + onRejectFeedbackChange: setRejectFeedback, + onAcceptFeedbackChange: setAcceptFeedback, + yesInputMode, + noInputMode, + }), + [filePath, toolPermissionContext, operationType, yesInputMode, noInputMode], + ) + + // Handle option selection using shared handlers + const onChange = useCallback( + (option: PermissionOption, input: T, feedback?: string) => { + const params: PermissionHandlerParams = { + messageId: toolUseConfirm.assistantMessage.message.id, + path: filePath, + toolUseConfirm, + toolPermissionContext, + onDone, + onReject, + completionType, + languageName, + operationType, + } + + // Override the input in toolUseConfirm to pass the parsed input + const originalOnAllow = toolUseConfirm.onAllow + toolUseConfirm.onAllow = ( + _input: unknown, + permissionUpdates: PermissionUpdate[], + feedback?: string, + ) => { + originalOnAllow(input, permissionUpdates, feedback) + } + + const handler = PERMISSION_HANDLERS[option.type] + handler(params, { + feedback, + hasFeedback: !!feedback, + enteredFeedbackMode: + option.type === 'accept-once' + ? yesFeedbackModeEntered + : noFeedbackModeEntered, + scope: option.type === 'accept-session' ? option.scope : undefined, + }) + }, + [ + filePath, + completionType, + languageName, + toolUseConfirm, + toolPermissionContext, + onDone, + onReject, + operationType, + yesFeedbackModeEntered, + noFeedbackModeEntered, + ], + ) + + // Handler for confirm:cycleMode - select accept-session option + const handleCycleMode = useCallback(() => { + const sessionOption = options.find(o => o.option.type === 'accept-session') + if (sessionOption) { + const parsedInput = parseInput(toolUseConfirm.input) + onChange(sessionOption.option, parsedInput) + } + }, [options, parseInput, toolUseConfirm.input, onChange]) + + // Register keyboard shortcut handler via keybindings system + useKeybindings( + { 'confirm:cycleMode': handleCycleMode }, + { context: 'Confirmation' }, + ) + + // Wrap setFocusedOption and reset input mode when navigating away + const handleFocusedOptionChange = useCallback( + (value: string) => { + // Reset input mode when navigating away, but only if no text typed + if (value !== 'yes' && yesInputMode && !acceptFeedback.trim()) { + setYesInputMode(false) + } + if (value !== 'no' && noInputMode && !rejectFeedback.trim()) { + setNoInputMode(false) + } + setFocusedOption(value) + }, + [yesInputMode, noInputMode, acceptFeedback, rejectFeedback], + ) + + // Handle Tab key toggling input mode for Yes/No options + const handleInputModeToggle = useCallback( + (value: string) => { + const analyticsProps = { + toolName: sanitizeToolNameForAnalytics( + toolUseConfirm.tool.name, + ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + isMcp: toolUseConfirm.tool.isMcp ?? false, + } + + if (value === 'yes') { + if (yesInputMode) { + setYesInputMode(false) + logEvent('tengu_accept_feedback_mode_collapsed', analyticsProps) + } else { + setYesInputMode(true) + setYesFeedbackModeEntered(true) + logEvent('tengu_accept_feedback_mode_entered', analyticsProps) + } + } else if (value === 'no') { + if (noInputMode) { + setNoInputMode(false) + logEvent('tengu_reject_feedback_mode_collapsed', analyticsProps) + } else { + setNoInputMode(true) + setNoFeedbackModeEntered(true) + logEvent('tengu_reject_feedback_mode_entered', analyticsProps) + } + } + }, + [yesInputMode, noInputMode, toolUseConfirm], + ) + + return { + options, + onChange, + acceptFeedback, + rejectFeedback, + focusedOption, + setFocusedOption: handleFocusedOptionChange, + handleInputModeToggle, + yesInputMode, + noInputMode, + } +} diff --git a/_all-in-one-upload/cc-haha/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx b/_all-in-one-upload/cc-haha/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx new file mode 100644 index 0000000..e6275cb --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx @@ -0,0 +1,115 @@ +import { c as _c } from "react/compiler-runtime"; +import React from 'react'; +import { Box, Text, useTheme } from '../../../ink.js'; +import { FallbackPermissionRequest } from '../FallbackPermissionRequest.js'; +import { FilePermissionDialog } from '../FilePermissionDialog/FilePermissionDialog.js'; +import type { ToolInput } from '../FilePermissionDialog/useFilePermissionDialog.js'; +import type { PermissionRequestProps, ToolUseConfirm } from '../PermissionRequest.js'; +function pathFromToolUse(toolUseConfirm: ToolUseConfirm): string | null { + const tool = toolUseConfirm.tool; + if ('getPath' in tool && typeof tool.getPath === 'function') { + try { + return tool.getPath(toolUseConfirm.input); + } catch { + return null; + } + } + return null; +} +export function FilesystemPermissionRequest(t0) { + const $ = _c(30); + const { + toolUseConfirm, + onDone, + onReject, + verbose, + toolUseContext, + workerBadge + } = t0; + const [theme] = useTheme(); + let t1; + if ($[0] !== toolUseConfirm) { + t1 = pathFromToolUse(toolUseConfirm); + $[0] = toolUseConfirm; + $[1] = t1; + } else { + t1 = $[1]; + } + const path = t1; + let t2; + if ($[2] !== toolUseConfirm.input || $[3] !== toolUseConfirm.tool) { + t2 = toolUseConfirm.tool.userFacingName(toolUseConfirm.input as never); + $[2] = toolUseConfirm.input; + $[3] = toolUseConfirm.tool; + $[4] = t2; + } else { + t2 = $[4]; + } + const userFacingName = t2; + const isReadOnly = toolUseConfirm.tool.isReadOnly(toolUseConfirm.input); + const userFacingReadOrEdit = isReadOnly ? "Read" : "Edit"; + const title = `${userFacingReadOrEdit} file`; + const parseInput = _temp; + if (!path) { + let t3; + if ($[5] !== onDone || $[6] !== onReject || $[7] !== toolUseConfirm || $[8] !== toolUseContext || $[9] !== verbose || $[10] !== workerBadge) { + t3 = ; + $[5] = onDone; + $[6] = onReject; + $[7] = toolUseConfirm; + $[8] = toolUseContext; + $[9] = verbose; + $[10] = workerBadge; + $[11] = t3; + } else { + t3 = $[11]; + } + return t3; + } + let t3; + if ($[12] !== theme || $[13] !== toolUseConfirm.input || $[14] !== toolUseConfirm.tool || $[15] !== verbose) { + t3 = toolUseConfirm.tool.renderToolUseMessage(toolUseConfirm.input as never, { + theme, + verbose + }); + $[12] = theme; + $[13] = toolUseConfirm.input; + $[14] = toolUseConfirm.tool; + $[15] = verbose; + $[16] = t3; + } else { + t3 = $[16]; + } + let t4; + if ($[17] !== t3 || $[18] !== userFacingName) { + t4 = {userFacingName}({t3}); + $[17] = t3; + $[18] = userFacingName; + $[19] = t4; + } else { + t4 = $[19]; + } + const content = t4; + const t5 = isReadOnly ? "read" : "write"; + let t6; + if ($[20] !== content || $[21] !== onDone || $[22] !== onReject || $[23] !== path || $[24] !== t5 || $[25] !== title || $[26] !== toolUseConfirm || $[27] !== toolUseContext || $[28] !== workerBadge) { + t6 = ; + $[20] = content; + $[21] = onDone; + $[22] = onReject; + $[23] = path; + $[24] = t5; + $[25] = title; + $[26] = toolUseConfirm; + $[27] = toolUseContext; + $[28] = workerBadge; + $[29] = t6; + } else { + t6 = $[29]; + } + return t6; +} +function _temp(input) { + return input as ToolInput; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJveCIsIlRleHQiLCJ1c2VUaGVtZSIsIkZhbGxiYWNrUGVybWlzc2lvblJlcXVlc3QiLCJGaWxlUGVybWlzc2lvbkRpYWxvZyIsIlRvb2xJbnB1dCIsIlBlcm1pc3Npb25SZXF1ZXN0UHJvcHMiLCJUb29sVXNlQ29uZmlybSIsInBhdGhGcm9tVG9vbFVzZSIsInRvb2xVc2VDb25maXJtIiwidG9vbCIsImdldFBhdGgiLCJpbnB1dCIsIkZpbGVzeXN0ZW1QZXJtaXNzaW9uUmVxdWVzdCIsInQwIiwiJCIsIl9jIiwib25Eb25lIiwib25SZWplY3QiLCJ2ZXJib3NlIiwidG9vbFVzZUNvbnRleHQiLCJ3b3JrZXJCYWRnZSIsInRoZW1lIiwidDEiLCJwYXRoIiwidDIiLCJ1c2VyRmFjaW5nTmFtZSIsImlzUmVhZE9ubHkiLCJ1c2VyRmFjaW5nUmVhZE9yRWRpdCIsInRpdGxlIiwicGFyc2VJbnB1dCIsIl90ZW1wIiwidDMiLCJyZW5kZXJUb29sVXNlTWVzc2FnZSIsInQ0IiwiY29udGVudCIsInQ1IiwidDYiXSwic291cmNlcyI6WyJGaWxlc3lzdGVtUGVybWlzc2lvblJlcXVlc3QudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IEJveCwgVGV4dCwgdXNlVGhlbWUgfSBmcm9tICcuLi8uLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBGYWxsYmFja1Blcm1pc3Npb25SZXF1ZXN0IH0gZnJvbSAnLi4vRmFsbGJhY2tQZXJtaXNzaW9uUmVxdWVzdC5qcydcbmltcG9ydCB7IEZpbGVQZXJtaXNzaW9uRGlhbG9nIH0gZnJvbSAnLi4vRmlsZVBlcm1pc3Npb25EaWFsb2cvRmlsZVBlcm1pc3Npb25EaWFsb2cuanMnXG5pbXBvcnQgdHlwZSB7IFRvb2xJbnB1dCB9IGZyb20gJy4uL0ZpbGVQZXJtaXNzaW9uRGlhbG9nL3VzZUZpbGVQZXJtaXNzaW9uRGlhbG9nLmpzJ1xuaW1wb3J0IHR5cGUge1xuICBQZXJtaXNzaW9uUmVxdWVzdFByb3BzLFxuICBUb29sVXNlQ29uZmlybSxcbn0gZnJvbSAnLi4vUGVybWlzc2lvblJlcXVlc3QuanMnXG5cbmZ1bmN0aW9uIHBhdGhGcm9tVG9vbFVzZSh0b29sVXNlQ29uZmlybTogVG9vbFVzZUNvbmZpcm0pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgdG9vbCA9IHRvb2xVc2VDb25maXJtLnRvb2xcbiAgaWYgKCdnZXRQYXRoJyBpbiB0b29sICYmIHR5cGVvZiB0b29sLmdldFBhdGggPT09ICdmdW5jdGlvbicpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRvb2wuZ2V0UGF0aCh0b29sVXNlQ29uZmlybS5pbnB1dClcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBGaWxlc3lzdGVtUGVybWlzc2lvblJlcXVlc3Qoe1xuICB0b29sVXNlQ29uZmlybSxcbiAgb25Eb25lLFxuICBvblJlamVjdCxcbiAgdmVyYm9zZSxcbiAgdG9vbFVzZUNvbnRleHQsXG4gIHdvcmtlckJhZGdlLFxufTogUGVybWlzc2lvblJlcXVlc3RQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IFt0aGVtZV0gPSB1c2VUaGVtZSgpXG4gIGNvbnN0IHBhdGggPSBwYXRoRnJvbVRvb2xVc2UodG9vbFVzZUNvbmZpcm0pXG4gIGNvbnN0IHVzZXJGYWNpbmdOYW1lID0gdG9vbFVzZUNvbmZpcm0udG9vbC51c2VyRmFjaW5nTmFtZShcbiAgICB0b29sVXNlQ29uZmlybS5pbnB1dCBhcyBuZXZlcixcbiAgKVxuXG4gIGNvbnN0IGlzUmVhZE9ubHkgPSB0b29sVXNlQ29uZmlybS50b29sLmlzUmVhZE9ubHkodG9vbFVzZUNvbmZpcm0uaW5wdXQpXG4gIGNvbnN0IHVzZXJGYWNpbmdSZWFkT3JFZGl0ID0gaXNSZWFkT25seSA/ICdSZWFkJyA6ICdFZGl0J1xuXG4gIC8vIFVzZSBzaW1wbGUgc2luZ3VsYXIgZm9ybSAtIHRoZSBhY3R1YWwgb3BlcmF0aW9uIGRldGFpbHMgYXJlIHNob3duIGluIGNvbnRlbnRcbiAgY29uc3QgdGl0bGUgPSBgJHt1c2VyRmFjaW5nUmVhZE9yRWRpdH0gZmlsZWBcblxuICAvLyBTaW1wbGUgcGFzcy10aHJvdWdoIHBhcnNlciBzaW5jZSB3ZSBkb24ndCBuZWVkIHRvIHRyYW5zZm9ybSB0aGUgaW5wdXRcbiAgY29uc3QgcGFyc2VJbnB1dCA9IChpbnB1dDogdW5rbm93bik6IFRvb2xJbnB1dCA9PiBpbnB1dCBhcyBUb29sSW5wdXRcblxuICAvLyBGYWxsIGJhY2sgdG8gZ2VuZXJpYyBwZXJtaXNzaW9uIHJlcXVlc3QgaWYgbm8gcGF0aCBpcyBmb3VuZFxuICBpZiAoIXBhdGgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPEZhbGxiYWNrUGVybWlzc2lvblJlcXVlc3RcbiAgICAgICAgdG9vbFVzZUNvbmZpcm09e3Rvb2xVc2VDb25maXJtfVxuICAgICAgICB0b29sVXNlQ29udGV4dD17dG9vbFVzZUNvbnRleHR9XG4gICAgICAgIG9uRG9uZT17b25Eb25lfVxuICAgICAgICBvblJlamVjdD17b25SZWplY3R9XG4gICAgICAgIHZlcmJvc2U9e3ZlcmJvc2V9XG4gICAgICAgIHdvcmtlckJhZGdlPXt3b3JrZXJCYWRnZX1cbiAgICAgIC8+XG4gICAgKVxuICB9XG5cbiAgLy8gUmVuZGVyIHRvb2wgdXNlIG1lc3NhZ2UgY29udGVudFxuICBjb25zdCBjb250ZW50ID0gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiIHBhZGRpbmdYPXsyfSBwYWRkaW5nWT17MX0+XG4gICAgICA8VGV4dD5cbiAgICAgICAge3VzZXJGYWNpbmdOYW1lfShcbiAgICAgICAge3Rvb2xVc2VDb25maXJtLnRvb2wucmVuZGVyVG9vbFVzZU1lc3NhZ2UoXG4gICAgICAgICAgdG9vbFVzZUNvbmZpcm0uaW5wdXQgYXMgbmV2ZXIsXG4gICAgICAgICAgeyB0aGVtZSwgdmVyYm9zZSB9LFxuICAgICAgICApfVxuICAgICAgICApXG4gICAgICA8L1RleHQ+XG4gICAgPC9Cb3g+XG4gIClcblxuICByZXR1cm4gKFxuICAgIDxGaWxlUGVybWlzc2lvbkRpYWxvZ1xuICAgICAgdG9vbFVzZUNvbmZpcm09e3Rvb2xVc2VDb25maXJtfVxuICAgICAgdG9vbFVzZUNvbnRleHQ9e3Rvb2xVc2VDb250ZXh0fVxuICAgICAgb25Eb25lPXtvbkRvbmV9XG4gICAgICBvblJlamVjdD17b25SZWplY3R9XG4gICAgICB3b3JrZXJCYWRnZT17d29ya2VyQmFkZ2V9XG4gICAgICB0aXRsZT17dGl0bGV9XG4gICAgICBjb250ZW50PXtjb250ZW50fVxuICAgICAgcGF0aD17cGF0aH1cbiAgICAgIHBhcnNlSW5wdXQ9e3BhcnNlSW5wdXR9XG4gICAgICBvcGVyYXRpb25UeXBlPXtpc1JlYWRPbmx5ID8gJ3JlYWQnIDogJ3dyaXRlJ31cbiAgICAgIGNvbXBsZXRpb25UeXBlPVwidG9vbF91c2Vfc2luZ2xlXCJcbiAgICAvPlxuICApXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPQSxLQUFLLE1BQU0sT0FBTztBQUN6QixTQUFTQyxHQUFHLEVBQUVDLElBQUksRUFBRUMsUUFBUSxRQUFRLGlCQUFpQjtBQUNyRCxTQUFTQyx5QkFBeUIsUUFBUSxpQ0FBaUM7QUFDM0UsU0FBU0Msb0JBQW9CLFFBQVEsaURBQWlEO0FBQ3RGLGNBQWNDLFNBQVMsUUFBUSxvREFBb0Q7QUFDbkYsY0FDRUMsc0JBQXNCLEVBQ3RCQyxjQUFjLFFBQ1QseUJBQXlCO0FBRWhDLFNBQVNDLGVBQWVBLENBQUNDLGNBQWMsRUFBRUYsY0FBYyxDQUFDLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FBQztFQUN0RSxNQUFNRyxJQUFJLEdBQUdELGNBQWMsQ0FBQ0MsSUFBSTtFQUNoQyxJQUFJLFNBQVMsSUFBSUEsSUFBSSxJQUFJLE9BQU9BLElBQUksQ0FBQ0MsT0FBTyxLQUFLLFVBQVUsRUFBRTtJQUMzRCxJQUFJO01BQ0YsT0FBT0Qs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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/permissions/PermissionExplanation.tsx b/_all-in-one-upload/cc-haha/src/components/permissions/PermissionExplanation.tsx new file mode 100644 index 0000000..b7fd36b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/permissions/PermissionExplanation.tsx @@ -0,0 +1,272 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { Suspense, use, useState } from 'react'; +import { Box, Text } from '../../ink.js'; +import { useKeybinding } from '../../keybindings/useKeybinding.js'; +import { logEvent } from '../../services/analytics/index.js'; +import type { Message } from '../../types/message.js'; +import { generatePermissionExplanation, isPermissionExplainerEnabled, type PermissionExplanation as PermissionExplanationType, type RiskLevel } from '../../utils/permissions/permissionExplainer.js'; +import { ShimmerChar } from '../Spinner/ShimmerChar.js'; +import { useShimmerAnimation } from '../Spinner/useShimmerAnimation.js'; +const LOADING_MESSAGE = 'Loading explanation…'; +function ShimmerLoadingText() { + const $ = _c(7); + const [ref, glimmerIndex] = useShimmerAnimation("responding", LOADING_MESSAGE, false); + let t0; + if ($[0] !== glimmerIndex) { + t0 = LOADING_MESSAGE.split("").map((char, index) => ); + $[0] = glimmerIndex; + $[1] = t0; + } else { + t0 = $[1]; + } + let t1; + if ($[2] !== t0) { + t1 = {t0}; + $[2] = t0; + $[3] = t1; + } else { + t1 = $[3]; + } + let t2; + if ($[4] !== ref || $[5] !== t1) { + t2 = {t1}; + $[4] = ref; + $[5] = t1; + $[6] = t2; + } else { + t2 = $[6]; + } + return t2; +} +function getRiskColor(riskLevel: RiskLevel): 'success' | 'warning' | 'error' { + switch (riskLevel) { + case 'LOW': + return 'success'; + case 'MEDIUM': + return 'warning'; + case 'HIGH': + return 'error'; + } +} +function getRiskLabel(riskLevel: RiskLevel): string { + switch (riskLevel) { + case 'LOW': + return 'Low risk'; + case 'MEDIUM': + return 'Med risk'; + case 'HIGH': + return 'High risk'; + } +} +type PermissionExplanationProps = { + toolName: string; + toolInput: unknown; + toolDescription?: string; + messages?: Message[]; +}; +type ExplainerState = { + visible: boolean; + enabled: boolean; + promise: Promise | null; +}; + +/** + * Creates an explanation promise that never rejects. + * Errors are caught and returned as null. + */ +function createExplanationPromise(props: PermissionExplanationProps): Promise { + return generatePermissionExplanation({ + toolName: props.toolName, + toolInput: props.toolInput, + toolDescription: props.toolDescription, + messages: props.messages, + signal: new AbortController().signal // Won't abort - request is fast enough + }).catch(() => null); +} + +/** + * Hook that manages the permission explainer state. + * Creates the fetch promise lazily (only when user hits Ctrl+E) + * to avoid consuming tokens for explanations users never view. + */ +export function usePermissionExplainerUI(props) { + const $ = _c(9); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = isPermissionExplainerEnabled(); + $[0] = t0; + } else { + t0 = $[0]; + } + const enabled = t0; + const [visible, setVisible] = useState(false); + const [promise, setPromise] = useState(null); + let t1; + if ($[1] !== promise || $[2] !== props || $[3] !== visible) { + t1 = () => { + if (!visible) { + logEvent("tengu_permission_explainer_shortcut_used", {}); + if (!promise) { + setPromise(createExplanationPromise(props)); + } + } + setVisible(_temp); + }; + $[1] = promise; + $[2] = props; + $[3] = visible; + $[4] = t1; + } else { + t1 = $[4]; + } + let t2; + if ($[5] === Symbol.for("react.memo_cache_sentinel")) { + t2 = { + context: "Confirmation", + isActive: enabled + }; + $[5] = t2; + } else { + t2 = $[5]; + } + useKeybinding("confirm:toggleExplanation", t1, t2); + let t3; + if ($[6] !== promise || $[7] !== visible) { + t3 = { + visible, + enabled, + promise + }; + $[6] = promise; + $[7] = visible; + $[8] = t3; + } else { + t3 = $[8]; + } + return t3; +} + +/** + * Inner component that uses React 19's use() to read the promise. + * Suspends while loading, returns null on error. + */ +function _temp(v) { + return !v; +} +function ExplanationResult(t0) { + const $ = _c(21); + const { + promise + } = t0; + const explanation = use(promise); + if (!explanation) { + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = Explanation unavailable; + $[0] = t1; + } else { + t1 = $[0]; + } + return t1; + } + let t1; + if ($[1] !== explanation.explanation) { + t1 = {explanation.explanation}; + $[1] = explanation.explanation; + $[2] = t1; + } else { + t1 = $[2]; + } + let t2; + if ($[3] !== explanation.reasoning) { + t2 = {explanation.reasoning}; + $[3] = explanation.reasoning; + $[4] = t2; + } else { + t2 = $[4]; + } + let t3; + if ($[5] !== explanation.riskLevel) { + t3 = getRiskColor(explanation.riskLevel); + $[5] = explanation.riskLevel; + $[6] = t3; + } else { + t3 = $[6]; + } + let t4; + if ($[7] !== explanation.riskLevel) { + t4 = getRiskLabel(explanation.riskLevel); + $[7] = explanation.riskLevel; + $[8] = t4; + } else { + t4 = $[8]; + } + let t5; + if ($[9] !== t3 || $[10] !== t4) { + t5 = {t4}:; + $[9] = t3; + $[10] = t4; + $[11] = t5; + } else { + t5 = $[11]; + } + let t6; + if ($[12] !== explanation.risk) { + t6 = {explanation.risk}; + $[12] = explanation.risk; + $[13] = t6; + } else { + t6 = $[13]; + } + let t7; + if ($[14] !== t5 || $[15] !== t6) { + t7 = {t5}{t6}; + $[14] = t5; + $[15] = t6; + $[16] = t7; + } else { + t7 = $[16]; + } + let t8; + if ($[17] !== t1 || $[18] !== t2 || $[19] !== t7) { + t8 = {t1}{t2}{t7}; + $[17] = t1; + $[18] = t2; + $[19] = t7; + $[20] = t8; + } else { + t8 = $[20]; + } + return t8; +} + +/** + * Content component - shows loading (via Suspense) or explanation when visible + */ +export function PermissionExplainerContent(t0) { + const $ = _c(3); + const { + visible, + promise + } = t0; + if (!visible || !promise) { + return null; + } + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = ; + $[0] = t1; + } else { + t1 = $[0]; + } + let t2; + if ($[1] !== promise) { + t2 = ; + $[1] = promise; + $[2] = t2; + } else { + t2 = $[2]; + } + return t2; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlN1c3BlbnNlIiwidXNlIiwidXNlU3RhdGUiLCJCb3giLCJUZXh0IiwidXNlS2V5YmluZGluZyIsImxvZ0V2ZW50IiwiTWVzc2FnZSIsImdlbmVyYXRlUGVybWlzc2lvbkV4cGxhbmF0aW9uIiwiaXNQZXJtaXNzaW9uRXhwbGFpbmVyRW5hYmxlZCIsIlBlcm1pc3Npb25FeHBsYW5hdGlvbiIsIlBlcm1pc3Npb25FeHBsYW5hdGlvblR5cGUiLCJSaXNrTGV2ZWwiLCJTaGltbWVyQ2hhciIsInVzZVNoaW1tZXJBbmltYXRpb24iLCJMT0FESU5HX01FU1NBR0UiLCJTaGltbWVyTG9hZGluZ1RleHQiLCIkIiwiX2MiLCJyZWYiLCJnbGltbWVySW5kZXgiLCJ0MCIsInNwbGl0IiwibWFwIiwiY2hhciIsImluZGV4IiwidDEiLCJ0MiIsImdldFJpc2tDb2xvciIsInJpc2tMZXZlbCIsImdldFJpc2tMYWJlbCIsIlBlcm1pc3Npb25FeHBsYW5hdGlvblByb3BzIiwidG9vbE5hbWUiLCJ0b29sSW5wdXQiLCJ0b29sRGVzY3JpcHRpb24iLCJtZXNzYWdlcyIsIkV4cGxhaW5lclN0YXRlIiwidmlzaWJsZSIsImVuYWJsZWQiLCJwcm9taXNlIiwiUHJvbWlzZSIsImNyZWF0ZUV4cGxhbmF0aW9uUHJvbWlzZSIsInByb3BzIiwic2lnbmFsIiwiQWJvcnRDb250cm9sbGVyIiwiY2F0Y2giLCJ1c2VQZXJtaXNzaW9uRXhwbGFpbmVyVUkiLCJTeW1ib2wiLCJmb3IiLCJzZXRWaXNpYmxlIiwic2V0UHJvbWlzZSIsIl90ZW1wIiwiY29udGV4dCIsImlzQWN0aXZlIiwidDMiLCJ2IiwiRXhwbGFuYXRpb25SZXN1bHQiLCJleHBsYW5hdGlvbiIsInJlYXNvbmluZyIsInQ0IiwidDUiLCJ0NiIsInJpc2siLCJ0NyIsInQ4IiwiUGVybWlzc2lvbkV4cGxhaW5lckNvbnRlbnQiXSwic291cmNlcyI6WyJQZXJtaXNzaW9uRXhwbGFuYXRpb24udHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwgeyBTdXNwZW5zZSwgdXNlLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQm94LCBUZXh0IH0gZnJvbSAnLi4vLi4vaW5rLmpzJ1xuaW1wb3J0IHsgdXNlS2V5YmluZGluZyB9IGZyb20gJy4uLy4uL2tleWJpbmRpbmdzL3VzZUtleWJpbmRpbmcuanMnXG5pbXBvcnQgeyBsb2dFdmVudCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB0eXBlIHsgTWVzc2FnZSB9IGZyb20gJy4uLy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQge1xuICBnZW5lcmF0ZVBlcm1pc3Npb25FeHBsYW5hdGlvbixcbiAgaXNQZXJtaXNzaW9uRXhwbGFpbmVyRW5hYmxlZCxcbiAgdHlwZSBQZXJtaXNzaW9uRXhwbGFuYXRpb24gYXMgUGVybWlzc2lvbkV4cGxhbmF0aW9uVHlwZSxcbiAgdHlwZSBSaXNrTGV2ZWwsXG59IGZyb20gJy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL3Blcm1pc3Npb25FeHBsYWluZXIuanMnXG5pbXBvcnQgeyBTaGltbWVyQ2hhciB9IGZyb20gJy4uL1NwaW5uZXIvU2hpbW1lckNoYXIuanMnXG5pbXBvcnQgeyB1c2VTaGltbWVyQW5pbWF0aW9uIH0gZnJvbSAnLi4vU3Bpbm5lci91c2VTaGltbWVyQW5pbWF0aW9uLmpzJ1xuXG5jb25zdCBMT0FESU5HX01FU1NBR0UgPSAnTG9hZGluZyBleHBsYW5hdGlvbuKApidcblxuZnVuY3Rpb24gU2hpbW1lckxvYWRpbmdUZXh0KCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IFtyZWYsIGdsaW1tZXJJbmRleF0gPSB1c2VTaGltbWVyQW5pbWF0aW9uKFxuICAgICdyZXNwb25kaW5nJyxcbiAgICBMT0FESU5HX01FU1NBR0UsXG4gICAgZmFsc2UsXG4gIClcblxuICByZXR1cm4gKFxuICAgIDxCb3ggcmVmPXtyZWZ9PlxuICAgICAgPFRleHQ+XG4gICAgICAgIHtMT0FESU5HX01FU1NBR0Uuc3BsaXQoJycpLm1hcCgoY2hhciwgaW5kZXgpID0+IChcbiAgICAgICAgICA8U2hpbW1lckNoYXJcbiAgICAgICAgICAgIGtleT17aW5kZXh9XG4gICAgICAgICAgICBjaGFyPXtjaGFyfVxuICAgICAgICAgICAgaW5kZXg9e2luZGV4fVxuICAgICAgICAgICAgZ2xpbW1lckluZGV4PXtnbGltbWVySW5kZXh9XG4gICAgICAgICAgICBtZXNzYWdlQ29sb3I9XCJpbmFjdGl2ZVwiXG4gICAgICAgICAgICBzaGltbWVyQ29sb3I9XCJ0ZXh0XCJcbiAgICAgICAgICAvPlxuICAgICAgICApKX1cbiAgICAgIDwvVGV4dD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG5mdW5jdGlvbiBnZXRSaXNrQ29sb3Iocmlza0xldmVsOiBSaXNrTGV2ZWwpOiAnc3VjY2VzcycgfCAnd2FybmluZycgfCAnZXJyb3InIHtcbiAgc3dpdGNoIChyaXNrTGV2ZWwpIHtcbiAgICBjYXNlICdMT1cnOlxuICAgICAgcmV0dXJuICdzdWNjZXNzJ1xuICAgIGNhc2UgJ01FRElVTSc6XG4gICAgICByZXR1cm4gJ3dhcm5pbmcnXG4gICAgY2FzZSAnSElHSCc6XG4gICAgICByZXR1cm4gJ2Vycm9yJ1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFJpc2tMYWJlbChyaXNrTGV2ZWw6IFJpc2tMZXZlbCk6IHN0cmluZyB7XG4gIHN3aXRjaCAocmlza0xldmVsKSB7XG4gICAgY2FzZSAnTE9XJzpcbiAgICAgIHJldHVybiAnTG93IHJpc2snXG4gICAgY2FzZSAnTUVESVVNJzpcbiAgICAgIHJldHVybiAnTWVkIHJpc2snXG4gICAgY2FzZSAnSElHSCc6XG4gICAgICByZXR1cm4gJ0hpZ2ggcmlzaydcbiAgfVxufVxuXG50eXBlIFBlcm1pc3Npb25FeHBsYW5hdGlvblByb3BzID0ge1xuICB0b29sTmFtZTogc3RyaW5nXG4gIHRvb2xJbnB1dDogdW5rbm93blxuICB0b29sRGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgbWVzc2FnZXM/OiBNZXNzYWdlW11cbn1cblxudHlwZSBFeHBsYWluZXJTdGF0ZSA9IHtcbiAgdmlzaWJsZTogYm9vbGVhblxuICBlbmFibGVkOiBib29sZWFuXG4gIHByb21pc2U6IFByb21pc2U8UGVybWlzc2lvbkV4cGxhbmF0aW9uVHlwZSB8IG51bGw+IHwgbnVsbFxufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gZXhwbGFuYXRpb24gcHJvbWlzZSB0aGF0IG5ldmVyIHJlamVjdHMuXG4gKiBFcnJvcnMgYXJlIGNhdWdodCBhbmQgcmV0dXJuZWQgYXMgbnVsbC5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlRXhwbGFuYXRpb25Qcm9taXNlKFxuICBwcm9wczogUGVybWlzc2lvbkV4cGxhbmF0aW9uUHJvcHMsXG4pOiBQcm9taXNlPFBlcm1pc3Npb25FeHBsYW5hdGlvblR5cGUgfCBudWxsPiB7XG4gIHJldHVybiBnZW5lcmF0ZVBlcm1pc3Npb25FeHBsYW5hdGlvbih7XG4gICAgdG9vbE5hbWU6IHByb3BzLnRvb2xOYW1lLFxuICAgIHRvb2xJbnB1dDogcHJvcHMudG9vbElucHV0LFxuICAgIHRvb2xEZXNjcmlwdGlvbjogcHJvcHMudG9vbERlc2NyaXB0aW9uLFxuICAgIG1lc3NhZ2VzOiBwcm9wcy5tZXNzYWdlcyxcbiAgICBzaWduYWw6IG5ldyBBYm9ydENvbnRyb2xsZXIoKS5zaWduYWwsIC8vIFdvbid0IGFib3J0IC0gcmVxdWVzdCBpcyBmYXN0IGVub3VnaFxuICB9KS5jYXRjaCgoKSA9PiBudWxsKVxufVxuXG4vKipcbiAqIEhvb2sgdGhhdCBtYW5hZ2VzIHRoZSBwZXJtaXNzaW9uIGV4cGxhaW5lciBzdGF0ZS5cbiAqIENyZWF0ZXMgdGhlIGZldGNoIHByb21pc2UgbGF6aWx5IChvbmx5IHdoZW4gdXNlciBoaXRzIEN0cmwrRSlcbiAqIHRvIGF2b2lkIGNvbnN1bWluZyB0b2tlbnMgZm9yIGV4cGxhbmF0aW9ucyB1c2VycyBuZXZlciB2aWV3LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlUGVybWlzc2lvbkV4cGxhaW5lclVJKFxuICBwcm9wczogUGVybWlzc2lvbkV4cGxhbmF0aW9uUHJvcHMsXG4pOiBFeHBsYWluZXJTdGF0ZSB7XG4gIGNvbnN0IGVuYWJsZWQgPSBpc1Blcm1pc3Npb25FeHBsYWluZXJFbmFibGVkKClcbiAgY29uc3QgW3Zpc2libGUsIHNldFZpc2libGVdID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFtwcm9taXNlLCBzZXRQcm9taXNlXSA9XG4gICAgdXNlU3RhdGU8UHJvbWlzZTxQZXJtaXNzaW9uRXhwbGFuYXRpb25UeXBlIHwgbnVsbD4gfCBudWxsPihudWxsKVxuXG4gIC8vIFVzZSBrZXliaW5kaW5nIGZvciBjdHJsK2UgdG9nZ2xlIChjb25maWd1cmFibGUgdmlhIGtleWJpbmRpbmdzLmpzb24pXG4gIHVzZUtleWJpbmRpbmcoXG4gICAgJ2NvbmZpcm06dG9nZ2xlRXhwbGFuYXRpb24nLFxuICAgICgpID0+IHtcbiAgICAgIGlmICghdmlzaWJsZSkge1xuICAgICAgICBsb2dFdmVudCgndGVuZ3VfcGVybWlzc2lvbl9leHBsYWluZXJfc2hvcnRjdXRfdXNlZCcsIHt9KVxuICAgICAgICAvLyBPbmx5IGNyZWF0ZSB0aGUgcHJvbWlzZSBvbiBmaXJzdCB0b2dnbGUgKGxhenkgbG9hZGluZylcbiAgICAgICAgaWYgKCFwcm9taXNlKSB7XG4gICAgICAgICAgc2V0UHJvbWlzZShjcmVhdGVFeHBsYW5hdGlvblByb21pc2UocHJvcHMpKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzZXRWaXNpYmxlKHYgPT4gIXYpXG4gICAgfSxcbiAgICB7IGNvbnRleHQ6ICdDb25maXJtYXRpb24nLCBpc0FjdGl2ZTogZW5hYmxlZCB9LFxuICApXG5cbiAgcmV0dXJuIHsgdmlzaWJsZSwgZW5hYmxlZCwgcHJvbWlzZSB9XG59XG5cbi8qKlxuICogSW5uZXIgY29tcG9uZW50IHRoYXQgdXNlcyBSZWFjdCAxOSdzIHVzZSgpIHRvIHJlYWQgdGhlIHByb21pc2UuXG4gKiBTdXNwZW5kcyB3aGlsZSBsb2FkaW5nLCByZXR1cm5zIG51bGwgb24gZXJyb3IuXG4gKi9cbmZ1bmN0aW9uIEV4cGxhbmF0aW9uUmVzdWx0KHtcbiAgcHJvbWlzZSxcbn06IHtcbiAgcHJvbWlzZTogUHJvbWlzZTxQZXJtaXNzaW9uRXhwbGFuYXRpb25UeXBlIHwgbnVsbD5cbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBleHBsYW5hdGlvbiA9IHVzZShwcm9taXNlKVxuXG4gIGlmICghZXhwbGFuYXRpb24pIHtcbiAgICByZXR1cm4gKFxuICAgICAgPEJveCBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICA8VGV4dCBkaW1Db2xvcj5FeHBsYW5hdGlvbiB1bmF2YWlsYWJsZTwvVGV4dD5cbiAgICAgIDwvQm94PlxuICAgIClcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgbWFyZ2luVG9wPXsxfT5cbiAgICAgIDxUZXh0PntleHBsYW5hdGlvbi5leHBsYW5hdGlvbn08L1RleHQ+XG4gICAgICA8Qm94IG1hcmdpblRvcD17MX0+XG4gICAgICAgIDxUZXh0PntleHBsYW5hdGlvbi5yZWFzb25pbmd9PC9UZXh0PlxuICAgICAgPC9Cb3g+XG4gICAgICA8Qm94IG1hcmdpblRvcD17MX0+XG4gICAgICAgIDxUZXh0PlxuICAgICAgICAgIDxUZXh0IGNvbG9yPXtnZXRSaXNrQ29sb3IoZXhwbGFuYXRpb24ucmlza0xldmVsKX0+XG4gICAgICAgICAgICB7Z2V0Umlza0xhYmVsKGV4cGxhbmF0aW9uLnJpc2tMZXZlbCl9OlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8VGV4dD4ge2V4cGxhbmF0aW9uLnJpc2t9PC9UZXh0PlxuICAgICAgICA8L1RleHQ+XG4gICAgICA8L0JveD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG4vKipcbiAqIENvbnRlbnQgY29tcG9uZW50IC0gc2hvd3MgbG9hZGluZyAodmlhIFN1c3BlbnNlKSBvciBleHBsYW5hdGlvbiB3aGVuIHZpc2libGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFBlcm1pc3Npb25FeHBsYWluZXJDb250ZW50KHtcbiAgdmlzaWJsZSxcbiAgcHJvbWlzZSxcbn06IHtcbiAgdmlzaWJsZTogYm9vbGVhblxuICBwcm9taXNlOiBQcm9taXNlPFBlcm1pc3Npb25FeHBsYW5hdGlvblR5cGUgfCBudWxsPiB8IG51bGxcbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBpZiAoIXZpc2libGUgfHwgIXByb21pc2UpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgcmV0dXJuIChcbiAgICA8U3VzcGVuc2VcbiAgICAgIGZhbGxiYWNrPXtcbiAgICAgICAgPEJveCBtYXJnaW5Ub3A9ezF9PlxuICAgICAgICAgIDxTaGltbWVyTG9hZGluZ1RleHQgLz5cbiAgICAgICAgPC9Cb3g+XG4gICAgICB9XG4gICAgPlxuICAgICAgPEV4cGxhbmF0aW9uUmVzdWx0IHByb21pc2U9e3Byb21pc2V9IC8+XG4gICAgPC9TdXNwZW5zZT5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUFJQyxRQUFRLEVBQUVDLEdBQUcsRUFBRUMsUUFBUSxRQUFRLE9BQU87QUFDdEQsU0FBU0MsR0FBRyxFQUFFQyxJQUFJLFFBQVEsY0FBYztBQUN4QyxTQUFTQyxhQUFhLFFBQVEsb0NBQW9DO0FBQ2xFLFNBQVNDLFFBQVEsUUFBUSxtQ0FBbUM7QUFDNUQsY0FBY0MsT0FBTyxRQUFRLHdCQUF3QjtBQUNyRCxTQUNFQyw2QkFBNkIsRUFDN0JDLDRCQUE0QixFQUM1QixLQUFLQyxxQkFBcUIsSUFBSUMseUJBQXlCLEVBQ3ZELEtBQUtDLFNBQVMsUUFDVCxnREFBZ0Q7QUFDdkQsU0FBU0MsV0FBVyxRQUFRLDJCQUEyQjtBQUN2RCxTQUFTQyxtQkFBbUIsUUFBUSxtQ0FBbUM7QUFFdkUsTUFBTUMsZUFBZSxHQUFHLHNCQUFzQjtBQUU5QyxTQUFBQyxtQkFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUNFLE9BQUFDLEdBQUEsRUFBQUMsWUFBQSxJQUE0Qk4sbUJBQW1CLENBQzdDLFlBQVksRUFDWkMsZUFBZSxFQUNmLEtBQ0YsQ0FBQztFQUFBLElBQUFNLEVBQUE7RUFBQSxJQUFBSixDQUFBLFFBQUFHLFlBQUE7SUFLTUMsRUFBQSxHQUFBTixlQUFlLENBQUFPLEtBQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQUMsR0FBSSxDQUFDLENBQUFDLElBQUEsRUFBQUMsS0FBQSxLQUM3QixDQUFDLFdBQVcsQ0FDTEEsR0FBSyxDQUFMQSxNQUFJLENBQUMsQ0FDSkQsSUFBSSxDQUFKQSxLQUFHLENBQUMsQ0FDSEMsS0FBSyxDQUFMQSxNQUFJLENBQUMsQ0FDRUwsWUFBWSxDQUFaQSxhQUFXLENBQUMsQ0FDYixZQUFVLENBQVYsVUFBVSxDQUNWLFlBQU0sQ0FBTixNQUFNLEdBRXRCLENBQUM7SUFBQUgsQ0FBQSxNQUFBRyxZQUFBO0lBQUFILENBQUEsTUFBQUksRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUosQ0FBQTtFQUFBO0VBQUEsSUFBQVMsRUFBQTtFQUFBLElBQUFULENBQUEsUUFBQUksRUFBQTtJQVZKSyxFQUFBLElBQUMsSUFBSSxDQUNGLENBQUFMLEVBU0EsQ0FDSCxFQVhDLElBQUksQ0FXRTtJQUFBSixDQUFBLE1BQUFJLEVBQUE7SUFBQUosQ0FBQSxNQUFBUyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBVCxDQUFBO0VBQUE7RUFBQSxJQUFBVSxFQUFBO0VBQUEsSUFBQVYsQ0FBQSxRQUFBRSxHQUFBLElBQUFGLENBQUEsUUFBQVMsRUFBQTtJQVpUQyxFQUFBLElBQUMsR0FBRyxDQUFNUixHQUFHLENBQUhBLElBQUUsQ0FBQyxDQUNYLENBQUFPLEVBV00sQ0FDUixFQWJDLEdBQUcsQ0FhRTtJQUFBVCxDQUFBLE1BQUFFLEdBQUE7SUFBQUYsQ0FBQSxNQUFBUyxFQUFBO0lBQUFULENBQUEsTUFBQVUsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVYsQ0FBQTtFQUFBO0VBQUEsT0FiTlUsRUFhTTtBQUFBO0FBSVYsU0FBU0MsWUFBWUEsQ0FBQ0MsU0FBUyxFQUFFakIsU0FBUyxDQUFDLEVBQUUsU0FBUyxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUM7RUFDM0UsUUFBUWlCLFNBQVM7SUFDZixLQUFLLEtBQUs7TUFDUixPQUFPLFNBQVM7SUFDbEIsS0FBSyxRQUFRO01BQ1gsT0FBTyxTQUFTO0lBQ2xCLEtBQUssTUFBTTtNQUNULE9BQU8sT0FBTztFQUNsQjtBQUNGO0FBRUEsU0FBU0MsWUFBWUEsQ0FBQ0QsU0FBUyxFQUFFakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxDQUFDO0VBQ2xELFFBQVFpQixTQUFTO0lBQ2YsS0FBSyxLQUFLO01BQ1IsT0FBTyxVQUFVO0lBQ25CLEtBQUssUUFBUTtNQUNYLE9BQU8sVUFBVTtJQUNuQixLQUFLLE1BQU07TUFDVCxPQUFPLFdBQVc7RUFDdEI7QUFDRjtBQUVBLEtBQUtFLDBCQUEwQixHQUFHO0VBQ2hDQyxRQUFRLEVBQUUsTUFBTTtFQUNoQkMsU0FBUyxFQUFFLE9BQU87RUFDbEJDLGVBQWUsQ0FBQyxFQUFFLE1BQU07RUFDeEJDLFFBQVEsQ0FBQyxFQUFFNUIsT0FBTyxFQUFFO0FBQ3RCLENBQUM7QUFFRCxLQUFLNkIsY0FBYyxHQUFHO0VBQ3BCQyxPQUFPLEVBQUUsT0FBTztFQUNoQkMsT0FBTyxFQUFFLE9BQU87RUFDaEJDLE9BQU8sRUFBRUMsT0FBTyxDQUFDN0IseUJBQXlCLEdBQUcsSUFBSSxDQUFDLEdBQUcsSUFBSTtBQUMzRCxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzhCLHdCQUF3QkEsQ0FDL0JDLEtBQUssRUFBRVgsMEJBQTBCLENBQ2xDLEVBQUVTLE9BQU8sQ0FBQzdCLHlCQUF5QixHQUFHLElBQUksQ0FBQyxDQUFDO0VBQzNDLE9BQU9ILDZCQUE2QixDQUFDO0lBQ25Dd0IsUUFBUSxFQUFFVSxLQUFLLENBQUNWLFFBQVE7SUFDeEJDLFNBQVMsRUFBRVMsS0FBSyxDQUFDVCxTQUFTO0lBQzFCQyxlQUFlLEVBQUVRLEtBQUssQ0FBQ1IsZUFBZTtJQUN0Q0MsUUFBUSxFQUFFTyxLQUFLLENBQUNQLFFBQVE7SUFDeEJRLE1BQU0sRUFBRSxJQUFJQyxlQUFlLENBQUMsQ0FBQyxDQUFDRCxNQUFNLENBQUU7RUFDeEMsQ0FBQyxDQUFDLENBQUNFLEtBQUssQ0FBQyxNQUFNLElBQUksQ0FBQztBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxTQUFBQyx5QkFBQUosS0FBQTtFQUFBLE1BQUF6QixDQUFBLEdBQUFDLEVBQUE7RUFBQSxJQUFBRyxFQUFBO0VBQUEsSUFBQUosQ0FBQSxRQUFBOEIsTUFBQSxDQUFBQyxHQUFBO0lBR1czQixFQUFBLEdBQUFaLDRCQUE0QixDQUFDLENBQUM7SUFBQVEsQ0FBQSxNQUFBSSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBSixDQUFBO0VBQUE7RUFBOUMsTUFBQXFCLE9BQUEsR0FBZ0JqQixFQUE4QjtFQUM5QyxPQUFBZ0IsT0FBQSxFQUFBWSxVQUFBLElBQThCL0MsUUFBUSxDQUFDLEtBQUssQ0FBQztFQUM3QyxPQUFBcUMsT0FBQSxFQUFBVyxVQUFBLElBQ0VoRCxRQUFRLENBQW1ELElBQUksQ0FBQztFQUFBLElBQUF3QixFQUFBO0VBQUEsSUFBQVQsQ0FBQSxRQUFBc0IsT0FBQSxJQUFBdEIsQ0FBQSxRQUFBeUIsS0FBQSxJQUFBekIsQ0FBQSxRQUFBb0IsT0FBQTtJQUtoRVgsRUFBQSxHQUFBQSxDQUFBO01BQ0UsSUFBSSxDQUFDVyxPQUFPO1FBQ1YvQixRQUFRLENBQUMsMENBQTBDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFeEQsSUFBSSxDQUFDaUMsT0FBTztVQUNWVyxVQUFVLENBQUNULHdCQUF3QixDQUFDQyxLQUFLLENBQUMsQ0FBQztRQUFBO01BQzVDO01BRUhPLFVBQVUsQ0FBQ0UsS0FBTyxDQUFDO0lBQUEsQ0FDcEI7SUFBQWxDLENBQUEsTUFBQXNCLE9BQUE7SUFBQXRCLENBQUEsTUFBQXlCLEtBQUE7SUFBQXpCLENBQUEsTUFBQW9CLE9BQUE7SUFBQXBCLENBQUEsTUFBQVMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVQsQ0FBQTtFQUFBO0VBQUEsSUFBQVUsRUFBQTtFQUFBLElBQUFWLENBQUEsUUFBQThCLE1BQUEsQ0FBQUMsR0FBQTtJQUNEckIsRUFBQTtNQUFBeUIsT0FBQSxFQUFXLGNBQWM7TUFBQUMsUUFBQSxFQUFZZjtJQUFRLENBQUM7SUFBQXJCLENBQUEsTUFBQVUsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVYsQ0FBQTtFQUFBO0VBWmhEWixhQUFhLENBQ1gsMkJBQTJCLEVBQzNCcUIsRUFTQyxFQUNEQyxFQUNGLENBQUM7RUFBQSxJQUFBMkIsRUFBQTtFQUFBLElBQUFyQyxDQUFBLFFBQUFzQixPQUFBLElBQUF0QixDQUFBLFFBQUFvQixPQUFBO0lBRU1pQixFQUFBO01BQUFqQixPQUFBO01BQUFDLE9BQUE7TUFBQUM7SUFBNEIsQ0FBQztJQUFBdEIsQ0FBQSxNQUFBc0IsT0FBQTtJQUFBdEIsQ0FBQSxNQUFBb0IsT0FBQTtJQUFBcEIsQ0FBQSxNQUFBcUMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQXJDLENBQUE7RUFBQTtFQUFBLE9BQTdCcUMsRUFBNkI7QUFBQTs7QUFHdEM7QUFDQTtBQUNBO0FBQ0E7QUE5Qk8sU0FBQUgsTUFBQUksQ0FBQTtFQUFBLE9BbUJlLENBQUNBLENBQUM7QUFBQTtBQVl4QixTQUFBQyxrQkFBQW5DLEVBQUE7RUFBQSxNQUFBSixDQUFBLEdBQUFDLEVBQUE7RUFBMkI7SUFBQXFCO0VBQUEsSUFBQWxCLEVBSTFCO0VBQ0MsTUFBQW9DLFdBQUEsR0FBb0J4RCxHQUFHLENBQUNzQyxPQUFPLENBQUM7RUFFaEMsSUFBSSxDQUFDa0IsV0FBVztJQUFBLElBQUEvQixFQUFBO0lBQUEsSUFBQVQsQ0FBQSxRQUFBOEIsTUFBQSxDQUFBQyxHQUFBO01BRVp0QixFQUFBLElBQUMsR0FBRyxDQUFZLFNBQUMsQ0FBRCxHQUFDLENBQ2YsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFSLEtBQU8sQ0FBQyxDQUFDLHVCQUF1QixFQUFyQyxJQUFJLENBQ1AsRUFGQyxHQUFHLENBRUU7TUFBQVQsQ0FBQSxNQUFBUyxFQUFBO0lBQUE7TUFBQUEsRUFBQSxHQUFBVCxDQUFBO0lBQUE7SUFBQSxPQUZOUyxFQUVNO0VBQUE7RUFFVCxJQUFBQSxFQUFBO0VBQUEsSUFBQVQsQ0FBQSxRQUFBd0MsV0FBQSxDQUFBQSxXQUFBO0lBSUcvQixFQUFBLElBQUMsSUFBSSxDQUFFLENBQUErQixXQUFXLENBQUFBLFdBQVcsQ0FBRSxFQUE5QixJQUFJLENBQWlDO0lBQUF4QyxDQUFBLE1BQUF3QyxXQUFBLENBQUFBLFdBQUE7SUFBQXhDLENBQUEsTUFBQVMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVQsQ0FBQTtFQUFBO0VBQUEsSUFBQVUsRUFBQTtFQUFBLElBQUFWLENBQUEsUUFBQXdDLFdBQUEsQ0FBQUMsU0FBQTtJQUN0Qy9CLEVBQUEsSUFBQyxHQUFHLENBQVksU0FBQyxDQUFELEdBQUMsQ0FDZixDQUFDLElBQUksQ0FBRSxDQUFBOEIsV0FBVyxDQUFBQyxTQUFTLENBQUUsRUFBNUIsSUFBSSxDQUNQLEVBRkMsR0FBRyxDQUVFO0lBQUF6QyxDQUFBLE1BQUF3QyxXQUFBLENBQUFDLFNBQUE7SUFBQXpDLENBQUEsTUFBQVUsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVYsQ0FBQTtFQUFBO0VBQUEsSUFBQXFDLEVBQUE7RUFBQSxJQUFBckMsQ0FBQSxRQUFBd0MsV0FBQSxDQUFBNUIsU0FBQTtJQUdXeUIsRUFBQSxHQUFBMUIsWUFBWSxDQUFDNkIsV0FBVyxDQUFBNUIsU0FBVSxDQUFDO0lBQUFaLENBQUEsTUFBQXdDLFdBQUEsQ0FBQTVCLFNBQUE7SUFBQVosQ0FBQSxNQUFBcUMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQXJDLENBQUE7RUFBQTtFQUFBLElBQUEwQyxFQUFBO0VBQUEsSUFBQTFDLENBQUEsUUFBQXdDLFdBQUEsQ0FBQTVCLFNBQUE7SUFDN0M4QixFQUFBLEdBQUE3QixZQUFZLENBQUMyQixXQUFXLENBQUE1QixTQUFVLENBQUM7SUFBQVosQ0FBQSxNQUFBd0MsV0FBQSxDQUFBNUIsU0FBQTtJQUFBWixDQUFBLE1BQUEwQyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBMUMsQ0FBQTtFQUFBO0VBQUEsSUFBQTJDLEVBQUE7RUFBQSxJQUFBM0MsQ0FBQSxRQUFBcUMsRUFBQSxJQUFBckMsQ0FBQSxTQUFBMEMsRUFBQTtJQUR0Q0MsRUFBQSxJQUFDLElBQUksQ0FBUSxLQUFtQyxDQUFuQyxDQUFBTixFQUFrQyxDQUFDLENBQzdDLENBQUFLLEVBQWtDLENBQUUsQ0FDdkMsRUFGQyxJQUFJLENBRUU7SUFBQTFDLENBQUEsTUFBQXFDLEVBQUE7SUFBQXJDLENBQUEsT0FBQTBDLEVBQUE7SUFBQTFDLENBQUEsT0FBQTJDLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUEzQyxDQUFBO0VBQUE7RUFBQSxJQUFBNEMsRUFBQTtFQUFBLElBQUE1QyxDQUFBLFNBQUF3QyxXQUFBLENBQUFLLElBQUE7SUFDUEQsRUFBQSxJQUFDLElBQUksQ0FBQyxDQUFFLENBQUFKLFdBQVcsQ0FBQUssSUFBSSxDQUFFLEVBQXhCLElBQUksQ0FBMkI7SUFBQTdDLENBQUEsT0FBQXdDLFdBQUEsQ0FBQUssSUFBQTtJQUFBN0MsQ0FBQSxPQUFBNEMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQTVDLENBQUE7RUFBQTtFQUFBLElBQUE4QyxFQUFBO0VBQUEsSUFBQTlDLENBQUEsU0FBQTJDLEVBQUEsSUFBQTNDLENBQUEsU0FBQTRDLEVBQUE7SUFMcENFLEVBQUEsSUFBQyxHQUFHLENBQVksU0FBQyxDQUFELEdBQUMsQ0FDZixDQUFDLElBQUksQ0FDSCxDQUFBSCxFQUVNLENBQ04sQ0FBQUMsRUFBK0IsQ0FDakMsRUFMQyxJQUFJLENBTVAsRUFQQyxHQUFHLENBT0U7SUFBQTVDLENBQUEsT0FBQTJDLEVBQUE7SUFBQTNDLENBQUEsT0FBQTRDLEVBQUE7SUFBQTVDLENBQUEsT0FBQThDLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUE5QyxDQUFBO0VBQUE7RUFBQSxJQUFBK0MsRUFBQTtFQUFBLElBQUEvQyxDQUFBLFNBQUFTLEVBQUEsSUFBQVQsQ0FBQSxTQUFBVSxFQUFBLElBQUFWLENBQUEsU0FBQThDLEVBQUE7SUFaUkMsRUFBQSxJQUFDLEdBQUcsQ0FBZSxhQUFRLENBQVIsUUFBUSxDQUFZLFNBQUMsQ0FBRCxHQUFDLENBQ3RDLENBQUF0QyxFQUFxQyxDQUNyQyxDQUFBQyxFQUVLLENBQ0wsQ0FBQW9DLEVBT0ssQ0FDUCxFQWJDLEdBQUcsQ0FhRTtJQUFBOUMsQ0FBQSxPQUFBUyxFQUFBO0lBQUFULENBQUEsT0FBQVUsRUFBQTtJQUFBVixDQUFBLE9BQUE4QyxFQUFBO0lBQUE5QyxDQUFBLE9BQUErQyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBL0MsQ0FBQTtFQUFBO0VBQUEsT0FiTitDLEVBYU07QUFBQTs7QUFJVjtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQUFDLDJCQUFBNUMsRUFBQTtFQUFBLE1BQUFKLENBQUEsR0FBQUMsRUFBQTtFQUFvQztJQUFBbUIsT0FBQTtJQUFBRTtFQUFBLElBQUFsQixFQU0xQztFQUNDLElBQUksQ0FBQ2dCLE9BQW1CLElBQXBCLENBQWFFLE9BQU87SUFBQSxPQUNmLElBQUk7RUFBQTtFQUNaLElBQUFiLEVBQUE7RUFBQSxJQUFBVCxDQUFBLFFBQUE4QixNQUFBLENBQUFDLEdBQUE7SUFLS3RCLEVBQUEsSUFBQyxHQUFHLENBQVksU0FBQyxDQUFELEdBQUMsQ0FDZixDQUFDLGtCQUFrQixHQUNyQixFQUZDLEdBQUcsQ0FFRTtJQUFBVCxDQUFBLE1BQUFTLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFULENBQUE7RUFBQTtFQUFBLElBQUFVLEVBQUE7RUFBQSxJQUFBVixDQUFBLFFBQUFzQixPQUFBO0lBSlZaLEVBQUEsSUFBQyxRQUFRLENBRUwsUUFFTSxDQUZOLENBQUFELEVBRUssQ0FBQyxDQUdSLENBQUMsaUJBQWlCLENBQVVhLE9BQU8sQ0FBUEEsUUFBTSxDQUFDLEdBQ3JDLEVBUkMsUUFBUSxDQVFFO0lBQUF0QixDQUFBLE1BQUFzQixPQUFBO0lBQUF0QixDQUFBLE1BQUFVLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFWLENBQUE7RUFBQTtFQUFBLE9BUlhVLEVBUVc7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/permissions/rules/PermissionRuleInput.tsx b/_all-in-one-upload/cc-haha/src/components/permissions/rules/PermissionRuleInput.tsx new file mode 100644 index 0000000..13b7b0b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/permissions/rules/PermissionRuleInput.tsx @@ -0,0 +1,138 @@ +import { c as _c } from "react/compiler-runtime"; +import figures from 'figures'; +import * as React from 'react'; +import { useState } from 'react'; +import TextInput from '../../../components/TextInput.js'; +import { useExitOnCtrlCDWithKeybindings } from '../../../hooks/useExitOnCtrlCDWithKeybindings.js'; +import { useTerminalSize } from '../../../hooks/useTerminalSize.js'; +import { Box, Newline, Text } from '../../../ink.js'; +import { useKeybinding } from '../../../keybindings/useKeybinding.js'; +import { BashTool } from '../../../tools/BashTool/BashTool.js'; +import { WebFetchTool } from '../../../tools/WebFetchTool/WebFetchTool.js'; +import type { PermissionBehavior, PermissionRuleValue } from '../../../utils/permissions/PermissionRule.js'; +import { permissionRuleValueFromString, permissionRuleValueToString } from '../../../utils/permissions/permissionRuleParser.js'; +export type PermissionRuleInputProps = { + onCancel: () => void; + onSubmit: (ruleValue: PermissionRuleValue, ruleBehavior: PermissionBehavior) => void; + ruleBehavior: PermissionBehavior; +}; +export function PermissionRuleInput(t0) { + const $ = _c(24); + const { + onCancel, + onSubmit, + ruleBehavior + } = t0; + const [inputValue, setInputValue] = useState(""); + const [cursorOffset, setCursorOffset] = useState(0); + const exitState = useExitOnCtrlCDWithKeybindings(); + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = { + context: "Settings" + }; + $[0] = t1; + } else { + t1 = $[0]; + } + useKeybinding("confirm:no", onCancel, t1); + const { + columns + } = useTerminalSize(); + const textInputColumns = columns - 6; + let t2; + if ($[1] !== onSubmit || $[2] !== ruleBehavior) { + t2 = value => { + const trimmedValue = value.trim(); + if (trimmedValue.length === 0) { + return; + } + const ruleValue = permissionRuleValueFromString(trimmedValue); + onSubmit(ruleValue, ruleBehavior); + }; + $[1] = onSubmit; + $[2] = ruleBehavior; + $[3] = t2; + } else { + t2 = $[3]; + } + const handleSubmit = t2; + let t3; + if ($[4] !== ruleBehavior) { + t3 = Add {ruleBehavior} permission rule; + $[4] = ruleBehavior; + $[5] = t3; + } else { + t3 = $[5]; + } + let t4; + if ($[6] === Symbol.for("react.memo_cache_sentinel")) { + t4 = ; + $[6] = t4; + } else { + t4 = $[6]; + } + let t5; + let t6; + if ($[7] === Symbol.for("react.memo_cache_sentinel")) { + t5 = {permissionRuleValueToString({ + toolName: WebFetchTool.name + })}; + t6 = or ; + $[7] = t5; + $[8] = t6; + } else { + t5 = $[7]; + t6 = $[8]; + } + let t7; + if ($[9] === Symbol.for("react.memo_cache_sentinel")) { + t7 = Permission rules are a tool name, optionally followed by a specifier in parentheses.{t4}e.g.,{" "}{t5}{t6}{permissionRuleValueToString({ + toolName: BashTool.name, + ruleContent: "ls:*" + })}; + $[9] = t7; + } else { + t7 = $[9]; + } + let t8; + if ($[10] !== cursorOffset || $[11] !== handleSubmit || $[12] !== inputValue || $[13] !== textInputColumns) { + t8 = {t7}; + $[10] = cursorOffset; + $[11] = handleSubmit; + $[12] = inputValue; + $[13] = textInputColumns; + $[14] = t8; + } else { + t8 = $[14]; + } + let t9; + if ($[15] !== t3 || $[16] !== t8) { + t9 = {t3}{t8}; + $[15] = t3; + $[16] = t8; + $[17] = t9; + } else { + t9 = $[17]; + } + let t10; + if ($[18] !== exitState.keyName || $[19] !== exitState.pending) { + t10 = {exitState.pending ? Press {exitState.keyName} again to exit : Enter to submit · Esc to cancel}; + $[18] = exitState.keyName; + $[19] = exitState.pending; + $[20] = t10; + } else { + t10 = $[20]; + } + let t11; + if ($[21] !== t10 || $[22] !== t9) { + t11 = <>{t9}{t10}; + $[21] = t10; + $[22] = t9; + $[23] = t11; + } else { + t11 = $[23]; + } + return t11; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmaWd1cmVzIiwiUmVhY3QiLCJ1c2VTdGF0ZSIsIlRleHRJbnB1dCIsInVzZUV4aXRPbkN0cmxDRFdpdGhLZXliaW5kaW5ncyIsInVzZVRlcm1pbmFsU2l6ZSIsIkJveCIsIk5ld2xpbmUiLCJUZXh0IiwidXNlS2V5YmluZGluZyIsIkJhc2hUb29sIiwiV2ViRmV0Y2hUb29sIiwiUGVybWlzc2lvbkJlaGF2aW9yIiwiUGVybWlzc2lvblJ1bGVWYWx1ZSIsInBlcm1pc3Npb25SdWxlVmFsdWVGcm9tU3RyaW5nIiwicGVybWlzc2lvblJ1bGVWYWx1ZVRvU3RyaW5nIiwiUGVybWlzc2lvblJ1bGVJbnB1dFByb3BzIiwib25DYW5jZWwiLCJvblN1Ym1pdCIsInJ1bGVWYWx1ZSIsInJ1bGVCZWhhdmlvciIsIlBlcm1pc3Npb25SdWxlSW5wdXQiLCJ0MCIsIiQiLCJfYyIsImlucHV0VmFsdWUiLCJzZXRJbnB1dFZhbHVlIiwiY3Vyc29yT2Zmc2V0Iiwic2V0Q3Vyc29yT2Zmc2V0IiwiZXhpdFN0YXRlIiwidDEiLCJTeW1ib2wiLCJmb3IiLCJjb250ZXh0IiwiY29sdW1ucyIsInRleHRJbnB1dENvbHVtbnMiLCJ0MiIsInZhbHVlIiwidHJpbW1lZFZhbHVlIiwidHJpbSIsImxlbmd0aCIsImhhbmRsZVN1Ym1pdCIsInQzIiwidDQiLCJ0NSIsInQ2IiwidG9vbE5hbWUiLCJuYW1lIiwidDciLCJydWxlQ29udGVudCIsInQ4IiwiZWxsaXBzaXMiLCJ0OSIsInQxMCIsImtleU5hbWUiLCJwZW5kaW5nIiwidDExIl0sInNvdXJjZXMiOlsiUGVybWlzc2lvblJ1bGVJbnB1dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZpZ3VyZXMgZnJvbSAnZmlndXJlcydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBUZXh0SW5wdXQgZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy9UZXh0SW5wdXQuanMnXG5pbXBvcnQgeyB1c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MgfSBmcm9tICcuLi8uLi8uLi9ob29rcy91c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MuanMnXG5pbXBvcnQgeyB1c2VUZXJtaW5hbFNpemUgfSBmcm9tICcuLi8uLi8uLi9ob29rcy91c2VUZXJtaW5hbFNpemUuanMnXG5pbXBvcnQgeyBCb3gsIE5ld2xpbmUsIFRleHQgfSBmcm9tICcuLi8uLi8uLi9pbmsuanMnXG5pbXBvcnQgeyB1c2VLZXliaW5kaW5nIH0gZnJvbSAnLi4vLi4vLi4va2V5YmluZGluZ3MvdXNlS2V5YmluZGluZy5qcydcbmltcG9ydCB7IEJhc2hUb29sIH0gZnJvbSAnLi4vLi4vLi4vdG9vbHMvQmFzaFRvb2wvQmFzaFRvb2wuanMnXG5pbXBvcnQgeyBXZWJGZXRjaFRvb2wgfSBmcm9tICcuLi8uLi8uLi90b29scy9XZWJGZXRjaFRvb2wvV2ViRmV0Y2hUb29sLmpzJ1xuaW1wb3J0IHR5cGUge1xuICBQZXJtaXNzaW9uQmVoYXZpb3IsXG4gIFBlcm1pc3Npb25SdWxlVmFsdWUsXG59IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25SdWxlLmpzJ1xuaW1wb3J0IHtcbiAgcGVybWlzc2lvblJ1bGVWYWx1ZUZyb21TdHJpbmcsXG4gIHBlcm1pc3Npb25SdWxlVmFsdWVUb1N0cmluZyxcbn0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvcGVybWlzc2lvbnMvcGVybWlzc2lvblJ1bGVQYXJzZXIuanMnXG5cbmV4cG9ydCB0eXBlIFBlcm1pc3Npb25SdWxlSW5wdXRQcm9wcyA9IHtcbiAgb25DYW5jZWw6ICgpID0+IHZvaWRcbiAgb25TdWJtaXQ6IChcbiAgICBydWxlVmFsdWU6IFBlcm1pc3Npb25SdWxlVmFsdWUsXG4gICAgcnVsZUJlaGF2aW9yOiBQZXJtaXNzaW9uQmVoYXZpb3IsXG4gICkgPT4gdm9pZFxuICBydWxlQmVoYXZpb3I6IFBlcm1pc3Npb25CZWhhdmlvclxufVxuXG5leHBvcnQgZnVuY3Rpb24gUGVybWlzc2lvblJ1bGVJbnB1dCh7XG4gIG9uQ2FuY2VsLFxuICBvblN1Ym1pdCxcbiAgcnVsZUJlaGF2aW9yLFxufTogUGVybWlzc2lvblJ1bGVJbnB1dFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3QgW2lucHV0VmFsdWUsIHNldElucHV0VmFsdWVdID0gdXNlU3RhdGUoJycpXG4gIGNvbnN0IFtjdXJzb3JPZmZzZXQsIHNldEN1cnNvck9mZnNldF0gPSB1c2VTdGF0ZSgwKVxuICBjb25zdCBleGl0U3RhdGUgPSB1c2VFeGl0T25DdHJsQ0RXaXRoS2V5YmluZGluZ3MoKVxuXG4gIC8vIFVzZSBjb25maWd1cmFibGUga2V5YmluZGluZyBmb3IgRVNDIHRvIGNhbmNlbFxuICAvLyBVc2UgU2V0dGluZ3MgY29udGV4dCBzbyAnbicga2V5IGRvZXNuJ3QgY2FuY2VsIChhbGxvd3MgdHlwaW5nICduJyBpbiBpbnB1dClcbiAgdXNlS2V5YmluZGluZygnY29uZmlybTpubycsIG9uQ2FuY2VsLCB7IGNvbnRleHQ6ICdTZXR0aW5ncycgfSlcblxuICBjb25zdCB7IGNvbHVtbnMgfSA9IHVzZVRlcm1pbmFsU2l6ZSgpXG4gIGNvbnN0IHRleHRJbnB1dENvbHVtbnMgPSBjb2x1bW5zIC0gNlxuXG4gIGNvbnN0IGhhbmRsZVN1Ym1pdCA9ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgdHJpbW1lZFZhbHVlID0gdmFsdWUudHJpbSgpXG4gICAgaWYgKHRyaW1tZWRWYWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBjb25zdCBydWxlVmFsdWUgPSBwZXJtaXNzaW9uUnVsZVZhbHVlRnJvbVN0cmluZyh0cmltbWVkVmFsdWUpXG4gICAgb25TdWJtaXQocnVsZVZhbHVlLCBydWxlQmVoYXZpb3IpXG4gIH1cblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8Qm94XG4gICAgICAgIGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIlxuICAgICAgICBnYXA9ezF9XG4gICAgICAgIGJvcmRlclN0eWxlPVwicm91bmRcIlxuICAgICAgICBwYWRkaW5nTGVmdD17MX1cbiAgICAgICAgcGFkZGluZ1JpZ2h0PXsxfVxuICAgICAgICBib3JkZXJDb2xvcj1cInBlcm1pc3Npb25cIlxuICAgICAgPlxuICAgICAgICA8VGV4dCBib2xkIGNvbG9yPVwicGVybWlzc2lvblwiPlxuICAgICAgICAgIEFkZCB7cnVsZUJlaGF2aW9yfSBwZXJtaXNzaW9uIHJ1bGVcbiAgICAgICAgPC9UZXh0PlxuICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICA8VGV4dD5cbiAgICAgICAgICAgIFBlcm1pc3Npb24gcnVsZXMgYXJlIGEgdG9vbCBuYW1lLCBvcHRpb25hbGx5IGZvbGxvd2VkIGJ5IGEgc3BlY2lmaWVyXG4gICAgICAgICAgICBpbiBwYXJlbnRoZXNlcy5cbiAgICAgICAgICAgIDxOZXdsaW5lIC8+XG4gICAgICAgICAgICBlLmcuLHsnICd9XG4gICAgICAgICAgICA8VGV4dCBib2xkPlxuICAgICAgICAgICAgICB7cGVybWlzc2lvblJ1bGVWYWx1ZVRvU3RyaW5nKHsgdG9vbE5hbWU6IFdlYkZldGNoVG9vbC5uYW1lIH0pfVxuICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgPFRleHQgYm9sZD17ZmFsc2V9PiBvciA8L1RleHQ+XG4gICAgICAgICAgICA8VGV4dCBib2xkPlxuICAgICAgICAgICAgICB7cGVybWlzc2lvblJ1bGVWYWx1ZVRvU3RyaW5nKHtcbiAgICAgICAgICAgICAgICB0b29sTmFtZTogQmFzaFRvb2wubmFtZSxcbiAgICAgICAgICAgICAgICBydWxlQ29udGVudDogJ2xzOionLFxuICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgPEJveCBib3JkZXJEaW1Db2xvciBib3JkZXJTdHlsZT1cInJvdW5kXCIgbWFyZ2luWT17MX0gcGFkZGluZ0xlZnQ9ezF9PlxuICAgICAgICAgICAgPFRleHRJbnB1dFxuICAgICAgICAgICAgICBzaG93Q3Vyc29yXG4gICAgICAgICAgICAgIHZhbHVlPXtpbnB1dFZhbHVlfVxuICAgICAgICAgICAgICBvbkNoYW5nZT17c2V0SW5wdXRWYWx1ZX1cbiAgICAgICAgICAgICAgb25TdWJtaXQ9e2hhbmRsZVN1Ym1pdH1cbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9e2BFbnRlciBwZXJtaXNzaW9uIHJ1bGUke2ZpZ3VyZXMuZWxsaXBzaXN9YH1cbiAgICAgICAgICAgICAgY29sdW1ucz17dGV4dElucHV0Q29sdW1uc31cbiAgICAgICAgICAgICAgY3Vyc29yT2Zmc2V0PXtjdXJzb3JPZmZzZXR9XG4gICAgICAgICAgICAgIG9uQ2hhbmdlQ3Vyc29yT2Zmc2V0PXtzZXRDdXJzb3JPZmZzZXR9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvQm94PlxuICAgICAgICA8L0JveD5cbiAgICAgIDwvQm94PlxuICAgICAgPEJveCBtYXJnaW5MZWZ0PXszfT5cbiAgICAgICAge2V4aXRTdGF0ZS5wZW5kaW5nID8gKFxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlByZXNzIHtleGl0U3RhdGUua2V5TmFtZX0gYWdhaW4gdG8gZXhpdDwvVGV4dD5cbiAgICAgICAgKSA6IChcbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5FbnRlciB0byBzdWJtaXQgwrcgRXNjIHRvIGNhbmNlbDwvVGV4dD5cbiAgICAgICAgKX1cbiAgICAgIDwvQm94PlxuICAgIDwvPlxuICApXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPQSxPQUFPLE1BQU0sU0FBUztBQUM3QixPQUFPLEtBQUtDLEtBQUssTUFBTSxPQUFPO0FBQzlCLFNBQVNDLFFBQVEsUUFBUSxPQUFPO0FBQ2hDLE9BQU9DLFNBQVMsTUFBTSxrQ0FBa0M7QUFDeEQsU0FBU0MsOEJBQThCLFFBQVEsa0RBQWtEO0FBQ2pH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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/sandbox/SandboxDependenciesTab.tsx b/_all-in-one-upload/cc-haha/src/components/sandbox/SandboxDependenciesTab.tsx new file mode 100644 index 0000000..c9ecbc5 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/sandbox/SandboxDependenciesTab.tsx @@ -0,0 +1,120 @@ +import { c as _c } from "react/compiler-runtime"; +import React from 'react'; +import { Box, Text } from '../../ink.js'; +import { getPlatform } from '../../utils/platform.js'; +import type { SandboxDependencyCheck } from '../../utils/sandbox/sandbox-adapter.js'; +type Props = { + depCheck: SandboxDependencyCheck; +}; +export function SandboxDependenciesTab(t0) { + const $ = _c(24); + const { + depCheck + } = t0; + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = getPlatform(); + $[0] = t1; + } else { + t1 = $[0]; + } + const platform = t1; + const isMac = platform === "macos"; + let t2; + if ($[1] !== depCheck.errors) { + t2 = depCheck.errors.some(_temp); + $[1] = depCheck.errors; + $[2] = t2; + } else { + t2 = $[2]; + } + const rgMissing = t2; + let t3; + if ($[3] !== depCheck.errors) { + t3 = depCheck.errors.some(_temp2); + $[3] = depCheck.errors; + $[4] = t3; + } else { + t3 = $[4]; + } + const bwrapMissing = t3; + let t4; + if ($[5] !== depCheck.errors) { + t4 = depCheck.errors.some(_temp3); + $[5] = depCheck.errors; + $[6] = t4; + } else { + t4 = $[6]; + } + const socatMissing = t4; + const seccompMissing = depCheck.warnings.length > 0; + let t5; + if ($[7] !== bwrapMissing || $[8] !== depCheck.errors || $[9] !== rgMissing || $[10] !== seccompMissing || $[11] !== socatMissing) { + const otherErrors = depCheck.errors.filter(_temp4); + const rgInstallHint = isMac ? "brew install ripgrep" : "apt install ripgrep"; + let t6; + if ($[13] === Symbol.for("react.memo_cache_sentinel")) { + t6 = isMac && seatbelt: built-in (macOS); + $[13] = t6; + } else { + t6 = $[13]; + } + let t7; + let t8; + if ($[14] !== rgMissing) { + t7 = ripgrep (rg):{" "}{rgMissing ? not found : found}; + t8 = rgMissing && {" "}· {rgInstallHint}; + $[14] = rgMissing; + $[15] = t7; + $[16] = t8; + } else { + t7 = $[15]; + t8 = $[16]; + } + let t9; + if ($[17] !== t7 || $[18] !== t8) { + t9 = {t7}{t8}; + $[17] = t7; + $[18] = t8; + $[19] = t9; + } else { + t9 = $[19]; + } + let t10; + if ($[20] !== bwrapMissing || $[21] !== seccompMissing || $[22] !== socatMissing) { + t10 = !isMac && <>bubblewrap (bwrap):{" "}{bwrapMissing ? not installed : installed}{bwrapMissing && {" "}· apt install bubblewrap}socat:{" "}{socatMissing ? not installed : installed}{socatMissing && {" "}· apt install socat}seccomp filter:{" "}{seccompMissing ? not installed : installed}{seccompMissing && (required to block unix domain sockets)}{seccompMissing && {" "}· npm install -g @anthropic-ai/sandbox-runtime{" "}· or copy vendor/seccomp/* from sandbox-runtime and set{" "}sandbox.seccomp.bpfPath and applyPath in settings.json}; + $[20] = bwrapMissing; + $[21] = seccompMissing; + $[22] = socatMissing; + $[23] = t10; + } else { + t10 = $[23]; + } + t5 = {t6}{t9}{t10}{otherErrors.map(_temp5)}; + $[7] = bwrapMissing; + $[8] = depCheck.errors; + $[9] = rgMissing; + $[10] = seccompMissing; + $[11] = socatMissing; + $[12] = t5; + } else { + t5 = $[12]; + } + return t5; +} +function _temp5(err) { + return {err}; +} +function _temp4(e_2) { + return !e_2.includes("ripgrep") && !e_2.includes("bwrap") && !e_2.includes("socat"); +} +function _temp3(e_1) { + return e_1.includes("socat"); +} +function _temp2(e_0) { + return e_0.includes("bwrap"); +} +function _temp(e) { + return e.includes("ripgrep"); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJveCIsIlRleHQiLCJnZXRQbGF0Zm9ybSIsIlNhbmRib3hEZXBlbmRlbmN5Q2hlY2siLCJQcm9wcyIsImRlcENoZWNrIiwiU2FuZGJveERlcGVuZGVuY2llc1RhYiIsInQwIiwiJCIsIl9jIiwidDEiLCJTeW1ib2wiLCJmb3IiLCJwbGF0Zm9ybSIsImlzTWFjIiwidDIiLCJlcnJvcnMiLCJzb21lIiwiX3RlbXAiLCJyZ01pc3NpbmciLCJ0MyIsIl90ZW1wMiIsImJ3cmFwTWlzc2luZyIsInQ0IiwiX3RlbXAzIiwic29jYXRNaXNzaW5nIiwic2VjY29tcE1pc3NpbmciLCJ3YXJuaW5ncyIsImxlbmd0aCIsInQ1Iiwib3RoZXJFcnJvcnMiLCJmaWx0ZXIiLCJfdGVtcDQiLCJyZ0luc3RhbGxIaW50IiwidDYiLCJ0NyIsInQ4IiwidDkiLCJ0MTAiLCJtYXAiLCJfdGVtcDUiLCJlcnIiLCJlXzIiLCJlIiwiaW5jbHVkZXMiLCJlXzEiLCJlXzAiXSwic291cmNlcyI6WyJTYW5kYm94RGVwZW5kZW5jaWVzVGFiLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBnZXRQbGF0Zm9ybSB9IGZyb20gJy4uLy4uL3V0aWxzL3BsYXRmb3JtLmpzJ1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94RGVwZW5kZW5jeUNoZWNrIH0gZnJvbSAnLi4vLi4vdXRpbHMvc2FuZGJveC9zYW5kYm94LWFkYXB0ZXIuanMnXG5cbnR5cGUgUHJvcHMgPSB7XG4gIGRlcENoZWNrOiBTYW5kYm94RGVwZW5kZW5jeUNoZWNrXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBTYW5kYm94RGVwZW5kZW5jaWVzVGFiKHsgZGVwQ2hlY2sgfTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBwbGF0Zm9ybSA9IGdldFBsYXRmb3JtKClcbiAgY29uc3QgaXNNYWMgPSBwbGF0Zm9ybSA9PT0gJ21hY29zJ1xuXG4gIC8vIHJpcGdyZXAgaXMgcmVxdWlyZWQgb24gYWxsIHBsYXRmb3JtcyAodXNlZCB0byBzY2FuIGZvciBkYW5nZXJvdXMgZGlycykuXG4gIC8vIE9uIG1hY09TLCBzZWF0YmVsdCBpcyBidWlsdCBpbnRvIHRoZSBPUyDigJQgcmlwZ3JlcCBpcyB0aGUgb25seSBydW50aW1lIGRlcC5cbiAgLy8gT24gTGludXgvV1NMLCBid3JhcCArIHNvY2F0IGFyZSByZXF1aXJlZCwgc2VjY29tcCBpcyBvcHRpb25hbC5cbiAgLy9cbiAgLy8gIzMxODA0OiBwcmV2aW91c2x5IHRoaXMgdGFiIHVuY29uZGl0aW9uYWxseSByZW5kZXJlZCBMaW51eCBkZXBzIChid3JhcCxcbiAgLy8gc29jYXQsIHNlY2NvbXApLiBXaGVuIHJpcGdyZXAgd2FzIG1pc3Npbmcgb24gbWFjT1MsIHVzZXJzIHNhdyBjb25mdXNpbmdcbiAgLy8gTGludXggaW5zdGFsbCBpbnN0cnVjdGlvbnMgYW5kIG5vIG1lbnRpb24gb2YgdGhlIGFjdHVhbCBwcm9ibGVtLlxuICBjb25zdCByZ01pc3NpbmcgPSBkZXBDaGVjay5lcnJvcnMuc29tZShlID0+IGUuaW5jbHVkZXMoJ3JpcGdyZXAnKSlcbiAgY29uc3QgYndyYXBNaXNzaW5nID0gZGVwQ2hlY2suZXJyb3JzLnNvbWUoZSA9PiBlLmluY2x1ZGVzKCdid3JhcCcpKVxuICBjb25zdCBzb2NhdE1pc3NpbmcgPSBkZXBDaGVjay5lcnJvcnMuc29tZShlID0+IGUuaW5jbHVkZXMoJ3NvY2F0JykpXG4gIGNvbnN0IHNlY2NvbXBNaXNzaW5nID0gZGVwQ2hlY2sud2FybmluZ3MubGVuZ3RoID4gMFxuXG4gIC8vIEFueSBlcnJvcnMgd2UgZG9uJ3QgaGF2ZSBhIGRlZGljYXRlZCByb3cgZm9yIOKAlCByZW5kZXIgdmVyYmF0aW0gc28gdGhleVxuICAvLyBhcmVuJ3Qgc2lsZW50bHkgc3dhbGxvd2VkIChlLmcuIFwiVW5zdXBwb3J0ZWQgcGxhdGZvcm1cIiBvciBmdXR1cmUgZGVwcykuXG4gIGNvbnN0IG90aGVyRXJyb3JzID0gZGVwQ2hlY2suZXJyb3JzLmZpbHRlcihcbiAgICBlID0+ICFlLmluY2x1ZGVzKCdyaXBncmVwJykgJiYgIWUuaW5jbHVkZXMoJ2J3cmFwJykgJiYgIWUuaW5jbHVkZXMoJ3NvY2F0JyksXG4gIClcblxuICBjb25zdCByZ0luc3RhbGxIaW50ID0gaXNNYWMgPyAnYnJldyBpbnN0YWxsIHJpcGdyZXAnIDogJ2FwdCBpbnN0YWxsIHJpcGdyZXAnXG5cbiAgcmV0dXJuIChcbiAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBwYWRkaW5nWT17MX0gZ2FwPXsxfT5cbiAgICAgIHtpc01hYyAmJiAoXG4gICAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgc2VhdGJlbHQ6IDxUZXh0IGNvbG9yPVwic3VjY2Vzc1wiPmJ1aWx0LWluIChtYWNPUyk8L1RleHQ+XG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICl9XG5cbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8VGV4dD5cbiAgICAgICAgICByaXBncmVwIChyZyk6eycgJ31cbiAgICAgICAgICB7cmdNaXNzaW5nID8gKFxuICAgICAgICAgICAgPFRleHQgY29sb3I9XCJlcnJvclwiPm5vdCBmb3VuZDwvVGV4dD5cbiAgICAgICAgICApIDogKFxuICAgICAgICAgICAgPFRleHQgY29sb3I9XCJzdWNjZXNzXCI+Zm91bmQ8L1RleHQ+XG4gICAgICAgICAgKX1cbiAgICAgICAgPC9UZXh0PlxuICAgICAgICB7cmdNaXNzaW5nICYmIChcbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgIHsnICAnfcK3IHtyZ0luc3RhbGxIaW50fVxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgKX1cbiAgICAgIDwvQm94PlxuXG4gICAgICB7IWlzTWFjICYmIChcbiAgICAgICAgPD5cbiAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgICBidWJibGV3cmFwIChid3JhcCk6eycgJ31cbiAgICAgICAgICAgICAge2J3cmFwTWlzc2luZyA/IChcbiAgICAgICAgICAgICAgICA8VGV4dCBjb2xvcj1cImVycm9yXCI+bm90IGluc3RhbGxlZDwvVGV4dD5cbiAgICAgICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICAgICA8VGV4dCBjb2xvcj1cInN1Y2Nlc3NcIj5pbnN0YWxsZWQ8L1RleHQ+XG4gICAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICB7YndyYXBNaXNzaW5nICYmIChcbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+eycgICd9wrcgYXB0IGluc3RhbGwgYnViYmxld3JhcDwvVGV4dD5cbiAgICAgICAgICAgICl9XG4gICAgICAgICAgPC9Cb3g+XG5cbiAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgICBzb2NhdDp7JyAnfVxuICAgICAgICAgICAgICB7c29jYXRNaXNzaW5nID8gKFxuICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwiZXJyb3JcIj5ub3QgaW5zdGFsbGVkPC9UZXh0PlxuICAgICAgICAgICAgICApIDogKFxuICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwic3VjY2Vzc1wiPmluc3RhbGxlZDwvVGV4dD5cbiAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgIHtzb2NhdE1pc3NpbmcgJiYgPFRleHQgZGltQ29sb3I+eycgICd9wrcgYXB0IGluc3RhbGwgc29jYXQ8L1RleHQ+fVxuICAgICAgICAgIDwvQm94PlxuXG4gICAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCI+XG4gICAgICAgICAgICA8VGV4dD5cbiAgICAgICAgICAgICAgc2VjY29tcCBmaWx0ZXI6eycgJ31cbiAgICAgICAgICAgICAge3NlY2NvbXBNaXNzaW5nID8gKFxuICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwid2FybmluZ1wiPm5vdCBpbnN0YWxsZWQ8L1RleHQ+XG4gICAgICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICAgICAgPFRleHQgY29sb3I9XCJzdWNjZXNzXCI+aW5zdGFsbGVkPC9UZXh0PlxuICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICB7c2VjY29tcE1pc3NpbmcgJiYgKFxuICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPiAocmVxdWlyZWQgdG8gYmxvY2sgdW5peCBkb21haW4gc29ja2V0cyk8L1RleHQ+XG4gICAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICB7c2VjY29tcE1pc3NpbmcgJiYgKFxuICAgICAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgICAgICAgIHsnICAnfcK3IG5wbSBpbnN0YWxsIC1nIEBhbnRocm9waWMtYWkvc2FuZGJveC1ydW50aW1lXG4gICAgICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICAgICAgeycgICd9wrcgb3IgY29weSB2ZW5kb3Ivc2VjY29tcC8qIGZyb20gc2FuZGJveC1ydW50aW1lIGFuZCBzZXRcbiAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgICAgICB7JyAgICAnfXNhbmRib3guc2VjY29tcC5icGZQYXRoIGFuZCBhcHBseVBhdGggaW4gc2V0dGluZ3MuanNvblxuICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgICApfVxuICAgICAgICAgIDwvQm94PlxuICAgICAgICA8Lz5cbiAgICAgICl9XG5cbiAgICAgIHtvdGhlckVycm9ycy5tYXAoZXJyID0+IChcbiAgICAgICAgPFRleHQga2V5PXtlcnJ9IGNvbG9yPVwiZXJyb3JcIj5cbiAgICAgICAgICB7ZXJyfVxuICAgICAgICA8L1RleHQ+XG4gICAgICApKX1cbiAgICA8L0JveD5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxNQUFNLE9BQU87QUFDekIsU0FBU0MsR0FBRyxFQUFFQyxJQUFJLFFBQVEsY0FBYztBQUN4QyxTQUFTQyxXQUFXLFFBQVEseUJBQXlCO0FBQ3JELGNBQWNDLHNCQUFzQixRQUFRLHdDQUF3QztBQUVwRixLQUFLQyxLQUFLLEdBQUc7RUFDWEMsUUFBUSxFQUFFRixzQkFBc0I7QUFDbEMsQ0FBQztBQUVELE9BQU8sU0FBQUcsdUJBQUFDLEVBQUE7RUFBQSxNQUFBQyxDQUFBLEdBQUFDLEVBQUE7RUFBZ0M7SUFBQUo7RUFBQSxJQUFBRSxFQUFtQjtFQUFBLElBQUFHLEVBQUE7RUFBQSxJQUFBRixDQUFBLFFBQUFHLE1BQUEsQ0FBQUMsR0FBQTtJQUN2Q0YsRUFBQSxHQUFBUixXQUFXLENBQUMsQ0FBQztJQUFBTSxDQUFBLE1BQUFFLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFGLENBQUE7RUFBQTtFQUE5QixNQUFBSyxRQUFBLEdBQWlCSCxFQUFhO0VBQzlCLE1BQUFJLEtBQUEsR0FBY0QsUUFBUSxLQUFLLE9BQU87RUFBQSxJQUFBRSxFQUFBO0VBQUEsSUFBQVAsQ0FBQSxRQUFBSCxRQUFBLENBQUFXLE1BQUE7SUFTaEJELEVBQUEsR0FBQVYsUUFBUSxDQUFBVyxNQUFPLENBQUFDLElBQUssQ0FBQ0MsS0FBMEIsQ0FBQztJQUFBVixDQUFBLE1BQUFILFFBQUEsQ0FBQVcsTUFBQTtJQUFBUixDQUFBLE1BQUFPLEVB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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/scheduled-tasks/types.ts b/_all-in-one-upload/cc-haha/src/components/scheduled-tasks/types.ts new file mode 100644 index 0000000..8f6034a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/scheduled-tasks/types.ts @@ -0,0 +1,12 @@ +export type ScheduledTaskWizardData = { + name?: string + description?: string + prompt?: string + model?: string + permissionMode?: string + folder?: string + worktree?: boolean + frequency?: string + scheduledTime?: string + cron?: string +} diff --git a/_all-in-one-upload/cc-haha/src/components/shell/ExpandShellOutputContext.tsx b/_all-in-one-upload/cc-haha/src/components/shell/ExpandShellOutputContext.tsx new file mode 100644 index 0000000..2452208 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/shell/ExpandShellOutputContext.tsx @@ -0,0 +1,36 @@ +import { c as _c } from "react/compiler-runtime"; +import * as React from 'react'; +import { useContext } from 'react'; + +/** + * Context to indicate that shell output should be shown in full (not truncated). + * Used to auto-expand the most recent user `!` command output. + * + * This follows the same pattern as MessageResponseContext and SubAgentContext - + * a boolean context that child components can check to modify their behavior. + */ +const ExpandShellOutputContext = React.createContext(false); +export function ExpandShellOutputProvider(t0) { + const $ = _c(2); + const { + children + } = t0; + let t1; + if ($[0] !== children) { + t1 = {children}; + $[0] = children; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} + +/** + * Returns true if this component is rendered inside an ExpandShellOutputProvider, + * indicating the shell output should be shown in full rather than truncated. + */ +export function useExpandShellOutput() { + return useContext(ExpandShellOutputContext); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZUNvbnRleHQiLCJFeHBhbmRTaGVsbE91dHB1dENvbnRleHQiLCJjcmVhdGVDb250ZXh0IiwiRXhwYW5kU2hlbGxPdXRwdXRQcm92aWRlciIsInQwIiwiJCIsIl9jIiwiY2hpbGRyZW4iLCJ0MSIsInVzZUV4cGFuZFNoZWxsT3V0cHV0Il0sInNvdXJjZXMiOlsiRXhwYW5kU2hlbGxPdXRwdXRDb250ZXh0LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUNvbnRleHQgfSBmcm9tICdyZWFjdCdcblxuLyoqXG4gKiBDb250ZXh0IHRvIGluZGljYXRlIHRoYXQgc2hlbGwgb3V0cHV0IHNob3VsZCBiZSBzaG93biBpbiBmdWxsIChub3QgdHJ1bmNhdGVkKS5cbiAqIFVzZWQgdG8gYXV0by1leHBhbmQgdGhlIG1vc3QgcmVjZW50IHVzZXIgYCFgIGNvbW1hbmQgb3V0cHV0LlxuICpcbiAqIFRoaXMgZm9sbG93cyB0aGUgc2FtZSBwYXR0ZXJuIGFzIE1lc3NhZ2VSZXNwb25zZUNvbnRleHQgYW5kIFN1YkFnZW50Q29udGV4dCAtXG4gKiBhIGJvb2xlYW4gY29udGV4dCB0aGF0IGNoaWxkIGNvbXBvbmVudHMgY2FuIGNoZWNrIHRvIG1vZGlmeSB0aGVpciBiZWhhdmlvci5cbiAqL1xuY29uc3QgRXhwYW5kU2hlbGxPdXRwdXRDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChmYWxzZSlcblxuZXhwb3J0IGZ1bmN0aW9uIEV4cGFuZFNoZWxsT3V0cHV0UHJvdmlkZXIoe1xuICBjaGlsZHJlbixcbn06IHtcbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZVxufSk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIHJldHVybiAoXG4gICAgPEV4cGFuZFNoZWxsT3V0cHV0Q29udGV4dC5Qcm92aWRlciB2YWx1ZT17dHJ1ZX0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9FeHBhbmRTaGVsbE91dHB1dENvbnRleHQuUHJvdmlkZXI+XG4gIClcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBjb21wb25lbnQgaXMgcmVuZGVyZWQgaW5zaWRlIGFuIEV4cGFuZFNoZWxsT3V0cHV0UHJvdmlkZXIsXG4gKiBpbmRpY2F0aW5nIHRoZSBzaGVsbCBvdXRwdXQgc2hvdWxkIGJlIHNob3duIGluIGZ1bGwgcmF0aGVyIHRoYW4gdHJ1bmNhdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlRXhwYW5kU2hlbGxPdXRwdXQoKTogYm9vbGVhbiB7XG4gIHJldHVybiB1c2VDb250ZXh0KEV4cGFuZFNoZWxsT3V0cHV0Q29udGV4dClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsVUFBVSxRQUFRLE9BQU87O0FBRWxDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTUMsd0JBQXdCLEdBQUdGLEtBQUssQ0FBQ0csYUFBYSxDQUFDLEtBQUssQ0FBQztBQUUzRCxPQUFPLFNBQUFDLDBCQUFBQyxFQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBQW1DO0lBQUFDO0VBQUEsSUFBQUgsRUFJekM7RUFBQSxJQUFBSSxFQUFBO0VBQUEsSUFBQUgsQ0FBQSxRQUFBRSxRQUFBO0lBRUdDLEVBQUEsc0NBQTBDLEtBQUksQ0FBSixLQUFHLENBQUMsQ0FDM0NELFNBQU8sQ0FDVixvQ0FBb0M7SUFBQUYsQ0FBQSxNQUFBRSxRQUFBO0lBQUFGLENBQUEsTUFBQUcsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUgsQ0FBQTtFQUFBO0VBQUEsT0FGcENHLEVBRW9DO0FBQUE7O0FBSXhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxTQUFBQyxxQkFBQTtFQUFBLE9BQ0VULFVBQVUsQ0FBQ0Msd0JBQXdCLENBQUM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/components/wizard/index.ts b/_all-in-one-upload/cc-haha/src/components/wizard/index.ts new file mode 100644 index 0000000..29a4c8e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/components/wizard/index.ts @@ -0,0 +1,9 @@ +export type { + WizardContextValue, + WizardProviderProps, + WizardStepComponent, +} from './types.js' +export { useWizard } from './useWizard.js' +export { WizardDialogLayout } from './WizardDialogLayout.js' +export { WizardNavigationFooter } from './WizardNavigationFooter.js' +export { WizardProvider } from './WizardProvider.js' diff --git a/_all-in-one-upload/cc-haha/src/constants/github-app.ts b/_all-in-one-upload/cc-haha/src/constants/github-app.ts new file mode 100644 index 0000000..1df9f51 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/constants/github-app.ts @@ -0,0 +1,144 @@ +export const PR_TITLE = 'Add Claude Code GitHub Workflow' + +export const GITHUB_ACTION_SETUP_DOCS_URL = + 'https://github.com/anthropics/claude-code-action/blob/main/docs/setup.md' + +export const WORKFLOW_CONTENT = `name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: \${{ secrets.ANTHROPIC_API_KEY }} + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. + # prompt: 'Update the pull request description to include a summary of changes.' + + # Optional: Add claude_args to customize behavior and configuration + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + # claude_args: '--allowed-tools Bash(gh pr:*)' + +` + +export const PR_BODY = `## 🤖 Installing Claude Code GitHub App + +This PR adds a GitHub Actions workflow that enables Claude Code integration in our repository. + +### What is Claude Code? + +[Claude Code](https://claude.com/claude-code) is an AI coding agent that can help with: +- Bug fixes and improvements +- Documentation updates +- Implementing new features +- Code reviews and suggestions +- Writing tests +- And more! + +### How it works + +Once this PR is merged, we'll be able to interact with Claude by mentioning @claude in a pull request or issue comment. +Once the workflow is triggered, Claude will analyze the comment and surrounding context, and execute on the request in a GitHub action. + +### Important Notes + +- **This workflow won't take effect until this PR is merged** +- **@claude mentions won't work until after the merge is complete** +- The workflow runs automatically whenever Claude is mentioned in PR or issue comments +- Claude gets access to the entire PR or issue context including files, diffs, and previous comments + +### Security + +- Our Anthropic API key is securely stored as a GitHub Actions secret +- Only users with write access to the repository can trigger the workflow +- All Claude runs are stored in the GitHub Actions run history +- Claude's default tools are limited to reading/writing files and interacting with our repo by creating comments, branches, and commits. +- We can add more allowed tools by adding them to the workflow file like: + +\`\`\` +allowed_tools: Bash(npm install),Bash(npm run build),Bash(npm run lint),Bash(npm run test) +\`\`\` + +There's more information in the [Claude Code action repo](https://github.com/anthropics/claude-code-action). + +After merging this PR, let's try mentioning @claude in a comment on any PR to get started!` + +export const CODE_REVIEW_PLUGIN_WORKFLOW_CONTENT = `name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize, ready_for_review, reopened] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: \${{ secrets.ANTHROPIC_API_KEY }} + plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' + plugins: 'code-review@claude-code-plugins' + prompt: '/code-review:code-review \${{ github.repository }}/pull/\${{ github.event.pull_request.number }}' + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + +` diff --git a/_all-in-one-upload/cc-haha/src/context/voice.tsx b/_all-in-one-upload/cc-haha/src/context/voice.tsx new file mode 100644 index 0000000..04e14dd --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/context/voice.tsx @@ -0,0 +1,88 @@ +import { c as _c } from "react/compiler-runtime"; +import React, { createContext, useContext, useState, useSyncExternalStore } from 'react'; +import { createStore, type Store } from '../state/store.js'; +export type VoiceState = { + voiceState: 'idle' | 'recording' | 'processing'; + voiceError: string | null; + voiceInterimTranscript: string; + voiceAudioLevels: number[]; + voiceWarmingUp: boolean; +}; +const DEFAULT_STATE: VoiceState = { + voiceState: 'idle', + voiceError: null, + voiceInterimTranscript: '', + voiceAudioLevels: [], + voiceWarmingUp: false +}; +type VoiceStore = Store; +const VoiceContext = createContext(null); +type Props = { + children: React.ReactNode; +}; +export function VoiceProvider(t0) { + const $ = _c(3); + const { + children + } = t0; + const [store] = useState(_temp); + let t1; + if ($[0] !== children || $[1] !== store) { + t1 = {children}; + $[0] = children; + $[1] = store; + $[2] = t1; + } else { + t1 = $[2]; + } + return t1; +} +function _temp() { + return createStore(DEFAULT_STATE); +} +function useVoiceStore() { + const store = useContext(VoiceContext); + if (!store) { + throw new Error("useVoiceState must be used within a VoiceProvider"); + } + return store; +} + +/** + * Subscribe to a slice of voice state. Only re-renders when the selected + * value changes (compared via Object.is). + */ +export function useVoiceState(selector) { + const $ = _c(3); + const store = useVoiceStore(); + let t0; + if ($[0] !== selector || $[1] !== store) { + t0 = () => selector(store.getState()); + $[0] = selector; + $[1] = store; + $[2] = t0; + } else { + t0 = $[2]; + } + const get = t0; + return useSyncExternalStore(store.subscribe, get, get); +} + +/** + * Get the voice state setter. Stable reference — never causes re-renders. + * store.setState is synchronous: callers can read getVoiceState() immediately + * after to observe the new value (VoiceKeybindingHandler relies on this). + */ +export function useSetVoiceState() { + return useVoiceStore().setState; +} + +/** + * Get a synchronous reader for fresh state inside callbacks. Unlike + * useVoiceState (which subscribes), this doesn't cause re-renders — use + * inside event handlers that need to read state set earlier in the same tick. + */ +export function useGetVoiceState() { + return useVoiceStore().getState; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwidXNlU3RhdGUiLCJ1c2VTeW5jRXh0ZXJuYWxTdG9yZSIsImNyZWF0ZVN0b3JlIiwiU3RvcmUiLCJWb2ljZVN0YXRlIiwidm9pY2VTdGF0ZSIsInZvaWNlRXJyb3IiLCJ2b2ljZUludGVyaW1UcmFuc2NyaXB0Iiwidm9pY2VBdWRpb0xldmVscyIsInZvaWNlV2FybWluZ1VwIiwiREVGQVVMVF9TVEFURSIsIlZvaWNlU3RvcmUiLCJWb2ljZUNvbnRleHQiLCJQcm9wcyIsImNoaWxkcmVuIiwiUmVhY3ROb2RlIiwiVm9pY2VQcm92aWRlciIsInQwIiwiJCIsIl9jIiwic3RvcmUiLCJfdGVtcCIsInQxIiwidXNlVm9pY2VTdG9yZSIsIkVycm9yIiwidXNlVm9pY2VTdGF0ZSIsInNlbGVjdG9yIiwiZ2V0U3RhdGUiLCJnZXQiLCJzdWJzY3JpYmUiLCJ1c2VTZXRWb2ljZVN0YXRlIiwic2V0U3RhdGUiLCJ1c2VHZXRWb2ljZVN0YXRlIl0sInNvdXJjZXMiOlsidm9pY2UudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VTdGF0ZSxcbiAgdXNlU3luY0V4dGVybmFsU3RvcmUsXG59IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3JlYXRlU3RvcmUsIHR5cGUgU3RvcmUgfSBmcm9tICcuLi9zdGF0ZS9zdG9yZS5qcydcblxuZXhwb3J0IHR5cGUgVm9pY2VTdGF0ZSA9IHtcbiAgdm9pY2VTdGF0ZTogJ2lkbGUnIHwgJ3JlY29yZGluZycgfCAncHJvY2Vzc2luZydcbiAgdm9pY2VFcnJvcjogc3RyaW5nIHwgbnVsbFxuICB2b2ljZUludGVyaW1UcmFuc2NyaXB0OiBzdHJpbmdcbiAgdm9pY2VBdWRpb0xldmVsczogbnVtYmVyW11cbiAgdm9pY2VXYXJtaW5nVXA6IGJvb2xlYW5cbn1cblxuY29uc3QgREVGQVVMVF9TVEFURTogVm9pY2VTdGF0ZSA9IHtcbiAgdm9pY2VTdGF0ZTogJ2lkbGUnLFxuICB2b2ljZUVycm9yOiBudWxsLFxuICB2b2ljZUludGVyaW1UcmFuc2NyaXB0OiAnJyxcbiAgdm9pY2VBdWRpb0xldmVsczogW10sXG4gIHZvaWNlV2FybWluZ1VwOiBmYWxzZSxcbn1cblxudHlwZSBWb2ljZVN0b3JlID0gU3RvcmU8Vm9pY2VTdGF0ZT5cblxuY29uc3QgVm9pY2VDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxWb2ljZVN0b3JlIHwgbnVsbD4obnVsbClcblxudHlwZSBQcm9wcyA9IHtcbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gVm9pY2VQcm92aWRlcih7IGNoaWxkcmVuIH06IFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgLy8gU3RvcmUgaXMgY3JlYXRlZCBvbmNlIOKAlCBzdGFibGUgY29udGV4dCB2YWx1ZSBtZWFucyB0aGUgcHJvdmlkZXIgbmV2ZXJcbiAgLy8gdHJpZ2dlcnMgcmUtcmVuZGVycy4gQ29uc3VtZXJzIHN1YnNjcmliZSB0byBzbGljZXMgdmlhIHVzZVZvaWNlU3RhdGUuXG4gIGNvbnN0IFtzdG9yZV0gPSB1c2VTdGF0ZSgoKSA9PiBjcmVhdGVTdG9yZTxWb2ljZVN0YXRlPihERUZBVUxUX1NUQVRFKSlcbiAgcmV0dXJuIDxWb2ljZUNvbnRleHQuUHJvdmlkZXIgdmFsdWU9e3N0b3JlfT57Y2hpbGRyZW59PC9Wb2ljZUNvbnRleHQuUHJvdmlkZXI+XG59XG5cbmZ1bmN0aW9uIHVzZVZvaWNlU3RvcmUoKTogVm9pY2VTdG9yZSB7XG4gIGNvbnN0IHN0b3JlID0gdXNlQ29udGV4dChWb2ljZUNvbnRleHQpXG4gIGlmICghc3RvcmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzZVZvaWNlU3RhdGUgbXVzdCBiZSB1c2VkIHdpdGhpbiBhIFZvaWNlUHJvdmlkZXInKVxuICB9XG4gIHJldHVybiBzdG9yZVxufVxuXG4vKipcbiAqIFN1YnNjcmliZSB0byBhIHNsaWNlIG9mIHZvaWNlIHN0YXRlLiBPbmx5IHJlLXJlbmRlcnMgd2hlbiB0aGUgc2VsZWN0ZWRcbiAqIHZhbHVlIGNoYW5nZXMgKGNvbXBhcmVkIHZpYSBPYmplY3QuaXMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlVm9pY2VTdGF0ZTxUPihzZWxlY3RvcjogKHN0YXRlOiBWb2ljZVN0YXRlKSA9PiBUKTogVCB7XG4gIGNvbnN0IHN0b3JlID0gdXNlVm9pY2VTdG9yZSgpXG4gIGNvbnN0IGdldCA9ICgpID0+IHNlbGVjdG9yKHN0b3JlLmdldFN0YXRlKCkpXG4gIHJldHVybiB1c2VTeW5jRXh0ZXJuYWxTdG9yZShzdG9yZS5zdWJzY3JpYmUsIGdldCwgZ2V0KVxufVxuXG4vKipcbiAqIEdldCB0aGUgdm9pY2Ugc3RhdGUgc2V0dGVyLiBTdGFibGUgcmVmZXJlbmNlIOKAlCBuZXZlciBjYXVzZXMgcmUtcmVuZGVycy5cbiAqIHN0b3JlLnNldFN0YXRlIGlzIHN5bmNocm9ub3VzOiBjYWxsZXJzIGNhbiByZWFkIGdldFZvaWNlU3RhdGUoKSBpbW1lZGlhdGVseVxuICogYWZ0ZXIgdG8gb2JzZXJ2ZSB0aGUgbmV3IHZhbHVlIChWb2ljZUtleWJpbmRpbmdIYW5kbGVyIHJlbGllcyBvbiB0aGlzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVNldFZvaWNlU3RhdGUoKTogKFxuICB1cGRhdGVyOiAocHJldjogVm9pY2VTdGF0ZSkgPT4gVm9pY2VTdGF0ZSxcbikgPT4gdm9pZCB7XG4gIHJldHVybiB1c2VWb2ljZVN0b3JlKCkuc2V0U3RhdGVcbn1cblxuLyoqXG4gKiBHZXQgYSBzeW5jaHJvbm91cyByZWFkZXIgZm9yIGZyZXNoIHN0YXRlIGluc2lkZSBjYWxsYmFja3MuIFVubGlrZVxuICogdXNlVm9pY2VTdGF0ZSAod2hpY2ggc3Vic2NyaWJlcyksIHRoaXMgZG9lc24ndCBjYXVzZSByZS1yZW5kZXJzIOKAlCB1c2VcbiAqIGluc2lkZSBldmVudCBoYW5kbGVycyB0aGF0IG5lZWQgdG8gcmVhZCBzdGF0ZSBzZXQgZWFybGllciBpbiB0aGUgc2FtZSB0aWNrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlR2V0Vm9pY2VTdGF0ZSgpOiAoKSA9PiBWb2ljZVN0YXRlIHtcbiAgcmV0dXJuIHVzZVZvaWNlU3RvcmUoKS5nZXRTdGF0ZVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUNWQyxhQUFhLEVBQ2JDLFVBQVUsRUFDVkMsUUFBUSxFQUNSQyxvQkFBb0IsUUFDZixPQUFPO0FBQ2QsU0FBU0MsV0FBVyxFQUFFLEtBQUtDLEtBQUssUUFBUSxtQkFBbUI7QUFFM0QsT0FBTyxLQUFLQyxVQUFVLEdBQUc7RUFDdkJDLFVBQVUsRUFBRSxNQUFNLEdBQUcsV0FBVyxHQUFHLFlBQVk7RUFDL0NDLFVBQVUsRUFBRSxNQUFNLEdBQUcsSUFBSTtFQUN6QkMsc0JBQXNCLEVBQUUsTUFBTTtFQUM5QkMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFO0VBQzFCQyxjQUFjLEVBQUUsT0FBTztBQUN6QixDQUFDO0FBRUQsTUFBTUMsYUFBYSxFQUFFTixVQUFVLEdBQUc7RUFDaENDLFVBQVUsRUFBRSxNQUFNO0VBQ2xCQyxVQUFVLEVBQUUsSUFBSTtFQUNoQkMsc0JBQXNCLEVBQUUsRUFBRTtFQUMxQkMsZ0JBQWdCLEVBQUUsRUFBRTtFQUNwQkMsY0FBYyxFQUFFO0FBQ2xCLENBQUM7QUFFRCxLQUFLRSxVQUFVLEdBQUdSLEtBQUssQ0FBQ0MsVUFBVSxDQUFDO0FBRW5DLE1BQU1RLFlBQVksR0FBR2QsYUFBYSxDQUFDYSxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO0FBRTNELEtBQUtFLEtBQUssR0FBRztFQUNYQyxRQUFRLEVBQUVqQixLQUFLLENBQUNrQixTQUFTO0FBQzNCLENBQUM7QUFFRCxPQUFPLFNBQUFDLGNBQUFDLEVBQUE7RUFBQSxNQUFBQyxDQUFBLEdBQUFDLEVBQUE7RUFBdUI7SUFBQUw7RUFBQSxJQUFBRyxFQUFtQjtFQUcvQyxPQUFBRyxLQUFBLElBQWdCcEIsUUFBUSxDQUFDcUIsS0FBNEMsQ0FBQztFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBSixDQUFBLFFBQUFKLFFBQUEsSUFBQUksQ0FBQSxRQUFBRSxLQUFBO0lBQy9ERSxFQUFBLDBCQUE4QkYsS0FBSyxDQUFMQSxNQUFJLENBQUMsQ0FBR04sU0FBTyxDQUFFLHdCQUF3QjtJQUFBSSxDQUFBLE1BQUFKLFFBQUE7SUFBQUksQ0FBQSxNQUFBRSxLQUFBO0lBQUFGLENBQUEsTUFBQUksRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUosQ0FBQTtFQUFBO0VBQUEsT0FBdkVJLEVBQXVFO0FBQUE7QUFKekUsU0FBQUQsTUFBQTtFQUFBLE9BRzBCbkIsV0FBVyxDQUFhUSxhQUFhLENBQUM7QUFBQTtBQUl2RSxTQUFBYSxjQUFBO0VBQ0UsTUFBQUgsS0FBQSxHQUFjckIsVUFBVSxDQUFDYSxZQUFZLENBQUM7RUFDdEMsSUFBSSxDQUFDUSxLQUFLO0lBQ1IsTUFBTSxJQUFJSSxLQUFLLENBQUMsbURBQW1ELENBQUM7RUFBQTtFQUNyRSxPQUNNSixLQUFLO0FBQUE7O0FBR2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQUFLLGNBQUFDLFFBQUE7RUFBQSxNQUFBUixDQUFBLEdBQUFDLEVBQUE7RUFDTCxNQUFBQyxLQUFBLEdBQWNHLGFBQWEsQ0FBQyxDQUFDO0VBQUEsSUFBQU4sRUFBQTtFQUFBLElBQUFDLENBQUEsUUFBQVEsUUFBQSxJQUFBUixDQUFBLFFBQUFFLEtBQUE7SUFDakJILEVBQUEsR0FBQUEsQ0FBQSxLQUFNUyxRQUFRLENBQUNOLEtBQUssQ0FBQU8sUUFBUyxDQUFDLENBQUMsQ0FBQztJQUFBVCxDQUFBLE1BQUFRLFFBQUE7SUFBQVIsQ0FBQSxNQUFBRSxLQUFBO0lBQUFGLENBQUEsTUFBQUQsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUMsQ0FBQTtFQUFBO0VBQTVDLE1BQUFVLEdBQUEsR0FBWVgsRUFBZ0M7RUFBQSxPQUNyQ2hCLG9CQUFvQixDQUFDbUIsS0FBSyxDQUFBUyxTQUFVLEVBQUVELEdBQUcsRUFBRUEsR0FBRyxDQUFDO0FBQUE7O0FBR3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQUFFLGlCQUFBO0VBQUEsT0FHRVAsYUFBYSxDQUFDLENBQUMsQ0FBQVEsUUFBUztBQUFBOztBQUdqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxTQUFBQyxpQkFBQTtFQUFBLE9BQ0VULGFBQWEsQ0FBQyxDQUFDLENBQUFJLFFBQVM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ== \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/entrypoints/sdk/coreTypes.generated.ts b/_all-in-one-upload/cc-haha/src/entrypoints/sdk/coreTypes.generated.ts new file mode 100644 index 0000000..51d022e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/entrypoints/sdk/coreTypes.generated.ts @@ -0,0 +1,3 @@ +// Local recovery stub for missing generated SDK types. +// The leaked source tree does not include this codegen artifact. +export {} diff --git a/_all-in-one-upload/cc-haha/src/hooks/.syncthing.usePromptsFromClaudeInChrome.tsx.tmp b/_all-in-one-upload/cc-haha/src/hooks/.syncthing.usePromptsFromClaudeInChrome.tsx.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ed949a135d23121efac180c2cda3c1900fec44e6 GIT binary patch literal 11623 zcmeIuF#!Mo0K%a4Pwi_6h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM V7%*VKfB^#r3>YwAz<>b*H!v+{00961 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/src/hooks/notifs/useSettingsErrors.tsx b/_all-in-one-upload/cc-haha/src/hooks/notifs/useSettingsErrors.tsx new file mode 100644 index 0000000..d269482 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/notifs/useSettingsErrors.tsx @@ -0,0 +1,69 @@ +import { c as _c } from "react/compiler-runtime"; +import { useCallback, useEffect, useState } from 'react'; +import { useNotifications } from 'src/context/notifications.js'; +import { getIsRemoteMode } from '../../bootstrap/state.js'; +import { getSettingsWithAllErrors } from '../../utils/settings/allErrors.js'; +import type { ValidationError } from '../../utils/settings/validation.js'; +import { useSettingsChange } from '../useSettingsChange.js'; +const SETTINGS_ERRORS_NOTIFICATION_KEY = 'settings-errors'; +export function useSettingsErrors() { + const $ = _c(6); + const { + addNotification, + removeNotification + } = useNotifications(); + const [errors_0, setErrors] = useState(_temp); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = () => { + const { + errors: errors_1 + } = getSettingsWithAllErrors(); + setErrors(errors_1); + }; + $[0] = t0; + } else { + t0 = $[0]; + } + const handleSettingsChange = t0; + useSettingsChange(handleSettingsChange); + let t1; + let t2; + if ($[1] !== addNotification || $[2] !== errors_0 || $[3] !== removeNotification) { + t1 = () => { + if (getIsRemoteMode()) { + return; + } + if (errors_0.length > 0) { + const message = `Found ${errors_0.length} settings ${errors_0.length === 1 ? "issue" : "issues"} · /doctor for details`; + addNotification({ + key: SETTINGS_ERRORS_NOTIFICATION_KEY, + text: message, + color: "warning", + priority: "high", + timeoutMs: 60000 + }); + } else { + removeNotification(SETTINGS_ERRORS_NOTIFICATION_KEY); + } + }; + t2 = [errors_0, addNotification, removeNotification]; + $[1] = addNotification; + $[2] = errors_0; + $[3] = removeNotification; + $[4] = t1; + $[5] = t2; + } else { + t1 = $[4]; + t2 = $[5]; + } + useEffect(t1, t2); + return errors_0; +} +function _temp() { + const { + errors + } = getSettingsWithAllErrors(); + return errors; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ1c2VDYWxsYmFjayIsInVzZUVmZmVjdCIsInVzZVN0YXRlIiwidXNlTm90aWZpY2F0aW9ucyIsImdldElzUmVtb3RlTW9kZSIsImdldFNldHRpbmdzV2l0aEFsbEVycm9ycyIsIlZhbGlkYXRpb25FcnJvciIsInVzZVNldHRpbmdzQ2hhbmdlIiwiU0VUVElOR1NfRVJST1JTX05PVElGSUNBVElPTl9LRVkiLCJ1c2VTZXR0aW5nc0Vycm9ycyIsIiQiLCJfYyIsImFkZE5vdGlmaWNhdGlvbiIsInJlbW92ZU5vdGlmaWNhdGlvbiIsImVycm9yc18wIiwic2V0RXJyb3JzIiwiX3RlbXAiLCJ0MCIsIlN5bWJvbCIsImZvciIsImVycm9ycyIsImVycm9yc18xIiwiaGFuZGxlU2V0dGluZ3NDaGFuZ2UiLCJ0MSIsInQyIiwibGVuZ3RoIiwibWVzc2FnZSIsImtleSIsInRleHQiLCJjb2xvciIsInByaW9yaXR5IiwidGltZW91dE1zIl0sInNvdXJjZXMiOlsidXNlU2V0dGluZ3NFcnJvcnMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyB1c2VOb3RpZmljYXRpb25zIH0gZnJvbSAnc3JjL2NvbnRleHQvbm90aWZpY2F0aW9ucy5qcydcbmltcG9ydCB7IGdldElzUmVtb3RlTW9kZSB9IGZyb20gJy4uLy4uL2Jvb3RzdHJhcC9zdGF0ZS5qcydcbmltcG9ydCB7IGdldFNldHRpbmdzV2l0aEFsbEVycm9ycyB9IGZyb20gJy4uLy4uL3V0aWxzL3NldHRpbmdzL2FsbEVycm9ycy5qcydcbmltcG9ydCB0eXBlIHsgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vLi4vdXRpbHMvc2V0dGluZ3MvdmFsaWRhdGlvbi5qcydcbmltcG9ydCB7IHVzZVNldHRpbmdzQ2hhbmdlIH0gZnJvbSAnLi4vdXNlU2V0dGluZ3NDaGFuZ2UuanMnXG5cbmNvbnN0IFNFVFRJTkdTX0VSUk9SU19OT1RJRklDQVRJT05fS0VZID0gJ3NldHRpbmdzLWVycm9ycydcblxuZXhwb3J0IGZ1bmN0aW9uIHVzZVNldHRpbmdzRXJyb3JzKCk6IFZhbGlkYXRpb25FcnJvcltdIHtcbiAgY29uc3QgeyBhZGROb3RpZmljYXRpb24sIHJlbW92ZU5vdGlmaWNhdGlvbiB9ID0gdXNlTm90aWZpY2F0aW9ucygpXG4gIGNvbnN0IFtlcnJvcnMsIHNldEVycm9yc10gPSB1c2VTdGF0ZTxWYWxpZGF0aW9uRXJyb3JbXT4oKCkgPT4ge1xuICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBnZXRTZXR0aW5nc1dpdGhBbGxFcnJvcnMoKVxuICAgIHJldHVybiBlcnJvcnNcbiAgfSlcblxuICBjb25zdCBoYW5kbGVTZXR0aW5nc0NoYW5nZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBjb25zdCB7IGVycm9ycyB9ID0gZ2V0U2V0dGluZ3NXaXRoQWxsRXJyb3JzKClcbiAgICBzZXRFcnJvcnMoZXJyb3JzKVxuICB9LCBbXSlcblxuICB1c2VTZXR0aW5nc0NoYW5nZShoYW5kbGVTZXR0aW5nc0NoYW5nZSlcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChnZXRJc1JlbW90ZU1vZGUoKSkgcmV0dXJuXG4gICAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYEZvdW5kICR7ZXJyb3JzLmxlbmd0aH0gc2V0dGluZ3MgJHtlcnJvcnMubGVuZ3RoID09PSAxID8gJ2lzc3VlJyA6ICdpc3N1ZXMnfSDCtyAvZG9jdG9yIGZvciBkZXRhaWxzYFxuICAgICAgYWRkTm90aWZpY2F0aW9uKHtcbiAgICAgICAga2V5OiBTRVRUSU5HU19FUlJPUlNfTk9USUZJQ0FUSU9OX0tFWSxcbiAgICAgICAgdGV4dDogbWVzc2FnZSxcbiAgICAgICAgY29sb3I6ICd3YXJuaW5nJyxcbiAgICAgICAgcHJpb3JpdHk6ICdoaWdoJyxcbiAgICAgICAgdGltZW91dE1zOiA2MDAwMCxcbiAgICAgIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHJlbW92ZU5vdGlmaWNhdGlvbihTRVRUSU5HU19FUlJPUlNfTk9USUZJQ0FUSU9OX0tFWSlcbiAgICB9XG4gIH0sIFtlcnJvcnMsIGFkZE5vdGlmaWNhdGlvbiwgcmVtb3ZlTm90aWZpY2F0aW9uXSlcblxuICByZXR1cm4gZXJyb3JzXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxTQUFTQSxXQUFXLEVBQUVDLFNBQVMsRUFBRUMsUUFBUSxRQUFRLE9BQU87QUFDeEQsU0FBU0MsZ0JBQWdCLFFBQVEsOEJBQThCO0FBQy9ELFNBQVNDLGVBQWUsUUFBUSwwQkFBMEI7QUFDMUQsU0FBU0Msd0JBQXdCLFFBQVEsbUNBQW1DO0FBQzVFLGNBQWNDLGVBQWUsUUFBUSxvQ0FBb0M7QUFDekUsU0FBU0MsaUJBQWlCLFFBQVEseUJBQXlCO0FBRTNELE1BQU1DLGdDQUFnQyxHQUFHLGlCQUFpQjtBQUUxRCxPQUFPLFNBQUFDLGtCQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBQ0w7SUFBQUMsZUFBQTtJQUFBQztFQUFBLElBQWdEVixnQkFBZ0IsQ0FBQyxDQUFDO0VBQ2xFLE9BQUFXLFFBQUEsRUFBQUMsU0FBQSxJQUE0QmIsUUFBUSxDQUFvQmMsS0FHdkQsQ0FBQztFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBUCxDQUFBLFFBQUFRLE1BQUEsQ0FBQUMsR0FBQTtJQUV1Q0YsRUFBQSxHQUFBQSxDQUFBO01BQ3ZDO1FBQUFHLE1BQUEsRUFBQUM7TUFBQSxJQUFtQmhCLHdCQUF3QixDQUFDLENBQUM7TUFDN0NVLFNBQVMsQ0FBQ0ssUUFBTSxDQUFDO0lBQUEsQ0FDbEI7SUFBQVYsQ0FBQSxNQUFBTyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBUCxDQUFBO0VBQUE7RUFIRCxNQUFBWSxvQkFBQSxHQUE2QkwsRUFHdkI7RUFFTlYsaUJBQWlCLENBQUNlLG9CQUFvQixDQUFDO0VBQUEsSUFBQUMsRUFBQTtFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBZCxDQUFBLFFBQUFFLGVBQUEsSUFBQUYsQ0FBQSxRQUFBSSxRQUFBLElBQUFKLENBQUEsUUFBQUcsa0JBQUE7SUFFN0JVLEVBQUEsR0FBQUEsQ0FBQTtNQUNSLElBQUluQixlQUFlLENBQUMsQ0FBQztRQUFBO01BQUE7TUFDckIsSUFBSWdCLFFBQU0sQ0FBQUssTUFBTyxHQUFHLENBQUM7UUFDbkIsTUFBQUMsT0FBQSxHQUFnQixTQUFTTixRQUFNLENBQUFLLE1BQU8sYUFBYUwsUUFBTSxDQUFBSyxNQUFPLEtBQUssQ0FBc0IsR0FBeEMsT0FBd0MsR0FBeEMsUUFBd0Msd0JBQXdCO1FBQ25IYixlQUFlLENBQUM7VUFBQWUsR0FBQSxFQUNUbkIsZ0NBQWdDO1VBQUFvQixJQUFBLEVBQy9CRixPQUFPO1VBQUFHLEtBQUEsRUFDTixTQUFTO1VBQUFDLFFBQUEsRUFDTixNQUFNO1VBQUFDLFNBQUEsRUFDTDtRQUNiLENBQUMsQ0FBQztNQUFBO1FBRUZsQixrQkFBa0IsQ0FBQ0wsZ0NBQWdDLENBQUM7TUFBQTtJQUNyRCxDQUNGO0lBQUVnQixFQUFBLElBQUNKLFFBQU0sRUFBRVIsZUFBZSxFQUFFQyxrQkFBa0IsQ0FBQztJQUFBSCxDQUFBLE1BQUFFLGVBQUE7SUFBQUYsQ0FBQSxNQUFBSSxRQUFBO0lBQUFKLENBQUEsTUFBQUcsa0JBQUE7SUFBQUgsQ0FBQSxNQUFBYSxFQUFBO0lBQUFiLENBQUEsTUFBQWMsRUFBQTtFQUFBO0lBQUFELEVBQUEsR0FBQWIsQ0FBQTtJQUFBYyxFQUFBLEdBQUFkLENBQUE7RUFBQTtFQWRoRFQsU0FBUyxDQUFDc0IsRUFjVCxFQUFFQyxFQUE2QyxDQUFDO0VBQUEsT0FFMUNKLFFBQU07QUFBQTtBQTlCUixTQUFBSixNQUFBO0VBR0g7SUFBQUk7RUFBQSxJQUFtQmYsd0JBQXdCLENBQUMsQ0FBQztFQUFBLE9BQ3RDZSxNQUFNO0FBQUEiLCJpZ25vcmVMaXN0IjpbXX0= \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/hooks/notifs/useStartupNotification.ts b/_all-in-one-upload/cc-haha/src/hooks/notifs/useStartupNotification.ts new file mode 100644 index 0000000..4e2fa8f --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/notifs/useStartupNotification.ts @@ -0,0 +1,41 @@ +import { useEffect, useRef } from 'react' +import { getIsRemoteMode } from '../../bootstrap/state.js' +import { + type Notification, + useNotifications, +} from '../../context/notifications.js' +import { logError } from '../../utils/log.js' + +type Result = Notification | Notification[] | null + +/** + * Fires notification(s) once on mount. Encapsulates the remote-mode gate and + * once-per-session ref guard that was hand-rolled across 10+ notifs/ hooks. + * + * The compute fn runs exactly once on first effect. Return null to skip, + * a Notification to fire one, or an array to fire several. Sync or async. + * Rejections are routed to logError. + */ +export function useStartupNotification( + compute: () => Result | Promise, +): void { + const { addNotification } = useNotifications() + const hasRunRef = useRef(false) + const computeRef = useRef(compute) + computeRef.current = compute + + useEffect(() => { + if (getIsRemoteMode() || hasRunRef.current) return + hasRunRef.current = true + + void Promise.resolve() + .then(() => computeRef.current()) + .then(result => { + if (!result) return + for (const n of Array.isArray(result) ? result : [result]) { + addNotification(n) + } + }) + .catch(logError) + }, [addNotification]) +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/renderPlaceholder.ts b/_all-in-one-upload/cc-haha/src/hooks/renderPlaceholder.ts new file mode 100644 index 0000000..50913ff --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/renderPlaceholder.ts @@ -0,0 +1,51 @@ +import chalk from 'chalk' + +type PlaceholderRendererProps = { + placeholder?: string + value: string + showCursor?: boolean + focus?: boolean + terminalFocus: boolean + invert?: (text: string) => string + hidePlaceholderText?: boolean +} + +export function renderPlaceholder({ + placeholder, + value, + showCursor, + focus, + terminalFocus = true, + invert = chalk.inverse, + hidePlaceholderText = false, +}: PlaceholderRendererProps): { + renderedPlaceholder: string | undefined + showPlaceholder: boolean +} { + let renderedPlaceholder: string | undefined = undefined + + if (placeholder) { + if (hidePlaceholderText) { + // Voice recording: show only the cursor, no placeholder text + renderedPlaceholder = + showCursor && focus && terminalFocus ? invert(' ') : '' + } else { + renderedPlaceholder = chalk.dim(placeholder) + + // Show inverse cursor only when both input and terminal are focused + if (showCursor && focus && terminalFocus) { + renderedPlaceholder = + placeholder.length > 0 + ? invert(placeholder[0]!) + chalk.dim(placeholder.slice(1)) + : invert(' ') + } + } + } + + const showPlaceholder = value.length === 0 && Boolean(placeholder) + + return { + renderedPlaceholder, + showPlaceholder, + } +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/toolPermission/PermissionContext.ts b/_all-in-one-upload/cc-haha/src/hooks/toolPermission/PermissionContext.ts new file mode 100644 index 0000000..43ae7e8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/toolPermission/PermissionContext.ts @@ -0,0 +1,388 @@ +import { feature } from 'bun:bundle' +import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/messages.mjs' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from 'src/services/analytics/index.js' +import { sanitizeToolNameForAnalytics } from 'src/services/analytics/metadata.js' +import type { ToolUseConfirm } from '../../components/permissions/PermissionRequest.js' +import type { + ToolPermissionContext, + Tool as ToolType, + ToolUseContext, +} from '../../Tool.js' +import { awaitClassifierAutoApproval } from '../../tools/BashTool/bashPermissions.js' +import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js' +import type { AssistantMessage } from '../../types/message.js' +import type { + PendingClassifierCheck, + PermissionAllowDecision, + PermissionDecisionReason, + PermissionDenyDecision, +} from '../../types/permissions.js' +import { setClassifierApproval } from '../../utils/classifierApprovals.js' +import { logForDebugging } from '../../utils/debug.js' +import { executePermissionRequestHooks } from '../../utils/hooks.js' +import { + REJECT_MESSAGE, + REJECT_MESSAGE_WITH_REASON_PREFIX, + SUBAGENT_REJECT_MESSAGE, + SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX, + withMemoryCorrectionHint, +} from '../../utils/messages.js' +import type { PermissionDecision } from '../../utils/permissions/PermissionResult.js' +import { + applyPermissionUpdates, + persistPermissionUpdates, + supportsPersistence, +} from '../../utils/permissions/PermissionUpdate.js' +import type { PermissionUpdate } from '../../utils/permissions/PermissionUpdateSchema.js' +import { + logPermissionDecision, + type PermissionDecisionArgs, +} from './permissionLogging.js' + +type PermissionApprovalSource = + | { type: 'hook'; permanent?: boolean } + | { type: 'user'; permanent: boolean } + | { type: 'classifier' } + +type PermissionRejectionSource = + | { type: 'hook' } + | { type: 'user_abort' } + | { type: 'user_reject'; hasFeedback: boolean } + +// Generic interface for permission queue operations, decoupled from React. +// In the REPL, these are backed by React state. +type PermissionQueueOps = { + push(item: ToolUseConfirm): void + remove(toolUseID: string): void + update(toolUseID: string, patch: Partial): void +} + +type ResolveOnce = { + resolve(value: T): void + isResolved(): boolean + /** + * Atomically check-and-mark as resolved. Returns true if this caller + * won the race (nobody else has resolved yet), false otherwise. + * Use this in async callbacks BEFORE awaiting, to close the window + * between the `isResolved()` check and the actual `resolve()` call. + */ + claim(): boolean +} + +function createResolveOnce(resolve: (value: T) => void): ResolveOnce { + let claimed = false + let delivered = false + return { + resolve(value: T) { + if (delivered) return + delivered = true + claimed = true + resolve(value) + }, + isResolved() { + return claimed + }, + claim() { + if (claimed) return false + claimed = true + return true + }, + } +} + +function createPermissionContext( + tool: ToolType, + input: Record, + toolUseContext: ToolUseContext, + assistantMessage: AssistantMessage, + toolUseID: string, + setToolPermissionContext: (context: ToolPermissionContext) => void, + queueOps?: PermissionQueueOps, +) { + const messageId = assistantMessage.message.id + const ctx = { + tool, + input, + toolUseContext, + assistantMessage, + messageId, + toolUseID, + logDecision( + args: PermissionDecisionArgs, + opts?: { + input?: Record + permissionPromptStartTimeMs?: number + }, + ) { + logPermissionDecision( + { + tool, + input: opts?.input ?? input, + toolUseContext, + messageId, + toolUseID, + }, + args, + opts?.permissionPromptStartTimeMs, + ) + }, + logCancelled() { + logEvent('tengu_tool_use_cancelled', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + }) + }, + async persistPermissions(updates: PermissionUpdate[]) { + if (updates.length === 0) return false + persistPermissionUpdates(updates) + const appState = toolUseContext.getAppState() + setToolPermissionContext( + applyPermissionUpdates(appState.toolPermissionContext, updates), + ) + return updates.some(update => supportsPersistence(update.destination)) + }, + resolveIfAborted(resolve: (decision: PermissionDecision) => void) { + if (!toolUseContext.abortController.signal.aborted) return false + this.logCancelled() + resolve(this.cancelAndAbort(undefined, true)) + return true + }, + cancelAndAbort( + feedback?: string, + isAbort?: boolean, + contentBlocks?: ContentBlockParam[], + ): PermissionDecision { + const sub = !!toolUseContext.agentId + const baseMessage = feedback + ? `${sub ? SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX : REJECT_MESSAGE_WITH_REASON_PREFIX}${feedback}` + : sub + ? SUBAGENT_REJECT_MESSAGE + : REJECT_MESSAGE + const message = sub ? baseMessage : withMemoryCorrectionHint(baseMessage) + if (isAbort || (!feedback && !contentBlocks?.length && !sub)) { + logForDebugging( + `Aborting: tool=${tool.name} isAbort=${isAbort} hasFeedback=${!!feedback} isSubagent=${sub}`, + ) + toolUseContext.abortController.abort() + } + return { behavior: 'ask', message, contentBlocks } + }, + ...(feature('BASH_CLASSIFIER') + ? { + async tryClassifier( + pendingClassifierCheck: PendingClassifierCheck | undefined, + updatedInput: Record | undefined, + ): Promise { + if (tool.name !== BASH_TOOL_NAME || !pendingClassifierCheck) { + return null + } + const classifierDecision = await awaitClassifierAutoApproval( + pendingClassifierCheck, + toolUseContext.abortController.signal, + toolUseContext.options.isNonInteractiveSession, + ) + if (!classifierDecision) { + return null + } + if ( + feature('TRANSCRIPT_CLASSIFIER') && + classifierDecision.type === 'classifier' + ) { + const matchedRule = classifierDecision.reason.match( + /^Allowed by prompt rule: "(.+)"$/, + )?.[1] + if (matchedRule) { + setClassifierApproval(toolUseID, matchedRule) + } + } + logPermissionDecision( + { tool, input, toolUseContext, messageId, toolUseID }, + { decision: 'accept', source: { type: 'classifier' } }, + undefined, + ) + return { + behavior: 'allow' as const, + updatedInput: updatedInput ?? input, + userModified: false, + decisionReason: classifierDecision, + } + }, + } + : {}), + async runHooks( + permissionMode: string | undefined, + suggestions: PermissionUpdate[] | undefined, + updatedInput?: Record, + permissionPromptStartTimeMs?: number, + ): Promise { + for await (const hookResult of executePermissionRequestHooks( + tool.name, + toolUseID, + input, + toolUseContext, + permissionMode, + suggestions, + toolUseContext.abortController.signal, + )) { + if (hookResult.permissionRequestResult) { + const decision = hookResult.permissionRequestResult + if (decision.behavior === 'allow') { + const finalInput = decision.updatedInput ?? updatedInput ?? input + return await this.handleHookAllow( + finalInput, + decision.updatedPermissions ?? [], + permissionPromptStartTimeMs, + ) + } else if (decision.behavior === 'deny') { + this.logDecision( + { decision: 'reject', source: { type: 'hook' } }, + { permissionPromptStartTimeMs }, + ) + if (decision.interrupt) { + logForDebugging( + `Hook interrupt: tool=${tool.name} hookMessage=${decision.message}`, + ) + toolUseContext.abortController.abort() + } + return this.buildDeny( + decision.message || 'Permission denied by hook', + { + type: 'hook', + hookName: 'PermissionRequest', + reason: decision.message, + }, + ) + } + } + } + return null + }, + buildAllow( + updatedInput: Record, + opts?: { + userModified?: boolean + decisionReason?: PermissionDecisionReason + acceptFeedback?: string + contentBlocks?: ContentBlockParam[] + }, + ): PermissionAllowDecision { + return { + behavior: 'allow' as const, + updatedInput, + userModified: opts?.userModified ?? false, + ...(opts?.decisionReason && { decisionReason: opts.decisionReason }), + ...(opts?.acceptFeedback && { acceptFeedback: opts.acceptFeedback }), + ...(opts?.contentBlocks && + opts.contentBlocks.length > 0 && { + contentBlocks: opts.contentBlocks, + }), + } + }, + buildDeny( + message: string, + decisionReason: PermissionDecisionReason, + ): PermissionDenyDecision { + return { behavior: 'deny' as const, message, decisionReason } + }, + async handleUserAllow( + updatedInput: Record, + permissionUpdates: PermissionUpdate[], + feedback?: string, + permissionPromptStartTimeMs?: number, + contentBlocks?: ContentBlockParam[], + decisionReason?: PermissionDecisionReason, + ): Promise { + const acceptedPermanentUpdates = + await this.persistPermissions(permissionUpdates) + this.logDecision( + { + decision: 'accept', + source: { type: 'user', permanent: acceptedPermanentUpdates }, + }, + { input: updatedInput, permissionPromptStartTimeMs }, + ) + const userModified = tool.inputsEquivalent + ? !tool.inputsEquivalent(input, updatedInput) + : false + const trimmedFeedback = feedback?.trim() + return this.buildAllow(updatedInput, { + userModified, + decisionReason, + acceptFeedback: trimmedFeedback || undefined, + contentBlocks, + }) + }, + async handleHookAllow( + finalInput: Record, + permissionUpdates: PermissionUpdate[], + permissionPromptStartTimeMs?: number, + ): Promise { + const acceptedPermanentUpdates = + await this.persistPermissions(permissionUpdates) + this.logDecision( + { + decision: 'accept', + source: { type: 'hook', permanent: acceptedPermanentUpdates }, + }, + { input: finalInput, permissionPromptStartTimeMs }, + ) + return this.buildAllow(finalInput, { + decisionReason: { type: 'hook', hookName: 'PermissionRequest' }, + }) + }, + pushToQueue(item: ToolUseConfirm) { + queueOps?.push(item) + }, + removeFromQueue() { + queueOps?.remove(toolUseID) + }, + updateQueueItem(patch: Partial) { + queueOps?.update(toolUseID, patch) + }, + } + return Object.freeze(ctx) +} + +type PermissionContext = ReturnType + +/** + * Create a PermissionQueueOps backed by a React state setter. + * This is the bridge between React's `setToolUseConfirmQueue` and the + * generic queue interface used by PermissionContext. + */ +function createPermissionQueueOps( + setToolUseConfirmQueue: React.Dispatch< + React.SetStateAction + >, +): PermissionQueueOps { + return { + push(item: ToolUseConfirm) { + setToolUseConfirmQueue(queue => [...queue, item]) + }, + remove(toolUseID: string) { + setToolUseConfirmQueue(queue => + queue.filter(item => item.toolUseID !== toolUseID), + ) + }, + update(toolUseID: string, patch: Partial) { + setToolUseConfirmQueue(queue => + queue.map(item => + item.toolUseID === toolUseID ? { ...item, ...patch } : item, + ), + ) + }, + } +} + +export { createPermissionContext, createPermissionQueueOps, createResolveOnce } +export type { + PermissionContext, + PermissionApprovalSource, + PermissionQueueOps, + PermissionRejectionSource, + ResolveOnce, +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useCanUseTool.tsx b/_all-in-one-upload/cc-haha/src/hooks/useCanUseTool.tsx new file mode 100644 index 0000000..1eb77d5 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useCanUseTool.tsx @@ -0,0 +1,204 @@ +import { c as _c } from "react/compiler-runtime"; +import { feature } from 'bun:bundle'; +import { APIUserAbortError } from '@anthropic-ai/sdk'; +import * as React from 'react'; +import { useCallback } from 'react'; +import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js'; +import { sanitizeToolNameForAnalytics } from 'src/services/analytics/metadata.js'; +import type { ToolUseConfirm } from '../components/permissions/PermissionRequest.js'; +import { Text } from '../ink.js'; +import type { ToolPermissionContext, Tool as ToolType, ToolUseContext } from '../Tool.js'; +import { consumeSpeculativeClassifierCheck, peekSpeculativeClassifierCheck } from '../tools/BashTool/bashPermissions.js'; +import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js'; +import type { AssistantMessage } from '../types/message.js'; +import { recordAutoModeDenial } from '../utils/autoModeDenials.js'; +import { clearClassifierChecking, setClassifierApproval, setYoloClassifierApproval } from '../utils/classifierApprovals.js'; +import { logForDebugging } from '../utils/debug.js'; +import { AbortError } from '../utils/errors.js'; +import { logError } from '../utils/log.js'; +import type { PermissionDecision } from '../utils/permissions/PermissionResult.js'; +import { hasPermissionsToUseTool } from '../utils/permissions/permissions.js'; +import { jsonStringify } from '../utils/slowOperations.js'; +import { handleCoordinatorPermission } from './toolPermission/handlers/coordinatorHandler.js'; +import { handleInteractivePermission } from './toolPermission/handlers/interactiveHandler.js'; +import { handleSwarmWorkerPermission } from './toolPermission/handlers/swarmWorkerHandler.js'; +import { createPermissionContext, createPermissionQueueOps } from './toolPermission/PermissionContext.js'; +import { logPermissionDecision } from './toolPermission/permissionLogging.js'; +export type CanUseToolFn = Record> = (tool: ToolType, input: Input, toolUseContext: ToolUseContext, assistantMessage: AssistantMessage, toolUseID: string, forceDecision?: PermissionDecision) => Promise>; +function useCanUseTool(setToolUseConfirmQueue, setToolPermissionContext) { + const $ = _c(3); + let t0; + if ($[0] !== setToolPermissionContext || $[1] !== setToolUseConfirmQueue) { + t0 = async (tool, input, toolUseContext, assistantMessage, toolUseID, forceDecision) => new Promise(resolve => { + const ctx = createPermissionContext(tool, input, toolUseContext, assistantMessage, toolUseID, setToolPermissionContext, createPermissionQueueOps(setToolUseConfirmQueue)); + if (ctx.resolveIfAborted(resolve)) { + return; + } + const decisionPromise = forceDecision !== undefined ? Promise.resolve(forceDecision) : hasPermissionsToUseTool(tool, input, toolUseContext, assistantMessage, toolUseID); + return decisionPromise.then(async result => { + if (result.behavior === "allow") { + if (ctx.resolveIfAborted(resolve)) { + return; + } + if (feature("TRANSCRIPT_CLASSIFIER") && result.decisionReason?.type === "classifier" && result.decisionReason.classifier === "auto-mode") { + setYoloClassifierApproval(toolUseID, result.decisionReason.reason); + } + ctx.logDecision({ + decision: "accept", + source: "config" + }); + resolve(ctx.buildAllow(result.updatedInput ?? input, { + decisionReason: result.decisionReason + })); + return; + } + const appState = toolUseContext.getAppState(); + const description = await tool.description(input as never, { + isNonInteractiveSession: toolUseContext.options.isNonInteractiveSession, + toolPermissionContext: appState.toolPermissionContext, + tools: toolUseContext.options.tools + }); + if (ctx.resolveIfAborted(resolve)) { + return; + } + switch (result.behavior) { + case "deny": + { + logPermissionDecision({ + tool, + input, + toolUseContext, + messageId: ctx.messageId, + toolUseID + }, { + decision: "reject", + source: "config" + }); + if (feature("TRANSCRIPT_CLASSIFIER") && result.decisionReason?.type === "classifier" && result.decisionReason.classifier === "auto-mode") { + recordAutoModeDenial({ + toolName: tool.name, + display: description, + reason: result.decisionReason.reason ?? "", + timestamp: Date.now() + }); + toolUseContext.addNotification?.({ + key: "auto-mode-denied", + priority: "immediate", + jsx: <>{tool.userFacingName(input).toLowerCase()} denied by auto mode · /permissions + }); + } + resolve(result); + return; + } + case "ask": + { + if (appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog) { + const coordinatorDecision = await handleCoordinatorPermission({ + ctx, + ...(feature("BASH_CLASSIFIER") ? { + pendingClassifierCheck: result.pendingClassifierCheck + } : {}), + updatedInput: result.updatedInput, + suggestions: result.suggestions, + permissionMode: appState.toolPermissionContext.mode + }); + if (coordinatorDecision) { + resolve(coordinatorDecision); + return; + } + } + if (ctx.resolveIfAborted(resolve)) { + return; + } + const swarmDecision = await handleSwarmWorkerPermission({ + ctx, + description, + ...(feature("BASH_CLASSIFIER") ? { + pendingClassifierCheck: result.pendingClassifierCheck + } : {}), + updatedInput: result.updatedInput, + suggestions: result.suggestions + }); + if (swarmDecision) { + resolve(swarmDecision); + return; + } + if (feature("BASH_CLASSIFIER") && result.pendingClassifierCheck && tool.name === BASH_TOOL_NAME && !appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog) { + const speculativePromise = peekSpeculativeClassifierCheck((input as { + command: string; + }).command); + if (speculativePromise) { + const raceResult = await Promise.race([speculativePromise.then(_temp), new Promise(_temp2)]); + if (ctx.resolveIfAborted(resolve)) { + return; + } + if (raceResult.type === "result" && raceResult.result.matches && raceResult.result.confidence === "high" && feature("BASH_CLASSIFIER")) { + consumeSpeculativeClassifierCheck((input as { + command: string; + }).command); + const matchedRule = raceResult.result.matchedDescription ?? undefined; + if (matchedRule) { + setClassifierApproval(toolUseID, matchedRule); + } + ctx.logDecision({ + decision: "accept", + source: { + type: "classifier" + } + }); + resolve(ctx.buildAllow(result.updatedInput ?? input as Record, { + decisionReason: { + type: "classifier" as const, + classifier: "bash_allow" as const, + reason: `Allowed by prompt rule: "${raceResult.result.matchedDescription}"` + } + })); + return; + } + } + } + handleInteractivePermission({ + ctx, + description, + result, + awaitAutomatedChecksBeforeDialog: appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog, + bridgeCallbacks: feature("BRIDGE_MODE") ? appState.replBridgePermissionCallbacks : undefined, + channelCallbacks: feature("KAIROS") || feature("KAIROS_CHANNELS") ? appState.channelPermissionCallbacks : undefined + }, resolve); + return; + } + } + }).catch(error => { + if (error instanceof AbortError || error instanceof APIUserAbortError) { + logForDebugging(`Permission check threw ${error.constructor.name} for tool=${tool.name}: ${error.message}`); + ctx.logCancelled(); + resolve(ctx.cancelAndAbort(undefined, true)); + } else { + logError(error); + resolve(ctx.cancelAndAbort(undefined, true)); + } + }).finally(() => { + clearClassifierChecking(toolUseID); + }); + }); + $[0] = setToolPermissionContext; + $[1] = setToolUseConfirmQueue; + $[2] = t0; + } else { + t0 = $[2]; + } + return t0; +} +function _temp2(res) { + return setTimeout(res, 2000, { + type: "timeout" as const + }); +} +function _temp(r) { + return { + type: "result" as const, + result: r + }; +} +export default useCanUseTool; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiQVBJVXNlckFib3J0RXJyb3IiLCJSZWFjdCIsInVzZUNhbGxiYWNrIiwiQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyIsImxvZ0V2ZW50Iiwic2FuaXRpemVUb29sTmFtZUZvckFuYWx5dGljcyIsIlRvb2xVc2VDb25maXJtIiwiVGV4dCIsIlRvb2xQZXJtaXNzaW9uQ29udGV4dCIsIlRvb2wiLCJUb29sVHlwZSIsIlRvb2xVc2VDb250ZXh0IiwiY29uc3VtZVNwZWN1bGF0aXZlQ2xhc3NpZmllckNoZWNrIiwicGVla1NwZWN1bGF0aXZlQ2xhc3NpZmllckNoZWNrIiwiQkFTSF9UT09MX05BTUUiLCJBc3Npc3RhbnRNZXNzYWdlIiwicmVjb3JkQXV0b01vZGVEZW5pYWwiLCJjbGVhckNsYXNzaWZpZXJDaGVja2luZyIsInNldENsYXNzaWZpZXJBcHByb3ZhbCIsInNldFlvbG9DbGFzc2lmaWVyQXBwcm92YWwiLCJsb2dGb3JEZWJ1Z2dpbmciLCJBYm9ydEVycm9yIiwibG9nRXJyb3IiLCJQZXJtaXNzaW9uRGVjaXNpb24iLCJoYXNQZXJtaXNzaW9uc1RvVXNlVG9vbCIsImpzb25TdHJpbmdpZnkiLCJoYW5kbGVDb29yZGluYXRvclBlcm1pc3Npb24iLCJoYW5kbGVJbnRlcmFjdGl2ZVBlcm1pc3Npb24iLCJoYW5kbGVTd2FybVdvcmtlclBlcm1pc3Npb24iLCJjcmVhdGVQZXJtaXNzaW9uQ29udGV4dCIsImNyZWF0ZVBlcm1pc3Npb25RdWV1ZU9wcyIsImxvZ1Blcm1pc3Npb25EZWNpc2lvbiIsIkNhblVzZVRvb2xGbiIsIlJlY29yZCIsInRvb2wiLCJpbnB1dCIsIklucHV0IiwidG9vbFVzZUNvbnRleHQiLCJhc3Npc3RhbnRNZXNzYWdlIiwidG9vbFVzZUlEIiwiZm9yY2VEZWNpc2lvbiIsIlByb21pc2UiLCJ1c2VDYW5Vc2VUb29sIiwic2V0VG9vbFVzZUNvbmZpcm1RdWV1ZSIsInNldFRvb2xQZXJtaXNzaW9uQ29udGV4dCIsIiQiLCJfYyIsInQwIiwicmVzb2x2ZSIsImN0eCIsInJlc29sdmVJZkFib3J0ZWQiLCJkZWNpc2lvblByb21pc2UiLCJ1bmRlZmluZWQiLCJ0aGVuIiwicmVzdWx0IiwiYmVoYXZpb3IiLCJkZWNpc2lvblJlYXNvbiIsInR5cGUiLCJjbGFzc2lmaWVyIiwicmVhc29uIiwibG9nRGVjaXNpb24iLCJkZWNpc2lvbiIsInNvdXJjZSIsImJ1aWxkQWxsb3ciLCJ1cGRhdGVkSW5wdXQiLCJhcHBTdGF0ZSIsImdldEFwcFN0YXRlIiwiZGVzY3JpcHRpb24iLCJpc05vbkludGVyYWN0aXZlU2Vzc2lvbiIsIm9wdGlvbnMiLCJ0b29sUGVybWlzc2lvbkNvbnRleHQiLCJ0b29scyIsIm1lc3NhZ2VJZCIsInRvb2xOYW1lIiwibmFtZSIsImRpc3BsYXkiLCJ0aW1lc3RhbXAiLCJEYXRlIiwibm93IiwiYWRkTm90aWZpY2F0aW9uIiwia2V5IiwicHJpb3JpdHkiLCJqc3giLCJ1c2VyRmFjaW5nTmFtZSIsInRvTG93ZXJDYXNlIiwiYXdhaXRBdXRvbWF0ZWRDaGVja3NCZWZvcmVEaWFsb2ciLCJjb29yZGluYXRvckRlY2lzaW9uIiwicGVuZGluZ0NsYXNzaWZpZXJDaGVjayIsInN1Z2dlc3Rpb25zIiwicGVybWlzc2lvbk1vZGUiLCJtb2RlIiwic3dhcm1EZWNpc2lvbiIsInNwZWN1bGF0aXZlUHJvbWlzZSIsImNvbW1hbmQiLCJyYWNlUmVzdWx0IiwicmFjZSIsIl90ZW1wIiwiX3RlbXAyIiwibWF0Y2hlcyIsImNvbmZpZGVuY2UiLCJtYXRjaGVkUnVsZSIsIm1hdGNoZWREZXNjcmlwdGlvbiIsImNvbnN0IiwiYnJpZGdlQ2FsbGJhY2tzIiwicmVwbEJyaWRnZVBlcm1pc3Npb25DYWxsYmFja3MiLCJjaGFubmVsQ2FsbGJhY2tzIiwiY2hhbm5lbFBlcm1pc3Npb25DYWxsYmFja3MiLCJjYXRjaCIsImVycm9yIiwiY29uc3RydWN0b3IiLCJtZXNzYWdlIiwibG9nQ2FuY2VsbGVkIiwiY2FuY2VsQW5kQWJvcnQiLCJmaW5hbGx5IiwicmVzIiwic2V0VGltZW91dCIsInIiXSwic291cmNlcyI6WyJ1c2VDYW5Vc2VUb29sLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmZWF0dXJlIH0gZnJvbSAnYnVuOmJ1bmRsZSdcbmltcG9ydCB7IEFQSVVzZXJBYm9ydEVycm9yIH0gZnJvbSAnQGFudGhyb3BpYy1haS9zZGsnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUNhbGxiYWNrIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQge1xuICB0eXBlIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMsXG4gIGxvZ0V2ZW50LFxufSBmcm9tICdzcmMvc2VydmljZXMvYW5hbHl0aWNzL2luZGV4LmpzJ1xuaW1wb3J0IHsgc2FuaXRpemVUb29sTmFtZUZvckFuYWx5dGljcyB9IGZyb20gJ3NyYy9zZXJ2aWNlcy9hbmFseXRpY3MvbWV0YWRhdGEuanMnXG5pbXBvcnQgdHlwZSB7IFRvb2xVc2VDb25maXJtIH0gZnJvbSAnLi4vY29tcG9uZW50cy9wZXJtaXNzaW9ucy9QZXJtaXNzaW9uUmVxdWVzdC5qcydcbmltcG9ydCB7IFRleHQgfSBmcm9tICcuLi9pbmsuanMnXG5pbXBvcnQgdHlwZSB7XG4gIFRvb2xQZXJtaXNzaW9uQ29udGV4dCxcbiAgVG9vbCBhcyBUb29sVHlwZSxcbiAgVG9vbFVzZUNvbnRleHQsXG59IGZyb20gJy4uL1Rvb2wuanMnXG5pbXBvcnQge1xuICBjb25zdW1lU3BlY3VsYXRpdmVDbGFzc2lmaWVyQ2hlY2ssXG4gIHBlZWtTcGVjdWxhdGl2ZUNsYXNzaWZpZXJDaGVjayxcbn0gZnJvbSAnLi4vdG9vbHMvQmFzaFRvb2wvYmFzaFBlcm1pc3Npb25zLmpzJ1xuaW1wb3J0IHsgQkFTSF9UT09MX05BTUUgfSBmcm9tICcuLi90b29scy9CYXNoVG9vbC90b29sTmFtZS5qcydcbmltcG9ydCB0eXBlIHsgQXNzaXN0YW50TWVzc2FnZSB9IGZyb20gJy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgeyByZWNvcmRBdXRvTW9kZURlbmlhbCB9IGZyb20gJy4uL3V0aWxzL2F1dG9Nb2RlRGVuaWFscy5qcydcbmltcG9ydCB7XG4gIGNsZWFyQ2xhc3NpZmllckNoZWNraW5nLFxuICBzZXRDbGFzc2lmaWVyQXBwcm92YWwsXG4gIHNldFlvbG9DbGFzc2lmaWVyQXBwcm92YWwsXG59IGZyb20gJy4uL3V0aWxzL2NsYXNzaWZpZXJBcHByb3ZhbHMuanMnXG5pbXBvcnQgeyBsb2dGb3JEZWJ1Z2dpbmcgfSBmcm9tICcuLi91dGlscy9kZWJ1Zy5qcydcbmltcG9ydCB7IEFib3J0RXJyb3IgfSBmcm9tICcuLi91dGlscy9lcnJvcnMuanMnXG5pbXBvcnQgeyBsb2dFcnJvciB9IGZyb20gJy4uL3V0aWxzL2xvZy5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvbkRlY2lzaW9uIH0gZnJvbSAnLi4vdXRpbHMvcGVybWlzc2lvbnMvUGVybWlzc2lvblJlc3VsdC5qcydcbmltcG9ydCB7IGhhc1Blcm1pc3Npb25zVG9Vc2VUb29sIH0gZnJvbSAnLi4vdXRpbHMvcGVybWlzc2lvbnMvcGVybWlzc2lvbnMuanMnXG5pbXBvcnQgeyBqc29uU3RyaW5naWZ5IH0gZnJvbSAnLi4vdXRpbHMvc2xvd09wZXJhdGlvbnMuanMnXG5pbXBvcnQgeyBoYW5kbGVDb29yZGluYXRvclBlcm1pc3Npb24gfSBmcm9tICcuL3Rvb2xQZXJtaXNzaW9uL2hhbmRsZXJzL2Nvb3JkaW5hdG9ySGFuZGxlci5qcydcbmltcG9ydCB7IGhhbmRsZUludGVyYWN0aXZlUGVybWlzc2lvbiB9IGZyb20gJy4vdG9vbFBlcm1pc3Npb24vaGFuZGxlcnMvaW50ZXJhY3RpdmVIYW5kbGVyLmpzJ1xuaW1wb3J0IHsgaGFuZGxlU3dhcm1Xb3JrZXJQZXJtaXNzaW9uIH0gZnJvbSAnLi90b29sUGVybWlzc2lvbi9oYW5kbGVycy9zd2FybVdvcmtlckhhbmRsZXIuanMnXG5pbXBvcnQge1xuICBjcmVhdGVQZXJtaXNzaW9uQ29udGV4dCxcbiAgY3JlYXRlUGVybWlzc2lvblF1ZXVlT3BzLFxufSBmcm9tICcuL3Rvb2xQZXJtaXNzaW9uL1Blcm1pc3Npb25Db250ZXh0LmpzJ1xuaW1wb3J0IHsgbG9nUGVybWlzc2lvbkRlY2lzaW9uIH0gZnJvbSAnLi90b29sUGVybWlzc2lvbi9wZXJtaXNzaW9uTG9nZ2luZy5qcydcblxuZXhwb3J0IHR5cGUgQ2FuVXNlVG9vbEZuPFxuICBJbnB1dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4+ID0gKFxuICB0b29sOiBUb29sVHlwZSxcbiAgaW5wdXQ6IElucHV0LFxuICB0b29sVXNlQ29udGV4dDogVG9vbFVzZUNvbnRleHQsXG4gIGFzc2lzdGFudE1lc3NhZ2U6IEFzc2lzdGFudE1lc3NhZ2UsXG4gIHRvb2xVc2VJRDogc3RyaW5nLFxuICBmb3JjZURlY2lzaW9uPzogUGVybWlzc2lvbkRlY2lzaW9uPElucHV0PixcbikgPT4gUHJvbWlzZTxQZXJtaXNzaW9uRGVjaXNpb248SW5wdXQ+PlxuXG5mdW5jdGlvbiB1c2VDYW5Vc2VUb29sKFxuICBzZXRUb29sVXNlQ29uZmlybVF1ZXVlOiBSZWFjdC5EaXNwYXRjaDxcbiAgICBSZWFjdC5TZXRTdGF0ZUFjdGlvbjxUb29sVXNlQ29uZmlybVtdPlxuICA+LFxuICBzZXRUb29sUGVybWlzc2lvbkNvbnRleHQ6IChjb250ZXh0OiBUb29sUGVybWlzc2lvbkNvbnRleHQpID0+IHZvaWQsXG4pOiBDYW5Vc2VUb29sRm4ge1xuICByZXR1cm4gdXNlQ2FsbGJhY2s8Q2FuVXNlVG9vbEZuPihcbiAgICBhc3luYyAoXG4gICAgICB0b29sLFxuICAgICAgaW5wdXQsXG4gICAgICB0b29sVXNlQ29udGV4dCxcbiAgICAgIGFzc2lzdGFudE1lc3NhZ2UsXG4gICAgICB0b29sVXNlSUQsXG4gICAgICBmb3JjZURlY2lzaW9uLFxuICAgICkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICBjb25zdCBjdHggPSBjcmVhdGVQZXJtaXNzaW9uQ29udGV4dChcbiAgICAgICAgICB0b29sLFxuICAgICAgICAgIGlucHV0LFxuICAgICAgICAgIHRvb2xVc2VDb250ZXh0LFxuICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2UsXG4gICAgICAgICAgdG9vbFVzZUlELFxuICAgICAgICAgIHNldFRvb2xQZXJtaXNzaW9uQ29udGV4dCxcbiAgICAgICAgICBjcmVhdGVQZXJtaXNzaW9uUXVldWVPcHMoc2V0VG9vbFVzZUNvbmZpcm1RdWV1ZSksXG4gICAgICAgIClcblxuICAgICAgICBpZiAoY3R4LnJlc29sdmVJZkFib3J0ZWQocmVzb2x2ZSkpIHJldHVyblxuXG4gICAgICAgIGNvbnN0IGRlY2lzaW9uUHJvbWlzZSA9XG4gICAgICAgICAgZm9yY2VEZWNpc2lvbiAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IFByb21pc2UucmVzb2x2ZShmb3JjZURlY2lzaW9uKVxuICAgICAgICAgICAgOiBoYXNQZXJtaXNzaW9uc1RvVXNlVG9vbChcbiAgICAgICAgICAgICAgICB0b29sLFxuICAgICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICAgIHRvb2xVc2VDb250ZXh0LFxuICAgICAgICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgdG9vbFVzZUlELFxuICAgICAgICAgICAgICApXG5cbiAgICAgICAgcmV0dXJuIGRlY2lzaW9uUHJvbWlzZVxuICAgICAgICAgIC50aGVuKGFzeW5jIHJlc3VsdCA9PiB7XG4gICAgICAgICAgICAvLyBbQU5ULU9OTFldIExvZyBhbGwgdG9vbCBwZXJtaXNzaW9uIGRlY2lzaW9ucyB3aXRoIHRvb2wgbmFtZSBhbmQgYXJnc1xuICAgICAgICAgICAgaWYgKFwiZXh0ZXJuYWxcIiA9PT0gJ2FudCcpIHtcbiAgICAgICAgICAgICAgbG9nRXZlbnQoJ3Rlbmd1X2ludGVybmFsX3Rvb2xfcGVybWlzc2lvbl9kZWNpc2lvbicsIHtcbiAgICAgICAgICAgICAgICB0b29sTmFtZTogc2FuaXRpemVUb29sTmFtZUZvckFuYWx5dGljcyh0b29sLm5hbWUpLFxuICAgICAgICAgICAgICAgIGJlaGF2aW9yOlxuICAgICAgICAgICAgICAgICAgcmVzdWx0LmJlaGF2aW9yIGFzIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMsXG4gICAgICAgICAgICAgICAgLy8gTm90ZTogaW5wdXQgY29udGFpbnMgY29kZS9maWxlcGF0aHMsIG9ubHkgbG9nIGZvciBhbnRzXG4gICAgICAgICAgICAgICAgaW5wdXQ6IGpzb25TdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgICAgICApIGFzIEFuYWx5dGljc01ldGFkYXRhX0lfVkVSSUZJRURfVEhJU19JU19OT1RfQ09ERV9PUl9GSUxFUEFUSFMsXG4gICAgICAgICAgICAgICAgbWVzc2FnZUlEOlxuICAgICAgICAgICAgICAgICAgY3R4Lm1lc3NhZ2VJZCBhcyBBbmFseXRpY3NNZXRhZGF0YV9JX1ZFUklGSUVEX1RISVNfSVNfTk9UX0NPREVfT1JfRklMRVBBVEhTLFxuICAgICAgICAgICAgICAgIGlzTWNwOiB0b29sLmlzTWNwID8/IGZhbHNlLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIYXMgcGVybWlzc2lvbnMgdG8gdXNlIHRvb2wsIGdyYW50ZWQgaW4gY29uZmlnXG4gICAgICAgICAgICBpZiAocmVzdWx0LmJlaGF2aW9yID09PSAnYWxsb3cnKSB7XG4gICAgICAgICAgICAgIGlmIChjdHgucmVzb2x2ZUlmQWJvcnRlZChyZXNvbHZlKSkgcmV0dXJuXG4gICAgICAgICAgICAgIC8vIFRyYWNrIGF1dG8gbW9kZSBjbGFzc2lmaWVyIGFwcHJvdmFscyBmb3IgVUkgZGlzcGxheVxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgZmVhdHVyZSgnVFJBTlNDUklQVF9DTEFTU0lGSUVSJykgJiZcbiAgICAgICAgICAgICAgICByZXN1bHQuZGVjaXNpb25SZWFzb24/LnR5cGUgPT09ICdjbGFzc2lmaWVyJyAmJlxuICAgICAgICAgICAgICAgIHJlc3VsdC5kZWNpc2lvblJlYXNvbi5jbGFzc2lmaWVyID09PSAnYXV0by1tb2RlJ1xuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBzZXRZb2xvQ2xhc3NpZmllckFwcHJvdmFsKFxuICAgICAgICAgICAgICAgICAgdG9vbFVzZUlELFxuICAgICAgICAgICAgICAgICAgcmVzdWx0LmRlY2lzaW9uUmVhc29uLnJlYXNvbixcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBjdHgubG9nRGVjaXNpb24oeyBkZWNpc2lvbjogJ2FjY2VwdCcsIHNvdXJjZTogJ2NvbmZpZycgfSlcblxuICAgICAgICAgICAgICByZXNvbHZlKFxuICAgICAgICAgICAgICAgIGN0eC5idWlsZEFsbG93KHJlc3VsdC51cGRhdGVkSW5wdXQgPz8gaW5wdXQsIHtcbiAgICAgICAgICAgICAgICAgIGRlY2lzaW9uUmVhc29uOiByZXN1bHQuZGVjaXNpb25SZWFzb24sXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGFwcFN0YXRlID0gdG9vbFVzZUNvbnRleHQuZ2V0QXBwU3RhdGUoKVxuICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBhd2FpdCB0b29sLmRlc2NyaXB0aW9uKGlucHV0IGFzIG5ldmVyLCB7XG4gICAgICAgICAgICAgIGlzTm9uSW50ZXJhY3RpdmVTZXNzaW9uOlxuICAgICAgICAgICAgICAgIHRvb2xVc2VDb250ZXh0Lm9wdGlvbnMuaXNOb25JbnRlcmFjdGl2ZVNlc3Npb24sXG4gICAgICAgICAgICAgIHRvb2xQZXJtaXNzaW9uQ29udGV4dDogYXBwU3RhdGUudG9vbFBlcm1pc3Npb25Db250ZXh0LFxuICAgICAgICAgICAgICB0b29sczogdG9vbFVzZUNvbnRleHQub3B0aW9ucy50b29scyxcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIGlmIChjdHgucmVzb2x2ZUlmQWJvcnRlZChyZXNvbHZlKSkgcmV0dXJuXG5cbiAgICAgICAgICAgIC8vIERvZXMgbm90IGhhdmUgcGVybWlzc2lvbnMgdG8gdXNlIHRvb2wsIGNoZWNrIHRoZSBiZWhhdmlvclxuICAgICAgICAgICAgc3dpdGNoIChyZXN1bHQuYmVoYXZpb3IpIHtcbiAgICAgICAgICAgICAgY2FzZSAnZGVueSc6IHtcbiAgICAgICAgICAgICAgICBsb2dQZXJtaXNzaW9uRGVjaXNpb24oXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHRvb2wsXG4gICAgICAgICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICAgICAgICB0b29sVXNlQ29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUlkOiBjdHgubWVzc2FnZUlkLFxuICAgICAgICAgICAgICAgICAgICB0b29sVXNlSUQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgeyBkZWNpc2lvbjogJ3JlamVjdCcsIHNvdXJjZTogJ2NvbmZpZycgfSxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgZmVhdHVyZSgnVFJBTlNDUklQVF9DTEFTU0lGSUVSJykgJiZcbiAgICAgICAgICAgICAgICAgIHJlc3VsdC5kZWNpc2lvblJlYXNvbj8udHlwZSA9PT0gJ2NsYXNzaWZpZXInICYmXG4gICAgICAgICAgICAgICAgICByZXN1bHQuZGVjaXNpb25SZWFzb24uY2xhc3NpZmllciA9PT0gJ2F1dG8tbW9kZSdcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIHJlY29yZEF1dG9Nb2RlRGVuaWFsKHtcbiAgICAgICAgICAgICAgICAgICAgdG9vbE5hbWU6IHRvb2wubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogcmVzdWx0LmRlY2lzaW9uUmVhc29uLnJlYXNvbiA/PyAnJyxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIHRvb2xVc2VDb250ZXh0LmFkZE5vdGlmaWNhdGlvbj8uKHtcbiAgICAgICAgICAgICAgICAgICAga2V5OiAnYXV0by1tb2RlLWRlbmllZCcsXG4gICAgICAgICAgICAgICAgICAgIHByaW9yaXR5OiAnaW1tZWRpYXRlJyxcbiAgICAgICAgICAgICAgICAgICAganN4OiAoXG4gICAgICAgICAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxUZXh0IGNvbG9yPVwiZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAge3Rvb2wudXNlckZhY2luZ05hbWUoaW5wdXQpLnRvTG93ZXJDYXNlKCl9IGRlbmllZCBieVxuICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvIG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPiDCtyAvcGVybWlzc2lvbnM8L1RleHQ+XG4gICAgICAgICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3VsdClcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGNhc2UgJ2Fzayc6IHtcbiAgICAgICAgICAgICAgICAvLyBGb3IgY29vcmRpbmF0b3Igd29ya2VycywgYXdhaXQgYXV0b21hdGVkIGNoZWNrcyBiZWZvcmUgc2hvd2luZyBkaWFsb2cuXG4gICAgICAgICAgICAgICAgLy8gQmFja2dyb3VuZCB3b3JrZXJzIHNob3VsZCBvbmx5IGludGVycnVwdCB0aGUgdXNlciB3aGVuIGF1dG9tYXRlZCBjaGVja3MgY2FuJ3QgZGVjaWRlLlxuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIGFwcFN0YXRlLnRvb2xQZXJtaXNzaW9uQ29udGV4dFxuICAgICAgICAgICAgICAgICAgICAuYXdhaXRBdXRvbWF0ZWRDaGVja3NCZWZvcmVEaWFsb2dcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGNvb3JkaW5hdG9yRGVjaXNpb24gPSBhd2FpdCBoYW5kbGVDb29yZGluYXRvclBlcm1pc3Npb24oXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBjdHgsXG4gICAgICAgICAgICAgICAgICAgICAgLi4uKGZlYXR1cmUoJ0JBU0hfQ0xBU1NJRklFUicpXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZW5kaW5nQ2xhc3NpZmllckNoZWNrOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnBlbmRpbmdDbGFzc2lmaWVyQ2hlY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZWRJbnB1dDogcmVzdWx0LnVwZGF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9uczogcmVzdWx0LnN1Z2dlc3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb25Nb2RlOiBhcHBTdGF0ZS50b29sUGVybWlzc2lvbkNvbnRleHQubW9kZSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgIGlmIChjb29yZGluYXRvckRlY2lzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY29vcmRpbmF0b3JEZWNpc2lvbilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAvLyBudWxsIG1lYW5zIG5laXRoZXIgYXV0b21hdGVkIGNoZWNrIHJlc29sdmVkIC0tIGZhbGwgdGhyb3VnaCB0byBkaWFsb2cgYmVsb3cuXG4gICAgICAgICAgICAgICAgICAvLyBIb29rcyBhbHJlYWR5IHJhbiwgY2xhc3NpZmllciBhbHJlYWR5IGNvbnN1bWVkLlxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFmdGVyIGF3YWl0aW5nIGF1dG9tYXRlZCBjaGVja3MsIHZlcmlmeSB0aGUgcmVxdWVzdCB3YXNuJ3QgYWJvcnRlZFxuICAgICAgICAgICAgICAgIC8vIHdoaWxlIHdlIHdlcmUgd2FpdGluZy4gV2l0aG91dCB0aGlzIGNoZWNrLCBhIHN0YWxlIGRpYWxvZyBjb3VsZCBhcHBlYXIuXG4gICAgICAgICAgICAgICAgaWYgKGN0eC5yZXNvbHZlSWZBYm9ydGVkKHJlc29sdmUpKSByZXR1cm5cblxuICAgICAgICAgICAgICAgIC8vIEZvciBzd2FybSB3b3JrZXJzLCB0cnkgY2xhc3NpZmllciBhdXRvLWFwcHJvdmFsIHRoZW5cbiAgICAgICAgICAgICAgICAvLyBmb3J3YXJkIHBlcm1pc3Npb24gcmVxdWVzdHMgdG8gdGhlIGxlYWRlciB2aWEgbWFpbGJveC5cbiAgICAgICAgICAgICAgICBjb25zdCBzd2FybURlY2lzaW9uID0gYXdhaXQgaGFuZGxlU3dhcm1Xb3JrZXJQZXJtaXNzaW9uKHtcbiAgICAgICAgICAgICAgICAgIGN0eCxcbiAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgICAgICAgLi4uKGZlYXR1cmUoJ0JBU0hfQ0xBU1NJRklFUicpXG4gICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ0NsYXNzaWZpZXJDaGVjazogcmVzdWx0LnBlbmRpbmdDbGFzc2lmaWVyQ2hlY2ssXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAgICAgICAgIHVwZGF0ZWRJbnB1dDogcmVzdWx0LnVwZGF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zOiByZXN1bHQuc3VnZ2VzdGlvbnMsXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICBpZiAoc3dhcm1EZWNpc2lvbikge1xuICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzd2FybURlY2lzaW9uKVxuICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gR3JhY2UgcGVyaW9kOiB3YWl0IHVwIHRvIDJzIGZvciBzcGVjdWxhdGl2ZSBjbGFzc2lmaWVyXG4gICAgICAgICAgICAgICAgLy8gdG8gcmVzb2x2ZSBiZWZvcmUgc2hvd2luZyB0aGUgZGlhbG9nIChtYWluIGFnZW50IG9ubHkpXG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgZmVhdHVyZSgnQkFTSF9DTEFTU0lGSUVSJykgJiZcbiAgICAgICAgICAgICAgICAgIHJlc3VsdC5wZW5kaW5nQ2xhc3NpZmllckNoZWNrICYmXG4gICAgICAgICAgICAgICAgICB0b29sLm5hbWUgPT09IEJBU0hfVE9PTF9OQU1FICYmXG4gICAgICAgICAgICAgICAgICAhYXBwU3RhdGUudG9vbFBlcm1pc3Npb25Db250ZXh0XG4gICAgICAgICAgICAgICAgICAgIC5hd2FpdEF1dG9tYXRlZENoZWNrc0JlZm9yZURpYWxvZ1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgY29uc3Qgc3BlY3VsYXRpdmVQcm9taXNlID0gcGVla1NwZWN1bGF0aXZlQ2xhc3NpZmllckNoZWNrKFxuICAgICAgICAgICAgICAgICAgICAoaW5wdXQgYXMgeyBjb21tYW5kOiBzdHJpbmcgfSkuY29tbWFuZCxcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgIGlmIChzcGVjdWxhdGl2ZVByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFjZVJlc3VsdCA9IGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgICAgICAgICAgICAgICAgc3BlY3VsYXRpdmVQcm9taXNlLnRoZW4ociA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3Jlc3VsdCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQ6IHIsXG4gICAgICAgICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlPHsgdHlwZTogJ3RpbWVvdXQnIH0+KHJlcyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtc3ludGF4IC0tIHJlc29sdmVzIHdpdGggYSB2YWx1ZSwgbm90IHZvaWRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQocmVzLCAyMDAwLCB7IHR5cGU6ICd0aW1lb3V0JyBhcyBjb25zdCB9KSxcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBdKVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdHgucmVzb2x2ZUlmQWJvcnRlZChyZXNvbHZlKSkgcmV0dXJuXG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgIHJhY2VSZXN1bHQudHlwZSA9PT0gJ3Jlc3VsdCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICByYWNlUmVzdWx0LnJlc3VsdC5tYXRjaGVzICYmXG4gICAgICAgICAgICAgICAgICAgICAgcmFjZVJlc3VsdC5yZXN1bHQuY29uZmlkZW5jZSA9PT0gJ2hpZ2gnICYmXG4gICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZSgnQkFTSF9DTEFTU0lGSUVSJylcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gQ2xhc3NpZmllciBhcHByb3ZlZCB3aXRoaW4gZ3JhY2UgcGVyaW9kIOKAlCBza2lwIGRpYWxvZ1xuICAgICAgICAgICAgICAgICAgICAgIHZvaWQgY29uc3VtZVNwZWN1bGF0aXZlQ2xhc3NpZmllckNoZWNrKFxuICAgICAgICAgICAgICAgICAgICAgICAgKGlucHV0IGFzIHsgY29tbWFuZDogc3RyaW5nIH0pLmNvbW1hbmQsXG4gICAgICAgICAgICAgICAgICAgICAgKVxuXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0Y2hlZFJ1bGUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgcmFjZVJlc3VsdC5yZXN1bHQubWF0Y2hlZERlc2NyaXB0aW9uID8/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVkUnVsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0Q2xhc3NpZmllckFwcHJvdmFsKHRvb2xVc2VJRCwgbWF0Y2hlZFJ1bGUpXG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgY3R4LmxvZ0RlY2lzaW9uKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY2lzaW9uOiAnYWNjZXB0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogeyB0eXBlOiAnY2xhc3NpZmllcicgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoXG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYnVpbGRBbGxvdyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnVwZGF0ZWRJbnB1dCA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbnB1dCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpc2lvblJlYXNvbjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NsYXNzaWZpZXInIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NpZmllcjogJ2Jhc2hfYWxsb3cnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiBgQWxsb3dlZCBieSBwcm9tcHQgcnVsZTogXCIke3JhY2VSZXN1bHQucmVzdWx0Lm1hdGNoZWREZXNjcmlwdGlvbn1cImAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIFRpbWVvdXQgb3Igbm8gbWF0Y2gg4oCUIGZhbGwgdGhyb3VnaCB0byBzaG93IGRpYWxvZ1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFNob3cgZGlhbG9nIGFuZCBzdGFydCBob29rcy9jbGFzc2lmaWVyIGluIGJhY2tncm91bmRcbiAgICAgICAgICAgICAgICBoYW5kbGVJbnRlcmFjdGl2ZVBlcm1pc3Npb24oXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCxcbiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgICAgICAgICAgYXdhaXRBdXRvbWF0ZWRDaGVja3NCZWZvcmVEaWFsb2c6XG4gICAgICAgICAgICAgICAgICAgICAgYXBwU3RhdGUudG9vbFBlcm1pc3Npb25Db250ZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICAuYXdhaXRBdXRvbWF0ZWRDaGVja3NCZWZvcmVEaWFsb2csXG4gICAgICAgICAgICAgICAgICAgIGJyaWRnZUNhbGxiYWNrczogZmVhdHVyZSgnQlJJREdFX01PREUnKVxuICAgICAgICAgICAgICAgICAgICAgID8gYXBwU3RhdGUucmVwbEJyaWRnZVBlcm1pc3Npb25DYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbENhbGxiYWNrczpcbiAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlKCdLQUlST1MnKSB8fCBmZWF0dXJlKCdLQUlST1NfQ0hBTk5FTFMnKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyBhcHBTdGF0ZS5jaGFubmVsUGVybWlzc2lvbkNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgICAgICAgICApXG5cbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBBYm9ydEVycm9yIHx8XG4gICAgICAgICAgICAgIGVycm9yIGluc3RhbmNlb2YgQVBJVXNlckFib3J0RXJyb3JcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBsb2dGb3JEZWJ1Z2dpbmcoXG4gICAgICAgICAgICAgICAgYFBlcm1pc3Npb24gY2hlY2sgdGhyZXcgJHtlcnJvci5jb25zdHJ1Y3Rvci5uYW1lfSBmb3IgdG9vbD0ke3Rvb2wubmFtZX06ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIGN0eC5sb2dDYW5jZWxsZWQoKVxuICAgICAgICAgICAgICByZXNvbHZlKGN0eC5jYW5jZWxBbmRBYm9ydCh1bmRlZmluZWQsIHRydWUpKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbG9nRXJyb3IoZXJyb3IpXG4gICAgICAgICAgICAgIHJlc29sdmUoY3R4LmNhbmNlbEFuZEFib3J0KHVuZGVmaW5lZCwgdHJ1ZSkpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICBjbGVhckNsYXNzaWZpZXJDaGVja2luZyh0b29sVXNlSUQpXG4gICAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgfSxcbiAgICBbc2V0VG9vbFVzZUNvbmZpcm1RdWV1ZSwgc2V0VG9vbFBlcm1pc3Npb25Db250ZXh0XSxcbiAgKVxufVxuXG5leHBvcnQgZGVmYXVsdCB1c2VDYW5Vc2VUb29sXG4iXSwibWFwcGluZ3MiOiI7QUFBQSxTQUFTQSxPQUFPLFFBQVEsWUFBWTtBQUNwQyxTQUFTQyxpQkFBaUIsUUFBUSxtQkFBbUI7QUFDckQsT0FBTyxLQUFLQyxLQUFLLE1BQU0sT0FBTztBQUM5QixTQUFTQyxXQUFXLFFBQVEsT0FBTztBQUNuQyxTQUNFLEtBQUtDLDBEQUEwRCxFQUMvREMsUUFBUSxRQUNILGlDQUFpQztBQUN4QyxTQUFTQyw0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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/hooks/useClipboardImageHint.ts b/_all-in-one-upload/cc-haha/src/hooks/useClipboardImageHint.ts new file mode 100644 index 0000000..48aa528 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useClipboardImageHint.ts @@ -0,0 +1,77 @@ +import { useEffect, useRef } from 'react' +import { useNotifications } from '../context/notifications.js' +import { getShortcutDisplay } from '../keybindings/shortcutFormat.js' +import { hasImageInClipboard } from '../utils/imagePaste.js' + +const NOTIFICATION_KEY = 'clipboard-image-hint' +// Small debounce to batch rapid focus changes +const FOCUS_CHECK_DEBOUNCE_MS = 1000 +// Don't show the hint more than once per this interval +const HINT_COOLDOWN_MS = 30000 + +/** + * Hook that shows a notification when the terminal regains focus + * and the clipboard contains an image. + * + * @param isFocused - Whether the terminal is currently focused + * @param enabled - Whether image paste is enabled (onImagePaste is defined) + */ +export function useClipboardImageHint( + isFocused: boolean, + enabled: boolean, +): void { + const { addNotification } = useNotifications() + const lastFocusedRef = useRef(isFocused) + const lastHintTimeRef = useRef(0) + const checkTimeoutRef = useRef(null) + + useEffect(() => { + // Only trigger on focus regain (was unfocused, now focused) + const wasFocused = lastFocusedRef.current + lastFocusedRef.current = isFocused + + if (!enabled || !isFocused || wasFocused) { + return + } + + // Clear any pending check + if (checkTimeoutRef.current) { + clearTimeout(checkTimeoutRef.current) + } + + // Small debounce to batch rapid focus changes + checkTimeoutRef.current = setTimeout( + async (checkTimeoutRef, lastHintTimeRef, addNotification) => { + checkTimeoutRef.current = null + + // Check cooldown to avoid spamming the user + const now = Date.now() + if (now - lastHintTimeRef.current < HINT_COOLDOWN_MS) { + return + } + + // Check if clipboard has an image (async osascript call) + if (await hasImageInClipboard()) { + lastHintTimeRef.current = now + addNotification({ + key: NOTIFICATION_KEY, + text: `Image in clipboard · ${getShortcutDisplay('chat:imagePaste', 'Chat', 'ctrl+v')} to paste`, + priority: 'immediate', + timeoutMs: 8000, + }) + } + }, + FOCUS_CHECK_DEBOUNCE_MS, + checkTimeoutRef, + lastHintTimeRef, + addNotification, + ) + + return () => { + if (checkTimeoutRef.current) { + clearTimeout(checkTimeoutRef.current) + checkTimeoutRef.current = null + } + } + }, [isFocused, enabled, addNotification]) +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useDiffData.ts b/_all-in-one-upload/cc-haha/src/hooks/useDiffData.ts new file mode 100644 index 0000000..176bcf0 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useDiffData.ts @@ -0,0 +1,110 @@ +import type { StructuredPatchHunk } from 'diff' +import { useEffect, useMemo, useState } from 'react' +import { + fetchGitDiff, + fetchGitDiffHunks, + type GitDiffResult, + type GitDiffStats, +} from '../utils/gitDiff.js' + +const MAX_LINES_PER_FILE = 400 + +export type DiffFile = { + path: string + linesAdded: number + linesRemoved: number + isBinary: boolean + isLargeFile: boolean + isTruncated: boolean + isNewFile?: boolean + isUntracked?: boolean +} + +export type DiffData = { + stats: GitDiffStats | null + files: DiffFile[] + hunks: Map + loading: boolean +} + +/** + * Hook to fetch current git diff data on demand. + * Fetches both stats and hunks when component mounts. + */ +export function useDiffData(): DiffData { + const [diffResult, setDiffResult] = useState(null) + const [hunks, setHunks] = useState>( + new Map(), + ) + const [loading, setLoading] = useState(true) + + // Fetch diff data on mount + useEffect(() => { + let cancelled = false + + async function loadDiffData() { + try { + // Fetch both stats and hunks + const [statsResult, hunksResult] = await Promise.all([ + fetchGitDiff(), + fetchGitDiffHunks(), + ]) + + if (!cancelled) { + setDiffResult(statsResult) + setHunks(hunksResult) + setLoading(false) + } + } catch (_error) { + if (!cancelled) { + setDiffResult(null) + setHunks(new Map()) + setLoading(false) + } + } + } + + void loadDiffData() + + return () => { + cancelled = true + } + }, []) + + return useMemo(() => { + if (!diffResult) { + return { stats: null, files: [], hunks: new Map(), loading } + } + + const { stats, perFileStats } = diffResult + const files: DiffFile[] = [] + + // Iterate over perFileStats to get all files including large/skipped ones + for (const [path, fileStats] of perFileStats) { + const fileHunks = hunks.get(path) + const isUntracked = fileStats.isUntracked ?? false + + // Detect large file (in perFileStats but not in hunks, and not binary/untracked) + const isLargeFile = !fileStats.isBinary && !isUntracked && !fileHunks + + // Detect truncated file (total > limit means we truncated) + const totalLines = fileStats.added + fileStats.removed + const isTruncated = + !isLargeFile && !fileStats.isBinary && totalLines > MAX_LINES_PER_FILE + + files.push({ + path, + linesAdded: fileStats.added, + linesRemoved: fileStats.removed, + isBinary: fileStats.isBinary, + isLargeFile, + isTruncated, + isUntracked, + }) + } + + files.sort((a, b) => a.path.localeCompare(b.path)) + + return { stats, files, hunks, loading: false } + }, [diffResult, hunks, loading]) +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useExitOnCtrlCDWithKeybindings.ts b/_all-in-one-upload/cc-haha/src/hooks/useExitOnCtrlCDWithKeybindings.ts new file mode 100644 index 0000000..7f30f55 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useExitOnCtrlCDWithKeybindings.ts @@ -0,0 +1,24 @@ +import { useKeybindings } from '../keybindings/useKeybinding.js' +import { type ExitState, useExitOnCtrlCD } from './useExitOnCtrlCD.js' + +export type { ExitState } + +/** + * Convenience hook that wires up useExitOnCtrlCD with useKeybindings. + * + * This is the standard way to use useExitOnCtrlCD in components. + * The separation exists to avoid import cycles - useExitOnCtrlCD.ts + * doesn't import from the keybindings module directly. + * + * @param onExit - Optional custom exit handler + * @param onInterrupt - Optional callback for features to handle interrupt (ctrl+c). + * Return true if handled, false to fall through to double-press exit. + * @param isActive - Whether the keybinding is active (default true). + */ +export function useExitOnCtrlCDWithKeybindings( + onExit?: () => void, + onInterrupt?: () => boolean, + isActive?: boolean, +): ExitState { + return useExitOnCtrlCD(useKeybindings, onInterrupt, onExit, isActive) +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useIdeConnectionStatus.ts b/_all-in-one-upload/cc-haha/src/hooks/useIdeConnectionStatus.ts new file mode 100644 index 0000000..418e3dc --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useIdeConnectionStatus.ts @@ -0,0 +1,33 @@ +import { useMemo } from 'react' +import type { MCPServerConnection } from '../services/mcp/types.js' + +export type IdeStatus = 'connected' | 'disconnected' | 'pending' | null + +type IdeConnectionResult = { + status: IdeStatus + ideName: string | null +} + +export function useIdeConnectionStatus( + mcpClients?: MCPServerConnection[], +): IdeConnectionResult { + return useMemo(() => { + const ideClient = mcpClients?.find(client => client.name === 'ide') + if (!ideClient) { + return { status: null, ideName: null } + } + // Extract IDE name from config if available + const config = ideClient.config + const ideName = + config.type === 'sse-ide' || config.type === 'ws-ide' + ? config.ideName + : null + if (ideClient.type === 'connected') { + return { status: 'connected', ideName } + } + if (ideClient.type === 'pending') { + return { status: 'pending', ideName } + } + return { status: 'disconnected', ideName } + }, [mcpClients]) +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useIssueFlagBanner.ts b/_all-in-one-upload/cc-haha/src/hooks/useIssueFlagBanner.ts new file mode 100644 index 0000000..adb3083 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useIssueFlagBanner.ts @@ -0,0 +1,133 @@ +import { useMemo, useRef } from 'react' +import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js' +import type { Message } from '../types/message.js' +import { getUserMessageText } from '../utils/messages.js' + +const EXTERNAL_COMMAND_PATTERNS = [ + /\bcurl\b/, + /\bwget\b/, + /\bssh\b/, + /\bkubectl\b/, + /\bsrun\b/, + /\bdocker\b/, + /\bbq\b/, + /\bgsutil\b/, + /\bgcloud\b/, + /\baws\b/, + /\bgit\s+push\b/, + /\bgit\s+pull\b/, + /\bgit\s+fetch\b/, + /\bgh\s+(pr|issue)\b/, + /\bnc\b/, + /\bncat\b/, + /\btelnet\b/, + /\bftp\b/, +] + +const FRICTION_PATTERNS = [ + // "No," or "No!" at start — comma/exclamation implies correction tone + // (avoids "No problem", "No thanks", "No I think we should...") + /^no[,!]\s/i, + // Direct corrections about Claude's output + /\bthat'?s (wrong|incorrect|not (what|right|correct))\b/i, + /\bnot what I (asked|wanted|meant|said)\b/i, + // Referencing prior instructions Claude missed + /\bI (said|asked|wanted|told you|already said)\b/i, + // Questioning Claude's actions + /\bwhy did you\b/i, + /\byou should(n'?t| not)? have\b/i, + /\byou were supposed to\b/i, + // Explicit retry/revert of Claude's work + /\btry again\b/i, + /\b(undo|revert) (that|this|it|what you)\b/i, +] + +export function isSessionContainerCompatible(messages: Message[]): boolean { + for (const msg of messages) { + if (msg.type !== 'assistant') { + continue + } + const content = msg.message.content + if (!Array.isArray(content)) { + continue + } + for (const block of content) { + if (block.type !== 'tool_use' || !('name' in block)) { + continue + } + const toolName = block.name as string + if (toolName.startsWith('mcp__')) { + return false + } + if (toolName === BASH_TOOL_NAME) { + const input = (block as { input?: Record }).input + const command = (input?.command as string) || '' + if (EXTERNAL_COMMAND_PATTERNS.some(p => p.test(command))) { + return false + } + } + } + } + return true +} + +export function hasFrictionSignal(messages: Message[]): boolean { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]! + if (msg.type !== 'user') { + continue + } + const text = getUserMessageText(msg) + if (!text) { + continue + } + return FRICTION_PATTERNS.some(p => p.test(text)) + } + return false +} + +const MIN_SUBMIT_COUNT = 3 +const COOLDOWN_MS = 30 * 60 * 1000 + +export function useIssueFlagBanner( + messages: Message[], + submitCount: number, +): boolean { + if (process.env.USER_TYPE !== 'ant') { + return false + } + + // biome-ignore lint/correctness/useHookAtTopLevel: process.env.USER_TYPE is a compile-time constant + const lastTriggeredAtRef = useRef(0) + // biome-ignore lint/correctness/useHookAtTopLevel: process.env.USER_TYPE is a compile-time constant + const activeForSubmitRef = useRef(-1) + + // Memoize the O(messages) scans. This hook runs on every REPL render + // (including every keystroke), but messages is stable during typing. + // isSessionContainerCompatible walks all messages + regex-tests each + // bash command — by far the heaviest work here. + // biome-ignore lint/correctness/useHookAtTopLevel: process.env.USER_TYPE is a compile-time constant + const shouldTrigger = useMemo( + () => isSessionContainerCompatible(messages) && hasFrictionSignal(messages), + [messages], + ) + + // Keep showing the banner until the user submits another message + if (activeForSubmitRef.current === submitCount) { + return true + } + + if (Date.now() - lastTriggeredAtRef.current < COOLDOWN_MS) { + return false + } + if (submitCount < MIN_SUBMIT_COUNT) { + return false + } + if (!shouldTrigger) { + return false + } + + lastTriggeredAtRef.current = Date.now() + activeForSubmitRef.current = submitCount + return true +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/usePluginRecommendationBase.tsx b/_all-in-one-upload/cc-haha/src/hooks/usePluginRecommendationBase.tsx new file mode 100644 index 0000000..9a2a2d4 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/usePluginRecommendationBase.tsx @@ -0,0 +1,105 @@ +import { c as _c } from "react/compiler-runtime"; +/** + * Shared state machine + install helper for plugin-recommendation hooks + * (LSP, claude-code-hint). Centralizes the gate chain, async-guard, + * and success/failure notification JSX so new sources stay small. + */ + +import figures from 'figures'; +import * as React from 'react'; +import { getIsRemoteMode } from '../bootstrap/state.js'; +import type { useNotifications } from '../context/notifications.js'; +import { Text } from '../ink.js'; +import { logError } from '../utils/log.js'; +import { getPluginById } from '../utils/plugins/marketplaceManager.js'; +type AddNotification = ReturnType['addNotification']; +type PluginData = NonNullable>>; + +/** + * Call tryResolve inside a useEffect; it applies standard gates (remote + * mode, already-showing, in-flight) then runs resolve(). Non-null return + * becomes the recommendation. Include tryResolve in effect deps — its + * identity tracks recommendation, so clearing re-triggers resolution. + */ +export function usePluginRecommendationBase() { + const $ = _c(6); + const [recommendation, setRecommendation] = React.useState(null); + const isCheckingRef = React.useRef(false); + let t0; + if ($[0] !== recommendation) { + t0 = resolve => { + if (getIsRemoteMode()) { + return; + } + if (recommendation) { + return; + } + if (isCheckingRef.current) { + return; + } + isCheckingRef.current = true; + resolve().then(rec => { + if (rec) { + setRecommendation(rec); + } + }).catch(logError).finally(() => { + isCheckingRef.current = false; + }); + }; + $[0] = recommendation; + $[1] = t0; + } else { + t0 = $[1]; + } + const tryResolve = t0; + let t1; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t1 = () => setRecommendation(null); + $[2] = t1; + } else { + t1 = $[2]; + } + const clearRecommendation = t1; + let t2; + if ($[3] !== recommendation || $[4] !== tryResolve) { + t2 = { + recommendation, + clearRecommendation, + tryResolve + }; + $[3] = recommendation; + $[4] = tryResolve; + $[5] = t2; + } else { + t2 = $[5]; + } + return t2; +} + +/** Look up plugin, run install(), emit standard success/failure notification. */ +export async function installPluginAndNotify(pluginId: string, pluginName: string, keyPrefix: string, addNotification: AddNotification, install: (pluginData: PluginData) => Promise): Promise { + try { + const pluginData = await getPluginById(pluginId); + if (!pluginData) { + throw new Error(`Plugin ${pluginId} not found in marketplace`); + } + await install(pluginData); + addNotification({ + key: `${keyPrefix}-installed`, + jsx: + {figures.tick} {pluginName} installed · restart to apply + , + priority: 'immediate', + timeoutMs: 5000 + }); + } catch (error) { + logError(error); + addNotification({ + key: `${keyPrefix}-install-failed`, + jsx: Failed to install {pluginName}, + priority: 'immediate', + timeoutMs: 5000 + }); + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmaWd1cmVzIiwiUmVhY3QiLCJnZXRJc1JlbW90ZU1vZGUiLCJ1c2VOb3RpZmljYXRpb25zIiwiVGV4dCIsImxvZ0Vycm9yIiwiZ2V0UGx1Z2luQnlJZCIsIkFkZE5vdGlmaWNhdGlvbiIsIlJldHVyblR5cGUiLCJQbHVnaW5EYXRhIiwiTm9uTnVsbGFibGUiLCJBd2FpdGVkIiwidXNlUGx1Z2luUmVjb21tZW5kYXRpb25CYXNlIiwiJCIsIl9jIiwicmVjb21tZW5kYXRpb24iLCJzZXRSZWNvbW1lbmRhdGlvbiIsInVzZVN0YXRlIiwiaXNDaGVja2luZ1JlZiIsInVzZVJlZiIsInQwIiwicmVzb2x2ZSIsImN1cnJlbnQiLCJ0aGVuIiwicmVjIiwiY2F0Y2giLCJmaW5hbGx5IiwidHJ5UmVzb2x2ZSIsInQxIiwiU3ltYm9sIiwiZm9yIiwiY2xlYXJSZWNvbW1lbmRhdGlvbiIsInQyIiwiaW5zdGFsbFBsdWdpbkFuZE5vdGlmeSIsInBsdWdpbklkIiwicGx1Z2luTmFtZSIsImtleVByZWZpeCIsImFkZE5vdGlmaWNhdGlvbiIsImluc3RhbGwiLCJwbHVnaW5EYXRhIiwiUHJvbWlzZSIsIkVycm9yIiwia2V5IiwianN4IiwidGljayIsInByaW9yaXR5IiwidGltZW91dE1zIiwiZXJyb3IiXSwic291cmNlcyI6WyJ1c2VQbHVnaW5SZWNvbW1lbmRhdGlvbkJhc2UudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU2hhcmVkIHN0YXRlIG1hY2hpbmUgKyBpbnN0YWxsIGhlbHBlciBmb3IgcGx1Z2luLXJlY29tbWVuZGF0aW9uIGhvb2tzXG4gKiAoTFNQLCBjbGF1ZGUtY29kZS1oaW50KS4gQ2VudHJhbGl6ZXMgdGhlIGdhdGUgY2hhaW4sIGFzeW5jLWd1YXJkLFxuICogYW5kIHN1Y2Nlc3MvZmFpbHVyZSBub3RpZmljYXRpb24gSlNYIHNvIG5ldyBzb3VyY2VzIHN0YXkgc21hbGwuXG4gKi9cblxuaW1wb3J0IGZpZ3VyZXMgZnJvbSAnZmlndXJlcydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgZ2V0SXNSZW1vdGVNb2RlIH0gZnJvbSAnLi4vYm9vdHN0cmFwL3N0YXRlLmpzJ1xuaW1wb3J0IHR5cGUgeyB1c2VOb3RpZmljYXRpb25zIH0gZnJvbSAnLi4vY29udGV4dC9ub3RpZmljYXRpb25zLmpzJ1xuaW1wb3J0IHsgVGV4dCB9IGZyb20gJy4uL2luay5qcydcbmltcG9ydCB7IGxvZ0Vycm9yIH0gZnJvbSAnLi4vdXRpbHMvbG9nLmpzJ1xuaW1wb3J0IHsgZ2V0UGx1Z2luQnlJZCB9IGZyb20gJy4uL3V0aWxzL3BsdWdpbnMvbWFya2V0cGxhY2VNYW5hZ2VyLmpzJ1xuXG50eXBlIEFkZE5vdGlmaWNhdGlvbiA9IFJldHVyblR5cGU8dHlwZW9mIHVzZU5vdGlmaWNhdGlvbnM+WydhZGROb3RpZmljYXRpb24nXVxudHlwZSBQbHVnaW5EYXRhID0gTm9uTnVsbGFibGU8QXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBnZXRQbHVnaW5CeUlkPj4+XG5cbi8qKlxuICogQ2FsbCB0cnlSZXNvbHZlIGluc2lkZSBhIHVzZUVmZmVjdDsgaXQgYXBwbGllcyBzdGFuZGFyZCBnYXRlcyAocmVtb3RlXG4gKiBtb2RlLCBhbHJlYWR5LXNob3dpbmcsIGluLWZsaWdodCkgdGhlbiBydW5zIHJlc29sdmUoKS4gTm9uLW51bGwgcmV0dXJuXG4gKiBiZWNvbWVzIHRoZSByZWNvbW1lbmRhdGlvbi4gSW5jbHVkZSB0cnlSZXNvbHZlIGluIGVmZmVjdCBkZXBzIOKAlCBpdHNcbiAqIGlkZW50aXR5IHRyYWNrcyByZWNvbW1lbmRhdGlvbiwgc28gY2xlYXJpbmcgcmUtdHJpZ2dlcnMgcmVzb2x1dGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVBsdWdpblJlY29tbWVuZGF0aW9uQmFzZTxUPigpOiB7XG4gIHJlY29tbWVuZGF0aW9uOiBUIHwgbnVsbFxuICBjbGVhclJlY29tbWVuZGF0aW9uOiAoKSA9PiB2b2lkXG4gIHRyeVJlc29sdmU6IChyZXNvbHZlOiAoKSA9PiBQcm9taXNlPFQgfCBudWxsPikgPT4gdm9pZFxufSB7XG4gIGNvbnN0IFtyZWNvbW1lbmRhdGlvbiwgc2V0UmVjb21tZW5kYXRpb25dID0gUmVhY3QudXNlU3RhdGU8VCB8IG51bGw+KG51bGwpXG4gIGNvbnN0IGlzQ2hlY2tpbmdSZWYgPSBSZWFjdC51c2VSZWYoZmFsc2UpXG5cbiAgY29uc3QgdHJ5UmVzb2x2ZSA9IFJlYWN0LnVzZUNhbGxiYWNrKFxuICAgIChyZXNvbHZlOiAoKSA9PiBQcm9taXNlPFQgfCBudWxsPikgPT4ge1xuICAgICAgaWYgKGdldElzUmVtb3RlTW9kZSgpKSByZXR1cm5cbiAgICAgIGlmIChyZWNvbW1lbmRhdGlvbikgcmV0dXJuXG4gICAgICBpZiAoaXNDaGVja2luZ1JlZi5jdXJyZW50KSByZXR1cm5cblxuICAgICAgaXNDaGVja2luZ1JlZi5jdXJyZW50ID0gdHJ1ZVxuICAgICAgdm9pZCByZXNvbHZlKClcbiAgICAgICAgLnRoZW4ocmVjID0+IHtcbiAgICAgICAgICBpZiAocmVjKSBzZXRSZWNvbW1lbmRhdGlvbihyZWMpXG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChsb2dFcnJvcilcbiAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgIGlzQ2hlY2tpbmdSZWYuY3VycmVudCA9IGZhbHNlXG4gICAgICAgIH0pXG4gICAgfSxcbiAgICBbcmVjb21tZW5kYXRpb25dLFxuICApXG5cbiAgY29uc3QgY2xlYXJSZWNvbW1lbmRhdGlvbiA9IFJlYWN0LnVzZUNhbGxiYWNrKFxuICAgICgpID0+IHNldFJlY29tbWVuZGF0aW9uKG51bGwpLFxuICAgIFtdLFxuICApXG5cbiAgcmV0dXJuIHsgcmVjb21tZW5kYXRpb24sIGNsZWFyUmVjb21tZW5kYXRpb24sIHRyeVJlc29sdmUgfVxufVxuXG4vKiogTG9vayB1cCBwbHVnaW4sIHJ1biBpbnN0YWxsKCksIGVtaXQgc3RhbmRhcmQgc3VjY2Vzcy9mYWlsdXJlIG5vdGlmaWNhdGlvbi4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsUGx1Z2luQW5kTm90aWZ5KFxuICBwbHVnaW5JZDogc3RyaW5nLFxuICBwbHVnaW5OYW1lOiBzdHJpbmcsXG4gIGtleVByZWZpeDogc3RyaW5nLFxuICBhZGROb3RpZmljYXRpb246IEFkZE5vdGlmaWNhdGlvbixcbiAgaW5zdGFsbDogKHBsdWdpbkRhdGE6IFBsdWdpbkRhdGEpID0+IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwbHVnaW5EYXRhID0gYXdhaXQgZ2V0UGx1Z2luQnlJZChwbHVnaW5JZClcbiAgICBpZiAoIXBsdWdpbkRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUGx1Z2luICR7cGx1Z2luSWR9IG5vdCBmb3VuZCBpbiBtYXJrZXRwbGFjZWApXG4gICAgfVxuICAgIGF3YWl0IGluc3RhbGwocGx1Z2luRGF0YSlcbiAgICBhZGROb3RpZmljYXRpb24oe1xuICAgICAga2V5OiBgJHtrZXlQcmVmaXh9LWluc3RhbGxlZGAsXG4gICAgICBqc3g6IChcbiAgICAgICAgPFRleHQgY29sb3I9XCJzdWNjZXNzXCI+XG4gICAgICAgICAge2ZpZ3VyZXMudGlja30ge3BsdWdpbk5hbWV9IGluc3RhbGxlZCDCtyByZXN0YXJ0IHRvIGFwcGx5XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICksXG4gICAgICBwcmlvcml0eTogJ2ltbWVkaWF0ZScsXG4gICAgICB0aW1lb3V0TXM6IDUwMDAsXG4gICAgfSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dFcnJvcihlcnJvcilcbiAgICBhZGROb3RpZmljYXRpb24oe1xuICAgICAga2V5OiBgJHtrZXlQcmVmaXh9LWluc3RhbGwtZmFpbGVkYCxcbiAgICAgIGpzeDogPFRleHQgY29sb3I9XCJlcnJvclwiPkZhaWxlZCB0byBpbnN0YWxsIHtwbHVnaW5OYW1lfTwvVGV4dD4sXG4gICAgICBwcmlvcml0eTogJ2ltbWVkaWF0ZScsXG4gICAgICB0aW1lb3V0TXM6IDUwMDAsXG4gICAgfSlcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxPQUFPQSxPQUFPLE1BQU0sU0FBUztBQUM3QixPQUFPLEtBQUtDLEtBQUssTUFBTSxPQUFPO0FBQzlCLFNBQVNDLGVBQWUsUUFBUSx1QkFBdUI7QUFDdkQsY0FBY0MsZ0JBQWdCLFFBQVEsNkJBQTZCO0FBQ25FLFNBQVNDLElBQUksUUFBUSxXQUFXO0FBQ2hDLFNBQVNDLFFBQVEsUUFBUSxpQkFBaUI7QUFDMUMsU0FBU0MsYUFBYSxRQUFRLHdDQUF3QztBQUV0RSxLQUFLQyxlQUFlLEdBQUdDLFVBQVUsQ0FBQyxPQUFPTCxnQkFBZ0IsQ0FBQyxDQUFDLGlCQUFpQixDQUFDO0FBQzdFLEtBQUtNLFVBQVUsR0FBR0MsV0FBVyxDQUFDQyxPQUFPLENBQUNILFVBQVUsQ0FBQyxPQUFPRixhQUFhLENBQUMsQ0FBQyxDQUFDOztBQUV4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQUFNLDRCQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBS0wsT0FBQUMsY0FBQSxFQUFBQyxpQkFBQSxJQUE0Q2YsS0FBSyxDQUFBZ0IsUUFBUyxDQUFXLElBQUksQ0FBQztFQUMxRSxNQUFBQyxhQUFBLEdBQXNCakIsS0FBSyxDQUFBa0IsTUFBTyxDQUFDLEtBQUssQ0FBQztFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBUCxDQUFBLFFBQUFFLGNBQUE7SUFHdkNLLEVBQUEsR0FBQUMsT0FBQTtNQUNFLElBQUluQixlQUFlLENBQUMsQ0FBQztRQUFBO01BQUE7TUFDckIsSUFBSWEsY0FBYztRQUFBO01BQUE7TUFDbEIsSUFBSUcsYUFBYSxDQUFBSSxPQUFRO1FBQUE7TUFBQTtNQUV6QkosYUFBYSxDQUFBSSxPQUFBLEdBQVcsSUFBSDtNQUNoQkQsT0FBTyxDQUFDLENBQUMsQ0FBQUUsSUFDUCxDQUFDQyxHQUFBO1FBQ0osSUFBSUEsR0FBRztVQUFFUixpQkFBaUIsQ0FBQ1EsR0FBRyxDQUFDO1FBQUE7TUFBQSxDQUNoQyxDQUFDLENBQUFDLEtBQ0ksQ0FBQ3BCLFFBQVEsQ0FBQyxDQUFBcUIsT0FDUixDQUFDO1FBQ1BSLGFBQWEsQ0FBQUksT0FBQSxHQUFXLEtBQUg7TUFBQSxDQUN0QixDQUFDO0lBQUEsQ0FDTDtJQUFBVCxDQUFBLE1BQUFFLGNBQUE7SUFBQUYsQ0FBQSxNQUFBTyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBUCxDQUFBO0VBQUE7RUFmSCxNQUFBYyxVQUFBLEdBQW1CUCxFQWlCbEI7RUFBQSxJQUFBUSxFQUFBO0VBQUEsSUFBQWYsQ0FBQSxRQUFBZ0IsTUFBQSxDQUFBQyxHQUFBO0lBR0NGLEVBQUEsR0FBQUEsQ0FBQSxLQUFNWixpQkFBaUIsQ0FBQyxJQUFJLENBQUM7SUFBQUgsQ0FBQSxNQUFBZSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBZixDQUFBO0VBQUE7RUFEL0IsTUFBQWtCLG1CQUFBLEdBQTRCSCxFQUczQjtFQUFBLElBQUFJLEVBQUE7RUFBQSxJQUFBbkIsQ0FBQSxRQUFBRSxjQUFBLElBQUFGLENBQUEsUUFBQWMsVUFBQTtJQUVNSyxFQUFBO01BQUFqQixjQUFBO01BQUFnQixtQkFBQTtNQUFBSjtJQUFrRCxDQUFDO0lBQUFkLENBQUEsTUFBQUUsY0FBQTtJQUFBRixDQUFBLE1BQUFjLFVBQUE7SUFBQWQsQ0FBQSxNQUFBbUIsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQW5CLENBQUE7RUFBQTtFQUFBLE9BQW5EbUIsRUFBbUQ7QUFBQTs7QUFHNUQ7QUFDQSxPQUFPLGVBQWVDLHNCQUFzQkEsQ0FDMUNDLFFBQVEsRUFBRSxNQUFNLEVBQ2hCQyxVQUFVLEVBQUUsTUFBTSxFQUNsQkMsU0FBUyxFQUFFLE1BQU0sRUFDakJDLGVBQWUsRUFBRTlCLGVBQWUsRUFDaEMrQixPQUFPLEVBQUUsQ0FBQ0MsVUFBVSxFQUFFOUIsVUFBVSxFQUFFLEdBQUcrQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQ25ELEVBQUVBLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztFQUNmLElBQUk7SUFDRixNQUFNRCxVQUFVLEdBQUcsTUFBTWpDLGFBQWEsQ0FBQzRCLFFBQVEsQ0FBQztJQUNoRCxJQUFJLENBQUNLLFVBQVUsRUFBRTtNQUNmLE1BQU0sSUFBSUUsS0FBSyxDQUFDLFVBQVVQLFFBQVEsMkJBQTJCLENBQUM7SUFDaEU7SUFDQSxNQUFNSSxPQUFPLENBQUNDLFVBQVUsQ0FBQztJQUN6QkYsZUFBZSxDQUFDO01BQ2RLLEdBQUcsRUFBRSxHQUFHTixTQUFTLFlBQVk7TUFDN0JPLEdBQUcsRUFDRCxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUztBQUM3QixVQUFVLENBQUMzQyxPQUFPLENBQUM0QyxJQUFJLENBQUMsQ0FBQyxDQUFDVCxVQUFVLENBQUM7QUFDckMsUUFBUSxFQUFFLElBQUksQ0FDUDtNQUNEVSxRQUFRLEVBQUUsV0FBVztNQUNyQkMsU0FBUyxFQUFFO0lBQ2IsQ0FBQyxDQUFDO0VBQ0osQ0FBQyxDQUFDLE9BQU9DLEtBQUssRUFBRTtJQUNkMUMsUUFBUSxDQUFDMEMsS0FBSyxDQUFDO0lBQ2ZWLGVBQWUsQ0FBQztNQUNkSyxHQUFHLEVBQUUsR0FBR04sU0FBUyxpQkFBaUI7TUFDbENPLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDUixVQUFVLENBQUMsRUFBRSxJQUFJLENBQUM7TUFDOURVLFFBQVEsRUFBRSxXQUFXO01BQ3JCQyxTQUFTLEVBQUU7SUFDYixDQUFDLENBQUM7RUFDSjtBQUNGIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/hooks/useTerminalSize.ts b/_all-in-one-upload/cc-haha/src/hooks/useTerminalSize.ts new file mode 100644 index 0000000..68e24df --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useTerminalSize.ts @@ -0,0 +1,15 @@ +import { useContext } from 'react' +import { + type TerminalSize, + TerminalSizeContext, +} from 'src/ink/components/TerminalSizeContext.js' + +export function useTerminalSize(): TerminalSize { + const size = useContext(TerminalSizeContext) + + if (!size) { + throw new Error('useTerminalSize must be used within an Ink App component') + } + + return size +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useUpdateNotification.ts b/_all-in-one-upload/cc-haha/src/hooks/useUpdateNotification.ts new file mode 100644 index 0000000..c9a7b2a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useUpdateNotification.ts @@ -0,0 +1,34 @@ +import { useState } from 'react' +import { major, minor, patch } from 'semver' + +export function getSemverPart(version: string): string { + return `${major(version, { loose: true })}.${minor(version, { loose: true })}.${patch(version, { loose: true })}` +} + +export function shouldShowUpdateNotification( + updatedVersion: string, + lastNotifiedSemver: string | null, +): boolean { + const updatedSemver = getSemverPart(updatedVersion) + return updatedSemver !== lastNotifiedSemver +} + +export function useUpdateNotification( + updatedVersion: string | null | undefined, + initialVersion: string = MACRO.VERSION, +): string | null { + const [lastNotifiedSemver, setLastNotifiedSemver] = useState( + () => getSemverPart(initialVersion), + ) + + if (!updatedVersion) { + return null + } + + const updatedSemver = getSemverPart(updatedVersion) + if (updatedSemver !== lastNotifiedSemver) { + setLastNotifiedSemver(updatedSemver) + return updatedSemver + } + return null +} diff --git a/_all-in-one-upload/cc-haha/src/hooks/useVoiceEnabled.ts b/_all-in-one-upload/cc-haha/src/hooks/useVoiceEnabled.ts new file mode 100644 index 0000000..ece0691 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/hooks/useVoiceEnabled.ts @@ -0,0 +1,25 @@ +import { useMemo } from 'react' +import { useAppState } from '../state/AppState.js' +import { + hasVoiceAuth, + isVoiceGrowthBookEnabled, +} from '../voice/voiceModeEnabled.js' + +/** + * Combines user intent (settings.voiceEnabled) with auth + GB kill-switch. + * Only the auth half is memoized on authVersion — it's the expensive one + * (cold getClaudeAIOAuthTokens memoize → sync `security` spawn, ~60ms/call, + * ~180ms total in profile v5 when token refresh cleared the cache mid-session). + * GB is a cheap cached-map lookup and stays outside the memo so a mid-session + * kill-switch flip still takes effect on the next render. + * + * authVersion bumps on /login only. Background token refresh leaves it alone + * (user is still authed), so the auth memo stays correct without re-eval. + */ +export function useVoiceEnabled(): boolean { + const userIntent = useAppState(s => s.settings.voiceEnabled === true) + const authVersion = useAppState(s => s.authVersion) + // eslint-disable-next-line react-hooks/exhaustive-deps + const authed = useMemo(hasVoiceAuth, [authVersion]) + return userIntent && authed && isVoiceGrowthBookEnabled() +} diff --git a/_all-in-one-upload/cc-haha/src/ink/clearTerminal.ts b/_all-in-one-upload/cc-haha/src/ink/clearTerminal.ts new file mode 100644 index 0000000..38d4a68 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/clearTerminal.ts @@ -0,0 +1,74 @@ +/** + * Cross-platform terminal clearing with scrollback support. + * Detects modern terminals that support ESC[3J for clearing scrollback. + */ + +import { + CURSOR_HOME, + csi, + ERASE_SCREEN, + ERASE_SCROLLBACK, +} from './termio/csi.js' + +// HVP (Horizontal Vertical Position) - legacy Windows cursor home +const CURSOR_HOME_WINDOWS = csi(0, 'f') + +function isWindowsTerminal(): boolean { + return process.platform === 'win32' && !!process.env.WT_SESSION +} + +function isMintty(): boolean { + // mintty 3.1.5+ sets TERM_PROGRAM to 'mintty' + if (process.env.TERM_PROGRAM === 'mintty') { + return true + } + // GitBash/MSYS2/MINGW use mintty and set MSYSTEM + if (process.platform === 'win32' && process.env.MSYSTEM) { + return true + } + return false +} + +function isModernWindowsTerminal(): boolean { + // Windows Terminal sets WT_SESSION environment variable + if (isWindowsTerminal()) { + return true + } + + // VS Code integrated terminal on Windows with ConPTY support + if ( + process.platform === 'win32' && + process.env.TERM_PROGRAM === 'vscode' && + process.env.TERM_PROGRAM_VERSION + ) { + return true + } + + // mintty (GitBash/MSYS2/Cygwin) supports modern escape sequences + if (isMintty()) { + return true + } + + return false +} + +/** + * Returns the ANSI escape sequence to clear the terminal including scrollback. + * Automatically detects terminal capabilities. + */ +export function getClearTerminalSequence(): string { + if (process.platform === 'win32') { + if (isModernWindowsTerminal()) { + return ERASE_SCREEN + ERASE_SCROLLBACK + CURSOR_HOME + } else { + // Legacy Windows console - can't clear scrollback + return ERASE_SCREEN + CURSOR_HOME_WINDOWS + } + } + return ERASE_SCREEN + ERASE_SCROLLBACK + CURSOR_HOME +} + +/** + * Clears the terminal screen. On supported terminals, also clears scrollback. + */ +export const clearTerminal = getClearTerminalSequence() diff --git a/_all-in-one-upload/cc-haha/src/ink/components/RawAnsi.tsx b/_all-in-one-upload/cc-haha/src/ink/components/RawAnsi.tsx new file mode 100644 index 0000000..919e453 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/components/RawAnsi.tsx @@ -0,0 +1,57 @@ +import { c as _c } from "react/compiler-runtime"; +import React from 'react'; +type Props = { + /** + * Pre-rendered ANSI lines. Each element must be exactly one terminal row + * (already wrapped to `width` by the producer) with ANSI escape codes inline. + */ + lines: string[]; + /** Column width the producer wrapped to. Sent to Yoga as the fixed leaf width. */ + width: number; +}; + +/** + * Bypass the → React tree → Yoga → squash → re-serialize roundtrip for + * content that is already terminal-ready. + * + * Use this when an external renderer (e.g. the ColorDiff NAPI module) has + * already produced ANSI-escaped, width-wrapped output. A normal mount + * reparses that output into one React per style span, lays out each + * span as a Yoga flex child, then walks the tree to re-emit the same escape + * codes it was given. For a long transcript full of syntax-highlighted diffs + * that roundtrip is the dominant cost of the render. + * + * This component emits a single Yoga leaf with a constant-time measure func + * (width × lines.length) and hands the joined string straight to output.write(), + * which already splits on '\n' and parses ANSI into the screen buffer. + */ +export function RawAnsi(t0) { + const $ = _c(6); + const { + lines, + width + } = t0; + if (lines.length === 0) { + return null; + } + let t1; + if ($[0] !== lines) { + t1 = lines.join("\n"); + $[0] = lines; + $[1] = t1; + } else { + t1 = $[1]; + } + let t2; + if ($[2] !== lines.length || $[3] !== t1 || $[4] !== width) { + t2 = ; + $[2] = lines.length; + $[3] = t1; + $[4] = width; + $[5] = t2; + } else { + t2 = $[5]; + } + return t2; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlByb3BzIiwibGluZXMiLCJ3aWR0aCIsIlJhd0Fuc2kiLCJ0MCIsIiQiLCJfYyIsImxlbmd0aCIsInQxIiwiam9pbiIsInQyIl0sInNvdXJjZXMiOlsiUmF3QW5zaS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuXG50eXBlIFByb3BzID0ge1xuICAvKipcbiAgICogUHJlLXJlbmRlcmVkIEFOU0kgbGluZXMuIEVhY2ggZWxlbWVudCBtdXN0IGJlIGV4YWN0bHkgb25lIHRlcm1pbmFsIHJvd1xuICAgKiAoYWxyZWFkeSB3cmFwcGVkIHRvIGB3aWR0aGAgYnkgdGhlIHByb2R1Y2VyKSB3aXRoIEFOU0kgZXNjYXBlIGNvZGVzIGlubGluZS5cbiAgICovXG4gIGxpbmVzOiBzdHJpbmdbXVxuICAvKiogQ29sdW1uIHdpZHRoIHRoZSBwcm9kdWNlciB3cmFwcGVkIHRvLiBTZW50IHRvIFlvZ2EgYXMgdGhlIGZpeGVkIGxlYWYgd2lkdGguICovXG4gIHdpZHRoOiBudW1iZXJcbn1cblxuLyoqXG4gKiBCeXBhc3MgdGhlIDxBbnNpPiDihpIgUmVhY3QgdHJlZSDihpIgWW9nYSDihpIgc3F1YXNoIOKGkiByZS1zZXJpYWxpemUgcm91bmR0cmlwIGZvclxuICogY29udGVudCB0aGF0IGlzIGFscmVhZHkgdGVybWluYWwtcmVhZHkuXG4gKlxuICogVXNlIHRoaXMgd2hlbiBhbiBleHRlcm5hbCByZW5kZXJlciAoZS5nLiB0aGUgQ29sb3JEaWZmIE5BUEkgbW9kdWxlKSBoYXNcbiAqIGFscmVhZHkgcHJvZHVjZWQgQU5TSS1lc2NhcGVkLCB3aWR0aC13cmFwcGVkIG91dHB1dC4gQSBub3JtYWwgPEFuc2k+IG1vdW50XG4gKiByZXBhcnNlcyB0aGF0IG91dHB1dCBpbnRvIG9uZSBSZWFjdCA8VGV4dD4gcGVyIHN0eWxlIHNwYW4sIGxheXMgb3V0IGVhY2hcbiAqIHNwYW4gYXMgYSBZb2dhIGZsZXggY2hpbGQsIHRoZW4gd2Fsa3MgdGhlIHRyZWUgdG8gcmUtZW1pdCB0aGUgc2FtZSBlc2NhcGVcbiAqIGNvZGVzIGl0IHdhcyBnaXZlbi4gRm9yIGEgbG9uZyB0cmFuc2NyaXB0IGZ1bGwgb2Ygc3ludGF4LWhpZ2hsaWdodGVkIGRpZmZzXG4gKiB0aGF0IHJvdW5kdHJpcCBpcyB0aGUgZG9taW5hbnQgY29zdCBvZiB0aGUgcmVuZGVyLlxuICpcbiAqIFRoaXMgY29tcG9uZW50IGVtaXRzIGEgc2luZ2xlIFlvZ2EgbGVhZiB3aXRoIGEgY29uc3RhbnQtdGltZSBtZWFzdXJlIGZ1bmNcbiAqICh3aWR0aCDDlyBsaW5lcy5sZW5ndGgpIGFuZCBoYW5kcyB0aGUgam9pbmVkIHN0cmluZyBzdHJhaWdodCB0byBvdXRwdXQud3JpdGUoKSxcbiAqIHdoaWNoIGFscmVhZHkgc3BsaXRzIG9uICdcXG4nIGFuZCBwYXJzZXMgQU5TSSBpbnRvIHRoZSBzY3JlZW4gYnVmZmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmF3QW5zaSh7IGxpbmVzLCB3aWR0aCB9OiBQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGlmIChsaW5lcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIHJldHVybiAoXG4gICAgPGluay1yYXctYW5zaVxuICAgICAgcmF3VGV4dD17bGluZXMuam9pbignXFxuJyl9XG4gICAgICByYXdXaWR0aD17d2lkdGh9XG4gICAgICByYXdIZWlnaHQ9e2xpbmVzLmxlbmd0aH1cbiAgICAvPlxuICApXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPQSxLQUFLLE1BQU0sT0FBTztBQUV6QixLQUFLQyxLQUFLLEdBQUc7RUFDWDtBQUNGO0FBQ0E7QUFDQTtFQUNFQyxLQUFLLEVBQUUsTUFBTSxFQUFFO0VBQ2Y7RUFDQUMsS0FBSyxFQUFFLE1BQU07QUFDZixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU8sU0FBQUMsUUFBQUMsRUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUFpQjtJQUFBTCxLQUFBO0lBQUFDO0VBQUEsSUFBQUUsRUFBdUI7RUFDN0MsSUFBSUgsS0FBSyxDQUFBTSxNQUFPLEtBQUssQ0FBQztJQUFBLE9BQ2IsSUFBSTtFQUFBO0VBQ1osSUFBQUMsRUFBQTtFQUFBLElBQUFILENBQUEsUUFBQUosS0FBQTtJQUdZTyxFQUFBLEdBQUFQLEtBQUssQ0FBQVEsSUFBSyxDQUFDLElBQUksQ0FBQztJQUFBSixDQUFBLE1BQUFKLEtBQUE7SUFBQUksQ0FBQSxNQUFBRyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBSCxDQUFBO0VBQUE7RUFBQSxJQUFBSyxFQUFBO0VBQUEsSUFBQUwsQ0FBQSxRQUFBSixLQUFBLENBQUFNLE1BQUEsSUFBQUYsQ0FBQSxRQUFBRyxFQUFBLElBQUFILENBQUEsUUFBQUgsS0FBQTtJQUQzQlEsRUFBQSxnQkFJRSxDQUhTLE9BQWdCLENBQWhCLENBQUFGLEVBQWUsQ0FBQyxDQUNmTixRQUFLLENBQUxBLE1BQUksQ0FBQyxDQUNKLFNBQVksQ0FBWixDQUFBRCxLQUFLLENBQUFNLE1BQU0sQ0FBQyxHQUN2QjtJQUFBRixDQUFBLE1BQUFKLEtBQUEsQ0FBQU0sTUFBQTtJQUFBRixDQUFBLE1BQUFHLEVBQUE7SUFBQUgsQ0FBQSxNQUFBSCxLQUFBO0lBQUFHLENBQUEsTUFBQUssRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUwsQ0FBQTtFQUFBO0VBQUEsT0FKRkssRUFJRTtBQUFBIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/ink/events/dispatcher.ts b/_all-in-one-upload/cc-haha/src/ink/events/dispatcher.ts new file mode 100644 index 0000000..a310d38 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/events/dispatcher.ts @@ -0,0 +1,233 @@ +import { + ContinuousEventPriority, + DefaultEventPriority, + DiscreteEventPriority, + NoEventPriority, +} from 'react-reconciler/constants.js' +import { logError } from '../../utils/log.js' +import { HANDLER_FOR_EVENT } from './event-handlers.js' +import type { EventTarget, TerminalEvent } from './terminal-event.js' + +// -- + +type DispatchListener = { + node: EventTarget + handler: (event: TerminalEvent) => void + phase: 'capturing' | 'at_target' | 'bubbling' +} + +function getHandler( + node: EventTarget, + eventType: string, + capture: boolean, +): ((event: TerminalEvent) => void) | undefined { + const handlers = node._eventHandlers + if (!handlers) return undefined + + const mapping = HANDLER_FOR_EVENT[eventType] + if (!mapping) return undefined + + const propName = capture ? mapping.capture : mapping.bubble + if (!propName) return undefined + + return handlers[propName] as ((event: TerminalEvent) => void) | undefined +} + +/** + * Collect all listeners for an event in dispatch order. + * + * Uses react-dom's two-phase accumulation pattern: + * - Walk from target to root + * - Capture handlers are prepended (unshift) → root-first + * - Bubble handlers are appended (push) → target-first + * + * Result: [root-cap, ..., parent-cap, target-cap, target-bub, parent-bub, ..., root-bub] + */ +function collectListeners( + target: EventTarget, + event: TerminalEvent, +): DispatchListener[] { + const listeners: DispatchListener[] = [] + + let node: EventTarget | undefined = target + while (node) { + const isTarget = node === target + + const captureHandler = getHandler(node, event.type, true) + const bubbleHandler = getHandler(node, event.type, false) + + if (captureHandler) { + listeners.unshift({ + node, + handler: captureHandler, + phase: isTarget ? 'at_target' : 'capturing', + }) + } + + if (bubbleHandler && (event.bubbles || isTarget)) { + listeners.push({ + node, + handler: bubbleHandler, + phase: isTarget ? 'at_target' : 'bubbling', + }) + } + + node = node.parentNode + } + + return listeners +} + +/** + * Execute collected listeners with propagation control. + * + * Before each handler, calls event._prepareForTarget(node) so event + * subclasses can do per-node setup. + */ +function processDispatchQueue( + listeners: DispatchListener[], + event: TerminalEvent, +): void { + let previousNode: EventTarget | undefined + + for (const { node, handler, phase } of listeners) { + if (event._isImmediatePropagationStopped()) { + break + } + + if (event._isPropagationStopped() && node !== previousNode) { + break + } + + event._setEventPhase(phase) + event._setCurrentTarget(node) + event._prepareForTarget(node) + + try { + handler(event) + } catch (error) { + logError(error) + } + + previousNode = node + } +} + +// -- + +/** + * Map terminal event types to React scheduling priorities. + * Mirrors react-dom's getEventPriority() switch. + */ +function getEventPriority(eventType: string): number { + switch (eventType) { + case 'keydown': + case 'keyup': + case 'click': + case 'focus': + case 'blur': + case 'paste': + return DiscreteEventPriority as number + case 'resize': + case 'scroll': + case 'mousemove': + return ContinuousEventPriority as number + default: + return DefaultEventPriority as number + } +} + +// -- + +type DiscreteUpdates = ( + fn: (a: A, b: B) => boolean, + a: A, + b: B, + c: undefined, + d: undefined, +) => boolean + +/** + * Owns event dispatch state and the capture/bubble dispatch loop. + * + * The reconciler host config reads currentEvent and currentUpdatePriority + * to implement resolveUpdatePriority, resolveEventType, and + * resolveEventTimeStamp — mirroring how react-dom's host config reads + * ReactDOMSharedInternals and window.event. + * + * discreteUpdates is injected after construction (by InkReconciler) + * to break the import cycle. + */ +export class Dispatcher { + currentEvent: TerminalEvent | null = null + currentUpdatePriority: number = DefaultEventPriority as number + discreteUpdates: DiscreteUpdates | null = null + + /** + * Infer event priority from the currently-dispatching event. + * Called by the reconciler host config's resolveUpdatePriority + * when no explicit priority has been set. + */ + resolveEventPriority(): number { + if (this.currentUpdatePriority !== (NoEventPriority as number)) { + return this.currentUpdatePriority + } + if (this.currentEvent) { + return getEventPriority(this.currentEvent.type) + } + return DefaultEventPriority as number + } + + /** + * Dispatch an event through capture and bubble phases. + * Returns true if preventDefault() was NOT called. + */ + dispatch(target: EventTarget, event: TerminalEvent): boolean { + const previousEvent = this.currentEvent + this.currentEvent = event + try { + event._setTarget(target) + + const listeners = collectListeners(target, event) + processDispatchQueue(listeners, event) + + event._setEventPhase('none') + event._setCurrentTarget(null) + + return !event.defaultPrevented + } finally { + this.currentEvent = previousEvent + } + } + + /** + * Dispatch with discrete (sync) priority. + * For user-initiated events: keyboard, click, focus, paste. + */ + dispatchDiscrete(target: EventTarget, event: TerminalEvent): boolean { + if (!this.discreteUpdates) { + return this.dispatch(target, event) + } + return this.discreteUpdates( + (t, e) => this.dispatch(t, e), + target, + event, + undefined, + undefined, + ) + } + + /** + * Dispatch with continuous priority. + * For high-frequency events: resize, scroll, mouse move. + */ + dispatchContinuous(target: EventTarget, event: TerminalEvent): boolean { + const previousPriority = this.currentUpdatePriority + try { + this.currentUpdatePriority = ContinuousEventPriority as number + return this.dispatch(target, event) + } finally { + this.currentUpdatePriority = previousPriority + } + } +} diff --git a/_all-in-one-upload/cc-haha/src/ink/events/terminal-event.ts b/_all-in-one-upload/cc-haha/src/ink/events/terminal-event.ts new file mode 100644 index 0000000..9a86bf8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/events/terminal-event.ts @@ -0,0 +1,107 @@ +import { Event } from './event.js' + +type EventPhase = 'none' | 'capturing' | 'at_target' | 'bubbling' + +type TerminalEventInit = { + bubbles?: boolean + cancelable?: boolean +} + +/** + * Base class for all terminal events with DOM-style propagation. + * + * Extends Event so existing event types (ClickEvent, InputEvent, + * TerminalFocusEvent) share a common ancestor and can migrate later. + * + * Mirrors the browser's Event API: target, currentTarget, eventPhase, + * stopPropagation(), preventDefault(), timeStamp. + */ +export class TerminalEvent extends Event { + readonly type: string + readonly timeStamp: number + readonly bubbles: boolean + readonly cancelable: boolean + + private _target: EventTarget | null = null + private _currentTarget: EventTarget | null = null + private _eventPhase: EventPhase = 'none' + private _propagationStopped = false + private _defaultPrevented = false + + constructor(type: string, init?: TerminalEventInit) { + super() + this.type = type + this.timeStamp = performance.now() + this.bubbles = init?.bubbles ?? true + this.cancelable = init?.cancelable ?? true + } + + get target(): EventTarget | null { + return this._target + } + + get currentTarget(): EventTarget | null { + return this._currentTarget + } + + get eventPhase(): EventPhase { + return this._eventPhase + } + + get defaultPrevented(): boolean { + return this._defaultPrevented + } + + stopPropagation(): void { + this._propagationStopped = true + } + + override stopImmediatePropagation(): void { + super.stopImmediatePropagation() + this._propagationStopped = true + } + + preventDefault(): void { + if (this.cancelable) { + this._defaultPrevented = true + } + } + + // -- Internal setters used by the Dispatcher + + /** @internal */ + _setTarget(target: EventTarget): void { + this._target = target + } + + /** @internal */ + _setCurrentTarget(target: EventTarget | null): void { + this._currentTarget = target + } + + /** @internal */ + _setEventPhase(phase: EventPhase): void { + this._eventPhase = phase + } + + /** @internal */ + _isPropagationStopped(): boolean { + return this._propagationStopped + } + + /** @internal */ + _isImmediatePropagationStopped(): boolean { + return this.didStopImmediatePropagation() + } + + /** + * Hook for subclasses to do per-node setup before each handler fires. + * Default is a no-op. + */ + _prepareForTarget(_target: EventTarget): void {} +} + +export type EventTarget = { + parentNode: EventTarget | undefined + _eventHandlers?: Record +} diff --git a/_all-in-one-upload/cc-haha/src/ink/hooks/use-terminal-title.ts b/_all-in-one-upload/cc-haha/src/ink/hooks/use-terminal-title.ts new file mode 100644 index 0000000..d820cd7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/hooks/use-terminal-title.ts @@ -0,0 +1,31 @@ +import { useContext, useEffect } from 'react' +import stripAnsi from 'strip-ansi' +import { OSC, osc } from '../termio/osc.js' +import { TerminalWriteContext } from '../useTerminalNotification.js' + +/** + * Declaratively set the terminal tab/window title. + * + * Pass a string to set the title. ANSI escape sequences are stripped + * automatically so callers don't need to know about terminal encoding. + * Pass `null` to opt out — the hook becomes a no-op and leaves the + * terminal title untouched. + * + * On Windows, uses `process.title` (classic conhost doesn't support OSC). + * Elsewhere, writes OSC 0 (set title+icon) via Ink's stdout. + */ +export function useTerminalTitle(title: string | null): void { + const writeRaw = useContext(TerminalWriteContext) + + useEffect(() => { + if (title === null || !writeRaw) return + + const clean = stripAnsi(title) + + if (process.platform === 'win32') { + process.title = clean + } else { + writeRaw(osc(OSC.SET_TITLE_AND_ICON, clean)) + } + }, [title, writeRaw]) +} diff --git a/_all-in-one-upload/cc-haha/src/ink/layout/engine.ts b/_all-in-one-upload/cc-haha/src/ink/layout/engine.ts new file mode 100644 index 0000000..38f6dcb --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/layout/engine.ts @@ -0,0 +1,6 @@ +import type { LayoutNode } from './node.js' +import { createYogaLayoutNode } from './yoga.js' + +export function createLayoutNode(): LayoutNode { + return createYogaLayoutNode() +} diff --git a/_all-in-one-upload/cc-haha/src/ink/measure-element.ts b/_all-in-one-upload/cc-haha/src/ink/measure-element.ts new file mode 100644 index 0000000..ed56eaf --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/measure-element.ts @@ -0,0 +1,23 @@ +import type { DOMElement } from './dom.js' + +type Output = { + /** + * Element width. + */ + width: number + + /** + * Element height. + */ + height: number +} + +/** + * Measure the dimensions of a particular `` element. + */ +const measureElement = (node: DOMElement): Output => ({ + width: node.yogaNode?.getComputedWidth() ?? 0, + height: node.yogaNode?.getComputedHeight() ?? 0, +}) + +export default measureElement diff --git a/_all-in-one-upload/cc-haha/src/ink/render-node-to-output.ts b/_all-in-one-upload/cc-haha/src/ink/render-node-to-output.ts new file mode 100644 index 0000000..73bbbbe --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/ink/render-node-to-output.ts @@ -0,0 +1,1462 @@ +import indentString from 'indent-string' +import { applyTextStyles } from './colorize.js' +import type { DOMElement } from './dom.js' +import getMaxWidth from './get-max-width.js' +import type { Rectangle } from './layout/geometry.js' +import { LayoutDisplay, LayoutEdge, type LayoutNode } from './layout/node.js' +import { nodeCache, pendingClears } from './node-cache.js' +import type Output from './output.js' +import renderBorder from './render-border.js' +import type { Screen } from './screen.js' +import { + type StyledSegment, + squashTextNodesToSegments, +} from './squash-text-nodes.js' +import type { Color } from './styles.js' +import { isXtermJs } from './terminal.js' +import { widestLine } from './widest-line.js' +import wrapText from './wrap-text.js' + +// Matches detectXtermJsWheel() in ScrollKeybindingHandler.tsx — the curve +// and drain must agree on terminal detection. TERM_PROGRAM check is the sync +// fallback; isXtermJs() is the authoritative XTVERSION-probe result. +function isXtermJsHost(): boolean { + return process.env.TERM_PROGRAM === 'vscode' || isXtermJs() +} + +// Per-frame scratch: set when any node's yoga position/size differs from +// its cached value, or a child was removed. Read by ink.tsx to decide +// whether the full-damage sledgehammer (PR #20120) is needed this frame. +// Applies on both alt-screen and main-screen. Steady-state frames +// (spinner tick, clock tick, text append into a fixed-height box) don't +// shift layout → narrow damage bounds → O(changed cells) diff instead of +// O(rows×cols). +let layoutShifted = false + +export function resetLayoutShifted(): void { + layoutShifted = false +} + +export function didLayoutShift(): boolean { + return layoutShifted +} + +// DECSTBM scroll optimization hint. When a ScrollBox's scrollTop changes +// between frames (and nothing else moved), log-update.ts can emit a +// hardware scroll (DECSTBM + SU/SD) instead of rewriting the whole +// viewport. top/bottom are 0-indexed inclusive screen rows; delta > 0 = +// content moved up (scrollTop increased, CSI n S). +export type ScrollHint = { top: number; bottom: number; delta: number } +let scrollHint: ScrollHint | null = null + +// Rects of position:absolute nodes from the PREVIOUS frame, used by +// ScrollBox's blit+shift third-pass repair (see usage site). Recorded at +// three paths — full-render nodeCache.set, node-level blit early-return, +// blitEscapingAbsoluteDescendants — so clean-overlay consecutive scrolls +// still have the rect. +let absoluteRectsPrev: Rectangle[] = [] +let absoluteRectsCur: Rectangle[] = [] + +export function resetScrollHint(): void { + scrollHint = null + absoluteRectsPrev = absoluteRectsCur + absoluteRectsCur = [] +} + +export function getScrollHint(): ScrollHint | null { + return scrollHint +} + +// The ScrollBox DOM node (if any) with pendingScrollDelta left after this +// frame's drain. renderer.ts calls markDirty(it) post-render so the NEXT +// frame's root blit check fails and we descend to continue draining. +// Without this, after the scrollbox's dirty flag is cleared (line ~721), +// the next frame blits root and never reaches the scrollbox — drain stalls. +let scrollDrainNode: DOMElement | null = null + +export function resetScrollDrainNode(): void { + scrollDrainNode = null +} + +export function getScrollDrainNode(): DOMElement | null { + return scrollDrainNode +} + +// At-bottom follow scroll event this frame. When streaming content +// triggers scrollTop = maxScroll, the ScrollBox records the delta + +// viewport bounds here. ink.tsx consumes it post-render to translate any active +// text selection by -delta so the highlight stays anchored to the TEXT +// (native terminal behavior — the selection walks up the screen as content +// scrolls, eventually clipping at the top). The frontFrame screen buffer +// still holds the old content at that point — captureScrolledRows reads +// from it before the front/back swap to preserve the text for copy. +export type FollowScroll = { + delta: number + viewportTop: number + viewportBottom: number +} +let followScroll: FollowScroll | null = null + +export function consumeFollowScroll(): FollowScroll | null { + const f = followScroll + followScroll = null + return f +} + +// ── Native terminal drain (iTerm2/Ghostty/etc. — proportional events) ── +// Minimum rows applied per frame. Above this, drain is proportional (~3/4 +// of remaining) so big bursts catch up in log₄ frames while the tail +// decelerates smoothly. Hard cap is innerHeight-1 so DECSTBM hint fires. +const SCROLL_MIN_PER_FRAME = 4 + +// ── xterm.js (VS Code) smooth drain ── +// Low pending (≤5) drains ALL in one frame — slow wheel clicks should be +// instant (click → visible jump → done), not micro-stutter 1-row frames. +// Higher pending drains at a small fixed step so fast-scroll animation +// stays smooth (no big jumps). Pending >MAX snaps excess. +const SCROLL_INSTANT_THRESHOLD = 5 // ≤ this: drain all at once +const SCROLL_HIGH_PENDING = 12 // threshold for HIGH step +const SCROLL_STEP_MED = 2 // pending (INSTANT, HIGH): catch-up +const SCROLL_STEP_HIGH = 3 // pending ≥ HIGH: fast flick +const SCROLL_MAX_PENDING = 30 // snap excess beyond this + +// xterm.js adaptive drain. Returns rows applied; mutates pendingScrollDelta. +function drainAdaptive( + node: DOMElement, + pending: number, + innerHeight: number, +): number { + const sign = pending > 0 ? 1 : -1 + let abs = Math.abs(pending) + let applied = 0 + // Snap excess beyond animation window so big flicks don't coast. + if (abs > SCROLL_MAX_PENDING) { + applied += sign * (abs - SCROLL_MAX_PENDING) + abs = SCROLL_MAX_PENDING + } + // ≤5: drain all (slow click = instant). Above: small fixed step. + const step = + abs <= SCROLL_INSTANT_THRESHOLD + ? abs + : abs < SCROLL_HIGH_PENDING + ? SCROLL_STEP_MED + : SCROLL_STEP_HIGH + applied += sign * step + const rem = abs - step + // Cap total at innerHeight-1 so DECSTBM blit+shift fast path fires + // (matches drainProportional). Excess stays in pendingScrollDelta. + const cap = Math.max(1, innerHeight - 1) + const totalAbs = Math.abs(applied) + if (totalAbs > cap) { + const excess = totalAbs - cap + node.pendingScrollDelta = sign * (rem + excess) + return sign * cap + } + node.pendingScrollDelta = rem > 0 ? sign * rem : undefined + return applied +} + +// Native proportional drain. step = max(MIN, floor(abs*3/4)), capped at +// innerHeight-1 so DECSTBM + blit+shift fast path fire. +function drainProportional( + node: DOMElement, + pending: number, + innerHeight: number, +): number { + const abs = Math.abs(pending) + const cap = Math.max(1, innerHeight - 1) + const step = Math.min(cap, Math.max(SCROLL_MIN_PER_FRAME, (abs * 3) >> 2)) + if (abs <= step) { + node.pendingScrollDelta = undefined + return pending + } + const applied = pending > 0 ? step : -step + node.pendingScrollDelta = pending - applied + return applied +} + +// OSC 8 hyperlink escape sequences. Empty params (;;) — ansi-tokenize only +// recognizes this exact prefix. The id= param (for grouping wrapped lines) +// is added at terminal-output time in termio/osc.ts link(). +const OSC = '\u001B]' +const BEL = '\u0007' + +function wrapWithOsc8Link(text: string, url: string): string { + return `${OSC}8;;${url}${BEL}${text}${OSC}8;;${BEL}` +} + +/** + * Build a mapping from each character position in the plain text to its segment index. + * Returns an array where charToSegment[i] is the segment index for character i. + */ +function buildCharToSegmentMap(segments: StyledSegment[]): number[] { + const map: number[] = [] + for (let i = 0; i < segments.length; i++) { + const len = segments[i]!.text.length + for (let j = 0; j < len; j++) { + map.push(i) + } + } + return map +} + +/** + * Apply styles to wrapped text by mapping each character back to its original segment. + * This preserves per-segment styles even when text wraps across lines. + * + * @param trimEnabled - Whether whitespace trimming is enabled (wrap-trim mode). + * When true, we skip whitespace in the original that was trimmed from the output. + * When false (wrap mode), all whitespace is preserved so no skipping is needed. + */ +function applyStylesToWrappedText( + wrappedPlain: string, + segments: StyledSegment[], + charToSegment: number[], + originalPlain: string, + trimEnabled: boolean = false, +): string { + const lines = wrappedPlain.split('\n') + const resultLines: string[] = [] + + let charIndex = 0 + for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) { + const line = lines[lineIdx]! + + // In trim mode, skip leading whitespace that was trimmed from this line. + // Only skip if the original has whitespace but the output line doesn't start + // with whitespace (meaning it was trimmed). If both have whitespace, the + // whitespace was preserved and we shouldn't skip. + if (trimEnabled && line.length > 0) { + const lineStartsWithWhitespace = /\s/.test(line[0]!) + const originalHasWhitespace = + charIndex < originalPlain.length && /\s/.test(originalPlain[charIndex]!) + + // Only skip if original has whitespace but line doesn't + if (originalHasWhitespace && !lineStartsWithWhitespace) { + while ( + charIndex < originalPlain.length && + /\s/.test(originalPlain[charIndex]!) + ) { + charIndex++ + } + } + } + + let styledLine = '' + let runStart = 0 + let runSegmentIndex = charToSegment[charIndex] ?? 0 + + for (let i = 0; i < line.length; i++) { + const currentSegmentIndex = charToSegment[charIndex] ?? runSegmentIndex + + if (currentSegmentIndex !== runSegmentIndex) { + // Flush the current run + const runText = line.slice(runStart, i) + const segment = segments[runSegmentIndex] + if (segment) { + let styled = applyTextStyles(runText, segment.styles) + if (segment.hyperlink) { + styled = wrapWithOsc8Link(styled, segment.hyperlink) + } + styledLine += styled + } else { + styledLine += runText + } + runStart = i + runSegmentIndex = currentSegmentIndex + } + + charIndex++ + } + + // Flush the final run + const runText = line.slice(runStart) + const segment = segments[runSegmentIndex] + if (segment) { + let styled = applyTextStyles(runText, segment.styles) + if (segment.hyperlink) { + styled = wrapWithOsc8Link(styled, segment.hyperlink) + } + styledLine += styled + } else { + styledLine += runText + } + + resultLines.push(styledLine) + + // Skip newline character in original that corresponds to this line break. + // This is needed when the original text contains actual newlines (not just + // wrapping-inserted newlines). Without this, charIndex gets out of sync + // because the newline is in originalPlain/charToSegment but not in the + // split lines. + if (charIndex < originalPlain.length && originalPlain[charIndex] === '\n') { + charIndex++ + } + + // In trim mode, skip whitespace that was replaced by newline when wrapping. + // We skip whitespace in the original until we reach a character that matches + // the first character of the next line. This handles cases like: + // - "AB \tD" wrapped to "AB\n\tD" - skip spaces until we hit the tab + // In non-trim mode, whitespace is preserved so no skipping is needed. + if (trimEnabled && lineIdx < lines.length - 1) { + const nextLine = lines[lineIdx + 1]! + const nextLineFirstChar = nextLine.length > 0 ? nextLine[0] : null + + // Skip whitespace until we hit a char that matches the next line's first char + while ( + charIndex < originalPlain.length && + /\s/.test(originalPlain[charIndex]!) + ) { + // Stop if we found the character that starts the next line + if ( + nextLineFirstChar !== null && + originalPlain[charIndex] === nextLineFirstChar + ) { + break + } + charIndex++ + } + } + } + + return resultLines.join('\n') +} + +/** + * Wrap text and record which output lines are soft-wrap continuations + * (i.e. the `\n` before them was inserted by word-wrap, not in the + * source). wrapAnsi already processes each input line independently, so + * wrapping per-input-line here gives identical output to a single + * whole-string wrap while letting us mark per-piece provenance. + * Truncate modes never add newlines (cli-truncate is whole-string) so + * they fall through with softWrap undefined — no tracking, no behavior + * change from the pre-softWrap path. + */ +function wrapWithSoftWrap( + plainText: string, + maxWidth: number, + textWrap: Parameters[2], +): { wrapped: string; softWrap: boolean[] | undefined } { + if (textWrap !== 'wrap' && textWrap !== 'wrap-trim') { + return { + wrapped: wrapText(plainText, maxWidth, textWrap), + softWrap: undefined, + } + } + const origLines = plainText.split('\n') + const outLines: string[] = [] + const softWrap: boolean[] = [] + for (const orig of origLines) { + const pieces = wrapText(orig, maxWidth, textWrap).split('\n') + for (let i = 0; i < pieces.length; i++) { + outLines.push(pieces[i]!) + softWrap.push(i > 0) + } + } + return { wrapped: outLines.join('\n'), softWrap } +} + +// If parent container is ``, text nodes will be treated as separate nodes in +// the tree and will have their own coordinates in the layout. +// To ensure text nodes are aligned correctly, take X and Y of the first text node +// and use it as offset for the rest of the nodes +// Only first node is taken into account, because other text nodes can't have margin or padding, +// so their coordinates will be relative to the first node anyway +function applyPaddingToText( + node: DOMElement, + text: string, + softWrap?: boolean[], +): string { + const yogaNode = node.childNodes[0]?.yogaNode + + if (yogaNode) { + const offsetX = yogaNode.getComputedLeft() + const offsetY = yogaNode.getComputedTop() + text = '\n'.repeat(offsetY) + indentString(text, offsetX) + if (softWrap && offsetY > 0) { + // Prepend `false` for each padding line so indices stay aligned + // with text.split('\n'). Mutate in place — caller owns the array. + softWrap.unshift(...Array(offsetY).fill(false)) + } + } + + return text +} + +// After nodes are laid out, render each to output object, which later gets rendered to terminal +function renderNodeToOutput( + node: DOMElement, + output: Output, + { + offsetX = 0, + offsetY = 0, + prevScreen, + skipSelfBlit = false, + inheritedBackgroundColor, + }: { + offsetX?: number + offsetY?: number + prevScreen: Screen | undefined + // Force this node to descend instead of blitting its own rect, while + // still passing prevScreen to children. Used for non-opaque absolute + // overlays over a dirty clipped region: the overlay's full rect has + // transparent gaps (stale underlying content in prevScreen), but its + // opaque descendants' narrower rects are safe to blit. + skipSelfBlit?: boolean + inheritedBackgroundColor?: Color + }, +): void { + const { yogaNode } = node + + if (yogaNode) { + if (yogaNode.getDisplay() === LayoutDisplay.None) { + // Clear old position if node was visible before becoming hidden + if (node.dirty) { + const cached = nodeCache.get(node) + if (cached) { + output.clear({ + x: Math.floor(cached.x), + y: Math.floor(cached.y), + width: Math.floor(cached.width), + height: Math.floor(cached.height), + }) + // Drop descendants' cache too — hideInstance's markDirty walks UP + // only, so descendants' .dirty stays false. Their nodeCache entries + // survive with pre-hide rects. On unhide, if position didn't shift, + // the blit check at line ~432 passes and copies EMPTY cells from + // prevScreen (cleared here) → content vanishes. + dropSubtreeCache(node) + layoutShifted = true + } + } + return + } + + // Left and top positions in Yoga are relative to their parent node + const x = offsetX + yogaNode.getComputedLeft() + const yogaTop = yogaNode.getComputedTop() + let y = offsetY + yogaTop + const width = yogaNode.getComputedWidth() + const height = yogaNode.getComputedHeight() + + // Absolute-positioned overlays (e.g. autocomplete menus with bottom='100%') + // can compute negative screen y when they extend above the viewport. Without + // clamping, setCellAt drops cells at y<0, clipping the TOP of the content + // (best matches in an autocomplete). By clamping to 0, we shift the element + // down so the top rows are visible and the bottom overflows below — the + // opaque prop ensures it paints over whatever is underneath. + if (y < 0 && node.style.position === 'absolute') { + y = 0 + } + + // Check if we can skip this subtree (clean node with unchanged layout). + // Blit cells from previous screen instead of re-rendering. + const cached = nodeCache.get(node) + if ( + !node.dirty && + !skipSelfBlit && + node.pendingScrollDelta === undefined && + cached && + cached.x === x && + cached.y === y && + cached.width === width && + cached.height === height && + prevScreen + ) { + const fx = Math.floor(x) + const fy = Math.floor(y) + const fw = Math.floor(width) + const fh = Math.floor(height) + output.blit(prevScreen, fx, fy, fw, fh) + if (node.style.position === 'absolute') { + absoluteRectsCur.push(cached) + } + // Absolute descendants can paint outside this node's layout bounds + // (e.g. a slash menu with position='absolute' bottom='100%' floats + // above). If a dirty clipped sibling re-rendered and overwrote those + // cells, the blit above only restored this node's own rect — the + // absolute descendants' cells are lost. Re-blit them from prevScreen + // so the overlays survive. + blitEscapingAbsoluteDescendants(node, output, prevScreen, fx, fy, fw, fh) + return + } + + // Clear stale content from the old position when re-rendering. + // Dirty: content changed. Moved: position/size changed (e.g., sibling + // above changed height), old cells still on the terminal. + const positionChanged = + cached !== undefined && + (cached.x !== x || + cached.y !== y || + cached.width !== width || + cached.height !== height) + if (positionChanged) { + layoutShifted = true + } + if (cached && (node.dirty || positionChanged)) { + output.clear( + { + x: Math.floor(cached.x), + y: Math.floor(cached.y), + width: Math.floor(cached.width), + height: Math.floor(cached.height), + }, + node.style.position === 'absolute', + ) + } + + // Read before deleting — hasRemovedChild disables prevScreen blitting + // for siblings to prevent stale overflow content from being restored. + const clears = pendingClears.get(node) + const hasRemovedChild = clears !== undefined + if (hasRemovedChild) { + layoutShifted = true + for (const rect of clears) { + output.clear({ + x: Math.floor(rect.x), + y: Math.floor(rect.y), + width: Math.floor(rect.width), + height: Math.floor(rect.height), + }) + } + pendingClears.delete(node) + } + + // Yoga squeezed this node to zero height (overflow in a height-constrained + // parent) AND a sibling lands at the same y. Skip rendering — both would + // write to the same row; if the sibling's content is shorter, this node's + // tail chars ghost (e.g. "false" + "true" = "truee"). The clear above + // already handled the visible→squeezed transition. + // + // The sibling-overlap check is load-bearing: Yoga's pixel-grid rounding + // can give a box h=0 while still leaving a row for it (next sibling at + // y+1, not y). HelpV2's third shortcuts column hits this — skipping + // unconditionally drops "ctrl + z to suspend" from /help output. + if (height === 0 && siblingSharesY(node, yogaNode)) { + nodeCache.set(node, { x, y, width, height, top: yogaTop }) + node.dirty = false + return + } + + if (node.nodeName === 'ink-raw-ansi') { + // Pre-rendered ANSI content. The producer already wrapped to width and + // emitted terminal-ready escape codes. Skip squash, measure, wrap, and + // style re-application — output.write() parses ANSI directly into cells. + const text = node.attributes['rawText'] as string + if (text) { + output.write(x, y, text) + } + } else if (node.nodeName === 'ink-text') { + const segments = squashTextNodesToSegments( + node, + inheritedBackgroundColor + ? { backgroundColor: inheritedBackgroundColor } + : undefined, + ) + + // First, get plain text to check if wrapping is needed + const plainText = segments.map(s => s.text).join('') + + if (plainText.length > 0) { + // Upstream Ink uses getMaxWidth(yogaNode) unclamped here. That + // width comes from Yoga's AtMost pass and can exceed the actual + // screen space (see getMaxWidth docstring). Yoga's height for this + // node already reflects the constrained Exactly pass, so clamping + // the wrap width here keeps line count consistent with layout. + // Without this, characters past the screen edge are dropped by + // setCellAt's bounds check. + const maxWidth = Math.min(getMaxWidth(yogaNode), output.width - x) + const textWrap = node.style.textWrap ?? 'wrap' + + // Check if wrapping is needed + const needsWrapping = widestLine(plainText) > maxWidth + + let text: string + let softWrap: boolean[] | undefined + if (needsWrapping && segments.length === 1) { + // Single segment: wrap plain text first, then apply styles to each line + const segment = segments[0]! + const w = wrapWithSoftWrap(plainText, maxWidth, textWrap) + softWrap = w.softWrap + text = w.wrapped + .split('\n') + .map(line => { + let styled = applyTextStyles(line, segment.styles) + // Apply OSC 8 hyperlink per-line so each line is independently + // clickable. output.ts splits on newlines and tokenizes each + // line separately, so a single wrapper around the whole block + // would only apply the hyperlink to the first line. + if (segment.hyperlink) { + styled = wrapWithOsc8Link(styled, segment.hyperlink) + } + return styled + }) + .join('\n') + } else if (needsWrapping) { + // Multiple segments with wrapping: wrap plain text first, then re-apply + // each segment's styles based on character positions. This preserves + // per-segment styles even when text wraps across lines. + const w = wrapWithSoftWrap(plainText, maxWidth, textWrap) + softWrap = w.softWrap + const charToSegment = buildCharToSegmentMap(segments) + text = applyStylesToWrappedText( + w.wrapped, + segments, + charToSegment, + plainText, + textWrap === 'wrap-trim', + ) + // Hyperlinks are handled per-run in applyStylesToWrappedText via + // wrapWithOsc8Link, similar to how styles are applied per-run. + } else { + // No wrapping needed: apply styles directly + text = segments + .map(segment => { + let styledText = applyTextStyles(segment.text, segment.styles) + if (segment.hyperlink) { + styledText = wrapWithOsc8Link(styledText, segment.hyperlink) + } + return styledText + }) + .join('') + } + + text = applyPaddingToText(node, text, softWrap) + + output.write(x, y, text, softWrap) + } + } else if (node.nodeName === 'ink-box') { + const boxBackgroundColor = + node.style.backgroundColor ?? inheritedBackgroundColor + + // Mark this box's region as non-selectable (fullscreen text + // selection). noSelect ops are applied AFTER blits/writes in + // output.get(), so this wins regardless of what's rendered into + // the region — including blits from prevScreen when the box is + // clean (the op is emitted on both the dirty-render path here + // AND on the blit fast-path at line ~235 since blitRegion copies + // the noSelect bitmap alongside cells). + // + // 'from-left-edge' extends the exclusion from col 0 so any + // upstream indentation (tool prefix, tree lines) is covered too + // — a multi-row drag over a diff gutter shouldn't pick up the + // ` ⎿ ` prefix on row 0 or the blank cells under it on row 1+. + if (node.style.noSelect) { + const boxX = Math.floor(x) + const fromEdge = node.style.noSelect === 'from-left-edge' + output.noSelect({ + x: fromEdge ? 0 : boxX, + y: Math.floor(y), + width: fromEdge ? boxX + Math.floor(width) : Math.floor(width), + height: Math.floor(height), + }) + } + + const overflowX = node.style.overflowX ?? node.style.overflow + const overflowY = node.style.overflowY ?? node.style.overflow + const clipHorizontally = overflowX === 'hidden' || overflowX === 'scroll' + const clipVertically = overflowY === 'hidden' || overflowY === 'scroll' + const isScrollY = overflowY === 'scroll' + + const needsClip = clipHorizontally || clipVertically + let y1: number | undefined + let y2: number | undefined + if (needsClip) { + const x1 = clipHorizontally + ? x + yogaNode.getComputedBorder(LayoutEdge.Left) + : undefined + + const x2 = clipHorizontally + ? x + + yogaNode.getComputedWidth() - + yogaNode.getComputedBorder(LayoutEdge.Right) + : undefined + + y1 = clipVertically + ? y + yogaNode.getComputedBorder(LayoutEdge.Top) + : undefined + + y2 = clipVertically + ? y + + yogaNode.getComputedHeight() - + yogaNode.getComputedBorder(LayoutEdge.Bottom) + : undefined + + output.clip({ x1, x2, y1, y2 }) + } + + if (isScrollY) { + // Scroll containers follow the ScrollBox component structure: + // a single content-wrapper child with flexShrink:0 (doesn't shrink + // to fit), whose children are the scrollable items. scrollHeight + // comes from the wrapper's intrinsic Yoga height. The wrapper is + // rendered with its Y translated by -scrollTop; its children are + // culled against the visible window. + const padTop = yogaNode.getComputedPadding(LayoutEdge.Top) + const innerHeight = Math.max( + 0, + (y2 ?? y + height) - + (y1 ?? y) - + padTop - + yogaNode.getComputedPadding(LayoutEdge.Bottom), + ) + + const content = node.childNodes.find(c => (c as DOMElement).yogaNode) as + | DOMElement + | undefined + const contentYoga = content?.yogaNode + // scrollHeight is the intrinsic height of the content wrapper. + // Do NOT add getComputedTop() — that's the wrapper's offset + // within the viewport (equal to the scroll container's + // paddingTop), and innerHeight already subtracts padding, so + // including it double-counts padding and inflates maxScroll. + const scrollHeight = contentYoga?.getComputedHeight() ?? 0 + // Capture previous scroll bounds BEFORE overwriting — the at-bottom + // follow check compares against last frame's max. + const prevScrollHeight = node.scrollHeight ?? scrollHeight + const prevInnerHeight = node.scrollViewportHeight ?? innerHeight + node.scrollHeight = scrollHeight + node.scrollViewportHeight = innerHeight + // Absolute screen-buffer row where the scrollable area (inside + // padding) begins. Exposed via ScrollBoxHandle.getViewportTop() so + // drag-to-scroll can detect when the drag leaves the scroll viewport. + node.scrollViewportTop = (y1 ?? y) + padTop + + const maxScroll = Math.max(0, scrollHeight - innerHeight) + // scrollAnchor: scroll so the anchored element's top is at the + // viewport top (plus offset). Yoga is FRESH — same calculateLayout + // pass that just produced scrollHeight. Deterministic alternative + // to scrollTo(N) which bakes a number that's stale by the throttled + // render; the element ref defers the read to now. One-shot snap. + // A prior eased-seek version (proportional drain over ~5 frames) + // moved scrollTop without firing React's notify → parent's quantized + // store snapshot never updated → StickyTracker got stale range props + // → firstVisible wrong. Also: SCROLL_MIN_PER_FRAME=4 with snap-at-1 + // ping-ponged forever at delta=2. Smooth needs drain-end notify + // plumbing; shipping instant first. stickyScroll overrides. + if (node.scrollAnchor) { + const anchorTop = node.scrollAnchor.el.yogaNode?.getComputedTop() + if (anchorTop != null) { + node.scrollTop = anchorTop + node.scrollAnchor.offset + node.pendingScrollDelta = undefined + } + node.scrollAnchor = undefined + } + // At-bottom follow. Positional: if scrollTop was at (or past) the + // previous max, pin to the new max. Scroll away → stop following; + // scroll back (or scrollToBottom/sticky attr) → resume. The sticky + // flag is OR'd in for cold start (scrollTop=0 before first layout) + // and scrollToBottom-from-far-away (flag set before scrollTop moves) + // — the imperative field takes precedence over the attribute so + // scrollTo/scrollBy can break stickiness. pendingDelta<0 guard: + // don't cancel an in-flight scroll-up when content races in. + // Capture scrollTop before follow so ink.tsx can translate any + // active text selection by the same delta (native terminal behavior: + // view keeps scrolling, highlight walks up with the text). + const scrollTopBeforeFollow = node.scrollTop ?? 0 + const sticky = + node.stickyScroll ?? Boolean(node.attributes['stickyScroll']) + const prevMaxScroll = Math.max(0, prevScrollHeight - prevInnerHeight) + // Positional check only valid when content grew — virtualization can + // transiently SHRINK scrollHeight (tail unmount + stale heightCache + // spacer) making scrollTop >= prevMaxScroll true by artifact, not + // because the user was at bottom. + const grew = scrollHeight >= prevScrollHeight + const atBottom = + sticky || (grew && scrollTopBeforeFollow >= prevMaxScroll) + if (atBottom && (node.pendingScrollDelta ?? 0) >= 0) { + node.scrollTop = maxScroll + node.pendingScrollDelta = undefined + // Sync flag so useVirtualScroll's isSticky() agrees with positional + // state — sticky-broken-but-at-bottom (wheel tremor, click-select + // at max) otherwise leaves useVirtualScroll's clamp holding the + // viewport short of new streaming content. scrollTo/scrollBy set + // false; this restores true, same as scrollToBottom() would. + // Only restore when (a) positionally at bottom and (b) the flag + // was explicitly broken (===false) by scrollTo/scrollBy. When + // undefined (never set by user action) leave it alone — setting it + // would make the sticky flag sticky-by-default and lock out + // direct scrollTop writes (e.g. the alt-screen-perf test). + if ( + node.stickyScroll === false && + scrollTopBeforeFollow >= prevMaxScroll + ) { + node.stickyScroll = true + } + } + const followDelta = (node.scrollTop ?? 0) - scrollTopBeforeFollow + if (followDelta > 0) { + const vpTop = node.scrollViewportTop ?? 0 + followScroll = { + delta: followDelta, + viewportTop: vpTop, + viewportBottom: vpTop + innerHeight - 1, + } + } + // Drain pendingScrollDelta. Native terminals (proportional burst + // events) use proportional drain; xterm.js (VS Code, sparse events + + // app-side accel curve) uses adaptive small-step drain. isXtermJs() + // depends on the async XTVERSION probe, but by the time this runs + // (pendingScrollDelta is only set by wheel events, >>50ms after + // startup) the probe has resolved — same timing guarantee the + // wheel-accel curve relies on. + let cur = node.scrollTop ?? 0 + const pending = node.pendingScrollDelta + const cMin = node.scrollClampMin + const cMax = node.scrollClampMax + const haveClamp = cMin !== undefined && cMax !== undefined + if (pending !== undefined && pending !== 0) { + // Drain continues even past the clamp — the render-clamp below + // holds the VISUAL at the mounted edge regardless. Hard-stopping + // here caused stop-start jutter: drain hits edge → pause → React + // commits → clamp widens → drain resumes → edge again. Letting + // scrollTop advance smoothly while the clamp lags gives continuous + // visual scroll at React's commit rate (the clamp catches up each + // commit). But THROTTLE the drain when already past the clamp so + // scrollTop doesn't race 5000 rows ahead of the mounted range + // (slide-cap would then take 200 commits to catch up = long + // perceived stall at the edge). Past-clamp drain caps at ~4 rows/ + // frame, roughly matching React's slide rate so the gap stays + // bounded and catch-up is quick once input stops. + const pastClamp = + haveClamp && + ((pending < 0 && cur < cMin) || (pending > 0 && cur > cMax)) + const eff = pastClamp ? Math.min(4, innerHeight >> 3) : innerHeight + cur += isXtermJsHost() + ? drainAdaptive(node, pending, eff) + : drainProportional(node, pending, eff) + } else if (pending === 0) { + // Opposite scrollBy calls cancelled to zero — clear so we don't + // schedule an infinite loop of no-op drain frames. + node.pendingScrollDelta = undefined + } + let scrollTop = Math.max(0, Math.min(cur, maxScroll)) + // Virtual-scroll clamp: if scrollTop raced past the currently-mounted + // range (burst PageUp before React re-renders), render at the EDGE of + // the mounted children instead of blank spacer. Do NOT write back to + // node.scrollTop — the clamped value is for this paint only; the real + // scrollTop stays so React's next commit sees the target and mounts + // the right range. Not scheduling scrollDrainNode here keeps the + // clamp passive — React's commit → resetAfterCommit → onRender will + // paint again with fresh bounds. + const clamped = haveClamp + ? Math.max(cMin, Math.min(scrollTop, cMax)) + : scrollTop + node.scrollTop = scrollTop + // Clamp hitting top/bottom consumes any remainder. Set drainPending + // only after clamp so a wasted no-op frame isn't scheduled. + if (scrollTop !== cur) node.pendingScrollDelta = undefined + if (node.pendingScrollDelta !== undefined) scrollDrainNode = node + scrollTop = clamped + + if (content && contentYoga) { + // Compute content wrapper's absolute render position with scroll + // offset applied, then render its children with culling. + const contentX = x + contentYoga.getComputedLeft() + const contentY = y + contentYoga.getComputedTop() - scrollTop + // layoutShifted detection gap: when scrollTop moves by >= viewport + // height (batched PageUps, fast wheel), every visible child gets + // culled (cache dropped) and every newly-visible child has no + // cache — so the children's positionChanged check can't fire. + // The content wrapper's cached y (which encodes -scrollTop) is + // the only node that survives to witness the scroll. + const contentCached = nodeCache.get(content) + let hint: ScrollHint | null = null + if (contentCached && contentCached.y !== contentY) { + // delta = newScrollTop - oldScrollTop (positive = scrolled down). + // Capture a DECSTBM hint if the container itself didn't move + // and the shift fits within the viewport — otherwise the full + // rewrite is needed anyway, and layoutShifted stays the fallback. + const delta = contentCached.y - contentY + const regionTop = Math.floor(y + contentYoga.getComputedTop()) + const regionBottom = regionTop + innerHeight - 1 + if ( + cached?.y === y && + cached.height === height && + innerHeight > 0 && + Math.abs(delta) < innerHeight + ) { + hint = { top: regionTop, bottom: regionBottom, delta } + scrollHint = hint + } else { + layoutShifted = true + } + } + // Fast path: scroll (hint captured) with usable prevScreen. + // Blit prevScreen's scroll region into next.screen, shift in-place + // by delta (mirrors DECSTBM), then render ONLY the edge rows. The + // nested clip keeps child writes out of stable rows — a tall child + // that spans edge+stable still renders but stable cells are + // clipped, preserving the blit. Avoids re-rendering every visible + // child (expensive for long syntax-highlighted transcripts). + // + // When content.dirty (e.g. streaming text at the bottom of the + // scroll), we still use the fast path — the dirty child is almost + // always in the edge rows (the bottom, where new content appears). + // After edge rendering, any dirty children in stable rows are + // re-rendered in a second pass to avoid showing stale blitted + // content. + // + // Guard: the fast path only handles pure scroll or bottom-append. + // Child removal/insertion changes the content height in a way that + // doesn't match the scroll delta — fall back to the full path so + // removed children don't leave stale cells and shifted siblings + // render at their new positions. + const scrollHeight = contentYoga.getComputedHeight() + const prevHeight = contentCached?.height ?? scrollHeight + const heightDelta = scrollHeight - prevHeight + const safeForFastPath = + !hint || + heightDelta === 0 || + (hint.delta > 0 && heightDelta === hint.delta) + // scrollHint is set above when hint is captured. If safeForFastPath + // is false the full path renders a next.screen that doesn't match + // the DECSTBM shift — emitting DECSTBM leaves stale rows (seen as + // content bleeding through during scroll-up + streaming). Clear it. + if (!safeForFastPath) scrollHint = null + if (hint && prevScreen && safeForFastPath) { + const { top, bottom, delta } = hint + const w = Math.floor(width) + output.blit(prevScreen, Math.floor(x), top, w, bottom - top + 1) + output.shift(top, bottom, delta) + // Edge rows: new content entering the viewport. + const edgeTop = delta > 0 ? bottom - delta + 1 : top + const edgeBottom = delta > 0 ? bottom : top - delta - 1 + output.clear({ + x: Math.floor(x), + y: edgeTop, + width: w, + height: edgeBottom - edgeTop + 1, + }) + output.clip({ + x1: undefined, + x2: undefined, + y1: edgeTop, + y2: edgeBottom + 1, + }) + // Snapshot dirty children before the first pass — the first + // pass clears dirty flags, and edge-spanning children would be + // missed by the second pass without this snapshot. + const dirtyChildren = content.dirty + ? new Set(content.childNodes.filter(c => (c as DOMElement).dirty)) + : null + renderScrolledChildren( + content, + output, + contentX, + contentY, + hasRemovedChild, + undefined, + // Cull to edge in child-local coords (inverse of contentY offset). + edgeTop - contentY, + edgeBottom + 1 - contentY, + boxBackgroundColor, + true, + ) + output.unclip() + + // Second pass: re-render children in stable rows whose screen + // position doesn't match where the shift put their old pixels. + // Covers TWO cases: + // 1. Dirty children — their content changed, blitted pixels are + // stale regardless of position. + // 2. Clean children BELOW a middle-growth point — when a dirty + // sibling above them grows, their yogaTop increases but + // scrollTop increases by the same amount (sticky), so their + // screenY is CONSTANT. The shift moved their old pixels to + // screenY-delta (wrong); they should stay at screenY. Without + // this, the spinner/tmux-monitor ghost at shifted positions + // during streaming (e.g. triple spinner, pill duplication). + // For bottom-append (the common case), all clean children are + // ABOVE the growth point; their screenY decreased by delta and + // the shift put them at the right place — skipped here, fast + // path preserved. + if (dirtyChildren) { + const edgeTopLocal = edgeTop - contentY + const edgeBottomLocal = edgeBottom + 1 - contentY + const spaces = ' '.repeat(w) + // Track cumulative height change of children iterated so far. + // A clean child's yogaTop is unchanged iff this is zero (no + // sibling above it grew/shrank/mounted). When zero, the skip + // check cached.y−delta === screenY reduces to delta === delta + // (tautology) → skip without yoga reads. Restores O(dirty) + // that #24536 traded away: for bottom-append the dirty child + // is last (all clean children skip); for virtual-scroll range + // shift the topSpacer shrink + new-item heights self-balance + // to zero before reaching the clean block. Middle-growth + // leaves shift non-zero → clean children after the growth + // point fall through to yoga + the fine-grained check below, + // preserving the ghost-box fix. + let cumHeightShift = 0 + for (const childNode of content.childNodes) { + const childElem = childNode as DOMElement + const isDirty = dirtyChildren.has(childNode) + if (!isDirty && cumHeightShift === 0) { + if (nodeCache.has(childElem)) continue + // Uncached = culled last frame, now re-entering. blit + // never painted it → fall through to yoga + render. + // Height unchanged (clean), so cumHeightShift stays 0. + } + const cy = childElem.yogaNode + if (!cy) continue + const childTop = cy.getComputedTop() + const childH = cy.getComputedHeight() + const childBottom = childTop + childH + if (isDirty) { + const prev = nodeCache.get(childElem) + cumHeightShift += childH - (prev ? prev.height : 0) + } + // Skip culled children (outside viewport) + if ( + childBottom <= scrollTop || + childTop >= scrollTop + innerHeight + ) + continue + // Skip children entirely within edge rows (already rendered) + if (childTop >= edgeTopLocal && childBottom <= edgeBottomLocal) + continue + const screenY = Math.floor(contentY + childTop) + // Clean children reaching here have cumHeightShift ≠ 0 OR + // no cache. Re-check precisely: cached.y − delta is where + // the shift left old pixels; if it equals new screenY the + // blit is correct (shift re-balanced at this child, or + // yogaTop happens to net out). No cache → blit never + // painted it → render. + if (!isDirty) { + const childCached = nodeCache.get(childElem) + if ( + childCached && + Math.floor(childCached.y) - delta === screenY + ) { + continue + } + } + // Wipe this child's region with spaces to overwrite stale + // blitted content — output.clear() only expands damage and + // cannot zero cells that the blit already wrote. + const screenBottom = Math.min( + Math.floor(contentY + childBottom), + Math.floor((y1 ?? y) + padTop + innerHeight), + ) + if (screenY < screenBottom) { + const fill = Array(screenBottom - screenY) + .fill(spaces) + .join('\n') + output.write(Math.floor(x), screenY, fill) + output.clip({ + x1: undefined, + x2: undefined, + y1: screenY, + y2: screenBottom, + }) + renderNodeToOutput(childElem, output, { + offsetX: contentX, + offsetY: contentY, + prevScreen: undefined, + inheritedBackgroundColor: boxBackgroundColor, + }) + output.unclip() + } + } + } + + // Third pass: repair rows where shifted copies of absolute + // overlays landed. The blit copied prevScreen cells INCLUDING + // overlay pixels (overlays render AFTER this ScrollBox so they + // painted into prevScreen's scroll region). After shift, those + // pixels sit at (rect.y - delta) — neither edge render nor the + // overlay's own re-render covers them. Wipe and re-render + // ScrollBox content so the diff writes correct cells. + const spaces = absoluteRectsPrev.length ? ' '.repeat(w) : '' + for (const r of absoluteRectsPrev) { + if (r.y >= bottom + 1 || r.y + r.height <= top) continue + const shiftedTop = Math.max(top, Math.floor(r.y) - delta) + const shiftedBottom = Math.min( + bottom + 1, + Math.floor(r.y + r.height) - delta, + ) + // Skip if entirely within edge rows (already rendered). + if (shiftedTop >= edgeTop && shiftedBottom <= edgeBottom + 1) + continue + if (shiftedTop >= shiftedBottom) continue + const fill = Array(shiftedBottom - shiftedTop) + .fill(spaces) + .join('\n') + output.write(Math.floor(x), shiftedTop, fill) + output.clip({ + x1: undefined, + x2: undefined, + y1: shiftedTop, + y2: shiftedBottom, + }) + renderScrolledChildren( + content, + output, + contentX, + contentY, + hasRemovedChild, + undefined, + shiftedTop - contentY, + shiftedBottom - contentY, + boxBackgroundColor, + true, + ) + output.unclip() + } + } else { + // Full path. Two sub-cases: + // + // Scrolled without a usable hint (big jump, container moved): + // child positions in prevScreen are stale. Clear the viewport + // and disable blit so children don't restore shifted content. + // + // No scroll (spinner tick, content edit): child positions in + // prevScreen are still valid. Skip the viewport clear and pass + // prevScreen so unchanged children blit. Dirty children already + // self-clear via their own cached-rect clear. Without this, a + // spinner inside ScrollBox forces a full-content rewrite every + // frame — on wide terminals over tmux (no BSU/ESU) the + // bandwidth crosses the chunk boundary and the frame tears. + const scrolled = contentCached && contentCached.y !== contentY + if (scrolled && y1 !== undefined && y2 !== undefined) { + output.clear({ + x: Math.floor(x), + y: Math.floor(y1), + width: Math.floor(width), + height: Math.floor(y2 - y1), + }) + } + // positionChanged (ScrollBox height shrunk — pill mount) means a + // child spanning the old bottom edge would blit its full cached + // rect past the new clip. output.ts clips blits now, but also + // disable prevScreen here so the partial-row child re-renders at + // correct bounds instead of blitting a clipped (truncated) old + // rect. + renderScrolledChildren( + content, + output, + contentX, + contentY, + hasRemovedChild, + scrolled || positionChanged ? undefined : prevScreen, + scrollTop, + scrollTop + innerHeight, + boxBackgroundColor, + ) + } + nodeCache.set(content, { + x: contentX, + y: contentY, + width: contentYoga.getComputedWidth(), + height: contentYoga.getComputedHeight(), + }) + content.dirty = false + } + } else { + // Fill interior with background color before rendering children. + // This covers padding areas and empty space; child text inherits + // the color via inheritedBackgroundColor so written cells also + // get the background. + // Disable prevScreen for children: the fill overwrites the entire + // interior each render, so child blits from prevScreen would restore + // stale cells (wrong bg if it changed) on top of the fresh fill. + const ownBackgroundColor = node.style.backgroundColor + if (ownBackgroundColor || node.style.opaque) { + const borderLeft = yogaNode.getComputedBorder(LayoutEdge.Left) + const borderRight = yogaNode.getComputedBorder(LayoutEdge.Right) + const borderTop = yogaNode.getComputedBorder(LayoutEdge.Top) + const borderBottom = yogaNode.getComputedBorder(LayoutEdge.Bottom) + const innerWidth = Math.floor(width) - borderLeft - borderRight + const innerHeight = Math.floor(height) - borderTop - borderBottom + if (innerWidth > 0 && innerHeight > 0) { + const spaces = ' '.repeat(innerWidth) + const fillLine = ownBackgroundColor + ? applyTextStyles(spaces, { backgroundColor: ownBackgroundColor }) + : spaces + const fill = Array(innerHeight).fill(fillLine).join('\n') + output.write(x + borderLeft, y + borderTop, fill) + } + } + + renderChildren( + node, + output, + x, + y, + hasRemovedChild, + // backgroundColor and opaque both disable child blit: the fill + // overwrites the entire interior each render, so any child whose + // layout position shifted would blit stale cells from prevScreen + // on top of the fresh fill. Previously opaque kept blit enabled + // on the assumption that plain-space fill + unchanged children = + // valid composite, but children CAN reposition (ScrollBox remeasure + // on re-render → /permissions body blanked on Down arrow, #25436). + ownBackgroundColor || node.style.opaque ? undefined : prevScreen, + boxBackgroundColor, + ) + } + + if (needsClip) { + output.unclip() + } + + // Render border AFTER children to ensure it's not overwritten by child + // clearing operations. When a child shrinks, it clears its old area, + // which may overlap with where the parent's border now is. + renderBorder(x, y, node, output) + } else if (node.nodeName === 'ink-root') { + renderChildren( + node, + output, + x, + y, + hasRemovedChild, + prevScreen, + inheritedBackgroundColor, + ) + } + + // Cache layout bounds for dirty tracking + const rect = { x, y, width, height, top: yogaTop } + nodeCache.set(node, rect) + if (node.style.position === 'absolute') { + absoluteRectsCur.push(rect) + } + node.dirty = false + } +} + +// Overflow contamination: content overflows right/down, so clean siblings +// AFTER a dirty/removed sibling can contain stale overflow in prevScreen. +// Disable blit for siblings after a dirty child — but still pass prevScreen +// TO the dirty child itself so its clean descendants can blit. The dirty +// child's own blit check already fails (node.dirty=true at line 216), so +// passing prevScreen only benefits its subtree. +// For removed children we don't know their original position, so +// conservatively disable blit for all. +// +// Clipped children (overflow hidden/scroll on both axes) cannot overflow +// onto later siblings — their content is confined to their layout bounds. +// Skip the contamination guard for them so later siblings can still blit. +// Without this, a spinner inside a ScrollBox dirties the wrapper on every +// tick and the bottom prompt section never blits → 100% writes every frame. +// +// Exception: absolute-positioned clipped children may have layout bounds +// that overlap arbitrary siblings, so the clipping does not help. +// +// Overlap contamination (seenDirtyClipped): a later ABSOLUTE sibling whose +// rect sits inside a dirty clipped child's bounds would blit stale cells +// from prevScreen — the clipped child just rewrote those cells this frame. +// The clipsBothAxes skip only protects against OVERFLOW (clipped child +// painting outside its bounds), not overlap (absolute sibling painting +// inside them). For non-opaque absolute siblings, skipSelfBlit forces +// descent (the full-width rect has transparent gaps → stale blit) while +// still passing prevScreen so opaque descendants can blit their narrower +// rects (NewMessagesPill's inner Text with backgroundColor). Opaque +// absolute siblings fill their entire rect — direct blit is safe. +function renderChildren( + node: DOMElement, + output: Output, + offsetX: number, + offsetY: number, + hasRemovedChild: boolean, + prevScreen: Screen | undefined, + inheritedBackgroundColor: Color | undefined, +): void { + let seenDirtyChild = false + let seenDirtyClipped = false + for (const childNode of node.childNodes) { + const childElem = childNode as DOMElement + // Capture dirty before rendering — renderNodeToOutput clears the flag + const wasDirty = childElem.dirty + const isAbsolute = childElem.style.position === 'absolute' + renderNodeToOutput(childElem, output, { + offsetX, + offsetY, + prevScreen: hasRemovedChild || seenDirtyChild ? undefined : prevScreen, + // Short-circuits on seenDirtyClipped (false in the common case) so + // the opaque/bg reads don't happen per-child per-frame. + skipSelfBlit: + seenDirtyClipped && + isAbsolute && + !childElem.style.opaque && + childElem.style.backgroundColor === undefined, + inheritedBackgroundColor, + }) + if (wasDirty && !seenDirtyChild) { + if (!clipsBothAxes(childElem) || isAbsolute) { + seenDirtyChild = true + } else { + seenDirtyClipped = true + } + } + } +} + +function clipsBothAxes(node: DOMElement): boolean { + const ox = node.style.overflowX ?? node.style.overflow + const oy = node.style.overflowY ?? node.style.overflow + return ( + (ox === 'hidden' || ox === 'scroll') && (oy === 'hidden' || oy === 'scroll') + ) +} + +// When Yoga squeezes a box to h=0, the ghost only happens if a sibling +// lands at the same computed top — then both write to that row and the +// shorter content leaves the longer's tail visible. Yoga's pixel-grid +// rounding can give h=0 while still advancing the next sibling's top +// (HelpV2's third shortcuts column), so h=0 alone isn't sufficient. +function siblingSharesY(node: DOMElement, yogaNode: LayoutNode): boolean { + const parent = node.parentNode + if (!parent) return false + const myTop = yogaNode.getComputedTop() + const siblings = parent.childNodes + const idx = siblings.indexOf(node) + for (let i = idx + 1; i < siblings.length; i++) { + const sib = (siblings[i] as DOMElement).yogaNode + if (!sib) continue + return sib.getComputedTop() === myTop + } + // No next sibling with a yoga node — check previous. A run of h=0 boxes + // at the tail would all share y with each other. + for (let i = idx - 1; i >= 0; i--) { + const sib = (siblings[i] as DOMElement).yogaNode + if (!sib) continue + return sib.getComputedTop() === myTop + } + return false +} + +// When a node blits, its absolute-positioned descendants that paint outside +// the node's layout bounds are NOT covered by the blit (which only copies +// the node's own rect). If a dirty sibling re-rendered and overwrote those +// cells, we must re-blit them from prevScreen so the overlays survive. +// Example: PromptInputFooter's slash menu uses position='absolute' bottom='100%' +// to float above the prompt; a spinner tick in the ScrollBox above re-renders +// and overwrites those cells. Without this, the menu vanishes on the next frame. +function blitEscapingAbsoluteDescendants( + node: DOMElement, + output: Output, + prevScreen: Screen, + px: number, + py: number, + pw: number, + ph: number, +): void { + const pr = px + pw + const pb = py + ph + for (const child of node.childNodes) { + if (child.nodeName === '#text') continue + const elem = child as DOMElement + if (elem.style.position === 'absolute') { + const cached = nodeCache.get(elem) + if (cached) { + absoluteRectsCur.push(cached) + const cx = Math.floor(cached.x) + const cy = Math.floor(cached.y) + const cw = Math.floor(cached.width) + const ch = Math.floor(cached.height) + // Only blit rects that extend outside the parent's layout bounds — + // cells within the parent rect are already covered by the parent blit. + if (cx < px || cy < py || cx + cw > pr || cy + ch > pb) { + output.blit(prevScreen, cx, cy, cw, ch) + } + } + } + // Recurse — absolute descendants can be nested arbitrarily deep + blitEscapingAbsoluteDescendants(elem, output, prevScreen, px, py, pw, ph) + } +} + +// Render children of a scroll container with viewport culling. +// scrollTopY..scrollBottomY are the visible window in CHILD-LOCAL Yoga coords +// (i.e. what getComputedTop() returns). Children entirely outside this window +// are skipped; their nodeCache entry is deleted so if they re-enter the +// viewport later they don't emit a stale clear for a position now occupied +// by a sibling. +function renderScrolledChildren( + node: DOMElement, + output: Output, + offsetX: number, + offsetY: number, + hasRemovedChild: boolean, + prevScreen: Screen | undefined, + scrollTopY: number, + scrollBottomY: number, + inheritedBackgroundColor: Color | undefined, + // When true (DECSTBM fast path), culled children keep their cache — + // the blit+shift put stable rows in next.screen so stale cache is + // never read. Avoids walking O(total_children * subtree_depth) per frame. + preserveCulledCache = false, +): void { + let seenDirtyChild = false + // Track cumulative height shift of dirty children iterated so far. When + // zero, a clean child's yogaTop is unchanged (no sibling above it grew), + // so cached.top is fresh and the cull check skips yoga. Bottom-append + // has the dirty child last → all prior clean children hit cache → + // O(dirty) not O(mounted). Middle-growth leaves shift non-zero after + // the dirty child → subsequent children yoga-read (needed for correct + // culling since their yogaTop shifted). + let cumHeightShift = 0 + for (const childNode of node.childNodes) { + const childElem = childNode as DOMElement + const cy = childElem.yogaNode + if (cy) { + const cached = nodeCache.get(childElem) + let top: number + let height: number + if ( + cached?.top !== undefined && + !childElem.dirty && + cumHeightShift === 0 + ) { + top = cached.top + height = cached.height + } else { + top = cy.getComputedTop() + height = cy.getComputedHeight() + if (childElem.dirty) { + cumHeightShift += height - (cached ? cached.height : 0) + } + // Refresh cached top so next frame's cumShift===0 path stays + // correct. For culled children with preserveCulledCache=true this + // is the ONLY refresh point — without it, a middle-growth frame + // leaves stale tops that misfire next frame. + if (cached) cached.top = top + } + const bottom = top + height + if (bottom <= scrollTopY || top >= scrollBottomY) { + // Culled — outside visible window. Drop stale cache entries from + // the subtree so when this child re-enters it doesn't fire clears + // at positions now occupied by siblings. The viewport-clear on + // scroll-change handles the visible-area repaint. + if (!preserveCulledCache) dropSubtreeCache(childElem) + continue + } + } + const wasDirty = childElem.dirty + renderNodeToOutput(childElem, output, { + offsetX, + offsetY, + prevScreen: hasRemovedChild || seenDirtyChild ? undefined : prevScreen, + inheritedBackgroundColor, + }) + if (wasDirty) { + seenDirtyChild = true + } + } +} + +function dropSubtreeCache(node: DOMElement): void { + nodeCache.delete(node) + for (const child of node.childNodes) { + if (child.nodeName !== '#text') { + dropSubtreeCache(child as DOMElement) + } + } +} + +// Exported for testing +export { buildCharToSegmentMap, applyStylesToWrappedText } + +export default renderNodeToOutput diff --git a/_all-in-one-upload/cc-haha/src/keybindings/shortcutFormat.ts b/_all-in-one-upload/cc-haha/src/keybindings/shortcutFormat.ts new file mode 100644 index 0000000..45db3b0 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/keybindings/shortcutFormat.ts @@ -0,0 +1,63 @@ +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../services/analytics/index.js' +import { loadKeybindingsSync } from './loadUserBindings.js' +import { getBindingDisplayText } from './resolver.js' +import type { KeybindingContextName } from './types.js' + +// TODO(keybindings-migration): Remove fallback parameter after migration is +// complete and we've confirmed no 'keybinding_fallback_used' events are being +// logged. The fallback exists as a safety net during migration - if bindings +// fail to load or an action isn't found, we fall back to hardcoded values. +// Once stable, callers should be able to trust that getBindingDisplayText +// always returns a value for known actions, and we can remove this defensive +// pattern. + +// Track which action+context pairs have already logged a fallback event +// to avoid duplicate events from repeated calls in non-React contexts. +const LOGGED_FALLBACKS = new Set() + +/** + * Get the display text for a configured shortcut without React hooks. + * Use this in non-React contexts (commands, services, etc.). + * + * This lives in its own module (not useShortcutDisplay.ts) so that + * non-React callers like query/stopHooks.ts don't pull React into their + * module graph via the sibling hook. + * + * @param action - The action name (e.g., 'app:toggleTranscript') + * @param context - The keybinding context (e.g., 'Global') + * @param fallback - Fallback text if binding not found + * @returns The configured shortcut display text + * + * @example + * const expandShortcut = getShortcutDisplay('app:toggleTranscript', 'Global', 'ctrl+o') + * // Returns the user's configured binding, or 'ctrl+o' as default + */ +export function getShortcutDisplay( + action: string, + context: KeybindingContextName, + fallback: string, +): string { + const bindings = loadKeybindingsSync() + const resolved = getBindingDisplayText(action, context, bindings) + if (resolved === undefined) { + const key = `${action}:${context}` + if (!LOGGED_FALLBACKS.has(key)) { + LOGGED_FALLBACKS.add(key) + logEvent('tengu_keybinding_fallback_used', { + action: + action as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + context: + context as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + fallback: + fallback as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + reason: + 'action_not_found' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }) + } + return fallback + } + return resolved +} diff --git a/_all-in-one-upload/cc-haha/src/memdir/memoryShapeTelemetry.ts b/_all-in-one-upload/cc-haha/src/memdir/memoryShapeTelemetry.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/memdir/memoryShapeTelemetry.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/migrations/resetProToOpusDefault.ts b/_all-in-one-upload/cc-haha/src/migrations/resetProToOpusDefault.ts new file mode 100644 index 0000000..601872f --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/migrations/resetProToOpusDefault.ts @@ -0,0 +1,51 @@ +import { logEvent } from 'src/services/analytics/index.js' +import { isProSubscriber } from '../utils/auth.js' +import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js' +import { getAPIProvider } from '../utils/model/providers.js' +import { getSettings_DEPRECATED } from '../utils/settings/settings.js' + +export function resetProToOpusDefault(): void { + const config = getGlobalConfig() + + if (config.opusProMigrationComplete) { + return + } + + const apiProvider = getAPIProvider() + + // Pro users on firstParty get auto-migrated to Opus 4.5 default + if (apiProvider !== 'firstParty' || !isProSubscriber()) { + saveGlobalConfig(current => ({ + ...current, + opusProMigrationComplete: true, + })) + logEvent('tengu_reset_pro_to_opus_default', { skipped: true }) + return + } + + const settings = getSettings_DEPRECATED() + + // Only show notification if user was on default (no custom model setting) + if (settings?.model === undefined) { + const opusProMigrationTimestamp = Date.now() + saveGlobalConfig(current => ({ + ...current, + opusProMigrationComplete: true, + opusProMigrationTimestamp, + })) + logEvent('tengu_reset_pro_to_opus_default', { + skipped: false, + had_custom_model: false, + }) + } else { + // User has a custom model setting, just mark migration complete + saveGlobalConfig(current => ({ + ...current, + opusProMigrationComplete: true, + })) + logEvent('tengu_reset_pro_to_opus_default', { + skipped: false, + had_custom_model: true, + }) + } +} diff --git a/_all-in-one-upload/cc-haha/src/query/transitions.ts b/_all-in-one-upload/cc-haha/src/query/transitions.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/query/transitions.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/server/__tests__/.syncthing.providers-real.test.ts.tmp b/_all-in-one-upload/cc-haha/src/server/__tests__/.syncthing.providers-real.test.ts.tmp new file mode 100644 index 0000000000000000000000000000000000000000..81c491163ad0c5d71bca850690dc7e749429e316 GIT binary patch literal 8915 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM J7%*VqYG5MM00961 literal 0 HcmV?d00001 diff --git a/_all-in-one-upload/cc-haha/src/server/__tests__/fixtures/mock-sdk-cli.ts b/_all-in-one-upload/cc-haha/src/server/__tests__/fixtures/mock-sdk-cli.ts new file mode 100644 index 0000000..605aaae --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/__tests__/fixtures/mock-sdk-cli.ts @@ -0,0 +1,274 @@ +const args = process.argv.slice(2) + +function getArg(name: string): string | undefined { + const index = args.indexOf(name) + return index >= 0 ? args[index + 1] : undefined +} + +function emit(ws: WebSocket, payload: Record) { + ws.send(JSON.stringify(payload) + '\n') +} + +function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +function extractUserText(message: any): string { + const content = message?.message?.content + if (!Array.isArray(content)) return '' + return content + .filter((block: any) => block?.type === 'text' && typeof block.text === 'string') + .map((block: any) => block.text) + .join(' ') +} + +const sdkUrl = getArg('--sdk-url') +const sessionId = getArg('--session-id') || crypto.randomUUID() +const initMode = process.env.MOCK_SDK_INIT_MODE || 'on_open' +const streamDelayMs = Number(process.env.MOCK_SDK_STREAM_DELAY_MS || '0') +const exitAfterOpenMs = Number(process.env.MOCK_SDK_EXIT_AFTER_OPEN_MS || '0') +const exitAfterFirstUserMs = Number(process.env.MOCK_SDK_EXIT_AFTER_FIRST_USER_MS || '0') +let initSent = false +let firstUserExitScheduled = false + +if (!sdkUrl) { + console.error('Missing --sdk-url') + process.exit(1) +} + +const ws = new WebSocket(sdkUrl) + +function sendInit() { + if (initSent) return + initSent = true + emit(ws, { + type: 'system', + subtype: 'init', + model: 'mock-opus', + slash_commands: [{ name: 'help', description: 'Show help' }], + session_id: sessionId, + }) +} + +ws.addEventListener('open', () => { + if (initMode !== 'on_first_user') { + sendInit() + } + if (exitAfterOpenMs > 0) { + setTimeout(() => process.exit(1), exitAfterOpenMs) + } +}) + +ws.addEventListener('message', (event) => { + const payload = typeof event.data === 'string' ? event.data : String(event.data) + const lines = payload.split('\n').map(line => line.trim()).filter(Boolean) + + void (async () => { + for (const line of lines) { + const parsed = JSON.parse(line) + + if (parsed.type === 'user') { + sendInit() + if (exitAfterFirstUserMs > 0 && !firstUserExitScheduled) { + firstUserExitScheduled = true + setTimeout(() => process.exit(1), exitAfterFirstUserMs) + continue + } + const text = extractUserText(parsed) + const slashCommand = text.trim() + if (slashCommand === '/cost') { + emit(ws, { + type: 'system', + subtype: 'local_command_output', + content: 'Total cost: $0.0000\nTotal duration: 0s', + session_id: sessionId, + }) + emit(ws, { + type: 'result', + subtype: 'success', + is_error: false, + result: 'Total cost: $0.0000', + usage: { input_tokens: 0, output_tokens: 0 }, + session_id: sessionId, + }) + continue + } + if (slashCommand === '/context') { + emit(ws, { + type: 'system', + subtype: 'local_command_output', + content: '## Context Usage\n\n| Type | Tokens |\n| --- | ---: |\n| System prompt | 123 |', + session_id: sessionId, + }) + emit(ws, { + type: 'result', + subtype: 'success', + is_error: false, + result: 'Context usage', + usage: { input_tokens: 0, output_tokens: 0 }, + session_id: sessionId, + }) + continue + } + emit(ws, { + type: 'stream_event', + event: { type: 'message_start' }, + session_id: sessionId, + }) + emit(ws, { + type: 'stream_event', + event: { + type: 'content_block_start', + index: 0, + content_block: { type: 'text', text: '' }, + }, + session_id: sessionId, + }) + emit(ws, { + type: 'stream_event', + event: { + type: 'content_block_delta', + index: 0, + delta: { type: 'thinking_delta', thinking: 'Mock thinking...' }, + }, + session_id: sessionId, + }) + if (streamDelayMs > 0) await delay(streamDelayMs) + emit(ws, { + type: 'stream_event', + event: { + type: 'content_block_delta', + index: 0, + delta: { type: 'text_delta', text: `Echo: ${text}` }, + }, + session_id: sessionId, + }) + if (streamDelayMs > 0) await delay(streamDelayMs) + emit(ws, { + type: 'stream_event', + event: { type: 'content_block_stop', index: 0 }, + session_id: sessionId, + }) + emit(ws, { + type: 'result', + subtype: 'success', + is_error: false, + result: `Echo: ${text}`, + usage: { input_tokens: 3, output_tokens: 2 }, + session_id: sessionId, + }) + } + + if (parsed.type === 'control_request' && parsed.request?.subtype === 'interrupt') { + emit(ws, { + type: 'result', + subtype: 'success', + is_error: false, + result: 'Interrupted', + usage: { input_tokens: 0, output_tokens: 0 }, + session_id: sessionId, + }) + } + + if (parsed.type === 'control_request' && parsed.request?.subtype === 'get_session_usage') { + emit(ws, { + type: 'control_response', + response: { + subtype: 'success', + request_id: parsed.request_id, + response: { + totalCostUSD: 0.1234, + costDisplay: '$0.1234', + hasUnknownModelCost: false, + totalAPIDuration: 4, + totalDuration: 43, + totalLinesAdded: 0, + totalLinesRemoved: 0, + totalInputTokens: 27000, + totalOutputTokens: 41, + totalCacheReadInputTokens: 0, + totalCacheCreationInputTokens: 0, + totalWebSearchRequests: 0, + models: [{ + model: 'mock-opus', + displayName: 'mock-opus', + inputTokens: 27000, + outputTokens: 41, + cacheReadInputTokens: 0, + cacheCreationInputTokens: 0, + webSearchRequests: 0, + costUSD: 0.1234, + costDisplay: '$0.1234', + contextWindow: 200000, + maxOutputTokens: 8192, + }], + }, + }, + session_id: sessionId, + }) + } + + if (parsed.type === 'control_request' && parsed.request?.subtype === 'get_context_usage') { + emit(ws, { + type: 'control_response', + response: { + subtype: 'success', + request_id: parsed.request_id, + response: { + categories: [ + { name: 'System prompt', tokens: 6800, color: '#8a8a8a' }, + { name: 'MCP tools', tokens: 5900, color: '#06b6d4' }, + { name: 'Messages', tokens: 2400, color: '#7c3aed' }, + { name: 'Free space', tokens: 132000, color: '#a1a1aa' }, + ], + totalTokens: 27000, + maxTokens: 200000, + rawMaxTokens: 200000, + percentage: 13, + gridRows: Array.from({ length: 10 }, (_, row) => + Array.from({ length: 10 }, (_, col) => { + const index = row * 10 + col + return { + color: index < 13 ? '#06b6d4' : '#a1a1aa', + isFilled: index < 13, + categoryName: index < 13 ? 'Used' : 'Free space', + tokens: 2000, + percentage: 1, + squareFullness: index < 13 ? 1 : 0, + } + }), + ), + model: 'mock-opus', + estimateOnly: parsed.request.estimateOnly === true, + memoryFiles: [], + mcpTools: [{ name: 'mock_tool', serverName: 'mock', tokens: 144, isLoaded: true }], + agents: [], + skills: { totalSkills: 1, includedSkills: 1, tokens: 3000, skillFrontmatter: [] }, + isAutoCompactEnabled: true, + apiUsage: null, + }, + }, + session_id: sessionId, + }) + } + + if (parsed.type === 'control_request' && parsed.request?.subtype === 'mcp_status') { + emit(ws, { + type: 'control_response', + response: { + subtype: 'success', + request_id: parsed.request_id, + response: { + mcpServers: [{ name: 'mock', status: 'connected' }], + }, + }, + session_id: sessionId, + }) + } + } + })() +}) + +ws.addEventListener('close', () => { + process.exit(0) +}) diff --git a/_all-in-one-upload/cc-haha/src/server/__tests__/scheduled-tasks.test.ts b/_all-in-one-upload/cc-haha/src/server/__tests__/scheduled-tasks.test.ts new file mode 100644 index 0000000..8b03198 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/__tests__/scheduled-tasks.test.ts @@ -0,0 +1,371 @@ +/** + * Unit tests for CronService, SearchService, and Scheduled Tasks API + */ + +import { describe, it, expect, beforeEach, afterEach, spyOn } from 'bun:test' +import * as fs from 'fs/promises' +import * as path from 'path' +import * as os from 'os' +import { CronService } from '../services/cronService.js' +import { SearchService } from '../services/searchService.js' + +// ─── Test helpers ─────────────────────────────────────────────────────────── + +let tmpDir: string +const originalConfigDir = process.env.CLAUDE_CONFIG_DIR + +async function createTmpDir(): Promise { + const dir = path.join(os.tmpdir(), `claude-test-${Date.now()}-${Math.random().toString(36).slice(2)}`) + await fs.mkdir(dir, { recursive: true }) + return dir +} + +async function cleanupTmpDir(dir: string): Promise { + try { + await fs.rm(dir, { recursive: true, force: true }) + } catch { + // ignore + } +} + +// ─── CronService tests ───────────────────────────────────────────────────── + +describe('CronService', () => { + let service: CronService + + beforeEach(async () => { + tmpDir = await createTmpDir() + process.env.CLAUDE_CONFIG_DIR = tmpDir + service = new CronService() + }) + + afterEach(async () => { + if (originalConfigDir) { + process.env.CLAUDE_CONFIG_DIR = originalConfigDir + } else { + delete process.env.CLAUDE_CONFIG_DIR + } + await cleanupTmpDir(tmpDir) + }) + + it('should return empty list when no tasks file exists', async () => { + const tasks = await service.listTasks() + expect(tasks).toEqual([]) + }) + + it('should create a task with generated id and createdAt', async () => { + const task = await service.createTask({ + cron: '0 9 * * *', + prompt: 'Review commits', + recurring: true, + }) + + expect(task.id).toBeDefined() + expect(task.id).toHaveLength(8) // 4 bytes hex + expect(task.cron).toBe('0 9 * * *') + expect(task.prompt).toBe('Review commits') + expect(task.recurring).toBe(true) + expect(task.createdAt).toBeGreaterThan(0) + }) + + it('should persist tasks to file', async () => { + await service.createTask({ cron: '0 9 * * *', prompt: 'Task 1' }) + await service.createTask({ cron: '30 18 * * 5', prompt: 'Task 2' }) + + const tasks = await service.listTasks() + expect(tasks).toHaveLength(2) + expect(tasks[0].prompt).toBe('Task 1') + expect(tasks[1].prompt).toBe('Task 2') + }) + + it('should update an existing task', async () => { + const created = await service.createTask({ + cron: '0 9 * * *', + prompt: 'Original prompt', + }) + + const updated = await service.updateTask(created.id, { + prompt: 'Updated prompt', + recurring: true, + }) + + expect(updated.id).toBe(created.id) + expect(updated.prompt).toBe('Updated prompt') + expect(updated.recurring).toBe(true) + expect(updated.createdAt).toBe(created.createdAt) + }) + + it('should throw when updating a non-existent task', async () => { + await expect( + service.updateTask('nonexistent', { prompt: 'x' }), + ).rejects.toThrow('Task not found') + }) + + it('should delete a task', async () => { + const created = await service.createTask({ + cron: '0 9 * * *', + prompt: 'To delete', + }) + + await service.deleteTask(created.id) + const tasks = await service.listTasks() + expect(tasks).toHaveLength(0) + }) + + it('should throw when deleting a non-existent task', async () => { + await expect(service.deleteTask('nonexistent')).rejects.toThrow( + 'Task not found', + ) + }) + + it('should generate unique IDs', async () => { + const ids = new Set() + for (let i = 0; i < 20; i++) { + const task = await service.createTask({ + cron: '* * * * *', + prompt: `Task ${i}`, + }) + ids.add(task.id) + } + expect(ids.size).toBe(20) + }) + + it('should reject create when cron or prompt is missing', async () => { + await expect( + service.createTask({ cron: '', prompt: 'something' }), + ).rejects.toThrow() + + await expect( + service.createTask({ cron: '* * * * *', prompt: '' }), + ).rejects.toThrow() + }) + + it('should retry the atomic write when rename returns ENOENT', async () => { + const originalRename = fs.rename + let renameCalls = 0 + + const renameSpy = spyOn(fs, 'rename') + renameSpy.mockImplementation(async (...args) => { + renameCalls += 1 + + if (renameCalls === 1) { + const error = new Error( + 'ENOENT: no such file or directory, rename tmp -> scheduled_tasks.json', + ) as NodeJS.ErrnoException + error.code = 'ENOENT' + throw error + } + + return originalRename(...args) + }) + + try { + const task = await service.createTask({ + cron: '0 9 * * *', + prompt: 'Retry rename once', + }) + + const tasks = await service.listTasks() + expect(task.id).toBeDefined() + expect(tasks).toHaveLength(1) + expect(tasks[0]?.prompt).toBe('Retry rename once') + expect(renameCalls).toBe(2) + } finally { + renameSpy.mockRestore() + } + }) +}) + +// ─── SearchService tests ──────────────────────────────────────────────────── + +describe('SearchService', () => { + let service: SearchService + let searchDir: string + + beforeEach(async () => { + tmpDir = await createTmpDir() + process.env.CLAUDE_CONFIG_DIR = tmpDir + service = new SearchService() + + // 创建搜索用的临时文件 + searchDir = path.join(tmpDir, 'workspace') + await fs.mkdir(searchDir, { recursive: true }) + await fs.writeFile( + path.join(searchDir, 'hello.txt'), + 'Hello World\nThis is a test\nAnother line\n', + ) + await fs.writeFile( + path.join(searchDir, 'code.ts'), + 'function greet() {\n return "hello"\n}\n', + ) + }) + + afterEach(async () => { + if (originalConfigDir) { + process.env.CLAUDE_CONFIG_DIR = originalConfigDir + } else { + delete process.env.CLAUDE_CONFIG_DIR + } + await cleanupTmpDir(tmpDir) + }) + + it('should find matches in workspace files', async () => { + const results = await service.searchWorkspace('Hello', { cwd: searchDir }) + expect(results.length).toBeGreaterThan(0) + expect(results[0].text).toContain('Hello') + }) + + it('should return empty results when nothing matches', async () => { + const results = await service.searchWorkspace('ZZZZNONEXISTENT', { + cwd: searchDir, + }) + expect(results).toHaveLength(0) + }) + + it('should respect maxResults limit', async () => { + // 写入多行匹配 + const lines = Array.from({ length: 50 }, (_, i) => `match line ${i}`).join( + '\n', + ) + await fs.writeFile(path.join(searchDir, 'many.txt'), lines) + + const results = await service.searchWorkspace('match', { + cwd: searchDir, + maxResults: 5, + }) + expect(results.length).toBeLessThanOrEqual(5) + }) + + it('should reject empty query', async () => { + await expect(service.searchWorkspace('')).rejects.toThrow() + }) + + it('should return empty session results when no projects dir exists', async () => { + const results = await service.searchSessions('test') + expect(results).toEqual([]) + }) +}) + +// ─── Scheduled Tasks API integration ──────────────────────────────────────── + +describe('Scheduled Tasks API', () => { + // 直接测试 handler 函数,不需要启动完整服务器 + let handleScheduledTasksApi: ( + req: Request, + url: URL, + segments: string[], + ) => Promise + + beforeEach(async () => { + tmpDir = await createTmpDir() + process.env.CLAUDE_CONFIG_DIR = tmpDir + + // 动态导入以获取最新的环境变量 + const mod = await import('../api/scheduled-tasks.js') + handleScheduledTasksApi = mod.handleScheduledTasksApi + }) + + afterEach(async () => { + if (originalConfigDir) { + process.env.CLAUDE_CONFIG_DIR = originalConfigDir + } else { + delete process.env.CLAUDE_CONFIG_DIR + } + await cleanupTmpDir(tmpDir) + }) + + it('should list empty tasks via GET', async () => { + const req = new Request('http://localhost/api/scheduled-tasks', { + method: 'GET', + }) + const url = new URL(req.url) + const resp = await handleScheduledTasksApi(req, url, [ + 'api', + 'scheduled-tasks', + ]) + const body = (await resp.json()) as { tasks: unknown[] } + expect(resp.status).toBe(200) + expect(body.tasks).toEqual([]) + }) + + it('should create a task via POST', async () => { + const req = new Request('http://localhost/api/scheduled-tasks', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + cron: '0 9 * * *', + prompt: 'Daily review', + recurring: true, + }), + }) + const url = new URL(req.url) + const resp = await handleScheduledTasksApi(req, url, [ + 'api', + 'scheduled-tasks', + ]) + const body = (await resp.json()) as { task: { id: string; prompt: string } } + expect(resp.status).toBe(201) + expect(body.task.id).toBeDefined() + expect(body.task.prompt).toBe('Daily review') + }) + + it('should CRUD a full lifecycle', async () => { + // Create + const createReq = new Request('http://localhost/api/scheduled-tasks', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ cron: '0 9 * * *', prompt: 'Test task' }), + }) + const createResp = await handleScheduledTasksApi( + createReq, + new URL(createReq.url), + ['api', 'scheduled-tasks'], + ) + const { task } = (await createResp.json()) as { + task: { id: string; prompt: string } + } + + // Update + const updateReq = new Request( + `http://localhost/api/scheduled-tasks/${task.id}`, + { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ prompt: 'Updated task' }), + }, + ) + const updateResp = await handleScheduledTasksApi( + updateReq, + new URL(updateReq.url), + ['api', 'scheduled-tasks', task.id], + ) + const updated = (await updateResp.json()) as { + task: { id: string; prompt: string } + } + expect(updated.task.prompt).toBe('Updated task') + + // Delete + const deleteReq = new Request( + `http://localhost/api/scheduled-tasks/${task.id}`, + { method: 'DELETE' }, + ) + const deleteResp = await handleScheduledTasksApi( + deleteReq, + new URL(deleteReq.url), + ['api', 'scheduled-tasks', task.id], + ) + expect(deleteResp.status).toBe(200) + + // Verify empty + const listReq = new Request('http://localhost/api/scheduled-tasks', { + method: 'GET', + }) + const listResp = await handleScheduledTasksApi( + listReq, + new URL(listReq.url), + ['api', 'scheduled-tasks'], + ) + const list = (await listResp.json()) as { tasks: unknown[] } + expect(list.tasks).toHaveLength(0) + }) +}) diff --git a/_all-in-one-upload/cc-haha/src/server/api/agents.ts b/_all-in-one-upload/cc-haha/src/server/api/agents.ts new file mode 100644 index 0000000..de23d84 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/api/agents.ts @@ -0,0 +1,234 @@ +/** + * Agents REST API + * + * GET /api/agents — 获取 Agent 列表 + * GET /api/agents/:name — 获取 Agent 详情 + * POST /api/agents — 创建 Agent + * PUT /api/agents/:name — 更新 Agent + * DELETE /api/agents/:name — 删除 Agent + * + * GET /api/tasks — 获取后台任务列表 + * GET /api/tasks/:id — 获取任务详情 + */ + +import { AgentService } from '../services/agentService.js' +import { taskService } from '../services/taskService.js' +import { ApiError, errorResponse } from '../middleware/errorHandler.js' +import { resetTaskList } from '../../utils/tasks.js' +import { + resolveAgentModelDisplay, + resolveAgentOverrides, + type ResolvedAgent, +} from '../../tools/AgentTool/agentDisplay.js' +import { + clearAgentDefinitionsCache, + getAgentDefinitionsWithOverrides, + type AgentDefinition as SharedAgentDefinition, +} from '../../tools/AgentTool/loadAgentsDir.js' +import { getCwd } from '../../utils/cwd.js' + +const agentService = new AgentService() + +export async function handleAgentsApi( + req: Request, + url: URL, + segments: string[], +): Promise { + try { + const resource = segments[1] // 'agents' | 'tasks' + + if (resource === 'tasks') { + return await handleTasksApi(req, segments) + } + + return await handleAgents(req, url, segments) + } catch (error) { + return errorResponse(error) + } +} + +// ─── Agent CRUD ───────────────────────────────────────────────────────────── + +async function handleAgents( + req: Request, + url: URL, + segments: string[], +): Promise { + const method = req.method + const agentName = segments[2] ? decodeURIComponent(segments[2]) : undefined + + // ── GET /api/agents ────────────────────────────────────────────────── + if (method === 'GET' && !agentName) { + const cwd = url.searchParams.get('cwd') || getCwd() + const { activeAgents, allAgents } = await getAgentDefinitionsWithOverrides(cwd) + const resolvedAgents = resolveAgentOverrides(allAgents, activeAgents) + + return Response.json({ + activeAgents: activeAgents.map(agent => serializeActiveAgent(agent, true)), + allAgents: resolvedAgents.map(serializeResolvedAgent), + }) + } + + // ── GET /api/agents/:name ──────────────────────────────────────────── + if (method === 'GET' && agentName) { + const agent = await agentService.getAgent(agentName) + if (!agent) { + throw ApiError.notFound(`Agent not found: ${agentName}`) + } + return Response.json({ agent }) + } + + // ── POST /api/agents ───────────────────────────────────────────────── + if (method === 'POST' && !agentName) { + const body = await parseJsonBody(req) + if (!body.name || typeof body.name !== 'string') { + throw ApiError.badRequest('Missing or invalid "name" in request body') + } + await agentService.createAgent({ + name: body.name as string, + description: body.description as string | undefined, + model: body.model as string | undefined, + tools: body.tools as string[] | undefined, + systemPrompt: body.systemPrompt as string | undefined, + color: body.color as string | undefined, + }) + clearAgentDefinitionsCache() + return Response.json({ ok: true }, { status: 201 }) + } + + // ── PUT /api/agents/:name ──────────────────────────────────────────── + if (method === 'PUT' && agentName) { + const body = await parseJsonBody(req) + await agentService.updateAgent(agentName, body as Record) + clearAgentDefinitionsCache() + const updated = await agentService.getAgent(agentName) + return Response.json({ agent: updated }) + } + + // ── DELETE /api/agents/:name ───────────────────────────────────────── + if (method === 'DELETE' && agentName) { + await agentService.deleteAgent(agentName) + clearAgentDefinitionsCache() + return Response.json({ ok: true }) + } + + throw new ApiError( + 405, + `Method ${method} not allowed on /api/agents${agentName ? `/${agentName}` : ''}`, + 'METHOD_NOT_ALLOWED', + ) +} + +// ─── Tasks API ───────────────────────────────────────────────────────────── +// +// GET /api/tasks → list all tasks (across all task lists) +// GET /api/tasks/lists → list all task lists with summaries +// GET /api/tasks/lists/:taskListId → get all tasks for a specific task list +// GET /api/tasks/lists/:taskListId/:id → get a single task +// POST /api/tasks/lists/:taskListId/reset → clear a completed task list + +async function handleTasksApi( + req: Request, + segments: string[], +): Promise { + const sub = segments[2] // 'lists' or undefined + + if (sub === 'lists') { + const taskListId = segments[3] + const taskId = segments[4] + + if (req.method === 'POST' && taskListId && taskId === 'reset') { + await resetTaskList(taskListId) + return Response.json({ ok: true }) + } + + if (req.method !== 'GET') { + throw new ApiError( + 405, + `Method ${req.method} not allowed on /api/tasks/lists`, + 'METHOD_NOT_ALLOWED', + ) + } + + if (taskListId && taskId) { + // GET /api/tasks/lists/:taskListId/:taskId + const task = await taskService.getTask(taskListId, taskId) + if (!task) throw ApiError.notFound(`Task not found: ${taskListId}/${taskId}`) + return Response.json({ task }) + } + + if (taskListId) { + // GET /api/tasks/lists/:taskListId + const tasks = await taskService.getTasksForList(taskListId) + return Response.json({ tasks }) + } + + // GET /api/tasks/lists + const lists = await taskService.listTaskLists() + return Response.json({ lists }) + } + + if (req.method !== 'GET') { + throw new ApiError( + 405, + `Method ${req.method} not allowed on /api/tasks`, + 'METHOD_NOT_ALLOWED', + ) + } + + // GET /api/tasks — list all tasks + const tasks = await taskService.listTasks() + return Response.json({ tasks }) +} + +// ─── Helpers ──────────────────────────────────────────────────────────────── + +async function parseJsonBody(req: Request): Promise> { + try { + return (await req.json()) as Record + } catch { + throw ApiError.badRequest('Invalid JSON body') + } +} + +type ApiAgentDefinition = { + agentType: string + description?: string + model?: string + modelDisplay?: string + tools?: string[] + systemPrompt?: string + color?: string + source: SharedAgentDefinition['source'] + baseDir?: string + isActive: boolean +} + +type ApiResolvedAgentDefinition = ApiAgentDefinition & { + overriddenBy?: SharedAgentDefinition['source'] +} + +function serializeActiveAgent( + agent: SharedAgentDefinition, + isActive: boolean, +): ApiAgentDefinition { + return { + agentType: agent.agentType, + description: agent.whenToUse, + model: agent.model, + modelDisplay: resolveAgentModelDisplay(agent), + tools: agent.tools, + systemPrompt: agent.getSystemPrompt.length === 0 ? agent.getSystemPrompt() : undefined, + color: agent.color, + source: agent.source, + baseDir: agent.baseDir, + isActive, + } +} + +function serializeResolvedAgent(agent: ResolvedAgent): ApiResolvedAgentDefinition { + return { + ...serializeActiveAgent(agent, !agent.overriddenBy), + overriddenBy: agent.overriddenBy, + } +} diff --git a/_all-in-one-upload/cc-haha/src/server/index.ts b/_all-in-one-upload/cc-haha/src/server/index.ts new file mode 100644 index 0000000..7e6816a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/index.ts @@ -0,0 +1,271 @@ +/** + * Claude Code Desktop App — HTTP + WebSocket Server + * + * 为桌面端 UI 提供 REST API 和 WebSocket 实时通信。 + * 读写与 CLI 完全相同的文件系统,确保 CLI/UI 数据互通。 + */ + +import { handleApiRequest } from './router.js' +import { handleWebSocket, type WebSocketData } from './ws/handler.js' +import { corsHeaders } from './middleware/cors.js' +import { requireAuth } from './middleware/auth.js' +import { teamWatcher } from './services/teamWatcher.js' +import { cronScheduler } from './services/cronScheduler.js' +import { handleProxyRequest } from './proxy/handler.js' +import { ProviderService } from './services/providerService.js' +import { handleHahaOAuthCallback } from './api/haha-oauth.js' +import { ensureDesktopCliLauncherInstalled } from './services/desktopCliLauncherService.js' + +function readArgValue(flag: string): string | undefined { + const args = process.argv.slice(2) + const index = args.indexOf(flag) + if (index === -1) return undefined + return args[index + 1] +} + +function hasArgFlag(flag: string): boolean { + return process.argv.slice(2).includes(flag) +} + +function resolveServerOptions() { + const portArg = readArgValue('--port') + const port = Number.parseInt(portArg || process.env.SERVER_PORT || '3456', 10) + const host = readArgValue('--host') || process.env.SERVER_HOST || '127.0.0.1' + const cliPath = readArgValue('--cli-path') + const authRequired = hasArgFlag('--auth-required') + + if (cliPath) { + process.env.CLAUDE_CLI_PATH = cliPath + } + + return { port, host, authRequired } +} + +const SERVER_OPTIONS = resolveServerOptions() +const PORT = SERVER_OPTIONS.port +const HOST = SERVER_OPTIONS.host + +export function startServer(port = PORT, host = HOST) { + ProviderService.setServerPort(port) + const localConnectHost = + host === '0.0.0.0' || host === '127.0.0.1' || host === 'localhost' + ? '127.0.0.1' + : host + + /** + * Auth is required when explicitly opted in or when bound to a non-localhost address. + * - Default localhost dev: no auth needed (tests pass as-is). + * - Production / non-localhost (e.g. 0.0.0.0): auth enforced automatically. + * - Explicit opt-in: SERVER_AUTH_REQUIRED=1 forces auth even on localhost. + * - Explicit opt-out: SERVER_AUTH_REQUIRED=0 disables auth even on 0.0.0.0 + * (use only in trusted environments — e.g. a Docker container whose port + * is published to host loopback only). Takes precedence over the auto rule. + */ + const authForcedOff = process.env.SERVER_AUTH_REQUIRED === '0' + const authRequired = authForcedOff + ? false + : SERVER_OPTIONS.authRequired || + process.env.SERVER_AUTH_REQUIRED === '1' || + host !== '127.0.0.1' + + const server = Bun.serve({ + port, + hostname: host, + idleTimeout: 60, + + async fetch(req, server) { + const url = new URL(req.url) + + const origin = req.headers.get('Origin') + + // Handle CORS preflight + if (req.method === 'OPTIONS') { + return new Response(null, { status: 204, headers: corsHeaders(origin) }) + } + + // WebSocket upgrade + if (url.pathname.startsWith('/ws/')) { + // Enforce authentication when required + if (authRequired) { + const authError = requireAuth(req) + if (authError) { + const headers = new Headers(authError.headers) + for (const [key, value] of Object.entries(corsHeaders(origin))) { + headers.set(key, value) + } + return new Response(authError.body, { status: authError.status, headers }) + } + } + + // Validate session ID format + const sessionId = url.pathname.split('/').pop() || '' + if (!sessionId || !/^[0-9a-zA-Z_-]{1,64}$/.test(sessionId)) { + return new Response('Invalid session ID', { status: 400 }) + } + const upgraded = server.upgrade(req, { + data: { + sessionId, + connectedAt: Date.now(), + channel: 'client', + sdkToken: null, + serverPort: port, + serverHost: localConnectHost, + }, + }) + if (upgraded) return undefined + return new Response('WebSocket upgrade failed', { status: 400 }) + } + + // Internal SDK WebSocket used by the spawned Claude CLI. + if (url.pathname.startsWith('/sdk/')) { + const sessionId = url.pathname.split('/').pop() || '' + if (!sessionId || !/^[0-9a-zA-Z_-]{1,64}$/.test(sessionId)) { + return new Response('Invalid session ID', { status: 400 }) + } + const upgraded = server.upgrade(req, { + data: { + sessionId, + connectedAt: Date.now(), + channel: 'sdk', + sdkToken: url.searchParams.get('token'), + serverPort: port, + serverHost: localConnectHost, + }, + }) + if (upgraded) return undefined + return new Response('WebSocket upgrade failed', { status: 400 }) + } + + if (url.pathname === '/callback') { + return handleHahaOAuthCallback(url) + } + + // REST API + if (url.pathname.startsWith('/api/')) { + // Enforce authentication when required + if (authRequired) { + const authError = requireAuth(req) + if (authError) { + const headers = new Headers(authError.headers) + for (const [key, value] of Object.entries(corsHeaders(origin))) { + headers.set(key, value) + } + return new Response(authError.body, { status: authError.status, headers }) + } + } + + try { + const response = await handleApiRequest(req, url) + // Add CORS headers to all responses + const headers = new Headers(response.headers) + for (const [key, value] of Object.entries(corsHeaders(origin))) { + headers.set(key, value) + } + return new Response(response.body, { + status: response.status, + headers, + }) + } catch (error) { + console.error('[Server] API error:', error) + return Response.json( + { error: 'Internal server error' }, + { status: 500, headers: corsHeaders() } + ) + } + } + + // Proxy — protocol-translating reverse proxy for OpenAI-compatible APIs + if (url.pathname.startsWith('/proxy/')) { + if (authRequired) { + const authError = requireAuth(req) + if (authError) { + const headers = new Headers(authError.headers) + for (const [key, value] of Object.entries(corsHeaders(origin))) { + headers.set(key, value) + } + return new Response(authError.body, { status: authError.status, headers }) + } + } + try { + const response = await handleProxyRequest(req, url) + const headers = new Headers(response.headers) + for (const [key, value] of Object.entries(corsHeaders(origin))) { + headers.set(key, value) + } + return new Response(response.body, { + status: response.status, + headers, + }) + } catch (error) { + console.error('[Server] Proxy error:', error) + return Response.json( + { type: 'error', error: { type: 'api_error', message: 'Internal proxy error' } }, + { status: 500, headers: corsHeaders() }, + ) + } + } + + // Health check + if (url.pathname === '/health') { + return Response.json( + { status: 'ok', timestamp: new Date().toISOString() }, + { headers: corsHeaders(origin) }, + ) + } + + return new Response('Not Found', { status: 404 }) + }, + + websocket: handleWebSocket, + }) + + // Start watching ~/.claude/teams/ for real-time WebSocket push + teamWatcher.start() + + // Start the cron scheduler to execute scheduled tasks + cronScheduler.start() + + void ensureDesktopCliLauncherInstalled().catch((error) => { + console.error( + '[desktop-cli-launcher] failed to install bundled launcher:', + error instanceof Error ? error.message : error, + ) + }) + + console.log(`[Server] Claude Code API server running at http://${host}:${port}`) + return server +} + +// ─── Graceful shutdown: kill all CLI subprocesses on exit ──────────────────── +import { conversationService } from './services/conversationService.js' + +function cleanupAllSessions() { + const active = conversationService.getActiveSessions() + if (active.length > 0) { + console.log(`[Server] Shutting down — killing ${active.length} CLI subprocess(es)`) + for (const sessionId of active) { + conversationService.stopSession(sessionId) + } + } +} + +process.on('SIGTERM', () => { + console.log('[Server] Received SIGTERM') + cleanupAllSessions() + process.exit(0) +}) + +process.on('SIGINT', () => { + console.log('[Server] Received SIGINT') + cleanupAllSessions() + process.exit(0) +}) + +process.on('exit', () => { + cleanupAllSessions() +}) + +// Direct execution +if (import.meta.main) { + startServer() +} diff --git a/_all-in-one-upload/cc-haha/src/server/middleware/cors.test.ts b/_all-in-one-upload/cc-haha/src/server/middleware/cors.test.ts new file mode 100644 index 0000000..5753ada --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/middleware/cors.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'bun:test' +import { corsHeaders } from './cors' + +describe('corsHeaders', () => { + it('allows localhost browser origins', () => { + expect(corsHeaders('http://127.0.0.1:1420')['Access-Control-Allow-Origin']).toBe('http://127.0.0.1:1420') + expect(corsHeaders('http://localhost:3000')['Access-Control-Allow-Origin']).toBe('http://localhost:3000') + }) + + it('allows tauri webview origins used in production builds', () => { + expect(corsHeaders('http://tauri.localhost')['Access-Control-Allow-Origin']).toBe('http://tauri.localhost') + expect(corsHeaders('https://tauri.localhost')['Access-Control-Allow-Origin']).toBe('https://tauri.localhost') + expect(corsHeaders('tauri://localhost')['Access-Control-Allow-Origin']).toBe('tauri://localhost') + }) + + it('falls back for unknown origins', () => { + expect(corsHeaders('https://example.com')['Access-Control-Allow-Origin']).toBe('http://localhost:3000') + expect(corsHeaders(null)['Access-Control-Allow-Origin']).toBe('http://localhost:3000') + }) +}) diff --git a/_all-in-one-upload/cc-haha/src/server/proxy/streaming/openaiChatStreamToAnthropic.ts b/_all-in-one-upload/cc-haha/src/server/proxy/streaming/openaiChatStreamToAnthropic.ts new file mode 100644 index 0000000..054ecc7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/server/proxy/streaming/openaiChatStreamToAnthropic.ts @@ -0,0 +1,542 @@ +/** + * Streaming SSE transformation: OpenAI Chat Completions → Anthropic Messages + * + * Converts an OpenAI-compatible streaming response into Anthropic Messages + * streaming format. Follows the patterns established by LiteLLM's + * AnthropicStreamWrapper for correctness across many providers. + * + * Anthropic event order: + * message_start + * → (content_block_start → content_block_delta* → content_block_stop)* + * → message_delta + * → message_stop + * + * Derived from cc-switch (https://github.com/farion1231/cc-switch) + * Original work by Jason Young, MIT License + * + * Provider-specific reasoning formats handled: + * - delta.reasoning_content (DeepSeek, OpenRouter, XAI, Perplexity, …) + * - delta.thinking_blocks (OpenAI o-series) + * - delta.reasoning (GLM-5, Cerebras, Groq — mapped to reasoning_content) + */ + +import type { OpenAIChatStreamChunk } from '../transform/types.js' + +// ─── Types ───────────────────────────────────────────────── + +type ContentBlockType = 'text' | 'thinking' | 'tool_use' + +type ToolBlockState = { + id: string + name: string + argsBuffer: string + started: boolean + anthropicIndex: number +} + +type SseEvent = { event: string; data: unknown } + +type StreamState = { + // Event queue — guarantees correct multi-event ordering + queue: SseEvent[] + + // Content block tracking (mirrors LiteLLM's state machine) + currentBlockType: ContentBlockType + currentBlockIndex: number + nextContentIndex: number + blockStartSent: boolean // content_block_start emitted for current block? + blockStopSent: boolean // content_block_stop emitted for current block? + + // Tool call tracking + toolBlocks: Map + + // Message lifecycle + model: string + messageStartSent: boolean + messageDeltaSent: boolean + messageStopSent: boolean + + // Holding pattern: hold message_delta until usage arrives + // (some providers send finish_reason and usage in separate chunks) + heldMessageDelta: SseEvent | null +} + +// ─── Helpers ─────────────────────────────────────────────── + +function formatSse(event: string, data: unknown): string { + return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n` +} + +function createState(model: string): StreamState { + return { + queue: [], + currentBlockType: 'text', + currentBlockIndex: -1, + nextContentIndex: 0, + blockStartSent: false, + blockStopSent: false, + toolBlocks: new Map(), + model, + messageStartSent: false, + messageDeltaSent: false, + messageStopSent: false, + heldMessageDelta: null, + } +} + +// ─── Public entry point ──────────────────────────────────── + +/** + * Transform an OpenAI Chat Completions SSE stream into an Anthropic Messages SSE stream. + */ +export function openaiChatStreamToAnthropic( + upstream: ReadableStream, + model: string, +): ReadableStream { + const encoder = new TextEncoder() + const decoder = new TextDecoder() + let buffer = '' + const state = createState(model) + + return new ReadableStream({ + async start(controller) { + const reader = upstream.getReader() + let errored = false + + try { + while (true) { + const { done, value } = await reader.read() + if (done) break + + buffer += decoder.decode(value, { stream: true }) + const lines = buffer.split('\n') + buffer = lines.pop() || '' + + for (const line of lines) { + const trimmed = line.trim() + if (!trimmed || trimmed.startsWith(':')) continue + + if (trimmed === 'data: [DONE]') { + finalizeStream(state) + flushQueue(state, controller, encoder) + continue + } + + if (!trimmed.startsWith('data: ')) continue + const jsonStr = trimmed.slice(6) + + let chunk: OpenAIChatStreamChunk + try { + chunk = JSON.parse(jsonStr) + } catch { + continue + } + + processChunk(chunk, state) + flushQueue(state, controller, encoder) + } + } + } catch (err) { + errored = true + controller.error(err) + } finally { + if (!errored) { + finalizeStream(state) + flushQueue(state, controller, encoder) + controller.close() + } + } + }, + }) +} + +// ─── Queue management ────────────────────────────────────── + +function enqueue(state: StreamState, event: string, data: unknown): void { + state.queue.push({ event, data }) +} + +function flushQueue( + state: StreamState, + controller: ReadableStreamDefaultController, + encoder: TextEncoder, +): void { + for (const item of state.queue) { + controller.enqueue(encoder.encode(formatSse(item.event, item.data))) + } + state.queue.length = 0 +} + +// ─── Message lifecycle events ────────────────────────────── + +function ensureMessageStart(state: StreamState, chunkId?: string): void { + if (state.messageStartSent) return + state.messageStartSent = true + enqueue(state, 'message_start', { + type: 'message_start', + message: { + id: chunkId || `msg_${Date.now()}`, + type: 'message', + role: 'assistant', + content: [], + model: state.model, + stop_reason: null, + stop_sequence: null, + usage: { input_tokens: 0, output_tokens: 0 }, + }, + }) +} + +// ─── Content block lifecycle ─────────────────────────────── + +function openBlock(state: StreamState, blockType: ContentBlockType, block: Record): number { + const index = state.nextContentIndex++ + state.currentBlockType = blockType + state.currentBlockIndex = index + state.blockStartSent = true + state.blockStopSent = false + enqueue(state, 'content_block_start', { + type: 'content_block_start', + index, + content_block: block, + }) + return index +} + +function emitDelta(state: StreamState, index: number, delta: Record): void { + enqueue(state, 'content_block_delta', { + type: 'content_block_delta', + index, + delta, + }) +} + +function closeCurrentBlock(state: StreamState): void { + if (!state.blockStartSent || state.blockStopSent) return + state.blockStopSent = true + enqueue(state, 'content_block_stop', { + type: 'content_block_stop', + index: state.currentBlockIndex, + }) +} + +function closeAllToolBlocks(state: StreamState): void { + for (const [, block] of state.toolBlocks) { + if (block.started) { + enqueue(state, 'content_block_stop', { + type: 'content_block_stop', + index: block.anthropicIndex, + }) + } + } + state.toolBlocks.clear() +} + +function closeAllOpenBlocks(state: StreamState): void { + // Close current text/thinking block + closeCurrentBlock(state) + // Close all tool blocks + closeAllToolBlocks(state) +} + +// ─── Block type detection (follows LiteLLM priority) ─────── + +type DeltaEx = Record & { + content?: string | null + tool_calls?: Array<{ + index: number + id?: string + type?: string + function?: { name?: string; arguments?: string } + }> +} + +/** + * Extract reasoning/thinking content from delta regardless of provider format. + * + * Handles: + * delta.reasoning_content — DeepSeek, OpenRouter, XAI, Perplexity + * delta.reasoning — GLM-5, Cerebras, Groq + * delta.thinking_blocks — OpenAI o-series + */ +function extractReasoning(delta: DeltaEx): { thinking: string; signature: string } | null { + // Format 1: reasoning_content (most common) + if (typeof delta.reasoning_content === 'string' && delta.reasoning_content) { + return { thinking: delta.reasoning_content, signature: '' } + } + + // Format 2: reasoning (GLM-5, Cerebras, Groq) + if (typeof delta.reasoning === 'string' && delta.reasoning) { + return { thinking: delta.reasoning, signature: '' } + } + + // Format 3: thinking_blocks (OpenAI o-series) + const thinkingBlocks = delta.thinking_blocks as Array> | undefined + if (Array.isArray(thinkingBlocks) && thinkingBlocks.length > 0) { + const block = thinkingBlocks[0] + if (block.type === 'thinking') { + const thinking = (block.thinking as string) || '' + const signature = (block.signature as string) || '' + if (thinking || signature) { + return { thinking, signature } + } + } + } + + return null +} + +/** + * Determine what block type this chunk carries and whether it's a new block. + * Priority (matches LiteLLM): tool_calls > text > reasoning > ignore + */ +function detectBlockTransition( + delta: DeltaEx, + state: StreamState, +): { type: ContentBlockType; isNew: boolean } | null { + // Priority 1: Tool calls + if (delta.tool_calls && delta.tool_calls.length > 0) { + const tc = delta.tool_calls[0] + // A tool call with function.name signals a NEW tool block + const isNew = state.currentBlockType !== 'tool_use' || !!(tc.function?.name) + return { type: 'tool_use', isNew } + } + + // Priority 2: Text content + if (delta.content != null && delta.content !== '') { + const isNew = state.currentBlockType !== 'text' || !state.blockStartSent + return { type: 'text', isNew } + } + + // Priority 3: Reasoning/thinking + const reasoning = extractReasoning(delta) + if (reasoning) { + const isNew = state.currentBlockType !== 'thinking' || !state.blockStartSent + return { type: 'thinking', isNew } + } + + return null +} + +// ─── Main chunk processing ───────────────────────────────── + +function processChunk(chunk: OpenAIChatStreamChunk, state: StreamState): void { + const choice = chunk.choices?.[0] + + // Handle chunks with empty/missing choices (some providers send these) + if (!choice) { + // Check if this is a usage-only chunk (no choices but has usage) + if (chunk.usage && state.heldMessageDelta) { + mergeUsageIntoHeldDelta(state, chunk.usage) + } + return + } + + // Update model from first chunk + state.model = chunk.model || state.model + ensureMessageStart(state, chunk.id) + + const delta = choice.delta as DeltaEx + + // Detect what this chunk carries + const transition = detectBlockTransition(delta, state) + + if (transition) { + // Handle block transition: close previous block if type changed + if (transition.isNew && state.blockStartSent && !state.blockStopSent) { + if (transition.type !== 'tool_use') { + // For text/thinking, close the current block + closeCurrentBlock(state) + } else if (state.currentBlockType !== 'tool_use') { + // Switching TO tool_use from text/thinking: close current + closeCurrentBlock(state) + } + } + + switch (transition.type) { + case 'thinking': + handleThinking(delta, state) + break + case 'text': + handleText(delta, state) + break + case 'tool_use': + handleToolCalls(delta, state) + break + } + } + + // Handle finish_reason + if (choice.finish_reason) { + handleFinishReason(choice.finish_reason, chunk, state) + } +} + +// ─── Content handlers ────────────────────────────────────── + +function handleThinking(delta: DeltaEx, state: StreamState): void { + const reasoning = extractReasoning(delta) + if (!reasoning) return + + if (state.currentBlockType !== 'thinking' || !state.blockStartSent) { + openBlock(state, 'thinking', { type: 'thinking', thinking: '' }) + } + + if (reasoning.thinking) { + emitDelta(state, state.currentBlockIndex, { + type: 'thinking_delta', thinking: reasoning.thinking, + }) + } + if (reasoning.signature) { + emitDelta(state, state.currentBlockIndex, { + type: 'signature_delta', signature: reasoning.signature, + }) + } +} + +function handleText(delta: DeltaEx, state: StreamState): void { + if (delta.content == null || delta.content === '') return + + if (state.currentBlockType !== 'text' || !state.blockStartSent) { + openBlock(state, 'text', { type: 'text', text: '' }) + } + + emitDelta(state, state.currentBlockIndex, { + type: 'text_delta', text: delta.content, + }) +} + +function handleToolCalls(delta: DeltaEx, state: StreamState): void { + if (!delta.tool_calls) return + + for (const tc of delta.tool_calls) { + const tcIndex = tc.index + + if (!state.toolBlocks.has(tcIndex)) { + state.toolBlocks.set(tcIndex, { + id: '', name: '', argsBuffer: '', started: false, anthropicIndex: -1, + }) + } + + const block = state.toolBlocks.get(tcIndex)! + if (tc.id) block.id = tc.id + if (tc.function?.name) block.name += tc.function.name + if (tc.function?.arguments) block.argsBuffer += tc.function.arguments + + // Start tool block once we have id + name + if (!block.started && block.id && block.name) { + block.started = true + block.anthropicIndex = state.nextContentIndex++ + state.currentBlockType = 'tool_use' + state.blockStartSent = true + state.blockStopSent = false + + enqueue(state, 'content_block_start', { + type: 'content_block_start', + index: block.anthropicIndex, + content_block: { type: 'tool_use', id: block.id, name: block.name, input: {} }, + }) + + // Flush buffered arguments + if (block.argsBuffer) { + emitDelta(state, block.anthropicIndex, { + type: 'input_json_delta', partial_json: block.argsBuffer, + }) + } + } else if (block.started && tc.function?.arguments) { + emitDelta(state, block.anthropicIndex, { + type: 'input_json_delta', partial_json: tc.function.arguments, + }) + } + } +} + +// ─── Finish & usage handling ─────────────────────────────── + +function handleFinishReason( + finishReason: string, + chunk: OpenAIChatStreamChunk, + state: StreamState, +): void { + if (state.messageDeltaSent) return + + // CRITICAL: close ALL content blocks BEFORE message_delta + closeAllOpenBlocks(state) + + const stopReason = mapFinishReason(finishReason) + const usage = chunk.usage + ? { output_tokens: chunk.usage.completion_tokens || 0 } + : { output_tokens: 0 } + + const messageDelta: SseEvent = { + event: 'message_delta', + data: { + type: 'message_delta', + delta: { stop_reason: stopReason, stop_sequence: null }, + usage, + }, + } + + // If usage is available in the same chunk, emit immediately + if (chunk.usage) { + state.messageDeltaSent = true + state.queue.push(messageDelta) + } else { + // Hold message_delta, wait for usage chunk + state.heldMessageDelta = messageDelta + } +} + +function mergeUsageIntoHeldDelta( + state: StreamState, + usage: NonNullable, +): void { + if (!state.heldMessageDelta) return + + const data = state.heldMessageDelta.data as Record + data.usage = { output_tokens: usage.completion_tokens || 0 } + state.messageDeltaSent = true + state.queue.push(state.heldMessageDelta) + state.heldMessageDelta = null +} + +function finalizeStream(state: StreamState): void { + if (state.messageStopSent) return + state.messageStopSent = true + + ensureMessageStart(state) + + // Close any remaining open blocks + closeAllOpenBlocks(state) + + // Flush held message_delta if still waiting for usage + if (state.heldMessageDelta && !state.messageDeltaSent) { + state.messageDeltaSent = true + state.queue.push(state.heldMessageDelta) + state.heldMessageDelta = null + } + + // Emit message_delta if never sent (e.g., stream ended without finish_reason) + if (!state.messageDeltaSent) { + state.messageDeltaSent = true + enqueue(state, 'message_delta', { + type: 'message_delta', + delta: { stop_reason: 'end_turn', stop_sequence: null }, + usage: { output_tokens: 0 }, + }) + } + + enqueue(state, 'message_stop', { type: 'message_stop' }) +} + +// ─── Utilities ───────────────────────────────────────────── + +function mapFinishReason(reason: string): string { + switch (reason) { + case 'stop': return 'end_turn' + case 'tool_calls': return 'tool_use' + case 'length': return 'max_tokens' + case 'content_filter': return 'end_turn' + default: return 'end_turn' + } +} diff --git a/_all-in-one-upload/cc-haha/src/services/autoDream/autoDream.ts b/_all-in-one-upload/cc-haha/src/services/autoDream/autoDream.ts new file mode 100644 index 0000000..d387d9f --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/autoDream/autoDream.ts @@ -0,0 +1,324 @@ +// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered +// Background memory consolidation. Fires the /dream prompt as a forked +// subagent when time-gate passes AND enough sessions have accumulated. +// +// Gate order (cheapest first): +// 1. Time: hours since lastConsolidatedAt >= minHours (one stat) +// 2. Sessions: transcript count with mtime > lastConsolidatedAt >= minSessions +// 3. Lock: no other process mid-consolidation +// +// State is closure-scoped inside initAutoDream() rather than module-level +// (tests call initAutoDream() in beforeEach for a fresh closure). + +import type { REPLHookContext } from '../../utils/hooks/postSamplingHooks.js' +import { + createCacheSafeParams, + runForkedAgent, +} from '../../utils/forkedAgent.js' +import { + createUserMessage, + createMemorySavedMessage, +} from '../../utils/messages.js' +import type { Message } from '../../types/message.js' +import { logForDebugging } from '../../utils/debug.js' +import type { ToolUseContext } from '../../Tool.js' +import { logEvent } from '../analytics/index.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../analytics/growthbook.js' +import { isAutoMemoryEnabled, getAutoMemPath } from '../../memdir/paths.js' +import { isAutoDreamEnabled } from './config.js' +import { getProjectDir } from '../../utils/sessionStorage.js' +import { + getOriginalCwd, + getKairosActive, + getIsRemoteMode, + getSessionId, +} from '../../bootstrap/state.js' +import { createAutoMemCanUseTool } from '../extractMemories/extractMemories.js' +import { buildConsolidationPrompt } from './consolidationPrompt.js' +import { + readLastConsolidatedAt, + listSessionsTouchedSince, + tryAcquireConsolidationLock, + rollbackConsolidationLock, +} from './consolidationLock.js' +import { + registerDreamTask, + addDreamTurn, + completeDreamTask, + failDreamTask, + isDreamTask, +} from '../../tasks/DreamTask/DreamTask.js' +import { FILE_EDIT_TOOL_NAME } from '../../tools/FileEditTool/constants.js' +import { FILE_WRITE_TOOL_NAME } from '../../tools/FileWriteTool/prompt.js' + +// Scan throttle: when time-gate passes but session-gate doesn't, the lock +// mtime doesn't advance, so the time-gate keeps passing every turn. +const SESSION_SCAN_INTERVAL_MS = 10 * 60 * 1000 + +type AutoDreamConfig = { + minHours: number + minSessions: number +} + +const DEFAULTS: AutoDreamConfig = { + minHours: 24, + minSessions: 5, +} + +/** + * Thresholds from tengu_onyx_plover. The enabled gate lives in config.ts + * (isAutoDreamEnabled); this returns only the scheduling knobs. Defensive + * per-field validation since GB cache can return stale wrong-type values. + */ +function getConfig(): AutoDreamConfig { + const raw = + getFeatureValue_CACHED_MAY_BE_STALE | null>( + 'tengu_onyx_plover', + null, + ) + return { + minHours: + typeof raw?.minHours === 'number' && + Number.isFinite(raw.minHours) && + raw.minHours > 0 + ? raw.minHours + : DEFAULTS.minHours, + minSessions: + typeof raw?.minSessions === 'number' && + Number.isFinite(raw.minSessions) && + raw.minSessions > 0 + ? raw.minSessions + : DEFAULTS.minSessions, + } +} + +function isGateOpen(): boolean { + if (getKairosActive()) return false // KAIROS mode uses disk-skill dream + if (getIsRemoteMode()) return false + if (!isAutoMemoryEnabled()) return false + return isAutoDreamEnabled() +} + +// Ant-build-only test override. Bypasses enabled/time/session gates but NOT +// the lock (so repeated turns don't pile up dreams) or the memory-dir +// precondition. Still scans sessions so the prompt's session-hint is populated. +function isForced(): boolean { + return false +} + +type AppendSystemMessageFn = NonNullable + +let runner: + | (( + context: REPLHookContext, + appendSystemMessage?: AppendSystemMessageFn, + ) => Promise) + | null = null + +/** + * Call once at startup (from backgroundHousekeeping alongside + * initExtractMemories), or per-test in beforeEach for a fresh closure. + */ +export function initAutoDream(): void { + let lastSessionScanAt = 0 + + runner = async function runAutoDream(context, appendSystemMessage) { + const cfg = getConfig() + const force = isForced() + if (!force && !isGateOpen()) return + + // --- Time gate --- + let lastAt: number + try { + lastAt = await readLastConsolidatedAt() + } catch (e: unknown) { + logForDebugging( + `[autoDream] readLastConsolidatedAt failed: ${(e as Error).message}`, + ) + return + } + const hoursSince = (Date.now() - lastAt) / 3_600_000 + if (!force && hoursSince < cfg.minHours) return + + // --- Scan throttle --- + const sinceScanMs = Date.now() - lastSessionScanAt + if (!force && sinceScanMs < SESSION_SCAN_INTERVAL_MS) { + logForDebugging( + `[autoDream] scan throttle — time-gate passed but last scan was ${Math.round(sinceScanMs / 1000)}s ago`, + ) + return + } + lastSessionScanAt = Date.now() + + // --- Session gate --- + let sessionIds: string[] + try { + sessionIds = await listSessionsTouchedSince(lastAt) + } catch (e: unknown) { + logForDebugging( + `[autoDream] listSessionsTouchedSince failed: ${(e as Error).message}`, + ) + return + } + // Exclude the current session (its mtime is always recent). + const currentSession = getSessionId() + sessionIds = sessionIds.filter(id => id !== currentSession) + if (!force && sessionIds.length < cfg.minSessions) { + logForDebugging( + `[autoDream] skip — ${sessionIds.length} sessions since last consolidation, need ${cfg.minSessions}`, + ) + return + } + + // --- Lock --- + // Under force, skip acquire entirely — use the existing mtime so + // kill's rollback is a no-op (rewinds to where it already is). + // The lock file stays untouched; next non-force turn sees it as-is. + let priorMtime: number | null + if (force) { + priorMtime = lastAt + } else { + try { + priorMtime = await tryAcquireConsolidationLock() + } catch (e: unknown) { + logForDebugging( + `[autoDream] lock acquire failed: ${(e as Error).message}`, + ) + return + } + if (priorMtime === null) return + } + + logForDebugging( + `[autoDream] firing — ${hoursSince.toFixed(1)}h since last, ${sessionIds.length} sessions to review`, + ) + logEvent('tengu_auto_dream_fired', { + hours_since: Math.round(hoursSince), + sessions_since: sessionIds.length, + }) + + const setAppState = + context.toolUseContext.setAppStateForTasks ?? + context.toolUseContext.setAppState + const abortController = new AbortController() + const taskId = registerDreamTask(setAppState, { + sessionsReviewing: sessionIds.length, + priorMtime, + abortController, + }) + + try { + const memoryRoot = getAutoMemPath() + const transcriptDir = getProjectDir(getOriginalCwd()) + // Tool constraints note goes in `extra`, not the shared prompt body — + // manual /dream runs in the main loop with normal permissions and this + // would be misleading there. + const extra = ` + +**Tool constraints for this run:** Bash is restricted to read-only commands (\`ls\`, \`find\`, \`grep\`, \`cat\`, \`stat\`, \`wc\`, \`head\`, \`tail\`, and similar). Anything that writes, redirects to a file, or modifies state will be denied. Plan your exploration with this in mind — no need to probe. + +Sessions since last consolidation (${sessionIds.length}): +${sessionIds.map(id => `- ${id}`).join('\n')}` + const prompt = buildConsolidationPrompt(memoryRoot, transcriptDir, extra) + + const result = await runForkedAgent({ + promptMessages: [createUserMessage({ content: prompt })], + cacheSafeParams: createCacheSafeParams(context), + canUseTool: createAutoMemCanUseTool(memoryRoot), + querySource: 'auto_dream', + forkLabel: 'auto_dream', + skipTranscript: true, + overrides: { abortController }, + onMessage: makeDreamProgressWatcher(taskId, setAppState), + }) + + completeDreamTask(taskId, setAppState) + // Inline completion summary in the main transcript (same surface as + // extractMemories's "Saved N memories" message). + const dreamState = context.toolUseContext.getAppState().tasks?.[taskId] + if ( + appendSystemMessage && + isDreamTask(dreamState) && + dreamState.filesTouched.length > 0 + ) { + appendSystemMessage({ + ...createMemorySavedMessage(dreamState.filesTouched), + verb: 'Improved', + }) + } + logForDebugging( + `[autoDream] completed — cache: read=${result.totalUsage.cache_read_input_tokens} created=${result.totalUsage.cache_creation_input_tokens}`, + ) + logEvent('tengu_auto_dream_completed', { + cache_read: result.totalUsage.cache_read_input_tokens, + cache_created: result.totalUsage.cache_creation_input_tokens, + output: result.totalUsage.output_tokens, + sessions_reviewed: sessionIds.length, + }) + } catch (e: unknown) { + // If the user killed from the bg-tasks dialog, DreamTask.kill already + // aborted, rolled back the lock, and set status=killed. Don't overwrite + // or double-rollback. + if (abortController.signal.aborted) { + logForDebugging('[autoDream] aborted by user') + return + } + logForDebugging(`[autoDream] fork failed: ${(e as Error).message}`) + logEvent('tengu_auto_dream_failed', {}) + failDreamTask(taskId, setAppState) + // Rewind mtime so time-gate passes again. Scan throttle is the backoff. + await rollbackConsolidationLock(priorMtime) + } + } +} + +/** + * Watch the forked agent's messages. For each assistant turn, extracts any + * text blocks (the agent's reasoning/summary — what the user wants to see) + * and collapses tool_use blocks to a count. Edit/Write file_paths are + * collected for phase-flip + the inline completion message. + */ +function makeDreamProgressWatcher( + taskId: string, + setAppState: import('../../Task.js').SetAppState, +): (msg: Message) => void { + return msg => { + if (msg.type !== 'assistant') return + let text = '' + let toolUseCount = 0 + const touchedPaths: string[] = [] + for (const block of msg.message.content) { + if (block.type === 'text') { + text += block.text + } else if (block.type === 'tool_use') { + toolUseCount++ + if ( + block.name === FILE_EDIT_TOOL_NAME || + block.name === FILE_WRITE_TOOL_NAME + ) { + const input = block.input as { file_path?: unknown } + if (typeof input.file_path === 'string') { + touchedPaths.push(input.file_path) + } + } + } + } + addDreamTurn( + taskId, + { text: text.trim(), toolUseCount }, + touchedPaths, + setAppState, + ) + } +} + +/** + * Entry point from stopHooks. No-op until initAutoDream() has been called. + * Per-turn cost when enabled: one GB cache read + one stat. + */ +export async function executeAutoDream( + context: REPLHookContext, + appendSystemMessage?: AppendSystemMessageFn, +): Promise { + await runner?.(context, appendSystemMessage) +} diff --git a/_all-in-one-upload/cc-haha/src/services/autoDream/config.ts b/_all-in-one-upload/cc-haha/src/services/autoDream/config.ts new file mode 100644 index 0000000..3ed70ef --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/autoDream/config.ts @@ -0,0 +1,21 @@ +// Leaf config module — intentionally minimal imports so UI components +// can read the auto-dream enabled state without dragging in the forked +// agent / task registry / message builder chain that autoDream.ts pulls in. + +import { getInitialSettings } from '../../utils/settings/settings.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../analytics/growthbook.js' + +/** + * Whether background memory consolidation should run. User setting + * (autoDreamEnabled in settings.json) overrides the GrowthBook default + * when explicitly set; otherwise falls through to tengu_onyx_plover. + */ +export function isAutoDreamEnabled(): boolean { + const setting = getInitialSettings().autoDreamEnabled + if (setting !== undefined) return setting + const gb = getFeatureValue_CACHED_MAY_BE_STALE<{ enabled?: unknown } | null>( + 'tengu_onyx_plover', + null, + ) + return gb?.enabled === true +} diff --git a/_all-in-one-upload/cc-haha/src/services/compact/apiMicrocompact.ts b/_all-in-one-upload/cc-haha/src/services/compact/apiMicrocompact.ts new file mode 100644 index 0000000..4a6b84b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/compact/apiMicrocompact.ts @@ -0,0 +1,153 @@ +import { FILE_EDIT_TOOL_NAME } from 'src/tools/FileEditTool/constants.js' +import { FILE_READ_TOOL_NAME } from 'src/tools/FileReadTool/prompt.js' +import { FILE_WRITE_TOOL_NAME } from 'src/tools/FileWriteTool/prompt.js' +import { GLOB_TOOL_NAME } from 'src/tools/GlobTool/prompt.js' +import { GREP_TOOL_NAME } from 'src/tools/GrepTool/prompt.js' +import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js' +import { WEB_FETCH_TOOL_NAME } from 'src/tools/WebFetchTool/prompt.js' +import { WEB_SEARCH_TOOL_NAME } from 'src/tools/WebSearchTool/prompt.js' +import { SHELL_TOOL_NAMES } from 'src/utils/shell/shellToolUtils.js' +import { isEnvTruthy } from '../../utils/envUtils.js' + +// docs: https://docs.google.com/document/d/1oCT4evvWTh3P6z-kcfNQwWTCxAhkoFndSaNS9Gm40uw/edit?tab=t.0 + +// Default values for context management strategies +// Match client-side microcompact token values +const DEFAULT_MAX_INPUT_TOKENS = 180_000 // Typical warning threshold +const DEFAULT_TARGET_INPUT_TOKENS = 40_000 // Keep last 40k tokens like client-side + +const TOOLS_CLEARABLE_RESULTS = [ + ...SHELL_TOOL_NAMES, + GLOB_TOOL_NAME, + GREP_TOOL_NAME, + FILE_READ_TOOL_NAME, + WEB_FETCH_TOOL_NAME, + WEB_SEARCH_TOOL_NAME, +] + +const TOOLS_CLEARABLE_USES = [ + FILE_EDIT_TOOL_NAME, + FILE_WRITE_TOOL_NAME, + NOTEBOOK_EDIT_TOOL_NAME, +] + +// Context management strategy types matching API documentation +export type ContextEditStrategy = + | { + type: 'clear_tool_uses_20250919' + trigger?: { + type: 'input_tokens' + value: number + } + keep?: { + type: 'tool_uses' + value: number + } + clear_tool_inputs?: boolean | string[] + exclude_tools?: string[] + clear_at_least?: { + type: 'input_tokens' + value: number + } + } + | { + type: 'clear_thinking_20251015' + keep: { type: 'thinking_turns'; value: number } | 'all' + } + +// Context management configuration wrapper +export type ContextManagementConfig = { + edits: ContextEditStrategy[] +} + +// API-based microcompact implementation that uses native context management +export function getAPIContextManagement(options?: { + hasThinking?: boolean + isRedactThinkingActive?: boolean + clearAllThinking?: boolean +}): ContextManagementConfig | undefined { + const { + hasThinking = false, + isRedactThinkingActive = false, + clearAllThinking = false, + } = options ?? {} + + const strategies: ContextEditStrategy[] = [] + + // Preserve thinking blocks in previous assistant turns. Skip when + // redact-thinking is active — redacted blocks have no model-visible content. + // When clearAllThinking is set (>1h idle = cache miss), keep only the last + // thinking turn — the API schema requires value >= 1, and omitting the edit + // falls back to the model-policy default (often "all"), which wouldn't clear. + if (hasThinking && !isRedactThinkingActive) { + strategies.push({ + type: 'clear_thinking_20251015', + keep: clearAllThinking ? { type: 'thinking_turns', value: 1 } : 'all', + }) + } + + // Tool clearing strategies are ant-only + if (process.env.USER_TYPE !== 'ant') { + return strategies.length > 0 ? { edits: strategies } : undefined + } + + const useClearToolResults = isEnvTruthy( + process.env.USE_API_CLEAR_TOOL_RESULTS, + ) + const useClearToolUses = isEnvTruthy(process.env.USE_API_CLEAR_TOOL_USES) + + // If no tool clearing strategy is enabled, return early + if (!useClearToolResults && !useClearToolUses) { + return strategies.length > 0 ? { edits: strategies } : undefined + } + + if (useClearToolResults) { + const triggerThreshold = process.env.API_MAX_INPUT_TOKENS + ? parseInt(process.env.API_MAX_INPUT_TOKENS) + : DEFAULT_MAX_INPUT_TOKENS + const keepTarget = process.env.API_TARGET_INPUT_TOKENS + ? parseInt(process.env.API_TARGET_INPUT_TOKENS) + : DEFAULT_TARGET_INPUT_TOKENS + + const strategy: ContextEditStrategy = { + type: 'clear_tool_uses_20250919', + trigger: { + type: 'input_tokens', + value: triggerThreshold, + }, + clear_at_least: { + type: 'input_tokens', + value: triggerThreshold - keepTarget, + }, + clear_tool_inputs: TOOLS_CLEARABLE_RESULTS, + } + + strategies.push(strategy) + } + + if (useClearToolUses) { + const triggerThreshold = process.env.API_MAX_INPUT_TOKENS + ? parseInt(process.env.API_MAX_INPUT_TOKENS) + : DEFAULT_MAX_INPUT_TOKENS + const keepTarget = process.env.API_TARGET_INPUT_TOKENS + ? parseInt(process.env.API_TARGET_INPUT_TOKENS) + : DEFAULT_TARGET_INPUT_TOKENS + + const strategy: ContextEditStrategy = { + type: 'clear_tool_uses_20250919', + trigger: { + type: 'input_tokens', + value: triggerThreshold, + }, + clear_at_least: { + type: 'input_tokens', + value: triggerThreshold - keepTarget, + }, + exclude_tools: TOOLS_CLEARABLE_USES, + } + + strategies.push(strategy) + } + + return strategies.length > 0 ? { edits: strategies } : undefined +} diff --git a/_all-in-one-upload/cc-haha/src/services/compact/compact.ts b/_all-in-one-upload/cc-haha/src/services/compact/compact.ts new file mode 100644 index 0000000..f8f86ea --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/compact/compact.ts @@ -0,0 +1,1705 @@ +import { feature } from 'bun:bundle' +import type { UUID } from 'crypto' +import uniqBy from 'lodash-es/uniqBy.js' + +/* eslint-disable @typescript-eslint/no-require-imports */ +const sessionTranscriptModule = feature('KAIROS') + ? (require('../sessionTranscript/sessionTranscript.js') as typeof import('../sessionTranscript/sessionTranscript.js')) + : null + +import { APIUserAbortError } from '@anthropic-ai/sdk' +import { markPostCompaction } from 'src/bootstrap/state.js' +import { getInvokedSkillsForAgent } from '../../bootstrap/state.js' +import type { QuerySource } from '../../constants/querySource.js' +import type { CanUseToolFn } from '../../hooks/useCanUseTool.js' +import type { Tool, ToolUseContext } from '../../Tool.js' +import type { LocalAgentTaskState } from '../../tasks/LocalAgentTask/LocalAgentTask.js' +import { FileReadTool } from '../../tools/FileReadTool/FileReadTool.js' +import { + FILE_READ_TOOL_NAME, + FILE_UNCHANGED_STUB, +} from '../../tools/FileReadTool/prompt.js' +import { ToolSearchTool } from '../../tools/ToolSearchTool/ToolSearchTool.js' +import type { AgentId } from '../../types/ids.js' +import type { + AssistantMessage, + AttachmentMessage, + HookResultMessage, + Message, + PartialCompactDirection, + SystemCompactBoundaryMessage, + SystemMessage, + UserMessage, +} from '../../types/message.js' +import { + createAttachmentMessage, + generateFileAttachment, + getAgentListingDeltaAttachment, + getDeferredToolsDeltaAttachment, + getMcpInstructionsDeltaAttachment, +} from '../../utils/attachments.js' +import { getMemoryPath } from '../../utils/config.js' +import { COMPACT_MAX_OUTPUT_TOKENS } from '../../utils/context.js' +import { + analyzeContext, + tokenStatsToStatsigMetrics, +} from '../../utils/contextAnalysis.js' +import { logForDebugging } from '../../utils/debug.js' +import { hasExactErrorMessage } from '../../utils/errors.js' +import { cacheToObject } from '../../utils/fileStateCache.js' +import { + type CacheSafeParams, + runForkedAgent, +} from '../../utils/forkedAgent.js' +import { + executePostCompactHooks, + executePreCompactHooks, +} from '../../utils/hooks.js' +import { logError } from '../../utils/log.js' +import { MEMORY_TYPE_VALUES } from '../../utils/memory/types.js' +import { + createCompactBoundaryMessage, + createUserMessage, + getAssistantMessageText, + getLastAssistantMessage, + getMessagesAfterCompactBoundary, + isCompactBoundaryMessage, + normalizeMessagesForAPI, +} from '../../utils/messages.js' +import { expandPath } from '../../utils/path.js' +import { getPlan, getPlanFilePath } from '../../utils/plans.js' +import { + isSessionActivityTrackingActive, + sendSessionActivitySignal, +} from '../../utils/sessionActivity.js' +import { processSessionStartHooks } from '../../utils/sessionStart.js' +import { + getTranscriptPath, + reAppendSessionMetadata, +} from '../../utils/sessionStorage.js' +import { sleep } from '../../utils/sleep.js' +import { jsonStringify } from '../../utils/slowOperations.js' +/* eslint-enable @typescript-eslint/no-require-imports */ +import { asSystemPrompt } from '../../utils/systemPromptType.js' +import { getTaskOutputPath } from '../../utils/task/diskOutput.js' +import { + getTokenUsage, + tokenCountFromLastAPIResponse, + tokenCountWithEstimation, +} from '../../utils/tokens.js' +import { + extractDiscoveredToolNames, + isToolSearchEnabled, +} from '../../utils/toolSearch.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../analytics/growthbook.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../analytics/index.js' +import { + getMaxOutputTokensForModel, + queryModelWithStreaming, +} from '../api/claude.js' +import { + getPromptTooLongTokenGap, + PROMPT_TOO_LONG_ERROR_MESSAGE, + startsWithApiErrorPrefix, +} from '../api/errors.js' +import { notifyCompaction } from '../api/promptCacheBreakDetection.js' +import { getRetryDelay } from '../api/withRetry.js' +import { logPermissionContextForAnts } from '../internalLogging.js' +import { + roughTokenCountEstimation, + roughTokenCountEstimationForMessages, +} from '../tokenEstimation.js' +import { groupMessagesByApiRound } from './grouping.js' +import { + getCompactPrompt, + getCompactUserSummaryMessage, + getPartialCompactPrompt, +} from './prompt.js' + +export const POST_COMPACT_MAX_FILES_TO_RESTORE = 5 +export const POST_COMPACT_TOKEN_BUDGET = 50_000 +export const POST_COMPACT_MAX_TOKENS_PER_FILE = 5_000 +// Skills can be large (verify=18.7KB, claude-api=20.1KB). Previously re-injected +// unbounded on every compact → 5-10K tok/compact. Per-skill truncation beats +// dropping — instructions at the top of a skill file are usually the critical +// part. Budget sized to hold ~5 skills at the per-skill cap. +export const POST_COMPACT_MAX_TOKENS_PER_SKILL = 5_000 +export const POST_COMPACT_SKILLS_TOKEN_BUDGET = 25_000 +const MAX_COMPACT_STREAMING_RETRIES = 2 + +/** + * Strip image blocks from user messages before sending for compaction. + * Images are not needed for generating a conversation summary and can + * cause the compaction API call itself to hit the prompt-too-long limit, + * especially in CCD sessions where users frequently attach images. + * Replaces image blocks with a text marker so the summary still notes + * that an image was shared. + * + * Note: Only user messages contain images (either directly attached or within + * tool_result content from tools). Assistant messages contain text, tool_use, + * and thinking blocks but not images. + */ +export function stripImagesFromMessages(messages: Message[]): Message[] { + return messages.map(message => { + if (message.type !== 'user') { + return message + } + + const content = message.message.content + if (!Array.isArray(content)) { + return message + } + + let hasMediaBlock = false + const newContent = content.flatMap(block => { + if (block.type === 'image') { + hasMediaBlock = true + return [{ type: 'text' as const, text: '[image]' }] + } + if (block.type === 'document') { + hasMediaBlock = true + return [{ type: 'text' as const, text: '[document]' }] + } + // Also strip images/documents nested inside tool_result content arrays + if (block.type === 'tool_result' && Array.isArray(block.content)) { + let toolHasMedia = false + const newToolContent = block.content.map(item => { + if (item.type === 'image') { + toolHasMedia = true + return { type: 'text' as const, text: '[image]' } + } + if (item.type === 'document') { + toolHasMedia = true + return { type: 'text' as const, text: '[document]' } + } + return item + }) + if (toolHasMedia) { + hasMediaBlock = true + return [{ ...block, content: newToolContent }] + } + } + return [block] + }) + + if (!hasMediaBlock) { + return message + } + + return { + ...message, + message: { + ...message.message, + content: newContent, + }, + } as typeof message + }) +} + +/** + * Strip attachment types that are re-injected post-compaction anyway. + * skill_discovery/skill_listing are re-surfaced by resetSentSkillNames() + * + the next turn's discovery signal, so feeding them to the summarizer + * wastes tokens and pollutes the summary with stale skill suggestions. + * + * No-op when EXPERIMENTAL_SKILL_SEARCH is off (the attachment types + * don't exist on external builds). + */ +export function stripReinjectedAttachments(messages: Message[]): Message[] { + if (feature('EXPERIMENTAL_SKILL_SEARCH')) { + return messages.filter( + m => + !( + m.type === 'attachment' && + (m.attachment.type === 'skill_discovery' || + m.attachment.type === 'skill_listing') + ), + ) + } + return messages +} + +export const ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = + 'Not enough messages to compact.' +const MAX_PTL_RETRIES = 3 +const PTL_RETRY_MARKER = '[earlier conversation truncated for compaction retry]' + +/** + * Drops the oldest API-round groups from messages until tokenGap is covered. + * Falls back to dropping 20% of groups when the gap is unparseable (some + * Vertex/Bedrock error formats). Returns null when nothing can be dropped + * without leaving an empty summarize set. + * + * This is the last-resort escape hatch for CC-1180 — when the compact request + * itself hits prompt-too-long, the user is otherwise stuck. Dropping the + * oldest context is lossy but unblocks them. The reactive-compact path + * (compactMessages.ts) has the proper retry loop that peels from the tail; + * this helper is the dumb-but-safe fallback for the proactive/manual path + * that wasn't migrated in bfdb472f's unification. + */ +export function truncateHeadForPTLRetry( + messages: Message[], + ptlResponse: AssistantMessage, +): Message[] | null { + // Strip our own synthetic marker from a previous retry before grouping. + // Otherwise it becomes its own group 0 and the 20% fallback stalls + // (drops only the marker, re-adds it, zero progress on retry 2+). + const input = + messages[0]?.type === 'user' && + messages[0].isMeta && + messages[0].message.content === PTL_RETRY_MARKER + ? messages.slice(1) + : messages + + const groups = groupMessagesByApiRound(input) + if (groups.length < 2) return null + + const tokenGap = getPromptTooLongTokenGap(ptlResponse) + let dropCount: number + if (tokenGap !== undefined) { + let acc = 0 + dropCount = 0 + for (const g of groups) { + acc += roughTokenCountEstimationForMessages(g) + dropCount++ + if (acc >= tokenGap) break + } + } else { + dropCount = Math.max(1, Math.floor(groups.length * 0.2)) + } + + // Keep at least one group so there's something to summarize. + dropCount = Math.min(dropCount, groups.length - 1) + if (dropCount < 1) return null + + const sliced = groups.slice(dropCount).flat() + // groupMessagesByApiRound puts the preamble in group 0 and starts every + // subsequent group with an assistant message. Dropping group 0 leaves an + // assistant-first sequence which the API rejects (first message must be + // role=user). Prepend a synthetic user marker — ensureToolResultPairing + // already handles any orphaned tool_results this creates. + if (sliced[0]?.type === 'assistant') { + return [ + createUserMessage({ content: PTL_RETRY_MARKER, isMeta: true }), + ...sliced, + ] + } + return sliced +} + +export const ERROR_MESSAGE_PROMPT_TOO_LONG = + 'Conversation too long. Press esc twice to go up a few messages and try again.' +export const ERROR_MESSAGE_USER_ABORT = 'API Error: Request was aborted.' +export const ERROR_MESSAGE_INCOMPLETE_RESPONSE = + 'Compaction interrupted · This may be due to network issues — please try again.' + +export interface CompactionResult { + boundaryMarker: SystemMessage + summaryMessages: UserMessage[] + attachments: AttachmentMessage[] + hookResults: HookResultMessage[] + messagesToKeep?: Message[] + userDisplayMessage?: string + preCompactTokenCount?: number + postCompactTokenCount?: number + truePostCompactTokenCount?: number + compactionUsage?: ReturnType +} + +/** + * Diagnosis context passed from autoCompactIfNeeded into compactConversation. + * Lets the tengu_compact event disambiguate same-chain loops (H2) from + * cross-agent (H1/H5) and manual-vs-auto (H3) compactions without joins. + */ +export type RecompactionInfo = { + isRecompactionInChain: boolean + turnsSincePreviousCompact: number + previousCompactTurnId?: string + autoCompactThreshold: number + querySource?: QuerySource +} + +/** + * Build the base post-compact messages array from a CompactionResult. + * This ensures consistent ordering across all compaction paths. + * Order: boundaryMarker, summaryMessages, messagesToKeep, attachments, hookResults + */ +export function buildPostCompactMessages(result: CompactionResult): Message[] { + return [ + result.boundaryMarker, + ...result.summaryMessages, + ...(result.messagesToKeep ?? []), + ...result.attachments, + ...result.hookResults, + ] +} + +/** + * Annotate a compact boundary with relink metadata for messagesToKeep. + * Preserved messages keep their original parentUuids on disk (dedup-skipped); + * the loader uses this to patch head→anchor and anchor's-other-children→tail. + * + * `anchorUuid` = what sits immediately before keep[0] in the desired chain: + * - suffix-preserving (reactive/session-memory): last summary message + * - prefix-preserving (partial compact): the boundary itself + */ +export function annotateBoundaryWithPreservedSegment( + boundary: SystemCompactBoundaryMessage, + anchorUuid: UUID, + messagesToKeep: readonly Message[] | undefined, +): SystemCompactBoundaryMessage { + const keep = messagesToKeep ?? [] + if (keep.length === 0) return boundary + return { + ...boundary, + compactMetadata: { + ...boundary.compactMetadata, + preservedSegment: { + headUuid: keep[0]!.uuid, + anchorUuid, + tailUuid: keep.at(-1)!.uuid, + }, + }, + } +} + +/** + * Merges user-supplied custom instructions with hook-provided instructions. + * User instructions come first; hook instructions are appended. + * Empty strings normalize to undefined. + */ +export function mergeHookInstructions( + userInstructions: string | undefined, + hookInstructions: string | undefined, +): string | undefined { + if (!hookInstructions) return userInstructions || undefined + if (!userInstructions) return hookInstructions + return `${userInstructions}\n\n${hookInstructions}` +} + +/** + * Creates a compact version of a conversation by summarizing older messages + * and preserving recent conversation history. + */ +export async function compactConversation( + messages: Message[], + context: ToolUseContext, + cacheSafeParams: CacheSafeParams, + suppressFollowUpQuestions: boolean, + customInstructions?: string, + isAutoCompact: boolean = false, + recompactionInfo?: RecompactionInfo, +): Promise { + try { + if (messages.length === 0) { + throw new Error(ERROR_MESSAGE_NOT_ENOUGH_MESSAGES) + } + + const preCompactTokenCount = tokenCountWithEstimation(messages) + + const appState = context.getAppState() + void logPermissionContextForAnts(appState.toolPermissionContext, 'summary') + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'pre_compact', + }) + + // Execute PreCompact hooks + context.setSDKStatus?.('compacting') + const hookResult = await executePreCompactHooks( + { + trigger: isAutoCompact ? 'auto' : 'manual', + customInstructions: customInstructions ?? null, + }, + context.abortController.signal, + ) + customInstructions = mergeHookInstructions( + customInstructions, + hookResult.newCustomInstructions, + ) + const userDisplayMessage = hookResult.userDisplayMessage + + // Show requesting mode with up arrow and custom message + context.setStreamMode?.('requesting') + context.setResponseLength?.(() => 0) + context.onCompactProgress?.({ type: 'compact_start' }) + + // 3P default: true — forked-agent path reuses main conversation's prompt cache. + // Experiment (Jan 2026) confirmed: false path is 98% cache miss, costs ~0.76% of + // fleet cache_creation (~38B tok/day), concentrated in ephemeral envs (CCR/GHA/SDK) + // with cold GB cache and 3P providers where GB is disabled. GB gate kept as kill-switch. + const promptCacheSharingEnabled = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_compact_cache_prefix', + true, + ) + + const compactPrompt = getCompactPrompt(customInstructions) + const summaryRequest = createUserMessage({ + content: compactPrompt, + }) + + let messagesToSummarize = messages + let retryCacheSafeParams = cacheSafeParams + let summaryResponse: AssistantMessage + let summary: string | null + let ptlAttempts = 0 + for (;;) { + summaryResponse = await streamCompactSummary({ + messages: messagesToSummarize, + summaryRequest, + appState, + context, + preCompactTokenCount, + cacheSafeParams: retryCacheSafeParams, + }) + summary = getAssistantMessageText(summaryResponse) + if (!summary?.startsWith(PROMPT_TOO_LONG_ERROR_MESSAGE)) break + + // CC-1180: compact request itself hit prompt-too-long. Truncate the + // oldest API-round groups and retry rather than leaving the user stuck. + ptlAttempts++ + const truncated = + ptlAttempts <= MAX_PTL_RETRIES + ? truncateHeadForPTLRetry(messagesToSummarize, summaryResponse) + : null + if (!truncated) { + logEvent('tengu_compact_failed', { + reason: + 'prompt_too_long' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + promptCacheSharingEnabled, + ptlAttempts, + }) + throw new Error(ERROR_MESSAGE_PROMPT_TOO_LONG) + } + logEvent('tengu_compact_ptl_retry', { + attempt: ptlAttempts, + droppedMessages: messagesToSummarize.length - truncated.length, + remainingMessages: truncated.length, + }) + messagesToSummarize = truncated + // The forked-agent path reads from cacheSafeParams.forkContextMessages, + // not the messages param — thread the truncated set through both paths. + retryCacheSafeParams = { + ...retryCacheSafeParams, + forkContextMessages: truncated, + } + } + + if (!summary) { + logForDebugging( + `Compact failed: no summary text in response. Response: ${jsonStringify(summaryResponse)}`, + { level: 'error' }, + ) + logEvent('tengu_compact_failed', { + reason: + 'no_summary' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + promptCacheSharingEnabled, + }) + throw new Error( + `Failed to generate conversation summary - response did not contain valid text content`, + ) + } else if (startsWithApiErrorPrefix(summary)) { + logEvent('tengu_compact_failed', { + reason: + 'api_error' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + promptCacheSharingEnabled, + }) + throw new Error(summary) + } + + // Store the current file state before clearing + const preCompactReadFileState = cacheToObject(context.readFileState) + + // Clear the cache + context.readFileState.clear() + context.loadedNestedMemoryPaths?.clear() + + // Intentionally NOT resetting sentSkillNames: re-injecting the full + // skill_listing (~4K tokens) post-compact is pure cache_creation with + // marginal benefit. The model still has SkillTool in its schema and + // invoked_skills attachment (below) preserves used-skill content. Ants + // with EXPERIMENTAL_SKILL_SEARCH already skip re-injection via the + // early-return in getSkillListingAttachments. + + // Run async attachment generation in parallel + const [fileAttachments, asyncAgentAttachments] = await Promise.all([ + createPostCompactFileAttachments( + preCompactReadFileState, + context, + POST_COMPACT_MAX_FILES_TO_RESTORE, + ), + createAsyncAgentAttachmentsIfNeeded(context), + ]) + + const postCompactFileAttachments: AttachmentMessage[] = [ + ...fileAttachments, + ...asyncAgentAttachments, + ] + const planAttachment = createPlanAttachmentIfNeeded(context.agentId) + if (planAttachment) { + postCompactFileAttachments.push(planAttachment) + } + + // Add plan mode instructions if currently in plan mode, so the model + // continues operating in plan mode after compaction + const planModeAttachment = await createPlanModeAttachmentIfNeeded(context) + if (planModeAttachment) { + postCompactFileAttachments.push(planModeAttachment) + } + + // Add skill attachment if skills were invoked in this session + const skillAttachment = createSkillAttachmentIfNeeded(context.agentId) + if (skillAttachment) { + postCompactFileAttachments.push(skillAttachment) + } + + // Compaction ate prior delta attachments. Re-announce from the current + // state so the model has tool/instruction context on the first + // post-compact turn. Empty message history → diff against nothing → + // announces the full set. + for (const att of getDeferredToolsDeltaAttachment( + context.options.tools, + context.options.mainLoopModel, + [], + { callSite: 'compact_full' }, + )) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + for (const att of getAgentListingDeltaAttachment(context, [])) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + for (const att of getMcpInstructionsDeltaAttachment( + context.options.mcpClients, + context.options.tools, + context.options.mainLoopModel, + [], + )) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'session_start', + }) + // Execute SessionStart hooks after successful compaction + const hookMessages = await processSessionStartHooks('compact', { + model: context.options.mainLoopModel, + }) + + // Create the compact boundary marker and summary messages before the + // event so we can compute the true resulting-context size. + const boundaryMarker = createCompactBoundaryMessage( + isAutoCompact ? 'auto' : 'manual', + preCompactTokenCount ?? 0, + messages.at(-1)?.uuid, + ) + // Carry loaded-tool state — the summary doesn't preserve tool_reference + // blocks, so the post-compact schema filter needs this to keep sending + // already-loaded deferred tool schemas to the API. + const preCompactDiscovered = extractDiscoveredToolNames(messages) + if (preCompactDiscovered.size > 0) { + boundaryMarker.compactMetadata.preCompactDiscoveredTools = [ + ...preCompactDiscovered, + ].sort() + } + + const transcriptPath = getTranscriptPath() + const summaryMessages: UserMessage[] = [ + createUserMessage({ + content: getCompactUserSummaryMessage( + summary, + suppressFollowUpQuestions, + transcriptPath, + ), + isCompactSummary: true, + isVisibleInTranscriptOnly: true, + }), + ] + + // Previously "postCompactTokenCount" — renamed because this is the + // compact API call's total usage (input_tokens ≈ preCompactTokenCount), + // NOT the size of the resulting context. Kept for event-field continuity. + const compactionCallTotalTokens = tokenCountFromLastAPIResponse([ + summaryResponse, + ]) + + // Message-payload estimate of the resulting context. The next iteration's + // shouldAutoCompact will see this PLUS ~20-40K for system prompt + tools + + // userContext (via API usage.input_tokens). So `willRetriggerNextTurn: true` + // is a strong signal; `false` may still retrigger when this is close to threshold. + const truePostCompactTokenCount = roughTokenCountEstimationForMessages([ + boundaryMarker, + ...summaryMessages, + ...postCompactFileAttachments, + ...hookMessages, + ]) + + // Extract compaction API usage metrics + const compactionUsage = getTokenUsage(summaryResponse) + + const querySourceForEvent = + recompactionInfo?.querySource ?? context.options.querySource ?? 'unknown' + + logEvent('tengu_compact', { + preCompactTokenCount, + // Kept for continuity — semantically the compact API call's total usage + postCompactTokenCount: compactionCallTotalTokens, + truePostCompactTokenCount, + autoCompactThreshold: recompactionInfo?.autoCompactThreshold ?? -1, + willRetriggerNextTurn: + recompactionInfo !== undefined && + truePostCompactTokenCount >= recompactionInfo.autoCompactThreshold, + isAutoCompact, + querySource: + querySourceForEvent as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryChainId: (context.queryTracking?.chainId ?? + '') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: context.queryTracking?.depth ?? -1, + isRecompactionInChain: recompactionInfo?.isRecompactionInChain ?? false, + turnsSincePreviousCompact: + recompactionInfo?.turnsSincePreviousCompact ?? -1, + previousCompactTurnId: (recompactionInfo?.previousCompactTurnId ?? + '') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + compactionInputTokens: compactionUsage?.input_tokens, + compactionOutputTokens: compactionUsage?.output_tokens, + compactionCacheReadTokens: compactionUsage?.cache_read_input_tokens ?? 0, + compactionCacheCreationTokens: + compactionUsage?.cache_creation_input_tokens ?? 0, + compactionTotalTokens: compactionUsage + ? compactionUsage.input_tokens + + (compactionUsage.cache_creation_input_tokens ?? 0) + + (compactionUsage.cache_read_input_tokens ?? 0) + + compactionUsage.output_tokens + : 0, + promptCacheSharingEnabled, + // analyzeContext walks every content block (~11ms on a 4.5K-message + // session) purely for this telemetry breakdown. Computed here, past + // the compaction-API await, so the sync walk doesn't starve the + // render loop before compaction even starts. Same deferral pattern + // as reactiveCompact.ts. + ...(() => { + try { + return tokenStatsToStatsigMetrics(analyzeContext(messages)) + } catch (error) { + logError(error as Error) + return {} + } + })(), + }) + + // Reset cache read baseline so the post-compact drop isn't flagged as a break + if (feature('PROMPT_CACHE_BREAK_DETECTION')) { + notifyCompaction( + context.options.querySource ?? 'compact', + context.agentId, + ) + } + markPostCompaction() + + // Re-append session metadata (custom title, tag) so it stays within + // the 16KB tail window that readLiteMetadata reads for --resume display. + // Without this, enough post-compaction messages push the metadata entry + // out of the window, causing --resume to show the auto-generated title + // instead of the user-set session name. + reAppendSessionMetadata() + + // Write a reduced transcript segment for the pre-compaction messages + // (assistant mode only). Fire-and-forget — errors are logged internally. + if (feature('KAIROS')) { + void sessionTranscriptModule?.writeSessionTranscriptSegment(messages) + } + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'post_compact', + }) + const postCompactHookResult = await executePostCompactHooks( + { + trigger: isAutoCompact ? 'auto' : 'manual', + compactSummary: summary, + }, + context.abortController.signal, + ) + + const combinedUserDisplayMessage = [ + userDisplayMessage, + postCompactHookResult.userDisplayMessage, + ] + .filter(Boolean) + .join('\n') + + return { + boundaryMarker, + summaryMessages, + attachments: postCompactFileAttachments, + hookResults: hookMessages, + userDisplayMessage: combinedUserDisplayMessage || undefined, + preCompactTokenCount, + postCompactTokenCount: compactionCallTotalTokens, + truePostCompactTokenCount, + compactionUsage, + } + } catch (error) { + // Only show the error notification for manual /compact. + // Auto-compact failures are retried on the next turn and the + // notification is confusing when compaction eventually succeeds. + if (!isAutoCompact) { + addErrorNotificationIfNeeded(error, context) + } + throw error + } finally { + context.setStreamMode?.('requesting') + context.setResponseLength?.(() => 0) + context.onCompactProgress?.({ type: 'compact_end' }) + context.setSDKStatus?.(null) + } +} + +/** + * Performs a partial compaction around the selected message index. + * Direction 'from': summarizes messages after the index, keeps earlier ones. + * Prompt cache for kept (earlier) messages is preserved. + * Direction 'up_to': summarizes messages before the index, keeps later ones. + * Prompt cache is invalidated since the summary precedes the kept messages. + */ +export async function partialCompactConversation( + allMessages: Message[], + pivotIndex: number, + context: ToolUseContext, + cacheSafeParams: CacheSafeParams, + userFeedback?: string, + direction: PartialCompactDirection = 'from', +): Promise { + try { + const messagesToSummarize = + direction === 'up_to' + ? allMessages.slice(0, pivotIndex) + : allMessages.slice(pivotIndex) + // 'up_to' must strip old compact boundaries/summaries: for 'up_to', + // summary_B sits BEFORE kept, so a stale boundary_A in kept wins + // findLastCompactBoundaryIndex's backward scan and drops summary_B. + // 'from' keeps them: summary_B sits AFTER kept (backward scan still + // works), and removing an old summary would lose its covered history. + const messagesToKeep = + direction === 'up_to' + ? allMessages + .slice(pivotIndex) + .filter( + m => + m.type !== 'progress' && + !isCompactBoundaryMessage(m) && + !(m.type === 'user' && m.isCompactSummary), + ) + : allMessages.slice(0, pivotIndex).filter(m => m.type !== 'progress') + + if (messagesToSummarize.length === 0) { + throw new Error( + direction === 'up_to' + ? 'Nothing to summarize before the selected message.' + : 'Nothing to summarize after the selected message.', + ) + } + + const preCompactTokenCount = tokenCountWithEstimation(allMessages) + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'pre_compact', + }) + + context.setSDKStatus?.('compacting') + const hookResult = await executePreCompactHooks( + { + trigger: 'manual', + customInstructions: null, + }, + context.abortController.signal, + ) + + // Merge hook instructions with user feedback + let customInstructions: string | undefined + if (hookResult.newCustomInstructions && userFeedback) { + customInstructions = `${hookResult.newCustomInstructions}\n\nUser context: ${userFeedback}` + } else if (hookResult.newCustomInstructions) { + customInstructions = hookResult.newCustomInstructions + } else if (userFeedback) { + customInstructions = `User context: ${userFeedback}` + } + + context.setStreamMode?.('requesting') + context.setResponseLength?.(() => 0) + context.onCompactProgress?.({ type: 'compact_start' }) + + const compactPrompt = getPartialCompactPrompt(customInstructions, direction) + const summaryRequest = createUserMessage({ + content: compactPrompt, + }) + + const failureMetadata = { + preCompactTokenCount, + direction: + direction as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + messagesSummarized: messagesToSummarize.length, + } + + // 'up_to' prefix hits cache directly; 'from' sends all (tail wouldn't cache). + // PTL retry breaks the cache prefix but unblocks the user (CC-1180). + let apiMessages = direction === 'up_to' ? messagesToSummarize : allMessages + let retryCacheSafeParams = + direction === 'up_to' + ? { ...cacheSafeParams, forkContextMessages: messagesToSummarize } + : cacheSafeParams + let summaryResponse: AssistantMessage + let summary: string | null + let ptlAttempts = 0 + for (;;) { + summaryResponse = await streamCompactSummary({ + messages: apiMessages, + summaryRequest, + appState: context.getAppState(), + context, + preCompactTokenCount, + cacheSafeParams: retryCacheSafeParams, + }) + summary = getAssistantMessageText(summaryResponse) + if (!summary?.startsWith(PROMPT_TOO_LONG_ERROR_MESSAGE)) break + + ptlAttempts++ + const truncated = + ptlAttempts <= MAX_PTL_RETRIES + ? truncateHeadForPTLRetry(apiMessages, summaryResponse) + : null + if (!truncated) { + logEvent('tengu_partial_compact_failed', { + reason: + 'prompt_too_long' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...failureMetadata, + ptlAttempts, + }) + throw new Error(ERROR_MESSAGE_PROMPT_TOO_LONG) + } + logEvent('tengu_compact_ptl_retry', { + attempt: ptlAttempts, + droppedMessages: apiMessages.length - truncated.length, + remainingMessages: truncated.length, + path: 'partial' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }) + apiMessages = truncated + retryCacheSafeParams = { + ...retryCacheSafeParams, + forkContextMessages: truncated, + } + } + if (!summary) { + logEvent('tengu_partial_compact_failed', { + reason: + 'no_summary' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...failureMetadata, + }) + throw new Error( + 'Failed to generate conversation summary - response did not contain valid text content', + ) + } else if (startsWithApiErrorPrefix(summary)) { + logEvent('tengu_partial_compact_failed', { + reason: + 'api_error' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...failureMetadata, + }) + throw new Error(summary) + } + + // Store the current file state before clearing + const preCompactReadFileState = cacheToObject(context.readFileState) + context.readFileState.clear() + context.loadedNestedMemoryPaths?.clear() + // Intentionally NOT resetting sentSkillNames — see compactConversation() + // for rationale (~4K tokens saved per compact event). + + const [fileAttachments, asyncAgentAttachments] = await Promise.all([ + createPostCompactFileAttachments( + preCompactReadFileState, + context, + POST_COMPACT_MAX_FILES_TO_RESTORE, + messagesToKeep, + ), + createAsyncAgentAttachmentsIfNeeded(context), + ]) + + const postCompactFileAttachments: AttachmentMessage[] = [ + ...fileAttachments, + ...asyncAgentAttachments, + ] + const planAttachment = createPlanAttachmentIfNeeded(context.agentId) + if (planAttachment) { + postCompactFileAttachments.push(planAttachment) + } + + // Add plan mode instructions if currently in plan mode + const planModeAttachment = await createPlanModeAttachmentIfNeeded(context) + if (planModeAttachment) { + postCompactFileAttachments.push(planModeAttachment) + } + + const skillAttachment = createSkillAttachmentIfNeeded(context.agentId) + if (skillAttachment) { + postCompactFileAttachments.push(skillAttachment) + } + + // Re-announce only what was in the summarized portion — messagesToKeep + // is scanned, so anything already announced there is skipped. + for (const att of getDeferredToolsDeltaAttachment( + context.options.tools, + context.options.mainLoopModel, + messagesToKeep, + { callSite: 'compact_partial' }, + )) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + for (const att of getAgentListingDeltaAttachment(context, messagesToKeep)) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + for (const att of getMcpInstructionsDeltaAttachment( + context.options.mcpClients, + context.options.tools, + context.options.mainLoopModel, + messagesToKeep, + )) { + postCompactFileAttachments.push(createAttachmentMessage(att)) + } + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'session_start', + }) + const hookMessages = await processSessionStartHooks('compact', { + model: context.options.mainLoopModel, + }) + + const postCompactTokenCount = tokenCountFromLastAPIResponse([ + summaryResponse, + ]) + const compactionUsage = getTokenUsage(summaryResponse) + + logEvent('tengu_partial_compact', { + preCompactTokenCount, + postCompactTokenCount, + messagesKept: messagesToKeep.length, + messagesSummarized: messagesToSummarize.length, + direction: + direction as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + hasUserFeedback: !!userFeedback, + trigger: + 'message_selector' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + compactionInputTokens: compactionUsage?.input_tokens, + compactionOutputTokens: compactionUsage?.output_tokens, + compactionCacheReadTokens: compactionUsage?.cache_read_input_tokens ?? 0, + compactionCacheCreationTokens: + compactionUsage?.cache_creation_input_tokens ?? 0, + }) + + // Progress messages aren't loggable, so forkSessionImpl would null out + // a logicalParentUuid pointing at one. Both directions skip them. + const lastPreCompactUuid = + direction === 'up_to' + ? allMessages.slice(0, pivotIndex).findLast(m => m.type !== 'progress') + ?.uuid + : messagesToKeep.at(-1)?.uuid + const boundaryMarker = createCompactBoundaryMessage( + 'manual', + preCompactTokenCount ?? 0, + lastPreCompactUuid, + userFeedback, + messagesToSummarize.length, + ) + // allMessages not just messagesToSummarize — set union is idempotent, + // simpler than tracking which half each tool lived in. + const preCompactDiscovered = extractDiscoveredToolNames(allMessages) + if (preCompactDiscovered.size > 0) { + boundaryMarker.compactMetadata.preCompactDiscoveredTools = [ + ...preCompactDiscovered, + ].sort() + } + + const transcriptPath = getTranscriptPath() + const summaryMessages: UserMessage[] = [ + createUserMessage({ + content: getCompactUserSummaryMessage(summary, false, transcriptPath), + isCompactSummary: true, + ...(messagesToKeep.length > 0 + ? { + summarizeMetadata: { + messagesSummarized: messagesToSummarize.length, + userContext: userFeedback, + direction, + }, + } + : { isVisibleInTranscriptOnly: true as const }), + }), + ] + + if (feature('PROMPT_CACHE_BREAK_DETECTION')) { + notifyCompaction( + context.options.querySource ?? 'compact', + context.agentId, + ) + } + markPostCompaction() + + // Re-append session metadata (custom title, tag) so it stays within + // the 16KB tail window that readLiteMetadata reads for --resume display. + reAppendSessionMetadata() + + if (feature('KAIROS')) { + void sessionTranscriptModule?.writeSessionTranscriptSegment( + messagesToSummarize, + ) + } + + context.onCompactProgress?.({ + type: 'hooks_start', + hookType: 'post_compact', + }) + const postCompactHookResult = await executePostCompactHooks( + { + trigger: 'manual', + compactSummary: summary, + }, + context.abortController.signal, + ) + + // 'from': prefix-preserving → boundary; 'up_to': suffix → last summary + const anchorUuid = + direction === 'up_to' + ? (summaryMessages.at(-1)?.uuid ?? boundaryMarker.uuid) + : boundaryMarker.uuid + return { + boundaryMarker: annotateBoundaryWithPreservedSegment( + boundaryMarker, + anchorUuid, + messagesToKeep, + ), + summaryMessages, + messagesToKeep, + attachments: postCompactFileAttachments, + hookResults: hookMessages, + userDisplayMessage: postCompactHookResult.userDisplayMessage, + preCompactTokenCount, + postCompactTokenCount, + compactionUsage, + } + } catch (error) { + addErrorNotificationIfNeeded(error, context) + throw error + } finally { + context.setStreamMode?.('requesting') + context.setResponseLength?.(() => 0) + context.onCompactProgress?.({ type: 'compact_end' }) + context.setSDKStatus?.(null) + } +} + +function addErrorNotificationIfNeeded( + error: unknown, + context: Pick, +) { + if ( + !hasExactErrorMessage(error, ERROR_MESSAGE_USER_ABORT) && + !hasExactErrorMessage(error, ERROR_MESSAGE_NOT_ENOUGH_MESSAGES) + ) { + context.addNotification?.({ + key: 'error-compacting-conversation', + text: 'Error compacting conversation', + priority: 'immediate', + color: 'error', + }) + } +} + +export function createCompactCanUseTool(): CanUseToolFn { + return async () => ({ + behavior: 'deny' as const, + message: 'Tool use is not allowed during compaction', + decisionReason: { + type: 'other' as const, + reason: 'compaction agent should only produce text summary', + }, + }) +} + +async function streamCompactSummary({ + messages, + summaryRequest, + appState, + context, + preCompactTokenCount, + cacheSafeParams, +}: { + messages: Message[] + summaryRequest: UserMessage + appState: Awaited> + context: ToolUseContext + preCompactTokenCount: number + cacheSafeParams: CacheSafeParams +}): Promise { + // When prompt cache sharing is enabled, use forked agent to reuse the + // main conversation's cached prefix (system prompt, tools, context messages). + // Falls back to regular streaming path on failure. + // 3P default: true — see comment at the other tengu_compact_cache_prefix read above. + const promptCacheSharingEnabled = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_compact_cache_prefix', + true, + ) + // Send keep-alive signals during compaction to prevent remote session + // WebSocket idle timeouts from dropping bridge connections. Compaction + // API calls can take 5-10+ seconds, during which no other messages + // flow through the transport — without keep-alives, the server may + // close the WebSocket for inactivity. + // Two signals: (1) PUT /worker heartbeat via sessionActivity, and + // (2) re-emit 'compacting' status so the SDK event stream stays active + // and the server doesn't consider the session stale. + const activityInterval = isSessionActivityTrackingActive() + ? setInterval( + (statusSetter?: (status: 'compacting' | null) => void) => { + sendSessionActivitySignal() + statusSetter?.('compacting') + }, + 30_000, + context.setSDKStatus, + ) + : undefined + + try { + if (promptCacheSharingEnabled) { + try { + // DO NOT set maxOutputTokens here. The fork piggybacks on the main thread's + // prompt cache by sending identical cache-key params (system, tools, model, + // messages prefix, thinking config). Setting maxOutputTokens would clamp + // budget_tokens via Math.min(budget, maxOutputTokens-1) in claude.ts, + // creating a thinking config mismatch that invalidates the cache. + // The streaming fallback path (below) can safely set maxOutputTokensOverride + // since it doesn't share cache with the main thread. + const result = await runForkedAgent({ + promptMessages: [summaryRequest], + cacheSafeParams, + canUseTool: createCompactCanUseTool(), + querySource: 'compact', + forkLabel: 'compact', + maxTurns: 1, + skipCacheWrite: true, + // Pass the compact context's abortController so user Esc aborts the + // fork — same signal the streaming fallback uses at + // `signal: context.abortController.signal` below. + overrides: { abortController: context.abortController }, + }) + const assistantMsg = getLastAssistantMessage(result.messages) + const assistantText = assistantMsg + ? getAssistantMessageText(assistantMsg) + : null + // Guard isApiErrorMessage: query() catches API errors (including + // APIUserAbortError on ESC) and yields them as synthetic assistant + // messages. Without this check, an aborted compact "succeeds" with + // "Request was aborted." as the summary — the text doesn't start with + // "API Error" so the caller's startsWithApiErrorPrefix guard misses it. + if (assistantMsg && assistantText && !assistantMsg.isApiErrorMessage) { + // Skip success logging for PTL error text — it's returned so the + // caller's retry loop catches it, but it's not a successful summary. + if (!assistantText.startsWith(PROMPT_TOO_LONG_ERROR_MESSAGE)) { + logEvent('tengu_compact_cache_sharing_success', { + preCompactTokenCount, + outputTokens: result.totalUsage.output_tokens, + cacheReadInputTokens: result.totalUsage.cache_read_input_tokens, + cacheCreationInputTokens: + result.totalUsage.cache_creation_input_tokens, + cacheHitRate: + result.totalUsage.cache_read_input_tokens > 0 + ? result.totalUsage.cache_read_input_tokens / + (result.totalUsage.cache_read_input_tokens + + result.totalUsage.cache_creation_input_tokens + + result.totalUsage.input_tokens) + : 0, + }) + } + return assistantMsg + } + logForDebugging( + `Compact cache sharing: no text in response, falling back. Response: ${jsonStringify(assistantMsg)}`, + { level: 'warn' }, + ) + logEvent('tengu_compact_cache_sharing_fallback', { + reason: + 'no_text_response' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + }) + } catch (error) { + logError(error) + logEvent('tengu_compact_cache_sharing_fallback', { + reason: + 'error' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + }) + } + } + + // Regular streaming path (fallback when cache sharing fails or is disabled) + const retryEnabled = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_compact_streaming_retry', + false, + ) + const maxAttempts = retryEnabled ? MAX_COMPACT_STREAMING_RETRIES : 1 + + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + // Reset state for retry + let hasStartedStreaming = false + let response: AssistantMessage | undefined + context.setResponseLength?.(() => 0) + + // Check if tool search is enabled using the main loop's tools list. + // context.options.tools includes MCP tools merged via useMergedTools. + const useToolSearch = await isToolSearchEnabled( + context.options.mainLoopModel, + context.options.tools, + async () => appState.toolPermissionContext, + context.options.agentDefinitions.activeAgents, + 'compact', + ) + + // When tool search is enabled, include ToolSearchTool and MCP tools. They get + // defer_loading: true and don't count against context - the API filters them out + // of system_prompt_tools before token counting (see api/token_count_api/counting.py:188 + // and api/public_api/messages/handler.py:324). + // Filter MCP tools from context.options.tools (not appState.mcp.tools) so we + // get the permission-filtered set from useMergedTools — same source used for + // isToolSearchEnabled above and normalizeMessagesForAPI below. + // Deduplicate by name to avoid API errors when MCP tools share names with built-in tools. + const tools: Tool[] = useToolSearch + ? uniqBy( + [ + FileReadTool, + ToolSearchTool, + ...context.options.tools.filter(t => t.isMcp), + ], + 'name', + ) + : [FileReadTool] + + const streamingGen = queryModelWithStreaming({ + messages: normalizeMessagesForAPI( + stripImagesFromMessages( + stripReinjectedAttachments([ + ...getMessagesAfterCompactBoundary(messages), + summaryRequest, + ]), + ), + context.options.tools, + ), + systemPrompt: asSystemPrompt([ + 'You are a helpful AI assistant tasked with summarizing conversations.', + ]), + thinkingConfig: { type: 'disabled' as const }, + tools, + signal: context.abortController.signal, + options: { + async getToolPermissionContext() { + const appState = context.getAppState() + return appState.toolPermissionContext + }, + model: context.options.mainLoopModel, + toolChoice: undefined, + isNonInteractiveSession: context.options.isNonInteractiveSession, + hasAppendSystemPrompt: !!context.options.appendSystemPrompt, + maxOutputTokensOverride: Math.min( + COMPACT_MAX_OUTPUT_TOKENS, + getMaxOutputTokensForModel(context.options.mainLoopModel), + ), + querySource: 'compact', + agents: context.options.agentDefinitions.activeAgents, + mcpTools: [], + effortValue: appState.effortValue, + }, + }) + const streamIter = streamingGen[Symbol.asyncIterator]() + let next = await streamIter.next() + + while (!next.done) { + const event = next.value + + if ( + !hasStartedStreaming && + event.type === 'stream_event' && + event.event.type === 'content_block_start' && + event.event.content_block.type === 'text' + ) { + hasStartedStreaming = true + context.setStreamMode?.('responding') + } + + if ( + event.type === 'stream_event' && + event.event.type === 'content_block_delta' && + event.event.delta.type === 'text_delta' + ) { + const charactersStreamed = event.event.delta.text.length + context.setResponseLength?.(length => length + charactersStreamed) + } + + if (event.type === 'assistant') { + response = event + } + + next = await streamIter.next() + } + + if (response) { + return response + } + + if (attempt < maxAttempts) { + logEvent('tengu_compact_streaming_retry', { + attempt, + preCompactTokenCount, + hasStartedStreaming, + }) + await sleep(getRetryDelay(attempt), context.abortController.signal, { + abortError: () => new APIUserAbortError(), + }) + continue + } + + logForDebugging( + `Compact streaming failed after ${attempt} attempts. hasStartedStreaming=${hasStartedStreaming}`, + { level: 'error' }, + ) + logEvent('tengu_compact_failed', { + reason: + 'no_streaming_response' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + preCompactTokenCount, + hasStartedStreaming, + retryEnabled, + attempts: attempt, + promptCacheSharingEnabled, + }) + throw new Error(ERROR_MESSAGE_INCOMPLETE_RESPONSE) + } + + // This should never be reached due to the throw above, but TypeScript needs it + throw new Error(ERROR_MESSAGE_INCOMPLETE_RESPONSE) + } finally { + clearInterval(activityInterval) + } +} + +/** + * Creates attachment messages for recently accessed files to restore them after compaction. + * This prevents the model from having to re-read files that were recently accessed. + * Re-reads files using FileReadTool to get fresh content with proper validation. + * Files are selected based on recency, but constrained by both file count and token budget limits. + * + * Files already present as Read tool results in preservedMessages are skipped — + * re-injecting identical content the model can already see in the preserved tail + * is pure waste (up to 25K tok/compact). Mirrors the diff-against-preserved + * pattern that getDeferredToolsDeltaAttachment uses at the same call sites. + * + * @param readFileState The current file state tracking recently read files + * @param toolUseContext The tool use context for calling FileReadTool + * @param maxFiles Maximum number of files to restore (default: 5) + * @param preservedMessages Messages kept post-compact; Read results here are skipped + * @returns Array of attachment messages for the most recently accessed files that fit within token budget + */ +export async function createPostCompactFileAttachments( + readFileState: Record, + toolUseContext: ToolUseContext, + maxFiles: number, + preservedMessages: Message[] = [], +): Promise { + const preservedReadPaths = collectReadToolFilePaths(preservedMessages) + const recentFiles = Object.entries(readFileState) + .map(([filename, state]) => ({ filename, ...state })) + .filter( + file => + !shouldExcludeFromPostCompactRestore( + file.filename, + toolUseContext.agentId, + ) && !preservedReadPaths.has(expandPath(file.filename)), + ) + .sort((a, b) => b.timestamp - a.timestamp) + .slice(0, maxFiles) + + const results = await Promise.all( + recentFiles.map(async file => { + const attachment = await generateFileAttachment( + file.filename, + { + ...toolUseContext, + fileReadingLimits: { + maxTokens: POST_COMPACT_MAX_TOKENS_PER_FILE, + }, + }, + 'tengu_post_compact_file_restore_success', + 'tengu_post_compact_file_restore_error', + 'compact', + ) + return attachment ? createAttachmentMessage(attachment) : null + }), + ) + + let usedTokens = 0 + return results.filter((result): result is AttachmentMessage => { + if (result === null) { + return false + } + const attachmentTokens = roughTokenCountEstimation(jsonStringify(result)) + if (usedTokens + attachmentTokens <= POST_COMPACT_TOKEN_BUDGET) { + usedTokens += attachmentTokens + return true + } + return false + }) +} + +/** + * Creates a plan file attachment if a plan file exists for the current session. + * This ensures the plan is preserved after compaction. + */ +export function createPlanAttachmentIfNeeded( + agentId?: AgentId, +): AttachmentMessage | null { + const planContent = getPlan(agentId) + + if (!planContent) { + return null + } + + const planFilePath = getPlanFilePath(agentId) + + return createAttachmentMessage({ + type: 'plan_file_reference', + planFilePath, + planContent, + }) +} + +/** + * Creates an attachment for invoked skills to preserve their content across compaction. + * Only includes skills scoped to the given agent (or main session when agentId is null/undefined). + * This ensures skill guidelines remain available after the conversation is summarized + * without leaking skills from other agent contexts. + */ +export function createSkillAttachmentIfNeeded( + agentId?: string, +): AttachmentMessage | null { + const invokedSkills = getInvokedSkillsForAgent(agentId) + + if (invokedSkills.size === 0) { + return null + } + + // Sorted most-recent-first so budget pressure drops the least-relevant skills. + // Per-skill truncation keeps the head of each file (where setup/usage + // instructions typically live) rather than dropping whole skills. + let usedTokens = 0 + const skills = Array.from(invokedSkills.values()) + .sort((a, b) => b.invokedAt - a.invokedAt) + .map(skill => ({ + name: skill.skillName, + path: skill.skillPath, + content: truncateToTokens( + skill.content, + POST_COMPACT_MAX_TOKENS_PER_SKILL, + ), + })) + .filter(skill => { + const tokens = roughTokenCountEstimation(skill.content) + if (usedTokens + tokens > POST_COMPACT_SKILLS_TOKEN_BUDGET) { + return false + } + usedTokens += tokens + return true + }) + + if (skills.length === 0) { + return null + } + + return createAttachmentMessage({ + type: 'invoked_skills', + skills, + }) +} + +/** + * Creates a plan_mode attachment if the user is currently in plan mode. + * This ensures the model continues to operate in plan mode after compaction + * (otherwise it would lose the plan mode instructions since those are + * normally only injected on tool-use turns via getAttachmentMessages). + */ +export async function createPlanModeAttachmentIfNeeded( + context: ToolUseContext, +): Promise { + const appState = context.getAppState() + if (appState.toolPermissionContext.mode !== 'plan') { + return null + } + + const planFilePath = getPlanFilePath(context.agentId) + const planExists = getPlan(context.agentId) !== null + + return createAttachmentMessage({ + type: 'plan_mode', + reminderType: 'full', + isSubAgent: !!context.agentId, + planFilePath, + planExists, + }) +} + +/** + * Creates attachments for async agents so the model knows about them after + * compaction. Covers both agents still running in the background (so the model + * doesn't spawn a duplicate) and agents that have finished but whose results + * haven't been retrieved yet. + */ +export async function createAsyncAgentAttachmentsIfNeeded( + context: ToolUseContext, +): Promise { + const appState = context.getAppState() + const asyncAgents = Object.values(appState.tasks).filter( + (task): task is LocalAgentTaskState => task.type === 'local_agent', + ) + + return asyncAgents.flatMap(agent => { + if ( + agent.retrieved || + agent.status === 'pending' || + agent.agentId === context.agentId + ) { + return [] + } + return [ + createAttachmentMessage({ + type: 'task_status', + taskId: agent.agentId, + taskType: 'local_agent', + description: agent.description, + status: agent.status, + deltaSummary: + agent.status === 'running' + ? (agent.progress?.summary ?? null) + : (agent.error ?? null), + outputFilePath: getTaskOutputPath(agent.agentId), + }), + ] + }) +} + +/** + * Scan messages for Read tool_use blocks and collect their file_path inputs + * (normalized via expandPath). Used to dedup post-compact file restoration + * against what's already visible in the preserved tail. + * + * Skips Reads whose tool_result is a dedup stub — the stub points at an + * earlier full Read that may have been compacted away, so we want + * createPostCompactFileAttachments to re-inject the real content. + */ +function collectReadToolFilePaths(messages: Message[]): Set { + const stubIds = new Set() + for (const message of messages) { + if (message.type !== 'user' || !Array.isArray(message.message.content)) { + continue + } + for (const block of message.message.content) { + if ( + block.type === 'tool_result' && + typeof block.content === 'string' && + block.content.startsWith(FILE_UNCHANGED_STUB) + ) { + stubIds.add(block.tool_use_id) + } + } + } + + const paths = new Set() + for (const message of messages) { + if ( + message.type !== 'assistant' || + !Array.isArray(message.message.content) + ) { + continue + } + for (const block of message.message.content) { + if ( + block.type !== 'tool_use' || + block.name !== FILE_READ_TOOL_NAME || + stubIds.has(block.id) + ) { + continue + } + const input = block.input + if ( + input && + typeof input === 'object' && + 'file_path' in input && + typeof input.file_path === 'string' + ) { + paths.add(expandPath(input.file_path)) + } + } + } + return paths +} + +const SKILL_TRUNCATION_MARKER = + '\n\n[... skill content truncated for compaction; use Read on the skill path if you need the full text]' + +/** + * Truncate content to roughly maxTokens, keeping the head. roughTokenCountEstimation + * uses ~4 chars/token (its default bytesPerToken), so char budget = maxTokens * 4 + * minus the marker so the result stays within budget. Marker tells the model it + * can Read the full file if needed. + */ +function truncateToTokens(content: string, maxTokens: number): string { + if (roughTokenCountEstimation(content) <= maxTokens) { + return content + } + const charBudget = maxTokens * 4 - SKILL_TRUNCATION_MARKER.length + return content.slice(0, charBudget) + SKILL_TRUNCATION_MARKER +} + +function shouldExcludeFromPostCompactRestore( + filename: string, + agentId?: AgentId, +): boolean { + const normalizedFilename = expandPath(filename) + // Exclude plan files + try { + const planFilePath = expandPath(getPlanFilePath(agentId)) + if (normalizedFilename === planFilePath) { + return true + } + } catch { + // If we can't get plan file path, continue with other checks + } + + // Exclude all types of claude.md files + // TODO: Refactor to use isMemoryFilePath() from claudemd.ts for consistency + // and to also match child directory memory files (.claude/rules/*.md, etc.) + try { + const normalizedMemoryPaths = new Set( + MEMORY_TYPE_VALUES.map(type => expandPath(getMemoryPath(type))), + ) + + if (normalizedMemoryPaths.has(normalizedFilename)) { + return true + } + } catch { + // If we can't get memory paths, continue + } + + return false +} diff --git a/_all-in-one-upload/cc-haha/src/services/remoteManagedSettings/syncCacheState.ts b/_all-in-one-upload/cc-haha/src/services/remoteManagedSettings/syncCacheState.ts new file mode 100644 index 0000000..6186c6b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/remoteManagedSettings/syncCacheState.ts @@ -0,0 +1,96 @@ +/** + * Leaf state module for the remote-managed-settings sync cache. + * + * Split from syncCache.ts to break the settings.ts → syncCache.ts → auth.ts → + * settings.ts cycle. auth.ts sits inside the large settings SCC; importing it + * from settings.ts's own dependency chain pulls hundreds of modules into the + * eagerly-evaluated SCC at startup. + * + * This module imports only leaves (path, envUtils, file, json, types, + * settings/settingsCache — also a leaf, only type-imports validation). settings.ts + * reads the cache from here. syncCache.ts keeps isRemoteManagedSettingsEligible + * (the auth-touching part) and re-exports everything from here for callers that + * don't care about the cycle. + * + * Eligibility is a tri-state here: undefined (not yet determined — return + * null), false (ineligible — return null), true (proceed). managedEnv.ts + * calls isRemoteManagedSettingsEligible() just before the policySettings + * read — after userSettings/flagSettings env vars are applied, so the check + * sees config-provided CLAUDE_CODE_USE_BEDROCK/ANTHROPIC_BASE_URL. That call + * computes once and mirrors the result here via setEligibility(). Every + * subsequent read hits the cached bool instead of re-running the auth chain. + */ + +import { join } from 'path' +import { getClaudeConfigHomeDir } from '../../utils/envUtils.js' +import { readFileSync } from '../../utils/fileRead.js' +import { stripBOM } from '../../utils/jsonRead.js' +import { resetSettingsCache } from '../../utils/settings/settingsCache.js' +import type { SettingsJson } from '../../utils/settings/types.js' +import { jsonParse } from '../../utils/slowOperations.js' + +const SETTINGS_FILENAME = 'remote-settings.json' + +let sessionCache: SettingsJson | null = null +let eligible: boolean | undefined + +export function setSessionCache(value: SettingsJson | null): void { + sessionCache = value +} + +export function resetSyncCache(): void { + sessionCache = null + eligible = undefined +} + +export function setEligibility(v: boolean): boolean { + eligible = v + return v +} + +export function getSettingsPath(): string { + return join(getClaudeConfigHomeDir(), SETTINGS_FILENAME) +} + +// sync IO — settings pipeline is sync. fileRead and jsonRead are leaves; +// file.ts and json.ts both sit in the settings SCC. +function loadSettings(): SettingsJson | null { + try { + const content = readFileSync(getSettingsPath()) + const data: unknown = jsonParse(stripBOM(content)) + if (!data || typeof data !== 'object' || Array.isArray(data)) { + return null + } + return data as SettingsJson + } catch { + return null + } +} + +export function getRemoteManagedSettingsSyncFromCache(): SettingsJson | null { + if (eligible !== true) return null + if (sessionCache) return sessionCache + const cachedSettings = loadSettings() + if (cachedSettings) { + sessionCache = cachedSettings + // Remote settings just became available for the first time. Any merged + // getSettings_DEPRECATED() result cached before this moment is missing + // the policySettings layer (the `eligible !== true` guard above returned + // null). Flush so the next merged read re-merges with this layer visible. + // + // Fires at most once: subsequent calls hit `if (sessionCache)` above. + // When called from loadSettingsFromDisk() (settings.ts:546), the merged + // cache is still null (setSessionSettingsCache runs at :732 after + // loadSettingsFromDisk returns) — no-op. The async-fetch arm (index.ts + // setSessionCache + notifyChange) already handles its own reset. + // + // gh-23085: isBridgeEnabled() at main.tsx Commander-definition time + // (before preAction → init() → isRemoteManagedSettingsEligible()) reached + // getSettings_DEPRECATED() at auth.ts:115. The try/catch in bridgeEnabled + // swallowed the later getGlobalConfig() throw, but the merged settings + // cache was already poisoned. See managedSettingsHeadless.int.test.ts. + resetSettingsCache() + return cachedSettings + } + return null +} diff --git a/_all-in-one-upload/cc-haha/src/services/teamMemorySync/types.ts b/_all-in-one-upload/cc-haha/src/services/teamMemorySync/types.ts new file mode 100644 index 0000000..452cd1e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/teamMemorySync/types.ts @@ -0,0 +1,156 @@ +/** + * Team Memory Sync Types + * + * Zod schemas and types for the repo-scoped team memory sync API. + * Based on the backend API contract from anthropic/anthropic#250711. + */ + +import { z } from 'zod/v4' +import { lazySchema } from '../../utils/lazySchema.js' + +/** + * Content portion of team memory data - flat key-value storage. + * Keys are file paths relative to the team memory directory (e.g. "MEMORY.md", "patterns.md"). + * Values are UTF-8 string content (typically Markdown). + */ +export const TeamMemoryContentSchema = lazySchema(() => + z.object({ + entries: z.record(z.string(), z.string()), + // Per-key SHA-256 of entry content (`sha256:`). Added in + // anthropic/anthropic#283027. Optional for forward-compat with older + // server deployments; empty map when entries is empty. + entryChecksums: z.record(z.string(), z.string()).optional(), + }), +) + +/** + * Full response from GET /api/claude_code/team_memory + */ +export const TeamMemoryDataSchema = lazySchema(() => + z.object({ + organizationId: z.string(), + repo: z.string(), + version: z.number(), + lastModified: z.string(), // ISO 8601 timestamp + checksum: z.string(), // SHA256 with 'sha256:' prefix + content: TeamMemoryContentSchema(), + }), +) + +/** + * Structured 413 error body from the server (anthropic/anthropic#293258). + * The server's RequestTooLargeException serializes error_code and the + * extra_details dict flattened into error.details. We only model the + * too-many-entries case; entry-too-large is handled via MAX_FILE_SIZE_BYTES + * pre-check on the client side and would need a separate schema. + */ +export const TeamMemoryTooManyEntriesSchema = lazySchema(() => + z.object({ + error: z.object({ + details: z.object({ + error_code: z.literal('team_memory_too_many_entries'), + max_entries: z.number().int().positive(), + received_entries: z.number().int().positive(), + }), + }), + }), +) + +export type TeamMemoryData = z.infer> + +/** + * A file skipped during push because it contains a detected secret. + * The path is relative to the team memory directory. Only the matched + * gitleaks rule ID is recorded — never the secret value itself. + */ +export type SkippedSecretFile = { + path: string + /** Gitleaks rule ID (e.g., "github-pat", "aws-access-token") */ + ruleId: string + /** Human-readable label derived from rule ID */ + label: string +} + +/** + * Result from fetching team memory + */ +export type TeamMemorySyncFetchResult = { + success: boolean + data?: TeamMemoryData + isEmpty?: boolean // true if 404 (no data exists) + notModified?: boolean // true if 304 (ETag matched, no changes) + checksum?: string // ETag from response header + error?: string + skipRetry?: boolean + errorType?: 'auth' | 'timeout' | 'network' | 'parse' | 'unknown' + httpStatus?: number +} + +/** + * Lightweight metadata-only probe result (GET ?view=hashes). + * Contains per-key checksums without entry bodies. Used to refresh + * serverChecksums cheaply during 412 conflict resolution. + */ +export type TeamMemoryHashesResult = { + success: boolean + version?: number + checksum?: string + entryChecksums?: Record + error?: string + errorType?: 'auth' | 'timeout' | 'network' | 'parse' | 'unknown' + httpStatus?: number +} + +/** + * Result from uploading team memory with conflict info + */ +export type TeamMemorySyncPushResult = { + success: boolean + filesUploaded: number + checksum?: string + conflict?: boolean // true if 412 Precondition Failed + error?: string + /** Files skipped because they contain detected secrets (PSR M22174). */ + skippedSecrets?: SkippedSecretFile[] + errorType?: + | 'auth' + | 'timeout' + | 'network' + | 'conflict' + | 'unknown' + | 'no_oauth' + | 'no_repo' + httpStatus?: number +} + +/** + * Result from uploading team memory + */ +export type TeamMemorySyncUploadResult = { + success: boolean + checksum?: string + lastModified?: string + conflict?: boolean // true if 412 Precondition Failed + error?: string + errorType?: 'auth' | 'timeout' | 'network' | 'unknown' + httpStatus?: number + /** + * Structured error_code from a parsed 413 body (anthropic/anthropic#293258). + * Currently only 'team_memory_too_many_entries' is modelled; if the server + * adds more (entry_too_large, total_bytes_exceeded) they'd extend this + * union. Passed straight through to the tengu_team_mem_sync_push event + * as a Datadog-filterable facet. + */ + serverErrorCode?: 'team_memory_too_many_entries' + /** + * Server-enforced max_entries, populated when serverErrorCode is + * team_memory_too_many_entries. Lets the caller cache the effective + * (possibly per-org) limit for subsequent pushes. + */ + serverMaxEntries?: number + /** + * How many entries the rejected push would have produced after merge. + * Populated alongside serverMaxEntries. + */ + serverReceivedEntries?: number +} diff --git a/_all-in-one-upload/cc-haha/src/services/tools/toolExecution.ts b/_all-in-one-upload/cc-haha/src/services/tools/toolExecution.ts new file mode 100644 index 0000000..40ef38e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/services/tools/toolExecution.ts @@ -0,0 +1,1745 @@ +import { feature } from 'bun:bundle' +import type { + ContentBlockParam, + ToolResultBlockParam, + ToolUseBlock, +} from '@anthropic-ai/sdk/resources/index.mjs' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from 'src/services/analytics/index.js' +import { + extractMcpToolDetails, + extractSkillName, + extractToolInputForTelemetry, + getFileExtensionForAnalytics, + getFileExtensionsFromBashCommand, + isToolDetailsLoggingEnabled, + mcpToolDetailsForAnalytics, + sanitizeToolNameForAnalytics, +} from 'src/services/analytics/metadata.js' +import { + addToToolDuration, + getCodeEditToolDecisionCounter, + getStatsStore, +} from '../../bootstrap/state.js' +import { + buildCodeEditToolAttributes, + isCodeEditingTool, +} from '../../hooks/toolPermission/permissionLogging.js' +import type { CanUseToolFn } from '../../hooks/useCanUseTool.js' +import { + findToolByName, + type Tool, + type ToolProgress, + type ToolProgressData, + type ToolUseContext, +} from '../../Tool.js' +import type { BashToolInput } from '../../tools/BashTool/BashTool.js' +import { startSpeculativeClassifierCheck } from '../../tools/BashTool/bashPermissions.js' +import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js' +import { FILE_EDIT_TOOL_NAME } from '../../tools/FileEditTool/constants.js' +import { FILE_READ_TOOL_NAME } from '../../tools/FileReadTool/prompt.js' +import { FILE_WRITE_TOOL_NAME } from '../../tools/FileWriteTool/prompt.js' +import { NOTEBOOK_EDIT_TOOL_NAME } from '../../tools/NotebookEditTool/constants.js' +import { POWERSHELL_TOOL_NAME } from '../../tools/PowerShellTool/toolName.js' +import { parseGitCommitId } from '../../tools/shared/gitOperationTracking.js' +import { + isDeferredTool, + TOOL_SEARCH_TOOL_NAME, +} from '../../tools/ToolSearchTool/prompt.js' +import { getAllBaseTools } from '../../tools.js' +import type { HookProgress } from '../../types/hooks.js' +import type { + AssistantMessage, + AttachmentMessage, + Message, + ProgressMessage, + StopHookInfo, +} from '../../types/message.js' +import { count } from '../../utils/array.js' +import { createAttachmentMessage } from '../../utils/attachments.js' +import { logForDebugging } from '../../utils/debug.js' +import { + AbortError, + errorMessage, + getErrnoCode, + ShellError, + TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, +} from '../../utils/errors.js' +import { executePermissionDeniedHooks } from '../../utils/hooks.js' +import { logError } from '../../utils/log.js' +import { + CANCEL_MESSAGE, + createProgressMessage, + createStopHookSummaryMessage, + createToolResultStopMessage, + createUserMessage, + withMemoryCorrectionHint, +} from '../../utils/messages.js' +import type { + PermissionDecisionReason, + PermissionResult, +} from '../../utils/permissions/PermissionResult.js' +import { + startSessionActivity, + stopSessionActivity, +} from '../../utils/sessionActivity.js' +import { jsonStringify } from '../../utils/slowOperations.js' +import { Stream } from '../../utils/stream.js' +import { logOTelEvent } from '../../utils/telemetry/events.js' +import { + addToolContentEvent, + endToolBlockedOnUserSpan, + endToolExecutionSpan, + endToolSpan, + isBetaTracingEnabled, + startToolBlockedOnUserSpan, + startToolExecutionSpan, + startToolSpan, +} from '../../utils/telemetry/sessionTracing.js' +import { + formatError, + formatZodValidationError, +} from '../../utils/toolErrors.js' +import { + processPreMappedToolResultBlock, + processToolResultBlock, +} from '../../utils/toolResultStorage.js' +import { + extractDiscoveredToolNames, + isToolSearchEnabledOptimistic, + isToolSearchToolAvailable, +} from '../../utils/toolSearch.js' +import { + McpAuthError, + McpToolCallError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, +} from '../mcp/client.js' +import { mcpInfoFromString } from '../mcp/mcpStringUtils.js' +import { normalizeNameForMCP } from '../mcp/normalization.js' +import type { MCPServerConnection } from '../mcp/types.js' +import { + getLoggingSafeMcpBaseUrl, + getMcpServerScopeFromToolName, + isMcpTool, +} from '../mcp/utils.js' +import { + resolveHookPermissionDecision, + runPostToolUseFailureHooks, + runPostToolUseHooks, + runPreToolUseHooks, +} from './toolHooks.js' + +/** Minimum total hook duration (ms) to show inline timing summary */ +export const HOOK_TIMING_DISPLAY_THRESHOLD_MS = 500 +/** Log a debug warning when hooks/permission-decision block for this long. Matches + * BashTool's PROGRESS_THRESHOLD_MS — the collapsed view feels stuck past this. */ +const SLOW_PHASE_LOG_THRESHOLD_MS = 2000 + +/** + * Classify a tool execution error into a telemetry-safe string. + * + * In minified/external builds, `error.constructor.name` is mangled into + * short identifiers like "nJT" or "Chq" — useless for diagnostics. + * This function extracts structured, telemetry-safe information instead: + * - TelemetrySafeError: use its telemetryMessage (already vetted) + * - Node.js fs errors: log the error code (ENOENT, EACCES, etc.) + * - Known error types: use their unminified name + * - Fallback: "Error" (better than a mangled 3-char identifier) + */ +export function classifyToolError(error: unknown): string { + if ( + error instanceof TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS + ) { + return error.telemetryMessage.slice(0, 200) + } + if (error instanceof Error) { + // Node.js filesystem errors have a `code` property (ENOENT, EACCES, etc.) + // These are safe to log and much more useful than the constructor name. + const errnoCode = getErrnoCode(error) + if (typeof errnoCode === 'string') { + return `Error:${errnoCode}` + } + // ShellError, ImageSizeError, etc. have stable `.name` properties + // that survive minification (they're set in the constructor). + if (error.name && error.name !== 'Error' && error.name.length > 3) { + return error.name.slice(0, 60) + } + return 'Error' + } + return 'UnknownError' +} + +/** + * Map a rule's origin to the documented OTel `source` vocabulary, matching + * the interactive path's semantics (permissionLogging.ts:81): session-scoped + * grants are temporary, on-disk grants are permanent, and user-authored + * denies are user_reject regardless of persistence. Everything the user + * didn't write (cliArg, policySettings, projectSettings, flagSettings) is + * config. + */ +function ruleSourceToOTelSource( + ruleSource: string, + behavior: 'allow' | 'deny', +): string { + switch (ruleSource) { + case 'session': + return behavior === 'allow' ? 'user_temporary' : 'user_reject' + case 'localSettings': + case 'userSettings': + return behavior === 'allow' ? 'user_permanent' : 'user_reject' + default: + return 'config' + } +} + +/** + * Map a PermissionDecisionReason to the OTel `source` label for the + * non-interactive tool_decision path, staying within the documented + * vocabulary (config, hook, user_permanent, user_temporary, user_reject). + * + * For permissionPromptTool, the SDK host may set decisionClassification on + * the PermissionResult to tell us exactly what happened (once vs always vs + * cache hit — the host knows, we can't tell from {behavior:'allow'} alone). + * Without it, we fall back conservatively: allow → user_temporary, + * deny → user_reject. + */ +function decisionReasonToOTelSource( + reason: PermissionDecisionReason | undefined, + behavior: 'allow' | 'deny', +): string { + if (!reason) { + return 'config' + } + switch (reason.type) { + case 'permissionPromptTool': { + // toolResult is typed `unknown` on PermissionDecisionReason but carries + // the parsed Output from PermissionPromptToolResultSchema. Narrow at + // runtime rather than widen the cross-file type. + const toolResult = reason.toolResult as + | { decisionClassification?: string } + | undefined + const classified = toolResult?.decisionClassification + if ( + classified === 'user_temporary' || + classified === 'user_permanent' || + classified === 'user_reject' + ) { + return classified + } + return behavior === 'allow' ? 'user_temporary' : 'user_reject' + } + case 'rule': + return ruleSourceToOTelSource(reason.rule.source, behavior) + case 'hook': + return 'hook' + case 'mode': + case 'classifier': + case 'subcommandResults': + case 'asyncAgent': + case 'sandboxOverride': + case 'workingDir': + case 'safetyCheck': + case 'other': + return 'config' + default: { + const _exhaustive: never = reason + return 'config' + } + } +} + +function getNextImagePasteId(messages: Message[]): number { + let maxId = 0 + for (const message of messages) { + if (message.type === 'user' && message.imagePasteIds) { + for (const id of message.imagePasteIds) { + if (id > maxId) maxId = id + } + } + } + return maxId + 1 +} + +export type MessageUpdateLazy = { + message: M + contextModifier?: { + toolUseID: string + modifyContext: (context: ToolUseContext) => ToolUseContext + } +} + +export type McpServerType = + | 'stdio' + | 'sse' + | 'http' + | 'ws' + | 'sdk' + | 'sse-ide' + | 'ws-ide' + | 'claudeai-proxy' + | undefined + +function findMcpServerConnection( + toolName: string, + mcpClients: MCPServerConnection[], +): MCPServerConnection | undefined { + if (!toolName.startsWith('mcp__')) { + return undefined + } + + const mcpInfo = mcpInfoFromString(toolName) + if (!mcpInfo) { + return undefined + } + + // mcpInfo.serverName is normalized (e.g., "claude_ai_Slack"), but client.name + // is the original name (e.g., "claude.ai Slack"). Normalize both for comparison. + return mcpClients.find( + client => normalizeNameForMCP(client.name) === mcpInfo.serverName, + ) +} + +/** + * Extracts the MCP server transport type from a tool name. + * Returns the server type (stdio, sse, http, ws, sdk, etc.) for MCP tools, + * or undefined for built-in tools. + */ +function getMcpServerType( + toolName: string, + mcpClients: MCPServerConnection[], +): McpServerType { + const serverConnection = findMcpServerConnection(toolName, mcpClients) + + if (serverConnection?.type === 'connected') { + // Handle stdio configs where type field is optional (defaults to 'stdio') + return serverConnection.config.type ?? 'stdio' + } + + return undefined +} + +/** + * Extracts the MCP server base URL for a tool by looking up its server connection. + * Returns undefined for stdio servers, built-in tools, or if the server is not connected. + */ +function getMcpServerBaseUrlFromToolName( + toolName: string, + mcpClients: MCPServerConnection[], +): string | undefined { + const serverConnection = findMcpServerConnection(toolName, mcpClients) + if (serverConnection?.type !== 'connected') { + return undefined + } + return getLoggingSafeMcpBaseUrl(serverConnection.config) +} + +export async function* runToolUse( + toolUse: ToolUseBlock, + assistantMessage: AssistantMessage, + canUseTool: CanUseToolFn, + toolUseContext: ToolUseContext, +): AsyncGenerator { + const toolName = toolUse.name + // First try to find in the available tools (what the model sees) + let tool = findToolByName(toolUseContext.options.tools, toolName) + + // If not found, check if it's a deprecated tool being called by alias + // (e.g., old transcripts calling "KillShell" which is now an alias for "TaskStop") + // Only fall back for tools where the name matches an alias, not the primary name + if (!tool) { + const fallbackTool = findToolByName(getAllBaseTools(), toolName) + // Only use fallback if the tool was found via alias (deprecated name) + if (fallbackTool && fallbackTool.aliases?.includes(toolName)) { + tool = fallbackTool + } + } + const messageId = assistantMessage.message.id + const requestId = assistantMessage.requestId + const mcpServerType = getMcpServerType( + toolName, + toolUseContext.options.mcpClients, + ) + const mcpServerBaseUrl = getMcpServerBaseUrlFromToolName( + toolName, + toolUseContext.options.mcpClients, + ) + + // Check if the tool exists + if (!tool) { + const sanitizedToolName = sanitizeToolNameForAnalytics(toolName) + logForDebugging(`Unknown tool ${toolName}: ${toolUse.id}`) + logEvent('tengu_tool_use_error', { + error: + `No such tool available: ${sanitizedToolName}` as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizedToolName, + toolUseID: + toolUse.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + isMcp: toolName.startsWith('mcp__'), + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(toolName, mcpServerType, mcpServerBaseUrl), + }) + yield { + message: createUserMessage({ + content: [ + { + type: 'tool_result', + content: `Error: No such tool available: ${toolName}`, + is_error: true, + tool_use_id: toolUse.id, + }, + ], + toolUseResult: `Error: No such tool available: ${toolName}`, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + } + return + } + + const toolInput = toolUse.input as { [key: string]: string } + try { + if (toolUseContext.abortController.signal.aborted) { + logEvent('tengu_tool_use_cancelled', { + toolName: sanitizeToolNameForAnalytics(tool.name), + toolUseID: + toolUse.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + isMcp: tool.isMcp ?? false, + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics( + tool.name, + mcpServerType, + mcpServerBaseUrl, + ), + }) + const content = createToolResultStopMessage(toolUse.id) + content.content = withMemoryCorrectionHint(CANCEL_MESSAGE) + yield { + message: createUserMessage({ + content: [content], + toolUseResult: CANCEL_MESSAGE, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + } + return + } + + for await (const update of streamedCheckPermissionsAndCallTool( + tool, + toolUse.id, + toolInput, + toolUseContext, + canUseTool, + assistantMessage, + messageId, + requestId, + mcpServerType, + mcpServerBaseUrl, + )) { + yield update + } + } catch (error) { + logError(error) + const errorMessage = error instanceof Error ? error.message : String(error) + const toolInfo = tool ? ` (${tool.name})` : '' + const detailedError = `Error calling tool${toolInfo}: ${errorMessage}` + + yield { + message: createUserMessage({ + content: [ + { + type: 'tool_result', + content: `${detailedError}`, + is_error: true, + tool_use_id: toolUse.id, + }, + ], + toolUseResult: detailedError, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + } + } +} + +function streamedCheckPermissionsAndCallTool( + tool: Tool, + toolUseID: string, + input: { [key: string]: boolean | string | number }, + toolUseContext: ToolUseContext, + canUseTool: CanUseToolFn, + assistantMessage: AssistantMessage, + messageId: string, + requestId: string | undefined, + mcpServerType: McpServerType, + mcpServerBaseUrl: ReturnType, +): AsyncIterable { + // This is a bit of a hack to get progress events and final results + // into a single async iterable. + // + // Ideally the progress reporting and tool call reporting would + // be via separate mechanisms. + const stream = new Stream() + checkPermissionsAndCallTool( + tool, + toolUseID, + input, + toolUseContext, + canUseTool, + assistantMessage, + messageId, + requestId, + mcpServerType, + mcpServerBaseUrl, + progress => { + logEvent('tengu_tool_use_progress', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + isMcp: tool.isMcp ?? false, + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics( + tool.name, + mcpServerType, + mcpServerBaseUrl, + ), + }) + stream.enqueue({ + message: createProgressMessage({ + toolUseID: progress.toolUseID, + parentToolUseID: toolUseID, + data: progress.data, + }), + }) + }, + ) + .then(results => { + for (const result of results) { + stream.enqueue(result) + } + }) + .catch(error => { + stream.error(error) + }) + .finally(() => { + stream.done() + }) + return stream +} + +/** + * Appended to Zod errors when a deferred tool wasn't in the discovered-tool + * set — re-runs the claude.ts schema-filter scan dispatch-time to detect the + * mismatch. The raw Zod error ("expected array, got string") doesn't tell the + * model to re-load the tool; this hint does. Null if the schema was sent. + */ +export function buildSchemaNotSentHint( + tool: Tool, + messages: Message[], + tools: readonly { name: string }[], +): string | null { + // Optimistic gating — reconstructing claude.ts's full useToolSearch + // computation is fragile. These two gates prevent pointing at a ToolSearch + // that isn't callable; occasional misfires (Haiku, tst-auto below threshold) + // cost one extra round-trip on an already-failing path. + if (!isToolSearchEnabledOptimistic()) return null + if (!isToolSearchToolAvailable(tools)) return null + if (!isDeferredTool(tool)) return null + const discovered = extractDiscoveredToolNames(messages) + if (discovered.has(tool.name)) return null + return ( + `\n\nThis tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. ` + + `Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. ` + + `Load the tool first: call ${TOOL_SEARCH_TOOL_NAME} with query "select:${tool.name}", then retry this call.` + ) +} + +async function checkPermissionsAndCallTool( + tool: Tool, + toolUseID: string, + input: { [key: string]: boolean | string | number }, + toolUseContext: ToolUseContext, + canUseTool: CanUseToolFn, + assistantMessage: AssistantMessage, + messageId: string, + requestId: string | undefined, + mcpServerType: McpServerType, + mcpServerBaseUrl: ReturnType, + onToolProgress: ( + progress: ToolProgress | ProgressMessage, + ) => void, +): Promise { + // Validate input types with zod (surprisingly, the model is not great at generating valid input) + const parsedInput = tool.inputSchema.safeParse(input) + if (!parsedInput.success) { + let errorContent = formatZodValidationError(tool.name, parsedInput.error) + + const schemaHint = buildSchemaNotSentHint( + tool, + toolUseContext.messages, + toolUseContext.options.tools, + ) + if (schemaHint) { + logEvent('tengu_deferred_tool_schema_not_sent', { + toolName: sanitizeToolNameForAnalytics(tool.name), + isMcp: tool.isMcp ?? false, + }) + errorContent += schemaHint + } + + logForDebugging( + `${tool.name} tool input error: ${errorContent.slice(0, 200)}`, + ) + logEvent('tengu_tool_use_error', { + error: + 'InputValidationError' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + errorDetails: errorContent.slice( + 0, + 2000, + ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + isMcp: tool.isMcp ?? false, + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(tool.name, mcpServerType, mcpServerBaseUrl), + }) + return [ + { + message: createUserMessage({ + content: [ + { + type: 'tool_result', + content: `InputValidationError: ${errorContent}`, + is_error: true, + tool_use_id: toolUseID, + }, + ], + toolUseResult: `InputValidationError: ${parsedInput.error.message}`, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + }, + ] + } + + // Validate input values. Each tool has its own validation logic + const isValidCall = await tool.validateInput?.( + parsedInput.data, + toolUseContext, + ) + if (isValidCall?.result === false) { + logForDebugging( + `${tool.name} tool validation error: ${isValidCall.message?.slice(0, 200)}`, + ) + logEvent('tengu_tool_use_error', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + error: + isValidCall.message as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + errorCode: isValidCall.errorCode, + isMcp: tool.isMcp ?? false, + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(tool.name, mcpServerType, mcpServerBaseUrl), + }) + return [ + { + message: createUserMessage({ + content: [ + { + type: 'tool_result', + content: `${isValidCall.message}`, + is_error: true, + tool_use_id: toolUseID, + }, + ], + toolUseResult: `Error: ${isValidCall.message}`, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + }, + ] + } + // Speculatively start the bash allow classifier check early so it runs in + // parallel with pre-tool hooks, deny/ask classifiers, and permission dialog + // setup. The UI indicator (setClassifierChecking) is NOT set here — it's + // set in interactiveHandler.ts only when the permission check returns `ask` + // with a pendingClassifierCheck. This avoids flashing "classifier running" + // for commands that auto-allow via prefix rules. + if ( + tool.name === BASH_TOOL_NAME && + parsedInput.data && + 'command' in parsedInput.data + ) { + const appState = toolUseContext.getAppState() + startSpeculativeClassifierCheck( + (parsedInput.data as BashToolInput).command, + appState.toolPermissionContext, + toolUseContext.abortController.signal, + toolUseContext.options.isNonInteractiveSession, + ) + } + + const resultingMessages = [] + + // Defense-in-depth: strip _simulatedSedEdit from model-provided Bash input. + // This field is internal-only — it must only be injected by the permission + // system (SedEditPermissionRequest) after user approval. If the model supplies + // it, the schema's strictObject should already reject it, but we strip here + // as a safeguard against future regressions. + let processedInput = parsedInput.data + if ( + tool.name === BASH_TOOL_NAME && + processedInput && + typeof processedInput === 'object' && + '_simulatedSedEdit' in processedInput + ) { + const { _simulatedSedEdit: _, ...rest } = + processedInput as typeof processedInput & { + _simulatedSedEdit: unknown + } + processedInput = rest as typeof processedInput + } + + // Backfill legacy/derived fields on a shallow clone so hooks/canUseTool see + // them without affecting tool.call(). SendMessageTool adds fields; file + // tools overwrite file_path with expandPath — that mutation must not reach + // call() because tool results embed the input path verbatim (e.g. "File + // created successfully at: {path}"), and changing it alters the serialized + // transcript and VCR fixture hashes. If a hook/permission later returns a + // fresh updatedInput, callInput converges on it below — that replacement + // is intentional and should reach call(). + let callInput = processedInput + const backfilledClone = + tool.backfillObservableInput && + typeof processedInput === 'object' && + processedInput !== null + ? ({ ...processedInput } as typeof processedInput) + : null + if (backfilledClone) { + tool.backfillObservableInput!(backfilledClone as Record) + processedInput = backfilledClone + } + + let shouldPreventContinuation = false + let stopReason: string | undefined + let hookPermissionResult: PermissionResult | undefined + const preToolHookInfos: StopHookInfo[] = [] + const preToolHookStart = Date.now() + for await (const result of runPreToolUseHooks( + toolUseContext, + tool, + processedInput, + toolUseID, + assistantMessage.message.id, + requestId, + mcpServerType, + mcpServerBaseUrl, + )) { + switch (result.type) { + case 'message': + if (result.message.message.type === 'progress') { + onToolProgress(result.message.message) + } else { + resultingMessages.push(result.message) + const att = result.message.message.attachment + if ( + att && + 'command' in att && + att.command !== undefined && + 'durationMs' in att && + att.durationMs !== undefined + ) { + preToolHookInfos.push({ + command: att.command, + durationMs: att.durationMs, + }) + } + } + break + case 'hookPermissionResult': + hookPermissionResult = result.hookPermissionResult + break + case 'hookUpdatedInput': + // Hook provided updatedInput without making a permission decision (passthrough) + // Update processedInput so it's used in the normal permission flow + processedInput = result.updatedInput + break + case 'preventContinuation': + shouldPreventContinuation = result.shouldPreventContinuation + break + case 'stopReason': + stopReason = result.stopReason + break + case 'additionalContext': + resultingMessages.push(result.message) + break + case 'stop': + getStatsStore()?.observe( + 'pre_tool_hook_duration_ms', + Date.now() - preToolHookStart, + ) + resultingMessages.push({ + message: createUserMessage({ + content: [createToolResultStopMessage(toolUseID)], + toolUseResult: `Error: ${stopReason}`, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + }) + return resultingMessages + } + } + const preToolHookDurationMs = Date.now() - preToolHookStart + getStatsStore()?.observe('pre_tool_hook_duration_ms', preToolHookDurationMs) + if (preToolHookDurationMs >= SLOW_PHASE_LOG_THRESHOLD_MS) { + logForDebugging( + `Slow PreToolUse hooks: ${preToolHookDurationMs}ms for ${tool.name} (${preToolHookInfos.length} hooks)`, + { level: 'info' }, + ) + } + + // Emit PreToolUse summary immediately so it's visible while the tool executes. + // Use wall-clock time (not sum of individual durations) since hooks run in parallel. + if (process.env.USER_TYPE === 'ant' && preToolHookInfos.length > 0) { + if (preToolHookDurationMs > HOOK_TIMING_DISPLAY_THRESHOLD_MS) { + resultingMessages.push({ + message: createStopHookSummaryMessage( + preToolHookInfos.length, + preToolHookInfos, + [], + false, + undefined, + false, + 'suggestion', + undefined, + 'PreToolUse', + preToolHookDurationMs, + ), + }) + } + } + + const toolAttributes: Record = {} + if (processedInput && typeof processedInput === 'object') { + if (tool.name === FILE_READ_TOOL_NAME && 'file_path' in processedInput) { + toolAttributes.file_path = String(processedInput.file_path) + } else if ( + (tool.name === FILE_EDIT_TOOL_NAME || + tool.name === FILE_WRITE_TOOL_NAME) && + 'file_path' in processedInput + ) { + toolAttributes.file_path = String(processedInput.file_path) + } else if (tool.name === BASH_TOOL_NAME && 'command' in processedInput) { + const bashInput = processedInput as BashToolInput + toolAttributes.full_command = bashInput.command + } + } + + startToolSpan( + tool.name, + toolAttributes, + isBetaTracingEnabled() ? jsonStringify(processedInput) : undefined, + ) + startToolBlockedOnUserSpan() + + // Check whether we have permission to use the tool, + // and ask the user for permission if we don't + const permissionMode = toolUseContext.getAppState().toolPermissionContext.mode + const permissionStart = Date.now() + + const resolved = await resolveHookPermissionDecision( + hookPermissionResult, + tool, + processedInput, + toolUseContext, + canUseTool, + assistantMessage, + toolUseID, + ) + const permissionDecision = resolved.decision + processedInput = resolved.input + const permissionDurationMs = Date.now() - permissionStart + // In auto mode, canUseTool awaits the classifier (side_query) — if that's + // slow the collapsed view shows "Running…" with no (Ns) tick since + // bash_progress hasn't started yet. Auto-only: in default mode this timer + // includes interactive-dialog wait (user think time), which is just noise. + if ( + permissionDurationMs >= SLOW_PHASE_LOG_THRESHOLD_MS && + permissionMode === 'auto' + ) { + logForDebugging( + `Slow permission decision: ${permissionDurationMs}ms for ${tool.name} ` + + `(mode=${permissionMode}, behavior=${permissionDecision.behavior})`, + { level: 'info' }, + ) + } + + // Emit tool_decision OTel event and code-edit counter if the interactive + // permission path didn't already log it (headless mode bypasses permission + // logging, so we need to emit both the generic event and the code-edit + // counter here) + if ( + permissionDecision.behavior !== 'ask' && + !toolUseContext.toolDecisions?.has(toolUseID) + ) { + const decision = + permissionDecision.behavior === 'allow' ? 'accept' : 'reject' + const source = decisionReasonToOTelSource( + permissionDecision.decisionReason, + permissionDecision.behavior, + ) + void logOTelEvent('tool_decision', { + decision, + source, + tool_name: sanitizeToolNameForAnalytics(tool.name), + }) + + // Increment code-edit tool decision counter for headless mode + if (isCodeEditingTool(tool.name)) { + void buildCodeEditToolAttributes( + tool, + processedInput, + decision, + source, + ).then(attributes => getCodeEditToolDecisionCounter()?.add(1, attributes)) + } + } + + // Add message if permission was granted/denied by PermissionRequest hook + if ( + permissionDecision.decisionReason?.type === 'hook' && + permissionDecision.decisionReason.hookName === 'PermissionRequest' && + permissionDecision.behavior !== 'ask' + ) { + resultingMessages.push({ + message: createAttachmentMessage({ + type: 'hook_permission_decision', + decision: permissionDecision.behavior, + toolUseID, + hookEvent: 'PermissionRequest', + }), + }) + } + + if (permissionDecision.behavior !== 'allow') { + logForDebugging(`${tool.name} tool permission denied`) + const decisionInfo = toolUseContext.toolDecisions?.get(toolUseID) + endToolBlockedOnUserSpan('reject', decisionInfo?.source || 'unknown') + endToolSpan() + + logEvent('tengu_tool_use_can_use_tool_rejected', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(tool.name, mcpServerType, mcpServerBaseUrl), + }) + let errorMessage = permissionDecision.message + // Only use generic "Execution stopped" message if we don't have a detailed hook message + if (shouldPreventContinuation && !errorMessage) { + errorMessage = `Execution stopped by PreToolUse hook${stopReason ? `: ${stopReason}` : ''}` + } + + // Build top-level content: tool_result (text-only for is_error compatibility) + images alongside + const messageContent: ContentBlockParam[] = [ + { + type: 'tool_result', + content: errorMessage, + is_error: true, + tool_use_id: toolUseID, + }, + ] + + // Add image blocks at top level (not inside tool_result, which rejects non-text with is_error) + const rejectContentBlocks = + permissionDecision.behavior === 'ask' + ? permissionDecision.contentBlocks + : undefined + if (rejectContentBlocks?.length) { + messageContent.push(...rejectContentBlocks) + } + + // Generate sequential imagePasteIds so each image renders with a distinct label + let rejectImageIds: number[] | undefined + if (rejectContentBlocks?.length) { + const imageCount = count( + rejectContentBlocks, + (b: ContentBlockParam) => b.type === 'image', + ) + if (imageCount > 0) { + const startId = getNextImagePasteId(toolUseContext.messages) + rejectImageIds = Array.from( + { length: imageCount }, + (_, i) => startId + i, + ) + } + } + + resultingMessages.push({ + message: createUserMessage({ + content: messageContent, + imagePasteIds: rejectImageIds, + toolUseResult: `Error: ${errorMessage}`, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + }) + + // Run PermissionDenied hooks for auto mode classifier denials. + // If a hook returns {retry: true}, tell the model it may retry. + if ( + feature('TRANSCRIPT_CLASSIFIER') && + permissionDecision.decisionReason?.type === 'classifier' && + permissionDecision.decisionReason.classifier === 'auto-mode' + ) { + let hookSaysRetry = false + for await (const result of executePermissionDeniedHooks( + tool.name, + toolUseID, + processedInput, + permissionDecision.decisionReason.reason ?? 'Permission denied', + toolUseContext, + permissionMode, + toolUseContext.abortController.signal, + )) { + if (result.retry) hookSaysRetry = true + } + if (hookSaysRetry) { + resultingMessages.push({ + message: createUserMessage({ + content: + 'The PermissionDenied hook indicated this command is now approved. You may retry it if you would like.', + isMeta: true, + }), + }) + } + } + + return resultingMessages + } + logEvent('tengu_tool_use_can_use_tool_allowed', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(tool.name, mcpServerType, mcpServerBaseUrl), + }) + + // Use the updated input from permissions if provided + // (Don't overwrite if undefined - processedInput may have been modified by passthrough hooks) + if (permissionDecision.updatedInput !== undefined) { + processedInput = permissionDecision.updatedInput + } + + // Prepare tool parameters for logging in tool_result event. + // Gated by OTEL_LOG_TOOL_DETAILS — tool parameters can contain sensitive + // content (bash commands, MCP server names, etc.) so they're opt-in only. + const telemetryToolInput = extractToolInputForTelemetry(processedInput) + let toolParameters: Record = {} + if (isToolDetailsLoggingEnabled()) { + if (tool.name === BASH_TOOL_NAME && 'command' in processedInput) { + const bashInput = processedInput as BashToolInput + const commandParts = bashInput.command.trim().split(/\s+/) + const bashCommand = commandParts[0] || '' + + toolParameters = { + bash_command: bashCommand, + full_command: bashInput.command, + ...(bashInput.timeout !== undefined && { + timeout: bashInput.timeout, + }), + ...(bashInput.description !== undefined && { + description: bashInput.description, + }), + ...('dangerouslyDisableSandbox' in bashInput && { + dangerouslyDisableSandbox: bashInput.dangerouslyDisableSandbox, + }), + } + } + + const mcpDetails = extractMcpToolDetails(tool.name) + if (mcpDetails) { + toolParameters.mcp_server_name = mcpDetails.serverName + toolParameters.mcp_tool_name = mcpDetails.mcpToolName + } + const skillName = extractSkillName(tool.name, processedInput) + if (skillName) { + toolParameters.skill_name = skillName + } + } + + const decisionInfo = toolUseContext.toolDecisions?.get(toolUseID) + endToolBlockedOnUserSpan( + decisionInfo?.decision || 'unknown', + decisionInfo?.source || 'unknown', + ) + startToolExecutionSpan() + + const startTime = Date.now() + + startSessionActivity('tool_exec') + // If processedInput still points at the backfill clone, no hook/permission + // replaced it — pass the pre-backfill callInput so call() sees the model's + // original field values. Otherwise converge on the hook-supplied input. + // Permission/hook flows may return a fresh object derived from the + // backfilled clone (e.g. via inputSchema.parse). If its file_path matches + // the backfill-expanded value, restore the model's original so the tool + // result string embeds the path the model emitted — keeps transcript/VCR + // hashes stable. Other hook modifications flow through unchanged. + if ( + backfilledClone && + processedInput !== callInput && + typeof processedInput === 'object' && + processedInput !== null && + 'file_path' in processedInput && + 'file_path' in (callInput as Record) && + (processedInput as Record).file_path === + (backfilledClone as Record).file_path + ) { + callInput = { + ...processedInput, + file_path: (callInput as Record).file_path, + } as typeof processedInput + } else if (processedInput !== backfilledClone) { + callInput = processedInput + } + try { + const result = await tool.call( + callInput, + { + ...toolUseContext, + toolUseId: toolUseID, + userModified: permissionDecision.userModified ?? false, + }, + canUseTool, + assistantMessage, + progress => { + onToolProgress({ + toolUseID: progress.toolUseID, + data: progress.data, + }) + }, + ) + const durationMs = Date.now() - startTime + addToToolDuration(durationMs) + + // Log tool content/output as span event if enabled + if (result.data && typeof result.data === 'object') { + const contentAttributes: Record = {} + + // Read tool: capture file_path and content + if (tool.name === FILE_READ_TOOL_NAME && 'content' in result.data) { + if ('file_path' in processedInput) { + contentAttributes.file_path = String(processedInput.file_path) + } + contentAttributes.content = String(result.data.content) + } + + // Edit/Write tools: capture file_path and diff + if ( + (tool.name === FILE_EDIT_TOOL_NAME || + tool.name === FILE_WRITE_TOOL_NAME) && + 'file_path' in processedInput + ) { + contentAttributes.file_path = String(processedInput.file_path) + + // For Edit, capture the actual changes made + if (tool.name === FILE_EDIT_TOOL_NAME && 'diff' in result.data) { + contentAttributes.diff = String(result.data.diff) + } + // For Write, capture the written content + if (tool.name === FILE_WRITE_TOOL_NAME && 'content' in processedInput) { + contentAttributes.content = String(processedInput.content) + } + } + + // Bash tool: capture command + if (tool.name === BASH_TOOL_NAME && 'command' in processedInput) { + const bashInput = processedInput as BashToolInput + contentAttributes.bash_command = bashInput.command + // Also capture output if available + if ('output' in result.data) { + contentAttributes.output = String(result.data.output) + } + } + + if (Object.keys(contentAttributes).length > 0) { + addToolContentEvent('tool.output', contentAttributes) + } + } + + // Capture structured output from tool result if present + if (typeof result === 'object' && 'structured_output' in result) { + // Store the structured output in an attachment message + resultingMessages.push({ + message: createAttachmentMessage({ + type: 'structured_output', + data: result.structured_output, + }), + }) + } + + endToolExecutionSpan({ success: true }) + // Pass tool result for new_context logging + const toolResultStr = + result.data && typeof result.data === 'object' + ? jsonStringify(result.data) + : String(result.data ?? '') + endToolSpan(toolResultStr) + + // Map the tool result to API format once and cache it. This block is reused + // by addToolResult (skipping the remap) and measured here for analytics. + const mappedToolResultBlock = tool.mapToolResultToToolResultBlockParam( + result.data, + toolUseID, + ) + const mappedContent = mappedToolResultBlock.content + const toolResultSizeBytes = !mappedContent + ? 0 + : typeof mappedContent === 'string' + ? mappedContent.length + : jsonStringify(mappedContent).length + + // Extract file extension for file-related tools + let fileExtension: ReturnType + if (processedInput && typeof processedInput === 'object') { + if ( + (tool.name === FILE_READ_TOOL_NAME || + tool.name === FILE_EDIT_TOOL_NAME || + tool.name === FILE_WRITE_TOOL_NAME) && + 'file_path' in processedInput + ) { + fileExtension = getFileExtensionForAnalytics( + String(processedInput.file_path), + ) + } else if ( + tool.name === NOTEBOOK_EDIT_TOOL_NAME && + 'notebook_path' in processedInput + ) { + fileExtension = getFileExtensionForAnalytics( + String(processedInput.notebook_path), + ) + } else if (tool.name === BASH_TOOL_NAME && 'command' in processedInput) { + const bashInput = processedInput as BashToolInput + fileExtension = getFileExtensionsFromBashCommand( + bashInput.command, + bashInput._simulatedSedEdit?.filePath, + ) + } + } + + logEvent('tengu_tool_use_success', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + isMcp: tool.isMcp ?? false, + durationMs, + preToolHookDurationMs, + toolResultSizeBytes, + ...(fileExtension !== undefined && { fileExtension }), + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics(tool.name, mcpServerType, mcpServerBaseUrl), + }) + + // Enrich tool parameters with git commit ID from successful git commit output + if ( + isToolDetailsLoggingEnabled() && + (tool.name === BASH_TOOL_NAME || tool.name === POWERSHELL_TOOL_NAME) && + 'command' in processedInput && + typeof processedInput.command === 'string' && + processedInput.command.match(/\bgit\s+commit\b/) && + result.data && + typeof result.data === 'object' && + 'stdout' in result.data + ) { + const gitCommitId = parseGitCommitId(String(result.data.stdout)) + if (gitCommitId) { + toolParameters.git_commit_id = gitCommitId + } + } + + // Log tool result event for OTLP with tool parameters and decision context + const mcpServerScope = isMcpTool(tool) + ? getMcpServerScopeFromToolName(tool.name) + : null + + void logOTelEvent('tool_result', { + tool_name: sanitizeToolNameForAnalytics(tool.name), + success: 'true', + duration_ms: String(durationMs), + ...(Object.keys(toolParameters).length > 0 && { + tool_parameters: jsonStringify(toolParameters), + }), + ...(telemetryToolInput && { tool_input: telemetryToolInput }), + tool_result_size_bytes: String(toolResultSizeBytes), + ...(decisionInfo && { + decision_source: decisionInfo.source, + decision_type: decisionInfo.decision, + }), + ...(mcpServerScope && { mcp_server_scope: mcpServerScope }), + }) + + // Run PostToolUse hooks + let toolOutput = result.data + const hookResults = [] + const toolContextModifier = result.contextModifier + const mcpMeta = result.mcpMeta + + async function addToolResult( + toolUseResult: unknown, + preMappedBlock?: ToolResultBlockParam, + ) { + // Use the pre-mapped block when available (non-MCP tools where hooks + // don't modify the output), otherwise map from scratch. + const toolResultBlock = preMappedBlock + ? await processPreMappedToolResultBlock( + preMappedBlock, + tool.name, + tool.maxResultSizeChars, + ) + : await processToolResultBlock(tool, toolUseResult, toolUseID) + + // Build content blocks - tool result first, then optional feedback + const contentBlocks: ContentBlockParam[] = [toolResultBlock] + // Add accept feedback if user provided feedback when approving + // (acceptFeedback only exists on PermissionAllowDecision, which is guaranteed here) + if ( + 'acceptFeedback' in permissionDecision && + permissionDecision.acceptFeedback + ) { + contentBlocks.push({ + type: 'text', + text: permissionDecision.acceptFeedback, + }) + } + + // Add content blocks (e.g., pasted images) from the permission decision + const allowContentBlocks = + 'contentBlocks' in permissionDecision + ? permissionDecision.contentBlocks + : undefined + if (allowContentBlocks?.length) { + contentBlocks.push(...allowContentBlocks) + } + + // Generate sequential imagePasteIds so each image renders with a distinct label + let allowImageIds: number[] | undefined + if (allowContentBlocks?.length) { + const imageCount = count( + allowContentBlocks, + (b: ContentBlockParam) => b.type === 'image', + ) + if (imageCount > 0) { + const startId = getNextImagePasteId(toolUseContext.messages) + allowImageIds = Array.from( + { length: imageCount }, + (_, i) => startId + i, + ) + } + } + + resultingMessages.push({ + message: createUserMessage({ + content: contentBlocks, + imagePasteIds: allowImageIds, + toolUseResult: + toolUseContext.agentId && !toolUseContext.preserveToolUseResults + ? undefined + : toolUseResult, + mcpMeta: toolUseContext.agentId ? undefined : mcpMeta, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + contextModifier: toolContextModifier + ? { + toolUseID: toolUseID, + modifyContext: toolContextModifier, + } + : undefined, + }) + } + + // TOOD(hackyon): refactor so we don't have different experiences for MCP tools + if (!isMcpTool(tool)) { + await addToolResult(toolOutput, mappedToolResultBlock) + } + + const postToolHookInfos: StopHookInfo[] = [] + const postToolHookStart = Date.now() + for await (const hookResult of runPostToolUseHooks( + toolUseContext, + tool, + toolUseID, + assistantMessage.message.id, + processedInput, + toolOutput, + requestId, + mcpServerType, + mcpServerBaseUrl, + )) { + if ('updatedMCPToolOutput' in hookResult) { + if (isMcpTool(tool)) { + toolOutput = hookResult.updatedMCPToolOutput + } + } else if (isMcpTool(tool)) { + hookResults.push(hookResult) + if (hookResult.message.type === 'attachment') { + const att = hookResult.message.attachment + if ( + 'command' in att && + att.command !== undefined && + 'durationMs' in att && + att.durationMs !== undefined + ) { + postToolHookInfos.push({ + command: att.command, + durationMs: att.durationMs, + }) + } + } + } else { + resultingMessages.push(hookResult) + if (hookResult.message.type === 'attachment') { + const att = hookResult.message.attachment + if ( + 'command' in att && + att.command !== undefined && + 'durationMs' in att && + att.durationMs !== undefined + ) { + postToolHookInfos.push({ + command: att.command, + durationMs: att.durationMs, + }) + } + } + } + } + const postToolHookDurationMs = Date.now() - postToolHookStart + if (postToolHookDurationMs >= SLOW_PHASE_LOG_THRESHOLD_MS) { + logForDebugging( + `Slow PostToolUse hooks: ${postToolHookDurationMs}ms for ${tool.name} (${postToolHookInfos.length} hooks)`, + { level: 'info' }, + ) + } + + if (isMcpTool(tool)) { + await addToolResult(toolOutput) + } + + // Show PostToolUse hook timing inline below tool result when > 500ms. + // Use wall-clock time (not sum of individual durations) since hooks run in parallel. + if (process.env.USER_TYPE === 'ant' && postToolHookInfos.length > 0) { + if (postToolHookDurationMs > HOOK_TIMING_DISPLAY_THRESHOLD_MS) { + resultingMessages.push({ + message: createStopHookSummaryMessage( + postToolHookInfos.length, + postToolHookInfos, + [], + false, + undefined, + false, + 'suggestion', + undefined, + 'PostToolUse', + postToolHookDurationMs, + ), + }) + } + } + + // If the tool provided new messages, add them to the list to return. + if (result.newMessages && result.newMessages.length > 0) { + for (const message of result.newMessages) { + resultingMessages.push({ message }) + } + } + // If hook indicated to prevent continuation after successful execution, yield a stop reason message + if (shouldPreventContinuation) { + resultingMessages.push({ + message: createAttachmentMessage({ + type: 'hook_stopped_continuation', + message: stopReason || 'Execution stopped by hook', + hookName: `PreToolUse:${tool.name}`, + toolUseID: toolUseID, + hookEvent: 'PreToolUse', + }), + }) + } + + // Yield the remaining hook results after the other messages are sent + for (const hookResult of hookResults) { + resultingMessages.push(hookResult) + } + return resultingMessages + } catch (error) { + const durationMs = Date.now() - startTime + addToToolDuration(durationMs) + + endToolExecutionSpan({ + success: false, + error: errorMessage(error), + }) + endToolSpan() + + // Handle MCP auth errors by updating the client status to 'needs-auth' + // This updates the /mcp display to show the server needs re-authorization + if (error instanceof McpAuthError) { + toolUseContext.setAppState(prevState => { + const serverName = error.serverName + const existingClientIndex = prevState.mcp.clients.findIndex( + c => c.name === serverName, + ) + if (existingClientIndex === -1) { + return prevState + } + const existingClient = prevState.mcp.clients[existingClientIndex] + // Only update if client was connected (don't overwrite other states) + if (!existingClient || existingClient.type !== 'connected') { + return prevState + } + const updatedClients = [...prevState.mcp.clients] + updatedClients[existingClientIndex] = { + name: serverName, + type: 'needs-auth' as const, + config: existingClient.config, + } + return { + ...prevState, + mcp: { + ...prevState.mcp, + clients: updatedClients, + }, + } + }) + } + + if (!(error instanceof AbortError)) { + const errorMsg = errorMessage(error) + logForDebugging( + `${tool.name} tool error (${durationMs}ms): ${errorMsg.slice(0, 200)}`, + ) + if (!(error instanceof ShellError)) { + logError(error) + } + logEvent('tengu_tool_use_error', { + messageID: + messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + toolName: sanitizeToolNameForAnalytics(tool.name), + error: classifyToolError( + error, + ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + isMcp: tool.isMcp ?? false, + + queryChainId: toolUseContext.queryTracking + ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: toolUseContext.queryTracking?.depth, + ...(mcpServerType && { + mcpServerType: + mcpServerType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(mcpServerBaseUrl && { + mcpServerBaseUrl: + mcpServerBaseUrl as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(requestId && { + requestId: + requestId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...mcpToolDetailsForAnalytics( + tool.name, + mcpServerType, + mcpServerBaseUrl, + ), + }) + // Log tool result error event for OTLP with tool parameters and decision context + const mcpServerScope = isMcpTool(tool) + ? getMcpServerScopeFromToolName(tool.name) + : null + + void logOTelEvent('tool_result', { + tool_name: sanitizeToolNameForAnalytics(tool.name), + use_id: toolUseID, + success: 'false', + duration_ms: String(durationMs), + error: errorMessage(error), + ...(Object.keys(toolParameters).length > 0 && { + tool_parameters: jsonStringify(toolParameters), + }), + ...(telemetryToolInput && { tool_input: telemetryToolInput }), + ...(decisionInfo && { + decision_source: decisionInfo.source, + decision_type: decisionInfo.decision, + }), + ...(mcpServerScope && { mcp_server_scope: mcpServerScope }), + }) + } + const content = formatError(error) + + // Determine if this was a user interrupt + const isInterrupt = error instanceof AbortError + + // Run PostToolUseFailure hooks + const hookMessages: MessageUpdateLazy< + AttachmentMessage | ProgressMessage + >[] = [] + for await (const hookResult of runPostToolUseFailureHooks( + toolUseContext, + tool, + toolUseID, + messageId, + processedInput, + content, + isInterrupt, + requestId, + mcpServerType, + mcpServerBaseUrl, + )) { + hookMessages.push(hookResult) + } + + return [ + { + message: createUserMessage({ + content: [ + { + type: 'tool_result', + content, + is_error: true, + tool_use_id: toolUseID, + }, + ], + toolUseResult: `Error: ${content}`, + mcpMeta: toolUseContext.agentId + ? undefined + : error instanceof + McpToolCallError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS + ? error.mcpMeta + : undefined, + sourceToolAssistantUUID: assistantMessage.uuid, + }), + }, + ...hookMessages, + ] + } finally { + stopSessionActivity('tool_exec') + // Clean up decision info after logging + if (decisionInfo) { + toolUseContext.toolDecisions?.delete(toolUseID) + } + } +} diff --git a/_all-in-one-upload/cc-haha/src/skills/bundled/claude-api/go/claude-api.md b/_all-in-one-upload/cc-haha/src/skills/bundled/claude-api/go/claude-api.md new file mode 100644 index 0000000..7a4d285 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/skills/bundled/claude-api/go/claude-api.md @@ -0,0 +1,2 @@ + +stub diff --git a/_all-in-one-upload/cc-haha/src/skills/bundled/remember.ts b/_all-in-one-upload/cc-haha/src/skills/bundled/remember.ts new file mode 100644 index 0000000..40bd1a9 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/skills/bundled/remember.ts @@ -0,0 +1,82 @@ +import { isAutoMemoryEnabled } from '../../memdir/paths.js' +import { registerBundledSkill } from '../bundledSkills.js' + +export function registerRememberSkill(): void { + if (process.env.USER_TYPE !== 'ant') { + return + } + + const SKILL_PROMPT = `# Memory Review + +## Goal +Review the user's memory landscape and produce a clear report of proposed changes, grouped by action type. Do NOT apply changes — present proposals for user approval. + +## Steps + +### 1. Gather all memory layers +Read CLAUDE.md and CLAUDE.local.md from the project root (if they exist). Your auto-memory content is already in your system prompt — review it there. Note which team memory sections exist, if any. + +**Success criteria**: You have the contents of all memory layers and can compare them. + +### 2. Classify each auto-memory entry +For each substantive entry in auto-memory, determine the best destination: + +| Destination | What belongs there | Examples | +|---|---|---| +| **CLAUDE.md** | Project conventions and instructions for Claude that all contributors should follow | "use bun not npm", "API routes use kebab-case", "test command is bun test", "prefer functional style" | +| **CLAUDE.local.md** | Personal instructions for Claude specific to this user, not applicable to other contributors | "I prefer concise responses", "always explain trade-offs", "don't auto-commit", "run tests before committing" | +| **Team memory** | Org-wide knowledge that applies across repositories (only if team memory is configured) | "deploy PRs go through #deploy-queue", "staging is at staging.internal", "platform team owns infra" | +| **Stay in auto-memory** | Working notes, temporary context, or entries that don't clearly fit elsewhere | Session-specific observations, uncertain patterns | + +**Important distinctions:** +- CLAUDE.md and CLAUDE.local.md contain instructions for Claude, not user preferences for external tools (editor theme, IDE keybindings, etc. don't belong in either) +- Workflow practices (PR conventions, merge strategies, branch naming) are ambiguous — ask the user whether they're personal or team-wide +- When unsure, ask rather than guess + +**Success criteria**: Each entry has a proposed destination or is flagged as ambiguous. + +### 3. Identify cleanup opportunities +Scan across all layers for: +- **Duplicates**: Auto-memory entries already captured in CLAUDE.md or CLAUDE.local.md → propose removing from auto-memory +- **Outdated**: CLAUDE.md or CLAUDE.local.md entries contradicted by newer auto-memory entries → propose updating the older layer +- **Conflicts**: Contradictions between any two layers → propose resolution, noting which is more recent + +**Success criteria**: All cross-layer issues identified. + +### 4. Present the report +Output a structured report grouped by action type: +1. **Promotions** — entries to move, with destination and rationale +2. **Cleanup** — duplicates, outdated entries, conflicts to resolve +3. **Ambiguous** — entries where you need the user's input on destination +4. **No action needed** — brief note on entries that should stay put + +If auto-memory is empty, say so and offer to review CLAUDE.md for cleanup. + +**Success criteria**: User can review and approve/reject each proposal individually. + +## Rules +- Present ALL proposals before making any changes +- Do NOT modify files without explicit user approval +- Do NOT create new files unless the target doesn't exist yet +- Ask about ambiguous entries — don't guess +` + + registerBundledSkill({ + name: 'remember', + description: + 'Review auto-memory entries and propose promotions to CLAUDE.md, CLAUDE.local.md, or shared memory. Also detects outdated, conflicting, and duplicate entries across memory layers.', + whenToUse: + 'Use when the user wants to review, organize, or promote their auto-memory entries. Also useful for cleaning up outdated or conflicting entries across CLAUDE.md, CLAUDE.local.md, and auto-memory.', + userInvocable: true, + isEnabled: () => isAutoMemoryEnabled(), + async getPromptForCommand(args) { + let prompt = SKILL_PROMPT + + if (args) { + prompt += `\n## Additional context from user\n\n${args}` + } + + return [{ type: 'text', text: prompt }] + }, + }) +} diff --git a/_all-in-one-upload/cc-haha/src/tools/AgentTool/UI.tsx b/_all-in-one-upload/cc-haha/src/tools/AgentTool/UI.tsx new file mode 100644 index 0000000..497805a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/AgentTool/UI.tsx @@ -0,0 +1,872 @@ +import { c as _c } from "react/compiler-runtime"; +import type { ToolResultBlockParam, ToolUseBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'; +import * as React from 'react'; +import { ConfigurableShortcutHint } from 'src/components/ConfigurableShortcutHint.js'; +import { CtrlOToExpand, SubAgentProvider } from 'src/components/CtrlOToExpand.js'; +import { Byline } from 'src/components/design-system/Byline.js'; +import { KeyboardShortcutHint } from 'src/components/design-system/KeyboardShortcutHint.js'; +import type { z } from 'zod/v4'; +import { AgentProgressLine } from '../../components/AgentProgressLine.js'; +import { FallbackToolUseErrorMessage } from '../../components/FallbackToolUseErrorMessage.js'; +import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage.js'; +import { Markdown } from '../../components/Markdown.js'; +import { Message as MessageComponent } from '../../components/Message.js'; +import { MessageResponse } from '../../components/MessageResponse.js'; +import { ToolUseLoader } from '../../components/ToolUseLoader.js'; +import { Box, Text } from '../../ink.js'; +import { getDumpPromptsPath } from '../../services/api/dumpPrompts.js'; +import { findToolByName, type Tools } from '../../Tool.js'; +import type { Message, ProgressMessage } from '../../types/message.js'; +import type { AgentToolProgress } from '../../types/tools.js'; +import { count } from '../../utils/array.js'; +import { getSearchOrReadFromContent, getSearchReadSummaryText } from '../../utils/collapseReadSearch.js'; +import { getDisplayPath } from '../../utils/file.js'; +import { formatDuration, formatNumber } from '../../utils/format.js'; +import { buildSubagentLookups, createAssistantMessage, EMPTY_LOOKUPS } from '../../utils/messages.js'; +import type { ModelAlias } from '../../utils/model/aliases.js'; +import { getMainLoopModel, parseUserSpecifiedModel, renderModelName } from '../../utils/model/model.js'; +import type { Theme, ThemeName } from '../../utils/theme.js'; +import type { outputSchema, Progress, RemoteLaunchedOutput } from './AgentTool.js'; +import { inputSchema } from './AgentTool.js'; +import { getAgentColor } from './agentColorManager.js'; +import { GENERAL_PURPOSE_AGENT } from './built-in/generalPurposeAgent.js'; +const MAX_PROGRESS_MESSAGES_TO_SHOW = 3; + +/** + * Guard: checks if progress data has a `message` field (agent_progress or + * skill_progress). Other progress types (e.g. bash_progress forwarded from + * sub-agents) lack this field and must be skipped by UI helpers. + */ +function hasProgressMessage(data: Progress): data is AgentToolProgress { + if (!('message' in data)) { + return false; + } + const msg = (data as AgentToolProgress).message; + return msg != null && typeof msg === 'object' && 'type' in msg; +} + +/** + * Check if a progress message is a search/read/REPL operation (tool use or result). + * Returns { isSearch, isRead, isREPL } if it's a collapsible operation, null otherwise. + * + * For tool_result messages, uses the provided `toolUseByID` map to find the + * corresponding tool_use block instead of relying on `normalizedMessages`. + */ +function getSearchOrReadInfo(progressMessage: ProgressMessage, tools: Tools, toolUseByID: Map): { + isSearch: boolean; + isRead: boolean; + isREPL: boolean; +} | null { + if (!hasProgressMessage(progressMessage.data)) { + return null; + } + const message = progressMessage.data.message; + + // Check tool_use (assistant message) + if (message.type === 'assistant') { + return getSearchOrReadFromContent(message.message.content[0], tools); + } + + // Check tool_result (user message) - find corresponding tool use from the map + if (message.type === 'user') { + const content = message.message.content[0]; + if (content?.type === 'tool_result') { + const toolUse = toolUseByID.get(content.tool_use_id); + if (toolUse) { + return getSearchOrReadFromContent(toolUse, tools); + } + } + } + return null; +} +type SummaryMessage = { + type: 'summary'; + searchCount: number; + readCount: number; + replCount: number; + uuid: string; + isActive: boolean; // true if still in progress (last message was tool_use, not tool_result) +}; +type ProcessedMessage = { + type: 'original'; + message: ProgressMessage; +} | SummaryMessage; + +/** + * Process progress messages to group consecutive search/read operations into summaries. + * For ants only - returns original messages for non-ants. + * @param isAgentRunning - If true, the last group is always marked as active (in progress) + */ +function processProgressMessages(messages: ProgressMessage[], tools: Tools, isAgentRunning: boolean): ProcessedMessage[] { + // Only process for ants + if ("external" !== 'ant') { + return messages.filter((m): m is ProgressMessage => hasProgressMessage(m.data) && m.data.message.type !== 'user').map(m => ({ + type: 'original', + message: m + })); + } + const result: ProcessedMessage[] = []; + let currentGroup: { + searchCount: number; + readCount: number; + replCount: number; + startUuid: string; + } | null = null; + function flushGroup(isActive: boolean): void { + if (currentGroup && (currentGroup.searchCount > 0 || currentGroup.readCount > 0 || currentGroup.replCount > 0)) { + result.push({ + type: 'summary', + searchCount: currentGroup.searchCount, + readCount: currentGroup.readCount, + replCount: currentGroup.replCount, + uuid: `summary-${currentGroup.startUuid}`, + isActive + }); + } + currentGroup = null; + } + const agentMessages = messages.filter((m): m is ProgressMessage => hasProgressMessage(m.data)); + + // Build tool_use lookup incrementally as we iterate + const toolUseByID = new Map(); + for (const msg of agentMessages) { + // Track tool_use blocks as we see them + if (msg.data.message.type === 'assistant') { + for (const c of msg.data.message.message.content) { + if (c.type === 'tool_use') { + toolUseByID.set(c.id, c as ToolUseBlockParam); + } + } + } + const info = getSearchOrReadInfo(msg, tools, toolUseByID); + if (info && (info.isSearch || info.isRead || info.isREPL)) { + // This is a search/read/REPL operation - add to current group + if (!currentGroup) { + currentGroup = { + searchCount: 0, + readCount: 0, + replCount: 0, + startUuid: msg.uuid + }; + } + // Only count tool_result messages (not tool_use) to avoid double counting + if (msg.data.message.type === 'user') { + if (info.isSearch) { + currentGroup.searchCount++; + } else if (info.isREPL) { + currentGroup.replCount++; + } else if (info.isRead) { + currentGroup.readCount++; + } + } + } else { + // Non-search/read/REPL message - flush current group (completed) and add this message + flushGroup(false); + // Skip user tool_result messages — subagent progress messages lack + // toolUseResult, so UserToolSuccessMessage returns null and the + // height=1 Box in renderToolUseProgressMessage shows as a blank line. + if (msg.data.message.type !== 'user') { + result.push({ + type: 'original', + message: msg + }); + } + } + } + + // Flush any remaining group - it's active if the agent is still running + flushGroup(isAgentRunning); + return result; +} +const ESTIMATED_LINES_PER_TOOL = 9; +const TERMINAL_BUFFER_LINES = 7; +type Output = z.input>; +export function AgentPromptDisplay(t0) { + const $ = _c(3); + const { + prompt, + dim: t1 + } = t0; + t1 === undefined ? false : t1; + let t2; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t2 = Prompt:; + $[0] = t2; + } else { + t2 = $[0]; + } + let t3; + if ($[1] !== prompt) { + t3 = {t2}{prompt}; + $[1] = prompt; + $[2] = t3; + } else { + t3 = $[2]; + } + return t3; +} +export function AgentResponseDisplay(t0) { + const $ = _c(5); + const { + content + } = t0; + let t1; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t1 = Response:; + $[0] = t1; + } else { + t1 = $[0]; + } + let t2; + if ($[1] !== content) { + t2 = content.map(_temp); + $[1] = content; + $[2] = t2; + } else { + t2 = $[2]; + } + let t3; + if ($[3] !== t2) { + t3 = {t1}{t2}; + $[3] = t2; + $[4] = t3; + } else { + t3 = $[4]; + } + return t3; +} +function _temp(block, index) { + return {block.text}; +} +type VerboseAgentTranscriptProps = { + progressMessages: ProgressMessage[]; + tools: Tools; + verbose: boolean; +}; +function VerboseAgentTranscript(t0) { + const $ = _c(15); + const { + progressMessages, + tools, + verbose + } = t0; + let t1; + if ($[0] !== progressMessages) { + t1 = buildSubagentLookups(progressMessages.filter(_temp2).map(_temp3)); + $[0] = progressMessages; + $[1] = t1; + } else { + t1 = $[1]; + } + const { + lookups: agentLookups, + inProgressToolUseIDs + } = t1; + let t2; + if ($[2] !== agentLookups || $[3] !== inProgressToolUseIDs || $[4] !== progressMessages || $[5] !== tools || $[6] !== verbose) { + const filteredMessages = progressMessages.filter(_temp4); + let t3; + if ($[8] !== agentLookups || $[9] !== inProgressToolUseIDs || $[10] !== tools || $[11] !== verbose) { + t3 = progressMessage => ; + $[8] = agentLookups; + $[9] = inProgressToolUseIDs; + $[10] = tools; + $[11] = verbose; + $[12] = t3; + } else { + t3 = $[12]; + } + t2 = filteredMessages.map(t3); + $[2] = agentLookups; + $[3] = inProgressToolUseIDs; + $[4] = progressMessages; + $[5] = tools; + $[6] = verbose; + $[7] = t2; + } else { + t2 = $[7]; + } + let t3; + if ($[13] !== t2) { + t3 = <>{t2}; + $[13] = t2; + $[14] = t3; + } else { + t3 = $[14]; + } + return t3; +} +function _temp4(pm_1) { + if (!hasProgressMessage(pm_1.data)) { + return false; + } + const msg = pm_1.data.message; + if (msg.type === "user" && msg.toolUseResult === undefined) { + return false; + } + return true; +} +function _temp3(pm_0) { + return pm_0.data; +} +function _temp2(pm) { + return hasProgressMessage(pm.data); +} +export function renderToolResultMessage(data: Output, progressMessagesForMessage: ProgressMessage[], { + tools, + verbose, + theme, + isTranscriptMode = false +}: { + tools: Tools; + verbose: boolean; + theme: ThemeName; + isTranscriptMode?: boolean; +}): React.ReactNode { + // Remote-launched agents (ant-only) use a private output type not in the + // public schema. Narrow via the internal discriminant. + const internal = data as Output | RemoteLaunchedOutput; + if (internal.status === 'remote_launched') { + return + + + Remote agent launched{' '} + + · {internal.taskId} · {internal.sessionUrl} + + + + ; + } + if (data.status === 'async_launched') { + const { + prompt + } = data; + return + + + Backgrounded agent + {!isTranscriptMode && + {' ('} + + + {prompt && } + + {')'} + } + + + {isTranscriptMode && prompt && + + } + ; + } + if (data.status !== 'completed') { + return null; + } + const { + agentId, + totalDurationMs, + totalToolUseCount, + totalTokens, + usage, + content, + prompt + } = data; + const result = [totalToolUseCount === 1 ? '1 tool use' : `${totalToolUseCount} tool uses`, formatNumber(totalTokens) + ' tokens', formatDuration(totalDurationMs)]; + const completionMessage = `Done (${result.join(' · ')})`; + const finalAssistantMessage = createAssistantMessage({ + content: completionMessage, + usage: { + ...usage, + inference_geo: null, + iterations: null, + speed: null + } + }); + return + {"external" === 'ant' && + + [ANT-ONLY] API calls: {getDisplayPath(getDumpPromptsPath(agentId))} + + } + {isTranscriptMode && prompt && + + } + {isTranscriptMode ? + + : null} + {isTranscriptMode && content && content.length > 0 && + + } + + + + {!isTranscriptMode && + {' '} + + } + ; +} +export function renderToolUseMessage({ + description, + prompt +}: Partial<{ + description: string; + prompt: string; +}>): React.ReactNode { + if (!description || !prompt) { + return null; + } + return description; +} +export function renderToolUseTag(input: Partial<{ + description: string; + prompt: string; + subagent_type: string; + model?: ModelAlias; +}>): React.ReactNode { + const tags: React.ReactNode[] = []; + if (input.model) { + const mainModel = getMainLoopModel(); + const agentModel = parseUserSpecifiedModel(input.model); + if (agentModel !== mainModel) { + tags.push( + {renderModelName(agentModel)} + ); + } + } + if (tags.length === 0) { + return null; + } + return <>{tags}; +} +const INITIALIZING_TEXT = 'Initializing…'; +export function renderToolUseProgressMessage(progressMessages: ProgressMessage[], { + tools, + verbose, + terminalSize, + inProgressToolCallCount, + isTranscriptMode = false +}: { + tools: Tools; + verbose: boolean; + terminalSize?: { + columns: number; + rows: number; + }; + inProgressToolCallCount?: number; + isTranscriptMode?: boolean; +}): React.ReactNode { + if (!progressMessages.length) { + return + {INITIALIZING_TEXT} + ; + } + + // Checks to see if we should show a super condensed progress message summary. + // This prevents flickers when the terminal size is too small to render all the dynamic content + const toolToolRenderLinesEstimate = (inProgressToolCallCount ?? 1) * ESTIMATED_LINES_PER_TOOL + TERMINAL_BUFFER_LINES; + const shouldUseCondensedMode = !isTranscriptMode && terminalSize && terminalSize.rows && terminalSize.rows < toolToolRenderLinesEstimate; + const getProgressStats = () => { + const toolUseCount = count(progressMessages, msg => { + if (!hasProgressMessage(msg.data)) { + return false; + } + const message = msg.data.message; + return message.message.content.some(content => content.type === 'tool_use'); + }); + const latestAssistant = progressMessages.findLast((msg): msg is ProgressMessage => hasProgressMessage(msg.data) && msg.data.message.type === 'assistant'); + let tokens = null; + if (latestAssistant?.data.message.type === 'assistant') { + const usage = latestAssistant.data.message.message.usage; + tokens = (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0) + usage.input_tokens + usage.output_tokens; + } + return { + toolUseCount, + tokens + }; + }; + if (shouldUseCondensedMode) { + const { + toolUseCount, + tokens + } = getProgressStats(); + return + + In progress… · {toolUseCount} tool{' '} + {toolUseCount === 1 ? 'use' : 'uses'} + {tokens && ` · ${formatNumber(tokens)} tokens`} ·{' '} + + + ; + } + + // Process messages to group consecutive search/read operations into summaries (ants only) + // isAgentRunning=true since this is the progress view while the agent is still running + const processedMessages = processProgressMessages(progressMessages, tools, true); + + // For display, take the last few processed messages + const displayedMessages = isTranscriptMode ? processedMessages : processedMessages.slice(-MAX_PROGRESS_MESSAGES_TO_SHOW); + + // Count hidden tool uses specifically (not all messages) to match the + // final "Done (N tool uses)" count. Each tool use generates multiple + // progress messages (tool_use + tool_result + text), so counting all + // hidden messages inflates the number shown to the user. + const hiddenMessages = isTranscriptMode ? [] : processedMessages.slice(0, Math.max(0, processedMessages.length - MAX_PROGRESS_MESSAGES_TO_SHOW)); + const hiddenToolUseCount = count(hiddenMessages, m => { + if (m.type === 'summary') { + return m.searchCount + m.readCount + m.replCount > 0; + } + const data = m.message.data; + if (!hasProgressMessage(data)) { + return false; + } + return data.message.message.content.some(content => content.type === 'tool_use'); + }); + const firstData = progressMessages[0]?.data; + const prompt = firstData && hasProgressMessage(firstData) ? firstData.prompt : undefined; + + // After grouping, displayedMessages can be empty when the only progress so + // far is an assistant tool_use for a search/read op (grouped but not yet + // counted, since counts increment on tool_result). Fall back to the + // initializing text so MessageResponse doesn't render a bare ⎿. + if (displayedMessages.length === 0 && !(isTranscriptMode && prompt)) { + return + {INITIALIZING_TEXT} + ; + } + const { + lookups: subagentLookups, + inProgressToolUseIDs: collapsedInProgressIDs + } = buildSubagentLookups(progressMessages.filter((pm): pm is ProgressMessage => hasProgressMessage(pm.data)).map(pm => pm.data)); + return + + + {isTranscriptMode && prompt && + + } + {displayedMessages.map(processed => { + if (processed.type === 'summary') { + // Render summary for grouped search/read/REPL operations using shared formatting + const summaryText = getSearchReadSummaryText(processed.searchCount, processed.readCount, processed.isActive, processed.replCount); + return + {summaryText} + ; + } + // Render original message without height=1 wrapper so null + // content (tool not found, renderToolUseMessage returns null) + // doesn't leave a blank line. Tool call headers are single-line + // anyway so truncation isn't needed. + return ; + })} + + {hiddenToolUseCount > 0 && + +{hiddenToolUseCount} more tool{' '} + {hiddenToolUseCount === 1 ? 'use' : 'uses'} + } + + ; +} +export function renderToolUseRejectedMessage(_input: { + description: string; + prompt: string; + subagent_type: string; +}, { + progressMessagesForMessage, + tools, + verbose, + isTranscriptMode +}: { + columns: number; + messages: Message[]; + style?: 'condensed'; + theme: ThemeName; + progressMessagesForMessage: ProgressMessage[]; + tools: Tools; + verbose: boolean; + isTranscriptMode?: boolean; +}): React.ReactNode { + // Get agentId from progress messages if available (agent was running before rejection) + const firstData = progressMessagesForMessage[0]?.data; + const agentId = firstData && hasProgressMessage(firstData) ? firstData.agentId : undefined; + return <> + {"external" === 'ant' && agentId && + + [ANT-ONLY] API calls: {getDisplayPath(getDumpPromptsPath(agentId))} + + } + {renderToolUseProgressMessage(progressMessagesForMessage, { + tools, + verbose, + isTranscriptMode + })} + + ; +} +export function renderToolUseErrorMessage(result: ToolResultBlockParam['content'], { + progressMessagesForMessage, + tools, + verbose, + isTranscriptMode +}: { + progressMessagesForMessage: ProgressMessage[]; + tools: Tools; + verbose: boolean; + isTranscriptMode?: boolean; +}): React.ReactNode { + return <> + {renderToolUseProgressMessage(progressMessagesForMessage, { + tools, + verbose, + isTranscriptMode + })} + + ; +} +function calculateAgentStats(progressMessages: ProgressMessage[]): { + toolUseCount: number; + tokens: number | null; +} { + const toolUseCount = count(progressMessages, msg => { + if (!hasProgressMessage(msg.data)) { + return false; + } + const message = msg.data.message; + return message.type === 'user' && message.message.content.some(content => content.type === 'tool_result'); + }); + const latestAssistant = progressMessages.findLast((msg): msg is ProgressMessage => hasProgressMessage(msg.data) && msg.data.message.type === 'assistant'); + let tokens = null; + if (latestAssistant?.data.message.type === 'assistant') { + const usage = latestAssistant.data.message.message.usage; + tokens = (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0) + usage.input_tokens + usage.output_tokens; + } + return { + toolUseCount, + tokens + }; +} +export function renderGroupedAgentToolUse(toolUses: Array<{ + param: ToolUseBlockParam; + isResolved: boolean; + isError: boolean; + isInProgress: boolean; + progressMessages: ProgressMessage[]; + result?: { + param: ToolResultBlockParam; + output: Output; + }; +}>, options: { + shouldAnimate: boolean; + tools: Tools; +}): React.ReactNode | null { + const { + shouldAnimate, + tools + } = options; + + // Calculate stats for each agent + const agentStats = toolUses.map(({ + param, + isResolved, + isError, + progressMessages, + result + }) => { + const stats = calculateAgentStats(progressMessages); + const lastToolInfo = extractLastToolInfo(progressMessages, tools); + const parsedInput = inputSchema().safeParse(param.input); + + // teammate_spawned is not part of the exported Output type (cast through unknown + // for dead code elimination), so check via string comparison on the raw value + const isTeammateSpawn = result?.output?.status as string === 'teammate_spawned'; + + // For teammate spawns, show @name with type in parens and description as status + let agentType: string; + let description: string | undefined; + let color: keyof Theme | undefined; + let descriptionColor: keyof Theme | undefined; + let taskDescription: string | undefined; + if (isTeammateSpawn && parsedInput.success && parsedInput.data.name) { + agentType = `@${parsedInput.data.name}`; + const subagentType = parsedInput.data.subagent_type; + description = isCustomSubagentType(subagentType) ? subagentType : undefined; + taskDescription = parsedInput.data.description; + // Use the custom agent definition's color on the type, not the name + descriptionColor = isCustomSubagentType(subagentType) ? getAgentColor(subagentType) as keyof Theme | undefined : undefined; + } else { + agentType = parsedInput.success ? userFacingName(parsedInput.data) : 'Agent'; + description = parsedInput.success ? parsedInput.data.description : undefined; + color = parsedInput.success ? userFacingNameBackgroundColor(parsedInput.data) : undefined; + taskDescription = undefined; + } + + // Check if this was launched as a background agent OR backgrounded mid-execution + const launchedAsAsync = parsedInput.success && 'run_in_background' in parsedInput.data && parsedInput.data.run_in_background === true; + const outputStatus = (result?.output as { + status?: string; + } | undefined)?.status; + const backgroundedMidExecution = outputStatus === 'async_launched' || outputStatus === 'remote_launched'; + const isAsync = launchedAsAsync || backgroundedMidExecution || isTeammateSpawn; + const name = parsedInput.success ? parsedInput.data.name : undefined; + return { + id: param.id, + agentType, + description, + toolUseCount: stats.toolUseCount, + tokens: stats.tokens, + isResolved, + isError, + isAsync, + color, + descriptionColor, + lastToolInfo, + taskDescription, + name + }; + }); + const anyUnresolved = toolUses.some(t => !t.isResolved); + const anyError = toolUses.some(t => t.isError); + const allComplete = !anyUnresolved; + + // Check if all agents are the same type + const allSameType = agentStats.length > 0 && agentStats.every(stat => stat.agentType === agentStats[0]?.agentType); + const commonType = allSameType && agentStats[0]?.agentType !== 'Agent' ? agentStats[0]?.agentType : null; + + // Check if all resolved agents are async (background) + const allAsync = agentStats.every(stat => stat.isAsync); + return + + + + {allComplete ? allAsync ? <> + {toolUses.length} background agents launched{' '} + + + + : <> + {toolUses.length}{' '} + {commonType ? `${commonType} agents` : 'agents'} finished + : <> + Running {toolUses.length}{' '} + {commonType ? `${commonType} agents` : 'agents'}… + }{' '} + + {!allAsync && } + + {agentStats.map((stat, index) => )} + ; +} +export function userFacingName(input: Partial<{ + description: string; + prompt: string; + subagent_type: string; + name: string; + team_name: string; +}> | undefined): string { + if (input?.subagent_type && input.subagent_type !== GENERAL_PURPOSE_AGENT.agentType) { + // Display "worker" agents as "Agent" for cleaner UI + if (input.subagent_type === 'worker') { + return 'Agent'; + } + return input.subagent_type; + } + return 'Agent'; +} +export function userFacingNameBackgroundColor(input: Partial<{ + description: string; + prompt: string; + subagent_type: string; +}> | undefined): keyof Theme | undefined { + if (!input?.subagent_type) { + return undefined; + } + + // Get the color for this agent + return getAgentColor(input.subagent_type) as keyof Theme | undefined; +} +export function extractLastToolInfo(progressMessages: ProgressMessage[], tools: Tools): string | null { + // Build tool_use lookup from all progress messages (needed for reverse iteration) + const toolUseByID = new Map(); + for (const pm of progressMessages) { + if (!hasProgressMessage(pm.data)) { + continue; + } + if (pm.data.message.type === 'assistant') { + for (const c of pm.data.message.message.content) { + if (c.type === 'tool_use') { + toolUseByID.set(c.id, c as ToolUseBlockParam); + } + } + } + } + + // Count trailing consecutive search/read operations from the end + let searchCount = 0; + let readCount = 0; + for (let i = progressMessages.length - 1; i >= 0; i--) { + const msg = progressMessages[i]!; + if (!hasProgressMessage(msg.data)) { + continue; + } + const info = getSearchOrReadInfo(msg, tools, toolUseByID); + if (info && (info.isSearch || info.isRead)) { + // Only count tool_result messages to avoid double counting + if (msg.data.message.type === 'user') { + if (info.isSearch) { + searchCount++; + } else if (info.isRead) { + readCount++; + } + } + } else { + break; + } + } + if (searchCount + readCount >= 2) { + return getSearchReadSummaryText(searchCount, readCount, true); + } + + // Find the last tool_result message + const lastToolResult = progressMessages.findLast((msg): msg is ProgressMessage => { + if (!hasProgressMessage(msg.data)) { + return false; + } + const message = msg.data.message; + return message.type === 'user' && message.message.content.some(c => c.type === 'tool_result'); + }); + if (lastToolResult?.data.message.type === 'user') { + const toolResultBlock = lastToolResult.data.message.message.content.find(c => c.type === 'tool_result'); + if (toolResultBlock?.type === 'tool_result') { + // Look up the corresponding tool_use — already indexed above + const toolUseBlock = toolUseByID.get(toolResultBlock.tool_use_id); + if (toolUseBlock) { + const tool = findToolByName(tools, toolUseBlock.name); + if (!tool) { + return toolUseBlock.name; // Fallback to raw name + } + const input = toolUseBlock.input as Record; + const parsedInput = tool.inputSchema.safeParse(input); + + // Get user-facing tool name + const userFacingToolName = tool.userFacingName(parsedInput.success ? parsedInput.data : undefined); + + // Try to get summary from the tool itself + if (tool.getToolUseSummary) { + const summary = tool.getToolUseSummary(parsedInput.success ? parsedInput.data : undefined); + if (summary) { + return `${userFacingToolName}: ${summary}`; + } + } + + // Default: just show user-facing tool name + return userFacingToolName; + } + } + } + return null; +} +function isCustomSubagentType(subagentType: string | undefined): subagentType is string { + return !!subagentType && subagentType !== GENERAL_PURPOSE_AGENT.agentType && subagentType !== 'worker'; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJUb29sUmVzdWx0QmxvY2tQYXJhbSIsIlRvb2xVc2VCbG9ja1BhcmFtIiwiUmVhY3QiLCJDb25maWd1cmFibGVTaG9ydGN1dEhpbnQiLCJDdHJsT1RvRXhwYW5kIiwiU3ViQWdlbnRQcm92aWRlciIsIkJ5bGluZSIsIktleWJvYXJkU2hvcnRjdXRIaW50IiwieiIsIkFnZW50UHJvZ3Jlc3NMaW5lIiwiRmFsbGJhY2tUb29sVXNlRXJyb3JNZXNzYWdlIiwiRmFsbGJhY2tUb29sVXNlUmVqZWN0ZWRNZXNzYWdlIiwiTWFya2Rvd24iLCJNZXNzYWdlIiwiTWVzc2FnZUNvbXBvbmVudCIsIk1lc3NhZ2VSZXNwb25zZSIsIlRvb2xVc2VMb2FkZXIiLCJCb3giLCJUZXh0IiwiZ2V0RHVtcFByb21wdHNQYXRoIiwiZmluZFRvb2xCeU5hbWUiLCJUb29scyIsIlByb2dyZXNzTWVzc2FnZSIsIkFnZW50VG9vbFByb2dyZXNzIiwiY291bnQiLCJnZXRTZWFyY2hPclJlYWRGcm9tQ29udGVudCIsImdldFNlYXJjaFJlYWRTdW1tYXJ5VGV4dCIsImdldERpc3BsYXlQYXRoIiwiZm9ybWF0RHVyYXRpb24iLCJmb3JtYXROdW1iZXIiLCJidWlsZFN1YmFnZW50TG9va3VwcyIsImNyZWF0ZUFzc2lzdGFudE1lc3NhZ2UiLCJFTVBUWV9MT09LVVBTIiwiTW9kZWxBbGlhcyIsImdldE1haW5Mb29wTW9kZWwiLCJwYXJzZVVzZXJTcGVjaWZpZWRNb2RlbCIsInJlbmRlck1vZGVsTmFtZSIsIlRoZW1lIiwiVGhlbWVOYW1lIiwib3V0cHV0U2NoZW1hIiwiUHJvZ3Jlc3MiLCJSZW1vdGVMYXVuY2hlZE91dHB1dCIsImlucHV0U2NoZW1hIiwiZ2V0QWdlbnRDb2xvciIsIkdFTkVSQUxfUFVSUE9TRV9BR0VOVCIsIk1BWF9QUk9HUkVTU19NRVNTQUdFU19UT19TSE9XIiwiaGFzUHJvZ3Jlc3NNZXNzYWdlIiwiZGF0YSIsIm1zZyIsIm1lc3NhZ2UiLCJnZXRTZWFyY2hPclJlYWRJbmZvIiwicHJvZ3Jlc3NNZXNzYWdlIiwidG9vbHMiLCJ0b29sVXNlQnlJRCIsIk1hcCIsImlzU2VhcmNoIiwiaXNSZWFkIiwiaXNSRVBMIiwidHlwZSIsImNvbnRlbnQiLCJ0b29sVXNlIiwiZ2V0IiwidG9vbF91c2VfaWQiLCJTdW1tYXJ5TWVzc2FnZSIsInNlYXJjaENvdW50IiwicmVhZENvdW50IiwicmVwbENvdW50IiwidXVpZCIsImlzQWN0aXZlIiwiUHJvY2Vzc2VkTWVzc2FnZSIsInByb2Nlc3NQcm9ncmVzc01lc3NhZ2VzIiwibWVzc2FnZXMiLCJpc0FnZW50UnVubmluZyIsImZpbHRlciIsIm0iLCJtYXAiLCJyZXN1bHQiLCJjdXJyZW50R3JvdXAiLCJzdGFydFV1aWQiLCJmbHVzaEdyb3VwIiwicHVzaCIsImFnZW50TWVzc2FnZXMiLCJjIiwic2V0IiwiaWQiLCJpbmZvIiwiRVNUSU1BVEVEX0xJTkVTX1BFUl9UT09MIiwiVEVSTUlOQUxfQlVGRkVSX0xJTkVTIiwiT3V0cHV0IiwiaW5wdXQiLCJSZXR1cm5UeXBlIiwiQWdlbnRQcm9tcHREaXNwbGF5IiwidDAiLCIkIiwiX2MiLCJwcm9tcHQiLCJkaW0iLCJ0MSIsInVuZGVmaW5lZCIsInQyIiwiU3ltYm9sIiwiZm9yIiwidDMiLCJBZ2VudFJlc3BvbnNlRGlzcGxheSIsIl90ZW1wIiwiYmxvY2siLCJpbmRleCIsInRleHQiLCJWZXJib3NlQWdlbnRUcmFuc2NyaXB0UHJvcHMiLCJwcm9ncmVzc01lc3NhZ2VzIiwidmVyYm9zZSIsIlZlcmJvc2VBZ2VudFRyYW5zY3JpcHQiLCJfdGVtcDIiLCJfdGVtcDMiLCJsb29rdXBzIiwiYWdlbnRMb29rdXBzIiwiaW5Qcm9ncmVzc1Rvb2xVc2VJRHMiLCJmaWx0ZXJlZE1lc3NhZ2VzIiwiX3RlbXA0IiwicG1fMSIsInBtIiwidG9vbFVzZVJlc3VsdCIsInBtXzAiLCJyZW5kZXJUb29sUmVzdWx0TWVzc2FnZSIsInByb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlIiwidGhlbWUiLCJpc1RyYW5zY3JpcHRNb2RlIiwiUmVhY3ROb2RlIiwiaW50ZXJuYWwiLCJzdGF0dXMiLCJ0YXNrSWQiLCJzZXNzaW9uVXJsIiwiYWdlbnRJZCIsInRvdGFsRHVyYXRpb25NcyIsInRvdGFsVG9vbFVzZUNvdW50IiwidG90YWxUb2tlbnMiLCJ1c2FnZSIsImNvbXBsZXRpb25NZXNzYWdlIiwiam9pbiIsImZpbmFsQXNzaXN0YW50TWVzc2FnZSIsImluZmVyZW5jZV9nZW8iLCJpdGVyYXRpb25zIiwic3BlZWQiLCJsZW5ndGgiLCJTZXQiLCJyZW5kZXJUb29sVXNlTWVzc2FnZSIsImRlc2NyaXB0aW9uIiwiUGFydGlhbCIsInJlbmRlclRvb2xVc2VUYWciLCJzdWJhZ2VudF90eXBlIiwibW9kZWwiLCJ0YWdzIiwibWFpbk1vZGVsIiwiYWdlbnRNb2RlbCIsIklOSVRJQUxJWklOR19URVhUIiwicmVuZGVyVG9vbFVzZVByb2dyZXNzTWVzc2FnZSIsInRlcm1pbmFsU2l6ZSIsImluUHJvZ3Jlc3NUb29sQ2FsbENvdW50IiwiY29sdW1ucyIsInJvd3MiLCJ0b29sVG9vbFJlbmRlckxpbmVzRXN0aW1hdGUiLCJzaG91bGRVc2VDb25kZW5zZWRNb2RlIiwiZ2V0UHJvZ3Jlc3NTdGF0cyIsInRvb2xVc2VDb3VudCIsInNvbWUiLCJsYXRlc3RBc3Npc3RhbnQiLCJmaW5kTGFzdCIsInRva2VucyIsImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyIsImNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zIiwiaW5wdXRfdG9rZW5zIiwib3V0cHV0X3Rva2VucyIsInByb2Nlc3NlZE1lc3NhZ2VzIiwiZGlzcGxheWVkTWVzc2FnZXMiLCJzbGljZSIsImhpZGRlbk1lc3NhZ2VzIiwiTWF0aCIsIm1heCIsImhpZGRlblRvb2xVc2VDb3VudCIsImZpcnN0RGF0YSIsInN1YmFnZW50TG9va3VwcyIsImNvbGxhcHNlZEluUHJvZ3Jlc3NJRHMiLCJwcm9jZXNzZWQiLCJzdW1tYXJ5VGV4dCIsInJlbmRlclRvb2xVc2VSZWplY3RlZE1lc3NhZ2UiLCJfaW5wdXQiLCJzdHlsZSIsInJlbmRlclRvb2xVc2VFcnJvck1lc3NhZ2UiLCJjYWxjdWxhdGVBZ2VudFN0YXRzIiwicmVuZGVyR3JvdXBlZEFnZW50VG9vbFVzZSIsInRvb2xVc2VzIiwiQXJyYXkiLCJwYXJhbSIsImlzUmVzb2x2ZWQiLCJpc0Vycm9yIiwiaXNJblByb2dyZXNzIiwib3V0cHV0Iiwib3B0aW9ucyIsInNob3VsZEFuaW1hdGUiLCJhZ2VudFN0YXRzIiwic3RhdHMiLCJsYXN0VG9vbEluZm8iLCJleHRyYWN0TGFzdFRvb2xJbmZvIiwicGFyc2VkSW5wdXQiLCJzYWZlUGFyc2UiLCJpc1RlYW1tYXRlU3Bhd24iLCJhZ2VudFR5cGUiLCJjb2xvciIsImRlc2NyaXB0aW9uQ29sb3IiLCJ0YXNrRGVzY3JpcHRpb24iLCJzdWNjZXNzIiwibmFtZSIsInN1YmFnZW50VHlwZSIsImlzQ3VzdG9tU3ViYWdlbnRUeXBlIiwidXNlckZhY2luZ05hbWUiLCJ1c2VyRmFjaW5nTmFtZUJhY2tncm91bmRDb2xvciIsImxhdW5jaGVkQXNBc3luYyIsInJ1bl9pbl9iYWNrZ3JvdW5kIiwib3V0cHV0U3RhdHVzIiwiYmFja2dyb3VuZGVkTWlkRXhlY3V0aW9uIiwiaXNBc3luYyIsImFueVVucmVzb2x2ZWQiLCJ0IiwiYW55RXJyb3IiLCJhbGxDb21wbGV0ZSIsImFsbFNhbWVUeXBlIiwiZXZlcnkiLCJzdGF0IiwiY29tbW9uVHlwZSIsImFsbEFzeW5jIiwidGVhbV9uYW1lIiwiaSIsImxhc3RUb29sUmVzdWx0IiwidG9vbFJlc3VsdEJsb2NrIiwiZmluZCIsInRvb2xVc2VCbG9jayIsInRvb2wiLCJSZWNvcmQiLCJ1c2VyRmFjaW5nVG9vbE5hbWUiLCJnZXRUb29sVXNlU3VtbWFyeSIsInN1bW1hcnkiXSwic291cmNlcyI6WyJVSS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUge1xuICBUb29sUmVzdWx0QmxvY2tQYXJhbSxcbiAgVG9vbFVzZUJsb2NrUGFyYW0sXG59IGZyb20gJ0BhbnRocm9waWMtYWkvc2RrL3Jlc291cmNlcy9pbmRleC5tanMnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IENvbmZpZ3VyYWJsZVNob3J0Y3V0SGludCB9IGZyb20gJ3NyYy9jb21wb25lbnRzL0NvbmZpZ3VyYWJsZVNob3J0Y3V0SGludC5qcydcbmltcG9ydCB7XG4gIEN0cmxPVG9FeHBhbmQsXG4gIFN1YkFnZW50UHJvdmlkZXIsXG59IGZyb20gJ3NyYy9jb21wb25lbnRzL0N0cmxPVG9FeHBhbmQuanMnXG5pbXBvcnQgeyBCeWxpbmUgfSBmcm9tICdzcmMvY29tcG9uZW50cy9kZXNpZ24tc3lzdGVtL0J5bGluZS5qcydcbmltcG9ydCB7IEtleWJvYXJkU2hvcnRjdXRIaW50IH0gZnJvbSAnc3JjL2NvbXBvbmVudHMvZGVzaWduLXN5c3RlbS9LZXlib2FyZFNob3J0Y3V0SGludC5qcydcbmltcG9ydCB0eXBlIHsgeiB9IGZyb20gJ3pvZC92NCdcbmltcG9ydCB7IEFnZW50UHJvZ3Jlc3NMaW5lIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9BZ2VudFByb2dyZXNzTGluZS5qcydcbmltcG9ydCB7IEZhbGxiYWNrVG9vbFVzZUVycm9yTWVzc2FnZSB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvRmFsbGJhY2tUb29sVXNlRXJyb3JNZXNzYWdlLmpzJ1xuaW1wb3J0IHsgRmFsbGJhY2tUb29sVXNlUmVqZWN0ZWRNZXNzYWdlIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9GYWxsYmFja1Rvb2xVc2VSZWplY3RlZE1lc3NhZ2UuanMnXG5pbXBvcnQgeyBNYXJrZG93biB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvTWFya2Rvd24uanMnXG5pbXBvcnQgeyBNZXNzYWdlIGFzIE1lc3NhZ2VDb21wb25lbnQgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL01lc3NhZ2UuanMnXG5pbXBvcnQgeyBNZXNzYWdlUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL01lc3NhZ2VSZXNwb25zZS5qcydcbmltcG9ydCB7IFRvb2xVc2VMb2FkZXIgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL1Rvb2xVc2VMb2FkZXIuanMnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBnZXREdW1wUHJvbXB0c1BhdGggfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9hcGkvZHVtcFByb21wdHMuanMnXG5pbXBvcnQgeyBmaW5kVG9vbEJ5TmFtZSwgdHlwZSBUb29scyB9IGZyb20gJy4uLy4uL1Rvb2wuanMnXG5pbXBvcnQgdHlwZSB7IE1lc3NhZ2UsIFByb2dyZXNzTWVzc2FnZSB9IGZyb20gJy4uLy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50VG9vbFByb2dyZXNzIH0gZnJvbSAnLi4vLi4vdHlwZXMvdG9vbHMuanMnXG5pbXBvcnQgeyBjb3VudCB9IGZyb20gJy4uLy4uL3V0aWxzL2FycmF5LmpzJ1xuaW1wb3J0IHtcbiAgZ2V0U2VhcmNoT3JSZWFkRnJvbUNvbnRlbnQsXG4gIGdldFNlYXJjaFJlYWRTdW1tYXJ5VGV4dCxcbn0gZnJvbSAnLi4vLi4vdXRpbHMvY29sbGFwc2VSZWFkU2VhcmNoLmpzJ1xuaW1wb3J0IHsgZ2V0RGlzcGxheVBhdGggfSBmcm9tICcuLi8uLi91dGlscy9maWxlLmpzJ1xuaW1wb3J0IHsgZm9ybWF0RHVyYXRpb24sIGZvcm1hdE51bWJlciB9IGZyb20gJy4uLy4uL3V0aWxzL2Zvcm1hdC5qcydcbmltcG9ydCB7XG4gIGJ1aWxkU3ViYWdlbnRMb29rdXBzLFxuICBjcmVhdGVBc3Npc3RhbnRNZXNzYWdlLFxuICBFTVBUWV9MT09LVVBTLFxufSBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlcy5qcydcbmltcG9ydCB0eXBlIHsgTW9kZWxBbGlhcyB9IGZyb20gJy4uLy4uL3V0aWxzL21vZGVsL2FsaWFzZXMuanMnXG5pbXBvcnQge1xuICBnZXRNYWluTG9vcE1vZGVsLFxuICBwYXJzZVVzZXJTcGVjaWZpZWRNb2RlbCxcbiAgcmVuZGVyTW9kZWxOYW1lLFxufSBmcm9tICcuLi8uLi91dGlscy9tb2RlbC9tb2RlbC5qcydcbmltcG9ydCB0eXBlIHsgVGhlbWUsIFRoZW1lTmFtZSB9IGZyb20gJy4uLy4uL3V0aWxzL3RoZW1lLmpzJ1xuaW1wb3J0IHR5cGUge1xuICBvdXRwdXRTY2hlbWEsXG4gIFByb2dyZXNzLFxuICBSZW1vdGVMYXVuY2hlZE91dHB1dCxcbn0gZnJvbSAnLi9BZ2VudFRvb2wuanMnXG5pbXBvcnQgeyBpbnB1dFNjaGVtYSB9IGZyb20gJy4vQWdlbnRUb29sLmpzJ1xuaW1wb3J0IHsgZ2V0QWdlbnRDb2xvciB9IGZyb20gJy4vYWdlbnRDb2xvck1hbmFnZXIuanMnXG5pbXBvcnQgeyBHRU5FUkFMX1BVUlBPU0VfQUdFTlQgfSBmcm9tICcuL2J1aWx0LWluL2dlbmVyYWxQdXJwb3NlQWdlbnQuanMnXG5cbmNvbnN0IE1BWF9QUk9HUkVTU19NRVNTQUdFU19UT19TSE9XID0gM1xuXG4vKipcbiAqIEd1YXJkOiBjaGVja3MgaWYgcHJvZ3Jlc3MgZGF0YSBoYXMgYSBgbWVzc2FnZWAgZmllbGQgKGFnZW50X3Byb2dyZXNzIG9yXG4gKiBza2lsbF9wcm9ncmVzcykuICBPdGhlciBwcm9ncmVzcyB0eXBlcyAoZS5nLiBiYXNoX3Byb2dyZXNzIGZvcndhcmRlZCBmcm9tXG4gKiBzdWItYWdlbnRzKSBsYWNrIHRoaXMgZmllbGQgYW5kIG11c3QgYmUgc2tpcHBlZCBieSBVSSBoZWxwZXJzLlxuICovXG5mdW5jdGlvbiBoYXNQcm9ncmVzc01lc3NhZ2UoZGF0YTogUHJvZ3Jlc3MpOiBkYXRhIGlzIEFnZW50VG9vbFByb2dyZXNzIHtcbiAgaWYgKCEoJ21lc3NhZ2UnIGluIGRhdGEpKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgY29uc3QgbXNnID0gKGRhdGEgYXMgQWdlbnRUb29sUHJvZ3Jlc3MpLm1lc3NhZ2VcbiAgcmV0dXJuIG1zZyAhPSBudWxsICYmIHR5cGVvZiBtc2cgPT09ICdvYmplY3QnICYmICd0eXBlJyBpbiBtc2dcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhIHByb2dyZXNzIG1lc3NhZ2UgaXMgYSBzZWFyY2gvcmVhZC9SRVBMIG9wZXJhdGlvbiAodG9vbCB1c2Ugb3IgcmVzdWx0KS5cbiAqIFJldHVybnMgeyBpc1NlYXJjaCwgaXNSZWFkLCBpc1JFUEwgfSBpZiBpdCdzIGEgY29sbGFwc2libGUgb3BlcmF0aW9uLCBudWxsIG90aGVyd2lzZS5cbiAqXG4gKiBGb3IgdG9vbF9yZXN1bHQgbWVzc2FnZXMsIHVzZXMgdGhlIHByb3ZpZGVkIGB0b29sVXNlQnlJRGAgbWFwIHRvIGZpbmQgdGhlXG4gKiBjb3JyZXNwb25kaW5nIHRvb2xfdXNlIGJsb2NrIGluc3RlYWQgb2YgcmVseWluZyBvbiBgbm9ybWFsaXplZE1lc3NhZ2VzYC5cbiAqL1xuZnVuY3Rpb24gZ2V0U2VhcmNoT3JSZWFkSW5mbyhcbiAgcHJvZ3Jlc3NNZXNzYWdlOiBQcm9ncmVzc01lc3NhZ2U8UHJvZ3Jlc3M+LFxuICB0b29sczogVG9vbHMsXG4gIHRvb2xVc2VCeUlEOiBNYXA8c3RyaW5nLCBUb29sVXNlQmxvY2tQYXJhbT4sXG4pOiB7IGlzU2VhcmNoOiBib29sZWFuOyBpc1JlYWQ6IGJvb2xlYW47IGlzUkVQTDogYm9vbGVhbiB9IHwgbnVsbCB7XG4gIGlmICghaGFzUHJvZ3Jlc3NNZXNzYWdlKHByb2dyZXNzTWVzc2FnZS5kYXRhKSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgY29uc3QgbWVzc2FnZSA9IHByb2dyZXNzTWVzc2FnZS5kYXRhLm1lc3NhZ2VcblxuICAvLyBDaGVjayB0b29sX3VzZSAoYXNzaXN0YW50IG1lc3NhZ2UpXG4gIGlmIChtZXNzYWdlLnR5cGUgPT09ICdhc3Npc3RhbnQnKSB7XG4gICAgcmV0dXJuIGdldFNlYXJjaE9yUmVhZEZyb21Db250ZW50KG1lc3NhZ2UubWVzc2FnZS5jb250ZW50WzBdLCB0b29scylcbiAgfVxuXG4gIC8vIENoZWNrIHRvb2xfcmVzdWx0ICh1c2VyIG1lc3NhZ2UpIC0gZmluZCBjb3JyZXNwb25kaW5nIHRvb2wgdXNlIGZyb20gdGhlIG1hcFxuICBpZiAobWVzc2FnZS50eXBlID09PSAndXNlcicpIHtcbiAgICBjb25zdCBjb250ZW50ID0gbWVzc2FnZS5tZXNzYWdlLmNvbnRlbnRbMF1cbiAgICBpZiAoY29udGVudD8udHlwZSA9PT0gJ3Rvb2xfcmVzdWx0Jykge1xuICAgICAgY29uc3QgdG9vbFVzZSA9IHRvb2xVc2VCeUlELmdldChjb250ZW50LnRvb2xfdXNlX2lkKVxuICAgICAgaWYgKHRvb2xVc2UpIHtcbiAgICAgICAgcmV0dXJuIGdldFNlYXJjaE9yUmVhZEZyb21Db250ZW50KHRvb2xVc2UsIHRvb2xzKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsXG59XG5cbnR5cGUgU3VtbWFyeU1lc3NhZ2UgPSB7XG4gIHR5cGU6ICdzdW1tYXJ5J1xuICBzZWFyY2hDb3VudDogbnVtYmVyXG4gIHJlYWRDb3VudDogbnVtYmVyXG4gIHJlcGxDb3VudDogbnVtYmVyXG4gIHV1aWQ6IHN0cmluZ1xuICBpc0FjdGl2ZTogYm9vbGVhbiAvLyB0cnVlIGlmIHN0aWxsIGluIHByb2dyZXNzIChsYXN0IG1lc3NhZ2Ugd2FzIHRvb2xfdXNlLCBub3QgdG9vbF9yZXN1bHQpXG59XG5cbnR5cGUgUHJvY2Vzc2VkTWVzc2FnZSA9XG4gIHwgeyB0eXBlOiAnb3JpZ2luYWwnOyBtZXNzYWdlOiBQcm9ncmVzc01lc3NhZ2U8QWdlbnRUb29sUHJvZ3Jlc3M+IH1cbiAgfCBTdW1tYXJ5TWVzc2FnZVxuXG4vKipcbiAqIFByb2Nlc3MgcHJvZ3Jlc3MgbWVzc2FnZXMgdG8gZ3JvdXAgY29uc2VjdXRpdmUgc2VhcmNoL3JlYWQgb3BlcmF0aW9ucyBpbnRvIHN1bW1hcmllcy5cbiAqIEZvciBhbnRzIG9ubHkgLSByZXR1cm5zIG9yaWdpbmFsIG1lc3NhZ2VzIGZvciBub24tYW50cy5cbiAqIEBwYXJhbSBpc0FnZW50UnVubmluZyAtIElmIHRydWUsIHRoZSBsYXN0IGdyb3VwIGlzIGFsd2F5cyBtYXJrZWQgYXMgYWN0aXZlIChpbiBwcm9ncmVzcylcbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1Byb2dyZXNzTWVzc2FnZXMoXG4gIG1lc3NhZ2VzOiBQcm9ncmVzc01lc3NhZ2U8UHJvZ3Jlc3M+W10sXG4gIHRvb2xzOiBUb29scyxcbiAgaXNBZ2VudFJ1bm5pbmc6IGJvb2xlYW4sXG4pOiBQcm9jZXNzZWRNZXNzYWdlW10ge1xuICAvLyBPbmx5IHByb2Nlc3MgZm9yIGFudHNcbiAgaWYgKFwiZXh0ZXJuYWxcIiAhPT0gJ2FudCcpIHtcbiAgICByZXR1cm4gbWVzc2FnZXNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChtKTogbSBpcyBQcm9ncmVzc01lc3NhZ2U8QWdlbnRUb29sUHJvZ3Jlc3M+ID0+XG4gICAgICAgICAgaGFzUHJvZ3Jlc3NNZXNzYWdlKG0uZGF0YSkgJiYgbS5kYXRhLm1lc3NhZ2UudHlwZSAhPT0gJ3VzZXInLFxuICAgICAgKVxuICAgICAgLm1hcChtID0+ICh7IHR5cGU6ICdvcmlnaW5hbCcsIG1lc3NhZ2U6IG0gfSkpXG4gIH1cblxuICBjb25zdCByZXN1bHQ6IFByb2Nlc3NlZE1lc3NhZ2VbXSA9IFtdXG4gIGxldCBjdXJyZW50R3JvdXA6IHtcbiAgICBzZWFyY2hDb3VudDogbnVtYmVyXG4gICAgcmVhZENvdW50OiBudW1iZXJcbiAgICByZXBsQ291bnQ6IG51bWJlclxuICAgIHN0YXJ0VXVpZDogc3RyaW5nXG4gIH0gfCBudWxsID0gbnVsbFxuXG4gIGZ1bmN0aW9uIGZsdXNoR3JvdXAoaXNBY3RpdmU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50R3JvdXAgJiZcbiAgICAgIChjdXJyZW50R3JvdXAuc2VhcmNoQ291bnQgPiAwIHx8XG4gICAgICAgIGN1cnJlbnRHcm91cC5yZWFkQ291bnQgPiAwIHx8XG4gICAgICAgIGN1cnJlbnRHcm91cC5yZXBsQ291bnQgPiAwKVxuICAgICkge1xuICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICB0eXBlOiAnc3VtbWFyeScsXG4gICAgICAgIHNlYXJjaENvdW50OiBjdXJyZW50R3JvdXAuc2VhcmNoQ291bnQsXG4gICAgICAgIHJlYWRDb3VudDogY3VycmVudEdyb3VwLnJlYWRDb3VudCxcbiAgICAgICAgcmVwbENvdW50OiBjdXJyZW50R3JvdXAucmVwbENvdW50LFxuICAgICAgICB1dWlkOiBgc3VtbWFyeS0ke2N1cnJlbnRHcm91cC5zdGFydFV1aWR9YCxcbiAgICAgICAgaXNBY3RpdmUsXG4gICAgICB9KVxuICAgIH1cbiAgICBjdXJyZW50R3JvdXAgPSBudWxsXG4gIH1cblxuICBjb25zdCBhZ2VudE1lc3NhZ2VzID0gbWVzc2FnZXMuZmlsdGVyKFxuICAgIChtKTogbSBpcyBQcm9ncmVzc01lc3NhZ2U8QWdlbnRUb29sUHJvZ3Jlc3M+ID0+IGhhc1Byb2dyZXNzTWVzc2FnZShtLmRhdGEpLFxuICApXG5cbiAgLy8gQnVpbGQgdG9vbF91c2UgbG9va3VwIGluY3JlbWVudGFsbHkgYXMgd2UgaXRlcmF0ZVxuICBjb25zdCB0b29sVXNlQnlJRCA9IG5ldyBNYXA8c3RyaW5nLCBUb29sVXNlQmxvY2tQYXJhbT4oKVxuICBmb3IgKGNvbnN0IG1zZyBvZiBhZ2VudE1lc3NhZ2VzKSB7XG4gICAgLy8gVHJhY2sgdG9vbF91c2UgYmxvY2tzIGFzIHdlIHNlZSB0aGVtXG4gICAgaWYgKG1zZy5kYXRhLm1lc3NhZ2UudHlwZSA9PT0gJ2Fzc2lzdGFudCcpIHtcbiAgICAgIGZvciAoY29uc3QgYyBvZiBtc2cuZGF0YS5tZXNzYWdlLm1lc3NhZ2UuY29udGVudCkge1xuICAgICAgICBpZiAoYy50eXBlID09PSAndG9vbF91c2UnKSB7XG4gICAgICAgICAgdG9vbFVzZUJ5SUQuc2V0KGMuaWQsIGMgYXMgVG9vbFVzZUJsb2NrUGFyYW0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaW5mbyA9IGdldFNlYXJjaE9yUmVhZEluZm8obXNnLCB0b29scywgdG9vbFVzZUJ5SUQpXG5cbiAgICBpZiAoaW5mbyAmJiAoaW5mby5pc1NlYXJjaCB8fCBpbmZvLmlzUmVhZCB8fCBpbmZvLmlzUkVQTCkpIHtcbiAgICAgIC8vIFRoaXMgaXMgYSBzZWFyY2gvcmVhZC9SRVBMIG9wZXJhdGlvbiAtIGFkZCB0byBjdXJyZW50IGdyb3VwXG4gICAgICBpZiAoIWN1cnJlbnRHcm91cCkge1xuICAgICAgICBjdXJyZW50R3JvdXAgPSB7XG4gICAgICAgICAgc2VhcmNoQ291bnQ6IDAsXG4gICAgICAgICAgcmVhZENvdW50OiAwLFxuICAgICAgICAgIHJlcGxDb3VudDogMCxcbiAgICAgICAgICBzdGFydFV1aWQ6IG1zZy51dWlkLFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBPbmx5IGNvdW50IHRvb2xfcmVzdWx0IG1lc3NhZ2VzIChub3QgdG9vbF91c2UpIHRvIGF2b2lkIGRvdWJsZSBjb3VudGluZ1xuICAgICAgaWYgKG1zZy5kYXRhLm1lc3NhZ2UudHlwZSA9PT0gJ3VzZXInKSB7XG4gICAgICAgIGlmIChpbmZvLmlzU2VhcmNoKSB7XG4gICAgICAgICAgY3VycmVudEdyb3VwLnNlYXJjaENvdW50KytcbiAgICAgICAgfSBlbHNlIGlmIChpbmZvLmlzUkVQTCkge1xuICAgICAgICAgIGN1cnJlbnRHcm91cC5yZXBsQ291bnQrK1xuICAgICAgICB9IGVsc2UgaWYgKGluZm8uaXNSZWFkKSB7XG4gICAgICAgICAgY3VycmVudEdyb3VwLnJlYWRDb3VudCsrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gTm9uLXNlYXJjaC9yZWFkL1JFUEwgbWVzc2FnZSAtIGZsdXNoIGN1cnJlbnQgZ3JvdXAgKGNvbXBsZXRlZCkgYW5kIGFkZCB0aGlzIG1lc3NhZ2VcbiAgICAgIGZsdXNoR3JvdXAoZmFsc2UpXG4gICAgICAvLyBTa2lwIHVzZXIgdG9vbF9yZXN1bHQgbWVzc2FnZXMg4oCUIHN1YmFnZW50IHByb2dyZXNzIG1lc3NhZ2VzIGxhY2tcbiAgICAgIC8vIHRvb2xVc2VSZXN1bHQsIHNvIFVzZXJUb29sU3VjY2Vzc01lc3NhZ2UgcmV0dXJucyBudWxsIGFuZCB0aGVcbiAgICAgIC8vIGhlaWdodD0xIEJveCBpbiByZW5kZXJUb29sVXNlUHJvZ3Jlc3NNZXNzYWdlIHNob3dzIGFzIGEgYmxhbmsgbGluZS5cbiAgICAgIGlmIChtc2cuZGF0YS5tZXNzYWdlLnR5cGUgIT09ICd1c2VyJykge1xuICAgICAgICByZXN1bHQucHVzaCh7IHR5cGU6ICdvcmlnaW5hbCcsIG1lc3NhZ2U6IG1zZyB9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIEZsdXNoIGFueSByZW1haW5pbmcgZ3JvdXAgLSBpdCdzIGFjdGl2ZSBpZiB0aGUgYWdlbnQgaXMgc3RpbGwgcnVubmluZ1xuICBmbHVzaEdyb3VwKGlzQWdlbnRSdW5uaW5nKVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxuY29uc3QgRVNUSU1BVEVEX0xJTkVTX1BFUl9UT09MID0gOVxuY29uc3QgVEVSTUlOQUxfQlVGRkVSX0xJTkVTID0gN1xuXG50eXBlIE91dHB1dCA9IHouaW5wdXQ8UmV0dXJuVHlwZTx0eXBlb2Ygb3V0cHV0U2NoZW1hPj5cblxuZXhwb3J0IGZ1bmN0aW9uIEFnZW50UHJvbXB0RGlzcGxheSh7XG4gIHByb21wdCxcbiAgZGltOiBfZGltID0gZmFsc2UsXG59OiB7XG4gIHByb21wdDogc3RyaW5nXG4gIHRoZW1lPzogVGhlbWVOYW1lIC8vIGRlcHJlY2F0ZWQsIGtlcHQgZm9yIGNvbXBhdGliaWxpdHkgLSBNYXJrZG93biB1c2VzIHVzZVRoZW1lIGludGVybmFsbHlcbiAgZGltPzogYm9vbGVhbiAvLyBkZXByZWNhdGVkLCBrZXB0IGZvciBjb21wYXRpYmlsaXR5IC0gZGltQ29sb3IgY2Fubm90IGJlIGFwcGxpZWQgdG8gQm94IChNYXJrZG93biByZXR1cm5zIEJveClcbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgPFRleHQgY29sb3I9XCJzdWNjZXNzXCIgYm9sZD5cbiAgICAgICAgUHJvbXB0OlxuICAgICAgPC9UZXh0PlxuICAgICAgPEJveCBwYWRkaW5nTGVmdD17Mn0+XG4gICAgICAgIDxNYXJrZG93bj57cHJvbXB0fTwvTWFya2Rvd24+XG4gICAgICA8L0JveD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gQWdlbnRSZXNwb25zZURpc3BsYXkoe1xuICBjb250ZW50LFxufToge1xuICBjb250ZW50OiB7IHR5cGU6IHN0cmluZzsgdGV4dDogc3RyaW5nIH1bXVxuICB0aGVtZT86IFRoZW1lTmFtZSAvLyBkZXByZWNhdGVkLCBrZXB0IGZvciBjb21wYXRpYmlsaXR5IC0gTWFya2Rvd24gdXNlcyB1c2VUaGVtZSBpbnRlcm5hbGx5XG59KTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgcmV0dXJuIChcbiAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgIDxUZXh0IGNvbG9yPVwic3VjY2Vzc1wiIGJvbGQ+XG4gICAgICAgIFJlc3BvbnNlOlxuICAgICAgPC9UZXh0PlxuICAgICAge2NvbnRlbnQubWFwKChibG9jazogeyB0eXBlOiBzdHJpbmc7IHRleHQ6IHN0cmluZyB9LCBpbmRleDogbnVtYmVyKSA9PiAoXG4gICAgICAgIDxCb3gga2V5PXtpbmRleH0gcGFkZGluZ0xlZnQ9ezJ9IG1hcmdpblRvcD17aW5kZXggPT09IDAgPyAwIDogMX0+XG4gICAgICAgICAgPE1hcmtkb3duPntibG9jay50ZXh0fTwvTWFya2Rvd24+XG4gICAgICAgIDwvQm94PlxuICAgICAgKSl9XG4gICAgPC9Cb3g+XG4gIClcbn1cblxudHlwZSBWZXJib3NlQWdlbnRUcmFuc2NyaXB0UHJvcHMgPSB7XG4gIHByb2dyZXNzTWVzc2FnZXM6IFByb2dyZXNzTWVzc2FnZTxQcm9ncmVzcz5bXVxuICB0b29sczogVG9vbHNcbiAgdmVyYm9zZTogYm9vbGVhblxufVxuXG5mdW5jdGlvbiBWZXJib3NlQWdlbnRUcmFuc2NyaXB0KHtcbiAgcHJvZ3Jlc3NNZXNzYWdlcyxcbiAgdG9vbHMsXG4gIHZlcmJvc2UsXG59OiBWZXJib3NlQWdlbnRUcmFuc2NyaXB0UHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCB7IGxvb2t1cHM6IGFnZW50TG9va3VwcywgaW5Qcm9ncmVzc1Rvb2xVc2VJRHMgfSA9IGJ1aWxkU3ViYWdlbnRMb29rdXBzKFxuICAgIHByb2dyZXNzTWVzc2FnZXNcbiAgICAgIC5maWx0ZXIoKHBtKTogcG0gaXMgUHJvZ3Jlc3NNZXNzYWdlPEFnZW50VG9vbFByb2dyZXNzPiA9PlxuICAgICAgICBoYXNQcm9ncmVzc01lc3NhZ2UocG0uZGF0YSksXG4gICAgICApXG4gICAgICAubWFwKHBtID0+IHBtLmRhdGEpLFxuICApXG5cbiAgLy8gRmlsdGVyIG91dCB1c2VyIHRvb2xfcmVzdWx0IG1lc3NhZ2VzIHRoYXQgbGFjayB0b29sVXNlUmVzdWx0LlxuICAvLyBTdWJhZ2VudCBwcm9ncmVzcyBtZXNzYWdlcyBkb24ndCBjYXJyeSB0aGUgcGFyc2VkIHRvb2wgb3V0cHV0LFxuICAvLyBzbyBVc2VyVG9vbFN1Y2Nlc3NNZXNzYWdlIHJldHVybnMgbnVsbCBhbmQgTWVzc2FnZVJlc3BvbnNlIHJlbmRlcnNcbiAgLy8gYSBiYXJlIOKOvyB3aXRoIG5vIGNvbnRlbnQuXG4gIGNvbnN0IGZpbHRlcmVkTWVzc2FnZXMgPSBwcm9ncmVzc01lc3NhZ2VzLmZpbHRlcihcbiAgICAocG0pOiBwbSBpcyBQcm9ncmVzc01lc3NhZ2U8QWdlbnRUb29sUHJvZ3Jlc3M+ID0+IHtcbiAgICAgIGlmICghaGFzUHJvZ3Jlc3NNZXNzYWdlKHBtLmRhdGEpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgICAgY29uc3QgbXNnID0gcG0uZGF0YS5tZXNzYWdlXG4gICAgICBpZiAobXNnLnR5cGUgPT09ICd1c2VyJyAmJiBtc2cudG9vbFVzZVJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9LFxuICApXG5cbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAge2ZpbHRlcmVkTWVzc2FnZXMubWFwKHByb2dyZXNzTWVzc2FnZSA9PiAoXG4gICAgICAgIDxNZXNzYWdlUmVzcG9uc2Uga2V5PXtwcm9ncmVzc01lc3NhZ2UudXVpZH0gaGVpZ2h0PXsxfT5cbiAgICAgICAgICA8TWVzc2FnZUNvbXBvbmVudFxuICAgICAgICAgICAgbWVzc2FnZT17cHJvZ3Jlc3NNZXNzYWdlLmRhdGEubWVzc2FnZX1cbiAgICAgICAgICAgIGxvb2t1cHM9e2FnZW50TG9va3Vwc31cbiAgICAgICAgICAgIGFkZE1hcmdpbj17ZmFsc2V9XG4gICAgICAgICAgICB0b29scz17dG9vbHN9XG4gICAgICAgICAgICBjb21tYW5kcz17W119XG4gICAgICAgICAgICB2ZXJib3NlPXt2ZXJib3NlfVxuICAgICAgICAgICAgaW5Qcm9ncmVzc1Rvb2xVc2VJRHM9e2luUHJvZ3Jlc3NUb29sVXNlSURzfVxuICAgICAgICAgICAgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2U9e1tdfVxuICAgICAgICAgICAgc2hvdWxkQW5pbWF0ZT17ZmFsc2V9XG4gICAgICAgICAgICBzaG91bGRTaG93RG90PXtmYWxzZX1cbiAgICAgICAgICAgIGlzVHJhbnNjcmlwdE1vZGU9e2ZhbHNlfVxuICAgICAgICAgICAgaXNTdGF0aWM9e3RydWV9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgICApKX1cbiAgICA8Lz5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2UoXG4gIGRhdGE6IE91dHB1dCxcbiAgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2U6IFByb2dyZXNzTWVzc2FnZTxQcm9ncmVzcz5bXSxcbiAge1xuICAgIHRvb2xzLFxuICAgIHZlcmJvc2UsXG4gICAgdGhlbWUsXG4gICAgaXNUcmFuc2NyaXB0TW9kZSA9IGZhbHNlLFxuICB9OiB7XG4gICAgdG9vbHM6IFRvb2xzXG4gICAgdmVyYm9zZTogYm9vbGVhblxuICAgIHRoZW1lOiBUaGVtZU5hbWVcbiAgICBpc1RyYW5zY3JpcHRNb2RlPzogYm9vbGVhblxuICB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgLy8gUmVtb3RlLWxhdW5jaGVkIGFnZW50cyAoYW50LW9ubHkpIHVzZSBhIHByaXZhdGUgb3V0cHV0IHR5cGUgbm90IGluIHRoZVxuICAvLyBwdWJsaWMgc2NoZW1hLiBOYXJyb3cgdmlhIHRoZSBpbnRlcm5hbCBkaXNjcmltaW5hbnQuXG4gIGNvbnN0IGludGVybmFsID0gZGF0YSBhcyBPdXRwdXQgfCBSZW1vdGVMYXVuY2hlZE91dHB1dFxuICBpZiAoaW50ZXJuYWwuc3RhdHVzID09PSAncmVtb3RlX2xhdW5jaGVkJykge1xuICAgIHJldHVybiAoXG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgUmVtb3RlIGFnZW50IGxhdW5jaGVkeycgJ31cbiAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICDCtyB7aW50ZXJuYWwudGFza0lkfSDCtyB7aW50ZXJuYWwuc2Vzc2lvblVybH1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgPC9Cb3g+XG4gICAgKVxuICB9XG4gIGlmIChkYXRhLnN0YXR1cyA9PT0gJ2FzeW5jX2xhdW5jaGVkJykge1xuICAgIGNvbnN0IHsgcHJvbXB0IH0gPSBkYXRhXG4gICAgcmV0dXJuIChcbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICAgICAgPFRleHQ+XG4gICAgICAgICAgICBCYWNrZ3JvdW5kZWQgYWdlbnRcbiAgICAgICAgICAgIHshaXNUcmFuc2NyaXB0TW9kZSAmJiAoXG4gICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICAgIHsnICgnfVxuICAgICAgICAgICAgICAgIDxCeWxpbmU+XG4gICAgICAgICAgICAgICAgICA8S2V5Ym9hcmRTaG9ydGN1dEhpbnQgc2hvcnRjdXQ9XCLihpNcIiBhY3Rpb249XCJtYW5hZ2VcIiAvPlxuICAgICAgICAgICAgICAgICAge3Byb21wdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgICAgICAgICAgICBhY3Rpb249XCJhcHA6dG9nZ2xlVHJhbnNjcmlwdFwiXG4gICAgICAgICAgICAgICAgICAgICAgY29udGV4dD1cIkdsb2JhbFwiXG4gICAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2s9XCJjdHJsK29cIlxuICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uPVwiZXhwYW5kXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgPC9CeWxpbmU+XG4gICAgICAgICAgICAgICAgeycpJ31cbiAgICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgKX1cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICB7aXNUcmFuc2NyaXB0TW9kZSAmJiBwcm9tcHQgJiYgKFxuICAgICAgICAgIDxNZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgICAgICA8QWdlbnRQcm9tcHREaXNwbGF5IHByb21wdD17cHJvbXB0fSB0aGVtZT17dGhlbWV9IC8+XG4gICAgICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgICl9XG4gICAgICA8L0JveD5cbiAgICApXG4gIH1cblxuICBpZiAoZGF0YS5zdGF0dXMgIT09ICdjb21wbGV0ZWQnKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGNvbnN0IHtcbiAgICBhZ2VudElkLFxuICAgIHRvdGFsRHVyYXRpb25NcyxcbiAgICB0b3RhbFRvb2xVc2VDb3VudCxcbiAgICB0b3RhbFRva2VucyxcbiAgICB1c2FnZSxcbiAgICBjb250ZW50LFxuICAgIHByb21wdCxcbiAgfSA9IGRhdGFcbiAgY29uc3QgcmVzdWx0ID0gW1xuICAgIHRvdGFsVG9vbFVzZUNvdW50ID09PSAxID8gJzEgdG9vbCB1c2UnIDogYCR7dG90YWxUb29sVXNlQ291bnR9IHRvb2wgdXNlc2AsXG4gICAgZm9ybWF0TnVtYmVyKHRvdGFsVG9rZW5zKSArICcgdG9rZW5zJyxcbiAgICBmb3JtYXREdXJhdGlvbih0b3RhbER1cmF0aW9uTXMpLFxuICBdXG5cbiAgY29uc3QgY29tcGxldGlvbk1lc3NhZ2UgPSBgRG9uZSAoJHtyZXN1bHQuam9pbignIMK3ICcpfSlgXG5cbiAgY29uc3QgZmluYWxBc3Npc3RhbnRNZXNzYWdlID0gY3JlYXRlQXNzaXN0YW50TWVzc2FnZSh7XG4gICAgY29udGVudDogY29tcGxldGlvbk1lc3NhZ2UsXG4gICAgdXNhZ2U6IHsgLi4udXNhZ2UsIGluZmVyZW5jZV9nZW86IG51bGwsIGl0ZXJhdGlvbnM6IG51bGwsIHNwZWVkOiBudWxsIH0sXG4gIH0pXG5cbiAgcmV0dXJuIChcbiAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgIHtcImV4dGVybmFsXCIgPT09ICdhbnQnICYmIChcbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgICAgICA8VGV4dCBjb2xvcj1cIndhcm5pbmdcIj5cbiAgICAgICAgICAgIFtBTlQtT05MWV0gQVBJIGNhbGxzOiB7Z2V0RGlzcGxheVBhdGgoZ2V0RHVtcFByb21wdHNQYXRoKGFnZW50SWQpKX1cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgKX1cbiAgICAgIHtpc1RyYW5zY3JpcHRNb2RlICYmIHByb21wdCAmJiAoXG4gICAgICAgIDxNZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgICAgPEFnZW50UHJvbXB0RGlzcGxheSBwcm9tcHQ9e3Byb21wdH0gdGhlbWU9e3RoZW1lfSAvPlxuICAgICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICAgICl9XG4gICAgICB7aXNUcmFuc2NyaXB0TW9kZSA/IChcbiAgICAgICAgPFN1YkFnZW50UHJvdmlkZXI+XG4gICAgICAgICAgPFZlcmJvc2VBZ2VudFRyYW5zY3JpcHRcbiAgICAgICAgICAgIHByb2dyZXNzTWVzc2FnZXM9e3Byb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlfVxuICAgICAgICAgICAgdG9vbHM9e3Rvb2xzfVxuICAgICAgICAgICAgdmVyYm9zZT17dmVyYm9zZX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L1N1YkFnZW50UHJvdmlkZXI+XG4gICAgICApIDogbnVsbH1cbiAgICAgIHtpc1RyYW5zY3JpcHRNb2RlICYmIGNvbnRlbnQgJiYgY29udGVudC5sZW5ndGggPiAwICYmIChcbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgICAgICA8QWdlbnRSZXNwb25zZURpc3BsYXkgY29udGVudD17Y29udGVudH0gdGhlbWU9e3RoZW1lfSAvPlxuICAgICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICAgICl9XG4gICAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICAgIDxNZXNzYWdlQ29tcG9uZW50XG4gICAgICAgICAgbWVzc2FnZT17ZmluYWxBc3Npc3RhbnRNZXNzYWdlfVxuICAgICAgICAgIGxvb2t1cHM9e0VNUFRZX0xPT0tVUFN9XG4gICAgICAgICAgYWRkTWFyZ2luPXtmYWxzZX1cbiAgICAgICAgICB0b29scz17dG9vbHN9XG4gICAgICAgICAgY29tbWFuZHM9e1tdfVxuICAgICAgICAgIHZlcmJvc2U9e3ZlcmJvc2V9XG4gICAgICAgICAgaW5Qcm9ncmVzc1Rvb2xVc2VJRHM9e25ldyBTZXQoKX1cbiAgICAgICAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZT17W119XG4gICAgICAgICAgc2hvdWxkQW5pbWF0ZT17ZmFsc2V9XG4gICAgICAgICAgc2hvdWxkU2hvd0RvdD17ZmFsc2V9XG4gICAgICAgICAgaXNUcmFuc2NyaXB0TW9kZT17ZmFsc2V9XG4gICAgICAgICAgaXNTdGF0aWM9e3RydWV9XG4gICAgICAgIC8+XG4gICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICAgIHshaXNUcmFuc2NyaXB0TW9kZSAmJiAoXG4gICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgIHsnICAnfVxuICAgICAgICAgIDxDdHJsT1RvRXhwYW5kIC8+XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICl9XG4gICAgPC9Cb3g+XG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclRvb2xVc2VNZXNzYWdlKHtcbiAgZGVzY3JpcHRpb24sXG4gIHByb21wdCxcbn06IFBhcnRpYWw8e1xuICBkZXNjcmlwdGlvbjogc3RyaW5nXG4gIHByb21wdDogc3RyaW5nXG59Pik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGlmICghZGVzY3JpcHRpb24gfHwgIXByb21wdCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgcmV0dXJuIGRlc2NyaXB0aW9uXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlVGFnKFxuICBpbnB1dDogUGFydGlhbDx7XG4gICAgZGVzY3JpcHRpb246IHN0cmluZ1xuICAgIHByb21wdDogc3RyaW5nXG4gICAgc3ViYWdlbnRfdHlwZTogc3RyaW5nXG4gICAgbW9kZWw/OiBNb2RlbEFsaWFzXG4gIH0+LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3QgdGFnczogUmVhY3QuUmVhY3ROb2RlW10gPSBbXVxuXG4gIGlmIChpbnB1dC5tb2RlbCkge1xuICAgIGNvbnN0IG1haW5Nb2RlbCA9IGdldE1haW5Mb29wTW9kZWwoKVxuICAgIGNvbnN0IGFnZW50TW9kZWwgPSBwYXJzZVVzZXJTcGVjaWZpZWRNb2RlbChpbnB1dC5tb2RlbClcbiAgICBpZiAoYWdlbnRNb2RlbCAhPT0gbWFpbk1vZGVsKSB7XG4gICAgICB0YWdzLnB1c2goXG4gICAgICAgIDxCb3gga2V5PVwibW9kZWxcIiBmbGV4V3JhcD1cIm5vd3JhcFwiIG1hcmdpbkxlZnQ9ezF9PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPntyZW5kZXJNb2RlbE5hbWUoYWdlbnRNb2RlbCl9PC9UZXh0PlxuICAgICAgICA8L0JveD4sXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgaWYgKHRhZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHJldHVybiA8Pnt0YWdzfTwvPlxufVxuXG5jb25zdCBJTklUSUFMSVpJTkdfVEVYVCA9ICdJbml0aWFsaXppbmfigKYnXG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlUHJvZ3Jlc3NNZXNzYWdlKFxuICBwcm9ncmVzc01lc3NhZ2VzOiBQcm9ncmVzc01lc3NhZ2U8UHJvZ3Jlc3M+W10sXG4gIHtcbiAgICB0b29scyxcbiAgICB2ZXJib3NlLFxuICAgIHRlcm1pbmFsU2l6ZSxcbiAgICBpblByb2dyZXNzVG9vbENhbGxDb3VudCxcbiAgICBpc1RyYW5zY3JpcHRNb2RlID0gZmFsc2UsXG4gIH06IHtcbiAgICB0b29sczogVG9vbHNcbiAgICB2ZXJib3NlOiBib29sZWFuXG4gICAgdGVybWluYWxTaXplPzogeyBjb2x1bW5zOiBudW1iZXI7IHJvd3M6IG51bWJlciB9XG4gICAgaW5Qcm9ncmVzc1Rvb2xDYWxsQ291bnQ/OiBudW1iZXJcbiAgICBpc1RyYW5zY3JpcHRNb2RlPzogYm9vbGVhblxuICB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgaWYgKCFwcm9ncmVzc01lc3NhZ2VzLmxlbmd0aCkge1xuICAgIHJldHVybiAoXG4gICAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICAgIDxUZXh0IGRpbUNvbG9yPntJTklUSUFMSVpJTkdfVEVYVH08L1RleHQ+XG4gICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICApXG4gIH1cblxuICAvLyBDaGVja3MgdG8gc2VlIGlmIHdlIHNob3VsZCBzaG93IGEgc3VwZXIgY29uZGVuc2VkIHByb2dyZXNzIG1lc3NhZ2Ugc3VtbWFyeS5cbiAgLy8gVGhpcyBwcmV2ZW50cyBmbGlja2VycyB3aGVuIHRoZSB0ZXJtaW5hbCBzaXplIGlzIHRvbyBzbWFsbCB0byByZW5kZXIgYWxsIHRoZSBkeW5hbWljIGNvbnRlbnRcbiAgY29uc3QgdG9vbFRvb2xSZW5kZXJMaW5lc0VzdGltYXRlID1cbiAgICAoaW5Qcm9ncmVzc1Rvb2xDYWxsQ291bnQgPz8gMSkgKiBFU1RJTUFURURfTElORVNfUEVSX1RPT0wgK1xuICAgIFRFUk1JTkFMX0JVRkZFUl9MSU5FU1xuICBjb25zdCBzaG91bGRVc2VDb25kZW5zZWRNb2RlID1cbiAgICAhaXNUcmFuc2NyaXB0TW9kZSAmJlxuICAgIHRlcm1pbmFsU2l6ZSAmJlxuICAgIHRlcm1pbmFsU2l6ZS5yb3dzICYmXG4gICAgdGVybWluYWxTaXplLnJvd3MgPCB0b29sVG9vbFJlbmRlckxpbmVzRXN0aW1hdGVcblxuICBjb25zdCBnZXRQcm9ncmVzc1N0YXRzID0gKCkgPT4ge1xuICAgIGNvbnN0IHRvb2xVc2VDb3VudCA9IGNvdW50KHByb2dyZXNzTWVzc2FnZXMsIG1zZyA9PiB7XG4gICAgICBpZiAoIWhhc1Byb2dyZXNzTWVzc2FnZShtc2cuZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlID0gbXNnLmRhdGEubWVzc2FnZVxuICAgICAgcmV0dXJuIG1lc3NhZ2UubWVzc2FnZS5jb250ZW50LnNvbWUoXG4gICAgICAgIGNvbnRlbnQgPT4gY29udGVudC50eXBlID09PSAndG9vbF91c2UnLFxuICAgICAgKVxuICAgIH0pXG5cbiAgICBjb25zdCBsYXRlc3RBc3Npc3RhbnQgPSBwcm9ncmVzc01lc3NhZ2VzLmZpbmRMYXN0KFxuICAgICAgKG1zZyk6IG1zZyBpcyBQcm9ncmVzc01lc3NhZ2U8QWdlbnRUb29sUHJvZ3Jlc3M+ID0+XG4gICAgICAgIGhhc1Byb2dyZXNzTWVzc2FnZShtc2cuZGF0YSkgJiYgbXNnLmRhdGEubWVzc2FnZS50eXBlID09PSAnYXNzaXN0YW50JyxcbiAgICApXG5cbiAgICBsZXQgdG9rZW5zID0gbnVsbFxuICAgIGlmIChsYXRlc3RBc3Npc3RhbnQ/LmRhdGEubWVzc2FnZS50eXBlID09PSAnYXNzaXN0YW50Jykge1xuICAgICAgY29uc3QgdXNhZ2UgPSBsYXRlc3RBc3Npc3RhbnQuZGF0YS5tZXNzYWdlLm1lc3NhZ2UudXNhZ2VcbiAgICAgIHRva2VucyA9XG4gICAgICAgICh1c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMgPz8gMCkgK1xuICAgICAgICAodXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMgPz8gMCkgK1xuICAgICAgICB1c2FnZS5pbnB1dF90b2tlbnMgK1xuICAgICAgICB1c2FnZS5vdXRwdXRfdG9rZW5zXG4gICAgfVxuXG4gICAgcmV0dXJuIHsgdG9vbFVzZUNvdW50LCB0b2tlbnMgfVxuICB9XG5cbiAgaWYgKHNob3VsZFVzZUNvbmRlbnNlZE1vZGUpIHtcbiAgICBjb25zdCB7IHRvb2xVc2VDb3VudCwgdG9rZW5zIH0gPSBnZXRQcm9ncmVzc1N0YXRzKClcblxuICAgIHJldHVybiAoXG4gICAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgIEluIHByb2dyZXNz4oCmIMK3IDxUZXh0IGJvbGQ+e3Rvb2xVc2VDb3VudH08L1RleHQ+IHRvb2x7JyAnfVxuICAgICAgICAgIHt0b29sVXNlQ291bnQgPT09IDEgPyAndXNlJyA6ICd1c2VzJ31cbiAgICAgICAgICB7dG9rZW5zICYmIGAgwrcgJHtmb3JtYXROdW1iZXIodG9rZW5zKX0gdG9rZW5zYH0gwrd7JyAnfVxuICAgICAgICAgIDxDb25maWd1cmFibGVTaG9ydGN1dEhpbnRcbiAgICAgICAgICAgIGFjdGlvbj1cImFwcDp0b2dnbGVUcmFuc2NyaXB0XCJcbiAgICAgICAgICAgIGNvbnRleHQ9XCJHbG9iYWxcIlxuICAgICAgICAgICAgZmFsbGJhY2s9XCJjdHJsK29cIlxuICAgICAgICAgICAgZGVzY3JpcHRpb249XCJleHBhbmRcIlxuICAgICAgICAgICAgcGFyZW5zXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9UZXh0PlxuICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgKVxuICB9XG5cbiAgLy8gUHJvY2VzcyBtZXNzYWdlcyB0byBncm91cCBjb25zZWN1dGl2ZSBzZWFyY2gvcmVhZCBvcGVyYXRpb25zIGludG8gc3VtbWFyaWVzIChhbnRzIG9ubHkpXG4gIC8vIGlzQWdlbnRSdW5uaW5nPXRydWUgc2luY2UgdGhpcyBpcyB0aGUgcHJvZ3Jlc3MgdmlldyB3aGlsZSB0aGUgYWdlbnQgaXMgc3RpbGwgcnVubmluZ1xuICBjb25zdCBwcm9jZXNzZWRNZXNzYWdlcyA9IHByb2Nlc3NQcm9ncmVzc01lc3NhZ2VzKFxuICAgIHByb2dyZXNzTWVzc2FnZXMsXG4gICAgdG9vbHMsXG4gICAgdHJ1ZSxcbiAgKVxuXG4gIC8vIEZvciBkaXNwbGF5LCB0YWtlIHRoZSBsYXN0IGZldyBwcm9jZXNzZWQgbWVzc2FnZXNcbiAgY29uc3QgZGlzcGxheWVkTWVzc2FnZXMgPSBpc1RyYW5zY3JpcHRNb2RlXG4gICAgPyBwcm9jZXNzZWRNZXNzYWdlc1xuICAgIDogcHJvY2Vzc2VkTWVzc2FnZXMuc2xpY2UoLU1BWF9QUk9HUkVTU19NRVNTQUdFU19UT19TSE9XKVxuXG4gIC8vIENvdW50IGhpZGRlbiB0b29sIHVzZXMgc3BlY2lmaWNhbGx5IChub3QgYWxsIG1lc3NhZ2VzKSB0byBtYXRjaCB0aGVcbiAgLy8gZmluYWwgXCJEb25lIChOIHRvb2wgdXNlcylcIiBjb3VudC4gRWFjaCB0b29sIHVzZSBnZW5lcmF0ZXMgbXVsdGlwbGVcbiAgLy8gcHJvZ3Jlc3MgbWVzc2FnZXMgKHRvb2xfdXNlICsgdG9vbF9yZXN1bHQgKyB0ZXh0KSwgc28gY291bnRpbmcgYWxsXG4gIC8vIGhpZGRlbiBtZXNzYWdlcyBpbmZsYXRlcyB0aGUgbnVtYmVyIHNob3duIHRvIHRoZSB1c2VyLlxuICBjb25zdCBoaWRkZW5NZXNzYWdlcyA9IGlzVHJhbnNjcmlwdE1vZGVcbiAgICA/IFtdXG4gICAgOiBwcm9jZXNzZWRNZXNzYWdlcy5zbGljZShcbiAgICAgICAgMCxcbiAgICAgICAgTWF0aC5tYXgoMCwgcHJvY2Vzc2VkTWVzc2FnZXMubGVuZ3RoIC0gTUFYX1BST0dSRVNTX01FU1NBR0VTX1RPX1NIT1cpLFxuICAgICAgKVxuICBjb25zdCBoaWRkZW5Ub29sVXNlQ291bnQgPSBjb3VudChoaWRkZW5NZXNzYWdlcywgbSA9PiB7XG4gICAgaWYgKG0udHlwZSA9PT0gJ3N1bW1hcnknKSB7XG4gICAgICByZXR1cm4gbS5zZWFyY2hDb3VudCArIG0ucmVhZENvdW50ICsgbS5yZXBsQ291bnQgPiAwXG4gICAgfVxuICAgIGNvbnN0IGRhdGEgPSBtLm1lc3NhZ2UuZGF0YVxuICAgIGlmICghaGFzUHJvZ3Jlc3NNZXNzYWdlKGRhdGEpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgcmV0dXJuIGRhdGEubWVzc2FnZS5tZXNzYWdlLmNvbnRlbnQuc29tZShcbiAgICAgIGNvbnRlbnQgPT4gY29udGVudC50eXBlID09PSAndG9vbF91c2UnLFxuICAgIClcbiAgfSlcblxuICBjb25zdCBmaXJzdERhdGEgPSBwcm9ncmVzc01lc3NhZ2VzWzBdPy5kYXRhXG4gIGNvbnN0IHByb21wdCA9XG4gICAgZmlyc3REYXRhICYmIGhhc1Byb2dyZXNzTWVzc2FnZShmaXJzdERhdGEpID8gZmlyc3REYXRhLnByb21wdCA6IHVuZGVmaW5lZFxuXG4gIC8vIEFmdGVyIGdyb3VwaW5nLCBkaXNwbGF5ZWRNZXNzYWdlcyBjYW4gYmUgZW1wdHkgd2hlbiB0aGUgb25seSBwcm9ncmVzcyBzb1xuICAvLyBmYXIgaXMgYW4gYXNzaXN0YW50IHRvb2xfdXNlIGZvciBhIHNlYXJjaC9yZWFkIG9wIChncm91cGVkIGJ1dCBub3QgeWV0XG4gIC8vIGNvdW50ZWQsIHNpbmNlIGNvdW50cyBpbmNyZW1lbnQgb24gdG9vbF9yZXN1bHQpLiBGYWxsIGJhY2sgdG8gdGhlXG4gIC8vIGluaXRpYWxpemluZyB0ZXh0IHNvIE1lc3NhZ2VSZXNwb25zZSBkb2Vzbid0IHJlbmRlciBhIGJhcmUg4o6/LlxuICBpZiAoZGlzcGxheWVkTWVzc2FnZXMubGVuZ3RoID09PSAwICYmICEoaXNUcmFuc2NyaXB0TW9kZSAmJiBwcm9tcHQpKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxNZXNzYWdlUmVzcG9uc2UgaGVpZ2h0PXsxfT5cbiAgICAgICAgPFRleHQgZGltQ29sb3I+e0lOSVRJQUxJWklOR19URVhUfTwvVGV4dD5cbiAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgIClcbiAgfVxuXG4gIGNvbnN0IHtcbiAgICBsb29rdXBzOiBzdWJhZ2VudExvb2t1cHMsXG4gICAgaW5Qcm9ncmVzc1Rvb2xVc2VJRHM6IGNvbGxhcHNlZEluUHJvZ3Jlc3NJRHMsXG4gIH0gPSBidWlsZFN1YmFnZW50TG9va3VwcyhcbiAgICBwcm9ncmVzc01lc3NhZ2VzXG4gICAgICAuZmlsdGVyKChwbSk6IHBtIGlzIFByb2dyZXNzTWVzc2FnZTxBZ2VudFRvb2xQcm9ncmVzcz4gPT5cbiAgICAgICAgaGFzUHJvZ3Jlc3NNZXNzYWdlKHBtLmRhdGEpLFxuICAgICAgKVxuICAgICAgLm1hcChwbSA9PiBwbS5kYXRhKSxcbiAgKVxuXG4gIHJldHVybiAoXG4gICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8U3ViQWdlbnRQcm92aWRlcj5cbiAgICAgICAgICB7aXNUcmFuc2NyaXB0TW9kZSAmJiBwcm9tcHQgJiYgKFxuICAgICAgICAgICAgPEJveCBtYXJnaW5Cb3R0b209ezF9PlxuICAgICAgICAgICAgICA8QWdlbnRQcm9tcHREaXNwbGF5IHByb21wdD17cHJvbXB0fSAvPlxuICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgKX1cbiAgICAgICAgICB7ZGlzcGxheWVkTWVzc2FnZXMubWFwKHByb2Nlc3NlZCA9PiB7XG4gICAgICAgICAgICBpZiAocHJvY2Vzc2VkLnR5cGUgPT09ICdzdW1tYXJ5Jykge1xuICAgICAgICAgICAgICAvLyBSZW5kZXIgc3VtbWFyeSBmb3IgZ3JvdXBlZCBzZWFyY2gvcmVhZC9SRVBMIG9wZXJhdGlvbnMgdXNpbmcgc2hhcmVkIGZvcm1hdHRpbmdcbiAgICAgICAgICAgICAgY29uc3Qgc3VtbWFyeVRleHQgPSBnZXRTZWFyY2hSZWFkU3VtbWFyeVRleHQoXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkLnNlYXJjaENvdW50LFxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZC5yZWFkQ291bnQsXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkLmlzQWN0aXZlLFxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZC5yZXBsQ291bnQsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8Qm94IGtleT17cHJvY2Vzc2VkLnV1aWR9IGhlaWdodD17MX0gb3ZlcmZsb3c9XCJoaWRkZW5cIj5cbiAgICAgICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPntzdW1tYXJ5VGV4dH08L1RleHQ+XG4gICAgICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbmRlciBvcmlnaW5hbCBtZXNzYWdlIHdpdGhvdXQgaGVpZ2h0PTEgd3JhcHBlciBzbyBudWxsXG4gICAgICAgICAgICAvLyBjb250ZW50ICh0b29sIG5vdCBmb3VuZCwgcmVuZGVyVG9vbFVzZU1lc3NhZ2UgcmV0dXJucyBudWxsKVxuICAgICAgICAgICAgLy8gZG9lc24ndCBsZWF2ZSBhIGJsYW5rIGxpbmUuIFRvb2wgY2FsbCBoZWFkZXJzIGFyZSBzaW5nbGUtbGluZVxuICAgICAgICAgICAgLy8gYW55d2F5IHNvIHRydW5jYXRpb24gaXNuJ3QgbmVlZGVkLlxuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgPE1lc3NhZ2VDb21wb25lbnRcbiAgICAgICAgICAgICAgICBrZXk9e3Byb2Nlc3NlZC5tZXNzYWdlLnV1aWR9XG4gICAgICAgICAgICAgICAgbWVzc2FnZT17cHJvY2Vzc2VkLm1lc3NhZ2UuZGF0YS5tZXNzYWdlfVxuICAgICAgICAgICAgICAgIGxvb2t1cHM9e3N1YmFnZW50TG9va3Vwc31cbiAgICAgICAgICAgICAgICBhZGRNYXJnaW49e2ZhbHNlfVxuICAgICAgICAgICAgICAgIHRvb2xzPXt0b29sc31cbiAgICAgICAgICAgICAgICBjb21tYW5kcz17W119XG4gICAgICAgICAgICAgICAgdmVyYm9zZT17dmVyYm9zZX1cbiAgICAgICAgICAgICAgICBpblByb2dyZXNzVG9vbFVzZUlEcz17Y29sbGFwc2VkSW5Qcm9ncmVzc0lEc31cbiAgICAgICAgICAgICAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZT17W119XG4gICAgICAgICAgICAgICAgc2hvdWxkQW5pbWF0ZT17ZmFsc2V9XG4gICAgICAgICAgICAgICAgc2hvdWxkU2hvd0RvdD17ZmFsc2V9XG4gICAgICAgICAgICAgICAgc3R5bGU9XCJjb25kZW5zZWRcIlxuICAgICAgICAgICAgICAgIGlzVHJhbnNjcmlwdE1vZGU9e2ZhbHNlfVxuICAgICAgICAgICAgICAgIGlzU3RhdGljPXt0cnVlfVxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKVxuICAgICAgICAgIH0pfVxuICAgICAgICA8L1N1YkFnZW50UHJvdmlkZXI+XG4gICAgICAgIHtoaWRkZW5Ub29sVXNlQ291bnQgPiAwICYmIChcbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICAgICt7aGlkZGVuVG9vbFVzZUNvdW50fSBtb3JlIHRvb2x7JyAnfVxuICAgICAgICAgICAge2hpZGRlblRvb2xVc2VDb3VudCA9PT0gMSA/ICd1c2UnIDogJ3VzZXMnfSA8Q3RybE9Ub0V4cGFuZCAvPlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgKX1cbiAgICAgIDwvQm94PlxuICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlUmVqZWN0ZWRNZXNzYWdlKFxuICBfaW5wdXQ6IHsgZGVzY3JpcHRpb246IHN0cmluZzsgcHJvbXB0OiBzdHJpbmc7IHN1YmFnZW50X3R5cGU6IHN0cmluZyB9LFxuICB7XG4gICAgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UsXG4gICAgdG9vbHMsXG4gICAgdmVyYm9zZSxcbiAgICBpc1RyYW5zY3JpcHRNb2RlLFxuICB9OiB7XG4gICAgY29sdW1uczogbnVtYmVyXG4gICAgbWVzc2FnZXM6IE1lc3NhZ2VbXVxuICAgIHN0eWxlPzogJ2NvbmRlbnNlZCdcbiAgICB0aGVtZTogVGhlbWVOYW1lXG4gICAgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2U6IFByb2dyZXNzTWVzc2FnZTxQcm9ncmVzcz5bXVxuICAgIHRvb2xzOiBUb29sc1xuICAgIHZlcmJvc2U6IGJvb2xlYW5cbiAgICBpc1RyYW5zY3JpcHRNb2RlPzogYm9vbGVhblxuICB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgLy8gR2V0IGFnZW50SWQgZnJvbSBwcm9ncmVzcyBtZXNzYWdlcyBpZiBhdmFpbGFibGUgKGFnZW50IHdhcyBydW5uaW5nIGJlZm9yZSByZWplY3Rpb24pXG4gIGNvbnN0IGZpcnN0RGF0YSA9IHByb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlWzBdPy5kYXRhXG4gIGNvbnN0IGFnZW50SWQgPVxuICAgIGZpcnN0RGF0YSAmJiBoYXNQcm9ncmVzc01lc3NhZ2UoZmlyc3REYXRhKSA/IGZpcnN0RGF0YS5hZ2VudElkIDogdW5kZWZpbmVkXG5cbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAge1wiZXh0ZXJuYWxcIiA9PT0gJ2FudCcgJiYgYWdlbnRJZCAmJiAoXG4gICAgICAgIDxNZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgICAgPFRleHQgY29sb3I9XCJ3YXJuaW5nXCI+XG4gICAgICAgICAgICBbQU5ULU9OTFldIEFQSSBjYWxsczoge2dldERpc3BsYXlQYXRoKGdldER1bXBQcm9tcHRzUGF0aChhZ2VudElkKSl9XG4gICAgICAgICAgPC9UZXh0PlxuICAgICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICAgICl9XG4gICAgICB7cmVuZGVyVG9vbFVzZVByb2dyZXNzTWVzc2FnZShwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZSwge1xuICAgICAgICB0b29scyxcbiAgICAgICAgdmVyYm9zZSxcbiAgICAgICAgaXNUcmFuc2NyaXB0TW9kZSxcbiAgICAgIH0pfVxuICAgICAgPEZhbGxiYWNrVG9vbFVzZVJlamVjdGVkTWVzc2FnZSAvPlxuICAgIDwvPlxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlRXJyb3JNZXNzYWdlKFxuICByZXN1bHQ6IFRvb2xSZXN1bHRCbG9ja1BhcmFtWydjb250ZW50J10sXG4gIHtcbiAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZSxcbiAgICB0b29scyxcbiAgICB2ZXJib3NlLFxuICAgIGlzVHJhbnNjcmlwdE1vZGUsXG4gIH06IHtcbiAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZTogUHJvZ3Jlc3NNZXNzYWdlPFByb2dyZXNzPltdXG4gICAgdG9vbHM6IFRvb2xzXG4gICAgdmVyYm9zZTogYm9vbGVhblxuICAgIGlzVHJhbnNjcmlwdE1vZGU/OiBib29sZWFuXG4gIH0sXG4pOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICB7cmVuZGVyVG9vbFVzZVByb2dyZXNzTWVzc2FnZShwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZSwge1xuICAgICAgICB0b29scyxcbiAgICAgICAgdmVyYm9zZSxcbiAgICAgICAgaXNUcmFuc2NyaXB0TW9kZSxcbiAgICAgIH0pfVxuICAgICAgPEZhbGxiYWNrVG9vbFVzZUVycm9yTWVzc2FnZSByZXN1bHQ9e3Jlc3VsdH0gdmVyYm9zZT17dmVyYm9zZX0gLz5cbiAgICA8Lz5cbiAgKVxufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVBZ2VudFN0YXRzKHByb2dyZXNzTWVzc2FnZXM6IFByb2dyZXNzTWVzc2FnZTxQcm9ncmVzcz5bXSk6IHtcbiAgdG9vbFVzZUNvdW50OiBudW1iZXJcbiAgdG9rZW5zOiBudW1iZXIgfCBudWxsXG59IHtcbiAgY29uc3QgdG9vbFVzZUNvdW50ID0gY291bnQocHJvZ3Jlc3NNZXNzYWdlcywgbXNnID0+IHtcbiAgICBpZiAoIWhhc1Byb2dyZXNzTWVzc2FnZShtc2cuZGF0YSkpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBjb25zdCBtZXNzYWdlID0gbXNnLmRhdGEubWVzc2FnZVxuICAgIHJldHVybiAoXG4gICAgICBtZXNzYWdlLnR5cGUgPT09ICd1c2VyJyAmJlxuICAgICAgbWVzc2FnZS5tZXNzYWdlLmNvbnRlbnQuc29tZShjb250ZW50ID0+IGNvbnRlbnQudHlwZSA9PT0gJ3Rvb2xfcmVzdWx0JylcbiAgICApXG4gIH0pXG5cbiAgY29uc3QgbGF0ZXN0QXNzaXN0YW50ID0gcHJvZ3Jlc3NNZXNzYWdlcy5maW5kTGFzdChcbiAgICAobXNnKTogbXNnIGlzIFByb2dyZXNzTWVzc2FnZTxBZ2VudFRvb2xQcm9ncmVzcz4gPT5cbiAgICAgIGhhc1Byb2dyZXNzTWVzc2FnZShtc2cuZGF0YSkgJiYgbXNnLmRhdGEubWVzc2FnZS50eXBlID09PSAnYXNzaXN0YW50JyxcbiAgKVxuXG4gIGxldCB0b2tlbnMgPSBudWxsXG4gIGlmIChsYXRlc3RBc3Npc3RhbnQ/LmRhdGEubWVzc2FnZS50eXBlID09PSAnYXNzaXN0YW50Jykge1xuICAgIGNvbnN0IHVzYWdlID0gbGF0ZXN0QXNzaXN0YW50LmRhdGEubWVzc2FnZS5tZXNzYWdlLnVzYWdlXG4gICAgdG9rZW5zID1cbiAgICAgICh1c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMgPz8gMCkgK1xuICAgICAgKHVzYWdlLmNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zID8/IDApICtcbiAgICAgIHVzYWdlLmlucHV0X3Rva2VucyArXG4gICAgICB1c2FnZS5vdXRwdXRfdG9rZW5zXG4gIH1cblxuICByZXR1cm4geyB0b29sVXNlQ291bnQsIHRva2VucyB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJHcm91cGVkQWdlbnRUb29sVXNlKFxuICB0b29sVXNlczogQXJyYXk8e1xuICAgIHBhcmFtOiBUb29sVXNlQmxvY2tQYXJhbVxuICAgIGlzUmVzb2x2ZWQ6IGJvb2xlYW5cbiAgICBpc0Vycm9yOiBib29sZWFuXG4gICAgaXNJblByb2dyZXNzOiBib29sZWFuXG4gICAgcHJvZ3Jlc3NNZXNzYWdlczogUHJvZ3Jlc3NNZXNzYWdlPFByb2dyZXNzPltdXG4gICAgcmVzdWx0Pzoge1xuICAgICAgcGFyYW06IFRvb2xSZXN1bHRCbG9ja1BhcmFtXG4gICAgICBvdXRwdXQ6IE91dHB1dFxuICAgIH1cbiAgfT4sXG4gIG9wdGlvbnM6IHtcbiAgICBzaG91bGRBbmltYXRlOiBib29sZWFuXG4gICAgdG9vbHM6IFRvb2xzXG4gIH0sXG4pOiBSZWFjdC5SZWFjdE5vZGUgfCBudWxsIHtcbiAgY29uc3QgeyBzaG91bGRBbmltYXRlLCB0b29scyB9ID0gb3B0aW9uc1xuXG4gIC8vIENhbGN1bGF0ZSBzdGF0cyBmb3IgZWFjaCBhZ2VudFxuICBjb25zdCBhZ2VudFN0YXRzID0gdG9vbFVzZXMubWFwKFxuICAgICh7IHBhcmFtLCBpc1Jlc29sdmVkLCBpc0Vycm9yLCBwcm9ncmVzc01lc3NhZ2VzLCByZXN1bHQgfSkgPT4ge1xuICAgICAgY29uc3Qgc3RhdHMgPSBjYWxjdWxhdGVBZ2VudFN0YXRzKHByb2dyZXNzTWVzc2FnZXMpXG4gICAgICBjb25zdCBsYXN0VG9vbEluZm8gPSBleHRyYWN0TGFzdFRvb2xJbmZvKHByb2dyZXNzTWVzc2FnZXMsIHRvb2xzKVxuICAgICAgY29uc3QgcGFyc2VkSW5wdXQgPSBpbnB1dFNjaGVtYSgpLnNhZmVQYXJzZShwYXJhbS5pbnB1dClcblxuICAgICAgLy8gdGVhbW1hdGVfc3Bhd25lZCBpcyBub3QgcGFydCBvZiB0aGUgZXhwb3J0ZWQgT3V0cHV0IHR5cGUgKGNhc3QgdGhyb3VnaCB1bmtub3duXG4gICAgICAvLyBmb3IgZGVhZCBjb2RlIGVsaW1pbmF0aW9uKSwgc28gY2hlY2sgdmlhIHN0cmluZyBjb21wYXJpc29uIG9uIHRoZSByYXcgdmFsdWVcbiAgICAgIGNvbnN0IGlzVGVhbW1hdGVTcGF3biA9XG4gICAgICAgIChyZXN1bHQ/Lm91dHB1dD8uc3RhdHVzIGFzIHN0cmluZykgPT09ICd0ZWFtbWF0ZV9zcGF3bmVkJ1xuXG4gICAgICAvLyBGb3IgdGVhbW1hdGUgc3Bhd25zLCBzaG93IEBuYW1lIHdpdGggdHlwZSBpbiBwYXJlbnMgYW5kIGRlc2NyaXB0aW9uIGFzIHN0YXR1c1xuICAgICAgbGV0IGFnZW50VHlwZTogc3RyaW5nXG4gICAgICBsZXQgZGVzY3JpcHRpb246IHN0cmluZyB8IHVuZGVmaW5lZFxuICAgICAgbGV0IGNvbG9yOiBrZXlvZiBUaGVtZSB8IHVuZGVmaW5lZFxuICAgICAgbGV0IGRlc2NyaXB0aW9uQ29sb3I6IGtleW9mIFRoZW1lIHwgdW5kZWZpbmVkXG4gICAgICBsZXQgdGFza0Rlc2NyaXB0aW9uOiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgICAgIGlmIChpc1RlYW1tYXRlU3Bhd24gJiYgcGFyc2VkSW5wdXQuc3VjY2VzcyAmJiBwYXJzZWRJbnB1dC5kYXRhLm5hbWUpIHtcbiAgICAgICAgYWdlbnRUeXBlID0gYEAke3BhcnNlZElucHV0LmRhdGEubmFtZX1gXG4gICAgICAgIGNvbnN0IHN1YmFnZW50VHlwZSA9IHBhcnNlZElucHV0LmRhdGEuc3ViYWdlbnRfdHlwZVxuICAgICAgICBkZXNjcmlwdGlvbiA9IGlzQ3VzdG9tU3ViYWdlbnRUeXBlKHN1YmFnZW50VHlwZSlcbiAgICAgICAgICA/IHN1YmFnZW50VHlwZVxuICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgIHRhc2tEZXNjcmlwdGlvbiA9IHBhcnNlZElucHV0LmRhdGEuZGVzY3JpcHRpb25cbiAgICAgICAgLy8gVXNlIHRoZSBjdXN0b20gYWdlbnQgZGVmaW5pdGlvbidzIGNvbG9yIG9uIHRoZSB0eXBlLCBub3QgdGhlIG5hbWVcbiAgICAgICAgZGVzY3JpcHRpb25Db2xvciA9IGlzQ3VzdG9tU3ViYWdlbnRUeXBlKHN1YmFnZW50VHlwZSlcbiAgICAgICAgICA/IChnZXRBZ2VudENvbG9yKHN1YmFnZW50VHlwZSkgYXMga2V5b2YgVGhlbWUgfCB1bmRlZmluZWQpXG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFnZW50VHlwZSA9IHBhcnNlZElucHV0LnN1Y2Nlc3NcbiAgICAgICAgICA/IHVzZXJGYWNpbmdOYW1lKHBhcnNlZElucHV0LmRhdGEpXG4gICAgICAgICAgOiAnQWdlbnQnXG4gICAgICAgIGRlc2NyaXB0aW9uID0gcGFyc2VkSW5wdXQuc3VjY2Vzc1xuICAgICAgICAgID8gcGFyc2VkSW5wdXQuZGF0YS5kZXNjcmlwdGlvblxuICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgIGNvbG9yID0gcGFyc2VkSW5wdXQuc3VjY2Vzc1xuICAgICAgICAgID8gdXNlckZhY2luZ05hbWVCYWNrZ3JvdW5kQ29sb3IocGFyc2VkSW5wdXQuZGF0YSlcbiAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgICB0YXNrRGVzY3JpcHRpb24gPSB1bmRlZmluZWRcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhpcyB3YXMgbGF1bmNoZWQgYXMgYSBiYWNrZ3JvdW5kIGFnZW50IE9SIGJhY2tncm91bmRlZCBtaWQtZXhlY3V0aW9uXG4gICAgICBjb25zdCBsYXVuY2hlZEFzQXN5bmMgPVxuICAgICAgICBwYXJzZWRJbnB1dC5zdWNjZXNzICYmXG4gICAgICAgICdydW5faW5fYmFja2dyb3VuZCcgaW4gcGFyc2VkSW5wdXQuZGF0YSAmJlxuICAgICAgICBwYXJzZWRJbnB1dC5kYXRhLnJ1bl9pbl9iYWNrZ3JvdW5kID09PSB0cnVlXG4gICAgICBjb25zdCBvdXRwdXRTdGF0dXMgPSAocmVzdWx0Py5vdXRwdXQgYXMgeyBzdGF0dXM/OiBzdHJpbmcgfSB8IHVuZGVmaW5lZClcbiAgICAgICAgPy5zdGF0dXNcbiAgICAgIGNvbnN0IGJhY2tncm91bmRlZE1pZEV4ZWN1dGlvbiA9XG4gICAgICAgIG91dHB1dFN0YXR1cyA9PT0gJ2FzeW5jX2xhdW5jaGVkJyB8fCBvdXRwdXRTdGF0dXMgPT09ICdyZW1vdGVfbGF1bmNoZWQnXG4gICAgICBjb25zdCBpc0FzeW5jID1cbiAgICAgICAgbGF1bmNoZWRBc0FzeW5jIHx8IGJhY2tncm91bmRlZE1pZEV4ZWN1dGlvbiB8fCBpc1RlYW1tYXRlU3Bhd25cblxuICAgICAgY29uc3QgbmFtZSA9IHBhcnNlZElucHV0LnN1Y2Nlc3MgPyBwYXJzZWRJbnB1dC5kYXRhLm5hbWUgOiB1bmRlZmluZWRcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaWQ6IHBhcmFtLmlkLFxuICAgICAgICBhZ2VudFR5cGUsXG4gICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICB0b29sVXNlQ291bnQ6IHN0YXRzLnRvb2xVc2VDb3VudCxcbiAgICAgICAgdG9rZW5zOiBzdGF0cy50b2tlbnMsXG4gICAgICAgIGlzUmVzb2x2ZWQsXG4gICAgICAgIGlzRXJyb3IsXG4gICAgICAgIGlzQXN5bmMsXG4gICAgICAgIGNvbG9yLFxuICAgICAgICBkZXNjcmlwdGlvbkNvbG9yLFxuICAgICAgICBsYXN0VG9vbEluZm8sXG4gICAgICAgIHRhc2tEZXNjcmlwdGlvbixcbiAgICAgICAgbmFtZSxcbiAgICAgIH1cbiAgICB9LFxuICApXG5cbiAgY29uc3QgYW55VW5yZXNvbHZlZCA9IHRvb2xVc2VzLnNvbWUodCA9PiAhdC5pc1Jlc29sdmVkKVxuICBjb25zdCBhbnlFcnJvciA9IHRvb2xVc2VzLnNvbWUodCA9PiB0LmlzRXJyb3IpXG4gIGNvbnN0IGFsbENvbXBsZXRlID0gIWFueVVucmVzb2x2ZWRcblxuICAvLyBDaGVjayBpZiBhbGwgYWdlbnRzIGFyZSB0aGUgc2FtZSB0eXBlXG4gIGNvbnN0IGFsbFNhbWVUeXBlID1cbiAgICBhZ2VudFN0YXRzLmxlbmd0aCA+IDAgJiZcbiAgICBhZ2VudFN0YXRzLmV2ZXJ5KHN0YXQgPT4gc3RhdC5hZ2VudFR5cGUgPT09IGFnZW50U3RhdHNbMF0/LmFnZW50VHlwZSlcbiAgY29uc3QgY29tbW9uVHlwZSA9XG4gICAgYWxsU2FtZVR5cGUgJiYgYWdlbnRTdGF0c1swXT8uYWdlbnRUeXBlICE9PSAnQWdlbnQnXG4gICAgICA/IGFnZW50U3RhdHNbMF0/LmFnZW50VHlwZVxuICAgICAgOiBudWxsXG5cbiAgLy8gQ2hlY2sgaWYgYWxsIHJlc29sdmVkIGFnZW50cyBhcmUgYXN5bmMgKGJhY2tncm91bmQpXG4gIGNvbnN0IGFsbEFzeW5jID0gYWdlbnRTdGF0cy5ldmVyeShzdGF0ID0+IHN0YXQuaXNBc3luYylcblxuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiIG1hcmdpblRvcD17MX0+XG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJyb3dcIj5cbiAgICAgICAgPFRvb2xVc2VMb2FkZXJcbiAgICAgICAgICBzaG91bGRBbmltYXRlPXtzaG91bGRBbmltYXRlICYmIGFueVVucmVzb2x2ZWR9XG4gICAgICAgICAgaXNVbnJlc29sdmVkPXthbnlVbnJlc29sdmVkfVxuICAgICAgICAgIGlzRXJyb3I9e2FueUVycm9yfVxuICAgICAgICAvPlxuICAgICAgICA8VGV4dD5cbiAgICAgICAgICB7YWxsQ29tcGxldGUgPyAoXG4gICAgICAgICAgICBhbGxBc3luYyA/IChcbiAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICA8VGV4dCBib2xkPnt0b29sVXNlcy5sZW5ndGh9PC9UZXh0PiBiYWNrZ3JvdW5kIGFnZW50cyBsYXVuY2hlZHsnICd9XG4gICAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgICAgICA8S2V5Ym9hcmRTaG9ydGN1dEhpbnQgc2hvcnRjdXQ9XCLihpNcIiBhY3Rpb249XCJtYW5hZ2VcIiBwYXJlbnMgLz5cbiAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICA8VGV4dCBib2xkPnt0b29sVXNlcy5sZW5ndGh9PC9UZXh0PnsnICd9XG4gICAgICAgICAgICAgICAge2NvbW1vblR5cGUgPyBgJHtjb21tb25UeXBlfSBhZ2VudHNgIDogJ2FnZW50cyd9IGZpbmlzaGVkXG4gICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgKVxuICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICA8PlxuICAgICAgICAgICAgICBSdW5uaW5nIDxUZXh0IGJvbGQ+e3Rvb2xVc2VzLmxlbmd0aH08L1RleHQ+eycgJ31cbiAgICAgICAgICAgICAge2NvbW1vblR5cGUgPyBgJHtjb21tb25UeXBlfSBhZ2VudHNgIDogJ2FnZW50cyd94oCmXG4gICAgICAgICAgICA8Lz5cbiAgICAgICAgICApfXsnICd9XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICAgeyFhbGxBc3luYyAmJiA8Q3RybE9Ub0V4cGFuZCAvPn1cbiAgICAgIDwvQm94PlxuICAgICAge2FnZW50U3RhdHMubWFwKChzdGF0LCBpbmRleCkgPT4gKFxuICAgICAgICA8QWdlbnRQcm9ncmVzc0xpbmVcbiAgICAgICAgICBrZXk9e3N0YXQuaWR9XG4gICAgICAgICAgYWdlbnRUeXBlPXtzdGF0LmFnZW50VHlwZX1cbiAgICAgICAgICBkZXNjcmlwdGlvbj17c3RhdC5kZXNjcmlwdGlvbn1cbiAgICAgICAgICBkZXNjcmlwdGlvbkNvbG9yPXtzdGF0LmRlc2NyaXB0aW9uQ29sb3J9XG4gICAgICAgICAgdGFza0Rlc2NyaXB0aW9uPXtzdGF0LnRhc2tEZXNjcmlwdGlvbn1cbiAgICAgICAgICB0b29sVXNlQ291bnQ9e3N0YXQudG9vbFVzZUNvdW50fVxuICAgICAgICAgIHRva2Vucz17c3RhdC50b2tlbnN9XG4gICAgICAgICAgY29sb3I9e3N0YXQuY29sb3J9XG4gICAgICAgICAgaXNMYXN0PXtpbmRleCA9PT0gYWdlbnRTdGF0cy5sZW5ndGggLSAxfVxuICAgICAgICAgIGlzUmVzb2x2ZWQ9e3N0YXQuaXNSZXNvbHZlZH1cbiAgICAgICAgICBpc0Vycm9yPXtzdGF0LmlzRXJyb3J9XG4gICAgICAgICAgaXNBc3luYz17c3RhdC5pc0FzeW5jfVxuICAgICAgICAgIHNob3VsZEFuaW1hdGU9e3Nob3VsZEFuaW1hdGV9XG4gICAgICAgICAgbGFzdFRvb2xJbmZvPXtzdGF0Lmxhc3RUb29sSW5mb31cbiAgICAgICAgICBoaWRlVHlwZT17YWxsU2FtZVR5cGV9XG4gICAgICAgICAgbmFtZT17c3RhdC5uYW1lfVxuICAgICAgICAvPlxuICAgICAgKSl9XG4gICAgPC9Cb3g+XG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZXJGYWNpbmdOYW1lKFxuICBpbnB1dDpcbiAgICB8IFBhcnRpYWw8e1xuICAgICAgICBkZXNjcmlwdGlvbjogc3RyaW5nXG4gICAgICAgIHByb21wdDogc3RyaW5nXG4gICAgICAgIHN1YmFnZW50X3R5cGU6IHN0cmluZ1xuICAgICAgICBuYW1lOiBzdHJpbmdcbiAgICAgICAgdGVhbV9uYW1lOiBzdHJpbmdcbiAgICAgIH0+XG4gICAgfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcge1xuICBpZiAoXG4gICAgaW5wdXQ/LnN1YmFnZW50X3R5cGUgJiZcbiAgICBpbnB1dC5zdWJhZ2VudF90eXBlICE9PSBHRU5FUkFMX1BVUlBPU0VfQUdFTlQuYWdlbnRUeXBlXG4gICkge1xuICAgIC8vIERpc3BsYXkgXCJ3b3JrZXJcIiBhZ2VudHMgYXMgXCJBZ2VudFwiIGZvciBjbGVhbmVyIFVJXG4gICAgaWYgKGlucHV0LnN1YmFnZW50X3R5cGUgPT09ICd3b3JrZXInKSB7XG4gICAgICByZXR1cm4gJ0FnZW50J1xuICAgIH1cbiAgICByZXR1cm4gaW5wdXQuc3ViYWdlbnRfdHlwZVxuICB9XG4gIHJldHVybiAnQWdlbnQnXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VyRmFjaW5nTmFtZUJhY2tncm91bmRDb2xvcihcbiAgaW5wdXQ6XG4gICAgfCBQYXJ0aWFsPHsgZGVzY3JpcHRpb246IHN0cmluZzsgcHJvbXB0OiBzdHJpbmc7IHN1YmFnZW50X3R5cGU6IHN0cmluZyB9PlxuICAgIHwgdW5kZWZpbmVkLFxuKToga2V5b2YgVGhlbWUgfCB1bmRlZmluZWQge1xuICBpZiAoIWlucHV0Py5zdWJhZ2VudF90eXBlKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgLy8gR2V0IHRoZSBjb2xvciBmb3IgdGhpcyBhZ2VudFxuICByZXR1cm4gZ2V0QWdlbnRDb2xvcihpbnB1dC5zdWJhZ2VudF90eXBlKSBhcyBrZXlvZiBUaGVtZSB8IHVuZGVmaW5lZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdExhc3RUb29sSW5mbyhcbiAgcHJvZ3Jlc3NNZXNzYWdlczogUHJvZ3Jlc3NNZXNzYWdlPFByb2dyZXNzPltdLFxuICB0b29sczogVG9vbHMsXG4pOiBzdHJpbmcgfCBudWxsIHtcbiAgLy8gQnVpbGQgdG9vbF91c2UgbG9va3VwIGZyb20gYWxsIHByb2dyZXNzIG1lc3NhZ2VzIChuZWVkZWQgZm9yIHJldmVyc2UgaXRlcmF0aW9uKVxuICBjb25zdCB0b29sVXNlQnlJRCA9IG5ldyBNYXA8c3RyaW5nLCBUb29sVXNlQmxvY2tQYXJhbT4oKVxuICBmb3IgKGNvbnN0IHBtIG9mIHByb2dyZXNzTWVzc2FnZXMpIHtcbiAgICBpZiAoIWhhc1Byb2dyZXNzTWVzc2FnZShwbS5kYXRhKSkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYgKHBtLmRhdGEubWVzc2FnZS50eXBlID09PSAnYXNzaXN0YW50Jykge1xuICAgICAgZm9yIChjb25zdCBjIG9mIHBtLmRhdGEubWVzc2FnZS5tZXNzYWdlLmNvbnRlbnQpIHtcbiAgICAgICAgaWYgKGMudHlwZSA9PT0gJ3Rvb2xfdXNlJykge1xuICAgICAgICAgIHRvb2xVc2VCeUlELnNldChjLmlkLCBjIGFzIFRvb2xVc2VCbG9ja1BhcmFtKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gQ291bnQgdHJhaWxpbmcgY29uc2VjdXRpdmUgc2VhcmNoL3JlYWQgb3BlcmF0aW9ucyBmcm9tIHRoZSBlbmRcbiAgbGV0IHNlYXJjaENvdW50ID0gMFxuICBsZXQgcmVhZENvdW50ID0gMFxuICBmb3IgKGxldCBpID0gcHJvZ3Jlc3NNZXNzYWdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGNvbnN0IG1zZyA9IHByb2dyZXNzTWVzc2FnZXNbaV0hXG4gICAgaWYgKCFoYXNQcm9ncmVzc01lc3NhZ2UobXNnLmRhdGEpKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBjb25zdCBpbmZvID0gZ2V0U2VhcmNoT3JSZWFkSW5mbyhtc2csIHRvb2xzLCB0b29sVXNlQnlJRClcbiAgICBpZiAoaW5mbyAmJiAoaW5mby5pc1NlYXJjaCB8fCBpbmZvLmlzUmVhZCkpIHtcbiAgICAgIC8vIE9ubHkgY291bnQgdG9vbF9yZXN1bHQgbWVzc2FnZXMgdG8gYXZvaWQgZG91YmxlIGNvdW50aW5nXG4gICAgICBpZiAobXNnLmRhdGEubWVzc2FnZS50eXBlID09PSAndXNlcicpIHtcbiAgICAgICAgaWYgKGluZm8uaXNTZWFyY2gpIHtcbiAgICAgICAgICBzZWFyY2hDb3VudCsrXG4gICAgICAgIH0gZWxzZSBpZiAoaW5mby5pc1JlYWQpIHtcbiAgICAgICAgICByZWFkQ291bnQrK1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHNlYXJjaENvdW50ICsgcmVhZENvdW50ID49IDIpIHtcbiAgICByZXR1cm4gZ2V0U2VhcmNoUmVhZFN1bW1hcnlUZXh0KHNlYXJjaENvdW50LCByZWFkQ291bnQsIHRydWUpXG4gIH1cblxuICAvLyBGaW5kIHRoZSBsYXN0IHRvb2xfcmVzdWx0IG1lc3NhZ2VcbiAgY29uc3QgbGFzdFRvb2xSZXN1bHQgPSBwcm9ncmVzc01lc3NhZ2VzLmZpbmRMYXN0KFxuICAgIChtc2cpOiBtc2cgaXMgUHJvZ3Jlc3NNZXNzYWdlPEFnZW50VG9vbFByb2dyZXNzPiA9PiB7XG4gICAgICBpZiAoIWhhc1Byb2dyZXNzTWVzc2FnZShtc2cuZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlID0gbXNnLmRhdGEubWVzc2FnZVxuICAgICAgcmV0dXJuIChcbiAgICAgICAgbWVzc2FnZS50eXBlID09PSAndXNlcicgJiZcbiAgICAgICAgbWVzc2FnZS5tZXNzYWdlLmNvbnRlbnQuc29tZShjID0+IGMudHlwZSA9PT0gJ3Rvb2xfcmVzdWx0JylcbiAgICAgIClcbiAgICB9LFxuICApXG5cbiAgaWYgKGxhc3RUb29sUmVzdWx0Py5kYXRhLm1lc3NhZ2UudHlwZSA9PT0gJ3VzZXInKSB7XG4gICAgY29uc3QgdG9vbFJlc3VsdEJsb2NrID0gbGFzdFRvb2xSZXN1bHQuZGF0YS5tZXNzYWdlLm1lc3NhZ2UuY29udGVudC5maW5kKFxuICAgICAgYyA9PiBjLnR5cGUgPT09ICd0b29sX3Jlc3VsdCcsXG4gICAgKVxuXG4gICAgaWYgKHRvb2xSZXN1bHRCbG9jaz8udHlwZSA9PT0gJ3Rvb2xfcmVzdWx0Jykge1xuICAgICAgLy8gTG9vayB1cCB0aGUgY29ycmVzcG9uZGluZyB0b29sX3VzZSDigJQgYWxyZWFkeSBpbmRleGVkIGFib3ZlXG4gICAgICBjb25zdCB0b29sVXNlQmxvY2sgPSB0b29sVXNlQnlJRC5nZXQodG9vbFJlc3VsdEJsb2NrLnRvb2xfdXNlX2lkKVxuXG4gICAgICBpZiAodG9vbFVzZUJsb2NrKSB7XG4gICAgICAgIGNvbnN0IHRvb2wgPSBmaW5kVG9vbEJ5TmFtZSh0b29scywgdG9vbFVzZUJsb2NrLm5hbWUpXG4gICAgICAgIGlmICghdG9vbCkge1xuICAgICAgICAgIHJldHVybiB0b29sVXNlQmxvY2submFtZSAvLyBGYWxsYmFjayB0byByYXcgbmFtZVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaW5wdXQgPSB0b29sVXNlQmxvY2suaW5wdXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICAgICAgY29uc3QgcGFyc2VkSW5wdXQgPSB0b29sLmlucHV0U2NoZW1hLnNhZmVQYXJzZShpbnB1dClcblxuICAgICAgICAvLyBHZXQgdXNlci1mYWNpbmcgdG9vbCBuYW1lXG4gICAgICAgIGNvbnN0IHVzZXJGYWNpbmdUb29sTmFtZSA9IHRvb2wudXNlckZhY2luZ05hbWUoXG4gICAgICAgICAgcGFyc2VkSW5wdXQuc3VjY2VzcyA/IHBhcnNlZElucHV0LmRhdGEgOiB1bmRlZmluZWQsXG4gICAgICAgIClcblxuICAgICAgICAvLyBUcnkgdG8gZ2V0IHN1bW1hcnkgZnJvbSB0aGUgdG9vbCBpdHNlbGZcbiAgICAgICAgaWYgKHRvb2wuZ2V0VG9vbFVzZVN1bW1hcnkpIHtcbiAgICAgICAgICBjb25zdCBzdW1tYXJ5ID0gdG9vbC5nZXRUb29sVXNlU3VtbWFyeShcbiAgICAgICAgICAgIHBhcnNlZElucHV0LnN1Y2Nlc3MgPyBwYXJzZWRJbnB1dC5kYXRhIDogdW5kZWZpbmVkLFxuICAgICAgICAgIClcbiAgICAgICAgICBpZiAoc3VtbWFyeSkge1xuICAgICAgICAgICAgcmV0dXJuIGAke3VzZXJGYWNpbmdUb29sTmFtZX06ICR7c3VtbWFyeX1gXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmYXVsdDoganVzdCBzaG93IHVzZXItZmFjaW5nIHRvb2wgbmFtZVxuICAgICAgICByZXR1cm4gdXNlckZhY2luZ1Rvb2xOYW1lXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGxcbn1cblxuZnVuY3Rpb24gaXNDdXN0b21TdWJhZ2VudFR5cGUoXG4gIHN1YmFnZW50VHlwZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuKTogc3ViYWdlbnRUeXBlIGlzIHN0cmluZyB7XG4gIHJldHVybiAoXG4gICAgISFzdWJhZ2VudFR5cGUgJiZcbiAgICBzdWJhZ2VudFR5cGUgIT09IEdFTkVSQUxfUFVSUE9TRV9BR0VOVC5hZ2VudFR5cGUgJiZcbiAgICBzdWJhZ2VudFR5cGUgIT09ICd3b3JrZXInXG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLGNBQ0VBLG9CQUFvQixFQUNwQkMsaUJBQWlCLFFBQ1osdUNBQXVDO0FBQzlDLE9BQU8sS0FBS0MsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0Msd0JBQXdCLFFBQVEsNENBQTRDO0FBQ3JGLFNBQ0VDLGFBQWEsRUFDYkMsZ0JBQWdCLFFBQ1gsaUNBQWlDO0FBQ3hDLFNBQVNDLE1BQU0sUUFBUSx3Q0FBd0M7QUFDL0QsU0FBU0Msb0JBQW9CLFFBQVEsc0RBQXNEO0FBQzNGLGNBQWNDLENBQUMsUUFBUSxRQUFRO0FBQy9CLFNBQVNDLGlCQUFpQixRQUFRLHVDQUF1QztBQUN6RSxTQUFTQywyQkFBMkIsUUFBUSxpREFBaUQ7QUFDN0YsU0FBU0MsOEJBQThCLFFBQVEsb0RBQW9EO0FBQ25HLFNBQVNDLFFBQVEsUUFBUSw4QkFBOEI7QUFDdkQsU0FBU0MsT0FBTyxJQUFJQyxnQkFBZ0IsUUFBUSw2QkFBNkI7QUFDekUsU0FBU0MsZUFBZSxRQUFRLHFDQUFxQztBQUNyRSxTQUFTQyxhQUFhLFFBQVEsbUNBQW1D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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/tools/AgentTool/forkSubagent.ts b/_all-in-one-upload/cc-haha/src/tools/AgentTool/forkSubagent.ts new file mode 100644 index 0000000..3f5c354 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/AgentTool/forkSubagent.ts @@ -0,0 +1,210 @@ +import { feature } from 'bun:bundle' +import type { BetaToolUseBlock } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs' +import { randomUUID } from 'crypto' +import { getIsNonInteractiveSession } from '../../bootstrap/state.js' +import { + FORK_BOILERPLATE_TAG, + FORK_DIRECTIVE_PREFIX, +} from '../../constants/xml.js' +import { isCoordinatorMode } from '../../coordinator/coordinatorMode.js' +import type { + AssistantMessage, + Message as MessageType, +} from '../../types/message.js' +import { logForDebugging } from '../../utils/debug.js' +import { createUserMessage } from '../../utils/messages.js' +import type { BuiltInAgentDefinition } from './loadAgentsDir.js' + +/** + * Fork subagent feature gate. + * + * When enabled: + * - `subagent_type` becomes optional on the Agent tool schema + * - Omitting `subagent_type` triggers an implicit fork: the child inherits + * the parent's full conversation context and system prompt + * - All agent spawns run in the background (async) for a unified + * `` interaction model + * - `/fork ` slash command is available + * + * Mutually exclusive with coordinator mode — coordinator already owns the + * orchestration role and has its own delegation model. + */ +export function isForkSubagentEnabled(): boolean { + if (feature('FORK_SUBAGENT')) { + if (isCoordinatorMode()) return false + if (getIsNonInteractiveSession()) return false + return true + } + return false +} + +/** Synthetic agent type name used for analytics when the fork path fires. */ +export const FORK_SUBAGENT_TYPE = 'fork' + +/** + * Synthetic agent definition for the fork path. + * + * Not registered in builtInAgents — used only when `!subagent_type` and the + * experiment is active. `tools: ['*']` with `useExactTools` means the fork + * child receives the parent's exact tool pool (for cache-identical API + * prefixes). `permissionMode: 'bubble'` surfaces permission prompts to the + * parent terminal. `model: 'inherit'` keeps the parent's model for context + * length parity. + * + * The getSystemPrompt here is unused: the fork path passes + * `override.systemPrompt` with the parent's already-rendered system prompt + * bytes, threaded via `toolUseContext.renderedSystemPrompt`. Reconstructing + * by re-calling getSystemPrompt() can diverge (GrowthBook cold→warm) and + * bust the prompt cache; threading the rendered bytes is byte-exact. + */ +export const FORK_AGENT = { + agentType: FORK_SUBAGENT_TYPE, + whenToUse: + 'Implicit fork — inherits full conversation context. Not selectable via subagent_type; triggered by omitting subagent_type when the fork experiment is active.', + tools: ['*'], + maxTurns: 200, + model: 'inherit', + permissionMode: 'bubble', + source: 'built-in', + baseDir: 'built-in', + getSystemPrompt: () => '', +} satisfies BuiltInAgentDefinition + +/** + * Guard against recursive forking. Fork children keep the Agent tool in their + * tool pool for cache-identical tool definitions, so we reject fork attempts + * at call time by detecting the fork boilerplate tag in conversation history. + */ +export function isInForkChild(messages: MessageType[]): boolean { + return messages.some(m => { + if (m.type !== 'user') return false + const content = m.message.content + if (!Array.isArray(content)) return false + return content.some( + block => + block.type === 'text' && + block.text.includes(`<${FORK_BOILERPLATE_TAG}>`), + ) + }) +} + +/** Placeholder text used for all tool_result blocks in the fork prefix. + * Must be identical across all fork children for prompt cache sharing. */ +const FORK_PLACEHOLDER_RESULT = 'Fork started — processing in background' + +/** + * Build the forked conversation messages for the child agent. + * + * For prompt cache sharing, all fork children must produce byte-identical + * API request prefixes. This function: + * 1. Keeps the full parent assistant message (all tool_use blocks, thinking, text) + * 2. Builds a single user message with tool_results for every tool_use block + * using an identical placeholder, then appends a per-child directive text block + * + * Result: [...history, assistant(all_tool_uses), user(placeholder_results..., directive)] + * Only the final text block differs per child, maximizing cache hits. + */ +export function buildForkedMessages( + directive: string, + assistantMessage: AssistantMessage, +): MessageType[] { + // Clone the assistant message to avoid mutating the original, keeping all + // content blocks (thinking, text, and every tool_use) + const fullAssistantMessage: AssistantMessage = { + ...assistantMessage, + uuid: randomUUID(), + message: { + ...assistantMessage.message, + content: [...assistantMessage.message.content], + }, + } + + // Collect all tool_use blocks from the assistant message + const toolUseBlocks = assistantMessage.message.content.filter( + (block): block is BetaToolUseBlock => block.type === 'tool_use', + ) + + if (toolUseBlocks.length === 0) { + logForDebugging( + `No tool_use blocks found in assistant message for fork directive: ${directive.slice(0, 50)}...`, + { level: 'error' }, + ) + return [ + createUserMessage({ + content: [ + { type: 'text' as const, text: buildChildMessage(directive) }, + ], + }), + ] + } + + // Build tool_result blocks for every tool_use, all with identical placeholder text + const toolResultBlocks = toolUseBlocks.map(block => ({ + type: 'tool_result' as const, + tool_use_id: block.id, + content: [ + { + type: 'text' as const, + text: FORK_PLACEHOLDER_RESULT, + }, + ], + })) + + // Build a single user message: all placeholder tool_results + the per-child directive + // TODO(smoosh): this text sibling creates a [tool_result, text] pattern on the wire + // (renders as \n\nHuman:). One-off per-child construction, + // not a repeated teacher, so low-priority. If we ever care, use smooshIntoToolResult + // from src/utils/messages.ts to fold the directive into the last tool_result.content. + const toolResultMessage = createUserMessage({ + content: [ + ...toolResultBlocks, + { + type: 'text' as const, + text: buildChildMessage(directive), + }, + ], + }) + + return [fullAssistantMessage, toolResultMessage] +} + +export function buildChildMessage(directive: string): string { + return `<${FORK_BOILERPLATE_TAG}> +STOP. READ THIS FIRST. + +You are a forked worker process. You are NOT the main agent. + +RULES (non-negotiable): +1. Your system prompt says "default to forking." IGNORE IT \u2014 that's for the parent. You ARE the fork. Do NOT spawn sub-agents; execute directly. +2. Do NOT converse, ask questions, or suggest next steps +3. Do NOT editorialize or add meta-commentary +4. USE your tools directly: Bash, Read, Write, etc. +5. If you modify files, commit your changes before reporting. Include the commit hash in your report. +6. Do NOT emit text between tool calls. Use tools silently, then report once at the end. +7. Stay strictly within your directive's scope. If you discover related systems outside your scope, mention them in one sentence at most — other workers cover those areas. +8. Keep your report under 500 words unless the directive specifies otherwise. Be factual and concise. +9. Your response MUST begin with "Scope:". No preamble, no thinking-out-loud. +10. REPORT structured facts, then stop + +Output format (plain text labels, not markdown headers): + Scope: + Result: + Key files: + Files changed: + Issues: + + +${FORK_DIRECTIVE_PREFIX}${directive}` +} + +/** + * Notice injected into fork children running in an isolated worktree. + * Tells the child to translate paths from the inherited context, re-read + * potentially stale files, and that its changes are isolated. + */ +export function buildWorktreeNotice( + parentCwd: string, + worktreeCwd: string, +): string { + return `You've inherited the conversation context above from a parent agent working in ${parentCwd}. You are operating in an isolated git worktree at ${worktreeCwd} — same repository, same relative file structure, separate working copy. Paths in the inherited context refer to the parent's working directory; translate them to your worktree root. Re-read files before editing if the parent may have modified them since they appear in the context. Your changes stay in this worktree and will not affect the parent's files.` +} diff --git a/_all-in-one-upload/cc-haha/src/tools/AgentTool/runAgent.ts b/_all-in-one-upload/cc-haha/src/tools/AgentTool/runAgent.ts new file mode 100644 index 0000000..e2cb942 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/AgentTool/runAgent.ts @@ -0,0 +1,973 @@ +import { feature } from 'bun:bundle' +import type { UUID } from 'crypto' +import { randomUUID } from 'crypto' +import uniqBy from 'lodash-es/uniqBy.js' +import { logForDebugging } from 'src/utils/debug.js' +import { getProjectRoot, getSessionId } from '../../bootstrap/state.js' +import { getCommand, getSkillToolCommands, hasCommand } from '../../commands.js' +import { + DEFAULT_AGENT_PROMPT, + enhanceSystemPromptWithEnvDetails, +} from '../../constants/prompts.js' +import type { QuerySource } from '../../constants/querySource.js' +import { getSystemContext, getUserContext } from '../../context.js' +import type { CanUseToolFn } from '../../hooks/useCanUseTool.js' +import { query } from '../../query.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js' +import { getDumpPromptsPath } from '../../services/api/dumpPrompts.js' +import { cleanupAgentTracking } from '../../services/api/promptCacheBreakDetection.js' +import { + connectToServer, + fetchToolsForClient, +} from '../../services/mcp/client.js' +import { getMcpConfigByName } from '../../services/mcp/config.js' +import type { + MCPServerConnection, + ScopedMcpServerConfig, +} from '../../services/mcp/types.js' +import type { Tool, Tools, ToolUseContext } from '../../Tool.js' +import { killShellTasksForAgent } from '../../tasks/LocalShellTask/killShellTasks.js' +import type { Command } from '../../types/command.js' +import type { AgentId } from '../../types/ids.js' +import type { + AssistantMessage, + Message, + ProgressMessage, + RequestStartEvent, + StreamEvent, + SystemCompactBoundaryMessage, + TombstoneMessage, + ToolUseSummaryMessage, + UserMessage, +} from '../../types/message.js' +import { createAttachmentMessage } from '../../utils/attachments.js' +import { AbortError } from '../../utils/errors.js' +import { getDisplayPath } from '../../utils/file.js' +import { + cloneFileStateCache, + createFileStateCacheWithSizeLimit, + READ_FILE_STATE_CACHE_SIZE, +} from '../../utils/fileStateCache.js' +import { + type CacheSafeParams, + createSubagentContext, +} from '../../utils/forkedAgent.js' +import { registerFrontmatterHooks } from '../../utils/hooks/registerFrontmatterHooks.js' +import { clearSessionHooks } from '../../utils/hooks/sessionHooks.js' +import { executeSubagentStartHooks } from '../../utils/hooks.js' +import { createUserMessage } from '../../utils/messages.js' +import { getAgentModel } from '../../utils/model/agent.js' +import type { ModelAlias } from '../../utils/model/aliases.js' +import { + clearAgentTranscriptSubdir, + recordSidechainTranscript, + setAgentTranscriptSubdir, + writeAgentMetadata, +} from '../../utils/sessionStorage.js' +import { + isRestrictedToPluginOnly, + isSourceAdminTrusted, +} from '../../utils/settings/pluginOnlyPolicy.js' +import { + asSystemPrompt, + type SystemPrompt, +} from '../../utils/systemPromptType.js' +import { + isPerfettoTracingEnabled, + registerAgent as registerPerfettoAgent, + unregisterAgent as unregisterPerfettoAgent, +} from '../../utils/telemetry/perfettoTracing.js' +import type { ContentReplacementState } from '../../utils/toolResultStorage.js' +import { createAgentId } from '../../utils/uuid.js' +import { resolveAgentTools } from './agentToolUtils.js' +import { type AgentDefinition, isBuiltInAgent } from './loadAgentsDir.js' + +/** + * Initialize agent-specific MCP servers + * Agents can define their own MCP servers in their frontmatter that are additive + * to the parent's MCP clients. These servers are connected when the agent starts + * and cleaned up when the agent finishes. + * + * @param agentDefinition The agent definition with optional mcpServers + * @param parentClients MCP clients inherited from parent context + * @returns Merged clients (parent + agent-specific), agent MCP tools, and cleanup function + */ +async function initializeAgentMcpServers( + agentDefinition: AgentDefinition, + parentClients: MCPServerConnection[], +): Promise<{ + clients: MCPServerConnection[] + tools: Tools + cleanup: () => Promise +}> { + // If no agent-specific servers defined, return parent clients as-is + if (!agentDefinition.mcpServers?.length) { + return { + clients: parentClients, + tools: [], + cleanup: async () => {}, + } + } + + // When MCP is locked to plugin-only, skip frontmatter MCP servers for + // USER-CONTROLLED agents only. Plugin, built-in, and policySettings agents + // are admin-trusted — their frontmatter MCP is part of the admin-approved + // surface. Blocking them (as the first cut did) breaks plugin agents that + // legitimately need MCP, contradicting "plugin-provided always loads." + const agentIsAdminTrusted = isSourceAdminTrusted(agentDefinition.source) + if (isRestrictedToPluginOnly('mcp') && !agentIsAdminTrusted) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Skipping MCP servers: strictPluginOnlyCustomization locks MCP to plugin-only (agent source: ${agentDefinition.source})`, + ) + return { + clients: parentClients, + tools: [], + cleanup: async () => {}, + } + } + + const agentClients: MCPServerConnection[] = [] + // Track which clients were newly created (inline definitions) vs. shared from parent + // Only newly created clients should be cleaned up when the agent finishes + const newlyCreatedClients: MCPServerConnection[] = [] + const agentTools: Tool[] = [] + + for (const spec of agentDefinition.mcpServers) { + let config: ScopedMcpServerConfig | null = null + let name: string + let isNewlyCreated = false + + if (typeof spec === 'string') { + // Reference by name - look up in existing MCP configs + // This uses the memoized connectToServer, so we may get a shared client + name = spec + config = getMcpConfigByName(spec) + if (!config) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] MCP server not found: ${spec}`, + { level: 'warn' }, + ) + continue + } + } else { + // Inline definition as { [name]: config } + // These are agent-specific servers that should be cleaned up + const entries = Object.entries(spec) + if (entries.length !== 1) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Invalid MCP server spec: expected exactly one key`, + { level: 'warn' }, + ) + continue + } + const [serverName, serverConfig] = entries[0]! + name = serverName + config = { + ...serverConfig, + scope: 'dynamic' as const, + } as ScopedMcpServerConfig + isNewlyCreated = true + } + + // Connect to the server + const client = await connectToServer(name, config) + agentClients.push(client) + if (isNewlyCreated) { + newlyCreatedClients.push(client) + } + + // Fetch tools if connected + if (client.type === 'connected') { + const tools = await fetchToolsForClient(client) + agentTools.push(...tools) + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Connected to MCP server '${name}' with ${tools.length} tools`, + ) + } else { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Failed to connect to MCP server '${name}': ${client.type}`, + { level: 'warn' }, + ) + } + } + + // Create cleanup function for agent-specific servers + // Only clean up newly created clients (inline definitions), not shared/referenced ones + // Shared clients (referenced by string name) are memoized and used by the parent context + const cleanup = async () => { + for (const client of newlyCreatedClients) { + if (client.type === 'connected') { + try { + await client.cleanup() + } catch (error) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Error cleaning up MCP server '${client.name}': ${error}`, + { level: 'warn' }, + ) + } + } + } + } + + // Return merged clients (parent + agent-specific) and agent tools + return { + clients: [...parentClients, ...agentClients], + tools: agentTools, + cleanup, + } +} + +type QueryMessage = + | StreamEvent + | RequestStartEvent + | Message + | ToolUseSummaryMessage + | TombstoneMessage + +/** + * Type guard to check if a message from query() is a recordable Message type. + * Matches the types we want to record: assistant, user, progress, or system compact_boundary. + */ +function isRecordableMessage( + msg: QueryMessage, +): msg is + | AssistantMessage + | UserMessage + | ProgressMessage + | SystemCompactBoundaryMessage { + return ( + msg.type === 'assistant' || + msg.type === 'user' || + msg.type === 'progress' || + (msg.type === 'system' && + 'subtype' in msg && + msg.subtype === 'compact_boundary') + ) +} + +export async function* runAgent({ + agentDefinition, + promptMessages, + toolUseContext, + canUseTool, + isAsync, + canShowPermissionPrompts, + forkContextMessages, + querySource, + override, + model, + maxTurns, + preserveToolUseResults, + availableTools, + allowedTools, + onCacheSafeParams, + contentReplacementState, + useExactTools, + worktreePath, + description, + transcriptSubdir, + onQueryProgress, +}: { + agentDefinition: AgentDefinition + promptMessages: Message[] + toolUseContext: ToolUseContext + canUseTool: CanUseToolFn + isAsync: boolean + /** Whether this agent can show permission prompts. Defaults to !isAsync. + * Set to true for in-process teammates that run async but share the terminal. */ + canShowPermissionPrompts?: boolean + forkContextMessages?: Message[] + querySource: QuerySource + override?: { + userContext?: { [k: string]: string } + systemContext?: { [k: string]: string } + systemPrompt?: SystemPrompt + abortController?: AbortController + agentId?: AgentId + } + model?: ModelAlias + maxTurns?: number + /** Preserve toolUseResult on messages for subagents with viewable transcripts */ + preserveToolUseResults?: boolean + /** Precomputed tool pool for the worker agent. Computed by the caller + * (AgentTool.tsx) to avoid a circular dependency between runAgent and tools.ts. + * Always contains the full tool pool assembled with the worker's own permission + * mode, independent of the parent's tool restrictions. */ + availableTools: Tools + /** Tool permission rules to add to the agent's session allow rules. + * When provided, replaces ALL allow rules so the agent only has what's + * explicitly listed (parent approvals don't leak through). */ + allowedTools?: string[] + /** Optional callback invoked with CacheSafeParams after constructing the agent's + * system prompt, context, and tools. Used by background summarization to fork + * the agent's conversation for periodic progress summaries. */ + onCacheSafeParams?: (params: CacheSafeParams) => void + /** Replacement state reconstructed from a resumed sidechain transcript so + * the same tool results are re-replaced (prompt cache stability). When + * omitted, createSubagentContext clones the parent's state. */ + contentReplacementState?: ContentReplacementState + /** When true, use availableTools directly without filtering through + * resolveAgentTools(). Also inherits the parent's thinkingConfig and + * isNonInteractiveSession instead of overriding them. Used by the fork + * subagent path to produce byte-identical API request prefixes for + * prompt cache hits. */ + useExactTools?: boolean + /** Worktree path if the agent was spawned with isolation: "worktree". + * Persisted to metadata so resume can restore the correct cwd. */ + worktreePath?: string + /** Original task description from AgentTool input. Persisted to metadata + * so a resumed agent's notification can show the original description. */ + description?: string + /** Optional subdirectory under subagents/ to group this agent's transcript + * with related ones (e.g. workflows/ for workflow subagents). */ + transcriptSubdir?: string + /** Optional callback fired on every message yielded by query() — including + * stream_event deltas that runAgent otherwise drops. Use to detect liveness + * during long single-block streams (e.g. thinking) where no assistant + * message is yielded for >60s. */ + onQueryProgress?: () => void +}): AsyncGenerator { + // Track subagent usage for feature discovery + + const appState = toolUseContext.getAppState() + const permissionMode = appState.toolPermissionContext.mode + // Always-shared channel to the root AppState store. toolUseContext.setAppState + // is a no-op when the *parent* is itself an async agent (nested async→async), + // so session-scoped writes (hooks, bash tasks) must go through this instead. + const rootSetAppState = + toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState + + const resolvedAgentModel = getAgentModel( + agentDefinition.model, + toolUseContext.options.mainLoopModel, + model, + permissionMode, + ) + + const agentId = override?.agentId ? override.agentId : createAgentId() + + // Route this agent's transcript into a grouping subdirectory if requested + // (e.g. workflow subagents write to subagents/workflows//). + if (transcriptSubdir) { + setAgentTranscriptSubdir(agentId, transcriptSubdir) + } + + // Register agent in Perfetto trace for hierarchy visualization + if (isPerfettoTracingEnabled()) { + const parentId = toolUseContext.agentId ?? getSessionId() + registerPerfettoAgent(agentId, agentDefinition.agentType, parentId) + } + + // Log API calls path for subagents (ant-only) + if (process.env.USER_TYPE === 'ant') { + logForDebugging( + `[Subagent ${agentDefinition.agentType}] API calls: ${getDisplayPath(getDumpPromptsPath(agentId))}`, + ) + } + + // Handle message forking for context sharing + // Filter out incomplete tool calls from parent messages to avoid API errors + const contextMessages: Message[] = forkContextMessages + ? filterIncompleteToolCalls(forkContextMessages) + : [] + const initialMessages: Message[] = [...contextMessages, ...promptMessages] + + const agentReadFileState = + forkContextMessages !== undefined + ? cloneFileStateCache(toolUseContext.readFileState) + : createFileStateCacheWithSizeLimit(READ_FILE_STATE_CACHE_SIZE) + + const [baseUserContext, baseSystemContext] = await Promise.all([ + override?.userContext ?? getUserContext(), + override?.systemContext ?? getSystemContext(), + ]) + + // Read-only agents (Explore, Plan) don't act on commit/PR/lint rules from + // CLAUDE.md — the main agent has full context and interprets their output. + // Dropping claudeMd here saves ~5-15 Gtok/week across 34M+ Explore spawns. + // Explicit override.userContext from callers is preserved untouched. + // Kill-switch defaults true; flip tengu_slim_subagent_claudemd=false to revert. + const shouldOmitClaudeMd = + agentDefinition.omitClaudeMd && + !override?.userContext && + getFeatureValue_CACHED_MAY_BE_STALE('tengu_slim_subagent_claudemd', true) + const { claudeMd: _omittedClaudeMd, ...userContextNoClaudeMd } = + baseUserContext + const resolvedUserContext = shouldOmitClaudeMd + ? userContextNoClaudeMd + : baseUserContext + + // Explore/Plan are read-only search agents — the parent-session-start + // gitStatus (up to 40KB, explicitly labeled stale) is dead weight. If they + // need git info they run `git status` themselves and get fresh data. + // Saves ~1-3 Gtok/week fleet-wide. + const { gitStatus: _omittedGitStatus, ...systemContextNoGit } = + baseSystemContext + const resolvedSystemContext = + agentDefinition.agentType === 'Explore' || + agentDefinition.agentType === 'Plan' + ? systemContextNoGit + : baseSystemContext + + // Override permission mode if agent defines one + // However, don't override if parent is in bypassPermissions or acceptEdits mode - those should always take precedence + // For async agents, also set shouldAvoidPermissionPrompts since they can't show UI + const agentPermissionMode = agentDefinition.permissionMode + const agentGetAppState = () => { + const state = toolUseContext.getAppState() + let toolPermissionContext = state.toolPermissionContext + + // Override permission mode if agent defines one (unless parent is bypassPermissions, acceptEdits, or auto) + if ( + agentPermissionMode && + state.toolPermissionContext.mode !== 'bypassPermissions' && + state.toolPermissionContext.mode !== 'acceptEdits' && + !( + feature('TRANSCRIPT_CLASSIFIER') && + state.toolPermissionContext.mode === 'auto' + ) + ) { + toolPermissionContext = { + ...toolPermissionContext, + mode: agentPermissionMode, + } + } + + // Set flag to auto-deny prompts for agents that can't show UI + // Use explicit canShowPermissionPrompts if provided, otherwise: + // - bubble mode: always show prompts (bubbles to parent terminal) + // - default: !isAsync (sync agents show prompts, async agents don't) + const shouldAvoidPrompts = + canShowPermissionPrompts !== undefined + ? !canShowPermissionPrompts + : agentPermissionMode === 'bubble' + ? false + : isAsync + if (shouldAvoidPrompts) { + toolPermissionContext = { + ...toolPermissionContext, + shouldAvoidPermissionPrompts: true, + } + } + + // For background agents that can show prompts, await automated checks + // (classifier, permission hooks) before showing the permission dialog. + // Since these are background agents, waiting is fine — the user should + // only be interrupted when automated checks can't resolve the permission. + // This applies to bubble mode (always) and explicit canShowPermissionPrompts. + if (isAsync && !shouldAvoidPrompts) { + toolPermissionContext = { + ...toolPermissionContext, + awaitAutomatedChecksBeforeDialog: true, + } + } + + // Scope tool permissions: when allowedTools is provided, use them as session rules. + // IMPORTANT: Preserve cliArg rules (from SDK's --allowedTools) since those are + // explicit permissions from the SDK consumer that should apply to all agents. + // Only clear session-level rules from the parent to prevent unintended leakage. + if (allowedTools !== undefined) { + toolPermissionContext = { + ...toolPermissionContext, + alwaysAllowRules: { + // Preserve SDK-level permissions from --allowedTools + cliArg: state.toolPermissionContext.alwaysAllowRules.cliArg, + // Use the provided allowedTools as session-level permissions + session: [...allowedTools], + }, + } + } + + // Override effort level if agent defines one + const effortValue = + agentDefinition.effort !== undefined + ? agentDefinition.effort + : state.effortValue + + if ( + toolPermissionContext === state.toolPermissionContext && + effortValue === state.effortValue + ) { + return state + } + return { + ...state, + toolPermissionContext, + effortValue, + } + } + + const resolvedTools = useExactTools + ? availableTools + : resolveAgentTools(agentDefinition, availableTools, isAsync).resolvedTools + + const additionalWorkingDirectories = Array.from( + appState.toolPermissionContext.additionalWorkingDirectories.keys(), + ) + + const agentSystemPrompt = override?.systemPrompt + ? override.systemPrompt + : asSystemPrompt( + await getAgentSystemPrompt( + agentDefinition, + toolUseContext, + resolvedAgentModel, + additionalWorkingDirectories, + resolvedTools, + ), + ) + + // Determine abortController: + // - Override takes precedence + // - Async agents get a new unlinked controller (runs independently) + // - Sync agents share parent's controller + const agentAbortController = override?.abortController + ? override.abortController + : isAsync + ? new AbortController() + : toolUseContext.abortController + + // Execute SubagentStart hooks and collect additional context + const additionalContexts: string[] = [] + for await (const hookResult of executeSubagentStartHooks( + agentId, + agentDefinition.agentType, + agentAbortController.signal, + )) { + if ( + hookResult.additionalContexts && + hookResult.additionalContexts.length > 0 + ) { + additionalContexts.push(...hookResult.additionalContexts) + } + } + + // Add SubagentStart hook context as a user message (consistent with SessionStart/UserPromptSubmit) + if (additionalContexts.length > 0) { + const contextMessage = createAttachmentMessage({ + type: 'hook_additional_context', + content: additionalContexts, + hookName: 'SubagentStart', + toolUseID: randomUUID(), + hookEvent: 'SubagentStart', + }) + initialMessages.push(contextMessage) + } + + // Register agent's frontmatter hooks (scoped to agent lifecycle) + // Pass isAgent=true to convert Stop hooks to SubagentStop (since subagents trigger SubagentStop) + // Same admin-trusted gate for frontmatter hooks: under ["hooks"] alone + // (skills/agents not locked), user agents still load — block their + // frontmatter-hook REGISTRATION here where source is known, rather than + // blanket-blocking all session hooks at execution time (which would + // also kill plugin agents' hooks). + const hooksAllowedForThisAgent = + !isRestrictedToPluginOnly('hooks') || + isSourceAdminTrusted(agentDefinition.source) + if (agentDefinition.hooks && hooksAllowedForThisAgent) { + registerFrontmatterHooks( + rootSetAppState, + agentId, + agentDefinition.hooks, + `agent '${agentDefinition.agentType}'`, + true, // isAgent - converts Stop to SubagentStop + ) + } + + // Preload skills from agent frontmatter + const skillsToPreload = agentDefinition.skills ?? [] + if (skillsToPreload.length > 0) { + const allSkills = await getSkillToolCommands(getProjectRoot()) + + // Filter valid skills and warn about missing ones + const validSkills: Array<{ + skillName: string + skill: (typeof allSkills)[0] & { type: 'prompt' } + }> = [] + + for (const skillName of skillsToPreload) { + // Resolve the skill name, trying multiple strategies: + // 1. Exact match (hasCommand checks name, userFacingName, aliases) + // 2. Fully-qualified with agent's plugin prefix (e.g., "my-skill" → "plugin:my-skill") + // 3. Suffix match on ":skillName" for plugin-namespaced skills + const resolvedName = resolveSkillName( + skillName, + allSkills, + agentDefinition, + ) + if (!resolvedName) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Warning: Skill '${skillName}' specified in frontmatter was not found`, + { level: 'warn' }, + ) + continue + } + + const skill = getCommand(resolvedName, allSkills) + if (skill.type !== 'prompt') { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Warning: Skill '${skillName}' is not a prompt-based skill`, + { level: 'warn' }, + ) + continue + } + validSkills.push({ skillName, skill }) + } + + // Load all skill contents concurrently and add to initial messages + const { formatSkillLoadingMetadata } = await import( + '../../utils/processUserInput/processSlashCommand.js' + ) + const loaded = await Promise.all( + validSkills.map(async ({ skillName, skill }) => ({ + skillName, + skill, + content: await skill.getPromptForCommand('', toolUseContext), + })), + ) + for (const { skillName, skill, content } of loaded) { + logForDebugging( + `[Agent: ${agentDefinition.agentType}] Preloaded skill '${skillName}'`, + ) + + // Add command-message metadata so the UI shows which skill is loading + const metadata = formatSkillLoadingMetadata( + skillName, + skill.progressMessage, + ) + + initialMessages.push( + createUserMessage({ + content: [{ type: 'text', text: metadata }, ...content], + isMeta: true, + }), + ) + } + } + + // Initialize agent-specific MCP servers (additive to parent's servers) + const { + clients: mergedMcpClients, + tools: agentMcpTools, + cleanup: mcpCleanup, + } = await initializeAgentMcpServers( + agentDefinition, + toolUseContext.options.mcpClients, + ) + + // Merge agent MCP tools with resolved agent tools, deduplicating by name. + // resolvedTools is already deduplicated (see resolveAgentTools), so skip + // the spread + uniqBy overhead when there are no agent-specific MCP tools. + const allTools = + agentMcpTools.length > 0 + ? uniqBy([...resolvedTools, ...agentMcpTools], 'name') + : resolvedTools + + // Build agent-specific options + const agentOptions: ToolUseContext['options'] = { + isNonInteractiveSession: useExactTools + ? toolUseContext.options.isNonInteractiveSession + : isAsync + ? true + : (toolUseContext.options.isNonInteractiveSession ?? false), + appendSystemPrompt: toolUseContext.options.appendSystemPrompt, + tools: allTools, + commands: [], + debug: toolUseContext.options.debug, + verbose: toolUseContext.options.verbose, + mainLoopModel: resolvedAgentModel, + // For fork children (useExactTools), inherit thinking config to match the + // parent's API request prefix for prompt cache hits. For regular + // sub-agents, disable thinking to control output token costs. + thinkingConfig: useExactTools + ? toolUseContext.options.thinkingConfig + : { type: 'disabled' as const }, + mcpClients: mergedMcpClients, + mcpResources: toolUseContext.options.mcpResources, + agentDefinitions: toolUseContext.options.agentDefinitions, + // Fork children (useExactTools path) need querySource on context.options + // for the recursive-fork guard at AgentTool.tsx call() — it checks + // options.querySource === 'agent:builtin:fork'. This survives autocompact + // (which rewrites messages, not context.options). Without this, the guard + // reads undefined and only the message-scan fallback fires — which + // autocompact defeats by replacing the fork-boilerplate message. + ...(useExactTools && { querySource }), + } + + // Create subagent context using shared helper + // - Sync agents share setAppState, setResponseLength, abortController with parent + // - Async agents are fully isolated (but with explicit unlinked abortController) + const agentToolUseContext = createSubagentContext(toolUseContext, { + options: agentOptions, + agentId, + agentType: agentDefinition.agentType, + messages: initialMessages, + readFileState: agentReadFileState, + abortController: agentAbortController, + getAppState: agentGetAppState, + // Sync agents share these callbacks with parent + shareSetAppState: !isAsync, + shareSetResponseLength: true, // Both sync and async contribute to response metrics + criticalSystemReminder_EXPERIMENTAL: + agentDefinition.criticalSystemReminder_EXPERIMENTAL, + contentReplacementState, + }) + + // Preserve tool use results for subagents with viewable transcripts (in-process teammates) + if (preserveToolUseResults) { + agentToolUseContext.preserveToolUseResults = true + } + + // Expose cache-safe params for background summarization (prompt cache sharing) + if (onCacheSafeParams) { + onCacheSafeParams({ + systemPrompt: agentSystemPrompt, + userContext: resolvedUserContext, + systemContext: resolvedSystemContext, + toolUseContext: agentToolUseContext, + forkContextMessages: initialMessages, + }) + } + + // Record initial messages before the query loop starts, plus the agentType + // so resume can route correctly when subagent_type is omitted. Both writes + // are fire-and-forget — persistence failure shouldn't block the agent. + void recordSidechainTranscript(initialMessages, agentId).catch(_err => + logForDebugging(`Failed to record sidechain transcript: ${_err}`), + ) + void writeAgentMetadata(agentId, { + agentType: agentDefinition.agentType, + ...(worktreePath && { worktreePath }), + ...(description && { description }), + }).catch(_err => logForDebugging(`Failed to write agent metadata: ${_err}`)) + + // Track the last recorded message UUID for parent chain continuity + let lastRecordedUuid: UUID | null = initialMessages.at(-1)?.uuid ?? null + + try { + for await (const message of query({ + messages: initialMessages, + systemPrompt: agentSystemPrompt, + userContext: resolvedUserContext, + systemContext: resolvedSystemContext, + canUseTool, + toolUseContext: agentToolUseContext, + querySource, + maxTurns: maxTurns ?? agentDefinition.maxTurns, + })) { + onQueryProgress?.() + // Forward subagent API request starts to parent's metrics display + // so TTFT/OTPS update during subagent execution. + if ( + message.type === 'stream_event' && + message.event.type === 'message_start' && + message.ttftMs != null + ) { + toolUseContext.pushApiMetricsEntry?.(message.ttftMs) + continue + } + + // Yield attachment messages (e.g., structured_output) without recording them + if (message.type === 'attachment') { + // Handle max turns reached signal from query.ts + if (message.attachment.type === 'max_turns_reached') { + logForDebugging( + `[Agent +: $ +{ + agentDefinition.agentType +} +] Reached max turns limit ($ +{ + message.attachment.maxTurns +} +)`, + ) + break + } + yield message + continue + } + + if (isRecordableMessage(message)) { + // Record only the new message with correct parent (O(1) per message) + await recordSidechainTranscript( + [message], + agentId, + lastRecordedUuid, + ).catch(err => + logForDebugging(`Failed to record sidechain transcript: ${err}`), + ) + if (message.type !== 'progress') { + lastRecordedUuid = message.uuid + } + yield message + } + } + + if (agentAbortController.signal.aborted) { + throw new AbortError() + } + + // Run callback if provided (only built-in agents have callbacks) + if (isBuiltInAgent(agentDefinition) && agentDefinition.callback) { + agentDefinition.callback() + } + } finally { + // Clean up agent-specific MCP servers (runs on normal completion, abort, or error) + await mcpCleanup() + // Clean up agent's session hooks + if (agentDefinition.hooks) { + clearSessionHooks(rootSetAppState, agentId) + } + // Clean up prompt cache tracking state for this agent + if (feature('PROMPT_CACHE_BREAK_DETECTION')) { + cleanupAgentTracking(agentId) + } + // Release cloned file state cache memory + agentToolUseContext.readFileState.clear() + // Release the cloned fork context messages + initialMessages.length = 0 + // Release perfetto agent registry entry + unregisterPerfettoAgent(agentId) + // Release transcript subdir mapping + clearAgentTranscriptSubdir(agentId) + // Release this agent's todos entry. Without this, every subagent that + // called TodoWrite leaves a key in AppState.todos forever (even after all + // items complete, the value is [] but the key stays). Whale sessions + // spawn hundreds of agents; each orphaned key is a small leak that adds up. + rootSetAppState(prev => { + if (!(agentId in prev.todos)) return prev + const { [agentId]: _removed, ...todos } = prev.todos + return { ...prev, todos } + }) + // Kill any background bash tasks this agent spawned. Without this, a + // `run_in_background` shell loop (e.g. test fixture fake-logs.sh) outlives + // the agent as a PPID=1 zombie once the main session eventually exits. + killShellTasksForAgent(agentId, toolUseContext.getAppState, rootSetAppState) + /* eslint-disable @typescript-eslint/no-require-imports */ + if (feature('MONITOR_TOOL')) { + const mcpMod = + require('../../tasks/MonitorMcpTask/MonitorMcpTask.js') as typeof import('../../tasks/MonitorMcpTask/MonitorMcpTask.js') + mcpMod.killMonitorMcpTasksForAgent( + agentId, + toolUseContext.getAppState, + rootSetAppState, + ) + } + /* eslint-enable @typescript-eslint/no-require-imports */ + } +} + +/** + * Filters out assistant messages with incomplete tool calls (tool uses without results). + * This prevents API errors when sending messages with orphaned tool calls. + */ +export function filterIncompleteToolCalls(messages: Message[]): Message[] { + // Build a set of tool use IDs that have results + const toolUseIdsWithResults = new Set() + + for (const message of messages) { + if (message?.type === 'user') { + const userMessage = message as UserMessage + const content = userMessage.message.content + if (Array.isArray(content)) { + for (const block of content) { + if (block.type === 'tool_result' && block.tool_use_id) { + toolUseIdsWithResults.add(block.tool_use_id) + } + } + } + } + } + + // Filter out assistant messages that contain tool calls without results + return messages.filter(message => { + if (message?.type === 'assistant') { + const assistantMessage = message as AssistantMessage + const content = assistantMessage.message.content + if (Array.isArray(content)) { + // Check if this assistant message has any tool uses without results + const hasIncompleteToolCall = content.some( + block => + block.type === 'tool_use' && + block.id && + !toolUseIdsWithResults.has(block.id), + ) + // Exclude messages with incomplete tool calls + return !hasIncompleteToolCall + } + } + // Keep all non-assistant messages and assistant messages without tool calls + return true + }) +} + +async function getAgentSystemPrompt( + agentDefinition: AgentDefinition, + toolUseContext: Pick, + resolvedAgentModel: string, + additionalWorkingDirectories: string[], + resolvedTools: readonly Tool[], +): Promise { + const enabledToolNames = new Set(resolvedTools.map(t => t.name)) + try { + const agentPrompt = agentDefinition.getSystemPrompt({ toolUseContext }) + const prompts = [agentPrompt] + + return await enhanceSystemPromptWithEnvDetails( + prompts, + resolvedAgentModel, + additionalWorkingDirectories, + enabledToolNames, + ) + } catch (_error) { + return enhanceSystemPromptWithEnvDetails( + [DEFAULT_AGENT_PROMPT], + resolvedAgentModel, + additionalWorkingDirectories, + enabledToolNames, + ) + } +} + +/** + * Resolve a skill name from agent frontmatter to a registered command name. + * + * Plugin skills are registered with namespaced names (e.g., "my-plugin:my-skill") + * but agents reference them with bare names (e.g., "my-skill"). This function + * tries multiple resolution strategies: + * + * 1. Exact match via hasCommand (name, userFacingName, aliases) + * 2. Prefix with agent's plugin name (e.g., "my-skill" → "my-plugin:my-skill") + * 3. Suffix match — find any command whose name ends with ":skillName" + */ +function resolveSkillName( + skillName: string, + allSkills: Command[], + agentDefinition: AgentDefinition, +): string | null { + // 1. Direct match + if (hasCommand(skillName, allSkills)) { + return skillName + } + + // 2. Try prefixing with the agent's plugin name + // Plugin agents have agentType like "pluginName:agentName" + const pluginPrefix = agentDefinition.agentType.split(':')[0] + if (pluginPrefix) { + const qualifiedName = `${pluginPrefix}:${skillName}` + if (hasCommand(qualifiedName, allSkills)) { + return qualifiedName + } + } + + // 3. Suffix match — find a skill whose name ends with ":skillName" + const suffix = `:${skillName}` + const match = allSkills.find(cmd => cmd.name.endsWith(suffix)) + if (match) { + return match.name + } + + return null +} diff --git a/_all-in-one-upload/cc-haha/src/tools/BashTool/bashPermissions.ts b/_all-in-one-upload/cc-haha/src/tools/BashTool/bashPermissions.ts new file mode 100644 index 0000000..83b3c63 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/BashTool/bashPermissions.ts @@ -0,0 +1,2621 @@ +import { feature } from 'bun:bundle' +import { APIUserAbortError } from '@anthropic-ai/sdk' +import type { z } from 'zod/v4' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../../services/analytics/index.js' +import type { ToolPermissionContext, ToolUseContext } from '../../Tool.js' +import type { PendingClassifierCheck } from '../../types/permissions.js' +import { count } from '../../utils/array.js' +import { + checkSemantics, + nodeTypeId, + type ParseForSecurityResult, + parseForSecurityFromAst, + type Redirect, + type SimpleCommand, +} from '../../utils/bash/ast.js' +import { + type CommandPrefixResult, + extractOutputRedirections, + getCommandSubcommandPrefix, + splitCommand_DEPRECATED, +} from '../../utils/bash/commands.js' +import { parseCommandRaw } from '../../utils/bash/parser.js' +import { tryParseShellCommand } from '../../utils/bash/shellQuote.js' +import { getCwd } from '../../utils/cwd.js' +import { logForDebugging } from '../../utils/debug.js' +import { isEnvTruthy } from '../../utils/envUtils.js' +import { AbortError } from '../../utils/errors.js' +import type { + ClassifierBehavior, + ClassifierResult, +} from '../../utils/permissions/bashClassifier.js' +import { + classifyBashCommand, + getBashPromptAllowDescriptions, + getBashPromptAskDescriptions, + getBashPromptDenyDescriptions, + isClassifierPermissionsEnabled, +} from '../../utils/permissions/bashClassifier.js' +import type { + PermissionDecisionReason, + PermissionResult, +} from '../../utils/permissions/PermissionResult.js' +import type { + PermissionRule, + PermissionRuleValue, +} from '../../utils/permissions/PermissionRule.js' +import { extractRules } from '../../utils/permissions/PermissionUpdate.js' +import type { PermissionUpdate } from '../../utils/permissions/PermissionUpdateSchema.js' +import { permissionRuleValueToString } from '../../utils/permissions/permissionRuleParser.js' +import { + createPermissionRequestMessage, + getRuleByContentsForTool, +} from '../../utils/permissions/permissions.js' +import { + parsePermissionRule, + type ShellPermissionRule, + matchWildcardPattern as sharedMatchWildcardPattern, + permissionRuleExtractPrefix as sharedPermissionRuleExtractPrefix, + suggestionForExactCommand as sharedSuggestionForExactCommand, + suggestionForPrefix as sharedSuggestionForPrefix, +} from '../../utils/permissions/shellRuleMatching.js' +import { getPlatform } from '../../utils/platform.js' +import { SandboxManager } from '../../utils/sandbox/sandbox-adapter.js' +import { jsonStringify } from '../../utils/slowOperations.js' +import { windowsPathToPosixPath } from '../../utils/windowsPaths.js' +import { BashTool } from './BashTool.js' +import { checkCommandOperatorPermissions } from './bashCommandHelpers.js' +import { + bashCommandIsSafeAsync_DEPRECATED, + stripSafeHeredocSubstitutions, +} from './bashSecurity.js' +import { checkPermissionMode } from './modeValidation.js' +import { checkPathConstraints } from './pathValidation.js' +import { checkSedConstraints } from './sedValidation.js' +import { shouldUseSandbox } from './shouldUseSandbox.js' + +// DCE cliff: Bun's feature() evaluator has a per-function complexity budget. +// bashToolHasPermission is right at the limit. `import { X as Y }` aliases +// inside the import block count toward this budget; when they push it over +// the threshold Bun can no longer prove feature('BASH_CLASSIFIER') is a +// constant and silently evaluates the ternaries to `false`, dropping every +// pendingClassifierCheck spread. Keep aliases as top-level const rebindings +// instead. (See also the comment on checkSemanticsDeny below.) +const bashCommandIsSafeAsync = bashCommandIsSafeAsync_DEPRECATED +const splitCommand = splitCommand_DEPRECATED + +// Env-var assignment prefix (VAR=value). Shared across three while-loops that +// skip safe env vars before extracting the command name. +const ENV_VAR_ASSIGN_RE = /^[A-Za-z_]\w*=/ + +// CC-643: On complex compound commands, splitCommand_DEPRECATED can produce a +// very large subcommands array (possible exponential growth; #21405's ReDoS fix +// may have been incomplete). Each subcommand then runs tree-sitter parse + +// ~20 validators + logEvent (bashSecurity.ts), and with memoized metadata the +// resulting microtask chain starves the event loop — REPL freeze at 100% CPU, +// strace showed /proc/self/stat reads at ~127Hz with no epoll_wait. Fifty is +// generous: legitimate user commands don't split that wide. Above the cap we +// fall back to 'ask' (safe default — we can't prove safety, so we prompt). +export const MAX_SUBCOMMANDS_FOR_SECURITY_CHECK = 50 + +// GH#11380: Cap the number of per-subcommand rules suggested for compound +// commands. Beyond this, the "Yes, and don't ask again for X, Y, Z…" label +// degrades to "similar commands" anyway, and saving 10+ rules from one prompt +// is more likely noise than intent. Users chaining this many write commands +// in one && list are rare; they can always approve once and add rules manually. +export const MAX_SUGGESTED_RULES_FOR_COMPOUND = 5 + +/** + * [ANT-ONLY] Log classifier evaluation results for analysis. + * This helps us understand which classifier rules are being evaluated + * and how the classifier is deciding on commands. + */ +function logClassifierResultForAnts( + command: string, + behavior: ClassifierBehavior, + descriptions: string[], + result: ClassifierResult, +): void { + if (process.env.USER_TYPE !== 'ant') { + return + } + + logEvent('tengu_internal_bash_classifier_result', { + behavior: + behavior as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + descriptions: jsonStringify( + descriptions, + ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + matches: result.matches, + matchedDescription: (result.matchedDescription ?? + '') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + confidence: + result.confidence as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + reason: + result.reason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + // Note: command contains code/filepaths - this is ANT-ONLY so it's OK + command: + command as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }) +} + +/** + * Extract a stable command prefix (command + subcommand) from a raw command string. + * Skips leading env var assignments only if they are in SAFE_ENV_VARS (or + * ANT_ONLY_SAFE_ENV_VARS for ant users). Returns null if a non-safe env var is + * encountered (to fall back to exact match), or if the second token doesn't look + * like a subcommand (lowercase alphanumeric, e.g., "commit", "run"). + * + * Examples: + * 'git commit -m "fix typo"' → 'git commit' + * 'NODE_ENV=prod npm run build' → 'npm run' (NODE_ENV is safe) + * 'MY_VAR=val npm run build' → null (MY_VAR is not safe) + * 'ls -la' → null (flag, not a subcommand) + * 'cat file.txt' → null (filename, not a subcommand) + * 'chmod 755 file' → null (number, not a subcommand) + */ +export function getSimpleCommandPrefix(command: string): string | null { + const tokens = command.trim().split(/\s+/).filter(Boolean) + if (tokens.length === 0) return null + + // Skip env var assignments (VAR=value) at the start, but only if they are + // in SAFE_ENV_VARS (or ANT_ONLY_SAFE_ENV_VARS for ant users). If a non-safe + // env var is encountered, return null to fall back to exact match. This + // prevents generating prefix rules like Bash(npm run:*) that can never match + // at allow-rule check time, because stripSafeWrappers only strips safe vars. + let i = 0 + while (i < tokens.length && ENV_VAR_ASSIGN_RE.test(tokens[i]!)) { + const varName = tokens[i]!.split('=')[0]! + const isAntOnlySafe = + process.env.USER_TYPE === 'ant' && ANT_ONLY_SAFE_ENV_VARS.has(varName) + if (!SAFE_ENV_VARS.has(varName) && !isAntOnlySafe) { + return null + } + i++ + } + + const remaining = tokens.slice(i) + if (remaining.length < 2) return null + const subcmd = remaining[1]! + // Second token must look like a subcommand (e.g., "commit", "run", "compose"), + // not a flag (-rf), filename (file.txt), path (/tmp), URL, or number (755). + if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(subcmd)) return null + return remaining.slice(0, 2).join(' ') +} + +// Bare-prefix suggestions like `bash:*` or `sh:*` would allow arbitrary code +// via `-c`. Wrapper suggestions like `env:*` or `sudo:*` would do the same: +// `env` is NOT in SAFE_WRAPPER_PATTERNS, so `env bash -c "evil"` survives +// stripSafeWrappers unchanged and hits the startsWith("env ") check at +// the prefix-rule matcher. Shell list mirrors DANGEROUS_SHELL_PREFIXES in +// src/utils/shell/prefix.ts which guarded the old Haiku extractor. +const BARE_SHELL_PREFIXES = new Set([ + 'sh', + 'bash', + 'zsh', + 'fish', + 'csh', + 'tcsh', + 'ksh', + 'dash', + 'cmd', + 'powershell', + 'pwsh', + // wrappers that exec their args as a command + 'env', + 'xargs', + // SECURITY: checkSemantics (ast.ts) strips these wrappers to check the + // wrapped command. Suggesting `Bash(nice:*)` would be ≈ `Bash(*)` — users + // would add it after a prompt, then `nice rm -rf /` passes semantics while + // deny/cd+git gates see 'nice' (SAFE_WRAPPER_PATTERNS below didn't strip + // bare `nice` until this fix). Block these from ever being suggested. + 'nice', + 'stdbuf', + 'nohup', + 'timeout', + 'time', + // privilege escalation — sudo:* from `sudo -u foo ...` would auto-approve + // any future sudo invocation + 'sudo', + 'doas', + 'pkexec', +]) + +/** + * UI-only fallback: extract the first word alone when getSimpleCommandPrefix + * declines. In external builds TREE_SITTER_BASH is off, so the async + * tree-sitter refinement in BashPermissionRequest never fires — without this, + * pipes and compounds (`python3 file.py 2>&1 | tail -20`) dump into the + * editable field verbatim. + * + * Deliberately not used by suggestionForExactCommand: a backend-suggested + * `Bash(rm:*)` is too broad to auto-generate, but as an editable starting + * point it's what users expect (Slack C07VBSHV7EV/p1772670433193449). + * + * Reuses the same SAFE_ENV_VARS gate as getSimpleCommandPrefix — a rule like + * `Bash(python3:*)` can never match `RUN=/path python3 ...` at check time + * because stripSafeWrappers won't strip RUN. + */ +export function getFirstWordPrefix(command: string): string | null { + const tokens = command.trim().split(/\s+/).filter(Boolean) + + let i = 0 + while (i < tokens.length && ENV_VAR_ASSIGN_RE.test(tokens[i]!)) { + const varName = tokens[i]!.split('=')[0]! + const isAntOnlySafe = + process.env.USER_TYPE === 'ant' && ANT_ONLY_SAFE_ENV_VARS.has(varName) + if (!SAFE_ENV_VARS.has(varName) && !isAntOnlySafe) { + return null + } + i++ + } + + const cmd = tokens[i] + if (!cmd) return null + // Same shape check as the subcommand regex in getSimpleCommandPrefix: + // rejects paths (./script.sh, /usr/bin/python), flags, numbers, filenames. + if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(cmd)) return null + if (BARE_SHELL_PREFIXES.has(cmd)) return null + return cmd +} + +function suggestionForExactCommand(command: string): PermissionUpdate[] { + // Heredoc commands contain multi-line content that changes each invocation, + // making exact-match rules useless (they'll never match again). Extract a + // stable prefix before the heredoc operator and suggest a prefix rule instead. + const heredocPrefix = extractPrefixBeforeHeredoc(command) + if (heredocPrefix) { + return sharedSuggestionForPrefix(BashTool.name, heredocPrefix) + } + + // Multiline commands without heredoc also make poor exact-match rules. + // Saving the full multiline text can produce patterns containing `:*` in + // the middle, which fails permission validation and corrupts the settings + // file. Use the first line as a prefix rule instead. + if (command.includes('\n')) { + const firstLine = command.split('\n')[0]!.trim() + if (firstLine) { + return sharedSuggestionForPrefix(BashTool.name, firstLine) + } + } + + // Single-line commands: extract a 2-word prefix for reusable rules. + // Without this, exact-match rules are saved that never match future + // invocations with different arguments. + const prefix = getSimpleCommandPrefix(command) + if (prefix) { + return sharedSuggestionForPrefix(BashTool.name, prefix) + } + + return sharedSuggestionForExactCommand(BashTool.name, command) +} + +/** + * If the command contains a heredoc (<<), extract the command prefix before it. + * Returns the first word(s) before the heredoc operator as a stable prefix, + * or null if the command doesn't contain a heredoc. + * + * Examples: + * 'git commit -m "$(cat <<\'EOF\'\n...\nEOF\n)"' → 'git commit' + * 'cat <= tokens.length) return null + return tokens.slice(i, i + 2).join(' ') || null +} + +function suggestionForPrefix(prefix: string): PermissionUpdate[] { + return sharedSuggestionForPrefix(BashTool.name, prefix) +} + +/** + * Extract prefix from legacy :* syntax (e.g., "npm:*" -> "npm") + * Delegates to shared implementation. + */ +export const permissionRuleExtractPrefix = sharedPermissionRuleExtractPrefix + +/** + * Match a command against a wildcard pattern (case-sensitive for Bash). + * Delegates to shared implementation. + */ +export function matchWildcardPattern( + pattern: string, + command: string, +): boolean { + return sharedMatchWildcardPattern(pattern, command) +} + +/** + * Parse a permission rule into a structured rule object. + * Delegates to shared implementation. + */ +export const bashPermissionRule: ( + permissionRule: string, +) => ShellPermissionRule = parsePermissionRule + +/** + * Whitelist of environment variables that are safe to strip from commands. + * These variables CANNOT execute code or load libraries. + * + * SECURITY: These must NEVER be added to the whitelist: + * - PATH, LD_PRELOAD, LD_LIBRARY_PATH, DYLD_* (execution/library loading) + * - PYTHONPATH, NODE_PATH, CLASSPATH, RUBYLIB (module loading) + * - GOFLAGS, RUSTFLAGS, NODE_OPTIONS (can contain code execution flags) + * - HOME, TMPDIR, SHELL, BASH_ENV (affect system behavior) + */ +const SAFE_ENV_VARS = new Set([ + // Go - build/runtime settings only + 'GOEXPERIMENT', // experimental features + 'GOOS', // target OS + 'GOARCH', // target architecture + 'CGO_ENABLED', // enable/disable CGO + 'GO111MODULE', // module mode + + // Rust - logging/debugging only + 'RUST_BACKTRACE', // backtrace verbosity + 'RUST_LOG', // logging filter + + // Node - environment name only (not NODE_OPTIONS!) + 'NODE_ENV', + + // Python - behavior flags only (not PYTHONPATH!) + 'PYTHONUNBUFFERED', // disable buffering + 'PYTHONDONTWRITEBYTECODE', // no .pyc files + + // Pytest - test configuration + 'PYTEST_DISABLE_PLUGIN_AUTOLOAD', // disable plugin loading + 'PYTEST_DEBUG', // debug output + + // API keys and authentication + 'ANTHROPIC_API_KEY', // API authentication + + // Locale and character encoding + 'LANG', // default locale + 'LANGUAGE', // language preference list + 'LC_ALL', // override all locale settings + 'LC_CTYPE', // character classification + 'LC_TIME', // time format + 'CHARSET', // character set preference + + // Terminal and display + 'TERM', // terminal type + 'COLORTERM', // color terminal indicator + 'NO_COLOR', // disable color output (universal standard) + 'FORCE_COLOR', // force color output + 'TZ', // timezone + + // Color configuration for various tools + 'LS_COLORS', // colors for ls (GNU) + 'LSCOLORS', // colors for ls (BSD/macOS) + 'GREP_COLOR', // grep match color (deprecated) + 'GREP_COLORS', // grep color scheme + 'GCC_COLORS', // GCC diagnostic colors + + // Display formatting + 'TIME_STYLE', // time display format for ls + 'BLOCK_SIZE', // block size for du/df + 'BLOCKSIZE', // alternative block size +]) + +/** + * ANT-ONLY environment variables that are safe to strip from commands. + * These are only enabled when USER_TYPE === 'ant'. + * + * SECURITY: These env vars are stripped before permission-rule matching, which + * means `DOCKER_HOST=tcp://evil.com docker ps` matches a `Bash(docker ps:*)` + * rule after stripping. This is INTENTIONALLY ANT-ONLY (gated at line ~380) + * and MUST NEVER ship to external users. DOCKER_HOST redirects the Docker + * daemon endpoint — stripping it defeats prefix-based permission restrictions + * by hiding the network endpoint from the permission check. KUBECONFIG + * similarly controls which cluster kubectl talks to. These are convenience + * strippings for internal power users who accept the risk. + * + * Based on analysis of 30 days of tengu_internal_bash_tool_use_permission_request events. + */ +const ANT_ONLY_SAFE_ENV_VARS = new Set([ + // Kubernetes and container config (config file pointers, not execution) + 'KUBECONFIG', // kubectl config file path — controls which cluster kubectl uses + 'DOCKER_HOST', // Docker daemon socket/endpoint — controls which daemon docker talks to + + // Cloud provider project/profile selection (just names/identifiers) + 'AWS_PROFILE', // AWS profile name selection + 'CLOUDSDK_CORE_PROJECT', // GCP project ID + 'CLUSTER', // generic cluster name + + // Anthropic internal cluster selection (just names/identifiers) + 'COO_CLUSTER', // coo cluster name + 'COO_CLUSTER_NAME', // coo cluster name (alternate) + 'COO_NAMESPACE', // coo namespace + 'COO_LAUNCH_YAML_DRY_RUN', // dry run mode + + // Feature flags (boolean/string flags only) + 'SKIP_NODE_VERSION_CHECK', // skip version check + 'EXPECTTEST_ACCEPT', // accept test expectations + 'CI', // CI environment indicator + 'GIT_LFS_SKIP_SMUDGE', // skip LFS downloads + + // GPU/Device selection (just device IDs) + 'CUDA_VISIBLE_DEVICES', // GPU device selection + 'JAX_PLATFORMS', // JAX platform selection + + // Display/terminal settings + 'COLUMNS', // terminal width + 'TMUX', // TMUX socket info + + // Test/debug configuration + 'POSTGRESQL_VERSION', // postgres version string + 'FIRESTORE_EMULATOR_HOST', // emulator host:port + 'HARNESS_QUIET', // quiet mode flag + 'TEST_CROSSCHECK_LISTS_MATCH_UPDATE', // test update flag + 'DBT_PER_DEVELOPER_ENVIRONMENTS', // DBT config + 'STATSIG_FORD_DB_CHECKS', // statsig DB check flag + + // Build configuration + 'ANT_ENVIRONMENT', // Anthropic environment name + 'ANT_SERVICE', // Anthropic service name + 'MONOREPO_ROOT_DIR', // monorepo root path + + // Version selectors + 'PYENV_VERSION', // Python version selection + + // Credentials (approved subset - these don't change exfil risk) + 'PGPASSWORD', // Postgres password + 'GH_TOKEN', // GitHub token + 'GROWTHBOOK_API_KEY', // self-hosted growthbook +]) + +/** + * Strips full-line comments from a command. + * This handles cases where Claude adds comments in bash commands, e.g.: + * "# Check the logs directory\nls /home/user/logs" + * Should be stripped to: "ls /home/user/logs" + * + * Only strips full-line comments (lines where the entire line is a comment), + * not inline comments that appear after a command on the same line. + */ +function stripCommentLines(command: string): string { + const lines = command.split('\n') + const nonCommentLines = lines.filter(line => { + const trimmed = line.trim() + // Keep lines that are not empty and don't start with # + return trimmed !== '' && !trimmed.startsWith('#') + }) + + // If all lines were comments/empty, return original + if (nonCommentLines.length === 0) { + return command + } + + return nonCommentLines.join('\n') +} + +export function stripSafeWrappers(command: string): string { + // SECURITY: Use [ \t]+ not \s+ — \s matches \n/\r which are command + // separators in bash. Matching across a newline would strip the wrapper from + // one line and leave a different command on the next line for bash to execute. + // + // SECURITY: `(?:--[ \t]+)?` consumes the wrapper's own `--` so + // `nohup -- rm -- -/../foo` strips to `rm -- -/../foo` (not `-- rm ...` + // which would skip path validation with `--` as an unknown baseCmd). + const SAFE_WRAPPER_PATTERNS = [ + // timeout: enumerate GNU long flags — no-value (--foreground, + // --preserve-status, --verbose), value-taking in both =fused and + // space-separated forms (--kill-after=5, --kill-after 5, --signal=TERM, + // --signal TERM). Short: -v (no-arg), -k/-s with separate or fused value. + // SECURITY: flag VALUES use allowlist [A-Za-z0-9_.+-] (signals are + // TERM/KILL/9, durations are 5/5s/10.5). Previously [^ \t]+ matched + // $ ( ) ` | ; & — `timeout -k$(id) 10 ls` stripped to `ls`, matched + // Bash(ls:*), while bash expanded $(id) during word splitting BEFORE + // timeout ran. Contrast ENV_VAR_PATTERN below which already allowlists. + /^timeout[ \t]+(?:(?:--(?:foreground|preserve-status|verbose)|--(?:kill-after|signal)=[A-Za-z0-9_.+-]+|--(?:kill-after|signal)[ \t]+[A-Za-z0-9_.+-]+|-v|-[ks][ \t]+[A-Za-z0-9_.+-]+|-[ks][A-Za-z0-9_.+-]+)[ \t]+)*(?:--[ \t]+)?\d+(?:\.\d+)?[smhd]?[ \t]+/, + /^time[ \t]+(?:--[ \t]+)?/, + // SECURITY: keep in sync with checkSemantics wrapper-strip (ast.ts + // ~:1990-2080) AND stripWrappersFromArgv (pathValidation.ts ~:1260). + // Previously this pattern REQUIRED `-n N`; checkSemantics already handled + // bare `nice` and legacy `-N`. Asymmetry meant checkSemantics exposed the + // wrapped command to semantic checks but deny-rule matching and the cd+git + // gate saw the wrapper name. `nice rm -rf /` with Bash(rm:*) deny became + // ask instead of deny; `cd evil && nice git status` skipped the bare-repo + // RCE gate. PR #21503 fixed stripWrappersFromArgv; this was missed. + // Now matches: `nice cmd`, `nice -n N cmd`, `nice -N cmd` (all forms + // checkSemantics strips). + /^nice(?:[ \t]+-n[ \t]+-?\d+|[ \t]+-\d+)?[ \t]+(?:--[ \t]+)?/, + // stdbuf: fused short flags only (-o0, -eL). checkSemantics handles more + // (space-separated, long --output=MODE), but we fail-closed on those + // above so not over-stripping here is safe. Main need: `stdbuf -o0 cmd`. + /^stdbuf(?:[ \t]+-[ioe][LN0-9]+)+[ \t]+(?:--[ \t]+)?/, + /^nohup[ \t]+(?:--[ \t]+)?/, + ] as const + + // Pattern for environment variables: + // ^([A-Za-z_][A-Za-z0-9_]*) - Variable name (standard identifier) + // = - Equals sign + // ([A-Za-z0-9_./:-]+) - Value: alphanumeric + safe punctuation only + // [ \t]+ - Required HORIZONTAL whitespace after value + // + // SECURITY: Only matches unquoted values with safe characters (no $(), `, $var, ;|&). + // + // SECURITY: Trailing whitespace MUST be [ \t]+ (horizontal only), NOT \s+. + // \s matches \n/\r. If reconstructCommand emits an unquoted newline between + // `TZ=UTC` and `echo`, \s+ would match across it and strip `TZ=UTC`, + // leaving `echo curl evil.com` to match Bash(echo:*). But bash treats the + // newline as a command separator. Defense-in-depth with needsQuoting fix. + const ENV_VAR_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)=([A-Za-z0-9_./:-]+)[ \t]+/ + + let stripped = command + let previousStripped = '' + + // Phase 1: Strip leading env vars and comments only. + // In bash, env var assignments before a command (VAR=val cmd) are genuine + // shell-level assignments. These are safe to strip for permission matching. + while (stripped !== previousStripped) { + previousStripped = stripped + stripped = stripCommentLines(stripped) + + const envVarMatch = stripped.match(ENV_VAR_PATTERN) + if (envVarMatch) { + const varName = envVarMatch[1]! + const isAntOnlySafe = + process.env.USER_TYPE === 'ant' && ANT_ONLY_SAFE_ENV_VARS.has(varName) + if (SAFE_ENV_VARS.has(varName) || isAntOnlySafe) { + stripped = stripped.replace(ENV_VAR_PATTERN, '') + } + } + } + + // Phase 2: Strip wrapper commands and comments only. Do NOT strip env vars. + // Wrapper commands (timeout, time, nice, nohup) use execvp to run their + // arguments, so VAR=val after a wrapper is treated as the COMMAND to execute, + // not as an env var assignment. Stripping env vars here would create a + // mismatch between what the parser sees and what actually executes. + // (HackerOne #3543050) + previousStripped = '' + while (stripped !== previousStripped) { + previousStripped = stripped + stripped = stripCommentLines(stripped) + + for (const pattern of SAFE_WRAPPER_PATTERNS) { + stripped = stripped.replace(pattern, '') + } + } + + return stripped.trim() +} + +// SECURITY: allowlist for timeout flag VALUES (signals are TERM/KILL/9, +// durations are 5/5s/10.5). Rejects $ ( ) ` | ; & and newlines that +// previously matched via [^ \t]+ — `timeout -k$(id) 10 ls` must NOT strip. +const TIMEOUT_FLAG_VALUE_RE = /^[A-Za-z0-9_.+-]+$/ + +/** + * Parse timeout's GNU flags (long + short, fused + space-separated) and + * return the argv index of the DURATION token, or -1 if flags are unparseable. + * Enumerates: --foreground/--preserve-status/--verbose (no value), + * --kill-after/--signal (value, both =fused and space-separated), -v (no + * value), -k/-s (value, both fused and space-separated). + * + * Extracted from stripWrappersFromArgv to keep bashToolHasPermission under + * Bun's feature() DCE complexity threshold — inlining this breaks + * feature('BASH_CLASSIFIER') evaluation in classifier tests. + */ +function skipTimeoutFlags(a: readonly string[]): number { + let i = 1 + while (i < a.length) { + const arg = a[i]! + const next = a[i + 1] + if ( + arg === '--foreground' || + arg === '--preserve-status' || + arg === '--verbose' + ) + i++ + else if (/^--(?:kill-after|signal)=[A-Za-z0-9_.+-]+$/.test(arg)) i++ + else if ( + (arg === '--kill-after' || arg === '--signal') && + next && + TIMEOUT_FLAG_VALUE_RE.test(next) + ) + i += 2 + else if (arg === '--') { + i++ + break + } // end-of-options marker + else if (arg.startsWith('--')) return -1 + else if (arg === '-v') i++ + else if ( + (arg === '-k' || arg === '-s') && + next && + TIMEOUT_FLAG_VALUE_RE.test(next) + ) + i += 2 + else if (/^-[ks][A-Za-z0-9_.+-]+$/.test(arg)) i++ + else if (arg.startsWith('-')) return -1 + else break + } + return i +} + +/** + * Argv-level counterpart to stripSafeWrappers. Strips the same wrapper + * commands (timeout, time, nice, nohup) from AST-derived argv. Env vars + * are already separated into SimpleCommand.envVars so no env-var stripping. + * + * KEEP IN SYNC with SAFE_WRAPPER_PATTERNS above — if you add a wrapper + * there, add it here too. + */ +export function stripWrappersFromArgv(argv: string[]): string[] { + // SECURITY: Consume optional `--` after wrapper options, matching what the + // wrapper does. Otherwise `['nohup','--','rm','--','-/../foo']` yields `--` + // as baseCmd and skips path validation. See SAFE_WRAPPER_PATTERNS comment. + let a = argv + for (;;) { + if (a[0] === 'time' || a[0] === 'nohup') { + a = a.slice(a[1] === '--' ? 2 : 1) + } else if (a[0] === 'timeout') { + const i = skipTimeoutFlags(a) + if (i < 0 || !a[i] || !/^\d+(?:\.\d+)?[smhd]?$/.test(a[i]!)) return a + a = a.slice(i + 1) + } else if ( + a[0] === 'nice' && + a[1] === '-n' && + a[2] && + /^-?\d+$/.test(a[2]) + ) { + a = a.slice(a[3] === '--' ? 4 : 3) + } else { + return a + } + } +} + +/** + * Env vars that make a *different binary* run (injection or resolution hijack). + * Heuristic only — export-&& form bypasses this, and excludedCommands isn't a + * security boundary anyway. + */ +export const BINARY_HIJACK_VARS = /^(LD_|DYLD_|PATH$)/ + +/** + * Strip ALL leading env var prefixes from a command, regardless of whether the + * var name is in the safe-list. + * + * Used for deny/ask rule matching: when a user denies `claude` or `rm`, the + * command should stay blocked even if prefixed with arbitrary env vars like + * `FOO=bar claude`. The safe-list restriction in stripSafeWrappers is correct + * for allow rules (prevents `DOCKER_HOST=evil docker ps` from auto-matching + * `Bash(docker ps:*)`), but deny rules must be harder to circumvent. + * + * Also used for sandbox.excludedCommands matching (not a security boundary — + * permission prompts are), with BINARY_HIJACK_VARS as a blocklist. + * + * SECURITY: Uses a broader value pattern than stripSafeWrappers. The value + * pattern excludes only actual shell injection characters ($, backtick, ;, |, + * &, parens, redirects, quotes, backslash) and whitespace. Characters like + * =, +, @, ~, , are harmless in unquoted env var assignment position and must + * be matched to prevent trivial bypass via e.g. `FOO=a=b denied_command`. + * + * @param blocklist - optional regex tested against each var name; matching vars + * are NOT stripped (and stripping stops there). Omit for deny rules; pass + * BINARY_HIJACK_VARS for excludedCommands. + */ +export function stripAllLeadingEnvVars( + command: string, + blocklist?: RegExp, +): string { + // Broader value pattern for deny-rule stripping. Handles: + // + // - Standard assignment (FOO=bar), append (FOO+=bar), array (FOO[0]=bar) + // - Single-quoted values: '[^'\n\r]*' — bash suppresses all expansion + // - Double-quoted values with backslash escapes: "(?:\\.|[^"$`\\\n\r])*" + // In bash double quotes, only \$, \`, \", \\, and \newline are special. + // Other \x sequences are harmless, so we allow \. inside double quotes. + // We still exclude raw $ and ` (without backslash) to block expansion. + // - Unquoted values: excludes shell metacharacters, allows backslash escapes + // - Concatenated segments: FOO='x'y"z" — bash concatenates adjacent segments + // + // SECURITY: Trailing whitespace MUST be [ \t]+ (horizontal only), NOT \s+. + // + // The outer * matches one atomic unit per iteration: a complete quoted + // string, a backslash-escape pair, or a single unquoted safe character. + // The inner double-quote alternation (?:...|...)* is bounded by the + // closing ", so it cannot interact with the outer * for backtracking. + // + // Note: $ is excluded from unquoted/double-quoted value classes to block + // dangerous forms like $(cmd), ${var}, and $((expr)). This means + // FOO=$VAR is not stripped — adding $VAR matching creates ReDoS risk + // (CodeQL #671) and $VAR bypasses are low-priority. + const ENV_VAR_PATTERN = + /^([A-Za-z_][A-Za-z0-9_]*(?:\[[^\]]*\])?)\+?=(?:'[^'\n\r]*'|"(?:\\.|[^"$`\\\n\r])*"|\\.|[^ \t\n\r$`;|&()<>\\\\'"])*[ \t]+/ + + let stripped = command + let previousStripped = '' + + while (stripped !== previousStripped) { + previousStripped = stripped + stripped = stripCommentLines(stripped) + + const m = stripped.match(ENV_VAR_PATTERN) + if (!m) continue + if (blocklist?.test(m[1]!)) break + stripped = stripped.slice(m[0].length) + } + + return stripped.trim() +} + +function filterRulesByContentsMatchingInput( + input: z.infer, + rules: Map, + matchMode: 'exact' | 'prefix', + { + stripAllEnvVars = false, + skipCompoundCheck = false, + }: { stripAllEnvVars?: boolean; skipCompoundCheck?: boolean } = {}, +): PermissionRule[] { + const command = input.command.trim() + + // Strip output redirections for permission matching + // This allows rules like Bash(python:*) to match "python script.py > output.txt" + // Security validation of redirection targets happens separately in checkPathConstraints + const commandWithoutRedirections = + extractOutputRedirections(command).commandWithoutRedirections + + // For exact matching, try both the original command (to preserve quotes) + // and the command without redirections (to allow rules without redirections to match) + // For prefix matching, only use the command without redirections + const commandsForMatching = + matchMode === 'exact' + ? [command, commandWithoutRedirections] + : [commandWithoutRedirections] + + // Strip safe wrapper commands (timeout, time, nice, nohup) and env vars for matching + // This allows rules like Bash(npm install:*) to match "timeout 10 npm install foo" + // or "GOOS=linux go build" + const commandsToTry = commandsForMatching.flatMap(cmd => { + const strippedCommand = stripSafeWrappers(cmd) + return strippedCommand !== cmd ? [cmd, strippedCommand] : [cmd] + }) + + // SECURITY: For deny/ask rules, also try matching after stripping ALL leading + // env var prefixes. This prevents bypass via `FOO=bar denied_command` where + // FOO is not in the safe-list. The safe-list restriction in stripSafeWrappers + // is intentional for allow rules (see HackerOne #3543050), but deny rules + // must be harder to circumvent — a denied command should stay denied + // regardless of env var prefixes. + // + // We iteratively apply both stripping operations to all candidates until no + // new candidates are produced (fixed-point). This handles interleaved patterns + // like `nohup FOO=bar timeout 5 claude` where: + // 1. stripSafeWrappers strips `nohup` → `FOO=bar timeout 5 claude` + // 2. stripAllLeadingEnvVars strips `FOO=bar` → `timeout 5 claude` + // 3. stripSafeWrappers strips `timeout 5` → `claude` (deny match) + // + // Without iteration, single-pass compositions miss multi-layer interleaving. + if (stripAllEnvVars) { + const seen = new Set(commandsToTry) + let startIdx = 0 + + // Iterate until no new candidates are produced (fixed-point) + while (startIdx < commandsToTry.length) { + const endIdx = commandsToTry.length + for (let i = startIdx; i < endIdx; i++) { + const cmd = commandsToTry[i] + if (!cmd) { + continue + } + // Try stripping env vars + const envStripped = stripAllLeadingEnvVars(cmd) + if (!seen.has(envStripped)) { + commandsToTry.push(envStripped) + seen.add(envStripped) + } + // Try stripping safe wrappers + const wrapperStripped = stripSafeWrappers(cmd) + if (!seen.has(wrapperStripped)) { + commandsToTry.push(wrapperStripped) + seen.add(wrapperStripped) + } + } + startIdx = endIdx + } + } + + // Precompute compound-command status for each candidate to avoid re-parsing + // inside the rule filter loop (which would scale splitCommand calls with + // rules.length × commandsToTry.length). The compound check only applies to + // prefix/wildcard matching in 'prefix' mode, and only for allow rules. + // SECURITY: deny/ask rules must match compound commands so they can't be + // bypassed by wrapping a denied command in a compound expression. + const isCompoundCommand = new Map() + if (matchMode === 'prefix' && !skipCompoundCheck) { + for (const cmd of commandsToTry) { + if (!isCompoundCommand.has(cmd)) { + isCompoundCommand.set(cmd, splitCommand(cmd).length > 1) + } + } + } + + return Array.from(rules.entries()) + .filter(([ruleContent]) => { + const bashRule = bashPermissionRule(ruleContent) + + return commandsToTry.some(cmdToMatch => { + switch (bashRule.type) { + case 'exact': + return bashRule.command === cmdToMatch + case 'prefix': + switch (matchMode) { + // In 'exact' mode, only return true if the command exactly matches the prefix rule + case 'exact': + return bashRule.prefix === cmdToMatch + case 'prefix': { + // SECURITY: Don't allow prefix rules to match compound commands. + // e.g., Bash(cd:*) must NOT match "cd /path && python3 evil.py". + // In the normal flow commands are split before reaching here, but + // shell escaping can defeat the first splitCommand pass — e.g., + // cd src\&\& python3 hello.py → splitCommand → ["cd src&& python3 hello.py"] + // which then looks like a single command that starts with "cd ". + // Re-splitting the candidate here catches those cases. + if (isCompoundCommand.get(cmdToMatch)) { + return false + } + // Ensure word boundary: prefix must be followed by space or end of string + // This prevents "ls:*" from matching "lsof" or "lsattr" + if (cmdToMatch === bashRule.prefix) { + return true + } + if (cmdToMatch.startsWith(bashRule.prefix + ' ')) { + return true + } + // Also match "xargs " for bare xargs with no flags. + // This allows Bash(grep:*) to match "xargs grep pattern", + // and deny rules like Bash(rm:*) to block "xargs rm file". + // Natural word-boundary: "xargs -n1 grep" does NOT start with + // "xargs grep " so flagged xargs invocations are not matched. + const xargsPrefix = 'xargs ' + bashRule.prefix + if (cmdToMatch === xargsPrefix) { + return true + } + return cmdToMatch.startsWith(xargsPrefix + ' ') + } + } + break + case 'wildcard': + // SECURITY FIX: In exact match mode, wildcards must NOT match because we're + // checking the full unparsed command. Wildcard matching on unparsed commands + // allows "foo *" to match "foo arg && curl evil.com" since .* matches operators. + // Wildcards should only match after splitting into individual subcommands. + if (matchMode === 'exact') { + return false + } + // SECURITY: Same as for prefix rules, don't allow wildcard rules to match + // compound commands in prefix mode. e.g., Bash(cd *) must not match + // "cd /path && python3 evil.py" even though "cd *" pattern would match it. + if (isCompoundCommand.get(cmdToMatch)) { + return false + } + // In prefix mode (after splitting), wildcards can safely match subcommands + return matchWildcardPattern(bashRule.pattern, cmdToMatch) + } + }) + }) + .map(([, rule]) => rule) +} + +function matchingRulesForInput( + input: z.infer, + toolPermissionContext: ToolPermissionContext, + matchMode: 'exact' | 'prefix', + { skipCompoundCheck = false }: { skipCompoundCheck?: boolean } = {}, +) { + const denyRuleByContents = getRuleByContentsForTool( + toolPermissionContext, + BashTool, + 'deny', + ) + // SECURITY: Deny/ask rules use aggressive env var stripping so that + // `FOO=bar denied_command` still matches a deny rule for `denied_command`. + const matchingDenyRules = filterRulesByContentsMatchingInput( + input, + denyRuleByContents, + matchMode, + { stripAllEnvVars: true, skipCompoundCheck: true }, + ) + + const askRuleByContents = getRuleByContentsForTool( + toolPermissionContext, + BashTool, + 'ask', + ) + const matchingAskRules = filterRulesByContentsMatchingInput( + input, + askRuleByContents, + matchMode, + { stripAllEnvVars: true, skipCompoundCheck: true }, + ) + + const allowRuleByContents = getRuleByContentsForTool( + toolPermissionContext, + BashTool, + 'allow', + ) + const matchingAllowRules = filterRulesByContentsMatchingInput( + input, + allowRuleByContents, + matchMode, + { skipCompoundCheck }, + ) + + return { + matchingDenyRules, + matchingAskRules, + matchingAllowRules, + } +} + +/** + * Checks if the subcommand is an exact match for a permission rule + */ +export const bashToolCheckExactMatchPermission = ( + input: z.infer, + toolPermissionContext: ToolPermissionContext, +): PermissionResult => { + const command = input.command.trim() + const { matchingDenyRules, matchingAskRules, matchingAllowRules } = + matchingRulesForInput(input, toolPermissionContext, 'exact') + + // 1. Deny if exact command was denied + if (matchingDenyRules[0] !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${command} has been denied.`, + decisionReason: { + type: 'rule', + rule: matchingDenyRules[0], + }, + } + } + + // 2. Ask if exact command was in ask rules + if (matchingAskRules[0] !== undefined) { + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name), + decisionReason: { + type: 'rule', + rule: matchingAskRules[0], + }, + } + } + + // 3. Allow if exact command was allowed + if (matchingAllowRules[0] !== undefined) { + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'rule', + rule: matchingAllowRules[0], + }, + } + } + + // 4. Otherwise, passthrough + const decisionReason = { + type: 'other' as const, + reason: 'This command requires approval', + } + return { + behavior: 'passthrough', + message: createPermissionRequestMessage(BashTool.name, decisionReason), + decisionReason, + // Suggest exact match rule to user + // this may be overridden by prefix suggestions in `checkCommandAndSuggestRules()` + suggestions: suggestionForExactCommand(command), + } +} + +export const bashToolCheckPermission = ( + input: z.infer, + toolPermissionContext: ToolPermissionContext, + compoundCommandHasCd?: boolean, + astCommand?: SimpleCommand, +): PermissionResult => { + const command = input.command.trim() + + // 1. Check exact match first + const exactMatchResult = bashToolCheckExactMatchPermission( + input, + toolPermissionContext, + ) + + // 1a. Deny/ask if exact command has a rule + if ( + exactMatchResult.behavior === 'deny' || + exactMatchResult.behavior === 'ask' + ) { + return exactMatchResult + } + + // 2. Find all matching rules (prefix or exact) + // SECURITY FIX: Check Bash deny/ask rules BEFORE path constraints to prevent bypass + // via absolute paths outside the project directory (HackerOne report) + // When AST-parsed, the subcommand is already atomic — skip the legacy + // splitCommand re-check that misparses mid-word # as compound. + const { matchingDenyRules, matchingAskRules, matchingAllowRules } = + matchingRulesForInput(input, toolPermissionContext, 'prefix', { + skipCompoundCheck: astCommand !== undefined, + }) + + // 2a. Deny if command has a deny rule + if (matchingDenyRules[0] !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${command} has been denied.`, + decisionReason: { + type: 'rule', + rule: matchingDenyRules[0], + }, + } + } + + // 2b. Ask if command has an ask rule + if (matchingAskRules[0] !== undefined) { + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name), + decisionReason: { + type: 'rule', + rule: matchingAskRules[0], + }, + } + } + + // 3. Check path constraints + // This check comes after deny/ask rules so explicit rules take precedence. + // SECURITY: When AST-derived argv is available for this subcommand, pass + // it through so checkPathConstraints uses it directly instead of re-parsing + // with shell-quote (which has a single-quote backslash bug that causes + // parseCommandArguments to return [] and silently skip path validation). + const pathResult = checkPathConstraints( + input, + getCwd(), + toolPermissionContext, + compoundCommandHasCd, + astCommand?.redirects, + astCommand ? [astCommand] : undefined, + ) + if (pathResult.behavior !== 'passthrough') { + return pathResult + } + + // 4. Allow if command had an exact match allow + if (exactMatchResult.behavior === 'allow') { + return exactMatchResult + } + + // 5. Allow if command has an allow rule + if (matchingAllowRules[0] !== undefined) { + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'rule', + rule: matchingAllowRules[0], + }, + } + } + + // 5b. Check sed constraints (blocks dangerous sed operations before mode auto-allow) + const sedConstraintResult = checkSedConstraints(input, toolPermissionContext) + if (sedConstraintResult.behavior !== 'passthrough') { + return sedConstraintResult + } + + // 6. Check for mode-specific permission handling + const modeResult = checkPermissionMode(input, toolPermissionContext) + if (modeResult.behavior !== 'passthrough') { + return modeResult + } + + // 7. Check read-only rules + if (BashTool.isReadOnly(input)) { + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'other', + reason: 'Read-only command is allowed', + }, + } + } + + // 8. Passthrough since no rules match, will trigger permission prompt + const decisionReason = { + type: 'other' as const, + reason: 'This command requires approval', + } + return { + behavior: 'passthrough', + message: createPermissionRequestMessage(BashTool.name, decisionReason), + decisionReason, + // Suggest exact match rule to user + // this may be overridden by prefix suggestions in `checkCommandAndSuggestRules()` + suggestions: suggestionForExactCommand(command), + } +} + +/** + * Processes an individual subcommand and applies prefix checks & suggestions + */ +export async function checkCommandAndSuggestRules( + input: z.infer, + toolPermissionContext: ToolPermissionContext, + commandPrefixResult: CommandPrefixResult | null | undefined, + compoundCommandHasCd?: boolean, + astParseSucceeded?: boolean, +): Promise { + // 1. Check exact match first + const exactMatchResult = bashToolCheckExactMatchPermission( + input, + toolPermissionContext, + ) + if (exactMatchResult.behavior !== 'passthrough') { + return exactMatchResult + } + + // 2. Check the command prefix + const permissionResult = bashToolCheckPermission( + input, + toolPermissionContext, + compoundCommandHasCd, + ) + // 2a. Deny/ask if command was explictly denied/asked + if ( + permissionResult.behavior === 'deny' || + permissionResult.behavior === 'ask' + ) { + return permissionResult + } + + // 3. Ask for permission if command injection is detected. Skip when the + // AST parse already succeeded — tree-sitter has verified there are no + // hidden substitutions or structural tricks, so the legacy regex-based + // validators (backslash-escaped operators, etc.) would only add FPs. + if ( + !astParseSucceeded && + !isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_COMMAND_INJECTION_CHECK) + ) { + const safetyResult = await bashCommandIsSafeAsync(input.command) + + if (safetyResult.behavior !== 'passthrough') { + const decisionReason: PermissionDecisionReason = { + type: 'other' as const, + reason: + safetyResult.behavior === 'ask' && safetyResult.message + ? safetyResult.message + : 'This command contains patterns that could pose security risks and requires approval', + } + + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name, decisionReason), + decisionReason, + suggestions: [], // Don't suggest saving a potentially dangerous command + } + } + } + + // 4. Allow if command was allowed + if (permissionResult.behavior === 'allow') { + return permissionResult + } + + // 5. Suggest prefix if available, otherwise exact command + const suggestedUpdates = commandPrefixResult?.commandPrefix + ? suggestionForPrefix(commandPrefixResult.commandPrefix) + : suggestionForExactCommand(input.command) + + return { + ...permissionResult, + suggestions: suggestedUpdates, + } +} + +/** + * Checks if a command should be auto-allowed when sandboxed. + * Returns early if there are explicit deny/ask rules that should be respected. + * + * NOTE: This function should only be called when sandboxing and auto-allow are enabled. + * + * @param input - The bash tool input + * @param toolPermissionContext - The permission context + * @returns PermissionResult with: + * - deny/ask if explicit rule exists (exact or prefix) + * - allow if no explicit rules (sandbox auto-allow applies) + * - passthrough should not occur since we're in auto-allow mode + */ +function checkSandboxAutoAllow( + input: z.infer, + toolPermissionContext: ToolPermissionContext, +): PermissionResult { + const command = input.command.trim() + + // Check for explicit deny/ask rules on the full command (exact + prefix) + const { matchingDenyRules, matchingAskRules } = matchingRulesForInput( + input, + toolPermissionContext, + 'prefix', + ) + + // Return immediately if there's an explicit deny rule on the full command + if (matchingDenyRules[0] !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${command} has been denied.`, + decisionReason: { + type: 'rule', + rule: matchingDenyRules[0], + }, + } + } + + // SECURITY: For compound commands, check each subcommand against deny/ask + // rules. Prefix rules like Bash(rm:*) won't match the full compound command + // (e.g., "echo hello && rm -rf /" doesn't start with "rm"), so we must + // check each subcommand individually. + // IMPORTANT: Subcommand deny checks must run BEFORE full-command ask returns. + // Otherwise a wildcard ask rule matching the full command (e.g., Bash(*echo*)) + // would return 'ask' before a prefix deny rule on a subcommand (e.g., Bash(rm:*)) + // gets checked, downgrading a deny to an ask. + const subcommands = splitCommand(command) + if (subcommands.length > 1) { + let firstAskRule: PermissionRule | undefined + for (const sub of subcommands) { + const subResult = matchingRulesForInput( + { command: sub }, + toolPermissionContext, + 'prefix', + ) + // Deny takes priority — return immediately + if (subResult.matchingDenyRules[0] !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${command} has been denied.`, + decisionReason: { + type: 'rule', + rule: subResult.matchingDenyRules[0], + }, + } + } + // Stash first ask match; don't return yet (deny across all subs takes priority) + firstAskRule ??= subResult.matchingAskRules[0] + } + if (firstAskRule) { + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name), + decisionReason: { + type: 'rule', + rule: firstAskRule, + }, + } + } + } + + // Full-command ask check (after all deny sources have been exhausted) + if (matchingAskRules[0] !== undefined) { + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name), + decisionReason: { + type: 'rule', + rule: matchingAskRules[0], + }, + } + } + // No explicit rules, so auto-allow with sandbox + + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'other', + reason: 'Auto-allowed with sandbox (autoAllowBashIfSandboxed enabled)', + }, + } +} + +/** + * Filter out `cd ${cwd}` prefix subcommands, keeping astCommands aligned. + * Extracted to keep bashToolHasPermission under Bun's feature() DCE + * complexity threshold — inlining this breaks pendingClassifierCheck + * attachment in ~10 classifier tests. + */ +function filterCdCwdSubcommands( + rawSubcommands: string[], + astCommands: SimpleCommand[] | undefined, + cwd: string, + cwdMingw: string, +): { subcommands: string[]; astCommandsByIdx: (SimpleCommand | undefined)[] } { + const subcommands: string[] = [] + const astCommandsByIdx: (SimpleCommand | undefined)[] = [] + for (let i = 0; i < rawSubcommands.length; i++) { + const cmd = rawSubcommands[i]! + if (cmd === `cd ${cwd}` || cmd === `cd ${cwdMingw}`) continue + subcommands.push(cmd) + astCommandsByIdx.push(astCommands?.[i]) + } + return { subcommands, astCommandsByIdx } +} + +/** + * Early-exit deny enforcement for the AST too-complex and checkSemantics + * paths. Returns the exact-match result if non-passthrough (deny/ask/allow), + * then checks prefix/wildcard deny rules. Returns null if neither matched, + * meaning the caller should fall through to ask. Extracted to keep + * bashToolHasPermission under Bun's feature() DCE complexity threshold. + */ +function checkEarlyExitDeny( + input: z.infer, + toolPermissionContext: ToolPermissionContext, +): PermissionResult | null { + const exactMatchResult = bashToolCheckExactMatchPermission( + input, + toolPermissionContext, + ) + if (exactMatchResult.behavior !== 'passthrough') { + return exactMatchResult + } + const denyMatch = matchingRulesForInput( + input, + toolPermissionContext, + 'prefix', + ).matchingDenyRules[0] + if (denyMatch !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${input.command} has been denied.`, + decisionReason: { type: 'rule', rule: denyMatch }, + } + } + return null +} + +/** + * checkSemantics-path deny enforcement. Calls checkEarlyExitDeny (exact-match + * + full-command prefix deny), then checks each individual SimpleCommand .text + * span against prefix deny rules. The per-subcommand check is needed because + * filterRulesByContentsMatchingInput has a compound-command guard + * (splitCommand().length > 1 → prefix rules return false) that defeats + * `Bash(eval:*)` matching against a full pipeline like `echo foo | eval rm`. + * Each SimpleCommand span is a single command, so the guard doesn't fire. + * + * Separate helper (not folded into checkEarlyExitDeny or inlined at the call + * site) because bashToolHasPermission is tight against Bun's feature() DCE + * complexity threshold — adding even ~5 lines there breaks + * feature('BASH_CLASSIFIER') evaluation and drops pendingClassifierCheck. + */ +function checkSemanticsDeny( + input: z.infer, + toolPermissionContext: ToolPermissionContext, + commands: readonly { text: string }[], +): PermissionResult | null { + const fullCmd = checkEarlyExitDeny(input, toolPermissionContext) + if (fullCmd !== null) return fullCmd + for (const cmd of commands) { + const subDeny = matchingRulesForInput( + { ...input, command: cmd.text }, + toolPermissionContext, + 'prefix', + ).matchingDenyRules[0] + if (subDeny !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${input.command} has been denied.`, + decisionReason: { type: 'rule', rule: subDeny }, + } + } + } + return null +} + +/** + * Builds the pending classifier check metadata if classifier is enabled and has allow descriptions. + * Returns undefined if classifier is disabled, in auto mode, or no allow descriptions exist. + */ +function buildPendingClassifierCheck( + command: string, + toolPermissionContext: ToolPermissionContext, +): { command: string; cwd: string; descriptions: string[] } | undefined { + if (!isClassifierPermissionsEnabled()) { + return undefined + } + // Skip in auto mode - auto mode classifier handles all permission decisions + if (feature('TRANSCRIPT_CLASSIFIER') && toolPermissionContext.mode === 'auto') + return undefined + if (toolPermissionContext.mode === 'bypassPermissions') return undefined + + const allowDescriptions = getBashPromptAllowDescriptions( + toolPermissionContext, + ) + if (allowDescriptions.length === 0) return undefined + + return { + command, + cwd: getCwd(), + descriptions: allowDescriptions, + } +} + +const speculativeChecks = new Map>() + +/** + * Start a speculative bash allow classifier check early, so it runs in + * parallel with pre-tool hooks, deny/ask classifiers, and permission dialog setup. + * The result can be consumed later by executeAsyncClassifierCheck via + * consumeSpeculativeClassifierCheck. + */ +export function peekSpeculativeClassifierCheck( + command: string, +): Promise | undefined { + return speculativeChecks.get(command) +} + +export function startSpeculativeClassifierCheck( + command: string, + toolPermissionContext: ToolPermissionContext, + signal: AbortSignal, + isNonInteractiveSession: boolean, +): boolean { + // Same guards as buildPendingClassifierCheck + if (!isClassifierPermissionsEnabled()) return false + if (feature('TRANSCRIPT_CLASSIFIER') && toolPermissionContext.mode === 'auto') + return false + if (toolPermissionContext.mode === 'bypassPermissions') return false + const allowDescriptions = getBashPromptAllowDescriptions( + toolPermissionContext, + ) + if (allowDescriptions.length === 0) return false + + const cwd = getCwd() + const promise = classifyBashCommand( + command, + cwd, + allowDescriptions, + 'allow', + signal, + isNonInteractiveSession, + ) + // Prevent unhandled rejection if the signal aborts before this promise is consumed. + // The original promise (which may reject) is still stored in the Map for consumers to await. + promise.catch(() => {}) + speculativeChecks.set(command, promise) + return true +} + +/** + * Consume a speculative classifier check result for the given command. + * Returns the promise if one exists (and removes it from the map), or undefined. + */ +export function consumeSpeculativeClassifierCheck( + command: string, +): Promise | undefined { + const promise = speculativeChecks.get(command) + if (promise) { + speculativeChecks.delete(command) + } + return promise +} + +export function clearSpeculativeChecks(): void { + speculativeChecks.clear() +} + +/** + * Await a pending classifier check and return a PermissionDecisionReason if + * high-confidence allow, or undefined otherwise. + * + * Used by swarm agents (both tmux and in-process) to gate permission + * forwarding: run the classifier first, and only escalate to the leader + * if the classifier doesn't auto-approve. + */ +export async function awaitClassifierAutoApproval( + pendingCheck: PendingClassifierCheck, + signal: AbortSignal, + isNonInteractiveSession: boolean, +): Promise { + const { command, cwd, descriptions } = pendingCheck + const speculativeResult = consumeSpeculativeClassifierCheck(command) + const classifierResult = speculativeResult + ? await speculativeResult + : await classifyBashCommand( + command, + cwd, + descriptions, + 'allow', + signal, + isNonInteractiveSession, + ) + + logClassifierResultForAnts(command, 'allow', descriptions, classifierResult) + + if ( + feature('BASH_CLASSIFIER') && + classifierResult.matches && + classifierResult.confidence === 'high' + ) { + return { + type: 'classifier', + classifier: 'bash_allow', + reason: `Allowed by prompt rule: "${classifierResult.matchedDescription}"`, + } + } + return undefined +} + +type AsyncClassifierCheckCallbacks = { + shouldContinue: () => boolean + onAllow: (decisionReason: PermissionDecisionReason) => void + onComplete?: () => void +} + +/** + * Execute the bash allow classifier check asynchronously. + * This runs in the background while the permission prompt is shown. + * If the classifier allows with high confidence and the user hasn't interacted, auto-approves. + * + * @param pendingCheck - Classifier check metadata from bashToolHasPermission + * @param signal - Abort signal + * @param isNonInteractiveSession - Whether this is a non-interactive session + * @param callbacks - Callbacks to check if we should continue and handle approval + */ +export async function executeAsyncClassifierCheck( + pendingCheck: { command: string; cwd: string; descriptions: string[] }, + signal: AbortSignal, + isNonInteractiveSession: boolean, + callbacks: AsyncClassifierCheckCallbacks, +): Promise { + const { command, cwd, descriptions } = pendingCheck + const speculativeResult = consumeSpeculativeClassifierCheck(command) + + let classifierResult: ClassifierResult + try { + classifierResult = speculativeResult + ? await speculativeResult + : await classifyBashCommand( + command, + cwd, + descriptions, + 'allow', + signal, + isNonInteractiveSession, + ) + } catch (error: unknown) { + // When the coordinator session is cancelled, the abort signal fires and the + // classifier API call rejects with APIUserAbortError. This is expected and + // should not surface as an unhandled promise rejection. + if (error instanceof APIUserAbortError || error instanceof AbortError) { + callbacks.onComplete?.() + return + } + callbacks.onComplete?.() + throw error + } + + logClassifierResultForAnts(command, 'allow', descriptions, classifierResult) + + // Don't auto-approve if user already made a decision or has interacted + // with the permission dialog (e.g., arrow keys, tab, typing) + if (!callbacks.shouldContinue()) return + + if ( + feature('BASH_CLASSIFIER') && + classifierResult.matches && + classifierResult.confidence === 'high' + ) { + callbacks.onAllow({ + type: 'classifier', + classifier: 'bash_allow', + reason: `Allowed by prompt rule: "${classifierResult.matchedDescription}"`, + }) + } else { + // No match — notify so the checking indicator is cleared + callbacks.onComplete?.() + } +} + +/** + * The main implementation to check if we need to ask for user permission to call BashTool with a given input + */ +export async function bashToolHasPermission( + input: z.infer, + context: ToolUseContext, + getCommandSubcommandPrefixFn = getCommandSubcommandPrefix, +): Promise { + let appState = context.getAppState() + + // 0. AST-based security parse. This replaces both tryParseShellCommand + // (the shell-quote pre-check) and the bashCommandIsSafe misparsing gate. + // tree-sitter produces either a clean SimpleCommand[] (quotes resolved, + // no hidden substitutions) or 'too-complex' — which is exactly the signal + // we need to decide whether splitCommand's output can be trusted. + // + // When tree-sitter WASM is unavailable OR the injection check is disabled + // via env var, we fall back to the old path (legacy gate at ~1370 runs). + const injectionCheckDisabled = isEnvTruthy( + process.env.CLAUDE_CODE_DISABLE_COMMAND_INJECTION_CHECK, + ) + // GrowthBook killswitch for shadow mode — when off, skip the native parse + // entirely. Computed once; feature() must stay inline in the ternary below. + const shadowEnabled = feature('TREE_SITTER_BASH_SHADOW') + ? getFeatureValue_CACHED_MAY_BE_STALE('tengu_birch_trellis', true) + : false + // Parse once here; the resulting AST feeds both parseForSecurityFromAst + // and bashToolCheckCommandOperatorPermissions. + let astRoot = injectionCheckDisabled + ? null + : feature('TREE_SITTER_BASH_SHADOW') && !shadowEnabled + ? null + : await parseCommandRaw(input.command) + let astResult: ParseForSecurityResult = astRoot + ? parseForSecurityFromAst(input.command, astRoot) + : { kind: 'parse-unavailable' } + let astSubcommands: string[] | null = null + let astRedirects: Redirect[] | undefined + let astCommands: SimpleCommand[] | undefined + let shadowLegacySubs: string[] | undefined + + // Shadow-test tree-sitter: record its verdict, then force parse-unavailable + // so the legacy path stays authoritative. parseCommand stays gated on + // TREE_SITTER_BASH (not SHADOW) so legacy internals remain pure regex. + // One event per bash call captures both divergence AND unavailability + // reasons; module-load failures are separately covered by the + // session-scoped tengu_tree_sitter_load event. + if (feature('TREE_SITTER_BASH_SHADOW')) { + const available = astResult.kind !== 'parse-unavailable' + let tooComplex = false + let semanticFail = false + let subsDiffer = false + if (available) { + tooComplex = astResult.kind === 'too-complex' + semanticFail = + astResult.kind === 'simple' && !checkSemantics(astResult.commands).ok + const tsSubs = + astResult.kind === 'simple' + ? astResult.commands.map(c => c.text) + : undefined + const legacySubs = splitCommand(input.command) + shadowLegacySubs = legacySubs + subsDiffer = + tsSubs !== undefined && + (tsSubs.length !== legacySubs.length || + tsSubs.some((s, i) => s !== legacySubs[i])) + } + logEvent('tengu_tree_sitter_shadow', { + available, + astTooComplex: tooComplex, + astSemanticFail: semanticFail, + subsDiffer, + injectionCheckDisabled, + killswitchOff: !shadowEnabled, + cmdOverLength: input.command.length > 10000, + }) + // Always force legacy — shadow mode is observational only. + astResult = { kind: 'parse-unavailable' } + astRoot = null + } + + if (astResult.kind === 'too-complex') { + // Parse succeeded but found structure we can't statically analyze + // (command substitution, expansion, control flow, parser differential). + // Respect exact-match deny/ask/allow, then prefix/wildcard deny. Only + // fall through to ask if no deny matched — don't downgrade deny to ask. + const earlyExit = checkEarlyExitDeny(input, appState.toolPermissionContext) + if (earlyExit !== null) return earlyExit + const decisionReason: PermissionDecisionReason = { + type: 'other' as const, + reason: astResult.reason, + } + logEvent('tengu_bash_ast_too_complex', { + nodeTypeId: nodeTypeId(astResult.nodeType), + }) + return { + behavior: 'ask', + decisionReason, + message: createPermissionRequestMessage(BashTool.name, decisionReason), + suggestions: [], + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + + if (astResult.kind === 'simple') { + // Clean parse: check semantic-level concerns (zsh builtins, eval, etc.) + // that tokenize fine but are dangerous by name. + const sem = checkSemantics(astResult.commands) + if (!sem.ok) { + // Same deny-rule enforcement as the too-complex path: a user with + // `Bash(eval:*)` deny expects `eval "rm"` blocked, not downgraded. + const earlyExit = checkSemanticsDeny( + input, + appState.toolPermissionContext, + astResult.commands, + ) + if (earlyExit !== null) return earlyExit + const decisionReason: PermissionDecisionReason = { + type: 'other' as const, + reason: sem.reason, + } + return { + behavior: 'ask', + decisionReason, + message: createPermissionRequestMessage(BashTool.name, decisionReason), + suggestions: [], + } + } + // Stash the tokenized subcommands for use below. Downstream code (rule + // matching, path extraction, cd detection) still operates on strings, so + // we pass the original source span for each SimpleCommand. Downstream + // processing (stripSafeWrappers, parseCommandArguments) re-tokenizes + // these spans — that re-tokenization has known bugs (stripCommentLines + // mishandles newlines inside quotes), but checkSemantics already caught + // any argv element containing a newline, so those bugs can't bite here. + // Migrating downstream to operate on argv directly is a later commit. + astSubcommands = astResult.commands.map(c => c.text) + astRedirects = astResult.commands.flatMap(c => c.redirects) + astCommands = astResult.commands + } + + // Legacy shell-quote pre-check. Only reached on 'parse-unavailable' + // (tree-sitter not loaded OR TREE_SITTER_BASH feature gated off). Falls + // through to the full legacy path below. + if (astResult.kind === 'parse-unavailable') { + logForDebugging( + 'bashToolHasPermission: tree-sitter unavailable, using legacy shell-quote path', + ) + const parseResult = tryParseShellCommand(input.command) + if (!parseResult.success) { + const decisionReason = { + type: 'other' as const, + reason: `Command contains malformed syntax that cannot be parsed: ${parseResult.error}`, + } + return { + behavior: 'ask', + decisionReason, + message: createPermissionRequestMessage(BashTool.name, decisionReason), + } + } + } + + // Check sandbox auto-allow (which respects explicit deny/ask rules) + // Only call this if sandboxing and auto-allow are both enabled + if ( + SandboxManager.isSandboxingEnabled() && + SandboxManager.isAutoAllowBashIfSandboxedEnabled() && + shouldUseSandbox(input) + ) { + const sandboxAutoAllowResult = checkSandboxAutoAllow( + input, + appState.toolPermissionContext, + ) + if (sandboxAutoAllowResult.behavior !== 'passthrough') { + return sandboxAutoAllowResult + } + } + + // Check exact match first + const exactMatchResult = bashToolCheckExactMatchPermission( + input, + appState.toolPermissionContext, + ) + + // Exact command was denied + if (exactMatchResult.behavior === 'deny') { + return exactMatchResult + } + + // Check Bash prompt deny and ask rules in parallel (both use Haiku). + // Deny takes precedence over ask, and both take precedence over allow rules. + // Skip when in auto mode - auto mode classifier handles all permission decisions + if ( + isClassifierPermissionsEnabled() && + !( + feature('TRANSCRIPT_CLASSIFIER') && + appState.toolPermissionContext.mode === 'auto' + ) + ) { + const denyDescriptions = getBashPromptDenyDescriptions( + appState.toolPermissionContext, + ) + const askDescriptions = getBashPromptAskDescriptions( + appState.toolPermissionContext, + ) + const hasDeny = denyDescriptions.length > 0 + const hasAsk = askDescriptions.length > 0 + + if (hasDeny || hasAsk) { + const [denyResult, askResult] = await Promise.all([ + hasDeny + ? classifyBashCommand( + input.command, + getCwd(), + denyDescriptions, + 'deny', + context.abortController.signal, + context.options.isNonInteractiveSession, + ) + : null, + hasAsk + ? classifyBashCommand( + input.command, + getCwd(), + askDescriptions, + 'ask', + context.abortController.signal, + context.options.isNonInteractiveSession, + ) + : null, + ]) + + if (context.abortController.signal.aborted) { + throw new AbortError() + } + + if (denyResult) { + logClassifierResultForAnts( + input.command, + 'deny', + denyDescriptions, + denyResult, + ) + } + if (askResult) { + logClassifierResultForAnts( + input.command, + 'ask', + askDescriptions, + askResult, + ) + } + + // Deny takes precedence + if (denyResult?.matches && denyResult.confidence === 'high') { + return { + behavior: 'deny', + message: `Denied by Bash prompt rule: "${denyResult.matchedDescription}"`, + decisionReason: { + type: 'other', + reason: `Denied by Bash prompt rule: "${denyResult.matchedDescription}"`, + }, + } + } + + if (askResult?.matches && askResult.confidence === 'high') { + // Skip the Haiku call — the UI computes the prefix locally + // and lets the user edit it. Still call the injected function + // when tests override it. + let suggestions: PermissionUpdate[] + if (getCommandSubcommandPrefixFn === getCommandSubcommandPrefix) { + suggestions = suggestionForExactCommand(input.command) + } else { + const commandPrefixResult = await getCommandSubcommandPrefixFn( + input.command, + context.abortController.signal, + context.options.isNonInteractiveSession, + ) + if (context.abortController.signal.aborted) { + throw new AbortError() + } + suggestions = commandPrefixResult?.commandPrefix + ? suggestionForPrefix(commandPrefixResult.commandPrefix) + : suggestionForExactCommand(input.command) + } + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name), + decisionReason: { + type: 'other', + reason: `Required by Bash prompt rule: "${askResult.matchedDescription}"`, + }, + suggestions, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + } + } + + // Check for non-subcommand Bash operators like `>`, `|`, etc. + // This must happen before dangerous path checks so that piped commands + // are handled by the operator logic (which generates "multiple operations" messages) + const commandOperatorResult = await checkCommandOperatorPermissions( + input, + (i: z.infer) => + bashToolHasPermission(i, context, getCommandSubcommandPrefixFn), + { isNormalizedCdCommand, isNormalizedGitCommand }, + astRoot, + ) + if (commandOperatorResult.behavior !== 'passthrough') { + // SECURITY FIX: When pipe segment processing returns 'allow', we must still validate + // the ORIGINAL command. The pipe segment processing strips redirections before + // checking each segment, so commands like: + // echo 'x' | xargs printf '%s' >> /tmp/file + // would have both segments allowed (echo and xargs printf) but the >> redirection + // would bypass validation. We must check: + // 1. Path constraints for output redirections + // 2. Command safety for dangerous patterns (backticks, etc.) in redirect targets + if (commandOperatorResult.behavior === 'allow') { + // Check for dangerous patterns (backticks, $(), etc.) in the original command + // This catches cases like: echo x | xargs echo > `pwd`/evil.txt + // where the backtick is in the redirect target (stripped from segments) + // Gate on AST: when astSubcommands is non-null, tree-sitter already + // validated structure (backticks/$() in redirect targets would have + // returned too-complex). Matches gating at ~1481, ~1706, ~1755. + // Avoids FP: `find -exec {} \; | grep x` tripping on backslash-;. + // bashCommandIsSafe runs the full legacy regex battery (~20 patterns) — + // only call it when we'll actually use the result. + const safetyResult = + astSubcommands === null + ? await bashCommandIsSafeAsync(input.command) + : null + if ( + safetyResult !== null && + safetyResult.behavior !== 'passthrough' && + safetyResult.behavior !== 'allow' + ) { + // Attach pending classifier check - may auto-approve before user responds + appState = context.getAppState() + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name, { + type: 'other', + reason: + safetyResult.message ?? + 'Command contains patterns that require approval', + }), + decisionReason: { + type: 'other', + reason: + safetyResult.message ?? + 'Command contains patterns that require approval', + }, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + + appState = context.getAppState() + // SECURITY: Compute compoundCommandHasCd from the full command, NOT + // hardcode false. The pipe-handling path previously passed `false` here, + // disabling the cd+redirect check at pathValidation.ts:821. Appending + // `| echo done` to `cd .claude && echo x > settings.json` routed through + // this path with compoundCommandHasCd=false, letting the redirect write + // to .claude/settings.json without the cd+redirect block firing. + const pathResult = checkPathConstraints( + input, + getCwd(), + appState.toolPermissionContext, + commandHasAnyCd(input.command), + astRedirects, + astCommands, + ) + if (pathResult.behavior !== 'passthrough') { + return pathResult + } + } + + // When pipe segments return 'ask' (individual segments not allowed by rules), + // attach pending classifier check - may auto-approve before user responds. + if (commandOperatorResult.behavior === 'ask') { + appState = context.getAppState() + return { + ...commandOperatorResult, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + + return commandOperatorResult + } + + // SECURITY: Legacy misparsing gate. Only runs when the tree-sitter module + // is not loaded. Timeout/abort is fail-closed via too-complex (returned + // early above), not routed here. When the AST parse succeeded, + // astSubcommands is non-null and we've already validated structure; this + // block is skipped entirely. The AST's 'too-complex' result subsumes + // everything isBashSecurityCheckForMisparsing covered — both answer the + // same question: "can splitCommand be trusted on this input?" + if ( + astSubcommands === null && + !isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_COMMAND_INJECTION_CHECK) + ) { + const originalCommandSafetyResult = await bashCommandIsSafeAsync( + input.command, + ) + if ( + originalCommandSafetyResult.behavior === 'ask' && + originalCommandSafetyResult.isBashSecurityCheckForMisparsing + ) { + // Compound commands with safe heredoc patterns ($(cat <<'EOF'...EOF)) + // trigger the $() check on the unsplit command. Strip the safe heredocs + // and re-check the remainder — if other misparsing patterns exist + // (e.g. backslash-escaped operators), they must still block. + const remainder = stripSafeHeredocSubstitutions(input.command) + const remainderResult = + remainder !== null ? await bashCommandIsSafeAsync(remainder) : null + if ( + remainder === null || + (remainderResult?.behavior === 'ask' && + remainderResult.isBashSecurityCheckForMisparsing) + ) { + // Allow if the exact command has an explicit allow permission — the user + // made a conscious choice to permit this specific command. + appState = context.getAppState() + const exactMatchResult = bashToolCheckExactMatchPermission( + input, + appState.toolPermissionContext, + ) + if (exactMatchResult.behavior === 'allow') { + return exactMatchResult + } + // Attach pending classifier check - may auto-approve before user responds + const decisionReason: PermissionDecisionReason = { + type: 'other' as const, + reason: originalCommandSafetyResult.message, + } + return { + behavior: 'ask', + message: createPermissionRequestMessage( + BashTool.name, + decisionReason, + ), + decisionReason, + suggestions: [], // Don't suggest saving a potentially dangerous command + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + } + } + + // Split into subcommands. Prefer the AST-extracted spans; fall back to + // splitCommand only when tree-sitter was unavailable. The cd-cwd filter + // strips the `cd ${cwd}` prefix that models like to prepend. + const cwd = getCwd() + const cwdMingw = + getPlatform() === 'windows' ? windowsPathToPosixPath(cwd) : cwd + const rawSubcommands = + astSubcommands ?? shadowLegacySubs ?? splitCommand(input.command) + const { subcommands, astCommandsByIdx } = filterCdCwdSubcommands( + rawSubcommands, + astCommands, + cwd, + cwdMingw, + ) + + // CC-643: Cap subcommand fanout. Only the legacy splitCommand path can + // explode — the AST path returns a bounded list (astSubcommands !== null) + // or short-circuits to 'too-complex' for structures it can't represent. + if ( + astSubcommands === null && + subcommands.length > MAX_SUBCOMMANDS_FOR_SECURITY_CHECK + ) { + logForDebugging( + `bashPermissions: ${subcommands.length} subcommands exceeds cap (${MAX_SUBCOMMANDS_FOR_SECURITY_CHECK}) — returning ask`, + { level: 'debug' }, + ) + const decisionReason = { + type: 'other' as const, + reason: `Command splits into ${subcommands.length} subcommands, too many to safety-check individually`, + } + return { + behavior: 'ask', + message: createPermissionRequestMessage(BashTool.name, decisionReason), + decisionReason, + } + } + + // Ask if there are multiple `cd` commands + const cdCommands = subcommands.filter(subCommand => + isNormalizedCdCommand(subCommand), + ) + if (cdCommands.length > 1) { + const decisionReason = { + type: 'other' as const, + reason: + 'Multiple directory changes in one command require approval for clarity', + } + return { + behavior: 'ask', + decisionReason, + message: createPermissionRequestMessage(BashTool.name, decisionReason), + } + } + + // Track if compound command contains cd for security validation + // This prevents bypassing path checks via: cd .claude/ && mv test.txt settings.json + const compoundCommandHasCd = cdCommands.length > 0 + + // SECURITY: Block compound commands that have both cd AND git + // This prevents sandbox escape via: cd /malicious/dir && git status + // where the malicious directory contains a bare git repo with core.fsmonitor. + // This check must happen HERE (before subcommand-level permission checks) + // because bashToolCheckPermission checks each subcommand independently via + // BashTool.isReadOnly(), which would re-derive compoundCommandHasCd=false + // from just "git status" alone, bypassing the readOnlyValidation.ts check. + if (compoundCommandHasCd) { + const hasGitCommand = subcommands.some(cmd => + isNormalizedGitCommand(cmd.trim()), + ) + if (hasGitCommand) { + const decisionReason = { + type: 'other' as const, + reason: + 'Compound commands with cd and git require approval to prevent bare repository attacks', + } + return { + behavior: 'ask', + decisionReason, + message: createPermissionRequestMessage(BashTool.name, decisionReason), + } + } + } + + appState = context.getAppState() // re-compute the latest in case the user hit shift+tab + + // SECURITY FIX: Check Bash deny/ask rules BEFORE path constraints + // This ensures that explicit deny rules like Bash(ls:*) take precedence over + // path constraint checks that return 'ask' for paths outside the project. + // Without this ordering, absolute paths outside the project (e.g., ls /home) + // would bypass deny rules because checkPathConstraints would return 'ask' first. + // + // Note: bashToolCheckPermission calls checkPathConstraints internally, which handles + // output redirection validation on each subcommand. However, since splitCommand strips + // redirections before we get here, we MUST validate output redirections on the ORIGINAL + // command AFTER checking deny rules but BEFORE returning results. + const subcommandPermissionDecisions = subcommands.map((command, i) => + bashToolCheckPermission( + { command }, + appState.toolPermissionContext, + compoundCommandHasCd, + astCommandsByIdx[i], + ), + ) + + // Deny if any subcommands are denied + const deniedSubresult = subcommandPermissionDecisions.find( + _ => _.behavior === 'deny', + ) + if (deniedSubresult !== undefined) { + return { + behavior: 'deny', + message: `Permission to use ${BashTool.name} with command ${input.command} has been denied.`, + decisionReason: { + type: 'subcommandResults', + reasons: new Map( + subcommandPermissionDecisions.map((result, i) => [ + subcommands[i]!, + result, + ]), + ), + }, + } + } + + // Validate output redirections on the ORIGINAL command (before splitCommand stripped them) + // This must happen AFTER checking deny rules but BEFORE returning results. + // Output redirections like "> /etc/passwd" are stripped by splitCommand, so the per-subcommand + // checkPathConstraints calls won't see them. We validate them here on the original input. + // SECURITY: When AST data is available, pass AST-derived redirects so + // checkPathConstraints uses them directly instead of re-parsing with + // shell-quote (which has a known single-quote backslash misparsing bug + // that can silently hide redirect operators). + const pathResult = checkPathConstraints( + input, + getCwd(), + appState.toolPermissionContext, + compoundCommandHasCd, + astRedirects, + astCommands, + ) + if (pathResult.behavior === 'deny') { + return pathResult + } + + const askSubresult = subcommandPermissionDecisions.find( + _ => _.behavior === 'ask', + ) + const nonAllowCount = count( + subcommandPermissionDecisions, + _ => _.behavior !== 'allow', + ) + + // SECURITY (GH#28784): Only short-circuit on a path-constraint 'ask' when no + // subcommand independently produced an 'ask'. checkPathConstraints re-runs the + // path-command loop on the full input, so `cd && python3 foo.py` + // produces an ask with ONLY a Read(/**) suggestion — the UI renders it as + // "Yes, allow reading from /" and picking that option silently approves + // python3. When a subcommand has its own ask (e.g. the cd subcommand's own + // path-constraint ask), fall through: either the askSubresult short-circuit + // below fires (single non-allow subcommand) or the merge flow collects Bash + // rule suggestions for every non-allow subcommand. The per-subcommand + // checkPathConstraints call inside bashToolCheckPermission already captures + // the Read rule for the cd target in that path. + // + // When no subcommand asked (all allow, or all passthrough like `printf > file`), + // pathResult IS the only ask — return it so redirection checks surface. + if (pathResult.behavior === 'ask' && askSubresult === undefined) { + return pathResult + } + + // Ask if any subcommands require approval (e.g., ls/cd outside boundaries). + // Only short-circuit when exactly ONE subcommand needs approval — if multiple + // do (e.g. cd-outside-project ask + python3 passthrough), fall through to the + // merge flow so the prompt surfaces Bash rule suggestions for all of them + // instead of only the first ask's Read rule (GH#28784). + if (askSubresult !== undefined && nonAllowCount === 1) { + return { + ...askSubresult, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + + // Allow if exact command was allowed + if (exactMatchResult.behavior === 'allow') { + return exactMatchResult + } + + // If all subcommands are allowed via exact or prefix match, allow the + // command — but only if no command injection is possible. When the AST + // parse succeeded, each subcommand is already known-safe (no hidden + // substitutions, no structural tricks); the per-subcommand re-check is + // redundant. When on the legacy path, re-run bashCommandIsSafeAsync per sub. + let hasPossibleCommandInjection = false + if ( + astSubcommands === null && + !isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_COMMAND_INJECTION_CHECK) + ) { + // CC-643: Batch divergence telemetry into a single logEvent. The per-sub + // logEvent was the hot-path syscall driver (each call → /proc/self/stat + // via process.memoryUsage()). Aggregate count preserves the signal. + let divergenceCount = 0 + const onDivergence = () => { + divergenceCount++ + } + const results = await Promise.all( + subcommands.map(c => bashCommandIsSafeAsync(c, onDivergence)), + ) + hasPossibleCommandInjection = results.some( + r => r.behavior !== 'passthrough', + ) + if (divergenceCount > 0) { + logEvent('tengu_tree_sitter_security_divergence', { + quoteContextDivergence: true, + count: divergenceCount, + }) + } + } + if ( + subcommandPermissionDecisions.every(_ => _.behavior === 'allow') && + !hasPossibleCommandInjection + ) { + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'subcommandResults', + reasons: new Map( + subcommandPermissionDecisions.map((result, i) => [ + subcommands[i]!, + result, + ]), + ), + }, + } + } + + // Query Haiku for command prefixes + // Skip the Haiku call — the UI computes the prefix locally and + // lets the user edit it. Still call when a custom fn is injected (tests). + let commandSubcommandPrefix: Awaited< + ReturnType + > = null + if (getCommandSubcommandPrefixFn !== getCommandSubcommandPrefix) { + commandSubcommandPrefix = await getCommandSubcommandPrefixFn( + input.command, + context.abortController.signal, + context.options.isNonInteractiveSession, + ) + if (context.abortController.signal.aborted) { + throw new AbortError() + } + } + + // If there is only one command, no need to process subcommands + appState = context.getAppState() // re-compute the latest in case the user hit shift+tab + if (subcommands.length === 1) { + const result = await checkCommandAndSuggestRules( + { command: subcommands[0]! }, + appState.toolPermissionContext, + commandSubcommandPrefix, + compoundCommandHasCd, + astSubcommands !== null, + ) + // If command wasn't allowed, attach pending classifier check. + // At this point, 'ask' can only come from bashCommandIsSafe (security check inside + // checkCommandAndSuggestRules), NOT from explicit ask rules - those were already + // filtered out at step 13 (askSubresult check). The classifier can bypass security. + if (result.behavior === 'ask' || result.behavior === 'passthrough') { + return { + ...result, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } + } + return result + } + + // Check subcommand permission results + const subcommandResults: Map = new Map() + for (const subcommand of subcommands) { + subcommandResults.set( + subcommand, + await checkCommandAndSuggestRules( + { + // Pass through input params like `sandbox` + ...input, + command: subcommand, + }, + appState.toolPermissionContext, + commandSubcommandPrefix?.subcommandPrefixes.get(subcommand), + compoundCommandHasCd, + astSubcommands !== null, + ), + ) + } + + // Allow if all subcommands are allowed + // Note that this is different than 6b because we are checking the command injection results. + if ( + subcommands.every(subcommand => { + const permissionResult = subcommandResults.get(subcommand) + return permissionResult?.behavior === 'allow' + }) + ) { + // Keep subcommandResults as PermissionResult for decisionReason + return { + behavior: 'allow', + updatedInput: input, + decisionReason: { + type: 'subcommandResults', + reasons: subcommandResults, + }, + } + } + + // Otherwise, ask for permission + const collectedRules: Map = new Map() + + for (const [subcommand, permissionResult] of subcommandResults) { + if ( + permissionResult.behavior === 'ask' || + permissionResult.behavior === 'passthrough' + ) { + const updates = + 'suggestions' in permissionResult + ? permissionResult.suggestions + : undefined + + const rules = extractRules(updates) + for (const rule of rules) { + // Use string representation as key for deduplication + const ruleKey = permissionRuleValueToString(rule) + collectedRules.set(ruleKey, rule) + } + + // GH#28784 follow-up: security-check asks (compound-cd+write, process + // substitution, etc.) carry no suggestions. In a compound command like + // `cd ~/out && rm -rf x`, that means only cd's Read rule gets collected + // and the UI labels the prompt "Yes, allow reading from /" — never + // mentioning rm. Synthesize a Bash(exact) rule so the UI shows the + // chained command. Skip explicit ask rules (decisionReason.type 'rule') + // where the user deliberately wants to review each time. + if ( + permissionResult.behavior === 'ask' && + rules.length === 0 && + permissionResult.decisionReason?.type !== 'rule' + ) { + for (const rule of extractRules( + suggestionForExactCommand(subcommand), + )) { + const ruleKey = permissionRuleValueToString(rule) + collectedRules.set(ruleKey, rule) + } + } + // Note: We only collect rules, not other update types like mode changes + // This is appropriate for bash subcommands which primarily need rule suggestions + } + } + + const decisionReason = { + type: 'subcommandResults' as const, + reasons: subcommandResults, + } + + // GH#11380: Cap at MAX_SUGGESTED_RULES_FOR_COMPOUND. Map preserves insertion + // order (subcommand order), so slicing keeps the leftmost N. + const cappedRules = Array.from(collectedRules.values()).slice( + 0, + MAX_SUGGESTED_RULES_FOR_COMPOUND, + ) + const suggestedUpdates: PermissionUpdate[] | undefined = + cappedRules.length > 0 + ? [ + { + type: 'addRules', + rules: cappedRules, + behavior: 'allow', + destination: 'localSettings', + }, + ] + : undefined + + // Attach pending classifier check - may auto-approve before user responds. + // Behavior is 'ask' if any subcommand was 'ask' (e.g., path constraint or ask + // rule) — before the GH#28784 fix, ask subresults always short-circuited above + // so this path only saw 'passthrough' subcommands and hardcoded that. + return { + behavior: askSubresult !== undefined ? 'ask' : 'passthrough', + message: createPermissionRequestMessage(BashTool.name, decisionReason), + decisionReason, + suggestions: suggestedUpdates, + ...(feature('BASH_CLASSIFIER') + ? { + pendingClassifierCheck: buildPendingClassifierCheck( + input.command, + appState.toolPermissionContext, + ), + } + : {}), + } +} + +/** + * Checks if a subcommand is a git command after normalizing away safe wrappers + * (env vars, timeout, etc.) and shell quotes. + * + * SECURITY: Must normalize before matching to prevent bypasses like: + * 'git' status — shell quotes hide the command from a naive regex + * NO_COLOR=1 git status — env var prefix hides the command + */ +export function isNormalizedGitCommand(command: string): boolean { + // Fast path: catch the most common case before any parsing + if (command.startsWith('git ') || command === 'git') { + return true + } + const stripped = stripSafeWrappers(command) + const parsed = tryParseShellCommand(stripped) + if (parsed.success && parsed.tokens.length > 0) { + // Direct git command + if (parsed.tokens[0] === 'git') { + return true + } + // "xargs git ..." — xargs runs git in the current directory, + // so it must be treated as a git command for cd+git security checks. + // This matches the xargs prefix handling in filterRulesByContentsMatchingInput. + if (parsed.tokens[0] === 'xargs' && parsed.tokens.includes('git')) { + return true + } + return false + } + return /^git(?:\s|$)/.test(stripped) +} + +/** + * Checks if a subcommand is a cd command after normalizing away safe wrappers + * (env vars, timeout, etc.) and shell quotes. + * + * SECURITY: Must normalize before matching to prevent bypasses like: + * FORCE_COLOR=1 cd sub — env var prefix hides the cd from a naive /^cd / regex + * This mirrors isNormalizedGitCommand to ensure symmetric normalization. + * + * Also matches pushd/popd — they change cwd just like cd, so + * pushd /tmp/bare-repo && git status + * must trigger the same cd+git guard. Mirrors PowerShell's + * DIRECTORY_CHANGE_ALIASES (src/utils/powershell/parser.ts). + */ +export function isNormalizedCdCommand(command: string): boolean { + const stripped = stripSafeWrappers(command) + const parsed = tryParseShellCommand(stripped) + if (parsed.success && parsed.tokens.length > 0) { + const cmd = parsed.tokens[0] + return cmd === 'cd' || cmd === 'pushd' || cmd === 'popd' + } + return /^(?:cd|pushd|popd)(?:\s|$)/.test(stripped) +} + +/** + * Checks if a compound command contains any cd command, + * using normalized detection that handles env var prefixes and shell quotes. + */ +export function commandHasAnyCd(command: string): boolean { + return splitCommand(command).some(subcmd => + isNormalizedCdCommand(subcmd.trim()), + ) +} diff --git a/_all-in-one-upload/cc-haha/src/tools/BashTool/commentLabel.ts b/_all-in-one-upload/cc-haha/src/tools/BashTool/commentLabel.ts new file mode 100644 index 0000000..dd36df8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/BashTool/commentLabel.ts @@ -0,0 +1,13 @@ +/** + * If the first line of a bash command is a `# comment` (not a `#!` shebang), + * return the comment text stripped of the `#` prefix. Otherwise undefined. + * + * Under fullscreen mode this is the non-verbose tool-use label AND the + * collapse-group ⎿ hint — it's what Claude wrote for the human to read. + */ +export function extractBashCommentLabel(command: string): string | undefined { + const nl = command.indexOf('\n') + const firstLine = (nl === -1 ? command : command.slice(0, nl)).trim() + if (!firstLine.startsWith('#') || firstLine.startsWith('#!')) return undefined + return firstLine.replace(/^#+\s*/, '') || undefined +} diff --git a/_all-in-one-upload/cc-haha/src/tools/EnterPlanModeTool/UI.tsx b/_all-in-one-upload/cc-haha/src/tools/EnterPlanModeTool/UI.tsx new file mode 100644 index 0000000..1958fe3 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/EnterPlanModeTool/UI.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { BLACK_CIRCLE } from 'src/constants/figures.js'; +import { getModeColor } from 'src/utils/permissions/PermissionMode.js'; +import { Box, Text } from '../../ink.js'; +import type { ToolProgressData } from '../../Tool.js'; +import type { ProgressMessage } from '../../types/message.js'; +import type { ThemeName } from '../../utils/theme.js'; +import type { Output } from './EnterPlanModeTool.js'; +export function renderToolUseMessage(): React.ReactNode { + return null; +} +export function renderToolResultMessage(_output: Output, _progressMessagesForMessage: ProgressMessage[], _options: { + theme: ThemeName; +}): React.ReactNode { + return + + {BLACK_CIRCLE} + Entered plan mode + + + + Claude is now exploring and designing an implementation approach. + + + ; +} +export function renderToolUseRejectedMessage(): React.ReactNode { + return + {BLACK_CIRCLE} + User declined to enter plan mode + ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJMQUNLX0NJUkNMRSIsImdldE1vZGVDb2xvciIsIkJveCIsIlRleHQiLCJUb29sUHJvZ3Jlc3NEYXRhIiwiUHJvZ3Jlc3NNZXNzYWdlIiwiVGhlbWVOYW1lIiwiT3V0cHV0IiwicmVuZGVyVG9vbFVzZU1lc3NhZ2UiLCJSZWFjdE5vZGUiLCJyZW5kZXJUb29sUmVzdWx0TWVzc2FnZSIsIl9vdXRwdXQiLCJfcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJfb3B0aW9ucyIsInRoZW1lIiwicmVuZGVyVG9vbFVzZVJlamVjdGVkTWVzc2FnZSJdLCJzb3VyY2VzIjpbIlVJLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IEJMQUNLX0NJUkNMRSB9IGZyb20gJ3NyYy9jb25zdGFudHMvZmlndXJlcy5qcydcbmltcG9ydCB7IGdldE1vZGVDb2xvciB9IGZyb20gJ3NyYy91dGlscy9wZXJtaXNzaW9ucy9QZXJtaXNzaW9uTW9kZS5qcydcbmltcG9ydCB7IEJveCwgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB0eXBlIHsgVG9vbFByb2dyZXNzRGF0YSB9IGZyb20gJy4uLy4uL1Rvb2wuanMnXG5pbXBvcnQgdHlwZSB7IFByb2dyZXNzTWVzc2FnZSB9IGZyb20gJy4uLy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgdHlwZSB7IFRoZW1lTmFtZSB9IGZyb20gJy4uLy4uL3V0aWxzL3RoZW1lLmpzJ1xuaW1wb3J0IHR5cGUgeyBPdXRwdXQgfSBmcm9tICcuL0VudGVyUGxhbk1vZGVUb29sLmpzJ1xuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFVzZU1lc3NhZ2UoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgcmV0dXJuIG51bGxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclRvb2xSZXN1bHRNZXNzYWdlKFxuICBfb3V0cHV0OiBPdXRwdXQsXG4gIF9wcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZTogUHJvZ3Jlc3NNZXNzYWdlPFRvb2xQcm9ncmVzc0RhdGE+W10sXG4gIF9vcHRpb25zOiB7IHRoZW1lOiBUaGVtZU5hbWUgfSxcbik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIHJldHVybiAoXG4gICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgbWFyZ2luVG9wPXsxfT5cbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cInJvd1wiPlxuICAgICAgICA8VGV4dCBjb2xvcj17Z2V0TW9kZUNvbG9yKCdwbGFuJyl9PntCTEFDS19DSVJDTEV9PC9UZXh0PlxuICAgICAgICA8VGV4dD4gRW50ZXJlZCBwbGFuIG1vZGU8L1RleHQ+XG4gICAgICA8L0JveD5cbiAgICAgIDxCb3ggcGFkZGluZ0xlZnQ9ezJ9PlxuICAgICAgICA8VGV4dCBkaW1Db2xvcj5cbiAgICAgICAgICBDbGF1ZGUgaXMgbm93IGV4cGxvcmluZyBhbmQgZGVzaWduaW5nIGFuIGltcGxlbWVudGF0aW9uIGFwcHJvYWNoLlxuICAgICAgICA8L1RleHQ+XG4gICAgICA8L0JveD5cbiAgICA8L0JveD5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFVzZVJlamVjdGVkTWVzc2FnZSgpOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cInJvd1wiIG1hcmdpblRvcD17MX0+XG4gICAgICA8VGV4dCBjb2xvcj17Z2V0TW9kZUNvbG9yKCdkZWZhdWx0Jyl9PntCTEFDS19DSVJDTEV9PC9UZXh0PlxuICAgICAgPFRleHQ+IFVzZXIgZGVjbGluZWQgdG8gZW50ZXIgcGxhbiBtb2RlPC9UZXh0PlxuICAgIDwvQm94PlxuICApXG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsWUFBWSxRQUFRLDBCQUEwQjtBQUN2RCxTQUFTQyxZQUFZLFFBQVEseUNBQXlDO0FBQ3RFLFNBQVNDLEdBQUcsRUFBRUMsSUFBSSxRQUFRLGNBQWM7QUFDeEMsY0FBY0MsZ0JBQWdCLFFBQVEsZUFBZTtBQUNyRCxjQUFjQyxlQUFlLFFBQVEsd0JBQXdCO0FBQzdELGNBQWNDLFNBQVMsUUFBUSxzQkFBc0I7QUFDckQsY0FBY0MsTUFBTSxRQUFRLHdCQUF3QjtBQUVwRCxPQUFPLFNBQVNDLG9CQUFvQkEsQ0FBQSxDQUFFLEVBQUVULEtBQUssQ0FBQ1UsU0FBUyxDQUFDO0VBQ3RELE9BQU8sSUFBSTtBQUNiO0FBRUEsT0FBTyxTQUFTQyx1QkFBdUJBLENBQ3JDQyxPQUFPLEVBQUVKLE1BQU0sRUFDZkssMkJBQTJCLEVBQUVQLGVBQWUsQ0FBQ0QsZ0JBQWdCLENBQUMsRUFBRSxFQUNoRVMsUUFBUSxFQUFFO0VBQUVDLEtBQUssRUFBRVIsU0FBUztBQUFDLENBQUMsQ0FDL0IsRUFBRVAsS0FBSyxDQUFDVSxTQUFTLENBQUM7RUFDakIsT0FDRSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3QyxNQUFNLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxLQUFLO0FBQzlCLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUNSLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUNELFlBQVksQ0FBQyxFQUFFLElBQUk7QUFDL0QsUUFBUSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxJQUFJO0FBQ3RDLE1BQU0sRUFBRSxHQUFHO0FBQ1gsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUIsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRO0FBQ3RCO0FBQ0EsUUFBUSxFQUFFLElBQUk7QUFDZCxNQUFNLEVBQUUsR0FBRztBQUNYLElBQUksRUFBRSxHQUFHLENBQUM7QUFFVjtBQUVBLE9BQU8sU0FBU2UsNEJBQTRCQSxDQUFBLENBQUUsRUFBRWhCLEtBQUssQ0FBQ1UsU0FBUyxDQUFDO0VBQzlELE9BQ0UsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQ1IsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQ0QsWUFBWSxDQUFDLEVBQUUsSUFBSTtBQUNoRSxNQUFNLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxFQUFFLElBQUk7QUFDbkQsSUFBSSxFQUFFLEdBQUcsQ0FBQztBQUVWIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/tools/MCPTool/UI.tsx b/_all-in-one-upload/cc-haha/src/tools/MCPTool/UI.tsx new file mode 100644 index 0000000..bc33ffe --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/MCPTool/UI.tsx @@ -0,0 +1,403 @@ +import { c as _c } from "react/compiler-runtime"; +import { feature } from 'bun:bundle'; +import figures from 'figures'; +import * as React from 'react'; +import type { z } from 'zod/v4'; +import { ProgressBar } from '../../components/design-system/ProgressBar.js'; +import { MessageResponse } from '../../components/MessageResponse.js'; +import { linkifyUrlsInText, OutputLine } from '../../components/shell/OutputLine.js'; +import { stringWidth } from '../../ink/stringWidth.js'; +import { Ansi, Box, Text } from '../../ink.js'; +import type { ToolProgressData } from '../../Tool.js'; +import type { ProgressMessage } from '../../types/message.js'; +import type { MCPProgress } from '../../types/tools.js'; +import { formatNumber } from '../../utils/format.js'; +import { createHyperlink } from '../../utils/hyperlink.js'; +import { getContentSizeEstimate, type MCPToolResult } from '../../utils/mcpValidation.js'; +import { jsonParse, jsonStringify } from '../../utils/slowOperations.js'; +import type { inputSchema } from './MCPTool.js'; + +// Threshold for displaying warning about large MCP responses +const MCP_OUTPUT_WARNING_THRESHOLD_TOKENS = 10_000; + +// In non-verbose mode, truncate individual input values to keep the header +// compact. Matches BashTool's philosophy of showing enough to identify the +// call without dumping the entire payload inline. +const MAX_INPUT_VALUE_CHARS = 80; + +// Max number of top-level keys before we fall back to raw JSON display. +// Beyond this a flat k:v list is more noise than help. +const MAX_FLAT_JSON_KEYS = 12; + +// Don't attempt flat-object parsing for large blobs. +const MAX_FLAT_JSON_CHARS = 5_000; + +// Don't attempt to parse JSON blobs larger than this (perf safety). +const MAX_JSON_PARSE_CHARS = 200_000; + +// A string value is "dominant text payload" if it has newlines or is +// long enough that inline display would be worse than unwrapping. +const UNWRAP_MIN_STRING_LEN = 200; +export function renderToolUseMessage(input: z.infer>, { + verbose +}: { + verbose: boolean; +}): React.ReactNode { + if (Object.keys(input).length === 0) { + return ''; + } + return Object.entries(input).map(([key, value]) => { + let rendered = jsonStringify(value); + if (feature('MCP_RICH_OUTPUT') && !verbose && rendered.length > MAX_INPUT_VALUE_CHARS) { + rendered = rendered.slice(0, MAX_INPUT_VALUE_CHARS).trimEnd() + '…'; + } + return `${key}: ${rendered}`; + }).join(', '); +} +export function renderToolUseProgressMessage(progressMessagesForMessage: ProgressMessage[]): React.ReactNode { + const lastProgress = progressMessagesForMessage.at(-1); + if (!lastProgress?.data) { + return + Running… + ; + } + const { + progress, + total, + progressMessage + } = lastProgress.data; + if (progress === undefined) { + return + Running… + ; + } + if (total !== undefined && total > 0) { + const ratio = Math.min(1, Math.max(0, progress / total)); + const percentage = Math.round(ratio * 100); + return + + {progressMessage && {progressMessage}} + + + {percentage}% + + + ; + } + return + {progressMessage ?? `Processing… ${progress}`} + ; +} +export function renderToolResultMessage(output: string | MCPToolResult, _progressMessagesForMessage: ProgressMessage[], { + verbose, + input +}: { + verbose: boolean; + input?: unknown; +}): React.ReactNode { + const mcpOutput = output as MCPToolResult; + if (!verbose) { + const slackSend = trySlackSendCompact(mcpOutput, input); + if (slackSend !== null) { + return + + Sent a message to{' '} + {createHyperlink(slackSend.url, slackSend.channel)} + + ; + } + } + const estimatedTokens = getContentSizeEstimate(mcpOutput); + const showWarning = estimatedTokens > MCP_OUTPUT_WARNING_THRESHOLD_TOKENS; + const warningMessage = showWarning ? `${figures.warning} Large MCP response (~${formatNumber(estimatedTokens)} tokens), this can fill up context quickly` : null; + let contentElement: React.ReactNode; + if (Array.isArray(mcpOutput)) { + const contentBlocks = mcpOutput.map((item, i) => { + if (item.type === 'image') { + return + + [Image] + + ; + } + // For text blocks and any other block types, extract text if available + const textContent = item.type === 'text' && 'text' in item && item.text !== null && item.text !== undefined ? String(item.text) : ''; + return feature('MCP_RICH_OUTPUT') ? : ; + }); + + // Wrap array content in a column layout + contentElement = + {contentBlocks} + ; + } else if (!mcpOutput) { + contentElement = + + (No content) + + ; + } else { + contentElement = feature('MCP_RICH_OUTPUT') ? : ; + } + if (warningMessage) { + return + + {warningMessage} + + {contentElement} + ; + } + return contentElement; +} + +/** + * Render MCP text output. Tries three strategies in order: + * 1. If JSON wraps a single dominant text payload (e.g. slack's + * {"messages":"line1\nline2..."}), unwrap and let OutputLine truncate. + * 2. If JSON is a small flat-ish object, render as aligned key: value. + * 3. Otherwise fall through to OutputLine (pretty-print + truncate). + */ +function MCPTextOutput(t0) { + const $ = _c(18); + const { + content, + verbose + } = t0; + let t1; + if ($[0] !== content || $[1] !== verbose) { + t1 = Symbol.for("react.early_return_sentinel"); + bb0: { + const unwrapped = tryUnwrapTextPayload(content); + if (unwrapped !== null) { + const t2 = unwrapped.extras.length > 0 && {unwrapped.extras.map(_temp).join(" \xB7 ")}; + let t3; + if ($[3] !== unwrapped || $[4] !== verbose) { + t3 = ; + $[3] = unwrapped; + $[4] = verbose; + $[5] = t3; + } else { + t3 = $[5]; + } + let t4; + if ($[6] !== t2 || $[7] !== t3) { + t4 = {t2}{t3}; + $[6] = t2; + $[7] = t3; + $[8] = t4; + } else { + t4 = $[8]; + } + t1 = t4; + break bb0; + } + } + $[0] = content; + $[1] = verbose; + $[2] = t1; + } else { + t1 = $[2]; + } + if (t1 !== Symbol.for("react.early_return_sentinel")) { + return t1; + } + let t2; + if ($[9] !== content) { + t2 = Symbol.for("react.early_return_sentinel"); + bb1: { + const flat = tryFlattenJson(content); + if (flat !== null) { + const maxKeyWidth = Math.max(...flat.map(_temp2)); + let t3; + if ($[11] !== maxKeyWidth) { + t3 = (t4, i) => { + const [key, value] = t4; + return {key.padEnd(maxKeyWidth)}: {linkifyUrlsInText(value)}; + }; + $[11] = maxKeyWidth; + $[12] = t3; + } else { + t3 = $[12]; + } + const t4 = {flat.map(t3)}; + let t5; + if ($[13] !== t4) { + t5 = {t4}; + $[13] = t4; + $[14] = t5; + } else { + t5 = $[14]; + } + t2 = t5; + break bb1; + } + } + $[9] = content; + $[10] = t2; + } else { + t2 = $[10]; + } + if (t2 !== Symbol.for("react.early_return_sentinel")) { + return t2; + } + let t3; + if ($[15] !== content || $[16] !== verbose) { + t3 = ; + $[15] = content; + $[16] = verbose; + $[17] = t3; + } else { + t3 = $[17]; + } + return t3; +} + +/** + * Parse content as a JSON object and return its entries. Null if content + * doesn't parse, isn't an object, is too large, or has 0/too-many keys. + */ +function _temp2(t0) { + const [k_0] = t0; + return stringWidth(k_0); +} +function _temp(t0) { + const [k, v] = t0; + return `${k}: ${v}`; +} +function parseJsonEntries(content: string, { + maxChars, + maxKeys +}: { + maxChars: number; + maxKeys: number; +}): [string, unknown][] | null { + const trimmed = content.trim(); + if (trimmed.length === 0 || trimmed.length > maxChars || trimmed[0] !== '{') { + return null; + } + let parsed: unknown; + try { + parsed = jsonParse(trimmed); + } catch { + return null; + } + if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) { + return null; + } + const entries = Object.entries(parsed); + if (entries.length === 0 || entries.length > maxKeys) { + return null; + } + return entries; +} + +/** + * If content parses as a JSON object where every value is a scalar or a + * small nested object, flatten it to [key, displayValue] pairs. Nested + * objects get one-line JSON. Returns null if content doesn't qualify. + */ +export function tryFlattenJson(content: string): [string, string][] | null { + const entries = parseJsonEntries(content, { + maxChars: MAX_FLAT_JSON_CHARS, + maxKeys: MAX_FLAT_JSON_KEYS + }); + if (entries === null) return null; + const result: [string, string][] = []; + for (const [key, value] of entries) { + if (typeof value === 'string') { + result.push([key, value]); + } else if (value === null || typeof value === 'number' || typeof value === 'boolean') { + result.push([key, String(value)]); + } else if (typeof value === 'object') { + const compact = jsonStringify(value); + if (compact.length > 120) return null; + result.push([key, compact]); + } else { + return null; + } + } + return result; +} + +/** + * If content is a JSON object where one key holds a dominant string payload + * (multiline or long) and all siblings are small scalars, unwrap it. This + * handles the common MCP pattern of {"messages":"line1\nline2..."} where + * pretty-printing keeps \n escaped but we want real line breaks + truncation. + */ +export function tryUnwrapTextPayload(content: string): { + body: string; + extras: [string, string][]; +} | null { + const entries = parseJsonEntries(content, { + maxChars: MAX_JSON_PARSE_CHARS, + maxKeys: 4 + }); + if (entries === null) return null; + // Find the one dominant string payload. Trim first: a trailing \n on a + // short sibling (e.g. pagination hints) shouldn't make it "dominant". + let body: string | null = null; + const extras: [string, string][] = []; + for (const [key, value] of entries) { + if (typeof value === 'string') { + const t = value.trimEnd(); + const isDominant = t.length > UNWRAP_MIN_STRING_LEN || t.includes('\n') && t.length > 50; + if (isDominant) { + if (body !== null) return null; // two big strings — ambiguous + body = t; + continue; + } + if (t.length > 150) return null; + extras.push([key, t.replace(/\s+/g, ' ')]); + } else if (value === null || typeof value === 'number' || typeof value === 'boolean') { + extras.push([key, String(value)]); + } else { + return null; // nested object/array — use flat or pretty-print path + } + } + if (body === null) return null; + return { + body, + extras + }; +} +const SLACK_ARCHIVES_RE = /^https:\/\/[a-z0-9-]+\.slack\.com\/archives\/([A-Z0-9]+)\/p\d+$/; + +/** + * Detect a Slack send-message result and return a compact {channel, url} pair. + * Matches both hosted (claude.ai Slack) and community MCP server shapes — + * both return `message_link` in the result. The channel label prefers the + * tool input (may be a name like "#foo" or an ID like "C09EVDAN1NK") and + * falls back to the ID parsed from the archives URL. + */ +export function trySlackSendCompact(output: string | MCPToolResult, input: unknown): { + channel: string; + url: string; +} | null { + let text: unknown = output; + if (Array.isArray(output)) { + const block = output.find(b => b.type === 'text'); + text = block && 'text' in block ? block.text : undefined; + } + if (typeof text !== 'string' || !text.includes('"message_link"')) { + return null; + } + const entries = parseJsonEntries(text, { + maxChars: 2000, + maxKeys: 6 + }); + const url = entries?.find(([k]) => k === 'message_link')?.[1]; + if (typeof url !== 'string') return null; + const m = SLACK_ARCHIVES_RE.exec(url); + if (!m) return null; + const inp = input as { + channel_id?: unknown; + channel?: unknown; + } | undefined; + const raw = inp?.channel_id ?? inp?.channel ?? m[1]; + const label = typeof raw === 'string' && raw ? raw : 'slack'; + return { + channel: label.startsWith('#') ? label : `#${label}`, + url + }; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmZWF0dXJlIiwiZmlndXJlcyIsIlJlYWN0IiwieiIsIlByb2dyZXNzQmFyIiwiTWVzc2FnZVJlc3BvbnNlIiwibGlua2lmeVVybHNJblRleHQiLCJPdXRwdXRMaW5lIiwic3RyaW5nV2lkdGgiLCJBbnNpIiwiQm94IiwiVGV4dCIsIlRvb2xQcm9ncmVzc0RhdGEiLCJQcm9ncmVzc01lc3NhZ2UiLCJNQ1BQcm9ncmVzcyIsImZvcm1hdE51bWJlciIsImNyZWF0ZUh5cGVybGluayIsImdldENvbnRlbnRTaXplRXN0aW1hdGUiLCJNQ1BUb29sUmVzdWx0IiwianNvblBhcnNlIiwianNvblN0cmluZ2lmeSIsImlucHV0U2NoZW1hIiwiTUNQX09VVFBVVF9XQVJOSU5HX1RIUkVTSE9MRF9UT0tFTlMiLCJNQVhfSU5QVVRfVkFMVUVfQ0hBUlMiLCJNQVhfRkxBVF9KU09OX0tFWVMiLCJNQVhfRkxBVF9KU09OX0NIQVJTIiwiTUFYX0pTT05fUEFSU0VfQ0hBUlMiLCJVTldSQVBfTUlOX1NUUklOR19MRU4iLCJyZW5kZXJUb29sVXNlTWVzc2FnZSIsImlucHV0IiwiaW5mZXIiLCJSZXR1cm5UeXBlIiwidmVyYm9zZSIsIlJlYWN0Tm9kZSIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJlbnRyaWVzIiwibWFwIiwia2V5IiwidmFsdWUiLCJyZW5kZXJlZCIsInNsaWNlIiwidHJpbUVuZCIsImpvaW4iLCJyZW5kZXJUb29sVXNlUHJvZ3Jlc3NNZXNzYWdlIiwicHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJsYXN0UHJvZ3Jlc3MiLCJhdCIsImRhdGEiLCJwcm9ncmVzcyIsInRvdGFsIiwicHJvZ3Jlc3NNZXNzYWdlIiwidW5kZWZpbmVkIiwicmF0aW8iLCJNYXRoIiwibWluIiwibWF4IiwicGVyY2VudGFnZSIsInJvdW5kIiwicmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2UiLCJvdXRwdXQiLCJfcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJtY3BPdXRwdXQiLCJzbGFja1NlbmQiLCJ0cnlTbGFja1NlbmRDb21wYWN0IiwidXJsIiwiY2hhbm5lbCIsImVzdGltYXRlZFRva2VucyIsInNob3dXYXJuaW5nIiwid2FybmluZ01lc3NhZ2UiLCJ3YXJuaW5nIiwiY29udGVudEVsZW1lbnQiLCJBcnJheSIsImlzQXJyYXkiLCJjb250ZW50QmxvY2tzIiwiaXRlbSIsImkiLCJ0eXBlIiwidGV4dENvbnRlbnQiLCJ0ZXh0IiwiU3RyaW5nIiwiTUNQVGV4dE91dHB1dCIsInQwIiwiJCIsIl9jIiwiY29udGVudCIsInQxIiwiU3ltYm9sIiwiZm9yIiwiYmIwIiwidW53cmFwcGVkIiwidHJ5VW53cmFwVGV4dFBheWxvYWQiLCJ0MiIsImV4dHJhcyIsIl90ZW1wIiwidDMiLCJib2R5IiwidDQiLCJiYjEiLCJmbGF0IiwidHJ5RmxhdHRlbkpzb24iLCJtYXhLZXlXaWR0aCIsIl90ZW1wMiIsInBhZEVuZCIsInQ1Iiwia18wIiwiayIsInYiLCJwYXJzZUpzb25FbnRyaWVzIiwibWF4Q2hhcnMiLCJtYXhLZXlzIiwidHJpbW1lZCIsInRyaW0iLCJwYXJzZWQiLCJyZXN1bHQiLCJwdXNoIiwiY29tcGFjdCIsInQiLCJpc0RvbWluYW50IiwiaW5jbHVkZXMiLCJyZXBsYWNlIiwiU0xBQ0tfQVJDSElWRVNfUkUiLCJibG9jayIsImZpbmQiLCJiIiwibSIsImV4ZWMiLCJpbnAiLCJjaGFubmVsX2lkIiwicmF3IiwibGFiZWwiLCJzdGFydHNXaXRoIl0sInNvdXJjZXMiOlsiVUkudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGZlYXR1cmUgfSBmcm9tICdidW46YnVuZGxlJ1xuaW1wb3J0IGZpZ3VyZXMgZnJvbSAnZmlndXJlcydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHR5cGUgeyB6IH0gZnJvbSAnem9kL3Y0J1xuaW1wb3J0IHsgUHJvZ3Jlc3NCYXIgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL2Rlc2lnbi1zeXN0ZW0vUHJvZ3Jlc3NCYXIuanMnXG5pbXBvcnQgeyBNZXNzYWdlUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL01lc3NhZ2VSZXNwb25zZS5qcydcbmltcG9ydCB7XG4gIGxpbmtpZnlVcmxzSW5UZXh0LFxuICBPdXRwdXRMaW5lLFxufSBmcm9tICcuLi8uLi9jb21wb25lbnRzL3NoZWxsL091dHB1dExpbmUuanMnXG5pbXBvcnQgeyBzdHJpbmdXaWR0aCB9IGZyb20gJy4uLy4uL2luay9zdHJpbmdXaWR0aC5qcydcbmltcG9ydCB7IEFuc2ksIEJveCwgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB0eXBlIHsgVG9vbFByb2dyZXNzRGF0YSB9IGZyb20gJy4uLy4uL1Rvb2wuanMnXG5pbXBvcnQgdHlwZSB7IFByb2dyZXNzTWVzc2FnZSB9IGZyb20gJy4uLy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgdHlwZSB7IE1DUFByb2dyZXNzIH0gZnJvbSAnLi4vLi4vdHlwZXMvdG9vbHMuanMnXG5pbXBvcnQgeyBmb3JtYXROdW1iZXIgfSBmcm9tICcuLi8uLi91dGlscy9mb3JtYXQuanMnXG5pbXBvcnQgeyBjcmVhdGVIeXBlcmxpbmsgfSBmcm9tICcuLi8uLi91dGlscy9oeXBlcmxpbmsuanMnXG5pbXBvcnQge1xuICBnZXRDb250ZW50U2l6ZUVzdGltYXRlLFxuICB0eXBlIE1DUFRvb2xSZXN1bHQsXG59IGZyb20gJy4uLy4uL3V0aWxzL21jcFZhbGlkYXRpb24uanMnXG5pbXBvcnQgeyBqc29uUGFyc2UsIGpzb25TdHJpbmdpZnkgfSBmcm9tICcuLi8uLi91dGlscy9zbG93T3BlcmF0aW9ucy5qcydcbmltcG9ydCB0eXBlIHsgaW5wdXRTY2hlbWEgfSBmcm9tICcuL01DUFRvb2wuanMnXG5cbi8vIFRocmVzaG9sZCBmb3IgZGlzcGxheWluZyB3YXJuaW5nIGFib3V0IGxhcmdlIE1DUCByZXNwb25zZXNcbmNvbnN0IE1DUF9PVVRQVVRfV0FSTklOR19USFJFU0hPTERfVE9LRU5TID0gMTBfMDAwXG5cbi8vIEluIG5vbi12ZXJib3NlIG1vZGUsIHRydW5jYXRlIGluZGl2aWR1YWwgaW5wdXQgdmFsdWVzIHRvIGtlZXAgdGhlIGhlYWRlclxuLy8gY29tcGFjdC4gTWF0Y2hlcyBCYXNoVG9vbCdzIHBoaWxvc29waHkgb2Ygc2hvd2luZyBlbm91Z2ggdG8gaWRlbnRpZnkgdGhlXG4vLyBjYWxsIHdpdGhvdXQgZHVtcGluZyB0aGUgZW50aXJlIHBheWxvYWQgaW5saW5lLlxuY29uc3QgTUFYX0lOUFVUX1ZBTFVFX0NIQVJTID0gODBcblxuLy8gTWF4IG51bWJlciBvZiB0b3AtbGV2ZWwga2V5cyBiZWZvcmUgd2UgZmFsbCBiYWNrIHRvIHJhdyBKU09OIGRpc3BsYXkuXG4vLyBCZXlvbmQgdGhpcyBhIGZsYXQgazp2IGxpc3QgaXMgbW9yZSBub2lzZSB0aGFuIGhlbHAuXG5jb25zdCBNQVhfRkxBVF9KU09OX0tFWVMgPSAxMlxuXG4vLyBEb24ndCBhdHRlbXB0IGZsYXQtb2JqZWN0IHBhcnNpbmcgZm9yIGxhcmdlIGJsb2JzLlxuY29uc3QgTUFYX0ZMQVRfSlNPTl9DSEFSUyA9IDVfMDAwXG5cbi8vIERvbid0IGF0dGVtcHQgdG8gcGFyc2UgSlNPTiBibG9icyBsYXJnZXIgdGhhbiB0aGlzIChwZXJmIHNhZmV0eSkuXG5jb25zdCBNQVhfSlNPTl9QQVJTRV9DSEFSUyA9IDIwMF8wMDBcblxuLy8gQSBzdHJpbmcgdmFsdWUgaXMgXCJkb21pbmFudCB0ZXh0IHBheWxvYWRcIiBpZiBpdCBoYXMgbmV3bGluZXMgb3IgaXNcbi8vIGxvbmcgZW5vdWdoIHRoYXQgaW5saW5lIGRpc3BsYXkgd291bGQgYmUgd29yc2UgdGhhbiB1bndyYXBwaW5nLlxuY29uc3QgVU5XUkFQX01JTl9TVFJJTkdfTEVOID0gMjAwXG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlTWVzc2FnZShcbiAgaW5wdXQ6IHouaW5mZXI8UmV0dXJuVHlwZTx0eXBlb2YgaW5wdXRTY2hlbWE+PixcbiAgeyB2ZXJib3NlIH06IHsgdmVyYm9zZTogYm9vbGVhbiB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgaWYgKE9iamVjdC5rZXlzKGlucHV0KS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gJydcbiAgfVxuICByZXR1cm4gT2JqZWN0LmVudHJpZXMoaW5wdXQpXG4gICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBsZXQgcmVuZGVyZWQgPSBqc29uU3RyaW5naWZ5KHZhbHVlKVxuICAgICAgaWYgKFxuICAgICAgICBmZWF0dXJlKCdNQ1BfUklDSF9PVVRQVVQnKSAmJlxuICAgICAgICAhdmVyYm9zZSAmJlxuICAgICAgICByZW5kZXJlZC5sZW5ndGggPiBNQVhfSU5QVVRfVkFMVUVfQ0hBUlNcbiAgICAgICkge1xuICAgICAgICByZW5kZXJlZCA9IHJlbmRlcmVkLnNsaWNlKDAsIE1BWF9JTlBVVF9WQUxVRV9DSEFSUykudHJpbUVuZCgpICsgJ+KApidcbiAgICAgIH1cbiAgICAgIHJldHVybiBgJHtrZXl9OiAke3JlbmRlcmVkfWBcbiAgICB9KVxuICAgIC5qb2luKCcsICcpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb29sVXNlUHJvZ3Jlc3NNZXNzYWdlKFxuICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZTogUHJvZ3Jlc3NNZXNzYWdlPE1DUFByb2dyZXNzPltdLFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3QgbGFzdFByb2dyZXNzID0gcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UuYXQoLTEpXG5cbiAgaWYgKCFsYXN0UHJvZ3Jlc3M/LmRhdGEpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICA8VGV4dCBkaW1Db2xvcj5SdW5uaW5n4oCmPC9UZXh0PlxuICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgKVxuICB9XG5cbiAgY29uc3QgeyBwcm9ncmVzcywgdG90YWwsIHByb2dyZXNzTWVzc2FnZSB9ID0gbGFzdFByb2dyZXNzLmRhdGFcblxuICBpZiAocHJvZ3Jlc3MgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiAoXG4gICAgICA8TWVzc2FnZVJlc3BvbnNlIGhlaWdodD17MX0+XG4gICAgICAgIDxUZXh0IGRpbUNvbG9yPlJ1bm5pbmfigKY8L1RleHQ+XG4gICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICApXG4gIH1cblxuICBpZiAodG90YWwgIT09IHVuZGVmaW5lZCAmJiB0b3RhbCA+IDApIHtcbiAgICBjb25zdCByYXRpbyA9IE1hdGgubWluKDEsIE1hdGgubWF4KDAsIHByb2dyZXNzIC8gdG90YWwpKVxuICAgIGNvbnN0IHBlcmNlbnRhZ2UgPSBNYXRoLnJvdW5kKHJhdGlvICogMTAwKVxuICAgIHJldHVybiAoXG4gICAgICA8TWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICB7cHJvZ3Jlc3NNZXNzYWdlICYmIDxUZXh0IGRpbUNvbG9yPntwcm9ncmVzc01lc3NhZ2V9PC9UZXh0Pn1cbiAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJyb3dcIiBnYXA9ezF9PlxuICAgICAgICAgICAgPFByb2dyZXNzQmFyIHJhdGlvPXtyYXRpb30gd2lkdGg9ezIwfSAvPlxuICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+e3BlcmNlbnRhZ2V9JTwvVGV4dD5cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgICApXG4gIH1cblxuICByZXR1cm4gKFxuICAgIDxNZXNzYWdlUmVzcG9uc2UgaGVpZ2h0PXsxfT5cbiAgICAgIDxUZXh0IGRpbUNvbG9yPntwcm9ncmVzc01lc3NhZ2UgPz8gYFByb2Nlc3NpbmfigKYgJHtwcm9ncmVzc31gfTwvVGV4dD5cbiAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2UoXG4gIG91dHB1dDogc3RyaW5nIHwgTUNQVG9vbFJlc3VsdCxcbiAgX3Byb2dyZXNzTWVzc2FnZXNGb3JNZXNzYWdlOiBQcm9ncmVzc01lc3NhZ2U8VG9vbFByb2dyZXNzRGF0YT5bXSxcbiAgeyB2ZXJib3NlLCBpbnB1dCB9OiB7IHZlcmJvc2U6IGJvb2xlYW47IGlucHV0PzogdW5rbm93biB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3QgbWNwT3V0cHV0ID0gb3V0cHV0IGFzIE1DUFRvb2xSZXN1bHRcblxuICBpZiAoIXZlcmJvc2UpIHtcbiAgICBjb25zdCBzbGFja1NlbmQgPSB0cnlTbGFja1NlbmRDb21wYWN0KG1jcE91dHB1dCwgaW5wdXQpXG4gICAgaWYgKHNsYWNrU2VuZCAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgU2VudCBhIG1lc3NhZ2UgdG97JyAnfVxuICAgICAgICAgICAgPEFuc2k+e2NyZWF0ZUh5cGVybGluayhzbGFja1NlbmQudXJsLCBzbGFja1NlbmQuY2hhbm5lbCl9PC9BbnNpPlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgY29uc3QgZXN0aW1hdGVkVG9rZW5zID0gZ2V0Q29udGVudFNpemVFc3RpbWF0ZShtY3BPdXRwdXQpXG4gIGNvbnN0IHNob3dXYXJuaW5nID0gZXN0aW1hdGVkVG9rZW5zID4gTUNQX09VVFBVVF9XQVJOSU5HX1RIUkVTSE9MRF9UT0tFTlNcbiAgY29uc3Qgd2FybmluZ01lc3NhZ2UgPSBzaG93V2FybmluZ1xuICAgID8gYCR7ZmlndXJlcy53YXJuaW5nfSBMYXJnZSBNQ1AgcmVzcG9uc2UgKH4ke2Zvcm1hdE51bWJlcihlc3RpbWF0ZWRUb2tlbnMpfSB0b2tlbnMpLCB0aGlzIGNhbiBmaWxsIHVwIGNvbnRleHQgcXVpY2tseWBcbiAgICA6IG51bGxcblxuICBsZXQgY29udGVudEVsZW1lbnQ6IFJlYWN0LlJlYWN0Tm9kZVxuICBpZiAoQXJyYXkuaXNBcnJheShtY3BPdXRwdXQpKSB7XG4gICAgY29uc3QgY29udGVudEJsb2NrcyA9IG1jcE91dHB1dC5tYXAoKGl0ZW0sIGkpID0+IHtcbiAgICAgIGlmIChpdGVtLnR5cGUgPT09ICdpbWFnZScpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICA8Qm94XG4gICAgICAgICAgICBrZXk9e2l9XG4gICAgICAgICAgICBqdXN0aWZ5Q29udGVudD1cInNwYWNlLWJldHdlZW5cIlxuICAgICAgICAgICAgb3ZlcmZsb3dYPVwiaGlkZGVuXCJcbiAgICAgICAgICAgIHdpZHRoPVwiMTAwJVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgICAgICA8VGV4dD5bSW1hZ2VdPC9UZXh0PlxuICAgICAgICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgICAgPC9Cb3g+XG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIC8vIEZvciB0ZXh0IGJsb2NrcyBhbmQgYW55IG90aGVyIGJsb2NrIHR5cGVzLCBleHRyYWN0IHRleHQgaWYgYXZhaWxhYmxlXG4gICAgICBjb25zdCB0ZXh0Q29udGVudCA9XG4gICAgICAgIGl0ZW0udHlwZSA9PT0gJ3RleHQnICYmXG4gICAgICAgICd0ZXh0JyBpbiBpdGVtICYmXG4gICAgICAgIGl0ZW0udGV4dCAhPT0gbnVsbCAmJlxuICAgICAgICBpdGVtLnRleHQgIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gU3RyaW5nKGl0ZW0udGV4dClcbiAgICAgICAgICA6ICcnXG4gICAgICByZXR1cm4gZmVhdHVyZSgnTUNQX1JJQ0hfT1VUUFVUJykgPyAoXG4gICAgICAgIDxNQ1BUZXh0T3V0cHV0IGtleT17aX0gY29udGVudD17dGV4dENvbnRlbnR9IHZlcmJvc2U9e3ZlcmJvc2V9IC8+XG4gICAgICApIDogKFxuICAgICAgICA8T3V0cHV0TGluZSBrZXk9e2l9IGNvbnRlbnQ9e3RleHRDb250ZW50fSB2ZXJib3NlPXt2ZXJib3NlfSAvPlxuICAgICAgKVxuICAgIH0pXG5cbiAgICAvLyBXcmFwIGFycmF5IGNvbnRlbnQgaW4gYSBjb2x1bW4gbGF5b3V0XG4gICAgY29udGVudEVsZW1lbnQgPSAoXG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiB3aWR0aD1cIjEwMCVcIj5cbiAgICAgICAge2NvbnRlbnRCbG9ja3N9XG4gICAgICA8L0JveD5cbiAgICApXG4gIH0gZWxzZSBpZiAoIW1jcE91dHB1dCkge1xuICAgIGNvbnRlbnRFbGVtZW50ID0gKFxuICAgICAgPEJveCBqdXN0aWZ5Q29udGVudD1cInNwYWNlLWJldHdlZW5cIiBvdmVyZmxvd1g9XCJoaWRkZW5cIiB3aWR0aD1cIjEwMCVcIj5cbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPihObyBjb250ZW50KTwvVGV4dD5cbiAgICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgICA8L0JveD5cbiAgICApXG4gIH0gZWxzZSB7XG4gICAgY29udGVudEVsZW1lbnQgPSBmZWF0dXJlKCdNQ1BfUklDSF9PVVRQVVQnKSA/IChcbiAgICAgIDxNQ1BUZXh0T3V0cHV0IGNvbnRlbnQ9e21jcE91dHB1dH0gdmVyYm9zZT17dmVyYm9zZX0gLz5cbiAgICApIDogKFxuICAgICAgPE91dHB1dExpbmUgY29udGVudD17bWNwT3V0cHV0fSB2ZXJib3NlPXt2ZXJib3NlfSAvPlxuICAgIClcbiAgfVxuXG4gIGlmICh3YXJuaW5nTWVzc2FnZSkge1xuICAgIHJldHVybiAoXG4gICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgPE1lc3NhZ2VSZXNwb25zZSBoZWlnaHQ9ezF9PlxuICAgICAgICAgIDxUZXh0IGNvbG9yPVwid2FybmluZ1wiPnt3YXJuaW5nTWVzc2FnZX08L1RleHQ+XG4gICAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICB7Y29udGVudEVsZW1lbnR9XG4gICAgICA8L0JveD5cbiAgICApXG4gIH1cblxuICByZXR1cm4gY29udGVudEVsZW1lbnRcbn1cblxuLyoqXG4gKiBSZW5kZXIgTUNQIHRleHQgb3V0cHV0LiBUcmllcyB0aHJlZSBzdHJhdGVnaWVzIGluIG9yZGVyOlxuICogMS4gSWYgSlNPTiB3cmFwcyBhIHNpbmdsZSBkb21pbmFudCB0ZXh0IHBheWxvYWQgKGUuZy4gc2xhY2snc1xuICogICAge1wibWVzc2FnZXNcIjpcImxpbmUxXFxubGluZTIuLi5cIn0pLCB1bndyYXAgYW5kIGxldCBPdXRwdXRMaW5lIHRydW5jYXRlLlxuICogMi4gSWYgSlNPTiBpcyBhIHNtYWxsIGZsYXQtaXNoIG9iamVjdCwgcmVuZGVyIGFzIGFsaWduZWQga2V5OiB2YWx1ZS5cbiAqIDMuIE90aGVyd2lzZSBmYWxsIHRocm91Z2ggdG8gT3V0cHV0TGluZSAocHJldHR5LXByaW50ICsgdHJ1bmNhdGUpLlxuICovXG5mdW5jdGlvbiBNQ1BUZXh0T3V0cHV0KHtcbiAgY29udGVudCxcbiAgdmVyYm9zZSxcbn06IHtcbiAgY29udGVudDogc3RyaW5nXG4gIHZlcmJvc2U6IGJvb2xlYW5cbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCB1bndyYXBwZWQgPSB0cnlVbndyYXBUZXh0UGF5bG9hZChjb250ZW50KVxuICBpZiAodW53cmFwcGVkICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxNZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICAgIHt1bndyYXBwZWQuZXh0cmFzLmxlbmd0aCA+IDAgJiYgKFxuICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgICAgIHt1bndyYXBwZWQuZXh0cmFzLm1hcCgoW2ssIHZdKSA9PiBgJHtrfTogJHt2fWApLmpvaW4oJyDCtyAnKX1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICApfVxuICAgICAgICAgIDxPdXRwdXRMaW5lIGNvbnRlbnQ9e3Vud3JhcHBlZC5ib2R5fSB2ZXJib3NlPXt2ZXJib3NlfSBsaW5raWZ5VXJscyAvPlxuICAgICAgICA8L0JveD5cbiAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgIClcbiAgfVxuICBjb25zdCBmbGF0ID0gdHJ5RmxhdHRlbkpzb24oY29udGVudClcbiAgaWYgKGZsYXQgIT09IG51bGwpIHtcbiAgICBjb25zdCBtYXhLZXlXaWR0aCA9IE1hdGgubWF4KC4uLmZsYXQubWFwKChba10pID0+IHN0cmluZ1dpZHRoKGspKSlcbiAgICByZXR1cm4gKFxuICAgICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCI+XG4gICAgICAgICAge2ZsYXQubWFwKChba2V5LCB2YWx1ZV0sIGkpID0+IChcbiAgICAgICAgICAgIDxUZXh0IGtleT17aX0+XG4gICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPntrZXkucGFkRW5kKG1heEtleVdpZHRoKX06IDwvVGV4dD5cbiAgICAgICAgICAgICAgPEFuc2k+e2xpbmtpZnlVcmxzSW5UZXh0KHZhbHVlKX08L0Fuc2k+XG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgKSl9XG4gICAgICAgIDwvQm94PlxuICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgKVxuICB9XG4gIHJldHVybiA8T3V0cHV0TGluZSBjb250ZW50PXtjb250ZW50fSB2ZXJib3NlPXt2ZXJib3NlfSBsaW5raWZ5VXJscyAvPlxufVxuXG4vKipcbiAqIFBhcnNlIGNvbnRlbnQgYXMgYSBKU09OIG9iamVjdCBhbmQgcmV0dXJuIGl0cyBlbnRyaWVzLiBOdWxsIGlmIGNvbnRlbnRcbiAqIGRvZXNuJ3QgcGFyc2UsIGlzbid0IGFuIG9iamVjdCwgaXMgdG9vIGxhcmdlLCBvciBoYXMgMC90b28tbWFueSBrZXlzLlxuICovXG5mdW5jdGlvbiBwYXJzZUpzb25FbnRyaWVzKFxuICBjb250ZW50OiBzdHJpbmcsXG4gIHsgbWF4Q2hhcnMsIG1heEtleXMgfTogeyBtYXhDaGFyczogbnVtYmVyOyBtYXhLZXlzOiBudW1iZXIgfSxcbik6IFtzdHJpbmcsIHVua25vd25dW10gfCBudWxsIHtcbiAgY29uc3QgdHJpbW1lZCA9IGNvbnRlbnQudHJpbSgpXG4gIGlmICh0cmltbWVkLmxlbmd0aCA9PT0gMCB8fCB0cmltbWVkLmxlbmd0aCA+IG1heENoYXJzIHx8IHRyaW1tZWRbMF0gIT09ICd7Jykge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgbGV0IHBhcnNlZDogdW5rbm93blxuICB0cnkge1xuICAgIHBhcnNlZCA9IGpzb25QYXJzZSh0cmltbWVkKVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmIChwYXJzZWQgPT09IG51bGwgfHwgdHlwZW9mIHBhcnNlZCAhPT0gJ29iamVjdCcgfHwgQXJyYXkuaXNBcnJheShwYXJzZWQpKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBjb25zdCBlbnRyaWVzID0gT2JqZWN0LmVudHJpZXMocGFyc2VkKVxuICBpZiAoZW50cmllcy5sZW5ndGggPT09IDAgfHwgZW50cmllcy5sZW5ndGggPiBtYXhLZXlzKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICByZXR1cm4gZW50cmllc1xufVxuXG4vKipcbiAqIElmIGNvbnRlbnQgcGFyc2VzIGFzIGEgSlNPTiBvYmplY3Qgd2hlcmUgZXZlcnkgdmFsdWUgaXMgYSBzY2FsYXIgb3IgYVxuICogc21hbGwgbmVzdGVkIG9iamVjdCwgZmxhdHRlbiBpdCB0byBba2V5LCBkaXNwbGF5VmFsdWVdIHBhaXJzLiBOZXN0ZWRcbiAqIG9iamVjdHMgZ2V0IG9uZS1saW5lIEpTT04uIFJldHVybnMgbnVsbCBpZiBjb250ZW50IGRvZXNuJ3QgcXVhbGlmeS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyeUZsYXR0ZW5Kc29uKGNvbnRlbnQ6IHN0cmluZyk6IFtzdHJpbmcsIHN0cmluZ11bXSB8IG51bGwge1xuICBjb25zdCBlbnRyaWVzID0gcGFyc2VKc29uRW50cmllcyhjb250ZW50LCB7XG4gICAgbWF4Q2hhcnM6IE1BWF9GTEFUX0pTT05fQ0hBUlMsXG4gICAgbWF4S2V5czogTUFYX0ZMQVRfSlNPTl9LRVlTLFxuICB9KVxuICBpZiAoZW50cmllcyA9PT0gbnVsbCkgcmV0dXJuIG51bGxcbiAgY29uc3QgcmVzdWx0OiBbc3RyaW5nLCBzdHJpbmddW10gPSBbXVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJlc3VsdC5wdXNoKFtrZXksIHZhbHVlXSlcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgdmFsdWUgPT09IG51bGwgfHxcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgfHxcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nXG4gICAgKSB7XG4gICAgICByZXN1bHQucHVzaChba2V5LCBTdHJpbmcodmFsdWUpXSlcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IGNvbXBhY3QgPSBqc29uU3RyaW5naWZ5KHZhbHVlKVxuICAgICAgaWYgKGNvbXBhY3QubGVuZ3RoID4gMTIwKSByZXR1cm4gbnVsbFxuICAgICAgcmVzdWx0LnB1c2goW2tleSwgY29tcGFjdF0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuLyoqXG4gKiBJZiBjb250ZW50IGlzIGEgSlNPTiBvYmplY3Qgd2hlcmUgb25lIGtleSBob2xkcyBhIGRvbWluYW50IHN0cmluZyBwYXlsb2FkXG4gKiAobXVsdGlsaW5lIG9yIGxvbmcpIGFuZCBhbGwgc2libGluZ3MgYXJlIHNtYWxsIHNjYWxhcnMsIHVud3JhcCBpdC4gVGhpc1xuICogaGFuZGxlcyB0aGUgY29tbW9uIE1DUCBwYXR0ZXJuIG9mIHtcIm1lc3NhZ2VzXCI6XCJsaW5lMVxcbmxpbmUyLi4uXCJ9IHdoZXJlXG4gKiBwcmV0dHktcHJpbnRpbmcga2VlcHMgXFxuIGVzY2FwZWQgYnV0IHdlIHdhbnQgcmVhbCBsaW5lIGJyZWFrcyArIHRydW5jYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cnlVbndyYXBUZXh0UGF5bG9hZChcbiAgY29udGVudDogc3RyaW5nLFxuKTogeyBib2R5OiBzdHJpbmc7IGV4dHJhczogW3N0cmluZywgc3RyaW5nXVtdIH0gfCBudWxsIHtcbiAgY29uc3QgZW50cmllcyA9IHBhcnNlSnNvbkVudHJpZXMoY29udGVudCwge1xuICAgIG1heENoYXJzOiBNQVhfSlNPTl9QQVJTRV9DSEFSUyxcbiAgICBtYXhLZXlzOiA0LFxuICB9KVxuICBpZiAoZW50cmllcyA9PT0gbnVsbCkgcmV0dXJuIG51bGxcbiAgLy8gRmluZCB0aGUgb25lIGRvbWluYW50IHN0cmluZyBwYXlsb2FkLiBUcmltIGZpcnN0OiBhIHRyYWlsaW5nIFxcbiBvbiBhXG4gIC8vIHNob3J0IHNpYmxpbmcgKGUuZy4gcGFnaW5hdGlvbiBoaW50cykgc2hvdWxkbid0IG1ha2UgaXQgXCJkb21pbmFudFwiLlxuICBsZXQgYm9keTogc3RyaW5nIHwgbnVsbCA9IG51bGxcbiAgY29uc3QgZXh0cmFzOiBbc3RyaW5nLCBzdHJpbmddW10gPSBbXVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHQgPSB2YWx1ZS50cmltRW5kKClcbiAgICAgIGNvbnN0IGlzRG9taW5hbnQgPVxuICAgICAgICB0Lmxlbmd0aCA+IFVOV1JBUF9NSU5fU1RSSU5HX0xFTiB8fCAodC5pbmNsdWRlcygnXFxuJykgJiYgdC5sZW5ndGggPiA1MClcbiAgICAgIGlmIChpc0RvbWluYW50KSB7XG4gICAgICAgIGlmIChib2R5ICE9PSBudWxsKSByZXR1cm4gbnVsbCAvLyB0d28gYmlnIHN0cmluZ3Mg4oCUIGFtYmlndW91c1xuICAgICAgICBib2R5ID0gdFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgaWYgKHQubGVuZ3RoID4gMTUwKSByZXR1cm4gbnVsbFxuICAgICAgZXh0cmFzLnB1c2goW2tleSwgdC5yZXBsYWNlKC9cXHMrL2csICcgJyldKVxuICAgIH0gZWxzZSBpZiAoXG4gICAgICB2YWx1ZSA9PT0gbnVsbCB8fFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyB8fFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbidcbiAgICApIHtcbiAgICAgIGV4dHJhcy5wdXNoKFtrZXksIFN0cmluZyh2YWx1ZSldKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbCAvLyBuZXN0ZWQgb2JqZWN0L2FycmF5IOKAlCB1c2UgZmxhdCBvciBwcmV0dHktcHJpbnQgcGF0aFxuICAgIH1cbiAgfVxuICBpZiAoYm9keSA9PT0gbnVsbCkgcmV0dXJuIG51bGxcbiAgcmV0dXJuIHsgYm9keSwgZXh0cmFzIH1cbn1cblxuY29uc3QgU0xBQ0tfQVJDSElWRVNfUkUgPVxuICAvXmh0dHBzOlxcL1xcL1thLXowLTktXStcXC5zbGFja1xcLmNvbVxcL2FyY2hpdmVzXFwvKFtBLVowLTldKylcXC9wXFxkKyQvXG5cbi8qKlxuICogRGV0ZWN0IGEgU2xhY2sgc2VuZC1tZXNzYWdlIHJlc3VsdCBhbmQgcmV0dXJuIGEgY29tcGFjdCB7Y2hhbm5lbCwgdXJsfSBwYWlyLlxuICogTWF0Y2hlcyBib3RoIGhvc3RlZCAoY2xhdWRlLmFpIFNsYWNrKSBhbmQgY29tbXVuaXR5IE1DUCBzZXJ2ZXIgc2hhcGVzIOKAlFxuICogYm90aCByZXR1cm4gYG1lc3NhZ2VfbGlua2AgaW4gdGhlIHJlc3VsdC4gVGhlIGNoYW5uZWwgbGFiZWwgcHJlZmVycyB0aGVcbiAqIHRvb2wgaW5wdXQgKG1heSBiZSBhIG5hbWUgbGlrZSBcIiNmb29cIiBvciBhbiBJRCBsaWtlIFwiQzA5RVZEQU4xTktcIikgYW5kXG4gKiBmYWxscyBiYWNrIHRvIHRoZSBJRCBwYXJzZWQgZnJvbSB0aGUgYXJjaGl2ZXMgVVJMLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJ5U2xhY2tTZW5kQ29tcGFjdChcbiAgb3V0cHV0OiBzdHJpbmcgfCBNQ1BUb29sUmVzdWx0LFxuICBpbnB1dDogdW5rbm93bixcbik6IHsgY2hhbm5lbDogc3RyaW5nOyB1cmw6IHN0cmluZyB9IHwgbnVsbCB7XG4gIGxldCB0ZXh0OiB1bmtub3duID0gb3V0cHV0XG4gIGlmIChBcnJheS5pc0FycmF5KG91dHB1dCkpIHtcbiAgICBjb25zdCBibG9jayA9IG91dHB1dC5maW5kKGIgPT4gYi50eXBlID09PSAndGV4dCcpXG4gICAgdGV4dCA9IGJsb2NrICYmICd0ZXh0JyBpbiBibG9jayA/IGJsb2NrLnRleHQgOiB1bmRlZmluZWRcbiAgfVxuICBpZiAodHlwZW9mIHRleHQgIT09ICdzdHJpbmcnIHx8ICF0ZXh0LmluY2x1ZGVzKCdcIm1lc3NhZ2VfbGlua1wiJykpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgY29uc3QgZW50cmllcyA9IHBhcnNlSnNvbkVudHJpZXModGV4dCwgeyBtYXhDaGFyczogMjAwMCwgbWF4S2V5czogNiB9KVxuICBjb25zdCB1cmwgPSBlbnRyaWVzPy5maW5kKChba10pID0+IGsgPT09ICdtZXNzYWdlX2xpbmsnKT8uWzFdXG4gIGlmICh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgcmV0dXJuIG51bGxcbiAgY29uc3QgbSA9IFNMQUNLX0FSQ0hJVkVTX1JFLmV4ZWModXJsKVxuICBpZiAoIW0pIHJldHVybiBudWxsXG5cbiAgY29uc3QgaW5wID0gaW5wdXQgYXMgeyBjaGFubmVsX2lkPzogdW5rbm93bjsgY2hhbm5lbD86IHVua25vd24gfSB8IHVuZGVmaW5lZFxuICBjb25zdCByYXcgPSBpbnA/LmNoYW5uZWxfaWQgPz8gaW5wPy5jaGFubmVsID8/IG1bMV1cbiAgY29uc3QgbGFiZWwgPSB0eXBlb2YgcmF3ID09PSAnc3RyaW5nJyAmJiByYXcgPyByYXcgOiAnc2xhY2snXG4gIHJldHVybiB7IGNoYW5uZWw6IGxhYmVsLnN0YXJ0c1dpdGgoJyMnKSA/IGxhYmVsIDogYCMke2xhYmVsfWAsIHVybCB9XG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxTQUFTQSxPQUFPLFFBQVEsWUFBWTtBQUNwQyxPQUFPQyxPQUFPLE1BQU0sU0FBUztBQUM3QixPQUFPLEtBQUtDLEtBQUssTUFBTSxPQUFPO0FBQzlCLGNBQWNDLENBQUMsUUFBUSxRQUFRO0FBQy9CLFNBQVNDLFdBQVcsUUFBUSwrQ0FBK0M7QUFDM0UsU0FBU0MsZUFBZSxRQUFRLHFDQUFxQztBQUNyRSxTQUNFQyxpQkFBaUIsRUFDakJDLFVBQVUsUUFDTCxzQ0FBc0M7QUFDN0MsU0FBU0MsV0FBVyxRQUFRLDBCQUEwQjtBQUN0RCxTQUFTQyxJQUFJLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxRQUFRLGNBQWM7QUFDOUMsY0FBY0MsZ0JBQWdCLFFBQVEsZUFBZTtBQUNyRCxjQUFjQyxlQUFlLFFBQVEsd0JBQXdCO0FBQzdELGNBQWNDLFdBQVcsUUFBUSxzQkFBc0I7QUFDdkQsU0FBU0MsWUFBWSxRQUFRLHVCQUF1QjtBQUNwRCxTQUFTQyxlQUFlLFFBQVEsMEJBQTBCO0FBQzFELFNBQ0VDLHNCQUFzQixFQUN0QixLQUFLQyxhQUFhLFFBQ2IsOEJBQThCO0FBQ3JDLFNBQVNDLFNBQVMsRUFBRUMsYUFBYSxRQUFRLCtCQUErQjtBQUN4RSxjQUFjQyxXQUFXLFFBQVEsY0FBYzs7QUFFL0M7QUFDQSxNQUFNQyxtQ0FBbUMsR0FBRyxNQUFNOztBQUVsRDtBQUNBO0FBQ0E7QUFDQSxNQUFNQyxxQkFBcUIsR0FBRyxFQUFFOztBQUVoQztBQUNBO0FBQ0EsTUFBTUMsa0JBQWtCLEdBQUcs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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/tools/NotebookEditTool/UI.tsx b/_all-in-one-upload/cc-haha/src/tools/NotebookEditTool/UI.tsx new file mode 100644 index 0000000..017bbfd --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/NotebookEditTool/UI.tsx @@ -0,0 +1,93 @@ +import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'; +import * as React from 'react'; +import type { Message, ProgressMessage } from 'src/types/message.js'; +import { extractTag } from 'src/utils/messages.js'; +import type { ThemeName } from 'src/utils/theme.js'; +import type { z } from 'zod/v4'; +import { FallbackToolUseErrorMessage } from '../../components/FallbackToolUseErrorMessage.js'; +import { FilePathLink } from '../../components/FilePathLink.js'; +import { HighlightedCode } from '../../components/HighlightedCode.js'; +import { MessageResponse } from '../../components/MessageResponse.js'; +import { NotebookEditToolUseRejectedMessage } from '../../components/NotebookEditToolUseRejectedMessage.js'; +import { Box, Text } from '../../ink.js'; +import type { Tools } from '../../Tool.js'; +import { getDisplayPath } from '../../utils/file.js'; +import type { inputSchema, Output } from './NotebookEditTool.js'; +export function getToolUseSummary(input: Partial>> | undefined): string | null { + if (!input?.notebook_path) { + return null; + } + return getDisplayPath(input.notebook_path); +} +export function renderToolUseMessage({ + notebook_path, + cell_id, + new_source, + cell_type, + edit_mode +}: Partial>>, { + verbose +}: { + verbose: boolean; +}): React.ReactNode { + if (!notebook_path || !new_source || !cell_type) { + return null; + } + const displayPath = verbose ? notebook_path : getDisplayPath(notebook_path); + if (verbose) { + return <> + {displayPath} + {`@${cell_id}, content: ${new_source.slice(0, 30)}…, cell_type: ${cell_type}, edit_mode: ${edit_mode ?? 'replace'}`} + ; + } + return <> + {displayPath} + {`@${cell_id}`} + ; +} +export function renderToolUseRejectedMessage(input: z.infer>, { + verbose +}: { + columns?: number; + messages?: Message[]; + progressMessagesForMessage?: ProgressMessage[]; + theme?: ThemeName; + tools?: Tools; + verbose: boolean; +}): React.ReactNode { + return ; +} +export function renderToolUseErrorMessage(result: ToolResultBlockParam['content'], { + verbose +}: { + verbose: boolean; +}): React.ReactNode { + if (!verbose && typeof result === 'string' && extractTag(result, 'tool_use_error')) { + return + Error editing notebook + ; + } + return ; +} +export function renderToolResultMessage({ + cell_id, + new_source, + error +}: Output): React.ReactNode { + if (error) { + return + {error} + ; + } + return + + + Updated cell {cell_id}: + + + + + + ; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJUb29sUmVzdWx0QmxvY2tQYXJhbSIsIlJlYWN0IiwiTWVzc2FnZSIsIlByb2dyZXNzTWVzc2FnZSIsImV4dHJhY3RUYWciLCJUaGVtZU5hbWUiLCJ6IiwiRmFsbGJhY2tUb29sVXNlRXJyb3JNZXNzYWdlIiwiRmlsZVBhdGhMaW5rIiwiSGlnaGxpZ2h0ZWRDb2RlIiwiTWVzc2FnZVJlc3BvbnNlIiwiTm90ZWJvb2tFZGl0VG9vbFVzZVJlamVjdGVkTWVzc2FnZSIsIkJveCIsIlRleHQiLCJUb29scyIsImdldERpc3BsYXlQYXRoIiwiaW5wdXRTY2hlbWEiLCJPdXRwdXQiLCJnZXRUb29sVXNlU3VtbWFyeSIsImlucHV0IiwiUGFydGlhbCIsImluZmVyIiwiUmV0dXJuVHlwZSIsIm5vdGVib29rX3BhdGgiLCJyZW5kZXJUb29sVXNlTWVzc2FnZSIsImNlbGxfaWQiLCJuZXdfc291cmNlIiwiY2VsbF90eXBlIiwiZWRpdF9tb2RlIiwidmVyYm9zZSIsIlJlYWN0Tm9kZSIsImRpc3BsYXlQYXRoIiwic2xpY2UiLCJyZW5kZXJUb29sVXNlUmVqZWN0ZWRNZXNzYWdlIiwiY29sdW1ucyIsIm1lc3NhZ2VzIiwicHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJ0aGVtZSIsInRvb2xzIiwicmVuZGVyVG9vbFVzZUVycm9yTWVzc2FnZSIsInJlc3VsdCIsInJlbmRlclRvb2xSZXN1bHRNZXNzYWdlIiwiZXJyb3IiXSwic291cmNlcyI6WyJVSS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBUb29sUmVzdWx0QmxvY2tQYXJhbSB9IGZyb20gJ0BhbnRocm9waWMtYWkvc2RrL3Jlc291cmNlcy9pbmRleC5tanMnXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgTWVzc2FnZSwgUHJvZ3Jlc3NNZXNzYWdlIH0gZnJvbSAnc3JjL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgeyBleHRyYWN0VGFnIH0gZnJvbSAnc3JjL3V0aWxzL21lc3NhZ2VzLmpzJ1xuaW1wb3J0IHR5cGUgeyBUaGVtZU5hbWUgfSBmcm9tICdzcmMvdXRpbHMvdGhlbWUuanMnXG5pbXBvcnQgdHlwZSB7IHogfSBmcm9tICd6b2QvdjQnXG5pbXBvcnQgeyBGYWxsYmFja1Rvb2xVc2VFcnJvck1lc3NhZ2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL0ZhbGxiYWNrVG9vbFVzZUVycm9yTWVzc2FnZS5qcydcbmltcG9ydCB7IEZpbGVQYXRoTGluayB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvRmlsZVBhdGhMaW5rLmpzJ1xuaW1wb3J0IHsgSGlnaGxpZ2h0ZWRDb2RlIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9IaWdobGlnaHRlZENvZGUuanMnXG5pbXBvcnQgeyBNZXNzYWdlUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL01lc3NhZ2VSZXNwb25zZS5qcydcbmltcG9ydCB7IE5vdGVib29rRWRpdFRvb2xVc2VSZWplY3RlZE1lc3NhZ2UgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL05vdGVib29rRWRpdFRvb2xVc2VSZWplY3RlZE1lc3NhZ2UuanMnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgdHlwZSB7IFRvb2xzIH0gZnJvbSAnLi4vLi4vVG9vbC5qcydcbmltcG9ydCB7IGdldERpc3BsYXlQYXRoIH0gZnJvbSAnLi4vLi4vdXRpbHMvZmlsZS5qcydcbmltcG9ydCB0eXBlIHsgaW5wdXRTY2hlbWEsIE91dHB1dCB9IGZyb20gJy4vTm90ZWJvb2tFZGl0VG9vbC5qcydcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRvb2xVc2VTdW1tYXJ5KFxuICBpbnB1dDogUGFydGlhbDx6LmluZmVyPFJldHVyblR5cGU8dHlwZW9mIGlucHV0U2NoZW1hPj4+IHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICghaW5wdXQ/Lm5vdGVib29rX3BhdGgpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIHJldHVybiBnZXREaXNwbGF5UGF0aChpbnB1dC5ub3RlYm9va19wYXRoKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFVzZU1lc3NhZ2UoXG4gIHtcbiAgICBub3RlYm9va19wYXRoLFxuICAgIGNlbGxfaWQsXG4gICAgbmV3X3NvdXJjZSxcbiAgICBjZWxsX3R5cGUsXG4gICAgZWRpdF9tb2RlLFxuICB9OiBQYXJ0aWFsPHouaW5mZXI8UmV0dXJuVHlwZTx0eXBlb2YgaW5wdXRTY2hlbWE+Pj4sXG4gIHsgdmVyYm9zZSB9OiB7IHZlcmJvc2U6IGJvb2xlYW4gfSxcbik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGlmICghbm90ZWJvb2tfcGF0aCB8fCAhbmV3X3NvdXJjZSB8fCAhY2VsbF90eXBlKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBjb25zdCBkaXNwbGF5UGF0aCA9IHZlcmJvc2UgPyBub3RlYm9va19wYXRoIDogZ2V0RGlzcGxheVBhdGgobm90ZWJvb2tfcGF0aClcbiAgaWYgKHZlcmJvc2UpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPD5cbiAgICAgICAgPEZpbGVQYXRoTGluayBmaWxlUGF0aD17bm90ZWJvb2tfcGF0aH0+e2Rpc3BsYXlQYXRofTwvRmlsZVBhdGhMaW5rPlxuICAgICAgICB7YEAke2NlbGxfaWR9LCBjb250ZW50OiAke25ld19zb3VyY2Uuc2xpY2UoMCwgMzApfeKApiwgY2VsbF90eXBlOiAke2NlbGxfdHlwZX0sIGVkaXRfbW9kZTogJHtlZGl0X21vZGUgPz8gJ3JlcGxhY2UnfWB9XG4gICAgICA8Lz5cbiAgICApXG4gIH1cbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAgPEZpbGVQYXRoTGluayBmaWxlUGF0aD17bm90ZWJvb2tfcGF0aH0+e2Rpc3BsYXlQYXRofTwvRmlsZVBhdGhMaW5rPlxuICAgICAge2BAJHtjZWxsX2lkfWB9XG4gICAgPC8+XG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclRvb2xVc2VSZWplY3RlZE1lc3NhZ2UoXG4gIGlucHV0OiB6LmluZmVyPFJldHVyblR5cGU8dHlwZW9mIGlucHV0U2NoZW1hPj4sXG4gIHtcbiAgICB2ZXJib3NlLFxuICB9OiB7XG4gICAgY29sdW1ucz86IG51bWJlclxuICAgIG1lc3NhZ2VzPzogTWVzc2FnZVtdXG4gICAgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2U/OiBQcm9ncmVzc01lc3NhZ2VbXVxuICAgIHRoZW1lPzogVGhlbWVOYW1lXG4gICAgdG9vbHM/OiBUb29sc1xuICAgIHZlcmJvc2U6IGJvb2xlYW5cbiAgfSxcbik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIHJldHVybiAoXG4gICAgPE5vdGVib29rRWRpdFRvb2xVc2VSZWplY3RlZE1lc3NhZ2VcbiAgICAgIG5vdGVib29rX3BhdGg9e2lucHV0Lm5vdGVib29rX3BhdGh9XG4gICAgICBjZWxsX2lkPXtpbnB1dC5jZWxsX2lkfVxuICAgICAgbmV3X3NvdXJjZT17aW5wdXQubmV3X3NvdXJjZX1cbiAgICAgIGNlbGxfdHlwZT17aW5wdXQuY2VsbF90eXBlfVxuICAgICAgZWRpdF9tb2RlPXtpbnB1dC5lZGl0X21vZGV9XG4gICAgICB2ZXJib3NlPXt2ZXJib3NlfVxuICAgIC8+XG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclRvb2xVc2VFcnJvck1lc3NhZ2UoXG4gIHJlc3VsdDogVG9vbFJlc3VsdEJsb2NrUGFyYW1bJ2NvbnRlbnQnXSxcbiAgeyB2ZXJib3NlIH06IHsgdmVyYm9zZTogYm9vbGVhbiB9LFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgaWYgKFxuICAgICF2ZXJib3NlICYmXG4gICAgdHlwZW9mIHJlc3VsdCA9PT0gJ3N0cmluZycgJiZcbiAgICBleHRyYWN0VGFnKHJlc3VsdCwgJ3Rvb2xfdXNlX2Vycm9yJylcbiAgKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxNZXNzYWdlUmVzcG9uc2U+XG4gICAgICAgIDxUZXh0IGNvbG9yPVwiZXJyb3JcIj5FcnJvciBlZGl0aW5nIG5vdGVib29rPC9UZXh0PlxuICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgKVxuICB9XG4gIHJldHVybiA8RmFsbGJhY2tUb29sVXNlRXJyb3JNZXNzYWdlIHJlc3VsdD17cmVzdWx0fSB2ZXJib3NlPXt2ZXJib3NlfSAvPlxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyVG9vbFJlc3VsdE1lc3NhZ2Uoe1xuICBjZWxsX2lkLFxuICBuZXdfc291cmNlLFxuICBlcnJvcixcbn06IE91dHB1dCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGlmIChlcnJvcikge1xuICAgIHJldHVybiAoXG4gICAgICA8TWVzc2FnZVJlc3BvbnNlPlxuICAgICAgICA8VGV4dCBjb2xvcj1cImVycm9yXCI+e2Vycm9yfTwvVGV4dD5cbiAgICAgIDwvTWVzc2FnZVJlc3BvbnNlPlxuICAgIClcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgICA8VGV4dD5cbiAgICAgICAgICBVcGRhdGVkIGNlbGwgPFRleHQgYm9sZD57Y2VsbF9pZH08L1RleHQ+OlxuICAgICAgICA8L1RleHQ+XG4gICAgICAgIDxCb3ggbWFyZ2luTGVmdD17Mn0+XG4gICAgICAgICAgPEhpZ2hsaWdodGVkQ29kZSBjb2RlPXtuZXdfc291cmNlfSBmaWxlUGF0aD1cIm5vdGVib29rLnB5XCIgLz5cbiAgICAgICAgPC9Cb3g+XG4gICAgICA8L0JveD5cbiAgICA8L01lc3NhZ2VSZXNwb25zZT5cbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQSxjQUFjQSxvQkFBb0IsUUFBUSx1Q0FBdUM7QUFDakYsT0FBTyxLQUFLQyxLQUFLLE1BQU0sT0FBTztBQUM5QixjQUFjQyxPQUFPLEVBQUVDLGVBQWUsUUFBUSxzQkFBc0I7QUFDcEUsU0FBU0MsVUFBVSxRQUFRLHVCQUF1QjtBQUNsRCxjQUFjQyxTQUFTLFFBQVEsb0JBQW9CO0FBQ25ELGNBQWND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 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/tools/OverflowTestTool/OverflowTestTool.ts b/_all-in-one-upload/cc-haha/src/tools/OverflowTestTool/OverflowTestTool.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/OverflowTestTool/OverflowTestTool.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/clmTypes.ts b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/clmTypes.ts new file mode 100644 index 0000000..a615563 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/clmTypes.ts @@ -0,0 +1,211 @@ +/** + * PowerShell Constrained Language Mode allowed types. + * + * Microsoft's CLM restricts .NET type usage to this allowlist when PS runs + * under AppLocker/WDAC system lockdown. Any type NOT in this set is considered + * unsafe for untrusted code execution. + * + * We invert this: type literals not in this set → ask. One canonical check + * replaces enumerating individual dangerous types (named pipes, reflection, + * process spawning, P/Invoke marshaling, etc.). Microsoft maintains the list. + * + * Source: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes + * + * Normalization: entries stored lowercase, short AND full names where both + * exist (PS resolves type accelerators like [int] → System.Int32 at runtime; + * we match against what the AST emits, which is the literal text). + */ +export const CLM_ALLOWED_TYPES: ReadonlySet = new Set( + [ + // Type accelerators (short names as they appear in AST TypeName.Name) + // SECURITY: 'adsi' and 'adsisearcher' REMOVED. Both are Active Directory + // Service Interface types that perform NETWORK BINDS when cast: + // [adsi]'LDAP://evil.com/...' → connects to LDAP server + // [adsisearcher]'(objectClass=user)' → binds to AD and queries + // Microsoft's CLM allows these because it's for Windows admins in trusted + // domains; we block them since the target isn't validated. + 'alias', + 'allowemptycollection', + 'allowemptystring', + 'allownull', + 'argumentcompleter', + 'argumentcompletions', + 'array', + 'bigint', + 'bool', + 'byte', + 'char', + 'cimclass', + 'cimconverter', + 'ciminstance', + // 'cimsession' REMOVED — see wmi/adsi comment below + 'cimtype', + 'cmdletbinding', + 'cultureinfo', + 'datetime', + 'decimal', + 'double', + 'dsclocalconfigurationmanager', + 'dscproperty', + 'dscresource', + 'experimentaction', + 'experimental', + 'experimentalfeature', + 'float', + 'guid', + 'hashtable', + 'int', + 'int16', + 'int32', + 'int64', + 'ipaddress', + 'ipendpoint', + 'long', + 'mailaddress', + 'norunspaceaffinity', + 'nullstring', + 'objectsecurity', + 'ordered', + 'outputtype', + 'parameter', + 'physicaladdress', + 'pscredential', + 'pscustomobject', + 'psdefaultvalue', + 'pslistmodifier', + 'psobject', + 'psprimitivedictionary', + 'pstypenameattribute', + 'ref', + 'regex', + 'sbyte', + 'securestring', + 'semver', + 'short', + 'single', + 'string', + 'supportswildcards', + 'switch', + 'timespan', + 'uint', + 'uint16', + 'uint32', + 'uint64', + 'ulong', + 'uri', + 'ushort', + 'validatecount', + 'validatedrive', + 'validatelength', + 'validatenotnull', + 'validatenotnullorempty', + 'validatenotnullorwhitespace', + 'validatepattern', + 'validaterange', + 'validatescript', + 'validateset', + 'validatetrusteddata', + 'validateuserdrive', + 'version', + 'void', + 'wildcardpattern', + // SECURITY: 'wmi', 'wmiclass', 'wmisearcher', 'cimsession' REMOVED. + // WMI type casts perform WMI queries which can target remote computers + // (network request) and access dangerous classes like Win32_Process. + // cimsession creates a CIM session (network connection to remote host). + // [wmi]'\\evil-host\root\cimv2:Win32_Process.Handle="1"' → remote WMI + // [wmisearcher]'SELECT * FROM Win32_Process' → runs WQL query + // Same rationale as adsi/adsisearcher removal above. + 'x500distinguishedname', + 'x509certificate', + 'xml', + // Full names for accelerators that resolve to System.* (AST may emit either) + 'system.array', + 'system.boolean', + 'system.byte', + 'system.char', + 'system.datetime', + 'system.decimal', + 'system.double', + 'system.guid', + 'system.int16', + 'system.int32', + 'system.int64', + 'system.numerics.biginteger', + 'system.sbyte', + 'system.single', + 'system.string', + 'system.timespan', + 'system.uint16', + 'system.uint32', + 'system.uint64', + 'system.uri', + 'system.version', + 'system.void', + 'system.collections.hashtable', + 'system.text.regularexpressions.regex', + 'system.globalization.cultureinfo', + 'system.net.ipaddress', + 'system.net.ipendpoint', + 'system.net.mail.mailaddress', + 'system.net.networkinformation.physicaladdress', + 'system.security.securestring', + 'system.security.cryptography.x509certificates.x509certificate', + 'system.security.cryptography.x509certificates.x500distinguishedname', + 'system.xml.xmldocument', + // System.Management.Automation.* — FQ equivalents of PS-specific accelerators + 'system.management.automation.pscredential', + 'system.management.automation.pscustomobject', + 'system.management.automation.pslistmodifier', + 'system.management.automation.psobject', + 'system.management.automation.psprimitivedictionary', + 'system.management.automation.psreference', + 'system.management.automation.semanticversion', + 'system.management.automation.switchparameter', + 'system.management.automation.wildcardpattern', + 'system.management.automation.language.nullstring', + // Microsoft.Management.Infrastructure.* — FQ equivalents of CIM accelerators + // SECURITY: cimsession FQ REMOVED — same network-bind hazard as short name + // (creates a CIM session to a remote host). + 'microsoft.management.infrastructure.cimclass', + 'microsoft.management.infrastructure.cimconverter', + 'microsoft.management.infrastructure.ciminstance', + 'microsoft.management.infrastructure.cimtype', + // FQ equivalents of remaining short-name accelerators + // SECURITY: DirectoryEntry/DirectorySearcher/ManagementObject/ + // ManagementClass/ManagementObjectSearcher FQ REMOVED — same network-bind + // hazard as short names adsi/adsisearcher/wmi/wmiclass/wmisearcher + // (LDAP bind, remote WMI). See short-name removal comments above. + 'system.collections.specialized.ordereddictionary', + 'system.security.accesscontrol.objectsecurity', + // Arrays of allowed types are allowed (e.g. [string[]]) + // normalizeTypeName strips [] before lookup, so store the base name + 'object', + 'system.object', + // ModuleSpecification — full qualified name + 'microsoft.powershell.commands.modulespecification', + ].map(t => t.toLowerCase()), +) + +/** + * Normalize a type name from AST TypeName.FullName or TypeName.Name. + * Handles array suffix ([]) and generic brackets. + */ +export function normalizeTypeName(name: string): string { + // Strip array suffix: "String[]" → "string" (arrays of allowed types are allowed) + // Strip generic args: "List[int]" → "list" (conservative — the generic wrapper + // might be unsafe even if the type arg is safe, so we check the outer type) + return name + .toLowerCase() + .replace(/\[\]$/, '') + .replace(/\[.*\]$/, '') + .trim() +} + +/** + * True if typeName (from AST) is in Microsoft's CLM allowlist. + * Types NOT in this set trigger ask — they access system APIs CLM blocks. + */ +export function isClmAllowedType(typeName: string): boolean { + return CLM_ALLOWED_TYPES.has(normalizeTypeName(typeName)) +} diff --git a/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/commandSemantics.ts b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/commandSemantics.ts new file mode 100644 index 0000000..2fd66fc --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/commandSemantics.ts @@ -0,0 +1,142 @@ +/** + * Command semantics configuration for interpreting exit codes in PowerShell. + * + * PowerShell-native cmdlets do NOT need exit-code semantics: + * - Select-String (grep equivalent) exits 0 on no-match (returns $null) + * - Compare-Object (diff equivalent) exits 0 regardless + * - Test-Path exits 0 regardless (returns bool via pipeline) + * Native cmdlets signal failure via terminating errors ($?), not exit codes. + * + * However, EXTERNAL executables invoked from PowerShell DO set $LASTEXITCODE, + * and many use non-zero codes to convey information rather than failure: + * - grep.exe / rg.exe (Git for Windows, scoop, etc.): 1 = no match + * - findstr.exe (Windows native): 1 = no match + * - robocopy.exe (Windows native): 0-7 = success, 8+ = error (notorious!) + * + * Without this module, PowerShellTool throws ShellError on any non-zero exit, + * so `robocopy` reporting "files copied successfully" (exit 1) shows as an error. + */ + +export type CommandSemantic = ( + exitCode: number, + stdout: string, + stderr: string, +) => { + isError: boolean + message?: string +} + +/** + * Default semantic: treat only 0 as success, everything else as error + */ +const DEFAULT_SEMANTIC: CommandSemantic = (exitCode, _stdout, _stderr) => ({ + isError: exitCode !== 0, + message: + exitCode !== 0 ? `Command failed with exit code ${exitCode}` : undefined, +}) + +/** + * grep / ripgrep: 0 = matches found, 1 = no matches, 2+ = error + */ +const GREP_SEMANTIC: CommandSemantic = (exitCode, _stdout, _stderr) => ({ + isError: exitCode >= 2, + message: exitCode === 1 ? 'No matches found' : undefined, +}) + +/** + * Command-specific semantics for external executables. + * Keys are lowercase command names WITHOUT .exe suffix. + * + * Deliberately omitted: + * - 'diff': Ambiguous. Windows PowerShell 5.1 aliases `diff` → Compare-Object + * (exit 0 on differ), but PS Core / Git for Windows may resolve to diff.exe + * (exit 1 on differ). Cannot reliably interpret. + * - 'fc': Ambiguous. PowerShell aliases `fc` → Format-Custom (a native cmdlet), + * but `fc.exe` is the Windows file compare utility (exit 1 = files differ). + * Same aliasing problem as `diff`. + * - 'find': Ambiguous. Windows find.exe (text search) vs Unix find.exe + * (file search via Git for Windows) have different semantics. + * - 'test', '[': Not PowerShell constructs. + * - 'select-string', 'compare-object', 'test-path': Native cmdlets exit 0. + */ +const COMMAND_SEMANTICS: Map = new Map([ + // External grep/ripgrep (Git for Windows, scoop, choco) + ['grep', GREP_SEMANTIC], + ['rg', GREP_SEMANTIC], + + // findstr.exe: Windows native text search + // 0 = match found, 1 = no match, 2 = error + ['findstr', GREP_SEMANTIC], + + // robocopy.exe: Windows native robust file copy + // Exit codes are a BITFIELD — 0-7 are success, 8+ indicates at least one failure: + // 0 = no files copied, no mismatch, no failures (already in sync) + // 1 = files copied successfully + // 2 = extra files/dirs detected (no copy) + // 4 = mismatched files/dirs detected + // 8 = some files/dirs could not be copied (copy errors) + // 16 = serious error (robocopy did not copy any files) + // This is the single most common "CI failed but nothing's wrong" Windows gotcha. + [ + 'robocopy', + (exitCode, _stdout, _stderr) => ({ + isError: exitCode >= 8, + message: + exitCode === 0 + ? 'No files copied (already in sync)' + : exitCode >= 1 && exitCode < 8 + ? exitCode & 1 + ? 'Files copied successfully' + : 'Robocopy completed (no errors)' + : undefined, + }), + ], +]) + +/** + * Extract the command name from a single pipeline segment. + * Strips leading `&` / `.` call operators and `.exe` suffix, lowercases. + */ +function extractBaseCommand(segment: string): string { + // Strip PowerShell call operators: & "cmd", . "cmd" + // (& and . at segment start followed by whitespace invoke the next token) + const stripped = segment.trim().replace(/^[&.]\s+/, '') + const firstToken = stripped.split(/\s+/)[0] || '' + // Strip surrounding quotes if command was invoked as & "grep.exe" + const unquoted = firstToken.replace(/^["']|["']$/g, '') + // Strip path: C:\bin\grep.exe → grep.exe, .\rg.exe → rg.exe + const basename = unquoted.split(/[\\/]/).pop() || unquoted + // Strip .exe suffix (Windows is case-insensitive) + return basename.toLowerCase().replace(/\.exe$/, '') +} + +/** + * Extract the primary command from a PowerShell command line. + * Takes the LAST pipeline segment since that determines the exit code. + * + * Heuristic split on `;` and `|` — may get it wrong for quoted strings or + * complex constructs. Do NOT depend on this for security; it's only used + * for exit-code interpretation (false negatives just fall back to default). + */ +function heuristicallyExtractBaseCommand(command: string): string { + const segments = command.split(/[;|]/).filter(s => s.trim()) + const last = segments[segments.length - 1] || command + return extractBaseCommand(last) +} + +/** + * Interpret command result based on semantic rules + */ +export function interpretCommandResult( + command: string, + exitCode: number, + stdout: string, + stderr: string, +): { + isError: boolean + message?: string +} { + const baseCommand = heuristicallyExtractBaseCommand(command) + const semantic = COMMAND_SEMANTICS.get(baseCommand) ?? DEFAULT_SEMANTIC + return semantic(exitCode, stdout, stderr) +} diff --git a/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/destructiveCommandWarning.ts b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/destructiveCommandWarning.ts new file mode 100644 index 0000000..14f436d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/destructiveCommandWarning.ts @@ -0,0 +1,109 @@ +/** + * Detects potentially destructive PowerShell commands and returns a warning + * string for display in the permission dialog. This is purely informational + * -- it doesn't affect permission logic or auto-approval. + */ + +type DestructivePattern = { + pattern: RegExp + warning: string +} + +const DESTRUCTIVE_PATTERNS: DestructivePattern[] = [ + // Remove-Item with -Recurse and/or -Force (and common aliases) + // Anchored to statement start (^, |, ;, &, newline, {, () so `git rm --force` + // doesn't match — \b would match `rm` after any word boundary. The `{(` + // chars catch scriptblock/group bodies: `{ rm -Force ./x }`. The stopper + // adds only `}` (NOT `)`) — `}` ends a block so flags after it belong to a + // different statement (`if {rm} else {... -Force}`), but `)` closes a path + // grouping and flags after it are still this command's flags: + // `Remove-Item (Join-Path $r "tmp") -Recurse -Force` must still warn. + { + pattern: + /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Recurse\b[^|;&\n}]*-Force\b/i, + warning: 'Note: may recursively force-remove files', + }, + { + pattern: + /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Force\b[^|;&\n}]*-Recurse\b/i, + warning: 'Note: may recursively force-remove files', + }, + { + pattern: + /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Recurse\b/i, + warning: 'Note: may recursively remove files', + }, + { + pattern: + /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Force\b/i, + warning: 'Note: may force-remove files', + }, + + // Clear-Content on broad paths + { + pattern: /\bClear-Content\b[^|;&\n]*\*/i, + warning: 'Note: may clear content of multiple files', + }, + + // Format-Volume and Clear-Disk + { + pattern: /\bFormat-Volume\b/i, + warning: 'Note: may format a disk volume', + }, + { + pattern: /\bClear-Disk\b/i, + warning: 'Note: may clear a disk', + }, + + // Git destructive operations (same as BashTool) + { + pattern: /\bgit\s+reset\s+--hard\b/i, + warning: 'Note: may discard uncommitted changes', + }, + { + pattern: /\bgit\s+push\b[^|;&\n]*\s+(--force|--force-with-lease|-f)\b/i, + warning: 'Note: may overwrite remote history', + }, + { + pattern: + /\bgit\s+clean\b(?![^|;&\n]*(?:-[a-zA-Z]*n|--dry-run))[^|;&\n]*-[a-zA-Z]*f/i, + warning: 'Note: may permanently delete untracked files', + }, + { + pattern: /\bgit\s+stash\s+(drop|clear)\b/i, + warning: 'Note: may permanently remove stashed changes', + }, + + // Database operations + { + pattern: /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA)\b/i, + warning: 'Note: may drop or truncate database objects', + }, + + // System operations + { + pattern: /\bStop-Computer\b/i, + warning: 'Note: will shut down the computer', + }, + { + pattern: /\bRestart-Computer\b/i, + warning: 'Note: will restart the computer', + }, + { + pattern: /\bClear-RecycleBin\b/i, + warning: 'Note: permanently deletes recycled files', + }, +] + +/** + * Checks if a PowerShell command matches known destructive patterns. + * Returns a human-readable warning string, or null if no destructive pattern is detected. + */ +export function getDestructiveCommandWarning(command: string): string | null { + for (const { pattern, warning } of DESTRUCTIVE_PATTERNS) { + if (pattern.test(command)) { + return warning + } + } + return null +} diff --git a/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/powershellSecurity.ts b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/powershellSecurity.ts new file mode 100644 index 0000000..8439f86 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/PowerShellTool/powershellSecurity.ts @@ -0,0 +1,1090 @@ +/** + * PowerShell-specific security analysis for command validation. + * + * Detects dangerous patterns: code injection, download cradles, privilege + * escalation, dynamic command names, COM objects, etc. + * + * All checks are AST-based. If parsing failed (valid=false), none of the + * individual checks match and powershellCommandIsSafe returns 'ask'. + */ + +import { + DANGEROUS_SCRIPT_BLOCK_CMDLETS, + FILEPATH_EXECUTION_CMDLETS, + MODULE_LOADING_CMDLETS, +} from '../../utils/powershell/dangerousCmdlets.js' +import type { + ParsedCommandElement, + ParsedPowerShellCommand, +} from '../../utils/powershell/parser.js' +import { + COMMON_ALIASES, + commandHasArgAbbreviation, + deriveSecurityFlags, + getAllCommands, + getVariablesByScope, + hasCommandNamed, +} from '../../utils/powershell/parser.js' +import { isClmAllowedType } from './clmTypes.js' + +type PowerShellSecurityResult = { + behavior: 'passthrough' | 'ask' | 'allow' + message?: string +} + +const POWERSHELL_EXECUTABLES = new Set([ + 'pwsh', + 'pwsh.exe', + 'powershell', + 'powershell.exe', +]) + +/** + * Extracts the base executable name from a command, handling full paths + * like /usr/bin/pwsh, C:\Windows\...\powershell.exe, or .\pwsh. + */ +function isPowerShellExecutable(name: string): boolean { + const lower = name.toLowerCase() + if (POWERSHELL_EXECUTABLES.has(lower)) { + return true + } + // Extract basename from paths (both / and \ separators) + const lastSep = Math.max(lower.lastIndexOf('/'), lower.lastIndexOf('\\')) + if (lastSep >= 0) { + return POWERSHELL_EXECUTABLES.has(lower.slice(lastSep + 1)) + } + return false +} + +/** + * Alternative parameter-prefix characters that PowerShell accepts as equivalent + * to ASCII hyphen-minus (U+002D). PowerShell's tokenizer (SpecialCharacters.IsDash) + * and powershell.exe's CommandLineParameterParser both accept all four dash + * characters plus Windows PowerShell 5.1's `/` parameter delimiter. + * Extent.Text preserves the raw character; transformCommandAst uses ce.text for + * CommandParameterAst elements, so these reach us unchanged. + */ +const PS_ALT_PARAM_PREFIXES = new Set([ + '/', // Windows PowerShell 5.1 (powershell.exe, not pwsh 7+) + '\u2013', // en-dash + '\u2014', // em-dash + '\u2015', // horizontal bar +]) + +/** + * Wrapper around commandHasArgAbbreviation that also matches alternative + * parameter prefixes (`/`, en-dash, em-dash, horizontal-bar). PowerShell's + * tokenizer (SpecialCharacters.IsDash) accepts these for both powershell.exe + * args AND cmdlet parameters, so use this for ALL PS param checks — not just + * pwsh.exe invocations. Previously checkComObject/checkStartProcess/ + * checkDangerousFilePathExecution/checkForEachMemberName used bare + * commandHasArgAbbreviation, so `Start-Process foo –Verb RunAs` bypassed. + */ +function psExeHasParamAbbreviation( + cmd: ParsedCommandElement, + fullParam: string, + minPrefix: string, +): boolean { + if (commandHasArgAbbreviation(cmd, fullParam, minPrefix)) { + return true + } + // Normalize alternative prefixes to `-` and re-check. Build a synthetic cmd + // with normalized args; commandHasArgAbbreviation handles colon-value split. + const normalized: ParsedCommandElement = { + ...cmd, + args: cmd.args.map(a => + a.length > 0 && PS_ALT_PARAM_PREFIXES.has(a[0]!) ? '-' + a.slice(1) : a, + ), + } + return commandHasArgAbbreviation(normalized, fullParam, minPrefix) +} + +/** + * Checks if a PowerShell command uses Invoke-Expression or its alias (iex). + * These are equivalent to eval and can execute arbitrary code. + */ +function checkInvokeExpression( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (hasCommandNamed(parsed, 'Invoke-Expression')) { + return { + behavior: 'ask', + message: + 'Command uses Invoke-Expression which can execute arbitrary code', + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for dynamic command invocation where the command name itself is an + * expression that cannot be statically resolved. + * + * PoCs: + * & ${function:Invoke-Expression} 'payload' — VariableExpressionAst + * & ('iex','x')[0] 'payload' — IndexExpressionAst → 'Other' + * & ('i'+'ex') 'payload' — BinaryExpressionAst → 'Other' + * + * In all cases cmd.name is the literal extent text (e.g. "('iex','x')[0]"), + * which doesn't match hasCommandNamed('Invoke-Expression'). At runtime + * PowerShell evaluates the expression to a command name and invokes it. + * + * Legitimate command names are ALWAYS StringConstantExpressionAst (mapped to + * 'StringConstant'): `Get-Process`, `git`, `ls`. Any other element type in + * name position is dynamic. Rather than denylisting dynamic types (fragile — + * mapElementType's default case maps unknown AST types to 'Other', which a + * `=== 'Variable'` check misses), we allowlist 'StringConstant'. + * + * elementTypes[0] is the command-name element (transformCommandAst pushes it + * first, before arg elements). The `!== undefined` guard preserves fail-open + * when elementTypes is absent (parse-detail unavailable — if parsing failed + * entirely, valid=false already returns 'ask' earlier in the chain). + */ +function checkDynamicCommandName( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + if (cmd.elementType !== 'CommandAst') { + continue + } + const nameElementType = cmd.elementTypes?.[0] + if (nameElementType !== undefined && nameElementType !== 'StringConstant') { + return { + behavior: 'ask', + message: + 'Command name is a dynamic expression which cannot be statically validated', + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for encoded command parameters which obscure intent. + * These are commonly used in malware to bypass security tools. + */ +function checkEncodedCommand( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + if (isPowerShellExecutable(cmd.name)) { + if (psExeHasParamAbbreviation(cmd, '-encodedcommand', '-e')) { + return { + behavior: 'ask', + message: 'Command uses encoded parameters which obscure intent', + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for PowerShell re-invocation (nested pwsh/powershell process). + * + * Any PowerShell executable in command position is flagged — not just + * -Command/-File. Bare `pwsh` receiving stdin (`Get-Content x | pwsh`) or + * a positional script path executes arbitrary code with none of the explicit + * flags present. Same unvalidatable-nested-process reasoning as + * checkStartProcess vector 2: we cannot statically analyze what the child + * process will run. + */ +function checkPwshCommandOrFile( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + if (isPowerShellExecutable(cmd.name)) { + return { + behavior: 'ask', + message: + 'Command spawns a nested PowerShell process which cannot be validated', + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for download cradle patterns - common malware techniques + * that download and execute remote code. + * + * Per-statement: catches piped cradles (`IWR ... | IEX`). + * Cross-statement: catches split cradles (`$r = IWR ...; IEX $r.Content`). + * The cross-statement case is already blocked by checkInvokeExpression (which + * scans all statements), but this check improves the warning message. + */ +const DOWNLOADER_NAMES = new Set([ + 'invoke-webrequest', + 'iwr', + 'invoke-restmethod', + 'irm', + 'new-object', + 'start-bitstransfer', // MITRE T1197 +]) + +function isDownloader(name: string): boolean { + return DOWNLOADER_NAMES.has(name.toLowerCase()) +} + +function isIex(name: string): boolean { + const lower = name.toLowerCase() + return lower === 'invoke-expression' || lower === 'iex' +} + +function checkDownloadCradles( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + // Per-statement: piped cradle (IWR ... | IEX) + for (const statement of parsed.statements) { + const cmds = statement.commands + if (cmds.length < 2) { + continue + } + const hasDownloader = cmds.some(cmd => isDownloader(cmd.name)) + const hasIex = cmds.some(cmd => isIex(cmd.name)) + if (hasDownloader && hasIex) { + return { + behavior: 'ask', + message: 'Command downloads and executes remote code', + } + } + } + + // Cross-statement: split cradle ($r = IWR ...; IEX $r.Content). + // No new false positives: if IEX is present, checkInvokeExpression already asks. + const all = getAllCommands(parsed) + if (all.some(c => isDownloader(c.name)) && all.some(c => isIex(c.name))) { + return { + behavior: 'ask', + message: 'Command downloads and executes remote code', + } + } + + return { behavior: 'passthrough' } +} + +/** + * Checks for standalone download utilities — LOLBAS tools commonly used to + * fetch payloads. Unlike checkDownloadCradles (which requires download + IEX + * in-pipeline), this flags the download operation itself. + * + * Start-BitsTransfer: always a file transfer (MITRE T1197). + * certutil -urlcache: classic LOLBAS download. Only flagged with -urlcache; + * bare `certutil` has many legitimate cert-management uses. + * bitsadmin /transfer: legacy BITS download (pre-PowerShell). + */ +function checkDownloadUtilities( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + // Start-BitsTransfer is purpose-built for file transfer — no safe variant. + if (lower === 'start-bitstransfer') { + return { + behavior: 'ask', + message: 'Command downloads files via BITS transfer', + } + } + // certutil / certutil.exe — only when -urlcache is present. certutil has + // many non-download uses (cert store queries, encoding, etc.). + // certutil.exe accepts both -urlcache and /urlcache per standard Windows + // utility convention — check both forms (bitsadmin below does the same). + if (lower === 'certutil' || lower === 'certutil.exe') { + const hasUrlcache = cmd.args.some(a => { + const la = a.toLowerCase() + return la === '-urlcache' || la === '/urlcache' + }) + if (hasUrlcache) { + return { + behavior: 'ask', + message: 'Command uses certutil to download from a URL', + } + } + } + // bitsadmin /transfer — legacy BITS CLI, same threat as Start-BitsTransfer. + if (lower === 'bitsadmin' || lower === 'bitsadmin.exe') { + if (cmd.args.some(a => a.toLowerCase() === '/transfer')) { + return { + behavior: 'ask', + message: 'Command downloads files via BITS transfer', + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for Add-Type usage which compiles and loads .NET code at runtime. + * This can be used to execute arbitrary compiled code. + */ +function checkAddType( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (hasCommandNamed(parsed, 'Add-Type')) { + return { + behavior: 'ask', + message: 'Command compiles and loads .NET code', + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for New-Object -ComObject. COM objects like WScript.Shell, + * Shell.Application, MMC20.Application, Schedule.Service, Msxml2.XMLHTTP + * have their own execution/download capabilities — no IEX required. + * + * We can't enumerate all dangerous ProgIDs, so flag any -ComObject. Object + * creation alone is inert, but the prompt should warn the user that COM + * instantiation is an execution primitive. Method invocation on the result + * (.Run(), .Exec()) is separately caught by checkMemberInvocations. + */ +function checkComObject( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + if (cmd.name.toLowerCase() !== 'new-object') { + continue + } + // -ComObject min abbrev is -com (New-Object params: -TypeName, -ComObject, + // -ArgumentList, -Property, -Strict; -co is ambiguous in PS5.1 due to + // common params like -Confirm, so use -com). + if (psExeHasParamAbbreviation(cmd, '-comobject', '-com')) { + return { + behavior: 'ask', + message: + 'Command instantiates a COM object which may have execution capabilities', + } + } + // SECURITY: checkTypeLiterals only sees [bracket] syntax from + // parsed.typeLiterals. `New-Object System.Net.WebClient` passes the type + // as a STRING ARG (StringConstantExpressionAst), not a TypeExpressionAst, + // so CLM never fires. Extract -TypeName (named, colon-bound, or + // positional-0) and run through isClmAllowedType. Closes attackVectors D4. + let typeName: string | undefined + for (let i = 0; i < cmd.args.length; i++) { + const a = cmd.args[i]! + const lower = a.toLowerCase() + // -TypeName abbrev: -t is unambiguous (no other New-Object -t* params). + // Handle colon-bound form first: -TypeName:Foo.Bar + if (lower.startsWith('-t') && lower.includes(':')) { + const colonIdx = a.indexOf(':') + const paramPart = lower.slice(0, colonIdx) + if ('-typename'.startsWith(paramPart)) { + typeName = a.slice(colonIdx + 1) + break + } + } + // Space-separated form: -TypeName Foo.Bar + if ( + lower.startsWith('-t') && + '-typename'.startsWith(lower) && + cmd.args[i + 1] !== undefined + ) { + typeName = cmd.args[i + 1] + break + } + } + // Positional-0 binds to -TypeName (NetParameterSet default). Named params + // (-Strict, -ArgumentList, -Property, -ComObject) may appear before the + // positional TypeName, so scan past them to find the first non-consumed arg. + if (typeName === undefined) { + // New-Object named params that consume a following value argument + const VALUE_PARAMS = new Set(['-argumentlist', '-comobject', '-property']) + // Switch params (no value argument) + const SWITCH_PARAMS = new Set(['-strict']) + for (let i = 0; i < cmd.args.length; i++) { + const a = cmd.args[i]! + if (a.startsWith('-')) { + const lower = a.toLowerCase() + // Skip -TypeName variants (already handled by named-param loop above) + if (lower.startsWith('-t') && '-typename'.startsWith(lower)) { + i++ // skip value + continue + } + // Colon-bound form: -Param:Value (single token, no skip needed) + if (lower.includes(':')) continue + if (SWITCH_PARAMS.has(lower)) continue + if (VALUE_PARAMS.has(lower)) { + i++ // skip value + continue + } + // Unknown param — skip conservatively + continue + } + // First non-dash arg is the positional TypeName + typeName = a + break + } + } + if (typeName !== undefined && !isClmAllowedType(typeName)) { + return { + behavior: 'ask', + message: `New-Object instantiates .NET type '${typeName}' outside the ConstrainedLanguage allowlist`, + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for DANGEROUS_SCRIPT_BLOCK_CMDLETS invoked with -FilePath (or + * -LiteralPath). These run a script file — arbitrary code execution with no + * ScriptBlockAst in the tree. + * + * checkScriptBlockInjection only fires when hasScriptBlocks is true. With + * -FilePath there is no ScriptBlockAst, so DANGEROUS_SCRIPT_BLOCK_CMDLETS is + * never consulted. This check closes that gap for the -FilePath vector. + * + * Cmdlets in DANGEROUS_SCRIPT_BLOCK_CMDLETS that accept -FilePath: + * Invoke-Command -FilePath (icm alias via COMMON_ALIASES) + * Start-Job -FilePath, -LiteralPath + * Start-ThreadJob -FilePath + * Register-ScheduledJob -FilePath + * The *-PSSession and Register-*Event entries do not accept -FilePath. + * + * -f is unambiguous for -FilePath on all four (no other -f* params). + * -l is unambiguous for -LiteralPath on Start-Job; harmless no-op on the + * others (no -l* params to collide with). + */ + +function checkDangerousFilePathExecution( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + const resolved = COMMON_ALIASES[lower]?.toLowerCase() ?? lower + if (!FILEPATH_EXECUTION_CMDLETS.has(resolved)) { + continue + } + if ( + psExeHasParamAbbreviation(cmd, '-filepath', '-f') || + psExeHasParamAbbreviation(cmd, '-literalpath', '-l') + ) { + return { + behavior: 'ask', + message: `${cmd.name} -FilePath executes an arbitrary script file`, + } + } + // Positional binding: `Start-Job script.ps1` binds position-0 to + // -FilePath via FilePathParameterSet resolution (ScriptBlock args select + // ScriptBlockParameterSet instead). Same pattern as checkForEachMemberName: + // any non-dash StringConstant is a potential -FilePath. Over-flagging + // (e.g., `Start-Job -Name foo` where `foo` is StringConstant) is fail-safe. + for (let i = 0; i < cmd.args.length; i++) { + const argType = cmd.elementTypes?.[i + 1] + const arg = cmd.args[i] + if (argType === 'StringConstant' && arg && !arg.startsWith('-')) { + return { + behavior: 'ask', + message: `${cmd.name} with positional string argument binds to -FilePath and executes a script file`, + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for ForEach-Object -MemberName. Invokes a method by string name on + * every piped object — semantically equivalent to `| % { $_.Method() }` but + * without any ScriptBlockAst or InvokeMemberExpressionAst in the tree. + * + * PoC: `Get-Process | ForEach-Object -MemberName Kill` → kills all processes. + * checkScriptBlockInjection misses it (no script block); checkMemberInvocations + * misses it (no .Method() syntax). Aliases `%` and `foreach` resolve via + * COMMON_ALIASES. + */ +function checkForEachMemberName( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + const resolved = COMMON_ALIASES[lower]?.toLowerCase() ?? lower + if (resolved !== 'foreach-object') { + continue + } + // ForEach-Object params starting with -m: only -MemberName. -m is unambiguous. + if (psExeHasParamAbbreviation(cmd, '-membername', '-m')) { + return { + behavior: 'ask', + message: + 'ForEach-Object -MemberName invokes methods by string name which cannot be validated', + } + } + // PS7+: `ForEach-Object Kill` binds a positional string arg to + // -MemberName via MemberSet parameter-set resolution (ScriptBlock args + // select ScriptBlockSet instead). Scan ALL args — `-Verbose Kill` or + // `-ErrorAction Stop Kill` still binds Kill positionally. Any non-dash + // StringConstant is a potential -MemberName; over-flagging is fail-safe. + for (let i = 0; i < cmd.args.length; i++) { + const argType = cmd.elementTypes?.[i + 1] + const arg = cmd.args[i] + if (argType === 'StringConstant' && arg && !arg.startsWith('-')) { + return { + behavior: 'ask', + message: + 'ForEach-Object with positional string argument binds to -MemberName and invokes methods by name', + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Checks for dangerous Start-Process patterns. + * + * Two vectors: + * 1. `-Verb RunAs` — privilege escalation (UAC prompt). + * 2. Launching a PowerShell executable — nested invocation. + * `Start-Process pwsh -ArgumentList "-e "` evades + * checkEncodedCommand/checkPwshCommandOrFile because cmd.name is + * `Start-Process`, not `pwsh`. The `-e` lives inside the -ArgumentList + * string value and is never parsed as a param on the outer command. + * Rather than parse -ArgumentList contents (fragile — it's an opaque + * string or array), flag any Start-Process whose target is a PS + * executable: the nested invocation is unvalidatable by construction. + */ +function checkStartProcess( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (lower !== 'start-process' && lower !== 'saps' && lower !== 'start') { + continue + } + // Vector 1: -Verb RunAs (space or colon syntax). + // Space syntax: psExeHasParamAbbreviation finds -Verb/-v, then scan args + // for a bare 'runas' token. + if ( + psExeHasParamAbbreviation(cmd, '-Verb', '-v') && + cmd.args.some(a => a.toLowerCase() === 'runas') + ) { + return { + behavior: 'ask', + message: 'Command requests elevated privileges', + } + } + // Colon syntax — two layers: + // (a) Structural: PR #23554 added children[] for colon-bound param args. + // children[i] = [{type, text}] for the bound value. Check if any + // -v*-prefixed param has a child whose text normalizes (strip + // quotes/backtick/whitespace) to 'runas'. Robust against arbitrary + // quoting the regex can't anticipate. + // (b) Regex fallback: for parsed output without children[] or as + // defense-in-depth. -Verb:'RunAs', -Verb:"RunAs", -Verb:`runas all + // bypassed the old /...:runas$/ pattern because the quote/tick broke + // the match. + if (cmd.children) { + for (let i = 0; i < cmd.args.length; i++) { + // Strip backticks before matching param name (bug #14): -V`erb:RunAs + const argClean = cmd.args[i]!.replace(/`/g, '') + if (!/^[-\u2013\u2014\u2015/]v[a-z]*:/i.test(argClean)) continue + const kids = cmd.children[i] + if (!kids) continue + for (const child of kids) { + if (child.text.replace(/['"`\s]/g, '').toLowerCase() === 'runas') { + return { + behavior: 'ask', + message: 'Command requests elevated privileges', + } + } + } + } + } + if ( + cmd.args.some(a => { + // Strip backticks before matching (bug #14 / review nit #2) + const clean = a.replace(/`/g, '') + return /^[-\u2013\u2014\u2015/]v[a-z]*:['"` ]*runas['"` ]*$/i.test( + clean, + ) + }) + ) { + return { + behavior: 'ask', + message: 'Command requests elevated privileges', + } + } + // Vector 2: Start-Process targeting a PowerShell executable. + // Target is either the first positional arg or the value after -FilePath. + // Scan all args — any PS-executable token present is treated as the launch + // target. Known false-positive: path-valued params (-WorkingDirectory, + // -RedirectStandard*) whose basename is pwsh/powershell — + // isPowerShellExecutable extracts basenames from paths, so + // `-WorkingDirectory C:\projects\pwsh` triggers. Accepted trade-off: + // Start-Process is not in CMDLET_ALLOWLIST (always prompts regardless), + // result is ask not reject, and correctly parsing Start-Process parameter + // binding is fragile. Strip quotes the parser may have preserved. + for (const arg of cmd.args) { + const stripped = arg.replace(/^['"]|['"]$/g, '') + if (isPowerShellExecutable(stripped)) { + return { + behavior: 'ask', + message: + 'Start-Process launches a nested PowerShell process which cannot be validated', + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Cmdlets where script blocks are safe (filtering/output cmdlets). + * Script blocks piped to these are just predicates or projections, not arbitrary execution. + */ +const SAFE_SCRIPT_BLOCK_CMDLETS = new Set([ + 'where-object', + 'sort-object', + 'select-object', + 'group-object', + 'format-table', + 'format-list', + 'format-wide', + 'format-custom', + // NOT foreach-object — its block is arbitrary script, not a predicate. + // getAllCommands recurses so commands inside the block ARE checked, but + // non-command AST nodes (AssignmentStatementAst etc.) are invisible to it. + // See powershellPermissions.ts step-5 hasScriptBlocks guard. +]) + +/** + * Checks for script block injection patterns where script blocks + * appear in suspicious contexts that could execute arbitrary code. + * + * Script blocks used with safe filtering/output cmdlets (Where-Object, + * Sort-Object, Select-Object, Group-Object) are allowed. + * Script blocks used with dangerous cmdlets (Invoke-Command, Invoke-Expression, + * Start-Job, etc.) are flagged. + */ +function checkScriptBlockInjection( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + const security = deriveSecurityFlags(parsed) + if (!security.hasScriptBlocks) { + return { behavior: 'passthrough' } + } + + // Check all commands in the parsed result. If any command is in the + // dangerous set, flag it. If all commands with script blocks are in + // the safe set (or the allowlist), allow it. + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (DANGEROUS_SCRIPT_BLOCK_CMDLETS.has(lower)) { + return { + behavior: 'ask', + message: + 'Command contains script block with dangerous cmdlet that may execute arbitrary code', + } + } + } + + // Check if all commands are either safe script block consumers or don't use script blocks + const allCommandsSafe = getAllCommands(parsed).every(cmd => { + const lower = cmd.name.toLowerCase() + // Safe filtering/output cmdlets + if (SAFE_SCRIPT_BLOCK_CMDLETS.has(lower)) { + return true + } + // Resolve aliases + const alias = COMMON_ALIASES[lower] + if (alias && SAFE_SCRIPT_BLOCK_CMDLETS.has(alias.toLowerCase())) { + return true + } + // Unknown command with script blocks present — flag as potentially dangerous + return false + }) + + if (allCommandsSafe) { + return { behavior: 'passthrough' } + } + + return { + behavior: 'ask', + message: 'Command contains script block that may execute arbitrary code', + } +} + +/** + * AST-only check: Detects subexpressions $() which can hide command execution. + */ +function checkSubExpressions( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (deriveSecurityFlags(parsed).hasSubExpressions) { + return { + behavior: 'ask', + message: 'Command contains subexpressions $()', + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: Detects expandable strings (double-quoted) with embedded + * expressions like "$env:PATH" or "$(dangerous-command)". These can hide + * command execution or variable interpolation inside string literals. + */ +function checkExpandableStrings( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (deriveSecurityFlags(parsed).hasExpandableStrings) { + return { + behavior: 'ask', + message: 'Command contains expandable strings with embedded expressions', + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: Detects splatting (@variable) which can obscure arguments. + */ +function checkSplatting( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (deriveSecurityFlags(parsed).hasSplatting) { + return { + behavior: 'ask', + message: 'Command uses splatting (@variable)', + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: Detects stop-parsing token (--%) which prevents further parsing. + */ +function checkStopParsing( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (deriveSecurityFlags(parsed).hasStopParsing) { + return { + behavior: 'ask', + message: 'Command uses stop-parsing token (--%)', + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: Detects .NET method invocations which can access system APIs. + */ +function checkMemberInvocations( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + if (deriveSecurityFlags(parsed).hasMemberInvocations) { + return { + behavior: 'ask', + message: 'Command invokes .NET methods', + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: type literals outside Microsoft's ConstrainedLanguage + * allowlist. CLM blocks all .NET type access except ~90 primitives/attributes + * Microsoft considers safe for untrusted code. We trust that list as the + * "safe" boundary — anything outside it (Reflection.Assembly, IO.Pipes, + * Diagnostics.Process, InteropServices.Marshal, etc.) can access system APIs + * that compromise the permission model. + * + * Runs AFTER checkMemberInvocations: that broadly flags any ::Method / .Method() + * call; this check is the more specific "which types" signal. Both fire on + * [Reflection.Assembly]::Load; CLM gives the precise message. Pure type casts + * like [int]$x have no member invocation and only hit this check. + */ +function checkTypeLiterals( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const t of parsed.typeLiterals ?? []) { + if (!isClmAllowedType(t)) { + return { + behavior: 'ask', + message: `Command uses .NET type [${t}] outside the ConstrainedLanguage allowlist`, + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Invoke-Item (alias ii) opens a file with its default handler (ShellExecute + * on Windows, open/xdg-open on Unix). On an .exe/.ps1/.bat/.cmd this is RCE. + * Bug 008: ii is in no blocklist; passthrough prompt doesn't explain the + * exec hazard. Always ask — there is no safe variant (even opening .txt may + * invoke a user-configured handler that accepts arguments). + */ +function checkInvokeItem( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (lower === 'invoke-item' || lower === 'ii') { + return { + behavior: 'ask', + message: + 'Invoke-Item opens files with the default handler (ShellExecute). On executable files this runs arbitrary code.', + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Scheduled-task persistence primitives. Register-ScheduledJob was blocked + * (DANGEROUS_SCRIPT_BLOCK_CMDLETS); the newer Register-ScheduledTask cmdlet + * and legacy schtasks.exe /create were not. Persistence that survives the + * session with no explanatory prompt. + */ +const SCHEDULED_TASK_CMDLETS = new Set([ + 'register-scheduledtask', + 'new-scheduledtask', + 'new-scheduledtaskaction', + 'set-scheduledtask', +]) + +function checkScheduledTask( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (SCHEDULED_TASK_CMDLETS.has(lower)) { + return { + behavior: 'ask', + message: `${cmd.name} creates or modifies a scheduled task (persistence primitive)`, + } + } + if (lower === 'schtasks' || lower === 'schtasks.exe') { + if ( + cmd.args.some(a => { + const la = a.toLowerCase() + return ( + la === '/create' || + la === '/change' || + la === '-create' || + la === '-change' + ) + }) + ) { + return { + behavior: 'ask', + message: + 'schtasks with create/change modifies scheduled tasks (persistence primitive)', + } + } + } + } + return { behavior: 'passthrough' } +} + +/** + * AST-only check: Detects environment variable manipulation via Set-Item/New-Item on env: scope. + */ +const ENV_WRITE_CMDLETS = new Set([ + 'set-item', + 'si', + 'new-item', + 'ni', + 'remove-item', + 'ri', + 'del', + 'rm', + 'rd', + 'rmdir', + 'erase', + 'clear-item', + 'cli', + 'set-content', + // 'sc' omitted — collides with sc.exe on PS Core 7+, see COMMON_ALIASES note + 'add-content', + 'ac', +]) + +function checkEnvVarManipulation( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + const envVars = getVariablesByScope(parsed, 'env') + if (envVars.length === 0) { + return { behavior: 'passthrough' } + } + // Check if any command is a write cmdlet + for (const cmd of getAllCommands(parsed)) { + if (ENV_WRITE_CMDLETS.has(cmd.name.toLowerCase())) { + return { + behavior: 'ask', + message: 'Command modifies environment variables', + } + } + } + // Also flag if there are assignments involving env vars + if (deriveSecurityFlags(parsed).hasAssignments && envVars.length > 0) { + return { + behavior: 'ask', + message: 'Command modifies environment variables', + } + } + return { behavior: 'passthrough' } +} + +/** + * Module-loading cmdlets execute a .psm1's top-level script body (Import-Module) + * or download from arbitrary repositories (Install-Module, Save-Module). A + * wildcard allow rule like `Import-Module:*` would let an attacker-supplied + * .psm1 execute with the user's privileges — same risk as Invoke-Expression. + * + * NEVER_SUGGEST (dangerousCmdlets.ts) derives from this list so the UI + * never offers these as wildcard suggestions, but users can still manually + * write allow rules. This check ensures the permission engine independently + * gates these cmdlets. + */ + +function checkModuleLoading( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (MODULE_LOADING_CMDLETS.has(lower)) { + return { + behavior: 'ask', + message: + 'Command loads, installs, or downloads a PowerShell module or script, which can execute arbitrary code', + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Set-Alias/New-Alias can hijack future command resolution: after + * `Set-Alias Get-Content Invoke-Expression`, any later `Get-Content $x` + * executes arbitrary code. Set-Variable/New-Variable can poison + * `$PSDefaultParameterValues` (e.g., `Set-Variable PSDefaultParameterValues + * @{'*:Path'='/etc/passwd'}`) which alters every subsequent cmdlet's behavior. + * Neither effect can be validated statically — we'd need to track all future + * command resolutions in the session. Always ask. + */ +const RUNTIME_STATE_CMDLETS = new Set([ + 'set-alias', + 'sal', + 'new-alias', + 'nal', + 'set-variable', + 'sv', + 'new-variable', + 'nv', +]) + +function checkRuntimeStateManipulation( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + // Strip module qualifier: `Microsoft.PowerShell.Utility\Set-Alias` → `set-alias` + const raw = cmd.name.toLowerCase() + const lower = raw.includes('\\') + ? raw.slice(raw.lastIndexOf('\\') + 1) + : raw + if (RUNTIME_STATE_CMDLETS.has(lower)) { + return { + behavior: 'ask', + message: + 'Command creates or modifies an alias or variable that can affect future command resolution', + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Invoke-WmiMethod / Invoke-CimMethod are Start-Process equivalents via WMI. + * `Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "cmd /c ..."` + * spawns an arbitrary process, bypassing checkStartProcess entirely. No narrow + * safe usage exists — -Class and -MethodName accept arbitrary strings, so + * gating on Win32_Process specifically would miss -Class $x or other process- + * spawning WMI classes. Returns ask on any invocation. (security finding #34) + */ +const WMI_SPAWN_CMDLETS = new Set([ + 'invoke-wmimethod', + 'iwmi', + 'invoke-cimmethod', +]) + +function checkWmiProcessSpawn( + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + for (const cmd of getAllCommands(parsed)) { + const lower = cmd.name.toLowerCase() + if (WMI_SPAWN_CMDLETS.has(lower)) { + return { + behavior: 'ask', + message: `${cmd.name} can spawn arbitrary processes via WMI/CIM (Win32_Process Create)`, + } + } + } + return { behavior: 'passthrough' } +} + +/** + * Main entry point for PowerShell security validation. + * Checks a PowerShell command against known dangerous patterns. + * + * All checks are AST-based. If the AST parse failed (parsed.valid === false), + * none of the individual checks will match and we return 'ask' as a safe default. + * + * @param command - The PowerShell command to validate (unused, kept for API compat) + * @param parsed - Parsed AST from PowerShell's native parser (required) + * @returns Security result indicating whether the command is safe + */ +export function powershellCommandIsSafe( + _command: string, + parsed: ParsedPowerShellCommand, +): PowerShellSecurityResult { + // If the AST parse failed, we cannot determine safety -- ask the user + if (!parsed.valid) { + return { + behavior: 'ask', + message: 'Could not parse command for security analysis', + } + } + + const validators = [ + checkInvokeExpression, + checkDynamicCommandName, + checkEncodedCommand, + checkPwshCommandOrFile, + checkDownloadCradles, + checkDownloadUtilities, + checkAddType, + checkComObject, + checkDangerousFilePathExecution, + checkInvokeItem, + checkScheduledTask, + checkForEachMemberName, + checkStartProcess, + checkScriptBlockInjection, + checkSubExpressions, + checkExpandableStrings, + checkSplatting, + checkStopParsing, + checkMemberInvocations, + checkTypeLiterals, + checkEnvVarManipulation, + checkModuleLoading, + checkRuntimeStateManipulation, + checkWmiProcessSpawn, + ] + + for (const validator of validators) { + const result = validator(parsed) + if (result.behavior === 'ask') { + return result + } + } + + // All checks passed + return { behavior: 'passthrough' } +} diff --git a/_all-in-one-upload/cc-haha/src/tools/SubscribePRTool/SubscribePRTool.ts b/_all-in-one-upload/cc-haha/src/tools/SubscribePRTool/SubscribePRTool.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/SubscribePRTool/SubscribePRTool.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/tools/TaskUpdateTool/constants.ts b/_all-in-one-upload/cc-haha/src/tools/TaskUpdateTool/constants.ts new file mode 100644 index 0000000..62b4709 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/TaskUpdateTool/constants.ts @@ -0,0 +1 @@ +export const TASK_UPDATE_TOOL_NAME = 'TaskUpdate' diff --git a/_all-in-one-upload/cc-haha/src/tools/ToolSearchTool/ToolSearchTool.ts b/_all-in-one-upload/cc-haha/src/tools/ToolSearchTool/ToolSearchTool.ts new file mode 100644 index 0000000..ee43b66 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/tools/ToolSearchTool/ToolSearchTool.ts @@ -0,0 +1,471 @@ +import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs' +import memoize from 'lodash-es/memoize.js' +import { z } from 'zod/v4' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../../services/analytics/index.js' +import { + buildTool, + findToolByName, + type Tool, + type ToolDef, + type Tools, +} from '../../Tool.js' +import { logForDebugging } from '../../utils/debug.js' +import { lazySchema } from '../../utils/lazySchema.js' +import { escapeRegExp } from '../../utils/stringUtils.js' +import { isToolSearchEnabledOptimistic } from '../../utils/toolSearch.js' +import { getPrompt, isDeferredTool, TOOL_SEARCH_TOOL_NAME } from './prompt.js' + +export const inputSchema = lazySchema(() => + z.object({ + query: z + .string() + .describe( + 'Query to find deferred tools. Use "select:" for direct selection, or keywords to search.', + ), + max_results: z + .number() + .optional() + .default(5) + .describe('Maximum number of results to return (default: 5)'), + }), +) +type InputSchema = ReturnType + +export const outputSchema = lazySchema(() => + z.object({ + matches: z.array(z.string()), + query: z.string(), + total_deferred_tools: z.number(), + pending_mcp_servers: z.array(z.string()).optional(), + }), +) +type OutputSchema = ReturnType + +export type Output = z.infer + +// Track deferred tool names to detect when cache should be cleared +let cachedDeferredToolNames: string | null = null + +/** + * Get a cache key representing the current set of deferred tools. + */ +function getDeferredToolsCacheKey(deferredTools: Tools): string { + return deferredTools + .map(t => t.name) + .sort() + .join(',') +} + +/** + * Get tool description, memoized by tool name. + * Used for keyword search scoring. + */ +const getToolDescriptionMemoized = memoize( + async (toolName: string, tools: Tools): Promise => { + const tool = findToolByName(tools, toolName) + if (!tool) { + return '' + } + return tool.prompt({ + getToolPermissionContext: async () => ({ + mode: 'default' as const, + additionalWorkingDirectories: new Map(), + alwaysAllowRules: {}, + alwaysDenyRules: {}, + alwaysAskRules: {}, + isBypassPermissionsModeAvailable: false, + }), + tools, + agents: [], + }) + }, + (toolName: string) => toolName, +) + +/** + * Invalidate the description cache if deferred tools have changed. + */ +function maybeInvalidateCache(deferredTools: Tools): void { + const currentKey = getDeferredToolsCacheKey(deferredTools) + if (cachedDeferredToolNames !== currentKey) { + logForDebugging( + `ToolSearchTool: cache invalidated - deferred tools changed`, + ) + getToolDescriptionMemoized.cache.clear?.() + cachedDeferredToolNames = currentKey + } +} + +export function clearToolSearchDescriptionCache(): void { + getToolDescriptionMemoized.cache.clear?.() + cachedDeferredToolNames = null +} + +/** + * Build the search result output structure. + */ +function buildSearchResult( + matches: string[], + query: string, + totalDeferredTools: number, + pendingMcpServers?: string[], +): { data: Output } { + return { + data: { + matches, + query, + total_deferred_tools: totalDeferredTools, + ...(pendingMcpServers && pendingMcpServers.length > 0 + ? { pending_mcp_servers: pendingMcpServers } + : {}), + }, + } +} + +/** + * Parse tool name into searchable parts. + * Handles both MCP tools (mcp__server__action) and regular tools (CamelCase). + */ +function parseToolName(name: string): { + parts: string[] + full: string + isMcp: boolean +} { + // Check if it's an MCP tool + if (name.startsWith('mcp__')) { + const withoutPrefix = name.replace(/^mcp__/, '').toLowerCase() + const parts = withoutPrefix.split('__').flatMap(p => p.split('_')) + return { + parts: parts.filter(Boolean), + full: withoutPrefix.replace(/__/g, ' ').replace(/_/g, ' '), + isMcp: true, + } + } + + // Regular tool - split by CamelCase and underscores + const parts = name + .replace(/([a-z])([A-Z])/g, '$1 $2') // CamelCase to spaces + .replace(/_/g, ' ') + .toLowerCase() + .split(/\s+/) + .filter(Boolean) + + return { + parts, + full: parts.join(' '), + isMcp: false, + } +} + +/** + * Pre-compile word-boundary regexes for all search terms. + * Called once per search instead of tools×terms×2 times. + */ +function compileTermPatterns(terms: string[]): Map { + const patterns = new Map() + for (const term of terms) { + if (!patterns.has(term)) { + patterns.set(term, new RegExp(`\\b${escapeRegExp(term)}\\b`)) + } + } + return patterns +} + +/** + * Keyword-based search over tool names and descriptions. + * Handles both MCP tools (mcp__server__action) and regular tools (CamelCase). + * + * The model typically queries with: + * - Server names when it knows the integration (e.g., "slack", "github") + * - Action words when looking for functionality (e.g., "read", "list", "create") + * - Tool-specific terms (e.g., "notebook", "shell", "kill") + */ +async function searchToolsWithKeywords( + query: string, + deferredTools: Tools, + tools: Tools, + maxResults: number, +): Promise { + const queryLower = query.toLowerCase().trim() + + // Fast path: if query matches a tool name exactly, return it directly. + // Handles models using a bare tool name instead of select: prefix (seen + // from subagents/post-compaction). Checks deferred first, then falls back + // to the full tool set — selecting an already-loaded tool is a harmless + // no-op that lets the model proceed without retry churn. + const exactMatch = + deferredTools.find(t => t.name.toLowerCase() === queryLower) ?? + tools.find(t => t.name.toLowerCase() === queryLower) + if (exactMatch) { + return [exactMatch.name] + } + + // If query looks like an MCP tool prefix (mcp__server), find matching tools. + // Handles models searching by server name with mcp__ prefix. + if (queryLower.startsWith('mcp__') && queryLower.length > 5) { + const prefixMatches = deferredTools + .filter(t => t.name.toLowerCase().startsWith(queryLower)) + .slice(0, maxResults) + .map(t => t.name) + if (prefixMatches.length > 0) { + return prefixMatches + } + } + + const queryTerms = queryLower.split(/\s+/).filter(term => term.length > 0) + + // Partition into required (+prefixed) and optional terms + const requiredTerms: string[] = [] + const optionalTerms: string[] = [] + for (const term of queryTerms) { + if (term.startsWith('+') && term.length > 1) { + requiredTerms.push(term.slice(1)) + } else { + optionalTerms.push(term) + } + } + + const allScoringTerms = + requiredTerms.length > 0 ? [...requiredTerms, ...optionalTerms] : queryTerms + const termPatterns = compileTermPatterns(allScoringTerms) + + // Pre-filter to tools matching ALL required terms in name or description + let candidateTools = deferredTools + if (requiredTerms.length > 0) { + const matches = await Promise.all( + deferredTools.map(async tool => { + const parsed = parseToolName(tool.name) + const description = await getToolDescriptionMemoized(tool.name, tools) + const descNormalized = description.toLowerCase() + const hintNormalized = tool.searchHint?.toLowerCase() ?? '' + const matchesAll = requiredTerms.every(term => { + const pattern = termPatterns.get(term)! + return ( + parsed.parts.includes(term) || + parsed.parts.some(part => part.includes(term)) || + pattern.test(descNormalized) || + (hintNormalized && pattern.test(hintNormalized)) + ) + }) + return matchesAll ? tool : null + }), + ) + candidateTools = matches.filter((t): t is Tool => t !== null) + } + + const scored = await Promise.all( + candidateTools.map(async tool => { + const parsed = parseToolName(tool.name) + const description = await getToolDescriptionMemoized(tool.name, tools) + const descNormalized = description.toLowerCase() + const hintNormalized = tool.searchHint?.toLowerCase() ?? '' + + let score = 0 + for (const term of allScoringTerms) { + const pattern = termPatterns.get(term)! + + // Exact part match (high weight for MCP server names, tool name parts) + if (parsed.parts.includes(term)) { + score += parsed.isMcp ? 12 : 10 + } else if (parsed.parts.some(part => part.includes(term))) { + score += parsed.isMcp ? 6 : 5 + } + + // Full name fallback (for edge cases) + if (parsed.full.includes(term) && score === 0) { + score += 3 + } + + // searchHint match — curated capability phrase, higher signal than prompt + if (hintNormalized && pattern.test(hintNormalized)) { + score += 4 + } + + // Description match - use word boundary to avoid false positives + if (pattern.test(descNormalized)) { + score += 2 + } + } + + return { name: tool.name, score } + }), + ) + + return scored + .filter(item => item.score > 0) + .sort((a, b) => b.score - a.score) + .slice(0, maxResults) + .map(item => item.name) +} + +export const ToolSearchTool = buildTool({ + isEnabled() { + return isToolSearchEnabledOptimistic() + }, + isConcurrencySafe() { + return true + }, + isReadOnly() { + return true + }, + name: TOOL_SEARCH_TOOL_NAME, + maxResultSizeChars: 100_000, + async description() { + return getPrompt() + }, + async prompt() { + return getPrompt() + }, + get inputSchema(): InputSchema { + return inputSchema() + }, + get outputSchema(): OutputSchema { + return outputSchema() + }, + async call(input, { options: { tools }, getAppState }) { + const { query, max_results = 5 } = input + + const deferredTools = tools.filter(isDeferredTool) + maybeInvalidateCache(deferredTools) + + // Check for MCP servers still connecting + function getPendingServerNames(): string[] | undefined { + const appState = getAppState() + const pending = appState.mcp.clients.filter(c => c.type === 'pending') + return pending.length > 0 ? pending.map(s => s.name) : undefined + } + + // Helper to log search outcome + function logSearchOutcome( + matches: string[], + queryType: 'select' | 'keyword', + ): void { + logEvent('tengu_tool_search_outcome', { + query: + query as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryType: + queryType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + matchCount: matches.length, + totalDeferredTools: deferredTools.length, + maxResults: max_results, + hasMatches: matches.length > 0, + }) + } + + // Check for select: prefix — direct tool selection. + // Supports comma-separated multi-select: `select:A,B,C`. + // If a name isn't in the deferred set but IS in the full tool set, + // we still return it — the tool is already loaded, so "selecting" it + // is a harmless no-op that lets the model proceed without retry churn. + const selectMatch = query.match(/^select:(.+)$/i) + if (selectMatch) { + const requested = selectMatch[1]! + .split(',') + .map(s => s.trim()) + .filter(Boolean) + + const found: string[] = [] + const missing: string[] = [] + for (const toolName of requested) { + const tool = + findToolByName(deferredTools, toolName) ?? + findToolByName(tools, toolName) + if (tool) { + if (!found.includes(tool.name)) found.push(tool.name) + } else { + missing.push(toolName) + } + } + + if (found.length === 0) { + logForDebugging( + `ToolSearchTool: select failed — none found: ${missing.join(', ')}`, + ) + logSearchOutcome([], 'select') + const pendingServers = getPendingServerNames() + return buildSearchResult( + [], + query, + deferredTools.length, + pendingServers, + ) + } + + if (missing.length > 0) { + logForDebugging( + `ToolSearchTool: partial select — found: ${found.join(', ')}, missing: ${missing.join(', ')}`, + ) + } else { + logForDebugging(`ToolSearchTool: selected ${found.join(', ')}`) + } + logSearchOutcome(found, 'select') + return buildSearchResult(found, query, deferredTools.length) + } + + // Keyword search + const matches = await searchToolsWithKeywords( + query, + deferredTools, + tools, + max_results, + ) + + logForDebugging( + `ToolSearchTool: keyword search for "${query}", found ${matches.length} matches`, + ) + + logSearchOutcome(matches, 'keyword') + + // Include pending server info when search finds no matches + if (matches.length === 0) { + const pendingServers = getPendingServerNames() + return buildSearchResult( + matches, + query, + deferredTools.length, + pendingServers, + ) + } + + return buildSearchResult(matches, query, deferredTools.length) + }, + renderToolUseMessage() { + return null + }, + userFacingName: () => '', + /** + * Returns a tool_result with tool_reference blocks. + * This format works on 1P/Foundry. Bedrock/Vertex may not support + * client-side tool_reference expansion yet. + */ + mapToolResultToToolResultBlockParam( + content: Output, + toolUseID: string, + ): ToolResultBlockParam { + if (content.matches.length === 0) { + let text = 'No matching deferred tools found' + if ( + content.pending_mcp_servers && + content.pending_mcp_servers.length > 0 + ) { + text += `. Some MCP servers are still connecting: ${content.pending_mcp_servers.join(', ')}. Their tools will become available shortly — try searching again.` + } + return { + type: 'tool_result', + tool_use_id: toolUseID, + content: text, + } + } + return { + type: 'tool_result', + tool_use_id: toolUseID, + content: content.matches.map(name => ({ + type: 'tool_reference' as const, + tool_name: name, + })), + } as unknown as ToolResultBlockParam + }, +} satisfies ToolDef) diff --git a/_all-in-one-upload/cc-haha/src/types/statusLine.ts b/_all-in-one-upload/cc-haha/src/types/statusLine.ts new file mode 100644 index 0000000..c170c49 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/types/statusLine.ts @@ -0,0 +1,34 @@ +// @generated stub from scan-missing-imports +// 该文件自动生成,对应 ant-internal 的 feature() gated 模块。 +// 所有外部 build 的代码路径在 DCE 后都不会真的执行这里的代码,这只是 +// bun build resolver 的占位符。 +const __target = function noop() {} +const __handler: ProxyHandler = { + get(_t, prop) { + if (prop === '__esModule') return true + if (prop === 'default') return new Proxy(__target, __handler) + if (prop === Symbol.toPrimitive) return () => undefined + if (prop === Symbol.iterator) return function* () {} + if (prop === Symbol.asyncIterator) return async function* () {} + if (prop === 'then') return undefined + return new Proxy(__target, __handler) + }, + apply() { + return new Proxy(__target, __handler) + }, + construct() { + return new Proxy(__target, __handler) + }, +} +const stub: any = new Proxy(__target, __handler) +export default stub +export const __stubMissing = true +// 兼容常见的命名导出 —— 没列在这里的也会通过 default Proxy 兜底 +export const createCachedMCState = stub +export const isCachedMicrocompactEnabled = stub +export const isModelSupportedForCacheEditing = stub +export const getCachedMCConfig = stub +export const markToolsSentToAPI = stub +export const resetCachedMCState = stub +export const checkProtectedNamespace = stub +export const getCoordinatorUserContext = stub diff --git a/_all-in-one-upload/cc-haha/src/utils/advisor.ts b/_all-in-one-upload/cc-haha/src/utils/advisor.ts new file mode 100644 index 0000000..54a2dfb --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/advisor.ts @@ -0,0 +1,145 @@ +import type { BetaUsage } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../services/analytics/growthbook.js' +import { shouldIncludeFirstPartyOnlyBetas } from './betas.js' +import { isEnvTruthy } from './envUtils.js' +import { getInitialSettings } from './settings/settings.js' + +// The SDK does not yet have types for advisor blocks. +// TODO(hackyon): Migrate to the real anthropic SDK types when this feature ships publicly +export type AdvisorServerToolUseBlock = { + type: 'server_tool_use' + id: string + name: 'advisor' + input: { [key: string]: unknown } +} + +export type AdvisorToolResultBlock = { + type: 'advisor_tool_result' + tool_use_id: string + content: + | { + type: 'advisor_result' + text: string + } + | { + type: 'advisor_redacted_result' + encrypted_content: string + } + | { + type: 'advisor_tool_result_error' + error_code: string + } +} + +export type AdvisorBlock = AdvisorServerToolUseBlock | AdvisorToolResultBlock + +export function isAdvisorBlock(param: { + type: string + name?: string +}): param is AdvisorBlock { + return ( + param.type === 'advisor_tool_result' || + (param.type === 'server_tool_use' && param.name === 'advisor') + ) +} + +type AdvisorConfig = { + enabled?: boolean + canUserConfigure?: boolean + baseModel?: string + advisorModel?: string +} + +function getAdvisorConfig(): AdvisorConfig { + return getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_sage_compass', + {}, + ) +} + +export function isAdvisorEnabled(): boolean { + if (isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_ADVISOR_TOOL)) { + return false + } + // The advisor beta header is first-party only (Bedrock/Vertex 400 on it). + if (!shouldIncludeFirstPartyOnlyBetas()) { + return false + } + return getAdvisorConfig().enabled ?? false +} + +export function canUserConfigureAdvisor(): boolean { + return isAdvisorEnabled() && (getAdvisorConfig().canUserConfigure ?? false) +} + +export function getExperimentAdvisorModels(): + | { baseModel: string; advisorModel: string } + | undefined { + const config = getAdvisorConfig() + return isAdvisorEnabled() && + !canUserConfigureAdvisor() && + config.baseModel && + config.advisorModel + ? { baseModel: config.baseModel, advisorModel: config.advisorModel } + : undefined +} + +// @[MODEL LAUNCH]: Add the new model if it supports the advisor tool. +// Checks whether the main loop model supports calling the advisor tool. +export function modelSupportsAdvisor(model: string): boolean { + const m = model.toLowerCase() + return ( + m.includes('opus-4-6') || + m.includes('sonnet-4-6') || + process.env.USER_TYPE === 'ant' + ) +} + +// @[MODEL LAUNCH]: Add the new model if it can serve as an advisor model. +export function isValidAdvisorModel(model: string): boolean { + const m = model.toLowerCase() + return ( + m.includes('opus-4-6') || + m.includes('sonnet-4-6') || + process.env.USER_TYPE === 'ant' + ) +} + +export function getInitialAdvisorSetting(): string | undefined { + if (!isAdvisorEnabled()) { + return undefined + } + return getInitialSettings().advisorModel +} + +export function getAdvisorUsage( + usage: BetaUsage, +): Array { + const iterations = usage.iterations as + | Array<{ type: string }> + | null + | undefined + if (!iterations) { + return [] + } + return iterations.filter( + it => it.type === 'advisor_message', + ) as unknown as Array +} + +export const ADVISOR_TOOL_INSTRUCTIONS = `# Advisor Tool + +You have access to an \`advisor\` tool backed by a stronger reviewer model. It takes NO parameters -- when you call it, your entire conversation history is automatically forwarded. The advisor sees the task, every tool call you've made, every result you've seen. + +Call advisor BEFORE substantive work -- before writing code, before committing to an interpretation, before building on an assumption. If the task requires orientation first (finding files, reading code, seeing what's there), do that, then call advisor. Orientation is not substantive work. Writing, editing, and declaring an answer are. + +Also call advisor: +- When you believe the task is complete. BEFORE this call, make your deliverable durable: write the file, stage the change, save the result. The advisor call takes time; if the session ends during it, a durable result persists and an unwritten one doesn't. +- When stuck -- errors recurring, approach not converging, results that don't fit. +- When considering a change of approach. + +On tasks longer than a few steps, call advisor at least once before committing to an approach and once before declaring done. On short reactive tasks where the next action is dictated by tool output you just read, you don't need to keep calling -- the advisor adds most of its value on the first call, before the approach crystallizes. + +Give the advice serious weight. If you follow a step and it fails empirically, or you have primary-source evidence that contradicts a specific claim (the file says X, the code does Y), adapt. A passing self-test is not evidence the advice is wrong -- it's evidence your test doesn't check what the advice is checking. + +If you've already retrieved data pointing one way and the advisor points another: don't silently switch. Surface the conflict in one more advisor call -- "I found X, you suggest Y, which constraint breaks the tie?" The advisor saw your evidence but may have underweighted it; a reconcile call is cheaper than committing to the wrong branch.` diff --git a/_all-in-one-upload/cc-haha/src/utils/attachments.ts b/_all-in-one-upload/cc-haha/src/utils/attachments.ts new file mode 100644 index 0000000..556defe --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/attachments.ts @@ -0,0 +1,3993 @@ +// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered +import { + logEvent, + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, +} from 'src/services/analytics/index.js' +import { + toolMatchesName, + type Tools, + type ToolUseContext, + type ToolPermissionContext, +} from '../Tool.js' +import { + FileReadTool, + MaxFileReadTokenExceededError, + type Output as FileReadToolOutput, + readImageWithTokenBudget, +} from '../tools/FileReadTool/FileReadTool.js' +import { FileTooLargeError, readFileInRange } from './readFileInRange.js' +import { expandPath } from './path.js' +import { countCharInString } from './stringUtils.js' +import { count, uniq } from './array.js' +import { getFsImplementation } from './fsOperations.js' +import { readdir, stat } from 'fs/promises' +import type { IDESelection } from '../hooks/useIdeSelection.js' +import { TODO_WRITE_TOOL_NAME } from '../tools/TodoWriteTool/constants.js' +import { TASK_CREATE_TOOL_NAME } from '../tools/TaskCreateTool/constants.js' +import { TASK_UPDATE_TOOL_NAME } from '../tools/TaskUpdateTool/constants.js' +import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js' +import { SKILL_TOOL_NAME } from '../tools/SkillTool/constants.js' +import type { TodoList } from './todo/types.js' +import { + type Task, + listTasks, + getTaskListId, + isTodoV2Enabled, +} from './tasks.js' +import { getPlanFilePath, getPlan } from './plans.js' +import { getConnectedIdeName } from './ide.js' +import { + filterInjectedMemoryFiles, + getManagedAndUserConditionalRules, + getMemoryFiles, + getMemoryFilesForNestedDirectory, + getConditionalRulesForCwdLevelDirectory, + type MemoryFileInfo, +} from './claudemd.js' +import { dirname, parse, relative, resolve } from 'path' +import { getCwd } from 'src/utils/cwd.js' +import { getViewedTeammateTask } from '../state/selectors.js' +import { logError } from './log.js' +import { logAntError } from './debug.js' +import { isENOENT, toError } from './errors.js' +import type { DiagnosticFile } from '../services/diagnosticTracking.js' +import { diagnosticTracker } from '../services/diagnosticTracking.js' +import type { + AttachmentMessage, + Message, + MessageOrigin, +} from 'src/types/message.js' +import { + type QueuedCommand, + getImagePasteIds, + isValidImagePaste, +} from 'src/types/textInputTypes.js' +import { randomUUID, type UUID } from 'crypto' +import { getSettings_DEPRECATED } from './settings/settings.js' +import { getSnippetForTwoFileDiff } from 'src/tools/FileEditTool/utils.js' +import type { + ContentBlockParam, + ImageBlockParam, + Base64ImageSource, +} from '@anthropic-ai/sdk/resources/messages.mjs' +import { maybeResizeAndDownsampleImageBlock } from './imageResizer.js' +import type { PastedContent } from './config.js' +import { getGlobalConfig } from './config.js' +import { + getDefaultSonnetModel, + getDefaultHaikuModel, + getDefaultOpusModel, +} from './model/model.js' +import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js' +import { getSkillToolCommands, getMcpSkillCommands } from '../commands.js' +import type { Command } from '../types/command.js' +import uniqBy from 'lodash-es/uniqBy.js' +import { getProjectRoot } from '../bootstrap/state.js' +import { formatCommandsWithinBudget } from '../tools/SkillTool/prompt.js' +import { getContextWindowForModel } from './context.js' +import type { DiscoverySignal } from '../services/skillSearch/signals.js' +// Conditional require for DCE. All skill-search string literals that would +// otherwise leak into external builds live inside these modules. The only +// surfaces in THIS file are: the maybe() call (gated via spread below) and +// the skill_listing suppression check (uses the same skillSearchModules null +// check). The type-only DiscoverySignal import above is erased at compile time. +/* eslint-disable @typescript-eslint/no-require-imports */ +const skillSearchModules = feature('EXPERIMENTAL_SKILL_SEARCH') + ? { + featureCheck: + require('../services/skillSearch/featureCheck.js') as typeof import('../services/skillSearch/featureCheck.js'), + prefetch: + require('../services/skillSearch/prefetch.js') as typeof import('../services/skillSearch/prefetch.js'), + } + : null +const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') + ? (require('./permissions/autoModeState.js') as typeof import('./permissions/autoModeState.js')) + : null +/* eslint-enable @typescript-eslint/no-require-imports */ +import { + MAX_LINES_TO_READ, + FILE_READ_TOOL_NAME, +} from 'src/tools/FileReadTool/prompt.js' +import { getDefaultFileReadingLimits } from 'src/tools/FileReadTool/limits.js' +import { cacheKeys, type FileStateCache } from './fileStateCache.js' +import { + createAbortController, + createChildAbortController, +} from './abortController.js' +import { isAbortError } from './errors.js' +import { + getFileModificationTimeAsync, + isFileWithinReadSizeLimit, +} from './file.js' +import type { AgentDefinition } from '../tools/AgentTool/loadAgentsDir.js' +import { filterAgentsByMcpRequirements } from '../tools/AgentTool/loadAgentsDir.js' +import { AGENT_TOOL_NAME } from '../tools/AgentTool/constants.js' +import { + formatAgentLine, + shouldInjectAgentListInMessages, +} from '../tools/AgentTool/prompt.js' +import { filterDeniedAgents } from './permissions/permissions.js' +import { getSubscriptionType } from './auth.js' +import { mcpInfoFromString } from '../services/mcp/mcpStringUtils.js' +import { + matchingRuleForInput, + pathInAllowedWorkingPath, +} from './permissions/filesystem.js' +import { + generateTaskAttachments, + applyTaskOffsetsAndEvictions, +} from './task/framework.js' +import { getTaskOutputPath } from './task/diskOutput.js' +import { drainPendingMessages } from '../tasks/LocalAgentTask/LocalAgentTask.js' +import type { TaskType, TaskStatus } from '../Task.js' +import { + getOriginalCwd, + getSessionId, + getSdkBetas, + getTotalCostUSD, + getTotalOutputTokens, + getCurrentTurnTokenBudget, + getTurnOutputTokens, + hasExitedPlanModeInSession, + setHasExitedPlanMode, + needsPlanModeExitAttachment, + setNeedsPlanModeExitAttachment, + needsAutoModeExitAttachment, + setNeedsAutoModeExitAttachment, + getLastEmittedDate, + setLastEmittedDate, + getKairosActive, +} from '../bootstrap/state.js' +import type { QuerySource } from '../constants/querySource.js' +import { + getDeferredToolsDelta, + isDeferredToolsDeltaEnabled, + isToolSearchEnabledOptimistic, + isToolSearchToolAvailable, + modelSupportsToolReference, + type DeferredToolsDeltaScanContext, +} from './toolSearch.js' +import { + getMcpInstructionsDelta, + isMcpInstructionsDeltaEnabled, + type ClientSideInstruction, +} from './mcpInstructionsDelta.js' +import { CLAUDE_IN_CHROME_MCP_SERVER_NAME } from './claudeInChrome/common.js' +import { CHROME_TOOL_SEARCH_INSTRUCTIONS } from './claudeInChrome/prompt.js' +import type { MCPServerConnection } from '../services/mcp/types.js' +import type { + HookEvent, + SyncHookJSONOutput, +} from 'src/entrypoints/agentSdkTypes.js' +import { + checkForAsyncHookResponses, + removeDeliveredAsyncHooks, +} from './hooks/AsyncHookRegistry.js' +import { + checkForLSPDiagnostics, + clearAllLSPDiagnostics, +} from '../services/lsp/LSPDiagnosticRegistry.js' +import { logForDebugging } from './debug.js' +import { + extractTextContent, + getUserMessageText, + isThinkingMessage, +} from './messages.js' +import { isHumanTurn } from './messagePredicates.js' +import { isEnvTruthy, getClaudeConfigHomeDir } from './envUtils.js' +import { feature } from 'bun:bundle' +/* eslint-disable @typescript-eslint/no-require-imports */ +const BRIEF_TOOL_NAME: string | null = + feature('KAIROS') || feature('KAIROS_BRIEF') + ? ( + require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') + ).BRIEF_TOOL_NAME + : null +const sessionTranscriptModule = feature('KAIROS') + ? (require('../services/sessionTranscript/sessionTranscript.js') as typeof import('../services/sessionTranscript/sessionTranscript.js')) + : null +/* eslint-enable @typescript-eslint/no-require-imports */ +import { hasUltrathinkKeyword, isUltrathinkEnabled } from './thinking.js' +import { + tokenCountFromLastAPIResponse, + tokenCountWithEstimation, +} from './tokens.js' +import { + getEffectiveContextWindowSize, + isAutoCompactEnabled, +} from '../services/compact/autoCompact.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../services/analytics/growthbook.js' +import { + hasInstructionsLoadedHook, + executeInstructionsLoadedHooks, + type HookBlockingError, + type InstructionsMemoryType, +} from './hooks.js' +import { jsonStringify } from './slowOperations.js' +import { isPDFExtension } from './pdfUtils.js' +import { getLocalISODate } from '../constants/common.js' +import { getPDFPageCount } from './pdf.js' +import { PDF_AT_MENTION_INLINE_THRESHOLD } from '../constants/apiLimits.js' +import { isAgentSwarmsEnabled } from './agentSwarmsEnabled.js' +import { findRelevantMemories } from '../memdir/findRelevantMemories.js' +import { memoryAge, memoryFreshnessText } from '../memdir/memoryAge.js' +import { getAutoMemPath, isAutoMemoryEnabled } from '../memdir/paths.js' +import { getAgentMemoryDir } from '../tools/AgentTool/agentMemory.js' +import { + readUnreadMessages, + markMessagesAsReadByPredicate, + isShutdownApproved, + isStructuredProtocolMessage, + isIdleNotification, +} from './teammateMailbox.js' +import { + getAgentName, + getAgentId, + getTeamName, + isTeamLead, +} from './teammate.js' +import { isInProcessTeammate } from './teammateContext.js' +import { removeTeammateFromTeamFile } from './swarm/teamHelpers.js' +import { unassignTeammateTasks } from './tasks.js' +import { getCompanionIntroAttachment } from '../buddy/prompt.js' + +export const TODO_REMINDER_CONFIG = { + TURNS_SINCE_WRITE: 10, + TURNS_BETWEEN_REMINDERS: 10, +} as const + +export const PLAN_MODE_ATTACHMENT_CONFIG = { + TURNS_BETWEEN_ATTACHMENTS: 5, + FULL_REMINDER_EVERY_N_ATTACHMENTS: 5, +} as const + +export const AUTO_MODE_ATTACHMENT_CONFIG = { + TURNS_BETWEEN_ATTACHMENTS: 5, + FULL_REMINDER_EVERY_N_ATTACHMENTS: 5, +} as const + +const MAX_MEMORY_LINES = 200 +// Line cap alone doesn't bound size (200 × 500-char lines = 100KB). The +// surfacer injects up to 5 files per turn via , bypassing +// the per-message tool-result budget, so a tight per-file byte cap keeps +// aggregate injection bounded (5 × 4KB = 20KB/turn). Enforced via +// readFileInRange's truncateOnByteLimit option. Truncation means the +// most-relevant memory still surfaces: the frontmatter + opening context +// is usually what matters. +const MAX_MEMORY_BYTES = 4096 + +export const RELEVANT_MEMORIES_CONFIG = { + // Per-turn cap (5 × 4KB = 20KB) bounds a single injection, but over a + // long session the selector keeps surfacing distinct files — ~26K tokens/ + // session observed in prod. Cap the cumulative bytes: once hit, stop + // prefetching entirely. Budget is ~3 full injections; after that the + // most-relevant memories are already in context. Scanning messages + // (rather than tracking in toolUseContext) means compact naturally + // resets the counter — old attachments are gone from context, so + // re-surfacing is valid. + MAX_SESSION_BYTES: 60 * 1024, +} as const + +export const VERIFY_PLAN_REMINDER_CONFIG = { + TURNS_BETWEEN_REMINDERS: 10, +} as const + +export type FileAttachment = { + type: 'file' + filename: string + content: FileReadToolOutput + /** + * Whether the file was truncated due to size limits + */ + truncated?: boolean + /** Path relative to CWD at creation time, for stable display */ + displayPath: string +} + +export type CompactFileReferenceAttachment = { + type: 'compact_file_reference' + filename: string + /** Path relative to CWD at creation time, for stable display */ + displayPath: string +} + +export type PDFReferenceAttachment = { + type: 'pdf_reference' + filename: string + pageCount: number + fileSize: number + /** Path relative to CWD at creation time, for stable display */ + displayPath: string +} + +export type AlreadyReadFileAttachment = { + type: 'already_read_file' + filename: string + content: FileReadToolOutput + /** + * Whether the file was truncated due to size limits + */ + truncated?: boolean + /** Path relative to CWD at creation time, for stable display */ + displayPath: string +} + +export type AgentMentionAttachment = { + type: 'agent_mention' + agentType: string +} + +export type AsyncHookResponseAttachment = { + type: 'async_hook_response' + processId: string + hookName: string + hookEvent: HookEvent | 'StatusLine' | 'FileSuggestion' + toolName?: string + response: SyncHookJSONOutput + stdout: string + stderr: string + exitCode?: number +} + +export type HookAttachment = + | HookCancelledAttachment + | { + type: 'hook_blocking_error' + blockingError: HookBlockingError + hookName: string + toolUseID: string + hookEvent: HookEvent + } + | HookNonBlockingErrorAttachment + | HookErrorDuringExecutionAttachment + | { + type: 'hook_stopped_continuation' + message: string + hookName: string + toolUseID: string + hookEvent: HookEvent + } + | HookSuccessAttachment + | { + type: 'hook_additional_context' + content: string[] + hookName: string + toolUseID: string + hookEvent: HookEvent + } + | HookSystemMessageAttachment + | HookPermissionDecisionAttachment + +export type HookPermissionDecisionAttachment = { + type: 'hook_permission_decision' + decision: 'allow' | 'deny' + toolUseID: string + hookEvent: HookEvent +} + +export type HookSystemMessageAttachment = { + type: 'hook_system_message' + content: string + hookName: string + toolUseID: string + hookEvent: HookEvent +} + +export type HookCancelledAttachment = { + type: 'hook_cancelled' + hookName: string + toolUseID: string + hookEvent: HookEvent + command?: string + durationMs?: number +} + +export type HookErrorDuringExecutionAttachment = { + type: 'hook_error_during_execution' + content: string + hookName: string + toolUseID: string + hookEvent: HookEvent + command?: string + durationMs?: number +} + +export type HookSuccessAttachment = { + type: 'hook_success' + content: string + hookName: string + toolUseID: string + hookEvent: HookEvent + stdout?: string + stderr?: string + exitCode?: number + command?: string + durationMs?: number +} + +export type HookNonBlockingErrorAttachment = { + type: 'hook_non_blocking_error' + hookName: string + stderr: string + stdout: string + exitCode: number + toolUseID: string + hookEvent: HookEvent + command?: string + durationMs?: number +} + +export type Attachment = + /** + * User at-mentioned the file + */ + | FileAttachment + | CompactFileReferenceAttachment + | PDFReferenceAttachment + | AlreadyReadFileAttachment + /** + * An at-mentioned file was edited + */ + | { + type: 'edited_text_file' + filename: string + snippet: string + } + | { + type: 'edited_image_file' + filename: string + content: FileReadToolOutput + } + | { + type: 'directory' + path: string + content: string + /** Path relative to CWD at creation time, for stable display */ + displayPath: string + } + | { + type: 'selected_lines_in_ide' + ideName: string + lineStart: number + lineEnd: number + filename: string + content: string + /** Path relative to CWD at creation time, for stable display */ + displayPath: string + } + | { + type: 'opened_file_in_ide' + filename: string + } + | { + type: 'todo_reminder' + content: TodoList + itemCount: number + } + | { + type: 'task_reminder' + content: Task[] + itemCount: number + } + | { + type: 'nested_memory' + path: string + content: MemoryFileInfo + /** Path relative to CWD at creation time, for stable display */ + displayPath: string + } + | { + type: 'relevant_memories' + memories: { + path: string + content: string + mtimeMs: number + /** + * Pre-computed header string (age + path prefix). Computed once + * at attachment-creation time so the rendered bytes are stable + * across turns — recomputing memoryAge(mtimeMs) at render time + * calls Date.now(), so "saved 3 days ago" becomes "saved 4 days + * ago" across turns → different bytes → prompt cache bust. + * Optional for backward compat with resumed sessions; render + * path falls back to recomputing if missing. + */ + header?: string + /** + * lineCount when the file was truncated by readMemoriesForSurfacing, + * else undefined. Threaded to the readFileState write so + * getChangedFiles skips truncated memories (partial content would + * yield a misleading diff). + */ + limit?: number + }[] + } + | { + type: 'dynamic_skill' + skillDir: string + skillNames: string[] + /** Path relative to CWD at creation time, for stable display */ + displayPath: string + } + | { + type: 'skill_listing' + content: string + skillCount: number + isInitial: boolean + } + | { + type: 'skill_discovery' + skills: { name: string; description: string; shortId?: string }[] + signal: DiscoverySignal + source: 'native' | 'aki' | 'both' + } + | { + type: 'queued_command' + prompt: string | Array + source_uuid?: UUID + imagePasteIds?: number[] + /** Original queue mode — 'prompt' for user messages, 'task-notification' for system events */ + commandMode?: string + /** Provenance carried from QueuedCommand so mid-turn drains preserve it */ + origin?: MessageOrigin + /** Carried from QueuedCommand.isMeta — distinguishes human-typed from system-injected */ + isMeta?: boolean + } + | { + type: 'output_style' + style: string + } + | { + type: 'diagnostics' + files: DiagnosticFile[] + isNew: boolean + } + | { + type: 'plan_mode' + reminderType: 'full' | 'sparse' + isSubAgent?: boolean + planFilePath: string + planExists: boolean + } + | { + type: 'plan_mode_reentry' + planFilePath: string + } + | { + type: 'plan_mode_exit' + planFilePath: string + planExists: boolean + } + | { + type: 'auto_mode' + reminderType: 'full' | 'sparse' + } + | { + type: 'auto_mode_exit' + } + | { + type: 'critical_system_reminder' + content: string + } + | { + type: 'plan_file_reference' + planFilePath: string + planContent: string + } + | { + type: 'mcp_resource' + server: string + uri: string + name: string + description?: string + content: ReadResourceResult + } + | { + type: 'command_permissions' + allowedTools: string[] + model?: string + } + | AgentMentionAttachment + | { + type: 'task_status' + taskId: string + taskType: TaskType + status: TaskStatus + description: string + deltaSummary: string | null + outputFilePath?: string + } + | AsyncHookResponseAttachment + | { + type: 'token_usage' + used: number + total: number + remaining: number + } + | { + type: 'budget_usd' + used: number + total: number + remaining: number + } + | { + type: 'output_token_usage' + turn: number + session: number + budget: number | null + } + | { + type: 'structured_output' + data: unknown + } + | TeammateMailboxAttachment + | TeamContextAttachment + | HookAttachment + | { + type: 'invoked_skills' + skills: Array<{ + name: string + path: string + content: string + }> + } + | { + type: 'verify_plan_reminder' + } + | { + type: 'max_turns_reached' + maxTurns: number + turnCount: number + } + | { + type: 'current_session_memory' + content: string + path: string + tokenCount: number + } + | { + type: 'teammate_shutdown_batch' + count: number + } + | { + type: 'compaction_reminder' + } + | { + type: 'context_efficiency' + } + | { + type: 'date_change' + newDate: string + } + | { + type: 'ultrathink_effort' + level: 'high' + } + | { + type: 'deferred_tools_delta' + addedNames: string[] + addedLines: string[] + removedNames: string[] + } + | { + type: 'agent_listing_delta' + addedTypes: string[] + addedLines: string[] + removedTypes: string[] + /** True when this is the first announcement in the conversation */ + isInitial: boolean + /** Whether to include the "launch multiple agents concurrently" note (non-pro subscriptions) */ + showConcurrencyNote: boolean + } + | { + type: 'mcp_instructions_delta' + addedNames: string[] + addedBlocks: string[] + removedNames: string[] + } + | { + type: 'companion_intro' + name: string + species: string + } + | { + type: 'bagel_console' + errorCount: number + warningCount: number + sample: string + } + +export type TeammateMailboxAttachment = { + type: 'teammate_mailbox' + messages: Array<{ + from: string + text: string + timestamp: string + color?: string + summary?: string + }> +} + +export type TeamContextAttachment = { + type: 'team_context' + agentId: string + agentName: string + teamName: string + teamConfigPath: string + taskListPath: string +} + +/** + * This is janky + * TODO: Generate attachments when we create messages + */ +export async function getAttachments( + input: string | null, + toolUseContext: ToolUseContext, + ideSelection: IDESelection | null, + queuedCommands: QueuedCommand[], + messages?: Message[], + querySource?: QuerySource, + options?: { skipSkillDiscovery?: boolean }, +): Promise { + if ( + isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_ATTACHMENTS) || + isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE) + ) { + // query.ts:removeFromQueue dequeues these unconditionally after + // getAttachmentMessages runs — returning [] here silently drops them. + // Coworker runs with --bare and depends on task-notification for + // mid-tool-call notifications from Local*Task/Remote*Task. + return getQueuedCommandAttachments(queuedCommands) + } + + // This will slow down submissions + // TODO: Compute attachments as the user types, not here (though we use this + // function for slash command prompts too) + const abortController = createAbortController() + const timeoutId = setTimeout(ac => ac.abort(), 1000, abortController) + const context = { ...toolUseContext, abortController } + + const isMainThread = !toolUseContext.agentId + + // Attachments which are added in response to on user input + const userInputAttachments = input + ? [ + maybe('at_mentioned_files', () => + processAtMentionedFiles(input, context), + ), + maybe('mcp_resources', () => + processMcpResourceAttachments(input, context), + ), + maybe('agent_mentions', () => + Promise.resolve( + processAgentMentions( + input, + toolUseContext.options.agentDefinitions.activeAgents, + ), + ), + ), + // Skill discovery on turn 0 (user input as signal). Inter-turn + // discovery runs via startSkillDiscoveryPrefetch in query.ts, + // gated on write-pivot detection — see skillSearch/prefetch.ts. + // feature() here lets DCE drop the 'skill_discovery' string (and the + // function it calls) from external builds. + // + // skipSkillDiscovery gates out the SKILL.md-expansion path + // (getMessagesForPromptSlashCommand). When a skill is invoked, its + // SKILL.md content is passed as `input` here to extract @-mentions — + // but that content is NOT user intent and must not trigger discovery. + // Without this gate, a 110KB SKILL.md fires ~3.3s of chunked AKI + // queries on every skill invocation (session 13a9afae). + ...(feature('EXPERIMENTAL_SKILL_SEARCH') && + skillSearchModules && + !options?.skipSkillDiscovery + ? [ + maybe('skill_discovery', () => + skillSearchModules.prefetch.getTurnZeroSkillDiscovery( + input, + messages ?? [], + context, + ), + ), + ] + : []), + ] + : [] + + // Process user input attachments first (includes @mentioned files) + // This ensures files are added to nestedMemoryAttachmentTriggers before nested_memory processes them + const userAttachmentResults = await Promise.all(userInputAttachments) + + // Thread-safe attachments available in sub-agents + // NOTE: These must be created AFTER userInputAttachments completes to ensure + // nestedMemoryAttachmentTriggers is populated before getNestedMemoryAttachments runs + const allThreadAttachments = [ + // queuedCommands is already agent-scoped by the drain gate in query.ts — + // main thread gets agentId===undefined, subagents get their own agentId. + // Must run for all threads or subagent notifications drain into the void + // (removed from queue by removeFromQueue but never attached). + maybe('queued_commands', () => getQueuedCommandAttachments(queuedCommands)), + maybe('date_change', () => + Promise.resolve(getDateChangeAttachments(messages)), + ), + maybe('ultrathink_effort', () => + Promise.resolve(getUltrathinkEffortAttachment(input)), + ), + maybe('deferred_tools_delta', () => + Promise.resolve( + getDeferredToolsDeltaAttachment( + toolUseContext.options.tools, + toolUseContext.options.mainLoopModel, + messages, + { + callSite: isMainThread + ? 'attachments_main' + : 'attachments_subagent', + querySource, + }, + ), + ), + ), + maybe('agent_listing_delta', () => + Promise.resolve(getAgentListingDeltaAttachment(toolUseContext, messages)), + ), + maybe('mcp_instructions_delta', () => + Promise.resolve( + getMcpInstructionsDeltaAttachment( + toolUseContext.options.mcpClients, + toolUseContext.options.tools, + toolUseContext.options.mainLoopModel, + messages, + ), + ), + ), + maybe('companion_intro', () => + Promise.resolve(getCompanionIntroAttachment(messages)), + ), + maybe('changed_files', () => getChangedFiles(context)), + maybe('nested_memory', () => getNestedMemoryAttachments(context)), + // relevant_memories moved to async prefetch (startRelevantMemoryPrefetch) + maybe('dynamic_skill', () => getDynamicSkillAttachments(context)), + maybe('skill_listing', () => getSkillListingAttachments(context)), + // Inter-turn skill discovery now runs via startSkillDiscoveryPrefetch + // (query.ts, concurrent with the main turn). The blocking call that + // previously lived here was the assistant_turn signal — 97% of those + // Haiku calls found nothing in prod. Prefetch + await-at-collection + // replaces it; see src/services/skillSearch/prefetch.ts. + maybe('plan_mode', () => getPlanModeAttachments(messages, toolUseContext)), + maybe('plan_mode_exit', () => getPlanModeExitAttachment(toolUseContext)), + ...(feature('TRANSCRIPT_CLASSIFIER') + ? [ + maybe('auto_mode', () => + getAutoModeAttachments(messages, toolUseContext), + ), + maybe('auto_mode_exit', () => + getAutoModeExitAttachment(toolUseContext), + ), + ] + : []), + maybe('todo_reminders', () => + isTodoV2Enabled() + ? getTaskReminderAttachments(messages, toolUseContext) + : getTodoReminderAttachments(messages, toolUseContext), + ), + ...(isAgentSwarmsEnabled() + ? [ + // Skip teammate mailbox for the session_memory forked agent. + // It shares AppState.teamContext with the leader, so isTeamLead resolves + // true and it reads+marks-as-read the leader's DMs as ephemeral attachments, + // silently stealing messages that should be delivered as permanent turns. + ...(querySource === 'session_memory' + ? [] + : [ + maybe('teammate_mailbox', async () => + getTeammateMailboxAttachments(toolUseContext), + ), + ]), + maybe('team_context', async () => + getTeamContextAttachment(messages ?? []), + ), + ] + : []), + maybe('agent_pending_messages', async () => + getAgentPendingMessageAttachments(toolUseContext), + ), + maybe('critical_system_reminder', () => + Promise.resolve(getCriticalSystemReminderAttachment(toolUseContext)), + ), + ...(feature('COMPACTION_REMINDERS') + ? [ + maybe('compaction_reminder', () => + Promise.resolve( + getCompactionReminderAttachment( + messages ?? [], + toolUseContext.options.mainLoopModel, + ), + ), + ), + ] + : []), + ...(feature('HISTORY_SNIP') + ? [ + maybe('context_efficiency', () => + Promise.resolve(getContextEfficiencyAttachment(messages ?? [])), + ), + ] + : []), + ] + + // Attachments which are semantically only for the main conversation or don't have concurrency-safe implementations + const mainThreadAttachments = isMainThread + ? [ + maybe('ide_selection', async () => + getSelectedLinesFromIDE(ideSelection, toolUseContext), + ), + maybe('ide_opened_file', async () => + getOpenedFileFromIDE(ideSelection, toolUseContext), + ), + maybe('output_style', async () => + Promise.resolve(getOutputStyleAttachment()), + ), + maybe('diagnostics', async () => + getDiagnosticAttachments(toolUseContext), + ), + maybe('lsp_diagnostics', async () => + getLSPDiagnosticAttachments(toolUseContext), + ), + maybe('unified_tasks', async () => + getUnifiedTaskAttachments(toolUseContext), + ), + maybe('async_hook_responses', async () => + getAsyncHookResponseAttachments(), + ), + maybe('token_usage', async () => + Promise.resolve( + getTokenUsageAttachment( + messages ?? [], + toolUseContext.options.mainLoopModel, + ), + ), + ), + maybe('budget_usd', async () => + Promise.resolve( + getMaxBudgetUsdAttachment(toolUseContext.options.maxBudgetUsd), + ), + ), + maybe('output_token_usage', async () => + Promise.resolve(getOutputTokenUsageAttachment()), + ), + maybe('verify_plan_reminder', async () => + getVerifyPlanReminderAttachment(messages, toolUseContext), + ), + ] + : [] + + // Process thread and main thread attachments in parallel (no dependencies between them) + const [threadAttachmentResults, mainThreadAttachmentResults] = + await Promise.all([ + Promise.all(allThreadAttachments), + Promise.all(mainThreadAttachments), + ]) + + clearTimeout(timeoutId) + // Defensive: a getter leaking [undefined] crashes .map(a => a.type) below. + return [ + ...userAttachmentResults.flat(), + ...threadAttachmentResults.flat(), + ...mainThreadAttachmentResults.flat(), + ].filter(a => a !== undefined && a !== null) +} + +async function maybe(label: string, f: () => Promise): Promise { + const startTime = Date.now() + try { + const result = await f() + const duration = Date.now() - startTime + // Log only 5% of events to reduce volume + if (Math.random() < 0.05) { + // jsonStringify(undefined) returns undefined, so .length would throw + const attachmentSizeBytes = result + .filter(a => a !== undefined && a !== null) + .reduce((total, attachment) => { + return total + jsonStringify(attachment).length + }, 0) + logEvent('tengu_attachment_compute_duration', { + label, + duration_ms: duration, + attachment_size_bytes: attachmentSizeBytes, + attachment_count: result.length, + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) + } + return result + } catch (e) { + const duration = Date.now() - startTime + // Log only 5% of events to reduce volume + if (Math.random() < 0.05) { + logEvent('tengu_attachment_compute_duration', { + label, + duration_ms: duration, + error: true, + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) + } + logError(e) + // For Ant users, log the full error to help with debugging + logAntError(`Attachment error in ${label}`, e) + + return [] + } +} + +const INLINE_NOTIFICATION_MODES = new Set(['prompt', 'task-notification']) + +export async function getQueuedCommandAttachments( + queuedCommands: QueuedCommand[], +): Promise { + if (!queuedCommands) { + return [] + } + // Include both 'prompt' and 'task-notification' commands as attachments. + // During proactive agentic loops, task-notification commands would otherwise + // stay in the queue permanently (useQueueProcessor can't run while a query + // is active), causing hasPendingNotifications() to return true and Sleep to + // wake immediately with 0ms duration in an infinite loop. + const filtered = queuedCommands.filter(_ => + INLINE_NOTIFICATION_MODES.has(_.mode), + ) + return Promise.all( + filtered.map(async _ => { + const imageBlocks = await buildImageContentBlocks(_.pastedContents) + let prompt: string | Array = _.value + if (imageBlocks.length > 0) { + // Build content block array with text + images so the model sees them + const textValue = + typeof _.value === 'string' + ? _.value + : extractTextContent(_.value, '\n') + prompt = [{ type: 'text' as const, text: textValue }, ...imageBlocks] + } + return { + type: 'queued_command' as const, + prompt, + source_uuid: _.uuid, + imagePasteIds: getImagePasteIds(_.pastedContents), + commandMode: _.mode, + origin: _.origin, + isMeta: _.isMeta, + } + }), + ) +} + +export function getAgentPendingMessageAttachments( + toolUseContext: ToolUseContext, +): Attachment[] { + const agentId = toolUseContext.agentId + if (!agentId) return [] + const drained = drainPendingMessages( + agentId, + toolUseContext.getAppState, + toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState, + ) + return drained.map(msg => ({ + type: 'queued_command' as const, + prompt: msg, + origin: { kind: 'coordinator' as const }, + isMeta: true, + })) +} + +async function buildImageContentBlocks( + pastedContents: Record | undefined, +): Promise { + if (!pastedContents) { + return [] + } + const imageContents = Object.values(pastedContents).filter(isValidImagePaste) + if (imageContents.length === 0) { + return [] + } + const results = await Promise.all( + imageContents.map(async img => { + const imageBlock: ImageBlockParam = { + type: 'image', + source: { + type: 'base64', + media_type: (img.mediaType || + 'image/png') as Base64ImageSource['media_type'], + data: img.content, + }, + } + const resized = await maybeResizeAndDownsampleImageBlock(imageBlock) + return resized.block + }), + ) + return results +} + +function getPlanModeAttachmentTurnCount(messages: Message[]): { + turnCount: number + foundPlanModeAttachment: boolean +} { + let turnsSinceLastAttachment = 0 + let foundPlanModeAttachment = false + + // Iterate backwards to find most recent plan_mode attachment. + // Count HUMAN turns (non-meta, non-tool-result user messages), not assistant + // messages — the tool loop in query.ts calls getAttachmentMessages on every + // tool round, so counting assistant messages would fire the reminder every + // 5 tool calls instead of every 5 human turns. + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + + if ( + message?.type === 'user' && + !message.isMeta && + !hasToolResultContent(message.message.content) + ) { + turnsSinceLastAttachment++ + } else if ( + message?.type === 'attachment' && + (message.attachment.type === 'plan_mode' || + message.attachment.type === 'plan_mode_reentry') + ) { + foundPlanModeAttachment = true + break + } + } + + return { turnCount: turnsSinceLastAttachment, foundPlanModeAttachment } +} + +/** + * Count plan_mode attachments since the last plan_mode_exit (or from start if no exit). + * This ensures the full/sparse cycle resets when re-entering plan mode. + */ +function countPlanModeAttachmentsSinceLastExit(messages: Message[]): number { + let count = 0 + // Iterate backwards - if we hit a plan_mode_exit, stop counting + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + if (message?.type === 'attachment') { + if (message.attachment.type === 'plan_mode_exit') { + break // Stop counting at the last exit + } + if (message.attachment.type === 'plan_mode') { + count++ + } + } + } + return count +} + +async function getPlanModeAttachments( + messages: Message[] | undefined, + toolUseContext: ToolUseContext, +): Promise { + const appState = toolUseContext.getAppState() + const permissionContext = appState.toolPermissionContext + if (permissionContext.mode !== 'plan') { + return [] + } + + // Check if we should attach based on turn count (except for first turn) + if (messages && messages.length > 0) { + const { turnCount, foundPlanModeAttachment } = + getPlanModeAttachmentTurnCount(messages) + // Only throttle if we've already sent a plan_mode attachment before + // On first turn in plan mode, always attach + if ( + foundPlanModeAttachment && + turnCount < PLAN_MODE_ATTACHMENT_CONFIG.TURNS_BETWEEN_ATTACHMENTS + ) { + return [] + } + } + + const planFilePath = getPlanFilePath(toolUseContext.agentId) + const existingPlan = getPlan(toolUseContext.agentId) + + const attachments: Attachment[] = [] + + // Check for re-entry: flag is set AND plan file exists + if (hasExitedPlanModeInSession() && existingPlan !== null) { + attachments.push({ type: 'plan_mode_reentry', planFilePath }) + setHasExitedPlanMode(false) // Clear flag - one-time guidance + } + + // Determine if this should be a full or sparse reminder + // Full reminder on 1st, 6th, 11th... (every Nth attachment) + const attachmentCount = + countPlanModeAttachmentsSinceLastExit(messages ?? []) + 1 + const reminderType: 'full' | 'sparse' = + attachmentCount % + PLAN_MODE_ATTACHMENT_CONFIG.FULL_REMINDER_EVERY_N_ATTACHMENTS === + 1 + ? 'full' + : 'sparse' + + // Always add the main plan_mode attachment + attachments.push({ + type: 'plan_mode', + reminderType, + isSubAgent: !!toolUseContext.agentId, + planFilePath, + planExists: existingPlan !== null, + }) + + return attachments +} + +/** + * Returns a plan_mode_exit attachment if we just exited plan mode. + * This is a one-time notification to tell the model it's no longer in plan mode. + */ +async function getPlanModeExitAttachment( + toolUseContext: ToolUseContext, +): Promise { + // Only trigger if the flag is set (we just exited plan mode) + if (!needsPlanModeExitAttachment()) { + return [] + } + + const appState = toolUseContext.getAppState() + if (appState.toolPermissionContext.mode === 'plan') { + setNeedsPlanModeExitAttachment(false) + return [] + } + + // Clear the flag - this is a one-time notification + setNeedsPlanModeExitAttachment(false) + + const planFilePath = getPlanFilePath(toolUseContext.agentId) + const planExists = getPlan(toolUseContext.agentId) !== null + + // Note: skill discovery does NOT fire on plan exit. By the time the plan is + // written, it's too late — the model should have had relevant skills WHILE + // planning. The user_message signal already fires on the request that + // triggers planning ("plan how to deploy this"), which is the right moment. + return [{ type: 'plan_mode_exit', planFilePath, planExists }] +} + +function getAutoModeAttachmentTurnCount(messages: Message[]): { + turnCount: number + foundAutoModeAttachment: boolean +} { + let turnsSinceLastAttachment = 0 + let foundAutoModeAttachment = false + + // Iterate backwards to find most recent auto_mode attachment. + // Count HUMAN turns (non-meta, non-tool-result user messages), not assistant + // messages — the tool loop in query.ts calls getAttachmentMessages on every + // tool round, so a single human turn with 100 tool calls would fire ~20 + // reminders if we counted assistant messages. Auto mode's target use case is + // long agentic sessions, where this accumulated 60-105× per session. + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + + if ( + message?.type === 'user' && + !message.isMeta && + !hasToolResultContent(message.message.content) + ) { + turnsSinceLastAttachment++ + } else if ( + message?.type === 'attachment' && + message.attachment.type === 'auto_mode' + ) { + foundAutoModeAttachment = true + break + } else if ( + message?.type === 'attachment' && + message.attachment.type === 'auto_mode_exit' + ) { + // Exit resets the throttle — treat as if no prior attachment exists + break + } + } + + return { turnCount: turnsSinceLastAttachment, foundAutoModeAttachment } +} + +/** + * Count auto_mode attachments since the last auto_mode_exit (or from start if no exit). + * This ensures the full/sparse cycle resets when re-entering auto mode. + */ +function countAutoModeAttachmentsSinceLastExit(messages: Message[]): number { + let count = 0 + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + if (message?.type === 'attachment') { + if (message.attachment.type === 'auto_mode_exit') { + break + } + if (message.attachment.type === 'auto_mode') { + count++ + } + } + } + return count +} + +async function getAutoModeAttachments( + messages: Message[] | undefined, + toolUseContext: ToolUseContext, +): Promise { + const appState = toolUseContext.getAppState() + const permissionContext = appState.toolPermissionContext + const inAuto = permissionContext.mode === 'auto' + const inPlanWithAuto = + permissionContext.mode === 'plan' && + (autoModeStateModule?.isAutoModeActive() ?? false) + if (!inAuto && !inPlanWithAuto) { + return [] + } + + // Check if we should attach based on turn count (except for first turn) + if (messages && messages.length > 0) { + const { turnCount, foundAutoModeAttachment } = + getAutoModeAttachmentTurnCount(messages) + // Only throttle if we've already sent an auto_mode attachment before + // On first turn in auto mode, always attach + if ( + foundAutoModeAttachment && + turnCount < AUTO_MODE_ATTACHMENT_CONFIG.TURNS_BETWEEN_ATTACHMENTS + ) { + return [] + } + } + + // Determine if this should be a full or sparse reminder + const attachmentCount = + countAutoModeAttachmentsSinceLastExit(messages ?? []) + 1 + const reminderType: 'full' | 'sparse' = + attachmentCount % + AUTO_MODE_ATTACHMENT_CONFIG.FULL_REMINDER_EVERY_N_ATTACHMENTS === + 1 + ? 'full' + : 'sparse' + + return [{ type: 'auto_mode', reminderType }] +} + +/** + * Returns an auto_mode_exit attachment if we just exited auto mode. + * This is a one-time notification to tell the model it's no longer in auto mode. + */ +async function getAutoModeExitAttachment( + toolUseContext: ToolUseContext, +): Promise { + if (!needsAutoModeExitAttachment()) { + return [] + } + + const appState = toolUseContext.getAppState() + // Suppress when auto is still active — covers both mode==='auto' and + // plan-with-auto-active (where mode==='plan' but classifier runs). + if ( + appState.toolPermissionContext.mode === 'auto' || + (autoModeStateModule?.isAutoModeActive() ?? false) + ) { + setNeedsAutoModeExitAttachment(false) + return [] + } + + setNeedsAutoModeExitAttachment(false) + return [{ type: 'auto_mode_exit' }] +} + +/** + * Detects when the local date has changed since the last turn (user coding + * past midnight) and emits an attachment to notify the model. + * + * The date_change attachment is appended at the tail of the conversation, + * so the model learns the new date without mutating the cached prefix. + * messages[0] (from getUserContext → prependUserContext) intentionally + * keeps the stale date — clearing that cache would regenerate the prefix + * and turn the entire conversation into cache_creation on the next turn + * (~920K effective tokens per midnight crossing per overnight session). + * + * Exported for testing — regression guard for the cache-clear removal. + */ +export function getDateChangeAttachments( + messages: Message[] | undefined, +): Attachment[] { + const currentDate = getLocalISODate() + const lastDate = getLastEmittedDate() + + if (lastDate === null) { + // First turn — just record, no attachment needed + setLastEmittedDate(currentDate) + return [] + } + + if (currentDate === lastDate) { + return [] + } + + setLastEmittedDate(currentDate) + + // Assistant mode: flush yesterday's transcript to the per-day file so + // the /dream skill (1–5am local) finds it even if no compaction fires + // today. Fire-and-forget; writeSessionTranscriptSegment buckets by + // message timestamp so a multi-day gap flushes each day correctly. + if (feature('KAIROS')) { + if (getKairosActive() && messages !== undefined) { + sessionTranscriptModule?.flushOnDateChange(messages, currentDate) + } + } + + return [{ type: 'date_change', newDate: currentDate }] +} + +function getUltrathinkEffortAttachment(input: string | null): Attachment[] { + if (!isUltrathinkEnabled() || !input || !hasUltrathinkKeyword(input)) { + return [] + } + logEvent('tengu_ultrathink', {}) + return [{ type: 'ultrathink_effort', level: 'high' }] +} + +// Exported for compact.ts — the gate must be identical at both call sites. +export function getDeferredToolsDeltaAttachment( + tools: Tools, + model: string, + messages: Message[] | undefined, + scanContext?: DeferredToolsDeltaScanContext, +): Attachment[] { + if (!isDeferredToolsDeltaEnabled()) return [] + // These three checks mirror the sync parts of isToolSearchEnabled — + // the attachment text says "available via ToolSearch", so ToolSearch + // has to actually be in the request. The async auto-threshold check + // is not replicated (would double-fire tengu_tool_search_mode_decision); + // in tst-auto below-threshold the attachment can fire while ToolSearch + // is filtered out, but that's a narrow case and the tools announced + // are directly callable anyway. + if (!isToolSearchEnabledOptimistic()) return [] + if (!modelSupportsToolReference(model)) return [] + if (!isToolSearchToolAvailable(tools)) return [] + const delta = getDeferredToolsDelta(tools, messages ?? [], scanContext) + if (!delta) return [] + return [{ type: 'deferred_tools_delta', ...delta }] +} + +/** + * Diff the current filtered agent pool against what's already been announced + * in this conversation (reconstructed from prior agent_listing_delta + * attachments). Returns [] if nothing changed or the gate is off. + * + * The agent list was embedded in AgentTool's description, causing ~10.2% of + * fleet cache_creation: MCP async connect, /reload-plugins, or + * permission-mode change → description changes → full tool-schema cache bust. + * Moving the list here keeps the tool description static. + * + * Exported for compact.ts — re-announces the full set after compaction eats + * prior deltas. + */ +export function getAgentListingDeltaAttachment( + toolUseContext: ToolUseContext, + messages: Message[] | undefined, +): Attachment[] { + if (!shouldInjectAgentListInMessages()) return [] + + // Skip if AgentTool isn't in the pool — the listing would be unactionable. + if ( + !toolUseContext.options.tools.some(t => toolMatchesName(t, AGENT_TOOL_NAME)) + ) { + return [] + } + + const { activeAgents, allowedAgentTypes } = + toolUseContext.options.agentDefinitions + + // Mirror AgentTool.prompt()'s filtering: MCP requirements → deny rules → + // allowedAgentTypes restriction. Keep this in sync with AgentTool.tsx. + const mcpServers = new Set() + for (const tool of toolUseContext.options.tools) { + const info = mcpInfoFromString(tool.name) + if (info) mcpServers.add(info.serverName) + } + const permissionContext = toolUseContext.getAppState().toolPermissionContext + let filtered = filterDeniedAgents( + filterAgentsByMcpRequirements(activeAgents, [...mcpServers]), + permissionContext, + AGENT_TOOL_NAME, + ) + if (allowedAgentTypes) { + filtered = filtered.filter(a => allowedAgentTypes.includes(a.agentType)) + } + + // Reconstruct announced set from prior deltas in the transcript. + const announced = new Set() + for (const msg of messages ?? []) { + if (msg.type !== 'attachment') continue + if (msg.attachment.type !== 'agent_listing_delta') continue + for (const t of msg.attachment.addedTypes) announced.add(t) + for (const t of msg.attachment.removedTypes) announced.delete(t) + } + + const currentTypes = new Set(filtered.map(a => a.agentType)) + const added = filtered.filter(a => !announced.has(a.agentType)) + const removed: string[] = [] + for (const t of announced) { + if (!currentTypes.has(t)) removed.push(t) + } + + if (added.length === 0 && removed.length === 0) return [] + + // Sort for deterministic output — agent load order is nondeterministic + // (plugin load races, MCP async connect). + added.sort((a, b) => a.agentType.localeCompare(b.agentType)) + removed.sort() + + return [ + { + type: 'agent_listing_delta', + addedTypes: added.map(a => a.agentType), + addedLines: added.map(formatAgentLine), + removedTypes: removed, + isInitial: announced.size === 0, + showConcurrencyNote: getSubscriptionType() !== 'pro', + }, + ] +} + +// Exported for compact.ts / reactiveCompact.ts — single source of truth for the gate. +export function getMcpInstructionsDeltaAttachment( + mcpClients: MCPServerConnection[], + tools: Tools, + model: string, + messages: Message[] | undefined, +): Attachment[] { + if (!isMcpInstructionsDeltaEnabled()) return [] + + // The chrome ToolSearch hint is client-authored and ToolSearch-conditional; + // actual server `instructions` are unconditional. Decide the chrome part + // here, pass it into the pure diff as a synthesized entry. + const clientSide: ClientSideInstruction[] = [] + if ( + isToolSearchEnabledOptimistic() && + modelSupportsToolReference(model) && + isToolSearchToolAvailable(tools) + ) { + clientSide.push({ + serverName: CLAUDE_IN_CHROME_MCP_SERVER_NAME, + block: CHROME_TOOL_SEARCH_INSTRUCTIONS, + }) + } + + const delta = getMcpInstructionsDelta(mcpClients, messages ?? [], clientSide) + if (!delta) return [] + return [{ type: 'mcp_instructions_delta', ...delta }] +} + +function getCriticalSystemReminderAttachment( + toolUseContext: ToolUseContext, +): Attachment[] { + const reminder = toolUseContext.criticalSystemReminder_EXPERIMENTAL + if (!reminder) { + return [] + } + return [{ type: 'critical_system_reminder', content: reminder }] +} + +function getOutputStyleAttachment(): Attachment[] { + const settings = getSettings_DEPRECATED() + const outputStyle = settings?.outputStyle || 'default' + + // Only show for non-default styles + if (outputStyle === 'default') { + return [] + } + + return [ + { + type: 'output_style', + style: outputStyle, + }, + ] +} + +async function getSelectedLinesFromIDE( + ideSelection: IDESelection | null, + toolUseContext: ToolUseContext, +): Promise { + const ideName = getConnectedIdeName(toolUseContext.options.mcpClients) + if ( + !ideName || + ideSelection?.lineStart === undefined || + !ideSelection.text || + !ideSelection.filePath + ) { + return [] + } + + const appState = toolUseContext.getAppState() + if (isFileReadDenied(ideSelection.filePath, appState.toolPermissionContext)) { + return [] + } + + return [ + { + type: 'selected_lines_in_ide', + ideName, + lineStart: ideSelection.lineStart, + lineEnd: ideSelection.lineStart + ideSelection.lineCount - 1, + filename: ideSelection.filePath, + content: ideSelection.text, + displayPath: relative(getCwd(), ideSelection.filePath), + }, + ] +} + +/** + * Computes the directories to process for nested memory file loading. + * Returns two lists: + * - nestedDirs: Directories between CWD and targetPath (processed for CLAUDE.md + all rules) + * - cwdLevelDirs: Directories from root to CWD (processed for conditional rules only) + * + * @param targetPath The target file path + * @param originalCwd The original current working directory + * @returns Object with nestedDirs and cwdLevelDirs arrays, both ordered from parent to child + */ +export function getDirectoriesToProcess( + targetPath: string, + originalCwd: string, +): { nestedDirs: string[]; cwdLevelDirs: string[] } { + // Build list of directories from original CWD to targetPath's directory + const targetDir = dirname(resolve(targetPath)) + const nestedDirs: string[] = [] + let currentDir = targetDir + + // Walk up from target directory to original CWD + while (currentDir !== originalCwd && currentDir !== parse(currentDir).root) { + if (currentDir.startsWith(originalCwd)) { + nestedDirs.push(currentDir) + } + currentDir = dirname(currentDir) + } + + // Reverse to get order from CWD down to target + nestedDirs.reverse() + + // Build list of directories from root to CWD (for conditional rules only) + const cwdLevelDirs: string[] = [] + currentDir = originalCwd + + while (currentDir !== parse(currentDir).root) { + cwdLevelDirs.push(currentDir) + currentDir = dirname(currentDir) + } + + // Reverse to get order from root to CWD + cwdLevelDirs.reverse() + + return { nestedDirs, cwdLevelDirs } +} + +/** + * Converts memory files to attachments, filtering out already-loaded files. + * + * @param memoryFiles The memory files to convert + * @param toolUseContext The tool use context (for tracking loaded files) + * @returns Array of nested memory attachments + */ +function isInstructionsMemoryType( + type: MemoryFileInfo['type'], +): type is InstructionsMemoryType { + return ( + type === 'User' || + type === 'Project' || + type === 'Local' || + type === 'Managed' + ) +} + +/** Exported for testing — regression guard for LRU-eviction re-injection. */ +export function memoryFilesToAttachments( + memoryFiles: MemoryFileInfo[], + toolUseContext: ToolUseContext, + triggerFilePath?: string, +): Attachment[] { + const attachments: Attachment[] = [] + const shouldFireHook = hasInstructionsLoadedHook() + + for (const memoryFile of memoryFiles) { + // Dedup: loadedNestedMemoryPaths is a non-evicting Set; readFileState + // is a 100-entry LRU that drops entries in busy sessions, so relying + // on it alone re-injects the same CLAUDE.md on every eviction cycle. + if (toolUseContext.loadedNestedMemoryPaths?.has(memoryFile.path)) { + continue + } + if (!toolUseContext.readFileState.has(memoryFile.path)) { + attachments.push({ + type: 'nested_memory', + path: memoryFile.path, + content: memoryFile, + displayPath: relative(getCwd(), memoryFile.path), + }) + toolUseContext.loadedNestedMemoryPaths?.add(memoryFile.path) + + // Mark as loaded in readFileState — this provides cross-function and + // cross-turn dedup via the .has() check above. + // + // When the injected content doesn't match disk (stripped HTML comments, + // stripped frontmatter, truncated MEMORY.md), cache the RAW disk bytes + // with `isPartialView: true`. Edit/Write see the flag and require a real + // Read first; getChangedFiles sees real content + undefined offset/limit + // so mid-session change detection still works. + toolUseContext.readFileState.set(memoryFile.path, { + content: memoryFile.contentDiffersFromDisk + ? (memoryFile.rawContent ?? memoryFile.content) + : memoryFile.content, + timestamp: Date.now(), + offset: undefined, + limit: undefined, + isPartialView: memoryFile.contentDiffersFromDisk, + }) + + + // Fire InstructionsLoaded hook for audit/observability (fire-and-forget) + if (shouldFireHook && isInstructionsMemoryType(memoryFile.type)) { + const loadReason = memoryFile.globs + ? 'path_glob_match' + : memoryFile.parent + ? 'include' + : 'nested_traversal' + void executeInstructionsLoadedHooks( + memoryFile.path, + memoryFile.type, + loadReason, + { + globs: memoryFile.globs, + triggerFilePath, + parentFilePath: memoryFile.parent, + }, + ) + } + } + } + + return attachments +} + +/** + * Loads nested memory files for a given file path and returns them as attachments. + * This function performs directory traversal to find CLAUDE.md files and conditional rules + * that apply to the target file path. + * + * Processing order (must be preserved): + * 1. Managed/User conditional rules matching targetPath + * 2. Nested directories (CWD → target): CLAUDE.md + unconditional + conditional rules + * 3. CWD-level directories (root → CWD): conditional rules only + * + * @param filePath The file path to get nested memory files for + * @param toolUseContext The tool use context + * @param appState The app state containing tool permission context + * @returns Array of nested memory attachments + */ +async function getNestedMemoryAttachmentsForFile( + filePath: string, + toolUseContext: ToolUseContext, + appState: { toolPermissionContext: ToolPermissionContext }, +): Promise { + const attachments: Attachment[] = [] + + try { + // Early return if path is not in allowed working path + if (!pathInAllowedWorkingPath(filePath, appState.toolPermissionContext)) { + return attachments + } + + const processedPaths = new Set() + const originalCwd = getOriginalCwd() + + // Phase 1: Process Managed and User conditional rules + const managedUserRules = await getManagedAndUserConditionalRules( + filePath, + processedPaths, + ) + attachments.push( + ...memoryFilesToAttachments(managedUserRules, toolUseContext, filePath), + ) + + // Phase 2: Get directories to process + const { nestedDirs, cwdLevelDirs } = getDirectoriesToProcess( + filePath, + originalCwd, + ) + + const skipProjectLevel = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_paper_halyard', + false, + ) + + // Phase 3: Process nested directories (CWD → target) + // Each directory gets: CLAUDE.md + unconditional rules + conditional rules + for (const dir of nestedDirs) { + const memoryFiles = ( + await getMemoryFilesForNestedDirectory(dir, filePath, processedPaths) + ).filter( + f => !skipProjectLevel || (f.type !== 'Project' && f.type !== 'Local'), + ) + attachments.push( + ...memoryFilesToAttachments(memoryFiles, toolUseContext, filePath), + ) + } + + // Phase 4: Process CWD-level directories (root → CWD) + // Only conditional rules (unconditional rules are already loaded eagerly) + for (const dir of cwdLevelDirs) { + const conditionalRules = ( + await getConditionalRulesForCwdLevelDirectory( + dir, + filePath, + processedPaths, + ) + ).filter( + f => !skipProjectLevel || (f.type !== 'Project' && f.type !== 'Local'), + ) + attachments.push( + ...memoryFilesToAttachments(conditionalRules, toolUseContext, filePath), + ) + } + } catch (error) { + logError(error) + } + + return attachments +} + +async function getOpenedFileFromIDE( + ideSelection: IDESelection | null, + toolUseContext: ToolUseContext, +): Promise { + if (!ideSelection?.filePath || ideSelection.text) { + return [] + } + + const appState = toolUseContext.getAppState() + if (isFileReadDenied(ideSelection.filePath, appState.toolPermissionContext)) { + return [] + } + + // Get nested memory files + const nestedMemoryAttachments = await getNestedMemoryAttachmentsForFile( + ideSelection.filePath, + toolUseContext, + appState, + ) + + // Return nested memory attachments followed by the opened file attachment + return [ + ...nestedMemoryAttachments, + { + type: 'opened_file_in_ide', + filename: ideSelection.filePath, + }, + ] +} + +async function processAtMentionedFiles( + input: string, + toolUseContext: ToolUseContext, +): Promise { + const files = extractAtMentionedFiles(input) + if (files.length === 0) return [] + + const appState = toolUseContext.getAppState() + const results = await Promise.all( + files.map(async file => { + try { + const { filename, lineStart, lineEnd } = parseAtMentionedFileLines(file) + const absoluteFilename = expandPath(filename) + + if ( + isFileReadDenied(absoluteFilename, appState.toolPermissionContext) + ) { + return null + } + + // Check if it's a directory + try { + const stats = await stat(absoluteFilename) + if (stats.isDirectory()) { + try { + const entries = await readdir(absoluteFilename, { + withFileTypes: true, + }) + const MAX_DIR_ENTRIES = 1000 + const truncated = entries.length > MAX_DIR_ENTRIES + const names = entries.slice(0, MAX_DIR_ENTRIES).map(e => e.name) + if (truncated) { + names.push( + `\u2026 and ${entries.length - MAX_DIR_ENTRIES} more entries`, + ) + } + const stdout = names.join('\n') + logEvent('tengu_at_mention_extracting_directory_success', {}) + + return { + type: 'directory' as const, + path: absoluteFilename, + content: stdout, + displayPath: relative(getCwd(), absoluteFilename), + } + } catch { + return null + } + } + } catch { + // If stat fails, continue with file logic + } + + return await generateFileAttachment( + absoluteFilename, + toolUseContext, + 'tengu_at_mention_extracting_filename_success', + 'tengu_at_mention_extracting_filename_error', + 'at-mention', + { + offset: lineStart, + limit: lineEnd && lineStart ? lineEnd - lineStart + 1 : undefined, + }, + ) + } catch { + logEvent('tengu_at_mention_extracting_filename_error', {}) + } + }), + ) + return results.filter(Boolean) as Attachment[] +} + +function processAgentMentions( + input: string, + agents: AgentDefinition[], +): Attachment[] { + const agentMentions = extractAgentMentions(input) + if (agentMentions.length === 0) return [] + + const results = agentMentions.map(mention => { + const agentType = mention.replace('agent-', '') + const agentDef = agents.find(def => def.agentType === agentType) + + if (!agentDef) { + logEvent('tengu_at_mention_agent_not_found', {}) + return null + } + + logEvent('tengu_at_mention_agent_success', {}) + + return { + type: 'agent_mention' as const, + agentType: agentDef.agentType, + } + }) + + return results.filter( + (result): result is NonNullable => result !== null, + ) +} + +async function processMcpResourceAttachments( + input: string, + toolUseContext: ToolUseContext, +): Promise { + const resourceMentions = extractMcpResourceMentions(input) + if (resourceMentions.length === 0) return [] + + const mcpClients = toolUseContext.options.mcpClients || [] + + const results = await Promise.all( + resourceMentions.map(async mention => { + try { + const [serverName, ...uriParts] = mention.split(':') + const uri = uriParts.join(':') // Rejoin in case URI contains colons + + if (!serverName || !uri) { + logEvent('tengu_at_mention_mcp_resource_error', {}) + return null + } + + // Find the MCP client + const client = mcpClients.find(c => c.name === serverName) + if (!client || client.type !== 'connected') { + logEvent('tengu_at_mention_mcp_resource_error', {}) + return null + } + + // Find the resource in available resources to get its metadata + const serverResources = + toolUseContext.options.mcpResources?.[serverName] || [] + const resourceInfo = serverResources.find(r => r.uri === uri) + if (!resourceInfo) { + logEvent('tengu_at_mention_mcp_resource_error', {}) + return null + } + + try { + const result = await client.client.readResource({ + uri, + }) + + logEvent('tengu_at_mention_mcp_resource_success', {}) + + return { + type: 'mcp_resource' as const, + server: serverName, + uri, + name: resourceInfo.name || uri, + description: resourceInfo.description, + content: result, + } + } catch (error) { + logEvent('tengu_at_mention_mcp_resource_error', {}) + logError(error) + return null + } + } catch { + logEvent('tengu_at_mention_mcp_resource_error', {}) + return null + } + }), + ) + + return results.filter( + (result): result is NonNullable => result !== null, + ) as Attachment[] +} + +export async function getChangedFiles( + toolUseContext: ToolUseContext, +): Promise { + const filePaths = cacheKeys(toolUseContext.readFileState) + if (filePaths.length === 0) return [] + + const appState = toolUseContext.getAppState() + const results = await Promise.all( + filePaths.map(async filePath => { + const fileState = toolUseContext.readFileState.get(filePath) + if (!fileState) return null + + // TODO: Implement offset/limit support for changed files + if (fileState.offset !== undefined || fileState.limit !== undefined) { + return null + } + + const normalizedPath = expandPath(filePath) + + // Check if file has a deny rule configured + if (isFileReadDenied(normalizedPath, appState.toolPermissionContext)) { + return null + } + + try { + const mtime = await getFileModificationTimeAsync(normalizedPath) + if (mtime <= fileState.timestamp) { + return null + } + + const fileInput = { file_path: normalizedPath } + + // Validate file path is valid + const isValid = await FileReadTool.validateInput( + fileInput, + toolUseContext, + ) + if (!isValid.result) { + return null + } + + const result = await FileReadTool.call(fileInput, toolUseContext) + // Extract only the changed section + if (result.data.type === 'text') { + const snippet = getSnippetForTwoFileDiff( + fileState.content, + result.data.file.content, + ) + + // File was touched but not modified + if (snippet === '') { + return null + } + + return { + type: 'edited_text_file' as const, + filename: normalizedPath, + snippet, + } + } + + // For non-text files (images), apply the same token limit logic as FileReadTool + if (result.data.type === 'image') { + try { + const data = await readImageWithTokenBudget(normalizedPath) + return { + type: 'edited_image_file' as const, + filename: normalizedPath, + content: data, + } + } catch (compressionError) { + logError(compressionError) + logEvent('tengu_watched_file_compression_failed', { + file: normalizedPath, + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) + return null + } + } + + // notebook / pdf / parts — no diff representation; explicitly + // null so the map callback has no implicit-undefined path. + return null + } catch (err) { + // Evict ONLY on ENOENT (file truly deleted). Transient stat + // failures — atomic-save races (editor writes tmp→rename and + // stat hits the gap), EACCES churn, network-FS hiccups — must + // NOT evict, or the next Edit fails code-6 even though the + // file still exists and the model just read it. VS Code + // auto-save/format-on-save hits this race especially often. + // See regression analysis on PR #18525. + if (isENOENT(err)) { + toolUseContext.readFileState.delete(filePath) + } + return null + } + }), + ) + return results.filter(result => result != null) as Attachment[] +} + +/** + * Processes paths that need nested memory attachments and checks for nested CLAUDE.md files + * Uses nestedMemoryAttachmentTriggers field from ToolUseContext + */ +async function getNestedMemoryAttachments( + toolUseContext: ToolUseContext, +): Promise { + // Check triggers first — getAppState() waits for a React render cycle, + // and the common case is an empty trigger set. + if ( + !toolUseContext.nestedMemoryAttachmentTriggers || + toolUseContext.nestedMemoryAttachmentTriggers.size === 0 + ) { + return [] + } + + const appState = toolUseContext.getAppState() + const attachments: Attachment[] = [] + + for (const filePath of toolUseContext.nestedMemoryAttachmentTriggers) { + const nestedAttachments = await getNestedMemoryAttachmentsForFile( + filePath, + toolUseContext, + appState, + ) + attachments.push(...nestedAttachments) + } + + toolUseContext.nestedMemoryAttachmentTriggers.clear() + + return attachments +} + +async function getRelevantMemoryAttachments( + input: string, + agents: AgentDefinition[], + readFileState: FileStateCache, + recentTools: readonly string[], + signal: AbortSignal, + alreadySurfaced: ReadonlySet, +): Promise { + // If an agent is @-mentioned, search only its memory dir (isolation). + // Otherwise search the auto-memory dir. + const memoryDirs = extractAgentMentions(input).flatMap(mention => { + const agentType = mention.replace('agent-', '') + const agentDef = agents.find(def => def.agentType === agentType) + return agentDef?.memory + ? [getAgentMemoryDir(agentType, agentDef.memory)] + : [] + }) + const dirs = memoryDirs.length > 0 ? memoryDirs : [getAutoMemPath()] + + const allResults = await Promise.all( + dirs.map(dir => + findRelevantMemories( + input, + dir, + signal, + recentTools, + alreadySurfaced, + ).catch(() => []), + ), + ) + // alreadySurfaced is filtered inside the selector so Sonnet spends its + // 5-slot budget on fresh candidates; readFileState catches files the + // model read via FileReadTool. The redundant alreadySurfaced check here + // is a belt-and-suspenders guard (multi-dir results may re-introduce a + // path the selector filtered in a different dir). + const selected = allResults + .flat() + .filter(m => !readFileState.has(m.path) && !alreadySurfaced.has(m.path)) + .slice(0, 5) + + const memories = await readMemoriesForSurfacing(selected, signal) + + if (memories.length === 0) { + return [] + } + return [{ type: 'relevant_memories' as const, memories }] +} + +/** + * Scan messages for past relevant_memories attachments. Returns both the + * set of surfaced paths (for selector de-dup) and cumulative byte count + * (for session-total throttle). Scanning messages rather than tracking + * in toolUseContext means compact naturally resets both — old attachments + * are gone from the compacted transcript, so re-surfacing is valid again. + */ +export function collectSurfacedMemories(messages: ReadonlyArray): { + paths: Set + totalBytes: number +} { + const paths = new Set() + let totalBytes = 0 + for (const m of messages) { + if (m.type === 'attachment' && m.attachment.type === 'relevant_memories') { + for (const mem of m.attachment.memories) { + paths.add(mem.path) + totalBytes += mem.content.length + } + } + } + return { paths, totalBytes } +} + +/** + * Reads a set of relevance-ranked memory files for injection as + * attachments. Enforces both MAX_MEMORY_LINES and + * MAX_MEMORY_BYTES via readFileInRange's truncateOnByteLimit option. + * Truncation surfaces partial + * content with a note rather than dropping the file — findRelevantMemories + * already picked this as most-relevant, so the frontmatter + opening context + * is worth surfacing even if later lines are cut. + * + * Exported for direct testing without mocking the ranker + GB gates. + */ +export async function readMemoriesForSurfacing( + selected: ReadonlyArray<{ path: string; mtimeMs: number }>, + signal?: AbortSignal, +): Promise< + Array<{ + path: string + content: string + mtimeMs: number + header: string + limit?: number + }> +> { + const results = await Promise.all( + selected.map(async ({ path: filePath, mtimeMs }) => { + try { + const result = await readFileInRange( + filePath, + 0, + MAX_MEMORY_LINES, + MAX_MEMORY_BYTES, + signal, + { truncateOnByteLimit: true }, + ) + const truncated = + result.totalLines > MAX_MEMORY_LINES || result.truncatedByBytes + const content = truncated + ? result.content + + `\n\n> This memory file was truncated (${result.truncatedByBytes ? `${MAX_MEMORY_BYTES} byte limit` : `first ${MAX_MEMORY_LINES} lines`}). Use the ${FILE_READ_TOOL_NAME} tool to view the complete file at: ${filePath}` + : result.content + return { + path: filePath, + content, + mtimeMs, + header: memoryHeader(filePath, mtimeMs), + limit: truncated ? result.lineCount : undefined, + } + } catch { + return null + } + }), + ) + return results.filter(r => r !== null) +} + +/** + * Header string for a relevant-memory block. Exported so messages.ts + * can fall back for resumed sessions where the stored header is missing. + */ +export function memoryHeader(path: string, mtimeMs: number): string { + const staleness = memoryFreshnessText(mtimeMs) + return staleness + ? `${staleness}\n\nMemory: ${path}:` + : `Memory (saved ${memoryAge(mtimeMs)}): ${path}:` +} + +/** + * A memory relevance-selector prefetch handle. The promise is started once + * per user turn and runs while the main model streams and tools execute. + * At the collect point (post-tools), the caller reads settledAt to + * consume-if-ready or skip-and-retry-next-iteration — the prefetch never + * blocks the turn. + * + * Disposable: query.ts binds with `using`, so [Symbol.dispose] fires on all + * generator exit paths (return, throw, .return() closure) — aborting the + * in-flight request and emitting terminal telemetry without instrumenting + * each of the ~13 return sites inside the while loop. + */ +export type MemoryPrefetch = { + promise: Promise + /** Set by promise.finally(). null until the promise settles. */ + settledAt: number | null + /** Set by the collect point in query.ts. -1 until consumed. */ + consumedOnIteration: number + [Symbol.dispose](): void +} + +/** + * Starts the relevant memory search as an async prefetch. + * Extracts the last real user prompt from messages (skipping isMeta system + * injections) and kicks off a non-blocking search. Returns a Disposable + * handle with settlement tracking. Bound with `using` in query.ts. + */ +export function startRelevantMemoryPrefetch( + messages: ReadonlyArray, + toolUseContext: ToolUseContext, +): MemoryPrefetch | undefined { + if ( + !isAutoMemoryEnabled() || + !getFeatureValue_CACHED_MAY_BE_STALE('tengu_moth_copse', false) + ) { + return undefined + } + + const lastUserMessage = messages.findLast(m => m.type === 'user' && !m.isMeta) + if (!lastUserMessage) { + return undefined + } + + const input = getUserMessageText(lastUserMessage) + // Single-word prompts lack enough context for meaningful term extraction + if (!input || !/\s/.test(input.trim())) { + return undefined + } + + const surfaced = collectSurfacedMemories(messages) + if (surfaced.totalBytes >= RELEVANT_MEMORIES_CONFIG.MAX_SESSION_BYTES) { + return undefined + } + + // Chained to the turn-level abort so user Escape cancels the sideQuery + // immediately, not just on [Symbol.dispose] when queryLoop exits. + const controller = createChildAbortController(toolUseContext.abortController) + const firedAt = Date.now() + const promise = getRelevantMemoryAttachments( + input, + toolUseContext.options.agentDefinitions.activeAgents, + toolUseContext.readFileState, + collectRecentSuccessfulTools(messages, lastUserMessage), + controller.signal, + surfaced.paths, + ).catch(e => { + if (!isAbortError(e)) { + logError(e) + } + return [] + }) + + const handle: MemoryPrefetch = { + promise, + settledAt: null, + consumedOnIteration: -1, + [Symbol.dispose]() { + controller.abort() + logEvent('tengu_memdir_prefetch_collected', { + hidden_by_first_iteration: + handle.settledAt !== null && handle.consumedOnIteration === 0, + consumed_on_iteration: handle.consumedOnIteration, + latency_ms: (handle.settledAt ?? Date.now()) - firedAt, + }) + }, + } + void promise.finally(() => { + handle.settledAt = Date.now() + }) + return handle +} + +type ToolResultBlock = { + type: 'tool_result' + tool_use_id: string + is_error?: boolean +} + +function isToolResultBlock(b: unknown): b is ToolResultBlock { + return ( + typeof b === 'object' && + b !== null && + (b as ToolResultBlock).type === 'tool_result' && + typeof (b as ToolResultBlock).tool_use_id === 'string' + ) +} + +/** + * Check whether a user message's content contains tool_result blocks. + * This is more reliable than checking `toolUseResult === undefined` because + * sub-agent tool result messages explicitly set `toolUseResult` to `undefined` + * when `preserveToolUseResults` is false (the default for Explore agents). + */ +function hasToolResultContent(content: unknown): boolean { + return Array.isArray(content) && content.some(isToolResultBlock) +} + +/** + * Tools that succeeded (and never errored) since the previous real turn + * boundary. The memory selector uses this to suppress docs about tools + * that are working — surfacing reference material for a tool the model + * is already calling successfully is noise. + * + * Any error → tool excluded (model is struggling, docs stay available). + * No result yet → also excluded (outcome unknown). + * + * tool_use lives in assistant content; tool_result in user content + * (toolUseResult set, isMeta undefined). Both are within the scan window. + * Backward scan sees results before uses so we collect both by id and + * resolve after. + */ +export function collectRecentSuccessfulTools( + messages: ReadonlyArray, + lastUserMessage: Message, +): readonly string[] { + const useIdToName = new Map() + const resultByUseId = new Map() + for (let i = messages.length - 1; i >= 0; i--) { + const m = messages[i] + if (!m) continue + if (isHumanTurn(m) && m !== lastUserMessage) break + if (m.type === 'assistant' && typeof m.message.content !== 'string') { + for (const block of m.message.content) { + if (block.type === 'tool_use') useIdToName.set(block.id, block.name) + } + } else if ( + m.type === 'user' && + 'message' in m && + Array.isArray(m.message.content) + ) { + for (const block of m.message.content) { + if (isToolResultBlock(block)) { + resultByUseId.set(block.tool_use_id, block.is_error === true) + } + } + } + } + const failed = new Set() + const succeeded = new Set() + for (const [id, name] of useIdToName) { + const errored = resultByUseId.get(id) + if (errored === undefined) continue + if (errored) { + failed.add(name) + } else { + succeeded.add(name) + } + } + return [...succeeded].filter(t => !failed.has(t)) +} + + +/** + * Filters prefetched memory attachments to exclude memories the model already + * has in context via FileRead/Write/Edit tool calls (any iteration this turn) + * or a previous turn's memory surfacing — both tracked in the cumulative + * readFileState. Survivors are then marked in readFileState so subsequent + * turns won't re-surface them. + * + * The mark-after-filter ordering is load-bearing: readMemoriesForSurfacing + * used to write to readFileState during the prefetch, which meant the filter + * saw every prefetch-selected path as "already in context" and dropped them + * all (self-referential filter). Deferring the write to here, after the + * filter runs, breaks that cycle while still deduping against tool calls + * from any iteration. + */ +export function filterDuplicateMemoryAttachments( + attachments: Attachment[], + readFileState: FileStateCache, +): Attachment[] { + return attachments + .map(attachment => { + if (attachment.type !== 'relevant_memories') return attachment + const filtered = attachment.memories.filter( + m => !readFileState.has(m.path), + ) + for (const m of filtered) { + readFileState.set(m.path, { + content: m.content, + timestamp: m.mtimeMs, + offset: undefined, + limit: m.limit, + }) + } + return filtered.length > 0 ? { ...attachment, memories: filtered } : null + }) + .filter((a): a is Attachment => a !== null) +} + +/** + * Processes skill directories that were discovered during file operations. + * Uses dynamicSkillDirTriggers field from ToolUseContext + */ +async function getDynamicSkillAttachments( + toolUseContext: ToolUseContext, +): Promise { + const attachments: Attachment[] = [] + + if ( + toolUseContext.dynamicSkillDirTriggers && + toolUseContext.dynamicSkillDirTriggers.size > 0 + ) { + // Parallelize: readdir all skill dirs concurrently + const perDirResults = await Promise.all( + Array.from(toolUseContext.dynamicSkillDirTriggers).map(async skillDir => { + try { + const entries = await readdir(skillDir, { withFileTypes: true }) + const candidates = entries + .filter(e => e.isDirectory() || e.isSymbolicLink()) + .map(e => e.name) + // Parallelize: stat all SKILL.md candidates concurrently + const checked = await Promise.all( + candidates.map(async name => { + try { + await stat(resolve(skillDir, name, 'SKILL.md')) + return name + } catch { + return null // SKILL.md doesn't exist, skip this entry + } + }), + ) + return { + skillDir, + skillNames: checked.filter((n): n is string => n !== null), + } + } catch { + // Ignore errors reading skill directories (e.g., directory doesn't exist) + return { skillDir, skillNames: [] } + } + }), + ) + + for (const { skillDir, skillNames } of perDirResults) { + if (skillNames.length > 0) { + attachments.push({ + type: 'dynamic_skill', + skillDir, + skillNames, + displayPath: relative(getCwd(), skillDir), + }) + } + } + + toolUseContext.dynamicSkillDirTriggers.clear() + } + + return attachments +} + +// Track which skills have been sent to avoid re-sending. Keyed by agentId +// (empty string = main thread) so subagents get their own turn-0 listing — +// without per-agent scoping, the main thread populating this Set would cause +// every subagent's filterToBundledAndMcp result to dedup to empty. +const sentSkillNames = new Map>() + +// Called when the skill set genuinely changes (plugin reload, skill file +// change on disk) so new skills get announced. NOT called on compact — +// post-compact re-injection costs ~4K tokens/event for marginal benefit. +export function resetSentSkillNames(): void { + sentSkillNames.clear() + suppressNext = false +} + +/** + * Suppress the next skill-listing injection. Called by conversationRecovery + * on --resume when a skill_listing attachment already exists in the + * transcript. + * + * `sentSkillNames` is module-scope — process-local. Each `claude -p` spawn + * starts with an empty Map, so without this every resume re-injects the + * full ~600-token listing even though it's already in the conversation from + * the prior process. Shows up on every --resume; particularly loud for + * daemons that respawn frequently. + * + * Trade-off: skills added between sessions won't be announced until the + * next non-resume session. Acceptable — skill_listing was never meant to + * cover cross-process deltas, and the agent can still call them (they're + * in the Skill tool's runtime registry regardless). + */ +export function suppressNextSkillListing(): void { + suppressNext = true +} +let suppressNext = false + +// When skill-search is enabled and the filtered (bundled + MCP) listing exceeds +// this count, fall back to bundled-only. Protects MCP-heavy users (100+ servers) +// from truncation while keeping the turn-0 guarantee for typical setups. +const FILTERED_LISTING_MAX = 30 + +/** + * Filter skills to bundled (Anthropic-curated) + MCP (user-connected) only. + * Used when skill-search is enabled to resolve the turn-0 gap for subagents: + * these sources are small, intent-signaled, and won't hit the truncation budget. + * User/project/plugin skills (the long tail — 200+) go through discovery instead. + * + * Falls back to bundled-only if bundled+mcp exceeds FILTERED_LISTING_MAX. + */ +export function filterToBundledAndMcp(commands: Command[]): Command[] { + const filtered = commands.filter( + cmd => cmd.loadedFrom === 'bundled' || cmd.loadedFrom === 'mcp', + ) + if (filtered.length > FILTERED_LISTING_MAX) { + return filtered.filter(cmd => cmd.loadedFrom === 'bundled') + } + return filtered +} + +async function getSkillListingAttachments( + toolUseContext: ToolUseContext, +): Promise { + if (process.env.NODE_ENV === 'test') { + return [] + } + + // Skip skill listing for agents that don't have the Skill tool — they can't use skills directly. + if ( + !toolUseContext.options.tools.some(t => toolMatchesName(t, SKILL_TOOL_NAME)) + ) { + return [] + } + + const cwd = getProjectRoot() + const localCommands = await getSkillToolCommands(cwd) + const mcpSkills = getMcpSkillCommands( + toolUseContext.getAppState().mcp.commands, + ) + let allCommands = + mcpSkills.length > 0 + ? uniqBy([...localCommands, ...mcpSkills], 'name') + : localCommands + + // When skill search is active, filter to bundled + MCP instead of full + // suppression. Resolves the turn-0 gap: main thread gets turn-0 discovery + // via getTurnZeroSkillDiscovery (blocking), but subagents use the async + // subagent_spawn signal (collected post-tools, visible turn 1). Bundled + + // MCP are small and intent-signaled; user/project/plugin skills go through + // discovery. feature() first for DCE — the property-access string leaks + // otherwise even with ?. on null. + if ( + feature('EXPERIMENTAL_SKILL_SEARCH') && + skillSearchModules?.featureCheck.isSkillSearchEnabled() + ) { + allCommands = filterToBundledAndMcp(allCommands) + } + + const agentKey = toolUseContext.agentId ?? '' + let sent = sentSkillNames.get(agentKey) + if (!sent) { + sent = new Set() + sentSkillNames.set(agentKey, sent) + } + + // Resume path: prior process already injected a listing; it's in the + // transcript. Mark everything current as sent so only post-resume deltas + // (skills loaded later via /reload-plugins etc) get announced. + if (suppressNext) { + suppressNext = false + for (const cmd of allCommands) { + sent.add(cmd.name) + } + return [] + } + + // Find skills we haven't sent yet + const newSkills = allCommands.filter(cmd => !sent.has(cmd.name)) + + if (newSkills.length === 0) { + return [] + } + + // If no skills have been sent yet, this is the initial batch + const isInitial = sent.size === 0 + + // Mark as sent + for (const cmd of newSkills) { + sent.add(cmd.name) + } + + logForDebugging( + `Sending ${newSkills.length} skills via attachment (${isInitial ? 'initial' : 'dynamic'}, ${sent.size} total sent)`, + ) + + // Format within budget using existing logic + const contextWindowTokens = getContextWindowForModel( + toolUseContext.options.mainLoopModel, + getSdkBetas(), + ) + const content = formatCommandsWithinBudget(newSkills, contextWindowTokens) + + return [ + { + type: 'skill_listing', + content, + skillCount: newSkills.length, + isInitial, + }, + ] +} + +// getSkillDiscoveryAttachment moved to skillSearch/prefetch.ts as +// getTurnZeroSkillDiscovery — keeps the 'skill_discovery' string literal inside +// a feature-gated module so it doesn't leak into external builds. + +export function extractAtMentionedFiles(content: string): string[] { + // Extract filenames mentioned with @ symbol, including line range syntax: @file.txt#L10-20 + // Also supports quoted paths for files with spaces: @"my/file with spaces.txt" + // Example: "foo bar @baz moo" would extract "baz" + // Example: 'check @"my file.txt" please' would extract "my file.txt" + + // Two patterns: quoted paths and regular paths + const quotedAtMentionRegex = /(^|\s)@"([^"]+)"/g + const regularAtMentionRegex = /(^|\s)@([^\s]+)\b/g + + const quotedMatches: string[] = [] + const regularMatches: string[] = [] + + // Extract quoted mentions first (skip agent mentions like @"code-reviewer (agent)") + let match + while ((match = quotedAtMentionRegex.exec(content)) !== null) { + if (match[2] && !match[2].endsWith(' (agent)')) { + quotedMatches.push(match[2]) // The content inside quotes + } + } + + // Extract regular mentions + const regularMatchArray = content.match(regularAtMentionRegex) || [] + regularMatchArray.forEach(match => { + const filename = match.slice(match.indexOf('@') + 1) + // Don't include if it starts with a quote (already handled as quoted) + if (!filename.startsWith('"')) { + regularMatches.push(filename) + } + }) + + // Combine and deduplicate + return uniq([...quotedMatches, ...regularMatches]) +} + +export function extractMcpResourceMentions(content: string): string[] { + // Extract MCP resources mentioned with @ symbol in format @server:uri + // Example: "@server1:resource/path" would extract "server1:resource/path" + const atMentionRegex = /(^|\s)@([^\s]+:[^\s]+)\b/g + const matches = content.match(atMentionRegex) || [] + + // Remove the prefix (everything before @) from each match + return uniq(matches.map(match => match.slice(match.indexOf('@') + 1))) +} + +export function extractAgentMentions(content: string): string[] { + // Extract agent mentions in two formats: + // 1. @agent- (legacy/manual typing) + // Example: "@agent-code-elegance-refiner" → "agent-code-elegance-refiner" + // 2. @" (agent)" (from autocomplete selection) + // Example: '@"code-reviewer (agent)"' → "code-reviewer" + // Supports colons, dots, and at-signs for plugin-scoped agents like "@agent-asana:project-status-updater" + const results: string[] = [] + + // Match quoted format: @" (agent)" + const quotedAgentRegex = /(^|\s)@"([\w:.@-]+) \(agent\)"/g + let match + while ((match = quotedAgentRegex.exec(content)) !== null) { + if (match[2]) { + results.push(match[2]) + } + } + + // Match unquoted format: @agent- + const unquotedAgentRegex = /(^|\s)@(agent-[\w:.@-]+)/g + const unquotedMatches = content.match(unquotedAgentRegex) || [] + for (const m of unquotedMatches) { + results.push(m.slice(m.indexOf('@') + 1)) + } + + return uniq(results) +} + +interface AtMentionedFileLines { + filename: string + lineStart?: number + lineEnd?: number +} + +export function parseAtMentionedFileLines( + mention: string, +): AtMentionedFileLines { + // Parse mentions like "file.txt#L10-20", "file.txt#heading", or just "file.txt" + // Supports line ranges (#L10, #L10-20) and strips non-line-range fragments (#heading) + const match = mention.match(/^([^#]+)(?:#L(\d+)(?:-(\d+))?)?(?:#[^#]*)?$/) + + if (!match) { + return { filename: mention } + } + + const [, filename, lineStartStr, lineEndStr] = match + const lineStart = lineStartStr ? parseInt(lineStartStr, 10) : undefined + const lineEnd = lineEndStr ? parseInt(lineEndStr, 10) : lineStart + + return { filename: filename ?? mention, lineStart, lineEnd } +} + +async function getDiagnosticAttachments( + toolUseContext: ToolUseContext, +): Promise { + // Diagnostics are only useful if the agent has the Bash tool to act on them + if ( + !toolUseContext.options.tools.some(t => toolMatchesName(t, BASH_TOOL_NAME)) + ) { + return [] + } + + // Get new diagnostics from the tracker (IDE diagnostics via MCP) + const newDiagnostics = await diagnosticTracker.getNewDiagnostics() + if (newDiagnostics.length === 0) { + return [] + } + + return [ + { + type: 'diagnostics', + files: newDiagnostics, + isNew: true, + }, + ] +} + +/** + * Get LSP diagnostic attachments from passive LSP servers. + * Follows the AsyncHookRegistry pattern for consistent async attachment delivery. + */ +async function getLSPDiagnosticAttachments( + toolUseContext: ToolUseContext, +): Promise { + // LSP diagnostics are only useful if the agent has the Bash tool to act on them + if ( + !toolUseContext.options.tools.some(t => toolMatchesName(t, BASH_TOOL_NAME)) + ) { + return [] + } + + logForDebugging('LSP Diagnostics: getLSPDiagnosticAttachments called') + + try { + const diagnosticSets = checkForLSPDiagnostics() + + if (diagnosticSets.length === 0) { + return [] + } + + logForDebugging( + `LSP Diagnostics: Found ${diagnosticSets.length} pending diagnostic set(s)`, + ) + + // Convert each diagnostic set to an attachment + const attachments: Attachment[] = diagnosticSets.map(({ files }) => ({ + type: 'diagnostics' as const, + files, + isNew: true, + })) + + // Clear delivered diagnostics from registry to prevent memory leak + // Follows same pattern as removeDeliveredAsyncHooks + if (diagnosticSets.length > 0) { + clearAllLSPDiagnostics() + logForDebugging( + `LSP Diagnostics: Cleared ${diagnosticSets.length} delivered diagnostic(s) from registry`, + ) + } + + logForDebugging( + `LSP Diagnostics: Returning ${attachments.length} diagnostic attachment(s)`, + ) + + return attachments + } catch (error) { + const err = toError(error) + logError( + new Error(`Failed to get LSP diagnostic attachments: ${err.message}`), + ) + // Return empty array to allow other attachments to proceed + return [] + } +} + +export async function* getAttachmentMessages( + input: string | null, + toolUseContext: ToolUseContext, + ideSelection: IDESelection | null, + queuedCommands: QueuedCommand[], + messages?: Message[], + querySource?: QuerySource, + options?: { skipSkillDiscovery?: boolean }, +): AsyncGenerator { + // TODO: Compute this upstream + const attachments = await getAttachments( + input, + toolUseContext, + ideSelection, + queuedCommands, + messages, + querySource, + options, + ) + + if (attachments.length === 0) { + return + } + + logEvent('tengu_attachments', { + attachment_types: attachments.map( + _ => _.type, + ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }) + + for (const attachment of attachments) { + yield createAttachmentMessage(attachment) + } +} + +/** + * Generates a file attachment by reading a file with proper validation and truncation. + * This is the core file reading logic shared between @-mentioned files and post-compact restoration. + * + * @param filename The absolute path to the file to read + * @param toolUseContext The tool use context for calling FileReadTool + * @param options Optional configuration for file reading + * @returns A new_file attachment or null if the file couldn't be read + */ +/** + * Check if a PDF file should be represented as a lightweight reference + * instead of being inlined. Returns a PDFReferenceAttachment for large PDFs + * (more than PDF_AT_MENTION_INLINE_THRESHOLD pages), or null otherwise. + */ +export async function tryGetPDFReference( + filename: string, +): Promise { + const ext = parse(filename).ext.toLowerCase() + if (!isPDFExtension(ext)) { + return null + } + try { + const [stats, pageCount] = await Promise.all([ + getFsImplementation().stat(filename), + getPDFPageCount(filename), + ]) + // Use page count if available, otherwise fall back to size heuristic (~100KB per page) + const effectivePageCount = pageCount ?? Math.ceil(stats.size / (100 * 1024)) + if (effectivePageCount > PDF_AT_MENTION_INLINE_THRESHOLD) { + logEvent('tengu_pdf_reference_attachment', { + pageCount: effectivePageCount, + fileSize: stats.size, + hadPdfinfo: pageCount !== null, + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) + return { + type: 'pdf_reference', + filename, + pageCount: effectivePageCount, + fileSize: stats.size, + displayPath: relative(getCwd(), filename), + } + } + } catch { + // If we can't stat the file, return null to proceed with normal reading + } + return null +} + +export async function generateFileAttachment( + filename: string, + toolUseContext: ToolUseContext, + successEventName: string, + errorEventName: string, + mode: 'compact' | 'at-mention', + options?: { + offset?: number + limit?: number + }, +): Promise< + | FileAttachment + | CompactFileReferenceAttachment + | PDFReferenceAttachment + | AlreadyReadFileAttachment + | null +> { + const { offset, limit } = options ?? {} + + // Check if file has a deny rule configured + const appState = toolUseContext.getAppState() + if (isFileReadDenied(filename, appState.toolPermissionContext)) { + return null + } + + // Check file size before attempting to read (skip for PDFs — they have their own size/page handling below) + if ( + mode === 'at-mention' && + !isFileWithinReadSizeLimit( + filename, + getDefaultFileReadingLimits().maxSizeBytes, + ) + ) { + const ext = parse(filename).ext.toLowerCase() + if (!isPDFExtension(ext)) { + try { + const stats = await getFsImplementation().stat(filename) + logEvent('tengu_attachment_file_too_large', { + size_bytes: stats.size, + mode, + } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) + return null + } catch { + // If we can't stat the file, proceed with normal reading (will fail later if file doesn't exist) + } + } + } + + // For large PDFs on @ mention, return a lightweight reference instead of inlining + if (mode === 'at-mention') { + const pdfRef = await tryGetPDFReference(filename) + if (pdfRef) { + return pdfRef + } + } + + // Check if file is already in context with latest version + const existingFileState = toolUseContext.readFileState.get(filename) + if (existingFileState && mode === 'at-mention') { + try { + // Check if the file has been modified since we last read it + const mtimeMs = await getFileModificationTimeAsync(filename) + + // Handle timestamp format inconsistency: + // - FileReadTool stores Date.now() (current time when read) + // - FileEdit/WriteTools store mtimeMs (file modification time) + // + // If timestamp > mtimeMs, it was stored by FileReadTool using Date.now() + // In this case, we should not use the optimization since we can't reliably + // compare modification times. Only use optimization when timestamp <= mtimeMs, + // indicating it was stored by FileEdit/WriteTool with actual mtimeMs. + + if ( + existingFileState.timestamp <= mtimeMs && + mtimeMs === existingFileState.timestamp + ) { + // File hasn't been modified, return already_read_file attachment + // This tells the system the file is already in context and doesn't need to be sent to API + logEvent(successEventName, {}) + return { + type: 'already_read_file', + filename, + displayPath: relative(getCwd(), filename), + content: { + type: 'text', + file: { + filePath: filename, + content: existingFileState.content, + numLines: countCharInString(existingFileState.content, '\n') + 1, + startLine: offset ?? 1, + totalLines: + countCharInString(existingFileState.content, '\n') + 1, + }, + }, + } + } + } catch { + // If we can't stat the file, proceed with normal reading + } + } + + try { + const fileInput = { + file_path: filename, + offset, + limit, + } + + async function readTruncatedFile(): Promise< + | FileAttachment + | CompactFileReferenceAttachment + | AlreadyReadFileAttachment + | null + > { + if (mode === 'compact') { + return { + type: 'compact_file_reference', + filename, + displayPath: relative(getCwd(), filename), + } + } + + // Check deny rules before reading truncated file + const appState = toolUseContext.getAppState() + if (isFileReadDenied(filename, appState.toolPermissionContext)) { + return null + } + + try { + // Read only the first MAX_LINES_TO_READ lines for files that are too large + const truncatedInput = { + file_path: filename, + offset: offset ?? 1, + limit: MAX_LINES_TO_READ, + } + const result = await FileReadTool.call(truncatedInput, toolUseContext) + logEvent(successEventName, {}) + + return { + type: 'file' as const, + filename, + content: result.data, + truncated: true, + displayPath: relative(getCwd(), filename), + } + } catch { + logEvent(errorEventName, {}) + return null + } + } + + // Validate file path is valid + const isValid = await FileReadTool.validateInput(fileInput, toolUseContext) + if (!isValid.result) { + return null + } + + try { + const result = await FileReadTool.call(fileInput, toolUseContext) + logEvent(successEventName, {}) + return { + type: 'file', + filename, + content: result.data, + displayPath: relative(getCwd(), filename), + } + } catch (error) { + if ( + error instanceof MaxFileReadTokenExceededError || + error instanceof FileTooLargeError + ) { + return await readTruncatedFile() + } + throw error + } + } catch { + logEvent(errorEventName, {}) + return null + } +} + +export function createAttachmentMessage( + attachment: Attachment, +): AttachmentMessage { + return { + attachment, + type: 'attachment', + uuid: randomUUID(), + timestamp: new Date().toISOString(), + } +} + +function getTodoReminderTurnCounts(messages: Message[]): { + turnsSinceLastTodoWrite: number + turnsSinceLastReminder: number +} { + let lastTodoWriteIndex = -1 + let lastReminderIndex = -1 + let assistantTurnsSinceWrite = 0 + let assistantTurnsSinceReminder = 0 + + // Iterate backwards to find most recent events + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + + if (message?.type === 'assistant') { + if (isThinkingMessage(message)) { + // Skip thinking messages + continue + } + + // Check for TodoWrite usage BEFORE incrementing counter + // (we don't want to count the TodoWrite message itself as "1 turn since write") + if ( + lastTodoWriteIndex === -1 && + 'message' in message && + Array.isArray(message.message?.content) && + message.message.content.some( + block => block.type === 'tool_use' && block.name === 'TodoWrite', + ) + ) { + lastTodoWriteIndex = i + } + + // Count assistant turns before finding events + if (lastTodoWriteIndex === -1) assistantTurnsSinceWrite++ + if (lastReminderIndex === -1) assistantTurnsSinceReminder++ + } else if ( + lastReminderIndex === -1 && + message?.type === 'attachment' && + message.attachment.type === 'todo_reminder' + ) { + lastReminderIndex = i + } + + if (lastTodoWriteIndex !== -1 && lastReminderIndex !== -1) { + break + } + } + + return { + turnsSinceLastTodoWrite: assistantTurnsSinceWrite, + turnsSinceLastReminder: assistantTurnsSinceReminder, + } +} + +async function getTodoReminderAttachments( + messages: Message[] | undefined, + toolUseContext: ToolUseContext, +): Promise { + // Skip if TodoWrite tool is not available + if ( + !toolUseContext.options.tools.some(t => + toolMatchesName(t, TODO_WRITE_TOOL_NAME), + ) + ) { + return [] + } + + // When SendUserMessage is in the toolkit, it's the primary communication + // channel and the model is always told to use it (#20467). TodoWrite + // becomes a side channel — nudging the model about it conflicts with the + // brief workflow. The tool itself stays available; this only gates the + // "you haven't used it in a while" nag. + if ( + BRIEF_TOOL_NAME && + toolUseContext.options.tools.some(t => toolMatchesName(t, BRIEF_TOOL_NAME)) + ) { + return [] + } + + // Skip if no messages provided + if (!messages || messages.length === 0) { + return [] + } + + const { turnsSinceLastTodoWrite, turnsSinceLastReminder } = + getTodoReminderTurnCounts(messages) + + // Check if we should show a reminder + if ( + turnsSinceLastTodoWrite >= TODO_REMINDER_CONFIG.TURNS_SINCE_WRITE && + turnsSinceLastReminder >= TODO_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS + ) { + const todoKey = toolUseContext.agentId ?? getSessionId() + const appState = toolUseContext.getAppState() + const todos = appState.todos[todoKey] ?? [] + return [ + { + type: 'todo_reminder', + content: todos, + itemCount: todos.length, + }, + ] + } + + return [] +} + +function getTaskReminderTurnCounts(messages: Message[]): { + turnsSinceLastTaskManagement: number + turnsSinceLastReminder: number +} { + let lastTaskManagementIndex = -1 + let lastReminderIndex = -1 + let assistantTurnsSinceTaskManagement = 0 + let assistantTurnsSinceReminder = 0 + + // Iterate backwards to find most recent events + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + + if (message?.type === 'assistant') { + if (isThinkingMessage(message)) { + // Skip thinking messages + continue + } + + // Check for TaskCreate or TaskUpdate usage BEFORE incrementing counter + if ( + lastTaskManagementIndex === -1 && + 'message' in message && + Array.isArray(message.message?.content) && + message.message.content.some( + block => + block.type === 'tool_use' && + (block.name === TASK_CREATE_TOOL_NAME || + block.name === TASK_UPDATE_TOOL_NAME), + ) + ) { + lastTaskManagementIndex = i + } + + // Count assistant turns before finding events + if (lastTaskManagementIndex === -1) assistantTurnsSinceTaskManagement++ + if (lastReminderIndex === -1) assistantTurnsSinceReminder++ + } else if ( + lastReminderIndex === -1 && + message?.type === 'attachment' && + message.attachment.type === 'task_reminder' + ) { + lastReminderIndex = i + } + + if (lastTaskManagementIndex !== -1 && lastReminderIndex !== -1) { + break + } + } + + return { + turnsSinceLastTaskManagement: assistantTurnsSinceTaskManagement, + turnsSinceLastReminder: assistantTurnsSinceReminder, + } +} + +async function getTaskReminderAttachments( + messages: Message[] | undefined, + toolUseContext: ToolUseContext, +): Promise { + if (!isTodoV2Enabled()) { + return [] + } + + // Skip for ant users + if (process.env.USER_TYPE === 'ant') { + return [] + } + + // When SendUserMessage is in the toolkit, it's the primary communication + // channel and the model is always told to use it (#20467). TaskUpdate + // becomes a side channel — nudging the model about it conflicts with the + // brief workflow. The tool itself stays available; this only gates the nag. + if ( + BRIEF_TOOL_NAME && + toolUseContext.options.tools.some(t => toolMatchesName(t, BRIEF_TOOL_NAME)) + ) { + return [] + } + + // Skip if TaskUpdate tool is not available + if ( + !toolUseContext.options.tools.some(t => + toolMatchesName(t, TASK_UPDATE_TOOL_NAME), + ) + ) { + return [] + } + + // Skip if no messages provided + if (!messages || messages.length === 0) { + return [] + } + + const { turnsSinceLastTaskManagement, turnsSinceLastReminder } = + getTaskReminderTurnCounts(messages) + + // Check if we should show a reminder + if ( + turnsSinceLastTaskManagement >= TODO_REMINDER_CONFIG.TURNS_SINCE_WRITE && + turnsSinceLastReminder >= TODO_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS + ) { + const tasks = await listTasks(getTaskListId()) + return [ + { + type: 'task_reminder', + content: tasks, + itemCount: tasks.length, + }, + ] + } + + return [] +} + +/** + * Get attachments for all unified tasks using the Task framework. + * Replaces the old getBackgroundShellAttachments, getBackgroundRemoteSessionAttachments, + * and getAsyncAgentAttachments functions. + */ +async function getUnifiedTaskAttachments( + toolUseContext: ToolUseContext, +): Promise { + const appState = toolUseContext.getAppState() + const { attachments, updatedTaskOffsets, evictedTaskIds } = + await generateTaskAttachments(appState) + + applyTaskOffsetsAndEvictions( + toolUseContext.setAppState, + updatedTaskOffsets, + evictedTaskIds, + ) + + // Convert TaskAttachment to Attachment format + return attachments.map(taskAttachment => ({ + type: 'task_status' as const, + taskId: taskAttachment.taskId, + taskType: taskAttachment.taskType, + status: taskAttachment.status, + description: taskAttachment.description, + deltaSummary: taskAttachment.deltaSummary, + outputFilePath: getTaskOutputPath(taskAttachment.taskId), + })) +} + +async function getAsyncHookResponseAttachments(): Promise { + const responses = await checkForAsyncHookResponses() + + if (responses.length === 0) { + return [] + } + + logForDebugging( + `Hooks: getAsyncHookResponseAttachments found ${responses.length} responses`, + ) + + const attachments = responses.map( + ({ + processId, + response, + hookName, + hookEvent, + toolName, + pluginId, + stdout, + stderr, + exitCode, + }) => { + logForDebugging( + `Hooks: Creating attachment for ${processId} (${hookName}): ${jsonStringify(response)}`, + ) + return { + type: 'async_hook_response' as const, + processId, + hookName, + hookEvent, + toolName, + response, + stdout, + stderr, + exitCode, + } + }, + ) + + // Remove delivered hooks from registry to prevent re-processing + if (responses.length > 0) { + const processIds = responses.map(r => r.processId) + removeDeliveredAsyncHooks(processIds) + logForDebugging( + `Hooks: Removed ${processIds.length} delivered hooks from registry`, + ) + } + + logForDebugging( + `Hooks: getAsyncHookResponseAttachments found ${attachments.length} attachments`, + ) + + return attachments +} + +/** + * Get teammate mailbox attachments for agent swarm communication + * Teammates are independent Claude Code sessions running in parallel (swarms), + * not parent-child subagent relationships. + * + * This function checks two sources for messages: + * 1. File-based mailbox (for messages that arrived between polls) + * 2. AppState.inbox (for messages queued mid-turn by useInboxPoller) + * + * Messages from AppState.inbox are delivered mid-turn as attachments, + * allowing teammates to receive messages without waiting for the turn to end. + */ +async function getTeammateMailboxAttachments( + toolUseContext: ToolUseContext, +): Promise { + if (!isAgentSwarmsEnabled()) { + return [] + } + if (process.env.USER_TYPE !== 'ant') { + return [] + } + + // Get AppState early to check for team lead status + const appState = toolUseContext.getAppState() + + // Use agent name from helper (checks AsyncLocalStorage, then dynamicTeamContext) + const envAgentName = getAgentName() + + // Get team name (checks AsyncLocalStorage, dynamicTeamContext, then AppState) + const teamName = getTeamName(appState.teamContext) + + // Check if we're the team lead (uses shared logic from swarm utils) + const teamLeadStatus = isTeamLead(appState.teamContext) + + // Check if viewing a teammate's transcript (for in-process teammates) + const viewedTeammate = getViewedTeammateTask(appState) + + // Resolve agent name based on who we're VIEWING: + // - If viewing a teammate, use THEIR name (to read from their mailbox) + // - Otherwise use env var if set, or leader's name if we're the team lead + let agentName = viewedTeammate?.identity.agentName ?? envAgentName + if (!agentName && teamLeadStatus && appState.teamContext) { + const leadAgentId = appState.teamContext.leadAgentId + // Look up the lead's name from agents map (not the UUID) + agentName = appState.teamContext.teammates[leadAgentId]?.name || 'team-lead' + } + + logForDebugging( + `[SwarmMailbox] getTeammateMailboxAttachments called: envAgentName=${envAgentName}, isTeamLead=${teamLeadStatus}, resolved agentName=${agentName}, teamName=${teamName}`, + ) + + // Only check inbox if running as an agent in a swarm or team lead + if (!agentName) { + logForDebugging( + `[SwarmMailbox] Not checking inbox - not in a swarm or team lead`, + ) + return [] + } + + logForDebugging( + `[SwarmMailbox] Checking inbox for agent="${agentName}" team="${teamName || 'default'}"`, + ) + + // Check mailbox for unread messages (routes to in-process or file-based) + // Filter out structured protocol messages (permission requests/responses, shutdown + // messages, etc.) — these must be left unread for useInboxPoller to route to their + // proper handlers (workerPermissions queue, sandbox queue, etc.). Without filtering, + // attachment generation races with InboxPoller: whichever reads first marks all + // messages as read, and if attachments wins, protocol messages get bundled as raw + // LLM context text instead of being routed to their UI handlers. + const allUnreadMessages = await readUnreadMessages(agentName, teamName) + const unreadMessages = allUnreadMessages.filter( + m => !isStructuredProtocolMessage(m.text), + ) + logForDebugging( + `[MailboxBridge] Found ${allUnreadMessages.length} unread message(s) for "${agentName}" (${allUnreadMessages.length - unreadMessages.length} structured protocol messages filtered out)`, + ) + + // Also check AppState.inbox for pending messages (queued mid-turn by useInboxPoller) + // IMPORTANT: appState.inbox contains messages FROM teammates TO the leader. + // Only show these when viewing the leader's transcript (not a teammate's). + // When viewing a teammate, their messages come from the file-based mailbox above. + // In-process teammates share AppState with the leader — appState.inbox contains + // the LEADER's queued messages, not the teammate's. Skip it to prevent leakage + // (including self-echo from broadcasts). Teammates receive messages exclusively + // through their file-based mailbox + waitForNextPromptOrShutdown. + // Note: viewedTeammate was already computed above for agentName resolution + const pendingInboxMessages = + viewedTeammate || isInProcessTeammate() + ? [] // Viewing teammate or running as in-process teammate - don't show leader's inbox + : appState.inbox.messages.filter(m => m.status === 'pending') + logForDebugging( + `[SwarmMailbox] Found ${pendingInboxMessages.length} pending message(s) in AppState.inbox`, + ) + + // Combine both sources of messages WITH DEDUPLICATION + // The same message could exist in both file mailbox and AppState.inbox due to race conditions: + // 1. getTeammateMailboxAttachments reads file -> finds message M + // 2. InboxPoller reads same file -> queues M in AppState.inbox + // 3. getTeammateMailboxAttachments reads AppState -> finds M again + // We deduplicate using from+timestamp+text prefix as the key + const seen = new Set() + let allMessages: Array<{ + from: string + text: string + timestamp: string + color?: string + summary?: string + }> = [] + + for (const m of [...unreadMessages, ...pendingInboxMessages]) { + const key = `${m.from}|${m.timestamp}|${m.text.slice(0, 100)}` + if (!seen.has(key)) { + seen.add(key) + allMessages.push({ + from: m.from, + text: m.text, + timestamp: m.timestamp, + color: m.color, + summary: m.summary, + }) + } + } + + // Collapse multiple idle notifications per agent — keep only the latest. + // Single pass to parse, then filter without re-parsing. + const idleAgentByIndex = new Map() + const latestIdleByAgent = new Map() + for (let i = 0; i < allMessages.length; i++) { + const idle = isIdleNotification(allMessages[i]!.text) + if (idle) { + idleAgentByIndex.set(i, idle.from) + latestIdleByAgent.set(idle.from, i) + } + } + if (idleAgentByIndex.size > latestIdleByAgent.size) { + const beforeCount = allMessages.length + allMessages = allMessages.filter((_m, i) => { + const agent = idleAgentByIndex.get(i) + if (agent === undefined) return true + return latestIdleByAgent.get(agent) === i + }) + logForDebugging( + `[SwarmMailbox] Collapsed ${beforeCount - allMessages.length} duplicate idle notification(s)`, + ) + } + + if (allMessages.length === 0) { + logForDebugging(`[SwarmMailbox] No messages to deliver, returning empty`) + return [] + } + + logForDebugging( + `[SwarmMailbox] Returning ${allMessages.length} message(s) as attachment for "${agentName}" (${unreadMessages.length} from file, ${pendingInboxMessages.length} from AppState, after dedup)`, + ) + + // Build the attachment BEFORE marking messages as processed + // This prevents message loss if any operation below fails + const attachment: Attachment[] = [ + { + type: 'teammate_mailbox', + messages: allMessages, + }, + ] + + // Mark only non-structured mailbox messages as read after attachment is built. + // Structured protocol messages stay unread for useInboxPoller to handle. + if (unreadMessages.length > 0) { + await markMessagesAsReadByPredicate( + agentName, + m => !isStructuredProtocolMessage(m.text), + teamName, + ) + logForDebugging( + `[MailboxBridge] marked ${unreadMessages.length} non-structured message(s) as read for agent="${agentName}" team="${teamName || 'default'}"`, + ) + } + + // Process shutdown_approved messages - remove teammates from team file + // This mirrors what useInboxPoller does in interactive mode (lines 546-606) + // In -p mode, useInboxPoller doesn't run, so we must handle this here + if (teamLeadStatus && teamName) { + for (const m of allMessages) { + const shutdownApproval = isShutdownApproved(m.text) + if (shutdownApproval) { + const teammateToRemove = shutdownApproval.from + logForDebugging( + `[SwarmMailbox] Processing shutdown_approved from ${teammateToRemove}`, + ) + + // Find the teammate ID by name + const teammateId = appState.teamContext?.teammates + ? Object.entries(appState.teamContext.teammates).find( + ([, t]) => t.name === teammateToRemove, + )?.[0] + : undefined + + if (teammateId) { + // Remove from team file + removeTeammateFromTeamFile(teamName, { + agentId: teammateId, + name: teammateToRemove, + }) + logForDebugging( + `[SwarmMailbox] Removed ${teammateToRemove} from team file`, + ) + + // Unassign tasks owned by this teammate + await unassignTeammateTasks( + teamName, + teammateId, + teammateToRemove, + 'shutdown', + ) + + // Remove from teamContext in AppState + toolUseContext.setAppState(prev => { + if (!prev.teamContext?.teammates) return prev + if (!(teammateId in prev.teamContext.teammates)) return prev + const { [teammateId]: _, ...remainingTeammates } = + prev.teamContext.teammates + return { + ...prev, + teamContext: { + ...prev.teamContext, + teammates: remainingTeammates, + }, + } + }) + } + } + } + } + + // Mark AppState inbox messages as processed LAST, after attachment is built + // This ensures messages aren't lost if earlier operations fail + if (pendingInboxMessages.length > 0) { + const pendingIds = new Set(pendingInboxMessages.map(m => m.id)) + toolUseContext.setAppState(prev => ({ + ...prev, + inbox: { + messages: prev.inbox.messages.map(m => + pendingIds.has(m.id) ? { ...m, status: 'processed' as const } : m, + ), + }, + })) + } + + return attachment +} + +/** + * Get team context attachment for teammates in a swarm. + * Only injected on the first turn to provide team coordination instructions. + */ +function getTeamContextAttachment(messages: Message[]): Attachment[] { + const teamName = getTeamName() + const agentId = getAgentId() + const agentName = getAgentName() + + // Only inject for teammates (not team lead or non-team sessions) + if (!teamName || !agentId) { + return [] + } + + // Only inject on first turn - check if there are no assistant messages yet + const hasAssistantMessage = messages.some(m => m.type === 'assistant') + if (hasAssistantMessage) { + return [] + } + + const configDir = getClaudeConfigHomeDir() + const teamConfigPath = `${configDir}/teams/${teamName}/config.json` + const taskListPath = `${configDir}/tasks/${teamName}/` + + return [ + { + type: 'team_context', + agentId, + agentName: agentName || agentId, + teamName, + teamConfigPath, + taskListPath, + }, + ] +} + +function getTokenUsageAttachment( + messages: Message[], + model: string, +): Attachment[] { + if (!isEnvTruthy(process.env.CLAUDE_CODE_ENABLE_TOKEN_USAGE_ATTACHMENT)) { + return [] + } + + const contextWindow = getEffectiveContextWindowSize(model) + const usedTokens = tokenCountFromLastAPIResponse(messages) + + return [ + { + type: 'token_usage', + used: usedTokens, + total: contextWindow, + remaining: contextWindow - usedTokens, + }, + ] +} + +function getOutputTokenUsageAttachment(): Attachment[] { + if (feature('TOKEN_BUDGET')) { + const budget = getCurrentTurnTokenBudget() + if (budget === null || budget <= 0) { + return [] + } + return [ + { + type: 'output_token_usage', + turn: getTurnOutputTokens(), + session: getTotalOutputTokens(), + budget, + }, + ] + } + return [] +} + +function getMaxBudgetUsdAttachment(maxBudgetUsd?: number): Attachment[] { + if (maxBudgetUsd === undefined) { + return [] + } + + const usedCost = getTotalCostUSD() + const remainingBudget = maxBudgetUsd - usedCost + + return [ + { + type: 'budget_usd', + used: usedCost, + total: maxBudgetUsd, + remaining: remainingBudget, + }, + ] +} + +/** + * Count human turns since plan mode exit (plan_mode_exit attachment). + * Returns 0 if no plan_mode_exit attachment found. + * + * tool_result messages are type:'user' without isMeta, so filter by + * toolUseResult to avoid counting them — otherwise the 10-turn reminder + * interval fires every ~10 tool calls instead of ~10 human turns. + */ +export function getVerifyPlanReminderTurnCount(messages: Message[]): number { + let turnCount = 0 + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i] + if (message && isHumanTurn(message)) { + turnCount++ + } + // Stop counting at plan_mode_exit attachment (marks when implementation started) + if ( + message?.type === 'attachment' && + message.attachment.type === 'plan_mode_exit' + ) { + return turnCount + } + } + // No plan_mode_exit found + return 0 +} + +/** + * Get verify plan reminder attachment if the model hasn't called VerifyPlanExecution yet. + */ +async function getVerifyPlanReminderAttachment( + messages: Message[] | undefined, + toolUseContext: ToolUseContext, +): Promise { + if ( + process.env.USER_TYPE !== 'ant' || + !isEnvTruthy(process.env.CLAUDE_CODE_VERIFY_PLAN) + ) { + return [] + } + + const appState = toolUseContext.getAppState() + const pending = appState.pendingPlanVerification + + // Only remind if plan exists and verification not started or completed + if ( + !pending || + pending.verificationStarted || + pending.verificationCompleted + ) { + return [] + } + + // Only remind every N turns + if (messages && messages.length > 0) { + const turnCount = getVerifyPlanReminderTurnCount(messages) + if ( + turnCount === 0 || + turnCount % VERIFY_PLAN_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS !== 0 + ) { + return [] + } + } + + return [{ type: 'verify_plan_reminder' }] +} + +export function getCompactionReminderAttachment( + messages: Message[], + model: string, +): Attachment[] { + if (!getFeatureValue_CACHED_MAY_BE_STALE('tengu_marble_fox', false)) { + return [] + } + + if (!isAutoCompactEnabled()) { + return [] + } + + const contextWindow = getContextWindowForModel(model, getSdkBetas()) + if (contextWindow < 1_000_000) { + return [] + } + + const effectiveWindow = getEffectiveContextWindowSize(model) + const usedTokens = tokenCountWithEstimation(messages) + if (usedTokens < effectiveWindow * 0.25) { + return [] + } + + return [{ type: 'compaction_reminder' }] +} + +/** + * Context-efficiency nudge. Injected after every N tokens of growth without + * a snip. Pacing is handled entirely by shouldNudgeForSnips — the 10k + * interval resets on prior nudges, snip markers, snip boundaries, and + * compact boundaries. + */ +export function getContextEfficiencyAttachment( + messages: Message[], +): Attachment[] { + if (!feature('HISTORY_SNIP')) { + return [] + } + // Gate must match SnipTool.isEnabled() — don't nudge toward a tool that + // isn't in the tool list. Lazy require keeps this file snip-string-free. + const { isSnipRuntimeEnabled, shouldNudgeForSnips } = + // eslint-disable-next-line @typescript-eslint/no-require-imports + require('../services/compact/snipCompact.js') as typeof import('../services/compact/snipCompact.js') + if (!isSnipRuntimeEnabled()) { + return [] + } + + if (!shouldNudgeForSnips(messages)) { + return [] + } + + return [{ type: 'context_efficiency' }] +} + + +function isFileReadDenied( + filePath: string, + toolPermissionContext: ToolPermissionContext, +): boolean { + const denyRule = matchingRuleForInput( + filePath, + toolPermissionContext, + 'read', + 'deny', + ) + return denyRule !== null +} diff --git a/_all-in-one-upload/cc-haha/src/utils/codeIndexing.ts b/_all-in-one-upload/cc-haha/src/utils/codeIndexing.ts new file mode 100644 index 0000000..8bf076d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/codeIndexing.ts @@ -0,0 +1,206 @@ +/** + * Utility functions for detecting code indexing tool usage. + * + * Tracks usage of common code indexing solutions like Sourcegraph, Cody, etc. + * both via CLI commands and MCP server integrations. + */ + +/** + * Known code indexing tool identifiers. + * These are the normalized names used in analytics events. + */ +export type CodeIndexingTool = + // Code search engines + | 'sourcegraph' + | 'hound' + | 'seagoat' + | 'bloop' + | 'gitloop' + // AI coding assistants with indexing + | 'cody' + | 'aider' + | 'continue' + | 'github-copilot' + | 'cursor' + | 'tabby' + | 'codeium' + | 'tabnine' + | 'augment' + | 'windsurf' + | 'aide' + | 'pieces' + | 'qodo' + | 'amazon-q' + | 'gemini' + // MCP code indexing servers + | 'claude-context' + | 'code-index-mcp' + | 'local-code-search' + | 'autodev-codebase' + // Context providers + | 'openctx' + +/** + * Mapping of CLI command prefixes to code indexing tools. + * The key is the command name (first word of the command). + */ +const CLI_COMMAND_MAPPING: Record = { + // Sourcegraph ecosystem + src: 'sourcegraph', + cody: 'cody', + // AI coding assistants + aider: 'aider', + tabby: 'tabby', + tabnine: 'tabnine', + augment: 'augment', + pieces: 'pieces', + qodo: 'qodo', + aide: 'aide', + // Code search tools + hound: 'hound', + seagoat: 'seagoat', + bloop: 'bloop', + gitloop: 'gitloop', + // Cloud provider AI assistants + q: 'amazon-q', + gemini: 'gemini', +} + +/** + * Mapping of MCP server name patterns to code indexing tools. + * Patterns are matched case-insensitively against the server name. + */ +const MCP_SERVER_PATTERNS: Array<{ + pattern: RegExp + tool: CodeIndexingTool +}> = [ + // Sourcegraph ecosystem + { pattern: /^sourcegraph$/i, tool: 'sourcegraph' }, + { pattern: /^cody$/i, tool: 'cody' }, + { pattern: /^openctx$/i, tool: 'openctx' }, + // AI coding assistants + { pattern: /^aider$/i, tool: 'aider' }, + { pattern: /^continue$/i, tool: 'continue' }, + { pattern: /^github[-_]?copilot$/i, tool: 'github-copilot' }, + { pattern: /^copilot$/i, tool: 'github-copilot' }, + { pattern: /^cursor$/i, tool: 'cursor' }, + { pattern: /^tabby$/i, tool: 'tabby' }, + { pattern: /^codeium$/i, tool: 'codeium' }, + { pattern: /^tabnine$/i, tool: 'tabnine' }, + { pattern: /^augment[-_]?code$/i, tool: 'augment' }, + { pattern: /^augment$/i, tool: 'augment' }, + { pattern: /^windsurf$/i, tool: 'windsurf' }, + { pattern: /^aide$/i, tool: 'aide' }, + { pattern: /^codestory$/i, tool: 'aide' }, + { pattern: /^pieces$/i, tool: 'pieces' }, + { pattern: /^qodo$/i, tool: 'qodo' }, + { pattern: /^amazon[-_]?q$/i, tool: 'amazon-q' }, + { pattern: /^gemini[-_]?code[-_]?assist$/i, tool: 'gemini' }, + { pattern: /^gemini$/i, tool: 'gemini' }, + // Code search tools + { pattern: /^hound$/i, tool: 'hound' }, + { pattern: /^seagoat$/i, tool: 'seagoat' }, + { pattern: /^bloop$/i, tool: 'bloop' }, + { pattern: /^gitloop$/i, tool: 'gitloop' }, + // MCP code indexing servers + { pattern: /^claude[-_]?context$/i, tool: 'claude-context' }, + { pattern: /^code[-_]?index[-_]?mcp$/i, tool: 'code-index-mcp' }, + { pattern: /^code[-_]?index$/i, tool: 'code-index-mcp' }, + { pattern: /^local[-_]?code[-_]?search$/i, tool: 'local-code-search' }, + { pattern: /^codebase$/i, tool: 'autodev-codebase' }, + { pattern: /^autodev[-_]?codebase$/i, tool: 'autodev-codebase' }, + { pattern: /^code[-_]?context$/i, tool: 'claude-context' }, +] + +/** + * Detects if a bash command is using a code indexing CLI tool. + * + * @param command - The full bash command string + * @returns The code indexing tool identifier, or undefined if not a code indexing command + * + * @example + * detectCodeIndexingFromCommand('src search "pattern"') // returns 'sourcegraph' + * detectCodeIndexingFromCommand('cody chat --message "help"') // returns 'cody' + * detectCodeIndexingFromCommand('ls -la') // returns undefined + */ +export function detectCodeIndexingFromCommand( + command: string, +): CodeIndexingTool | undefined { + // Extract the first word (command name) + const trimmed = command.trim() + const firstWord = trimmed.split(/\s+/)[0]?.toLowerCase() + + if (!firstWord) { + return undefined + } + + // Check for npx/bunx prefixed commands + if (firstWord === 'npx' || firstWord === 'bunx') { + const secondWord = trimmed.split(/\s+/)[1]?.toLowerCase() + if (secondWord && secondWord in CLI_COMMAND_MAPPING) { + return CLI_COMMAND_MAPPING[secondWord] + } + } + + return CLI_COMMAND_MAPPING[firstWord] +} + +/** + * Detects if an MCP tool is from a code indexing server. + * + * @param toolName - The MCP tool name (format: mcp__serverName__toolName) + * @returns The code indexing tool identifier, or undefined if not a code indexing tool + * + * @example + * detectCodeIndexingFromMcpTool('mcp__sourcegraph__search') // returns 'sourcegraph' + * detectCodeIndexingFromMcpTool('mcp__cody__chat') // returns 'cody' + * detectCodeIndexingFromMcpTool('mcp__filesystem__read') // returns undefined + */ +export function detectCodeIndexingFromMcpTool( + toolName: string, +): CodeIndexingTool | undefined { + // MCP tool names follow the format: mcp__serverName__toolName + if (!toolName.startsWith('mcp__')) { + return undefined + } + + const parts = toolName.split('__') + if (parts.length < 3) { + return undefined + } + + const serverName = parts[1] + if (!serverName) { + return undefined + } + + for (const { pattern, tool } of MCP_SERVER_PATTERNS) { + if (pattern.test(serverName)) { + return tool + } + } + + return undefined +} + +/** + * Detects if an MCP server name corresponds to a code indexing tool. + * + * @param serverName - The MCP server name + * @returns The code indexing tool identifier, or undefined if not a code indexing server + * + * @example + * detectCodeIndexingFromMcpServerName('sourcegraph') // returns 'sourcegraph' + * detectCodeIndexingFromMcpServerName('filesystem') // returns undefined + */ +export function detectCodeIndexingFromMcpServerName( + serverName: string, +): CodeIndexingTool | undefined { + for (const { pattern, tool } of MCP_SERVER_PATTERNS) { + if (pattern.test(serverName)) { + return tool + } + } + + return undefined +} diff --git a/_all-in-one-upload/cc-haha/src/utils/configConstants.ts b/_all-in-one-upload/cc-haha/src/utils/configConstants.ts new file mode 100644 index 0000000..3d1e6af --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/configConstants.ts @@ -0,0 +1,21 @@ +// These constants are in a separate file to avoid circular dependency issues. +// Do NOT add imports to this file - it must remain dependency-free. + +export const NOTIFICATION_CHANNELS = [ + 'auto', + 'iterm2', + 'iterm2_with_bell', + 'terminal_bell', + 'kitty', + 'ghostty', + 'notifications_disabled', +] as const + +// Valid editor modes (excludes deprecated 'emacs' which is auto-migrated to 'normal') +export const EDITOR_MODES = ['normal', 'vim'] as const + +// Valid teammate modes for spawning +// 'tmux' = traditional tmux-based teammates +// 'in-process' = in-process teammates running in same process +// 'auto' = automatically choose based on context (default) +export const TEAMMATE_MODES = ['auto', 'tmux', 'in-process'] as const diff --git a/_all-in-one-upload/cc-haha/src/utils/context.ts b/_all-in-one-upload/cc-haha/src/utils/context.ts new file mode 100644 index 0000000..d9714de --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/context.ts @@ -0,0 +1,221 @@ +// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered +import { CONTEXT_1M_BETA_HEADER } from '../constants/betas.js' +import { getGlobalConfig } from './config.js' +import { isEnvTruthy } from './envUtils.js' +import { getCanonicalName } from './model/model.js' +import { getModelCapability } from './model/modelCapabilities.js' + +// Model context window size (200k tokens for all models right now) +export const MODEL_CONTEXT_WINDOW_DEFAULT = 200_000 + +// Maximum output tokens for compact operations +export const COMPACT_MAX_OUTPUT_TOKENS = 20_000 + +// Default max output tokens +const MAX_OUTPUT_TOKENS_DEFAULT = 32_000 +const MAX_OUTPUT_TOKENS_UPPER_LIMIT = 64_000 + +// Capped default for slot-reservation optimization. BQ p99 output = 4,911 +// tokens, so 32k/64k defaults over-reserve 8-16× slot capacity. With the cap +// enabled, <1% of requests hit the limit; those get one clean retry at 64k +// (see query.ts max_output_tokens_escalate). Cap is applied in +// claude.ts:getMaxOutputTokensForModel to avoid the growthbook→betas→context +// import cycle. +export const CAPPED_DEFAULT_MAX_TOKENS = 8_000 +export const ESCALATED_MAX_TOKENS = 64_000 + +/** + * Check if 1M context is disabled via environment variable. + * Used by C4E admins to disable 1M context for HIPAA compliance. + */ +export function is1mContextDisabled(): boolean { + return isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_1M_CONTEXT) +} + +export function has1mContext(model: string): boolean { + if (is1mContextDisabled()) { + return false + } + return /\[1m\]/i.test(model) +} + +// @[MODEL LAUNCH]: Update this pattern if the new model supports 1M context +export function modelSupports1M(model: string): boolean { + if (is1mContextDisabled()) { + return false + } + const canonical = getCanonicalName(model) + return canonical.includes('claude-sonnet-4') || canonical.includes('opus-4-6') +} + +export function getContextWindowForModel( + model: string, + betas?: string[], +): number { + // Allow override via environment variable (ant-only) + // This takes precedence over all other context window resolution, including 1M detection, + // so users can cap the effective context window for local decisions (auto-compact, etc.) + // while still using a 1M-capable endpoint. + if ( + process.env.USER_TYPE === 'ant' && + process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS + ) { + const override = parseInt(process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS, 10) + if (!isNaN(override) && override > 0) { + return override + } + } + + // [1m] suffix — explicit client-side opt-in, respected over all detection + if (has1mContext(model)) { + return 1_000_000 + } + + const cap = getModelCapability(model) + if (cap?.max_input_tokens && cap.max_input_tokens >= 100_000) { + if ( + cap.max_input_tokens > MODEL_CONTEXT_WINDOW_DEFAULT && + is1mContextDisabled() + ) { + return MODEL_CONTEXT_WINDOW_DEFAULT + } + return cap.max_input_tokens + } + + if (betas?.includes(CONTEXT_1M_BETA_HEADER) && modelSupports1M(model)) { + return 1_000_000 + } + if (getSonnet1mExpTreatmentEnabled(model)) { + return 1_000_000 + } + if (process.env.USER_TYPE === 'ant') { + const antModel = resolveAntModel(model) + if (antModel?.contextWindow) { + return antModel.contextWindow + } + } + return MODEL_CONTEXT_WINDOW_DEFAULT +} + +export function getSonnet1mExpTreatmentEnabled(model: string): boolean { + if (is1mContextDisabled()) { + return false + } + // Only applies to sonnet 4.6 without an explicit [1m] suffix + if (has1mContext(model)) { + return false + } + if (!getCanonicalName(model).includes('sonnet-4-6')) { + return false + } + return getGlobalConfig().clientDataCache?.['coral_reef_sonnet'] === 'true' +} + +/** + * Calculate context window usage percentage from token usage data. + * Returns used and remaining percentages, or null values if no usage data. + */ +export function calculateContextPercentages( + currentUsage: { + input_tokens: number + cache_creation_input_tokens: number + cache_read_input_tokens: number + } | null, + contextWindowSize: number, +): { used: number | null; remaining: number | null } { + if (!currentUsage) { + return { used: null, remaining: null } + } + + const totalInputTokens = + currentUsage.input_tokens + + currentUsage.cache_creation_input_tokens + + currentUsage.cache_read_input_tokens + + const usedPercentage = Math.round( + (totalInputTokens / contextWindowSize) * 100, + ) + const clampedUsed = Math.min(100, Math.max(0, usedPercentage)) + + return { + used: clampedUsed, + remaining: 100 - clampedUsed, + } +} + +/** + * Returns the model's default and upper limit for max output tokens. + */ +export function getModelMaxOutputTokens(model: string): { + default: number + upperLimit: number +} { + let defaultTokens: number + let upperLimit: number + + if (process.env.USER_TYPE === 'ant') { + const antModel = resolveAntModel(model.toLowerCase()) + if (antModel) { + defaultTokens = antModel.defaultMaxTokens ?? MAX_OUTPUT_TOKENS_DEFAULT + upperLimit = antModel.upperMaxTokensLimit ?? MAX_OUTPUT_TOKENS_UPPER_LIMIT + return { default: defaultTokens, upperLimit } + } + } + + const m = getCanonicalName(model) + + if (m.includes('opus-4-6')) { + defaultTokens = 64_000 + upperLimit = 128_000 + } else if (m.includes('sonnet-4-6')) { + defaultTokens = 32_000 + upperLimit = 128_000 + } else if ( + m.includes('opus-4-5') || + m.includes('sonnet-4') || + m.includes('haiku-4') + ) { + defaultTokens = 32_000 + upperLimit = 64_000 + } else if (m.includes('opus-4-1') || m.includes('opus-4')) { + defaultTokens = 32_000 + upperLimit = 32_000 + } else if (m.includes('claude-3-opus')) { + defaultTokens = 4_096 + upperLimit = 4_096 + } else if (m.includes('claude-3-sonnet')) { + defaultTokens = 8_192 + upperLimit = 8_192 + } else if (m.includes('claude-3-haiku')) { + defaultTokens = 4_096 + upperLimit = 4_096 + } else if (m.includes('3-5-sonnet') || m.includes('3-5-haiku')) { + defaultTokens = 8_192 + upperLimit = 8_192 + } else if (m.includes('3-7-sonnet')) { + defaultTokens = 32_000 + upperLimit = 64_000 + } else { + defaultTokens = MAX_OUTPUT_TOKENS_DEFAULT + upperLimit = MAX_OUTPUT_TOKENS_UPPER_LIMIT + } + + const cap = getModelCapability(model) + if (cap?.max_tokens && cap.max_tokens >= 4_096) { + upperLimit = cap.max_tokens + defaultTokens = Math.min(defaultTokens, upperLimit) + } + + return { default: defaultTokens, upperLimit } +} + +/** + * Returns the max thinking budget tokens for a given model. The max + * thinking tokens should be strictly less than the max output tokens. + * + * Deprecated since newer models use adaptive thinking rather than a + * strict thinking token budget. + */ +export function getMaxThinkingTokensForModel(model: string): number { + return getModelMaxOutputTokens(model).upperLimit - 1 +} diff --git a/_all-in-one-upload/cc-haha/src/utils/contextAnalysis.ts b/_all-in-one-upload/cc-haha/src/utils/contextAnalysis.ts new file mode 100644 index 0000000..2801d37 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/contextAnalysis.ts @@ -0,0 +1,272 @@ +import type { BetaContentBlock } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs' +import type { + ContentBlock, + ContentBlockParam, +} from '@anthropic-ai/sdk/resources/index.mjs' +import { roughTokenCountEstimation as countTokens } from '../services/tokenEstimation.js' +import type { + AssistantMessage, + Message, + UserMessage, +} from '../types/message.js' +import { normalizeMessagesForAPI } from './messages.js' +import { jsonStringify } from './slowOperations.js' + +type TokenStats = { + toolRequests: Map + toolResults: Map + humanMessages: number + assistantMessages: number + localCommandOutputs: number + other: number + attachments: Map + duplicateFileReads: Map + total: number +} + +export function analyzeContext(messages: Message[]): TokenStats { + const stats: TokenStats = { + toolRequests: new Map(), + toolResults: new Map(), + humanMessages: 0, + assistantMessages: 0, + localCommandOutputs: 0, + other: 0, + attachments: new Map(), + duplicateFileReads: new Map(), + total: 0, + } + + const toolIdsToToolNames = new Map() + const readToolIdToFilePath = new Map() + const fileReadStats = new Map< + string, + { count: number; totalTokens: number } + >() + + messages.forEach(msg => { + if (msg.type === 'attachment') { + const type = msg.attachment.type || 'unknown' + stats.attachments.set(type, (stats.attachments.get(type) || 0) + 1) + } + }) + + const normalizedMessages = normalizeMessagesForAPI(messages) + normalizedMessages.forEach(msg => { + const { content } = msg.message + + // Not sure if this path is still used, but adding as a fallback + if (typeof content === 'string') { + const tokens = countTokens(content) + stats.total += tokens + // Check if this is a local command output + if (msg.type === 'user' && content.includes('local-command-stdout')) { + stats.localCommandOutputs += tokens + } else { + stats[msg.type === 'user' ? 'humanMessages' : 'assistantMessages'] += + tokens + } + } else { + content.forEach(block => + processBlock( + block, + msg, + stats, + toolIdsToToolNames, + readToolIdToFilePath, + fileReadStats, + ), + ) + } + }) + + // Calculate duplicate file reads + fileReadStats.forEach((data, path) => { + if (data.count > 1) { + const averageTokensPerRead = Math.floor(data.totalTokens / data.count) + const duplicateTokens = averageTokensPerRead * (data.count - 1) + + stats.duplicateFileReads.set(path, { + count: data.count, + tokens: duplicateTokens, + }) + } + }) + + return stats +} + +function processBlock( + block: ContentBlockParam | ContentBlock | BetaContentBlock, + message: UserMessage | AssistantMessage, + stats: TokenStats, + toolIds: Map, + readToolPaths: Map, + fileReads: Map, +): void { + const tokens = countTokens(jsonStringify(block)) + stats.total += tokens + + switch (block.type) { + case 'text': + // Check if this is a local command output + if ( + message.type === 'user' && + 'text' in block && + block.text.includes('local-command-stdout') + ) { + stats.localCommandOutputs += tokens + } else { + stats[ + message.type === 'user' ? 'humanMessages' : 'assistantMessages' + ] += tokens + } + break + + case 'tool_use': { + if ('name' in block && 'id' in block) { + const toolName = block.name || 'unknown' + increment(stats.toolRequests, toolName, tokens) + toolIds.set(block.id, toolName) + + // Track Read tool file paths + if ( + toolName === 'Read' && + 'input' in block && + block.input && + typeof block.input === 'object' && + 'file_path' in block.input + ) { + const path = String( + (block.input as Record).file_path, + ) + readToolPaths.set(block.id, path) + } + } + break + } + + case 'tool_result': { + if ('tool_use_id' in block) { + const toolName = toolIds.get(block.tool_use_id) || 'unknown' + increment(stats.toolResults, toolName, tokens) + + // Track file read tokens + if (toolName === 'Read') { + const path = readToolPaths.get(block.tool_use_id) + if (path) { + const current = fileReads.get(path) || { count: 0, totalTokens: 0 } + fileReads.set(path, { + count: current.count + 1, + totalTokens: current.totalTokens + tokens, + }) + } + } + } + break + } + + case 'image': + case 'server_tool_use': + case 'web_search_tool_result': + case 'search_result': + case 'document': + case 'thinking': + case 'redacted_thinking': + case 'code_execution_tool_result': + case 'mcp_tool_use': + case 'mcp_tool_result': + case 'container_upload': + case 'web_fetch_tool_result': + case 'bash_code_execution_tool_result': + case 'text_editor_code_execution_tool_result': + case 'tool_search_tool_result': + case 'compaction': + // Don't care about these for now.. + stats['other'] += tokens + break + } +} + +function increment(map: Map, key: string, value: number): void { + map.set(key, (map.get(key) || 0) + value) +} + +export function tokenStatsToStatsigMetrics( + stats: TokenStats, +): Record { + const metrics: Record = { + total_tokens: stats.total, + human_message_tokens: stats.humanMessages, + assistant_message_tokens: stats.assistantMessages, + local_command_output_tokens: stats.localCommandOutputs, + other_tokens: stats.other, + } + + stats.attachments.forEach((count, type) => { + metrics[`attachment_${type}_count`] = count + }) + + stats.toolRequests.forEach((tokens, tool) => { + metrics[`tool_request_${tool}_tokens`] = tokens + }) + + stats.toolResults.forEach((tokens, tool) => { + metrics[`tool_result_${tool}_tokens`] = tokens + }) + + const duplicateTotal = [...stats.duplicateFileReads.values()].reduce( + (sum, d) => sum + d.tokens, + 0, + ) + + metrics.duplicate_read_tokens = duplicateTotal + metrics.duplicate_read_file_count = stats.duplicateFileReads.size + + if (stats.total > 0) { + metrics.human_message_percent = Math.round( + (stats.humanMessages / stats.total) * 100, + ) + metrics.assistant_message_percent = Math.round( + (stats.assistantMessages / stats.total) * 100, + ) + metrics.local_command_output_percent = Math.round( + (stats.localCommandOutputs / stats.total) * 100, + ) + metrics.duplicate_read_percent = Math.round( + (duplicateTotal / stats.total) * 100, + ) + + const toolRequestTotal = [...stats.toolRequests.values()].reduce( + (sum, v) => sum + v, + 0, + ) + const toolResultTotal = [...stats.toolResults.values()].reduce( + (sum, v) => sum + v, + 0, + ) + + metrics.tool_request_percent = Math.round( + (toolRequestTotal / stats.total) * 100, + ) + metrics.tool_result_percent = Math.round( + (toolResultTotal / stats.total) * 100, + ) + + // Add individual tool request percentages + stats.toolRequests.forEach((tokens, tool) => { + metrics[`tool_request_${tool}_percent`] = Math.round( + (tokens / stats.total) * 100, + ) + }) + + // Add individual tool result percentages + stats.toolResults.forEach((tokens, tool) => { + metrics[`tool_result_${tool}_percent`] = Math.round( + (tokens / stats.total) * 100, + ) + }) + } + + return metrics +} diff --git a/_all-in-one-upload/cc-haha/src/utils/conversationRecovery.ts b/_all-in-one-upload/cc-haha/src/utils/conversationRecovery.ts new file mode 100644 index 0000000..af5ea23 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/conversationRecovery.ts @@ -0,0 +1,597 @@ +import { feature } from 'bun:bundle' +import type { UUID } from 'crypto' +import { relative } from 'path' +import { getCwd } from 'src/utils/cwd.js' +import { addInvokedSkill } from '../bootstrap/state.js' +import { asSessionId } from '../types/ids.js' +import type { + AttributionSnapshotMessage, + ContextCollapseCommitEntry, + ContextCollapseSnapshotEntry, + LogOption, + PersistedWorktreeSession, + SerializedMessage, +} from '../types/logs.js' +import type { + Message, + NormalizedMessage, + NormalizedUserMessage, +} from '../types/message.js' +import { PERMISSION_MODES } from '../types/permissions.js' +import { suppressNextSkillListing } from './attachments.js' +import { + copyFileHistoryForResume, + type FileHistorySnapshot, +} from './fileHistory.js' +import { logError } from './log.js' +import { + createAssistantMessage, + createUserMessage, + filterOrphanedThinkingOnlyMessages, + filterUnresolvedToolUses, + filterWhitespaceOnlyAssistantMessages, + isToolUseResultMessage, + NO_RESPONSE_REQUESTED, + normalizeMessages, +} from './messages.js' +import { copyPlanForResume } from './plans.js' +import { processSessionStartHooks } from './sessionStart.js' +import { + buildConversationChain, + checkResumeConsistency, + getLastSessionLog, + getSessionIdFromLog, + isLiteLog, + loadFullLog, + loadMessageLogs, + loadTranscriptFile, + removeExtraFields, +} from './sessionStorage.js' +import type { ContentReplacementRecord } from './toolResultStorage.js' + +// Dead code elimination: ant-only tool names are conditionally required so +// their strings don't leak into external builds. Static imports always bundle. +/* eslint-disable @typescript-eslint/no-require-imports */ +const BRIEF_TOOL_NAME: string | null = + feature('KAIROS') || feature('KAIROS_BRIEF') + ? ( + require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') + ).BRIEF_TOOL_NAME + : null +const LEGACY_BRIEF_TOOL_NAME: string | null = + feature('KAIROS') || feature('KAIROS_BRIEF') + ? ( + require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') + ).LEGACY_BRIEF_TOOL_NAME + : null +const SEND_USER_FILE_TOOL_NAME: string | null = feature('KAIROS') + ? ( + require('../tools/SendUserFileTool/prompt.js') as typeof import('../tools/SendUserFileTool/prompt.js') + ).SEND_USER_FILE_TOOL_NAME + : null +/* eslint-enable @typescript-eslint/no-require-imports */ + +/** + * Transforms legacy attachment types to current types for backward compatibility + */ +function migrateLegacyAttachmentTypes(message: Message): Message { + if (message.type !== 'attachment') { + return message + } + + const attachment = message.attachment as { + type: string + [key: string]: unknown + } // Handle legacy types not in current type system + + // Transform legacy attachment types + if (attachment.type === 'new_file') { + return { + ...message, + attachment: { + ...attachment, + type: 'file', + displayPath: relative(getCwd(), attachment.filename as string), + }, + } as SerializedMessage // Cast entire message since we know the structure is correct + } + + if (attachment.type === 'new_directory') { + return { + ...message, + attachment: { + ...attachment, + type: 'directory', + displayPath: relative(getCwd(), attachment.path as string), + }, + } as SerializedMessage // Cast entire message since we know the structure is correct + } + + // Backfill displayPath for attachments from old sessions + if (!('displayPath' in attachment)) { + const path = + 'filename' in attachment + ? (attachment.filename as string) + : 'path' in attachment + ? (attachment.path as string) + : 'skillDir' in attachment + ? (attachment.skillDir as string) + : undefined + if (path) { + return { + ...message, + attachment: { + ...attachment, + displayPath: relative(getCwd(), path), + }, + } as Message + } + } + + return message +} + +export type TeleportRemoteResponse = { + log: Message[] + branch?: string +} + +export type TurnInterruptionState = + | { kind: 'none' } + | { kind: 'interrupted_prompt'; message: NormalizedUserMessage } + +export type DeserializeResult = { + messages: Message[] + turnInterruptionState: TurnInterruptionState +} + +/** + * Deserializes messages from a log file into the format expected by the REPL. + * Filters unresolved tool uses, orphaned thinking messages, and appends a + * synthetic assistant sentinel when the last message is from the user. + * @internal Exported for testing - use loadConversationForResume instead + */ +export function deserializeMessages(serializedMessages: Message[]): Message[] { + return deserializeMessagesWithInterruptDetection(serializedMessages).messages +} + +/** + * Like deserializeMessages, but also detects whether the session was + * interrupted mid-turn. Used by the SDK resume path to auto-continue + * interrupted turns after a gateway-triggered restart. + * @internal Exported for testing + */ +export function deserializeMessagesWithInterruptDetection( + serializedMessages: Message[], +): DeserializeResult { + try { + // Transform legacy attachment types before processing + const migratedMessages = serializedMessages.map( + migrateLegacyAttachmentTypes, + ) + + // Strip invalid permissionMode values from deserialized user messages. + // The field is unvalidated JSON from disk and may contain modes from a different build. + const validModes = new Set(PERMISSION_MODES) + for (const msg of migratedMessages) { + if ( + msg.type === 'user' && + msg.permissionMode !== undefined && + !validModes.has(msg.permissionMode) + ) { + msg.permissionMode = undefined + } + } + + // Filter out unresolved tool uses and any synthetic messages that follow them + const filteredToolUses = filterUnresolvedToolUses( + migratedMessages, + ) as NormalizedMessage[] + + // Filter out orphaned thinking-only assistant messages that can cause API errors + // during resume. These occur when streaming yields separate messages per content + // block and interleaved user messages prevent proper merging by message.id. + const filteredThinking = filterOrphanedThinkingOnlyMessages( + filteredToolUses, + ) as NormalizedMessage[] + + // Filter out assistant messages with only whitespace text content. + // This can happen when model outputs "\n\n" before thinking, user cancels mid-stream. + const filteredMessages = filterWhitespaceOnlyAssistantMessages( + filteredThinking, + ) as NormalizedMessage[] + + const internalState = detectTurnInterruption(filteredMessages) + + // Transform mid-turn interruptions into interrupted_prompt by appending + // a synthetic continuation message. This unifies both interruption kinds + // so the consumer only needs to handle interrupted_prompt. + let turnInterruptionState: TurnInterruptionState + if (internalState.kind === 'interrupted_turn') { + const [continuationMessage] = normalizeMessages([ + createUserMessage({ + content: 'Continue from where you left off.', + isMeta: true, + }), + ]) + filteredMessages.push(continuationMessage!) + turnInterruptionState = { + kind: 'interrupted_prompt', + message: continuationMessage!, + } + } else { + turnInterruptionState = internalState + } + + // Append a synthetic assistant sentinel after the last user message so + // the conversation is API-valid if no resume action is taken. Skip past + // trailing system/progress messages and insert right after the user + // message so removeInterruptedMessage's splice(idx, 2) removes the + // correct pair. + const lastRelevantIdx = filteredMessages.findLastIndex( + m => m.type !== 'system' && m.type !== 'progress', + ) + if ( + lastRelevantIdx !== -1 && + filteredMessages[lastRelevantIdx]!.type === 'user' + ) { + filteredMessages.splice( + lastRelevantIdx + 1, + 0, + createAssistantMessage({ + content: NO_RESPONSE_REQUESTED, + }) as NormalizedMessage, + ) + } + + return { messages: filteredMessages, turnInterruptionState } + } catch (error) { + logError(error as Error) + throw error + } +} + +/** + * Internal 3-way result from detection, before transforming interrupted_turn + * into interrupted_prompt with a synthetic continuation message. + */ +type InternalInterruptionState = + | TurnInterruptionState + | { kind: 'interrupted_turn' } + +/** + * Determines whether the conversation was interrupted mid-turn based on the + * last message after filtering. An assistant as last message (after filtering + * unresolved tool_uses) is treated as a completed turn because stop_reason is + * always null on persisted messages in the streaming path. + * + * System and progress messages are skipped when finding the last turn-relevant + * message — they are bookkeeping artifacts that should not mask a genuine + * interruption. Attachments are kept as part of the turn. + */ +function detectTurnInterruption( + messages: NormalizedMessage[], +): InternalInterruptionState { + if (messages.length === 0) { + return { kind: 'none' } + } + + // Find the last turn-relevant message, skipping system/progress and + // synthetic API error assistants. Error assistants are already filtered + // before API send (normalizeMessagesForAPI) — skipping them here lets + // auto-resume fire after retry exhaustion instead of reading the error as + // a completed turn. + const lastMessageIdx = messages.findLastIndex( + m => + m.type !== 'system' && + m.type !== 'progress' && + !(m.type === 'assistant' && m.isApiErrorMessage), + ) + const lastMessage = + lastMessageIdx !== -1 ? messages[lastMessageIdx] : undefined + + if (!lastMessage) { + return { kind: 'none' } + } + + if (lastMessage.type === 'assistant') { + // In the streaming path, stop_reason is always null on persisted messages + // because messages are recorded at content_block_stop time, before + // message_delta delivers the stop_reason. After filterUnresolvedToolUses + // has removed assistant messages with unmatched tool_uses, an assistant as + // the last message means the turn most likely completed normally. + return { kind: 'none' } + } + + if (lastMessage.type === 'user') { + if (lastMessage.isMeta || lastMessage.isCompactSummary) { + return { kind: 'none' } + } + if (isToolUseResultMessage(lastMessage)) { + // Brief mode (#20467) drops the trailing assistant text block, so a + // completed brief-mode turn legitimately ends on SendUserMessage's + // tool_result. Without this check, resume misclassifies every + // brief-mode session as interrupted mid-turn and injects a phantom + // "Continue from where you left off." before the user's real next + // prompt. Look back one step for the originating tool_use. + if (isTerminalToolResult(lastMessage, messages, lastMessageIdx)) { + return { kind: 'none' } + } + return { kind: 'interrupted_turn' } + } + // Plain text user prompt — CC hadn't started responding + return { kind: 'interrupted_prompt', message: lastMessage } + } + + if (lastMessage.type === 'attachment') { + // Attachments are part of the user turn — the user provided context but + // the assistant never responded. + return { kind: 'interrupted_turn' } + } + + return { kind: 'none' } +} + +/** + * Is this tool_result the output of a tool that legitimately terminates a + * turn? SendUserMessage is the canonical case: in brief mode, calling it is + * the turn's final act — there is no follow-up assistant text (#20467 + * removed it). A transcript ending here means the turn COMPLETED, not that + * it was killed mid-tool. + * + * Walks back to find the assistant tool_use that this result belongs to and + * checks its name. The matching tool_use is typically the immediately + * preceding relevant message (filterUnresolvedToolUses has already dropped + * unpaired ones), but we walk just in case system/progress noise is + * interleaved. + */ +function isTerminalToolResult( + result: NormalizedUserMessage, + messages: NormalizedMessage[], + resultIdx: number, +): boolean { + const content = result.message.content + if (!Array.isArray(content)) return false + const block = content[0] + if (block?.type !== 'tool_result') return false + const toolUseId = block.tool_use_id + + for (let i = resultIdx - 1; i >= 0; i--) { + const msg = messages[i]! + if (msg.type !== 'assistant') continue + for (const b of msg.message.content) { + if (b.type === 'tool_use' && b.id === toolUseId) { + return ( + b.name === BRIEF_TOOL_NAME || + b.name === LEGACY_BRIEF_TOOL_NAME || + b.name === SEND_USER_FILE_TOOL_NAME + ) + } + } + } + return false +} + +/** + * Restores skill state from invoked_skills attachments in messages. + * This ensures that skills are preserved across resume after compaction. + * Without this, if another compaction happens after resume, the skills would be lost + * because STATE.invokedSkills would be empty. + * @internal Exported for testing - use loadConversationForResume instead + */ +export function restoreSkillStateFromMessages(messages: Message[]): void { + for (const message of messages) { + if (message.type !== 'attachment') { + continue + } + if (message.attachment.type === 'invoked_skills') { + for (const skill of message.attachment.skills) { + if (skill.name && skill.path && skill.content) { + // Resume only happens for the main session, so agentId is null + addInvokedSkill(skill.name, skill.path, skill.content, null) + } + } + } + // A prior process already injected the skills-available reminder — it's + // in the transcript the model is about to see. sentSkillNames is + // process-local, so without this every resume re-announces the same + // ~600 tokens. Fire-once latch; consumed on the first attachment pass. + if (message.attachment.type === 'skill_listing') { + suppressNextSkillListing() + } + } +} + +/** + * Chain-walk a transcript jsonl by path. Same sequence loadFullLog + * runs internally — loadTranscriptFile → find newest non-sidechain + * leaf → buildConversationChain → removeExtraFields — just starting + * from an arbitrary path instead of the sid-derived one. + * + * leafUuids is populated by loadTranscriptFile as "uuids that no + * other message's parentUuid points at" — the chain tips. There can + * be several (sidechains, orphans); newest non-sidechain is the main + * conversation's end. + */ +export async function loadMessagesFromJsonlPath(path: string): Promise<{ + messages: SerializedMessage[] + sessionId: UUID | undefined +}> { + const { messages: byUuid, leafUuids } = await loadTranscriptFile(path) + let tip: (typeof byUuid extends Map ? T : never) | null = null + let tipTs = 0 + for (const m of byUuid.values()) { + if (m.isSidechain || !leafUuids.has(m.uuid)) continue + const ts = new Date(m.timestamp).getTime() + if (ts > tipTs) { + tipTs = ts + tip = m + } + } + if (!tip) return { messages: [], sessionId: undefined } + const chain = buildConversationChain(byUuid, tip) + return { + messages: removeExtraFields(chain), + // Leaf's sessionId — forked sessions copy chain[0] from the source + // transcript, so the root retains the source session's ID. Matches + // loadFullLog's mostRecentLeaf.sessionId. + sessionId: tip.sessionId as UUID | undefined, + } +} + +/** + * Loads a conversation for resume from various sources. + * This is the centralized function for loading and deserializing conversations. + * + * @param source - The source to load from: + * - undefined: load most recent conversation + * - string: session ID to load + * - LogOption: already loaded conversation + * @param sourceJsonlFile - Alternate: path to a transcript jsonl. + * Used when --resume receives a .jsonl path (cli/print.ts routes + * on suffix), typically for cross-directory resume where the + * transcript lives outside the current project dir. + * @returns Object containing the deserialized messages and the original log, or null if not found + */ +export async function loadConversationForResume( + source: string | LogOption | undefined, + sourceJsonlFile: string | undefined, +): Promise<{ + messages: Message[] + turnInterruptionState: TurnInterruptionState + fileHistorySnapshots?: FileHistorySnapshot[] + attributionSnapshots?: AttributionSnapshotMessage[] + contentReplacements?: ContentReplacementRecord[] + contextCollapseCommits?: ContextCollapseCommitEntry[] + contextCollapseSnapshot?: ContextCollapseSnapshotEntry + sessionId: UUID | undefined + // Session metadata for restoring agent context + agentName?: string + agentColor?: string + agentSetting?: string + customTitle?: string + tag?: string + mode?: 'coordinator' | 'normal' + worktreeSession?: PersistedWorktreeSession | null + prNumber?: number + prUrl?: string + prRepository?: string + // Full path to the session file (for cross-directory resume) + fullPath?: string +} | null> { + try { + let log: LogOption | null = null + let messages: Message[] | null = null + let sessionId: UUID | undefined + + if (source === undefined) { + // --continue: most recent session, skipping live --bg/daemon sessions + // that are actively writing their own transcript. + const logsPromise = loadMessageLogs() + let skip = new Set() + if (feature('BG_SESSIONS')) { + try { + const { listAllLiveSessions } = await import('./udsClient.js') + const live = await listAllLiveSessions() + skip = new Set( + live.flatMap(s => + s.kind && s.kind !== 'interactive' && s.sessionId + ? [s.sessionId] + : [], + ), + ) + } catch { + // UDS unavailable — treat all sessions as continuable + } + } + const logs = await logsPromise + log = + logs.find(l => { + const id = getSessionIdFromLog(l) + return !id || !skip.has(id) + }) ?? null + } else if (sourceJsonlFile) { + // --resume with a .jsonl path (cli/print.ts routes on suffix). + // Same chain walk as the sid branch below — only the starting + // path differs. + const loaded = await loadMessagesFromJsonlPath(sourceJsonlFile) + messages = loaded.messages + sessionId = loaded.sessionId + } else if (typeof source === 'string') { + // Load specific session by ID + log = await getLastSessionLog(source as UUID) + sessionId = source as UUID + } else { + // Already have a LogOption + log = source + } + + if (!log && !messages) { + return null + } + + if (log) { + // Load full messages for lite logs + if (isLiteLog(log)) { + log = await loadFullLog(log) + } + + // Determine sessionId first so we can pass it to copy functions + if (!sessionId) { + sessionId = getSessionIdFromLog(log) as UUID + } + // Pass the original session ID to ensure the plan slug is associated with + // the session we're resuming, not the temporary session ID before resume + if (sessionId) { + await copyPlanForResume(log, asSessionId(sessionId)) + } + + // Copy file history for resume + void copyFileHistoryForResume(log) + + messages = log.messages + checkResumeConsistency(messages) + } + + // Restore skill state from invoked_skills attachments before deserialization. + // This ensures skills survive multiple compaction cycles after resume. + restoreSkillStateFromMessages(messages!) + + // Deserialize messages to handle unresolved tool uses and ensure proper format + const deserialized = deserializeMessagesWithInterruptDetection(messages!) + messages = deserialized.messages + + // Process session start hooks for resume + const hookMessages = await processSessionStartHooks('resume', { sessionId }) + + // Append hook messages to the conversation + messages.push(...hookMessages) + + return { + messages, + turnInterruptionState: deserialized.turnInterruptionState, + fileHistorySnapshots: log?.fileHistorySnapshots, + attributionSnapshots: log?.attributionSnapshots, + contentReplacements: log?.contentReplacements, + contextCollapseCommits: log?.contextCollapseCommits, + contextCollapseSnapshot: log?.contextCollapseSnapshot, + sessionId, + // Include session metadata for restoring agent context on resume + agentName: log?.agentName, + agentColor: log?.agentColor, + agentSetting: log?.agentSetting, + customTitle: log?.customTitle, + tag: log?.tag, + mode: log?.mode, + worktreeSession: log?.worktreeSession, + prNumber: log?.prNumber, + prUrl: log?.prUrl, + prRepository: log?.prRepository, + // Include full path for cross-directory resume + fullPath: log?.fullPath, + } + } catch (error) { + logError(error as Error) + throw error + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/crypto.ts b/_all-in-one-upload/cc-haha/src/utils/crypto.ts new file mode 100644 index 0000000..a97fe05 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/crypto.ts @@ -0,0 +1,13 @@ +// Indirection point for the package.json "browser" field. When bun builds +// browser-sdk.js with --target browser, this file is swapped for +// crypto.browser.ts — avoiding a ~500KB crypto-browserify polyfill that Bun +// would otherwise inline for `import ... from 'crypto'`. Node/bun builds use +// this file unchanged. +// +// NOTE: `export { randomUUID } from 'crypto'` (re-export syntax) breaks under +// bun-internal's bytecode compilation — the generated bytecode shows the +// import but the binding doesn't link (`ReferenceError: randomUUID is not +// defined`). The explicit import-then-export below produces a correct live +// binding. See integration-tests-ant-native failure on PR #20957/#21178. +import { randomUUID } from 'crypto' +export { randomUUID } diff --git a/_all-in-one-upload/cc-haha/src/utils/debug.ts b/_all-in-one-upload/cc-haha/src/utils/debug.ts new file mode 100644 index 0000000..220da2b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/debug.ts @@ -0,0 +1,268 @@ +import { appendFile, mkdir, symlink, unlink } from 'fs/promises' +import memoize from 'lodash-es/memoize.js' +import { dirname, join } from 'path' +import { getSessionId } from 'src/bootstrap/state.js' + +import { type BufferedWriter, createBufferedWriter } from './bufferedWriter.js' +import { registerCleanup } from './cleanupRegistry.js' +import { + type DebugFilter, + parseDebugFilter, + shouldShowDebugMessage, +} from './debugFilter.js' +import { getClaudeConfigHomeDir, isEnvTruthy } from './envUtils.js' +import { getFsImplementation } from './fsOperations.js' +import { writeToStderr } from './process.js' +import { jsonStringify } from './slowOperations.js' + +export type DebugLogLevel = 'verbose' | 'debug' | 'info' | 'warn' | 'error' + +const LEVEL_ORDER: Record = { + verbose: 0, + debug: 1, + info: 2, + warn: 3, + error: 4, +} + +/** + * Minimum log level to include in debug output. Defaults to 'debug', which + * filters out 'verbose' messages. Set CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose to + * include high-volume diagnostics (e.g. full statusLine command, shell, cwd, + * stdout/stderr) that would otherwise drown out useful debug output. + */ +export const getMinDebugLogLevel = memoize((): DebugLogLevel => { + const raw = process.env.CLAUDE_CODE_DEBUG_LOG_LEVEL?.toLowerCase().trim() + if (raw && Object.hasOwn(LEVEL_ORDER, raw)) { + return raw as DebugLogLevel + } + return 'debug' +}) + +let runtimeDebugEnabled = false + +export const isDebugMode = memoize((): boolean => { + return ( + runtimeDebugEnabled || + isEnvTruthy(process.env.DEBUG) || + isEnvTruthy(process.env.DEBUG_SDK) || + process.argv.includes('--debug') || + process.argv.includes('-d') || + isDebugToStdErr() || + // Also check for --debug=pattern syntax + process.argv.some(arg => arg.startsWith('--debug=')) || + // --debug-file implicitly enables debug mode + getDebugFilePath() !== null + ) +}) + +/** + * Enables debug logging mid-session (e.g. via /debug). Non-ants don't write + * debug logs by default, so this lets them start capturing without restarting + * with --debug. Returns true if logging was already active. + */ +export function enableDebugLogging(): boolean { + const wasActive = isDebugMode() || process.env.USER_TYPE === 'ant' + runtimeDebugEnabled = true + isDebugMode.cache.clear?.() + return wasActive +} + +// Extract and parse debug filter from command line arguments +// Exported for testing purposes +export const getDebugFilter = memoize((): DebugFilter | null => { + // Look for --debug=pattern in argv + const debugArg = process.argv.find(arg => arg.startsWith('--debug=')) + if (!debugArg) { + return null + } + + // Extract the pattern after the equals sign + const filterPattern = debugArg.substring('--debug='.length) + return parseDebugFilter(filterPattern) +}) + +export const isDebugToStdErr = memoize((): boolean => { + return ( + process.argv.includes('--debug-to-stderr') || process.argv.includes('-d2e') + ) +}) + +export const getDebugFilePath = memoize((): string | null => { + for (let i = 0; i < process.argv.length; i++) { + const arg = process.argv[i]! + if (arg.startsWith('--debug-file=')) { + return arg.substring('--debug-file='.length) + } + if (arg === '--debug-file' && i + 1 < process.argv.length) { + return process.argv[i + 1]! + } + } + return null +}) + +function shouldLogDebugMessage(message: string): boolean { + if (process.env.NODE_ENV === 'test' && !isDebugToStdErr()) { + return false + } + + // Non-ants only write debug logs when debug mode is active (via --debug at + // startup or /debug mid-session). Ants always log for /share, bug reports. + if (process.env.USER_TYPE !== 'ant' && !isDebugMode()) { + return false + } + + if ( + typeof process === 'undefined' || + typeof process.versions === 'undefined' || + typeof process.versions.node === 'undefined' + ) { + return false + } + + const filter = getDebugFilter() + return shouldShowDebugMessage(message, filter) +} + +let hasFormattedOutput = false +export function setHasFormattedOutput(value: boolean): void { + hasFormattedOutput = value +} +export function getHasFormattedOutput(): boolean { + return hasFormattedOutput +} + +let debugWriter: BufferedWriter | null = null +let pendingWrite: Promise = Promise.resolve() + +// Module-level so .bind captures only its explicit args, not the +// writeFn closure's parent scope (Jarred, #22257). +async function appendAsync( + needMkdir: boolean, + dir: string, + path: string, + content: string, +): Promise { + if (needMkdir) { + await mkdir(dir, { recursive: true }).catch(() => {}) + } + await appendFile(path, content) + void updateLatestDebugLogSymlink() +} + +function noop(): void {} + +function getDebugWriter(): BufferedWriter { + if (!debugWriter) { + let ensuredDir: string | null = null + debugWriter = createBufferedWriter({ + writeFn: content => { + const path = getDebugLogPath() + const dir = dirname(path) + const needMkdir = ensuredDir !== dir + ensuredDir = dir + if (isDebugMode()) { + // immediateMode: must stay sync. Async writes are lost on direct + // process.exit() and keep the event loop alive in beforeExit + // handlers (infinite loop with Perfetto tracing). See #22257. + if (needMkdir) { + try { + getFsImplementation().mkdirSync(dir) + } catch { + // Directory already exists + } + } + getFsImplementation().appendFileSync(path, content) + void updateLatestDebugLogSymlink() + return + } + // Buffered path (ants without --debug): flushes ~1/sec so chain + // depth stays ~1. .bind over a closure so only the bound args are + // retained, not this scope. + pendingWrite = pendingWrite + .then(appendAsync.bind(null, needMkdir, dir, path, content)) + .catch(noop) + }, + flushIntervalMs: 1000, + maxBufferSize: 100, + immediateMode: isDebugMode(), + }) + registerCleanup(async () => { + debugWriter?.dispose() + await pendingWrite + }) + } + return debugWriter +} + +export async function flushDebugLogs(): Promise { + debugWriter?.flush() + await pendingWrite +} + +export function logForDebugging( + message: string, + { level }: { level: DebugLogLevel } = { + level: 'debug', + }, +): void { + if (LEVEL_ORDER[level] < LEVEL_ORDER[getMinDebugLogLevel()]) { + return + } + if (!shouldLogDebugMessage(message)) { + return + } + + // Multiline messages break the jsonl output format, so make any multiline messages JSON. + if (hasFormattedOutput && message.includes('\n')) { + message = jsonStringify(message) + } + const timestamp = new Date().toISOString() + const output = `${timestamp} [${level.toUpperCase()}] ${message.trim()}\n` + if (isDebugToStdErr()) { + writeToStderr(output) + return + } + + getDebugWriter().write(output) +} + +export function getDebugLogPath(): string { + return ( + getDebugFilePath() ?? + process.env.CLAUDE_CODE_DEBUG_LOGS_DIR ?? + join(getClaudeConfigHomeDir(), 'debug', `${getSessionId()}.txt`) + ) +} + +/** + * Updates the latest debug log symlink to point to the current debug log file. + * Creates or updates a symlink at ~/.claude/debug/latest + */ +const updateLatestDebugLogSymlink = memoize(async (): Promise => { + try { + const debugLogPath = getDebugLogPath() + const debugLogsDir = dirname(debugLogPath) + const latestSymlinkPath = join(debugLogsDir, 'latest') + + await unlink(latestSymlinkPath).catch(() => {}) + await symlink(debugLogPath, latestSymlinkPath) + } catch { + // Silently fail if symlink creation fails + } +}) + +/** + * Logs errors for Ants only, always visible in production. + */ +export function logAntError(context: string, error: unknown): void { + if (process.env.USER_TYPE !== 'ant') { + return + } + + if (error instanceof Error && error.stack) { + logForDebugging(`[ANT-ONLY] ${context} stack trace:\n${error.stack}`, { + level: 'error', + }) + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/directMemberMessage.ts b/_all-in-one-upload/cc-haha/src/utils/directMemberMessage.ts new file mode 100644 index 0000000..9429601 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/directMemberMessage.ts @@ -0,0 +1,69 @@ +import type { AppState } from '../state/AppState.js' + +/** + * Parse `@agent-name message` syntax for direct team member messaging. + */ +export function parseDirectMemberMessage(input: string): { + recipientName: string + message: string +} | null { + const match = input.match(/^@([\w-]+)\s+(.+)$/s) + if (!match) return null + + const [, recipientName, message] = match + if (!recipientName || !message) return null + + const trimmedMessage = message.trim() + if (!trimmedMessage) return null + + return { recipientName, message: trimmedMessage } +} + +export type DirectMessageResult = + | { success: true; recipientName: string } + | { + success: false + error: 'no_team_context' | 'unknown_recipient' + recipientName?: string + } + +type WriteToMailboxFn = ( + recipientName: string, + message: { from: string; text: string; timestamp: string }, + teamName: string, +) => Promise + +/** + * Send a direct message to a team member, bypassing the model. + */ +export async function sendDirectMemberMessage( + recipientName: string, + message: string, + teamContext: AppState['teamContext'], + writeToMailbox?: WriteToMailboxFn, +): Promise { + if (!teamContext || !writeToMailbox) { + return { success: false, error: 'no_team_context' } + } + + // Find team member by name + const member = Object.values(teamContext.teammates ?? {}).find( + t => t.name === recipientName, + ) + + if (!member) { + return { success: false, error: 'unknown_recipient', recipientName } + } + + await writeToMailbox( + recipientName, + { + from: 'user', + text: message, + timestamp: new Date().toISOString(), + }, + teamContext.teamName, + ) + + return { success: true, recipientName } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/errors.ts b/_all-in-one-upload/cc-haha/src/utils/errors.ts new file mode 100644 index 0000000..6a7f46e --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/errors.ts @@ -0,0 +1,238 @@ +import { APIUserAbortError } from '@anthropic-ai/sdk' + +export class ClaudeError extends Error { + constructor(message: string) { + super(message) + this.name = this.constructor.name + } +} + +export class MalformedCommandError extends Error {} + +export class AbortError extends Error { + constructor(message?: string) { + super(message) + this.name = 'AbortError' + } +} + +/** + * True iff `e` is any of the abort-shaped errors the codebase encounters: + * our AbortError class, a DOMException from AbortController.abort() + * (.name === 'AbortError'), or the SDK's APIUserAbortError. The SDK class + * is checked via instanceof because minified builds mangle class names — + * constructor.name becomes something like 'nJT' and the SDK never sets + * this.name, so string matching silently fails in production. + */ +export function isAbortError(e: unknown): boolean { + return ( + e instanceof AbortError || + e instanceof APIUserAbortError || + (e instanceof Error && e.name === 'AbortError') + ) +} + +/** + * Custom error class for configuration file parsing errors + * Includes the file path and the default configuration that should be used + */ +export class ConfigParseError extends Error { + filePath: string + defaultConfig: unknown + + constructor(message: string, filePath: string, defaultConfig: unknown) { + super(message) + this.name = 'ConfigParseError' + this.filePath = filePath + this.defaultConfig = defaultConfig + } +} + +export class ShellError extends Error { + constructor( + public readonly stdout: string, + public readonly stderr: string, + public readonly code: number, + public readonly interrupted: boolean, + ) { + super('Shell command failed') + this.name = 'ShellError' + } +} + +export class TeleportOperationError extends Error { + constructor( + message: string, + public readonly formattedMessage: string, + ) { + super(message) + this.name = 'TeleportOperationError' + } +} + +/** + * Error with a message that is safe to log to telemetry. + * Use the long name to confirm you've verified the message contains no + * sensitive data (file paths, URLs, code snippets). + * + * Single-arg: same message for user and telemetry + * Two-arg: different messages (e.g., full message has file path, telemetry doesn't) + * + * @example + * // Same message for both + * throw new TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS( + * 'MCP server "slack" connection timed out' + * ) + * + * // Different messages + * throw new TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS( + * `MCP tool timed out after ${ms}ms`, // Full message for logs/user + * 'MCP tool timed out' // Telemetry message + * ) + */ +export class TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS extends Error { + readonly telemetryMessage: string + + constructor(message: string, telemetryMessage?: string) { + super(message) + this.name = 'TelemetrySafeError' + this.telemetryMessage = telemetryMessage ?? message + } +} + +export function hasExactErrorMessage(error: unknown, message: string): boolean { + return error instanceof Error && error.message === message +} + +/** + * Normalize an unknown value into an Error. + * Use at catch-site boundaries when you need an Error instance. + */ +export function toError(e: unknown): Error { + return e instanceof Error ? e : new Error(String(e)) +} + +/** + * Extract a string message from an unknown error-like value. + * Use when you only need the message (e.g., for logging or display). + */ +export function errorMessage(e: unknown): string { + return e instanceof Error ? e.message : String(e) +} + +/** + * Extract the errno code (e.g., 'ENOENT', 'EACCES') from a caught error. + * Returns undefined if the error has no code or is not an ErrnoException. + * Replaces the `(e as NodeJS.ErrnoException).code` cast pattern. + */ +export function getErrnoCode(e: unknown): string | undefined { + if (e && typeof e === 'object' && 'code' in e && typeof e.code === 'string') { + return e.code + } + return undefined +} + +/** + * True if the error is ENOENT (file or directory does not exist). + * Replaces `(e as NodeJS.ErrnoException).code === 'ENOENT'`. + */ +export function isENOENT(e: unknown): boolean { + return getErrnoCode(e) === 'ENOENT' +} + +/** + * Extract the errno path (the filesystem path that triggered the error) + * from a caught error. Returns undefined if the error has no path. + * Replaces the `(e as NodeJS.ErrnoException).path` cast pattern. + */ +export function getErrnoPath(e: unknown): string | undefined { + if (e && typeof e === 'object' && 'path' in e && typeof e.path === 'string') { + return e.path + } + return undefined +} + +/** + * Extract error message + top N stack frames from an unknown error. + * Use when the error flows to the model as a tool_result — full stack + * traces are ~500-2000 chars of mostly-irrelevant internal frames and + * waste context tokens. Keep the full stack in debug logs instead. + */ +export function shortErrorStack(e: unknown, maxFrames = 5): string { + if (!(e instanceof Error)) return String(e) + if (!e.stack) return e.message + // V8/Bun stack format: "Name: message\n at frame1\n at frame2..." + // First line is the message; subsequent " at " lines are frames. + const lines = e.stack.split('\n') + const header = lines[0] ?? e.message + const frames = lines.slice(1).filter(l => l.trim().startsWith('at ')) + if (frames.length <= maxFrames) return e.stack + return [header, ...frames.slice(0, maxFrames)].join('\n') +} + +/** + * True if the error means the path is missing, inaccessible, or + * structurally unreachable — use in catch blocks after fs operations to + * distinguish expected "nothing there / no access" from unexpected errors. + * + * Covers: + * ENOENT — path does not exist + * EACCES — permission denied + * EPERM — operation not permitted + * ENOTDIR — a path component is not a directory (e.g. a file named + * `.claude` exists where a directory is expected) + * ELOOP — too many symlink levels (circular symlinks) + */ +export function isFsInaccessible(e: unknown): e is NodeJS.ErrnoException { + const code = getErrnoCode(e) + return ( + code === 'ENOENT' || + code === 'EACCES' || + code === 'EPERM' || + code === 'ENOTDIR' || + code === 'ELOOP' + ) +} + +export type AxiosErrorKind = + | 'auth' // 401/403 — caller typically sets skipRetry + | 'timeout' // ECONNABORTED + | 'network' // ECONNREFUSED/ENOTFOUND + | 'http' // other axios error (may have status) + | 'other' // not an axios error + +/** + * Classify a caught error from an axios request into one of a few buckets. + * Replaces the ~20-line isAxiosError → 401/403 → ECONNABORTED → ECONNREFUSED + * chain duplicated across sync-style services (settingsSync, policyLimits, + * remoteManagedSettings, teamMemorySync). + * + * Checks the `.isAxiosError` marker property directly (same as + * axios.isAxiosError()) to keep this module dependency-free. + */ +export function classifyAxiosError(e: unknown): { + kind: AxiosErrorKind + status?: number + message: string +} { + const message = errorMessage(e) + if ( + !e || + typeof e !== 'object' || + !('isAxiosError' in e) || + !e.isAxiosError + ) { + return { kind: 'other', message } + } + const err = e as { + response?: { status?: number } + code?: string + } + const status = err.response?.status + if (status === 401 || status === 403) return { kind: 'auth', status, message } + if (err.code === 'ECONNABORTED') return { kind: 'timeout', status, message } + if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') { + return { kind: 'network', status, message } + } + return { kind: 'http', status, message } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/exampleCommands.ts b/_all-in-one-upload/cc-haha/src/utils/exampleCommands.ts new file mode 100644 index 0000000..3aecc67 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/exampleCommands.ts @@ -0,0 +1,184 @@ +import memoize from 'lodash-es/memoize.js' +import sample from 'lodash-es/sample.js' +import { getCwd } from '../utils/cwd.js' +import { getCurrentProjectConfig, saveCurrentProjectConfig } from './config.js' +import { env } from './env.js' +import { execFileNoThrowWithCwd } from './execFileNoThrow.js' +import { getIsGit, gitExe } from './git.js' +import { logError } from './log.js' +import { getGitEmail } from './user.js' + +// Patterns that mark a file as non-core (auto-generated, dependency, or config). +// Used to filter example-command filename suggestions deterministically +// instead of shelling out to Haiku. +const NON_CORE_PATTERNS = [ + // lock / dependency manifests + /(?:^|\/)(?:package-lock\.json|yarn\.lock|bun\.lock|bun\.lockb|pnpm-lock\.yaml|Pipfile\.lock|poetry\.lock|Cargo\.lock|Gemfile\.lock|go\.sum|composer\.lock|uv\.lock)$/, + // generated / build artifacts + /\.generated\./, + /(?:^|\/)(?:dist|build|out|target|node_modules|\.next|__pycache__)\//, + /\.(?:min\.js|min\.css|map|pyc|pyo)$/, + // data / docs / config extensions (not "write a test for" material) + /\.(?:json|ya?ml|toml|xml|ini|cfg|conf|env|lock|txt|md|mdx|rst|csv|log|svg)$/i, + // configuration / metadata + /(?:^|\/)\.?(?:eslintrc|prettierrc|babelrc|editorconfig|gitignore|gitattributes|dockerignore|npmrc)/, + /(?:^|\/)(?:tsconfig|jsconfig|biome|vitest\.config|jest\.config|webpack\.config|vite\.config|rollup\.config)\.[a-z]+$/, + /(?:^|\/)\.(?:github|vscode|idea|claude)\//, + // docs / changelogs (not "how does X work" material) + /(?:^|\/)(?:CHANGELOG|LICENSE|CONTRIBUTING|CODEOWNERS|README)(?:\.[a-z]+)?$/i, +] + +function isCoreFile(path: string): boolean { + return !NON_CORE_PATTERNS.some(p => p.test(path)) +} + +/** + * Counts occurrences of items in an array and returns the top N items + * sorted by count in descending order, formatted as a string. + */ +export function countAndSortItems(items: string[], topN: number = 20): string { + const counts = new Map() + for (const item of items) { + counts.set(item, (counts.get(item) || 0) + 1) + } + return Array.from(counts.entries()) + .sort((a, b) => b[1] - a[1]) + .slice(0, topN) + .map(([item, count]) => `${count.toString().padStart(6)} ${item}`) + .join('\n') +} + +/** + * Picks up to `want` basenames from a frequency-sorted list of paths, + * skipping non-core files and spreading across different directories. + * Returns empty array if fewer than `want` core files are available. + */ +export function pickDiverseCoreFiles( + sortedPaths: string[], + want: number, +): string[] { + const picked: string[] = [] + const seenBasenames = new Set() + const dirTally = new Map() + + // Greedy: on each pass allow +1 file per directory. Keeps the + // top-5 from collapsing into a single hot folder while still + // letting a dominant folder contribute multiple files if the + // repo is narrow. + for (let cap = 1; picked.length < want && cap <= want; cap++) { + for (const p of sortedPaths) { + if (picked.length >= want) break + if (!isCoreFile(p)) continue + const lastSep = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\')) + const base = lastSep >= 0 ? p.slice(lastSep + 1) : p + if (!base || seenBasenames.has(base)) continue + const dir = lastSep >= 0 ? p.slice(0, lastSep) : '.' + if ((dirTally.get(dir) ?? 0) >= cap) continue + picked.push(base) + seenBasenames.add(base) + dirTally.set(dir, (dirTally.get(dir) ?? 0) + 1) + } + } + + return picked.length >= want ? picked : [] +} + +async function getFrequentlyModifiedFiles(): Promise { + if (process.env.NODE_ENV === 'test') return [] + if (env.platform === 'win32') return [] + if (!(await getIsGit())) return [] + + try { + // Collect frequently-modified files, preferring the user's own commits. + const userEmail = await getGitEmail() + + const logArgs = [ + 'log', + '-n', + '1000', + '--pretty=format:', + '--name-only', + '--diff-filter=M', + ] + + const counts = new Map() + const tallyInto = (stdout: string) => { + for (const line of stdout.split('\n')) { + const f = line.trim() + if (f) counts.set(f, (counts.get(f) ?? 0) + 1) + } + } + + if (userEmail) { + const { stdout } = await execFileNoThrowWithCwd( + 'git', + [...logArgs, `--author=${userEmail}`], + { cwd: getCwd() }, + ) + tallyInto(stdout) + } + + // Fall back to all authors if the user's own history is thin. + if (counts.size < 10) { + const { stdout } = await execFileNoThrowWithCwd(gitExe(), logArgs, { + cwd: getCwd(), + }) + tallyInto(stdout) + } + + const sorted = Array.from(counts.entries()) + .sort((a, b) => b[1] - a[1]) + .map(([p]) => p) + + return pickDiverseCoreFiles(sorted, 5) + } catch (err) { + logError(err as Error) + return [] + } +} + +const ONE_WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000 + +export const getExampleCommandFromCache = memoize(() => { + const projectConfig = getCurrentProjectConfig() + const frequentFile = projectConfig.exampleFiles?.length + ? sample(projectConfig.exampleFiles) + : '' + + const commands = [ + 'fix lint errors', + 'fix typecheck errors', + `how does ${frequentFile} work?`, + `refactor ${frequentFile}`, + 'how do I log an error?', + `edit ${frequentFile} to...`, + `write a test for ${frequentFile}`, + 'create a util logging.py that...', + ] + + return `Try "${sample(commands)}"` +}) + +export const refreshExampleCommands = memoize(async (): Promise => { + const projectConfig = getCurrentProjectConfig() + const now = Date.now() + const lastGenerated = projectConfig.exampleFilesGeneratedAt ?? 0 + + // Regenerate examples if they're over a week old + if (now - lastGenerated > ONE_WEEK_IN_MS) { + projectConfig.exampleFiles = [] + } + + // If no example files cached, kickstart fetch in background + if (!projectConfig.exampleFiles?.length) { + void getFrequentlyModifiedFiles().then(files => { + if (files.length) { + saveCurrentProjectConfig(current => ({ + ...current, + exampleFiles: files, + exampleFilesGeneratedAt: Date.now(), + })) + } + }) + } +}) diff --git a/_all-in-one-upload/cc-haha/src/utils/forkedAgent.ts b/_all-in-one-upload/cc-haha/src/utils/forkedAgent.ts new file mode 100644 index 0000000..eff9595 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/forkedAgent.ts @@ -0,0 +1,689 @@ +/** + * Helper for running forked agent query loops with usage tracking. + * + * This utility ensures forked agents: + * 1. Share identical cache-critical params with the parent to guarantee prompt cache hits + * 2. Track full usage metrics across the entire query loop + * 3. Log metrics via the tengu_fork_agent_query event when complete + * 4. Isolate mutable state to prevent interference with the main agent loop + */ + +import type { UUID } from 'crypto' +import { randomUUID } from 'crypto' +import type { PromptCommand } from '../commands.js' +import type { QuerySource } from '../constants/querySource.js' +import type { CanUseToolFn } from '../hooks/useCanUseTool.js' +import { query } from '../query.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../services/analytics/index.js' +import { accumulateUsage, updateUsage } from '../services/api/claude.js' +import { EMPTY_USAGE, type NonNullableUsage } from '../services/api/logging.js' +import type { ToolUseContext } from '../Tool.js' +import type { AgentDefinition } from '../tools/AgentTool/loadAgentsDir.js' +import type { AgentId } from '../types/ids.js' +import type { Message } from '../types/message.js' +import { createChildAbortController } from './abortController.js' +import { logForDebugging } from './debug.js' +import { cloneFileStateCache } from './fileStateCache.js' +import type { REPLHookContext } from './hooks/postSamplingHooks.js' +import { + createUserMessage, + extractTextContent, + getLastAssistantMessage, +} from './messages.js' +import { createDenialTrackingState } from './permissions/denialTracking.js' +import { parseToolListFromCLI } from './permissions/permissionSetup.js' +import { recordSidechainTranscript } from './sessionStorage.js' +import type { SystemPrompt } from './systemPromptType.js' +import { + type ContentReplacementState, + cloneContentReplacementState, +} from './toolResultStorage.js' +import { createAgentId } from './uuid.js' + +/** + * Parameters that must be identical between the fork and parent API requests + * to share the parent's prompt cache. The Anthropic API cache key is composed of: + * system prompt, tools, model, messages (prefix), and thinking config. + * + * CacheSafeParams carries the first five. Thinking config is derived from the + * inherited toolUseContext.options.thinkingConfig — but can be inadvertently + * changed if the fork sets maxOutputTokens, which clamps budget_tokens in + * claude.ts (but only for older models that do not use adaptive thinking). + * See the maxOutputTokens doc on ForkedAgentParams. + */ +export type CacheSafeParams = { + /** System prompt - must match parent for cache hits */ + systemPrompt: SystemPrompt + /** User context - prepended to messages, affects cache */ + userContext: { [k: string]: string } + /** System context - appended to system prompt, affects cache */ + systemContext: { [k: string]: string } + /** Tool use context containing tools, model, and other options */ + toolUseContext: ToolUseContext + /** Parent context messages for prompt cache sharing */ + forkContextMessages: Message[] +} + +// Slot written by handleStopHooks after each turn so post-turn forks +// (promptSuggestion, postTurnSummary, /btw) can share the main loop's +// prompt cache without each caller threading params through. +let lastCacheSafeParams: CacheSafeParams | null = null + +export function saveCacheSafeParams(params: CacheSafeParams | null): void { + lastCacheSafeParams = params +} + +export function getLastCacheSafeParams(): CacheSafeParams | null { + return lastCacheSafeParams +} + +export type ForkedAgentParams = { + /** Messages to start the forked query loop with */ + promptMessages: Message[] + /** Cache-safe parameters that must match the parent query */ + cacheSafeParams: CacheSafeParams + /** Permission check function for the forked agent */ + canUseTool: CanUseToolFn + /** Source identifier for tracking */ + querySource: QuerySource + /** Label for analytics (e.g., 'session_memory', 'supervisor') */ + forkLabel: string + /** Optional overrides for the subagent context (e.g., readFileState from setup phase) */ + overrides?: SubagentContextOverrides + /** + * Optional cap on output tokens. CAUTION: setting this changes both max_tokens + * AND budget_tokens (via clamping in claude.ts). If the fork uses cacheSafeParams + * to share the parent's prompt cache, a different budget_tokens will invalidate + * the cache — thinking config is part of the cache key. Only set this when cache + * sharing is not a goal (e.g., compact summaries). + */ + maxOutputTokens?: number + /** Optional cap on number of turns (API round-trips) */ + maxTurns?: number + /** Optional callback invoked for each message as it arrives (for streaming UI) */ + onMessage?: (message: Message) => void + /** Skip sidechain transcript recording (e.g., for ephemeral work like speculation) */ + skipTranscript?: boolean + /** Skip writing new prompt cache entries on the last message. For + * fire-and-forget forks where no future request will read from this prefix. */ + skipCacheWrite?: boolean +} + +export type ForkedAgentResult = { + /** All messages yielded during the query loop */ + messages: Message[] + /** Accumulated usage across all API calls in the loop */ + totalUsage: NonNullableUsage +} + +/** + * Creates CacheSafeParams from REPLHookContext. + * Use this helper when forking from a post-sampling hook context. + * + * To override specific fields (e.g., toolUseContext with cloned file state), + * spread the result and override: `{ ...createCacheSafeParams(context), toolUseContext: clonedContext }` + * + * @param context - The REPLHookContext from the post-sampling hook + */ +export function createCacheSafeParams( + context: REPLHookContext, +): CacheSafeParams { + return { + systemPrompt: context.systemPrompt, + userContext: context.userContext, + systemContext: context.systemContext, + toolUseContext: context.toolUseContext, + forkContextMessages: context.messages, + } +} + +/** + * Creates a modified getAppState that adds allowed tools to the permission context. + * This is used by forked skill/command execution to grant tool permissions. + */ +export function createGetAppStateWithAllowedTools( + baseGetAppState: ToolUseContext['getAppState'], + allowedTools: string[], +): ToolUseContext['getAppState'] { + if (allowedTools.length === 0) return baseGetAppState + return () => { + const appState = baseGetAppState() + return { + ...appState, + toolPermissionContext: { + ...appState.toolPermissionContext, + alwaysAllowRules: { + ...appState.toolPermissionContext.alwaysAllowRules, + command: [ + ...new Set([ + ...(appState.toolPermissionContext.alwaysAllowRules.command || + []), + ...allowedTools, + ]), + ], + }, + }, + } + } +} + +/** + * Result from preparing a forked command context. + */ +export type PreparedForkedContext = { + /** Skill content with args replaced */ + skillContent: string + /** Modified getAppState with allowed tools */ + modifiedGetAppState: ToolUseContext['getAppState'] + /** The general-purpose agent to use */ + baseAgent: AgentDefinition + /** Initial prompt messages */ + promptMessages: Message[] +} + +/** + * Prepares the context for executing a forked command/skill. + * This handles the common setup that both SkillTool and slash commands need. + */ +export async function prepareForkedCommandContext( + command: PromptCommand, + args: string, + context: ToolUseContext, +): Promise { + // Get skill content with $ARGUMENTS replaced + const skillPrompt = await command.getPromptForCommand(args, context) + const skillContent = skillPrompt + .map(block => (block.type === 'text' ? block.text : '')) + .join('\n') + + // Parse and prepare allowed tools + const allowedTools = parseToolListFromCLI(command.allowedTools ?? []) + + // Create modified context with allowed tools + const modifiedGetAppState = createGetAppStateWithAllowedTools( + context.getAppState, + allowedTools, + ) + + // Use command.agent if specified, otherwise 'general-purpose' + const agentTypeName = command.agent ?? 'general-purpose' + const agents = context.options.agentDefinitions.activeAgents + const baseAgent = + agents.find(a => a.agentType === agentTypeName) ?? + agents.find(a => a.agentType === 'general-purpose') ?? + agents[0] + + if (!baseAgent) { + throw new Error('No agent available for forked execution') + } + + // Prepare prompt messages + const promptMessages = [createUserMessage({ content: skillContent })] + + return { + skillContent, + modifiedGetAppState, + baseAgent, + promptMessages, + } +} + +/** + * Extracts result text from agent messages. + */ +export function extractResultText( + agentMessages: Message[], + defaultText = 'Execution completed', +): string { + const lastAssistantMessage = getLastAssistantMessage(agentMessages) + if (!lastAssistantMessage) return defaultText + + const textContent = extractTextContent( + lastAssistantMessage.message.content, + '\n', + ) + + return textContent || defaultText +} + +/** + * Options for creating a subagent context. + * + * By default, all mutable state is isolated to prevent interference with the parent. + * Use these options to: + * - Override specific fields (e.g., custom options, agentId, messages) + * - Explicitly opt-in to sharing specific callbacks (for interactive subagents) + */ +export type SubagentContextOverrides = { + /** Override the options object (e.g., custom tools, model) */ + options?: ToolUseContext['options'] + /** Override the agentId (for subagents with their own ID) */ + agentId?: AgentId + /** Override the agentType (for subagents with a specific type) */ + agentType?: string + /** Override the messages array */ + messages?: Message[] + /** Override the readFileState (e.g., fresh cache instead of clone) */ + readFileState?: ToolUseContext['readFileState'] + /** Override the abortController */ + abortController?: AbortController + /** Override the getAppState function */ + getAppState?: ToolUseContext['getAppState'] + + /** + * Explicit opt-in to share parent's setAppState callback. + * Use for interactive subagents that need to update shared state. + * @default false (isolated no-op) + */ + shareSetAppState?: boolean + /** + * Explicit opt-in to share parent's setResponseLength callback. + * Use for subagents that contribute to parent's response metrics. + * @default false (isolated no-op) + */ + shareSetResponseLength?: boolean + /** + * Explicit opt-in to share parent's abortController. + * Use for interactive subagents that should abort with parent. + * Note: Only applies if abortController override is not provided. + * @default false (new controller linked to parent) + */ + shareAbortController?: boolean + /** Critical system reminder to re-inject at every user turn */ + criticalSystemReminder_EXPERIMENTAL?: string + /** When true, canUseTool must always be called even when hooks auto-approve. + * Used by speculation for overlay file path rewriting. */ + requireCanUseTool?: boolean + /** Override replacement state — used by resumeAgentBackground to thread + * state reconstructed from the resumed sidechain so the same results + * are re-replaced (prompt cache stability). */ + contentReplacementState?: ContentReplacementState +} + +/** + * Creates an isolated ToolUseContext for subagents. + * + * By default, ALL mutable state is isolated to prevent interference: + * - readFileState: cloned from parent + * - abortController: new controller linked to parent (parent abort propagates) + * - getAppState: wrapped to set shouldAvoidPermissionPrompts + * - All mutation callbacks (setAppState, etc.): no-op + * - Fresh collections: nestedMemoryAttachmentTriggers, toolDecisions + * + * Callers can: + * - Override specific fields via the overrides parameter + * - Explicitly opt-in to sharing specific callbacks (shareSetAppState, etc.) + * + * @param parentContext - The parent's ToolUseContext to create subagent context from + * @param overrides - Optional overrides and sharing options + * + * @example + * // Full isolation (for background agents like session memory) + * const ctx = createSubagentContext(parentContext) + * + * @example + * // Custom options and agentId (for AgentTool async agents) + * const ctx = createSubagentContext(parentContext, { + * options: customOptions, + * agentId: newAgentId, + * messages: initialMessages, + * }) + * + * @example + * // Interactive subagent that shares some state + * const ctx = createSubagentContext(parentContext, { + * options: customOptions, + * agentId: newAgentId, + * shareSetAppState: true, + * shareSetResponseLength: true, + * shareAbortController: true, + * }) + */ +export function createSubagentContext( + parentContext: ToolUseContext, + overrides?: SubagentContextOverrides, +): ToolUseContext { + // Determine abortController: explicit override > share parent's > new child + const abortController = + overrides?.abortController ?? + (overrides?.shareAbortController + ? parentContext.abortController + : createChildAbortController(parentContext.abortController)) + + // Determine getAppState - wrap to set shouldAvoidPermissionPrompts unless sharing abortController + // (if sharing abortController, it's an interactive agent that CAN show UI) + const getAppState: ToolUseContext['getAppState'] = overrides?.getAppState + ? overrides.getAppState + : overrides?.shareAbortController + ? parentContext.getAppState + : () => { + const state = parentContext.getAppState() + if (state.toolPermissionContext.shouldAvoidPermissionPrompts) { + return state + } + return { + ...state, + toolPermissionContext: { + ...state.toolPermissionContext, + shouldAvoidPermissionPrompts: true, + }, + } + } + + return { + // Mutable state - cloned by default to maintain isolation + // Clone overrides.readFileState if provided, otherwise clone from parent + readFileState: cloneFileStateCache( + overrides?.readFileState ?? parentContext.readFileState, + ), + nestedMemoryAttachmentTriggers: new Set(), + loadedNestedMemoryPaths: new Set(), + dynamicSkillDirTriggers: new Set(), + // Per-subagent: tracks skills surfaced by discovery for was_discovered telemetry (SkillTool.ts:116) + discoveredSkillNames: new Set(), + toolDecisions: undefined, + // Budget decisions: override > clone of parent > undefined (feature off). + // + // Clone by default (not fresh): cache-sharing forks process parent + // messages containing parent tool_use_ids. A fresh state would see + // them as unseen and make divergent replacement decisions → wire + // prefix differs → cache miss. A clone makes identical decisions → + // cache hit. For non-forking subagents the parent UUIDs never match + // — clone is a harmless no-op. + // + // Override: AgentTool resume (reconstructed from sidechain records) + // and inProcessRunner (per-teammate persistent loop state). + contentReplacementState: + overrides?.contentReplacementState ?? + (parentContext.contentReplacementState + ? cloneContentReplacementState(parentContext.contentReplacementState) + : undefined), + + // AbortController + abortController, + + // AppState access + getAppState, + setAppState: overrides?.shareSetAppState + ? parentContext.setAppState + : () => {}, + // Task registration/kill must always reach the root store, even when + // setAppState is a no-op — otherwise async agents' background bash tasks + // are never registered and never killed (PPID=1 zombie). + setAppStateForTasks: + parentContext.setAppStateForTasks ?? parentContext.setAppState, + // Async subagents whose setAppState is a no-op need local denial tracking + // so the denial counter actually accumulates across retries. + localDenialTracking: overrides?.shareSetAppState + ? parentContext.localDenialTracking + : createDenialTrackingState(), + + // Mutation callbacks - no-op by default + setInProgressToolUseIDs: () => {}, + setResponseLength: overrides?.shareSetResponseLength + ? parentContext.setResponseLength + : () => {}, + pushApiMetricsEntry: overrides?.shareSetResponseLength + ? parentContext.pushApiMetricsEntry + : undefined, + updateFileHistoryState: () => {}, + // Attribution is scoped and functional (prev => next) — safe to share even + // when setAppState is stubbed. Concurrent calls compose via React's state queue. + updateAttributionState: parentContext.updateAttributionState, + + // UI callbacks - undefined for subagents (can't control parent UI) + addNotification: undefined, + setToolJSX: undefined, + setStreamMode: undefined, + setSDKStatus: undefined, + openMessageSelector: undefined, + + // Fields that can be overridden or copied from parent + options: overrides?.options ?? parentContext.options, + messages: overrides?.messages ?? parentContext.messages, + // Generate new agentId for subagents (each subagent should have its own ID) + agentId: overrides?.agentId ?? createAgentId(), + agentType: overrides?.agentType, + + // Create new query tracking chain for subagent with incremented depth + queryTracking: { + chainId: randomUUID(), + depth: (parentContext.queryTracking?.depth ?? -1) + 1, + }, + fileReadingLimits: parentContext.fileReadingLimits, + userModified: parentContext.userModified, + criticalSystemReminder_EXPERIMENTAL: + overrides?.criticalSystemReminder_EXPERIMENTAL, + requireCanUseTool: overrides?.requireCanUseTool, + } +} + +/** + * Runs a forked agent query loop and tracks cache hit metrics. + * + * This function: + * 1. Uses identical cache-safe params from parent to enable prompt caching + * 2. Accumulates usage across all query iterations + * 3. Logs tengu_fork_agent_query with full usage when complete + * + * @example + * ```typescript + * const result = await runForkedAgent({ + * promptMessages: [createUserMessage({ content: userPrompt })], + * cacheSafeParams: { + * systemPrompt, + * userContext, + * systemContext, + * toolUseContext: clonedToolUseContext, + * forkContextMessages: messages, + * }, + * canUseTool, + * querySource: 'session_memory', + * forkLabel: 'session_memory', + * }) + * ``` + */ +export async function runForkedAgent({ + promptMessages, + cacheSafeParams, + canUseTool, + querySource, + forkLabel, + overrides, + maxOutputTokens, + maxTurns, + onMessage, + skipTranscript, + skipCacheWrite, +}: ForkedAgentParams): Promise { + const startTime = Date.now() + const outputMessages: Message[] = [] + let totalUsage: NonNullableUsage = { ...EMPTY_USAGE } + + const { + systemPrompt, + userContext, + systemContext, + toolUseContext, + forkContextMessages, + } = cacheSafeParams + + // Create isolated context to prevent mutation of parent state + const isolatedToolUseContext = createSubagentContext( + toolUseContext, + overrides, + ) + + // Do NOT filterIncompleteToolCalls here — it drops the whole assistant on + // partial tool batches, orphaning the paired results (API 400). Dangling + // tool_uses are repaired downstream by ensureToolResultPairing in claude.ts, + // same as the main thread — identical post-repair prefix keeps the cache hit. + const initialMessages: Message[] = [...forkContextMessages, ...promptMessages] + + // Generate agent ID and record initial messages for transcript + // When skipTranscript is set, skip agent ID creation and all transcript I/O + const agentId = skipTranscript ? undefined : createAgentId(forkLabel) + let lastRecordedUuid: UUID | null = null + if (agentId) { + await recordSidechainTranscript(initialMessages, agentId).catch(err => + logForDebugging( + `Forked agent [${forkLabel}] failed to record initial transcript: ${err}`, + ), + ) + // Track the last recorded message UUID for parent chain continuity + lastRecordedUuid = + initialMessages.length > 0 + ? initialMessages[initialMessages.length - 1]!.uuid + : null + } + + // Run the query loop with isolated context (cache-safe params preserved) + try { + for await (const message of query({ + messages: initialMessages, + systemPrompt, + userContext, + systemContext, + canUseTool, + toolUseContext: isolatedToolUseContext, + querySource, + maxOutputTokensOverride: maxOutputTokens, + maxTurns, + skipCacheWrite, + })) { + // Extract real usage from message_delta stream events (final usage per API call) + if (message.type === 'stream_event') { + if ( + 'event' in message && + message.event?.type === 'message_delta' && + message.event.usage + ) { + const turnUsage = updateUsage({ ...EMPTY_USAGE }, message.event.usage) + totalUsage = accumulateUsage(totalUsage, turnUsage) + } + continue + } + if (message.type === 'stream_request_start') { + continue + } + + logForDebugging( + `Forked agent [${forkLabel}] received message: type=${message.type}`, + ) + + outputMessages.push(message as Message) + onMessage?.(message as Message) + + // Record transcript for recordable message types (same pattern as runAgent.ts) + const msg = message as Message + if ( + agentId && + (msg.type === 'assistant' || + msg.type === 'user' || + msg.type === 'progress') + ) { + await recordSidechainTranscript([msg], agentId, lastRecordedUuid).catch( + err => + logForDebugging( + `Forked agent [${forkLabel}] failed to record transcript: ${err}`, + ), + ) + if (msg.type !== 'progress') { + lastRecordedUuid = msg.uuid + } + } + } + } finally { + // Release cloned file state cache memory (same pattern as runAgent.ts) + isolatedToolUseContext.readFileState.clear() + // Release the cloned fork context messages + initialMessages.length = 0 + } + + logForDebugging( + `Forked agent [${forkLabel}] finished: ${outputMessages.length} messages, types=[${outputMessages.map(m => m.type).join(', ')}], totalUsage: input=${totalUsage.input_tokens} output=${totalUsage.output_tokens} cacheRead=${totalUsage.cache_read_input_tokens} cacheCreate=${totalUsage.cache_creation_input_tokens}`, + ) + + const durationMs = Date.now() - startTime + + // Log the fork query metrics with full NonNullableUsage + logForkAgentQueryEvent({ + forkLabel, + querySource, + durationMs, + messageCount: outputMessages.length, + totalUsage, + queryTracking: toolUseContext.queryTracking, + }) + + return { + messages: outputMessages, + totalUsage, + } +} + +/** + * Logs the tengu_fork_agent_query event with full NonNullableUsage fields. + */ +function logForkAgentQueryEvent({ + forkLabel, + querySource, + durationMs, + messageCount, + totalUsage, + queryTracking, +}: { + forkLabel: string + querySource: QuerySource + durationMs: number + messageCount: number + totalUsage: NonNullableUsage + queryTracking?: { chainId: string; depth: number } +}): void { + // Calculate cache hit rate + const totalInputTokens = + totalUsage.input_tokens + + totalUsage.cache_creation_input_tokens + + totalUsage.cache_read_input_tokens + const cacheHitRate = + totalInputTokens > 0 + ? totalUsage.cache_read_input_tokens / totalInputTokens + : 0 + + logEvent('tengu_fork_agent_query', { + // Metadata + forkLabel: + forkLabel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + querySource: + querySource as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + durationMs, + messageCount, + + // NonNullableUsage fields + inputTokens: totalUsage.input_tokens, + outputTokens: totalUsage.output_tokens, + cacheReadInputTokens: totalUsage.cache_read_input_tokens, + cacheCreationInputTokens: totalUsage.cache_creation_input_tokens, + serviceTier: + totalUsage.service_tier as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + cacheCreationEphemeral1hTokens: + totalUsage.cache_creation.ephemeral_1h_input_tokens, + cacheCreationEphemeral5mTokens: + totalUsage.cache_creation.ephemeral_5m_input_tokens, + + // Derived metrics + cacheHitRate, + + // Query tracking + ...(queryTracking + ? { + queryChainId: + queryTracking.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + queryDepth: queryTracking.depth, + } + : {}), + }) +} diff --git a/_all-in-one-upload/cc-haha/src/utils/generatedFiles.ts b/_all-in-one-upload/cc-haha/src/utils/generatedFiles.ts new file mode 100644 index 0000000..76d1412 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/generatedFiles.ts @@ -0,0 +1,136 @@ +import { basename, extname, posix, sep } from 'path' + +/** + * File patterns that should be excluded from attribution. + * Based on GitHub Linguist vendored patterns and common generated file patterns. + */ + +// Exact file name matches (case-insensitive) +const EXCLUDED_FILENAMES = new Set([ + 'package-lock.json', + 'yarn.lock', + 'pnpm-lock.yaml', + 'bun.lockb', + 'bun.lock', + 'composer.lock', + 'gemfile.lock', + 'cargo.lock', + 'poetry.lock', + 'pipfile.lock', + 'shrinkwrap.json', + 'npm-shrinkwrap.json', +]) + +// File extension patterns (case-insensitive) +const EXCLUDED_EXTENSIONS = new Set([ + '.lock', + '.min.js', + '.min.css', + '.min.html', + '.bundle.js', + '.bundle.css', + '.generated.ts', + '.generated.js', + '.d.ts', // TypeScript declaration files +]) + +// Directory patterns that indicate generated/vendored content +const EXCLUDED_DIRECTORIES = [ + '/dist/', + '/build/', + '/out/', + '/output/', + '/node_modules/', + '/vendor/', + '/vendored/', + '/third_party/', + '/third-party/', + '/external/', + '/.next/', + '/.nuxt/', + '/.svelte-kit/', + '/coverage/', + '/__pycache__/', + '/.tox/', + '/venv/', + '/.venv/', + '/target/release/', + '/target/debug/', +] + +// Filename patterns using regex for more complex matching +const EXCLUDED_FILENAME_PATTERNS = [ + /^.*\.min\.[a-z]+$/i, // *.min.* + /^.*-min\.[a-z]+$/i, // *-min.* + /^.*\.bundle\.[a-z]+$/i, // *.bundle.* + /^.*\.generated\.[a-z]+$/i, // *.generated.* + /^.*\.gen\.[a-z]+$/i, // *.gen.* + /^.*\.auto\.[a-z]+$/i, // *.auto.* + /^.*_generated\.[a-z]+$/i, // *_generated.* + /^.*_gen\.[a-z]+$/i, // *_gen.* + /^.*\.pb\.(go|js|ts|py|rb)$/i, // Protocol buffer generated files + /^.*_pb2?\.py$/i, // Python protobuf files + /^.*\.pb\.h$/i, // C++ protobuf headers + /^.*\.grpc\.[a-z]+$/i, // gRPC generated files + /^.*\.swagger\.[a-z]+$/i, // Swagger generated files + /^.*\.openapi\.[a-z]+$/i, // OpenAPI generated files +] + +/** + * Check if a file should be excluded from attribution based on Linguist-style rules. + * + * @param filePath - Relative file path from repository root + * @returns true if the file should be excluded from attribution + */ +export function isGeneratedFile(filePath: string): boolean { + // Normalize path separators for consistent pattern matching (patterns use posix-style /) + const normalizedPath = + posix.sep + filePath.split(sep).join(posix.sep).replace(/^\/+/, '') + const fileName = basename(filePath).toLowerCase() + const ext = extname(filePath).toLowerCase() + + // Check exact filename matches + if (EXCLUDED_FILENAMES.has(fileName)) { + return true + } + + // Check extension matches + if (EXCLUDED_EXTENSIONS.has(ext)) { + return true + } + + // Check for compound extensions like .min.js + const parts = fileName.split('.') + if (parts.length > 2) { + const compoundExt = '.' + parts.slice(-2).join('.') + if (EXCLUDED_EXTENSIONS.has(compoundExt)) { + return true + } + } + + // Check directory patterns + for (const dir of EXCLUDED_DIRECTORIES) { + if (normalizedPath.includes(dir)) { + return true + } + } + + // Check filename patterns + for (const pattern of EXCLUDED_FILENAME_PATTERNS) { + if (pattern.test(fileName)) { + return true + } + } + + return false +} + +/** + * Filter a list of files to exclude generated files. + * + * @param files - Array of file paths + * @returns Array of files that are not generated + */ +export function filterGeneratedFiles(files: string[]): string[] { + return files.filter(file => !isGeneratedFile(file)) +} diff --git a/_all-in-one-upload/cc-haha/src/utils/gitSettings.ts b/_all-in-one-upload/cc-haha/src/utils/gitSettings.ts new file mode 100644 index 0000000..f142995 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/gitSettings.ts @@ -0,0 +1,18 @@ +// Git-related behaviors that depend on user settings. +// +// This lives outside git.ts because git.ts is in the vscode extension's +// dep graph and must stay free of settings.ts, which transitively pulls +// @opentelemetry/api + undici (forbidden in vscode). It's also a cycle: +// settings.ts → git/gitignore.ts → git.ts, so git.ts → settings.ts loops. +// +// If you're tempted to add `import settings` to git.ts — don't. Put it here. + +import { isEnvDefinedFalsy, isEnvTruthy } from './envUtils.js' +import { getInitialSettings } from './settings/settings.js' + +export function shouldIncludeGitInstructions(): boolean { + const envVal = process.env.CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS + if (isEnvTruthy(envVal)) return false + if (isEnvDefinedFalsy(envVal)) return true + return getInitialSettings().includeGitInstructions ?? true +} diff --git a/_all-in-one-upload/cc-haha/src/utils/headlessProfiler.ts b/_all-in-one-upload/cc-haha/src/utils/headlessProfiler.ts new file mode 100644 index 0000000..50aadaf --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/headlessProfiler.ts @@ -0,0 +1,178 @@ +/** + * Headless mode profiling utility for measuring per-turn latency in -p (print) mode. + * + * Tracks key timing phases per turn: + * - Time to system message output (turn 0 only) + * - Time to first query started + * - Time to first API response (TTFT) + * + * Uses Node.js built-in performance hooks API for standard timing measurement. + * Sampled logging: 100% of ant users, 5% of external users. + * + * Set CLAUDE_CODE_PROFILE_STARTUP=1 for detailed logging output. + */ + +import { getIsNonInteractiveSession } from '../bootstrap/state.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../services/analytics/index.js' +import { logForDebugging } from './debug.js' +import { isEnvTruthy } from './envUtils.js' +import { getPerformance } from './profilerBase.js' +import { jsonStringify } from './slowOperations.js' + +// Detailed profiling mode - same env var as startupProfiler +// eslint-disable-next-line custom-rules/no-process-env-top-level +const DETAILED_PROFILING = isEnvTruthy(process.env.CLAUDE_CODE_PROFILE_STARTUP) + +// Sampling for Statsig logging: 100% ant, 5% external +// Decision made once at module load - non-sampled users pay no profiling cost +const STATSIG_SAMPLE_RATE = 0.05 +// eslint-disable-next-line custom-rules/no-process-env-top-level +const STATSIG_LOGGING_SAMPLED = + process.env.USER_TYPE === 'ant' || Math.random() < STATSIG_SAMPLE_RATE + +// Enable profiling if either detailed mode OR sampled for Statsig +const SHOULD_PROFILE = DETAILED_PROFILING || STATSIG_LOGGING_SAMPLED + +// Use a unique prefix to avoid conflicts with other profiler marks +const MARK_PREFIX = 'headless_' + +// Track current turn number (auto-incremented by headlessProfilerStartTurn) +let currentTurnNumber = -1 + +/** + * Clear all headless profiler marks from performance timeline + */ +function clearHeadlessMarks(): void { + const perf = getPerformance() + const allMarks = perf.getEntriesByType('mark') + for (const mark of allMarks) { + if (mark.name.startsWith(MARK_PREFIX)) { + perf.clearMarks(mark.name) + } + } +} + +/** + * Start a new turn for profiling. Clears previous marks, increments turn number, + * and records turn_start. Call this at the beginning of each user message processing. + */ +export function headlessProfilerStartTurn(): void { + // Only profile in headless/non-interactive mode + if (!getIsNonInteractiveSession()) return + // Only profile if enabled + if (!SHOULD_PROFILE) return + + currentTurnNumber++ + clearHeadlessMarks() + + const perf = getPerformance() + perf.mark(`${MARK_PREFIX}turn_start`) + + if (DETAILED_PROFILING) { + logForDebugging(`[headlessProfiler] Started turn ${currentTurnNumber}`) + } +} + +/** + * Record a checkpoint with the given name. + * Only records if in headless mode and profiling is enabled. + */ +export function headlessProfilerCheckpoint(name: string): void { + // Only profile in headless/non-interactive mode + if (!getIsNonInteractiveSession()) return + // Only profile if enabled + if (!SHOULD_PROFILE) return + + const perf = getPerformance() + perf.mark(`${MARK_PREFIX}${name}`) + + if (DETAILED_PROFILING) { + logForDebugging( + `[headlessProfiler] Checkpoint: ${name} at ${perf.now().toFixed(1)}ms`, + ) + } +} + +/** + * Log headless latency metrics for the current turn to Statsig. + * Call this at the end of each turn (before processing next user message). + */ +export function logHeadlessProfilerTurn(): void { + // Only log in headless mode + if (!getIsNonInteractiveSession()) return + // Only log if enabled + if (!SHOULD_PROFILE) return + + const perf = getPerformance() + const allMarks = perf.getEntriesByType('mark') + + // Filter to only our headless marks + const marks = allMarks.filter(mark => mark.name.startsWith(MARK_PREFIX)) + if (marks.length === 0) return + + // Build checkpoint lookup (strip prefix for easier access) + const checkpointTimes = new Map() + for (const mark of marks) { + const name = mark.name.slice(MARK_PREFIX.length) + checkpointTimes.set(name, mark.startTime) + } + + const turnStart = checkpointTimes.get('turn_start') + if (turnStart === undefined) return + + // Compute phase durations relative to turn_start + const metadata: Record = { + turn_number: currentTurnNumber, + } + + // Time to system message from process start (only meaningful for turn 0) + // Use absolute time since perf_hooks startTime is relative to process start + const systemMessageTime = checkpointTimes.get('system_message_yielded') + if (systemMessageTime !== undefined && currentTurnNumber === 0) { + metadata.time_to_system_message_ms = Math.round(systemMessageTime) + } + + // Time to query start + const queryStartTime = checkpointTimes.get('query_started') + if (queryStartTime !== undefined) { + metadata.time_to_query_start_ms = Math.round(queryStartTime - turnStart) + } + + // Time to first response (first chunk from API) + const firstChunkTime = checkpointTimes.get('first_chunk') + if (firstChunkTime !== undefined) { + metadata.time_to_first_response_ms = Math.round(firstChunkTime - turnStart) + } + + // Query overhead (time between query start and API request sent) + const apiRequestTime = checkpointTimes.get('api_request_sent') + if (queryStartTime !== undefined && apiRequestTime !== undefined) { + metadata.query_overhead_ms = Math.round(apiRequestTime - queryStartTime) + } + + // Add checkpoint count for debugging + metadata.checkpoint_count = marks.length + + // Add entrypoint for segmentation (sdk-ts, sdk-py, sdk-cli, or undefined) + if (process.env.CLAUDE_CODE_ENTRYPOINT) { + metadata.entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT + } + + // Log to Statsig if sampled + if (STATSIG_LOGGING_SAMPLED) { + logEvent( + 'tengu_headless_latency', + metadata as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ) + } + + // Log detailed output if CLAUDE_CODE_PROFILE_STARTUP=1 + if (DETAILED_PROFILING) { + logForDebugging( + `[headlessProfiler] Turn ${currentTurnNumber} metrics: ${jsonStringify(metadata)}`, + ) + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/hooks/fileChangedWatcher.ts b/_all-in-one-upload/cc-haha/src/utils/hooks/fileChangedWatcher.ts new file mode 100644 index 0000000..3d5f771 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/hooks/fileChangedWatcher.ts @@ -0,0 +1,191 @@ +import chokidar, { type FSWatcher } from 'chokidar' +import { isAbsolute, join } from 'path' +import { registerCleanup } from '../cleanupRegistry.js' +import { logForDebugging } from '../debug.js' +import { errorMessage } from '../errors.js' +import { + executeCwdChangedHooks, + executeFileChangedHooks, + type HookOutsideReplResult, +} from '../hooks.js' +import { clearCwdEnvFiles } from '../sessionEnvironment.js' +import { getHooksConfigFromSnapshot } from './hooksConfigSnapshot.js' + +let watcher: FSWatcher | null = null +let currentCwd: string +let dynamicWatchPaths: string[] = [] +let dynamicWatchPathsSorted: string[] = [] +let initialized = false +let hasEnvHooks = false +let notifyCallback: ((text: string, isError: boolean) => void) | null = null + +export function setEnvHookNotifier( + cb: ((text: string, isError: boolean) => void) | null, +): void { + notifyCallback = cb +} + +export function initializeFileChangedWatcher(cwd: string): void { + if (initialized) return + initialized = true + currentCwd = cwd + + const config = getHooksConfigFromSnapshot() + hasEnvHooks = + (config?.CwdChanged?.length ?? 0) > 0 || + (config?.FileChanged?.length ?? 0) > 0 + + if (hasEnvHooks) { + registerCleanup(async () => dispose()) + } + + const paths = resolveWatchPaths(config) + if (paths.length === 0) return + + startWatching(paths) +} + +function resolveWatchPaths( + config?: ReturnType, +): string[] { + const matchers = (config ?? getHooksConfigFromSnapshot())?.FileChanged ?? [] + + // Matcher field: filenames to watch in cwd, pipe-separated (e.g. ".envrc|.env") + const staticPaths: string[] = [] + for (const m of matchers) { + if (!m.matcher) continue + for (const name of m.matcher.split('|').map(s => s.trim())) { + if (!name) continue + staticPaths.push(isAbsolute(name) ? name : join(currentCwd, name)) + } + } + + // Combine static matcher paths with dynamic paths from hook output + return [...new Set([...staticPaths, ...dynamicWatchPaths])] +} + +function startWatching(paths: string[]): void { + logForDebugging(`FileChanged: watching ${paths.length} paths`) + watcher = chokidar.watch(paths, { + persistent: true, + ignoreInitial: true, + awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 200 }, + ignorePermissionErrors: true, + }) + watcher.on('change', p => handleFileEvent(p, 'change')) + watcher.on('add', p => handleFileEvent(p, 'add')) + watcher.on('unlink', p => handleFileEvent(p, 'unlink')) +} + +function handleFileEvent( + path: string, + event: 'change' | 'add' | 'unlink', +): void { + logForDebugging(`FileChanged: ${event} ${path}`) + void executeFileChangedHooks(path, event) + .then(({ results, watchPaths, systemMessages }) => { + if (watchPaths.length > 0) { + updateWatchPaths(watchPaths) + } + for (const msg of systemMessages) { + notifyCallback?.(msg, false) + } + for (const r of results) { + if (!r.succeeded && r.output) { + notifyCallback?.(r.output, true) + } + } + }) + .catch(e => { + const msg = errorMessage(e) + logForDebugging(`FileChanged hook failed: ${msg}`, { + level: 'error', + }) + notifyCallback?.(msg, true) + }) +} + +export function updateWatchPaths(paths: string[]): void { + if (!initialized) return + const sorted = paths.slice().sort() + if ( + sorted.length === dynamicWatchPathsSorted.length && + sorted.every((p, i) => p === dynamicWatchPathsSorted[i]) + ) { + return + } + dynamicWatchPaths = paths + dynamicWatchPathsSorted = sorted + restartWatching() +} + +function restartWatching(): void { + if (watcher) { + void watcher.close() + watcher = null + } + const paths = resolveWatchPaths() + if (paths.length > 0) { + startWatching(paths) + } +} + +export async function onCwdChangedForHooks( + oldCwd: string, + newCwd: string, +): Promise { + if (oldCwd === newCwd) return + + // Re-evaluate from the current snapshot so mid-session hook changes are picked up + const config = getHooksConfigFromSnapshot() + const currentHasEnvHooks = + (config?.CwdChanged?.length ?? 0) > 0 || + (config?.FileChanged?.length ?? 0) > 0 + if (!currentHasEnvHooks) return + currentCwd = newCwd + + await clearCwdEnvFiles() + const hookResult = await executeCwdChangedHooks(oldCwd, newCwd).catch(e => { + const msg = errorMessage(e) + logForDebugging(`CwdChanged hook failed: ${msg}`, { + level: 'error', + }) + notifyCallback?.(msg, true) + return { + results: [] as HookOutsideReplResult[], + watchPaths: [] as string[], + systemMessages: [] as string[], + } + }) + dynamicWatchPaths = hookResult.watchPaths + dynamicWatchPathsSorted = hookResult.watchPaths.slice().sort() + for (const msg of hookResult.systemMessages) { + notifyCallback?.(msg, false) + } + for (const r of hookResult.results) { + if (!r.succeeded && r.output) { + notifyCallback?.(r.output, true) + } + } + + // Re-resolve matcher paths against the new cwd + if (initialized) { + restartWatching() + } +} + +function dispose(): void { + if (watcher) { + void watcher.close() + watcher = null + } + dynamicWatchPaths = [] + dynamicWatchPathsSorted = [] + initialized = false + hasEnvHooks = false + notifyCallback = null +} + +export function resetFileChangedWatcherForTesting(): void { + dispose() +} diff --git a/_all-in-one-upload/cc-haha/src/utils/hooks/hooksConfigManager.ts b/_all-in-one-upload/cc-haha/src/utils/hooks/hooksConfigManager.ts new file mode 100644 index 0000000..c7c5a0d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/hooks/hooksConfigManager.ts @@ -0,0 +1,400 @@ +import memoize from 'lodash-es/memoize.js' +import type { HookEvent } from 'src/entrypoints/agentSdkTypes.js' +import { getRegisteredHooks } from '../../bootstrap/state.js' +import type { AppState } from '../../state/AppState.js' +import { + getAllHooks, + type IndividualHookConfig, + sortMatchersByPriority, +} from './hooksSettings.js' + +export type MatcherMetadata = { + fieldToMatch: string + values: string[] +} + +export type HookEventMetadata = { + summary: string + description: string + matcherMetadata?: MatcherMetadata +} + +// Hook event metadata configuration. +// Resolver uses sorted-joined string key so that callers passing a fresh +// toolNames array each render (e.g. HooksConfigMenu) hit the cache instead +// of leaking a new entry per call. +export const getHookEventMetadata = memoize( + function (toolNames: string[]): Record { + return { + PreToolUse: { + summary: 'Before tool execution', + description: + 'Input to command is JSON of tool call arguments.\nExit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to model and block tool call\nOther exit codes - show stderr to user only but continue with tool call', + matcherMetadata: { + fieldToMatch: 'tool_name', + values: toolNames, + }, + }, + PostToolUse: { + summary: 'After tool execution', + description: + 'Input to command is JSON with fields "inputs" (tool call arguments) and "response" (tool call response).\nExit code 0 - stdout shown in transcript mode (ctrl+o)\nExit code 2 - show stderr to model immediately\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'tool_name', + values: toolNames, + }, + }, + PostToolUseFailure: { + summary: 'After tool execution fails', + description: + 'Input to command is JSON with tool_name, tool_input, tool_use_id, error, error_type, is_interrupt, and is_timeout.\nExit code 0 - stdout shown in transcript mode (ctrl+o)\nExit code 2 - show stderr to model immediately\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'tool_name', + values: toolNames, + }, + }, + PermissionDenied: { + summary: 'After auto mode classifier denies a tool call', + description: + 'Input to command is JSON with tool_name, tool_input, tool_use_id, and reason.\nReturn {"hookSpecificOutput":{"hookEventName":"PermissionDenied","retry":true}} to tell the model it may retry.\nExit code 0 - stdout shown in transcript mode (ctrl+o)\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'tool_name', + values: toolNames, + }, + }, + Notification: { + summary: 'When notifications are sent', + description: + 'Input to command is JSON with notification message and type.\nExit code 0 - stdout/stderr not shown\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'notification_type', + values: [ + 'permission_prompt', + 'idle_prompt', + 'auth_success', + 'elicitation_dialog', + 'elicitation_complete', + 'elicitation_response', + ], + }, + }, + UserPromptSubmit: { + summary: 'When the user submits a prompt', + description: + 'Input to command is JSON with original user prompt text.\nExit code 0 - stdout shown to Claude\nExit code 2 - block processing, erase original prompt, and show stderr to user only\nOther exit codes - show stderr to user only', + }, + SessionStart: { + summary: 'When a new session is started', + description: + 'Input to command is JSON with session start source.\nExit code 0 - stdout shown to Claude\nBlocking errors are ignored\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'source', + values: ['startup', 'resume', 'clear', 'compact'], + }, + }, + Stop: { + summary: 'Right before Claude concludes its response', + description: + 'Exit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to model and continue conversation\nOther exit codes - show stderr to user only', + }, + StopFailure: { + summary: 'When the turn ends due to an API error', + description: + 'Fires instead of Stop when an API error (rate limit, auth failure, etc.) ended the turn. Fire-and-forget — hook output and exit codes are ignored.', + matcherMetadata: { + fieldToMatch: 'error', + values: [ + 'rate_limit', + 'authentication_failed', + 'billing_error', + 'invalid_request', + 'server_error', + 'max_output_tokens', + 'unknown', + ], + }, + }, + SubagentStart: { + summary: 'When a subagent (Agent tool call) is started', + description: + 'Input to command is JSON with agent_id and agent_type.\nExit code 0 - stdout shown to subagent\nBlocking errors are ignored\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'agent_type', + values: [], // Will be populated with available agent types + }, + }, + SubagentStop: { + summary: + 'Right before a subagent (Agent tool call) concludes its response', + description: + 'Input to command is JSON with agent_id, agent_type, and agent_transcript_path.\nExit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to subagent and continue having it run\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'agent_type', + values: [], // Will be populated with available agent types + }, + }, + PreCompact: { + summary: 'Before conversation compaction', + description: + 'Input to command is JSON with compaction details.\nExit code 0 - stdout appended as custom compact instructions\nExit code 2 - block compaction\nOther exit codes - show stderr to user only but continue with compaction', + matcherMetadata: { + fieldToMatch: 'trigger', + values: ['manual', 'auto'], + }, + }, + PostCompact: { + summary: 'After conversation compaction', + description: + 'Input to command is JSON with compaction details and the summary.\nExit code 0 - stdout shown to user\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'trigger', + values: ['manual', 'auto'], + }, + }, + SessionEnd: { + summary: 'When a session is ending', + description: + 'Input to command is JSON with session end reason.\nExit code 0 - command completes successfully\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'reason', + values: ['clear', 'logout', 'prompt_input_exit', 'other'], + }, + }, + PermissionRequest: { + summary: 'When a permission dialog is displayed', + description: + 'Input to command is JSON with tool_name, tool_input, and tool_use_id.\nOutput JSON with hookSpecificOutput containing decision to allow or deny.\nExit code 0 - use hook decision if provided\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'tool_name', + values: toolNames, + }, + }, + Setup: { + summary: 'Repo setup hooks for init and maintenance', + description: + 'Input to command is JSON with trigger (init or maintenance).\nExit code 0 - stdout shown to Claude\nBlocking errors are ignored\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'trigger', + values: ['init', 'maintenance'], + }, + }, + TeammateIdle: { + summary: 'When a teammate is about to go idle', + description: + 'Input to command is JSON with teammate_name and team_name.\nExit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to teammate and prevent idle (teammate continues working)\nOther exit codes - show stderr to user only', + }, + TaskCreated: { + summary: 'When a task is being created', + description: + 'Input to command is JSON with task_id, task_subject, task_description, teammate_name, and team_name.\nExit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to model and prevent task creation\nOther exit codes - show stderr to user only', + }, + TaskCompleted: { + summary: 'When a task is being marked as completed', + description: + 'Input to command is JSON with task_id, task_subject, task_description, teammate_name, and team_name.\nExit code 0 - stdout/stderr not shown\nExit code 2 - show stderr to model and prevent task completion\nOther exit codes - show stderr to user only', + }, + Elicitation: { + summary: 'When an MCP server requests user input (elicitation)', + description: + 'Input to command is JSON with mcp_server_name, message, and requested_schema.\nOutput JSON with hookSpecificOutput containing action (accept/decline/cancel) and optional content.\nExit code 0 - use hook response if provided\nExit code 2 - deny the elicitation\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'mcp_server_name', + values: [], + }, + }, + ElicitationResult: { + summary: 'After a user responds to an MCP elicitation', + description: + 'Input to command is JSON with mcp_server_name, action, content, mode, and elicitation_id.\nOutput JSON with hookSpecificOutput containing optional action and content to override the response.\nExit code 0 - use hook response if provided\nExit code 2 - block the response (action becomes decline)\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'mcp_server_name', + values: [], + }, + }, + ConfigChange: { + summary: 'When configuration files change during a session', + description: + 'Input to command is JSON with source (user_settings, project_settings, local_settings, policy_settings, skills) and file_path.\nExit code 0 - allow the change\nExit code 2 - block the change from being applied to the session\nOther exit codes - show stderr to user only', + matcherMetadata: { + fieldToMatch: 'source', + values: [ + 'user_settings', + 'project_settings', + 'local_settings', + 'policy_settings', + 'skills', + ], + }, + }, + InstructionsLoaded: { + summary: 'When an instruction file (CLAUDE.md or rule) is loaded', + description: + 'Input to command is JSON with file_path, memory_type (User, Project, Local, Managed), load_reason (session_start, nested_traversal, path_glob_match, include, compact), globs (optional — the paths: frontmatter patterns that matched), trigger_file_path (optional — the file Claude touched that caused the load), and parent_file_path (optional — the file that @-included this one).\nExit code 0 - command completes successfully\nOther exit codes - show stderr to user only\nThis hook is observability-only and does not support blocking.', + matcherMetadata: { + fieldToMatch: 'load_reason', + values: [ + 'session_start', + 'nested_traversal', + 'path_glob_match', + 'include', + 'compact', + ], + }, + }, + WorktreeCreate: { + summary: 'Create an isolated worktree for VCS-agnostic isolation', + description: + 'Input to command is JSON with name (suggested worktree slug).\nStdout should contain the absolute path to the created worktree directory.\nExit code 0 - worktree created successfully\nOther exit codes - worktree creation failed', + }, + WorktreeRemove: { + summary: 'Remove a previously created worktree', + description: + 'Input to command is JSON with worktree_path (absolute path to worktree).\nExit code 0 - worktree removed successfully\nOther exit codes - show stderr to user only', + }, + CwdChanged: { + summary: 'After the working directory changes', + description: + 'Input to command is JSON with old_cwd and new_cwd.\nCLAUDE_ENV_FILE is set — write bash exports there to apply env to subsequent BashTool commands.\nHook output can include hookSpecificOutput.watchPaths (array of absolute paths) to register with the FileChanged watcher.\nExit code 0 - command completes successfully\nOther exit codes - show stderr to user only', + }, + FileChanged: { + summary: 'When a watched file changes', + description: + 'Input to command is JSON with file_path and event (change, add, unlink).\nCLAUDE_ENV_FILE is set — write bash exports there to apply env to subsequent BashTool commands.\nThe matcher field specifies filenames to watch in the current directory (e.g. ".envrc|.env").\nHook output can include hookSpecificOutput.watchPaths (array of absolute paths) to dynamically update the watch list.\nExit code 0 - command completes successfully\nOther exit codes - show stderr to user only', + }, + } + }, + toolNames => toolNames.slice().sort().join(','), +) + +// Group hooks by event and matcher +export function groupHooksByEventAndMatcher( + appState: AppState, + toolNames: string[], +): Record> { + const grouped: Record> = { + PreToolUse: {}, + PostToolUse: {}, + PostToolUseFailure: {}, + PermissionDenied: {}, + Notification: {}, + UserPromptSubmit: {}, + SessionStart: {}, + SessionEnd: {}, + Stop: {}, + StopFailure: {}, + SubagentStart: {}, + SubagentStop: {}, + PreCompact: {}, + PostCompact: {}, + PermissionRequest: {}, + Setup: {}, + TeammateIdle: {}, + TaskCreated: {}, + TaskCompleted: {}, + Elicitation: {}, + ElicitationResult: {}, + ConfigChange: {}, + WorktreeCreate: {}, + WorktreeRemove: {}, + InstructionsLoaded: {}, + CwdChanged: {}, + FileChanged: {}, + } + + const metadata = getHookEventMetadata(toolNames) + + // Include hooks from settings files + getAllHooks(appState).forEach(hook => { + const eventGroup = grouped[hook.event] + if (eventGroup) { + // For events without matchers, use empty string as key + const matcherKey = + metadata[hook.event].matcherMetadata !== undefined + ? hook.matcher || '' + : '' + if (!eventGroup[matcherKey]) { + eventGroup[matcherKey] = [] + } + eventGroup[matcherKey].push(hook) + } + }) + + // Include registered hooks (e.g., plugin hooks) + const registeredHooks = getRegisteredHooks() + if (registeredHooks) { + for (const [event, matchers] of Object.entries(registeredHooks)) { + const hookEvent = event as HookEvent + const eventGroup = grouped[hookEvent] + if (!eventGroup) continue + + for (const matcher of matchers) { + const matcherKey = matcher.matcher || '' + + // Only PluginHookMatcher has pluginRoot; HookCallbackMatcher (internal + // callbacks like attributionHooks, sessionFileAccessHooks) does not. + if ('pluginRoot' in matcher) { + eventGroup[matcherKey] ??= [] + for (const hook of matcher.hooks) { + eventGroup[matcherKey].push({ + event: hookEvent, + config: hook, + matcher: matcher.matcher, + source: 'pluginHook', + pluginName: matcher.pluginId, + }) + } + } else if (process.env.USER_TYPE === 'ant') { + eventGroup[matcherKey] ??= [] + for (const _hook of matcher.hooks) { + eventGroup[matcherKey].push({ + event: hookEvent, + config: { + type: 'command', + command: '[ANT-ONLY] Built-in Hook', + }, + matcher: matcher.matcher, + source: 'builtinHook', + }) + } + } + } + } + } + + return grouped +} + +// Get sorted matchers for a specific event +export function getSortedMatchersForEvent( + hooksByEventAndMatcher: Record< + HookEvent, + Record + >, + event: HookEvent, +): string[] { + const matchers = Object.keys(hooksByEventAndMatcher[event] || {}) + return sortMatchersByPriority(matchers, hooksByEventAndMatcher, event) +} + +// Get hooks for a specific event and matcher +export function getHooksForMatcher( + hooksByEventAndMatcher: Record< + HookEvent, + Record + >, + event: HookEvent, + matcher: string | null, +): IndividualHookConfig[] { + // For events without matchers, hooks are stored with empty string as key + // because the record keys must be strings. + const matcherKey = matcher ?? '' + return hooksByEventAndMatcher[event]?.[matcherKey] ?? [] +} + +// Get metadata for a specific event's matcher +export function getMatcherMetadata( + event: HookEvent, + toolNames: string[], +): MatcherMetadata | undefined { + return getHookEventMetadata(toolNames)[event].matcherMetadata +} diff --git a/_all-in-one-upload/cc-haha/src/utils/iTermBackup.ts b/_all-in-one-upload/cc-haha/src/utils/iTermBackup.ts new file mode 100644 index 0000000..10c6bbf --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/iTermBackup.ts @@ -0,0 +1,73 @@ +import { copyFile, stat } from 'fs/promises' +import { homedir } from 'os' +import { join } from 'path' +import { getGlobalConfig, saveGlobalConfig } from './config.js' +import { logError } from './log.js' + +export function markITerm2SetupComplete(): void { + saveGlobalConfig(current => ({ + ...current, + iterm2SetupInProgress: false, + })) +} + +function getIterm2RecoveryInfo(): { + inProgress: boolean + backupPath: string | null +} { + const config = getGlobalConfig() + return { + inProgress: config.iterm2SetupInProgress ?? false, + backupPath: config.iterm2BackupPath || null, + } +} + +function getITerm2PlistPath(): string { + return join( + homedir(), + 'Library', + 'Preferences', + 'com.googlecode.iterm2.plist', + ) +} + +type RestoreResult = + | { + status: 'restored' | 'no_backup' + } + | { + status: 'failed' + backupPath: string + } + +export async function checkAndRestoreITerm2Backup(): Promise { + const { inProgress, backupPath } = getIterm2RecoveryInfo() + if (!inProgress) { + return { status: 'no_backup' } + } + + if (!backupPath) { + markITerm2SetupComplete() + return { status: 'no_backup' } + } + + try { + await stat(backupPath) + } catch { + markITerm2SetupComplete() + return { status: 'no_backup' } + } + + try { + await copyFile(backupPath, getITerm2PlistPath()) + + markITerm2SetupComplete() + return { status: 'restored' } + } catch (restoreError) { + logError( + new Error(`Failed to restore iTerm2 settings with: ${restoreError}`), + ) + markITerm2SetupComplete() + return { status: 'failed', backupPath } + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/model/deprecation.ts b/_all-in-one-upload/cc-haha/src/utils/model/deprecation.ts new file mode 100644 index 0000000..a8b0ee2 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/model/deprecation.ts @@ -0,0 +1,101 @@ +/** + * Model deprecation utilities + * + * Contains information about deprecated models and their retirement dates. + */ + +import { type APIProvider, getAPIProvider } from './providers.js' + +type DeprecatedModelInfo = { + isDeprecated: true + modelName: string + retirementDate: string +} + +type NotDeprecatedInfo = { + isDeprecated: false +} + +type DeprecationInfo = DeprecatedModelInfo | NotDeprecatedInfo + +type DeprecationEntry = { + /** Human-readable model name */ + modelName: string + /** Retirement dates by provider (null = not deprecated for that provider) */ + retirementDates: Record +} + +/** + * Deprecated models and their retirement dates by provider. + * Keys are substrings to match in model IDs (case-insensitive). + * To add a new deprecated model, add an entry to this object. + */ +const DEPRECATED_MODELS: Record = { + 'claude-3-opus': { + modelName: 'Claude 3 Opus', + retirementDates: { + firstParty: 'January 5, 2026', + bedrock: 'January 15, 2026', + vertex: 'January 5, 2026', + foundry: 'January 5, 2026', + }, + }, + 'claude-3-7-sonnet': { + modelName: 'Claude 3.7 Sonnet', + retirementDates: { + firstParty: 'February 19, 2026', + bedrock: 'April 28, 2026', + vertex: 'May 11, 2026', + foundry: 'February 19, 2026', + }, + }, + 'claude-3-5-haiku': { + modelName: 'Claude 3.5 Haiku', + retirementDates: { + firstParty: 'February 19, 2026', + bedrock: null, + vertex: null, + foundry: null, + }, + }, +} + +/** + * Check if a model is deprecated and get its deprecation info + */ +function getDeprecatedModelInfo(modelId: string): DeprecationInfo { + const lowercaseModelId = modelId.toLowerCase() + const provider = getAPIProvider() + + for (const [key, value] of Object.entries(DEPRECATED_MODELS)) { + const retirementDate = value.retirementDates[provider] + if (!lowercaseModelId.includes(key) || !retirementDate) { + continue + } + return { + isDeprecated: true, + modelName: value.modelName, + retirementDate, + } + } + + return { isDeprecated: false } +} + +/** + * Get a deprecation warning message for a model, or null if not deprecated + */ +export function getModelDeprecationWarning( + modelId: string | null, +): string | null { + if (!modelId) { + return null + } + + const info = getDeprecatedModelInfo(modelId) + if (!info.isDeprecated) { + return null + } + + return `⚠ ${info.modelName} will be retired on ${info.retirementDate}. Consider switching to a newer model.` +} diff --git a/_all-in-one-upload/cc-haha/src/utils/model/modelAllowlist.ts b/_all-in-one-upload/cc-haha/src/utils/model/modelAllowlist.ts new file mode 100644 index 0000000..b3f8647 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/model/modelAllowlist.ts @@ -0,0 +1,170 @@ +import { getSettings_DEPRECATED } from '../settings/settings.js' +import { isModelAlias, isModelFamilyAlias } from './aliases.js' +import { parseUserSpecifiedModel } from './model.js' +import { resolveOverriddenModel } from './modelStrings.js' + +/** + * Check if a model belongs to a given family by checking if its name + * (or resolved name) contains the family identifier. + */ +function modelBelongsToFamily(model: string, family: string): boolean { + if (model.includes(family)) { + return true + } + // Resolve aliases like "best" → "claude-opus-4-7" to check family membership + if (isModelAlias(model)) { + const resolved = parseUserSpecifiedModel(model).toLowerCase() + return resolved.includes(family) + } + return false +} + +/** + * Check if a model name starts with a prefix at a segment boundary. + * The prefix must match up to the end of the name or a "-" separator. + * e.g. "claude-opus-4-5" matches "claude-opus-4-5-20251101" but not "claude-opus-4-50". + */ +function prefixMatchesModel(modelName: string, prefix: string): boolean { + if (!modelName.startsWith(prefix)) { + return false + } + return modelName.length === prefix.length || modelName[prefix.length] === '-' +} + +/** + * Check if a model matches a version-prefix entry in the allowlist. + * Supports shorthand like "opus-4-5" (mapped to "claude-opus-4-5") and + * full prefixes like "claude-opus-4-5". Resolves input aliases before matching. + */ +function modelMatchesVersionPrefix(model: string, entry: string): boolean { + // Resolve the input model to a full name if it's an alias + const resolvedModel = isModelAlias(model) + ? parseUserSpecifiedModel(model).toLowerCase() + : model + + // Try the entry as-is (e.g. "claude-opus-4-5") + if (prefixMatchesModel(resolvedModel, entry)) { + return true + } + // Try with "claude-" prefix (e.g. "opus-4-5" → "claude-opus-4-5") + if ( + !entry.startsWith('claude-') && + prefixMatchesModel(resolvedModel, `claude-${entry}`) + ) { + return true + } + return false +} + +/** + * Check if a family alias is narrowed by more specific entries in the allowlist. + * When the allowlist contains both "opus" and "opus-4-5", the specific entry + * takes precedence — "opus" alone would be a wildcard, but "opus-4-5" narrows + * it to only that version. + */ +function familyHasSpecificEntries( + family: string, + allowlist: string[], +): boolean { + for (const entry of allowlist) { + if (isModelFamilyAlias(entry)) { + continue + } + // Check if entry is a version-qualified variant of this family + // e.g., "opus-4-5" or "claude-opus-4-5-20251101" for the "opus" family + // Must match at a segment boundary (followed by '-' or end) to avoid + // false positives like "opusplan" matching "opus" + const idx = entry.indexOf(family) + if (idx === -1) { + continue + } + const afterFamily = idx + family.length + if (afterFamily === entry.length || entry[afterFamily] === '-') { + return true + } + } + return false +} + +/** + * Check if a model is allowed by the availableModels allowlist in settings. + * If availableModels is not set, all models are allowed. + * + * Matching tiers: + * 1. Family aliases ("opus", "sonnet", "haiku") — wildcard for the entire family, + * UNLESS more specific entries for that family also exist (e.g., "opus-4-5"). + * In that case, the family wildcard is ignored and only the specific entries apply. + * 2. Version prefixes ("opus-4-5", "claude-opus-4-5") — any build of that version + * 3. Full model IDs ("claude-opus-4-5-20251101") — exact match only + */ +export function isModelAllowed(model: string): boolean { + const settings = getSettings_DEPRECATED() || {} + const { availableModels } = settings + if (!availableModels) { + return true // No restrictions + } + if (availableModels.length === 0) { + return false // Empty allowlist blocks all user-specified models + } + + const resolvedModel = resolveOverriddenModel(model) + const normalizedModel = resolvedModel.trim().toLowerCase() + const normalizedAllowlist = availableModels.map(m => m.trim().toLowerCase()) + + // Direct match (alias-to-alias or full-name-to-full-name) + // Skip family aliases that have been narrowed by specific entries — + // e.g., "opus" in ["opus", "opus-4-5"] should NOT directly match, + // because the admin intends to restrict to opus 4.5 only. + if (normalizedAllowlist.includes(normalizedModel)) { + if ( + !isModelFamilyAlias(normalizedModel) || + !familyHasSpecificEntries(normalizedModel, normalizedAllowlist) + ) { + return true + } + } + + // Family-level aliases in the allowlist match any model in that family, + // but only if no more specific entries exist for that family. + // e.g., ["opus"] allows all opus, but ["opus", "opus-4-5"] only allows opus 4.5. + for (const entry of normalizedAllowlist) { + if ( + isModelFamilyAlias(entry) && + !familyHasSpecificEntries(entry, normalizedAllowlist) && + modelBelongsToFamily(normalizedModel, entry) + ) { + return true + } + } + + // For non-family entries, do bidirectional alias resolution + // If model is an alias, resolve it and check if the resolved name is in the list + if (isModelAlias(normalizedModel)) { + const resolved = parseUserSpecifiedModel(normalizedModel).toLowerCase() + if (normalizedAllowlist.includes(resolved)) { + return true + } + } + + // If any non-family alias in the allowlist resolves to the input model + for (const entry of normalizedAllowlist) { + if (!isModelFamilyAlias(entry) && isModelAlias(entry)) { + const resolved = parseUserSpecifiedModel(entry).toLowerCase() + if (resolved === normalizedModel) { + return true + } + } + } + + // Version-prefix matching: "opus-4-5" or "claude-opus-4-5" matches + // "claude-opus-4-5-20251101" at a segment boundary + for (const entry of normalizedAllowlist) { + if (!isModelFamilyAlias(entry) && !isModelAlias(entry)) { + if (modelMatchesVersionPrefix(normalizedModel, entry)) { + return true + } + } + } + + return false +} diff --git a/_all-in-one-upload/cc-haha/src/utils/model/modelOptions.ts b/_all-in-one-upload/cc-haha/src/utils/model/modelOptions.ts new file mode 100644 index 0000000..80e2878 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/model/modelOptions.ts @@ -0,0 +1,540 @@ +// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered +import { getInitialMainLoopModel } from '../../bootstrap/state.js' +import { + isClaudeAISubscriber, + isMaxSubscriber, + isTeamPremiumSubscriber, +} from '../auth.js' +import { getModelStrings } from './modelStrings.js' +import { + COST_TIER_3_15, + COST_HAIKU_35, + COST_HAIKU_45, + formatModelPricing, +} from '../modelCost.js' +import { getSettings_DEPRECATED } from '../settings/settings.js' +import { checkOpus1mAccess, checkSonnet1mAccess } from './check1mAccess.js' +import { getAPIProvider } from './providers.js' +import { isModelAllowed } from './modelAllowlist.js' +import { + getCanonicalName, + getClaudeAiUserDefaultModelDescription, + getDefaultSonnetModel, + getDefaultOpusModel, + getDefaultHaikuModel, + getDefaultMainLoopModelSetting, + getMarketingNameForModel, + getUserSpecifiedModelSetting, + isOpus1mMergeEnabled, + getOpus46PricingSuffix, + renderDefaultModelSetting, + type ModelSetting, +} from './model.js' +import { has1mContext } from '../context.js' +import { getGlobalConfig } from '../config.js' + +// @[MODEL LAUNCH]: Update all the available and default model option strings below. + +export type ModelOption = { + value: ModelSetting + label: string + description: string + descriptionForModel?: string +} + +export function getDefaultOptionForUser(fastMode = false): ModelOption { + if (process.env.USER_TYPE === 'ant') { + const currentModel = renderDefaultModelSetting( + getDefaultMainLoopModelSetting(), + ) + return { + value: null, + label: 'Default (recommended)', + description: `Use the default model for Ants (currently ${currentModel})`, + descriptionForModel: `Default model (currently ${currentModel})`, + } + } + + // Subscribers + if (isClaudeAISubscriber()) { + return { + value: null, + label: 'Default (recommended)', + description: getClaudeAiUserDefaultModelDescription(fastMode), + } + } + + // PAYG + const is3P = getAPIProvider() !== 'firstParty' + return { + value: null, + label: 'Default (recommended)', + description: `Use the default model (currently ${renderDefaultModelSetting(getDefaultMainLoopModelSetting())})${is3P ? '' : ` · ${formatModelPricing(COST_TIER_3_15)}`}`, + } +} + +function getCustomSonnetOption(): ModelOption | undefined { + const is3P = getAPIProvider() !== 'firstParty' + const customSonnetModel = process.env.ANTHROPIC_DEFAULT_SONNET_MODEL + // When a 3P user has a custom sonnet model string, show it directly + if (is3P && customSonnetModel) { + const is1m = has1mContext(customSonnetModel) + return { + value: 'sonnet', + label: + process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_NAME ?? customSonnetModel, + description: + process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION ?? + `Custom Sonnet model${is1m ? ' (1M context)' : ''}`, + descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION ?? `Custom Sonnet model${is1m ? ' with 1M context' : ''}`} (${customSonnetModel})`, + } + } +} + +// @[MODEL LAUNCH]: Update or add model option functions (getSonnetXXOption, getOpusXXOption, etc.) +// with the new model's label and description. These appear in the /model picker. +function getSonnet46Option(): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: is3P ? getModelStrings().sonnet46 : 'sonnet', + label: 'Sonnet', + description: `Sonnet 4.6 · Best for everyday tasks${is3P ? '' : ` · ${formatModelPricing(COST_TIER_3_15)}`}`, + descriptionForModel: + 'Sonnet 4.6 - best for everyday tasks. Generally recommended for most coding tasks', + } +} + +function getCustomOpusOption(): ModelOption | undefined { + const is3P = getAPIProvider() !== 'firstParty' + const customOpusModel = process.env.ANTHROPIC_DEFAULT_OPUS_MODEL + // When a 3P user has a custom opus model string, show it directly + if (is3P && customOpusModel) { + const is1m = has1mContext(customOpusModel) + return { + value: 'opus', + label: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_NAME ?? customOpusModel, + description: + process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION ?? + `Custom Opus model${is1m ? ' (1M context)' : ''}`, + descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION ?? `Custom Opus model${is1m ? ' with 1M context' : ''}`} (${customOpusModel})`, + } + } +} + +function getOpus41Option(): ModelOption { + return { + value: 'opus', + label: 'Opus 4.1', + description: `Opus 4.1 · Legacy`, + descriptionForModel: 'Opus 4.1 - legacy version', + } +} + +function getOpus46Option(fastMode = false): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: is3P ? getModelStrings().opus46 : 'opus', + label: 'Opus', + description: `Opus 4.7 · Most capable for complex work${getOpus46PricingSuffix(fastMode)}`, + descriptionForModel: 'Opus 4.7 - most capable for complex work', + } +} + +export function getSonnet46_1MOption(): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: is3P ? getModelStrings().sonnet46 + '[1m]' : 'sonnet[1m]', + label: 'Sonnet (1M context)', + description: `Sonnet 4.6 for long sessions${is3P ? '' : ` · ${formatModelPricing(COST_TIER_3_15)}`}`, + descriptionForModel: + 'Sonnet 4.6 with 1M context window - for long sessions with large codebases', + } +} + +export function getOpus46_1MOption(fastMode = false): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: is3P ? getModelStrings().opus46 + '[1m]' : 'opus[1m]', + label: 'Opus (1M context)', + description: `Opus 4.7 for long sessions${getOpus46PricingSuffix(fastMode)}`, + descriptionForModel: + 'Opus 4.7 with 1M context window - for long sessions with large codebases', + } +} + +function getCustomHaikuOption(): ModelOption | undefined { + const is3P = getAPIProvider() !== 'firstParty' + const customHaikuModel = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL + // When a 3P user has a custom haiku model string, show it directly + if (is3P && customHaikuModel) { + return { + value: 'haiku', + label: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME ?? customHaikuModel, + description: + process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION ?? + 'Custom Haiku model', + descriptionForModel: `${process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION ?? 'Custom Haiku model'} (${customHaikuModel})`, + } + } +} + +function getHaiku45Option(): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: 'haiku', + label: 'Haiku', + description: `Haiku 4.5 · Fastest for quick answers${is3P ? '' : ` · ${formatModelPricing(COST_HAIKU_45)}`}`, + descriptionForModel: + 'Haiku 4.5 - fastest for quick answers. Lower cost but less capable than Sonnet 4.6.', + } +} + +function getHaiku35Option(): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: 'haiku', + label: 'Haiku', + description: `Haiku 3.5 for simple tasks${is3P ? '' : ` · ${formatModelPricing(COST_HAIKU_35)}`}`, + descriptionForModel: + 'Haiku 3.5 - faster and lower cost, but less capable than Sonnet. Use for simple tasks.', + } +} + +function getHaikuOption(): ModelOption { + // Return correct Haiku option based on provider + const haikuModel = getDefaultHaikuModel() + return haikuModel === getModelStrings().haiku45 + ? getHaiku45Option() + : getHaiku35Option() +} + +function getMaxOpusOption(fastMode = false): ModelOption { + return { + value: 'opus', + label: 'Opus', + description: `Opus 4.7 · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`, + } +} + +export function getMaxSonnet46_1MOption(): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + const billingInfo = isClaudeAISubscriber() ? ' · Billed as extra usage' : '' + return { + value: 'sonnet[1m]', + label: 'Sonnet (1M context)', + description: `Sonnet 4.6 with 1M context${billingInfo}${is3P ? '' : ` · ${formatModelPricing(COST_TIER_3_15)}`}`, + } +} + +export function getMaxOpus46_1MOption(fastMode = false): ModelOption { + const billingInfo = isClaudeAISubscriber() ? ' · Billed as extra usage' : '' + return { + value: 'opus[1m]', + label: 'Opus (1M context)', + description: `Opus 4.7 with 1M context${billingInfo}${getOpus46PricingSuffix(fastMode)}`, + } +} + +function getMergedOpus1MOption(fastMode = false): ModelOption { + const is3P = getAPIProvider() !== 'firstParty' + return { + value: is3P ? getModelStrings().opus46 + '[1m]' : 'opus[1m]', + label: 'Opus (1M context)', + description: `Opus 4.7 with 1M context · Most capable for complex work${!is3P && fastMode ? getOpus46PricingSuffix(fastMode) : ''}`, + descriptionForModel: + 'Opus 4.7 with 1M context - most capable for complex work', + } +} + +const MaxSonnet46Option: ModelOption = { + value: 'sonnet', + label: 'Sonnet', + description: 'Sonnet 4.6 · Best for everyday tasks', +} + +const MaxHaiku45Option: ModelOption = { + value: 'haiku', + label: 'Haiku', + description: 'Haiku 4.5 · Fastest for quick answers', +} + +function getOpusPlanOption(): ModelOption { + return { + value: 'opusplan', + label: 'Opus Plan Mode', + description: 'Use Opus 4.7 in plan mode, Sonnet 4.6 otherwise', + } +} + +// @[MODEL LAUNCH]: Update the model picker lists below to include/reorder options for the new model. +// Each user tier (ant, Max/Team Premium, Pro/Team Standard/Enterprise, PAYG 1P, PAYG 3P) has its own list. +function getModelOptionsBase(fastMode = false): ModelOption[] { + if (process.env.USER_TYPE === 'ant') { + // Build options from antModels config + const antModelOptions: ModelOption[] = getAntModels().map(m => ({ + value: m.alias, + label: m.label, + description: m.description ?? `[ANT-ONLY] ${m.label} (${m.model})`, + })) + + return [ + getDefaultOptionForUser(), + ...antModelOptions, + getMergedOpus1MOption(fastMode), + getSonnet46Option(), + getSonnet46_1MOption(), + getHaiku45Option(), + ] + } + + if (isClaudeAISubscriber()) { + if (isMaxSubscriber() || isTeamPremiumSubscriber()) { + // Max and Team Premium users: Opus is default, show Sonnet as alternative + const premiumOptions = [getDefaultOptionForUser(fastMode)] + if (!isOpus1mMergeEnabled() && checkOpus1mAccess()) { + premiumOptions.push(getMaxOpus46_1MOption(fastMode)) + } + + premiumOptions.push(MaxSonnet46Option) + if (checkSonnet1mAccess()) { + premiumOptions.push(getMaxSonnet46_1MOption()) + } + + premiumOptions.push(MaxHaiku45Option) + return premiumOptions + } + + // Pro/Team Standard/Enterprise users: Sonnet is default, show Opus as alternative + const standardOptions = [getDefaultOptionForUser(fastMode)] + if (checkSonnet1mAccess()) { + standardOptions.push(getMaxSonnet46_1MOption()) + } + + if (isOpus1mMergeEnabled()) { + standardOptions.push(getMergedOpus1MOption(fastMode)) + } else { + standardOptions.push(getMaxOpusOption(fastMode)) + if (checkOpus1mAccess()) { + standardOptions.push(getMaxOpus46_1MOption(fastMode)) + } + } + + standardOptions.push(MaxHaiku45Option) + return standardOptions + } + + // PAYG 1P API: Default (Sonnet) + Sonnet 1M + Opus 4.7 + Opus 1M + Haiku + if (getAPIProvider() === 'firstParty') { + const payg1POptions = [getDefaultOptionForUser(fastMode)] + if (checkSonnet1mAccess()) { + payg1POptions.push(getSonnet46_1MOption()) + } + if (isOpus1mMergeEnabled()) { + payg1POptions.push(getMergedOpus1MOption(fastMode)) + } else { + payg1POptions.push(getOpus46Option(fastMode)) + if (checkOpus1mAccess()) { + payg1POptions.push(getOpus46_1MOption(fastMode)) + } + } + payg1POptions.push(getHaiku45Option()) + return payg1POptions + } + + // PAYG 3P: Default (Sonnet 4.5) + Sonnet (3P custom) or Sonnet 4.6/1M + Opus (3P custom) or Opus 4.1/Opus 4.7/Opus1M + Haiku + Opus 4.1 + const payg3pOptions = [getDefaultOptionForUser(fastMode)] + + const customSonnet = getCustomSonnetOption() + if (customSonnet !== undefined) { + payg3pOptions.push(customSonnet) + } else { + // Add Sonnet 4.6 since Sonnet 4.5 is the default + payg3pOptions.push(getSonnet46Option()) + if (checkSonnet1mAccess()) { + payg3pOptions.push(getSonnet46_1MOption()) + } + } + + const customOpus = getCustomOpusOption() + if (customOpus !== undefined) { + payg3pOptions.push(customOpus) + } else { + // Add Opus 4.1, Opus 4.7 and Opus 4.7 1M + payg3pOptions.push(getOpus41Option()) // This is the default opus + payg3pOptions.push(getOpus46Option(fastMode)) + if (checkOpus1mAccess()) { + payg3pOptions.push(getOpus46_1MOption(fastMode)) + } + } + const customHaiku = getCustomHaikuOption() + if (customHaiku !== undefined) { + payg3pOptions.push(customHaiku) + } else { + payg3pOptions.push(getHaikuOption()) + } + return payg3pOptions +} + +// @[MODEL LAUNCH]: Add the new model ID to the appropriate family pattern below +// so the "newer version available" hint works correctly. +/** + * Map a full model name to its family alias and the marketing name of the + * version the alias currently resolves to. Used to detect when a user has + * a specific older version pinned and a newer one is available. + */ +function getModelFamilyInfo( + model: string, +): { alias: string; currentVersionName: string } | null { + const canonical = getCanonicalName(model) + + // Sonnet family + if ( + canonical.includes('claude-sonnet-4-6') || + canonical.includes('claude-sonnet-4-5') || + canonical.includes('claude-sonnet-4-') || + canonical.includes('claude-3-7-sonnet') || + canonical.includes('claude-3-5-sonnet') + ) { + const currentName = getMarketingNameForModel(getDefaultSonnetModel()) + if (currentName) { + return { alias: 'Sonnet', currentVersionName: currentName } + } + } + + // Opus family + if (canonical.includes('claude-opus-4')) { + const currentName = getMarketingNameForModel(getDefaultOpusModel()) + if (currentName) { + return { alias: 'Opus', currentVersionName: currentName } + } + } + + // Haiku family + if ( + canonical.includes('claude-haiku') || + canonical.includes('claude-3-5-haiku') + ) { + const currentName = getMarketingNameForModel(getDefaultHaikuModel()) + if (currentName) { + return { alias: 'Haiku', currentVersionName: currentName } + } + } + + return null +} + +/** + * Returns a ModelOption for a known Anthropic model with a human-readable + * label, and an upgrade hint if a newer version is available via the alias. + * Returns null if the model is not recognized. + */ +function getKnownModelOption(model: string): ModelOption | null { + const marketingName = getMarketingNameForModel(model) + if (!marketingName) return null + + const familyInfo = getModelFamilyInfo(model) + if (!familyInfo) { + return { + value: model, + label: marketingName, + description: model, + } + } + + // Check if the alias currently resolves to a different (newer) version + if (marketingName !== familyInfo.currentVersionName) { + return { + value: model, + label: marketingName, + description: `Newer version available · select ${familyInfo.alias} for ${familyInfo.currentVersionName}`, + } + } + + // Same version as the alias — just show the friendly name + return { + value: model, + label: marketingName, + description: model, + } +} + +export function getModelOptions(fastMode = false): ModelOption[] { + const options = getModelOptionsBase(fastMode) + + // Add the custom model from the ANTHROPIC_CUSTOM_MODEL_OPTION env var + const envCustomModel = process.env.ANTHROPIC_CUSTOM_MODEL_OPTION + if ( + envCustomModel && + !options.some(existing => existing.value === envCustomModel) + ) { + options.push({ + value: envCustomModel, + label: process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME ?? envCustomModel, + description: + process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION ?? + `Custom model (${envCustomModel})`, + }) + } + + // Append additional model options fetched during bootstrap + for (const opt of getGlobalConfig().additionalModelOptionsCache ?? []) { + if (!options.some(existing => existing.value === opt.value)) { + options.push(opt) + } + } + + // Add custom model from either the current model value or the initial one + // if it is not already in the options. + let customModel: ModelSetting = null + const currentMainLoopModel = getUserSpecifiedModelSetting() + const initialMainLoopModel = getInitialMainLoopModel() + if (currentMainLoopModel !== undefined && currentMainLoopModel !== null) { + customModel = currentMainLoopModel + } else if (initialMainLoopModel !== null) { + customModel = initialMainLoopModel + } + if (customModel === null || options.some(opt => opt.value === customModel)) { + return filterModelOptionsByAllowlist(options) + } else if (customModel === 'opusplan') { + return filterModelOptionsByAllowlist([...options, getOpusPlanOption()]) + } else if (customModel === 'opus' && getAPIProvider() === 'firstParty') { + return filterModelOptionsByAllowlist([ + ...options, + getMaxOpusOption(fastMode), + ]) + } else if (customModel === 'opus[1m]' && getAPIProvider() === 'firstParty') { + return filterModelOptionsByAllowlist([ + ...options, + getMergedOpus1MOption(fastMode), + ]) + } else { + // Try to show a human-readable label for known Anthropic models, with an + // upgrade hint if the alias now resolves to a newer version. + const knownOption = getKnownModelOption(customModel) + if (knownOption) { + options.push(knownOption) + } else { + options.push({ + value: customModel, + label: customModel, + description: 'Custom model', + }) + } + return filterModelOptionsByAllowlist(options) + } +} + +/** + * Filter model options by the availableModels allowlist. + * Always preserves the "Default" option (value: null). + */ +function filterModelOptionsByAllowlist(options: ModelOption[]): ModelOption[] { + const settings = getSettings_DEPRECATED() || {} + if (!settings.availableModels) { + return options // No restrictions + } + return options.filter( + opt => + opt.value === null || (opt.value !== null && isModelAllowed(opt.value)), + ) +} diff --git a/_all-in-one-upload/cc-haha/src/utils/modifiers.ts b/_all-in-one-upload/cc-haha/src/utils/modifiers.ts new file mode 100644 index 0000000..02d8c52 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/modifiers.ts @@ -0,0 +1,40 @@ +export type ModifierKey = 'shift' | 'command' | 'control' | 'option' + +let prewarmed = false + +/** + * Pre-warm the native module by loading it in advance. + * Call this early to avoid delay on first use. + */ +export function prewarmModifiers(): void { + if (prewarmed || process.platform !== 'darwin') { + return + } + prewarmed = true + // Load module in background + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { prewarm } = require('modifiers-napi') as { prewarm: () => void } + prewarm() + } catch { + // Ignore errors during prewarm + } +} + +/** + * Check if a specific modifier key is currently pressed (synchronous). + */ +export function isModifierPressed(modifier: ModifierKey): boolean { + if (process.platform !== 'darwin') { + return false + } + try { + // Dynamic import to avoid loading native module at top level + const { isModifierPressed: nativeIsModifierPressed } = + // eslint-disable-next-line @typescript-eslint/no-require-imports + require('modifiers-napi') as { isModifierPressed: (m: string) => boolean } + return nativeIsModifierPressed(modifier) + } catch { + return false + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/nativeInstaller/download.ts b/_all-in-one-upload/cc-haha/src/utils/nativeInstaller/download.ts new file mode 100644 index 0000000..fa11e67 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/nativeInstaller/download.ts @@ -0,0 +1,523 @@ +/** + * Download functionality for native installer + * + * Handles downloading Claude binaries from various sources: + * - Artifactory NPM packages + * - GCS bucket + */ + +import { feature } from 'bun:bundle' +import axios from 'axios' +import { createHash } from 'crypto' +import { chmod, writeFile } from 'fs/promises' +import { join } from 'path' +import { logEvent } from 'src/services/analytics/index.js' +import type { ReleaseChannel } from '../config.js' +import { logForDebugging } from '../debug.js' +import { toError } from '../errors.js' +import { execFileNoThrowWithCwd } from '../execFileNoThrow.js' +import { getFsImplementation } from '../fsOperations.js' +import { logError } from '../log.js' +import { sleep } from '../sleep.js' +import { jsonStringify, writeFileSync_DEPRECATED } from '../slowOperations.js' +import { getBinaryName, getPlatform } from './installer.js' + +const GCS_BUCKET_URL = + 'https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases' +export const ARTIFACTORY_REGISTRY_URL = + 'https://artifactory.infra.ant.dev/artifactory/api/npm/npm-all/' + +export async function getLatestVersionFromArtifactory( + tag: string = 'latest', +): Promise { + const startTime = Date.now() + const { stdout, code, stderr } = await execFileNoThrowWithCwd( + 'npm', + [ + 'view', + `${MACRO.NATIVE_PACKAGE_URL}@${tag}`, + 'version', + '--prefer-online', + '--registry', + ARTIFACTORY_REGISTRY_URL, + ], + { + timeout: 30000, + preserveOutputOnError: true, + }, + ) + + const latencyMs = Date.now() - startTime + + if (code !== 0) { + logEvent('tengu_version_check_failure', { + latency_ms: latencyMs, + source_npm: true, + exit_code: code, + }) + const error = new Error(`npm view failed with code ${code}: ${stderr}`) + logError(error) + throw error + } + + logEvent('tengu_version_check_success', { + latency_ms: latencyMs, + source_npm: true, + }) + logForDebugging( + `npm view ${MACRO.NATIVE_PACKAGE_URL}@${tag} version: ${stdout}`, + ) + const latestVersion = stdout.trim() + return latestVersion +} + +export async function getLatestVersionFromBinaryRepo( + channel: ReleaseChannel = 'latest', + baseUrl: string, + authConfig?: { auth: { username: string; password: string } }, +): Promise { + const startTime = Date.now() + try { + const response = await axios.get(`${baseUrl}/${channel}`, { + timeout: 30000, + responseType: 'text', + ...authConfig, + }) + const latencyMs = Date.now() - startTime + logEvent('tengu_version_check_success', { + latency_ms: latencyMs, + }) + return response.data.trim() + } catch (error) { + const latencyMs = Date.now() - startTime + const errorMessage = error instanceof Error ? error.message : String(error) + let httpStatus: number | undefined + if (axios.isAxiosError(error) && error.response) { + httpStatus = error.response.status + } + + logEvent('tengu_version_check_failure', { + latency_ms: latencyMs, + http_status: httpStatus, + is_timeout: errorMessage.includes('timeout'), + }) + const fetchError = new Error( + `Failed to fetch version from ${baseUrl}/${channel}: ${errorMessage}`, + ) + logError(fetchError) + throw fetchError + } +} + +export async function getLatestVersion( + channelOrVersion: string, +): Promise { + // Direct version - match internal format too (e.g. 1.0.30-dev.shaf4937ce) + if (/^v?\d+\.\d+\.\d+(-\S+)?$/.test(channelOrVersion)) { + const normalized = channelOrVersion.startsWith('v') + ? channelOrVersion.slice(1) + : channelOrVersion + // 99.99.x is reserved for CI smoke-test fixtures on real GCS. + // feature() is false in all shipped builds — DCE collapses this to an + // unconditional throw. Only `bun --feature=ALLOW_TEST_VERSIONS` (the + // smoke test's source-level invocation) bypasses. + if (/^99\.99\./.test(normalized) && !feature('ALLOW_TEST_VERSIONS')) { + throw new Error( + `Version ${normalized} is not available for installation. Use 'stable' or 'latest'.`, + ) + } + return normalized + } + + // ReleaseChannel validation + const channel = channelOrVersion as ReleaseChannel + if (channel !== 'stable' && channel !== 'latest') { + throw new Error( + `Invalid channel: ${channelOrVersion}. Use 'stable' or 'latest'`, + ) + } + + // Route to appropriate source + if (process.env.USER_TYPE === 'ant') { + // Use Artifactory for ant users + const npmTag = channel === 'stable' ? 'stable' : 'latest' + return getLatestVersionFromArtifactory(npmTag) + } + + // Use GCS for external users + return getLatestVersionFromBinaryRepo(channel, GCS_BUCKET_URL) +} + +export async function downloadVersionFromArtifactory( + version: string, + stagingPath: string, +) { + const fs = getFsImplementation() + + // If we get here, we own the lock and can delete a partial download + await fs.rm(stagingPath, { recursive: true, force: true }) + + // Get the platform-specific package name + const platform = getPlatform() + const platformPackageName = `${MACRO.NATIVE_PACKAGE_URL}-${platform}` + + // Fetch integrity hash for the platform-specific package + logForDebugging( + `Fetching integrity hash for ${platformPackageName}@${version}`, + ) + const { + stdout: integrityOutput, + code, + stderr, + } = await execFileNoThrowWithCwd( + 'npm', + [ + 'view', + `${platformPackageName}@${version}`, + 'dist.integrity', + '--registry', + ARTIFACTORY_REGISTRY_URL, + ], + { + timeout: 30000, + preserveOutputOnError: true, + }, + ) + + if (code !== 0) { + throw new Error(`npm view integrity failed with code ${code}: ${stderr}`) + } + + const integrity = integrityOutput.trim() + if (!integrity) { + throw new Error( + `Failed to fetch integrity hash for ${platformPackageName}@${version}`, + ) + } + + logForDebugging(`Got integrity hash for ${platform}: ${integrity}`) + + // Create isolated npm project in staging + await fs.mkdir(stagingPath) + + const packageJson = { + name: 'claude-native-installer', + version: '0.0.1', + dependencies: { + [MACRO.NATIVE_PACKAGE_URL!]: version, + }, + } + + // Create package-lock.json with integrity verification for platform-specific package + const packageLock = { + name: 'claude-native-installer', + version: '0.0.1', + lockfileVersion: 3, + requires: true, + packages: { + '': { + name: 'claude-native-installer', + version: '0.0.1', + dependencies: { + [MACRO.NATIVE_PACKAGE_URL!]: version, + }, + }, + [`node_modules/${MACRO.NATIVE_PACKAGE_URL}`]: { + version: version, + optionalDependencies: { + [platformPackageName]: version, + }, + }, + [`node_modules/${platformPackageName}`]: { + version: version, + integrity: integrity, + }, + }, + } + + writeFileSync_DEPRECATED( + join(stagingPath, 'package.json'), + jsonStringify(packageJson, null, 2), + { encoding: 'utf8', flush: true }, + ) + + writeFileSync_DEPRECATED( + join(stagingPath, 'package-lock.json'), + jsonStringify(packageLock, null, 2), + { encoding: 'utf8', flush: true }, + ) + + // Install with npm - it will verify integrity from package-lock.json + // Use --prefer-online to force fresh metadata checks, helping with Artifactory replication delays + const result = await execFileNoThrowWithCwd( + 'npm', + ['ci', '--prefer-online', '--registry', ARTIFACTORY_REGISTRY_URL], + { + timeout: 60000, + preserveOutputOnError: true, + cwd: stagingPath, + }, + ) + + if (result.code !== 0) { + throw new Error(`npm ci failed with code ${result.code}: ${result.stderr}`) + } + + logForDebugging( + `Successfully downloaded and verified ${MACRO.NATIVE_PACKAGE_URL}@${version}`, + ) +} + +// Stall timeout: abort if no bytes received for this duration +const DEFAULT_STALL_TIMEOUT_MS = 60000 // 60 seconds +const MAX_DOWNLOAD_RETRIES = 3 + +function getStallTimeoutMs(): number { + return ( + Number(process.env.CLAUDE_CODE_STALL_TIMEOUT_MS_FOR_TESTING) || + DEFAULT_STALL_TIMEOUT_MS + ) +} + +class StallTimeoutError extends Error { + constructor() { + super('Download stalled: no data received for 60 seconds') + this.name = 'StallTimeoutError' + } +} + +/** + * Common logic for downloading and verifying a binary. + * Includes stall detection (aborts if no bytes for 60s) and retry logic. + */ +async function downloadAndVerifyBinary( + binaryUrl: string, + expectedChecksum: string, + binaryPath: string, + requestConfig: Record = {}, +) { + let lastError: Error | undefined + + for (let attempt = 1; attempt <= MAX_DOWNLOAD_RETRIES; attempt++) { + const controller = new AbortController() + let stallTimer: ReturnType | undefined + + const clearStallTimer = () => { + if (stallTimer) { + clearTimeout(stallTimer) + stallTimer = undefined + } + } + + const resetStallTimer = () => { + clearStallTimer() + stallTimer = setTimeout(c => c.abort(), getStallTimeoutMs(), controller) + } + + try { + // Start the stall timer before the request + resetStallTimer() + + const response = await axios.get(binaryUrl, { + timeout: 5 * 60000, // 5 minute total timeout + responseType: 'arraybuffer', + signal: controller.signal, + onDownloadProgress: () => { + // Reset stall timer on each chunk of data received + resetStallTimer() + }, + ...requestConfig, + }) + + clearStallTimer() + + // Verify checksum + const hash = createHash('sha256') + hash.update(response.data) + const actualChecksum = hash.digest('hex') + + if (actualChecksum !== expectedChecksum) { + throw new Error( + `Checksum mismatch: expected ${expectedChecksum}, got ${actualChecksum}`, + ) + } + + // Write binary to disk + await writeFile(binaryPath, Buffer.from(response.data)) + await chmod(binaryPath, 0o755) + + // Success - return early + return + } catch (error) { + clearStallTimer() + + // Check if this was a stall timeout (axios wraps abort signals in CanceledError) + const isStallTimeout = axios.isCancel(error) + + if (isStallTimeout) { + lastError = new StallTimeoutError() + } else { + lastError = toError(error) + } + + // Only retry on stall timeouts + if (isStallTimeout && attempt < MAX_DOWNLOAD_RETRIES) { + logForDebugging( + `Download stalled on attempt ${attempt}/${MAX_DOWNLOAD_RETRIES}, retrying...`, + ) + // Brief pause before retry to let network recover + await sleep(1000) + continue + } + + // Don't retry other errors (HTTP errors, checksum mismatches, etc.) + throw lastError + } + } + + // Should not reach here, but just in case + throw lastError ?? new Error('Download failed after all retries') +} + +export async function downloadVersionFromBinaryRepo( + version: string, + stagingPath: string, + baseUrl: string, + authConfig?: { + auth?: { username: string; password: string } + headers?: Record + }, +) { + const fs = getFsImplementation() + + // If we get here, we own the lock and can delete a partial download + await fs.rm(stagingPath, { recursive: true, force: true }) + + // Get platform + const platform = getPlatform() + const startTime = Date.now() + + // Log download attempt start + logEvent('tengu_binary_download_attempt', {}) + + // Fetch manifest to get checksum + let manifest + try { + const manifestResponse = await axios.get( + `${baseUrl}/${version}/manifest.json`, + { + timeout: 10000, + responseType: 'json', + ...authConfig, + }, + ) + manifest = manifestResponse.data + } catch (error) { + const latencyMs = Date.now() - startTime + const errorMessage = error instanceof Error ? error.message : String(error) + let httpStatus: number | undefined + if (axios.isAxiosError(error) && error.response) { + httpStatus = error.response.status + } + + logEvent('tengu_binary_manifest_fetch_failure', { + latency_ms: latencyMs, + http_status: httpStatus, + is_timeout: errorMessage.includes('timeout'), + }) + logError( + new Error( + `Failed to fetch manifest from ${baseUrl}/${version}/manifest.json: ${errorMessage}`, + ), + ) + throw error + } + + const platformInfo = manifest.platforms[platform] + + if (!platformInfo) { + logEvent('tengu_binary_platform_not_found', {}) + throw new Error( + `Platform ${platform} not found in manifest for version ${version}`, + ) + } + + const expectedChecksum = platformInfo.checksum + + // Both GCS and generic bucket use identical layout: ${baseUrl}/${version}/${platform}/${binaryName} + const binaryName = getBinaryName(platform) + const binaryUrl = `${baseUrl}/${version}/${platform}/${binaryName}` + + // Write to staging + await fs.mkdir(stagingPath) + const binaryPath = join(stagingPath, binaryName) + + try { + await downloadAndVerifyBinary( + binaryUrl, + expectedChecksum, + binaryPath, + authConfig || {}, + ) + const latencyMs = Date.now() - startTime + logEvent('tengu_binary_download_success', { + latency_ms: latencyMs, + }) + } catch (error) { + const latencyMs = Date.now() - startTime + const errorMessage = error instanceof Error ? error.message : String(error) + let httpStatus: number | undefined + if (axios.isAxiosError(error) && error.response) { + httpStatus = error.response.status + } + + logEvent('tengu_binary_download_failure', { + latency_ms: latencyMs, + http_status: httpStatus, + is_timeout: errorMessage.includes('timeout'), + is_checksum_mismatch: errorMessage.includes('Checksum mismatch'), + }) + logError( + new Error(`Failed to download binary from ${binaryUrl}: ${errorMessage}`), + ) + throw error + } +} + +export async function downloadVersion( + version: string, + stagingPath: string, +): Promise<'npm' | 'binary'> { + // Test-fixture versions route to the private sentinel bucket. DCE'd in all + // shipped builds — the string 'claude-code-ci-sentinel' and the gcloud call + // never exist in compiled binaries. Same gcloud-token pattern as + // remoteSkillLoader.ts:175-195. + if (feature('ALLOW_TEST_VERSIONS') && /^99\.99\./.test(version)) { + const { stdout } = await execFileNoThrowWithCwd('gcloud', [ + 'auth', + 'print-access-token', + ]) + await downloadVersionFromBinaryRepo( + version, + stagingPath, + 'https://storage.googleapis.com/claude-code-ci-sentinel', + { headers: { Authorization: `Bearer ${stdout.trim()}` } }, + ) + return 'binary' + } + + if (process.env.USER_TYPE === 'ant') { + // Use Artifactory for ant users + await downloadVersionFromArtifactory(version, stagingPath) + return 'npm' + } + + // Use GCS for external users + await downloadVersionFromBinaryRepo(version, stagingPath, GCS_BUCKET_URL) + return 'binary' +} + +// Exported for testing +export { StallTimeoutError, MAX_DOWNLOAD_RETRIES } +export const STALL_TIMEOUT_MS = DEFAULT_STALL_TIMEOUT_MS +export const _downloadAndVerifyBinaryForTesting = downloadAndVerifyBinary diff --git a/_all-in-one-upload/cc-haha/src/utils/pdf.ts b/_all-in-one-upload/cc-haha/src/utils/pdf.ts new file mode 100644 index 0000000..65dc506 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/pdf.ts @@ -0,0 +1,300 @@ +import { randomUUID } from 'crypto' +import { mkdir, readdir, readFile } from 'fs/promises' +import { join } from 'path' +import { + PDF_MAX_EXTRACT_SIZE, + PDF_TARGET_RAW_SIZE, +} from '../constants/apiLimits.js' +import { errorMessage } from './errors.js' +import { execFileNoThrow } from './execFileNoThrow.js' +import { formatFileSize } from './format.js' +import { getFsImplementation } from './fsOperations.js' +import { getToolResultsDir } from './toolResultStorage.js' + +export type PDFError = { + reason: + | 'empty' + | 'too_large' + | 'password_protected' + | 'corrupted' + | 'unknown' + | 'unavailable' + message: string +} + +export type PDFResult = + | { success: true; data: T } + | { success: false; error: PDFError } + +/** + * Read a PDF file and return it as base64-encoded data. + * @param filePath Path to the PDF file + * @returns Result containing PDF data or a structured error + */ +export async function readPDF(filePath: string): Promise< + PDFResult<{ + type: 'pdf' + file: { + filePath: string + base64: string + originalSize: number + } + }> +> { + try { + const fs = getFsImplementation() + const stats = await fs.stat(filePath) + const originalSize = stats.size + + // Check if file is empty + if (originalSize === 0) { + return { + success: false, + error: { reason: 'empty', message: `PDF file is empty: ${filePath}` }, + } + } + + // Check if PDF exceeds maximum size + // The API has a 32MB total request limit. After base64 encoding (~33% larger), + // a PDF must be under ~20MB raw to leave room for conversation context. + if (originalSize > PDF_TARGET_RAW_SIZE) { + return { + success: false, + error: { + reason: 'too_large', + message: `PDF file exceeds maximum allowed size of ${formatFileSize(PDF_TARGET_RAW_SIZE)}.`, + }, + } + } + + const fileBuffer = await readFile(filePath) + + // Validate PDF magic bytes — reject files that aren't actually PDFs + // (e.g., HTML files renamed to .pdf) before they enter conversation context. + // Once an invalid PDF document block is in the message history, every subsequent + // API call fails with 400 "The PDF specified was not valid" and the session + // becomes unrecoverable without /clear. + const header = fileBuffer.subarray(0, 5).toString('ascii') + if (!header.startsWith('%PDF-')) { + return { + success: false, + error: { + reason: 'corrupted', + message: `File is not a valid PDF (missing %PDF- header): ${filePath}`, + }, + } + } + + const base64 = fileBuffer.toString('base64') + + // Note: We cannot check page count here without parsing the PDF + // The API will enforce the 100-page limit and return an error if exceeded + + return { + success: true, + data: { + type: 'pdf', + file: { + filePath, + base64, + originalSize, + }, + }, + } + } catch (e: unknown) { + return { + success: false, + error: { + reason: 'unknown', + message: errorMessage(e), + }, + } + } +} + +/** + * Get the number of pages in a PDF file using `pdfinfo` (from poppler-utils). + * Returns `null` if pdfinfo is not available or if the page count cannot be determined. + */ +export async function getPDFPageCount( + filePath: string, +): Promise { + const { code, stdout } = await execFileNoThrow('pdfinfo', [filePath], { + timeout: 10_000, + useCwd: false, + }) + if (code !== 0) { + return null + } + const match = /^Pages:\s+(\d+)/m.exec(stdout) + if (!match) { + return null + } + const count = parseInt(match[1]!, 10) + return isNaN(count) ? null : count +} + +export type PDFExtractPagesResult = { + type: 'parts' + file: { + filePath: string + originalSize: number + count: number + outputDir: string + } +} + +let pdftoppmAvailable: boolean | undefined + +/** + * Reset the pdftoppm availability cache. Used by tests only. + */ +export function resetPdftoppmCache(): void { + pdftoppmAvailable = undefined +} + +/** + * Check whether the `pdftoppm` binary (from poppler-utils) is available. + * The result is cached for the lifetime of the process. + */ +export async function isPdftoppmAvailable(): Promise { + if (pdftoppmAvailable !== undefined) return pdftoppmAvailable + const { code, stderr } = await execFileNoThrow('pdftoppm', ['-v'], { + timeout: 5000, + useCwd: false, + }) + // pdftoppm prints version info to stderr and exits 0 (or sometimes 99 on older versions) + pdftoppmAvailable = code === 0 || stderr.length > 0 + return pdftoppmAvailable +} + +/** + * Extract PDF pages as JPEG images using pdftoppm. + * Produces page-01.jpg, page-02.jpg, etc. in an output directory. + * This enables reading large PDFs and works with all API providers. + * + * @param filePath Path to the PDF file + * @param options Optional page range (1-indexed, inclusive) + */ +export async function extractPDFPages( + filePath: string, + options?: { firstPage?: number; lastPage?: number }, +): Promise> { + try { + const fs = getFsImplementation() + const stats = await fs.stat(filePath) + const originalSize = stats.size + + if (originalSize === 0) { + return { + success: false, + error: { reason: 'empty', message: `PDF file is empty: ${filePath}` }, + } + } + + if (originalSize > PDF_MAX_EXTRACT_SIZE) { + return { + success: false, + error: { + reason: 'too_large', + message: `PDF file exceeds maximum allowed size for text extraction (${formatFileSize(PDF_MAX_EXTRACT_SIZE)}).`, + }, + } + } + + const available = await isPdftoppmAvailable() + if (!available) { + return { + success: false, + error: { + reason: 'unavailable', + message: + 'pdftoppm is not installed. Install poppler-utils (e.g. `brew install poppler` or `apt-get install poppler-utils`) to enable PDF page rendering.', + }, + } + } + + const uuid = randomUUID() + const outputDir = join(getToolResultsDir(), `pdf-${uuid}`) + await mkdir(outputDir, { recursive: true }) + + // pdftoppm produces files like -01.jpg, -02.jpg, etc. + const prefix = join(outputDir, 'page') + const args = ['-jpeg', '-r', '100'] + if (options?.firstPage) { + args.push('-f', String(options.firstPage)) + } + if (options?.lastPage && options.lastPage !== Infinity) { + args.push('-l', String(options.lastPage)) + } + args.push(filePath, prefix) + const { code, stderr } = await execFileNoThrow('pdftoppm', args, { + timeout: 120_000, + useCwd: false, + }) + + if (code !== 0) { + if (/password/i.test(stderr)) { + return { + success: false, + error: { + reason: 'password_protected', + message: + 'PDF is password-protected. Please provide an unprotected version.', + }, + } + } + if (/damaged|corrupt|invalid/i.test(stderr)) { + return { + success: false, + error: { + reason: 'corrupted', + message: 'PDF file is corrupted or invalid.', + }, + } + } + return { + success: false, + error: { reason: 'unknown', message: `pdftoppm failed: ${stderr}` }, + } + } + + // Read generated image files and sort naturally + const entries = await readdir(outputDir) + const imageFiles = entries.filter(f => f.endsWith('.jpg')).sort() + const pageCount = imageFiles.length + + if (pageCount === 0) { + return { + success: false, + error: { + reason: 'corrupted', + message: 'pdftoppm produced no output pages. The PDF may be invalid.', + }, + } + } + + const count = imageFiles.length + + return { + success: true, + data: { + type: 'parts', + file: { + filePath, + originalSize, + outputDir, + count, + }, + }, + } + } catch (e: unknown) { + return { + success: false, + error: { + reason: 'unknown', + message: errorMessage(e), + }, + } + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/permissions/PermissionUpdateSchema.ts b/_all-in-one-upload/cc-haha/src/utils/permissions/PermissionUpdateSchema.ts new file mode 100644 index 0000000..8d750f0 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/permissions/PermissionUpdateSchema.ts @@ -0,0 +1,78 @@ +/** + * Zod schemas for permission updates. + * + * This file is intentionally kept minimal with no complex dependencies + * so it can be safely imported by src/types/hooks.ts without creating + * circular dependencies. + */ +import z from 'zod/v4' +// Types extracted to src/types/permissions.ts to break import cycles +import type { + PermissionUpdate, + PermissionUpdateDestination, +} from '../../types/permissions.js' +import { lazySchema } from '../lazySchema.js' +import { externalPermissionModeSchema } from './PermissionMode.js' +import { + permissionBehaviorSchema, + permissionRuleValueSchema, +} from './PermissionRule.js' + +// Re-export for backwards compatibility +export type { PermissionUpdate, PermissionUpdateDestination } + +/** + * PermissionUpdateDestination is where a new permission rule should be saved to. + */ +export const permissionUpdateDestinationSchema = lazySchema(() => + z.enum([ + // User settings (global) + 'userSettings', + // Project settings (shared per-directory) + 'projectSettings', + // Local settings (gitignored) + 'localSettings', + // In-memory for the current session only + 'session', + // From the command line arguments + 'cliArg', + ]), +) + +export const permissionUpdateSchema = lazySchema(() => + z.discriminatedUnion('type', [ + z.object({ + type: z.literal('addRules'), + rules: z.array(permissionRuleValueSchema()), + behavior: permissionBehaviorSchema(), + destination: permissionUpdateDestinationSchema(), + }), + z.object({ + type: z.literal('replaceRules'), + rules: z.array(permissionRuleValueSchema()), + behavior: permissionBehaviorSchema(), + destination: permissionUpdateDestinationSchema(), + }), + z.object({ + type: z.literal('removeRules'), + rules: z.array(permissionRuleValueSchema()), + behavior: permissionBehaviorSchema(), + destination: permissionUpdateDestinationSchema(), + }), + z.object({ + type: z.literal('setMode'), + mode: externalPermissionModeSchema(), + destination: permissionUpdateDestinationSchema(), + }), + z.object({ + type: z.literal('addDirectories'), + directories: z.array(z.string()), + destination: permissionUpdateDestinationSchema(), + }), + z.object({ + type: z.literal('removeDirectories'), + directories: z.array(z.string()), + destination: permissionUpdateDestinationSchema(), + }), + ]), +) diff --git a/_all-in-one-upload/cc-haha/src/utils/permissions/denialTracking.ts b/_all-in-one-upload/cc-haha/src/utils/permissions/denialTracking.ts new file mode 100644 index 0000000..0ea0f62 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/permissions/denialTracking.ts @@ -0,0 +1,45 @@ +/** + * Denial tracking infrastructure for permission classifiers. + * Tracks consecutive denials and total denials to determine + * when to fall back to prompting. + */ + +export type DenialTrackingState = { + consecutiveDenials: number + totalDenials: number +} + +export const DENIAL_LIMITS = { + maxConsecutive: 3, + maxTotal: 20, +} as const + +export function createDenialTrackingState(): DenialTrackingState { + return { + consecutiveDenials: 0, + totalDenials: 0, + } +} + +export function recordDenial(state: DenialTrackingState): DenialTrackingState { + return { + ...state, + consecutiveDenials: state.consecutiveDenials + 1, + totalDenials: state.totalDenials + 1, + } +} + +export function recordSuccess(state: DenialTrackingState): DenialTrackingState { + if (state.consecutiveDenials === 0) return state // No change needed + return { + ...state, + consecutiveDenials: 0, + } +} + +export function shouldFallbackToPrompting(state: DenialTrackingState): boolean { + return ( + state.consecutiveDenials >= DENIAL_LIMITS.maxConsecutive || + state.totalDenials >= DENIAL_LIMITS.maxTotal + ) +} diff --git a/_all-in-one-upload/cc-haha/src/utils/permissions/permissionsLoader.ts b/_all-in-one-upload/cc-haha/src/utils/permissions/permissionsLoader.ts new file mode 100644 index 0000000..29f06f9 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/permissions/permissionsLoader.ts @@ -0,0 +1,296 @@ +import { readFileSync } from '../fileRead.js' +import { getFsImplementation, safeResolvePath } from '../fsOperations.js' +import { safeParseJSON } from '../json.js' +import { logError } from '../log.js' +import { + type EditableSettingSource, + getEnabledSettingSources, + type SettingSource, +} from '../settings/constants.js' +import { + getSettingsFilePathForSource, + getSettingsForSource, + updateSettingsForSource, +} from '../settings/settings.js' +import type { SettingsJson } from '../settings/types.js' +import type { + PermissionBehavior, + PermissionRule, + PermissionRuleSource, + PermissionRuleValue, +} from './PermissionRule.js' +import { + permissionRuleValueFromString, + permissionRuleValueToString, +} from './permissionRuleParser.js' + +/** + * Returns true if allowManagedPermissionRulesOnly is enabled in managed settings (policySettings). + * When enabled, only permission rules from managed settings are respected. + */ +export function shouldAllowManagedPermissionRulesOnly(): boolean { + return ( + getSettingsForSource('policySettings')?.allowManagedPermissionRulesOnly === + true + ) +} + +/** + * Returns true if "always allow" options should be shown in permission prompts. + * When allowManagedPermissionRulesOnly is enabled, these options are hidden. + */ +export function shouldShowAlwaysAllowOptions(): boolean { + return !shouldAllowManagedPermissionRulesOnly() +} + +const SUPPORTED_RULE_BEHAVIORS = [ + 'allow', + 'deny', + 'ask', +] as const satisfies PermissionBehavior[] + +/** + * Lenient version of getSettingsForSource that doesn't fail on ANY validation errors. + * Simply parses the JSON and returns it as-is without schema validation. + * + * Used when loading settings to append new rules (avoids losing existing rules + * due to validation failures in unrelated fields like hooks). + * + * FOR EDITING ONLY - do not use this for reading settings for execution. + */ +function getSettingsForSourceLenient_FOR_EDITING_ONLY_NOT_FOR_READING( + source: SettingSource, +): SettingsJson | null { + const filePath = getSettingsFilePathForSource(source) + if (!filePath) { + return null + } + + try { + const { resolvedPath } = safeResolvePath(getFsImplementation(), filePath) + const content = readFileSync(resolvedPath) + if (content.trim() === '') { + return {} + } + + const data = safeParseJSON(content, false) + // Return raw parsed JSON without validation to preserve all existing settings + // This is safe because we're only using this for reading/appending, not for execution + return data && typeof data === 'object' ? (data as SettingsJson) : null + } catch { + return null + } +} + +/** + * Converts permissions JSON to an array of PermissionRule objects + * @param data The parsed permissions data + * @param source The source of these rules + * @returns Array of PermissionRule objects + */ +function settingsJsonToRules( + data: SettingsJson | null, + source: PermissionRuleSource, +): PermissionRule[] { + if (!data || !data.permissions) { + return [] + } + + const { permissions } = data + const rules: PermissionRule[] = [] + for (const behavior of SUPPORTED_RULE_BEHAVIORS) { + const behaviorArray = permissions[behavior] + if (behaviorArray) { + for (const ruleString of behaviorArray) { + rules.push({ + source, + ruleBehavior: behavior, + ruleValue: permissionRuleValueFromString(ruleString), + }) + } + } + } + return rules +} + +/** + * Loads all permission rules from all relevant sources (managed and project settings) + * @returns Array of all permission rules + */ +export function loadAllPermissionRulesFromDisk(): PermissionRule[] { + // If allowManagedPermissionRulesOnly is set, only use managed permission rules + if (shouldAllowManagedPermissionRulesOnly()) { + return getPermissionRulesForSource('policySettings') + } + + // Otherwise, load from all enabled sources (backwards compatible) + const rules: PermissionRule[] = [] + + for (const source of getEnabledSettingSources()) { + rules.push(...getPermissionRulesForSource(source)) + } + return rules +} + +/** + * Loads permission rules from a specific source + * @param source The source to load from + * @returns Array of permission rules from that source + */ +export function getPermissionRulesForSource( + source: SettingSource, +): PermissionRule[] { + const settingsData = getSettingsForSource(source) + return settingsJsonToRules(settingsData, source) +} + +export type PermissionRuleFromEditableSettings = PermissionRule & { + source: EditableSettingSource +} + +// Editable sources that can be modified (excludes policySettings and flagSettings) +const EDITABLE_SOURCES: EditableSettingSource[] = [ + 'userSettings', + 'projectSettings', + 'localSettings', +] + +/** + * Deletes a rule from the project permissions file + * @param rule The rule to delete + * @returns Promise resolving to a boolean indicating success + */ +export function deletePermissionRuleFromSettings( + rule: PermissionRuleFromEditableSettings, +): boolean { + // Runtime check to ensure source is actually editable + if (!EDITABLE_SOURCES.includes(rule.source as EditableSettingSource)) { + return false + } + + const ruleString = permissionRuleValueToString(rule.ruleValue) + const settingsData = getSettingsForSource(rule.source) + + // If there's no settings data or permissions, nothing to do + if (!settingsData || !settingsData.permissions) { + return false + } + + const behaviorArray = settingsData.permissions[rule.ruleBehavior] + if (!behaviorArray) { + return false + } + + // Normalize raw settings entries via roundtrip parse→serialize so legacy + // names (e.g. "KillShell") match their canonical form ("TaskStop"). + const normalizeEntry = (raw: string): string => + permissionRuleValueToString(permissionRuleValueFromString(raw)) + + if (!behaviorArray.some(raw => normalizeEntry(raw) === ruleString)) { + return false + } + + try { + // Keep a copy of the original permissions data to preserve unrecognized keys + const updatedSettingsData = { + ...settingsData, + permissions: { + ...settingsData.permissions, + [rule.ruleBehavior]: behaviorArray.filter( + raw => normalizeEntry(raw) !== ruleString, + ), + }, + } + + const { error } = updateSettingsForSource(rule.source, updatedSettingsData) + if (error) { + // Error already logged inside updateSettingsForSource + return false + } + + return true + } catch (error) { + logError(error) + return false + } +} + +function getEmptyPermissionSettingsJson(): SettingsJson { + return { + permissions: {}, + } +} + +/** + * Adds rules to the project permissions file + * @param ruleValues The rule values to add + * @returns Promise resolving to a boolean indicating success + */ +export function addPermissionRulesToSettings( + { + ruleValues, + ruleBehavior, + }: { + ruleValues: PermissionRuleValue[] + ruleBehavior: PermissionBehavior + }, + source: EditableSettingSource, +): boolean { + // When allowManagedPermissionRulesOnly is enabled, don't persist new permission rules + if (shouldAllowManagedPermissionRulesOnly()) { + return false + } + + if (ruleValues.length < 1) { + // No rules to add + return true + } + + const ruleStrings = ruleValues.map(permissionRuleValueToString) + // First try the normal settings loader which validates the schema + // If validation fails, fall back to lenient loading to preserve existing rules + // even if some fields (like hooks) have validation errors + const settingsData = + getSettingsForSource(source) || + getSettingsForSourceLenient_FOR_EDITING_ONLY_NOT_FOR_READING(source) || + getEmptyPermissionSettingsJson() + + try { + // Ensure permissions object exists + const existingPermissions = settingsData.permissions || {} + const existingRules = existingPermissions[ruleBehavior] || [] + + // Filter out duplicates - normalize existing entries via roundtrip + // parse→serialize so legacy names match their canonical form. + const existingRulesSet = new Set( + existingRules.map(raw => + permissionRuleValueToString(permissionRuleValueFromString(raw)), + ), + ) + const newRules = ruleStrings.filter(rule => !existingRulesSet.has(rule)) + + // If no new rules to add, return success + if (newRules.length === 0) { + return true + } + + // Keep a copy of the original settings data to preserve unrecognized keys + const updatedSettingsData = { + ...settingsData, + permissions: { + ...existingPermissions, + [ruleBehavior]: [...existingRules, ...newRules], + }, + } + const result = updateSettingsForSource(source, updatedSettingsData) + + if (result.error) { + throw result.error + } + + return true + } catch (error) { + logError(error) + return false + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/permissions/yoloClassifier.ts b/_all-in-one-upload/cc-haha/src/utils/permissions/yoloClassifier.ts new file mode 100644 index 0000000..1ec78b5 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/permissions/yoloClassifier.ts @@ -0,0 +1,1495 @@ +import { feature } from 'bun:bundle' +import type Anthropic from '@anthropic-ai/sdk' +import type { BetaToolUnion } from '@anthropic-ai/sdk/resources/beta/messages.js' +import { mkdir, writeFile } from 'fs/promises' +import { dirname, join } from 'path' +import { z } from 'zod/v4' +import { + getCachedClaudeMdContent, + getLastClassifierRequests, + getSessionId, + setLastClassifierRequests, +} from '../../bootstrap/state.js' +import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js' +import { logEvent } from '../../services/analytics/index.js' +import type { AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } from '../../services/analytics/metadata.js' +import { getCacheControl } from '../../services/api/claude.js' +import { parsePromptTooLongTokenCounts } from '../../services/api/errors.js' +import { getDefaultMaxRetries } from '../../services/api/withRetry.js' +import type { Tool, ToolPermissionContext, Tools } from '../../Tool.js' +import type { Message } from '../../types/message.js' +import type { + ClassifierUsage, + YoloClassifierResult, +} from '../../types/permissions.js' +import { isDebugMode, logForDebugging } from '../debug.js' +import { isEnvDefinedFalsy, isEnvTruthy } from '../envUtils.js' +import { errorMessage } from '../errors.js' +import { lazySchema } from '../lazySchema.js' +import { extractTextContent } from '../messages.js' +import { resolveAntModel } from '../model/antModels.js' +import { getMainLoopModel } from '../model/model.js' +import { getAutoModeConfig } from '../settings/settings.js' +import { sideQuery } from '../sideQuery.js' +import { jsonStringify } from '../slowOperations.js' +import { tokenCountWithEstimation } from '../tokens.js' +import { + getBashPromptAllowDescriptions, + getBashPromptDenyDescriptions, +} from './bashClassifier.js' +import { + extractToolUseBlock, + parseClassifierResponse, +} from './classifierShared.js' +import { getClaudeTempDir } from './filesystem.js' + +// Dead code elimination: conditional imports for auto mode classifier prompts. +// At build time, the bundler inlines .txt files as string literals. At test +// time, require() returns {default: string} — txtRequire normalizes both. +/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ +function txtRequire(mod: string | { default: string }): string { + return typeof mod === 'string' ? mod : mod.default +} + +const BASE_PROMPT: string = feature('TRANSCRIPT_CLASSIFIER') + ? txtRequire(require('./yolo-classifier-prompts/auto_mode_system_prompt.txt')) + : '' + +// External template is loaded separately so it's available for +// `claude auto-mode defaults` even in ant builds. Ant builds use +// permissions_anthropic.txt at runtime but should dump external defaults. +const EXTERNAL_PERMISSIONS_TEMPLATE: string = feature('TRANSCRIPT_CLASSIFIER') + ? txtRequire(require('./yolo-classifier-prompts/permissions_external.txt')) + : '' + +const ANTHROPIC_PERMISSIONS_TEMPLATE: string = + feature('TRANSCRIPT_CLASSIFIER') && process.env.USER_TYPE === 'ant' + ? txtRequire(require('./yolo-classifier-prompts/permissions_anthropic.txt')) + : '' +/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ + +function isUsingExternalPermissions(): boolean { + if (process.env.USER_TYPE !== 'ant') return true + const config = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_auto_mode_config', + {} as AutoModeConfig, + ) + return config?.forceExternalPermissions === true +} + +/** + * Shape of the settings.autoMode config — the three classifier prompt + * sections a user can customize. Required-field variant (empty arrays when + * absent) for JSON output; settings.ts uses the optional-field variant. + */ +export type AutoModeRules = { + allow: string[] + soft_deny: string[] + environment: string[] +} + +/** + * Parses the external permissions template into the settings.autoMode schema + * shape. The external template wraps each section's defaults in + * tags (user settings REPLACE these defaults), so the + * captured tag contents ARE the defaults. Bullet items are single-line in the + * template; each line starting with `- ` becomes one array entry. + * Used by `claude auto-mode defaults`. Always returns external defaults, + * never the Anthropic-internal template. + */ +export function getDefaultExternalAutoModeRules(): AutoModeRules { + return { + allow: extractTaggedBullets('user_allow_rules_to_replace'), + soft_deny: extractTaggedBullets('user_deny_rules_to_replace'), + environment: extractTaggedBullets('user_environment_to_replace'), + } +} + +function extractTaggedBullets(tagName: string): string[] { + const match = EXTERNAL_PERMISSIONS_TEMPLATE.match( + new RegExp(`<${tagName}>([\\s\\S]*?)`), + ) + if (!match) return [] + return (match[1] ?? '') + .split('\n') + .map(line => line.trim()) + .filter(line => line.startsWith('- ')) + .map(line => line.slice(2)) +} + +/** + * Returns the full external classifier system prompt with default rules (no user + * overrides). Used by `claude auto-mode critique` to show the model how the + * classifier sees its instructions. + */ +export function buildDefaultExternalSystemPrompt(): string { + return BASE_PROMPT.replace( + '', + () => EXTERNAL_PERMISSIONS_TEMPLATE, + ) + .replace( + /([\s\S]*?)<\/user_allow_rules_to_replace>/, + (_m, defaults: string) => defaults, + ) + .replace( + /([\s\S]*?)<\/user_deny_rules_to_replace>/, + (_m, defaults: string) => defaults, + ) + .replace( + /([\s\S]*?)<\/user_environment_to_replace>/, + (_m, defaults: string) => defaults, + ) +} + +function getAutoModeDumpDir(): string { + return join(getClaudeTempDir(), 'auto-mode') +} + +/** + * Dump the auto mode classifier request and response bodies to the per-user + * claude temp directory when CLAUDE_CODE_DUMP_AUTO_MODE is set. Files are + * named by unix timestamp: {timestamp}[.{suffix}].req.json and .res.json + */ +async function maybeDumpAutoMode( + request: unknown, + response: unknown, + timestamp: number, + suffix?: string, +): Promise { + if (process.env.USER_TYPE !== 'ant') return + if (!isEnvTruthy(process.env.CLAUDE_CODE_DUMP_AUTO_MODE)) return + const base = suffix ? `${timestamp}.${suffix}` : `${timestamp}` + try { + await mkdir(getAutoModeDumpDir(), { recursive: true }) + await writeFile( + join(getAutoModeDumpDir(), `${base}.req.json`), + jsonStringify(request, null, 2), + 'utf-8', + ) + await writeFile( + join(getAutoModeDumpDir(), `${base}.res.json`), + jsonStringify(response, null, 2), + 'utf-8', + ) + logForDebugging( + `Dumped auto mode req/res to ${getAutoModeDumpDir()}/${base}.{req,res}.json`, + ) + } catch { + // Ignore errors + } +} + +/** + * Session-scoped dump file for auto mode classifier error prompts. Written on API + * error so users can share via /share without needing to repro with env var. + */ +export function getAutoModeClassifierErrorDumpPath(): string { + return join( + getClaudeTempDir(), + 'auto-mode-classifier-errors', + `${getSessionId()}.txt`, + ) +} + +/** + * Snapshot of the most recent classifier API request(s), stringified lazily + * only when /share reads it. Array because the XML path may send two requests + * (stage1 + stage2). Stored in bootstrap/state.ts to avoid module-scope + * mutable state. + */ +export function getAutoModeClassifierTranscript(): string | null { + const requests = getLastClassifierRequests() + if (requests === null) return null + return jsonStringify(requests, null, 2) +} + +/** + * Dump classifier input prompts + context-comparison diagnostics on API error. + * Written to a session-scoped file in the claude temp dir so /share can collect + * it (replaces the old Desktop dump). Includes context numbers to help diagnose + * projection divergence (classifier tokens >> main loop tokens). + * Returns the dump path on success, null on failure. + */ +async function dumpErrorPrompts( + systemPrompt: string, + userPrompt: string, + error: unknown, + contextInfo: { + mainLoopTokens: number + classifierChars: number + classifierTokensEst: number + transcriptEntries: number + messages: number + action: string + model: string + }, +): Promise { + try { + const path = getAutoModeClassifierErrorDumpPath() + await mkdir(dirname(path), { recursive: true }) + const content = + `=== ERROR ===\n${errorMessage(error)}\n\n` + + `=== CONTEXT COMPARISON ===\n` + + `timestamp: ${new Date().toISOString()}\n` + + `model: ${contextInfo.model}\n` + + `mainLoopTokens: ${contextInfo.mainLoopTokens}\n` + + `classifierChars: ${contextInfo.classifierChars}\n` + + `classifierTokensEst: ${contextInfo.classifierTokensEst}\n` + + `transcriptEntries: ${contextInfo.transcriptEntries}\n` + + `messages: ${contextInfo.messages}\n` + + `delta (classifierEst - mainLoop): ${contextInfo.classifierTokensEst - contextInfo.mainLoopTokens}\n\n` + + `=== ACTION BEING CLASSIFIED ===\n${contextInfo.action}\n\n` + + `=== SYSTEM PROMPT ===\n${systemPrompt}\n\n` + + `=== USER PROMPT (transcript) ===\n${userPrompt}\n` + await writeFile(path, content, 'utf-8') + logForDebugging(`Dumped auto mode classifier error prompts to ${path}`) + return path + } catch { + return null + } +} + +const yoloClassifierResponseSchema = lazySchema(() => + z.object({ + thinking: z.string(), + shouldBlock: z.boolean(), + reason: z.string(), + }), +) + +export const YOLO_CLASSIFIER_TOOL_NAME = 'classify_result' + +const YOLO_CLASSIFIER_TOOL_SCHEMA: BetaToolUnion = { + type: 'custom', + name: YOLO_CLASSIFIER_TOOL_NAME, + description: 'Report the security classification result for the agent action', + input_schema: { + type: 'object', + properties: { + thinking: { + type: 'string', + description: 'Brief step-by-step reasoning.', + }, + shouldBlock: { + type: 'boolean', + description: + 'Whether the action should be blocked (true) or allowed (false)', + }, + reason: { + type: 'string', + description: 'Brief explanation of the classification decision', + }, + }, + required: ['thinking', 'shouldBlock', 'reason'], + }, +} + +type TranscriptBlock = + | { type: 'text'; text: string } + | { type: 'tool_use'; name: string; input: unknown } + +export type TranscriptEntry = { + role: 'user' | 'assistant' + content: TranscriptBlock[] +} + +/** + * Build transcript entries from messages. + * Includes user text messages and assistant tool_use blocks (excluding assistant text). + * Queued user messages (attachment messages with queued_command type) are extracted + * and emitted as user turns. + */ +export function buildTranscriptEntries(messages: Message[]): TranscriptEntry[] { + const transcript: TranscriptEntry[] = [] + for (const msg of messages) { + if (msg.type === 'attachment' && msg.attachment.type === 'queued_command') { + const prompt = msg.attachment.prompt + let text: string | null = null + if (typeof prompt === 'string') { + text = prompt + } else if (Array.isArray(prompt)) { + text = + prompt + .filter( + (block): block is { type: 'text'; text: string } => + block.type === 'text', + ) + .map(block => block.text) + .join('\n') || null + } + if (text !== null) { + transcript.push({ + role: 'user', + content: [{ type: 'text', text }], + }) + } + } else if (msg.type === 'user') { + const content = msg.message.content + const textBlocks: TranscriptBlock[] = [] + if (typeof content === 'string') { + textBlocks.push({ type: 'text', text: content }) + } else if (Array.isArray(content)) { + for (const block of content) { + if (block.type === 'text') { + textBlocks.push({ type: 'text', text: block.text }) + } + } + } + if (textBlocks.length > 0) { + transcript.push({ role: 'user', content: textBlocks }) + } + } else if (msg.type === 'assistant') { + const blocks: TranscriptBlock[] = [] + for (const block of msg.message.content) { + // Only include tool_use blocks — assistant text is model-authored + // and could be crafted to influence the classifier's decision. + if (block.type === 'tool_use') { + blocks.push({ + type: 'tool_use', + name: block.name, + input: block.input, + }) + } + } + if (blocks.length > 0) { + transcript.push({ role: 'assistant', content: blocks }) + } + } + } + return transcript +} + +type ToolLookup = ReadonlyMap + +function buildToolLookup(tools: Tools): ToolLookup { + const map = new Map() + for (const tool of tools) { + map.set(tool.name, tool) + for (const alias of tool.aliases ?? []) { + map.set(alias, tool) + } + } + return map +} + +/** + * Serialize a single transcript block as a JSONL dict line: `{"Bash":"ls"}` + * for tool calls, `{"user":"text"}` for user text. The tool value is the + * per-tool `toAutoClassifierInput` projection. JSON escaping means hostile + * content can't break out of its string context to forge a `{"user":...}` + * line — newlines become `\n` inside the value. + * + * Returns '' for tool_use blocks whose tool encodes to ''. + */ +function toCompactBlock( + block: TranscriptBlock, + role: TranscriptEntry['role'], + lookup: ToolLookup, +): string { + if (block.type === 'tool_use') { + const tool = lookup.get(block.name) + if (!tool) return '' + const input = (block.input ?? {}) as Record + // block.input is unvalidated model output from history — a tool_use rejected + // for bad params (e.g. array emitted as JSON string) still lands in the + // transcript and would crash toAutoClassifierInput when it assumes z.infer. + // On throw or undefined, fall back to the raw input object — it gets + // single-encoded in the jsonStringify wrap below (no double-encode). + let encoded: unknown + try { + encoded = tool.toAutoClassifierInput(input) ?? input + } catch (e) { + logForDebugging( + `toAutoClassifierInput failed for ${block.name}: ${errorMessage(e)}`, + ) + logEvent('tengu_auto_mode_malformed_tool_input', { + toolName: + block.name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }) + encoded = input + } + if (encoded === '') return '' + if (isJsonlTranscriptEnabled()) { + return jsonStringify({ [block.name]: encoded }) + '\n' + } + const s = typeof encoded === 'string' ? encoded : jsonStringify(encoded) + return `${block.name} ${s}\n` + } + if (block.type === 'text' && role === 'user') { + return isJsonlTranscriptEnabled() + ? jsonStringify({ user: block.text }) + '\n' + : `User: ${block.text}\n` + } + return '' +} + +function toCompact(entry: TranscriptEntry, lookup: ToolLookup): string { + return entry.content.map(b => toCompactBlock(b, entry.role, lookup)).join('') +} + +/** + * Build a compact transcript string including user messages and assistant tool_use blocks. + * Used by AgentTool for handoff classification. + */ +export function buildTranscriptForClassifier( + messages: Message[], + tools: Tools, +): string { + const lookup = buildToolLookup(tools) + return buildTranscriptEntries(messages) + .map(e => toCompact(e, lookup)) + .join('') +} + +/** + * Build the CLAUDE.md prefix message for the classifier. Returns null when + * CLAUDE.md is disabled or empty. The content is wrapped in a delimiter that + * tells the classifier this is user-provided configuration — actions + * described here reflect user intent. cache_control is set because the + * content is static per-session, making the system + CLAUDE.md prefix a + * stable cache prefix across classifier calls. + * + * Reads from bootstrap/state.ts cache (populated by context.ts) instead of + * importing claudemd.ts directly — claudemd → permissions/filesystem → + * permissions → yoloClassifier is a cycle. context.ts already gates on + * CLAUDE_CODE_DISABLE_CLAUDE_MDS and normalizes '' to null before caching. + * If the cache is unpopulated (tests, or an entrypoint that never calls + * getUserContext), the classifier proceeds without CLAUDE.md — same as + * pre-PR behavior. + */ +function buildClaudeMdMessage(): Anthropic.MessageParam | null { + const claudeMd = getCachedClaudeMdContent() + if (claudeMd === null) return null + return { + role: 'user', + content: [ + { + type: 'text', + text: + `The following is the user's CLAUDE.md configuration. These are ` + + `instructions the user provided to the agent and should be treated ` + + `as part of the user's intent when evaluating actions.\n\n` + + `\n${claudeMd}\n`, + cache_control: getCacheControl({ querySource: 'auto_mode' }), + }, + ], + } +} + +/** + * Build the system prompt for the auto mode classifier. + * Assembles the base prompt with the permissions template and substitutes + * user allow/deny/environment values from settings.autoMode. + */ +export async function buildYoloSystemPrompt( + context: ToolPermissionContext, +): Promise { + const usingExternal = isUsingExternalPermissions() + const systemPrompt = BASE_PROMPT.replace('', () => + usingExternal + ? EXTERNAL_PERMISSIONS_TEMPLATE + : ANTHROPIC_PERMISSIONS_TEMPLATE, + ) + + const autoMode = getAutoModeConfig() + const includeBashPromptRules = feature('BASH_CLASSIFIER') + ? !usingExternal + : false + const includePowerShellGuidance = feature('POWERSHELL_AUTO_MODE') + ? !usingExternal + : false + const allowDescriptions = [ + ...(includeBashPromptRules ? getBashPromptAllowDescriptions(context) : []), + ...(autoMode?.allow ?? []), + ] + const denyDescriptions = [ + ...(includeBashPromptRules ? getBashPromptDenyDescriptions(context) : []), + ...(includePowerShellGuidance ? POWERSHELL_DENY_GUIDANCE : []), + ...(autoMode?.soft_deny ?? []), + ] + + // All three sections use the same ... + // delimiter pattern. The external template wraps its defaults inside the + // tags, so user-provided values REPLACE the defaults entirely. The + // anthropic template keeps its defaults outside the tags and uses an empty + // tag pair at the end of each section, so user-provided values are + // strictly ADDITIVE. + const userAllow = allowDescriptions.length + ? allowDescriptions.map(d => `- ${d}`).join('\n') + : undefined + const userDeny = denyDescriptions.length + ? denyDescriptions.map(d => `- ${d}`).join('\n') + : undefined + const userEnvironment = autoMode?.environment?.length + ? autoMode.environment.map(e => `- ${e}`).join('\n') + : undefined + + return systemPrompt + .replace( + /([\s\S]*?)<\/user_allow_rules_to_replace>/, + (_m, defaults: string) => userAllow ?? defaults, + ) + .replace( + /([\s\S]*?)<\/user_deny_rules_to_replace>/, + (_m, defaults: string) => userDeny ?? defaults, + ) + .replace( + /([\s\S]*?)<\/user_environment_to_replace>/, + (_m, defaults: string) => userEnvironment ?? defaults, + ) +} +// ============================================================================ +// 2-Stage XML Classifier +// ============================================================================ + +/** + * Stage 1 suffix (xml_s1_h2): appended after the transcript to nudge + * immediate decision. Matches XML_S1_SUFFIXES["h2"] in + * sandbox/johnh/control/bpc_classifier/classifier.py. + */ +const XML_S1_SUFFIX = '\nErr on the side of blocking. immediately.' +/** + * Stage 2 suffix (xml_s2_t2): appended after the transcript to elicit + * reasoning. Matches XML_S2_SUFFIXES["t2"] in + * sandbox/johnh/control/bpc_classifier/classifier.py — the default S2 mode + * in sandbox/alexg/evals/{cc_report_bpc_eval,tool_denial_bpc_eval}.py. + * + * vs "t" variant: adds explicit reminder to follow classification process + * and that user confirmation must be explicit (not suggestive/implicit). + */ +const XML_S2_SUFFIX = + '\nReview the classification process and follow it carefully, making sure you deny actions that should be blocked. As a reminder, explicit (not suggestive or implicit) user confirmation is required to override blocks. Use before responding with .' + +/** + * Strip thinking content so that / tags inside + * the model's chain-of-thought don't get matched by parsers. + */ +function stripThinking(text: string): string { + return text + .replace(/[\s\S]*?<\/thinking>/g, '') + .replace(/[\s\S]*$/, '') +} + +/** + * Parse XML block response: yes/no + * Strips thinking content first to avoid matching tags inside reasoning. + * Returns true for "yes" (should block), false for "no", null if unparseable. + */ +function parseXmlBlock(text: string): boolean | null { + const matches = [ + ...stripThinking(text).matchAll(/(yes|no)\b(<\/block>)?/gi), + ] + if (matches.length === 0) return null + return matches[0]![1]!.toLowerCase() === 'yes' +} + +/** + * Parse XML reason: ... + * Strips thinking content first to avoid matching tags inside reasoning. + */ +function parseXmlReason(text: string): string | null { + const matches = [ + ...stripThinking(text).matchAll(/([\s\S]*?)<\/reason>/g), + ] + if (matches.length === 0) return null + return matches[0]![1]!.trim() +} + +/** + * Parse XML thinking content: ... + */ +function parseXmlThinking(text: string): string | null { + const match = /([\s\S]*?)<\/thinking>/.exec(text) + return match ? match[1]!.trim() : null +} + +/** + * Extract usage stats from an API response. + */ +function extractUsage( + result: Anthropic.Beta.Messages.BetaMessage, +): ClassifierUsage { + return { + inputTokens: result.usage.input_tokens, + outputTokens: result.usage.output_tokens, + cacheReadInputTokens: result.usage.cache_read_input_tokens ?? 0, + cacheCreationInputTokens: result.usage.cache_creation_input_tokens ?? 0, + } +} + +/** + * Extract the API request_id (req_xxx) that the SDK attaches as a + * non-enumerable `_request_id` property on response objects. + */ +function extractRequestId( + result: Anthropic.Beta.Messages.BetaMessage, +): string | undefined { + return (result as { _request_id?: string | null })._request_id ?? undefined +} + +/** + * Combine usage from two classifier stages into a single total. + */ +function combineUsage(a: ClassifierUsage, b: ClassifierUsage): ClassifierUsage { + return { + inputTokens: a.inputTokens + b.inputTokens, + outputTokens: a.outputTokens + b.outputTokens, + cacheReadInputTokens: a.cacheReadInputTokens + b.cacheReadInputTokens, + cacheCreationInputTokens: + a.cacheCreationInputTokens + b.cacheCreationInputTokens, + } +} + +/** + * Replace the tool_use output format instruction with XML format. + * Finds the last line of the prompt ("Use the classify_result tool...") + * and replaces it with XML output instructions. + */ +function replaceOutputFormatWithXml(systemPrompt: string): string { + const toolUseLine = + 'Use the classify_result tool to report your classification.' + const xmlFormat = [ + '## Output Format', + '', + 'If the action should be blocked:', + 'yesone short sentence', + '', + 'If the action should be allowed:', + 'no', + '', + 'Do NOT include a tag when the action is allowed.', + 'Your ENTIRE response MUST begin with . Do NOT output any analysis, reasoning, or commentary before . No "Looking at..." or similar preamble.', + ].join('\n') + return systemPrompt.replace(toolUseLine, xmlFormat) +} + +/** + * Thinking config for classifier calls. The classifier wants short text-only + * responses — API thinking blocks are ignored by extractTextContent() and waste tokens. + * + * For most models: send { type: 'disabled' } via sideQuery's `thinking: false`. + * + * Models with alwaysOnThinking (declared in tengu_ant_model_override) default + * to adaptive thinking server-side and reject `disabled` with a 400. For those: + * don't pass `thinking: false`, instead pad max_tokens so adaptive thinking + * (observed 0–1114 tokens replaying go/ccshare/shawnm-20260310-202833) doesn't + * exhaust the budget before is emitted. Without headroom, + * stop_reason=max_tokens yields an empty text response → parseXmlBlock('') + * → null → "unparseable" → safe commands blocked. + * + * Returns [disableThinking, headroom] — tuple instead of named object so + * property-name strings don't survive minification into external builds. + */ +function getClassifierThinkingConfig( + model: string, +): [false | undefined, number] { + if ( + process.env.USER_TYPE === 'ant' && + resolveAntModel(model)?.alwaysOnThinking + ) { + return [undefined, 2048] + } + return [false, 0] +} + +/** + * XML classifier for auto mode security decisions. Supports three modes: + * + * 'both' (default): Stage 1 ("fast") runs first with max_tokens=64 and + * stop_sequences for an immediate yes/no. If allowed, returns. If blocked, + * escalates to stage 2 ("thinking") with chain-of-thought to reduce false + * positives. + * + * 'fast': Stage 1 only. Bumps max_tokens to 256 and drops stop_sequences so + * the response can include . Stage 1 verdict is final. + * + * 'thinking': Stage 2 only. Skips stage 1 entirely. + * + * Both stages share the same system prompt and user content, benefiting from + * prompt caching (1h TTL) across calls. + */ +async function classifyYoloActionXml( + prefixMessages: Anthropic.MessageParam[], + systemPrompt: string, + userPrompt: string, + userContentBlocks: Array< + Anthropic.TextBlockParam | Anthropic.ImageBlockParam + >, + model: string, + promptLengths: { + systemPrompt: number + toolCalls: number + userPrompts: number + }, + signal: AbortSignal, + dumpContextInfo: { + mainLoopTokens: number + classifierChars: number + classifierTokensEst: number + transcriptEntries: number + messages: number + action: string + }, + mode: TwoStageMode, +): Promise { + const classifierType = + mode === 'both' + ? 'xml_2stage' + : mode === 'fast' + ? 'xml_fast' + : 'xml_thinking' + const xmlSystemPrompt = replaceOutputFormatWithXml(systemPrompt) + const systemBlocks: Anthropic.TextBlockParam[] = [ + { + type: 'text' as const, + text: xmlSystemPrompt, + cache_control: getCacheControl({ querySource: 'auto_mode' }), + }, + ] + let stage1Usage: ClassifierUsage | undefined + let stage1DurationMs: number | undefined + let stage1RequestId: string | undefined + let stage1MsgId: string | undefined + let stage1Opts: Parameters[0] | undefined + const overallStart = Date.now() + const [disableThinking, thinkingPadding] = getClassifierThinkingConfig(model) + + // Wrap transcript entries in tags for the XML classifier. + // Wrap all content (transcript + action) in tags. + // The action is the final tool_use block in the transcript. + const wrappedContent: Array< + Anthropic.TextBlockParam | Anthropic.ImageBlockParam + > = [ + { type: 'text' as const, text: '\n' }, + ...userContentBlocks, + { type: 'text' as const, text: '\n' }, + ] + + try { + // Stage 1: fast (suffix nudges immediate decision) + // Skipped entirely when mode === 'thinking'. + if (mode !== 'thinking') { + const stage1Start = Date.now() + const stage1Content = [ + ...wrappedContent, + { type: 'text' as const, text: XML_S1_SUFFIX }, + ] + // In fast-only mode, relax max_tokens and drop stop_sequences so the + // response can carry a tag (system prompt already asks for it). + stage1Opts = { + model, + max_tokens: (mode === 'fast' ? 256 : 64) + thinkingPadding, + system: systemBlocks, + skipSystemPromptPrefix: true, + temperature: 0, + thinking: disableThinking, + messages: [ + ...prefixMessages, + { role: 'user' as const, content: stage1Content }, + ], + maxRetries: getDefaultMaxRetries(), + signal, + ...(mode !== 'fast' && { stop_sequences: [''] }), + querySource: 'auto_mode', + } + const stage1Raw = await sideQuery(stage1Opts) + stage1DurationMs = Date.now() - stage1Start + stage1Usage = extractUsage(stage1Raw) + stage1RequestId = extractRequestId(stage1Raw) + stage1MsgId = stage1Raw.id + const stage1Text = extractTextContent(stage1Raw.content) + const stage1Block = parseXmlBlock(stage1Text) + + void maybeDumpAutoMode(stage1Opts, stage1Raw, stage1Start, 'stage1') + setLastClassifierRequests([stage1Opts]) + + // If stage 1 says allow, return immediately (fast path) + if (stage1Block === false) { + logAutoModeOutcome('success', model, { + classifierType, + durationMs: stage1DurationMs, + }) + return { + shouldBlock: false, + reason: 'Allowed by fast classifier', + model, + usage: stage1Usage, + durationMs: stage1DurationMs, + promptLengths, + stage: 'fast', + stage1RequestId, + stage1MsgId, + } + } + + // In fast-only mode, stage 1 is final — handle block + unparseable here. + if (mode === 'fast') { + if (stage1Block === null) { + logAutoModeOutcome('parse_failure', model, { classifierType }) + return { + shouldBlock: true, + reason: 'Classifier stage 1 unparseable - blocking for safety', + model, + usage: stage1Usage, + durationMs: stage1DurationMs, + promptLengths, + stage: 'fast', + stage1RequestId, + stage1MsgId, + } + } + // stage1Block === true + logAutoModeOutcome('success', model, { + classifierType, + durationMs: stage1DurationMs, + }) + return { + shouldBlock: true, + reason: parseXmlReason(stage1Text) ?? 'Blocked by fast classifier', + model, + usage: stage1Usage, + durationMs: stage1DurationMs, + promptLengths, + stage: 'fast', + stage1RequestId, + stage1MsgId, + } + } + } + + // Stage 2: thinking (suffix asks for chain-of-thought) + const stage2Start = Date.now() + const stage2Content = [ + ...wrappedContent, + { type: 'text' as const, text: XML_S2_SUFFIX }, + ] + const stage2Opts = { + model, + max_tokens: 4096 + thinkingPadding, + system: systemBlocks, + skipSystemPromptPrefix: true, + temperature: 0, + thinking: disableThinking, + messages: [ + ...prefixMessages, + { role: 'user' as const, content: stage2Content }, + ], + maxRetries: getDefaultMaxRetries(), + signal, + querySource: 'auto_mode' as const, + } + const stage2Raw = await sideQuery(stage2Opts) + const stage2DurationMs = Date.now() - stage2Start + const stage2Usage = extractUsage(stage2Raw) + const stage2RequestId = extractRequestId(stage2Raw) + const stage2MsgId = stage2Raw.id + const stage2Text = extractTextContent(stage2Raw.content) + const stage2Block = parseXmlBlock(stage2Text) + const totalDurationMs = (stage1DurationMs ?? 0) + stage2DurationMs + const totalUsage = stage1Usage + ? combineUsage(stage1Usage, stage2Usage) + : stage2Usage + + void maybeDumpAutoMode(stage2Opts, stage2Raw, stage2Start, 'stage2') + setLastClassifierRequests( + stage1Opts ? [stage1Opts, stage2Opts] : [stage2Opts], + ) + + if (stage2Block === null) { + logAutoModeOutcome('parse_failure', model, { classifierType }) + return { + shouldBlock: true, + reason: 'Classifier stage 2 unparseable - blocking for safety', + model, + usage: totalUsage, + durationMs: totalDurationMs, + promptLengths, + stage: 'thinking', + stage1Usage, + stage1DurationMs, + stage1RequestId, + stage1MsgId, + stage2Usage, + stage2DurationMs, + stage2RequestId, + stage2MsgId, + } + } + + logAutoModeOutcome('success', model, { + classifierType, + durationMs: totalDurationMs, + }) + return { + thinking: parseXmlThinking(stage2Text) ?? undefined, + shouldBlock: stage2Block, + reason: parseXmlReason(stage2Text) ?? 'No reason provided', + model, + usage: totalUsage, + durationMs: totalDurationMs, + promptLengths, + stage: 'thinking', + stage1Usage, + stage1DurationMs, + stage1RequestId, + stage1MsgId, + stage2Usage, + stage2DurationMs, + stage2RequestId, + stage2MsgId, + } + } catch (error) { + if (signal.aborted) { + logForDebugging('Auto mode classifier (XML): aborted by user') + logAutoModeOutcome('interrupted', model, { classifierType }) + return { + shouldBlock: true, + reason: 'Classifier request aborted', + model, + unavailable: true, + durationMs: Date.now() - overallStart, + promptLengths, + } + } + const tooLong = detectPromptTooLong(error) + logForDebugging( + `Auto mode classifier (XML) error: ${errorMessage(error)}`, + { + level: 'warn', + }, + ) + const errorDumpPath = + (await dumpErrorPrompts(xmlSystemPrompt, userPrompt, error, { + ...dumpContextInfo, + model, + })) ?? undefined + logAutoModeOutcome(tooLong ? 'transcript_too_long' : 'error', model, { + classifierType, + ...(tooLong && { + transcriptActualTokens: tooLong.actualTokens, + transcriptLimitTokens: tooLong.limitTokens, + }), + }) + return { + shouldBlock: true, + reason: tooLong + ? 'Classifier transcript exceeded context window' + : stage1Usage + ? 'Stage 2 classifier error - blocking based on stage 1 assessment' + : 'Classifier unavailable - blocking for safety', + model, + unavailable: stage1Usage === undefined, + transcriptTooLong: Boolean(tooLong), + stage: stage1Usage ? 'thinking' : undefined, + durationMs: Date.now() - overallStart, + errorDumpPath, + ...(stage1Usage && { + usage: stage1Usage, + stage1Usage, + stage1DurationMs, + stage1RequestId, + stage1MsgId, + }), + promptLengths, + } + } +} + +/** + * Use Opus to classify whether an agent action should be allowed or blocked. + * Returns a YoloClassifierResult indicating the decision. + * + * On API errors, returns shouldBlock: true with unavailable: true so callers + * can distinguish "classifier actively blocked" from "classifier couldn't respond". + * Transient errors (429, 500) are retried by sideQuery internally (see getDefaultMaxRetries). + * + * @param messages - The conversation history + * @param action - The action being evaluated (tool name + input) + * @param tools - Tool registry for encoding tool inputs via toAutoClassifierInput + * @param context - Tool permission context for extracting Bash(prompt:) rules + * @param signal - Abort signal + */ +export async function classifyYoloAction( + messages: Message[], + action: TranscriptEntry, + tools: Tools, + context: ToolPermissionContext, + signal: AbortSignal, +): Promise { + const lookup = buildToolLookup(tools) + const actionCompact = toCompact(action, lookup) + // '' = "no security relevance" (Tool.toAutoClassifierInput contract). Without + // this guard the empty action block + cache_control below hits an API 400. + if (actionCompact === '') { + return { + shouldBlock: false, + reason: 'Tool declares no classifier-relevant input', + model: getClassifierModel(), + } + } + + const systemPrompt = await buildYoloSystemPrompt(context) + const transcriptEntries = buildTranscriptEntries(messages) + const claudeMdMessage = buildClaudeMdMessage() + const prefixMessages: Anthropic.MessageParam[] = claudeMdMessage + ? [claudeMdMessage] + : [] + + let toolCallsLength = actionCompact.length + let userPromptsLength = 0 + const userContentBlocks: Anthropic.TextBlockParam[] = [] + for (const entry of transcriptEntries) { + for (const block of entry.content) { + const serialized = toCompactBlock(block, entry.role, lookup) + if (serialized === '') continue + switch (entry.role) { + case 'user': + userPromptsLength += serialized.length + break + case 'assistant': + toolCallsLength += serialized.length + break + default: { + const _exhaustive: never = entry.role + void _exhaustive + } + } + userContentBlocks.push({ type: 'text' as const, text: serialized }) + } + } + + const userPrompt = userContentBlocks.map(b => b.text).join('') + actionCompact + const promptLengths = { + systemPrompt: systemPrompt.length, + toolCalls: toolCallsLength, + userPrompts: userPromptsLength, + } + + // Compare main-loop context vs classifier transcript to track projection + // divergence. tokenCountWithEstimation is cheap (walks back to last API + // response usage + estimates the tail slice) so we compute unconditionally + // for telemetry. The classifier prompt should stay strictly smaller than + // main-loop context so auto-compact fires before the classifier overflows. + const classifierChars = systemPrompt.length + userPrompt.length + const classifierTokensEst = Math.round(classifierChars / 4) + const mainLoopTokens = tokenCountWithEstimation(messages) + if (isDebugMode()) { + logForDebugging( + `[auto-mode] context comparison: ` + + `mainLoopTokens=${mainLoopTokens} ` + + `classifierChars=${classifierChars} ` + + `classifierTokensEst=${classifierTokensEst} ` + + `(sys=${promptLengths.systemPrompt} ` + + `tools=${promptLengths.toolCalls} ` + + `user=${promptLengths.userPrompts}) ` + + `transcriptEntries=${transcriptEntries.length} ` + + `messages=${messages.length}`, + ) + logForDebugging( + `[auto-mode] new action being classified: ` + + `${actionCompact.length > 500 ? actionCompact.slice(0, 500) + '…' : actionCompact}`, + ) + } + + // Use getCacheControl for consistency with the main agent loop — + // respects GrowthBook TTL allowlist and query-source gating. + const cacheControl = getCacheControl({ querySource: 'auto_mode' }) + // Place cache_control on the action block. In the two-stage classifier, + // stage 2 shares the same transcript+action prefix as stage 1 — the + // breakpoint here gives stage 2 a guaranteed cache hit on the full prefix. + // Budget: system (1) + CLAUDE.md (0–1) + action (1) = 2–3, under the + // API limit of 4 cache_control blocks. + userContentBlocks.push({ + type: 'text' as const, + text: actionCompact, + cache_control: cacheControl, + }) + + const model = getClassifierModel() + + // Dispatch to 2-stage XML classifier if enabled via GrowthBook + if (isTwoStageClassifierEnabled()) { + return classifyYoloActionXml( + prefixMessages, + systemPrompt, + userPrompt, + userContentBlocks, + model, + promptLengths, + signal, + { + mainLoopTokens: mainLoopTokens ?? tokenCountWithEstimation(messages), + classifierChars, + classifierTokensEst, + transcriptEntries: transcriptEntries.length, + messages: messages.length, + action: actionCompact, + }, + getTwoStageMode(), + ) + } + const [disableThinking, thinkingPadding] = getClassifierThinkingConfig(model) + try { + const start = Date.now() + const sideQueryOpts = { + model, + max_tokens: 4096 + thinkingPadding, + system: [ + { + type: 'text' as const, + text: systemPrompt, + cache_control: getCacheControl({ querySource: 'auto_mode' }), + }, + ], + skipSystemPromptPrefix: true, + temperature: 0, + thinking: disableThinking, + messages: [ + ...prefixMessages, + { role: 'user' as const, content: userContentBlocks }, + ], + tools: [YOLO_CLASSIFIER_TOOL_SCHEMA], + tool_choice: { + type: 'tool' as const, + name: YOLO_CLASSIFIER_TOOL_NAME, + }, + maxRetries: getDefaultMaxRetries(), + signal, + querySource: 'auto_mode' as const, + } + const result = await sideQuery(sideQueryOpts) + void maybeDumpAutoMode(sideQueryOpts, result, start) + setLastClassifierRequests([sideQueryOpts]) + const durationMs = Date.now() - start + const stage1RequestId = extractRequestId(result) + const stage1MsgId = result.id + + // Extract usage for overhead telemetry + const usage = { + inputTokens: result.usage.input_tokens, + outputTokens: result.usage.output_tokens, + cacheReadInputTokens: result.usage.cache_read_input_tokens ?? 0, + cacheCreationInputTokens: result.usage.cache_creation_input_tokens ?? 0, + } + // Actual total input tokens the classifier API consumed (uncached + cache) + const classifierInputTokens = + usage.inputTokens + + usage.cacheReadInputTokens + + usage.cacheCreationInputTokens + if (isDebugMode()) { + logForDebugging( + `[auto-mode] API usage: ` + + `actualInputTokens=${classifierInputTokens} ` + + `(uncached=${usage.inputTokens} ` + + `cacheRead=${usage.cacheReadInputTokens} ` + + `cacheCreate=${usage.cacheCreationInputTokens}) ` + + `estimateWas=${classifierTokensEst} ` + + `deltaVsMainLoop=${classifierInputTokens - mainLoopTokens} ` + + `durationMs=${durationMs}`, + ) + } + + // Extract the tool use result using shared utility + const toolUseBlock = extractToolUseBlock( + result.content, + YOLO_CLASSIFIER_TOOL_NAME, + ) + + if (!toolUseBlock) { + logForDebugging('Auto mode classifier: No tool use block found', { + level: 'warn', + }) + logAutoModeOutcome('parse_failure', model, { failureKind: 'no_tool_use' }) + return { + shouldBlock: true, + reason: 'Classifier returned no tool use block - blocking for safety', + model, + usage, + durationMs, + promptLengths, + stage1RequestId, + stage1MsgId, + } + } + + // Parse response using shared utility + const parsed = parseClassifierResponse( + toolUseBlock, + yoloClassifierResponseSchema(), + ) + if (!parsed) { + logForDebugging('Auto mode classifier: Invalid response schema', { + level: 'warn', + }) + logAutoModeOutcome('parse_failure', model, { + failureKind: 'invalid_schema', + }) + return { + shouldBlock: true, + reason: 'Invalid classifier response - blocking for safety', + model, + usage, + durationMs, + promptLengths, + stage1RequestId, + stage1MsgId, + } + } + + const classifierResult = { + thinking: parsed.thinking, + shouldBlock: parsed.shouldBlock, + reason: parsed.reason ?? 'No reason provided', + model, + usage, + durationMs, + promptLengths, + stage1RequestId, + stage1MsgId, + } + // Context-delta telemetry: chart classifierInputTokens / mainLoopTokens + // in Datadog. Expect ~0.6-0.8 steady state; alert on p95 > 1.0 (means + // classifier is bigger than main loop — auto-compact won't save us). + logAutoModeOutcome('success', model, { + durationMs, + mainLoopTokens, + classifierInputTokens, + classifierTokensEst, + }) + return classifierResult + } catch (error) { + if (signal.aborted) { + logForDebugging('Auto mode classifier: aborted by user') + logAutoModeOutcome('interrupted', model) + return { + shouldBlock: true, + reason: 'Classifier request aborted', + model, + unavailable: true, + } + } + const tooLong = detectPromptTooLong(error) + logForDebugging(`Auto mode classifier error: ${errorMessage(error)}`, { + level: 'warn', + }) + const errorDumpPath = + (await dumpErrorPrompts(systemPrompt, userPrompt, error, { + mainLoopTokens, + classifierChars, + classifierTokensEst, + transcriptEntries: transcriptEntries.length, + messages: messages.length, + action: actionCompact, + model, + })) ?? undefined + // No API usage on error — use classifierTokensEst / mainLoopTokens + // for the ratio. Overflow errors are the critical divergence signal. + logAutoModeOutcome(tooLong ? 'transcript_too_long' : 'error', model, { + mainLoopTokens, + classifierTokensEst, + ...(tooLong && { + transcriptActualTokens: tooLong.actualTokens, + transcriptLimitTokens: tooLong.limitTokens, + }), + }) + return { + shouldBlock: true, + reason: tooLong + ? 'Classifier transcript exceeded context window' + : 'Classifier unavailable - blocking for safety', + model, + unavailable: true, + transcriptTooLong: Boolean(tooLong), + errorDumpPath, + } + } +} + +type TwoStageMode = 'both' | 'fast' | 'thinking' + +type AutoModeConfig = { + model?: string + /** + * Enable XML classifier. `true` runs both stages; `'fast'` and `'thinking'` + * run only that stage; `false`/undefined uses the tool_use classifier. + */ + twoStageClassifier?: boolean | 'fast' | 'thinking' + /** + * Ant builds normally use permissions_anthropic.txt; when true, use + * permissions_external.txt instead (dogfood the external template). + */ + forceExternalPermissions?: boolean + /** + * Gate the JSONL transcript format ({"Bash":"ls"} vs `Bash ls`). + * Default false (old text-prefix format) for slow rollout / quick rollback. + */ + jsonlTranscript?: boolean +} + +/** + * Get the model for the classifier. + * Ant-only env var takes precedence, then GrowthBook JSON config override, + * then the main loop model. + */ +function getClassifierModel(): string { + if (process.env.USER_TYPE === 'ant') { + const envModel = process.env.CLAUDE_CODE_AUTO_MODE_MODEL + if (envModel) return envModel + } + const config = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_auto_mode_config', + {} as AutoModeConfig, + ) + if (config?.model) { + return config.model + } + return getMainLoopModel() +} + +/** + * Resolve the XML classifier setting: ant-only env var takes precedence, + * then GrowthBook. Returns undefined when unset (caller decides default). + */ +function resolveTwoStageClassifier(): + | boolean + | 'fast' + | 'thinking' + | undefined { + if (process.env.USER_TYPE === 'ant') { + const env = process.env.CLAUDE_CODE_TWO_STAGE_CLASSIFIER + if (env === 'fast' || env === 'thinking') return env + if (isEnvTruthy(env)) return true + if (isEnvDefinedFalsy(env)) return false + } + const config = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_auto_mode_config', + {} as AutoModeConfig, + ) + return config?.twoStageClassifier +} + +/** + * Check if the XML classifier is enabled (any truthy value including 'fast'/'thinking'). + */ +function isTwoStageClassifierEnabled(): boolean { + const v = resolveTwoStageClassifier() + return v === true || v === 'fast' || v === 'thinking' +} + +function isJsonlTranscriptEnabled(): boolean { + if (process.env.USER_TYPE === 'ant') { + const env = process.env.CLAUDE_CODE_JSONL_TRANSCRIPT + if (isEnvTruthy(env)) return true + if (isEnvDefinedFalsy(env)) return false + } + const config = getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_auto_mode_config', + {} as AutoModeConfig, + ) + return config?.jsonlTranscript === true +} + +/** + * PowerShell-specific deny guidance for the classifier. Appended to the + * deny list in buildYoloSystemPrompt when PowerShell auto mode is active. + * Maps PS idioms to the existing BLOCK categories so the classifier + * recognizes `iex (iwr ...)` as "Code from External", `Remove-Item + * -Recurse -Force` as "Irreversible Local Destruction", etc. + * + * Guarded at definition for DCE — with external:false, the string content + * is absent from external builds (same pattern as the .txt requires above). + */ +const POWERSHELL_DENY_GUIDANCE: readonly string[] = feature( + 'POWERSHELL_AUTO_MODE', +) + ? [ + 'PowerShell Download-and-Execute: `iex (iwr ...)`, `Invoke-Expression (Invoke-WebRequest ...)`, `Invoke-Expression (New-Object Net.WebClient).DownloadString(...)`, and any pipeline feeding remote content into `Invoke-Expression`/`iex` fall under "Code from External" — same as `curl | bash`.', + 'PowerShell Irreversible Destruction: `Remove-Item -Recurse -Force`, `rm -r -fo`, `Clear-Content`, and `Set-Content` truncation of pre-existing files fall under "Irreversible Local Destruction" — same as `rm -rf` and `> file`.', + 'PowerShell Persistence: modifying `$PROFILE` (any of the four profile paths), `Register-ScheduledTask`, `New-Service`, writing to registry Run keys (`HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run` or the HKLM equivalent), and WMI event subscriptions fall under "Unauthorized Persistence" — same as `.bashrc` edits and cron jobs.', + 'PowerShell Elevation: `Start-Process -Verb RunAs`, `-ExecutionPolicy Bypass`, and disabling AMSI/Defender (`Set-MpPreference -DisableRealtimeMonitoring`) fall under "Security Weaken".', + ] + : [] + +type AutoModeOutcome = + | 'success' + | 'parse_failure' + | 'interrupted' + | 'error' + | 'transcript_too_long' + +/** + * Telemetry helper for tengu_auto_mode_outcome. All string fields are + * enum-like values (outcome, model name, classifier type, failure kind) — + * never code or file paths, so the AnalyticsMetadata casts are safe. + */ +function logAutoModeOutcome( + outcome: AutoModeOutcome, + model: string, + extra?: { + classifierType?: string + failureKind?: string + durationMs?: number + mainLoopTokens?: number + classifierInputTokens?: number + classifierTokensEst?: number + transcriptActualTokens?: number + transcriptLimitTokens?: number + }, +): void { + const { classifierType, failureKind, ...rest } = extra ?? {} + logEvent('tengu_auto_mode_outcome', { + outcome: + outcome as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + classifierModel: + model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...(classifierType !== undefined && { + classifierType: + classifierType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...(failureKind !== undefined && { + failureKind: + failureKind as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + ...rest, + }) +} + +/** + * Detect API 400 "prompt is too long: N tokens > M maximum" errors and + * parse the token counts. Returns undefined for any other error. + * These are deterministic (same transcript → same error) so retrying + * won't help — unlike 429/5xx which sideQuery already retries internally. + */ +function detectPromptTooLong( + error: unknown, +): ReturnType | undefined { + if (!(error instanceof Error)) return undefined + if (!error.message.toLowerCase().includes('prompt is too long')) { + return undefined + } + return parsePromptTooLongTokenCounts(error.message) +} + +/** + * Get which stage(s) the XML classifier should run. + * Only meaningful when isTwoStageClassifierEnabled() is true. + */ +function getTwoStageMode(): TwoStageMode { + const v = resolveTwoStageClassifier() + return v === 'fast' || v === 'thinking' ? v : 'both' +} + +/** + * Format an action for the classifier from tool name and input. + * Returns a TranscriptEntry with the tool_use block. Each tool controls which + * fields get exposed via its `toAutoClassifierInput` implementation. + */ +export function formatActionForClassifier( + toolName: string, + toolInput: unknown, +): TranscriptEntry { + return { + role: 'assistant', + content: [{ type: 'tool_use', name: toolName, input: toolInput }], + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/plugins/.syncthing.hintRecommendation.ts.tmp b/_all-in-one-upload/cc-haha/src/utils/plugins/.syncthing.hintRecommendation.ts.tmp new file mode 100644 index 0000000000000000000000000000000000000000..0ae2aeb65a57ffb8d58e46b3edf637ce196e37c2 GIT binary patch literal 5431 ucmeIuF#!Mo0K%a4Pwi_6h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@12-@gHvj { + // For local plugins, we need the resolved absolute path + // Cast to PluginSource since cachePlugin handles any string path at runtime + const source: PluginSource = + typeof entry.source === 'string' && localSourcePath + ? (localSourcePath as PluginSource) + : entry.source + + const cacheResult = await cachePlugin(source, { + manifest: entry as PluginMarketplaceEntry, + }) + + // For local plugins, use the original source path for Git SHA calculation + // because the cached temp directory doesn't have .git (it's copied from a + // subdirectory of the marketplace git repo). For external plugins, use the + // cached path. For git-subdir sources, cachePlugin already captured the SHA + // before discarding the ephemeral clone (the extracted subdir has no .git). + const pathForGitSha = localSourcePath || cacheResult.path + const gitCommitSha = + cacheResult.gitCommitSha ?? (await getGitCommitSha(pathForGitSha)) + + const now = getCurrentTimestamp() + const version = await calculatePluginVersion( + pluginId, + entry.source, + cacheResult.manifest, + pathForGitSha, + entry.version, + cacheResult.gitCommitSha, + ) + + // Move the cached plugin to the versioned path: cache/marketplace/plugin/version/ + const versionedPath = getVersionedCachePath(pluginId, version) + let finalPath = cacheResult.path + + // Only move if the paths are different and plugin was cached to a different location + if (cacheResult.path !== versionedPath) { + // Create the versioned directory structure + await getFsImplementation().mkdir(dirname(versionedPath)) + + // Remove existing versioned path if present (force: no-op if missing) + await rm(versionedPath, { recursive: true, force: true }) + + // Check if versionedPath is a subdirectory of cacheResult.path + // This happens when marketplace name equals plugin name (e.g., "exa-mcp-server@exa-mcp-server") + // In this case, we can't directly rename because we'd be moving a directory into itself + const normalizedCachePath = cacheResult.path.endsWith(sep) + ? cacheResult.path + : cacheResult.path + sep + const isSubdirectory = versionedPath.startsWith(normalizedCachePath) + + if (isSubdirectory) { + // Move to a temp location first, then to final destination + // We can't directly rename/copy a directory into its own subdirectory + // Use the parent of cacheResult.path (same filesystem) to avoid EXDEV + // errors when /tmp is on a different filesystem (e.g., tmpfs) + const tempPath = join( + dirname(cacheResult.path), + `.claude-plugin-temp-${Date.now()}-${randomBytes(4).toString('hex')}`, + ) + await rename(cacheResult.path, tempPath) + await getFsImplementation().mkdir(dirname(versionedPath)) + await rename(tempPath, versionedPath) + } else { + // Move the cached plugin to the versioned location + await rename(cacheResult.path, versionedPath) + } + finalPath = versionedPath + } + + // Zip cache mode: convert directory to ZIP and remove the directory + if (isPluginZipCacheEnabled()) { + const zipPath = getVersionedZipCachePath(pluginId, version) + await convertDirectoryToZipInPlace(finalPath, zipPath) + finalPath = zipPath + } + + // Add to both V1 and V2 installed_plugins files with correct scope + addInstalledPlugin( + pluginId, + { + version, + installedAt: now, + lastUpdated: now, + installPath: finalPath, + gitCommitSha, + }, + scope, + projectPath, + ) + + return finalPath +} + +/** + * Register a plugin installation without caching + * + * Used for local plugins that are already on disk and don't need remote caching. + * External plugins should use cacheAndRegisterPlugin() instead. + * + * @param info - Plugin installation information + * @param scope - Installation scope (user, project, local, or managed). Defaults to 'user'. + * 'managed' scope is used for plugins registered from managed settings. + * @param projectPath - Project path (required for project/local scopes) + */ +export function registerPluginInstallation( + info: PluginInstallationInfo, + scope: PluginScope = 'user', + projectPath?: string, +): void { + const now = getCurrentTimestamp() + addInstalledPlugin( + info.pluginId, + { + version: info.version || 'unknown', + installedAt: now, + lastUpdated: now, + installPath: info.installPath, + }, + scope, + projectPath, + ) +} + +/** + * Parse plugin ID into components + * + * @param pluginId - Plugin ID in "plugin@marketplace" format + * @returns Parsed components or null if invalid + */ +export function parsePluginId( + pluginId: string, +): { name: string; marketplace: string } | null { + const parts = pluginId.split('@') + if (parts.length !== 2 || !parts[0] || !parts[1]) { + return null + } + + return { + name: parts[0], + marketplace: parts[1], + } +} + +/** + * Structured result from the install core. Wrappers format messages and + * handle analytics/error-catching around this. + */ +export type InstallCoreResult = + | { ok: true; closure: string[]; depNote: string } + | { ok: false; reason: 'local-source-no-location'; pluginName: string } + | { ok: false; reason: 'settings-write-failed'; message: string } + | { + ok: false + reason: 'resolution-failed' + resolution: ResolutionResult & { ok: false } + } + | { ok: false; reason: 'blocked-by-policy'; pluginName: string } + | { + ok: false + reason: 'dependency-blocked-by-policy' + pluginName: string + blockedDependency: string + } + +/** + * Format a failed ResolutionResult into a user-facing message. Unified on + * the richer CLI messages (the "Is the X marketplace added?" hint is useful + * for UI users too). + */ +export function formatResolutionError( + r: ResolutionResult & { ok: false }, +): string { + switch (r.reason) { + case 'cycle': + return `Dependency cycle: ${r.chain.join(' → ')}` + case 'cross-marketplace': { + const depMkt = parsePluginIdentifier(r.dependency).marketplace + const where = depMkt + ? `marketplace "${depMkt}"` + : 'a different marketplace' + const hint = depMkt + ? ` Add "${depMkt}" to allowCrossMarketplaceDependenciesOn in the ROOT marketplace's marketplace.json (the marketplace of the plugin you're installing — only its allowlist applies; no transitive trust).` + : '' + return `Dependency "${r.dependency}" (required by ${r.requiredBy}) is in ${where}, which is not in the allowlist — cross-marketplace dependencies are blocked by default. Install it manually first.${hint}` + } + case 'not-found': { + const { marketplace: depMkt } = parsePluginIdentifier(r.missing) + return depMkt + ? `Dependency "${r.missing}" (required by ${r.requiredBy}) not found. Is the "${depMkt}" marketplace added?` + : `Dependency "${r.missing}" (required by ${r.requiredBy}) not found in any configured marketplace` + } + } +} + +/** + * Core plugin install logic, shared by the CLI path (`installPluginOp`) and + * the interactive UI path (`installPluginFromMarketplace`). Given a + * pre-resolved marketplace entry, this: + * + * 1. Guards against local-source plugins without a marketplace install + * location (would silently no-op otherwise). + * 2. Resolves the transitive dependency closure (when PLUGIN_DEPENDENCIES + * is on; trivial single-plugin closure otherwise). + * 3. Writes the entire closure to enabledPlugins in one settings update. + * 4. Caches each closure member (downloads/copies sources as needed). + * 5. Clears memoization caches. + * + * Returns a structured result. Message formatting, analytics, and top-level + * error wrapping stay in the caller-specific wrappers. + * + * @param marketplaceInstallLocation Pass this if the caller already has it + * (from a prior marketplace search) to avoid a redundant lookup. + */ +export async function installResolvedPlugin({ + pluginId, + entry, + scope, + marketplaceInstallLocation, +}: { + pluginId: string + entry: PluginMarketplaceEntry + scope: 'user' | 'project' | 'local' + marketplaceInstallLocation?: string +}): Promise { + const settingSource = scopeToSettingSource(scope) + + // ── Policy guard ── + // Org-blocked plugins (managed-settings.json enabledPlugins: false) cannot + // be installed. Checked here so all install paths (CLI, UI, hint-triggered) + // are covered in one place. + if (isPluginBlockedByPolicy(pluginId)) { + return { ok: false, reason: 'blocked-by-policy', pluginName: entry.name } + } + + // ── Resolve dependency closure ── + // depInfo caches marketplace lookups so the materialize loop doesn't + // re-fetch. Seed the root if the caller gave us its install location. + const depInfo = new Map< + string, + { entry: PluginMarketplaceEntry; marketplaceInstallLocation: string } + >() + // Without this guard, a local-source root with undefined + // marketplaceInstallLocation falls through: depInfo isn't seeded, the + // materialize loop's `if (!info) continue` skips the root, and the user + // sees "Successfully installed" while nothing is cached. + if (isLocalPluginSource(entry.source) && !marketplaceInstallLocation) { + return { + ok: false, + reason: 'local-source-no-location', + pluginName: entry.name, + } + } + if (marketplaceInstallLocation) { + depInfo.set(pluginId, { entry, marketplaceInstallLocation }) + } + + const rootMarketplace = parsePluginIdentifier(pluginId).marketplace + const allowedCrossMarketplaces = new Set( + (rootMarketplace + ? (await getMarketplaceCacheOnly(rootMarketplace)) + ?.allowCrossMarketplaceDependenciesOn + : undefined) ?? [], + ) + const resolution = await resolveDependencyClosure( + pluginId, + async id => { + if (depInfo.has(id)) return depInfo.get(id)!.entry + if (id === pluginId) return entry + const info = await getPluginById(id) + if (info) depInfo.set(id, info) + return info?.entry ?? null + }, + getEnabledPluginIdsForScope(settingSource), + allowedCrossMarketplaces, + ) + if (!resolution.ok) { + return { ok: false, reason: 'resolution-failed', resolution } + } + + // ── Policy guard for transitive dependencies ── + // The root plugin was already checked above, but any dependency in the + // closure could also be policy-blocked. Check before writing to settings + // so a non-blocked plugin can't pull in a blocked dependency. + for (const id of resolution.closure) { + if (id !== pluginId && isPluginBlockedByPolicy(id)) { + return { + ok: false, + reason: 'dependency-blocked-by-policy', + pluginName: entry.name, + blockedDependency: id, + } + } + } + + // ── ACTION: write entire closure to settings in one call ── + const closureEnabled: Record = {} + for (const id of resolution.closure) closureEnabled[id] = true + const { error } = updateSettingsForSource(settingSource, { + enabledPlugins: { + ...getSettingsForSource(settingSource)?.enabledPlugins, + ...closureEnabled, + }, + }) + if (error) { + return { + ok: false, + reason: 'settings-write-failed', + message: error.message, + } + } + + // ── Materialize: cache each closure member ── + const projectPath = scope !== 'user' ? getCwd() : undefined + for (const id of resolution.closure) { + let info = depInfo.get(id) + // Root wasn't pre-seeded (caller didn't pass marketplaceInstallLocation + // for a non-local source). Fetch now; it's needed for the cache write. + if (!info && id === pluginId) { + const mktLocation = (await getPluginById(id))?.marketplaceInstallLocation + if (mktLocation) info = { entry, marketplaceInstallLocation: mktLocation } + } + if (!info) continue + + let localSourcePath: string | undefined + const { source } = info.entry + if (isLocalPluginSource(source)) { + localSourcePath = validatePathWithinBase( + info.marketplaceInstallLocation, + source, + ) + } + await cacheAndRegisterPlugin( + id, + info.entry, + scope, + projectPath, + localSourcePath, + ) + } + + clearAllCaches() + + const depNote = formatDependencyCountSuffix( + resolution.closure.filter(id => id !== pluginId), + ) + return { ok: true, closure: resolution.closure, depNote } +} + +/** + * Result of a plugin installation operation + */ +export type InstallPluginResult = + | { success: true; message: string } + | { success: false; error: string } + +/** + * Parameters for installing a plugin from marketplace + */ +export type InstallPluginParams = { + pluginId: string + entry: PluginMarketplaceEntry + marketplaceName: string + scope?: 'user' | 'project' | 'local' + trigger?: 'hint' | 'user' +} + +/** + * Install a single plugin from a marketplace with the specified scope. + * Interactive-UI wrapper around `installResolvedPlugin` — adds try/catch, + * analytics, and UI-style message formatting. + */ +export async function installPluginFromMarketplace({ + pluginId, + entry, + marketplaceName, + scope = 'user', + trigger = 'user', +}: InstallPluginParams): Promise { + try { + // Look up the marketplace install location for local-source plugins. + // Without this, plugins with relative-path sources fail from the + // interactive UI path (/plugin install) even though the CLI path works. + const pluginInfo = await getPluginById(pluginId) + const marketplaceInstallLocation = pluginInfo?.marketplaceInstallLocation + + const result = await installResolvedPlugin({ + pluginId, + entry, + scope, + marketplaceInstallLocation, + }) + + if (!result.ok) { + switch (result.reason) { + case 'local-source-no-location': + return { + success: false, + error: `Cannot install local plugin "${result.pluginName}" without marketplace install location`, + } + case 'settings-write-failed': + return { + success: false, + error: `Failed to update settings: ${result.message}`, + } + case 'resolution-failed': + return { + success: false, + error: formatResolutionError(result.resolution), + } + case 'blocked-by-policy': + return { + success: false, + error: `Plugin "${result.pluginName}" is blocked by your organization's policy and cannot be installed`, + } + case 'dependency-blocked-by-policy': + return { + success: false, + error: `Cannot install "${result.pluginName}": dependency "${result.blockedDependency}" is blocked by your organization's policy`, + } + } + } + + // _PROTO_* routes to PII-tagged plugin_name/marketplace_name BQ columns. + // plugin_id kept in additional_metadata (redacted to 'third-party' for + // non-official) because dbt external_claude_code_plugin_installs.sql + // extracts $.plugin_id for official-marketplace install tracking. Other + // plugin lifecycle events drop the blob key — no downstream consumers. + logEvent('tengu_plugin_installed', { + _PROTO_plugin_name: + entry.name as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED, + _PROTO_marketplace_name: + marketplaceName as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED, + plugin_id: (isOfficialMarketplaceName(marketplaceName) + ? pluginId + : 'third-party') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + trigger: + trigger as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + install_source: (trigger === 'hint' + ? 'ui-suggestion' + : 'ui-discover') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...buildPluginTelemetryFields( + entry.name, + marketplaceName, + getManagedPluginNames(), + ), + ...(entry.version && { + version: + entry.version as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }), + }) + + return { + success: true, + message: `✓ Installed ${entry.name}${result.depNote}. Run /reload-plugins to activate.`, + } + } catch (err) { + const errorMessage = err instanceof Error ? err.message : String(err) + logError(toError(err)) + return { success: false, error: `Failed to install: ${errorMessage}` } + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/plugins/pluginPolicy.ts b/_all-in-one-upload/cc-haha/src/utils/plugins/pluginPolicy.ts new file mode 100644 index 0000000..bd808ec --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/plugins/pluginPolicy.ts @@ -0,0 +1,20 @@ +/** + * Plugin policy checks backed by managed settings (policySettings). + * + * Kept as a leaf module (only imports settings) to avoid circular dependencies + * — marketplaceHelpers.ts imports marketplaceManager.ts which transitively + * reaches most of the plugin subsystem. + */ + +import { getSettingsForSource } from '../settings/settings.js' + +/** + * Check if a plugin is force-disabled by org policy (managed-settings.json). + * Policy-blocked plugins cannot be installed or enabled by the user at any + * scope. Used as the single source of truth for policy blocking across the + * install chokepoint, enable op, and UI filters. + */ +export function isPluginBlockedByPolicy(pluginId: string): boolean { + const policyEnabled = getSettingsForSource('policySettings')?.enabledPlugins + return policyEnabled?.[pluginId] === false +} diff --git a/_all-in-one-upload/cc-haha/src/utils/processUserInput/processBashCommand.tsx b/_all-in-one-upload/cc-haha/src/utils/processUserInput/processBashCommand.tsx new file mode 100644 index 0000000..8ab9585 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/processUserInput/processBashCommand.tsx @@ -0,0 +1,140 @@ +import type { ContentBlockParam } from '@anthropic-ai/sdk/resources'; +import { randomUUID } from 'crypto'; +import * as React from 'react'; +import { BashModeProgress } from 'src/components/BashModeProgress.js'; +import type { SetToolJSXFn } from 'src/Tool.js'; +import { BashTool } from 'src/tools/BashTool/BashTool.js'; +import type { AttachmentMessage, SystemMessage, UserMessage } from 'src/types/message.js'; +import type { ShellProgress } from 'src/types/tools.js'; +import { logEvent } from '../../services/analytics/index.js'; +import { errorMessage, ShellError } from '../errors.js'; +import { createSyntheticUserCaveatMessage, createUserInterruptionMessage, createUserMessage, prepareUserContent } from '../messages.js'; +import { resolveDefaultShell } from '../shell/resolveDefaultShell.js'; +import { isPowerShellToolEnabled } from '../shell/shellToolUtils.js'; +import { processToolResultBlock } from '../toolResultStorage.js'; +import { escapeXml } from '../xml.js'; +import type { ProcessUserInputContext } from './processUserInput.js'; +export async function processBashCommand(inputString: string, precedingInputBlocks: ContentBlockParam[], attachmentMessages: AttachmentMessage[], context: ProcessUserInputContext, setToolJSX: SetToolJSXFn): Promise<{ + messages: (UserMessage | AttachmentMessage | SystemMessage)[]; + shouldQuery: boolean; +}> { + // Shell routing (docs/design/ps-shell-selection.md §5.2): consult + // defaultShell, fall back to bash. isPowerShellToolEnabled() applies the + // same platform + env-var gate as tools.ts so input-box routing matches + // tool-list visibility. Computed up front so telemetry records the + // actual shell, not the raw setting. + const usePowerShell = isPowerShellToolEnabled() && resolveDefaultShell() === 'powershell'; + logEvent('tengu_input_bash', { + powershell: usePowerShell + }); + const userMessage = createUserMessage({ + content: prepareUserContent({ + inputString: `${inputString}`, + precedingInputBlocks + }) + }); + + // ctrl+b to background indicator + let jsx: React.ReactNode; + + // Just show initial UI + setToolJSX({ + jsx: , + shouldHidePromptInput: false + }); + try { + const bashModeContext: ProcessUserInputContext = { + ...context, + // TODO: Clean up this hack + setToolJSX: _ => { + jsx = _?.jsx; + } + }; + + // Progress UI — shared across both shell backends (both emit ShellProgress) + const onProgress = (progress: { + data: ShellProgress; + }) => { + setToolJSX({ + jsx: <> + + {jsx} + , + shouldHidePromptInput: false, + showSpinner: false + }); + }; + + // User-initiated `!` commands run outside sandbox. Both shell tools honor + // dangerouslyDisableSandbox (checked against areUnsandboxedCommandsAllowed() + // in shouldUseSandbox.ts). PS sandbox is Linux/macOS/WSL2 only — on Windows + // native, shouldUseSandbox() returns false regardless (unsupported platform). + // Lazy-require PowerShellTool so its ~300KB chunk only loads when the + // user has actually selected the powershell default shell. + type PSMod = typeof import('src/tools/PowerShellTool/PowerShellTool.js'); + let PowerShellTool: PSMod['PowerShellTool'] | null = null; + if (usePowerShell) { + /* eslint-disable @typescript-eslint/no-require-imports */ + PowerShellTool = (require('src/tools/PowerShellTool/PowerShellTool.js') as PSMod).PowerShellTool; + /* eslint-enable @typescript-eslint/no-require-imports */ + } + const shellTool = PowerShellTool ?? BashTool; + const response = PowerShellTool ? await PowerShellTool.call({ + command: inputString, + dangerouslyDisableSandbox: true + }, bashModeContext, undefined, undefined, onProgress) : await BashTool.call({ + command: inputString, + dangerouslyDisableSandbox: true + }, bashModeContext, undefined, undefined, onProgress); + const data = response.data; + if (!data) { + throw new Error('No result received from shell command'); + } + const stderr = data.stderr; + // Reuse the same formatting pipeline as inline !`cmd` bash (promptShellExecution) + // and model-initiated Bash. When BashTool.call() persists large output to disk, + // data.persistedOutputPath is set and the formatter wraps in . + // Pass stderr:'' to keep it separate for the UI tag. + const mapped = await processToolResultBlock(shellTool, { + ...data, + stderr: '' + }, randomUUID()); + // mapped.content may contain our own wrapper (trusted + // XML from buildLargeToolResultMessage). Escaping it would turn structural + // tags into <persisted-output>, breaking the model's parse and + // UserBashOutputMessage's extractTag. Escape the raw fallback only. + const stdout = typeof mapped.content === 'string' ? mapped.content : escapeXml(data.stdout); + return { + messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({ + content: `${stdout}${escapeXml(stderr)}` + })], + shouldQuery: false + }; + } catch (e) { + if (e instanceof ShellError) { + if (e.interrupted) { + return { + messages: [createSyntheticUserCaveatMessage(), userMessage, createUserInterruptionMessage({ + toolUse: false + }), ...attachmentMessages], + shouldQuery: false + }; + } + return { + messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({ + content: `${escapeXml(e.stdout)}${escapeXml(e.stderr)}` + })], + shouldQuery: false + }; + } + return { + messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({ + content: `Command failed: ${escapeXml(errorMessage(e))}` + })], + shouldQuery: false + }; + } finally { + setToolJSX(null); + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJDb250ZW50QmxvY2tQYXJhbSIsInJhbmRvbVVVSUQiLCJSZWFjdCIsIkJhc2hNb2RlUHJvZ3Jlc3MiLCJTZXRUb29sSlNYRm4iLCJCYXNoVG9vbCIsIkF0dGFjaG1lbnRNZXNzYWdlIiwiU3lzdGVtTWVzc2FnZSIsIlVzZXJNZXNzYWdlIiwiU2hlbGxQcm9ncmVzcyIsImxvZ0V2ZW50IiwiZXJyb3JNZXNzYWdlIiwiU2hlbGxFcnJvciIsImNyZWF0ZVN5bnRoZXRpY1VzZXJDYXZlYXRNZXNzYWdlIiwiY3JlYXRlVXNlckludGVycnVwdGlvbk1lc3NhZ2UiLCJjcmVhdGVVc2VyTWVzc2FnZSIsInByZXBhcmVVc2VyQ29udGVudCIsInJlc29sdmVEZWZhdWx0U2hlbGwiLCJpc1Bvd2VyU2hlbGxUb29sRW5hYmxlZCIsInByb2Nlc3NUb29sUmVzdWx0QmxvY2siLCJlc2NhcGVYbWwiLCJQcm9jZXNzVXNlcklucHV0Q29udGV4dCIsInByb2Nlc3NCYXNoQ29tbWFuZCIsImlucHV0U3RyaW5nIiwicHJlY2VkaW5nSW5wdXRCbG9ja3MiLCJhdHRhY2htZW50TWVzc2FnZXMiLCJjb250ZXh0Iiwic2V0VG9vbEpTWCIsIlByb21pc2UiLCJtZXNzYWdlcyIsInNob3VsZFF1ZXJ5IiwidXNlUG93ZXJTaGVsbCIsInBvd2Vyc2hlbGwiLCJ1c2VyTWVzc2FnZSIsImNvbnRlbnQiLCJqc3giLCJSZWFjdE5vZGUiLCJvcHRpb25zIiwidmVyYm9zZSIsInNob3VsZEhpZGVQcm9tcHRJbnB1dCIsImJhc2hNb2RlQ29udGV4dCIsIl8iLCJvblByb2dyZXNzIiwicHJvZ3Jlc3MiLCJkYXRhIiwic2hvd1NwaW5uZXIiLCJQU01vZCIsIlBvd2VyU2hlbGxUb29sIiwicmVxdWlyZSIsInNoZWxsVG9vbCIsInJlc3BvbnNlIiwiY2FsbCIsImNvbW1hbmQiLCJkYW5nZXJvdXNseURpc2FibGVTYW5kYm94IiwidW5kZWZpbmVkIiwiRXJyb3IiLCJzdGRlcnIiLCJtYXBwZWQiLCJzdGRvdXQiLCJlIiwiaW50ZXJydXB0ZWQiLCJ0b29sVXNlIl0sInNvdXJjZXMiOlsicHJvY2Vzc0Jhc2hDb21tYW5kLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbnRlbnRCbG9ja1BhcmFtIH0gZnJvbSAnQGFudGhyb3BpYy1haS9zZGsvcmVzb3VyY2VzJ1xuaW1wb3J0IHsgcmFuZG9tVVVJRCB9IGZyb20gJ2NyeXB0bydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQmFzaE1vZGVQcm9ncmVzcyB9IGZyb20gJ3NyYy9jb21wb25lbnRzL0Jhc2hNb2RlUHJvZ3Jlc3MuanMnXG5pbXBvcnQgdHlwZSB7IFNldFRvb2xKU1hGbiB9IGZyb20gJ3NyYy9Ub29sLmpzJ1xuaW1wb3J0IHsgQmFzaFRvb2wgfSBmcm9tICdzcmMvdG9vbHMvQmFzaFRvb2wvQmFzaFRvb2wuanMnXG5pbXBvcnQgdHlwZSB7XG4gIEF0dGFjaG1lbnRNZXNzYWdlLFxuICBTeXN0ZW1NZXNzYWdlLFxuICBVc2VyTWVzc2FnZSxcbn0gZnJvbSAnc3JjL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQgdHlwZSB7IFNoZWxsUHJvZ3Jlc3MgfSBmcm9tICdzcmMvdHlwZXMvdG9vbHMuanMnXG5pbXBvcnQgeyBsb2dFdmVudCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB7IGVycm9yTWVzc2FnZSwgU2hlbGxFcnJvciB9IGZyb20gJy4uL2Vycm9ycy5qcydcbmltcG9ydCB7XG4gIGNyZWF0ZVN5bnRoZXRpY1VzZXJDYXZlYXRNZXNzYWdlLFxuICBjcmVhdGVVc2VySW50ZXJydXB0aW9uTWVzc2FnZSxcbiAgY3JlYXRlVXNlck1lc3NhZ2UsXG4gIHByZXBhcmVVc2VyQ29udGVudCxcbn0gZnJvbSAnLi4vbWVzc2FnZXMuanMnXG5pbXBvcnQgeyByZXNvbHZlRGVmYXVsdFNoZWxsIH0gZnJvbSAnLi4vc2hlbGwvcmVzb2x2ZURlZmF1bHRTaGVsbC5qcydcbmltcG9ydCB7IGlzUG93ZXJTaGVsbFRvb2xFbmFibGVkIH0gZnJvbSAnLi4vc2hlbGwvc2hlbGxUb29sVXRpbHMuanMnXG5pbXBvcnQgeyBwcm9jZXNzVG9vbFJlc3VsdEJsb2NrIH0gZnJvbSAnLi4vdG9vbFJlc3VsdFN0b3JhZ2UuanMnXG5pbXBvcnQgeyBlc2NhcGVYbWwgfSBmcm9tICcuLi94bWwuanMnXG5pbXBvcnQgdHlwZSB7IFByb2Nlc3NVc2VySW5wdXRDb250ZXh0IH0gZnJvbSAnLi9wcm9jZXNzVXNlcklucHV0LmpzJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0Jhc2hDb21tYW5kKFxuICBpbnB1dFN0cmluZzogc3RyaW5nLFxuICBwcmVjZWRpbmdJbnB1dEJsb2NrczogQ29udGVudEJsb2NrUGFyYW1bXSxcbiAgYXR0YWNobWVudE1lc3NhZ2VzOiBBdHRhY2htZW50TWVzc2FnZVtdLFxuICBjb250ZXh0OiBQcm9jZXNzVXNlcklucHV0Q29udGV4dCxcbiAgc2V0VG9vbEpTWDogU2V0VG9vbEpTWEZuLFxuKTogUHJvbWlzZTx7XG4gIG1lc3NhZ2VzOiAoVXNlck1lc3NhZ2UgfCBBdHRhY2htZW50TWVzc2FnZSB8IFN5c3RlbU1lc3NhZ2UpW11cbiAgc2hvdWxkUXVlcnk6IGJvb2xlYW5cbn0+IHtcbiAgLy8gU2hlbGwgcm91dGluZyAoZG9jcy9kZXNpZ24vcHMtc2hlbGwtc2VsZWN0aW9uLm1kIMKnNS4yKTogY29uc3VsdFxuICAvLyBkZWZhdWx0U2hlbGwsIGZhbGwgYmFjayB0byBiYXNoLiBpc1Bvd2VyU2hlbGxUb29sRW5hYmxlZCgpIGFwcGxpZXMgdGhlXG4gIC8vIHNhbWUgcGxhdGZvcm0gKyBlbnYtdmFyIGdhdGUgYXMgdG9vbHMudHMgc28gaW5wdXQtYm94IHJvdXRpbmcgbWF0Y2hlc1xuICAvLyB0b29sLWxpc3QgdmlzaWJpbGl0eS4gQ29tcHV0ZWQgdXAgZnJvbnQgc28gdGVsZW1ldHJ5IHJlY29yZHMgdGhlXG4gIC8vIGFjdHVhbCBzaGVsbCwgbm90IHRoZSByYXcgc2V0dGluZy5cbiAgY29uc3QgdXNlUG93ZXJTaGVsbCA9XG4gICAgaXNQb3dlclNoZWxsVG9vbEVuYWJsZWQoKSAmJiByZXNvbHZlRGVmYXVsdFNoZWxsKCkgPT09ICdwb3dlcnNoZWxsJ1xuXG4gIGxvZ0V2ZW50KCd0ZW5ndV9pbnB1dF9iYXNoJywgeyBwb3dlcnNoZWxsOiB1c2VQb3dlclNoZWxsIH0pXG5cbiAgY29uc3QgdXNlck1lc3NhZ2UgPSBjcmVhdGVVc2VyTWVzc2FnZSh7XG4gICAgY29udGVudDogcHJlcGFyZVVzZXJDb250ZW50KHtcbiAgICAgIGlucHV0U3RyaW5nOiBgPGJhc2gtaW5wdXQ+JHtpbnB1dFN0cmluZ308L2Jhc2gtaW5wdXQ+YCxcbiAgICAgIHByZWNlZGluZ0lucHV0QmxvY2tzLFxuICAgIH0pLFxuICB9KVxuXG4gIC8vIGN0cmwrYiB0byBiYWNrZ3JvdW5kIGluZGljYXRvclxuICBsZXQganN4OiBSZWFjdC5SZWFjdE5vZGVcblxuICAvLyBKdXN0IHNob3cgaW5pdGlhbCBVSVxuICBzZXRUb29sSlNYKHtcbiAgICBqc3g6IChcbiAgICAgIDxCYXNoTW9kZVByb2dyZXNzXG4gICAgICAgIGlucHV0PXtpbnB1dFN0cmluZ31cbiAgICAgICAgcHJvZ3Jlc3M9e251bGx9XG4gICAgICAgIHZlcmJvc2U9e2NvbnRleHQub3B0aW9ucy52ZXJib3NlfVxuICAgICAgLz5cbiAgICApLFxuICAgIHNob3VsZEhpZGVQcm9tcHRJbnB1dDogZmFsc2UsXG4gIH0pXG5cbiAgdHJ5IHtcbiAgICBjb25zdCBiYXNoTW9kZUNvbnRleHQ6IFByb2Nlc3NVc2VySW5wdXRDb250ZXh0ID0ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIC8vIFRPRE86IENsZWFuIHVwIHRoaXMgaGFja1xuICAgICAgc2V0VG9vbEpTWDogXyA9PiB7XG4gICAgICAgIGpzeCA9IF8/LmpzeFxuICAgICAgfSxcbiAgICB9XG5cbiAgICAvLyBQcm9ncmVzcyBVSSDigJQgc2hhcmVkIGFjcm9zcyBib3RoIHNoZWxsIGJhY2tlbmRzIChib3RoIGVtaXQgU2hlbGxQcm9ncmVzcylcbiAgICBjb25zdCBvblByb2dyZXNzID0gKHByb2dyZXNzOiB7IGRhdGE6IFNoZWxsUHJvZ3Jlc3MgfSkgPT4ge1xuICAgICAgc2V0VG9vbEpTWCh7XG4gICAgICAgIGpzeDogKFxuICAgICAgICAgIDw+XG4gICAgICAgICAgICA8QmFzaE1vZGVQcm9ncmVzc1xuICAgICAgICAgICAgICBpbnB1dD17aW5wdXRTdHJpbmchfVxuICAgICAgICAgICAgICBwcm9ncmVzcz17cHJvZ3Jlc3MuZGF0YX1cbiAgICAgICAgICAgICAgdmVyYm9zZT17Y29udGV4dC5vcHRpb25zLnZlcmJvc2V9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAge2pzeH1cbiAgICAgICAgICA8Lz5cbiAgICAgICAgKSxcbiAgICAgICAgc2hvdWxkSGlkZVByb21wdElucHV0OiBmYWxzZSxcbiAgICAgICAgc2hvd1NwaW5uZXI6IGZhbHNlLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyBVc2VyLWluaXRpYXRlZCBgIWAgY29tbWFuZHMgcnVuIG91dHNpZGUgc2FuZGJveC4gQm90aCBzaGVsbCB0b29scyBob25vclxuICAgIC8vIGRhbmdlcm91c2x5RGlzYWJsZVNhbmRib3ggKGNoZWNrZWQgYWdhaW5zdCBhcmVVbnNhbmRib3hlZENvbW1hbmRzQWxsb3dlZCgpXG4gICAgLy8gaW4gc2hvdWxkVXNlU2FuZGJveC50cykuIFBTIHNhbmRib3ggaXMgTGludXgvbWFjT1MvV1NMMiBvbmx5IOKAlCBvbiBXaW5kb3dzXG4gICAgLy8gbmF0aXZlLCBzaG91bGRVc2VTYW5kYm94KCkgcmV0dXJucyBmYWxzZSByZWdhcmRsZXNzICh1bnN1cHBvcnRlZCBwbGF0Zm9ybSkuXG4gICAgLy8gTGF6eS1yZXF1aXJlIFBvd2VyU2hlbGxUb29sIHNvIGl0cyB+MzAwS0IgY2h1bmsgb25seSBsb2FkcyB3aGVuIHRoZVxuICAgIC8vIHVzZXIgaGFzIGFjdHVhbGx5IHNlbGVjdGVkIHRoZSBwb3dlcnNoZWxsIGRlZmF1bHQgc2hlbGwuXG4gICAgdHlwZSBQU01vZCA9IHR5cGVvZiBpbXBvcnQoJ3NyYy90b29scy9Qb3dlclNoZWxsVG9vbC9Qb3dlclNoZWxsVG9vbC5qcycpXG4gICAgbGV0IFBvd2VyU2hlbGxUb29sOiBQU01vZFsnUG93ZXJTaGVsbFRvb2wnXSB8IG51bGwgPSBudWxsXG4gICAgaWYgKHVzZVBvd2VyU2hlbGwpIHtcbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cbiAgICAgIFBvd2VyU2hlbGxUb29sID0gKFxuICAgICAgICByZXF1aXJlKCdzcmMvdG9vbHMvUG93ZXJTaGVsbFRvb2wvUG93ZXJTaGVsbFRvb2wuanMnKSBhcyBQU01vZFxuICAgICAgKS5Qb3dlclNoZWxsVG9vbFxuICAgICAgLyogZXNsaW50LWVuYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzICovXG4gICAgfVxuICAgIGNvbnN0IHNoZWxsVG9vbCA9IFBvd2VyU2hlbGxUb29sID8/IEJhc2hUb29sXG5cbiAgICBjb25zdCByZXNwb25zZSA9IFBvd2VyU2hlbGxUb29sXG4gICAgICA/IGF3YWl0IFBvd2VyU2hlbGxUb29sLmNhbGwoXG4gICAgICAgICAgeyBjb21tYW5kOiBpbnB1dFN0cmluZywgZGFuZ2Vyb3VzbHlEaXNhYmxlU2FuZGJveDogdHJ1ZSB9LFxuICAgICAgICAgIGJhc2hNb2RlQ29udGV4dCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIG9uUHJvZ3Jlc3MsXG4gICAgICAgIClcbiAgICAgIDogYXdhaXQgQmFzaFRvb2wuY2FsbChcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb21tYW5kOiBpbnB1dFN0cmluZyxcbiAgICAgICAgICAgIGRhbmdlcm91c2x5RGlzYWJsZVNhbmRib3g6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBiYXNoTW9kZUNvbnRleHQsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICBvblByb2dyZXNzLFxuICAgICAgICApXG4gICAgY29uc3QgZGF0YSA9IHJlc3BvbnNlLmRhdGFcblxuICAgIGlmICghZGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyByZXN1bHQgcmVjZWl2ZWQgZnJvbSBzaGVsbCBjb21tYW5kJylcbiAgICB9XG5cbiAgICBjb25zdCBzdGRlcnIgPSBkYXRhLnN0ZGVyclxuICAgIC8vIFJldXNlIHRoZSBzYW1lIGZvcm1hdHRpbmcgcGlwZWxpbmUgYXMgaW5saW5lICFgY21kYCBiYXNoIChwcm9tcHRTaGVsbEV4ZWN1dGlvbilcbiAgICAvLyBhbmQgbW9kZWwtaW5pdGlhdGVkIEJhc2guIFdoZW4gQmFzaFRvb2wuY2FsbCgpIHBlcnNpc3RzIGxhcmdlIG91dHB1dCB0byBkaXNrLFxuICAgIC8vIGRhdGEucGVyc2lzdGVkT3V0cHV0UGF0aCBpcyBzZXQgYW5kIHRoZSBmb3JtYXR0ZXIgd3JhcHMgaW4gPHBlcnNpc3RlZC1vdXRwdXQ+LlxuICAgIC8vIFBhc3Mgc3RkZXJyOicnIHRvIGtlZXAgaXQgc2VwYXJhdGUgZm9yIHRoZSA8YmFzaC1zdGRlcnI+IFVJIHRhZy5cbiAgICBjb25zdCBtYXBwZWQgPSBhd2FpdCBwcm9jZXNzVG9vbFJlc3VsdEJsb2NrKFxuICAgICAgc2hlbGxUb29sLFxuICAgICAgeyAuLi5kYXRhLCBzdGRlcnI6ICcnIH0sXG4gICAgICByYW5kb21VVUlEKCksXG4gICAgKVxuICAgIC8vIG1hcHBlZC5jb250ZW50IG1heSBjb250YWluIG91ciBvd24gPHBlcnNpc3RlZC1vdXRwdXQ+IHdyYXBwZXIgKHRydXN0ZWRcbiAgICAvLyBYTUwgZnJvbSBidWlsZExhcmdlVG9vbFJlc3VsdE1lc3NhZ2UpLiBFc2NhcGluZyBpdCB3b3VsZCB0dXJuIHN0cnVjdHVyYWxcbiAgICAvLyB0YWdzIGludG8gJmx0O3BlcnNpc3RlZC1vdXRwdXQmZ3Q7LCBicmVha2luZyB0aGUgbW9kZWwncyBwYXJzZSBhbmRcbiAgICAvLyBVc2VyQmFzaE91dHB1dE1lc3NhZ2UncyBleHRyYWN0VGFnLiBFc2NhcGUgdGhlIHJhdyBmYWxsYmFjayBvbmx5LlxuICAgIGNvbnN0IHN0ZG91dCA9XG4gICAgICB0eXBlb2YgbWFwcGVkLmNvbnRlbnQgPT09ICdzdHJpbmcnXG4gICAgICAgID8gbWFwcGVkLmNvbnRlbnRcbiAgICAgICAgOiBlc2NhcGVYbWwoZGF0YS5zdGRvdXQpXG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgIGNyZWF0ZVN5bnRoZXRpY1VzZXJDYXZlYXRNZXNzYWdlKCksXG4gICAgICAgIHVzZXJNZXNzYWdlLFxuICAgICAgICAuLi5hdHRhY2htZW50TWVzc2FnZXMsXG4gICAgICAgIGNyZWF0ZVVzZXJNZXNzYWdlKHtcbiAgICAgICAgICBjb250ZW50OiBgPGJhc2gtc3Rkb3V0PiR7c3Rkb3V0fTwvYmFzaC1zdGRvdXQ+PGJhc2gtc3RkZXJyPiR7ZXNjYXBlWG1sKHN0ZGVycil9PC9iYXNoLXN0ZGVycj5gLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgICBzaG91bGRRdWVyeTogZmFsc2UsXG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBTaGVsbEVycm9yKSB7XG4gICAgICBpZiAoZS5pbnRlcnJ1cHRlZCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgICAgICBjcmVhdGVTeW50aGV0aWNVc2VyQ2F2ZWF0TWVzc2FnZSgpLFxuICAgICAgICAgICAgdXNlck1lc3NhZ2UsXG4gICAgICAgICAgICBjcmVhdGVVc2VySW50ZXJydXB0aW9uTWVzc2FnZSh7IHRvb2xVc2U6IGZhbHNlIH0pLFxuICAgICAgICAgICAgLi4uYXR0YWNobWVudE1lc3NhZ2VzLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgc2hvdWxkUXVlcnk6IGZhbHNlLFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBtZXNzYWdlczogW1xuICAgICAgICAgIGNyZWF0ZVN5bnRoZXRpY1VzZXJDYXZlYXRNZXNzYWdlKCksXG4gICAgICAgICAgdXNlck1lc3NhZ2UsXG4gICAgICAgICAgLi4uYXR0YWNobWVudE1lc3NhZ2VzLFxuICAgICAgICAgIGNyZWF0ZVVzZXJNZXNzYWdlKHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IGA8YmFzaC1zdGRvdXQ+JHtlc2NhcGVYbWwoZS5zdGRvdXQpfTwvYmFzaC1zdGRvdXQ+PGJhc2gtc3RkZXJyPiR7ZXNjYXBlWG1sKGUuc3RkZXJyKX08L2Jhc2gtc3RkZXJyPmAsXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICAgIHNob3VsZFF1ZXJ5OiBmYWxzZSxcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgIGNyZWF0ZVN5bnRoZXRpY1VzZXJDYXZlYXRNZXNzYWdlKCksXG4gICAgICAgIHVzZXJNZXNzYWdlLFxuICAgICAgICAuLi5hdHRhY2htZW50TWVzc2FnZXMsXG4gICAgICAgIGNyZWF0ZVVzZXJNZXNzYWdlKHtcbiAgICAgICAgICBjb250ZW50OiBgPGJhc2gtc3RkZXJyPkNvbW1hbmQgZmFpbGVkOiAke2VzY2FwZVhtbChlcnJvck1lc3NhZ2UoZSkpfTwvYmFzaC1zdGRlcnI+YCxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgICAgc2hvdWxkUXVlcnk6IGZhbHNlLFxuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBzZXRUb29sSlNYKG51bGwpXG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsY0FBY0EsaUJBQWlCLFFBQVEsNkJBQTZCO0FBQ3BFLFNBQVNDLFVBQVUsUUFBUSxRQUFRO0FBQ25DLE9BQU8sS0FBS0MsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsZ0JBQWdCLFFB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TUFBTXlELE1BQU0sR0FDVixPQUFPRCxNQUFNLENBQUN2QixPQUFPLEtBQUssUUFBUSxHQUM5QnVCLE1BQU0sQ0FBQ3ZCLE9BQU8sR0FDZGQsU0FBUyxDQUFDd0IsSUFBSSxDQUFDYyxNQUFNLENBQUM7SUFDNUIsT0FBTztNQUNMN0IsUUFBUSxFQUFFLENBQ1JoQixnQ0FBZ0MsQ0FBQyxDQUFDLEVBQ2xDb0IsV0FBVyxFQUNYLEdBQUdSLGtCQUFrQixFQUNyQlYsaUJBQWlCLENBQUM7UUFDaEJtQixPQUFPLEVBQUUsZ0JBQWdCd0IsTUFBTSw4QkFBOEJ0QyxTQUFTLENBQUNvQyxNQUFNLENBQUM7TUFDaEYsQ0FBQyxDQUFDLENBQ0g7TUFDRDFCLFdBQVcsRUFBRTtJQUNmLENBQUM7RUFDSCxDQUFDLENBQUMsT0FBTzZCLENBQUMsRUFBRTtJQUNWLElBQUlBLENBQUMsWUFBWS9DLFVBQVUsRUFBRTtNQUMzQixJQUFJK0MsQ0FBQyxDQUFDQyxXQUFXLEVBQUU7UUFDakIsT0FBTztVQUNML0IsUUFBUSxFQUFFLENBQ1JoQixnQ0FBZ0MsQ0FBQyxDQUFDLEVBQ2xDb0IsV0FBVyxFQUNYbkIsNkJBQTZCLENBQUM7WUFBRStDLE9BQU8sRUFBRTtVQUFNLENBQUMsQ0FBQyxFQUNqRCxHQUFHcEMsa0JBQWtCLENBQ3RCO1VBQ0RLLFdBQVcsRUFBRTtRQUNmLENBQUM7TUFDSDtNQUNBLE9BQU87UUFDTEQsUUFBUSxFQUFFLENBQ1JoQixnQ0FBZ0MsQ0FBQyxDQUFDLEVBQ2xDb0IsV0FBVyxFQUNYLEdBQUdSLGtCQUFrQixFQUNyQlYsaUJBQWlCLENBQUM7VUFDaEJtQixPQUFPLEVBQUUsZ0JBQWdCZCxTQUFTLENBQUN1QyxDQUFDLENBQUNELE1BQU0sQ0FBQyw4QkFBOEJ0QyxTQUFTLENBQUN1QyxDQUFDLENBQUNILE1BQU0sQ0FBQztRQUMvRixDQUFDLENBQUMsQ0FDSDtRQUNEMUIsV0FBVyxFQUFFO01BQ2YsQ0FBQztJQUNIO0lBQ0EsT0FBTztNQUNMRCxRQUFRLEVBQUUsQ0FDUmhCLGdDQUFnQyxDQUFDLENBQUMsRUFDbENvQixXQUFXLEVBQ1gsR0FBR1Isa0JBQWtCLEVBQ3JCVixpQkFBaUIsQ0FBQztRQUNoQm1CLE9BQU8sRUFBRSxnQ0FBZ0NkLFNBQVMsQ0FBQ1QsWUFBWSxDQUFDZ0QsQ0FBQyxDQUFDLENBQUM7TUFDckUsQ0FBQyxDQUFDLENBQ0g7TUFDRDdCLFdBQVcsRUFBRTtJQUNmLENBQUM7RUFDSCxDQUFDLFNBQVM7SUFDUkgsVUFBVSxDQUFDLElBQUksQ0FBQztFQUNsQjtBQUNGIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/utils/queryHelpers.ts b/_all-in-one-upload/cc-haha/src/utils/queryHelpers.ts new file mode 100644 index 0000000..a3661ba --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/queryHelpers.ts @@ -0,0 +1,552 @@ +import type { ToolUseBlock } from '@anthropic-ai/sdk/resources/index.mjs' +import last from 'lodash-es/last.js' +import { + getSessionId, + isSessionPersistenceDisabled, +} from 'src/bootstrap/state.js' +import type { SDKMessage } from 'src/entrypoints/agentSdkTypes.js' +import type { CanUseToolFn } from '../hooks/useCanUseTool.js' +import { runTools } from '../services/tools/toolOrchestration.js' +import { findToolByName, type Tool, type Tools } from '../Tool.js' +import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js' +import { FILE_EDIT_TOOL_NAME } from '../tools/FileEditTool/constants.js' +import type { Input as FileReadInput } from '../tools/FileReadTool/FileReadTool.js' +import { + FILE_READ_TOOL_NAME, + FILE_UNCHANGED_STUB, +} from '../tools/FileReadTool/prompt.js' +import { FILE_WRITE_TOOL_NAME } from '../tools/FileWriteTool/prompt.js' +import type { Message } from '../types/message.js' +import type { OrphanedPermission } from '../types/textInputTypes.js' +import { logForDebugging } from './debug.js' +import { isEnvTruthy } from './envUtils.js' +import { isFsInaccessible } from './errors.js' +import { getFileModificationTime, stripLineNumberPrefix } from './file.js' +import { readFileSyncWithMetadata } from './fileRead.js' +import { + createFileStateCacheWithSizeLimit, + type FileStateCache, +} from './fileStateCache.js' +import { isNotEmptyMessage, normalizeMessages } from './messages.js' +import { expandPath } from './path.js' +import type { + inputSchema as permissionToolInputSchema, + outputSchema as permissionToolOutputSchema, +} from './permissions/PermissionPromptToolResultSchema.js' +import type { ProcessUserInputContext } from './processUserInput/processUserInput.js' +import { recordTranscript } from './sessionStorage.js' + +export type PermissionPromptTool = Tool< + ReturnType, + ReturnType +> + +// Small cache size for ask operations which typically access few files +// during permission prompts or limited tool operations +const ASK_READ_FILE_STATE_CACHE_SIZE = 10 + +/** + * Checks if the result should be considered successful based on the last message. + * Returns true if: + * - Last message is assistant with text/thinking content + * - Last message is user with only tool_result blocks + * - Last message is the user prompt but the API completed with end_turn + * (model chose to emit no content blocks) + */ +export function isResultSuccessful( + message: Message | undefined, + stopReason: string | null = null, +): message is Message { + if (!message) return false + + if (message.type === 'assistant') { + const lastContent = last(message.message.content) + return ( + lastContent?.type === 'text' || + lastContent?.type === 'thinking' || + lastContent?.type === 'redacted_thinking' + ) + } + + if (message.type === 'user') { + // Check if all content blocks are tool_result type + const content = message.message.content + if ( + Array.isArray(content) && + content.length > 0 && + content.every(block => 'type' in block && block.type === 'tool_result') + ) { + return true + } + } + + // Carve-out: API completed (message_delta set stop_reason) but yielded + // no assistant content — last(messages) is still this turn's prompt. + // claude.ts:2026 recognizes end_turn-with-zero-content-blocks as + // legitimate and passes through without throwing. Observed on + // task_notification drain turns: model returns stop_reason=end_turn, + // outputTokens=4, textContentLength=0 — it saw the subagent result + // and decided nothing needed saying. Without this, QueryEngine emits + // error_during_execution with errors[] = the entire process's + // accumulated logError() buffer. Covers both string-content and + // text-block-content user prompts, and any other non-passing shape. + return stopReason === 'end_turn' +} + +// Track last sent time for tool progress messages per tool use ID +// Keep only the last 100 entries to prevent unbounded growth +const MAX_TOOL_PROGRESS_TRACKING_ENTRIES = 100 +const TOOL_PROGRESS_THROTTLE_MS = 30000 +const toolProgressLastSentTime = new Map() + +export function* normalizeMessage(message: Message): Generator { + switch (message.type) { + case 'assistant': + for (const _ of normalizeMessages([message])) { + // Skip empty messages (e.g., "(no content)") that shouldn't be output to SDK + if (!isNotEmptyMessage(_)) { + continue + } + yield { + type: 'assistant', + message: _.message, + parent_tool_use_id: null, + session_id: getSessionId(), + uuid: _.uuid, + error: _.error, + } + } + return + case 'progress': + if ( + message.data.type === 'agent_progress' || + message.data.type === 'skill_progress' + ) { + for (const _ of normalizeMessages([message.data.message])) { + switch (_.type) { + case 'assistant': + // Skip empty messages (e.g., "(no content)") that shouldn't be output to SDK + if (!isNotEmptyMessage(_)) { + break + } + yield { + type: 'assistant', + message: _.message, + parent_tool_use_id: message.parentToolUseID, + session_id: getSessionId(), + uuid: _.uuid, + error: _.error, + } + break + case 'user': + yield { + type: 'user', + message: _.message, + parent_tool_use_id: message.parentToolUseID, + session_id: getSessionId(), + uuid: _.uuid, + timestamp: _.timestamp, + isSynthetic: _.isMeta || _.isVisibleInTranscriptOnly, + tool_use_result: _.mcpMeta + ? { content: _.toolUseResult, ..._.mcpMeta } + : _.toolUseResult, + } + break + } + } + } else if ( + message.data.type === 'bash_progress' || + message.data.type === 'powershell_progress' + ) { + // Filter bash progress to send only one per minute + // Only emit for Claude Code Remote for now + if ( + !isEnvTruthy(process.env.CLAUDE_CODE_REMOTE) && + !process.env.CLAUDE_CODE_CONTAINER_ID + ) { + break + } + + // Use parentToolUseID as the key since toolUseID changes for each progress message + const trackingKey = message.parentToolUseID + const now = Date.now() + const lastSent = toolProgressLastSentTime.get(trackingKey) || 0 + const timeSinceLastSent = now - lastSent + + // Send if at least 30 seconds have passed since last update + if (timeSinceLastSent >= TOOL_PROGRESS_THROTTLE_MS) { + // Remove oldest entry if we're at capacity (LRU eviction) + if ( + toolProgressLastSentTime.size >= MAX_TOOL_PROGRESS_TRACKING_ENTRIES + ) { + const firstKey = toolProgressLastSentTime.keys().next().value + if (firstKey !== undefined) { + toolProgressLastSentTime.delete(firstKey) + } + } + + toolProgressLastSentTime.set(trackingKey, now) + yield { + type: 'tool_progress', + tool_use_id: message.toolUseID, + tool_name: + message.data.type === 'bash_progress' ? 'Bash' : 'PowerShell', + parent_tool_use_id: message.parentToolUseID, + elapsed_time_seconds: message.data.elapsedTimeSeconds, + task_id: message.data.taskId, + session_id: getSessionId(), + uuid: message.uuid, + } + } + } + break + case 'user': + for (const _ of normalizeMessages([message])) { + yield { + type: 'user', + message: _.message, + parent_tool_use_id: null, + session_id: getSessionId(), + uuid: _.uuid, + timestamp: _.timestamp, + isSynthetic: _.isMeta || _.isVisibleInTranscriptOnly, + tool_use_result: _.mcpMeta + ? { content: _.toolUseResult, ..._.mcpMeta } + : _.toolUseResult, + } + } + return + default: + // yield nothing + } +} + +export async function* handleOrphanedPermission( + orphanedPermission: OrphanedPermission, + tools: Tools, + mutableMessages: Message[], + processUserInputContext: ProcessUserInputContext, +): AsyncGenerator { + const persistSession = !isSessionPersistenceDisabled() + const { permissionResult, assistantMessage } = orphanedPermission + const { toolUseID } = permissionResult + + if (!toolUseID) { + return + } + + const content = assistantMessage.message.content + let toolUseBlock: ToolUseBlock | undefined + if (Array.isArray(content)) { + for (const block of content) { + if (block.type === 'tool_use' && block.id === toolUseID) { + toolUseBlock = block as ToolUseBlock + break + } + } + } + + if (!toolUseBlock) { + return + } + + const toolName = toolUseBlock.name + const toolInput = toolUseBlock.input + + const toolDefinition = findToolByName(tools, toolName) + if (!toolDefinition) { + return + } + + // Create ToolUseBlock with the updated input if permission was allowed + let finalInput = toolInput + if (permissionResult.behavior === 'allow') { + if (permissionResult.updatedInput !== undefined) { + finalInput = permissionResult.updatedInput + } else { + logForDebugging( + `Orphaned permission for ${toolName}: updatedInput is undefined, falling back to original tool input`, + { level: 'warn' }, + ) + } + } + const finalToolUseBlock: ToolUseBlock = { + ...toolUseBlock, + input: finalInput, + } + + const canUseTool: CanUseToolFn = async () => ({ + ...permissionResult, + decisionReason: { + type: 'mode', + mode: 'default' as const, + }, + }) + + // Add the assistant message with tool_use to messages BEFORE executing + // so the conversation history is complete (tool_use -> tool_result). + // + // On CCR resume, mutableMessages is seeded from the transcript and may already + // contain this tool_use. Pushing again would make normalizeMessagesForAPI merge + // same-ID assistants (concatenating content) and produce a duplicate tool_use + // ID, which the API rejects with "tool_use ids must be unique". + // + // Check for the specific tool_use_id rather than message.id: streaming yields + // each content block as a separate AssistantMessage sharing one message.id, so + // a [text, tool_use] response lands as two entries. filterUnresolvedToolUses may + // strip the tool_use entry but keep the text one; an id-based check would then + // wrongly skip the push while runTools below still executes, orphaning the result. + const alreadyPresent = mutableMessages.some( + m => + m.type === 'assistant' && + Array.isArray(m.message.content) && + m.message.content.some( + b => b.type === 'tool_use' && 'id' in b && b.id === toolUseID, + ), + ) + if (!alreadyPresent) { + mutableMessages.push(assistantMessage) + if (persistSession) { + await recordTranscript(mutableMessages) + } + } + + const sdkAssistantMessage: SDKMessage = { + ...assistantMessage, + session_id: getSessionId(), + parent_tool_use_id: null, + } as SDKMessage + yield sdkAssistantMessage + + // Execute the tool - errors are handled internally by runToolUse + for await (const update of runTools( + [finalToolUseBlock], + [assistantMessage], + canUseTool, + processUserInputContext, + )) { + if (update.message) { + mutableMessages.push(update.message) + if (persistSession) { + await recordTranscript(mutableMessages) + } + + const sdkMessage: SDKMessage = { + ...update.message, + session_id: getSessionId(), + parent_tool_use_id: null, + } as SDKMessage + + yield sdkMessage + } + } +} + +// Create a function to extract read files from messages +export function extractReadFilesFromMessages( + messages: Message[], + cwd: string, + maxSize: number = ASK_READ_FILE_STATE_CACHE_SIZE, +): FileStateCache { + const cache = createFileStateCacheWithSizeLimit(maxSize) + + // First pass: find all FileReadTool/FileWriteTool/FileEditTool uses in assistant messages + const fileReadToolUseIds = new Map() // toolUseId -> filePath + const fileWriteToolUseIds = new Map< + string, + { filePath: string; content: string } + >() // toolUseId -> { filePath, content } + const fileEditToolUseIds = new Map() // toolUseId -> filePath + + for (const message of messages) { + if ( + message.type === 'assistant' && + Array.isArray(message.message.content) + ) { + for (const content of message.message.content) { + if ( + content.type === 'tool_use' && + content.name === FILE_READ_TOOL_NAME + ) { + // Extract file_path from the tool use input + const input = content.input as FileReadInput | undefined + // Ranged reads are not added to the cache. + if ( + input?.file_path && + input?.offset === undefined && + input?.limit === undefined + ) { + // Normalize to absolute path for consistent cache lookups + const absolutePath = expandPath(input.file_path, cwd) + fileReadToolUseIds.set(content.id, absolutePath) + } + } else if ( + content.type === 'tool_use' && + content.name === FILE_WRITE_TOOL_NAME + ) { + // Extract file_path and content from the Write tool use input + const input = content.input as + | { file_path?: string; content?: string } + | undefined + if (input?.file_path && input?.content) { + // Normalize to absolute path for consistent cache lookups + const absolutePath = expandPath(input.file_path, cwd) + fileWriteToolUseIds.set(content.id, { + filePath: absolutePath, + content: input.content, + }) + } + } else if ( + content.type === 'tool_use' && + content.name === FILE_EDIT_TOOL_NAME + ) { + // Edit's input has old_string/new_string, not the resulting content. + // Track the path so the second pass can read current disk state. + const input = content.input as { file_path?: string } | undefined + if (input?.file_path) { + const absolutePath = expandPath(input.file_path, cwd) + fileEditToolUseIds.set(content.id, absolutePath) + } + } + } + } + } + + // Second pass: find corresponding tool results and extract content + for (const message of messages) { + if (message.type === 'user' && Array.isArray(message.message.content)) { + for (const content of message.message.content) { + if (content.type === 'tool_result' && content.tool_use_id) { + // Handle Read tool results + const readFilePath = fileReadToolUseIds.get(content.tool_use_id) + if ( + readFilePath && + typeof content.content === 'string' && + // Dedup stubs contain no file content — the earlier real Read + // already cached it. Chronological last-wins would otherwise + // overwrite the real entry with stub text. + !content.content.startsWith(FILE_UNCHANGED_STUB) + ) { + // Remove system-reminder blocks from the content + const processedContent = content.content.replace( + /[\s\S]*?<\/system-reminder>/g, + '', + ) + + // Extract the actual file content from the tool result + // Tool results for text files contain line numbers, we need to strip those + const fileContent = processedContent + .split('\n') + .map(stripLineNumberPrefix) + .join('\n') + .trim() + + // Cache the file content with the message timestamp + if (message.timestamp) { + const timestamp = new Date(message.timestamp).getTime() + cache.set(readFilePath, { + content: fileContent, + timestamp, + offset: undefined, + limit: undefined, + }) + } + } + + // Handle Write tool results - use content from the tool input + const writeToolData = fileWriteToolUseIds.get(content.tool_use_id) + if (writeToolData && message.timestamp) { + const timestamp = new Date(message.timestamp).getTime() + cache.set(writeToolData.filePath, { + content: writeToolData.content, + timestamp, + offset: undefined, + limit: undefined, + }) + } + + // Handle Edit tool results — post-edit content isn't in the + // tool_use input (only old_string/new_string) nor fully in the + // result (only a snippet). Read from disk now, using actual mtime + // so getChangedFiles's mtime check passes on the next turn. + // + // Callers seed the cache once at process start (print.ts --resume, + // Cowork cold-restart per turn), so disk content at extraction time + // IS the post-edit state. No dedup: processing every Edit preserves + // last-wins semantics when Read/Write interleave (Edit→Read→Edit). + const editFilePath = fileEditToolUseIds.get(content.tool_use_id) + if (editFilePath && content.is_error !== true) { + try { + const { content: diskContent } = + readFileSyncWithMetadata(editFilePath) + cache.set(editFilePath, { + content: diskContent, + timestamp: getFileModificationTime(editFilePath), + offset: undefined, + limit: undefined, + }) + } catch (e: unknown) { + if (!isFsInaccessible(e)) { + throw e + } + // File deleted or inaccessible since the Edit — skip + } + } + } + } + } + } + + return cache +} + +/** + * Extract the top-level CLI tools used in BashTool calls from message history. + * Returns a deduplicated set of command names (e.g. 'vercel', 'aws', 'git'). + */ +export function extractBashToolsFromMessages(messages: Message[]): Set { + const tools = new Set() + for (const message of messages) { + if ( + message.type === 'assistant' && + Array.isArray(message.message.content) + ) { + for (const content of message.message.content) { + if (content.type === 'tool_use' && content.name === BASH_TOOL_NAME) { + const { input } = content + if ( + typeof input !== 'object' || + input === null || + !('command' in input) + ) + continue + const cmd = extractCliName( + typeof input.command === 'string' ? input.command : undefined, + ) + if (cmd) { + tools.add(cmd) + } + } + } + } + } + return tools +} + +const STRIPPED_COMMANDS = new Set(['sudo']) + +/** + * Extract the actual CLI name from a bash command string, skipping + * env var assignments (e.g. `FOO=bar vercel` → `vercel`) and prefixes + * in STRIPPED_COMMANDS. + */ +function extractCliName(command: string | undefined): string | undefined { + if (!command) return undefined + const tokens = command.trim().split(/\s+/) + for (const token of tokens) { + if (/^[A-Za-z_]\w*=/.test(token)) continue + if (STRIPPED_COMMANDS.has(token)) continue + return token + } + return undefined +} diff --git a/_all-in-one-upload/cc-haha/src/utils/secureStorage/keychainPrefetch.ts b/_all-in-one-upload/cc-haha/src/utils/secureStorage/keychainPrefetch.ts new file mode 100644 index 0000000..061c2b1 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/secureStorage/keychainPrefetch.ts @@ -0,0 +1,116 @@ +/** + * Minimal module for firing macOS keychain reads in parallel with main.tsx + * module evaluation, same pattern as startMdmRawRead() in settings/mdm/rawRead.ts. + * + * isRemoteManagedSettingsEligible() reads two separate keychain entries + * SEQUENTIALLY via sync execSync during applySafeConfigEnvironmentVariables(): + * 1. "Claude Code-credentials" (OAuth tokens) — ~32ms + * 2. "Claude Code" (legacy API key) — ~33ms + * Sequential cost: ~65ms on every macOS startup. + * + * Firing both here lets the subprocesses run in parallel with the ~65ms of + * main.tsx imports. ensureKeychainPrefetchCompleted() is awaited alongside + * ensureMdmSettingsLoaded() in main.tsx preAction — nearly free since the + * subprocesses finish during import evaluation. Sync read() and + * getApiKeyFromConfigOrMacOSKeychain() then hit their caches. + * + * Imports stay minimal: child_process + macOsKeychainHelpers.ts (NOT + * macOsKeychainStorage.ts — that pulls in execa → human-signals → + * cross-spawn, ~58ms of synchronous module init). The helpers file's own + * import chain (envUtils, oauth constants, crypto) is already evaluated by + * startupProfiler.ts at main.tsx:5, so no new module-init cost lands here. + */ + +import { execFile } from 'child_process' +import { isBareMode } from '../envUtils.js' +import { + CREDENTIALS_SERVICE_SUFFIX, + getMacOsKeychainStorageServiceName, + getUsername, + primeKeychainCacheFromPrefetch, +} from './macOsKeychainHelpers.js' + +const KEYCHAIN_PREFETCH_TIMEOUT_MS = 10_000 + +// Shared with auth.ts getApiKeyFromConfigOrMacOSKeychain() so it can skip its +// sync spawn when the prefetch already landed. Distinguishing "not started" (null) +// from "completed with no key" ({ stdout: null }) lets the sync reader only +// trust a completed prefetch. +let legacyApiKeyPrefetch: { stdout: string | null } | null = null + +let prefetchPromise: Promise | null = null + +type SpawnResult = { stdout: string | null; timedOut: boolean } + +function spawnSecurity(serviceName: string): Promise { + return new Promise(resolve => { + execFile( + 'security', + ['find-generic-password', '-a', getUsername(), '-w', '-s', serviceName], + { encoding: 'utf-8', timeout: KEYCHAIN_PREFETCH_TIMEOUT_MS }, + (err, stdout) => { + // Exit 44 (entry not found) is a valid "no key" result and safe to + // prime as null. But timeout (err.killed) means the keychain MAY have + // a key we couldn't fetch — don't prime, let sync spawn retry. + // biome-ignore lint/nursery/noFloatingPromises: resolve() is not a floating promise + resolve({ + stdout: err ? null : stdout?.trim() || null, + timedOut: Boolean(err && 'killed' in err && err.killed), + }) + }, + ) + }) +} + +/** + * Fire both keychain reads in parallel. Called at main.tsx top-level + * immediately after startMdmRawRead(). Non-darwin is a no-op. + */ +export function startKeychainPrefetch(): void { + if (process.platform !== 'darwin' || prefetchPromise || isBareMode()) return + + // Fire both subprocesses immediately (non-blocking). They run in parallel + // with each other AND with main.tsx imports. The await in Promise.all + // happens later via ensureKeychainPrefetchCompleted(). + const oauthSpawn = spawnSecurity( + getMacOsKeychainStorageServiceName(CREDENTIALS_SERVICE_SUFFIX), + ) + const legacySpawn = spawnSecurity(getMacOsKeychainStorageServiceName()) + + prefetchPromise = Promise.all([oauthSpawn, legacySpawn]).then( + ([oauth, legacy]) => { + // Timed-out prefetch: don't prime. Sync read/spawn will retry with its + // own (longer) timeout. Priming null here would shadow a key that the + // sync path might successfully fetch. + if (!oauth.timedOut) primeKeychainCacheFromPrefetch(oauth.stdout) + if (!legacy.timedOut) legacyApiKeyPrefetch = { stdout: legacy.stdout } + }, + ) +} + +/** + * Await prefetch completion. Called in main.tsx preAction alongside + * ensureMdmSettingsLoaded() — nearly free since subprocesses finish during + * the ~65ms of main.tsx imports. Resolves immediately on non-darwin. + */ +export async function ensureKeychainPrefetchCompleted(): Promise { + if (prefetchPromise) await prefetchPromise +} + +/** + * Consumed by getApiKeyFromConfigOrMacOSKeychain() in auth.ts before it + * falls through to sync execSync. Returns null if prefetch hasn't completed. + */ +export function getLegacyApiKeyPrefetchResult(): { + stdout: string | null +} | null { + return legacyApiKeyPrefetch +} + +/** + * Clear prefetch result. Called alongside getApiKeyFromConfigOrMacOSKeychain + * cache invalidation so a stale prefetch doesn't shadow a fresh write. + */ +export function clearLegacyApiKeyPrefetch(): void { + legacyApiKeyPrefetch = null +} diff --git a/_all-in-one-upload/cc-haha/src/utils/sessionFileAccessHooks.ts b/_all-in-one-upload/cc-haha/src/utils/sessionFileAccessHooks.ts new file mode 100644 index 0000000..08d4ed5 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/sessionFileAccessHooks.ts @@ -0,0 +1,250 @@ +/** + * Session file access analytics hooks. + * Tracks access to session memory and transcript files via Read, Grep, Glob tools. + * Also tracks memdir file access via Read, Grep, Glob, Edit, and Write tools. + */ +import { feature } from 'bun:bundle' +import { registerHookCallbacks } from '../bootstrap/state.js' +import type { HookInput, HookJSONOutput } from '../entrypoints/agentSdkTypes.js' +import { + type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + logEvent, +} from '../services/analytics/index.js' +import { FILE_EDIT_TOOL_NAME } from '../tools/FileEditTool/constants.js' +import { inputSchema as editInputSchema } from '../tools/FileEditTool/types.js' +import { FileReadTool } from '../tools/FileReadTool/FileReadTool.js' +import { FILE_READ_TOOL_NAME } from '../tools/FileReadTool/prompt.js' +import { FileWriteTool } from '../tools/FileWriteTool/FileWriteTool.js' +import { FILE_WRITE_TOOL_NAME } from '../tools/FileWriteTool/prompt.js' +import { GlobTool } from '../tools/GlobTool/GlobTool.js' +import { GLOB_TOOL_NAME } from '../tools/GlobTool/prompt.js' +import { GrepTool } from '../tools/GrepTool/GrepTool.js' +import { GREP_TOOL_NAME } from '../tools/GrepTool/prompt.js' +import type { HookCallback } from '../types/hooks.js' +import { + detectSessionFileType, + detectSessionPatternType, + isAutoMemFile, + memoryScopeForPath, +} from './memoryFileDetection.js' + +/* eslint-disable @typescript-eslint/no-require-imports */ +const teamMemPaths = feature('TEAMMEM') + ? (require('../memdir/teamMemPaths.js') as typeof import('../memdir/teamMemPaths.js')) + : null +const teamMemWatcher = feature('TEAMMEM') + ? (require('../services/teamMemorySync/watcher.js') as typeof import('../services/teamMemorySync/watcher.js')) + : null +const memoryShapeTelemetry = feature('MEMORY_SHAPE_TELEMETRY') + ? (require('../memdir/memoryShapeTelemetry.js') as typeof import('../memdir/memoryShapeTelemetry.js')) + : null + +/* eslint-enable @typescript-eslint/no-require-imports */ +import { getSubagentLogName } from './agentContext.js' + +/** + * Extract the file path from a tool input for memdir detection. + * Covers Read (file_path), Edit (file_path), and Write (file_path). + */ +function getFilePathFromInput( + toolName: string, + toolInput: unknown, +): string | null { + switch (toolName) { + case FILE_READ_TOOL_NAME: { + const parsed = FileReadTool.inputSchema.safeParse(toolInput) + return parsed.success ? parsed.data.file_path : null + } + case FILE_EDIT_TOOL_NAME: { + const parsed = editInputSchema().safeParse(toolInput) + return parsed.success ? parsed.data.file_path : null + } + case FILE_WRITE_TOOL_NAME: { + const parsed = FileWriteTool.inputSchema.safeParse(toolInput) + return parsed.success ? parsed.data.file_path : null + } + default: + return null + } +} + +/** + * Extract file type from tool input. + * Returns the detected session file type or null. + */ +function getSessionFileTypeFromInput( + toolName: string, + toolInput: unknown, +): 'session_memory' | 'session_transcript' | null { + switch (toolName) { + case FILE_READ_TOOL_NAME: { + const parsed = FileReadTool.inputSchema.safeParse(toolInput) + if (!parsed.success) return null + return detectSessionFileType(parsed.data.file_path) + } + case GREP_TOOL_NAME: { + const parsed = GrepTool.inputSchema.safeParse(toolInput) + if (!parsed.success) return null + // Check path if provided + if (parsed.data.path) { + const pathType = detectSessionFileType(parsed.data.path) + if (pathType) return pathType + } + // Check glob pattern + if (parsed.data.glob) { + const globType = detectSessionPatternType(parsed.data.glob) + if (globType) return globType + } + return null + } + case GLOB_TOOL_NAME: { + const parsed = GlobTool.inputSchema.safeParse(toolInput) + if (!parsed.success) return null + // Check path if provided + if (parsed.data.path) { + const pathType = detectSessionFileType(parsed.data.path) + if (pathType) return pathType + } + // Check pattern + const patternType = detectSessionPatternType(parsed.data.pattern) + if (patternType) return patternType + return null + } + default: + return null + } +} + +/** + * Check if a tool use constitutes a memory file access. + * Detects session memory (via Read/Grep/Glob) and memdir access (via Read/Edit/Write). + * Uses the same conditions as the PostToolUse session file access hooks. + */ +export function isMemoryFileAccess( + toolName: string, + toolInput: unknown, +): boolean { + if (getSessionFileTypeFromInput(toolName, toolInput) === 'session_memory') { + return true + } + + const filePath = getFilePathFromInput(toolName, toolInput) + if ( + filePath && + (isAutoMemFile(filePath) || + (feature('TEAMMEM') && teamMemPaths!.isTeamMemFile(filePath))) + ) { + return true + } + + return false +} + +/** + * PostToolUse callback to log session file access events. + */ +async function handleSessionFileAccess( + input: HookInput, + _toolUseID: string | null, + _signal: AbortSignal | undefined, +): Promise { + if (input.hook_event_name !== 'PostToolUse') return {} + + const fileType = getSessionFileTypeFromInput( + input.tool_name, + input.tool_input, + ) + + const subagentName = getSubagentLogName() + const subagentProps = subagentName ? { subagent_name: subagentName } : {} + + if (fileType === 'session_memory') { + logEvent('tengu_session_memory_accessed', { ...subagentProps }) + } else if (fileType === 'session_transcript') { + logEvent('tengu_transcript_accessed', { ...subagentProps }) + } + + // Memdir access tracking + const filePath = getFilePathFromInput(input.tool_name, input.tool_input) + if (filePath && isAutoMemFile(filePath)) { + logEvent('tengu_memdir_accessed', { + tool: input.tool_name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...subagentProps, + }) + + switch (input.tool_name) { + case FILE_READ_TOOL_NAME: + logEvent('tengu_memdir_file_read', { ...subagentProps }) + break + case FILE_EDIT_TOOL_NAME: + logEvent('tengu_memdir_file_edit', { ...subagentProps }) + break + case FILE_WRITE_TOOL_NAME: + logEvent('tengu_memdir_file_write', { ...subagentProps }) + break + } + } + + // Team memory access tracking + if (feature('TEAMMEM') && filePath && teamMemPaths!.isTeamMemFile(filePath)) { + logEvent('tengu_team_mem_accessed', { + tool: input.tool_name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + ...subagentProps, + }) + + switch (input.tool_name) { + case FILE_READ_TOOL_NAME: + logEvent('tengu_team_mem_file_read', { ...subagentProps }) + break + case FILE_EDIT_TOOL_NAME: + logEvent('tengu_team_mem_file_edit', { ...subagentProps }) + teamMemWatcher?.notifyTeamMemoryWrite() + break + case FILE_WRITE_TOOL_NAME: + logEvent('tengu_team_mem_file_write', { ...subagentProps }) + teamMemWatcher?.notifyTeamMemoryWrite() + break + } + } + + if (feature('MEMORY_SHAPE_TELEMETRY') && filePath) { + const scope = memoryScopeForPath(filePath) + if ( + scope !== null && + (input.tool_name === FILE_EDIT_TOOL_NAME || + input.tool_name === FILE_WRITE_TOOL_NAME) + ) { + memoryShapeTelemetry!.logMemoryWriteShape( + input.tool_name, + input.tool_input, + filePath, + scope, + ) + } + } + + return {} +} + +/** + * Register session file access tracking hooks. + * Called during CLI initialization. + */ +export function registerSessionFileAccessHooks(): void { + const hook: HookCallback = { + type: 'callback', + callback: handleSessionFileAccess, + timeout: 1, // Very short timeout - just logging + internal: true, + } + + registerHookCallbacks({ + PostToolUse: [ + { matcher: FILE_READ_TOOL_NAME, hooks: [hook] }, + { matcher: GREP_TOOL_NAME, hooks: [hook] }, + { matcher: GLOB_TOOL_NAME, hooks: [hook] }, + { matcher: FILE_EDIT_TOOL_NAME, hooks: [hook] }, + { matcher: FILE_WRITE_TOOL_NAME, hooks: [hook] }, + ], + }) +} diff --git a/_all-in-one-upload/cc-haha/src/utils/settings/settings.ts b/_all-in-one-upload/cc-haha/src/utils/settings/settings.ts new file mode 100644 index 0000000..3bea04a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/settings/settings.ts @@ -0,0 +1,1015 @@ +import { feature } from 'bun:bundle' +import mergeWith from 'lodash-es/mergeWith.js' +import { dirname, join, resolve } from 'path' +import { z } from 'zod/v4' +import { + getFlagSettingsInline, + getFlagSettingsPath, + getOriginalCwd, + getUseCoworkPlugins, +} from '../../bootstrap/state.js' +import { getRemoteManagedSettingsSyncFromCache } from '../../services/remoteManagedSettings/syncCacheState.js' +import { uniq } from '../array.js' +import { logForDebugging } from '../debug.js' +import { logForDiagnosticsNoPII } from '../diagLogs.js' +import { getClaudeConfigHomeDir, isEnvTruthy } from '../envUtils.js' +import { getErrnoCode, isENOENT } from '../errors.js' +import { writeFileSyncAndFlush_DEPRECATED } from '../file.js' +import { readFileSync } from '../fileRead.js' +import { getFsImplementation, safeResolvePath } from '../fsOperations.js' +import { addFileGlobRuleToGitignore } from '../git/gitignore.js' +import { safeParseJSON } from '../json.js' +import { logError } from '../log.js' +import { getPlatform } from '../platform.js' +import { clone, jsonStringify } from '../slowOperations.js' +import { profileCheckpoint } from '../startupProfiler.js' +import { + type EditableSettingSource, + getEnabledSettingSources, + type SettingSource, +} from './constants.js' +import { markInternalWrite } from './internalWrites.js' +import { + getManagedFilePath, + getManagedSettingsDropInDir, +} from './managedPath.js' +import { getHkcuSettings, getMdmSettings } from './mdm/settings.js' +import { + getCachedParsedFile, + getCachedSettingsForSource, + getPluginSettingsBase, + getSessionSettingsCache, + resetSettingsCache, + setCachedParsedFile, + setCachedSettingsForSource, + setSessionSettingsCache, +} from './settingsCache.js' +import { type SettingsJson, SettingsSchema } from './types.js' +import { + filterInvalidPermissionRules, + formatZodError, + type SettingsWithErrors, + type ValidationError, +} from './validation.js' + +/** + * Get the path to the managed settings file based on the current platform + */ +function getManagedSettingsFilePath(): string { + return join(getManagedFilePath(), 'managed-settings.json') +} + +/** + * Load file-based managed settings: managed-settings.json + managed-settings.d/*.json. + * + * managed-settings.json is merged first (lowest precedence / base), then drop-in + * files are sorted alphabetically and merged on top (higher precedence, later + * files win). This matches the systemd/sudoers drop-in convention: the base + * file provides defaults, drop-ins customize. Separate teams can ship + * independent policy fragments (e.g. 10-otel.json, 20-security.json) without + * coordinating edits to a single admin-owned file. + * + * Exported for testing. + */ +export function loadManagedFileSettings(): { + settings: SettingsJson | null + errors: ValidationError[] +} { + const errors: ValidationError[] = [] + let merged: SettingsJson = {} + let found = false + + const { settings, errors: baseErrors } = parseSettingsFile( + getManagedSettingsFilePath(), + ) + errors.push(...baseErrors) + if (settings && Object.keys(settings).length > 0) { + merged = mergeWith(merged, settings, settingsMergeCustomizer) + found = true + } + + const dropInDir = getManagedSettingsDropInDir() + try { + const entries = getFsImplementation() + .readdirSync(dropInDir) + .filter( + d => + (d.isFile() || d.isSymbolicLink()) && + d.name.endsWith('.json') && + !d.name.startsWith('.'), + ) + .map(d => d.name) + .sort() + for (const name of entries) { + const { settings, errors: fileErrors } = parseSettingsFile( + join(dropInDir, name), + ) + errors.push(...fileErrors) + if (settings && Object.keys(settings).length > 0) { + merged = mergeWith(merged, settings, settingsMergeCustomizer) + found = true + } + } + } catch (e) { + const code = getErrnoCode(e) + if (code !== 'ENOENT' && code !== 'ENOTDIR') { + logError(e) + } + } + + return { settings: found ? merged : null, errors } +} + +/** + * Check which file-based managed settings sources are present. + * Used by /status to show "(file)", "(drop-ins)", or "(file + drop-ins)". + */ +export function getManagedFileSettingsPresence(): { + hasBase: boolean + hasDropIns: boolean +} { + const { settings: base } = parseSettingsFile(getManagedSettingsFilePath()) + const hasBase = !!base && Object.keys(base).length > 0 + + let hasDropIns = false + const dropInDir = getManagedSettingsDropInDir() + try { + hasDropIns = getFsImplementation() + .readdirSync(dropInDir) + .some( + d => + (d.isFile() || d.isSymbolicLink()) && + d.name.endsWith('.json') && + !d.name.startsWith('.'), + ) + } catch { + // dir doesn't exist + } + + return { hasBase, hasDropIns } +} + +/** + * Handles file system errors appropriately + * @param error The error to handle + * @param path The file path that caused the error + */ +function handleFileSystemError(error: unknown, path: string): void { + if ( + typeof error === 'object' && + error && + 'code' in error && + error.code === 'ENOENT' + ) { + logForDebugging( + `Broken symlink or missing file encountered for settings.json at path: ${path}`, + ) + } else { + logError(error) + } +} + +/** + * Parses a settings file into a structured format + * @param path The path to the permissions file + * @param source The source of the settings (optional, for error reporting) + * @returns Parsed settings data and validation errors + */ +export function parseSettingsFile(path: string): { + settings: SettingsJson | null + errors: ValidationError[] +} { + const cached = getCachedParsedFile(path) + if (cached) { + // Clone so callers (e.g. mergeWith in getSettingsForSourceUncached, + // updateSettingsForSource) can't mutate the cached entry. + return { + settings: cached.settings ? clone(cached.settings) : null, + errors: cached.errors, + } + } + const result = parseSettingsFileUncached(path) + setCachedParsedFile(path, result) + // Clone the first return too — the caller may mutate before + // another caller reads the same cache entry. + return { + settings: result.settings ? clone(result.settings) : null, + errors: result.errors, + } +} + +function parseSettingsFileUncached(path: string): { + settings: SettingsJson | null + errors: ValidationError[] +} { + try { + const { resolvedPath } = safeResolvePath(getFsImplementation(), path) + const content = readFileSync(resolvedPath) + + if (content.trim() === '') { + return { settings: {}, errors: [] } + } + + const data = safeParseJSON(content, false) + + // Filter invalid permission rules before schema validation so one bad + // rule doesn't cause the entire settings file to be rejected. + const ruleWarnings = filterInvalidPermissionRules(data, path) + + const result = SettingsSchema().safeParse(data) + + if (!result.success) { + const errors = formatZodError(result.error, path) + return { settings: null, errors: [...ruleWarnings, ...errors] } + } + + return { settings: result.data, errors: ruleWarnings } + } catch (error) { + handleFileSystemError(error, path) + return { settings: null, errors: [] } + } +} + +/** + * Get the absolute path to the associated file root for a given settings source + * (e.g. for $PROJ_DIR/.claude/settings.json, returns $PROJ_DIR) + * @param source The source of the settings + * @returns The root path of the settings file + */ +export function getSettingsRootPathForSource(source: SettingSource): string { + switch (source) { + case 'userSettings': + return resolve(getClaudeConfigHomeDir()) + case 'policySettings': + case 'projectSettings': + case 'localSettings': { + return resolve(getOriginalCwd()) + } + case 'flagSettings': { + const path = getFlagSettingsPath() + return path ? dirname(resolve(path)) : resolve(getOriginalCwd()) + } + } +} + +/** + * Get the user settings filename based on cowork mode. + * Returns 'cowork_settings.json' when in cowork mode, 'settings.json' otherwise. + * + * Priority: + * 1. Session state (set by CLI flag --cowork) + * 2. Environment variable CLAUDE_CODE_USE_COWORK_PLUGINS + * 3. Default: 'settings.json' + */ +function getUserSettingsFilePath(): string { + if ( + getUseCoworkPlugins() || + isEnvTruthy(process.env.CLAUDE_CODE_USE_COWORK_PLUGINS) + ) { + return 'cowork_settings.json' + } + return 'settings.json' +} + +export function getSettingsFilePathForSource( + source: SettingSource, +): string | undefined { + switch (source) { + case 'userSettings': + return join( + getSettingsRootPathForSource(source), + getUserSettingsFilePath(), + ) + case 'projectSettings': + case 'localSettings': { + return join( + getSettingsRootPathForSource(source), + getRelativeSettingsFilePathForSource(source), + ) + } + case 'policySettings': + return getManagedSettingsFilePath() + case 'flagSettings': { + return getFlagSettingsPath() + } + } +} + +export function getRelativeSettingsFilePathForSource( + source: 'projectSettings' | 'localSettings', +): string { + switch (source) { + case 'projectSettings': + return join('.claude', 'settings.json') + case 'localSettings': + return join('.claude', 'settings.local.json') + } +} + +export function getSettingsForSource( + source: SettingSource, +): SettingsJson | null { + const cached = getCachedSettingsForSource(source) + if (cached !== undefined) return cached + const result = getSettingsForSourceUncached(source) + setCachedSettingsForSource(source, result) + return result +} + +function getSettingsForSourceUncached( + source: SettingSource, +): SettingsJson | null { + // For policySettings: first source wins (remote > HKLM/plist > file > HKCU) + if (source === 'policySettings') { + const remoteSettings = getRemoteManagedSettingsSyncFromCache() + if (remoteSettings && Object.keys(remoteSettings).length > 0) { + return remoteSettings + } + + const mdmResult = getMdmSettings() + if (Object.keys(mdmResult.settings).length > 0) { + return mdmResult.settings + } + + const { settings: fileSettings } = loadManagedFileSettings() + if (fileSettings) { + return fileSettings + } + + const hkcu = getHkcuSettings() + if (Object.keys(hkcu.settings).length > 0) { + return hkcu.settings + } + + return null + } + + const settingsFilePath = getSettingsFilePathForSource(source) + const { settings: fileSettings } = settingsFilePath + ? parseSettingsFile(settingsFilePath) + : { settings: null } + + // For flagSettings, merge in any inline settings set via the SDK + if (source === 'flagSettings') { + const inlineSettings = getFlagSettingsInline() + if (inlineSettings) { + const parsed = SettingsSchema().safeParse(inlineSettings) + if (parsed.success) { + return mergeWith( + fileSettings || {}, + parsed.data, + settingsMergeCustomizer, + ) as SettingsJson + } + } + } + + return fileSettings +} + +/** + * Get the origin of the highest-priority active policy settings source. + * Uses "first source wins" — returns the first source that has content. + * Priority: remote > plist/hklm > file (managed-settings.json) > hkcu + */ +export function getPolicySettingsOrigin(): + | 'remote' + | 'plist' + | 'hklm' + | 'file' + | 'hkcu' + | null { + // 1. Remote (highest) + const remoteSettings = getRemoteManagedSettingsSyncFromCache() + if (remoteSettings && Object.keys(remoteSettings).length > 0) { + return 'remote' + } + + // 2. Admin-only MDM (HKLM / macOS plist) + const mdmResult = getMdmSettings() + if (Object.keys(mdmResult.settings).length > 0) { + return getPlatform() === 'macos' ? 'plist' : 'hklm' + } + + // 3. managed-settings.json + managed-settings.d/ (file-based, requires admin) + const { settings: fileSettings } = loadManagedFileSettings() + if (fileSettings) { + return 'file' + } + + // 4. HKCU (lowest — user-writable) + const hkcu = getHkcuSettings() + if (Object.keys(hkcu.settings).length > 0) { + return 'hkcu' + } + + return null +} + +/** + * Merges `settings` into the existing settings for `source` using lodash mergeWith. + * + * To delete a key from a record field (e.g. enabledPlugins, extraKnownMarketplaces), + * set it to `undefined` — do NOT use `delete`. mergeWith only detects deletion when + * the key is present with an explicit `undefined` value. + */ +export function updateSettingsForSource( + source: EditableSettingSource, + settings: SettingsJson, +): { error: Error | null } { + if ( + (source as unknown) === 'policySettings' || + (source as unknown) === 'flagSettings' + ) { + return { error: null } + } + + // Create the folder if needed + const filePath = getSettingsFilePathForSource(source) + if (!filePath) { + return { error: null } + } + + try { + getFsImplementation().mkdirSync(dirname(filePath)) + + // Try to get existing settings with validation. Bypass the per-source + // cache — mergeWith below mutates its target (including nested refs), + // and mutating the cached object would leak unpersisted state if the + // write fails before resetSettingsCache(). + let existingSettings = getSettingsForSourceUncached(source) + + // If validation failed, check if file exists with a JSON syntax error + if (!existingSettings) { + let content: string | null = null + try { + content = readFileSync(filePath) + } catch (e) { + if (!isENOENT(e)) { + throw e + } + // File doesn't exist — fall through to merge with empty settings + } + if (content !== null) { + const rawData = safeParseJSON(content) + if (rawData === null) { + // JSON syntax error - return validation error instead of overwriting + // safeParseJSON will already log the error, so we'll just return the error here + return { + error: new Error( + `Invalid JSON syntax in settings file at ${filePath}`, + ), + } + } + if (rawData && typeof rawData === 'object') { + existingSettings = rawData as SettingsJson + logForDebugging( + `Using raw settings from ${filePath} due to validation failure`, + ) + } + } + } + + const updatedSettings = mergeWith( + existingSettings || {}, + settings, + ( + _objValue: unknown, + srcValue: unknown, + key: string | number | symbol, + object: Record, + ) => { + // Handle undefined as deletion + if (srcValue === undefined && object && typeof key === 'string') { + delete object[key] + return undefined + } + // For arrays, always replace with the provided array + // This puts the responsibility on the caller to compute the desired final state + if (Array.isArray(srcValue)) { + return srcValue + } + // For non-arrays, let lodash handle the default merge behavior + return undefined + }, + ) + + // Mark this as an internal write before writing the file + markInternalWrite(filePath) + + writeFileSyncAndFlush_DEPRECATED( + filePath, + jsonStringify(updatedSettings, null, 2) + '\n', + ) + + // Invalidate the session cache since settings have been updated + resetSettingsCache() + + if (source === 'localSettings') { + // Okay to add to gitignore async without awaiting + void addFileGlobRuleToGitignore( + getRelativeSettingsFilePathForSource('localSettings'), + getOriginalCwd(), + ) + } + } catch (e) { + const error = new Error( + `Failed to read raw settings from ${filePath}: ${e}`, + ) + logError(error) + return { error } + } + + return { error: null } +} + +/** + * Custom merge function for arrays - concatenate and deduplicate + */ +function mergeArrays(targetArray: T[], sourceArray: T[]): T[] { + return uniq([...targetArray, ...sourceArray]) +} + +/** + * Custom merge function for lodash mergeWith when merging settings. + * Arrays are concatenated and deduplicated; other values use default lodash merge behavior. + * Exported for testing. + */ +export function settingsMergeCustomizer( + objValue: unknown, + srcValue: unknown, +): unknown { + if (Array.isArray(objValue) && Array.isArray(srcValue)) { + return mergeArrays(objValue, srcValue) + } + // Return undefined to let lodash handle default merge behavior + return undefined +} + +/** + * Get a list of setting keys from managed settings for logging purposes. + * For certain nested settings (permissions, sandbox, hooks), expands to show + * one level of nesting (e.g., "permissions.allow"). For other settings, + * returns only the top-level key. + * + * @param settings The settings object to extract keys from + * @returns Sorted array of key paths + */ +export function getManagedSettingsKeysForLogging( + settings: SettingsJson, +): string[] { + // Use .strip() to get only valid schema keys + const validSettings = SettingsSchema().strip().parse(settings) as Record< + string, + unknown + > + const keysToExpand = ['permissions', 'sandbox', 'hooks'] + const allKeys: string[] = [] + + // Define valid nested keys for each nested setting we expand + const validNestedKeys: Record> = { + permissions: new Set([ + 'allow', + 'deny', + 'ask', + 'defaultMode', + 'disableBypassPermissionsMode', + ...(feature('TRANSCRIPT_CLASSIFIER') ? ['disableAutoMode'] : []), + 'additionalDirectories', + ]), + sandbox: new Set([ + 'enabled', + 'failIfUnavailable', + 'allowUnsandboxedCommands', + 'network', + 'filesystem', + 'ignoreViolations', + 'excludedCommands', + 'autoAllowBashIfSandboxed', + 'enableWeakerNestedSandbox', + 'enableWeakerNetworkIsolation', + 'ripgrep', + ]), + // For hooks, we use z.record with enum keys, so we validate separately + hooks: new Set([ + 'PreToolUse', + 'PostToolUse', + 'Notification', + 'UserPromptSubmit', + 'SessionStart', + 'SessionEnd', + 'Stop', + 'SubagentStop', + 'PreCompact', + 'PostCompact', + 'TeammateIdle', + 'TaskCreated', + 'TaskCompleted', + ]), + } + + for (const key of Object.keys(validSettings)) { + if ( + keysToExpand.includes(key) && + validSettings[key] && + typeof validSettings[key] === 'object' + ) { + // Expand nested keys for these special settings (one level deep only) + const nestedObj = validSettings[key] as Record + const validKeys = validNestedKeys[key] + + if (validKeys) { + for (const nestedKey of Object.keys(nestedObj)) { + // Only include known valid nested keys + if (validKeys.has(nestedKey)) { + allKeys.push(`${key}.${nestedKey}`) + } + } + } + } else { + // For other settings, just use the top-level key + allKeys.push(key) + } + } + + return allKeys.sort() +} + +// Flag to prevent infinite recursion when loading settings +let isLoadingSettings = false + +/** + * Load settings from disk without using cache + * This is the original implementation that actually reads from files + */ +function loadSettingsFromDisk(): SettingsWithErrors { + // Prevent recursive calls to loadSettingsFromDisk + if (isLoadingSettings) { + return { settings: {}, errors: [] } + } + + const startTime = Date.now() + profileCheckpoint('loadSettingsFromDisk_start') + logForDiagnosticsNoPII('info', 'settings_load_started') + + isLoadingSettings = true + try { + // Start with plugin settings as the lowest priority base. + // All file-based sources (user, project, local, flag, policy) override these. + // Plugin settings only contain allowlisted keys (e.g., agent) that are valid SettingsJson fields. + const pluginSettings = getPluginSettingsBase() + let mergedSettings: SettingsJson = {} + if (pluginSettings) { + mergedSettings = mergeWith( + mergedSettings, + pluginSettings, + settingsMergeCustomizer, + ) + } + const allErrors: ValidationError[] = [] + const seenErrors = new Set() + const seenFiles = new Set() + + // Merge settings from each source in priority order with deep merging + for (const source of getEnabledSettingSources()) { + // policySettings: "first source wins" — use the highest-priority source + // that has content. Priority: remote > HKLM/plist > managed-settings.json > HKCU + if (source === 'policySettings') { + let policySettings: SettingsJson | null = null + const policyErrors: ValidationError[] = [] + + // 1. Remote (highest priority) + const remoteSettings = getRemoteManagedSettingsSyncFromCache() + if (remoteSettings && Object.keys(remoteSettings).length > 0) { + const result = SettingsSchema().safeParse(remoteSettings) + if (result.success) { + policySettings = result.data + } else { + // Remote exists but is invalid — surface errors even as we fall through + policyErrors.push( + ...formatZodError(result.error, 'remote managed settings'), + ) + } + } + + // 2. Admin-only MDM (HKLM / macOS plist) + if (!policySettings) { + const mdmResult = getMdmSettings() + if (Object.keys(mdmResult.settings).length > 0) { + policySettings = mdmResult.settings + } + policyErrors.push(...mdmResult.errors) + } + + // 3. managed-settings.json + managed-settings.d/ (file-based, requires admin) + if (!policySettings) { + const { settings, errors } = loadManagedFileSettings() + if (settings) { + policySettings = settings + } + policyErrors.push(...errors) + } + + // 4. HKCU (lowest — user-writable, only if nothing above exists) + if (!policySettings) { + const hkcu = getHkcuSettings() + if (Object.keys(hkcu.settings).length > 0) { + policySettings = hkcu.settings + } + policyErrors.push(...hkcu.errors) + } + + // Merge the winning policy source into the settings chain + if (policySettings) { + mergedSettings = mergeWith( + mergedSettings, + policySettings, + settingsMergeCustomizer, + ) + } + for (const error of policyErrors) { + const errorKey = `${error.file}:${error.path}:${error.message}` + if (!seenErrors.has(errorKey)) { + seenErrors.add(errorKey) + allErrors.push(error) + } + } + + continue + } + + const filePath = getSettingsFilePathForSource(source) + if (filePath) { + const resolvedPath = resolve(filePath) + + // Skip if we've already loaded this file from another source + if (!seenFiles.has(resolvedPath)) { + seenFiles.add(resolvedPath) + + const { settings, errors } = parseSettingsFile(filePath) + + // Add unique errors (deduplication) + for (const error of errors) { + const errorKey = `${error.file}:${error.path}:${error.message}` + if (!seenErrors.has(errorKey)) { + seenErrors.add(errorKey) + allErrors.push(error) + } + } + + if (settings) { + mergedSettings = mergeWith( + mergedSettings, + settings, + settingsMergeCustomizer, + ) + } + } + } + + // For flagSettings, also merge any inline settings set via the SDK + if (source === 'flagSettings') { + const inlineSettings = getFlagSettingsInline() + if (inlineSettings) { + const parsed = SettingsSchema().safeParse(inlineSettings) + if (parsed.success) { + mergedSettings = mergeWith( + mergedSettings, + parsed.data, + settingsMergeCustomizer, + ) + } + } + } + } + + logForDiagnosticsNoPII('info', 'settings_load_completed', { + duration_ms: Date.now() - startTime, + source_count: seenFiles.size, + error_count: allErrors.length, + }) + + return { settings: mergedSettings, errors: allErrors } + } finally { + isLoadingSettings = false + } +} + +/** + * Get merged settings from all sources in priority order + * Settings are merged from lowest to highest priority: + * userSettings -> projectSettings -> localSettings -> policySettings + * + * This function returns a snapshot of settings at the time of call. + * For React components, prefer using useSettings() hook for reactive updates + * when settings change on disk. + * + * Uses session-level caching to avoid repeated file I/O. + * Cache is invalidated when settings files change via resetSettingsCache(). + * + * @returns Merged settings from all available sources (always returns at least empty object) + */ +export function getInitialSettings(): SettingsJson { + const { settings } = getSettingsWithErrors() + return settings || {} +} + +/** + * @deprecated Use getInitialSettings() instead. This alias exists for backwards compatibility. + */ +export const getSettings_DEPRECATED = getInitialSettings + +export type SettingsWithSources = { + effective: SettingsJson + /** Ordered low-to-high priority — later entries override earlier ones. */ + sources: Array<{ source: SettingSource; settings: SettingsJson }> +} + +/** + * Get the effective merged settings alongside the raw per-source settings, + * in merge-priority order. Only includes sources that are enabled and have + * non-empty content. + * + * Always reads fresh from disk — resets the session cache so that `effective` + * and `sources` are consistent even if the change detector hasn't fired yet. + */ +export function getSettingsWithSources(): SettingsWithSources { + // Reset both caches so getSettingsForSource (per-source cache) and + // getInitialSettings (session cache) agree on the current disk state. + resetSettingsCache() + const sources: SettingsWithSources['sources'] = [] + for (const source of getEnabledSettingSources()) { + const settings = getSettingsForSource(source) + if (settings && Object.keys(settings).length > 0) { + sources.push({ source, settings }) + } + } + return { effective: getInitialSettings(), sources } +} + +/** + * Get merged settings and validation errors from all sources + * This function now uses session-level caching to avoid repeated file I/O. + * Settings changes require Claude Code restart, so cache is valid for entire session. + * @returns Merged settings and all validation errors encountered + */ +export function getSettingsWithErrors(): SettingsWithErrors { + // Use cached result if available + const cached = getSessionSettingsCache() + if (cached !== null) { + return cached + } + + // Load from disk and cache the result + const result = loadSettingsFromDisk() + profileCheckpoint('loadSettingsFromDisk_end') + setSessionSettingsCache(result) + return result +} + +/** + * Check if any raw settings file contains a specific key, regardless of validation. + * This is useful for detecting user intent even when settings validation fails. + * For example, if a user set cleanupPeriodDays but has validation errors elsewhere, + * we can detect they explicitly configured cleanup and skip cleanup rather than + * falling back to defaults. + */ +/** + * Returns true if any trusted settings source has accepted the bypass + * permissions mode dialog. projectSettings is intentionally excluded — + * a malicious project could otherwise auto-bypass the dialog (RCE risk). + */ +export function hasSkipDangerousModePermissionPrompt(): boolean { + return !!( + getSettingsForSource('userSettings')?.skipDangerousModePermissionPrompt || + getSettingsForSource('localSettings')?.skipDangerousModePermissionPrompt || + getSettingsForSource('flagSettings')?.skipDangerousModePermissionPrompt || + getSettingsForSource('policySettings')?.skipDangerousModePermissionPrompt + ) +} + +/** + * Returns true if any trusted settings source has accepted the auto + * mode opt-in dialog. projectSettings is intentionally excluded — + * a malicious project could otherwise auto-bypass the dialog (RCE risk). + */ +export function hasAutoModeOptIn(): boolean { + if (feature('TRANSCRIPT_CLASSIFIER')) { + const user = getSettingsForSource('userSettings')?.skipAutoPermissionPrompt + const local = + getSettingsForSource('localSettings')?.skipAutoPermissionPrompt + const flag = getSettingsForSource('flagSettings')?.skipAutoPermissionPrompt + const policy = + getSettingsForSource('policySettings')?.skipAutoPermissionPrompt + const result = !!(user || local || flag || policy) + logForDebugging( + `[auto-mode] hasAutoModeOptIn=${result} skipAutoPermissionPrompt: user=${user} local=${local} flag=${flag} policy=${policy}`, + ) + return result + } + return false +} + +/** + * Returns whether plan mode should use auto mode semantics. Default true + * (opt-out). Returns false if any trusted source explicitly sets false. + * projectSettings is excluded so a malicious project can't control this. + */ +export function getUseAutoModeDuringPlan(): boolean { + if (feature('TRANSCRIPT_CLASSIFIER')) { + return ( + getSettingsForSource('policySettings')?.useAutoModeDuringPlan !== false && + getSettingsForSource('flagSettings')?.useAutoModeDuringPlan !== false && + getSettingsForSource('userSettings')?.useAutoModeDuringPlan !== false && + getSettingsForSource('localSettings')?.useAutoModeDuringPlan !== false + ) + } + return true +} + +/** + * Returns the merged autoMode config from trusted settings sources. + * Only available when TRANSCRIPT_CLASSIFIER is active; returns undefined otherwise. + * projectSettings is intentionally excluded — a malicious project could + * otherwise inject classifier allow/deny rules (RCE risk). + */ +export function getAutoModeConfig(): + | { allow?: string[]; soft_deny?: string[]; environment?: string[] } + | undefined { + if (feature('TRANSCRIPT_CLASSIFIER')) { + const schema = z.object({ + allow: z.array(z.string()).optional(), + soft_deny: z.array(z.string()).optional(), + deny: z.array(z.string()).optional(), + environment: z.array(z.string()).optional(), + }) + + const allow: string[] = [] + const soft_deny: string[] = [] + const environment: string[] = [] + + for (const source of [ + 'userSettings', + 'localSettings', + 'flagSettings', + 'policySettings', + ] as const) { + const settings = getSettingsForSource(source) + if (!settings) continue + const result = schema.safeParse( + (settings as Record).autoMode, + ) + if (result.success) { + if (result.data.allow) allow.push(...result.data.allow) + if (result.data.soft_deny) soft_deny.push(...result.data.soft_deny) + if (process.env.USER_TYPE === 'ant') { + if (result.data.deny) soft_deny.push(...result.data.deny) + } + if (result.data.environment) + environment.push(...result.data.environment) + } + } + + if (allow.length > 0 || soft_deny.length > 0 || environment.length > 0) { + return { + ...(allow.length > 0 && { allow }), + ...(soft_deny.length > 0 && { soft_deny }), + ...(environment.length > 0 && { environment }), + } + } + } + return undefined +} + +export function rawSettingsContainsKey(key: string): boolean { + for (const source of getEnabledSettingSources()) { + // Skip policySettings - we only care about user-configured settings + if (source === 'policySettings') { + continue + } + + const filePath = getSettingsFilePathForSource(source) + if (!filePath) { + continue + } + + try { + const { resolvedPath } = safeResolvePath(getFsImplementation(), filePath) + const content = readFileSync(resolvedPath) + if (!content.trim()) { + continue + } + + const rawData = safeParseJSON(content, false) + if (rawData && typeof rawData === 'object' && key in rawData) { + return true + } + } catch (error) { + // File not found is expected - not all settings files exist + // Other errors (permissions, I/O) should be tracked + handleFileSystemError(error, filePath) + } + } + + return false +} diff --git a/_all-in-one-upload/cc-haha/src/utils/shell/powershellDetection.ts b/_all-in-one-upload/cc-haha/src/utils/shell/powershellDetection.ts new file mode 100644 index 0000000..acc3fb7 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/shell/powershellDetection.ts @@ -0,0 +1,107 @@ +import { realpath, stat } from 'fs/promises' +import { getPlatform } from '../platform.js' +import { which } from '../which.js' + +async function probePath(p: string): Promise { + try { + return (await stat(p)).isFile() ? p : null + } catch { + return null + } +} + +/** + * Attempts to find PowerShell on the system via PATH. + * Prefers pwsh (PowerShell Core 7+), falls back to powershell (5.1). + * + * On Linux, if PATH resolves to a snap launcher (/snap/…) — directly or + * via a symlink chain like /usr/bin/pwsh → /snap/bin/pwsh — probe known + * apt/rpm install locations instead: the snap launcher can hang in + * subprocesses while snapd initializes confinement, but the underlying + * binary at /opt/microsoft/powershell/7/pwsh is reliable. On + * Windows/macOS, PATH is sufficient. + */ +export async function findPowerShell(): Promise { + const pwshPath = await which('pwsh') + if (pwshPath) { + // Snap launcher hangs in subprocesses. Prefer the direct binary. + // Check both the resolved PATH entry and its symlink target: on + // some distros /usr/bin/pwsh is a symlink to /snap/bin/pwsh, which + // would bypass a naive startsWith('/snap/') on the which() result. + if (getPlatform() === 'linux') { + const resolved = await realpath(pwshPath).catch(() => pwshPath) + if (pwshPath.startsWith('/snap/') || resolved.startsWith('/snap/')) { + const direct = + (await probePath('/opt/microsoft/powershell/7/pwsh')) ?? + (await probePath('/usr/bin/pwsh')) + if (direct) { + const directResolved = await realpath(direct).catch(() => direct) + if ( + !direct.startsWith('/snap/') && + !directResolved.startsWith('/snap/') + ) { + return direct + } + } + } + } + return pwshPath + } + + const powershellPath = await which('powershell') + if (powershellPath) { + return powershellPath + } + + return null +} + +let cachedPowerShellPath: Promise | null = null + +/** + * Gets the cached PowerShell path. Returns a memoized promise that + * resolves to the PowerShell executable path or null. + */ +export function getCachedPowerShellPath(): Promise { + if (!cachedPowerShellPath) { + cachedPowerShellPath = findPowerShell() + } + return cachedPowerShellPath +} + +export type PowerShellEdition = 'core' | 'desktop' + +/** + * Infers the PowerShell edition from the binary name without spawning. + * - `pwsh` / `pwsh.exe` → 'core' (PowerShell 7+: supports `&&`, `||`, `?:`, `??`) + * - `powershell` / `powershell.exe` → 'desktop' (Windows PowerShell 5.1: + * no pipeline chain operators, stderr-sets-$? bug, UTF-16 default encoding) + * + * PowerShell 6 (also `pwsh`, no `&&`) has been EOL since 2020 and is not + * a realistic install target, so 'core' safely implies 7+ semantics. + * + * Used by the tool prompt to give version-appropriate syntax guidance so + * the model doesn't emit `cmd1 && cmd2` on 5.1 (parser error) or avoid + * `&&` on 7+ where it's the correct short-circuiting operator. + */ +export async function getPowerShellEdition(): Promise { + const p = await getCachedPowerShellPath() + if (!p) return null + // basename without extension, case-insensitive. Covers: + // C:\Program Files\PowerShell\7\pwsh.exe + // /opt/microsoft/powershell/7/pwsh + // C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe + const base = p + .split(/[/\\]/) + .pop()! + .toLowerCase() + .replace(/\.exe$/, '') + return base === 'pwsh' ? 'core' : 'desktop' +} + +/** + * Resets the cached PowerShell path. Only for testing. + */ +export function resetPowerShellCache(): void { + cachedPowerShellPath = null +} diff --git a/_all-in-one-upload/cc-haha/src/utils/sinks.ts b/_all-in-one-upload/cc-haha/src/utils/sinks.ts new file mode 100644 index 0000000..386ce6a --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/sinks.ts @@ -0,0 +1,16 @@ +import { initializeAnalyticsSink } from '../services/analytics/sink.js' +import { initializeErrorLogSink } from './errorLogSink.js' + +/** + * Attach error log and analytics sinks, draining any events queued before + * attachment. Both inits are idempotent. Called from setup() for the default + * command; other entrypoints (subcommands, daemon, bridge) call this directly + * since they bypass setup(). + * + * Leaf module — kept out of setup.ts to avoid the setup → commands → bridge + * → setup import cycle. + */ +export function initSinks(): void { + initializeErrorLogSink() + initializeAnalyticsSink() +} diff --git a/_all-in-one-upload/cc-haha/src/utils/staticRender.tsx b/_all-in-one-upload/cc-haha/src/utils/staticRender.tsx new file mode 100644 index 0000000..6a6917b --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/staticRender.tsx @@ -0,0 +1,116 @@ +import { c as _c } from "react/compiler-runtime"; +import * as React from 'react'; +import { useLayoutEffect } from 'react'; +import { PassThrough } from 'stream'; +import stripAnsi from 'strip-ansi'; +import { render, useApp } from '../ink.js'; + +// This is a workaround for the fact that Ink doesn't support multiple +// components in the same render tree. Instead of using a we just render +// the component to a string and then print it to stdout + +/** + * Wrapper component that exits after rendering. + * Uses useLayoutEffect to ensure we wait for React's commit phase to complete + * before exiting. This is more robust than process.nextTick() for React 19's + * async render cycle. + */ +function RenderOnceAndExit(t0) { + const $ = _c(5); + const { + children + } = t0; + const { + exit + } = useApp(); + let t1; + let t2; + if ($[0] !== exit) { + t1 = () => { + const timer = setTimeout(exit, 0); + return () => clearTimeout(timer); + }; + t2 = [exit]; + $[0] = exit; + $[1] = t1; + $[2] = t2; + } else { + t1 = $[1]; + t2 = $[2]; + } + useLayoutEffect(t1, t2); + let t3; + if ($[3] !== children) { + t3 = <>{children}; + $[3] = children; + $[4] = t3; + } else { + t3 = $[4]; + } + return t3; +} + +// DEC synchronized update markers used by terminals +const SYNC_START = '\x1B[?2026h'; +const SYNC_END = '\x1B[?2026l'; + +/** + * Extracts content from the first complete frame in Ink's output. + * Ink with non-TTY stdout outputs multiple frames, each wrapped in DEC synchronized + * update sequences ([?2026h ... [?2026l). We only want the first frame's content. + */ +function extractFirstFrame(output: string): string { + const startIndex = output.indexOf(SYNC_START); + if (startIndex === -1) return output; + const contentStart = startIndex + SYNC_START.length; + const endIndex = output.indexOf(SYNC_END, contentStart); + if (endIndex === -1) return output; + return output.slice(contentStart, endIndex); +} + +/** + * Renders a React node to a string with ANSI escape codes (for terminal output). + */ +export function renderToAnsiString(node: React.ReactNode, columns?: number): Promise { + return new Promise(async resolve => { + let output = ''; + + // Capture all writes. Set .columns so Ink (ink.tsx:~165) picks up a + // chosen width instead of PassThrough's undefined → 80 fallback — + // useful for rendering at terminal width for file dumps that should + // match what the user sees on screen. + const stream = new PassThrough(); + if (columns !== undefined) { + ; + (stream as unknown as { + columns: number; + }).columns = columns; + } + stream.on('data', chunk => { + output += chunk.toString(); + }); + + // Render the component wrapped in RenderOnceAndExit + // Non-TTY stdout (PassThrough) gives full-frame output instead of diffs + const instance = await render({node}, { + stdout: stream as unknown as NodeJS.WriteStream, + patchConsole: false + }); + + // Wait for the component to exit naturally + await instance.waitUntilExit(); + + // Extract only the first frame's content to avoid duplication + // (Ink outputs multiple frames in non-TTY mode) + await resolve(extractFirstFrame(output)); + }); +} + +/** + * Renders a React node to a plain text string (ANSI codes stripped). + */ +export async function renderToString(node: React.ReactNode, columns?: number): Promise { + const output = await renderToAnsiString(node, columns); + return stripAnsi(output); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZUxheW91dEVmZmVjdCIsIlBhc3NUaHJvdWdoIiwic3RyaXBBbnNpIiwicmVuZGVyIiwidXNlQXBwIiwiUmVuZGVyT25jZUFuZEV4aXQiLCJ0MCIsIiQiLCJfYyIsImNoaWxkcmVuIiwiZXhpdCIsInQxIiwidDIiLCJ0aW1lciIsInNldFRpbWVvdXQiLCJjbGVhclRpbWVvdXQiLCJ0MyIsIlNZTkNfU1RBUlQiLCJTWU5DX0VORCIsImV4dHJhY3RGaXJzdEZyYW1lIiwib3V0cHV0Iiwic3RhcnRJbmRleCIsImluZGV4T2YiLCJjb250ZW50U3RhcnQiLCJsZW5ndGgiLCJlbmRJbmRleCIsInNsaWNlIiwicmVuZGVyVG9BbnNpU3RyaW5nIiwibm9kZSIsIlJlYWN0Tm9kZSIsImNvbHVtbnMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInN0cmVhbSIsInVuZGVmaW5lZCIsIm9uIiwiY2h1bmsiLCJ0b1N0cmluZyIsImluc3RhbmNlIiwic3Rkb3V0IiwiTm9kZUpTIiwiV3JpdGVTdHJlYW0iLCJwYXRjaENvbnNvbGUiLCJ3YWl0VW50aWxFeGl0IiwicmVuZGVyVG9TdHJpbmciXSwic291cmNlcyI6WyJzdGF0aWNSZW5kZXIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgdXNlTGF5b3V0RWZmZWN0IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBQYXNzVGhyb3VnaCB9IGZyb20gJ3N0cmVhbSdcbmltcG9ydCBzdHJpcEFuc2kgZnJvbSAnc3RyaXAtYW5zaSdcbmltcG9ydCB7IHJlbmRlciwgdXNlQXBwIH0gZnJvbSAnLi4vaW5rLmpzJ1xuXG4vLyBUaGlzIGlzIGEgd29ya2Fyb3VuZCBmb3IgdGhlIGZhY3QgdGhhdCBJbmsgZG9lc24ndCBzdXBwb3J0IG11bHRpcGxlIDxTdGF0aWM+XG4vLyBjb21wb25lbnRzIGluIHRoZSBzYW1lIHJlbmRlciB0cmVlLiBJbnN0ZWFkIG9mIHVzaW5nIGEgPFN0YXRpYz4gd2UganVzdCByZW5kZXJcbi8vIHRoZSBjb21wb25lbnQgdG8gYSBzdHJpbmcgYW5kIHRoZW4gcHJpbnQgaXQgdG8gc3Rkb3V0XG5cbi8qKlxuICogV3JhcHBlciBjb21wb25lbnQgdGhhdCBleGl0cyBhZnRlciByZW5kZXJpbmcuXG4gKiBVc2VzIHVzZUxheW91dEVmZmVjdCB0byBlbnN1cmUgd2Ugd2FpdCBmb3IgUmVhY3QncyBjb21taXQgcGhhc2UgdG8gY29tcGxldGVcbiAqIGJlZm9yZSBleGl0aW5nLiBUaGlzIGlzIG1vcmUgcm9idXN0IHRoYW4gcHJvY2Vzcy5uZXh0VGljaygpIGZvciBSZWFjdCAxOSdzXG4gKiBhc3luYyByZW5kZXIgY3ljbGUuXG4gKi9cbmZ1bmN0aW9uIFJlbmRlck9uY2VBbmRFeGl0KHtcbiAgY2hpbGRyZW4sXG59OiB7XG4gIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGVcbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCB7IGV4aXQgfSA9IHVzZUFwcCgpXG5cbiAgLy8gdXNlTGF5b3V0RWZmZWN0IHJ1bnMgc3luY2hyb25vdXNseSBhZnRlciBSZWFjdCBjb21taXRzIERPTSBtdXRhdGlvbnMuXG4gIC8vIHNldFRpbWVvdXQoMCkgZGVmZXJzIGV4aXQgdG8gYWxsb3cgSW5rIHRvIGZsdXNoIG91dHB1dCB0byB0aGUgc3RyZWFtLlxuICB1c2VMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dChleGl0LCAwKVxuICAgIHJldHVybiAoKSA9PiBjbGVhclRpbWVvdXQodGltZXIpXG4gIH0sIFtleGl0XSlcblxuICByZXR1cm4gPD57Y2hpbGRyZW59PC8+XG59XG5cbi8vIERFQyBzeW5jaHJvbml6ZWQgdXBkYXRlIG1hcmtlcnMgdXNlZCBieSB0ZXJtaW5hbHNcbmNvbnN0IFNZTkNfU1RBUlQgPSAnXFx4MUJbPzIwMjZoJ1xuY29uc3QgU1lOQ19FTkQgPSAnXFx4MUJbPzIwMjZsJ1xuXG4vKipcbiAqIEV4dHJhY3RzIGNvbnRlbnQgZnJvbSB0aGUgZmlyc3QgY29tcGxldGUgZnJhbWUgaW4gSW5rJ3Mgb3V0cHV0LlxuICogSW5rIHdpdGggbm9uLVRUWSBzdGRvdXQgb3V0cHV0cyBtdWx0aXBsZSBmcmFtZXMsIGVhY2ggd3JhcHBlZCBpbiBERUMgc3luY2hyb25pemVkXG4gKiB1cGRhdGUgc2VxdWVuY2VzIChbPzIwMjZoIC4uLiBbPzIwMjZsKS4gV2Ugb25seSB3YW50IHRoZSBmaXJzdCBmcmFtZSdzIGNvbnRlbnQuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RGaXJzdEZyYW1lKG91dHB1dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc3RhcnRJbmRleCA9IG91dHB1dC5pbmRleE9mKFNZTkNfU1RBUlQpXG4gIGlmIChzdGFydEluZGV4ID09PSAtMSkgcmV0dXJuIG91dHB1dFxuXG4gIGNvbnN0IGNvbnRlbnRTdGFydCA9IHN0YXJ0SW5kZXggKyBTWU5DX1NUQVJULmxlbmd0aFxuICBjb25zdCBlbmRJbmRleCA9IG91dHB1dC5pbmRleE9mKFNZTkNfRU5ELCBjb250ZW50U3RhcnQpXG4gIGlmIChlbmRJbmRleCA9PT0gLTEpIHJldHVybiBvdXRwdXRcblxuICByZXR1cm4gb3V0cHV0LnNsaWNlKGNvbnRlbnRTdGFydCwgZW5kSW5kZXgpXG59XG5cbi8qKlxuICogUmVuZGVycyBhIFJlYWN0IG5vZGUgdG8gYSBzdHJpbmcgd2l0aCBBTlNJIGVzY2FwZSBjb2RlcyAoZm9yIHRlcm1pbmFsIG91dHB1dCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUb0Fuc2lTdHJpbmcoXG4gIG5vZGU6IFJlYWN0LlJlYWN0Tm9kZSxcbiAgY29sdW1ucz86IG51bWJlcixcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyByZXNvbHZlID0+IHtcbiAgICBsZXQgb3V0cHV0ID0gJydcblxuICAgIC8vIENhcHR1cmUgYWxsIHdyaXRlcy4gU2V0IC5jb2x1bW5zIHNvIEluayAoaW5rLnRzeDp+MTY1KSBwaWNrcyB1cCBhXG4gICAgLy8gY2hvc2VuIHdpZHRoIGluc3RlYWQgb2YgUGFzc1Rocm91Z2gncyB1bmRlZmluZWQg4oaSIDgwIGZhbGxiYWNrIOKAlFxuICAgIC8vIHVzZWZ1bCBmb3IgcmVuZGVyaW5nIGF0IHRlcm1pbmFsIHdpZHRoIGZvciBmaWxlIGR1bXBzIHRoYXQgc2hvdWxkXG4gICAgLy8gbWF0Y2ggd2hhdCB0aGUgdXNlciBzZWVzIG9uIHNjcmVlbi5cbiAgICBjb25zdCBzdHJlYW0gPSBuZXcgUGFzc1Rocm91Z2goKVxuICAgIGlmIChjb2x1bW5zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIDsoc3RyZWFtIGFzIHVua25vd24gYXMgeyBjb2x1bW5zOiBudW1iZXIgfSkuY29sdW1ucyA9IGNvbHVtbnNcbiAgICB9XG4gICAgc3RyZWFtLm9uKCdkYXRhJywgY2h1bmsgPT4ge1xuICAgICAgb3V0cHV0ICs9IGNodW5rLnRvU3RyaW5nKClcbiAgICB9KVxuXG4gICAgLy8gUmVuZGVyIHRoZSBjb21wb25lbnQgd3JhcHBlZCBpbiBSZW5kZXJPbmNlQW5kRXhpdFxuICAgIC8vIE5vbi1UVFkgc3Rkb3V0IChQYXNzVGhyb3VnaCkgZ2l2ZXMgZnVsbC1mcmFtZSBvdXRwdXQgaW5zdGVhZCBvZiBkaWZmc1xuICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgcmVuZGVyKFxuICAgICAgPFJlbmRlck9uY2VBbmRFeGl0Pntub2RlfTwvUmVuZGVyT25jZUFuZEV4aXQ+LFxuICAgICAge1xuICAgICAgICBzdGRvdXQ6IHN0cmVhbSBhcyB1bmtub3duIGFzIE5vZGVKUy5Xcml0ZVN0cmVhbSxcbiAgICAgICAgcGF0Y2hDb25zb2xlOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgKVxuXG4gICAgLy8gV2FpdCBmb3IgdGhlIGNvbXBvbmVudCB0byBleGl0IG5hdHVyYWxseVxuICAgIGF3YWl0IGluc3RhbmNlLndhaXRVbnRpbEV4aXQoKVxuXG4gICAgLy8gRXh0cmFjdCBvbmx5IHRoZSBmaXJzdCBmcmFtZSdzIGNvbnRlbnQgdG8gYXZvaWQgZHVwbGljYXRpb25cbiAgICAvLyAoSW5rIG91dHB1dHMgbXVsdGlwbGUgZnJhbWVzIGluIG5vbi1UVFkgbW9kZSlcbiAgICBhd2FpdCByZXNvbHZlKGV4dHJhY3RGaXJzdEZyYW1lKG91dHB1dCkpXG4gIH0pXG59XG5cbi8qKlxuICogUmVuZGVycyBhIFJlYWN0IG5vZGUgdG8gYSBwbGFpbiB0ZXh0IHN0cmluZyAoQU5TSSBjb2RlcyBzdHJpcHBlZCkuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW5kZXJUb1N0cmluZyhcbiAgbm9kZTogUmVhY3QuUmVhY3ROb2RlLFxuICBjb2x1bW5zPzogbnVtYmVyLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgcmVuZGVyVG9BbnNpU3RyaW5nKG5vZGUsIGNvbHVtbnMpXG4gIHJldHVybiBzdHJpcEFuc2kob3V0cHV0KVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxLQUFLQSxLQUFLLE1BQU0sT0FBTztBQUM5QixTQUFTQyxlQUFlLFFBQVEsT0FBTztBQUN2QyxTQUFTQyxXQUFXLFFBQVEsUUFBUTtBQUNwQyxPQUFPQyxTQUFTLE1BQU0sWUFBWTtBQUNsQyxTQUFTQyxNQUFNLEVBQUVDLE1BQU0sUUFBUSxXQUFXOztBQUUxQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBQUMsa0JBQUFDLEVBQUE7RUFBQSxNQUFBQyxDQUFBLEdBQUFDLEVBQUE7RUFBMkI7SUFBQUM7RUFBQSxJQUFBSCxFQUkxQjtFQUNDO0lBQUFJO0VBQUEsSUFBaUJOLE1BQU0sQ0FBQyxDQUFDO0VBQUEsSUFBQU8sRUFBQTtFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBTCxDQUFBLFFBQUFHLElBQUE7SUFJVEMsRUFBQSxHQUFBQSxDQUFBO01BQ2QsTUFBQUUsS0FBQSxHQUFjQyxVQUFVLENBQUNKLElBQUksRUFBRSxDQUFDLENBQUM7TUFBQSxPQUMxQixNQUFNSyxZQUFZLENBQUNGLEtBQUssQ0FBQztJQUFBLENBQ2pDO0lBQUVELEVBQUEsSUFBQ0YsSUFBSSxDQUFDO0lBQUFILENBQUEsTUFBQUcsSUFBQTtJQUFBSCxDQUFBLE1BQUFJLEVBQUE7SUFBQUosQ0FBQSxNQUFBSyxFQUFBO0VBQUE7SUFBQUQsRUFBQSxHQUFBSixDQUFBO0lBQUFLLEVBQUEsR0FBQUwsQ0FBQTtFQUFBO0VBSFRQLGVBQWUsQ0FBQ1csRUFHZixFQUFFQyxFQUFNLENBQUM7RUFBQSxJQUFBSSxFQUFBO0VBQUEsSUFBQVQsQ0FBQSxRQUFBRSxRQUFBO0lBRUhPLEVBQUEsS0FBR1AsU0FBTyxDQUFDLEdBQUk7SUFBQUYsQ0FBQSxNQUFBRSxRQUFBO0lBQUFGLENBQUEsTUFBQVMsRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQVQsQ0FBQTtFQUFBO0VBQUEsT0FBZlMsRUFBZTtBQUFBOztBQUd4QjtBQUNBLE1BQU1DLFVBQVUsR0FBRyxhQUFhO0FBQ2hDLE1BQU1DLFFBQVEsR0FBRyxhQUFhOztBQUU5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsaUJBQWlCQSxDQUFDQyxNQUFNLEVBQUUsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO0VBQ2pELE1BQU1DLFVBQVUsR0FBR0QsTUFBTSxDQUFDRSxPQUFPLENBQUNMLFVBQVUsQ0FBQztFQUM3QyxJQUFJSSxVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBT0QsTUFBTTtFQUVwQyxNQUFNRyxZQUFZLEdBQUdGLFVBQVUsR0FBR0osVUFBVSxDQUFDTyxNQUFNO0VBQ25ELE1BQU1DLFFBQVEsR0FBR0wsTUFBTSxDQUFDRSxPQUFPLENBQUNKLFFBQVEsRUFBRUssWUFBWSxDQUFDO0VBQ3ZELElBQUlFLFFBQVEsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPTCxNQUFNO0VBRWxDLE9BQU9BLE1BQU0sQ0FBQ00sS0FBSyxDQUFDSCxZQUFZLEVBQUVFLFFBQVEsQ0FBQztBQUM3Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFNBQVNFLGtCQUFrQkEsQ0FDaENDLElBQUksRUFBRTdCLEtBQUssQ0FBQzhCLFNBQVMsRUFDckJDLE9BQWdCLENBQVIsRUFBRSxNQUFNLENBQ2pCLEVBQUVDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztFQUNqQixPQUFPLElBQUlBLE9BQU8sQ0FBQyxNQUFNQyxPQUFPLElBQUk7SUFDbEMsSUFBSVosTUFBTSxHQUFHLEVBQUU7O0lBRWY7SUFDQTtJQUNBO0lBQ0E7SUFDQSxNQUFNYSxNQUFNLEdBQUcsSUFBSWhDLFdBQVcsQ0FBQyxDQUFDO0lBQ2hDLElBQUk2QixPQUFPLEtBQUtJLFNBQVMsRUFBRTtNQUN6QjtNQUFDLENBQUNELE1BQU0sSUFBSSxPQUFPLElBQUk7UUFBRUgsT0FBTyxFQUFFLE1BQU07TUFBQyxDQUFDLEVBQUVBLE9BQU8sR0FBR0EsT0FBTztJQUMvRDtJQUNBRyxNQUFNLENBQUNFLEVBQUUsQ0FBQyxNQUFNLEVBQUVDLEtBQUssSUFBSTtNQUN6QmhCLE1BQU0sSUFBSWdCLEtBQUssQ0FBQ0MsUUFBUSxDQUFDLENBQUM7SUFDNUIsQ0FBQyxDQUFDOztJQUVGO0lBQ0E7SUFDQSxNQUFNQyxRQUFRLEdBQUcsTUFBTW5DLE1BQU0sQ0FDM0IsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDeUIsSUFBSSxDQUFDLEVBQUUsaUJBQWlCLENBQUMsRUFDN0M7TUFDRVcsTUFBTSxFQUFFTixNQUFNLElBQUksT0FBTyxJQUFJTyxNQUFNLENBQUNDLFdBQVc7TUFDL0NDLFlBQVksRUFBRTtJQUNoQixDQUNGLENBQUM7O0lBRUQ7SUFDQSxNQUFNSixRQUFRLENBQUNLLGFBQWEsQ0FBQyxDQUFDOztJQUU5QjtJQUNBO0lBQ0EsTUFBTVgsT0FBTyxDQUFDYixpQkFBaUIsQ0FBQ0MsTUFBTSxDQUFDLENBQUM7RUFDMUMsQ0FBQyxDQUFDO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTyxlQUFld0IsY0FBY0EsQ0FDbENoQixJQUFJLEVBQUU3QixLQUFLLENBQUM4QixTQUFTLEVBQ3JCQyxPQUFnQixDQUFSLEVBQUUsTUFBTSxDQUNqQixFQUFFQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7RUFDakIsTUFBTVgsTUFBTSxHQUFHLE1BQU1PLGtCQUFrQixDQUFDQyxJQUFJLEVBQUVFLE9BQU8sQ0FBQztFQUN0RCxPQUFPNUIsU0FBUyxDQUFDa0IsTUFBTSxDQUFDO0FBQzFCIiwiaWdub3JlTGlzdCI6W119 \ No newline at end of file diff --git a/_all-in-one-upload/cc-haha/src/utils/subprocessEnv.ts b/_all-in-one-upload/cc-haha/src/utils/subprocessEnv.ts new file mode 100644 index 0000000..4eb62c9 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/subprocessEnv.ts @@ -0,0 +1,99 @@ +import { isEnvTruthy } from './envUtils.js' + +/** + * Env vars to strip from subprocess environments when running inside GitHub + * Actions. This prevents prompt-injection attacks from exfiltrating secrets + * via shell expansion (e.g., ${ANTHROPIC_API_KEY}) in Bash tool commands. + * + * The parent claude process keeps these vars (needed for API calls, lazy + * credential reads). Only child processes (bash, shell snapshot, MCP stdio, LSP, hooks) are scrubbed. + * + * GITHUB_TOKEN / GH_TOKEN are intentionally NOT scrubbed — wrapper scripts + * (gh.sh) need them to call the GitHub API. That token is job-scoped and + * expires when the workflow ends. + */ +const GHA_SUBPROCESS_SCRUB = [ + // Anthropic auth — claude re-reads these per-request, subprocesses don't need them + 'ANTHROPIC_API_KEY', + 'CLAUDE_CODE_OAUTH_TOKEN', + 'ANTHROPIC_AUTH_TOKEN', + 'ANTHROPIC_FOUNDRY_API_KEY', + 'ANTHROPIC_CUSTOM_HEADERS', + + // OTLP exporter headers — documented to carry Authorization=Bearer tokens + // for monitoring backends; read in-process by OTEL SDK, subprocesses never need them + 'OTEL_EXPORTER_OTLP_HEADERS', + 'OTEL_EXPORTER_OTLP_LOGS_HEADERS', + 'OTEL_EXPORTER_OTLP_METRICS_HEADERS', + 'OTEL_EXPORTER_OTLP_TRACES_HEADERS', + + // Cloud provider creds — same pattern (lazy SDK reads) + 'AWS_SECRET_ACCESS_KEY', + 'AWS_SESSION_TOKEN', + 'AWS_BEARER_TOKEN_BEDROCK', + 'GOOGLE_APPLICATION_CREDENTIALS', + 'AZURE_CLIENT_SECRET', + 'AZURE_CLIENT_CERTIFICATE_PATH', + + // GitHub Actions OIDC — consumed by the action's JS before claude spawns; + // leaking these allows minting an App installation token → repo takeover + 'ACTIONS_ID_TOKEN_REQUEST_TOKEN', + 'ACTIONS_ID_TOKEN_REQUEST_URL', + + // GitHub Actions artifact/cache API — cache poisoning → supply-chain pivot + 'ACTIONS_RUNTIME_TOKEN', + 'ACTIONS_RUNTIME_URL', + + // claude-code-action-specific duplicates — action JS consumes these during + // prepare, before spawning claude. ALL_INPUTS contains anthropic_api_key as JSON. + 'ALL_INPUTS', + 'OVERRIDE_GITHUB_TOKEN', + 'DEFAULT_WORKFLOW_TOKEN', + 'SSH_SIGNING_KEY', +] as const + +/** + * Returns a copy of process.env with sensitive secrets stripped, for use when + * spawning subprocesses (Bash tool, shell snapshot, MCP stdio servers, LSP + * servers, shell hooks). + * + * Gated on CLAUDE_CODE_SUBPROCESS_ENV_SCRUB. claude-code-action sets this + * automatically when `allowed_non_write_users` is configured — the flag that + * exposes a workflow to untrusted content (prompt injection surface). + */ +// Registered by init.ts after the upstreamproxy module is dynamically imported +// in CCR sessions. Stays undefined in non-CCR startups so we never pull in the +// upstreamproxy module graph (upstreamproxy.ts + relay.ts) via a static import. +let _getUpstreamProxyEnv: (() => Record) | undefined + +/** + * Called from init.ts to wire up the proxy env function after the upstreamproxy + * module has been lazily loaded. Must be called before any subprocess is spawned. + */ +export function registerUpstreamProxyEnvFn( + fn: () => Record, +): void { + _getUpstreamProxyEnv = fn +} + +export function subprocessEnv(): NodeJS.ProcessEnv { + // CCR upstreamproxy: inject HTTPS_PROXY + CA bundle vars so curl/gh/python + // in agent subprocesses route through the local relay. Returns {} when the + // proxy is disabled or not registered (non-CCR), so this is a no-op outside + // CCR containers. + const proxyEnv = _getUpstreamProxyEnv?.() ?? {} + + if (!isEnvTruthy(process.env.CLAUDE_CODE_SUBPROCESS_ENV_SCRUB)) { + return Object.keys(proxyEnv).length > 0 + ? { ...process.env, ...proxyEnv } + : process.env + } + const env = { ...process.env, ...proxyEnv } + for (const k of GHA_SUBPROCESS_SCRUB) { + delete env[k] + // GitHub Actions auto-creates INPUT_ for `with:` inputs, duplicating + // secrets like INPUT_ANTHROPIC_API_KEY. No-op for vars that aren't action inputs. + delete env[`INPUT_${k}`] + } + return env +} diff --git a/_all-in-one-upload/cc-haha/src/utils/swarm/backends/TmuxBackend.ts b/_all-in-one-upload/cc-haha/src/utils/swarm/backends/TmuxBackend.ts new file mode 100644 index 0000000..402afd8 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/swarm/backends/TmuxBackend.ts @@ -0,0 +1,764 @@ +import type { AgentColorName } from '../../../tools/AgentTool/agentColorManager.js' +import { logForDebugging } from '../../../utils/debug.js' +import { execFileNoThrow } from '../../../utils/execFileNoThrow.js' +import { logError } from '../../../utils/log.js' +import { count } from '../../array.js' +import { sleep } from '../../sleep.js' +import { + getSwarmSocketName, + HIDDEN_SESSION_NAME, + SWARM_SESSION_NAME, + SWARM_VIEW_WINDOW_NAME, + TMUX_COMMAND, +} from '../constants.js' +import { + getLeaderPaneId, + isInsideTmux as isInsideTmuxFromDetection, + isTmuxAvailable, +} from './detection.js' +import { registerTmuxBackend } from './registry.js' +import type { CreatePaneResult, PaneBackend, PaneId } from './types.js' + +// Track whether the first pane has been used for external swarm session +let firstPaneUsedForExternal = false + +// Cached leader window target (session:window format) to avoid repeated queries +let cachedLeaderWindowTarget: string | null = null + +// Lock mechanism to prevent race conditions when spawning teammates in parallel +let paneCreationLock: Promise = Promise.resolve() + +// Delay after pane creation to allow shell initialization (loading rc files, prompts, etc.) +// 200ms is enough for most shell configurations including slow ones like starship/oh-my-zsh +const PANE_SHELL_INIT_DELAY_MS = 200 + +function waitForPaneShellReady(): Promise { + return sleep(PANE_SHELL_INIT_DELAY_MS) +} + +/** + * Acquires a lock for pane creation, ensuring sequential execution. + * Returns a release function that must be called when done. + */ +function acquirePaneCreationLock(): Promise<() => void> { + let release: () => void + const newLock = new Promise(resolve => { + release = resolve + }) + + const previousLock = paneCreationLock + paneCreationLock = newLock + + return previousLock.then(() => release!) +} + +/** + * Gets the tmux color name for a given agent color. + * These are tmux's built-in color names that work with pane-border-style. + */ +function getTmuxColorName(color: AgentColorName): string { + const tmuxColors: Record = { + red: 'red', + blue: 'blue', + green: 'green', + yellow: 'yellow', + purple: 'magenta', + orange: 'colour208', + pink: 'colour205', + cyan: 'cyan', + } + return tmuxColors[color] +} + +/** + * Runs a tmux command in the user's original tmux session (no socket override). + * Use this for operations that interact with the user's tmux panes (split-pane with leader). + */ +function runTmuxInUserSession( + args: string[], +): Promise<{ stdout: string; stderr: string; code: number }> { + return execFileNoThrow(TMUX_COMMAND, args) +} + +/** + * Runs a tmux command in the external swarm socket. + * Use this for operations in the standalone swarm session (when user is not in tmux). + */ +function runTmuxInSwarm( + args: string[], +): Promise<{ stdout: string; stderr: string; code: number }> { + return execFileNoThrow(TMUX_COMMAND, ['-L', getSwarmSocketName(), ...args]) +} + +/** + * TmuxBackend implements PaneBackend using tmux for pane management. + * + * When running INSIDE tmux (leader is in tmux): + * - Splits the current window to add teammates alongside the leader + * - Leader stays on left (30%), teammates on right (70%) + * + * When running OUTSIDE tmux (leader is in regular terminal): + * - Creates a claude-swarm session with a swarm-view window + * - All teammates are equally distributed (no leader pane) + */ +export class TmuxBackend implements PaneBackend { + readonly type = 'tmux' as const + readonly displayName = 'tmux' + readonly supportsHideShow = true + + /** + * Checks if tmux is installed and available. + * Delegates to detection.ts for consistent detection logic. + */ + async isAvailable(): Promise { + return isTmuxAvailable() + } + + /** + * Checks if we're currently running inside a tmux session. + * Delegates to detection.ts for consistent detection logic. + */ + async isRunningInside(): Promise { + return isInsideTmuxFromDetection() + } + + /** + * Creates a new teammate pane in the swarm view. + * Uses a lock to prevent race conditions when multiple teammates are spawned in parallel. + */ + async createTeammatePaneInSwarmView( + name: string, + color: AgentColorName, + ): Promise { + const releaseLock = await acquirePaneCreationLock() + + try { + const insideTmux = await this.isRunningInside() + + if (insideTmux) { + return await this.createTeammatePaneWithLeader(name, color) + } + + return await this.createTeammatePaneExternal(name, color) + } finally { + releaseLock() + } + } + + /** + * Sends a command to a specific pane. + */ + async sendCommandToPane( + paneId: PaneId, + command: string, + useExternalSession = false, + ): Promise { + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + const result = await runTmux(['send-keys', '-t', paneId, command, 'Enter']) + + if (result.code !== 0) { + throw new Error( + `Failed to send command to pane ${paneId}: ${result.stderr}`, + ) + } + } + + /** + * Sets the border color for a specific pane. + */ + async setPaneBorderColor( + paneId: PaneId, + color: AgentColorName, + useExternalSession = false, + ): Promise { + const tmuxColor = getTmuxColorName(color) + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + + // Set pane-specific border style using pane options (requires tmux 3.2+) + await runTmux([ + 'select-pane', + '-t', + paneId, + '-P', + `bg=default,fg=${tmuxColor}`, + ]) + + await runTmux([ + 'set-option', + '-p', + '-t', + paneId, + 'pane-border-style', + `fg=${tmuxColor}`, + ]) + + await runTmux([ + 'set-option', + '-p', + '-t', + paneId, + 'pane-active-border-style', + `fg=${tmuxColor}`, + ]) + } + + /** + * Sets the title for a pane (shown in pane border if pane-border-status is set). + */ + async setPaneTitle( + paneId: PaneId, + name: string, + color: AgentColorName, + useExternalSession = false, + ): Promise { + const tmuxColor = getTmuxColorName(color) + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + + // Set the pane title + await runTmux(['select-pane', '-t', paneId, '-T', name]) + + // Enable pane border status with colored format + await runTmux([ + 'set-option', + '-p', + '-t', + paneId, + 'pane-border-format', + `#[fg=${tmuxColor},bold] #{pane_title} #[default]`, + ]) + } + + /** + * Enables pane border status for a window (shows pane titles). + */ + async enablePaneBorderStatus( + windowTarget?: string, + useExternalSession = false, + ): Promise { + const target = windowTarget || (await this.getCurrentWindowTarget()) + if (!target) { + return + } + + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + await runTmux([ + 'set-option', + '-w', + '-t', + target, + 'pane-border-status', + 'top', + ]) + } + + /** + * Rebalances panes to achieve the desired layout. + */ + async rebalancePanes( + windowTarget: string, + hasLeader: boolean, + ): Promise { + if (hasLeader) { + await this.rebalancePanesWithLeader(windowTarget) + } else { + await this.rebalancePanesTiled(windowTarget) + } + } + + /** + * Kills/closes a specific pane. + */ + async killPane(paneId: PaneId, useExternalSession = false): Promise { + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + const result = await runTmux(['kill-pane', '-t', paneId]) + return result.code === 0 + } + + /** + * Hides a pane by moving it to a detached hidden session. + * Creates the hidden session if it doesn't exist, then uses break-pane to move the pane there. + */ + async hidePane(paneId: PaneId, useExternalSession = false): Promise { + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + + // Create hidden session if it doesn't exist (detached, not visible) + await runTmux(['new-session', '-d', '-s', HIDDEN_SESSION_NAME]) + + // Move the pane to the hidden session + const result = await runTmux([ + 'break-pane', + '-d', + '-s', + paneId, + '-t', + `${HIDDEN_SESSION_NAME}:`, + ]) + + if (result.code === 0) { + logForDebugging(`[TmuxBackend] Hidden pane ${paneId}`) + } else { + logForDebugging( + `[TmuxBackend] Failed to hide pane ${paneId}: ${result.stderr}`, + ) + } + + return result.code === 0 + } + + /** + * Shows a previously hidden pane by joining it back into the target window. + * Uses `tmux join-pane` to move the pane back, then reapplies main-vertical layout + * with leader at 30%. + */ + async showPane( + paneId: PaneId, + targetWindowOrPane: string, + useExternalSession = false, + ): Promise { + const runTmux = useExternalSession ? runTmuxInSwarm : runTmuxInUserSession + + // join-pane -s: source pane to move + // -t: target window/pane to join into + // -h: join horizontally (side by side) + const result = await runTmux([ + 'join-pane', + '-h', + '-s', + paneId, + '-t', + targetWindowOrPane, + ]) + + if (result.code !== 0) { + logForDebugging( + `[TmuxBackend] Failed to show pane ${paneId}: ${result.stderr}`, + ) + return false + } + + logForDebugging( + `[TmuxBackend] Showed pane ${paneId} in ${targetWindowOrPane}`, + ) + + // Reapply main-vertical layout with leader at 30% + await runTmux(['select-layout', '-t', targetWindowOrPane, 'main-vertical']) + + // Get the first pane (leader) and resize to 30% + const panesResult = await runTmux([ + 'list-panes', + '-t', + targetWindowOrPane, + '-F', + '#{pane_id}', + ]) + + const panes = panesResult.stdout.trim().split('\n').filter(Boolean) + if (panes[0]) { + await runTmux(['resize-pane', '-t', panes[0], '-x', '30%']) + } + + return true + } + + // Private helper methods + + /** + * Gets the leader's pane ID. + * Uses the TMUX_PANE env var captured at module load to ensure we always + * get the leader's original pane, even if the user has switched panes. + */ + private async getCurrentPaneId(): Promise { + // Use the pane ID captured at startup (from TMUX_PANE env var) + const leaderPane = getLeaderPaneId() + if (leaderPane) { + return leaderPane + } + + // Fallback to dynamic query (shouldn't happen if we're inside tmux) + const result = await execFileNoThrow(TMUX_COMMAND, [ + 'display-message', + '-p', + '#{pane_id}', + ]) + + if (result.code !== 0) { + logForDebugging( + `[TmuxBackend] Failed to get current pane ID (exit ${result.code}): ${result.stderr}`, + ) + return null + } + + return result.stdout.trim() + } + + /** + * Gets the leader's window target (session:window format). + * Uses the leader's pane ID to query for its window, ensuring we get the + * correct window even if the user has switched to a different window. + * Caches the result since the leader's window won't change. + */ + private async getCurrentWindowTarget(): Promise { + // Return cached value if available + if (cachedLeaderWindowTarget) { + return cachedLeaderWindowTarget + } + + // Build the command - use -t to target the leader's pane specifically + const leaderPane = getLeaderPaneId() + const args = ['display-message'] + if (leaderPane) { + args.push('-t', leaderPane) + } + args.push('-p', '#{session_name}:#{window_index}') + + const result = await execFileNoThrow(TMUX_COMMAND, args) + + if (result.code !== 0) { + logForDebugging( + `[TmuxBackend] Failed to get current window target (exit ${result.code}): ${result.stderr}`, + ) + return null + } + + cachedLeaderWindowTarget = result.stdout.trim() + return cachedLeaderWindowTarget + } + + /** + * Gets the number of panes in a window. + */ + private async getCurrentWindowPaneCount( + windowTarget?: string, + useSwarmSocket = false, + ): Promise { + const target = windowTarget || (await this.getCurrentWindowTarget()) + if (!target) { + return null + } + + const args = ['list-panes', '-t', target, '-F', '#{pane_id}'] + const result = useSwarmSocket + ? await runTmuxInSwarm(args) + : await runTmuxInUserSession(args) + + if (result.code !== 0) { + logError( + new Error( + `[TmuxBackend] Failed to get pane count for ${target} (exit ${result.code}): ${result.stderr}`, + ), + ) + return null + } + + return count(result.stdout.trim().split('\n'), Boolean) + } + + /** + * Checks if a tmux session exists in the swarm socket. + */ + private async hasSessionInSwarm(sessionName: string): Promise { + const result = await runTmuxInSwarm(['has-session', '-t', sessionName]) + return result.code === 0 + } + + /** + * Creates the swarm session with a single window for teammates when running outside tmux. + */ + private async createExternalSwarmSession(): Promise<{ + windowTarget: string + paneId: string + }> { + const sessionExists = await this.hasSessionInSwarm(SWARM_SESSION_NAME) + + if (!sessionExists) { + const result = await runTmuxInSwarm([ + 'new-session', + '-d', + '-s', + SWARM_SESSION_NAME, + '-n', + SWARM_VIEW_WINDOW_NAME, + '-P', + '-F', + '#{pane_id}', + ]) + + if (result.code !== 0) { + throw new Error( + `Failed to create swarm session: ${result.stderr || 'Unknown error'}`, + ) + } + + const paneId = result.stdout.trim() + const windowTarget = `${SWARM_SESSION_NAME}:${SWARM_VIEW_WINDOW_NAME}` + + logForDebugging( + `[TmuxBackend] Created external swarm session with window ${windowTarget}, pane ${paneId}`, + ) + + return { windowTarget, paneId } + } + + // Session exists, check if swarm-view window exists + const listResult = await runTmuxInSwarm([ + 'list-windows', + '-t', + SWARM_SESSION_NAME, + '-F', + '#{window_name}', + ]) + + const windows = listResult.stdout.trim().split('\n').filter(Boolean) + const windowTarget = `${SWARM_SESSION_NAME}:${SWARM_VIEW_WINDOW_NAME}` + + if (windows.includes(SWARM_VIEW_WINDOW_NAME)) { + const paneResult = await runTmuxInSwarm([ + 'list-panes', + '-t', + windowTarget, + '-F', + '#{pane_id}', + ]) + + const panes = paneResult.stdout.trim().split('\n').filter(Boolean) + return { windowTarget, paneId: panes[0] || '' } + } + + // Create the swarm-view window + const createResult = await runTmuxInSwarm([ + 'new-window', + '-t', + SWARM_SESSION_NAME, + '-n', + SWARM_VIEW_WINDOW_NAME, + '-P', + '-F', + '#{pane_id}', + ]) + + if (createResult.code !== 0) { + throw new Error( + `Failed to create swarm-view window: ${createResult.stderr || 'Unknown error'}`, + ) + } + + return { windowTarget, paneId: createResult.stdout.trim() } + } + + /** + * Creates a teammate pane when running inside tmux (with leader). + */ + private async createTeammatePaneWithLeader( + teammateName: string, + teammateColor: AgentColorName, + ): Promise { + const currentPaneId = await this.getCurrentPaneId() + const windowTarget = await this.getCurrentWindowTarget() + + if (!currentPaneId || !windowTarget) { + throw new Error('Could not determine current tmux pane/window') + } + + const paneCount = await this.getCurrentWindowPaneCount(windowTarget) + if (paneCount === null) { + throw new Error('Could not determine pane count for current window') + } + const isFirstTeammate = paneCount === 1 + + let splitResult + if (isFirstTeammate) { + // First teammate: split horizontally from the leader pane + splitResult = await execFileNoThrow(TMUX_COMMAND, [ + 'split-window', + '-t', + currentPaneId, + '-h', + '-l', + '70%', + '-P', + '-F', + '#{pane_id}', + ]) + } else { + // Additional teammates: split from an existing teammate pane + const listResult = await execFileNoThrow(TMUX_COMMAND, [ + 'list-panes', + '-t', + windowTarget, + '-F', + '#{pane_id}', + ]) + + const panes = listResult.stdout.trim().split('\n').filter(Boolean) + const teammatePanes = panes.slice(1) + const teammateCount = teammatePanes.length + + const splitVertically = teammateCount % 2 === 1 + const targetPaneIndex = Math.floor((teammateCount - 1) / 2) + const targetPane = + teammatePanes[targetPaneIndex] || + teammatePanes[teammatePanes.length - 1] + + splitResult = await execFileNoThrow(TMUX_COMMAND, [ + 'split-window', + '-t', + targetPane!, + splitVertically ? '-v' : '-h', + '-P', + '-F', + '#{pane_id}', + ]) + } + + if (splitResult.code !== 0) { + throw new Error(`Failed to create teammate pane: ${splitResult.stderr}`) + } + + const paneId = splitResult.stdout.trim() + logForDebugging( + `[TmuxBackend] Created teammate pane for ${teammateName}: ${paneId}`, + ) + + await this.setPaneBorderColor(paneId, teammateColor) + await this.setPaneTitle(paneId, teammateName, teammateColor) + await this.rebalancePanesWithLeader(windowTarget) + + // Wait for shell to initialize before returning, so commands can be sent immediately + await waitForPaneShellReady() + + return { paneId, isFirstTeammate } + } + + /** + * Creates a teammate pane when running outside tmux (no leader in tmux). + */ + private async createTeammatePaneExternal( + teammateName: string, + teammateColor: AgentColorName, + ): Promise { + const { windowTarget, paneId: firstPaneId } = + await this.createExternalSwarmSession() + + const paneCount = await this.getCurrentWindowPaneCount(windowTarget, true) + if (paneCount === null) { + throw new Error('Could not determine pane count for swarm window') + } + const isFirstTeammate = !firstPaneUsedForExternal && paneCount === 1 + + let paneId: string + + if (isFirstTeammate) { + paneId = firstPaneId + firstPaneUsedForExternal = true + logForDebugging( + `[TmuxBackend] Using initial pane for first teammate ${teammateName}: ${paneId}`, + ) + + await this.enablePaneBorderStatus(windowTarget, true) + } else { + const listResult = await runTmuxInSwarm([ + 'list-panes', + '-t', + windowTarget, + '-F', + '#{pane_id}', + ]) + + const panes = listResult.stdout.trim().split('\n').filter(Boolean) + const teammateCount = panes.length + + const splitVertically = teammateCount % 2 === 1 + const targetPaneIndex = Math.floor((teammateCount - 1) / 2) + const targetPane = panes[targetPaneIndex] || panes[panes.length - 1] + + const splitResult = await runTmuxInSwarm([ + 'split-window', + '-t', + targetPane!, + splitVertically ? '-v' : '-h', + '-P', + '-F', + '#{pane_id}', + ]) + + if (splitResult.code !== 0) { + throw new Error(`Failed to create teammate pane: ${splitResult.stderr}`) + } + + paneId = splitResult.stdout.trim() + logForDebugging( + `[TmuxBackend] Created teammate pane for ${teammateName}: ${paneId}`, + ) + } + + await this.setPaneBorderColor(paneId, teammateColor, true) + await this.setPaneTitle(paneId, teammateName, teammateColor, true) + await this.rebalancePanesTiled(windowTarget) + + // Wait for shell to initialize before returning, so commands can be sent immediately + await waitForPaneShellReady() + + return { paneId, isFirstTeammate } + } + + /** + * Rebalances panes in a window with a leader. + */ + private async rebalancePanesWithLeader(windowTarget: string): Promise { + const listResult = await runTmuxInUserSession([ + 'list-panes', + '-t', + windowTarget, + '-F', + '#{pane_id}', + ]) + + const panes = listResult.stdout.trim().split('\n').filter(Boolean) + if (panes.length <= 2) { + return + } + + await runTmuxInUserSession([ + 'select-layout', + '-t', + windowTarget, + 'main-vertical', + ]) + + const leaderPane = panes[0] + await runTmuxInUserSession(['resize-pane', '-t', leaderPane!, '-x', '30%']) + + logForDebugging( + `[TmuxBackend] Rebalanced ${panes.length - 1} teammate panes with leader`, + ) + } + + /** + * Rebalances panes in a window without a leader (tiled layout). + */ + private async rebalancePanesTiled(windowTarget: string): Promise { + const listResult = await runTmuxInSwarm([ + 'list-panes', + '-t', + windowTarget, + '-F', + '#{pane_id}', + ]) + + const panes = listResult.stdout.trim().split('\n').filter(Boolean) + if (panes.length <= 1) { + return + } + + await runTmuxInSwarm(['select-layout', '-t', windowTarget, 'tiled']) + + logForDebugging( + `[TmuxBackend] Rebalanced ${panes.length} teammate panes with tiled layout`, + ) + } +} + +// Register the backend with the registry when this module is imported. +// This side effect is intentional - the registry needs backends to self-register to avoid circular dependencies. +// eslint-disable-next-line custom-rules/no-top-level-side-effects +registerTmuxBackend(TmuxBackend) diff --git a/_all-in-one-upload/cc-haha/src/utils/swarm/permissionSync.ts b/_all-in-one-upload/cc-haha/src/utils/swarm/permissionSync.ts new file mode 100644 index 0000000..001e7a2 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/swarm/permissionSync.ts @@ -0,0 +1,928 @@ +/** + * Synchronized Permission Prompts for Agent Swarms + * + * This module provides infrastructure for coordinating permission prompts across + * multiple agents in a swarm. When a worker agent needs permission for a tool use, + * it can forward the request to the team leader, who can then approve or deny it. + * + * The system uses the teammate mailbox for message passing: + * - Workers send permission requests to the leader's mailbox + * - Leaders send permission responses to the worker's mailbox + * + * Flow: + * 1. Worker agent encounters a permission prompt + * 2. Worker sends a permission_request message to the leader's mailbox + * 3. Leader polls for mailbox messages and detects permission requests + * 4. User approves/denies via the leader's UI + * 5. Leader sends a permission_response message to the worker's mailbox + * 6. Worker polls mailbox for responses and continues execution + */ + +import { mkdir, readdir, readFile, unlink, writeFile } from 'fs/promises' +import { join } from 'path' +import { z } from 'zod/v4' +import { logForDebugging } from '../debug.js' +import { getErrnoCode } from '../errors.js' +import { lazySchema } from '../lazySchema.js' +import * as lockfile from '../lockfile.js' +import { logError } from '../log.js' +import type { PermissionUpdate } from '../permissions/PermissionUpdateSchema.js' +import { jsonParse, jsonStringify } from '../slowOperations.js' +import { + getAgentId, + getAgentName, + getTeammateColor, + getTeamName, +} from '../teammate.js' +import { + createPermissionRequestMessage, + createPermissionResponseMessage, + createSandboxPermissionRequestMessage, + createSandboxPermissionResponseMessage, + writeToMailbox, +} from '../teammateMailbox.js' +import { getTeamDir, readTeamFileAsync } from './teamHelpers.js' + +/** + * Full request schema for a permission request from a worker to the leader + */ +export const SwarmPermissionRequestSchema = lazySchema(() => + z.object({ + /** Unique identifier for this request */ + id: z.string(), + /** Worker's CLAUDE_CODE_AGENT_ID */ + workerId: z.string(), + /** Worker's CLAUDE_CODE_AGENT_NAME */ + workerName: z.string(), + /** Worker's CLAUDE_CODE_AGENT_COLOR */ + workerColor: z.string().optional(), + /** Team name for routing */ + teamName: z.string(), + /** Tool name requiring permission (e.g., "Bash", "Edit") */ + toolName: z.string(), + /** Original toolUseID from worker's context */ + toolUseId: z.string(), + /** Human-readable description of the tool use */ + description: z.string(), + /** Serialized tool input */ + input: z.record(z.string(), z.unknown()), + /** Suggested permission rules from the permission result */ + permissionSuggestions: z.array(z.unknown()), + /** Status of the request */ + status: z.enum(['pending', 'approved', 'rejected']), + /** Who resolved the request */ + resolvedBy: z.enum(['worker', 'leader']).optional(), + /** Timestamp when resolved */ + resolvedAt: z.number().optional(), + /** Rejection feedback message */ + feedback: z.string().optional(), + /** Modified input if changed by resolver */ + updatedInput: z.record(z.string(), z.unknown()).optional(), + /** "Always allow" rules applied during resolution */ + permissionUpdates: z.array(z.unknown()).optional(), + /** Timestamp when request was created */ + createdAt: z.number(), + }), +) + +export type SwarmPermissionRequest = z.infer< + ReturnType +> + +/** + * Resolution data returned when leader/worker resolves a request + */ +export type PermissionResolution = { + /** Decision: approved or rejected */ + decision: 'approved' | 'rejected' + /** Who resolved it */ + resolvedBy: 'worker' | 'leader' + /** Optional feedback message if rejected */ + feedback?: string + /** Optional updated input if the resolver modified it */ + updatedInput?: Record + /** Permission updates to apply (e.g., "always allow" rules) */ + permissionUpdates?: PermissionUpdate[] +} + +/** + * Get the base directory for a team's permission requests + * Path: ~/.claude/teams/{teamName}/permissions/ + */ +export function getPermissionDir(teamName: string): string { + return join(getTeamDir(teamName), 'permissions') +} + +/** + * Get the pending directory for a team + */ +function getPendingDir(teamName: string): string { + return join(getPermissionDir(teamName), 'pending') +} + +/** + * Get the resolved directory for a team + */ +function getResolvedDir(teamName: string): string { + return join(getPermissionDir(teamName), 'resolved') +} + +/** + * Ensure the permissions directory structure exists (async) + */ +async function ensurePermissionDirsAsync(teamName: string): Promise { + const permDir = getPermissionDir(teamName) + const pendingDir = getPendingDir(teamName) + const resolvedDir = getResolvedDir(teamName) + + for (const dir of [permDir, pendingDir, resolvedDir]) { + await mkdir(dir, { recursive: true }) + } +} + +/** + * Get the path to a pending request file + */ +function getPendingRequestPath(teamName: string, requestId: string): string { + return join(getPendingDir(teamName), `${requestId}.json`) +} + +/** + * Get the path to a resolved request file + */ +function getResolvedRequestPath(teamName: string, requestId: string): string { + return join(getResolvedDir(teamName), `${requestId}.json`) +} + +/** + * Generate a unique request ID + */ +export function generateRequestId(): string { + return `perm-${Date.now()}-${Math.random().toString(36).substring(2, 9)}` +} + +/** + * Create a new SwarmPermissionRequest object + */ +export function createPermissionRequest(params: { + toolName: string + toolUseId: string + input: Record + description: string + permissionSuggestions?: unknown[] + teamName?: string + workerId?: string + workerName?: string + workerColor?: string +}): SwarmPermissionRequest { + const teamName = params.teamName || getTeamName() + const workerId = params.workerId || getAgentId() + const workerName = params.workerName || getAgentName() + const workerColor = params.workerColor || getTeammateColor() + + if (!teamName) { + throw new Error('Team name is required for permission requests') + } + if (!workerId) { + throw new Error('Worker ID is required for permission requests') + } + if (!workerName) { + throw new Error('Worker name is required for permission requests') + } + + return { + id: generateRequestId(), + workerId, + workerName, + workerColor, + teamName, + toolName: params.toolName, + toolUseId: params.toolUseId, + description: params.description, + input: params.input, + permissionSuggestions: params.permissionSuggestions || [], + status: 'pending', + createdAt: Date.now(), + } +} + +/** + * Write a permission request to the pending directory with file locking + * Called by worker agents when they need permission approval from the leader + * + * @returns The written request + */ +export async function writePermissionRequest( + request: SwarmPermissionRequest, +): Promise { + await ensurePermissionDirsAsync(request.teamName) + + const pendingPath = getPendingRequestPath(request.teamName, request.id) + const lockDir = getPendingDir(request.teamName) + + // Create a directory-level lock file for atomic writes + const lockFilePath = join(lockDir, '.lock') + await writeFile(lockFilePath, '', 'utf-8') + + let release: (() => Promise) | undefined + try { + release = await lockfile.lock(lockFilePath) + + // Write the request file + await writeFile(pendingPath, jsonStringify(request, null, 2), 'utf-8') + + logForDebugging( + `[PermissionSync] Wrote pending request ${request.id} from ${request.workerName} for ${request.toolName}`, + ) + + return request + } catch (error) { + logForDebugging( + `[PermissionSync] Failed to write permission request: ${error}`, + ) + logError(error) + throw error + } finally { + if (release) { + await release() + } + } +} + +/** + * Read all pending permission requests for a team + * Called by the team leader to see what requests need attention + */ +export async function readPendingPermissions( + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + logForDebugging('[PermissionSync] No team name available') + return [] + } + + const pendingDir = getPendingDir(team) + + let files: string[] + try { + files = await readdir(pendingDir) + } catch (e: unknown) { + const code = getErrnoCode(e) + if (code === 'ENOENT') { + return [] + } + logForDebugging(`[PermissionSync] Failed to read pending requests: ${e}`) + logError(e) + return [] + } + + const jsonFiles = files.filter(f => f.endsWith('.json') && f !== '.lock') + + const results = await Promise.all( + jsonFiles.map(async file => { + const filePath = join(pendingDir, file) + try { + const content = await readFile(filePath, 'utf-8') + const parsed = SwarmPermissionRequestSchema().safeParse( + jsonParse(content), + ) + if (parsed.success) { + return parsed.data + } + logForDebugging( + `[PermissionSync] Invalid request file ${file}: ${parsed.error.message}`, + ) + return null + } catch (err) { + logForDebugging( + `[PermissionSync] Failed to read request file ${file}: ${err}`, + ) + return null + } + }), + ) + + const requests = results.filter(r => r !== null) + + // Sort by creation time (oldest first) + requests.sort((a, b) => a.createdAt - b.createdAt) + + return requests +} + +/** + * Read a resolved permission request by ID + * Called by workers to check if their request has been resolved + * + * @returns The resolved request, or null if not yet resolved + */ +export async function readResolvedPermission( + requestId: string, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + return null + } + + const resolvedPath = getResolvedRequestPath(team, requestId) + + try { + const content = await readFile(resolvedPath, 'utf-8') + const parsed = SwarmPermissionRequestSchema().safeParse(jsonParse(content)) + if (parsed.success) { + return parsed.data + } + logForDebugging( + `[PermissionSync] Invalid resolved request ${requestId}: ${parsed.error.message}`, + ) + return null + } catch (e: unknown) { + const code = getErrnoCode(e) + if (code === 'ENOENT') { + return null + } + logForDebugging( + `[PermissionSync] Failed to read resolved request ${requestId}: ${e}`, + ) + logError(e) + return null + } +} + +/** + * Resolve a permission request + * Called by the team leader (or worker in self-resolution cases) + * + * Writes the resolution to resolved/, removes from pending/ + */ +export async function resolvePermission( + requestId: string, + resolution: PermissionResolution, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + logForDebugging('[PermissionSync] No team name available') + return false + } + + await ensurePermissionDirsAsync(team) + + const pendingPath = getPendingRequestPath(team, requestId) + const resolvedPath = getResolvedRequestPath(team, requestId) + const lockFilePath = join(getPendingDir(team), '.lock') + + await writeFile(lockFilePath, '', 'utf-8') + + let release: (() => Promise) | undefined + try { + release = await lockfile.lock(lockFilePath) + + // Read the pending request + let content: string + try { + content = await readFile(pendingPath, 'utf-8') + } catch (e: unknown) { + const code = getErrnoCode(e) + if (code === 'ENOENT') { + logForDebugging( + `[PermissionSync] Pending request not found: ${requestId}`, + ) + return false + } + throw e + } + + const parsed = SwarmPermissionRequestSchema().safeParse(jsonParse(content)) + if (!parsed.success) { + logForDebugging( + `[PermissionSync] Invalid pending request ${requestId}: ${parsed.error.message}`, + ) + return false + } + + const request = parsed.data + + // Update the request with resolution data + const resolvedRequest: SwarmPermissionRequest = { + ...request, + status: resolution.decision === 'approved' ? 'approved' : 'rejected', + resolvedBy: resolution.resolvedBy, + resolvedAt: Date.now(), + feedback: resolution.feedback, + updatedInput: resolution.updatedInput, + permissionUpdates: resolution.permissionUpdates, + } + + // Write to resolved directory + await writeFile( + resolvedPath, + jsonStringify(resolvedRequest, null, 2), + 'utf-8', + ) + + // Remove from pending directory + await unlink(pendingPath) + + logForDebugging( + `[PermissionSync] Resolved request ${requestId} with ${resolution.decision}`, + ) + + return true + } catch (error) { + logForDebugging(`[PermissionSync] Failed to resolve request: ${error}`) + logError(error) + return false + } finally { + if (release) { + await release() + } + } +} + +/** + * Clean up old resolved permission files + * Called periodically to prevent file accumulation + * + * @param teamName - Team name + * @param maxAgeMs - Maximum age in milliseconds (default: 1 hour) + */ +export async function cleanupOldResolutions( + teamName?: string, + maxAgeMs = 3600000, +): Promise { + const team = teamName || getTeamName() + if (!team) { + return 0 + } + + const resolvedDir = getResolvedDir(team) + + let files: string[] + try { + files = await readdir(resolvedDir) + } catch (e: unknown) { + const code = getErrnoCode(e) + if (code === 'ENOENT') { + return 0 + } + logForDebugging(`[PermissionSync] Failed to cleanup resolutions: ${e}`) + logError(e) + return 0 + } + + const now = Date.now() + const jsonFiles = files.filter(f => f.endsWith('.json')) + + const cleanupResults = await Promise.all( + jsonFiles.map(async file => { + const filePath = join(resolvedDir, file) + try { + const content = await readFile(filePath, 'utf-8') + const request = jsonParse(content) as SwarmPermissionRequest + + // Check if the resolution is old enough to clean up + // Use >= to handle edge case where maxAgeMs is 0 (clean up everything) + const resolvedAt = request.resolvedAt || request.createdAt + if (now - resolvedAt >= maxAgeMs) { + await unlink(filePath) + logForDebugging(`[PermissionSync] Cleaned up old resolution: ${file}`) + return 1 + } + return 0 + } catch { + // If we can't parse it, clean it up anyway + try { + await unlink(filePath) + return 1 + } catch { + // Ignore deletion errors + return 0 + } + } + }), + ) + + const cleanedCount = cleanupResults.reduce((sum, n) => sum + n, 0) + + if (cleanedCount > 0) { + logForDebugging( + `[PermissionSync] Cleaned up ${cleanedCount} old resolutions`, + ) + } + + return cleanedCount +} + +/** + * Legacy response type for worker polling + * Used for backward compatibility with worker integration code + */ +export type PermissionResponse = { + /** ID of the request this responds to */ + requestId: string + /** Decision: approved or denied */ + decision: 'approved' | 'denied' + /** Timestamp when response was created */ + timestamp: string + /** Optional feedback message if denied */ + feedback?: string + /** Optional updated input if the resolver modified it */ + updatedInput?: Record + /** Permission updates to apply (e.g., "always allow" rules) */ + permissionUpdates?: unknown[] +} + +/** + * Poll for a permission response (worker-side convenience function) + * Converts the resolved request into a simpler response format + * + * @returns The permission response, or null if not yet resolved + */ +export async function pollForResponse( + requestId: string, + _agentName?: string, + teamName?: string, +): Promise { + const resolved = await readResolvedPermission(requestId, teamName) + if (!resolved) { + return null + } + + return { + requestId: resolved.id, + decision: resolved.status === 'approved' ? 'approved' : 'denied', + timestamp: resolved.resolvedAt + ? new Date(resolved.resolvedAt).toISOString() + : new Date(resolved.createdAt).toISOString(), + feedback: resolved.feedback, + updatedInput: resolved.updatedInput, + permissionUpdates: resolved.permissionUpdates, + } +} + +/** + * Remove a worker's response after processing + * This is an alias for deleteResolvedPermission for backward compatibility + */ +export async function removeWorkerResponse( + requestId: string, + _agentName?: string, + teamName?: string, +): Promise { + await deleteResolvedPermission(requestId, teamName) +} + +/** + * Check if the current agent is a team leader + */ +export function isTeamLeader(teamName?: string): boolean { + const team = teamName || getTeamName() + if (!team) { + return false + } + + // Team leaders don't have an agent ID set, or their ID is 'team-lead' + const agentId = getAgentId() + + return !agentId || agentId === 'team-lead' +} + +/** + * Check if the current agent is a worker in a swarm + */ +export function isSwarmWorker(): boolean { + const teamName = getTeamName() + const agentId = getAgentId() + + return !!teamName && !!agentId && !isTeamLeader() +} + +/** + * Delete a resolved permission file + * Called after a worker has processed the resolution + */ +export async function deleteResolvedPermission( + requestId: string, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + return false + } + + const resolvedPath = getResolvedRequestPath(team, requestId) + + try { + await unlink(resolvedPath) + logForDebugging( + `[PermissionSync] Deleted resolved permission: ${requestId}`, + ) + return true + } catch (e: unknown) { + const code = getErrnoCode(e) + if (code === 'ENOENT') { + return false + } + logForDebugging( + `[PermissionSync] Failed to delete resolved permission: ${e}`, + ) + logError(e) + return false + } +} + +/** + * Submit a permission request (alias for writePermissionRequest) + * Provided for backward compatibility with worker integration code + */ +export const submitPermissionRequest = writePermissionRequest + +// ============================================================================ +// Mailbox-Based Permission System +// ============================================================================ + +/** + * Get the leader's name from the team file + * This is needed to send permission requests to the leader's mailbox + */ +export async function getLeaderName(teamName?: string): Promise { + const team = teamName || getTeamName() + if (!team) { + return null + } + + const teamFile = await readTeamFileAsync(team) + if (!teamFile) { + logForDebugging(`[PermissionSync] Team file not found for team: ${team}`) + return null + } + + const leadMember = teamFile.members.find( + m => m.agentId === teamFile.leadAgentId, + ) + return leadMember?.name || 'team-lead' +} + +/** + * Send a permission request to the leader via mailbox. + * This is the new mailbox-based approach that replaces the file-based pending directory. + * + * @param request - The permission request to send + * @returns true if the message was sent successfully + */ +export async function sendPermissionRequestViaMailbox( + request: SwarmPermissionRequest, +): Promise { + const leaderName = await getLeaderName(request.teamName) + if (!leaderName) { + logForDebugging( + `[PermissionSync] Cannot send permission request: leader name not found`, + ) + return false + } + + try { + // Create the permission request message + const message = createPermissionRequestMessage({ + request_id: request.id, + agent_id: request.workerName, + tool_name: request.toolName, + tool_use_id: request.toolUseId, + description: request.description, + input: request.input, + permission_suggestions: request.permissionSuggestions, + }) + + // Send to leader's mailbox (routes to in-process or file-based based on recipient) + await writeToMailbox( + leaderName, + { + from: request.workerName, + text: jsonStringify(message), + timestamp: new Date().toISOString(), + color: request.workerColor, + }, + request.teamName, + ) + + logForDebugging( + `[PermissionSync] Sent permission request ${request.id} to leader ${leaderName} via mailbox`, + ) + return true + } catch (error) { + logForDebugging( + `[PermissionSync] Failed to send permission request via mailbox: ${error}`, + ) + logError(error) + return false + } +} + +/** + * Send a permission response to a worker via mailbox. + * This is the new mailbox-based approach that replaces the file-based resolved directory. + * + * @param workerName - The worker's name to send the response to + * @param resolution - The permission resolution + * @param requestId - The original request ID + * @param teamName - The team name + * @returns true if the message was sent successfully + */ +export async function sendPermissionResponseViaMailbox( + workerName: string, + resolution: PermissionResolution, + requestId: string, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + logForDebugging( + `[PermissionSync] Cannot send permission response: team name not found`, + ) + return false + } + + try { + // Create the permission response message + const message = createPermissionResponseMessage({ + request_id: requestId, + subtype: resolution.decision === 'approved' ? 'success' : 'error', + error: resolution.feedback, + updated_input: resolution.updatedInput, + permission_updates: resolution.permissionUpdates, + }) + + // Get the sender name (leader's name) + const senderName = getAgentName() || 'team-lead' + + // Send to worker's mailbox (routes to in-process or file-based based on recipient) + await writeToMailbox( + workerName, + { + from: senderName, + text: jsonStringify(message), + timestamp: new Date().toISOString(), + }, + team, + ) + + logForDebugging( + `[PermissionSync] Sent permission response for ${requestId} to worker ${workerName} via mailbox`, + ) + return true + } catch (error) { + logForDebugging( + `[PermissionSync] Failed to send permission response via mailbox: ${error}`, + ) + logError(error) + return false + } +} + +// ============================================================================ +// Sandbox Permission Mailbox System +// ============================================================================ + +/** + * Generate a unique sandbox permission request ID + */ +export function generateSandboxRequestId(): string { + return `sandbox-${Date.now()}-${Math.random().toString(36).substring(2, 9)}` +} + +/** + * Send a sandbox permission request to the leader via mailbox. + * Called by workers when sandbox runtime needs network access approval. + * + * @param host - The host requesting network access + * @param requestId - Unique ID for this request + * @param teamName - Optional team name + * @returns true if the message was sent successfully + */ +export async function sendSandboxPermissionRequestViaMailbox( + host: string, + requestId: string, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + logForDebugging( + `[PermissionSync] Cannot send sandbox permission request: team name not found`, + ) + return false + } + + const leaderName = await getLeaderName(team) + if (!leaderName) { + logForDebugging( + `[PermissionSync] Cannot send sandbox permission request: leader name not found`, + ) + return false + } + + const workerId = getAgentId() + const workerName = getAgentName() + const workerColor = getTeammateColor() + + if (!workerId || !workerName) { + logForDebugging( + `[PermissionSync] Cannot send sandbox permission request: worker ID or name not found`, + ) + return false + } + + try { + const message = createSandboxPermissionRequestMessage({ + requestId, + workerId, + workerName, + workerColor, + host, + }) + + // Send to leader's mailbox (routes to in-process or file-based based on recipient) + await writeToMailbox( + leaderName, + { + from: workerName, + text: jsonStringify(message), + timestamp: new Date().toISOString(), + color: workerColor, + }, + team, + ) + + logForDebugging( + `[PermissionSync] Sent sandbox permission request ${requestId} for host ${host} to leader ${leaderName} via mailbox`, + ) + return true + } catch (error) { + logForDebugging( + `[PermissionSync] Failed to send sandbox permission request via mailbox: ${error}`, + ) + logError(error) + return false + } +} + +/** + * Send a sandbox permission response to a worker via mailbox. + * Called by the leader when approving/denying a sandbox network access request. + * + * @param workerName - The worker's name to send the response to + * @param requestId - The original request ID + * @param host - The host that was approved/denied + * @param allow - Whether the connection is allowed + * @param teamName - Optional team name + * @returns true if the message was sent successfully + */ +export async function sendSandboxPermissionResponseViaMailbox( + workerName: string, + requestId: string, + host: string, + allow: boolean, + teamName?: string, +): Promise { + const team = teamName || getTeamName() + if (!team) { + logForDebugging( + `[PermissionSync] Cannot send sandbox permission response: team name not found`, + ) + return false + } + + try { + const message = createSandboxPermissionResponseMessage({ + requestId, + host, + allow, + }) + + const senderName = getAgentName() || 'team-lead' + + // Send to worker's mailbox (routes to in-process or file-based based on recipient) + await writeToMailbox( + workerName, + { + from: senderName, + text: jsonStringify(message), + timestamp: new Date().toISOString(), + }, + team, + ) + + logForDebugging( + `[PermissionSync] Sent sandbox permission response for ${requestId} (host: ${host}, allow: ${allow}) to worker ${workerName} via mailbox`, + ) + return true + } catch (error) { + logForDebugging( + `[PermissionSync] Failed to send sandbox permission response via mailbox: ${error}`, + ) + logError(error) + return false + } +} diff --git a/_all-in-one-upload/cc-haha/src/utils/windowsPaths.ts b/_all-in-one-upload/cc-haha/src/utils/windowsPaths.ts new file mode 100644 index 0000000..776c2e3 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/utils/windowsPaths.ts @@ -0,0 +1,199 @@ +import memoize from 'lodash-es/memoize.js' +import * as path from 'path' +import * as pathWin32 from 'path/win32' +import { getCwd } from './cwd.js' +import { logForDebugging } from './debug.js' +import { execSync_DEPRECATED } from './execSyncWrapper.js' +import { memoizeWithLRU } from './memoize.js' +import { getPlatform } from './platform.js' + +/** + * Check if a file or directory exists on Windows using the dir command + * @param path - The path to check + * @returns true if the path exists, false otherwise + */ +function checkPathExists(path: string): boolean { + try { + execSync_DEPRECATED(`dir "${path}"`, { stdio: 'pipe' }) + return true + } catch { + return false + } +} + +/** + * Find an executable using where.exe on Windows + * @param executable - The name of the executable to find + * @returns The path to the executable or null if not found + */ +function findExecutable(executable: string): string | null { + // For git, check common installation locations first + if (executable === 'git') { + const defaultLocations = [ + // check 64 bit before 32 bit + 'C:\\Program Files\\Git\\cmd\\git.exe', + 'C:\\Program Files (x86)\\Git\\cmd\\git.exe', + // intentionally don't look for C:\Program Files\Git\mingw64\bin\git.exe + // because that directory is the "raw" tools with no environment setup + ] + + for (const location of defaultLocations) { + if (checkPathExists(location)) { + return location + } + } + } + + // Fall back to where.exe + try { + const result = execSync_DEPRECATED(`where.exe ${executable}`, { + stdio: 'pipe', + encoding: 'utf8', + }).trim() + + // SECURITY: Filter out any results from the current directory + // to prevent executing malicious git.bat/cmd/exe files + const paths = result.split('\r\n').filter(Boolean) + const cwd = getCwd().toLowerCase() + + for (const candidatePath of paths) { + // Normalize and compare paths to ensure we're not in current directory + const normalizedPath = path.resolve(candidatePath).toLowerCase() + const pathDir = path.dirname(normalizedPath).toLowerCase() + + // Skip if the executable is in the current working directory + if (pathDir === cwd || normalizedPath.startsWith(cwd + path.sep)) { + logForDebugging( + `Skipping potentially malicious executable in current directory: ${candidatePath}`, + ) + continue + } + + // Return the first valid path that's not in the current directory + return candidatePath + } + + return null + } catch { + return null + } +} + +/** + * If Windows, set the SHELL environment variable to git-bash path. + * This is used by BashTool and Shell.ts for user shell commands. + * COMSPEC is left unchanged for system process execution. + */ +export function setShellIfWindows(): void { + if (getPlatform() === 'windows') { + const gitBashPath = tryFindGitBashPath() + if (!gitBashPath) { + logForDebugging( + 'Git Bash not found on Windows; leaving SHELL unset for lazy fallback handling', + { level: 'warn' }, + ) + return + } + process.env.SHELL = gitBashPath + logForDebugging(`Using bash path: "${gitBashPath}"`) + } +} + +/** + * Best-effort Git Bash resolution on Windows. + * + * Returns null when Git Bash is unavailable so callers can decide whether to + * fall back (for example, to PowerShell) instead of hard-exiting the process. + */ +export const tryFindGitBashPath = memoize((): string | null => { + if (process.env.CLAUDE_CODE_GIT_BASH_PATH) { + if (checkPathExists(process.env.CLAUDE_CODE_GIT_BASH_PATH)) { + return process.env.CLAUDE_CODE_GIT_BASH_PATH + } + return null + } + + const gitPath = findExecutable('git') + if (gitPath) { + const bashPath = pathWin32.join(gitPath, '..', '..', 'bin', 'bash.exe') + if (checkPathExists(bashPath)) { + return bashPath + } + } + + return null +}) + +/** + * Find the path where `bash.exe` included with git-bash exists, exiting the process if not found. + */ +export const findGitBashPath = memoize((): string => { + const gitBashPath = tryFindGitBashPath() + if (gitBashPath) { + return gitBashPath + } + + if (process.env.CLAUDE_CODE_GIT_BASH_PATH) { + // biome-ignore lint/suspicious/noConsole:: intentional console output + console.error( + `Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path "${process.env.CLAUDE_CODE_GIT_BASH_PATH}"`, + ) + // eslint-disable-next-line custom-rules/no-process-exit + process.exit(1) + } + + // biome-ignore lint/suspicious/noConsole:: intentional console output + console.error( + 'Claude Code on Windows requires git-bash (https://git-scm.com/downloads/win). If installed but not in PATH, set environment variable pointing to your bash.exe, similar to: CLAUDE_CODE_GIT_BASH_PATH=C:\\Program Files\\Git\\bin\\bash.exe', + ) + // eslint-disable-next-line custom-rules/no-process-exit + process.exit(1) +}) + +/** Convert a Windows path to a POSIX path using pure JS. */ +export const windowsPathToPosixPath = memoizeWithLRU( + (windowsPath: string): string => { + // Handle UNC paths: \\server\share -> //server/share + if (windowsPath.startsWith('\\\\')) { + return windowsPath.replace(/\\/g, '/') + } + // Handle drive letter paths: C:\Users\foo -> /c/Users/foo + const match = windowsPath.match(/^([A-Za-z]):[/\\]/) + if (match) { + const driveLetter = match[1]!.toLowerCase() + return '/' + driveLetter + windowsPath.slice(2).replace(/\\/g, '/') + } + // Already POSIX or relative — just flip slashes + return windowsPath.replace(/\\/g, '/') + }, + (p: string) => p, + 500, +) + +/** Convert a POSIX path to a Windows path using pure JS. */ +export const posixPathToWindowsPath = memoizeWithLRU( + (posixPath: string): string => { + // Handle UNC paths: //server/share -> \\server\share + if (posixPath.startsWith('//')) { + return posixPath.replace(/\//g, '\\') + } + // Handle /cygdrive/c/... format + const cygdriveMatch = posixPath.match(/^\/cygdrive\/([A-Za-z])(\/|$)/) + if (cygdriveMatch) { + const driveLetter = cygdriveMatch[1]!.toUpperCase() + const rest = posixPath.slice(('/cygdrive/' + cygdriveMatch[1]).length) + return driveLetter + ':' + (rest || '\\').replace(/\//g, '\\') + } + // Handle /c/... format (MSYS2/Git Bash) + const driveMatch = posixPath.match(/^\/([A-Za-z])(\/|$)/) + if (driveMatch) { + const driveLetter = driveMatch[1]!.toUpperCase() + const rest = posixPath.slice(2) + return driveLetter + ':' + (rest || '\\').replace(/\//g, '\\') + } + // Already Windows or relative — just flip slashes + return posixPath.replace(/\//g, '\\') + }, + (p: string) => p, + 500, +) diff --git a/_all-in-one-upload/cc-haha/src/vendor/computer-use-mcp/tools.ts b/_all-in-one-upload/cc-haha/src/vendor/computer-use-mcp/tools.ts new file mode 100644 index 0000000..c744a23 --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/vendor/computer-use-mcp/tools.ts @@ -0,0 +1,706 @@ +/** + * MCP tool schemas for the computer-use server. Mirrors + * claude-for-chrome-mcp/src/browserTools.ts in shape (plain `Tool`-shaped + * object literals, no zod). + * + * Coordinate descriptions are baked in at tool-list build time from the + * `chicago_coordinate_mode` gate. The model sees exactly ONE coordinate + * convention in the param descriptions and never learns the other exists. + * The host (`serverDef.ts`) reads the same frozen gate value for + * `scaleCoord` — both must agree or clicks land in the wrong space. + */ + +import type { Tool } from "@modelcontextprotocol/sdk/types.js"; + +import type { CoordinateMode } from "./types.js"; + +// See packages/desktop/computer-use-mcp/COORDINATES.md before touching any +// model-facing coordinate text. Chrome's browserTools.ts:143 is the reference +// phrasing — "pixels from the left edge", no geometry, no number to do math with. +const COORD_DESC: Record = { + pixels: { + x: "Horizontal pixel position read directly from the most recent screenshot image, measured from the left edge. The server handles all scaling.", + y: "Vertical pixel position read directly from the most recent screenshot image, measured from the top edge. The server handles all scaling.", + }, + normalized_0_100: { + x: "Horizontal position as a percentage of screen width, 0.0–100.0 (0 = left edge, 100 = right edge).", + y: "Vertical position as a percentage of screen height, 0.0–100.0 (0 = top edge, 100 = bottom edge).", + }, +}; + +const FRONTMOST_GATE_DESC = + "The frontmost application must be in the session allowlist at the time of this call, or this tool returns an error and does nothing."; + +/** + * Item schema for the `actions` array in `computer_batch`, `teach_step`, and + * `teach_batch`. All three dispatch through the same `dispatchAction` path + * with the same validation — keep this enum in sync with `BATCHABLE_ACTIONS` + * in toolCalls.ts. + */ +const BATCH_ACTION_ITEM_SCHEMA = { + type: "object", + properties: { + action: { + type: "string", + enum: [ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "triple_click", + "scroll", + "hold_key", + "screenshot", + "cursor_position", + "left_mouse_down", + "left_mouse_up", + "wait", + ], + description: "The action to perform.", + }, + coordinate: { + type: "array", + items: { type: "number" }, + minItems: 2, + maxItems: 2, + description: + "(x, y) for click/mouse_move/scroll/left_click_drag end point.", + }, + start_coordinate: { + type: "array", + items: { type: "number" }, + minItems: 2, + maxItems: 2, + description: + "(x, y) drag start — left_click_drag only. Omit to drag from current cursor.", + }, + text: { + type: "string", + description: + "For type: the text. For key/hold_key: the chord string. For click/scroll: modifier keys to hold.", + }, + scroll_direction: { + type: "string", + enum: ["up", "down", "left", "right"], + }, + scroll_amount: { type: "integer", minimum: 0, maximum: 100 }, + duration: { + type: "number", + description: "Seconds (0–100). For hold_key/wait.", + }, + repeat: { + type: "integer", + minimum: 1, + maximum: 100, + description: "For key: repeat count.", + }, + }, + required: ["action"], +}; + +/** + * Build the tool list. Parameterized by capabilities and coordinate mode so + * descriptions are honest and unambiguous (plan §1 — "Unfiltered + honest"). + * + * `coordinateMode` MUST match what the host passes to `scaleCoord` at tool- + * -call time. Both should read the same frozen-at-load gate constant. + * + * `installedAppNames` — optional pre-sanitized list of app display names to + * enumerate in the `request_access` description. The caller is responsible + * for sanitization (length cap, character allowlist, sort, count cap) — + * this function just splices the list into the description verbatim. Omit + * to fall back to the generic "display names or bundle IDs" wording. + */ +export function buildComputerUseTools( + caps: { + screenshotFiltering: "native" | "none"; + platform: "darwin" | "win32"; + /** Include request_teach_access + teach_step. Read once at server construction. */ + teachMode?: boolean; + }, + coordinateMode: CoordinateMode, + installedAppNames?: string[], +): Tool[] { + const coord = COORD_DESC[coordinateMode]; + + // Shared hint suffix for BOTH request_access and request_teach_access — + // they use the same resolveRequestedApps path, so the model should get + // the same enumeration for both. + const installedAppsHint = + installedAppNames && installedAppNames.length > 0 + ? ` Available applications on this machine: ${installedAppNames.join(", ")}.` + : ""; + + // [x, y]` tuple — param shape for all + // click/move/scroll tools. + const coordinateTuple = { + type: "array", + items: { type: "number" }, + minItems: 2, + maxItems: 2, + description: `(x, y): ${coord.x}`, + }; + // Modifier hold during click. Shared across all 5 click variants. + const clickModifierText = { + type: "string", + description: + 'Modifier keys to hold during the click (e.g. "shift", "ctrl+shift"). Supports the same syntax as the key tool.', + }; + + const screenshotDesc = + caps.screenshotFiltering === "native" + ? "Take a screenshot of the primary display. Applications not in the session allowlist are excluded at the compositor level — only granted apps and the desktop are visible." + : "Take a screenshot of the primary display. On this platform, screenshots are NOT filtered — all open windows are visible. Input actions targeting apps not in the session allowlist are rejected."; + + return [ + { + name: "request_access", + description: + "Request user permission to control a set of applications for this session. Must be called before any other tool in this server. " + + "The user sees a single dialog listing all requested apps and either allows the whole set or denies it. " + + "Call this again mid-session to add more apps; previously granted apps remain granted. " + + "Returns the granted apps, denied apps, and screenshot filtering capability.", + inputSchema: { + type: "object" as const, + properties: { + apps: { + type: "array", + items: { type: "string" }, + description: + "Application display names (e.g. \"Slack\", \"Calendar\") or bundle identifiers (e.g. \"com.tinyspeck.slackmacgap\"). Display names are resolved case-insensitively against installed apps." + + installedAppsHint, + }, + reason: { + type: "string", + description: + "One-sentence explanation shown to the user in the approval dialog. Explain the task, not the mechanism.", + }, + clipboardRead: { + type: "boolean", + description: + "Also request permission to read the user's clipboard (separate checkbox in the dialog).", + }, + clipboardWrite: { + type: "boolean", + description: + "Also request permission to write the user's clipboard. When granted, multi-line `type` calls use the clipboard fast path.", + }, + systemKeyCombos: { + type: "boolean", + description: + "Also request permission to send system-level key combos (quit app, switch app, lock screen). Without this, those specific combos are blocked.", + }, + }, + required: ["apps", "reason"], + }, + }, + + { + name: "screenshot", + description: + screenshotDesc + + " Returns an error if the allowlist is empty. The returned image is what subsequent click coordinates are relative to.", + inputSchema: { + type: "object" as const, + properties: { + save_to_disk: { + type: "boolean", + description: + "Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image — screenshots you're just looking at don't need saving.", + }, + }, + required: [], + }, + }, + + { + name: "zoom", + description: + "Take a higher-resolution screenshot of a specific region of the last full-screen screenshot. Use this liberally to inspect small text, button labels, or fine UI details that are hard to read in the downsampled full-screen image. " + + "IMPORTANT: Coordinates in subsequent click calls always refer to the full-screen screenshot, never the zoomed image. This tool is read-only for inspecting detail.", + inputSchema: { + type: "object" as const, + properties: { + region: { + type: "array", + items: { type: "integer" }, + minItems: 4, + maxItems: 4, + description: + "(x0, y0, x1, y1): Rectangle to zoom into, in the coordinate space of the most recent full-screen screenshot. x0,y0 = top-left, x1,y1 = bottom-right.", + }, + save_to_disk: { + type: "boolean", + description: + "Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image.", + }, + }, + required: ["region"], + }, + }, + + { + name: "left_click", + description: `Left-click at the given coordinates. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + text: clickModifierText, + }, + required: ["coordinate"], + }, + }, + + { + name: "double_click", + description: `Double-click at the given coordinates. Selects a word in most text editors. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + text: clickModifierText, + }, + required: ["coordinate"], + }, + }, + + { + name: "triple_click", + description: `Triple-click at the given coordinates. Selects a line in most text editors. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + text: clickModifierText, + }, + required: ["coordinate"], + }, + }, + + { + name: "right_click", + description: `Right-click at the given coordinates. Opens a context menu in most applications. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + text: clickModifierText, + }, + required: ["coordinate"], + }, + }, + + { + name: "middle_click", + description: `Middle-click (scroll-wheel click) at the given coordinates. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + text: clickModifierText, + }, + required: ["coordinate"], + }, + }, + + { + name: "type", + description: `Type text into whatever currently has keyboard focus. ${FRONTMOST_GATE_DESC} Newlines are supported. For keyboard shortcuts use \`key\` instead.`, + inputSchema: { + type: "object" as const, + properties: { + text: { type: "string", description: "Text to type." }, + }, + required: ["text"], + }, + }, + + { + name: "key", + description: + `Press a key or key combination (e.g. "return", "escape", "cmd+a", "ctrl+shift+tab"). ${FRONTMOST_GATE_DESC} ` + + "System-level combos (quit app, switch app, lock screen) require the `systemKeyCombos` grant — without it they return an error. All other combos work.", + inputSchema: { + type: "object" as const, + properties: { + text: { + type: "string", + description: 'Modifiers joined with "+", e.g. "cmd+shift+a".', + }, + repeat: { + type: "integer", + minimum: 1, + maximum: 100, + description: "Number of times to repeat the key press. Default is 1.", + }, + }, + required: ["text"], + }, + }, + + { + name: "scroll", + description: `Scroll at the given coordinates. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + scroll_direction: { + type: "string", + enum: ["up", "down", "left", "right"], + description: "Direction to scroll.", + }, + scroll_amount: { + type: "integer", + minimum: 0, + maximum: 100, + description: "Number of scroll ticks.", + }, + }, + required: ["coordinate", "scroll_direction", "scroll_amount"], + }, + }, + + { + name: "left_click_drag", + description: `Press, move to target, and release. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: { + ...coordinateTuple, + description: `(x, y) end point: ${coord.x}`, + }, + start_coordinate: { + ...coordinateTuple, + description: `(x, y) start point. If omitted, drags from the current cursor position. ${coord.x}`, + }, + }, + required: ["coordinate"], + }, + }, + + { + name: "mouse_move", + description: `Move the mouse cursor without clicking. Useful for triggering hover states. ${FRONTMOST_GATE_DESC}`, + inputSchema: { + type: "object" as const, + properties: { + coordinate: coordinateTuple, + }, + required: ["coordinate"], + }, + }, + + { + name: "open_application", + description: + "Bring an application to the front, launching it if necessary. The target application must already be in the session allowlist — call request_access first.", + inputSchema: { + type: "object" as const, + properties: { + app: { + type: "string", + description: + "Display name (e.g. \"Slack\") or bundle identifier (e.g. \"com.tinyspeck.slackmacgap\").", + }, + }, + required: ["app"], + }, + }, + + { + name: "switch_display", + description: + "Switch which monitor subsequent screenshots capture. Use this when the " + + "application you need is on a different monitor than the one shown. " + + "The screenshot tool tells you which monitor it captured and lists " + + "other attached monitors by name — pass one of those names here. " + + "After switching, call screenshot to see the new monitor. " + + 'Pass "auto" to return to automatic monitor selection.', + inputSchema: { + type: "object" as const, + properties: { + display: { + type: "string", + description: + 'Monitor name from the screenshot note (e.g. "Built-in Retina Display", ' + + '"LG UltraFine"), or "auto" to re-enable automatic selection.', + }, + }, + required: ["display"], + }, + }, + + { + name: "list_granted_applications", + description: + "List the applications currently in the session allowlist, plus the active grant flags and coordinate mode. No side effects.", + inputSchema: { + type: "object" as const, + properties: {}, + required: [], + }, + }, + + { + name: "read_clipboard", + description: + "Read the current clipboard contents as text. Requires the `clipboardRead` grant.", + inputSchema: { + type: "object" as const, + properties: {}, + required: [], + }, + }, + + { + name: "write_clipboard", + description: + "Write text to the clipboard. Requires the `clipboardWrite` grant.", + inputSchema: { + type: "object" as const, + properties: { + text: { type: "string" }, + }, + required: ["text"], + }, + }, + + { + name: "wait", + description: "Wait for a specified duration.", + inputSchema: { + type: "object" as const, + properties: { + duration: { + type: "number", + description: "Duration in seconds (0–100).", + }, + }, + required: ["duration"], + }, + }, + + { + name: "cursor_position", + description: + "Get the current mouse cursor position. Returns image-pixel coordinates relative to the most recent screenshot, or logical points if no screenshot has been taken.", + inputSchema: { + type: "object" as const, + properties: {}, + required: [], + }, + }, + + { + name: "hold_key", + description: + `Press and hold a key or key combination for the specified duration, then release. ${FRONTMOST_GATE_DESC} ` + + "System-level combos require the `systemKeyCombos` grant.", + inputSchema: { + type: "object" as const, + properties: { + text: { + type: "string", + description: 'Key or chord to hold, e.g. "space", "shift+down".', + }, + duration: { + type: "number", + description: "Duration in seconds (0–100).", + }, + }, + required: ["text", "duration"], + }, + }, + + { + name: "left_mouse_down", + description: + `Press the left mouse button at the current cursor position and leave it held. ${FRONTMOST_GATE_DESC} ` + + "Use mouse_move first to position the cursor. Call left_mouse_up to release. Errors if the button is already held.", + inputSchema: { + type: "object" as const, + properties: {}, + required: [], + }, + }, + + { + name: "left_mouse_up", + description: + `Release the left mouse button at the current cursor position. ${FRONTMOST_GATE_DESC} ` + + "Pairs with left_mouse_down. Safe to call even if the button is not currently held.", + inputSchema: { + type: "object" as const, + properties: {}, + required: [], + }, + }, + + { + name: "computer_batch", + description: + "Execute a sequence of actions in ONE tool call. Each individual tool call requires a model→API round trip (seconds); " + + "batching a predictable sequence eliminates all but one. Use this whenever you can predict the outcome of several actions ahead — " + + "e.g. click a field, type into it, press Return. Actions execute sequentially and stop on the first error. " + + `${FRONTMOST_GATE_DESC} The frontmost check runs before EACH action inside the batch — if an action opens a non-allowed app, the next action's gate fires and the batch stops there. ` + + "Mid-batch screenshot actions are allowed for inspection but coordinates in subsequent clicks always refer to the PRE-BATCH full-screen screenshot.", + inputSchema: { + type: "object" as const, + properties: { + actions: { + type: "array", + minItems: 1, + items: BATCH_ACTION_ITEM_SCHEMA, + description: + 'List of actions. Example: [{"action":"left_click","coordinate":[100,200]},{"action":"type","text":"hello"},{"action":"key","text":"Return"}]', + }, + }, + required: ["actions"], + }, + }, + + ...(caps.teachMode ? buildTeachTools(coord, installedAppsHint) : []), + ]; +} + +/** + * Teach-mode tools. Split out so the spread above stays a single expression; + * takes `coord` so `teach_step.anchor`'s description uses the same + * frozen coordinate-mode phrasing as click coords, and `installedAppsHint` + * so `request_teach_access.apps` gets the same enumeration as + * `request_access.apps` (same resolution path → same hint). + */ +function buildTeachTools( + coord: { x: string; y: string }, + installedAppsHint: string, +): Tool[] { + // Shared between teach_step (top-level) and teach_batch (inside steps[] + // items). Depends on coord, so it lives inside this factory. + const teachStepProperties = { + explanation: { + type: "string", + description: + "Tooltip body text. Explain what the user is looking at and why it matters. " + + "This is the ONLY place the user sees your words — be complete but concise.", + }, + next_preview: { + type: "string", + description: + "One line describing exactly what will happen when the user clicks Next. " + + 'Example: "Next: I\'ll click Create Bucket and type the name." ' + + "Shown below the explanation in a smaller font.", + }, + anchor: { + type: "array", + items: { type: "number" }, + minItems: 2, + maxItems: 2, + description: + `(x, y) — where the tooltip arrow points. ${coord.x} ` + + "Omit to center the tooltip with no arrow (for general-context steps).", + }, + actions: { + type: "array", + // Empty allowed — "read this, click Next" steps. + items: BATCH_ACTION_ITEM_SCHEMA, + description: + "Actions to execute when the user clicks Next. Same item schema as computer_batch.actions. " + + "Empty array is valid for purely explanatory steps. Actions run sequentially and stop on first error.", + }, + } as const; + + return [ + { + name: "request_teach_access", + description: + "Request permission to guide the user through a task step-by-step with on-screen tooltips. " + + "Use this INSTEAD OF request_access when the user wants to LEARN how to do something " + + '(phrases like "teach me", "walk me through", "show me how", "help me learn"). ' + + "On approval the main Claude window hides and a fullscreen tooltip overlay appears. " + + "You then call teach_step repeatedly; each call shows one tooltip and waits for the user to click Next. " + + "Same app-allowlist semantics as request_access, but no clipboard/system-key flags. " + + "Teach mode ends automatically when your turn ends.", + inputSchema: { + type: "object" as const, + properties: { + apps: { + type: "array", + items: { type: "string" }, + description: + 'Application display names (e.g. "Slack", "Calendar") or bundle identifiers. Resolved case-insensitively against installed apps.' + + installedAppsHint, + }, + reason: { + type: "string", + description: + 'What you will be teaching. Shown in the approval dialog as "Claude wants to guide you through {reason}". Keep it short and task-focused.', + }, + }, + required: ["apps", "reason"], + }, + }, + + { + name: "teach_step", + description: + "Show one guided-tour tooltip and wait for the user to click Next. On Next, execute the actions, " + + "take a fresh screenshot, and return both — you do NOT need a separate screenshot call between steps. " + + "The returned image shows the state after your actions ran; anchor the next teach_step against it. " + + "IMPORTANT — the user only sees the tooltip during teach mode. Put ALL narration in `explanation`. " + + "Text you emit outside teach_step calls is NOT visible until teach mode ends. " + + "Pack as many actions as possible into each step's `actions` array — the user waits through " + + "the whole round trip between clicks, so one step that fills a form beats five steps that fill one field each. " + + "Returns {exited:true} if the user clicks Exit — do not call teach_step again after that. " + + "Take an initial screenshot before your FIRST teach_step to anchor it.", + inputSchema: { + type: "object" as const, + properties: teachStepProperties, + required: ["explanation", "next_preview", "actions"], + }, + }, + + { + name: "teach_batch", + description: + "Queue multiple teach steps in one tool call. Parallels computer_batch: " + + "N steps → one model↔API round trip instead of N. Each step still shows a tooltip " + + "and waits for the user's Next click, but YOU aren't waiting for a round trip between steps. " + + "You can call teach_batch multiple times in one tour — treat each batch as one predictable " + + "SEGMENT (typically: all the steps on one page). The returned screenshot shows the state " + + "after the batch's final actions; anchor the NEXT teach_batch against it. " + + "WITHIN a batch, all anchors and click coordinates refer to the PRE-BATCH screenshot " + + "(same invariant as computer_batch) — for steps 2+ in a batch, either omit anchor " + + "(centered tooltip) or target elements you know won't have moved. " + + "Good pattern: batch 5 tooltips on page A (last step navigates) → read returned screenshot → " + + "batch 3 tooltips on page B → done. " + + "Returns {exited:true, stepsCompleted:N} if the user clicks Exit — do NOT call again after that; " + + "{stepsCompleted, stepFailed, ...} if an action errors mid-batch; " + + "otherwise {stepsCompleted, results:[...]} plus a final screenshot. " + + "Fall back to individual teach_step calls when you need to react to each intermediate screenshot.", + inputSchema: { + type: "object" as const, + properties: { + steps: { + type: "array", + minItems: 1, + items: { + type: "object", + properties: teachStepProperties, + required: ["explanation", "next_preview", "actions"], + }, + description: + "Ordered steps. Validated upfront — a typo in step 5 errors before any tooltip shows.", + }, + }, + required: ["steps"], + }, + }, + ]; +} diff --git a/_all-in-one-upload/cc-haha/src/vim/types.ts b/_all-in-one-upload/cc-haha/src/vim/types.ts new file mode 100644 index 0000000..6ce950d --- /dev/null +++ b/_all-in-one-upload/cc-haha/src/vim/types.ts @@ -0,0 +1,199 @@ +/** + * Vim Mode State Machine Types + * + * This file defines the complete state machine for vim input handling. + * The types ARE the documentation - reading them tells you how the system works. + * + * State Diagram: + * ``` + * VimState + * ┌──────────────────────────────┬──────────────────────────────────────┐ + * │ INSERT │ NORMAL │ + * │ (tracks insertedText) │ (CommandState machine) │ + * │ │ │ + * │ │ idle ──┬─[d/c/y]──► operator │ + * │ │ ├─[1-9]────► count │ + * │ │ ├─[fFtT]───► find │ + * │ │ ├─[g]──────► g │ + * │ │ ├─[r]──────► replace │ + * │ │ └─[><]─────► indent │ + * │ │ │ + * │ │ operator ─┬─[motion]──► execute │ + * │ │ ├─[0-9]────► operatorCount│ + * │ │ ├─[ia]─────► operatorTextObj + * │ │ └─[fFtT]───► operatorFind │ + * └──────────────────────────────┴──────────────────────────────────────┘ + * ``` + */ + +// ============================================================================ +// Core Types +// ============================================================================ + +export type Operator = 'delete' | 'change' | 'yank' + +export type FindType = 'f' | 'F' | 't' | 'T' + +export type TextObjScope = 'inner' | 'around' + +// ============================================================================ +// State Machine Types +// ============================================================================ + +/** + * Complete vim state. Mode determines what data is tracked. + * + * INSERT mode: Track text being typed (for dot-repeat) + * NORMAL mode: Track command being parsed (state machine) + */ +export type VimState = + | { mode: 'INSERT'; insertedText: string } + | { mode: 'NORMAL'; command: CommandState } + +/** + * Command state machine for NORMAL mode. + * + * Each state knows exactly what input it's waiting for. + * TypeScript ensures exhaustive handling in switches. + */ +export type CommandState = + | { type: 'idle' } + | { type: 'count'; digits: string } + | { type: 'operator'; op: Operator; count: number } + | { type: 'operatorCount'; op: Operator; count: number; digits: string } + | { type: 'operatorFind'; op: Operator; count: number; find: FindType } + | { + type: 'operatorTextObj' + op: Operator + count: number + scope: TextObjScope + } + | { type: 'find'; find: FindType; count: number } + | { type: 'g'; count: number } + | { type: 'operatorG'; op: Operator; count: number } + | { type: 'replace'; count: number } + | { type: 'indent'; dir: '>' | '<'; count: number } + +/** + * Persistent state that survives across commands. + * This is the "memory" of vim - what gets recalled for repeats and pastes. + */ +export type PersistentState = { + lastChange: RecordedChange | null + lastFind: { type: FindType; char: string } | null + register: string + registerIsLinewise: boolean +} + +/** + * Recorded change for dot-repeat. + * Captures everything needed to replay a command. + */ +export type RecordedChange = + | { type: 'insert'; text: string } + | { + type: 'operator' + op: Operator + motion: string + count: number + } + | { + type: 'operatorTextObj' + op: Operator + objType: string + scope: TextObjScope + count: number + } + | { + type: 'operatorFind' + op: Operator + find: FindType + char: string + count: number + } + | { type: 'replace'; char: string; count: number } + | { type: 'x'; count: number } + | { type: 'toggleCase'; count: number } + | { type: 'indent'; dir: '>' | '<'; count: number } + | { type: 'openLine'; direction: 'above' | 'below' } + | { type: 'join'; count: number } + +// ============================================================================ +// Key Groups - Named constants, no magic strings +// ============================================================================ + +export const OPERATORS = { + d: 'delete', + c: 'change', + y: 'yank', +} as const satisfies Record + +export function isOperatorKey(key: string): key is keyof typeof OPERATORS { + return key in OPERATORS +} + +export const SIMPLE_MOTIONS = new Set([ + 'h', + 'l', + 'j', + 'k', // Basic movement + 'w', + 'b', + 'e', + 'W', + 'B', + 'E', // Word motions + '0', + '^', + '$', // Line positions +]) + +export const FIND_KEYS = new Set(['f', 'F', 't', 'T']) + +export const TEXT_OBJ_SCOPES = { + i: 'inner', + a: 'around', +} as const satisfies Record + +export function isTextObjScopeKey( + key: string, +): key is keyof typeof TEXT_OBJ_SCOPES { + return key in TEXT_OBJ_SCOPES +} + +export const TEXT_OBJ_TYPES = new Set([ + 'w', + 'W', // Word/WORD + '"', + "'", + '`', // Quotes + '(', + ')', + 'b', // Parens + '[', + ']', // Brackets + '{', + '}', + 'B', // Braces + '<', + '>', // Angle brackets +]) + +export const MAX_VIM_COUNT = 10000 + +// ============================================================================ +// State Factories +// ============================================================================ + +export function createInitialVimState(): VimState { + return { mode: 'INSERT', insertedText: '' } +} + +export function createInitialPersistentState(): PersistentState { + return { + lastChange: null, + lastFind: null, + register: '', + registerIsLinewise: false, + } +} diff --git a/_all-in-one-upload/new-api/LICENSE b/_all-in-one-upload/new-api/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/_all-in-one-upload/new-api/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/_all-in-one-upload/new-api/bin/migration_v0.3-v0.4.sql b/_all-in-one-upload/new-api/bin/migration_v0.3-v0.4.sql new file mode 100644 index 0000000..e6103c2 --- /dev/null +++ b/_all-in-one-upload/new-api/bin/migration_v0.3-v0.4.sql @@ -0,0 +1,17 @@ +INSERT INTO abilities (`group`, model, channel_id, enabled) +SELECT c.`group`, m.model, c.id, 1 +FROM channels c +CROSS JOIN ( + SELECT 'gpt-3.5-turbo' AS model UNION ALL + SELECT 'gpt-3.5-turbo-0301' AS model UNION ALL + SELECT 'gpt-4' AS model UNION ALL + SELECT 'gpt-4-0314' AS model +) AS m +WHERE c.status = 1 + AND NOT EXISTS ( + SELECT 1 + FROM abilities a + WHERE a.`group` = c.`group` + AND a.model = m.model + AND a.channel_id = c.id +); diff --git a/_all-in-one-upload/new-api/common/endpoint_type.go b/_all-in-one-upload/new-api/common/endpoint_type.go new file mode 100644 index 0000000..a5e2ff8 --- /dev/null +++ b/_all-in-one-upload/new-api/common/endpoint_type.go @@ -0,0 +1,45 @@ +package common + +import "github.com/QuantumNous/new-api/constant" + +// GetEndpointTypesByChannelType 获取渠道最优先端点类型(所有的渠道都支持 OpenAI 端点) +func GetEndpointTypesByChannelType(channelType int, modelName string) []constant.EndpointType { + var endpointTypes []constant.EndpointType + switch channelType { + case constant.ChannelTypeJina: + endpointTypes = []constant.EndpointType{constant.EndpointTypeJinaRerank} + //case constant.ChannelTypeMidjourney, constant.ChannelTypeMidjourneyPlus: + // endpointTypes = []constant.EndpointType{constant.EndpointTypeMidjourney} + //case constant.ChannelTypeSunoAPI: + // endpointTypes = []constant.EndpointType{constant.EndpointTypeSuno} + //case constant.ChannelTypeKling: + // endpointTypes = []constant.EndpointType{constant.EndpointTypeKling} + //case constant.ChannelTypeJimeng: + // endpointTypes = []constant.EndpointType{constant.EndpointTypeJimeng} + case constant.ChannelTypeAws: + fallthrough + case constant.ChannelTypeAnthropic: + endpointTypes = []constant.EndpointType{constant.EndpointTypeAnthropic, constant.EndpointTypeOpenAI} + case constant.ChannelTypeVertexAi: + fallthrough + case constant.ChannelTypeGemini: + endpointTypes = []constant.EndpointType{constant.EndpointTypeGemini, constant.EndpointTypeOpenAI} + case constant.ChannelTypeOpenRouter: // OpenRouter 只支持 OpenAI 端点 + endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI} + case constant.ChannelTypeXai: + endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI, constant.EndpointTypeOpenAIResponse} + case constant.ChannelTypeSora: + endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAIVideo} + default: + if IsOpenAIResponseOnlyModel(modelName) { + endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAIResponse} + } else { + endpointTypes = []constant.EndpointType{constant.EndpointTypeOpenAI} + } + } + if IsImageGenerationModel(modelName) { + // add to first + endpointTypes = append([]constant.EndpointType{constant.EndpointTypeImageGeneration}, endpointTypes...) + } + return endpointTypes +} diff --git a/_all-in-one-upload/new-api/common/go-channel.go b/_all-in-one-upload/new-api/common/go-channel.go new file mode 100644 index 0000000..f9168fc --- /dev/null +++ b/_all-in-one-upload/new-api/common/go-channel.go @@ -0,0 +1,53 @@ +package common + +import ( + "time" +) + +func SafeSendBool(ch chan bool, value bool) (closed bool) { + defer func() { + // Recover from panic if one occured. A panic would mean the channel was closed. + if recover() != nil { + closed = true + } + }() + + // This will panic if the channel is closed. + ch <- value + + // If the code reaches here, then the channel was not closed. + return false +} + +func SafeSendString(ch chan string, value string) (closed bool) { + defer func() { + // Recover from panic if one occured. A panic would mean the channel was closed. + if recover() != nil { + closed = true + } + }() + + // This will panic if the channel is closed. + ch <- value + + // If the code reaches here, then the channel was not closed. + return false +} + +// SafeSendStringTimeout send, return true, else return false +func SafeSendStringTimeout(ch chan string, value string, timeout int) (closed bool) { + defer func() { + // Recover from panic if one occured. A panic would mean the channel was closed. + if recover() != nil { + closed = false + } + }() + + // This will panic if the channel is closed. + select { + case ch <- value: + return true + case <-time.After(time.Duration(timeout) * time.Second): + return false + } +} diff --git a/_all-in-one-upload/new-api/common/str.go b/_all-in-one-upload/new-api/common/str.go new file mode 100644 index 0000000..71391f7 --- /dev/null +++ b/_all-in-one-upload/new-api/common/str.go @@ -0,0 +1,254 @@ +package common + +import ( + "encoding/base64" + "encoding/json" + "net/url" + "regexp" + "strconv" + "strings" + "unsafe" + + "github.com/samber/lo" +) + +var ( + maskURLPattern = regexp.MustCompile(`(http|https)://[^\s/$.?#].[^\s]*`) + maskDomainPattern = regexp.MustCompile(`\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}\b`) + maskIPPattern = regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}\b`) + // maskApiKeyPattern matches patterns like 'api_key:xxx' or "api_key:xxx" to mask the API key value + maskApiKeyPattern = regexp.MustCompile(`(['"]?)api_key:([^\s'"]+)(['"]?)`) +) + +func GetStringIfEmpty(str string, defaultValue string) string { + if str == "" { + return defaultValue + } + return str +} + +func GetRandomString(length int) string { + if length <= 0 { + return "" + } + return lo.RandomString(length, lo.AlphanumericCharset) +} + +func MapToJsonStr(m map[string]interface{}) string { + bytes, err := json.Marshal(m) + if err != nil { + return "" + } + return string(bytes) +} + +func StrToMap(str string) (map[string]interface{}, error) { + m := make(map[string]interface{}) + err := Unmarshal([]byte(str), &m) + if err != nil { + return nil, err + } + return m, nil +} + +func StrToJsonArray(str string) ([]interface{}, error) { + var js []interface{} + err := json.Unmarshal([]byte(str), &js) + if err != nil { + return nil, err + } + return js, nil +} + +func IsJsonArray(str string) bool { + var js []interface{} + return json.Unmarshal([]byte(str), &js) == nil +} + +func IsJsonObject(str string) bool { + var js map[string]interface{} + return json.Unmarshal([]byte(str), &js) == nil +} + +func String2Int(str string) int { + num, err := strconv.Atoi(str) + if err != nil { + return 0 + } + return num +} + +func StringsContains(strs []string, str string) bool { + for _, s := range strs { + if s == str { + return true + } + } + return false +} + +// StringToByteSlice []byte only read, panic on append +func StringToByteSlice(s string) []byte { + tmp1 := (*[2]uintptr)(unsafe.Pointer(&s)) + tmp2 := [3]uintptr{tmp1[0], tmp1[1], tmp1[1]} + return *(*[]byte)(unsafe.Pointer(&tmp2)) +} + +func EncodeBase64(str string) string { + return base64.StdEncoding.EncodeToString([]byte(str)) +} + +func GetJsonString(data any) string { + if data == nil { + return "" + } + b, _ := json.Marshal(data) + return string(b) +} + +// NormalizeBillingPreference clamps the billing preference to valid values. +func NormalizeBillingPreference(pref string) string { + switch strings.TrimSpace(pref) { + case "subscription_first", "wallet_first", "subscription_only", "wallet_only": + return strings.TrimSpace(pref) + default: + return "subscription_first" + } +} + +// MaskEmail masks a user email to prevent PII leakage in logs +// Returns "***masked***" if email is empty, otherwise shows only the domain part +func MaskEmail(email string) string { + if email == "" { + return "***masked***" + } + + // Find the @ symbol + atIndex := strings.Index(email, "@") + if atIndex == -1 { + // No @ symbol found, return masked + return "***masked***" + } + + // Return only the domain part with @ symbol + return "***@" + email[atIndex+1:] +} + +// maskHostTail returns the tail parts of a domain/host that should be preserved. +// It keeps 2 parts for likely country-code TLDs (e.g., co.uk, com.cn), otherwise keeps only the TLD. +func maskHostTail(parts []string) []string { + if len(parts) < 2 { + return parts + } + lastPart := parts[len(parts)-1] + secondLastPart := parts[len(parts)-2] + if len(lastPart) == 2 && len(secondLastPart) <= 3 { + // Likely country code TLD like co.uk, com.cn + return []string{secondLastPart, lastPart} + } + return []string{lastPart} +} + +// maskHostForURL collapses subdomains and keeps only masked prefix + preserved tail. +// Example: api.openai.com -> ***.com, sub.domain.co.uk -> ***.co.uk +func maskHostForURL(host string) string { + parts := strings.Split(host, ".") + if len(parts) < 2 { + return "***" + } + tail := maskHostTail(parts) + return "***." + strings.Join(tail, ".") +} + +// maskHostForPlainDomain masks a plain domain and reflects subdomain depth with multiple ***. +// Example: openai.com -> ***.com, api.openai.com -> ***.***.com, sub.domain.co.uk -> ***.***.co.uk +func maskHostForPlainDomain(domain string) string { + parts := strings.Split(domain, ".") + if len(parts) < 2 { + return domain + } + tail := maskHostTail(parts) + numStars := len(parts) - len(tail) + if numStars < 1 { + numStars = 1 + } + stars := strings.TrimSuffix(strings.Repeat("***.", numStars), ".") + return stars + "." + strings.Join(tail, ".") +} + +// MaskSensitiveInfo masks sensitive information like URLs, IPs, and domain names in a string +// Example: +// http://example.com -> http://***.com +// https://api.test.org/v1/users/123?key=secret -> https://***.org/***/***/?key=*** +// https://sub.domain.co.uk/path/to/resource -> https://***.co.uk/***/*** +// 192.168.1.1 -> ***.***.***.*** +// openai.com -> ***.com +// www.openai.com -> ***.***.com +// api.openai.com -> ***.***.com +func MaskSensitiveInfo(str string) string { + // Mask URLs + str = maskURLPattern.ReplaceAllStringFunc(str, func(urlStr string) string { + u, err := url.Parse(urlStr) + if err != nil { + return urlStr + } + + host := u.Host + if host == "" { + return urlStr + } + + // Mask host with unified logic + maskedHost := maskHostForURL(host) + + result := u.Scheme + "://" + maskedHost + + // Mask path + if u.Path != "" && u.Path != "/" { + pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") + maskedPathParts := make([]string, len(pathParts)) + for i := range pathParts { + if pathParts[i] != "" { + maskedPathParts[i] = "***" + } + } + if len(maskedPathParts) > 0 { + result += "/" + strings.Join(maskedPathParts, "/") + } + } else if u.Path == "/" { + result += "/" + } + + // Mask query parameters + if u.RawQuery != "" { + values, err := url.ParseQuery(u.RawQuery) + if err != nil { + // If can't parse query, just mask the whole query string + result += "?***" + } else { + maskedParams := make([]string, 0, len(values)) + for key := range values { + maskedParams = append(maskedParams, key+"=***") + } + if len(maskedParams) > 0 { + result += "?" + strings.Join(maskedParams, "&") + } + } + } + + return result + }) + + // Mask domain names without protocol (like openai.com, www.openai.com) + str = maskDomainPattern.ReplaceAllStringFunc(str, func(domain string) string { + return maskHostForPlainDomain(domain) + }) + + // Mask IP addresses + str = maskIPPattern.ReplaceAllString(str, "***.***.***.***") + + // Mask API keys (e.g., "api_key:AIzaSyAAAaUooTUni8AdaOkSRMda30n_Q4vrV70" -> "api_key:***") + str = maskApiKeyPattern.ReplaceAllString(str, "${1}api_key:***${3}") + + return str +} diff --git a/_all-in-one-upload/new-api/common/system_monitor_windows.go b/_all-in-one-upload/new-api/common/system_monitor_windows.go new file mode 100644 index 0000000..7db7667 --- /dev/null +++ b/_all-in-one-upload/new-api/common/system_monitor_windows.go @@ -0,0 +1,50 @@ +//go:build windows + +package common + +import ( + "os" + "syscall" + "unsafe" +) + +// GetDiskSpaceInfo 获取缓存目录所在磁盘的空间信息 (Windows) +func GetDiskSpaceInfo() DiskSpaceInfo { + cachePath := GetDiskCachePath() + if cachePath == "" { + cachePath = os.TempDir() + } + + info := DiskSpaceInfo{} + + kernel32 := syscall.NewLazyDLL("kernel32.dll") + getDiskFreeSpaceEx := kernel32.NewProc("GetDiskFreeSpaceExW") + + var freeBytesAvailable, totalBytes, totalFreeBytes uint64 + + pathPtr, err := syscall.UTF16PtrFromString(cachePath) + if err != nil { + return info + } + + ret, _, _ := getDiskFreeSpaceEx.Call( + uintptr(unsafe.Pointer(pathPtr)), + uintptr(unsafe.Pointer(&freeBytesAvailable)), + uintptr(unsafe.Pointer(&totalBytes)), + uintptr(unsafe.Pointer(&totalFreeBytes)), + ) + + if ret == 0 { + return info + } + + info.Total = totalBytes + info.Free = freeBytesAvailable + info.Used = totalBytes - totalFreeBytes + + if info.Total > 0 { + info.UsedPercent = float64(info.Used) / float64(info.Total) * 100 + } + + return info +} diff --git a/_all-in-one-upload/new-api/constant/context_key.go b/_all-in-one-upload/new-api/constant/context_key.go new file mode 100644 index 0000000..c28ad20 --- /dev/null +++ b/_all-in-one-upload/new-api/constant/context_key.go @@ -0,0 +1,69 @@ +package constant + +type ContextKey string + +const ( + ContextKeyTokenCountMeta ContextKey = "token_count_meta" + ContextKeyPromptTokens ContextKey = "prompt_tokens" + ContextKeyEstimatedTokens ContextKey = "estimated_tokens" + + ContextKeyOriginalModel ContextKey = "original_model" + ContextKeyRequestStartTime ContextKey = "request_start_time" + + /* token related keys */ + ContextKeyTokenUnlimited ContextKey = "token_unlimited_quota" + ContextKeyTokenKey ContextKey = "token_key" + ContextKeyTokenId ContextKey = "token_id" + ContextKeyTokenGroup ContextKey = "token_group" + ContextKeyTokenSpecificChannelId ContextKey = "specific_channel_id" + ContextKeyTokenModelLimitEnabled ContextKey = "token_model_limit_enabled" + ContextKeyTokenModelLimit ContextKey = "token_model_limit" + ContextKeyTokenCrossGroupRetry ContextKey = "token_cross_group_retry" + + /* channel related keys */ + ContextKeyChannelId ContextKey = "channel_id" + ContextKeyChannelName ContextKey = "channel_name" + ContextKeyChannelCreateTime ContextKey = "channel_create_time" + ContextKeyChannelBaseUrl ContextKey = "base_url" + ContextKeyChannelType ContextKey = "channel_type" + ContextKeyChannelSetting ContextKey = "channel_setting" + ContextKeyChannelOtherSetting ContextKey = "channel_other_setting" + ContextKeyChannelParamOverride ContextKey = "param_override" + ContextKeyChannelHeaderOverride ContextKey = "header_override" + ContextKeyChannelOrganization ContextKey = "channel_organization" + ContextKeyChannelAutoBan ContextKey = "auto_ban" + ContextKeyChannelModelMapping ContextKey = "model_mapping" + ContextKeyChannelStatusCodeMapping ContextKey = "status_code_mapping" + ContextKeyChannelIsMultiKey ContextKey = "channel_is_multi_key" + ContextKeyChannelMultiKeyIndex ContextKey = "channel_multi_key_index" + ContextKeyChannelKey ContextKey = "channel_key" + + ContextKeyAutoGroup ContextKey = "auto_group" + ContextKeyAutoGroupIndex ContextKey = "auto_group_index" + ContextKeyAutoGroupRetryIndex ContextKey = "auto_group_retry_index" + + /* user related keys */ + ContextKeyUserId ContextKey = "id" + ContextKeyUserSetting ContextKey = "user_setting" + ContextKeyUserQuota ContextKey = "user_quota" + ContextKeyUserStatus ContextKey = "user_status" + ContextKeyUserEmail ContextKey = "user_email" + ContextKeyUserGroup ContextKey = "user_group" + ContextKeyUsingGroup ContextKey = "group" + ContextKeyUserName ContextKey = "username" + + ContextKeyLocalCountTokens ContextKey = "local_count_tokens" + + ContextKeySystemPromptOverride ContextKey = "system_prompt_override" + + // ContextKeyFileSourcesToCleanup stores file sources that need cleanup when request ends + ContextKeyFileSourcesToCleanup ContextKey = "file_sources_to_cleanup" + + // ContextKeyAdminRejectReason stores an admin-only reject/block reason extracted from upstream responses. + // It is not returned to end users, but can be persisted into consume/error logs for debugging. + ContextKeyAdminRejectReason ContextKey = "admin_reject_reason" + + // ContextKeyLanguage stores the user's language preference for i18n + ContextKeyLanguage ContextKey = "language" + ContextKeyIsStream ContextKey = "is_stream" +) diff --git a/_all-in-one-upload/new-api/controller/channel_affinity_cache.go b/_all-in-one-upload/new-api/controller/channel_affinity_cache.go new file mode 100644 index 0000000..a72b04b --- /dev/null +++ b/_all-in-one-upload/new-api/controller/channel_affinity_cache.go @@ -0,0 +1,88 @@ +package controller + +import ( + "net/http" + "strings" + + "github.com/QuantumNous/new-api/service" + "github.com/gin-gonic/gin" +) + +func GetChannelAffinityCacheStats(c *gin.Context) { + stats := service.GetChannelAffinityCacheStats() + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": stats, + }) +} + +func ClearChannelAffinityCache(c *gin.Context) { + all := strings.TrimSpace(c.Query("all")) + ruleName := strings.TrimSpace(c.Query("rule_name")) + + if all == "true" { + deleted := service.ClearChannelAffinityCacheAll() + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": gin.H{ + "deleted": deleted, + }, + }) + return + } + + if ruleName == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "message": "缺少参数:rule_name,或使用 all=true 清空全部", + }) + return + } + + deleted, err := service.ClearChannelAffinityCacheByRuleName(ruleName) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "message": err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": gin.H{ + "deleted": deleted, + }, + }) +} + +func GetChannelAffinityUsageCacheStats(c *gin.Context) { + ruleName := strings.TrimSpace(c.Query("rule_name")) + usingGroup := strings.TrimSpace(c.Query("using_group")) + keyFp := strings.TrimSpace(c.Query("key_fp")) + + if ruleName == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "message": "missing param: rule_name", + }) + return + } + if keyFp == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "message": "missing param: key_fp", + }) + return + } + + stats := service.GetChannelAffinityUsageCacheStats(ruleName, usingGroup, keyFp) + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": stats, + }) +} diff --git a/_all-in-one-upload/new-api/controller/codex_oauth.go b/_all-in-one-upload/new-api/controller/codex_oauth.go new file mode 100644 index 0000000..de9743a --- /dev/null +++ b/_all-in-one-upload/new-api/controller/codex_oauth.go @@ -0,0 +1,247 @@ +package controller + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/model" + "github.com/QuantumNous/new-api/relay/channel/codex" + "github.com/QuantumNous/new-api/service" + + "github.com/gin-contrib/sessions" + "github.com/gin-gonic/gin" +) + +type codexOAuthCompleteRequest struct { + Input string `json:"input"` +} + +func codexOAuthSessionKey(channelID int, field string) string { + return fmt.Sprintf("codex_oauth_%s_%d", field, channelID) +} + +func parseCodexAuthorizationInput(input string) (code string, state string, err error) { + v := strings.TrimSpace(input) + if v == "" { + return "", "", errors.New("empty input") + } + if strings.Contains(v, "#") { + parts := strings.SplitN(v, "#", 2) + code = strings.TrimSpace(parts[0]) + state = strings.TrimSpace(parts[1]) + return code, state, nil + } + if strings.Contains(v, "code=") { + u, parseErr := url.Parse(v) + if parseErr == nil { + q := u.Query() + code = strings.TrimSpace(q.Get("code")) + state = strings.TrimSpace(q.Get("state")) + return code, state, nil + } + q, parseErr := url.ParseQuery(v) + if parseErr == nil { + code = strings.TrimSpace(q.Get("code")) + state = strings.TrimSpace(q.Get("state")) + return code, state, nil + } + } + + code = v + return code, "", nil +} + +func StartCodexOAuth(c *gin.Context) { + startCodexOAuthWithChannelID(c, 0) +} + +func StartCodexOAuthForChannel(c *gin.Context) { + channelID, err := strconv.Atoi(c.Param("id")) + if err != nil { + common.ApiError(c, fmt.Errorf("invalid channel id: %w", err)) + return + } + startCodexOAuthWithChannelID(c, channelID) +} + +func startCodexOAuthWithChannelID(c *gin.Context, channelID int) { + if channelID > 0 { + ch, err := model.GetChannelById(channelID, false) + if err != nil { + common.ApiError(c, err) + return + } + if ch == nil { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "channel not found"}) + return + } + if ch.Type != constant.ChannelTypeCodex { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "channel type is not Codex"}) + return + } + } + + flow, err := service.CreateCodexOAuthAuthorizationFlow() + if err != nil { + common.ApiError(c, err) + return + } + + session := sessions.Default(c) + session.Set(codexOAuthSessionKey(channelID, "state"), flow.State) + session.Set(codexOAuthSessionKey(channelID, "verifier"), flow.Verifier) + session.Set(codexOAuthSessionKey(channelID, "created_at"), time.Now().Unix()) + _ = session.Save() + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": gin.H{ + "authorize_url": flow.AuthorizeURL, + }, + }) +} + +func CompleteCodexOAuth(c *gin.Context) { + completeCodexOAuthWithChannelID(c, 0) +} + +func CompleteCodexOAuthForChannel(c *gin.Context) { + channelID, err := strconv.Atoi(c.Param("id")) + if err != nil { + common.ApiError(c, fmt.Errorf("invalid channel id: %w", err)) + return + } + completeCodexOAuthWithChannelID(c, channelID) +} + +func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) { + req := codexOAuthCompleteRequest{} + if err := c.ShouldBindJSON(&req); err != nil { + common.ApiError(c, err) + return + } + + code, state, err := parseCodexAuthorizationInput(req.Input) + if err != nil { + common.SysError("failed to parse codex authorization input: " + err.Error()) + c.JSON(http.StatusOK, gin.H{"success": false, "message": "解析授权信息失败,请检查输入格式"}) + return + } + if strings.TrimSpace(code) == "" { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "missing authorization code"}) + return + } + if strings.TrimSpace(state) == "" { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "missing state in input"}) + return + } + + channelProxy := "" + if channelID > 0 { + ch, err := model.GetChannelById(channelID, false) + if err != nil { + common.ApiError(c, err) + return + } + if ch == nil { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "channel not found"}) + return + } + if ch.Type != constant.ChannelTypeCodex { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "channel type is not Codex"}) + return + } + channelProxy = ch.GetSetting().Proxy + } + + session := sessions.Default(c) + expectedState, _ := session.Get(codexOAuthSessionKey(channelID, "state")).(string) + verifier, _ := session.Get(codexOAuthSessionKey(channelID, "verifier")).(string) + if strings.TrimSpace(expectedState) == "" || strings.TrimSpace(verifier) == "" { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "oauth flow not started or session expired"}) + return + } + if state != expectedState { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "state mismatch"}) + return + } + + ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second) + defer cancel() + + tokenRes, err := service.ExchangeCodexAuthorizationCodeWithProxy(ctx, code, verifier, channelProxy) + if err != nil { + common.SysError("failed to exchange codex authorization code: " + err.Error()) + c.JSON(http.StatusOK, gin.H{"success": false, "message": "授权码交换失败,请重试"}) + return + } + + accountID, ok := service.ExtractCodexAccountIDFromJWT(tokenRes.AccessToken) + if !ok { + c.JSON(http.StatusOK, gin.H{"success": false, "message": "failed to extract account_id from access_token"}) + return + } + email, _ := service.ExtractEmailFromJWT(tokenRes.AccessToken) + + key := codex.OAuthKey{ + AccessToken: tokenRes.AccessToken, + RefreshToken: tokenRes.RefreshToken, + AccountID: accountID, + LastRefresh: time.Now().Format(time.RFC3339), + Expired: tokenRes.ExpiresAt.Format(time.RFC3339), + Email: email, + Type: "codex", + } + encoded, err := common.Marshal(key) + if err != nil { + common.ApiError(c, err) + return + } + + session.Delete(codexOAuthSessionKey(channelID, "state")) + session.Delete(codexOAuthSessionKey(channelID, "verifier")) + session.Delete(codexOAuthSessionKey(channelID, "created_at")) + _ = session.Save() + + if channelID > 0 { + if err := model.DB.Model(&model.Channel{}).Where("id = ?", channelID).Update("key", string(encoded)).Error; err != nil { + common.ApiError(c, err) + return + } + model.InitChannelCache() + service.ResetProxyClientCache() + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "saved", + "data": gin.H{ + "channel_id": channelID, + "account_id": accountID, + "email": email, + "expires_at": key.Expired, + "last_refresh": key.LastRefresh, + }, + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "generated", + "data": gin.H{ + "key": string(encoded), + "account_id": accountID, + "email": email, + "expires_at": key.Expired, + "last_refresh": key.LastRefresh, + }, + }) +} diff --git a/_all-in-one-upload/new-api/controller/custom_oauth.go b/_all-in-one-upload/new-api/controller/custom_oauth.go new file mode 100644 index 0000000..c21ec79 --- /dev/null +++ b/_all-in-one-upload/new-api/controller/custom_oauth.go @@ -0,0 +1,584 @@ +package controller + +import ( + "context" + "io" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/model" + "github.com/QuantumNous/new-api/oauth" + "github.com/gin-gonic/gin" +) + +// CustomOAuthProviderResponse is the response structure for custom OAuth providers +// It excludes sensitive fields like client_secret +type CustomOAuthProviderResponse struct { + Id int `json:"id"` + Name string `json:"name"` + Slug string `json:"slug"` + Icon string `json:"icon"` + Enabled bool `json:"enabled"` + ClientId string `json:"client_id"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + UserInfoEndpoint string `json:"user_info_endpoint"` + Scopes string `json:"scopes"` + UserIdField string `json:"user_id_field"` + UsernameField string `json:"username_field"` + DisplayNameField string `json:"display_name_field"` + EmailField string `json:"email_field"` + WellKnown string `json:"well_known"` + AuthStyle int `json:"auth_style"` + AccessPolicy string `json:"access_policy"` + AccessDeniedMessage string `json:"access_denied_message"` +} + +type UserOAuthBindingResponse struct { + ProviderId int `json:"provider_id"` + ProviderName string `json:"provider_name"` + ProviderSlug string `json:"provider_slug"` + ProviderIcon string `json:"provider_icon"` + ProviderUserId string `json:"provider_user_id"` +} + +func toCustomOAuthProviderResponse(p *model.CustomOAuthProvider) *CustomOAuthProviderResponse { + return &CustomOAuthProviderResponse{ + Id: p.Id, + Name: p.Name, + Slug: p.Slug, + Icon: p.Icon, + Enabled: p.Enabled, + ClientId: p.ClientId, + AuthorizationEndpoint: p.AuthorizationEndpoint, + TokenEndpoint: p.TokenEndpoint, + UserInfoEndpoint: p.UserInfoEndpoint, + Scopes: p.Scopes, + UserIdField: p.UserIdField, + UsernameField: p.UsernameField, + DisplayNameField: p.DisplayNameField, + EmailField: p.EmailField, + WellKnown: p.WellKnown, + AuthStyle: p.AuthStyle, + AccessPolicy: p.AccessPolicy, + AccessDeniedMessage: p.AccessDeniedMessage, + } +} + +// GetCustomOAuthProviders returns all custom OAuth providers +func GetCustomOAuthProviders(c *gin.Context) { + providers, err := model.GetAllCustomOAuthProviders() + if err != nil { + common.ApiError(c, err) + return + } + + response := make([]*CustomOAuthProviderResponse, len(providers)) + for i, p := range providers { + response[i] = toCustomOAuthProviderResponse(p) + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": response, + }) +} + +// GetCustomOAuthProvider returns a single custom OAuth provider by ID +func GetCustomOAuthProvider(c *gin.Context) { + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + common.ApiErrorMsg(c, "无效的 ID") + return + } + + provider, err := model.GetCustomOAuthProviderById(id) + if err != nil { + common.ApiErrorMsg(c, "未找到该 OAuth 提供商") + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": toCustomOAuthProviderResponse(provider), + }) +} + +// CreateCustomOAuthProviderRequest is the request structure for creating a custom OAuth provider +type CreateCustomOAuthProviderRequest struct { + Name string `json:"name" binding:"required"` + Slug string `json:"slug" binding:"required"` + Icon string `json:"icon"` + Enabled bool `json:"enabled"` + ClientId string `json:"client_id" binding:"required"` + ClientSecret string `json:"client_secret" binding:"required"` + AuthorizationEndpoint string `json:"authorization_endpoint" binding:"required"` + TokenEndpoint string `json:"token_endpoint" binding:"required"` + UserInfoEndpoint string `json:"user_info_endpoint" binding:"required"` + Scopes string `json:"scopes"` + UserIdField string `json:"user_id_field"` + UsernameField string `json:"username_field"` + DisplayNameField string `json:"display_name_field"` + EmailField string `json:"email_field"` + WellKnown string `json:"well_known"` + AuthStyle int `json:"auth_style"` + AccessPolicy string `json:"access_policy"` + AccessDeniedMessage string `json:"access_denied_message"` +} + +type FetchCustomOAuthDiscoveryRequest struct { + WellKnownURL string `json:"well_known_url"` + IssuerURL string `json:"issuer_url"` +} + +// FetchCustomOAuthDiscovery fetches OIDC discovery document via backend (root-only route) +func FetchCustomOAuthDiscovery(c *gin.Context) { + var req FetchCustomOAuthDiscoveryRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.ApiErrorMsg(c, "无效的请求参数: "+err.Error()) + return + } + + wellKnownURL := strings.TrimSpace(req.WellKnownURL) + issuerURL := strings.TrimSpace(req.IssuerURL) + + if wellKnownURL == "" && issuerURL == "" { + common.ApiErrorMsg(c, "请先填写 Discovery URL 或 Issuer URL") + return + } + + targetURL := wellKnownURL + if targetURL == "" { + targetURL = strings.TrimRight(issuerURL, "/") + "/.well-known/openid-configuration" + } + targetURL = strings.TrimSpace(targetURL) + + parsedURL, err := url.Parse(targetURL) + if err != nil || parsedURL.Host == "" || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") { + common.ApiErrorMsg(c, "Discovery URL 无效,仅支持 http/https") + return + } + + ctx, cancel := context.WithTimeout(c.Request.Context(), 20*time.Second) + defer cancel() + + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil) + if err != nil { + common.ApiErrorMsg(c, "创建 Discovery 请求失败: "+err.Error()) + return + } + httpReq.Header.Set("Accept", "application/json") + + client := &http.Client{Timeout: 20 * time.Second} + resp, err := client.Do(httpReq) + if err != nil { + common.ApiErrorMsg(c, "获取 Discovery 配置失败: "+err.Error()) + return + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(io.LimitReader(resp.Body, 512)) + message := strings.TrimSpace(string(body)) + if message == "" { + message = resp.Status + } + common.ApiErrorMsg(c, "获取 Discovery 配置失败: "+message) + return + } + + var discovery map[string]any + if err = common.DecodeJson(resp.Body, &discovery); err != nil { + common.ApiErrorMsg(c, "解析 Discovery 配置失败: "+err.Error()) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": gin.H{ + "well_known_url": targetURL, + "discovery": discovery, + }, + }) +} + +// CreateCustomOAuthProvider creates a new custom OAuth provider +func CreateCustomOAuthProvider(c *gin.Context) { + var req CreateCustomOAuthProviderRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.ApiErrorMsg(c, "无效的请求参数: "+err.Error()) + return + } + + // Check if slug is already taken + if model.IsSlugTaken(req.Slug, 0) { + common.ApiErrorMsg(c, "该 Slug 已被使用") + return + } + + // Check if slug conflicts with built-in providers + if oauth.IsProviderRegistered(req.Slug) && !oauth.IsCustomProvider(req.Slug) { + common.ApiErrorMsg(c, "该 Slug 与内置 OAuth 提供商冲突") + return + } + + provider := &model.CustomOAuthProvider{ + Name: req.Name, + Slug: req.Slug, + Icon: req.Icon, + Enabled: req.Enabled, + ClientId: req.ClientId, + ClientSecret: req.ClientSecret, + AuthorizationEndpoint: req.AuthorizationEndpoint, + TokenEndpoint: req.TokenEndpoint, + UserInfoEndpoint: req.UserInfoEndpoint, + Scopes: req.Scopes, + UserIdField: req.UserIdField, + UsernameField: req.UsernameField, + DisplayNameField: req.DisplayNameField, + EmailField: req.EmailField, + WellKnown: req.WellKnown, + AuthStyle: req.AuthStyle, + AccessPolicy: req.AccessPolicy, + AccessDeniedMessage: req.AccessDeniedMessage, + } + + if err := model.CreateCustomOAuthProvider(provider); err != nil { + common.ApiError(c, err) + return + } + + // Register the provider in the OAuth registry + oauth.RegisterOrUpdateCustomProvider(provider) + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "创建成功", + "data": toCustomOAuthProviderResponse(provider), + }) +} + +// UpdateCustomOAuthProviderRequest is the request structure for updating a custom OAuth provider +type UpdateCustomOAuthProviderRequest struct { + Name string `json:"name"` + Slug string `json:"slug"` + Icon *string `json:"icon"` // Optional: if nil, keep existing + Enabled *bool `json:"enabled"` // Optional: if nil, keep existing + ClientId string `json:"client_id"` + ClientSecret string `json:"client_secret"` // Optional: if empty, keep existing + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + UserInfoEndpoint string `json:"user_info_endpoint"` + Scopes string `json:"scopes"` + UserIdField string `json:"user_id_field"` + UsernameField string `json:"username_field"` + DisplayNameField string `json:"display_name_field"` + EmailField string `json:"email_field"` + WellKnown *string `json:"well_known"` // Optional: if nil, keep existing + AuthStyle *int `json:"auth_style"` // Optional: if nil, keep existing + AccessPolicy *string `json:"access_policy"` // Optional: if nil, keep existing + AccessDeniedMessage *string `json:"access_denied_message"` // Optional: if nil, keep existing +} + +// UpdateCustomOAuthProvider updates an existing custom OAuth provider +func UpdateCustomOAuthProvider(c *gin.Context) { + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + common.ApiErrorMsg(c, "无效的 ID") + return + } + + var req UpdateCustomOAuthProviderRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.ApiErrorMsg(c, "无效的请求参数: "+err.Error()) + return + } + + // Get existing provider + provider, err := model.GetCustomOAuthProviderById(id) + if err != nil { + common.ApiErrorMsg(c, "未找到该 OAuth 提供商") + return + } + + oldSlug := provider.Slug + + // Check if new slug is taken by another provider + if req.Slug != "" && req.Slug != provider.Slug { + if model.IsSlugTaken(req.Slug, id) { + common.ApiErrorMsg(c, "该 Slug 已被使用") + return + } + // Check if slug conflicts with built-in providers + if oauth.IsProviderRegistered(req.Slug) && !oauth.IsCustomProvider(req.Slug) { + common.ApiErrorMsg(c, "该 Slug 与内置 OAuth 提供商冲突") + return + } + } + + // Update fields + if req.Name != "" { + provider.Name = req.Name + } + if req.Slug != "" { + provider.Slug = req.Slug + } + if req.Icon != nil { + provider.Icon = *req.Icon + } + if req.Enabled != nil { + provider.Enabled = *req.Enabled + } + if req.ClientId != "" { + provider.ClientId = req.ClientId + } + if req.ClientSecret != "" { + provider.ClientSecret = req.ClientSecret + } + if req.AuthorizationEndpoint != "" { + provider.AuthorizationEndpoint = req.AuthorizationEndpoint + } + if req.TokenEndpoint != "" { + provider.TokenEndpoint = req.TokenEndpoint + } + if req.UserInfoEndpoint != "" { + provider.UserInfoEndpoint = req.UserInfoEndpoint + } + if req.Scopes != "" { + provider.Scopes = req.Scopes + } + if req.UserIdField != "" { + provider.UserIdField = req.UserIdField + } + if req.UsernameField != "" { + provider.UsernameField = req.UsernameField + } + if req.DisplayNameField != "" { + provider.DisplayNameField = req.DisplayNameField + } + if req.EmailField != "" { + provider.EmailField = req.EmailField + } + if req.WellKnown != nil { + provider.WellKnown = *req.WellKnown + } + if req.AuthStyle != nil { + provider.AuthStyle = *req.AuthStyle + } + if req.AccessPolicy != nil { + provider.AccessPolicy = *req.AccessPolicy + } + if req.AccessDeniedMessage != nil { + provider.AccessDeniedMessage = *req.AccessDeniedMessage + } + + if err := model.UpdateCustomOAuthProvider(provider); err != nil { + common.ApiError(c, err) + return + } + + // Update the provider in the OAuth registry + if oldSlug != provider.Slug { + oauth.UnregisterCustomProvider(oldSlug) + } + oauth.RegisterOrUpdateCustomProvider(provider) + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "更新成功", + "data": toCustomOAuthProviderResponse(provider), + }) +} + +// DeleteCustomOAuthProvider deletes a custom OAuth provider +func DeleteCustomOAuthProvider(c *gin.Context) { + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + common.ApiErrorMsg(c, "无效的 ID") + return + } + + // Get existing provider to get slug + provider, err := model.GetCustomOAuthProviderById(id) + if err != nil { + common.ApiErrorMsg(c, "未找到该 OAuth 提供商") + return + } + + // Check if there are any user bindings + count, err := model.GetBindingCountByProviderId(id) + if err != nil { + common.SysError("Failed to get binding count for provider " + strconv.Itoa(id) + ": " + err.Error()) + common.ApiErrorMsg(c, "检查用户绑定时发生错误,请稍后重试") + return + } + if count > 0 { + common.ApiErrorMsg(c, "该 OAuth 提供商还有用户绑定,无法删除。请先解除所有用户绑定。") + return + } + + if err := model.DeleteCustomOAuthProvider(id); err != nil { + common.ApiError(c, err) + return + } + + // Unregister the provider from the OAuth registry + oauth.UnregisterCustomProvider(provider.Slug) + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "删除成功", + }) +} + +func buildUserOAuthBindingsResponse(userId int) ([]UserOAuthBindingResponse, error) { + bindings, err := model.GetUserOAuthBindingsByUserId(userId) + if err != nil { + return nil, err + } + + response := make([]UserOAuthBindingResponse, 0, len(bindings)) + for _, binding := range bindings { + provider, err := model.GetCustomOAuthProviderById(binding.ProviderId) + if err != nil { + continue + } + response = append(response, UserOAuthBindingResponse{ + ProviderId: binding.ProviderId, + ProviderName: provider.Name, + ProviderSlug: provider.Slug, + ProviderIcon: provider.Icon, + ProviderUserId: binding.ProviderUserId, + }) + } + + return response, nil +} + +// GetUserOAuthBindings returns all OAuth bindings for the current user +func GetUserOAuthBindings(c *gin.Context) { + userId := c.GetInt("id") + if userId == 0 { + common.ApiErrorMsg(c, "未登录") + return + } + + response, err := buildUserOAuthBindingsResponse(userId) + if err != nil { + common.ApiError(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": response, + }) +} + +func GetUserOAuthBindingsByAdmin(c *gin.Context) { + userIdStr := c.Param("id") + userId, err := strconv.Atoi(userIdStr) + if err != nil { + common.ApiErrorMsg(c, "invalid user id") + return + } + + targetUser, err := model.GetUserById(userId, false) + if err != nil { + common.ApiError(c, err) + return + } + + myRole := c.GetInt("role") + if myRole <= targetUser.Role && myRole != common.RoleRootUser { + common.ApiErrorMsg(c, "no permission") + return + } + + response, err := buildUserOAuthBindingsResponse(userId) + if err != nil { + common.ApiError(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": response, + }) +} + +// UnbindCustomOAuth unbinds a custom OAuth provider from the current user +func UnbindCustomOAuth(c *gin.Context) { + userId := c.GetInt("id") + if userId == 0 { + common.ApiErrorMsg(c, "未登录") + return + } + + providerIdStr := c.Param("provider_id") + providerId, err := strconv.Atoi(providerIdStr) + if err != nil { + common.ApiErrorMsg(c, "无效的提供商 ID") + return + } + + if err := model.DeleteUserOAuthBinding(userId, providerId); err != nil { + common.ApiError(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "解绑成功", + }) +} + +func UnbindCustomOAuthByAdmin(c *gin.Context) { + userIdStr := c.Param("id") + userId, err := strconv.Atoi(userIdStr) + if err != nil { + common.ApiErrorMsg(c, "invalid user id") + return + } + + targetUser, err := model.GetUserById(userId, false) + if err != nil { + common.ApiError(c, err) + return + } + + myRole := c.GetInt("role") + if myRole <= targetUser.Role && myRole != common.RoleRootUser { + common.ApiErrorMsg(c, "no permission") + return + } + + providerIdStr := c.Param("provider_id") + providerId, err := strconv.Atoi(providerIdStr) + if err != nil { + common.ApiErrorMsg(c, "invalid provider id") + return + } + + if err := model.DeleteUserOAuthBinding(userId, providerId); err != nil { + common.ApiError(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "success", + }) +} diff --git a/_all-in-one-upload/new-api/controller/subscription_payment_epay.go b/_all-in-one-upload/new-api/controller/subscription_payment_epay.go new file mode 100644 index 0000000..2567654 --- /dev/null +++ b/_all-in-one-upload/new-api/controller/subscription_payment_epay.go @@ -0,0 +1,217 @@ +package controller + +import ( + "fmt" + "net/http" + "net/url" + "strconv" + "time" + + "github.com/Calcium-Ion/go-epay/epay" + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/model" + "github.com/QuantumNous/new-api/service" + "github.com/QuantumNous/new-api/setting/operation_setting" + "github.com/QuantumNous/new-api/setting/system_setting" + "github.com/gin-gonic/gin" + "github.com/samber/lo" +) + +type SubscriptionEpayPayRequest struct { + PlanId int `json:"plan_id"` + PaymentMethod string `json:"payment_method"` +} + +func SubscriptionRequestEpay(c *gin.Context) { + var req SubscriptionEpayPayRequest + if err := c.ShouldBindJSON(&req); err != nil || req.PlanId <= 0 { + common.ApiErrorMsg(c, "参数错误") + return + } + + plan, err := model.GetSubscriptionPlanById(req.PlanId) + if err != nil { + common.ApiError(c, err) + return + } + if !plan.Enabled { + common.ApiErrorMsg(c, "套餐未启用") + return + } + if plan.PriceAmount < 0.01 { + common.ApiErrorMsg(c, "套餐金额过低") + return + } + if !operation_setting.ContainsPayMethod(req.PaymentMethod) { + common.ApiErrorMsg(c, "支付方式不存在") + return + } + + userId := c.GetInt("id") + if plan.MaxPurchasePerUser > 0 { + count, err := model.CountUserSubscriptionsByPlan(userId, plan.Id) + if err != nil { + common.ApiError(c, err) + return + } + if count >= int64(plan.MaxPurchasePerUser) { + common.ApiErrorMsg(c, "已达到该套餐购买上限") + return + } + } + + callBackAddress := service.GetCallbackAddress() + returnUrl, err := url.Parse(callBackAddress + "/api/subscription/epay/return") + if err != nil { + common.ApiErrorMsg(c, "回调地址配置错误") + return + } + notifyUrl, err := url.Parse(callBackAddress + "/api/subscription/epay/notify") + if err != nil { + common.ApiErrorMsg(c, "回调地址配置错误") + return + } + + tradeNo := fmt.Sprintf("%s%d", common.GetRandomString(6), time.Now().Unix()) + tradeNo = fmt.Sprintf("SUBUSR%dNO%s", userId, tradeNo) + + client := GetEpayClient() + if client == nil { + common.ApiErrorMsg(c, "当前管理员未配置支付信息") + return + } + + order := &model.SubscriptionOrder{ + UserId: userId, + PlanId: plan.Id, + Money: plan.PriceAmount, + TradeNo: tradeNo, + PaymentMethod: req.PaymentMethod, + PaymentProvider: model.PaymentProviderEpay, + CreateTime: time.Now().Unix(), + Status: common.TopUpStatusPending, + } + if err := order.Insert(); err != nil { + common.ApiErrorMsg(c, "创建订单失败") + return + } + uri, params, err := client.Purchase(&epay.PurchaseArgs{ + Type: req.PaymentMethod, + ServiceTradeNo: tradeNo, + Name: fmt.Sprintf("SUB:%s", plan.Title), + Money: strconv.FormatFloat(plan.PriceAmount, 'f', 2, 64), + Device: epay.PC, + NotifyUrl: notifyUrl, + ReturnUrl: returnUrl, + }) + if err != nil { + _ = model.ExpireSubscriptionOrder(tradeNo, model.PaymentProviderEpay) + common.ApiErrorMsg(c, "拉起支付失败") + return + } + c.JSON(http.StatusOK, gin.H{"message": "success", "data": params, "url": uri}) +} + +func SubscriptionEpayNotify(c *gin.Context) { + var params map[string]string + + if c.Request.Method == "POST" { + // POST 请求:从 POST body 解析参数 + if err := c.Request.ParseForm(); err != nil { + _, _ = c.Writer.Write([]byte("fail")) + return + } + params = lo.Reduce(lo.Keys(c.Request.PostForm), func(r map[string]string, t string, i int) map[string]string { + r[t] = c.Request.PostForm.Get(t) + return r + }, map[string]string{}) + } else { + // GET 请求:从 URL Query 解析参数 + params = lo.Reduce(lo.Keys(c.Request.URL.Query()), func(r map[string]string, t string, i int) map[string]string { + r[t] = c.Request.URL.Query().Get(t) + return r + }, map[string]string{}) + } + + if len(params) == 0 { + _, _ = c.Writer.Write([]byte("fail")) + return + } + + client := GetEpayClient() + if client == nil { + _, _ = c.Writer.Write([]byte("fail")) + return + } + verifyInfo, err := client.Verify(params) + if err != nil || !verifyInfo.VerifyStatus { + _, _ = c.Writer.Write([]byte("fail")) + return + } + + if verifyInfo.TradeStatus != epay.StatusTradeSuccess { + _, _ = c.Writer.Write([]byte("fail")) + return + } + + LockOrder(verifyInfo.ServiceTradeNo) + defer UnlockOrder(verifyInfo.ServiceTradeNo) + + if err := model.CompleteSubscriptionOrder(verifyInfo.ServiceTradeNo, common.GetJsonString(verifyInfo), model.PaymentProviderEpay, verifyInfo.Type); err != nil { + _, _ = c.Writer.Write([]byte("fail")) + return + } + + _, _ = c.Writer.Write([]byte("success")) +} + +// SubscriptionEpayReturn handles browser return after payment. +// It verifies the payload and completes the order, then redirects to console. +func SubscriptionEpayReturn(c *gin.Context) { + var params map[string]string + + if c.Request.Method == "POST" { + // POST 请求:从 POST body 解析参数 + if err := c.Request.ParseForm(); err != nil { + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=fail") + return + } + params = lo.Reduce(lo.Keys(c.Request.PostForm), func(r map[string]string, t string, i int) map[string]string { + r[t] = c.Request.PostForm.Get(t) + return r + }, map[string]string{}) + } else { + // GET 请求:从 URL Query 解析参数 + params = lo.Reduce(lo.Keys(c.Request.URL.Query()), func(r map[string]string, t string, i int) map[string]string { + r[t] = c.Request.URL.Query().Get(t) + return r + }, map[string]string{}) + } + + if len(params) == 0 { + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=fail") + return + } + + client := GetEpayClient() + if client == nil { + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=fail") + return + } + verifyInfo, err := client.Verify(params) + if err != nil || !verifyInfo.VerifyStatus { + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=fail") + return + } + if verifyInfo.TradeStatus == epay.StatusTradeSuccess { + LockOrder(verifyInfo.ServiceTradeNo) + defer UnlockOrder(verifyInfo.ServiceTradeNo) + if err := model.CompleteSubscriptionOrder(verifyInfo.ServiceTradeNo, common.GetJsonString(verifyInfo), model.PaymentProviderEpay, verifyInfo.Type); err != nil { + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=fail") + return + } + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=success") + return + } + c.Redirect(http.StatusFound, system_setting.ServerAddress+"/console/topup?pay=pending") +} diff --git a/_all-in-one-upload/new-api/docker-compose.local.yml b/_all-in-one-upload/new-api/docker-compose.local.yml new file mode 100644 index 0000000..cbde737 --- /dev/null +++ b/_all-in-one-upload/new-api/docker-compose.local.yml @@ -0,0 +1,4 @@ +services: + new-api: + ports: + - "3001:3000" diff --git a/_all-in-one-upload/new-api/docs/images/aliyun.png b/_all-in-one-upload/new-api/docs/images/aliyun.png new file mode 100644 index 0000000000000000000000000000000000000000..6266bfbff3603b0969ee557143a5ec18e7d9e045 GIT binary patch literal 5102 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 0 && args[0] != nil { + config.TemplateData = args[0] + } + + msg, err := loc.Localize(config) + if err != nil { + // Return key as fallback if translation not found + return key + } + return msg +} + +// userLangLoaderFunc is a function that loads user language from database/cache +// It's set by the model package to avoid circular imports +var userLangLoaderFunc func(userId int) string + +// SetUserLangLoader sets the function to load user language (called from model package) +func SetUserLangLoader(loader func(userId int) string) { + userLangLoaderFunc = loader +} + +// GetLangFromContext extracts the language setting from gin context +// It checks multiple sources in priority order: +// 1. User settings (ContextKeyUserSetting) - if already loaded (e.g., by TokenAuth) +// 2. Lazy load user language from cache/DB using user ID +// 3. Language set by middleware (ContextKeyLanguage) - from Accept-Language header +// 4. Default language (English) +func GetLangFromContext(c *gin.Context) string { + if c == nil { + return DefaultLang + } + + // 1. Try to get language from user settings (if already loaded by TokenAuth or other middleware) + if userSetting, ok := common.GetContextKeyType[dto.UserSetting](c, constant.ContextKeyUserSetting); ok { + if userSetting.Language != "" { + normalized := normalizeLang(userSetting.Language) + if IsSupported(normalized) { + return normalized + } + } + } + + // 2. Lazy load user language using user ID (for session-based auth where full settings aren't loaded) + if userLangLoaderFunc != nil { + if userId, exists := c.Get("id"); exists { + if uid, ok := userId.(int); ok && uid > 0 { + lang := userLangLoaderFunc(uid) + if lang != "" { + normalized := normalizeLang(lang) + if IsSupported(normalized) { + return normalized + } + } + } + } + } + + // 3. Try to get language from context (set by I18n middleware from Accept-Language) + if lang := c.GetString(string(constant.ContextKeyLanguage)); lang != "" { + normalized := normalizeLang(lang) + if IsSupported(normalized) { + return normalized + } + } + + // 4. Try Accept-Language header directly (fallback if middleware didn't run) + if acceptLang := c.GetHeader("Accept-Language"); acceptLang != "" { + lang := ParseAcceptLanguage(acceptLang) + if IsSupported(lang) { + return lang + } + } + + return DefaultLang +} + +// ParseAcceptLanguage parses the Accept-Language header and returns the preferred language +func ParseAcceptLanguage(header string) string { + if header == "" { + return DefaultLang + } + + // Simple parsing: take the first language tag + parts := strings.Split(header, ",") + if len(parts) == 0 { + return DefaultLang + } + + // Get the first language and remove quality value + firstLang := strings.TrimSpace(parts[0]) + if idx := strings.Index(firstLang, ";"); idx > 0 { + firstLang = firstLang[:idx] + } + + return normalizeLang(firstLang) +} + +// normalizeLang normalizes language code to supported format +func normalizeLang(lang string) string { + lang = strings.ToLower(strings.TrimSpace(lang)) + + // Handle common variations + switch { + case strings.HasPrefix(lang, "zh-tw"): + return LangZhTW + case strings.HasPrefix(lang, "zh"): + return LangZhCN + case strings.HasPrefix(lang, "en"): + return LangEn + default: + return DefaultLang + } +} + +// SupportedLanguages returns a list of supported language codes +func SupportedLanguages() []string { + return []string{LangZhCN, LangZhTW, LangEn} +} + +// IsSupported checks if a language code is supported +func IsSupported(lang string) bool { + lang = normalizeLang(lang) + for _, supported := range SupportedLanguages() { + if lang == supported { + return true + } + } + return false +} diff --git a/_all-in-one-upload/new-api/middleware/cache.go b/_all-in-one-upload/new-api/middleware/cache.go new file mode 100644 index 0000000..1a9dff8 --- /dev/null +++ b/_all-in-one-upload/new-api/middleware/cache.go @@ -0,0 +1,17 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" +) + +func Cache() func(c *gin.Context) { + return func(c *gin.Context) { + if c.Request.RequestURI == "/" { + c.Header("Cache-Control", "no-cache") + } else { + c.Header("Cache-Control", "max-age=604800") // one week + } + c.Header("Cache-Version", "b688f2fb5be447c25e5aa3bd063087a83db32a288bf6a4f35f2d8db310e40b14") + c.Next() + } +} diff --git a/_all-in-one-upload/new-api/middleware/distributor.go b/_all-in-one-upload/new-api/middleware/distributor.go new file mode 100644 index 0000000..2263fae --- /dev/null +++ b/_all-in-one-upload/new-api/middleware/distributor.go @@ -0,0 +1,435 @@ +package middleware + +import ( + "errors" + "fmt" + "net/http" + "slices" + "strconv" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/i18n" + "github.com/QuantumNous/new-api/model" + relayconstant "github.com/QuantumNous/new-api/relay/constant" + "github.com/QuantumNous/new-api/service" + "github.com/QuantumNous/new-api/setting/ratio_setting" + "github.com/QuantumNous/new-api/types" + + "github.com/gin-gonic/gin" +) + +type ModelRequest struct { + Model string `json:"model"` + Group string `json:"group,omitempty"` +} + +func Distribute() func(c *gin.Context) { + return func(c *gin.Context) { + var channel *model.Channel + channelId, ok := common.GetContextKey(c, constant.ContextKeyTokenSpecificChannelId) + modelRequest, shouldSelectChannel, err := getModelRequest(c) + if err != nil { + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()})) + return + } + if ok { + id, err := strconv.Atoi(channelId.(string)) + if err != nil { + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorInvalidChannelId)) + return + } + channel, err = model.GetChannelById(id, true) + if err != nil { + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorInvalidChannelId)) + return + } + if channel.Status != common.ChannelStatusEnabled { + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgDistributorChannelDisabled)) + return + } + } else { + // Select a channel for the user + // check token model mapping + modelLimitEnable := common.GetContextKeyBool(c, constant.ContextKeyTokenModelLimitEnabled) + if modelLimitEnable { + s, ok := common.GetContextKey(c, constant.ContextKeyTokenModelLimit) + if !ok { + // token model limit is empty, all models are not allowed + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgDistributorTokenNoModelAccess)) + return + } + var tokenModelLimit map[string]bool + tokenModelLimit, ok = s.(map[string]bool) + if !ok { + tokenModelLimit = map[string]bool{} + } + matchName := ratio_setting.FormatMatchingModelName(modelRequest.Model) // match gpts & thinking-* + if _, ok := tokenModelLimit[matchName]; !ok { + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgDistributorTokenModelForbidden, map[string]any{"Model": modelRequest.Model})) + return + } + } + + if shouldSelectChannel { + if modelRequest.Model == "" { + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorModelNameRequired)) + return + } + var selectGroup string + usingGroup := common.GetContextKeyString(c, constant.ContextKeyUsingGroup) + // check path is /pg/chat/completions + if strings.HasPrefix(c.Request.URL.Path, "/pg/chat/completions") { + playgroundRequest := &dto.PlayGroundRequest{} + err = common.UnmarshalBodyReusable(c, playgroundRequest) + if err != nil { + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorInvalidPlayground, map[string]any{"Error": err.Error()})) + return + } + if playgroundRequest.Group != "" { + if !service.GroupInUserUsableGroups(usingGroup, playgroundRequest.Group) && playgroundRequest.Group != usingGroup { + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgDistributorGroupAccessDenied)) + return + } + usingGroup = playgroundRequest.Group + common.SetContextKey(c, constant.ContextKeyUsingGroup, usingGroup) + } + } + + if preferredChannelID, found := service.GetPreferredChannelByAffinity(c, modelRequest.Model, usingGroup); found { + preferred, err := model.CacheGetChannel(preferredChannelID) + if err == nil && preferred != nil { + if preferred.Status != common.ChannelStatusEnabled { + if service.ShouldSkipRetryAfterChannelAffinityFailure(c) { + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgDistributorAffinityChannelDisabled)) + return + } + } else if usingGroup == "auto" { + userGroup := common.GetContextKeyString(c, constant.ContextKeyUserGroup) + autoGroups := service.GetUserAutoGroup(userGroup) + for _, g := range autoGroups { + if model.IsChannelEnabledForGroupModel(g, modelRequest.Model, preferred.Id) { + selectGroup = g + common.SetContextKey(c, constant.ContextKeyAutoGroup, g) + channel = preferred + service.MarkChannelAffinityUsed(c, g, preferred.Id) + break + } + } + } else if model.IsChannelEnabledForGroupModel(usingGroup, modelRequest.Model, preferred.Id) { + channel = preferred + selectGroup = usingGroup + service.MarkChannelAffinityUsed(c, usingGroup, preferred.Id) + } + } + } + + if channel == nil { + channel, selectGroup, err = service.CacheGetRandomSatisfiedChannel(&service.RetryParam{ + Ctx: c, + ModelName: modelRequest.Model, + TokenGroup: usingGroup, + Retry: common.GetPointer(0), + }) + if err != nil { + showGroup := usingGroup + if usingGroup == "auto" { + showGroup = fmt.Sprintf("auto(%s)", selectGroup) + } + message := i18n.T(c, i18n.MsgDistributorGetChannelFailed, map[string]any{"Group": showGroup, "Model": modelRequest.Model, "Error": err.Error()}) + // 如果错误,但是渠道不为空,说明是数据库一致性问题 + //if channel != nil { + // common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) + // message = "数据库一致性已被破坏,请联系管理员" + //} + abortWithOpenAiMessage(c, http.StatusServiceUnavailable, message, types.ErrorCodeModelNotFound) + return + } + if channel == nil { + abortWithOpenAiMessage(c, http.StatusServiceUnavailable, i18n.T(c, i18n.MsgDistributorNoAvailableChannel, map[string]any{"Group": usingGroup, "Model": modelRequest.Model}), types.ErrorCodeModelNotFound) + return + } + } + } + } + common.SetContextKey(c, constant.ContextKeyRequestStartTime, time.Now()) + SetupContextForSelectedChannel(c, channel, modelRequest.Model) + c.Next() + if channel != nil && c.Writer != nil && c.Writer.Status() < http.StatusBadRequest { + service.RecordChannelAffinity(c, channel.Id) + } + } +} + +// getModelFromRequest 从请求中读取模型信息 +// 根据 Content-Type 自动处理: +// - application/json +// - application/x-www-form-urlencoded +// - multipart/form-data +func getModelFromRequest(c *gin.Context) (*ModelRequest, error) { + var modelRequest ModelRequest + err := common.UnmarshalBodyReusable(c, &modelRequest) + if err != nil { + return nil, errors.New(i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()})) + } + return &modelRequest, nil +} + +func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) { + var modelRequest ModelRequest + shouldSelectChannel := true + var err error + if strings.Contains(c.Request.URL.Path, "/mj/") { + relayMode := relayconstant.Path2RelayModeMidjourney(c.Request.URL.Path) + if relayMode == relayconstant.RelayModeMidjourneyTaskFetch || + relayMode == relayconstant.RelayModeMidjourneyTaskFetchByCondition || + relayMode == relayconstant.RelayModeMidjourneyNotify || + relayMode == relayconstant.RelayModeMidjourneyTaskImageSeed { + shouldSelectChannel = false + } else { + midjourneyRequest := dto.MidjourneyRequest{} + err = common.UnmarshalBodyReusable(c, &midjourneyRequest) + if err != nil { + return nil, false, errors.New(i18n.T(c, i18n.MsgDistributorInvalidMidjourney, map[string]any{"Error": err.Error()})) + } + midjourneyModel, mjErr, success := service.GetMjRequestModel(relayMode, &midjourneyRequest) + if mjErr != nil { + return nil, false, fmt.Errorf("%s", mjErr.Description) + } + if midjourneyModel == "" { + if !success { + return nil, false, fmt.Errorf("%s", i18n.T(c, i18n.MsgDistributorInvalidParseModel)) + } else { + // task fetch, task fetch by condition, notify + shouldSelectChannel = false + } + } + modelRequest.Model = midjourneyModel + } + c.Set("relay_mode", relayMode) + } else if strings.Contains(c.Request.URL.Path, "/suno/") { + relayMode := relayconstant.Path2RelaySuno(c.Request.Method, c.Request.URL.Path) + if relayMode == relayconstant.RelayModeSunoFetch || + relayMode == relayconstant.RelayModeSunoFetchByID { + shouldSelectChannel = false + } else { + modelName := service.CoverTaskActionToModelName(constant.TaskPlatformSuno, c.Param("action")) + modelRequest.Model = modelName + } + c.Set("platform", string(constant.TaskPlatformSuno)) + c.Set("relay_mode", relayMode) + } else if strings.Contains(c.Request.URL.Path, "/v1/videos/") && strings.HasSuffix(c.Request.URL.Path, "/remix") { + relayMode := relayconstant.RelayModeVideoSubmit + c.Set("relay_mode", relayMode) + shouldSelectChannel = false + } else if strings.Contains(c.Request.URL.Path, "/v1/videos") { + //curl https://api.openai.com/v1/videos \ + // -H "Authorization: Bearer $OPENAI_API_KEY" \ + // -F "model=sora-2" \ + // -F "prompt=A calico cat playing a piano on stage" + // -F input_reference="@image.jpg" + relayMode := relayconstant.RelayModeUnknown + if c.Request.Method == http.MethodPost { + relayMode = relayconstant.RelayModeVideoSubmit + req, err := getModelFromRequest(c) + if err != nil { + return nil, false, err + } + if req != nil { + modelRequest.Model = req.Model + } + } else if c.Request.Method == http.MethodGet { + relayMode = relayconstant.RelayModeVideoFetchByID + shouldSelectChannel = false + } + c.Set("relay_mode", relayMode) + } else if strings.Contains(c.Request.URL.Path, "/v1/video/generations") { + relayMode := relayconstant.RelayModeUnknown + if c.Request.Method == http.MethodPost { + req, err := getModelFromRequest(c) + if err != nil { + return nil, false, err + } + modelRequest.Model = req.Model + relayMode = relayconstant.RelayModeVideoSubmit + } else if c.Request.Method == http.MethodGet { + relayMode = relayconstant.RelayModeVideoFetchByID + shouldSelectChannel = false + } + if _, ok := c.Get("relay_mode"); !ok { + c.Set("relay_mode", relayMode) + } + } else if strings.HasPrefix(c.Request.URL.Path, "/v1beta/models/") || strings.HasPrefix(c.Request.URL.Path, "/v1/models/") { + // Gemini API 路径处理: /v1beta/models/gemini-2.0-flash:generateContent + relayMode := relayconstant.RelayModeGemini + modelName := extractModelNameFromGeminiPath(c.Request.URL.Path) + if modelName != "" { + modelRequest.Model = modelName + } + c.Set("relay_mode", relayMode) + } else if !strings.HasPrefix(c.Request.URL.Path, "/v1/audio/transcriptions") && !strings.Contains(c.Request.Header.Get("Content-Type"), "multipart/form-data") { + req, err := getModelFromRequest(c) + if err != nil { + return nil, false, err + } + modelRequest.Model = req.Model + } + if strings.HasPrefix(c.Request.URL.Path, "/v1/realtime") { + //wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01 + modelRequest.Model = c.Query("model") + } + if strings.HasPrefix(c.Request.URL.Path, "/v1/moderations") { + if modelRequest.Model == "" { + modelRequest.Model = "text-moderation-stable" + } + } + if strings.HasSuffix(c.Request.URL.Path, "embeddings") { + if modelRequest.Model == "" { + modelRequest.Model = c.Param("model") + } + } + if strings.HasPrefix(c.Request.URL.Path, "/v1/images/generations") { + modelRequest.Model = common.GetStringIfEmpty(modelRequest.Model, "dall-e") + } else if strings.HasPrefix(c.Request.URL.Path, "/v1/images/edits") { + //modelRequest.Model = common.GetStringIfEmpty(c.PostForm("model"), "gpt-image-1") + contentType := c.ContentType() + if slices.Contains([]string{gin.MIMEPOSTForm, gin.MIMEMultipartPOSTForm}, contentType) { + req, err := getModelFromRequest(c) + if err == nil && req.Model != "" { + modelRequest.Model = req.Model + } + } + } + if strings.HasPrefix(c.Request.URL.Path, "/v1/audio") { + relayMode := relayconstant.RelayModeAudioSpeech + if strings.HasPrefix(c.Request.URL.Path, "/v1/audio/speech") { + + modelRequest.Model = common.GetStringIfEmpty(modelRequest.Model, "tts-1") + } else if strings.HasPrefix(c.Request.URL.Path, "/v1/audio/translations") { + // 先尝试从请求读取 + if req, err := getModelFromRequest(c); err == nil && req.Model != "" { + modelRequest.Model = req.Model + } + modelRequest.Model = common.GetStringIfEmpty(modelRequest.Model, "whisper-1") + relayMode = relayconstant.RelayModeAudioTranslation + } else if strings.HasPrefix(c.Request.URL.Path, "/v1/audio/transcriptions") { + // 先尝试从请求读取 + if req, err := getModelFromRequest(c); err == nil && req.Model != "" { + modelRequest.Model = req.Model + } + modelRequest.Model = common.GetStringIfEmpty(modelRequest.Model, "whisper-1") + relayMode = relayconstant.RelayModeAudioTranscription + } + c.Set("relay_mode", relayMode) + } + if strings.HasPrefix(c.Request.URL.Path, "/pg/chat/completions") { + // playground chat completions + req, err := getModelFromRequest(c) + if err != nil { + return nil, false, err + } + modelRequest.Model = req.Model + modelRequest.Group = req.Group + common.SetContextKey(c, constant.ContextKeyTokenGroup, modelRequest.Group) + } + + if strings.HasPrefix(c.Request.URL.Path, "/v1/responses/compact") && modelRequest.Model != "" { + modelRequest.Model = ratio_setting.WithCompactModelSuffix(modelRequest.Model) + } + return &modelRequest, shouldSelectChannel, nil +} + +func SetupContextForSelectedChannel(c *gin.Context, channel *model.Channel, modelName string) *types.NewAPIError { + c.Set("original_model", modelName) // for retry + if channel == nil { + return types.NewError(errors.New("channel is nil"), types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry()) + } + common.SetContextKey(c, constant.ContextKeyChannelId, channel.Id) + common.SetContextKey(c, constant.ContextKeyChannelName, channel.Name) + common.SetContextKey(c, constant.ContextKeyChannelType, channel.Type) + common.SetContextKey(c, constant.ContextKeyChannelCreateTime, channel.CreatedTime) + common.SetContextKey(c, constant.ContextKeyChannelSetting, channel.GetSetting()) + common.SetContextKey(c, constant.ContextKeyChannelOtherSetting, channel.GetOtherSettings()) + paramOverride := channel.GetParamOverride() + headerOverride := channel.GetHeaderOverride() + if mergedParam, applied := service.ApplyChannelAffinityOverrideTemplate(c, paramOverride); applied { + paramOverride = mergedParam + } + common.SetContextKey(c, constant.ContextKeyChannelParamOverride, paramOverride) + common.SetContextKey(c, constant.ContextKeyChannelHeaderOverride, headerOverride) + if nil != channel.OpenAIOrganization && *channel.OpenAIOrganization != "" { + common.SetContextKey(c, constant.ContextKeyChannelOrganization, *channel.OpenAIOrganization) + } + common.SetContextKey(c, constant.ContextKeyChannelAutoBan, channel.GetAutoBan()) + common.SetContextKey(c, constant.ContextKeyChannelModelMapping, channel.GetModelMapping()) + common.SetContextKey(c, constant.ContextKeyChannelStatusCodeMapping, channel.GetStatusCodeMapping()) + + key, index, newAPIError := channel.GetNextEnabledKey() + if newAPIError != nil { + return newAPIError + } + if channel.ChannelInfo.IsMultiKey { + common.SetContextKey(c, constant.ContextKeyChannelIsMultiKey, true) + common.SetContextKey(c, constant.ContextKeyChannelMultiKeyIndex, index) + } else { + // 必须设置为 false,否则在重试到单个 key 的时候会导致日志显示错误 + common.SetContextKey(c, constant.ContextKeyChannelIsMultiKey, false) + } + // c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", key)) + common.SetContextKey(c, constant.ContextKeyChannelKey, key) + common.SetContextKey(c, constant.ContextKeyChannelBaseUrl, channel.GetBaseURL()) + + common.SetContextKey(c, constant.ContextKeySystemPromptOverride, false) + + // TODO: api_version统一 + switch channel.Type { + case constant.ChannelTypeAzure: + c.Set("api_version", channel.Other) + case constant.ChannelTypeVertexAi: + c.Set("region", channel.Other) + case constant.ChannelTypeXunfei: + c.Set("api_version", channel.Other) + case constant.ChannelTypeGemini: + c.Set("api_version", channel.Other) + case constant.ChannelTypeAli: + c.Set("plugin", channel.Other) + case constant.ChannelCloudflare: + c.Set("api_version", channel.Other) + case constant.ChannelTypeMokaAI: + c.Set("api_version", channel.Other) + case constant.ChannelTypeCoze: + c.Set("bot_id", channel.Other) + } + return nil +} + +// extractModelNameFromGeminiPath 从 Gemini API URL 路径中提取模型名 +// 输入格式: /v1beta/models/gemini-2.0-flash:generateContent +// 输出: gemini-2.0-flash +func extractModelNameFromGeminiPath(path string) string { + // 查找 "/models/" 的位置 + modelsPrefix := "/models/" + modelsIndex := strings.Index(path, modelsPrefix) + if modelsIndex == -1 { + return "" + } + + // 从 "/models/" 之后开始提取 + startIndex := modelsIndex + len(modelsPrefix) + if startIndex >= len(path) { + return "" + } + + // 查找 ":" 的位置,模型名在 ":" 之前 + colonIndex := strings.Index(path[startIndex:], ":") + if colonIndex == -1 { + // 如果没有找到 ":",返回从 "/models/" 到路径结尾的部分 + return path[startIndex:] + } + + // 返回模型名部分 + return path[startIndex : startIndex+colonIndex] +} diff --git a/_all-in-one-upload/new-api/middleware/kling_adapter.go b/_all-in-one-upload/new-api/middleware/kling_adapter.go new file mode 100644 index 0000000..e200379 --- /dev/null +++ b/_all-in-one-upload/new-api/middleware/kling_adapter.go @@ -0,0 +1,52 @@ +package middleware + +import ( + "bytes" + "encoding/json" + "io" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + + "github.com/gin-gonic/gin" +) + +func KlingRequestConvert() func(c *gin.Context) { + return func(c *gin.Context) { + var originalReq map[string]interface{} + if err := common.UnmarshalBodyReusable(c, &originalReq); err != nil { + c.Next() + return + } + + // Support both model_name and model fields + model, _ := originalReq["model_name"].(string) + if model == "" { + model, _ = originalReq["model"].(string) + } + prompt, _ := originalReq["prompt"].(string) + + unifiedReq := map[string]interface{}{ + "model": model, + "prompt": prompt, + "metadata": originalReq, + } + + jsonData, err := json.Marshal(unifiedReq) + if err != nil { + c.Next() + return + } + + // Rewrite request body and path + c.Request.Body = io.NopCloser(bytes.NewBuffer(jsonData)) + c.Request.URL.Path = "/v1/video/generations" + if image, ok := originalReq["image"]; !ok || image == "" { + c.Set("action", constant.TaskActionTextGenerate) + } + + // We have to reset the request body for the next handlers + c.Set(common.KeyRequestBody, jsonData) + c.Next() + } +} diff --git a/_all-in-one-upload/new-api/model/setup.go b/_all-in-one-upload/new-api/model/setup.go new file mode 100644 index 0000000..c4d7997 --- /dev/null +++ b/_all-in-one-upload/new-api/model/setup.go @@ -0,0 +1,16 @@ +package model + +type Setup struct { + ID uint `json:"id" gorm:"primaryKey"` + Version string `json:"version" gorm:"type:varchar(50);not null"` + InitializedAt int64 `json:"initialized_at" gorm:"type:bigint;not null"` +} + +func GetSetup() *Setup { + var setup Setup + err := DB.First(&setup).Error + if err != nil { + return nil + } + return &setup +} diff --git a/_all-in-one-upload/new-api/model/user_cache.go b/_all-in-one-upload/new-api/model/user_cache.go new file mode 100644 index 0000000..80d0264 --- /dev/null +++ b/_all-in-one-upload/new-api/model/user_cache.go @@ -0,0 +1,239 @@ +package model + +import ( + "fmt" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + + "github.com/gin-gonic/gin" + + "github.com/bytedance/gopkg/util/gopool" +) + +// UserBase struct remains the same as it represents the cached data structure +type UserBase struct { + Id int `json:"id"` + Group string `json:"group"` + Email string `json:"email"` + Quota int `json:"quota"` + Status int `json:"status"` + Username string `json:"username"` + Setting string `json:"setting"` +} + +func (user *UserBase) WriteContext(c *gin.Context) { + common.SetContextKey(c, constant.ContextKeyUserGroup, user.Group) + common.SetContextKey(c, constant.ContextKeyUserQuota, user.Quota) + common.SetContextKey(c, constant.ContextKeyUserStatus, user.Status) + common.SetContextKey(c, constant.ContextKeyUserEmail, user.Email) + common.SetContextKey(c, constant.ContextKeyUserName, user.Username) + common.SetContextKey(c, constant.ContextKeyUserSetting, user.GetSetting()) +} + +func (user *UserBase) GetSetting() dto.UserSetting { + setting := dto.UserSetting{} + if user.Setting != "" { + err := common.Unmarshal([]byte(user.Setting), &setting) + if err != nil { + common.SysLog("failed to unmarshal setting: " + err.Error()) + } + } + return setting +} + +// getUserCacheKey returns the key for user cache +func getUserCacheKey(userId int) string { + return fmt.Sprintf("user:%d", userId) +} + +// invalidateUserCache clears user cache +func invalidateUserCache(userId int) error { + if !common.RedisEnabled { + return nil + } + return common.RedisDelKey(getUserCacheKey(userId)) +} + +// InvalidateUserCache is the exported version of invalidateUserCache. +// 供 controller 等上层包在用户状态变更(如禁用、删除、角色变更)后主动清理缓存。 +func InvalidateUserCache(userId int) error { + return invalidateUserCache(userId) +} + +// updateUserCache updates all user cache fields using hash +func updateUserCache(user User) error { + if !common.RedisEnabled { + return nil + } + + return common.RedisHSetObj( + getUserCacheKey(user.Id), + user.ToBaseUser(), + time.Duration(common.RedisKeyCacheSeconds())*time.Second, + ) +} + +// GetUserCache gets complete user cache from hash +func GetUserCache(userId int) (userCache *UserBase, err error) { + var user *User + var fromDB bool + defer func() { + // Update Redis cache asynchronously on successful DB read + if shouldUpdateRedis(fromDB, err) && user != nil { + gopool.Go(func() { + if err := updateUserCache(*user); err != nil { + common.SysLog("failed to update user status cache: " + err.Error()) + } + }) + } + }() + + // Try getting from Redis first + userCache, err = cacheGetUserBase(userId) + if err == nil { + return userCache, nil + } + + // If Redis fails, get from DB + fromDB = true + user, err = GetUserById(userId, false) + if err != nil { + return nil, err // Return nil and error if DB lookup fails + } + + // Create cache object from user data + userCache = &UserBase{ + Id: user.Id, + Group: user.Group, + Quota: user.Quota, + Status: user.Status, + Username: user.Username, + Setting: user.Setting, + Email: user.Email, + } + + return userCache, nil +} + +func cacheGetUserBase(userId int) (*UserBase, error) { + if !common.RedisEnabled { + return nil, fmt.Errorf("redis is not enabled") + } + var userCache UserBase + // Try getting from Redis first + err := common.RedisHGetObj(getUserCacheKey(userId), &userCache) + if err != nil { + return nil, err + } + return &userCache, nil +} + +// Add atomic quota operations using hash fields +func cacheIncrUserQuota(userId int, delta int64) error { + if !common.RedisEnabled { + return nil + } + return common.RedisHIncrBy(getUserCacheKey(userId), "Quota", delta) +} + +func cacheDecrUserQuota(userId int, delta int64) error { + return cacheIncrUserQuota(userId, -delta) +} + +// Helper functions to get individual fields if needed +func getUserGroupCache(userId int) (string, error) { + cache, err := GetUserCache(userId) + if err != nil { + return "", err + } + return cache.Group, nil +} + +func getUserQuotaCache(userId int) (int, error) { + cache, err := GetUserCache(userId) + if err != nil { + return 0, err + } + return cache.Quota, nil +} + +func getUserStatusCache(userId int) (int, error) { + cache, err := GetUserCache(userId) + if err != nil { + return 0, err + } + return cache.Status, nil +} + +func getUserNameCache(userId int) (string, error) { + cache, err := GetUserCache(userId) + if err != nil { + return "", err + } + return cache.Username, nil +} + +func getUserSettingCache(userId int) (dto.UserSetting, error) { + cache, err := GetUserCache(userId) + if err != nil { + return dto.UserSetting{}, err + } + return cache.GetSetting(), nil +} + +// New functions for individual field updates +func updateUserStatusCache(userId int, status bool) error { + if !common.RedisEnabled { + return nil + } + statusInt := common.UserStatusEnabled + if !status { + statusInt = common.UserStatusDisabled + } + return common.RedisHSetField(getUserCacheKey(userId), "Status", fmt.Sprintf("%d", statusInt)) +} + +func updateUserQuotaCache(userId int, quota int) error { + if !common.RedisEnabled { + return nil + } + return common.RedisHSetField(getUserCacheKey(userId), "Quota", fmt.Sprintf("%d", quota)) +} + +func updateUserGroupCache(userId int, group string) error { + if !common.RedisEnabled { + return nil + } + return common.RedisHSetField(getUserCacheKey(userId), "Group", group) +} + +func UpdateUserGroupCache(userId int, group string) error { + return updateUserGroupCache(userId, group) +} + +func updateUserNameCache(userId int, username string) error { + if !common.RedisEnabled { + return nil + } + return common.RedisHSetField(getUserCacheKey(userId), "Username", username) +} + +func updateUserSettingCache(userId int, setting string) error { + if !common.RedisEnabled { + return nil + } + return common.RedisHSetField(getUserCacheKey(userId), "Setting", setting) +} + +// GetUserLanguage returns the user's language preference from cache +// Uses the existing GetUserCache mechanism for efficiency +func GetUserLanguage(userId int) string { + userCache, err := GetUserCache(userId) + if err != nil { + return "" + } + return userCache.GetSetting().Language +} diff --git a/_all-in-one-upload/new-api/pkg/billingexpr/billingexpr_test.go b/_all-in-one-upload/new-api/pkg/billingexpr/billingexpr_test.go new file mode 100644 index 0000000..5a5412f --- /dev/null +++ b/_all-in-one-upload/new-api/pkg/billingexpr/billingexpr_test.go @@ -0,0 +1,1094 @@ +package billingexpr_test + +import ( + "math" + "math/rand" + "testing" + + "github.com/QuantumNous/new-api/pkg/billingexpr" +) + +// --------------------------------------------------------------------------- +// Claude-style: fixed tiers, input > 200K changes both input & output price +// --------------------------------------------------------------------------- + +const claudeExpr = `p <= 200000 ? tier("standard", p * 1.5 + c * 7.5) : tier("long_context", p * 3.0 + c * 11.25)` + +func TestClaude_StandardTier(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(claudeExpr, billingexpr.TokenParams{P: 100000, C: 5000}) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "standard") + } +} + +func TestClaude_LongContextTier(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(claudeExpr, billingexpr.TokenParams{P: 300000, C: 10000}) + if err != nil { + t.Fatal(err) + } + want := 300000*3.0 + 10000*11.25 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "long_context" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "long_context") + } +} + +func TestClaude_BoundaryExact(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(claudeExpr, billingexpr.TokenParams{P: 200000, C: 1000}) + if err != nil { + t.Fatal(err) + } + want := 200000*1.5 + 1000*7.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "standard") + } +} + +// --------------------------------------------------------------------------- +// GLM-style: multi-condition tiers with both input and output dimensions +// --------------------------------------------------------------------------- + +const glmExpr = ` +( + p < 32000 && c < 200 ? tier("tier1_short", (p)*2 + c*8) : + p < 32000 && c >= 200 ? tier("tier2_long_output", (p)*3 + c*14) : + tier("tier3_long_input", (p)*4 + c*16) +) / 1000000 +` + +func TestGLM_Tier1(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(glmExpr, billingexpr.TokenParams{P: 15000, C: 100}) + if err != nil { + t.Fatal(err) + } + want := (15000.0*2 + 100.0*8) / 1000000 + if math.Abs(cost-want) > 1e-10 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "tier1_short" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "tier1_short") + } +} + +func TestGLM_Tier2(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(glmExpr, billingexpr.TokenParams{P: 15000, C: 500}) + if err != nil { + t.Fatal(err) + } + want := (15000.0*3 + 500.0*14) / 1000000 + if math.Abs(cost-want) > 1e-10 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "tier2_long_output" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "tier2_long_output") + } +} + +func TestGLM_Tier3(t *testing.T) { + cost, trace, err := billingexpr.RunExpr(glmExpr, billingexpr.TokenParams{P: 50000, C: 100}) + if err != nil { + t.Fatal(err) + } + want := (50000.0*4 + 100.0*16) / 1000000 + if math.Abs(cost-want) > 1e-10 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "tier3_long_input" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "tier3_long_input") + } +} + +// --------------------------------------------------------------------------- +// Simple flat-rate (no tier() call) +// --------------------------------------------------------------------------- + +func TestSimpleExpr_NoTier(t *testing.T) { + cost, trace, err := billingexpr.RunExpr("p * 0.5 + c * 1.0", billingexpr.TokenParams{P: 1000, C: 500}) + if err != nil { + t.Fatal(err) + } + want := 1000*0.5 + 500*1.0 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "" { + t.Errorf("tier should be empty, got %q", trace.MatchedTier) + } +} + +// --------------------------------------------------------------------------- +// Math helper functions +// --------------------------------------------------------------------------- + +func TestMathHelpers(t *testing.T) { + cost, _, err := billingexpr.RunExpr("max(p, c) * 0.5 + min(p, c) * 0.1", billingexpr.TokenParams{P: 300, C: 500}) + if err != nil { + t.Fatal(err) + } + want := 500*0.5 + 300*0.1 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestRequestProbeHelpers(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `p * 0.5 + c * 1.0 * (param("service_tier") == "fast" ? 2 : 1)`, + billingexpr.TokenParams{P: 1000, C: 500}, + billingexpr.RequestInput{ + Body: []byte(`{"service_tier":"fast"}`), + }, + ) + if err != nil { + t.Fatal(err) + } + want := 1000*0.5 + 500*1.0*2 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestHeaderProbeHelper(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `p * 0.5 + c * 1.0 * (has(header("anthropic-beta"), "fast-mode") ? 2 : 1)`, + billingexpr.TokenParams{P: 1000, C: 500}, + billingexpr.RequestInput{ + Headers: map[string]string{ + "Anthropic-Beta": "fast-mode-2026-02-01", + }, + }, + ) + if err != nil { + t.Fatal(err) + } + want := 1000*0.5 + 500*1.0*2 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestParamProbeNestedBool(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `p * (param("stream_options.fast_mode") == true ? 1.5 : 1.0)`, + billingexpr.TokenParams{P: 100}, + billingexpr.RequestInput{ + Body: []byte(`{"stream_options":{"fast_mode":true}}`), + }, + ) + if err != nil { + t.Fatal(err) + } + want := 150.0 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestParamProbeArrayLength(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `p * (param("messages.#") > 20 ? 1.2 : 1.0)`, + billingexpr.TokenParams{P: 100}, + billingexpr.RequestInput{ + Body: []byte(`{"messages":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]}`), + }, + ) + if err != nil { + t.Fatal(err) + } + want := 120.0 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestRequestProbeMissingFieldReturnsNil(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `param("missing.value") == nil ? 2 : 1`, + billingexpr.TokenParams{}, + billingexpr.RequestInput{ + Body: []byte(`{"service_tier":"standard"}`), + }, + ) + if err != nil { + t.Fatal(err) + } + if cost != 2 { + t.Errorf("cost = %f, want 2", cost) + } +} + +func TestRequestProbeMultipleRulesMultiply(t *testing.T) { + cost, _, err := billingexpr.RunExprWithRequest( + `(param("service_tier") == "fast" ? 2 : 1) * (has(header("anthropic-beta"), "fast-mode-2026-02-01") ? 2.5 : 1)`, + billingexpr.TokenParams{}, + billingexpr.RequestInput{ + Headers: map[string]string{ + "Anthropic-Beta": "fast-mode-2026-02-01", + }, + Body: []byte(`{"service_tier":"fast"}`), + }, + ) + if err != nil { + t.Fatal(err) + } + if math.Abs(cost-5) > 1e-6 { + t.Errorf("cost = %f, want 5", cost) + } +} + +func TestCeilFloor(t *testing.T) { + cost, _, err := billingexpr.RunExpr("ceil(p / 1000) * 0.5", billingexpr.TokenParams{P: 1500}) + if err != nil { + t.Fatal(err) + } + want := math.Ceil(1500.0/1000) * 0.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +// --------------------------------------------------------------------------- +// Zero tokens +// --------------------------------------------------------------------------- + +func TestZeroTokens(t *testing.T) { + cost, _, err := billingexpr.RunExpr(claudeExpr, billingexpr.TokenParams{}) + if err != nil { + t.Fatal(err) + } + if cost != 0 { + t.Errorf("cost should be 0 for zero tokens, got %f", cost) + } +} + +// --------------------------------------------------------------------------- +// Rounding +// --------------------------------------------------------------------------- + +func TestQuotaRound(t *testing.T) { + tests := []struct { + in float64 + want int + }{ + {0, 0}, + {0.4, 0}, + {0.5, 1}, + {0.6, 1}, + {1.5, 2}, + {-0.5, -1}, + {-0.6, -1}, + {999.4999, 999}, + {999.5, 1000}, + {1e9 + 0.5, 1e9 + 1}, + } + for _, tt := range tests { + got := billingexpr.QuotaRound(tt.in) + if got != tt.want { + t.Errorf("QuotaRound(%f) = %d, want %d", tt.in, got, tt.want) + } + } +} + +// --------------------------------------------------------------------------- +// Settlement +// --------------------------------------------------------------------------- + +func TestComputeTieredQuota_Basic(t *testing.T) { + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: claudeExpr, + ExprHash: billingexpr.ExprHashString(claudeExpr), + GroupRatio: 1.0, + EstimatedPromptTokens: 100000, + EstimatedCompletionTokens: 5000, + EstimatedQuotaBeforeGroup: (100000*1.5 + 5000*7.5) / 1_000_000 * 500_000, + EstimatedQuotaAfterGroup: billingexpr.QuotaRound((100000*1.5 + 5000*7.5) / 1_000_000 * 500_000), + EstimatedTier: "standard", + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 300000, C: 10000}) + if err != nil { + t.Fatal(err) + } + + wantBefore := (300000*3.0 + 10000*11.25) / 1_000_000 * 500_000 + if math.Abs(result.ActualQuotaBeforeGroup-wantBefore) > 1e-6 { + t.Errorf("before group: got %f, want %f", result.ActualQuotaBeforeGroup, wantBefore) + } + if result.MatchedTier != "long_context" { + t.Errorf("tier = %q, want %q", result.MatchedTier, "long_context") + } + if !result.CrossedTier { + t.Error("expected crossed_tier=true (estimated standard, actual long_context)") + } +} + +func TestComputeTieredQuota_SameTier(t *testing.T) { + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: claudeExpr, + ExprHash: billingexpr.ExprHashString(claudeExpr), + GroupRatio: 1.5, + EstimatedPromptTokens: 50000, + EstimatedCompletionTokens: 1000, + EstimatedQuotaBeforeGroup: (50000*1.5 + 1000*7.5) / 1_000_000 * 500_000, + EstimatedQuotaAfterGroup: billingexpr.QuotaRound((50000*1.5 + 1000*7.5) / 1_000_000 * 500_000 * 1.5), + EstimatedTier: "standard", + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 80000, C: 2000}) + if err != nil { + t.Fatal(err) + } + + wantBefore := (80000*1.5 + 2000*7.5) / 1_000_000 * 500_000 + wantAfter := billingexpr.QuotaRound(wantBefore * 1.5) + if result.ActualQuotaAfterGroup != wantAfter { + t.Errorf("after group: got %d, want %d", result.ActualQuotaAfterGroup, wantAfter) + } + if result.CrossedTier { + t.Error("expected crossed_tier=false (both standard)") + } +} + +// --------------------------------------------------------------------------- +// Compile errors +// --------------------------------------------------------------------------- + +func TestCompileError(t *testing.T) { + _, _, err := billingexpr.RunExpr("invalid +-+ syntax", billingexpr.TokenParams{}) + if err == nil { + t.Error("expected compile error") + } +} + +// --------------------------------------------------------------------------- +// Compile Cache +// --------------------------------------------------------------------------- + +func TestCompileCache_SameResult(t *testing.T) { + r1, _, err := billingexpr.RunExpr("p * 0.5", billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + r2, _, err := billingexpr.RunExpr("p * 0.5", billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + if r1 != r2 { + t.Errorf("cached and uncached results differ: %f != %f", r1, r2) + } +} + +func TestInvalidateCache(t *testing.T) { + billingexpr.InvalidateCache() + r1, _, _ := billingexpr.RunExpr("p * 0.5", billingexpr.TokenParams{P: 100}) + billingexpr.InvalidateCache() + r2, _, _ := billingexpr.RunExpr("p * 0.5", billingexpr.TokenParams{P: 100}) + if r1 != r2 { + t.Errorf("post-invalidate results differ: %f != %f", r1, r2) + } +} + +// --------------------------------------------------------------------------- +// Hash +// --------------------------------------------------------------------------- + +func TestExprHashString_Deterministic(t *testing.T) { + h1 := billingexpr.ExprHashString("p * 0.5") + h2 := billingexpr.ExprHashString("p * 0.5") + if h1 != h2 { + t.Error("hash should be deterministic") + } + h3 := billingexpr.ExprHashString("p * 0.6") + if h1 == h3 { + t.Error("different expressions should have different hashes") + } +} + +// --------------------------------------------------------------------------- +// Cache variables: present +// --------------------------------------------------------------------------- + +const claudeWithCacheExpr = `p <= 200000 ? tier("standard", p * 1.5 + c * 7.5 + cr * 0.15 + cc * 1.875) : tier("long_context", p * 3.0 + c * 11.25 + cr * 0.3 + cc * 3.75)` + +func TestCachePresent_StandardTier(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 5000, CR: 50000, CC: 10000} + cost, trace, err := billingexpr.RunExpr(claudeWithCacheExpr, params) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + 50000*0.15 + 10000*1.875 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "standard") + } +} + +func TestCachePresent_LongContextTier(t *testing.T) { + params := billingexpr.TokenParams{P: 300000, C: 10000, CR: 100000, CC: 20000} + cost, trace, err := billingexpr.RunExpr(claudeWithCacheExpr, params) + if err != nil { + t.Fatal(err) + } + want := 300000*3.0 + 10000*11.25 + 100000*0.3 + 20000*3.75 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "long_context" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "long_context") + } +} + +// --------------------------------------------------------------------------- +// Cache variables: absent (all zero) — same expression still works +// --------------------------------------------------------------------------- + +func TestCacheAbsent_ZeroCacheTokens(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 5000} + cost, trace, err := billingexpr.RunExpr(claudeWithCacheExpr, params) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f (cache terms should be 0)", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "standard") + } +} + +// --------------------------------------------------------------------------- +// Mixed cache fields: cc and cc1h non-zero +// --------------------------------------------------------------------------- + +const claudeCacheSplitExpr = `tier("default", p * 1.5 + c * 7.5 + cr * 0.15 + cc * 2.0 + cc1h * 3.0)` + +func TestMixedCacheFields(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 5000, CR: 10000, CC: 5000, CC1h: 2000} + cost, _, err := billingexpr.RunExpr(claudeCacheSplitExpr, params) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + 10000*0.15 + 5000*2.0 + 2000*3.0 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } +} + +func TestMixedCacheFields_AllCacheZero(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 5000} + cost, _, err := billingexpr.RunExpr(claudeCacheSplitExpr, params) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f (all cache zero)", cost, want) + } +} + +// --------------------------------------------------------------------------- +// Backward compatibility: p+c only expressions still work with TokenParams +// --------------------------------------------------------------------------- + +func TestBackwardCompat_OldExprWithTokenParams(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 5000, CR: 99999, CC: 88888} + cost, trace, err := billingexpr.RunExpr(claudeExpr, params) + if err != nil { + t.Fatal(err) + } + want := 100000*1.5 + 5000*7.5 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f (old expr ignores cache fields)", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", trace.MatchedTier, "standard") + } +} + +// --------------------------------------------------------------------------- +// Settlement with cache tokens +// --------------------------------------------------------------------------- + +func TestComputeTieredQuota_WithCache(t *testing.T) { + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: claudeWithCacheExpr, + ExprHash: billingexpr.ExprHashString(claudeWithCacheExpr), + GroupRatio: 1.0, + EstimatedPromptTokens: 100000, + EstimatedCompletionTokens: 5000, + EstimatedQuotaBeforeGroup: (100000*1.5 + 5000*7.5) / 1_000_000 * 500_000, + EstimatedQuotaAfterGroup: billingexpr.QuotaRound((100000*1.5 + 5000*7.5) / 1_000_000 * 500_000), + EstimatedTier: "standard", + QuotaPerUnit: 500_000, + } + + params := billingexpr.TokenParams{P: 100000, C: 5000, CR: 50000, CC: 10000} + result, err := billingexpr.ComputeTieredQuota(snap, params) + if err != nil { + t.Fatal(err) + } + + wantBefore := (100000*1.5 + 5000*7.5 + 50000*0.15 + 10000*1.875) / 1_000_000 * 500_000 + if math.Abs(result.ActualQuotaBeforeGroup-wantBefore) > 1e-6 { + t.Errorf("before group: got %f, want %f", result.ActualQuotaBeforeGroup, wantBefore) + } + if result.MatchedTier != "standard" { + t.Errorf("tier = %q, want %q", result.MatchedTier, "standard") + } + if result.CrossedTier { + t.Error("expected crossed_tier=false (same tier)") + } +} + +func TestComputeTieredQuota_WithCacheCrossTier(t *testing.T) { + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: claudeWithCacheExpr, + ExprHash: billingexpr.ExprHashString(claudeWithCacheExpr), + GroupRatio: 2.0, + EstimatedPromptTokens: 100000, + EstimatedCompletionTokens: 5000, + EstimatedQuotaBeforeGroup: (100000*1.5 + 5000*7.5) / 1_000_000 * 500_000, + EstimatedQuotaAfterGroup: billingexpr.QuotaRound((100000*1.5 + 5000*7.5) / 1_000_000 * 500_000 * 2.0), + EstimatedTier: "standard", + QuotaPerUnit: 500_000, + } + + params := billingexpr.TokenParams{P: 300000, C: 10000, CR: 50000, CC: 10000} + result, err := billingexpr.ComputeTieredQuota(snap, params) + if err != nil { + t.Fatal(err) + } + + wantBefore := (300000*3.0 + 10000*11.25 + 50000*0.3 + 10000*3.75) / 1_000_000 * 500_000 + wantAfter := billingexpr.QuotaRound(wantBefore * 2.0) + if math.Abs(result.ActualQuotaBeforeGroup-wantBefore) > 1e-6 { + t.Errorf("before group: got %f, want %f", result.ActualQuotaBeforeGroup, wantBefore) + } + if result.ActualQuotaAfterGroup != wantAfter { + t.Errorf("after group: got %d, want %d", result.ActualQuotaAfterGroup, wantAfter) + } + if !result.CrossedTier { + t.Error("expected crossed_tier=true (estimated standard, actual long_context)") + } +} + +// --------------------------------------------------------------------------- +// Fuzz: random p/c/cache, verify non-negative result +// --------------------------------------------------------------------------- + +func TestFuzz_NonNegativeResults(t *testing.T) { + exprs := []string{ + claudeExpr, + claudeWithCacheExpr, + glmExpr, + "p * 0.5 + c * 1.0", + "max(p, c) * 0.1", + "p * 0.5 + cr * 0.1 + cc * 0.2", + } + + rng := rand.New(rand.NewSource(42)) + + for _, exprStr := range exprs { + for i := 0; i < 500; i++ { + params := billingexpr.TokenParams{ + P: math.Round(rng.Float64() * 1000000), + C: math.Round(rng.Float64() * 500000), + CR: math.Round(rng.Float64() * 200000), + CC: math.Round(rng.Float64() * 50000), + CC1h: math.Round(rng.Float64() * 10000), + } + + cost, _, err := billingexpr.RunExpr(exprStr, params) + if err != nil { + t.Fatalf("expr=%q params=%+v: %v", exprStr, params, err) + } + if cost < 0 { + t.Errorf("expr=%q params=%+v: negative cost %f", exprStr, params, cost) + } + } + } +} + +func TestFuzz_SettlementConsistency(t *testing.T) { + rng := rand.New(rand.NewSource(99)) + + for i := 0; i < 200; i++ { + estParams := billingexpr.TokenParams{ + P: math.Round(rng.Float64() * 500000), + C: math.Round(rng.Float64() * 100000), + CR: math.Round(rng.Float64() * 100000), + CC: math.Round(rng.Float64() * 30000), + } + actParams := billingexpr.TokenParams{ + P: math.Round(rng.Float64() * 500000), + C: math.Round(rng.Float64() * 100000), + CR: math.Round(rng.Float64() * 100000), + CC: math.Round(rng.Float64() * 30000), + } + groupRatio := 0.5 + rng.Float64()*2.0 + + estCost, estTrace, _ := billingexpr.RunExpr(claudeWithCacheExpr, estParams) + + const qpu = 500_000.0 + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: claudeWithCacheExpr, + ExprHash: billingexpr.ExprHashString(claudeWithCacheExpr), + GroupRatio: groupRatio, + EstimatedPromptTokens: int(estParams.P), + EstimatedCompletionTokens: int(estParams.C), + EstimatedQuotaBeforeGroup: estCost / 1_000_000 * qpu, + EstimatedQuotaAfterGroup: billingexpr.QuotaRound(estCost / 1_000_000 * qpu * groupRatio), + EstimatedTier: estTrace.MatchedTier, + QuotaPerUnit: qpu, + } + + result, err := billingexpr.ComputeTieredQuota(snap, actParams) + if err != nil { + t.Fatalf("iter %d: %v", i, err) + } + + directCost, _, _ := billingexpr.RunExpr(claudeWithCacheExpr, actParams) + directQuota := billingexpr.QuotaRound(directCost / 1_000_000 * qpu * groupRatio) + + if result.ActualQuotaAfterGroup != directQuota { + t.Errorf("iter %d: settlement %d != direct %d", i, result.ActualQuotaAfterGroup, directQuota) + } + } +} + +// --------------------------------------------------------------------------- +// Settlement-level tests for ComputeTieredQuota +// --------------------------------------------------------------------------- + +func TestComputeTieredQuota_BasicSettlement(t *testing.T) { + exprStr := `tier("default", p + c)` + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 3000, C: 2000}) + if err != nil { + t.Fatal(err) + } + // exprOutput = 5000; quota = 5000 / 1M * 500K = 2500 + if math.Abs(result.ActualQuotaBeforeGroup-2500) > 1e-6 { + t.Errorf("before group = %f, want 2500", result.ActualQuotaBeforeGroup) + } + if result.ActualQuotaAfterGroup != 2500 { + t.Errorf("after group = %d, want 2500", result.ActualQuotaAfterGroup) + } + if result.MatchedTier != "default" { + t.Errorf("tier = %q, want default", result.MatchedTier) + } +} + +func TestComputeTieredQuota_WithGroupRatio(t *testing.T) { + exprStr := `tier("default", p + c)` + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 2.0, + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 1000, C: 500}) + if err != nil { + t.Fatal(err) + } + // exprOutput = 1500; quotaBeforeGroup = 750; afterGroup = round(750 * 2.0) = 1500 + if result.ActualQuotaAfterGroup != 1500 { + t.Errorf("after group = %d, want 1500", result.ActualQuotaAfterGroup) + } +} + +func TestComputeTieredQuota_ZeroTokens(t *testing.T) { + exprStr := `tier("default", p * 2 + c * 10)` + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{}) + if err != nil { + t.Fatal(err) + } + if result.ActualQuotaAfterGroup != 0 { + t.Errorf("after group = %d, want 0", result.ActualQuotaAfterGroup) + } +} + +func TestComputeTieredQuota_RoundingEdge(t *testing.T) { + exprStr := `tier("default", p * 0.5)` // 3 * 0.5 = 1.5 (expr); 1.5 / 1M * 500K = 0.75; round(0.75) = 1 + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 3}) + if err != nil { + t.Fatal(err) + } + // 3 * 0.5 = 1.5 (expr); quota = 1.5 / 1M * 500K = 0.75; round(0.75) = 1 + if result.ActualQuotaAfterGroup != 1 { + t.Errorf("after group = %d, want 1 (round 0.75 up)", result.ActualQuotaAfterGroup) + } +} + +func TestComputeTieredQuota_RoundingEdgeDown(t *testing.T) { + exprStr := `tier("default", p * 0.4)` // 3 * 0.4 = 1.2 (expr); 1.2 / 1M * 500K = 0.6; round(0.6) = 1 + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + QuotaPerUnit: 500_000, + } + + result, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 3}) + if err != nil { + t.Fatal(err) + } + // 3 * 0.4 = 1.2 (expr); quota = 1.2 / 1M * 500K = 0.6; round(0.6) = 1 + if result.ActualQuotaAfterGroup != 1 { + t.Errorf("after group = %d, want 1 (round 0.6 up)", result.ActualQuotaAfterGroup) + } +} + +func TestComputeTieredQuotaWithRequest_ProbeAffectsQuota(t *testing.T) { + exprStr := `param("fast") == true ? tier("fast", p * 4) : tier("normal", p * 2)` + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + EstimatedTier: "normal", + QuotaPerUnit: 500_000, + } + + // Without request: normal tier + r1, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 1000}) + if err != nil { + t.Fatal(err) + } + // normal: p*2 = 2000; quota = 2000 / 1M * 500K = 1000 + if r1.ActualQuotaAfterGroup != 1000 { + t.Errorf("normal = %d, want 1000", r1.ActualQuotaAfterGroup) + } + + // With request: fast tier + r2, err := billingexpr.ComputeTieredQuotaWithRequest(snap, billingexpr.TokenParams{P: 1000}, billingexpr.RequestInput{ + Body: []byte(`{"fast":true}`), + }) + if err != nil { + t.Fatal(err) + } + // fast: p*4 = 4000; quota = 4000 / 1M * 500K = 2000 + if r2.ActualQuotaAfterGroup != 2000 { + t.Errorf("fast = %d, want 2000", r2.ActualQuotaAfterGroup) + } + if !r2.CrossedTier { + t.Error("expected CrossedTier = true when probe changes tier") + } +} + +func TestComputeTieredQuota_BoundaryTierCrossing(t *testing.T) { + exprStr := `p <= 100000 ? tier("small", p * 1) : tier("large", p * 2)` + snap := &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + ExprString: exprStr, + ExprHash: billingexpr.ExprHashString(exprStr), + GroupRatio: 1.0, + EstimatedTier: "small", + QuotaPerUnit: 500_000, + } + + // At boundary: small, p*1 = 100000; quota = 100000 / 1M * 500K = 50000 + r1, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 100000}) + if err != nil { + t.Fatal(err) + } + if r1.MatchedTier != "small" { + t.Errorf("at boundary: tier = %s, want small", r1.MatchedTier) + } + if r1.ActualQuotaAfterGroup != 50000 { + t.Errorf("at boundary: quota = %d, want 50000", r1.ActualQuotaAfterGroup) + } + + // Past boundary: large, p*2 = 200002; quota = 200002 / 1M * 500K = 100001 + r2, err := billingexpr.ComputeTieredQuota(snap, billingexpr.TokenParams{P: 100001}) + if err != nil { + t.Fatal(err) + } + if r2.MatchedTier != "large" { + t.Errorf("past boundary: tier = %s, want large", r2.MatchedTier) + } + if r2.ActualQuotaAfterGroup != 100001 { + t.Errorf("past boundary: quota = %d, want 100001", r2.ActualQuotaAfterGroup) + } + if !r2.CrossedTier { + t.Error("expected CrossedTier = true") + } +} + +// --------------------------------------------------------------------------- +// Time function tests +// --------------------------------------------------------------------------- + +func TestTimeFunctions_ValidTimezone(t *testing.T) { + exprStr := `tier("default", p) * (hour("UTC") >= 0 ? 1 : 1)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + if cost != 100 { + t.Errorf("cost = %f, want 100", cost) + } +} + +func TestTimeFunctions_AllFunctionsCompile(t *testing.T) { + exprStr := `tier("default", p) * (hour("Asia/Shanghai") >= 0 ? 1 : 1) * (minute("UTC") >= 0 ? 1 : 1) * (weekday("UTC") >= 0 ? 1 : 1) * (month("UTC") >= 1 ? 1 : 1) * (day("UTC") >= 1 ? 1 : 1)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 500}) + if err != nil { + t.Fatal(err) + } + if cost != 500 { + t.Errorf("cost = %f, want 500", cost) + } +} + +func TestTimeFunctions_InvalidTimezone(t *testing.T) { + exprStr := `tier("default", p) * (hour("Invalid/Zone") >= 0 ? 1 : 2)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + // Invalid timezone falls back to UTC; hour is 0-23, so condition is always true + if cost != 100 { + t.Errorf("cost = %f, want 100 (fallback to UTC)", cost) + } +} + +func TestTimeFunctions_EmptyTimezone(t *testing.T) { + exprStr := `tier("default", p) * (hour("") >= 0 ? 1 : 2)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + if cost != 100 { + t.Errorf("cost = %f, want 100 (empty tz -> UTC)", cost) + } +} + +func TestTimeFunctions_NightDiscountPattern(t *testing.T) { + exprStr := `tier("default", p * 2 + c * 10) * (hour("UTC") >= 21 || hour("UTC") < 6 ? 0.5 : 1)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 1000, C: 500}) + if err != nil { + t.Fatal(err) + } + // Base = 1000*2 + 500*10 = 7000; multiplier is either 0.5 or 1 depending on current UTC hour + if cost != 7000 && cost != 3500 { + t.Errorf("cost = %f, want 7000 or 3500", cost) + } +} + +func TestTimeFunctions_WeekdayRange(t *testing.T) { + exprStr := `tier("default", p) * (weekday("UTC") >= 0 && weekday("UTC") <= 6 ? 1 : 999)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 100}) + if err != nil { + t.Fatal(err) + } + // weekday is always 0-6, so multiplier is always 1 + if cost != 100 { + t.Errorf("cost = %f, want 100", cost) + } +} + +func TestTimeFunctions_MonthDayPattern(t *testing.T) { + exprStr := `tier("default", p) * (month("Asia/Shanghai") == 1 && day("Asia/Shanghai") == 1 ? 0.5 : 1)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 1000}) + if err != nil { + t.Fatal(err) + } + // Either 1000 (not Jan 1) or 500 (Jan 1) — both are valid + if cost != 1000 && cost != 500 { + t.Errorf("cost = %f, want 1000 or 500", cost) + } +} + +// --------------------------------------------------------------------------- +// Image and audio token tests +// --------------------------------------------------------------------------- + +func TestImageTokenVariable(t *testing.T) { + exprStr := `tier("base", p * 2 + c * 10 + img * 5)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 1000, C: 500, Img: 200}) + if err != nil { + t.Fatal(err) + } + // 1000*2 + 500*10 + 200*5 = 2000 + 5000 + 1000 = 8000 + if math.Abs(cost-8000) > 1e-6 { + t.Errorf("cost = %f, want 8000", cost) + } +} + +func TestAudioTokenVariables(t *testing.T) { + exprStr := `tier("base", p * 2 + c * 10 + ai * 50 + ao * 100)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 1000, C: 500, AI: 100, AO: 50}) + if err != nil { + t.Fatal(err) + } + // 1000*2 + 500*10 + 100*50 + 50*100 = 2000 + 5000 + 5000 + 5000 = 17000 + if math.Abs(cost-17000) > 1e-6 { + t.Errorf("cost = %f, want 17000", cost) + } +} + +func TestImageAudioVariables(t *testing.T) { + exprStr := `tier("base", p * 1 + img * 3 + ai * 5 + ao * 10)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 100, Img: 50, AI: 20, AO: 10}) + if err != nil { + t.Fatal(err) + } + // 100*1 + 50*3 + 20*5 + 10*10 = 100 + 150 + 100 + 100 = 450 + if math.Abs(cost-450) > 1e-6 { + t.Errorf("cost = %f, want 450", cost) + } +} + +func TestImageAudioZero(t *testing.T) { + exprStr := `tier("base", p * 2 + img * 5 + ai * 50 + ao * 100)` + cost, _, err := billingexpr.RunExpr(exprStr, billingexpr.TokenParams{P: 1000}) + if err != nil { + t.Fatal(err) + } + // img, ai, ao default to 0 + if math.Abs(cost-2000) > 1e-6 { + t.Errorf("cost = %f, want 2000", cost) + } +} + +// --------------------------------------------------------------------------- +// len variable tests — tier conditions based on context length +// --------------------------------------------------------------------------- + +const lenTieredExpr = `len <= 200000 ? tier("standard", p * 3 + c * 15 + cr * 0.3) : tier("long_context", p * 6 + c * 22.5 + cr * 0.6)` + +func TestLen_StandardTier(t *testing.T) { + params := billingexpr.TokenParams{P: 80000, C: 5000, Len: 100000, CR: 20000} + cost, trace, err := billingexpr.RunExpr(lenTieredExpr, params) + if err != nil { + t.Fatal(err) + } + want := 80000*3 + 5000*15 + 20000*0.3 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want standard", trace.MatchedTier) + } +} + +func TestLen_LongContextTier(t *testing.T) { + // p is low (cache subtracted), but len is high (full context) + params := billingexpr.TokenParams{P: 50000, C: 5000, Len: 300000, CR: 250000} + cost, trace, err := billingexpr.RunExpr(lenTieredExpr, params) + if err != nil { + t.Fatal(err) + } + want := 50000*6 + 5000*22.5 + 250000*0.6 + if math.Abs(cost-want) > 1e-6 { + t.Errorf("cost = %f, want %f", cost, want) + } + if trace.MatchedTier != "long_context" { + t.Errorf("tier = %q, want long_context (len=300000 > 200000)", trace.MatchedTier) + } +} + +func TestLen_BoundaryExact(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 1000, Len: 200000, CR: 100000} + _, trace, err := billingexpr.RunExpr(lenTieredExpr, params) + if err != nil { + t.Fatal(err) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want standard (len=200000 <= 200000)", trace.MatchedTier) + } +} + +func TestLen_BoundaryPlusOne(t *testing.T) { + params := billingexpr.TokenParams{P: 100000, C: 1000, Len: 200001, CR: 100001} + _, trace, err := billingexpr.RunExpr(lenTieredExpr, params) + if err != nil { + t.Fatal(err) + } + if trace.MatchedTier != "long_context" { + t.Errorf("tier = %q, want long_context (len=200001 > 200000)", trace.MatchedTier) + } +} + +func TestLen_ZeroDefaultsToZero(t *testing.T) { + // len defaults to 0 when not set + params := billingexpr.TokenParams{P: 1000, C: 500} + _, trace, err := billingexpr.RunExpr(lenTieredExpr, params) + if err != nil { + t.Fatal(err) + } + if trace.MatchedTier != "standard" { + t.Errorf("tier = %q, want standard (len=0 <= 200000)", trace.MatchedTier) + } +} + +// --------------------------------------------------------------------------- +// Benchmarks: compile vs cached execution +// --------------------------------------------------------------------------- + +const benchComplexExpr = `len <= 200000 ? tier("standard", p * 3 + c * 15 + cr * 0.3 + cc * 3.75 + cc1h * 6 + img * 3 + img_o * 30 + ai * 10 + ao * 40) : tier("long_context", p * 6 + c * 22.5 + cr * 0.6 + cc * 7.5 + cc1h * 12 + img * 6 + img_o * 60 + ai * 20 + ao * 80)` + +func BenchmarkExprCompile(b *testing.B) { + for i := 0; i < b.N; i++ { + billingexpr.InvalidateCache() + billingexpr.CompileFromCache(benchComplexExpr) + } +} + +func BenchmarkExprRunCached(b *testing.B) { + billingexpr.CompileFromCache(benchComplexExpr) + params := billingexpr.TokenParams{P: 150000, C: 10000, Len: 188000, CR: 30000, CC: 5000, Img: 2000, AI: 1000, AO: 500} + b.ResetTimer() + for i := 0; i < b.N; i++ { + billingexpr.RunExpr(benchComplexExpr, params) + } +} diff --git a/_all-in-one-upload/new-api/pkg/ionet/jsonutil.go b/_all-in-one-upload/new-api/pkg/ionet/jsonutil.go new file mode 100644 index 0000000..0b3219c --- /dev/null +++ b/_all-in-one-upload/new-api/pkg/ionet/jsonutil.go @@ -0,0 +1,96 @@ +package ionet + +import ( + "encoding/json" + "strings" + "time" + + "github.com/samber/lo" +) + +// decodeWithFlexibleTimes unmarshals API responses while tolerating timestamp strings +// that omit timezone information by normalizing them to RFC3339Nano. +func decodeWithFlexibleTimes(data []byte, target interface{}) error { + var intermediate interface{} + if err := json.Unmarshal(data, &intermediate); err != nil { + return err + } + + normalized := normalizeTimeValues(intermediate) + reencoded, err := json.Marshal(normalized) + if err != nil { + return err + } + + return json.Unmarshal(reencoded, target) +} + +func decodeData[T any](data []byte, target *T) error { + var wrapper struct { + Data T `json:"data"` + } + if err := json.Unmarshal(data, &wrapper); err != nil { + return err + } + *target = wrapper.Data + return nil +} + +func decodeDataWithFlexibleTimes[T any](data []byte, target *T) error { + var wrapper struct { + Data T `json:"data"` + } + if err := decodeWithFlexibleTimes(data, &wrapper); err != nil { + return err + } + *target = wrapper.Data + return nil +} + +func normalizeTimeValues(value interface{}) interface{} { + switch v := value.(type) { + case map[string]interface{}: + return lo.MapValues(v, func(val interface{}, _ string) interface{} { + return normalizeTimeValues(val) + }) + case []interface{}: + return lo.Map(v, func(item interface{}, _ int) interface{} { + return normalizeTimeValues(item) + }) + case string: + if normalized, changed := normalizeTimeString(v); changed { + return normalized + } + return v + default: + return value + } +} + +func normalizeTimeString(input string) (string, bool) { + trimmed := strings.TrimSpace(input) + if trimmed == "" { + return input, false + } + + if _, err := time.Parse(time.RFC3339Nano, trimmed); err == nil { + return trimmed, trimmed != input + } + if _, err := time.Parse(time.RFC3339, trimmed); err == nil { + return trimmed, trimmed != input + } + + layouts := []string{ + "2006-01-02T15:04:05.999999999", + "2006-01-02T15:04:05.999999", + "2006-01-02T15:04:05", + } + + for _, layout := range layouts { + if parsed, err := time.Parse(layout, trimmed); err == nil { + return parsed.UTC().Format(time.RFC3339Nano), true + } + } + + return input, false +} diff --git a/_all-in-one-upload/new-api/relay/channel/ali/constants.go b/_all-in-one-upload/new-api/relay/channel/ali/constants.go new file mode 100644 index 0000000..df64439 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/ali/constants.go @@ -0,0 +1,14 @@ +package ali + +var ModelList = []string{ + "qwen-turbo", + "qwen-plus", + "qwen-max", + "qwen-max-longcontext", + "qwq-32b", + "qwen3-235b-a22b", + "text-embedding-v1", + "gte-rerank-v2", +} + +var ChannelName = "ali" diff --git a/_all-in-one-upload/new-api/relay/channel/gemini/relay-gemini.go b/_all-in-one-upload/new-api/relay/channel/gemini/relay-gemini.go new file mode 100644 index 0000000..355c75d --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/gemini/relay-gemini.go @@ -0,0 +1,1725 @@ +package gemini + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "time" + "unicode/utf8" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/logger" + "github.com/QuantumNous/new-api/relay/channel/openai" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/relay/helper" + "github.com/QuantumNous/new-api/service" + "github.com/QuantumNous/new-api/setting/model_setting" + "github.com/QuantumNous/new-api/setting/reasoning" + "github.com/QuantumNous/new-api/types" + "github.com/gin-gonic/gin" + "github.com/samber/lo" +) + +// https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference?hl=zh-cn#blob +var geminiSupportedMimeTypes = map[string]bool{ + "application/pdf": true, + "audio/mpeg": true, + "audio/mp3": true, + "audio/wav": true, + "image/png": true, + "image/jpeg": true, + "image/jpg": true, // support old image/jpeg + "image/webp": true, + "image/heic": true, + "image/heif": true, + "text/plain": true, + "video/mov": true, + "video/mpeg": true, + "video/mp4": true, + "video/mpg": true, + "video/avi": true, + "video/wmv": true, + "video/mpegps": true, + "video/flv": true, +} + +const thoughtSignatureBypassValue = "context_engineering_is_the_way_to_go" + +// Gemini 允许的思考预算范围 +const ( + pro25MinBudget = 128 + pro25MaxBudget = 32768 + flash25MaxBudget = 24576 + flash25LiteMinBudget = 512 + flash25LiteMaxBudget = 24576 +) + +func isNew25ProModel(modelName string) bool { + return strings.HasPrefix(modelName, "gemini-2.5-pro") && + !strings.HasPrefix(modelName, "gemini-2.5-pro-preview-05-06") && + !strings.HasPrefix(modelName, "gemini-2.5-pro-preview-03-25") +} + +func is25FlashLiteModel(modelName string) bool { + return strings.HasPrefix(modelName, "gemini-2.5-flash-lite") +} + +// clampThinkingBudget 根据模型名称将预算限制在允许的范围内 +func clampThinkingBudget(modelName string, budget int) int { + isNew25Pro := isNew25ProModel(modelName) + is25FlashLite := is25FlashLiteModel(modelName) + + if is25FlashLite { + if budget < flash25LiteMinBudget { + return flash25LiteMinBudget + } + if budget > flash25LiteMaxBudget { + return flash25LiteMaxBudget + } + } else if isNew25Pro { + if budget < pro25MinBudget { + return pro25MinBudget + } + if budget > pro25MaxBudget { + return pro25MaxBudget + } + } else { // 其他模型 + if budget < 0 { + return 0 + } + if budget > flash25MaxBudget { + return flash25MaxBudget + } + } + return budget +} + +// "effort": "high" - Allocates a large portion of tokens for reasoning (approximately 80% of max_tokens) +// "effort": "medium" - Allocates a moderate portion of tokens (approximately 50% of max_tokens) +// "effort": "low" - Allocates a smaller portion of tokens (approximately 20% of max_tokens) +// "effort": "minimal" - Allocates a minimal portion of tokens (approximately 5% of max_tokens) +func clampThinkingBudgetByEffort(modelName string, effort string) int { + isNew25Pro := isNew25ProModel(modelName) + is25FlashLite := is25FlashLiteModel(modelName) + + maxBudget := 0 + if is25FlashLite { + maxBudget = flash25LiteMaxBudget + } + if isNew25Pro { + maxBudget = pro25MaxBudget + } else { + maxBudget = flash25MaxBudget + } + switch effort { + case "high": + maxBudget = maxBudget * 80 / 100 + case "medium": + maxBudget = maxBudget * 50 / 100 + case "low": + maxBudget = maxBudget * 20 / 100 + case "minimal": + maxBudget = maxBudget * 5 / 100 + } + return clampThinkingBudget(modelName, maxBudget) +} + +func ThinkingAdaptor(geminiRequest *dto.GeminiChatRequest, info *relaycommon.RelayInfo, oaiRequest ...dto.GeneralOpenAIRequest) { + if model_setting.GetGeminiSettings().ThinkingAdapterEnabled { + modelName := info.UpstreamModelName + isNew25Pro := strings.HasPrefix(modelName, "gemini-2.5-pro") && + !strings.HasPrefix(modelName, "gemini-2.5-pro-preview-05-06") && + !strings.HasPrefix(modelName, "gemini-2.5-pro-preview-03-25") + + if strings.Contains(modelName, "-thinking-") { + parts := strings.SplitN(modelName, "-thinking-", 2) + if len(parts) == 2 && parts[1] != "" { + if budgetTokens, err := strconv.Atoi(parts[1]); err == nil { + clampedBudget := clampThinkingBudget(modelName, budgetTokens) + geminiRequest.GenerationConfig.ThinkingConfig = &dto.GeminiThinkingConfig{ + ThinkingBudget: common.GetPointer(clampedBudget), + IncludeThoughts: true, + } + } + } + } else if strings.HasSuffix(modelName, "-thinking") { + unsupportedModels := []string{ + "gemini-2.5-pro-preview-05-06", + "gemini-2.5-pro-preview-03-25", + } + isUnsupported := false + for _, unsupportedModel := range unsupportedModels { + if strings.HasPrefix(modelName, unsupportedModel) { + isUnsupported = true + break + } + } + + if isUnsupported { + geminiRequest.GenerationConfig.ThinkingConfig = &dto.GeminiThinkingConfig{ + IncludeThoughts: true, + } + } else { + geminiRequest.GenerationConfig.ThinkingConfig = &dto.GeminiThinkingConfig{ + IncludeThoughts: true, + } + if geminiRequest.GenerationConfig.MaxOutputTokens != nil && *geminiRequest.GenerationConfig.MaxOutputTokens > 0 { + budgetTokens := model_setting.GetGeminiSettings().ThinkingAdapterBudgetTokensPercentage * float64(*geminiRequest.GenerationConfig.MaxOutputTokens) + clampedBudget := clampThinkingBudget(modelName, int(budgetTokens)) + geminiRequest.GenerationConfig.ThinkingConfig.ThinkingBudget = common.GetPointer(clampedBudget) + } else { + if len(oaiRequest) > 0 { + // 如果有reasoningEffort参数,则根据其值设置思考预算 + geminiRequest.GenerationConfig.ThinkingConfig.ThinkingBudget = common.GetPointer(clampThinkingBudgetByEffort(modelName, oaiRequest[0].ReasoningEffort)) + } + } + } + } else if strings.HasSuffix(modelName, "-nothinking") { + if !isNew25Pro { + geminiRequest.GenerationConfig.ThinkingConfig = &dto.GeminiThinkingConfig{ + ThinkingBudget: common.GetPointer(0), + } + } + } else if _, level, ok := reasoning.TrimEffortSuffix(info.UpstreamModelName); ok && level != "" { + geminiRequest.GenerationConfig.ThinkingConfig = &dto.GeminiThinkingConfig{ + IncludeThoughts: true, + ThinkingLevel: level, + } + info.ReasoningEffort = level + } + } +} + +// Setting safety to the lowest possible values since Gemini is already powerless enough +func CovertOpenAI2Gemini(c *gin.Context, textRequest dto.GeneralOpenAIRequest, info *relaycommon.RelayInfo) (*dto.GeminiChatRequest, error) { + + geminiRequest := dto.GeminiChatRequest{ + Contents: make([]dto.GeminiChatContent, 0, len(textRequest.Messages)), + GenerationConfig: dto.GeminiChatGenerationConfig{ + Temperature: textRequest.Temperature, + }, + } + + if textRequest.TopP != nil && *textRequest.TopP > 0 { + geminiRequest.GenerationConfig.TopP = common.GetPointer(*textRequest.TopP) + } + + if maxTokens := textRequest.GetMaxTokens(); maxTokens > 0 { + geminiRequest.GenerationConfig.MaxOutputTokens = common.GetPointer(maxTokens) + } + + if textRequest.Seed != nil && *textRequest.Seed != 0 { + geminiSeed := int64(lo.FromPtr(textRequest.Seed)) + geminiRequest.GenerationConfig.Seed = common.GetPointer(geminiSeed) + } + + attachThoughtSignature := (info.ChannelType == constant.ChannelTypeGemini || + info.ChannelType == constant.ChannelTypeVertexAi) && + model_setting.GetGeminiSettings().FunctionCallThoughtSignatureEnabled + + if model_setting.IsGeminiModelSupportImagine(info.UpstreamModelName) { + geminiRequest.GenerationConfig.ResponseModalities = []string{ + "TEXT", + "IMAGE", + } + } + if stopSequences := parseStopSequences(textRequest.Stop); len(stopSequences) > 0 { + // Gemini supports up to 5 stop sequences + if len(stopSequences) > 5 { + stopSequences = stopSequences[:5] + } + geminiRequest.GenerationConfig.StopSequences = stopSequences + } + + adaptorWithExtraBody := false + + // patch extra_body + if len(textRequest.ExtraBody) > 0 { + var extraBody map[string]interface{} + if err := common.Unmarshal(textRequest.ExtraBody, &extraBody); err != nil { + return nil, fmt.Errorf("invalid extra body: %w", err) + } + + // eg. {"google":{"thinking_config":{"thinking_budget":5324,"include_thoughts":true}}} + if googleBody, ok := extraBody["google"].(map[string]interface{}); ok { + if !strings.HasSuffix(info.UpstreamModelName, "-nothinking") { + adaptorWithExtraBody = true + // check error param name like thinkingConfig, should be thinking_config + if _, hasErrorParam := googleBody["thinkingConfig"]; hasErrorParam { + return nil, errors.New("extra_body.google.thinkingConfig is not supported, use extra_body.google.thinking_config instead") + } + + if thinkingConfig, ok := googleBody["thinking_config"].(map[string]interface{}); ok { + // check error param name like thinkingBudget, should be thinking_budget + if _, hasErrorParam := thinkingConfig["thinkingBudget"]; hasErrorParam { + return nil, errors.New("extra_body.google.thinking_config.thinkingBudget is not supported, use extra_body.google.thinking_config.thinking_budget instead") + } + var hasThinkingConfig bool + var tempThinkingConfig dto.GeminiThinkingConfig + + if thinkingBudget, exists := thinkingConfig["thinking_budget"]; exists { + switch v := thinkingBudget.(type) { + case float64: + budgetInt := int(v) + tempThinkingConfig.ThinkingBudget = common.GetPointer(budgetInt) + if budgetInt > 0 { + // 有正数预算 + tempThinkingConfig.IncludeThoughts = true + } else { + // 存在但为0或负数,禁用思考 + tempThinkingConfig.IncludeThoughts = false + } + hasThinkingConfig = true + default: + return nil, errors.New("extra_body.google.thinking_config.thinking_budget must be an integer") + } + } + + if includeThoughts, exists := thinkingConfig["include_thoughts"]; exists { + if v, ok := includeThoughts.(bool); ok { + tempThinkingConfig.IncludeThoughts = v + hasThinkingConfig = true + } else { + return nil, errors.New("extra_body.google.thinking_config.include_thoughts must be a boolean") + } + } + if thinkingLevel, exists := thinkingConfig["thinking_level"]; exists { + if v, ok := thinkingLevel.(string); ok { + tempThinkingConfig.ThinkingLevel = v + hasThinkingConfig = true + } else { + return nil, errors.New("extra_body.google.thinking_config.thinking_level must be a string") + } + } + + if hasThinkingConfig { + // 避免 panic: 仅在获得配置时分配,防止后续赋值时空指针 + if geminiRequest.GenerationConfig.ThinkingConfig == nil { + geminiRequest.GenerationConfig.ThinkingConfig = &tempThinkingConfig + } else { + // 如果已分配,则合并内容 + if tempThinkingConfig.ThinkingBudget != nil { + geminiRequest.GenerationConfig.ThinkingConfig.ThinkingBudget = tempThinkingConfig.ThinkingBudget + } + geminiRequest.GenerationConfig.ThinkingConfig.IncludeThoughts = tempThinkingConfig.IncludeThoughts + if tempThinkingConfig.ThinkingLevel != "" { + geminiRequest.GenerationConfig.ThinkingConfig.ThinkingLevel = tempThinkingConfig.ThinkingLevel + } + } + } + } + } + + // check error param name like imageConfig, should be image_config + if _, hasErrorParam := googleBody["imageConfig"]; hasErrorParam { + return nil, errors.New("extra_body.google.imageConfig is not supported, use extra_body.google.image_config instead") + } + + if imageConfig, ok := googleBody["image_config"].(map[string]interface{}); ok { + // check error param name like aspectRatio, should be aspect_ratio + if _, hasErrorParam := imageConfig["aspectRatio"]; hasErrorParam { + return nil, errors.New("extra_body.google.image_config.aspectRatio is not supported, use extra_body.google.image_config.aspect_ratio instead") + } + // check error param name like imageSize, should be image_size + if _, hasErrorParam := imageConfig["imageSize"]; hasErrorParam { + return nil, errors.New("extra_body.google.image_config.imageSize is not supported, use extra_body.google.image_config.image_size instead") + } + + // convert snake_case to camelCase for Gemini API + geminiImageConfig := make(map[string]interface{}) + if aspectRatio, ok := imageConfig["aspect_ratio"]; ok { + geminiImageConfig["aspectRatio"] = aspectRatio + } + if imageSize, ok := imageConfig["image_size"]; ok { + geminiImageConfig["imageSize"] = imageSize + } + + if len(geminiImageConfig) > 0 { + imageConfigBytes, err := common.Marshal(geminiImageConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal image_config: %w", err) + } + geminiRequest.GenerationConfig.ImageConfig = imageConfigBytes + } + } + } + } + + if !adaptorWithExtraBody { + ThinkingAdaptor(&geminiRequest, info, textRequest) + } + + safetySettings := make([]dto.GeminiChatSafetySettings, 0, len(SafetySettingList)) + for _, category := range SafetySettingList { + safetySettings = append(safetySettings, dto.GeminiChatSafetySettings{ + Category: category, + Threshold: model_setting.GetGeminiSafetySetting(category), + }) + } + geminiRequest.SafetySettings = safetySettings + + // openaiContent.FuncToToolCalls() + if textRequest.Tools != nil { + functions := make([]dto.FunctionRequest, 0, len(textRequest.Tools)) + googleSearch := false + codeExecution := false + urlContext := false + for _, tool := range textRequest.Tools { + if tool.Function.Name == "googleSearch" { + googleSearch = true + continue + } + if tool.Function.Name == "codeExecution" { + codeExecution = true + continue + } + if tool.Function.Name == "urlContext" { + urlContext = true + continue + } + if tool.Function.Parameters != nil { + + params, ok := tool.Function.Parameters.(map[string]interface{}) + if ok { + if props, hasProps := params["properties"].(map[string]interface{}); hasProps { + if len(props) == 0 { + tool.Function.Parameters = nil + } + } + } + } + // Clean the parameters before appending + cleanedParams := cleanFunctionParameters(tool.Function.Parameters) + tool.Function.Parameters = cleanedParams + functions = append(functions, tool.Function) + } + geminiTools := geminiRequest.GetTools() + if codeExecution { + geminiTools = append(geminiTools, dto.GeminiChatTool{ + CodeExecution: make(map[string]string), + }) + } + if googleSearch { + geminiTools = append(geminiTools, dto.GeminiChatTool{ + GoogleSearch: make(map[string]string), + }) + } + if urlContext { + geminiTools = append(geminiTools, dto.GeminiChatTool{ + URLContext: make(map[string]string), + }) + } + if len(functions) > 0 { + geminiTools = append(geminiTools, dto.GeminiChatTool{ + FunctionDeclarations: functions, + }) + } + geminiRequest.SetTools(geminiTools) + + // [NEW] Convert OpenAI tool_choice to Gemini toolConfig.functionCallingConfig + // Mapping: "auto" -> "AUTO", "none" -> "NONE", "required" -> "ANY" + // Object format: {"type": "function", "function": {"name": "xxx"}} -> "ANY" + allowedFunctionNames + if textRequest.ToolChoice != nil { + geminiRequest.ToolConfig = convertToolChoiceToGeminiConfig(textRequest.ToolChoice) + } + } + + if textRequest.ResponseFormat != nil && (textRequest.ResponseFormat.Type == "json_schema" || textRequest.ResponseFormat.Type == "json_object") { + geminiRequest.GenerationConfig.ResponseMimeType = "application/json" + + if len(textRequest.ResponseFormat.JsonSchema) > 0 { + // 先将json.RawMessage解析 + var jsonSchema dto.FormatJsonSchema + if err := common.Unmarshal(textRequest.ResponseFormat.JsonSchema, &jsonSchema); err == nil { + cleanedSchema := removeAdditionalPropertiesWithDepth(jsonSchema.Schema, 0) + geminiRequest.GenerationConfig.ResponseSchema = cleanedSchema + } + } + } + tool_call_ids := make(map[string]string) + var system_content []string + //shouldAddDummyModelMessage := false + for _, message := range textRequest.Messages { + if message.Role == "system" || message.Role == "developer" { + system_content = append(system_content, message.StringContent()) + continue + } else if message.Role == "tool" || message.Role == "function" { + if len(geminiRequest.Contents) == 0 || geminiRequest.Contents[len(geminiRequest.Contents)-1].Role == "model" { + geminiRequest.Contents = append(geminiRequest.Contents, dto.GeminiChatContent{ + Role: "user", + }) + } + var parts = &geminiRequest.Contents[len(geminiRequest.Contents)-1].Parts + name := "" + if message.Name != nil { + name = *message.Name + } else if val, exists := tool_call_ids[message.ToolCallId]; exists { + name = val + } + var contentMap map[string]interface{} + contentStr := message.StringContent() + + // 1. 尝试解析为 JSON 对象 + if err := json.Unmarshal([]byte(contentStr), &contentMap); err != nil { + // 2. 如果失败,尝试解析为 JSON 数组 + var contentSlice []interface{} + if err := json.Unmarshal([]byte(contentStr), &contentSlice); err == nil { + // 如果是数组,包装成对象 + contentMap = map[string]interface{}{"result": contentSlice} + } else { + // 3. 如果再次失败,作为纯文本处理 + contentMap = map[string]interface{}{"content": contentStr} + } + } + + functionResp := &dto.GeminiFunctionResponse{ + Name: name, + Response: contentMap, + } + + *parts = append(*parts, dto.GeminiPart{ + FunctionResponse: functionResp, + }) + continue + } + var parts []dto.GeminiPart + content := dto.GeminiChatContent{ + Role: message.Role, + } + shouldAttachThoughtSignature := attachThoughtSignature && (message.Role == "assistant" || message.Role == "model") + signatureAttached := false + // isToolCall := false + if message.ToolCalls != nil { + // message.Role = "model" + // isToolCall = true + for _, call := range message.ParseToolCalls() { + args := map[string]interface{}{} + if call.Function.Arguments != "" { + if json.Unmarshal([]byte(call.Function.Arguments), &args) != nil { + return nil, fmt.Errorf("invalid arguments for function %s, args: %s", call.Function.Name, call.Function.Arguments) + } + } + toolCall := dto.GeminiPart{ + FunctionCall: &dto.FunctionCall{ + FunctionName: call.Function.Name, + Arguments: args, + }, + } + if shouldAttachThoughtSignature && !signatureAttached && hasFunctionCallContent(toolCall.FunctionCall) && len(toolCall.ThoughtSignature) == 0 { + toolCall.ThoughtSignature = json.RawMessage(strconv.Quote(thoughtSignatureBypassValue)) + signatureAttached = true + } + parts = append(parts, toolCall) + tool_call_ids[call.ID] = call.Function.Name + } + } + + openaiContent := message.ParseContent() + for _, part := range openaiContent { + if part.Type == dto.ContentTypeText { + if part.Text == "" { + continue + } + // check markdown image ![image](data:image/jpeg;base64,xxxxxxxxxxxx) + // 使用字符串查找而非正则,避免大文本性能问题 + text := part.Text + hasMarkdownImage := false + for { + // 快速检查是否包含 markdown 图片标记 + startIdx := strings.Index(text, "![") + if startIdx == -1 { + break + } + // 找到 ]( + bracketIdx := strings.Index(text[startIdx:], "](data:") + if bracketIdx == -1 { + break + } + bracketIdx += startIdx + // 找到闭合的 ) + closeIdx := strings.Index(text[bracketIdx+2:], ")") + if closeIdx == -1 { + break + } + closeIdx += bracketIdx + 2 + + hasMarkdownImage = true + // 添加图片前的文本 + if startIdx > 0 { + textBefore := text[:startIdx] + if textBefore != "" { + parts = append(parts, dto.GeminiPart{ + Text: textBefore, + }) + } + } + // 提取 data URL (从 "](" 后面开始,到 ")" 之前) + dataUrl := text[bracketIdx+2 : closeIdx] + format, base64String, err := service.DecodeBase64FileData(dataUrl) + if err != nil { + return nil, fmt.Errorf("decode markdown base64 image data failed: %s", err.Error()) + } + imgPart := dto.GeminiPart{ + InlineData: &dto.GeminiInlineData{ + MimeType: format, + Data: base64String, + }, + } + if shouldAttachThoughtSignature { + imgPart.ThoughtSignature = json.RawMessage(strconv.Quote(thoughtSignatureBypassValue)) + } + parts = append(parts, imgPart) + // 继续处理剩余文本 + text = text[closeIdx+1:] + } + // 添加剩余文本或原始文本(如果没有找到 markdown 图片) + if !hasMarkdownImage { + parts = append(parts, dto.GeminiPart{ + Text: part.Text, + }) + } + } else { + source := part.ToFileSource() + if source == nil { + continue + } + base64Data, mimeType, err := service.GetBase64Data(c, source, "formatting image for Gemini") + if err != nil { + return nil, fmt.Errorf("get file data from '%s' failed: %w", source.GetIdentifier(), err) + } + + // 校验 MimeType 是否在 Gemini 支持的白名单中 + if _, ok := geminiSupportedMimeTypes[strings.ToLower(mimeType)]; !ok { + return nil, fmt.Errorf("mime type is not supported by Gemini: '%s', url: '%s', supported types are: %v", mimeType, source.GetIdentifier(), getSupportedMimeTypesList()) + } + + parts = append(parts, dto.GeminiPart{ + InlineData: &dto.GeminiInlineData{ + MimeType: mimeType, + Data: base64Data, + }, + }) + } + } + + // 如果需要附加签名但还没有附加(没有 tool_calls 或 tool_calls 为空), + // 则在第一个文本 part 上附加 thoughtSignature + if shouldAttachThoughtSignature && !signatureAttached && len(parts) > 0 { + for i := range parts { + if parts[i].Text != "" { + parts[i].ThoughtSignature = json.RawMessage(strconv.Quote(thoughtSignatureBypassValue)) + break + } + } + } + + content.Parts = parts + + // there's no assistant role in gemini and API shall vomit if Role is not user or model + if content.Role == "assistant" { + content.Role = "model" + } + if len(content.Parts) > 0 { + geminiRequest.Contents = append(geminiRequest.Contents, content) + } + } + + if len(system_content) > 0 { + geminiRequest.SystemInstructions = &dto.GeminiChatContent{ + Parts: []dto.GeminiPart{ + { + Text: strings.Join(system_content, "\n"), + }, + }, + } + } + + return &geminiRequest, nil +} + +// parseStopSequences 解析停止序列,支持字符串或字符串数组 +func parseStopSequences(stop any) []string { + if stop == nil { + return nil + } + + switch v := stop.(type) { + case string: + if v != "" { + return []string{v} + } + case []string: + return v + case []interface{}: + sequences := make([]string, 0, len(v)) + for _, item := range v { + if str, ok := item.(string); ok && str != "" { + sequences = append(sequences, str) + } + } + return sequences + } + return nil +} + +func hasFunctionCallContent(call *dto.FunctionCall) bool { + if call == nil { + return false + } + if strings.TrimSpace(call.FunctionName) != "" { + return true + } + + switch v := call.Arguments.(type) { + case nil: + return false + case string: + return strings.TrimSpace(v) != "" + case map[string]interface{}: + return len(v) > 0 + case []interface{}: + return len(v) > 0 + default: + return true + } +} + +// Helper function to get a list of supported MIME types for error messages +func getSupportedMimeTypesList() []string { + keys := make([]string, 0, len(geminiSupportedMimeTypes)) + for k := range geminiSupportedMimeTypes { + keys = append(keys, k) + } + return keys +} + +var geminiOpenAPISchemaAllowedFields = map[string]struct{}{ + "anyOf": {}, + "default": {}, + "description": {}, + "enum": {}, + "example": {}, + "format": {}, + "items": {}, + "maxItems": {}, + "maxLength": {}, + "maxProperties": {}, + "maximum": {}, + "minItems": {}, + "minLength": {}, + "minProperties": {}, + "minimum": {}, + "nullable": {}, + "pattern": {}, + "properties": {}, + "propertyOrdering": {}, + "required": {}, + "title": {}, + "type": {}, +} + +const geminiFunctionSchemaMaxDepth = 64 + +// cleanFunctionParameters recursively removes unsupported fields from Gemini function parameters. +func cleanFunctionParameters(params interface{}) interface{} { + return cleanFunctionParametersWithDepth(params, 0) +} + +func cleanFunctionParametersWithDepth(params interface{}, depth int) interface{} { + if params == nil { + return nil + } + + if depth >= geminiFunctionSchemaMaxDepth { + return cleanFunctionParametersShallow(params) + } + + switch v := params.(type) { + case map[string]interface{}: + // Keep only Gemini-supported OpenAPI schema subset fields (per official SDK Schema). + cleanedMap := make(map[string]interface{}, len(v)) + for k, val := range v { + if _, ok := geminiOpenAPISchemaAllowedFields[k]; ok { + cleanedMap[k] = val + } + } + + normalizeGeminiSchemaTypeAndNullable(cleanedMap) + + // Clean properties + if props, ok := cleanedMap["properties"].(map[string]interface{}); ok && props != nil { + cleanedProps := make(map[string]interface{}) + for propName, propValue := range props { + cleanedProps[propName] = cleanFunctionParametersWithDepth(propValue, depth+1) + } + cleanedMap["properties"] = cleanedProps + } + + // Recursively clean items in arrays + if items, ok := cleanedMap["items"].(map[string]interface{}); ok && items != nil { + cleanedMap["items"] = cleanFunctionParametersWithDepth(items, depth+1) + } + // OpenAPI tuple-style items is not supported by Gemini SDK Schema; keep first to avoid API rejection. + if itemsArray, ok := cleanedMap["items"].([]interface{}); ok && len(itemsArray) > 0 { + cleanedMap["items"] = cleanFunctionParametersWithDepth(itemsArray[0], depth+1) + } + + // Recursively clean anyOf + if nested, ok := cleanedMap["anyOf"].([]interface{}); ok && nested != nil { + cleanedNested := make([]interface{}, len(nested)) + for i, item := range nested { + cleanedNested[i] = cleanFunctionParametersWithDepth(item, depth+1) + } + cleanedMap["anyOf"] = cleanedNested + } + + return cleanedMap + + case []interface{}: + // Handle arrays of schemas + cleanedArray := make([]interface{}, len(v)) + for i, item := range v { + cleanedArray[i] = cleanFunctionParametersWithDepth(item, depth+1) + } + return cleanedArray + + default: + // Not a map or array, return as is (e.g., could be a primitive) + return params + } +} + +func cleanFunctionParametersShallow(params interface{}) interface{} { + switch v := params.(type) { + case map[string]interface{}: + cleanedMap := make(map[string]interface{}, len(v)) + for k, val := range v { + if _, ok := geminiOpenAPISchemaAllowedFields[k]; ok { + cleanedMap[k] = val + } + } + normalizeGeminiSchemaTypeAndNullable(cleanedMap) + // Stop recursion and avoid retaining huge nested structures. + delete(cleanedMap, "properties") + delete(cleanedMap, "items") + delete(cleanedMap, "anyOf") + return cleanedMap + case []interface{}: + // Prefer an empty list over deep recursion on attacker-controlled inputs. + return []interface{}{} + default: + return params + } +} + +func normalizeGeminiSchemaTypeAndNullable(schema map[string]interface{}) { + rawType, ok := schema["type"] + if !ok || rawType == nil { + return + } + + normalize := func(t string) (string, bool) { + switch strings.ToLower(strings.TrimSpace(t)) { + case "object": + return "OBJECT", false + case "array": + return "ARRAY", false + case "string": + return "STRING", false + case "integer": + return "INTEGER", false + case "number": + return "NUMBER", false + case "boolean": + return "BOOLEAN", false + case "null": + return "", true + default: + return t, false + } + } + + switch t := rawType.(type) { + case string: + normalized, isNull := normalize(t) + if isNull { + schema["nullable"] = true + delete(schema, "type") + return + } + schema["type"] = normalized + case []interface{}: + nullable := false + var chosen string + for _, item := range t { + if s, ok := item.(string); ok { + normalized, isNull := normalize(s) + if isNull { + nullable = true + continue + } + if chosen == "" { + chosen = normalized + } + } + } + if nullable { + schema["nullable"] = true + } + if chosen != "" { + schema["type"] = chosen + } else { + delete(schema, "type") + } + } +} + +func removeAdditionalPropertiesWithDepth(schema interface{}, depth int) interface{} { + if depth >= 5 { + return schema + } + + v, ok := schema.(map[string]interface{}) + if !ok || len(v) == 0 { + return schema + } + // 删除所有的title字段 + delete(v, "title") + delete(v, "$schema") + // 如果type不为object和array,则直接返回 + if typeVal, exists := v["type"]; !exists || (typeVal != "object" && typeVal != "array") { + return schema + } + switch v["type"] { + case "object": + delete(v, "additionalProperties") + // 处理 properties + if properties, ok := v["properties"].(map[string]interface{}); ok { + for key, value := range properties { + properties[key] = removeAdditionalPropertiesWithDepth(value, depth+1) + } + } + for _, field := range []string{"allOf", "anyOf", "oneOf"} { + if nested, ok := v[field].([]interface{}); ok { + for i, item := range nested { + nested[i] = removeAdditionalPropertiesWithDepth(item, depth+1) + } + } + } + case "array": + if items, ok := v["items"].(map[string]interface{}); ok { + v["items"] = removeAdditionalPropertiesWithDepth(items, depth+1) + } + } + + return v +} + +func unescapeString(s string) (string, error) { + var result []rune + escaped := false + i := 0 + + for i < len(s) { + r, size := utf8.DecodeRuneInString(s[i:]) // 正确解码UTF-8字符 + if r == utf8.RuneError { + return "", fmt.Errorf("invalid UTF-8 encoding") + } + + if escaped { + // 如果是转义符后的字符,检查其类型 + switch r { + case '"': + result = append(result, '"') + case '\\': + result = append(result, '\\') + case '/': + result = append(result, '/') + case 'b': + result = append(result, '\b') + case 'f': + result = append(result, '\f') + case 'n': + result = append(result, '\n') + case 'r': + result = append(result, '\r') + case 't': + result = append(result, '\t') + case '\'': + result = append(result, '\'') + default: + // 如果遇到一个非法的转义字符,直接按原样输出 + result = append(result, '\\', r) + } + escaped = false + } else { + if r == '\\' { + escaped = true // 记录反斜杠作为转义符 + } else { + result = append(result, r) + } + } + i += size // 移动到下一个字符 + } + + return string(result), nil +} +func unescapeMapOrSlice(data interface{}) interface{} { + switch v := data.(type) { + case map[string]interface{}: + for k, val := range v { + v[k] = unescapeMapOrSlice(val) + } + case []interface{}: + for i, val := range v { + v[i] = unescapeMapOrSlice(val) + } + case string: + if unescaped, err := unescapeString(v); err != nil { + return v + } else { + return unescaped + } + } + return data +} + +func getResponseToolCall(item *dto.GeminiPart) *dto.ToolCallResponse { + var argsBytes []byte + var err error + // 移除 unescapeMapOrSlice 调用,直接使用 json.Marshal + // JSON 序列化/反序列化已经正确处理了转义字符 + argsBytes, err = json.Marshal(item.FunctionCall.Arguments) + + if err != nil { + return nil + } + return &dto.ToolCallResponse{ + ID: fmt.Sprintf("call_%s", common.GetUUID()), + Type: "function", + Function: dto.FunctionResponse{ + Arguments: string(argsBytes), + Name: item.FunctionCall.FunctionName, + }, + } +} + +func buildUsageFromGeminiMetadata(metadata dto.GeminiUsageMetadata, fallbackPromptTokens int) dto.Usage { + promptTokens := metadata.PromptTokenCount + metadata.ToolUsePromptTokenCount + if promptTokens <= 0 && fallbackPromptTokens > 0 { + promptTokens = fallbackPromptTokens + } + + usage := dto.Usage{ + PromptTokens: promptTokens, + CompletionTokens: metadata.CandidatesTokenCount + metadata.ThoughtsTokenCount, + TotalTokens: metadata.TotalTokenCount, + } + usage.CompletionTokenDetails.ReasoningTokens = metadata.ThoughtsTokenCount + usage.PromptTokensDetails.CachedTokens = metadata.CachedContentTokenCount + + for _, detail := range metadata.PromptTokensDetails { + if detail.Modality == "AUDIO" { + usage.PromptTokensDetails.AudioTokens += detail.TokenCount + } else if detail.Modality == "TEXT" { + usage.PromptTokensDetails.TextTokens += detail.TokenCount + } + } + for _, detail := range metadata.ToolUsePromptTokensDetails { + if detail.Modality == "AUDIO" { + usage.PromptTokensDetails.AudioTokens += detail.TokenCount + } else if detail.Modality == "TEXT" { + usage.PromptTokensDetails.TextTokens += detail.TokenCount + } + } + for _, detail := range metadata.CandidatesTokensDetails { + switch detail.Modality { + case "IMAGE": + usage.CompletionTokenDetails.ImageTokens += detail.TokenCount + case "AUDIO": + usage.CompletionTokenDetails.AudioTokens += detail.TokenCount + case "TEXT": + usage.CompletionTokenDetails.TextTokens += detail.TokenCount + } + } + + if usage.TotalTokens > 0 && usage.CompletionTokens <= 0 { + usage.CompletionTokens = usage.TotalTokens - usage.PromptTokens + } + + if usage.PromptTokens > 0 && usage.PromptTokensDetails.TextTokens == 0 && usage.PromptTokensDetails.AudioTokens == 0 { + usage.PromptTokensDetails.TextTokens = usage.PromptTokens + } + + return usage +} + +func responseGeminiChat2OpenAI(c *gin.Context, response *dto.GeminiChatResponse) *dto.OpenAITextResponse { + fullTextResponse := dto.OpenAITextResponse{ + Id: helper.GetResponseID(c), + Object: "chat.completion", + Created: common.GetTimestamp(), + Choices: make([]dto.OpenAITextResponseChoice, 0, len(response.Candidates)), + } + isToolCall := false + for _, candidate := range response.Candidates { + choice := dto.OpenAITextResponseChoice{ + Index: int(candidate.Index), + Message: dto.Message{ + Role: "assistant", + Content: "", + }, + FinishReason: constant.FinishReasonStop, + } + if len(candidate.Content.Parts) > 0 { + var texts []string + var toolCalls []dto.ToolCallResponse + for _, part := range candidate.Content.Parts { + if part.InlineData != nil { + // 媒体内容 + if strings.HasPrefix(part.InlineData.MimeType, "image") { + imgText := "![image](data:" + part.InlineData.MimeType + ";base64," + part.InlineData.Data + ")" + texts = append(texts, imgText) + } else { + // 其他媒体类型,直接显示链接 + texts = append(texts, fmt.Sprintf("[media](data:%s;base64,%s)", part.InlineData.MimeType, part.InlineData.Data)) + } + } else if part.FunctionCall != nil { + choice.FinishReason = constant.FinishReasonToolCalls + if call := getResponseToolCall(&part); call != nil { + toolCalls = append(toolCalls, *call) + } + } else if part.Thought { + choice.Message.ReasoningContent = &part.Text + } else { + if part.ExecutableCode != nil { + texts = append(texts, "```"+part.ExecutableCode.Language+"\n"+part.ExecutableCode.Code+"\n```") + } else if part.CodeExecutionResult != nil { + texts = append(texts, "```output\n"+part.CodeExecutionResult.Output+"\n```") + } else { + // 过滤掉空行 + if part.Text != "\n" { + texts = append(texts, part.Text) + } + } + } + } + if len(toolCalls) > 0 { + choice.Message.SetToolCalls(toolCalls) + isToolCall = true + } + choice.Message.SetStringContent(strings.Join(texts, "\n")) + + } + if candidate.FinishReason != nil { + switch *candidate.FinishReason { + case "STOP": + choice.FinishReason = constant.FinishReasonStop + case "MAX_TOKENS": + choice.FinishReason = constant.FinishReasonLength + case "SAFETY": + // Safety filter triggered + choice.FinishReason = constant.FinishReasonContentFilter + case "RECITATION": + // Recitation (citation) detected + choice.FinishReason = constant.FinishReasonContentFilter + case "BLOCKLIST": + // Blocklist triggered + choice.FinishReason = constant.FinishReasonContentFilter + case "PROHIBITED_CONTENT": + // Prohibited content detected + choice.FinishReason = constant.FinishReasonContentFilter + case "SPII": + // Sensitive personally identifiable information + choice.FinishReason = constant.FinishReasonContentFilter + case "OTHER": + // Other reasons + choice.FinishReason = constant.FinishReasonContentFilter + default: + choice.FinishReason = constant.FinishReasonContentFilter + } + } + if isToolCall { + choice.FinishReason = constant.FinishReasonToolCalls + } + + fullTextResponse.Choices = append(fullTextResponse.Choices, choice) + } + return &fullTextResponse +} + +func streamResponseGeminiChat2OpenAI(geminiResponse *dto.GeminiChatResponse) (*dto.ChatCompletionsStreamResponse, bool) { + choices := make([]dto.ChatCompletionsStreamResponseChoice, 0, len(geminiResponse.Candidates)) + isStop := false + for _, candidate := range geminiResponse.Candidates { + if candidate.FinishReason != nil && *candidate.FinishReason == "STOP" { + isStop = true + candidate.FinishReason = nil + } + choice := dto.ChatCompletionsStreamResponseChoice{ + Index: int(candidate.Index), + Delta: dto.ChatCompletionsStreamResponseChoiceDelta{ + //Role: "assistant", + }, + } + var texts []string + isTools := false + isThought := false + if candidate.FinishReason != nil { + // Map Gemini FinishReason to OpenAI finish_reason + switch *candidate.FinishReason { + case "STOP": + // Normal completion + choice.FinishReason = &constant.FinishReasonStop + case "MAX_TOKENS": + // Reached maximum token limit + choice.FinishReason = &constant.FinishReasonLength + case "SAFETY": + // Safety filter triggered + choice.FinishReason = &constant.FinishReasonContentFilter + case "RECITATION": + // Recitation (citation) detected + choice.FinishReason = &constant.FinishReasonContentFilter + case "BLOCKLIST": + // Blocklist triggered + choice.FinishReason = &constant.FinishReasonContentFilter + case "PROHIBITED_CONTENT": + // Prohibited content detected + choice.FinishReason = &constant.FinishReasonContentFilter + case "SPII": + // Sensitive personally identifiable information + choice.FinishReason = &constant.FinishReasonContentFilter + case "OTHER": + // Other reasons + choice.FinishReason = &constant.FinishReasonContentFilter + default: + // Unknown reason, treat as content filter + choice.FinishReason = &constant.FinishReasonContentFilter + } + } + for _, part := range candidate.Content.Parts { + if part.InlineData != nil { + if strings.HasPrefix(part.InlineData.MimeType, "image") { + imgText := "![image](data:" + part.InlineData.MimeType + ";base64," + part.InlineData.Data + ")" + texts = append(texts, imgText) + } + } else if part.FunctionCall != nil { + isTools = true + if call := getResponseToolCall(&part); call != nil { + call.SetIndex(len(choice.Delta.ToolCalls)) + choice.Delta.ToolCalls = append(choice.Delta.ToolCalls, *call) + } + + } else if part.Thought { + isThought = true + texts = append(texts, part.Text) + } else { + if part.ExecutableCode != nil { + texts = append(texts, "```"+part.ExecutableCode.Language+"\n"+part.ExecutableCode.Code+"\n```\n") + } else if part.CodeExecutionResult != nil { + texts = append(texts, "```output\n"+part.CodeExecutionResult.Output+"\n```\n") + } else { + if part.Text != "\n" { + texts = append(texts, part.Text) + } + } + } + } + if isThought { + choice.Delta.SetReasoningContent(strings.Join(texts, "\n")) + } else { + choice.Delta.SetContentString(strings.Join(texts, "\n")) + } + if isTools { + choice.FinishReason = &constant.FinishReasonToolCalls + } + choices = append(choices, choice) + } + + var response dto.ChatCompletionsStreamResponse + response.Object = "chat.completion.chunk" + response.Choices = choices + return &response, isStop +} + +func handleStream(c *gin.Context, info *relaycommon.RelayInfo, resp *dto.ChatCompletionsStreamResponse) error { + streamData, err := common.Marshal(resp) + if err != nil { + return fmt.Errorf("failed to marshal stream response: %w", err) + } + err = openai.HandleStreamFormat(c, info, string(streamData), info.ChannelSetting.ForceFormat, info.ChannelSetting.ThinkingToContent) + if err != nil { + return fmt.Errorf("failed to handle stream format: %w", err) + } + return nil +} + +func handleFinalStream(c *gin.Context, info *relaycommon.RelayInfo, resp *dto.ChatCompletionsStreamResponse) error { + streamData, err := common.Marshal(resp) + if err != nil { + return fmt.Errorf("failed to marshal stream response: %w", err) + } + openai.HandleFinalResponse(c, info, string(streamData), resp.Id, resp.Created, resp.Model, resp.GetSystemFingerprint(), resp.Usage, false) + return nil +} + +func geminiStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response, callback func(data string, geminiResponse *dto.GeminiChatResponse) bool) (*dto.Usage, *types.NewAPIError) { + var usage = &dto.Usage{} + var imageCount int + responseText := strings.Builder{} + + helper.StreamScannerHandler(c, resp, info, func(data string, sr *helper.StreamResult) { + var geminiResponse dto.GeminiChatResponse + if err := common.UnmarshalJsonStr(data, &geminiResponse); err != nil { + sr.Stop(fmt.Errorf("unmarshal: %w", err)) + return + } + + if len(geminiResponse.Candidates) == 0 && geminiResponse.PromptFeedback != nil && geminiResponse.PromptFeedback.BlockReason != nil { + common.SetContextKey(c, constant.ContextKeyAdminRejectReason, fmt.Sprintf("gemini_block_reason=%s", *geminiResponse.PromptFeedback.BlockReason)) + } + + // 统计图片数量 + for _, candidate := range geminiResponse.Candidates { + for _, part := range candidate.Content.Parts { + if part.InlineData != nil && part.InlineData.MimeType != "" { + imageCount++ + } + if part.Text != "" { + responseText.WriteString(part.Text) + } + } + } + + // 更新使用量统计 + if geminiResponse.UsageMetadata.TotalTokenCount != 0 { + mappedUsage := buildUsageFromGeminiMetadata(geminiResponse.UsageMetadata, info.GetEstimatePromptTokens()) + *usage = mappedUsage + } + + if !callback(data, &geminiResponse) { + sr.Stop(fmt.Errorf("gemini callback stopped")) + } + }) + + if imageCount != 0 { + if usage.CompletionTokens == 0 { + usage.CompletionTokens = imageCount * 1400 + } + } + + if usage.CompletionTokens <= 0 { + if info.ReceivedResponseCount > 0 { + usage = service.ResponseText2Usage(c, responseText.String(), info.UpstreamModelName, info.GetEstimatePromptTokens()) + } else { + usage = &dto.Usage{} + } + } + + return usage, nil +} + +func GeminiChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { + id := helper.GetResponseID(c) + createAt := common.GetTimestamp() + finishReason := constant.FinishReasonStop + toolCallIndexByChoice := make(map[int]map[string]int) + nextToolCallIndexByChoice := make(map[int]int) + + usage, err := geminiStreamHandler(c, info, resp, func(data string, geminiResponse *dto.GeminiChatResponse) bool { + response, isStop := streamResponseGeminiChat2OpenAI(geminiResponse) + + response.Id = id + response.Created = createAt + response.Model = info.UpstreamModelName + for choiceIdx := range response.Choices { + choiceKey := response.Choices[choiceIdx].Index + for toolIdx := range response.Choices[choiceIdx].Delta.ToolCalls { + tool := &response.Choices[choiceIdx].Delta.ToolCalls[toolIdx] + if tool.ID == "" { + continue + } + m := toolCallIndexByChoice[choiceKey] + if m == nil { + m = make(map[string]int) + toolCallIndexByChoice[choiceKey] = m + } + if idx, ok := m[tool.ID]; ok { + tool.SetIndex(idx) + continue + } + idx := nextToolCallIndexByChoice[choiceKey] + nextToolCallIndexByChoice[choiceKey] = idx + 1 + m[tool.ID] = idx + tool.SetIndex(idx) + } + } + + logger.LogDebug(c, fmt.Sprintf("info.SendResponseCount = %d", info.SendResponseCount)) + if info.SendResponseCount == 0 { + // send first response + emptyResponse := helper.GenerateStartEmptyResponse(id, createAt, info.UpstreamModelName, nil) + if response.IsToolCall() { + if len(emptyResponse.Choices) > 0 && len(response.Choices) > 0 { + toolCalls := response.Choices[0].Delta.ToolCalls + copiedToolCalls := make([]dto.ToolCallResponse, len(toolCalls)) + for idx := range toolCalls { + copiedToolCalls[idx] = toolCalls[idx] + copiedToolCalls[idx].Function.Arguments = "" + } + emptyResponse.Choices[0].Delta.ToolCalls = copiedToolCalls + } + finishReason = constant.FinishReasonToolCalls + err := handleStream(c, info, emptyResponse) + if err != nil { + logger.LogError(c, err.Error()) + } + + response.ClearToolCalls() + if response.IsFinished() { + response.Choices[0].FinishReason = nil + } + } else { + err := handleStream(c, info, emptyResponse) + if err != nil { + logger.LogError(c, err.Error()) + } + } + } + + err := handleStream(c, info, response) + if err != nil { + logger.LogError(c, err.Error()) + } + if isStop { + _ = handleStream(c, info, helper.GenerateStopResponse(id, createAt, info.UpstreamModelName, finishReason)) + } + return true + }) + + if err != nil { + return usage, err + } + + response := helper.GenerateFinalUsageResponse(id, createAt, info.UpstreamModelName, *usage) + handleErr := handleFinalStream(c, info, response) + if handleErr != nil { + common.SysLog("send final response failed: " + handleErr.Error()) + } + return usage, nil +} + +func GeminiChatHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + service.CloseResponseBodyGracefully(resp) + if common.DebugEnabled { + println(string(responseBody)) + } + var geminiResponse dto.GeminiChatResponse + err = common.Unmarshal(responseBody, &geminiResponse) + if err != nil { + return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + if len(geminiResponse.Candidates) == 0 { + usage := buildUsageFromGeminiMetadata(geminiResponse.UsageMetadata, info.GetEstimatePromptTokens()) + + var newAPIError *types.NewAPIError + if geminiResponse.PromptFeedback != nil && geminiResponse.PromptFeedback.BlockReason != nil { + common.SetContextKey(c, constant.ContextKeyAdminRejectReason, fmt.Sprintf("gemini_block_reason=%s", *geminiResponse.PromptFeedback.BlockReason)) + newAPIError = types.NewOpenAIError( + errors.New("request blocked by Gemini API: "+*geminiResponse.PromptFeedback.BlockReason), + types.ErrorCodePromptBlocked, + http.StatusBadRequest, + ) + } else { + common.SetContextKey(c, constant.ContextKeyAdminRejectReason, "gemini_empty_candidates") + newAPIError = types.NewOpenAIError( + errors.New("empty response from Gemini API"), + types.ErrorCodeEmptyResponse, + http.StatusInternalServerError, + ) + } + + service.ResetStatusCode(newAPIError, c.GetString("status_code_mapping")) + + switch info.RelayFormat { + case types.RelayFormatClaude: + c.JSON(newAPIError.StatusCode, gin.H{ + "type": "error", + "error": newAPIError.ToClaudeError(), + }) + default: + c.JSON(newAPIError.StatusCode, gin.H{ + "error": newAPIError.ToOpenAIError(), + }) + } + return &usage, nil + } + fullTextResponse := responseGeminiChat2OpenAI(c, &geminiResponse) + fullTextResponse.Model = info.UpstreamModelName + usage := buildUsageFromGeminiMetadata(geminiResponse.UsageMetadata, info.GetEstimatePromptTokens()) + + fullTextResponse.Usage = usage + + switch info.RelayFormat { + case types.RelayFormatOpenAI: + responseBody, err = common.Marshal(fullTextResponse) + if err != nil { + return nil, types.NewError(err, types.ErrorCodeBadResponseBody) + } + case types.RelayFormatClaude: + claudeResp := service.ResponseOpenAI2Claude(fullTextResponse, info) + claudeRespStr, err := common.Marshal(claudeResp) + if err != nil { + return nil, types.NewError(err, types.ErrorCodeBadResponseBody) + } + responseBody = claudeRespStr + case types.RelayFormatGemini: + break + } + + service.IOCopyBytesGracefully(c, resp, responseBody) + + return &usage, nil +} + +func GeminiEmbeddingHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { + defer service.CloseResponseBodyGracefully(resp) + + responseBody, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return nil, types.NewOpenAIError(readErr, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + + var geminiResponse dto.GeminiBatchEmbeddingResponse + if jsonErr := common.Unmarshal(responseBody, &geminiResponse); jsonErr != nil { + return nil, types.NewOpenAIError(jsonErr, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + + // convert to openai format response + openAIResponse := dto.OpenAIEmbeddingResponse{ + Object: "list", + Data: make([]dto.OpenAIEmbeddingResponseItem, 0, len(geminiResponse.Embeddings)), + Model: info.UpstreamModelName, + } + + for i, embedding := range geminiResponse.Embeddings { + openAIResponse.Data = append(openAIResponse.Data, dto.OpenAIEmbeddingResponseItem{ + Object: "embedding", + Embedding: embedding.Values, + Index: i, + }) + } + + // calculate usage + // https://ai.google.dev/gemini-api/docs/pricing?hl=zh-cn#text-embedding-004 + // Google has not yet clarified how embedding models will be billed + // refer to openai billing method to use input tokens billing + // https://platform.openai.com/docs/guides/embeddings#what-are-embeddings + usage := service.ResponseText2Usage(c, "", info.UpstreamModelName, info.GetEstimatePromptTokens()) + openAIResponse.Usage = *usage + + jsonResponse, jsonErr := common.Marshal(openAIResponse) + if jsonErr != nil { + return nil, types.NewOpenAIError(jsonErr, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + + service.IOCopyBytesGracefully(c, resp, jsonResponse) + return usage, nil +} + +func GeminiImageHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Response) (*dto.Usage, *types.NewAPIError) { + responseBody, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return nil, types.NewOpenAIError(readErr, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + _ = resp.Body.Close() + + var geminiResponse dto.GeminiImageResponse + if jsonErr := common.Unmarshal(responseBody, &geminiResponse); jsonErr != nil { + return nil, types.NewOpenAIError(jsonErr, types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + + if len(geminiResponse.Predictions) == 0 { + return nil, types.NewOpenAIError(errors.New("no images generated"), types.ErrorCodeBadResponseBody, http.StatusInternalServerError) + } + + // convert to openai format response + openAIResponse := dto.ImageResponse{ + Created: common.GetTimestamp(), + Data: make([]dto.ImageData, 0, len(geminiResponse.Predictions)), + } + + for _, prediction := range geminiResponse.Predictions { + if prediction.RaiFilteredReason != "" { + continue // skip filtered image + } + openAIResponse.Data = append(openAIResponse.Data, dto.ImageData{ + B64Json: prediction.BytesBase64Encoded, + }) + } + + jsonResponse, jsonErr := json.Marshal(openAIResponse) + if jsonErr != nil { + return nil, types.NewError(jsonErr, types.ErrorCodeBadResponseBody) + } + + c.Writer.Header().Set("Content-Type", "application/json") + c.Writer.WriteHeader(resp.StatusCode) + _, _ = c.Writer.Write(jsonResponse) + + // https://github.com/google-gemini/cookbook/blob/719a27d752aac33f39de18a8d3cb42a70874917e/quickstarts/Counting_Tokens.ipynb + // each image has fixed 258 tokens + const imageTokens = 258 + generatedImages := len(openAIResponse.Data) + + usage := &dto.Usage{ + PromptTokens: imageTokens * generatedImages, // each generated image has fixed 258 tokens + CompletionTokens: 0, // image generation does not calculate completion tokens + TotalTokens: imageTokens * generatedImages, + } + + return usage, nil +} + +type GeminiModelsResponse struct { + Models []dto.GeminiModel `json:"models"` + NextPageToken string `json:"nextPageToken"` +} + +func FetchGeminiModels(baseURL, apiKey, proxyURL string) ([]string, error) { + client, err := service.GetHttpClientWithProxy(proxyURL) + if err != nil { + return nil, fmt.Errorf("创建HTTP客户端失败: %v", err) + } + + allModels := make([]string, 0) + nextPageToken := "" + maxPages := 100 // Safety limit to prevent infinite loops + + for page := 0; page < maxPages; page++ { + url := fmt.Sprintf("%s/v1beta/models", baseURL) + if nextPageToken != "" { + url = fmt.Sprintf("%s?pageToken=%s", url, nextPageToken) + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + request, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + cancel() + return nil, fmt.Errorf("创建请求失败: %v", err) + } + + request.Header.Set("x-goog-api-key", apiKey) + + response, err := client.Do(request) + if err != nil { + cancel() + return nil, fmt.Errorf("请求失败: %v", err) + } + + if response.StatusCode != http.StatusOK { + body, _ := io.ReadAll(response.Body) + response.Body.Close() + cancel() + return nil, fmt.Errorf("服务器返回错误 %d: %s", response.StatusCode, string(body)) + } + + body, err := io.ReadAll(response.Body) + response.Body.Close() + cancel() + if err != nil { + return nil, fmt.Errorf("读取响应失败: %v", err) + } + + var modelsResponse GeminiModelsResponse + if err = common.Unmarshal(body, &modelsResponse); err != nil { + return nil, fmt.Errorf("解析响应失败: %v", err) + } + + for _, model := range modelsResponse.Models { + modelNameValue, ok := model.Name.(string) + if !ok { + continue + } + modelName := strings.TrimPrefix(modelNameValue, "models/") + allModels = append(allModels, modelName) + } + + nextPageToken = modelsResponse.NextPageToken + if nextPageToken == "" { + break + } + } + + return allModels, nil +} + +// convertToolChoiceToGeminiConfig converts OpenAI tool_choice to Gemini toolConfig +// OpenAI tool_choice values: +// - "auto": Let the model decide (default) +// - "none": Don't call any tools +// - "required": Must call at least one tool +// - {"type": "function", "function": {"name": "xxx"}}: Call specific function +// +// Gemini functionCallingConfig.mode values: +// - "AUTO": Model decides whether to call functions +// - "NONE": Model won't call functions +// - "ANY": Model must call at least one function +func convertToolChoiceToGeminiConfig(toolChoice any) *dto.ToolConfig { + if toolChoice == nil { + return nil + } + + // Handle string values: "auto", "none", "required" + if toolChoiceStr, ok := toolChoice.(string); ok { + config := &dto.ToolConfig{ + FunctionCallingConfig: &dto.FunctionCallingConfig{}, + } + switch toolChoiceStr { + case "auto": + config.FunctionCallingConfig.Mode = "AUTO" + case "none": + config.FunctionCallingConfig.Mode = "NONE" + case "required": + config.FunctionCallingConfig.Mode = "ANY" + default: + // Unknown string value, default to AUTO + config.FunctionCallingConfig.Mode = "AUTO" + } + return config + } + + // Handle object value: {"type": "function", "function": {"name": "xxx"}} + if toolChoiceMap, ok := toolChoice.(map[string]interface{}); ok { + if toolChoiceMap["type"] == "function" { + config := &dto.ToolConfig{ + FunctionCallingConfig: &dto.FunctionCallingConfig{ + Mode: "ANY", + }, + } + // Extract function name if specified + if function, ok := toolChoiceMap["function"].(map[string]interface{}); ok { + if name, ok := function["name"].(string); ok && name != "" { + config.FunctionCallingConfig.AllowedFunctionNames = []string{name} + } + } + return config + } + // Unsupported map structure (type is not "function"), return nil + return nil + } + + // Unsupported type, return nil + return nil +} diff --git a/_all-in-one-upload/new-api/relay/channel/openai/constant.go b/_all-in-one-upload/new-api/relay/channel/openai/constant.go new file mode 100644 index 0000000..14e3d44 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/openai/constant.go @@ -0,0 +1,76 @@ +package openai + +var ModelList = []string{ + "gpt-3.5-turbo", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-instruct", "gpt-3.5-turbo-instruct-0914", + "gpt-4", "gpt-4-0613", "gpt-4-1106-preview", "gpt-4-0125-preview", + "gpt-4-32k", "gpt-4-32k-0613", + "gpt-4-turbo-preview", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", + "gpt-4-vision-preview", + "chatgpt-4o-latest", + "gpt-4o", "gpt-4o-2024-05-13", "gpt-4o-2024-08-06", "gpt-4o-2024-11-20", + "gpt-4o-transcribe", "gpt-4o-transcribe-diarize", + "gpt-4o-search-preview", "gpt-4o-search-preview-2025-03-11", + "gpt-4o-mini", "gpt-4o-mini-2024-07-18", + "gpt-4o-mini-transcribe", "gpt-4o-mini-transcribe-2025-03-20", "gpt-4o-mini-transcribe-2025-12-15", + "gpt-4o-mini-tts", "gpt-4o-mini-tts-2025-03-20", "gpt-4o-mini-tts-2025-12-15", + "gpt-4o-mini-search-preview", "gpt-4o-mini-search-preview-2025-03-11", + "gpt-4.5-preview", "gpt-4.5-preview-2025-02-27", + "gpt-4.1", "gpt-4.1-2025-04-14", + "gpt-4.1-mini", "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano", "gpt-4.1-nano-2025-04-14", + "o1", "o1-2024-12-17", + "o1-preview", "o1-preview-2024-09-12", + "o1-mini", "o1-mini-2024-09-12", + "o1-pro", "o1-pro-2025-03-19", + "o3-mini", "o3-mini-2025-01-31", + "o3-mini-high", "o3-mini-2025-01-31-high", + "o3-mini-low", "o3-mini-2025-01-31-low", + "o3-mini-medium", "o3-mini-2025-01-31-medium", + "o3", "o3-2025-04-16", + "o3-pro", "o3-pro-2025-06-10", + "o3-deep-research", "o3-deep-research-2025-06-26", + "o4-mini", "o4-mini-2025-04-16", + "o4-mini-deep-research", "o4-mini-deep-research-2025-06-26", + "gpt-5", "gpt-5-2025-08-07", "gpt-5-chat-latest", + "gpt-5-mini", "gpt-5-mini-2025-08-07", + "gpt-5-nano", "gpt-5-nano-2025-08-07", + "gpt-5-codex", + "gpt-5-pro", "gpt-5-pro-2025-10-06", + "gpt-5-search-api", "gpt-5-search-api-2025-10-14", + "gpt-5.1", "gpt-5.1-2025-11-13", "gpt-5.1-chat-latest", + "gpt-5.1-codex", "gpt-5.1-codex-mini", "gpt-5.1-codex-max", + "gpt-5.2", "gpt-5.2-2025-12-11", "gpt-5.2-chat-latest", + "gpt-5.2-pro", "gpt-5.2-pro-2025-12-11", + "gpt-5.2-codex", + "gpt-5.3-chat-latest", + "gpt-5.3-codex", + "gpt-5.4", "gpt-5.4-2026-03-05", + "gpt-5.4-pro", "gpt-5.4-pro-2026-03-05", + "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-audio-preview-2025-06-03", + "gpt-4o-realtime-preview", "gpt-4o-realtime-preview-2024-10-01", "gpt-4o-realtime-preview-2024-12-17", "gpt-4o-realtime-preview-2025-06-03", + "gpt-4o-mini-realtime-preview", "gpt-4o-mini-realtime-preview-2024-12-17", + "gpt-4o-mini-audio-preview", "gpt-4o-mini-audio-preview-2024-12-17", + "gpt-audio", "gpt-audio-2025-08-28", + "gpt-audio-mini", "gpt-audio-mini-2025-10-06", "gpt-audio-mini-2025-12-15", + "gpt-audio-1.5", + "gpt-realtime", "gpt-realtime-2025-08-28", + "gpt-realtime-mini", "gpt-realtime-mini-2025-10-06", "gpt-realtime-mini-2025-12-15", + "gpt-realtime-1.5", + "text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large", + "text-curie-001", "text-babbage-001", "text-ada-001", + "text-moderation-latest", "text-moderation-stable", + "omni-moderation-latest", "omni-moderation-2024-09-26", + "text-davinci-edit-001", + "davinci-002", "babbage-002", + "dall-e-2", "dall-e-3", + "gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5", + "chatgpt-image-latest", + "whisper-1", + "tts-1", "tts-1-1106", "tts-1-hd", "tts-1-hd-1106", + "computer-use-preview", "computer-use-preview-2025-03-11", + "sora-2", "sora-2-pro", +} + +var ChannelName = "openai" diff --git a/_all-in-one-upload/new-api/relay/channel/replicate/dto.go b/_all-in-one-upload/new-api/relay/channel/replicate/dto.go new file mode 100644 index 0000000..2ff06dc --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/replicate/dto.go @@ -0,0 +1,19 @@ +package replicate + +type PredictionResponse struct { + Status string `json:"status"` + Output any `json:"output"` + Error *PredictionError `json:"error"` +} + +type PredictionError struct { + Code string `json:"code"` + Message string `json:"message"` + Detail string `json:"detail"` +} + +type FileUploadResponse struct { + Urls struct { + Get string `json:"get"` + } `json:"urls"` +} diff --git a/_all-in-one-upload/new-api/relay/channel/task/hailuo/adaptor.go b/_all-in-one-upload/new-api/relay/channel/task/hailuo/adaptor.go new file mode 100644 index 0000000..28b3a97 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/task/hailuo/adaptor.go @@ -0,0 +1,302 @@ +package hailuo + +import ( + "bytes" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/model" + "github.com/gin-gonic/gin" + "github.com/pkg/errors" + + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/relay/channel" + taskcommon "github.com/QuantumNous/new-api/relay/channel/task/taskcommon" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/service" +) + +// https://platform.minimaxi.com/docs/api-reference/video-generation-intro +type TaskAdaptor struct { + taskcommon.BaseBilling + ChannelType int + apiKey string + baseURL string +} + +func (a *TaskAdaptor) Init(info *relaycommon.RelayInfo) { + a.ChannelType = info.ChannelType + a.baseURL = info.ChannelBaseUrl + a.apiKey = info.ApiKey +} + +func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycommon.RelayInfo) (taskErr *dto.TaskError) { + return relaycommon.ValidateBasicTaskRequest(c, info, constant.TaskActionGenerate) +} + +func (a *TaskAdaptor) BuildRequestURL(info *relaycommon.RelayInfo) (string, error) { + return fmt.Sprintf("%s%s", a.baseURL, TextToVideoEndpoint), nil +} + +func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + req.Header.Set("Authorization", "Bearer "+a.apiKey) + return nil +} + +func (a *TaskAdaptor) BuildRequestBody(c *gin.Context, info *relaycommon.RelayInfo) (io.Reader, error) { + v, exists := c.Get("task_request") + if !exists { + return nil, fmt.Errorf("request not found in context") + } + req, ok := v.(relaycommon.TaskSubmitReq) + if !ok { + return nil, fmt.Errorf("invalid request type in context") + } + + body, err := a.convertToRequestPayload(&req, info) + if err != nil { + return nil, errors.Wrap(err, "convert request payload failed") + } + + data, err := common.Marshal(body) + if err != nil { + return nil, err + } + + return bytes.NewReader(data), nil +} + +func (a *TaskAdaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (*http.Response, error) { + return channel.DoTaskApiRequest(a, c, info, requestBody) +} + +func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (taskID string, taskData []byte, taskErr *dto.TaskError) { + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + taskErr = service.TaskErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError) + return + } + _ = resp.Body.Close() + + var hResp VideoResponse + if err := common.Unmarshal(responseBody, &hResp); err != nil { + taskErr = service.TaskErrorWrapper(errors.Wrapf(err, "body: %s", responseBody), "unmarshal_response_body_failed", http.StatusInternalServerError) + return + } + + if hResp.BaseResp.StatusCode != StatusSuccess { + taskErr = service.TaskErrorWrapper( + fmt.Errorf("hailuo api error: %s", hResp.BaseResp.StatusMsg), + strconv.Itoa(hResp.BaseResp.StatusCode), + http.StatusBadRequest, + ) + return + } + + ov := dto.NewOpenAIVideo() + ov.ID = info.PublicTaskID + ov.TaskID = info.PublicTaskID + ov.CreatedAt = time.Now().Unix() + ov.Model = info.OriginModelName + + c.JSON(http.StatusOK, ov) + return hResp.TaskID, responseBody, nil +} + +func (a *TaskAdaptor) FetchTask(baseUrl, key string, body map[string]any, proxy string) (*http.Response, error) { + taskID, ok := body["task_id"].(string) + if !ok { + return nil, fmt.Errorf("invalid task_id") + } + + uri := fmt.Sprintf("%s%s?task_id=%s", baseUrl, QueryTaskEndpoint, taskID) + + req, err := http.NewRequest(http.MethodGet, uri, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("Authorization", "Bearer "+key) + + client, err := service.GetHttpClientWithProxy(proxy) + if err != nil { + return nil, fmt.Errorf("new proxy http client failed: %w", err) + } + return client.Do(req) +} + +func (a *TaskAdaptor) GetModelList() []string { + return ModelList +} + +func (a *TaskAdaptor) GetChannelName() string { + return ChannelName +} + +func (a *TaskAdaptor) convertToRequestPayload(req *relaycommon.TaskSubmitReq, info *relaycommon.RelayInfo) (*VideoRequest, error) { + modelConfig := GetModelConfig(info.UpstreamModelName) + duration := DefaultDuration + if req.Duration > 0 { + duration = req.Duration + } + resolution := modelConfig.DefaultResolution + if req.Size != "" { + resolution = a.parseResolutionFromSize(req.Size, modelConfig) + } + + videoRequest := &VideoRequest{ + Model: info.UpstreamModelName, + Prompt: req.Prompt, + Duration: &duration, + Resolution: resolution, + } + if err := req.UnmarshalMetadata(&videoRequest); err != nil { + return nil, errors.Wrap(err, "unmarshal metadata to video request failed") + } + + return videoRequest, nil +} + +func (a *TaskAdaptor) parseResolutionFromSize(size string, modelConfig ModelConfig) string { + switch { + case strings.Contains(size, "1080"): + return Resolution1080P + case strings.Contains(size, "768"): + return Resolution768P + case strings.Contains(size, "720"): + return Resolution720P + case strings.Contains(size, "512"): + return Resolution512P + default: + return modelConfig.DefaultResolution + } +} + +func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, error) { + resTask := QueryTaskResponse{} + if err := common.Unmarshal(respBody, &resTask); err != nil { + return nil, errors.Wrap(err, "unmarshal task result failed") + } + + taskResult := relaycommon.TaskInfo{} + + if resTask.BaseResp.StatusCode == StatusSuccess { + taskResult.Code = 0 + } else { + taskResult.Code = resTask.BaseResp.StatusCode + taskResult.Reason = resTask.BaseResp.StatusMsg + taskResult.Status = model.TaskStatusFailure + taskResult.Progress = "100%" + } + + switch resTask.Status { + case TaskStatusPreparing, TaskStatusQueueing, TaskStatusProcessing: + taskResult.Status = model.TaskStatusInProgress + taskResult.Progress = "30%" + if resTask.Status == TaskStatusProcessing { + taskResult.Progress = "50%" + } + case TaskStatusSuccess: + taskResult.Status = model.TaskStatusSuccess + taskResult.Progress = "100%" + taskResult.Url = a.buildVideoURL(resTask.TaskID, resTask.FileID) + case TaskStatusFailed: + taskResult.Status = model.TaskStatusFailure + taskResult.Progress = "100%" + if taskResult.Reason == "" { + taskResult.Reason = "task failed" + } + default: + taskResult.Status = model.TaskStatusInProgress + taskResult.Progress = "30%" + } + + return &taskResult, nil +} + +func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) { + var hailuoResp QueryTaskResponse + if err := common.Unmarshal(originTask.Data, &hailuoResp); err != nil { + return nil, errors.Wrap(err, "unmarshal hailuo task data failed") + } + + openAIVideo := originTask.ToOpenAIVideo() + if hailuoResp.BaseResp.StatusCode != StatusSuccess { + openAIVideo.Error = &dto.OpenAIVideoError{ + Message: hailuoResp.BaseResp.StatusMsg, + Code: strconv.Itoa(hailuoResp.BaseResp.StatusCode), + } + } + + jsonData, err := common.Marshal(openAIVideo) + if err != nil { + return nil, errors.Wrap(err, "marshal openai video failed") + } + + return jsonData, nil +} + +func (a *TaskAdaptor) buildVideoURL(_, fileID string) string { + if a.apiKey == "" || a.baseURL == "" { + return "" + } + + url := fmt.Sprintf("%s/v1/files/retrieve?file_id=%s", a.baseURL, fileID) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return "" + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("Authorization", "Bearer "+a.apiKey) + + resp, err := service.GetHttpClient().Do(req) + if err != nil { + return "" + } + defer resp.Body.Close() + + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + return "" + } + + var retrieveResp RetrieveFileResponse + if err := common.Unmarshal(responseBody, &retrieveResp); err != nil { + return "" + } + + if retrieveResp.BaseResp.StatusCode != StatusSuccess { + return "" + } + + return retrieveResp.File.DownloadURL +} + +func contains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} + +func containsInt(slice []int, item int) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} diff --git a/_all-in-one-upload/new-api/relay/channel/task/suno/adaptor.go b/_all-in-one-upload/new-api/relay/channel/task/suno/adaptor.go new file mode 100644 index 0000000..35b5e42 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/task/suno/adaptor.go @@ -0,0 +1,167 @@ +package suno + +import ( + "bytes" + "fmt" + "io" + "net/http" + "strings" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/relay/channel" + taskcommon "github.com/QuantumNous/new-api/relay/channel/task/taskcommon" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/service" + + "github.com/gin-gonic/gin" +) + +type TaskAdaptor struct { + taskcommon.BaseBilling + ChannelType int +} + +// ParseTaskResult is not used for Suno tasks. +// Suno polling uses a dedicated batch-fetch path (service.UpdateSunoTasks) that +// receives dto.TaskResponse[[]dto.SunoDataResponse] from the upstream /fetch API. +// This differs from the per-task polling used by video adaptors. +func (a *TaskAdaptor) ParseTaskResult([]byte) (*relaycommon.TaskInfo, error) { + return nil, fmt.Errorf("suno uses batch polling via UpdateSunoTasks, ParseTaskResult is not applicable") +} + +func (a *TaskAdaptor) Init(info *relaycommon.RelayInfo) { + a.ChannelType = info.ChannelType +} + +func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycommon.RelayInfo) (taskErr *dto.TaskError) { + action := strings.ToUpper(c.Param("action")) + + var sunoRequest *dto.SunoSubmitReq + err := common.UnmarshalBodyReusable(c, &sunoRequest) + if err != nil { + taskErr = service.TaskErrorWrapperLocal(err, "invalid_request", http.StatusBadRequest) + return + } + err = actionValidate(c, sunoRequest, action) + if err != nil { + taskErr = service.TaskErrorWrapperLocal(err, "invalid_request", http.StatusBadRequest) + return + } + + //if sunoRequest.ContinueClipId != "" { + // if sunoRequest.TaskID == "" { + // taskErr = service.TaskErrorWrapperLocal(fmt.Errorf("task id is empty"), "invalid_request", http.StatusBadRequest) + // return + // } + // info.OriginTaskID = sunoRequest.TaskID + //} + + info.Action = action + c.Set("task_request", sunoRequest) + return nil +} + +func (a *TaskAdaptor) BuildRequestURL(info *relaycommon.RelayInfo) (string, error) { + baseURL := info.ChannelBaseUrl + fullRequestURL := fmt.Sprintf("%s%s", baseURL, "/suno/submit/"+info.Action) + return fullRequestURL, nil +} + +func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { + req.Header.Set("Content-Type", c.Request.Header.Get("Content-Type")) + req.Header.Set("Accept", c.Request.Header.Get("Accept")) + req.Header.Set("Authorization", "Bearer "+info.ApiKey) + return nil +} + +func (a *TaskAdaptor) BuildRequestBody(c *gin.Context, info *relaycommon.RelayInfo) (io.Reader, error) { + sunoRequest, ok := c.Get("task_request") + if !ok { + return nil, fmt.Errorf("task_request not found in context") + } + data, err := common.Marshal(sunoRequest) + if err != nil { + return nil, err + } + return bytes.NewReader(data), nil +} + +func (a *TaskAdaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (*http.Response, error) { + return channel.DoTaskApiRequest(a, c, info, requestBody) +} + +func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (taskID string, taskData []byte, taskErr *dto.TaskError) { + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + taskErr = service.TaskErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError) + return + } + var sunoResponse dto.TaskResponse[string] + err = common.Unmarshal(responseBody, &sunoResponse) + if err != nil { + taskErr = service.TaskErrorWrapper(err, "unmarshal_response_body_failed", http.StatusInternalServerError) + return + } + if !sunoResponse.IsSuccess() { + taskErr = service.TaskErrorWrapper(fmt.Errorf("%s", sunoResponse.Message), sunoResponse.Code, http.StatusInternalServerError) + return + } + + // 使用公开 task_xxxx ID 替换上游 ID 返回给客户端 + publicResponse := dto.TaskResponse[string]{ + Code: sunoResponse.Code, + Message: sunoResponse.Message, + Data: info.PublicTaskID, + } + c.JSON(http.StatusOK, publicResponse) + + return sunoResponse.Data, nil, nil +} + +func (a *TaskAdaptor) GetModelList() []string { + return ModelList +} + +func (a *TaskAdaptor) GetChannelName() string { + return ChannelName +} + +func (a *TaskAdaptor) FetchTask(baseUrl, key string, body map[string]any, proxy string) (*http.Response, error) { + requestUrl := fmt.Sprintf("%s/suno/fetch", baseUrl) + byteBody, err := common.Marshal(body) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", requestUrl, bytes.NewBuffer(byteBody)) + if err != nil { + common.SysLog(fmt.Sprintf("Get Task error: %v", err)) + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer "+key) + client, err := service.GetHttpClientWithProxy(proxy) + if err != nil { + return nil, fmt.Errorf("new proxy http client failed: %w", err) + } + return client.Do(req) +} + +func actionValidate(c *gin.Context, sunoRequest *dto.SunoSubmitReq, action string) (err error) { + switch action { + case constant.SunoActionMusic: + if sunoRequest.Mv == "" { + sunoRequest.Mv = "chirp-v3-0" + } + case constant.SunoActionLyrics: + if sunoRequest.Prompt == "" { + err = fmt.Errorf("prompt_empty") + return + } + default: + err = fmt.Errorf("invalid_action") + } + return +} diff --git a/_all-in-one-upload/new-api/relay/channel/task/vertex/adaptor.go b/_all-in-one-upload/new-api/relay/channel/task/vertex/adaptor.go new file mode 100644 index 0000000..b76364e --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/task/vertex/adaptor.go @@ -0,0 +1,424 @@ +package vertex + +import ( + "bytes" + "fmt" + "io" + "net/http" + "regexp" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/model" + "github.com/gin-gonic/gin" + + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/relay/channel" + geminitask "github.com/QuantumNous/new-api/relay/channel/task/gemini" + taskcommon "github.com/QuantumNous/new-api/relay/channel/task/taskcommon" + vertexcore "github.com/QuantumNous/new-api/relay/channel/vertex" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/service" +) + +// ============================ +// Request / Response structures +// ============================ + +type fetchOperationPayload struct { + OperationName string `json:"operationName"` +} + +type submitResponse struct { + Name string `json:"name"` +} + +type operationVideo struct { + MimeType string `json:"mimeType"` + BytesBase64Encoded string `json:"bytesBase64Encoded"` + Encoding string `json:"encoding"` +} + +type operationResponse struct { + Name string `json:"name"` + Done bool `json:"done"` + Response struct { + Type string `json:"@type"` + RaiMediaFilteredCount int `json:"raiMediaFilteredCount"` + Videos []operationVideo `json:"videos"` + BytesBase64Encoded string `json:"bytesBase64Encoded"` + Encoding string `json:"encoding"` + Video string `json:"video"` + } `json:"response"` + Error struct { + Message string `json:"message"` + } `json:"error"` +} + +// ============================ +// Adaptor implementation +// ============================ + +type TaskAdaptor struct { + taskcommon.BaseBilling + ChannelType int + apiKey string + baseURL string +} + +func (a *TaskAdaptor) Init(info *relaycommon.RelayInfo) { + a.ChannelType = info.ChannelType + a.baseURL = info.ChannelBaseUrl + a.apiKey = info.ApiKey +} + +// ValidateRequestAndSetAction parses body, validates fields and sets default action. +func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycommon.RelayInfo) (taskErr *dto.TaskError) { + // Use the standard validation method for TaskSubmitReq + return relaycommon.ValidateBasicTaskRequest(c, info, constant.TaskActionTextGenerate) +} + +// BuildRequestURL constructs the upstream URL. +func (a *TaskAdaptor) BuildRequestURL(info *relaycommon.RelayInfo) (string, error) { + adc := &vertexcore.Credentials{} + if err := common.Unmarshal([]byte(a.apiKey), adc); err != nil { + return "", fmt.Errorf("failed to decode credentials: %w", err) + } + modelName := info.UpstreamModelName + if modelName == "" { + modelName = "veo-3.0-generate-001" + } + + region := vertexcore.GetModelRegion(info.ApiVersion, modelName) + if strings.TrimSpace(region) == "" { + region = "global" + } + if region == "global" { + return fmt.Sprintf( + "https://aiplatform.googleapis.com/v1/projects/%s/locations/global/publishers/google/models/%s:predictLongRunning", + adc.ProjectID, + modelName, + ), nil + } + return fmt.Sprintf( + "https://%s-aiplatform.googleapis.com/v1/projects/%s/locations/%s/publishers/google/models/%s:predictLongRunning", + region, + adc.ProjectID, + region, + modelName, + ), nil +} + +// BuildRequestHeader sets required headers. +func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + adc := &vertexcore.Credentials{} + if err := common.Unmarshal([]byte(a.apiKey), adc); err != nil { + return fmt.Errorf("failed to decode credentials: %w", err) + } + + proxy := "" + if info != nil { + proxy = info.ChannelSetting.Proxy + } + token, err := vertexcore.AcquireAccessToken(*adc, proxy) + if err != nil { + return fmt.Errorf("failed to acquire access token: %w", err) + } + req.Header.Set("Authorization", "Bearer "+token) + req.Header.Set("x-goog-user-project", adc.ProjectID) + return nil +} + +// EstimateBilling returns OtherRatios based on durationSeconds and resolution. +func (a *TaskAdaptor) EstimateBilling(c *gin.Context, info *relaycommon.RelayInfo) map[string]float64 { + v, ok := c.Get("task_request") + if !ok { + return nil + } + req := v.(relaycommon.TaskSubmitReq) + + seconds := geminitask.ResolveVeoDuration(req.Metadata, req.Duration, req.Seconds) + resolution := geminitask.ResolveVeoResolution(req.Metadata, req.Size) + resRatio := geminitask.VeoResolutionRatio(info.UpstreamModelName, resolution) + + return map[string]float64{ + "seconds": float64(seconds), + "resolution": resRatio, + } +} + +// BuildRequestBody converts request into Vertex specific format. +func (a *TaskAdaptor) BuildRequestBody(c *gin.Context, info *relaycommon.RelayInfo) (io.Reader, error) { + v, ok := c.Get("task_request") + if !ok { + return nil, fmt.Errorf("request not found in context") + } + req := v.(relaycommon.TaskSubmitReq) + + instance := geminitask.VeoInstance{Prompt: req.Prompt} + if img := geminitask.ExtractMultipartImage(c, info); img != nil { + instance.Image = img + } else if len(req.Images) > 0 { + if parsed := geminitask.ParseImageInput(req.Images[0]); parsed != nil { + instance.Image = parsed + info.Action = constant.TaskActionGenerate + } + } + + params := &geminitask.VeoParameters{} + if err := taskcommon.UnmarshalMetadata(req.Metadata, params); err != nil { + return nil, fmt.Errorf("unmarshal metadata failed: %w", err) + } + if params.DurationSeconds == 0 && req.Duration > 0 { + params.DurationSeconds = req.Duration + } + if params.Resolution == "" && req.Size != "" { + params.Resolution = geminitask.SizeToVeoResolution(req.Size) + } + if params.AspectRatio == "" && req.Size != "" { + params.AspectRatio = geminitask.SizeToVeoAspectRatio(req.Size) + } + params.Resolution = strings.ToLower(params.Resolution) + params.SampleCount = 1 + + body := geminitask.VeoRequestPayload{ + Instances: []geminitask.VeoInstance{instance}, + Parameters: params, + } + + data, err := common.Marshal(body) + if err != nil { + return nil, err + } + return bytes.NewReader(data), nil +} + +// DoRequest delegates to common helper. +func (a *TaskAdaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (*http.Response, error) { + return channel.DoTaskApiRequest(a, c, info, requestBody) +} + +// DoResponse handles upstream response, returns taskID etc. +func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (taskID string, taskData []byte, taskErr *dto.TaskError) { + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + return "", nil, service.TaskErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError) + } + _ = resp.Body.Close() + + var s submitResponse + if err := common.Unmarshal(responseBody, &s); err != nil { + return "", nil, service.TaskErrorWrapper(err, "unmarshal_response_failed", http.StatusInternalServerError) + } + if strings.TrimSpace(s.Name) == "" { + return "", nil, service.TaskErrorWrapper(fmt.Errorf("missing operation name"), "invalid_response", http.StatusInternalServerError) + } + localID := taskcommon.EncodeLocalTaskID(s.Name) + ov := dto.NewOpenAIVideo() + ov.ID = info.PublicTaskID + ov.TaskID = info.PublicTaskID + ov.CreatedAt = time.Now().Unix() + ov.Model = info.OriginModelName + c.JSON(http.StatusOK, ov) + return localID, responseBody, nil +} + +func (a *TaskAdaptor) GetModelList() []string { + return []string{ + "veo-3.0-generate-001", + "veo-3.0-fast-generate-001", + "veo-3.1-generate-preview", + "veo-3.1-fast-generate-preview", + } +} +func (a *TaskAdaptor) GetChannelName() string { return "vertex" } + +// FetchTask fetch task status +func (a *TaskAdaptor) FetchTask(baseUrl, key string, body map[string]any, proxy string) (*http.Response, error) { + taskID, ok := body["task_id"].(string) + if !ok { + return nil, fmt.Errorf("invalid task_id") + } + upstreamName, err := taskcommon.DecodeLocalTaskID(taskID) + if err != nil { + return nil, fmt.Errorf("decode task_id failed: %w", err) + } + region := extractRegionFromOperationName(upstreamName) + if region == "" { + region = "us-central1" + } + project := extractProjectFromOperationName(upstreamName) + modelName := extractModelFromOperationName(upstreamName) + if project == "" || modelName == "" { + return nil, fmt.Errorf("cannot extract project/model from operation name") + } + var url string + if region == "global" { + url = fmt.Sprintf("https://aiplatform.googleapis.com/v1/projects/%s/locations/global/publishers/google/models/%s:fetchPredictOperation", project, modelName) + } else { + url = fmt.Sprintf("https://%s-aiplatform.googleapis.com/v1/projects/%s/locations/%s/publishers/google/models/%s:fetchPredictOperation", region, project, region, modelName) + } + payload := fetchOperationPayload{OperationName: upstreamName} + data, err := common.Marshal(payload) + if err != nil { + return nil, err + } + adc := &vertexcore.Credentials{} + if err := common.Unmarshal([]byte(key), adc); err != nil { + return nil, fmt.Errorf("failed to decode credentials: %w", err) + } + token, err := vertexcore.AcquireAccessToken(*adc, proxy) + if err != nil { + return nil, fmt.Errorf("failed to acquire access token: %w", err) + } + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + req.Header.Set("Authorization", "Bearer "+token) + req.Header.Set("x-goog-user-project", adc.ProjectID) + client, err := service.GetHttpClientWithProxy(proxy) + if err != nil { + return nil, fmt.Errorf("new proxy http client failed: %w", err) + } + return client.Do(req) +} + +func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, error) { + var op operationResponse + if err := common.Unmarshal(respBody, &op); err != nil { + return nil, fmt.Errorf("unmarshal operation response failed: %w", err) + } + ti := &relaycommon.TaskInfo{} + if op.Error.Message != "" { + ti.Status = model.TaskStatusFailure + ti.Reason = op.Error.Message + ti.Progress = "100%" + return ti, nil + } + if !op.Done { + ti.Status = model.TaskStatusInProgress + ti.Progress = "50%" + return ti, nil + } + ti.Status = model.TaskStatusSuccess + ti.Progress = "100%" + if len(op.Response.Videos) > 0 { + v0 := op.Response.Videos[0] + if v0.BytesBase64Encoded != "" { + mime := strings.TrimSpace(v0.MimeType) + if mime == "" { + enc := strings.TrimSpace(v0.Encoding) + if enc == "" { + enc = "mp4" + } + if strings.Contains(enc, "/") { + mime = enc + } else { + mime = "video/" + enc + } + } + ti.Url = "data:" + mime + ";base64," + v0.BytesBase64Encoded + return ti, nil + } + } + if op.Response.BytesBase64Encoded != "" { + enc := strings.TrimSpace(op.Response.Encoding) + if enc == "" { + enc = "mp4" + } + mime := enc + if !strings.Contains(enc, "/") { + mime = "video/" + enc + } + ti.Url = "data:" + mime + ";base64," + op.Response.BytesBase64Encoded + return ti, nil + } + if op.Response.Video != "" { // some variants use `video` as base64 + enc := strings.TrimSpace(op.Response.Encoding) + if enc == "" { + enc = "mp4" + } + mime := enc + if !strings.Contains(enc, "/") { + mime = "video/" + enc + } + ti.Url = "data:" + mime + ";base64," + op.Response.Video + return ti, nil + } + return ti, nil +} + +func (a *TaskAdaptor) ConvertToOpenAIVideo(task *model.Task) ([]byte, error) { + // Use GetUpstreamTaskID() to get the real upstream operation name for model extraction. + // task.TaskID is now a public task_xxxx ID, no longer a base64-encoded upstream name. + upstreamTaskID := task.GetUpstreamTaskID() + upstreamName, err := taskcommon.DecodeLocalTaskID(upstreamTaskID) + if err != nil { + upstreamName = "" + } + modelName := extractModelFromOperationName(upstreamName) + if strings.TrimSpace(modelName) == "" { + modelName = "veo-3.0-generate-001" + } + v := dto.NewOpenAIVideo() + v.ID = task.TaskID + v.Model = modelName + v.Status = task.Status.ToVideoStatus() + v.SetProgressStr(task.Progress) + v.CreatedAt = task.CreatedAt + v.CompletedAt = task.UpdatedAt + if resultURL := task.GetResultURL(); strings.HasPrefix(resultURL, "data:") && len(resultURL) > 0 { + v.SetMetadata("url", resultURL) + } + + return common.Marshal(v) +} + +// ============================ +// helpers +// ============================ + +var regionRe = regexp.MustCompile(`locations/([a-z0-9-]+)/`) + +func extractRegionFromOperationName(name string) string { + m := regionRe.FindStringSubmatch(name) + if len(m) == 2 { + return m[1] + } + return "" +} + +var modelRe = regexp.MustCompile(`models/([^/]+)/operations/`) + +func extractModelFromOperationName(name string) string { + m := modelRe.FindStringSubmatch(name) + if len(m) == 2 { + return m[1] + } + idx := strings.Index(name, "models/") + if idx >= 0 { + s := name[idx+len("models/"):] + if p := strings.Index(s, "/operations/"); p > 0 { + return s[:p] + } + } + return "" +} + +var projectRe = regexp.MustCompile(`projects/([^/]+)/locations/`) + +func extractProjectFromOperationName(name string) string { + m := projectRe.FindStringSubmatch(name) + if len(m) == 2 { + return m[1] + } + return "" +} diff --git a/_all-in-one-upload/new-api/relay/channel/volcengine/constants.go b/_all-in-one-upload/new-api/relay/channel/volcengine/constants.go new file mode 100644 index 0000000..87a12b2 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/volcengine/constants.go @@ -0,0 +1,19 @@ +package volcengine + +var ModelList = []string{ + "Doubao-pro-128k", + "Doubao-pro-32k", + "Doubao-pro-4k", + "Doubao-lite-128k", + "Doubao-lite-32k", + "Doubao-lite-4k", + "Doubao-embedding", + "doubao-seedream-4-0-250828", + "seedream-4-0-250828", + "doubao-seedance-1-0-pro-250528", + "seedance-1-0-pro-250528", + "doubao-seed-1-6-thinking-250715", + "seed-1-6-thinking-250715", +} + +var ChannelName = "volcengine" diff --git a/_all-in-one-upload/new-api/relay/channel/xinference/constant.go b/_all-in-one-upload/new-api/relay/channel/xinference/constant.go new file mode 100644 index 0000000..a119084 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/xinference/constant.go @@ -0,0 +1,8 @@ +package xinference + +var ModelList = []string{ + "bge-reranker-v2-m3", + "jina-reranker-v2", +} + +var ChannelName = "xinference" diff --git a/_all-in-one-upload/new-api/relay/channel/zhipu_4v/relay-zhipu_v4.go b/_all-in-one-upload/new-api/relay/channel/zhipu_4v/relay-zhipu_v4.go new file mode 100644 index 0000000..91ef0c4 --- /dev/null +++ b/_all-in-one-upload/new-api/relay/channel/zhipu_4v/relay-zhipu_v4.go @@ -0,0 +1,60 @@ +package zhipu_4v + +import ( + "strings" + + "github.com/QuantumNous/new-api/dto" +) + +func requestOpenAI2Zhipu(request dto.GeneralOpenAIRequest) *dto.GeneralOpenAIRequest { + messages := make([]dto.Message, 0, len(request.Messages)) + for _, message := range request.Messages { + if !message.IsStringContent() { + mediaMessages := message.ParseContent() + for j, mediaMessage := range mediaMessages { + if mediaMessage.Type == dto.ContentTypeImageURL { + imageUrl := mediaMessage.GetImageMedia() + // check if base64 + if strings.HasPrefix(imageUrl.Url, "data:image/") { + // 去除base64数据的URL前缀(如果有) + if idx := strings.Index(imageUrl.Url, ","); idx != -1 { + imageUrl.Url = imageUrl.Url[idx+1:] + } + } + mediaMessage.ImageUrl = imageUrl + mediaMessages[j] = mediaMessage + } + } + message.SetMediaContent(mediaMessages) + } + messages = append(messages, dto.Message{ + Role: message.Role, + Content: message.Content, + ToolCalls: message.ToolCalls, + ToolCallId: message.ToolCallId, + }) + } + str, ok := request.Stop.(string) + var Stop []string + if ok { + Stop = []string{str} + } else { + Stop, _ = request.Stop.([]string) + } + out := &dto.GeneralOpenAIRequest{ + Model: request.Model, + Stream: request.Stream, + Messages: messages, + Temperature: request.Temperature, + TopP: request.TopP, + Stop: Stop, + Tools: request.Tools, + ToolChoice: request.ToolChoice, + THINKING: request.THINKING, + } + if request.MaxTokens != nil || request.MaxCompletionTokens != nil { + maxTokens := request.GetMaxTokens() + out.MaxTokens = &maxTokens + } + return out +} diff --git a/_all-in-one-upload/new-api/relay/helper/price.go b/_all-in-one-upload/new-api/relay/helper/price.go new file mode 100644 index 0000000..0e68edb --- /dev/null +++ b/_all-in-one-upload/new-api/relay/helper/price.go @@ -0,0 +1,308 @@ +package helper + +import ( + "fmt" + "strings" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/logger" + "github.com/QuantumNous/new-api/model" + "github.com/QuantumNous/new-api/pkg/billingexpr" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/setting/billing_setting" + "github.com/QuantumNous/new-api/setting/operation_setting" + "github.com/QuantumNous/new-api/setting/ratio_setting" + "github.com/QuantumNous/new-api/types" + + "github.com/gin-gonic/gin" +) + +func modelPriceNotConfiguredError(modelName string, userId int) error { + if model.IsAdmin(userId) { + return fmt.Errorf( + "模型 %s 的价格未配置。请前往「系统设置 → 运营设置」开启自用模式,或在「系统设置 → 分组与模型定价设置」中为该模型配置价格;"+ + "Model %s price not configured. Go to System Settings → Operation Settings to enable self-use mode, or configure the model price in System Settings → Group & Model Pricing.", + modelName, modelName, + ) + } + return fmt.Errorf( + "模型 %s 的价格尚未由管理员配置,暂时无法使用,请联系站点管理员开启该模型;"+ + "Model %s has not been priced by the administrator yet. Please contact the site administrator to enable this model.", + modelName, modelName, + ) +} + +// https://docs.claude.com/en/docs/build-with-claude/prompt-caching#1-hour-cache-duration +const claudeCacheCreation1hMultiplier = 6 / 3.75 + +// HandleGroupRatio checks for "auto_group" in the context and updates the group ratio and relayInfo.UsingGroup if present +func HandleGroupRatio(ctx *gin.Context, relayInfo *relaycommon.RelayInfo) types.GroupRatioInfo { + groupRatioInfo := types.GroupRatioInfo{ + GroupRatio: 1.0, // default ratio + GroupSpecialRatio: -1, + } + + // check auto group + autoGroup, exists := ctx.Get("auto_group") + if exists { + logger.LogDebug(ctx, fmt.Sprintf("final group: %s", autoGroup)) + relayInfo.UsingGroup = autoGroup.(string) + } + + // check user group special ratio + userGroupRatio, ok := ratio_setting.GetGroupGroupRatio(relayInfo.UserGroup, relayInfo.UsingGroup) + if ok { + // user group special ratio + groupRatioInfo.GroupSpecialRatio = userGroupRatio + groupRatioInfo.GroupRatio = userGroupRatio + groupRatioInfo.HasSpecialRatio = true + } else { + // normal group ratio + groupRatioInfo.GroupRatio = ratio_setting.GetGroupRatio(relayInfo.UsingGroup) + } + + return groupRatioInfo +} + +func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta) (types.PriceData, error) { + modelPrice, usePrice := ratio_setting.GetModelPrice(info.OriginModelName, false) + + groupRatioInfo := HandleGroupRatio(c, info) + + // Check if this model uses tiered_expr billing + if billing_setting.GetBillingMode(info.OriginModelName) == billing_setting.BillingModeTieredExpr { + return modelPriceHelperTiered(c, info, promptTokens, meta, groupRatioInfo) + } + + var preConsumedQuota int + var modelRatio float64 + var completionRatio float64 + var cacheRatio float64 + var imageRatio float64 + var cacheCreationRatio float64 + var cacheCreationRatio5m float64 + var cacheCreationRatio1h float64 + var audioRatio float64 + var audioCompletionRatio float64 + var freeModel bool + if !usePrice { + preConsumedTokens := common.Max(promptTokens, common.PreConsumedQuota) + if meta.MaxTokens != 0 { + preConsumedTokens += meta.MaxTokens + } + var success bool + var matchName string + modelRatio, success, matchName = ratio_setting.GetModelRatio(info.OriginModelName) + if !success { + acceptUnsetRatio := false + if info.UserSetting.AcceptUnsetRatioModel { + acceptUnsetRatio = true + } + if !acceptUnsetRatio { + return types.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId) + } + } + completionRatio = ratio_setting.GetCompletionRatio(info.OriginModelName) + cacheRatio, _ = ratio_setting.GetCacheRatio(info.OriginModelName) + cacheCreationRatio, _ = ratio_setting.GetCreateCacheRatio(info.OriginModelName) + cacheCreationRatio5m = cacheCreationRatio + // 固定1h和5min缓存写入价格的比例 + cacheCreationRatio1h = cacheCreationRatio * claudeCacheCreation1hMultiplier + imageRatio, _ = ratio_setting.GetImageRatio(info.OriginModelName) + audioRatio = ratio_setting.GetAudioRatio(info.OriginModelName) + audioCompletionRatio = ratio_setting.GetAudioCompletionRatio(info.OriginModelName) + ratio := modelRatio * groupRatioInfo.GroupRatio + preConsumedQuota = int(float64(preConsumedTokens) * ratio) + } else { + if meta.ImagePriceRatio != 0 { + modelPrice = modelPrice * meta.ImagePriceRatio + } + preConsumedQuota = int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio) + } + + // check if free model pre-consume is disabled + if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { + // if model price or ratio is 0, do not pre-consume quota + if groupRatioInfo.GroupRatio == 0 { + preConsumedQuota = 0 + freeModel = true + } else if usePrice { + if modelPrice == 0 { + preConsumedQuota = 0 + freeModel = true + } + } else { + if modelRatio == 0 { + preConsumedQuota = 0 + freeModel = true + } + } + } + + priceData := types.PriceData{ + FreeModel: freeModel, + ModelPrice: modelPrice, + ModelRatio: modelRatio, + CompletionRatio: completionRatio, + GroupRatioInfo: groupRatioInfo, + UsePrice: usePrice, + CacheRatio: cacheRatio, + ImageRatio: imageRatio, + AudioRatio: audioRatio, + AudioCompletionRatio: audioCompletionRatio, + CacheCreationRatio: cacheCreationRatio, + CacheCreation5mRatio: cacheCreationRatio5m, + CacheCreation1hRatio: cacheCreationRatio1h, + QuotaToPreConsume: preConsumedQuota, + } + + if common.DebugEnabled { + println(fmt.Sprintf("model_price_helper result: %s", priceData.ToSetting())) + } + info.PriceData = priceData + return priceData, nil +} + +// ModelPriceHelperPerCall 按次/按量计费的 PriceHelper (MJ、Task) +func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types.PriceData, error) { + groupRatioInfo := HandleGroupRatio(c, info) + + modelPrice, success := ratio_setting.GetModelPrice(info.OriginModelName, true) + usePrice := success + var modelRatio float64 + + if !success { + defaultPrice, ok := ratio_setting.GetDefaultModelPriceMap()[info.OriginModelName] + if ok { + modelPrice = defaultPrice + usePrice = true + } else { + var ratioSuccess bool + var matchName string + modelRatio, ratioSuccess, matchName = ratio_setting.GetModelRatio(info.OriginModelName) + acceptUnsetRatio := false + if info.UserSetting.AcceptUnsetRatioModel { + acceptUnsetRatio = true + } + if !ratioSuccess && !acceptUnsetRatio { + return types.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId) + } + } + } + + var quota int + freeModel := false + + if usePrice { + quota = int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio) + if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { + if groupRatioInfo.GroupRatio == 0 || modelPrice == 0 { + quota = 0 + freeModel = true + } + } + } else { + // 按量计费:以模型倍率的一半作为预扣额度 + quota = int(modelRatio / 2 * common.QuotaPerUnit * groupRatioInfo.GroupRatio) + modelPrice = -1 + if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { + if groupRatioInfo.GroupRatio == 0 || modelRatio == 0 { + quota = 0 + freeModel = true + } + } + } + + priceData := types.PriceData{ + FreeModel: freeModel, + ModelPrice: modelPrice, + ModelRatio: modelRatio, + UsePrice: usePrice, + Quota: quota, + GroupRatioInfo: groupRatioInfo, + } + return priceData, nil +} + +func HasModelBillingConfig(modelName string) bool { + if _, ok := ratio_setting.GetModelPrice(modelName, false); ok { + return true + } + if _, ok, _ := ratio_setting.GetModelRatio(modelName); ok { + return true + } + if billing_setting.GetBillingMode(modelName) != billing_setting.BillingModeTieredExpr { + return false + } + expr, ok := billing_setting.GetBillingExpr(modelName) + return ok && strings.TrimSpace(expr) != "" +} + +func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta, groupRatioInfo types.GroupRatioInfo) (types.PriceData, error) { + exprStr, ok := billing_setting.GetBillingExpr(info.OriginModelName) + if !ok { + return types.PriceData{}, fmt.Errorf("model %s is configured as tiered_expr but has no billing expression", info.OriginModelName) + } + + estimatedCompletionTokens := 0 + if meta.MaxTokens != 0 { + estimatedCompletionTokens = meta.MaxTokens + } + + requestInput, err := ResolveIncomingBillingExprRequestInput(c, info) + if err != nil { + return types.PriceData{}, err + } + + rawCost, trace, err := billingexpr.RunExprWithRequest(exprStr, billingexpr.TokenParams{ + P: float64(promptTokens), + C: float64(estimatedCompletionTokens), + Len: float64(promptTokens), + }, requestInput) + if err != nil { + return types.PriceData{}, fmt.Errorf("model %s tiered expr run failed: %w", info.OriginModelName, err) + } + + // Expression coefficients are $/1M tokens prices; convert to quota the same way per-call billing does. + quotaBeforeGroup := rawCost / 1_000_000 * common.QuotaPerUnit + preConsumedQuota := billingexpr.QuotaRound(quotaBeforeGroup * groupRatioInfo.GroupRatio) + + freeModel := false + if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { + if groupRatioInfo.GroupRatio == 0 { + preConsumedQuota = 0 + freeModel = true + } + } + + exprHash := billingexpr.ExprHashString(exprStr) + snapshot := &billingexpr.BillingSnapshot{ + BillingMode: billing_setting.BillingModeTieredExpr, + ModelName: info.OriginModelName, + ExprString: exprStr, + ExprHash: exprHash, + GroupRatio: groupRatioInfo.GroupRatio, + EstimatedPromptTokens: promptTokens, + EstimatedCompletionTokens: estimatedCompletionTokens, + EstimatedQuotaBeforeGroup: quotaBeforeGroup, + EstimatedQuotaAfterGroup: preConsumedQuota, + EstimatedTier: trace.MatchedTier, + QuotaPerUnit: common.QuotaPerUnit, + ExprVersion: billingexpr.ExprVersion(exprStr), + } + info.TieredBillingSnapshot = snapshot + info.BillingRequestInput = &requestInput + + priceData := types.PriceData{ + FreeModel: freeModel, + GroupRatioInfo: groupRatioInfo, + QuotaToPreConsume: preConsumedQuota, + } + + if common.DebugEnabled { + println(fmt.Sprintf("model_price_helper_tiered result: model=%s preConsume=%d quotaBeforeGroup=%.2f groupRatio=%.2f tier=%s", info.OriginModelName, preConsumedQuota, quotaBeforeGroup, groupRatioInfo.GroupRatio, trace.MatchedTier)) + } + + info.PriceData = priceData + return priceData, nil +} diff --git a/_all-in-one-upload/new-api/service/codex_oauth.go b/_all-in-one-upload/new-api/service/codex_oauth.go new file mode 100644 index 0000000..33ef1d6 --- /dev/null +++ b/_all-in-one-upload/new-api/service/codex_oauth.go @@ -0,0 +1,317 @@ +package service + +import ( + "context" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" +) + +const ( + codexOAuthClientID = "app_EMoamEEZ73f0CkXaXp7hrann" + codexOAuthAuthorizeURL = "https://auth.openai.com/oauth/authorize" + codexOAuthTokenURL = "https://auth.openai.com/oauth/token" + codexOAuthRedirectURI = "http://localhost:1455/auth/callback" + codexOAuthScope = "openid profile email offline_access" + codexJWTClaimPath = "https://api.openai.com/auth" + defaultHTTPTimeout = 20 * time.Second +) + +type CodexOAuthTokenResult struct { + AccessToken string + RefreshToken string + ExpiresAt time.Time +} + +type CodexOAuthAuthorizationFlow struct { + State string + Verifier string + Challenge string + AuthorizeURL string +} + +func RefreshCodexOAuthToken(ctx context.Context, refreshToken string) (*CodexOAuthTokenResult, error) { + return RefreshCodexOAuthTokenWithProxy(ctx, refreshToken, "") +} + +func RefreshCodexOAuthTokenWithProxy(ctx context.Context, refreshToken string, proxyURL string) (*CodexOAuthTokenResult, error) { + client, err := getCodexOAuthHTTPClient(proxyURL) + if err != nil { + return nil, err + } + return refreshCodexOAuthToken(ctx, client, codexOAuthTokenURL, codexOAuthClientID, refreshToken) +} + +func ExchangeCodexAuthorizationCode(ctx context.Context, code string, verifier string) (*CodexOAuthTokenResult, error) { + return ExchangeCodexAuthorizationCodeWithProxy(ctx, code, verifier, "") +} + +func ExchangeCodexAuthorizationCodeWithProxy(ctx context.Context, code string, verifier string, proxyURL string) (*CodexOAuthTokenResult, error) { + client, err := getCodexOAuthHTTPClient(proxyURL) + if err != nil { + return nil, err + } + return exchangeCodexAuthorizationCode(ctx, client, codexOAuthTokenURL, codexOAuthClientID, code, verifier, codexOAuthRedirectURI) +} + +func CreateCodexOAuthAuthorizationFlow() (*CodexOAuthAuthorizationFlow, error) { + state, err := createStateHex(16) + if err != nil { + return nil, err + } + verifier, challenge, err := generatePKCEPair() + if err != nil { + return nil, err + } + u, err := buildCodexAuthorizeURL(state, challenge) + if err != nil { + return nil, err + } + return &CodexOAuthAuthorizationFlow{ + State: state, + Verifier: verifier, + Challenge: challenge, + AuthorizeURL: u, + }, nil +} + +func refreshCodexOAuthToken( + ctx context.Context, + client *http.Client, + tokenURL string, + clientID string, + refreshToken string, +) (*CodexOAuthTokenResult, error) { + rt := strings.TrimSpace(refreshToken) + if rt == "" { + return nil, errors.New("empty refresh_token") + } + + form := url.Values{} + form.Set("grant_type", "refresh_token") + form.Set("refresh_token", rt) + form.Set("client_id", clientID) + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, tokenURL, strings.NewReader(form.Encode())) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", "application/json") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var payload struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresIn int `json:"expires_in"` + } + + if err := common.DecodeJson(resp.Body, &payload); err != nil { + return nil, err + } + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return nil, fmt.Errorf("codex oauth refresh failed: status=%d", resp.StatusCode) + } + + if strings.TrimSpace(payload.AccessToken) == "" || strings.TrimSpace(payload.RefreshToken) == "" || payload.ExpiresIn <= 0 { + return nil, errors.New("codex oauth refresh response missing fields") + } + + return &CodexOAuthTokenResult{ + AccessToken: strings.TrimSpace(payload.AccessToken), + RefreshToken: strings.TrimSpace(payload.RefreshToken), + ExpiresAt: time.Now().Add(time.Duration(payload.ExpiresIn) * time.Second), + }, nil +} + +func exchangeCodexAuthorizationCode( + ctx context.Context, + client *http.Client, + tokenURL string, + clientID string, + code string, + verifier string, + redirectURI string, +) (*CodexOAuthTokenResult, error) { + c := strings.TrimSpace(code) + v := strings.TrimSpace(verifier) + if c == "" { + return nil, errors.New("empty authorization code") + } + if v == "" { + return nil, errors.New("empty code_verifier") + } + + form := url.Values{} + form.Set("grant_type", "authorization_code") + form.Set("client_id", clientID) + form.Set("code", c) + form.Set("code_verifier", v) + form.Set("redirect_uri", redirectURI) + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, tokenURL, strings.NewReader(form.Encode())) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", "application/json") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var payload struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresIn int `json:"expires_in"` + } + if err := common.DecodeJson(resp.Body, &payload); err != nil { + return nil, err + } + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return nil, fmt.Errorf("codex oauth code exchange failed: status=%d", resp.StatusCode) + } + if strings.TrimSpace(payload.AccessToken) == "" || strings.TrimSpace(payload.RefreshToken) == "" || payload.ExpiresIn <= 0 { + return nil, errors.New("codex oauth token response missing fields") + } + return &CodexOAuthTokenResult{ + AccessToken: strings.TrimSpace(payload.AccessToken), + RefreshToken: strings.TrimSpace(payload.RefreshToken), + ExpiresAt: time.Now().Add(time.Duration(payload.ExpiresIn) * time.Second), + }, nil +} + +func getCodexOAuthHTTPClient(proxyURL string) (*http.Client, error) { + baseClient, err := GetHttpClientWithProxy(strings.TrimSpace(proxyURL)) + if err != nil { + return nil, err + } + if baseClient == nil { + return &http.Client{Timeout: defaultHTTPTimeout}, nil + } + clientCopy := *baseClient + clientCopy.Timeout = defaultHTTPTimeout + return &clientCopy, nil +} + +func buildCodexAuthorizeURL(state string, challenge string) (string, error) { + u, err := url.Parse(codexOAuthAuthorizeURL) + if err != nil { + return "", err + } + q := u.Query() + q.Set("response_type", "code") + q.Set("client_id", codexOAuthClientID) + q.Set("redirect_uri", codexOAuthRedirectURI) + q.Set("scope", codexOAuthScope) + q.Set("code_challenge", challenge) + q.Set("code_challenge_method", "S256") + q.Set("state", state) + q.Set("id_token_add_organizations", "true") + q.Set("codex_cli_simplified_flow", "true") + q.Set("originator", "codex_cli_rs") + u.RawQuery = q.Encode() + return u.String(), nil +} + +func createStateHex(nBytes int) (string, error) { + if nBytes <= 0 { + return "", errors.New("invalid state bytes length") + } + b := make([]byte, nBytes) + if _, err := rand.Read(b); err != nil { + return "", err + } + return fmt.Sprintf("%x", b), nil +} + +func generatePKCEPair() (verifier string, challenge string, err error) { + b := make([]byte, 32) + if _, err := rand.Read(b); err != nil { + return "", "", err + } + verifier = base64.RawURLEncoding.EncodeToString(b) + sum := sha256.Sum256([]byte(verifier)) + challenge = base64.RawURLEncoding.EncodeToString(sum[:]) + return verifier, challenge, nil +} + +func ExtractCodexAccountIDFromJWT(token string) (string, bool) { + claims, ok := decodeJWTClaims(token) + if !ok { + return "", false + } + raw, ok := claims[codexJWTClaimPath] + if !ok { + return "", false + } + obj, ok := raw.(map[string]any) + if !ok { + return "", false + } + v, ok := obj["chatgpt_account_id"] + if !ok { + return "", false + } + s, ok := v.(string) + if !ok { + return "", false + } + s = strings.TrimSpace(s) + if s == "" { + return "", false + } + return s, true +} + +func ExtractEmailFromJWT(token string) (string, bool) { + claims, ok := decodeJWTClaims(token) + if !ok { + return "", false + } + v, ok := claims["email"] + if !ok { + return "", false + } + s, ok := v.(string) + if !ok { + return "", false + } + s = strings.TrimSpace(s) + if s == "" { + return "", false + } + return s, true +} + +func decodeJWTClaims(token string) (map[string]any, bool) { + parts := strings.Split(token, ".") + if len(parts) != 3 { + return nil, false + } + payloadRaw, err := base64.RawURLEncoding.DecodeString(parts[1]) + if err != nil { + return nil, false + } + var claims map[string]any + if err := json.Unmarshal(payloadRaw, &claims); err != nil { + return nil, false + } + return claims, true +} diff --git a/_all-in-one-upload/new-api/service/quota.go b/_all-in-one-upload/new-api/service/quota.go new file mode 100644 index 0000000..398bd1b --- /dev/null +++ b/_all-in-one-upload/new-api/service/quota.go @@ -0,0 +1,544 @@ +package service + +import ( + "errors" + "fmt" + "log" + "math" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/logger" + "github.com/QuantumNous/new-api/model" + "github.com/QuantumNous/new-api/pkg/billingexpr" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/setting/ratio_setting" + "github.com/QuantumNous/new-api/setting/system_setting" + "github.com/QuantumNous/new-api/types" + + "github.com/bytedance/gopkg/util/gopool" + + "github.com/gin-gonic/gin" + "github.com/shopspring/decimal" +) + +type TokenDetails struct { + TextTokens int + AudioTokens int +} + +type QuotaInfo struct { + InputDetails TokenDetails + OutputDetails TokenDetails + ModelName string + UsePrice bool + ModelPrice float64 + ModelRatio float64 + GroupRatio float64 +} + +func hasCustomModelRatio(modelName string, currentRatio float64) bool { + defaultRatio, exists := ratio_setting.GetDefaultModelRatioMap()[modelName] + if !exists { + return true + } + return currentRatio != defaultRatio +} + +func calculateAudioQuota(info QuotaInfo) int { + if info.UsePrice { + modelPrice := decimal.NewFromFloat(info.ModelPrice) + quotaPerUnit := decimal.NewFromFloat(common.QuotaPerUnit) + groupRatio := decimal.NewFromFloat(info.GroupRatio) + + quota := modelPrice.Mul(quotaPerUnit).Mul(groupRatio) + return int(quota.IntPart()) + } + + completionRatio := decimal.NewFromFloat(ratio_setting.GetCompletionRatio(info.ModelName)) + audioRatio := decimal.NewFromFloat(ratio_setting.GetAudioRatio(info.ModelName)) + audioCompletionRatio := decimal.NewFromFloat(ratio_setting.GetAudioCompletionRatio(info.ModelName)) + + groupRatio := decimal.NewFromFloat(info.GroupRatio) + modelRatio := decimal.NewFromFloat(info.ModelRatio) + ratio := groupRatio.Mul(modelRatio) + + inputTextTokens := decimal.NewFromInt(int64(info.InputDetails.TextTokens)) + outputTextTokens := decimal.NewFromInt(int64(info.OutputDetails.TextTokens)) + inputAudioTokens := decimal.NewFromInt(int64(info.InputDetails.AudioTokens)) + outputAudioTokens := decimal.NewFromInt(int64(info.OutputDetails.AudioTokens)) + + quota := decimal.Zero + quota = quota.Add(inputTextTokens) + quota = quota.Add(outputTextTokens.Mul(completionRatio)) + quota = quota.Add(inputAudioTokens.Mul(audioRatio)) + quota = quota.Add(outputAudioTokens.Mul(audioRatio).Mul(audioCompletionRatio)) + + quota = quota.Mul(ratio) + + // If ratio is not zero and quota is less than or equal to zero, set quota to 1 + if !ratio.IsZero() && quota.LessThanOrEqual(decimal.Zero) { + quota = decimal.NewFromInt(1) + } + + return int(quota.Round(0).IntPart()) +} + +func PreWssConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, usage *dto.RealtimeUsage) error { + if relayInfo.UsePrice { + return nil + } + userQuota, err := model.GetUserQuota(relayInfo.UserId, false) + if err != nil { + return err + } + + token, err := model.GetTokenByKey(strings.TrimPrefix(relayInfo.TokenKey, "sk-"), false) + if err != nil { + return err + } + + modelName := relayInfo.OriginModelName + textInputTokens := usage.InputTokenDetails.TextTokens + textOutTokens := usage.OutputTokenDetails.TextTokens + audioInputTokens := usage.InputTokenDetails.AudioTokens + audioOutTokens := usage.OutputTokenDetails.AudioTokens + groupRatio := ratio_setting.GetGroupRatio(relayInfo.UsingGroup) + modelRatio, _, _ := ratio_setting.GetModelRatio(modelName) + + autoGroup, exists := common.GetContextKey(ctx, constant.ContextKeyAutoGroup) + if exists { + groupRatio = ratio_setting.GetGroupRatio(autoGroup.(string)) + log.Printf("final group ratio: %f", groupRatio) + relayInfo.UsingGroup = autoGroup.(string) + } + + actualGroupRatio := groupRatio + userGroupRatio, ok := ratio_setting.GetGroupGroupRatio(relayInfo.UserGroup, relayInfo.UsingGroup) + if ok { + actualGroupRatio = userGroupRatio + } + + quotaInfo := QuotaInfo{ + InputDetails: TokenDetails{ + TextTokens: textInputTokens, + AudioTokens: audioInputTokens, + }, + OutputDetails: TokenDetails{ + TextTokens: textOutTokens, + AudioTokens: audioOutTokens, + }, + ModelName: modelName, + UsePrice: relayInfo.UsePrice, + ModelRatio: modelRatio, + GroupRatio: actualGroupRatio, + } + + quota := calculateAudioQuota(quotaInfo) + + if userQuota < quota { + return fmt.Errorf("user quota is not enough, user quota: %s, need quota: %s", logger.FormatQuota(userQuota), logger.FormatQuota(quota)) + } + + if !token.UnlimitedQuota && token.RemainQuota < quota { + return fmt.Errorf("token quota is not enough, token remain quota: %s, need quota: %s", logger.FormatQuota(token.RemainQuota), logger.FormatQuota(quota)) + } + + err = PostConsumeQuota(relayInfo, quota, 0, false) + if err != nil { + return err + } + logger.LogInfo(ctx, "realtime streaming consume quota success, quota: "+fmt.Sprintf("%d", quota)) + return nil +} + +func PostWssConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, modelName string, + usage *dto.RealtimeUsage, extraContent string) { + + var tieredResult *billingexpr.TieredResult + tieredOk, tieredQuota, tieredRes := TryTieredSettle(relayInfo, billingexpr.TokenParams{ + P: float64(usage.InputTokens), + C: float64(usage.OutputTokens), + Len: float64(usage.InputTokens), + }) + if tieredOk { + tieredResult = tieredRes + } + + useTimeSeconds := time.Now().Unix() - relayInfo.StartTime.Unix() + textInputTokens := usage.InputTokenDetails.TextTokens + textOutTokens := usage.OutputTokenDetails.TextTokens + + audioInputTokens := usage.InputTokenDetails.AudioTokens + audioOutTokens := usage.OutputTokenDetails.AudioTokens + + tokenName := ctx.GetString("token_name") + completionRatio := decimal.NewFromFloat(ratio_setting.GetCompletionRatio(modelName)) + audioRatio := decimal.NewFromFloat(ratio_setting.GetAudioRatio(relayInfo.OriginModelName)) + audioCompletionRatio := decimal.NewFromFloat(ratio_setting.GetAudioCompletionRatio(modelName)) + + modelRatio := relayInfo.PriceData.ModelRatio + groupRatio := relayInfo.PriceData.GroupRatioInfo.GroupRatio + modelPrice := relayInfo.PriceData.ModelPrice + usePrice := relayInfo.PriceData.UsePrice + + quotaInfo := QuotaInfo{ + InputDetails: TokenDetails{ + TextTokens: textInputTokens, + AudioTokens: audioInputTokens, + }, + OutputDetails: TokenDetails{ + TextTokens: textOutTokens, + AudioTokens: audioOutTokens, + }, + ModelName: modelName, + UsePrice: usePrice, + ModelRatio: modelRatio, + GroupRatio: groupRatio, + } + + quota := calculateAudioQuota(quotaInfo) + if tieredOk { + quota = tieredQuota + } + + totalTokens := usage.TotalTokens + var logContent string + if !usePrice { + logContent = fmt.Sprintf("模型倍率 %.2f,补全倍率 %.2f,音频倍率 %.2f,音频补全倍率 %.2f,分组倍率 %.2f", + modelRatio, completionRatio.InexactFloat64(), audioRatio.InexactFloat64(), audioCompletionRatio.InexactFloat64(), groupRatio) + } else { + logContent = fmt.Sprintf("模型价格 %.2f,分组倍率 %.2f", modelPrice, groupRatio) + } + + // record all the consume log even if quota is 0 + if totalTokens == 0 { + // in this case, must be some error happened + // we cannot just return, because we may have to return the pre-consumed quota + quota = 0 + logContent += fmt.Sprintf("(可能是上游超时)") + logger.LogError(ctx, fmt.Sprintf("total tokens is 0, cannot consume quota, userId %d, channelId %d, "+ + "tokenId %d, model %s, pre-consumed quota %d", relayInfo.UserId, relayInfo.ChannelId, relayInfo.TokenId, modelName, relayInfo.FinalPreConsumedQuota)) + } else { + model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, quota) + model.UpdateChannelUsedQuota(relayInfo.ChannelId, quota) + } + + if err := SettleBilling(ctx, relayInfo, quota); err != nil { + logger.LogError(ctx, "error settling billing: "+err.Error()) + } + + logModel := modelName + if extraContent != "" { + logContent += ", " + extraContent + } + other := GenerateWssOtherInfo(ctx, relayInfo, usage, modelRatio, groupRatio, + completionRatio.InexactFloat64(), audioRatio.InexactFloat64(), audioCompletionRatio.InexactFloat64(), modelPrice, relayInfo.PriceData.GroupRatioInfo.GroupSpecialRatio) + if tieredResult != nil { + InjectTieredBillingInfo(other, relayInfo, tieredResult) + } + model.RecordConsumeLog(ctx, relayInfo.UserId, model.RecordConsumeLogParams{ + ChannelId: relayInfo.ChannelId, + PromptTokens: usage.InputTokens, + CompletionTokens: usage.OutputTokens, + ModelName: logModel, + TokenName: tokenName, + Quota: quota, + Content: logContent, + TokenId: relayInfo.TokenId, + UseTimeSeconds: int(useTimeSeconds), + IsStream: relayInfo.IsStream, + Group: relayInfo.UsingGroup, + Other: other, + }) +} + +func CalcOpenRouterCacheCreateTokens(usage dto.Usage, priceData types.PriceData) int { + if priceData.CacheCreationRatio == 1 { + return 0 + } + quotaPrice := priceData.ModelRatio / common.QuotaPerUnit + promptCacheCreatePrice := quotaPrice * priceData.CacheCreationRatio + promptCacheReadPrice := quotaPrice * priceData.CacheRatio + completionPrice := quotaPrice * priceData.CompletionRatio + + cost, _ := usage.Cost.(float64) + totalPromptTokens := float64(usage.PromptTokens) + completionTokens := float64(usage.CompletionTokens) + promptCacheReadTokens := float64(usage.PromptTokensDetails.CachedTokens) + + return int(math.Round((cost - + totalPromptTokens*quotaPrice + + promptCacheReadTokens*(quotaPrice-promptCacheReadPrice) - + completionTokens*completionPrice) / + (promptCacheCreatePrice - quotaPrice))) +} + +func PostAudioConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, usage *dto.Usage, extraContent string) { + + var tieredUsedVars map[string]bool + if snap := relayInfo.TieredBillingSnapshot; snap != nil { + tieredUsedVars = billingexpr.UsedVars(snap.ExprString) + } + var tieredResult *billingexpr.TieredResult + tieredOk, tieredQuota, tieredRes := TryTieredSettle(relayInfo, BuildTieredTokenParams(usage, false, tieredUsedVars)) + if tieredOk { + tieredResult = tieredRes + } + + useTimeSeconds := time.Now().Unix() - relayInfo.StartTime.Unix() + textInputTokens := usage.PromptTokensDetails.TextTokens + textOutTokens := usage.CompletionTokenDetails.TextTokens + + audioInputTokens := usage.PromptTokensDetails.AudioTokens + audioOutTokens := usage.CompletionTokenDetails.AudioTokens + + tokenName := ctx.GetString("token_name") + completionRatio := decimal.NewFromFloat(ratio_setting.GetCompletionRatio(relayInfo.OriginModelName)) + audioRatio := decimal.NewFromFloat(ratio_setting.GetAudioRatio(relayInfo.OriginModelName)) + audioCompletionRatio := decimal.NewFromFloat(ratio_setting.GetAudioCompletionRatio(relayInfo.OriginModelName)) + + modelRatio := relayInfo.PriceData.ModelRatio + groupRatio := relayInfo.PriceData.GroupRatioInfo.GroupRatio + modelPrice := relayInfo.PriceData.ModelPrice + usePrice := relayInfo.PriceData.UsePrice + + quotaInfo := QuotaInfo{ + InputDetails: TokenDetails{ + TextTokens: textInputTokens, + AudioTokens: audioInputTokens, + }, + OutputDetails: TokenDetails{ + TextTokens: textOutTokens, + AudioTokens: audioOutTokens, + }, + ModelName: relayInfo.OriginModelName, + UsePrice: usePrice, + ModelRatio: modelRatio, + GroupRatio: groupRatio, + } + + quota := calculateAudioQuota(quotaInfo) + if tieredOk { + quota = tieredQuota + } + + totalTokens := usage.TotalTokens + var logContent string + if !usePrice { + logContent = fmt.Sprintf("模型倍率 %.2f,补全倍率 %.2f,音频倍率 %.2f,音频补全倍率 %.2f,分组倍率 %.2f", + modelRatio, completionRatio.InexactFloat64(), audioRatio.InexactFloat64(), audioCompletionRatio.InexactFloat64(), groupRatio) + } else { + logContent = fmt.Sprintf("模型价格 %.2f,分组倍率 %.2f", modelPrice, groupRatio) + } + + // record all the consume log even if quota is 0 + if totalTokens == 0 { + // in this case, must be some error happened + // we cannot just return, because we may have to return the pre-consumed quota + quota = 0 + logContent += fmt.Sprintf("(可能是上游超时)") + logger.LogError(ctx, fmt.Sprintf("total tokens is 0, cannot consume quota, userId %d, channelId %d, "+ + "tokenId %d, model %s, pre-consumed quota %d", relayInfo.UserId, relayInfo.ChannelId, relayInfo.TokenId, relayInfo.OriginModelName, relayInfo.FinalPreConsumedQuota)) + } else { + model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, quota) + model.UpdateChannelUsedQuota(relayInfo.ChannelId, quota) + } + + if err := SettleBilling(ctx, relayInfo, quota); err != nil { + logger.LogError(ctx, "error settling billing: "+err.Error()) + } + + logModel := relayInfo.OriginModelName + if extraContent != "" { + logContent += ", " + extraContent + } + other := GenerateAudioOtherInfo(ctx, relayInfo, usage, modelRatio, groupRatio, + completionRatio.InexactFloat64(), audioRatio.InexactFloat64(), audioCompletionRatio.InexactFloat64(), modelPrice, relayInfo.PriceData.GroupRatioInfo.GroupSpecialRatio) + if tieredResult != nil { + InjectTieredBillingInfo(other, relayInfo, tieredResult) + } + model.RecordConsumeLog(ctx, relayInfo.UserId, model.RecordConsumeLogParams{ + ChannelId: relayInfo.ChannelId, + PromptTokens: usage.PromptTokens, + CompletionTokens: usage.CompletionTokens, + ModelName: logModel, + TokenName: tokenName, + Quota: quota, + Content: logContent, + TokenId: relayInfo.TokenId, + UseTimeSeconds: int(useTimeSeconds), + IsStream: relayInfo.IsStream, + Group: relayInfo.UsingGroup, + Other: other, + }) +} + +func PreConsumeTokenQuota(relayInfo *relaycommon.RelayInfo, quota int) error { + if quota < 0 { + return errors.New("quota 不能为负数!") + } + if relayInfo.IsPlayground { + return nil + } + //if relayInfo.TokenUnlimited { + // return nil + //} + token, err := model.GetTokenByKey(relayInfo.TokenKey, false) + if err != nil { + return err + } + if !relayInfo.TokenUnlimited && token.RemainQuota < quota { + return fmt.Errorf("token quota is not enough, token remain quota: %s, need quota: %s", logger.FormatQuota(token.RemainQuota), logger.FormatQuota(quota)) + } + err = model.DecreaseTokenQuota(relayInfo.TokenId, relayInfo.TokenKey, quota) + if err != nil { + return err + } + return nil +} + +func PostConsumeQuota(relayInfo *relaycommon.RelayInfo, quota int, preConsumedQuota int, sendEmail bool) (err error) { + + // 1) Consume from wallet quota OR subscription item + if relayInfo != nil && relayInfo.BillingSource == BillingSourceSubscription { + if relayInfo.SubscriptionId == 0 { + return errors.New("subscription id is missing") + } + delta := int64(quota) + if delta != 0 { + if err := model.PostConsumeUserSubscriptionDelta(relayInfo.SubscriptionId, delta); err != nil { + return err + } + relayInfo.SubscriptionPostDelta += delta + } + } else { + // Wallet + if quota > 0 { + err = model.DecreaseUserQuota(relayInfo.UserId, quota, false) + } else { + err = model.IncreaseUserQuota(relayInfo.UserId, -quota, false) + } + if err != nil { + return err + } + } + + if !relayInfo.IsPlayground { + if quota > 0 { + err = model.DecreaseTokenQuota(relayInfo.TokenId, relayInfo.TokenKey, quota) + } else { + err = model.IncreaseTokenQuota(relayInfo.TokenId, relayInfo.TokenKey, -quota) + } + if err != nil { + return err + } + } + + if sendEmail { + if (quota + preConsumedQuota) != 0 { + checkAndSendQuotaNotify(relayInfo, quota, preConsumedQuota) + } + } + + return nil +} + +func checkAndSendQuotaNotify(relayInfo *relaycommon.RelayInfo, quota int, preConsumedQuota int) { + gopool.Go(func() { + userSetting := relayInfo.UserSetting + threshold := common.QuotaRemindThreshold + if userSetting.QuotaWarningThreshold != 0 { + threshold = int(userSetting.QuotaWarningThreshold) + } + + //noMoreQuota := userCache.Quota-(quota+preConsumedQuota) <= 0 + quotaTooLow := false + consumeQuota := quota + preConsumedQuota + if relayInfo.UserQuota-consumeQuota < threshold { + quotaTooLow = true + } + if quotaTooLow { + prompt := "您的额度即将用尽" + topUpLink := fmt.Sprintf("%s/console/topup", system_setting.ServerAddress) + + // 根据通知方式生成不同的内容格式 + var content string + var values []interface{} + + notifyType := userSetting.NotifyType + if notifyType == "" { + notifyType = dto.NotifyTypeEmail + } + + if notifyType == dto.NotifyTypeBark { + // Bark推送使用简短文本,不支持HTML + content = "{{value}},剩余额度:{{value}},请及时充值" + values = []interface{}{prompt, logger.FormatQuota(relayInfo.UserQuota)} + } else if notifyType == dto.NotifyTypeGotify { + content = "{{value}},当前剩余额度为 {{value}},请及时充值。" + values = []interface{}{prompt, logger.FormatQuota(relayInfo.UserQuota)} + } else { + // 默认内容格式,适用于Email和Webhook(支持HTML) + content = "{{value}},当前剩余额度为 {{value}},为了不影响您的使用,请及时充值。
    充值链接:
    {{value}}" + values = []interface{}{prompt, logger.FormatQuota(relayInfo.UserQuota), topUpLink, topUpLink} + } + + err := NotifyUser(relayInfo.UserId, relayInfo.UserEmail, relayInfo.UserSetting, dto.NewNotify(dto.NotifyTypeQuotaExceed, prompt, content, values)) + if err != nil { + common.SysError(fmt.Sprintf("failed to send quota notify to user %d: %s", relayInfo.UserId, err.Error())) + } + } + }) +} + +func checkAndSendSubscriptionQuotaNotify(relayInfo *relaycommon.RelayInfo) { + gopool.Go(func() { + if relayInfo == nil { + return + } + if relayInfo.SubscriptionId == 0 || relayInfo.SubscriptionAmountTotal <= 0 { + return + } + + userSetting := relayInfo.UserSetting + threshold := common.QuotaRemindThreshold + if userSetting.QuotaWarningThreshold != 0 { + threshold = int(userSetting.QuotaWarningThreshold) + } + + usedAfter := relayInfo.SubscriptionAmountUsedAfterPreConsume + relayInfo.SubscriptionPostDelta + remaining := relayInfo.SubscriptionAmountTotal - usedAfter + if remaining >= int64(threshold) { + return + } + + prompt := "您的订阅额度即将用尽" + topUpLink := fmt.Sprintf("%s/console/topup", system_setting.ServerAddress) + + var content string + var values []interface{} + notifyType := userSetting.NotifyType + if notifyType == "" { + notifyType = dto.NotifyTypeEmail + } + + if notifyType == dto.NotifyTypeBark { + content = "{{value}},剩余额度:{{value}},请及时充值" + values = []interface{}{prompt, logger.FormatQuota(int(remaining))} + } else if notifyType == dto.NotifyTypeGotify { + content = "{{value}},当前剩余额度为 {{value}},请及时充值。" + values = []interface{}{prompt, logger.FormatQuota(int(remaining))} + } else { + content = "{{value}},当前剩余额度为 {{value}},为了不影响您的使用,请及时充值。
    充值链接:{{value}}" + values = []interface{}{prompt, logger.FormatQuota(int(remaining)), topUpLink, topUpLink} + } + + if err := NotifyUser(relayInfo.UserId, relayInfo.UserEmail, relayInfo.UserSetting, dto.NewNotify(dto.NotifyTypeQuotaExceed, prompt, content, values)); err != nil { + common.SysError(fmt.Sprintf("failed to send subscription quota notify to user %d: %s", relayInfo.UserId, err.Error())) + } + }) +} diff --git a/_all-in-one-upload/new-api/service/text_quota_test.go b/_all-in-one-upload/new-api/service/text_quota_test.go new file mode 100644 index 0000000..37ce187 --- /dev/null +++ b/_all-in-one-upload/new-api/service/text_quota_test.go @@ -0,0 +1,441 @@ +package service + +import ( + "net/http/httptest" + "testing" + "time" + + "github.com/QuantumNous/new-api/constant" + "github.com/QuantumNous/new-api/dto" + "github.com/QuantumNous/new-api/pkg/billingexpr" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/types" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/require" +) + +func TestCalculateTextQuotaSummaryUnifiedForClaudeSemantic(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + usage := &dto.Usage{ + PromptTokens: 1000, + CompletionTokens: 200, + PromptTokensDetails: dto.InputTokenDetails{ + CachedTokens: 100, + CachedCreationTokens: 50, + }, + ClaudeCacheCreation5mTokens: 10, + ClaudeCacheCreation1hTokens: 20, + } + + priceData := types.PriceData{ + ModelRatio: 1, + CompletionRatio: 2, + CacheRatio: 0.1, + CacheCreationRatio: 1.25, + CacheCreation5mRatio: 1.25, + CacheCreation1hRatio: 2, + GroupRatioInfo: types.GroupRatioInfo{ + GroupRatio: 1, + }, + } + + chatRelayInfo := &relaycommon.RelayInfo{ + RelayFormat: types.RelayFormatOpenAI, + FinalRequestRelayFormat: types.RelayFormatClaude, + OriginModelName: "claude-3-7-sonnet", + PriceData: priceData, + StartTime: time.Now(), + } + messageRelayInfo := &relaycommon.RelayInfo{ + RelayFormat: types.RelayFormatClaude, + FinalRequestRelayFormat: types.RelayFormatClaude, + OriginModelName: "claude-3-7-sonnet", + PriceData: priceData, + StartTime: time.Now(), + } + + chatSummary := calculateTextQuotaSummary(ctx, chatRelayInfo, usage) + messageSummary := calculateTextQuotaSummary(ctx, messageRelayInfo, usage) + + require.Equal(t, messageSummary.Quota, chatSummary.Quota) + require.Equal(t, messageSummary.CacheCreationTokens5m, chatSummary.CacheCreationTokens5m) + require.Equal(t, messageSummary.CacheCreationTokens1h, chatSummary.CacheCreationTokens1h) + require.True(t, chatSummary.IsClaudeUsageSemantic) + require.Equal(t, 1488, chatSummary.Quota) +} + +func TestCalculateTextQuotaSummaryUsesSplitClaudeCacheCreationRatios(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + RelayFormat: types.RelayFormatOpenAI, + FinalRequestRelayFormat: types.RelayFormatClaude, + OriginModelName: "claude-3-7-sonnet", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + CacheRatio: 0, + CacheCreationRatio: 1, + CacheCreation5mRatio: 2, + CacheCreation1hRatio: 3, + GroupRatioInfo: types.GroupRatioInfo{ + GroupRatio: 1, + }, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 100, + CompletionTokens: 0, + PromptTokensDetails: dto.InputTokenDetails{ + CachedCreationTokens: 10, + }, + ClaudeCacheCreation5mTokens: 2, + ClaudeCacheCreation1hTokens: 3, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // 100 + remaining(5)*1 + 2*2 + 3*3 = 118 + require.Equal(t, 118, summary.Quota) +} + +func TestCalculateTextQuotaSummaryUsesAnthropicUsageSemanticFromUpstreamUsage(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + RelayFormat: types.RelayFormatOpenAI, + OriginModelName: "claude-3-7-sonnet", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 2, + CacheRatio: 0.1, + CacheCreationRatio: 1.25, + CacheCreation5mRatio: 1.25, + CacheCreation1hRatio: 2, + GroupRatioInfo: types.GroupRatioInfo{ + GroupRatio: 1, + }, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 1000, + CompletionTokens: 200, + UsageSemantic: "anthropic", + PromptTokensDetails: dto.InputTokenDetails{ + CachedTokens: 100, + CachedCreationTokens: 50, + }, + ClaudeCacheCreation5mTokens: 10, + ClaudeCacheCreation1hTokens: 20, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + require.True(t, summary.IsClaudeUsageSemantic) + require.Equal(t, "anthropic", summary.UsageSemantic) + require.Equal(t, 1488, summary.Quota) +} + +func TestCacheWriteTokensTotal(t *testing.T) { + t.Run("split cache creation", func(t *testing.T) { + summary := textQuotaSummary{ + CacheCreationTokens: 50, + CacheCreationTokens5m: 10, + CacheCreationTokens1h: 20, + } + require.Equal(t, 50, cacheWriteTokensTotal(summary)) + }) + + t.Run("legacy cache creation", func(t *testing.T) { + summary := textQuotaSummary{CacheCreationTokens: 50} + require.Equal(t, 50, cacheWriteTokensTotal(summary)) + }) + + t.Run("split cache creation without aggregate remainder", func(t *testing.T) { + summary := textQuotaSummary{ + CacheCreationTokens5m: 10, + CacheCreationTokens1h: 20, + } + require.Equal(t, 30, cacheWriteTokensTotal(summary)) + }) +} + +func TestCalculateTextQuotaSummaryHandlesLegacyClaudeDerivedOpenAIUsage(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + RelayFormat: types.RelayFormatOpenAI, + OriginModelName: "claude-3-7-sonnet", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 5, + CacheRatio: 0.1, + CacheCreationRatio: 1.25, + CacheCreation5mRatio: 1.25, + CacheCreation1hRatio: 2, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 62, + CompletionTokens: 95, + PromptTokensDetails: dto.InputTokenDetails{ + CachedTokens: 3544, + }, + ClaudeCacheCreation5mTokens: 586, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // 62 + 3544*0.1 + 586*1.25 + 95*5 = 1624.9 => 1624 + require.Equal(t, 1624, summary.Quota) +} + +func TestCalculateTextQuotaSummarySeparatesOpenRouterCacheReadFromPromptBilling(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + OriginModelName: "openai/gpt-4.1", + ChannelMeta: &relaycommon.ChannelMeta{ + ChannelType: constant.ChannelTypeOpenRouter, + }, + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + CacheRatio: 0.1, + CacheCreationRatio: 1.25, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 2604, + CompletionTokens: 383, + PromptTokensDetails: dto.InputTokenDetails{ + CachedTokens: 2432, + }, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // OpenRouter OpenAI-format display keeps prompt_tokens as total input, + // but billing still separates normal input from cache read tokens. + // quota = (2604 - 2432) + 2432*0.1 + 383 = 798.2 => 798 + require.Equal(t, 2604, summary.PromptTokens) + require.Equal(t, 798, summary.Quota) +} + +func TestCalculateTextQuotaSummarySeparatesOpenRouterCacheCreationFromPromptBilling(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + OriginModelName: "openai/gpt-4.1", + ChannelMeta: &relaycommon.ChannelMeta{ + ChannelType: constant.ChannelTypeOpenRouter, + }, + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + CacheCreationRatio: 1.25, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 2604, + CompletionTokens: 383, + PromptTokensDetails: dto.InputTokenDetails{ + CachedCreationTokens: 100, + }, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // prompt_tokens is still logged as total input, but cache creation is billed separately. + // quota = (2604 - 100) + 100*1.25 + 383 = 3012 + require.Equal(t, 2604, summary.PromptTokens) + require.Equal(t, 3012, summary.Quota) +} + +func TestCalculateTextQuotaSummaryKeepsPrePRClaudeOpenRouterBilling(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + + relayInfo := &relaycommon.RelayInfo{ + FinalRequestRelayFormat: types.RelayFormatClaude, + OriginModelName: "anthropic/claude-3.7-sonnet", + ChannelMeta: &relaycommon.ChannelMeta{ + ChannelType: constant.ChannelTypeOpenRouter, + }, + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + CacheRatio: 0.1, + CacheCreationRatio: 1.25, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 2604, + CompletionTokens: 383, + PromptTokensDetails: dto.InputTokenDetails{ + CachedTokens: 2432, + }, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // Pre-PR PostClaudeConsumeQuota behavior for OpenRouter: + // prompt = 2604 - 2432 = 172 + // quota = 172 + 2432*0.1 + 383 = 798.2 => 798 + require.True(t, summary.IsClaudeUsageSemantic) + require.Equal(t, 172, summary.PromptTokens) + require.Equal(t, 798, summary.Quota) +} + +func TestComposeTieredTextQuotaKeepsToolCallSurcharges(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + ctx.Set("image_generation_call", true) + ctx.Set("image_generation_call_quality", "low") + ctx.Set("image_generation_call_size", "1024x1024") + + relayInfo := &relaycommon.RelayInfo{ + OriginModelName: "o1", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, + }, + ResponsesUsageInfo: &relaycommon.ResponsesUsageInfo{ + BuiltInTools: map[string]*relaycommon.BuildInToolInfo{ + dto.BuildInToolWebSearchPreview: &relaycommon.BuildInToolInfo{ + CallCount: 1, + }, + dto.BuildInToolFileSearch: &relaycommon.BuildInToolInfo{ + CallCount: 2, + }, + }, + }, + TieredBillingSnapshot: &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + GroupRatio: 1, + EstimatedQuotaBeforeGroup: 1000, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 100, + CompletionTokens: 50, + TotalTokens: 150, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + quota := composeTieredTextQuota(relayInfo, summary, 1000, &billingexpr.TieredResult{ + ActualQuotaBeforeGroup: 1000, + ActualQuotaAfterGroup: 1000, + }) + + require.Equal(t, int64(13000), summary.ToolCallSurchargeQuota.Round(0).IntPart()) + require.Equal(t, 14000, quota) +} + +func TestComposeTieredTextQuotaFallbackKeepsToolCallSurcharges(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + ctx.Set("claude_web_search_requests", 2) + + relayInfo := &relaycommon.RelayInfo{ + OriginModelName: "claude-3-7-sonnet", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1.25}, + }, + TieredBillingSnapshot: &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + GroupRatio: 1.25, + EstimatedQuotaBeforeGroup: 1000, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 100, + CompletionTokens: 50, + TotalTokens: 150, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + quota := composeTieredTextQuota(relayInfo, summary, 1250, nil) + + require.Equal(t, int64(12500), summary.ToolCallSurchargeQuota.Round(0).IntPart()) + require.Equal(t, 13750, quota) +} + +func TestComposeTieredTextQuotaErrorFallbackUsesPreConsumedQuota(t *testing.T) { + gin.SetMode(gin.TestMode) + w := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(w) + ctx.Set("claude_web_search_requests", 2) + + relayInfo := &relaycommon.RelayInfo{ + OriginModelName: "claude-3-7-sonnet", + PriceData: types.PriceData{ + ModelRatio: 1, + CompletionRatio: 1, + GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1.25}, + }, + TieredBillingSnapshot: &billingexpr.BillingSnapshot{ + BillingMode: "tiered_expr", + GroupRatio: 1.25, + EstimatedQuotaBeforeGroup: 1000, + }, + StartTime: time.Now(), + } + + usage := &dto.Usage{ + PromptTokens: 100, + CompletionTokens: 50, + TotalTokens: 150, + } + + summary := calculateTextQuotaSummary(ctx, relayInfo, usage) + + // tieredResult=nil simulates a settlement error where TryTieredSettle + // falls back to FinalPreConsumedQuota (2000), which differs from + // EstimatedQuotaBeforeGroup * GroupRatio (1250). + preConsumedFallback := 2000 + quota := composeTieredTextQuota(relayInfo, summary, preConsumedFallback, nil) + + require.Equal(t, int64(12500), summary.ToolCallSurchargeQuota.Round(0).IntPart()) + require.Equal(t, 14500, quota) +} diff --git a/_all-in-one-upload/new-api/service/violation_fee.go b/_all-in-one-upload/new-api/service/violation_fee.go new file mode 100644 index 0000000..4550885 --- /dev/null +++ b/_all-in-one-upload/new-api/service/violation_fee.go @@ -0,0 +1,164 @@ +package service + +import ( + "fmt" + "strings" + "time" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/logger" + "github.com/QuantumNous/new-api/model" + relaycommon "github.com/QuantumNous/new-api/relay/common" + "github.com/QuantumNous/new-api/setting/model_setting" + "github.com/QuantumNous/new-api/types" + + "github.com/shopspring/decimal" + + "github.com/gin-gonic/gin" +) + +const ( + ViolationFeeCodePrefix = "violation_fee." + CSAMViolationMarker = "Failed check: SAFETY_CHECK_TYPE" + ContentViolatesUsageMarker = "Content violates usage guidelines" +) + +func IsViolationFeeCode(code types.ErrorCode) bool { + return strings.HasPrefix(string(code), ViolationFeeCodePrefix) +} + +func HasCSAMViolationMarker(err *types.NewAPIError) bool { + if err == nil { + return false + } + if strings.Contains(err.Error(), CSAMViolationMarker) || strings.Contains(err.Error(), ContentViolatesUsageMarker) { + return true + } + msg := err.ToOpenAIError().Message + return strings.Contains(msg, CSAMViolationMarker) || strings.Contains(err.Error(), ContentViolatesUsageMarker) +} + +func WrapAsViolationFeeGrokCSAM(err *types.NewAPIError) *types.NewAPIError { + if err == nil { + return nil + } + oai := err.ToOpenAIError() + oai.Type = string(types.ErrorCodeViolationFeeGrokCSAM) + oai.Code = string(types.ErrorCodeViolationFeeGrokCSAM) + return types.WithOpenAIError(oai, err.StatusCode, types.ErrOptionWithSkipRetry()) +} + +// NormalizeViolationFeeError ensures: +// - if the CSAM marker is present, error.code is set to a stable violation-fee code and skip-retry is enabled. +// - if error.code already has the violation-fee prefix, skip-retry is enabled. +// +// It must be called before retry decision logic. +func NormalizeViolationFeeError(err *types.NewAPIError) *types.NewAPIError { + if err == nil { + return nil + } + + if HasCSAMViolationMarker(err) { + return WrapAsViolationFeeGrokCSAM(err) + } + + if IsViolationFeeCode(err.GetErrorCode()) { + oai := err.ToOpenAIError() + return types.WithOpenAIError(oai, err.StatusCode, types.ErrOptionWithSkipRetry()) + } + + return err +} + +func shouldChargeViolationFee(err *types.NewAPIError) bool { + if err == nil { + return false + } + if err.GetErrorCode() == types.ErrorCodeViolationFeeGrokCSAM { + return true + } + // In case some callers didn't normalize, keep a safety net. + return HasCSAMViolationMarker(err) +} + +func calcViolationFeeQuota(amount, groupRatio float64) int { + if amount <= 0 { + return 0 + } + if groupRatio <= 0 { + return 0 + } + quota := decimal.NewFromFloat(amount). + Mul(decimal.NewFromFloat(common.QuotaPerUnit)). + Mul(decimal.NewFromFloat(groupRatio)). + Round(0). + IntPart() + if quota <= 0 { + return 0 + } + return int(quota) +} + +// ChargeViolationFeeIfNeeded charges an additional fee after the normal flow finishes (including refund). +// It uses Grok fee settings as the fee policy. +func ChargeViolationFeeIfNeeded(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, apiErr *types.NewAPIError) bool { + if ctx == nil || relayInfo == nil || apiErr == nil { + return false + } + //if relayInfo.IsPlayground { + // return false + //} + if !shouldChargeViolationFee(apiErr) { + return false + } + + settings := model_setting.GetGrokSettings() + if settings == nil || !settings.ViolationDeductionEnabled { + return false + } + + groupRatio := relayInfo.PriceData.GroupRatioInfo.GroupRatio + feeQuota := calcViolationFeeQuota(settings.ViolationDeductionAmount, groupRatio) + if feeQuota <= 0 { + return false + } + + if err := PostConsumeQuota(relayInfo, feeQuota, 0, true); err != nil { + logger.LogError(ctx, fmt.Sprintf("failed to charge violation fee: %s", err.Error())) + return false + } + + model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, feeQuota) + model.UpdateChannelUsedQuota(relayInfo.ChannelId, feeQuota) + + useTimeSeconds := time.Now().Unix() - relayInfo.StartTime.Unix() + tokenName := ctx.GetString("token_name") + oai := apiErr.ToOpenAIError() + + other := map[string]any{ + "violation_fee": true, + "violation_fee_code": string(types.ErrorCodeViolationFeeGrokCSAM), + "fee_quota": feeQuota, + "base_amount": settings.ViolationDeductionAmount, + "group_ratio": groupRatio, + "status_code": apiErr.StatusCode, + "upstream_error_type": oai.Type, + "upstream_error_code": fmt.Sprintf("%v", oai.Code), + "violation_fee_marker": CSAMViolationMarker, + } + + model.RecordConsumeLog(ctx, relayInfo.UserId, model.RecordConsumeLogParams{ + ChannelId: relayInfo.ChannelId, + ModelName: relayInfo.OriginModelName, + TokenName: tokenName, + Quota: feeQuota, + Content: "Violation fee charged", + TokenId: relayInfo.TokenId, + UseTimeSeconds: int(useTimeSeconds), + IsStream: relayInfo.IsStream, + Group: relayInfo.UsingGroup, + Other: other, + }) + + return true +} diff --git a/_all-in-one-upload/new-api/setting/model_setting/claude_test.go b/_all-in-one-upload/new-api/setting/model_setting/claude_test.go new file mode 100644 index 0000000..0a806a7 --- /dev/null +++ b/_all-in-one-upload/new-api/setting/model_setting/claude_test.go @@ -0,0 +1,60 @@ +package model_setting + +import ( + "net/http" + "testing" +) + +func TestClaudeSettingsWriteHeadersMergesConfiguredValuesIntoSingleHeader(t *testing.T) { + settings := &ClaudeSettings{ + HeadersSettings: map[string]map[string][]string{ + "claude-3-7-sonnet-20250219-thinking": { + "anthropic-beta": { + "token-efficient-tools-2025-02-19", + }, + }, + }, + } + + headers := http.Header{} + headers.Set("anthropic-beta", "output-128k-2025-02-19") + + settings.WriteHeaders("claude-3-7-sonnet-20250219-thinking", &headers) + + got := headers.Values("anthropic-beta") + if len(got) != 1 { + t.Fatalf("expected a single merged header value, got %v", got) + } + expected := "output-128k-2025-02-19,token-efficient-tools-2025-02-19" + if got[0] != expected { + t.Fatalf("expected merged header %q, got %q", expected, got[0]) + } +} + +func TestClaudeSettingsWriteHeadersDeduplicatesAcrossCommaSeparatedAndRepeatedValues(t *testing.T) { + settings := &ClaudeSettings{ + HeadersSettings: map[string]map[string][]string{ + "claude-3-7-sonnet-20250219-thinking": { + "anthropic-beta": { + "token-efficient-tools-2025-02-19", + "computer-use-2025-01-24", + }, + }, + }, + } + + headers := http.Header{} + headers.Add("anthropic-beta", "output-128k-2025-02-19, token-efficient-tools-2025-02-19") + headers.Add("anthropic-beta", "token-efficient-tools-2025-02-19") + + settings.WriteHeaders("claude-3-7-sonnet-20250219-thinking", &headers) + + got := headers.Values("anthropic-beta") + if len(got) != 1 { + t.Fatalf("expected duplicate values to collapse into one header, got %v", got) + } + expected := "output-128k-2025-02-19,token-efficient-tools-2025-02-19,computer-use-2025-01-24" + if got[0] != expected { + t.Fatalf("expected deduplicated merged header %q, got %q", expected, got[0]) + } +} diff --git a/_all-in-one-upload/new-api/setting/operation_setting/channel_affinity_setting.go b/_all-in-one-upload/new-api/setting/operation_setting/channel_affinity_setting.go new file mode 100644 index 0000000..8cd605c --- /dev/null +++ b/_all-in-one-upload/new-api/setting/operation_setting/channel_affinity_setting.go @@ -0,0 +1,121 @@ +package operation_setting + +import "github.com/QuantumNous/new-api/setting/config" + +type ChannelAffinityKeySource struct { + Type string `json:"type"` // context_int, context_string, gjson + Key string `json:"key,omitempty"` + Path string `json:"path,omitempty"` +} + +type ChannelAffinityRule struct { + Name string `json:"name"` + ModelRegex []string `json:"model_regex"` + PathRegex []string `json:"path_regex"` + UserAgentInclude []string `json:"user_agent_include,omitempty"` + KeySources []ChannelAffinityKeySource `json:"key_sources"` + + ValueRegex string `json:"value_regex"` + TTLSeconds int `json:"ttl_seconds"` + + ParamOverrideTemplate map[string]interface{} `json:"param_override_template,omitempty"` + + SkipRetryOnFailure bool `json:"skip_retry_on_failure"` + + IncludeUsingGroup bool `json:"include_using_group"` + IncludeModelName bool `json:"include_model_name"` + IncludeRuleName bool `json:"include_rule_name"` +} + +type ChannelAffinitySetting struct { + Enabled bool `json:"enabled"` + SwitchOnSuccess bool `json:"switch_on_success"` + MaxEntries int `json:"max_entries"` + DefaultTTLSeconds int `json:"default_ttl_seconds"` + Rules []ChannelAffinityRule `json:"rules"` +} + +var codexCliPassThroughHeaders = []string{ + "Originator", + "Session_id", + "User-Agent", + "X-Codex-Beta-Features", + "X-Codex-Turn-Metadata", +} + +var claudeCliPassThroughHeaders = []string{ + "X-Stainless-Arch", + "X-Stainless-Lang", + "X-Stainless-Os", + "X-Stainless-Package-Version", + "X-Stainless-Retry-Count", + "X-Stainless-Runtime", + "X-Stainless-Runtime-Version", + "X-Stainless-Timeout", + "User-Agent", + "X-App", + "Anthropic-Beta", + "Anthropic-Dangerous-Direct-Browser-Access", + "Anthropic-Version", +} + +func buildPassHeaderTemplate(headers []string) map[string]interface{} { + clonedHeaders := make([]string, 0, len(headers)) + clonedHeaders = append(clonedHeaders, headers...) + return map[string]interface{}{ + "operations": []map[string]interface{}{ + { + "mode": "pass_headers", + "value": clonedHeaders, + "keep_origin": true, + }, + }, + } +} + +var channelAffinitySetting = ChannelAffinitySetting{ + Enabled: true, + SwitchOnSuccess: true, + MaxEntries: 100_000, + DefaultTTLSeconds: 3600, + Rules: []ChannelAffinityRule{ + { + Name: "codex cli trace", + ModelRegex: []string{"^gpt-.*$"}, + PathRegex: []string{"/v1/responses"}, + KeySources: []ChannelAffinityKeySource{ + {Type: "gjson", Path: "prompt_cache_key"}, + }, + ValueRegex: "", + TTLSeconds: 0, + ParamOverrideTemplate: buildPassHeaderTemplate(codexCliPassThroughHeaders), + SkipRetryOnFailure: true, + IncludeUsingGroup: true, + IncludeRuleName: true, + UserAgentInclude: nil, + }, + { + Name: "claude cli trace", + ModelRegex: []string{"^claude-.*$"}, + PathRegex: []string{"/v1/messages"}, + KeySources: []ChannelAffinityKeySource{ + {Type: "gjson", Path: "metadata.user_id"}, + }, + ValueRegex: "", + TTLSeconds: 0, + ParamOverrideTemplate: buildPassHeaderTemplate(claudeCliPassThroughHeaders), + SkipRetryOnFailure: true, + IncludeUsingGroup: true, + IncludeRuleName: true, + UserAgentInclude: nil, + }, + }, +} + +func init() { + config.GlobalConfig.Register("channel_affinity_setting", &channelAffinitySetting) +} + +func GetChannelAffinitySetting() *ChannelAffinitySetting { + return &channelAffinitySetting +} diff --git a/_all-in-one-upload/new-api/setting/payment_stripe.go b/_all-in-one-upload/new-api/setting/payment_stripe.go new file mode 100644 index 0000000..d97120c --- /dev/null +++ b/_all-in-one-upload/new-api/setting/payment_stripe.go @@ -0,0 +1,8 @@ +package setting + +var StripeApiSecret = "" +var StripeWebhookSecret = "" +var StripePriceId = "" +var StripeUnitPrice = 8.0 +var StripeMinTopUp = 1 +var StripePromotionCodesEnabled = false diff --git a/_all-in-one-upload/new-api/types/price_data.go b/_all-in-one-upload/new-api/types/price_data.go new file mode 100644 index 0000000..93bc6ae --- /dev/null +++ b/_all-in-one-upload/new-api/types/price_data.go @@ -0,0 +1,42 @@ +package types + +import "fmt" + +type GroupRatioInfo struct { + GroupRatio float64 + GroupSpecialRatio float64 + HasSpecialRatio bool +} + +type PriceData struct { + FreeModel bool + ModelPrice float64 + ModelRatio float64 + CompletionRatio float64 + CacheRatio float64 + CacheCreationRatio float64 + CacheCreation5mRatio float64 + CacheCreation1hRatio float64 + ImageRatio float64 + AudioRatio float64 + AudioCompletionRatio float64 + OtherRatios map[string]float64 + UsePrice bool + Quota int // 按次计费的最终额度(MJ / Task) + QuotaToPreConsume int // 按量计费的预消耗额度 + GroupRatioInfo GroupRatioInfo +} + +func (p *PriceData) AddOtherRatio(key string, ratio float64) { + if p.OtherRatios == nil { + p.OtherRatios = make(map[string]float64) + } + if ratio <= 0 { + return + } + p.OtherRatios[key] = ratio +} + +func (p *PriceData) ToSetting() string { + return fmt.Sprintf("ModelPrice: %f, ModelRatio: %f, CompletionRatio: %f, CacheRatio: %f, GroupRatio: %f, UsePrice: %t, CacheCreationRatio: %f, CacheCreation5mRatio: %f, CacheCreation1hRatio: %f, QuotaToPreConsume: %d, ImageRatio: %f, AudioRatio: %f, AudioCompletionRatio: %f", p.ModelPrice, p.ModelRatio, p.CompletionRatio, p.CacheRatio, p.GroupRatioInfo.GroupRatio, p.UsePrice, p.CacheCreationRatio, p.CacheCreation5mRatio, p.CacheCreation1hRatio, p.QuotaToPreConsume, p.ImageRatio, p.AudioRatio, p.AudioCompletionRatio) +} diff --git a/_all-in-one-upload/new-api/web/classic/package.json b/_all-in-one-upload/new-api/web/classic/package.json new file mode 100644 index 0000000..83b5d23 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/package.json @@ -0,0 +1,96 @@ +{ + "name": "react-template", + "version": "0.1.0", + "private": true, + "type": "module", + "dependencies": { + "@douyinfe/semi-icons": "^2.63.1", + "@douyinfe/semi-ui": "^2.69.1", + "@lobehub/icons": "^2.0.0", + "@visactor/react-vchart": "~1.8.8", + "@visactor/vchart": "~1.8.8", + "@visactor/vchart-semi-theme": "~1.8.8", + "axios": "1.15.0", + "clsx": "^2.1.1", + "dayjs": "^1.11.11", + "history": "^5.3.0", + "i18next": "^23.16.8", + "i18next-browser-languagedetector": "^7.2.0", + "katex": "^0.16.22", + "lucide-react": "^0.511.0", + "marked": "^4.1.1", + "mermaid": "^11.6.0", + "qrcode.react": "^4.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", + "react-fireworks": "^1.0.4", + "react-i18next": "^13.0.0", + "react-icons": "^5.5.0", + "react-markdown": "^10.1.0", + "react-router-dom": "^6.3.0", + "react-telegram-login": "^1.1.2", + "react-toastify": "^9.0.8", + "react-turnstile": "^1.0.5", + "rehype-highlight": "^7.0.2", + "rehype-katex": "^7.0.1", + "remark-breaks": "^4.0.0", + "remark-gfm": "^4.0.1", + "remark-math": "^6.0.0", + "sse.js": "^2.6.0", + "unist-util-visit": "^5.0.0", + "use-debounce": "^10.0.4" + }, + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "prettier . --check", + "lint:fix": "prettier . --write", + "eslint": "bunx eslint \"**/*.{js,jsx}\" --cache", + "eslint:fix": "bunx eslint \"**/*.{js,jsx}\" --fix --cache", + "preview": "vite preview", + "i18n:extract": "bunx i18next-cli extract", + "i18n:status": "bunx i18next-cli status", + "i18n:sync": "bunx i18next-cli sync", + "i18n:lint": "bunx i18next-cli lint" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@douyinfe/vite-plugin-semi": "^2.74.0-alpha.6", + "@so1ve/prettier-config": "^3.1.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.21", + "code-inspector-plugin": "^1.3.3", + "eslint": "8.57.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-react-hooks": "^5.2.0", + "i18next-cli": "^1.10.3", + "postcss": "^8.5.3", + "prettier": "^3.0.0", + "tailwindcss": "^3", + "typescript": "4.4.2", + "vite": "^5.2.0" + }, + "prettier": { + "singleQuote": true, + "jsxSingleQuote": true + }, + "proxy": "http://localhost:3000" +} diff --git a/_all-in-one-upload/new-api/web/classic/src/components/common/logo/OIDCIcon.jsx b/_all-in-one-upload/new-api/web/classic/src/components/common/logo/OIDCIcon.jsx new file mode 100644 index 0000000..28d538e --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/common/logo/OIDCIcon.jsx @@ -0,0 +1,57 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React from 'react'; +import { Icon } from '@douyinfe/semi-ui'; + +const OIDCIcon = (props) => { + function CustomIcon() { + return ( + + + + + ); + } + + return } />; +}; + +export default OIDCIcon; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/common/logo/WeChatIcon.jsx b/_all-in-one-upload/new-api/web/classic/src/components/common/logo/WeChatIcon.jsx new file mode 100644 index 0000000..f9f7057 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/common/logo/WeChatIcon.jsx @@ -0,0 +1,55 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React from 'react'; +import { Icon } from '@douyinfe/semi-ui'; + +const WeChatIcon = () => { + function CustomIcon() { + return ( + + + + + ); + } + + return ( +
    + } /> +
    + ); +}; + +export default WeChatIcon; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/layout/NoticeModal.jsx b/_all-in-one-upload/new-api/web/classic/src/components/layout/NoticeModal.jsx new file mode 100644 index 0000000..c8197a5 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/layout/NoticeModal.jsx @@ -0,0 +1,255 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React, { useEffect, useState, useContext, useMemo } from 'react'; +import { + Button, + Modal, + Empty, + Tabs, + TabPane, + Timeline, +} from '@douyinfe/semi-ui'; +import { useTranslation } from 'react-i18next'; +import { API, showError, getRelativeTime } from '../../helpers'; +import { marked } from 'marked'; +import { + IllustrationNoContent, + IllustrationNoContentDark, +} from '@douyinfe/semi-illustrations'; +import { StatusContext } from '../../context/Status'; +import { Bell, Megaphone } from 'lucide-react'; + +const NoticeModal = ({ + visible, + onClose, + isMobile, + defaultTab = 'inApp', + unreadKeys = [], +}) => { + const { t } = useTranslation(); + const [noticeContent, setNoticeContent] = useState(''); + const [loading, setLoading] = useState(false); + const [activeTab, setActiveTab] = useState(defaultTab); + + const [statusState] = useContext(StatusContext); + + const announcements = statusState?.status?.announcements || []; + + const unreadSet = useMemo(() => new Set(unreadKeys), [unreadKeys]); + + const getKeyForItem = (item) => + `${item?.publishDate || ''}-${(item?.content || '').slice(0, 30)}`; + + const processedAnnouncements = useMemo(() => { + return (announcements || []).slice(0, 20).map((item) => { + const pubDate = item?.publishDate ? new Date(item.publishDate) : null; + const absoluteTime = + pubDate && !isNaN(pubDate.getTime()) + ? `${pubDate.getFullYear()}-${String(pubDate.getMonth() + 1).padStart(2, '0')}-${String(pubDate.getDate()).padStart(2, '0')} ${String(pubDate.getHours()).padStart(2, '0')}:${String(pubDate.getMinutes()).padStart(2, '0')}` + : item?.publishDate || ''; + return { + key: getKeyForItem(item), + type: item.type || 'default', + time: absoluteTime, + content: item.content, + extra: item.extra, + relative: getRelativeTime(item.publishDate), + isUnread: unreadSet.has(getKeyForItem(item)), + }; + }); + }, [announcements, unreadSet]); + + const handleCloseTodayNotice = () => { + const today = new Date().toDateString(); + localStorage.setItem('notice_close_date', today); + onClose(); + }; + + const displayNotice = async () => { + setLoading(true); + try { + const res = await API.get('/api/notice'); + const { success, message, data } = res.data; + if (success) { + if (data !== '') { + const htmlNotice = marked.parse(data); + setNoticeContent(htmlNotice); + } else { + setNoticeContent(''); + } + } else { + showError(message); + } + } catch (error) { + showError(error.message); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (visible) { + displayNotice(); + } + }, [visible]); + + useEffect(() => { + if (visible) { + setActiveTab(defaultTab); + } + }, [defaultTab, visible]); + + const renderMarkdownNotice = () => { + if (loading) { + return ( +
    + +
    + ); + } + + if (!noticeContent) { + return ( +
    + + } + darkModeImage={ + + } + description={t('暂无公告')} + /> +
    + ); + } + + return ( +
    + ); + }; + + const renderAnnouncementTimeline = () => { + if (processedAnnouncements.length === 0) { + return ( +
    + + } + darkModeImage={ + + } + description={t('暂无系统公告')} + /> +
    + ); + } + + return ( +
    + + {processedAnnouncements.map((item, idx) => { + const htmlContent = marked.parse(item.content || ''); + const htmlExtra = item.extra ? marked.parse(item.extra) : ''; + return ( + + ) : null + } + className={item.isUnread ? '' : ''} + > +
    +
    +
    + + ); + })} + +
    + ); + }; + + const renderBody = () => { + if (activeTab === 'inApp') { + return renderMarkdownNotice(); + } + return renderAnnouncementTimeline(); + }; + + return ( + + {t('系统公告')} + + + {t('通知')} + + } + itemKey='inApp' + /> + + {t('系统公告')} + + } + itemKey='system' + /> + +
    + } + visible={visible} + onCancel={onClose} + footer={ +
    + + +
    + } + size={isMobile ? 'full-width' : 'large'} + > + {renderBody()} + + ); +}; + +export default NoticeModal; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/playground/configStorage.js b/_all-in-one-upload/new-api/web/classic/src/components/playground/configStorage.js new file mode 100644 index 0000000..d201ed6 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/playground/configStorage.js @@ -0,0 +1,234 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import { + STORAGE_KEYS, + DEFAULT_CONFIG, +} from '../../constants/playground.constants'; + +const MESSAGES_STORAGE_KEY = 'playground_messages'; + +/** + * 保存配置到 localStorage + * @param {Object} config - 要保存的配置对象 + */ +export const saveConfig = (config) => { + try { + const configToSave = { + ...config, + timestamp: new Date().toISOString(), + }; + localStorage.setItem(STORAGE_KEYS.CONFIG, JSON.stringify(configToSave)); + } catch (error) { + console.error('保存配置失败:', error); + } +}; + +/** + * 保存消息到 localStorage + * @param {Array} messages - 要保存的消息数组 + */ +export const saveMessages = (messages) => { + try { + const messagesToSave = { + messages, + timestamp: new Date().toISOString(), + }; + localStorage.setItem(STORAGE_KEYS.MESSAGES, JSON.stringify(messagesToSave)); + } catch (error) { + console.error('保存消息失败:', error); + } +}; + +/** + * 从 localStorage 加载配置 + * @returns {Object} 配置对象,如果不存在则返回默认配置 + */ +export const loadConfig = () => { + try { + const savedConfig = localStorage.getItem(STORAGE_KEYS.CONFIG); + if (savedConfig) { + const parsedConfig = JSON.parse(savedConfig); + const parsedMaxTokens = parseInt(parsedConfig?.inputs?.max_tokens, 10); + + const mergedConfig = { + inputs: { + ...DEFAULT_CONFIG.inputs, + ...parsedConfig.inputs, + max_tokens: Number.isNaN(parsedMaxTokens) + ? parsedConfig?.inputs?.max_tokens + : parsedMaxTokens, + }, + parameterEnabled: { + ...DEFAULT_CONFIG.parameterEnabled, + ...parsedConfig.parameterEnabled, + }, + showDebugPanel: + parsedConfig.showDebugPanel || DEFAULT_CONFIG.showDebugPanel, + customRequestMode: + parsedConfig.customRequestMode || DEFAULT_CONFIG.customRequestMode, + customRequestBody: + parsedConfig.customRequestBody || DEFAULT_CONFIG.customRequestBody, + }; + + return mergedConfig; + } + } catch (error) { + console.error('加载配置失败:', error); + } + + return DEFAULT_CONFIG; +}; + +/** + * 从 localStorage 加载消息 + * @returns {Array} 消息数组,如果不存在则返回 null + */ +export const loadMessages = () => { + try { + const savedMessages = localStorage.getItem(STORAGE_KEYS.MESSAGES); + if (savedMessages) { + const parsedMessages = JSON.parse(savedMessages); + return parsedMessages.messages || null; + } + } catch (error) { + console.error('加载消息失败:', error); + } + + return null; +}; + +/** + * 清除保存的配置 + */ +export const clearConfig = () => { + try { + localStorage.removeItem(STORAGE_KEYS.CONFIG); + localStorage.removeItem(STORAGE_KEYS.MESSAGES); // 同时清除消息 + } catch (error) { + console.error('清除配置失败:', error); + } +}; + +/** + * 清除保存的消息 + */ +export const clearMessages = () => { + try { + localStorage.removeItem(STORAGE_KEYS.MESSAGES); + } catch (error) { + console.error('清除消息失败:', error); + } +}; + +/** + * 检查是否有保存的配置 + * @returns {boolean} 是否存在保存的配置 + */ +export const hasStoredConfig = () => { + try { + return localStorage.getItem(STORAGE_KEYS.CONFIG) !== null; + } catch (error) { + console.error('检查配置失败:', error); + return false; + } +}; + +/** + * 获取配置的最后保存时间 + * @returns {string|null} 最后保存时间的 ISO 字符串 + */ +export const getConfigTimestamp = () => { + try { + const savedConfig = localStorage.getItem(STORAGE_KEYS.CONFIG); + if (savedConfig) { + const parsedConfig = JSON.parse(savedConfig); + return parsedConfig.timestamp || null; + } + } catch (error) { + console.error('获取配置时间戳失败:', error); + } + return null; +}; + +/** + * 导出配置为 JSON 文件(包含消息) + * @param {Object} config - 要导出的配置 + * @param {Array} messages - 要导出的消息 + */ +export const exportConfig = (config, messages = null) => { + try { + const configToExport = { + ...config, + messages: messages || loadMessages(), // 包含消息数据 + exportTime: new Date().toISOString(), + version: '1.0', + }; + + const dataStr = JSON.stringify(configToExport, null, 2); + const dataBlob = new Blob([dataStr], { type: 'application/json' }); + + const link = document.createElement('a'); + link.href = URL.createObjectURL(dataBlob); + link.download = `playground-config-${new Date().toISOString().split('T')[0]}.json`; + link.click(); + + URL.revokeObjectURL(link.href); + } catch (error) { + console.error('导出配置失败:', error); + } +}; + +/** + * 从文件导入配置(包含消息) + * @param {File} file - 包含配置的 JSON 文件 + * @returns {Promise} 导入的配置对象 + */ +export const importConfig = (file) => { + return new Promise((resolve, reject) => { + try { + const reader = new FileReader(); + reader.onload = (e) => { + try { + const importedConfig = JSON.parse(e.target.result); + + if (importedConfig.inputs && importedConfig.parameterEnabled) { + // 如果导入的配置包含消息,也一起导入 + if ( + importedConfig.messages && + Array.isArray(importedConfig.messages) + ) { + saveMessages(importedConfig.messages); + } + + resolve(importedConfig); + } else { + reject(new Error('配置文件格式无效')); + } + } catch (parseError) { + reject(new Error('解析配置文件失败: ' + parseError.message)); + } + }; + reader.onerror = () => reject(new Error('读取文件失败')); + reader.readAsText(file); + } catch (error) { + reject(new Error('导入配置失败: ' + error.message)); + } + }); +}; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/settings/PersonalSetting.jsx b/_all-in-one-upload/new-api/web/classic/src/components/settings/PersonalSetting.jsx new file mode 100644 index 0000000..e735c87 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/settings/PersonalSetting.jsx @@ -0,0 +1,668 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React, { useContext, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + API, + copy, + showError, + showInfo, + showSuccess, + setStatusData, + prepareCredentialCreationOptions, + buildRegistrationResult, + isPasskeySupported, + setUserData, +} from '../../helpers'; +import { UserContext } from '../../context/User'; +import { Modal } from '@douyinfe/semi-ui'; +import { useTranslation } from 'react-i18next'; + +// 导入子组件 +import UserInfoHeader from './personal/components/UserInfoHeader'; +import AccountManagement from './personal/cards/AccountManagement'; +import NotificationSettings from './personal/cards/NotificationSettings'; +import PreferencesSettings from './personal/cards/PreferencesSettings'; +import CheckinCalendar from './personal/cards/CheckinCalendar'; +import EmailBindModal from './personal/modals/EmailBindModal'; +import WeChatBindModal from './personal/modals/WeChatBindModal'; +import AccountDeleteModal from './personal/modals/AccountDeleteModal'; +import ChangePasswordModal from './personal/modals/ChangePasswordModal'; +import SecureVerificationModal from '../common/modals/SecureVerificationModal'; +import { useSecureVerification } from '../../hooks/common/useSecureVerification'; + +const PersonalSetting = () => { + const [userState, userDispatch] = useContext(UserContext); + let navigate = useNavigate(); + const { t } = useTranslation(); + + const [inputs, setInputs] = useState({ + wechat_verification_code: '', + email_verification_code: '', + email: '', + self_account_deletion_confirmation: '', + original_password: '', + set_new_password: '', + set_new_password_confirmation: '', + }); + const [status, setStatus] = useState({}); + const [showChangePasswordModal, setShowChangePasswordModal] = useState(false); + const [showWeChatBindModal, setShowWeChatBindModal] = useState(false); + const [showEmailBindModal, setShowEmailBindModal] = useState(false); + const [showAccountDeleteModal, setShowAccountDeleteModal] = useState(false); + const [turnstileEnabled, setTurnstileEnabled] = useState(false); + const [turnstileSiteKey, setTurnstileSiteKey] = useState(''); + const [turnstileToken, setTurnstileToken] = useState(''); + const [loading, setLoading] = useState(false); + const [disableButton, setDisableButton] = useState(false); + const [countdown, setCountdown] = useState(30); + const [systemToken, setSystemToken] = useState(''); + const [passkeyStatus, setPasskeyStatus] = useState({ enabled: false }); + const [passkeyRegisterLoading, setPasskeyRegisterLoading] = useState(false); + const [passkeyDeleteLoading, setPasskeyDeleteLoading] = useState(false); + const [passkeySupported, setPasskeySupported] = useState(false); + const [ + passkeyRequiredVerificationMethod, + setPasskeyRequiredVerificationMethod, + ] = useState(null); + const [notificationSettings, setNotificationSettings] = useState({ + warningType: 'email', + warningThreshold: 100000, + webhookUrl: '', + webhookSecret: '', + notificationEmail: '', + barkUrl: '', + gotifyUrl: '', + gotifyToken: '', + gotifyPriority: 5, + upstreamModelUpdateNotifyEnabled: false, + acceptUnsetModelRatioModel: false, + recordIpLog: false, + }); + + const { + isModalVisible: isPasskeyVerificationModalVisible, + verificationMethods: passkeyVerificationMethods, + verificationState: passkeyVerificationState, + startVerification: startPasskeyVerification, + executeVerification: executePasskeyVerification, + cancelVerification: cancelPasskeyVerification, + setVerificationCode: setPasskeyVerificationCode, + switchVerificationMethod: switchPasskeyVerificationMethod, + checkVerificationMethods: checkPasskeyVerificationMethods, + } = useSecureVerification({ + onSuccess: () => { + setPasskeyRequiredVerificationMethod(null); + }, + }); + + const visiblePasskeyVerificationMethods = passkeyRequiredVerificationMethod + ? { + ...passkeyVerificationMethods, + has2FA: + passkeyRequiredVerificationMethod === '2fa' && + passkeyVerificationMethods.has2FA, + hasPasskey: + passkeyRequiredVerificationMethod === 'passkey' && + passkeyVerificationMethods.hasPasskey, + } + : passkeyVerificationMethods; + + useEffect(() => { + let saved = localStorage.getItem('status'); + if (saved) { + const parsed = JSON.parse(saved); + setStatus(parsed); + if (parsed.turnstile_check) { + setTurnstileEnabled(true); + setTurnstileSiteKey(parsed.turnstile_site_key); + } else { + setTurnstileEnabled(false); + setTurnstileSiteKey(''); + } + } + // Always refresh status from server to avoid stale flags (e.g., admin just enabled OAuth) + (async () => { + try { + const res = await API.get('/api/status'); + const { success, data } = res.data; + if (success && data) { + setStatus(data); + setStatusData(data); + if (data.turnstile_check) { + setTurnstileEnabled(true); + setTurnstileSiteKey(data.turnstile_site_key); + } else { + setTurnstileEnabled(false); + setTurnstileSiteKey(''); + } + } + } catch (e) { + // ignore and keep local status + } + })(); + + getUserData(); + + isPasskeySupported() + .then(setPasskeySupported) + .catch(() => setPasskeySupported(false)); + }, []); + + useEffect(() => { + let countdownInterval = null; + if (disableButton && countdown > 0) { + countdownInterval = setInterval(() => { + setCountdown(countdown - 1); + }, 1000); + } else if (countdown === 0) { + setDisableButton(false); + setCountdown(30); + } + return () => clearInterval(countdownInterval); // Clean up on unmount + }, [disableButton, countdown]); + + useEffect(() => { + if (userState?.user?.setting) { + const settings = JSON.parse(userState.user.setting); + setNotificationSettings({ + warningType: settings.notify_type || 'email', + warningThreshold: settings.quota_warning_threshold || 500000, + webhookUrl: settings.webhook_url || '', + webhookSecret: settings.webhook_secret || '', + notificationEmail: settings.notification_email || '', + barkUrl: settings.bark_url || '', + gotifyUrl: settings.gotify_url || '', + gotifyToken: settings.gotify_token || '', + gotifyPriority: + settings.gotify_priority !== undefined ? settings.gotify_priority : 5, + upstreamModelUpdateNotifyEnabled: + settings.upstream_model_update_notify_enabled === true, + acceptUnsetModelRatioModel: + settings.accept_unset_model_ratio_model || false, + recordIpLog: settings.record_ip_log || false, + }); + } + }, [userState?.user?.setting]); + + const handleInputChange = (name, value) => { + setInputs((inputs) => ({ ...inputs, [name]: value })); + }; + + const generateAccessToken = async () => { + const res = await API.get('/api/user/token'); + const { success, message, data } = res.data; + if (success) { + setSystemToken(data); + await copy(data); + showSuccess(t('令牌已重置并已复制到剪贴板')); + } else { + showError(message); + } + }; + + const loadPasskeyStatus = async () => { + try { + const res = await API.get('/api/user/passkey'); + const { success, data, message } = res.data; + if (success) { + setPasskeyStatus({ + enabled: data?.enabled || false, + last_used_at: data?.last_used_at || null, + backup_eligible: data?.backup_eligible || false, + backup_state: data?.backup_state || false, + }); + } else { + showError(message); + } + } catch (error) { + // 忽略错误,保留默认状态 + } + }; + + const startPasskeyManagementVerification = async (apiCall, options = {}) => { + const methods = await checkPasskeyVerificationMethods(); + const requiredMethod = methods.has2FA + ? '2fa' + : methods.hasPasskey + ? 'passkey' + : null; + + if (!requiredMethod) { + showError(t('您需要先启用两步验证或 Passkey 才能执行此操作')); + return; + } + + if (requiredMethod === 'passkey' && !methods.passkeySupported) { + showInfo(t('当前设备不支持 Passkey')); + return; + } + + setPasskeyRequiredVerificationMethod(requiredMethod); + await startPasskeyVerification(apiCall, { + preferredMethod: requiredMethod, + title: t('安全验证'), + ...options, + }); + }; + + const startPasskeyRegistration = async () => { + const methods = await checkPasskeyVerificationMethods(); + if (!methods.has2FA) { + try { + await registerPasskey(); + } catch (error) { + showError(error.message || t('Passkey 注册失败,请重试')); + } + return; + } + + setPasskeyRequiredVerificationMethod('2fa'); + await startPasskeyVerification(registerPasskey, { + preferredMethod: '2fa', + title: t('安全验证'), + }); + }; + + const registerPasskey = async () => { + setPasskeyRegisterLoading(true); + try { + const beginRes = await API.post('/api/user/passkey/register/begin'); + const { success, message, data } = beginRes.data; + if (!success) { + throw new Error(message || t('无法发起 Passkey 注册')); + } + + const publicKey = prepareCredentialCreationOptions( + data?.options || data?.publicKey || data, + ); + const credential = await navigator.credentials.create({ publicKey }); + const payload = buildRegistrationResult(credential); + if (!payload) { + throw new Error(t('Passkey 注册失败,请重试')); + } + + const finishRes = await API.post( + '/api/user/passkey/register/finish', + payload, + ); + if (!finishRes.data.success) { + throw new Error( + finishRes.data.message || t('Passkey 注册失败,请重试'), + ); + } + + showSuccess(t('Passkey 注册成功')); + await loadPasskeyStatus(); + return finishRes.data; + } catch (error) { + if (error?.name === 'AbortError') { + showInfo(t('已取消 Passkey 注册')); + return { cancelled: true }; + } + throw new Error(error?.message || t('Passkey 注册失败,请重试')); + } finally { + setPasskeyRegisterLoading(false); + } + }; + + const handleRegisterPasskey = async () => { + if (!passkeySupported || !window.PublicKeyCredential) { + showInfo(t('当前设备不支持 Passkey')); + return; + } + await startPasskeyRegistration(); + }; + + const removePasskey = async () => { + setPasskeyDeleteLoading(true); + try { + const res = await API.delete('/api/user/passkey'); + const { success, message } = res.data; + if (!success) { + throw new Error(message || t('操作失败,请重试')); + } + + showSuccess(t('Passkey 已解绑')); + await loadPasskeyStatus(); + return res.data; + } catch (error) { + throw new Error(error?.message || t('操作失败,请重试')); + } finally { + setPasskeyDeleteLoading(false); + } + }; + + const handleRemovePasskey = async () => { + await startPasskeyManagementVerification(removePasskey); + }; + + const handlePasskeyVerificationCancel = () => { + setPasskeyRequiredVerificationMethod(null); + cancelPasskeyVerification(); + }; + + const getUserData = async () => { + let res = await API.get(`/api/user/self`); + const { success, message, data } = res.data; + if (success) { + userDispatch({ type: 'login', payload: data }); + setUserData(data); + await loadPasskeyStatus(); + } else { + showError(message); + } + }; + + const handleSystemTokenClick = async (e) => { + e.target.select(); + await copy(e.target.value); + showSuccess(t('系统令牌已复制到剪切板')); + }; + + const deleteAccount = async () => { + if (inputs.self_account_deletion_confirmation !== userState.user.username) { + showError(t('请输入你的账户名以确认删除!')); + return; + } + + const res = await API.delete('/api/user/self'); + const { success, message } = res.data; + + if (success) { + showSuccess(t('账户已删除!')); + await API.get('/api/user/logout'); + userDispatch({ type: 'logout' }); + localStorage.removeItem('user'); + navigate('/login'); + } else { + showError(message); + } + }; + + const bindWeChat = async () => { + if (inputs.wechat_verification_code === '') return; + const res = await API.post('/api/oauth/wechat/bind', { + code: inputs.wechat_verification_code, + }); + const { success, message } = res.data; + if (success) { + showSuccess(t('微信账户绑定成功!')); + setShowWeChatBindModal(false); + } else { + showError(message); + } + }; + + const changePassword = async () => { + // if (inputs.original_password === '') { + // showError(t('请输入原密码!')); + // return; + // } + if (inputs.set_new_password === '') { + showError(t('请输入新密码!')); + return; + } + if (inputs.original_password === inputs.set_new_password) { + showError(t('新密码需要和原密码不一致!')); + return; + } + if (inputs.set_new_password !== inputs.set_new_password_confirmation) { + showError(t('两次输入的密码不一致!')); + return; + } + const res = await API.put(`/api/user/self`, { + original_password: inputs.original_password, + password: inputs.set_new_password, + }); + const { success, message } = res.data; + if (success) { + showSuccess(t('密码修改成功!')); + setShowWeChatBindModal(false); + } else { + showError(message); + } + setShowChangePasswordModal(false); + }; + + const sendVerificationCode = async () => { + if (inputs.email === '') { + showError(t('请输入邮箱!')); + return; + } + setDisableButton(true); + if (turnstileEnabled && turnstileToken === '') { + showInfo(t('请稍后几秒重试,Turnstile 正在检查用户环境!')); + return; + } + setLoading(true); + const res = await API.get( + `/api/verification?email=${inputs.email}&turnstile=${turnstileToken}`, + ); + const { success, message } = res.data; + if (success) { + showSuccess(t('验证码发送成功,请检查邮箱!')); + } else { + showError(message); + } + setLoading(false); + }; + + const bindEmail = async () => { + if (inputs.email_verification_code === '') { + showError(t('请输入邮箱验证码!')); + return; + } + setLoading(true); + const res = await API.post('/api/oauth/email/bind', { + email: inputs.email, + code: inputs.email_verification_code, + }); + const { success, message } = res.data; + if (success) { + showSuccess(t('邮箱账户绑定成功!')); + setShowEmailBindModal(false); + userState.user.email = inputs.email; + } else { + showError(message); + } + setLoading(false); + }; + + const copyText = async (text) => { + if (await copy(text)) { + showSuccess(t('已复制:') + text); + } else { + // setSearchKeyword(text); + Modal.error({ title: t('无法复制到剪贴板,请手动复制'), content: text }); + } + }; + + const handleNotificationSettingChange = (type, value) => { + setNotificationSettings((prev) => ({ + ...prev, + [type]: value.target + ? value.target.value !== undefined + ? value.target.value + : value.target.checked + : value, // handle checkbox properly + })); + }; + + const saveNotificationSettings = async () => { + try { + const res = await API.put('/api/user/setting', { + notify_type: notificationSettings.warningType, + quota_warning_threshold: parseFloat( + notificationSettings.warningThreshold, + ), + webhook_url: notificationSettings.webhookUrl, + webhook_secret: notificationSettings.webhookSecret, + notification_email: notificationSettings.notificationEmail, + bark_url: notificationSettings.barkUrl, + gotify_url: notificationSettings.gotifyUrl, + gotify_token: notificationSettings.gotifyToken, + gotify_priority: (() => { + const parsed = parseInt(notificationSettings.gotifyPriority); + return isNaN(parsed) ? 5 : parsed; + })(), + upstream_model_update_notify_enabled: + notificationSettings.upstreamModelUpdateNotifyEnabled === true, + accept_unset_model_ratio_model: + notificationSettings.acceptUnsetModelRatioModel, + record_ip_log: notificationSettings.recordIpLog, + }); + + if (res.data.success) { + showSuccess(t('设置保存成功')); + await getUserData(); + } else { + showError(res.data.message); + } + } catch (error) { + showError(t('设置保存失败')); + } + }; + + return ( +
    +
    +
    + {/* 顶部用户信息区域 */} + + + {/* 签到日历 - 仅在启用时显示 */} + {status?.checkin_enabled && ( +
    + +
    + )} + + {/* 账户管理和其他设置 */} +
    + {/* 左侧:账户管理设置 */} +
    + + + {/* 偏好设置(语言等) */} + +
    + + {/* 右侧:其他设置 */} + +
    +
    +
    + + {/* 模态框组件 */} + + + + + + + + + +
    + ); +}; + +export default PersonalSetting; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/setup/index.jsx b/_all-in-one-upload/new-api/web/classic/src/components/setup/index.jsx new file mode 100644 index 0000000..7ce1247 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/setup/index.jsx @@ -0,0 +1,29 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +// 主要组件导出 +export { default as SetupWizard } from './SetupWizard'; + +export { default as StepNavigation } from './components/StepNavigation'; + +// 步骤组件导出 +export { default as DatabaseStep } from './components/steps/DatabaseStep'; +export { default as AdminStep } from './components/steps/AdminStep'; +export { default as UsageModeStep } from './components/steps/UsageModeStep'; +export { default as CompleteStep } from './components/steps/CompleteStep'; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/table/channels/index.jsx b/_all-in-one-upload/new-api/web/classic/src/components/table/channels/index.jsx new file mode 100644 index 0000000..4a22233 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/table/channels/index.jsx @@ -0,0 +1,116 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React from 'react'; +import { Banner } from '@douyinfe/semi-ui'; +import { IconAlertTriangle } from '@douyinfe/semi-icons'; +import CardPro from '../../common/ui/CardPro'; +import ChannelsTable from './ChannelsTable'; +import ChannelsActions from './ChannelsActions'; +import ChannelsFilters from './ChannelsFilters'; +import ChannelsTabs from './ChannelsTabs'; +import { useChannelsData } from '../../../hooks/channels/useChannelsData'; +import { useIsMobile } from '../../../hooks/common/useIsMobile'; +import BatchTagModal from './modals/BatchTagModal'; +import ModelTestModal from './modals/ModelTestModal'; +import ColumnSelectorModal from './modals/ColumnSelectorModal'; +import EditChannelModal from './modals/EditChannelModal'; +import EditTagModal from './modals/EditTagModal'; +import MultiKeyManageModal from './modals/MultiKeyManageModal'; +import ChannelUpstreamUpdateModal from './modals/ChannelUpstreamUpdateModal'; +import { createCardProPagination } from '../../../helpers/utils'; + +const ChannelsPage = () => { + const channelsData = useChannelsData(); + const isMobile = useIsMobile(); + + return ( + <> + {/* Modals */} + + channelsData.setShowEditTag(false)} + refresh={channelsData.refresh} + /> + + + + channelsData.setShowMultiKeyManageModal(false)} + channel={channelsData.currentMultiKeyChannel} + onRefresh={channelsData.refresh} + /> + + + {/* Main Content */} + {channelsData.globalPassThroughEnabled ? ( + + } + description={channelsData.t( + '已开启全局请求透传:参数覆写、模型重定向、渠道适配等 NewAPI 内置功能将失效,非最佳实践;如因此产生问题,请勿提交 issue 反馈。', + )} + style={{ marginBottom: 12 }} + /> + ) : null} + } + actionsArea={} + searchArea={} + paginationArea={createCardProPagination({ + currentPage: channelsData.activePage, + pageSize: channelsData.pageSize, + total: channelsData.channelCount, + onPageChange: channelsData.handlePageChange, + onPageSizeChange: channelsData.handlePageSizeChange, + isMobile: isMobile, + t: channelsData.t, + })} + t={channelsData.t} + > + + + + ); +}; + +export default ChannelsPage; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/table/channels/modals/EditChannelModal.jsx b/_all-in-one-upload/new-api/web/classic/src/components/table/channels/modals/EditChannelModal.jsx new file mode 100644 index 0000000..fad105b --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/table/channels/modals/EditChannelModal.jsx @@ -0,0 +1,3951 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React, { useEffect, useState, useRef, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { + API, + showError, + showInfo, + showSuccess, + verifyJSON, +} from '../../../../helpers'; +import { useIsMobile } from '../../../../hooks/common/useIsMobile'; +import { CHANNEL_OPTIONS, MODEL_FETCHABLE_CHANNEL_TYPES } from '../../../../constants'; +import { + SideSheet, + Space, + Spin, + Button, + Typography, + Checkbox, + Banner, + Modal, + ImagePreview, + Card, + Tag, + Avatar, + Form, + Row, + Col, + Highlight, + Input, + Tooltip, + Collapse, + Dropdown, +} from '@douyinfe/semi-ui'; +import { + getChannelModels, + copy, + getChannelIcon, + getModelCategories, + selectFilter, +} from '../../../../helpers'; +import ModelSelectModal from './ModelSelectModal'; +import SingleModelSelectModal from './SingleModelSelectModal'; +import OllamaModelModal from './OllamaModelModal'; +import CodexOAuthModal from './CodexOAuthModal'; +import ParamOverrideEditorModal from './ParamOverrideEditorModal'; +import JSONEditor from '../../../common/ui/JSONEditor'; +import SecureVerificationModal from '../../../common/modals/SecureVerificationModal'; +import StatusCodeRiskGuardModal from './StatusCodeRiskGuardModal'; +import ChannelKeyDisplay from '../../../common/ui/ChannelKeyDisplay'; +import { useSecureVerification } from '../../../../hooks/common/useSecureVerification'; +import { parseChannelConnectionString } from '../../../../helpers/token'; +import { createApiCalls } from '../../../../services/secureVerification'; +import { + collectInvalidStatusCodeEntries, + collectNewDisallowedStatusCodeRedirects, +} from './statusCodeRiskGuard'; +import { + IconSave, + IconClose, + IconServer, + IconSetting, + IconCode, + IconCopy, + IconGlobe, + IconBolt, + IconSearch, + IconChevronDown, +} from '@douyinfe/semi-icons'; + +const { Text, Title } = Typography; + +const MODEL_MAPPING_EXAMPLE = { + 'gpt-3.5-turbo': 'gpt-3.5-turbo-0125', +}; + +const STATUS_CODE_MAPPING_EXAMPLE = { + 400: '500', +}; + +const REGION_EXAMPLE = { + default: 'global', + 'gemini-1.5-pro-002': 'europe-west2', + 'gemini-1.5-flash-002': 'europe-west2', + 'claude-3-5-sonnet-20240620': 'europe-west1', +}; +const UPSTREAM_DETECTED_MODEL_PREVIEW_LIMIT = 8; +const ADVANCED_SETTINGS_EXPANDED_KEY = 'channel-advanced-settings-expanded'; + +const PARAM_OVERRIDE_LEGACY_TEMPLATE = { + temperature: 0, +}; + +const PARAM_OVERRIDE_OPERATIONS_TEMPLATE = { + operations: [ + { + path: 'temperature', + mode: 'set', + value: 0.7, + conditions: [ + { + path: 'model', + mode: 'prefix', + value: 'openai/', + }, + ], + logic: 'AND', + }, + ], +}; + +const DEPRECATED_DOUBAO_CODING_PLAN_BASE_URL = 'doubao-coding-plan'; + +// 支持并且已适配通过接口获取模型列表的渠道类型 +const MODEL_FETCHABLE_TYPES = new Set([ + 1, 4, 14, 34, 17, 26, 27, 24, 47, 25, 20, 23, 31, 40, 42, 48, 43, +]); + +function type2secretPrompt(type) { + // inputs.type === 15 ? '按照如下格式输入:APIKey|SecretKey' : (inputs.type === 18 ? '按照如下格式输入:APPID|APISecret|APIKey' : '请输入渠道对应的鉴权密钥') + switch (type) { + case 15: + return '按照如下格式输入:APIKey|SecretKey'; + case 18: + return '按照如下格式输入:APPID|APISecret|APIKey'; + case 22: + return '按照如下格式输入:APIKey-AppId,例如:fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041'; + case 23: + return '按照如下格式输入:AppId|SecretId|SecretKey'; + case 33: + return '按照如下格式输入:Ak|Sk|Region'; + case 45: + return '请输入渠道对应的鉴权密钥, 豆包语音输入:AppId|AccessToken'; + case 50: + return '按照如下格式输入: AccessKey|SecretKey, 如果上游是New API,则直接输ApiKey'; + case 51: + return '按照如下格式输入: AccessKey|SecretAccessKey'; + case 57: + return '请输入 JSON 格式的 OAuth 凭据(必须包含 access_token 和 account_id)'; + default: + return '请输入渠道对应的鉴权密钥'; + } +} + +const EditChannelModal = (props) => { + const { t } = useTranslation(); + const channelId = props.editingChannel.id; + const isEdit = channelId !== undefined; + const [loading, setLoading] = useState(isEdit); + const isMobile = useIsMobile(); + const handleCancel = () => { + props.handleClose(); + }; + const originInputs = { + name: '', + type: 1, + key: '', + openai_organization: '', + max_input_tokens: 0, + base_url: '', + other: '', + model_mapping: '', + param_override: '', + status_code_mapping: '', + models: [], + auto_ban: 1, + test_model: '', + groups: ['default'], + priority: 0, + weight: 0, + tag: '', + multi_key_mode: 'random', + // 渠道额外设置的默认值 + force_format: false, + thinking_to_content: false, + proxy: '', + pass_through_body_enabled: false, + system_prompt: '', + system_prompt_override: false, + settings: '', + // 仅 Vertex: 密钥格式(存入 settings.vertex_key_type) + vertex_key_type: 'json', + // 仅 AWS: 密钥格式和区域(存入 settings.aws_key_type 和 settings.aws_region) + aws_key_type: 'ak_sk', + // 企业账户设置 + is_enterprise_account: false, + // 字段透传控制默认值 + allow_service_tier: false, + disable_store: false, // false = 允许透传(默认开启) + allow_safety_identifier: false, + allow_include_obfuscation: false, + allow_inference_geo: false, + allow_speed: false, + claude_beta_query: false, + upstream_model_update_check_enabled: false, + upstream_model_update_auto_sync_enabled: false, + upstream_model_update_last_check_time: 0, + upstream_model_update_last_detected_models: [], + upstream_model_update_ignored_models: '', + }; + const [batch, setBatch] = useState(false); + const [multiToSingle, setMultiToSingle] = useState(false); + const [multiKeyMode, setMultiKeyMode] = useState('random'); + const [autoBan, setAutoBan] = useState(true); + const [inputs, setInputs] = useState(originInputs); + const [originModelOptions, setOriginModelOptions] = useState([]); + const [modelOptions, setModelOptions] = useState([]); + const [groupOptions, setGroupOptions] = useState([]); + const [basicModels, setBasicModels] = useState([]); + const [fullModels, setFullModels] = useState([]); + const [modelGroups, setModelGroups] = useState([]); + const [customModel, setCustomModel] = useState(''); + const [modelSearchValue, setModelSearchValue] = useState(''); + const [modalImageUrl, setModalImageUrl] = useState(''); + const [isModalOpenurl, setIsModalOpenurl] = useState(false); + const [modelModalVisible, setModelModalVisible] = useState(false); + const [fetchedModels, setFetchedModels] = useState([]); + const [modelMappingValueModalVisible, setModelMappingValueModalVisible] = + useState(false); + const [modelMappingValueModalModels, setModelMappingValueModalModels] = + useState([]); + const [modelMappingValueKey, setModelMappingValueKey] = useState(''); + const [modelMappingValueSelected, setModelMappingValueSelected] = + useState(''); + const [ollamaModalVisible, setOllamaModalVisible] = useState(false); + const formApiRef = useRef(null); + const [vertexKeys, setVertexKeys] = useState([]); + const [vertexFileList, setVertexFileList] = useState([]); + const vertexErroredNames = useRef(new Set()); // 避免重复报错 + const [isMultiKeyChannel, setIsMultiKeyChannel] = useState(false); + const [channelSearchValue, setChannelSearchValue] = useState(''); + const [useManualInput, setUseManualInput] = useState(false); // 是否使用手动输入模式 + const [keyMode, setKeyMode] = useState('append'); // 密钥模式:replace(覆盖)或 append(追加) + const [isEnterpriseAccount, setIsEnterpriseAccount] = useState(false); // 是否为企业账户 + const [doubaoApiEditUnlocked, setDoubaoApiEditUnlocked] = useState(false); // 豆包渠道自定义 API 地址隐藏入口 + const redirectModelList = useMemo(() => { + const mapping = inputs.model_mapping; + if (typeof mapping !== 'string') return []; + const trimmed = mapping.trim(); + if (!trimmed) return []; + try { + const parsed = JSON.parse(trimmed); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + return []; + } + const values = Object.values(parsed) + .map((value) => (typeof value === 'string' ? value.trim() : undefined)) + .filter((value) => value); + return Array.from(new Set(values)); + } catch (error) { + return []; + } + }, [inputs.model_mapping]); + const redirectModelKeyList = useMemo(() => { + const mapping = inputs.model_mapping; + if (typeof mapping !== 'string') return []; + const trimmed = mapping.trim(); + if (!trimmed) return []; + try { + const parsed = JSON.parse(trimmed); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + return []; + } + const keys = Object.keys(parsed) + .map((key) => key.trim()) + .filter((key) => key); + return Array.from(new Set(keys)); + } catch (error) { + return []; + } + }, [inputs.model_mapping]); + const upstreamDetectedModels = useMemo( + () => + Array.from( + new Set( + (inputs.upstream_model_update_last_detected_models || []) + .map((model) => String(model || '').trim()) + .filter(Boolean), + ), + ), + [inputs.upstream_model_update_last_detected_models], + ); + const upstreamDetectedModelsPreview = useMemo( + () => upstreamDetectedModels.slice(0, UPSTREAM_DETECTED_MODEL_PREVIEW_LIMIT), + [upstreamDetectedModels], + ); + const upstreamDetectedModelsOmittedCount = + upstreamDetectedModels.length - upstreamDetectedModelsPreview.length; + const modelSearchMatchedCount = useMemo(() => { + const keyword = modelSearchValue.trim(); + if (!keyword) { + return modelOptions.length; + } + return modelOptions.reduce( + (count, option) => count + (selectFilter(keyword, option) ? 1 : 0), + 0, + ); + }, [modelOptions, modelSearchValue]); + const modelSearchHintText = useMemo(() => { + const keyword = modelSearchValue.trim(); + if (!keyword || modelSearchMatchedCount !== 0) { + return ''; + } + return t('未匹配到模型,按回车键可将「{{name}}」作为自定义模型名添加', { + name: keyword, + }); + }, [modelSearchMatchedCount, modelSearchValue, t]); + const paramOverrideMeta = useMemo(() => { + const raw = + typeof inputs.param_override === 'string' + ? inputs.param_override.trim() + : ''; + if (!raw) { + return { + tagLabel: t('不更改'), + tagColor: 'grey', + preview: t( + '此项可选,用于覆盖请求参数。不支持覆盖 stream 参数', + ), + }; + } + if (!verifyJSON(raw)) { + return { + tagLabel: t('JSON格式错误'), + tagColor: 'red', + preview: raw, + }; + } + try { + const parsed = JSON.parse(raw); + const pretty = JSON.stringify(parsed, null, 2); + if ( + parsed && + typeof parsed === 'object' && + !Array.isArray(parsed) && + Array.isArray(parsed.operations) + ) { + return { + tagLabel: `${t('新格式模板')} (${parsed.operations.length})`, + tagColor: 'cyan', + preview: pretty, + }; + } + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + return { + tagLabel: `${t('旧格式模板')} (${Object.keys(parsed).length})`, + tagColor: 'blue', + preview: pretty, + }; + } + return { + tagLabel: t('自定义 JSON'), + tagColor: 'orange', + preview: pretty, + }; + } catch (error) { + return { + tagLabel: t('JSON格式错误'), + tagColor: 'red', + preview: raw, + }; + } + }, [inputs.param_override, t]); + const [isIonetChannel, setIsIonetChannel] = useState(false); + const [ionetMetadata, setIonetMetadata] = useState(null); + const [codexOAuthModalVisible, setCodexOAuthModalVisible] = useState(false); + const [codexCredentialRefreshing, setCodexCredentialRefreshing] = + useState(false); + const [paramOverrideEditorVisible, setParamOverrideEditorVisible] = + useState(false); + + // 密钥显示状态 + const [keyDisplayState, setKeyDisplayState] = useState({ + showModal: false, + keyData: '', + }); + + // 专门的2FA验证状态(用于TwoFactorAuthModal) + const [show2FAVerifyModal, setShow2FAVerifyModal] = useState(false); + const [verifyCode, setVerifyCode] = useState(''); + + useEffect(() => { + if (!isEdit) { + setIsIonetChannel(false); + setIonetMetadata(null); + } + }, [isEdit]); + + const handleOpenIonetDeployment = () => { + if (!ionetMetadata?.deployment_id) { + return; + } + const targetUrl = `/console/deployment?deployment_id=${ionetMetadata.deployment_id}`; + window.open(targetUrl, '_blank', 'noopener'); + }; + const [verifyLoading, setVerifyLoading] = useState(false); + const statusCodeRiskConfirmResolverRef = useRef(null); + const [statusCodeRiskConfirmVisible, setStatusCodeRiskConfirmVisible] = + useState(false); + const [statusCodeRiskDetailItems, setStatusCodeRiskDetailItems] = useState( + [], + ); + + // 剪贴板连接信息自动检测 + const [clipboardConfig, setClipboardConfig] = useState(null); + + // 高级设置折叠状态 + const [advancedSettingsOpen, setAdvancedSettingsOpen] = useState(false); + const toggleAdvancedSettings = (open) => { + setAdvancedSettingsOpen(open); + localStorage.setItem(ADVANCED_SETTINGS_EXPANDED_KEY, String(open)); + }; + const formContainerRef = useRef(null); + const doubaoApiClickCountRef = useRef(0); + const initialBaseUrlRef = useRef(''); + const initialModelsRef = useRef([]); + const initialModelMappingRef = useRef(''); + const initialStatusCodeMappingRef = useRef(''); + const doubaoCodingPlanDeprecationMessage = + 'Doubao Coding Plan 不再允许新增。根据火山方舟文档,Coding 套餐额度仅适用于 AI Coding 产品内调用,不适用于单独 API 调用;在非 AI Coding 产品中使用对应的 Base URL 和 API Key 可能被视为违规,并可能导致订阅停用或账号封禁。'; + const canKeepDeprecatedDoubaoCodingPlan = + initialBaseUrlRef.current === DEPRECATED_DOUBAO_CODING_PLAN_BASE_URL; + const doubaoCodingPlanOptionLabel = ( + + + Doubao Coding Plan + + + ); + + // 2FA状态更新辅助函数 + const updateTwoFAState = (updates) => { + setTwoFAState((prev) => ({ ...prev, ...updates })); + }; + // 使用通用安全验证 Hook + const { + isModalVisible, + verificationMethods, + verificationState, + withVerification, + executeVerification, + cancelVerification, + setVerificationCode, + switchVerificationMethod, + } = useSecureVerification({ + onSuccess: (result) => { + // 验证成功后显示密钥 + console.log('Verification success, result:', result); + if (result && result.success && result.data?.key) { + showSuccess(t('密钥获取成功')); + setKeyDisplayState({ + showModal: true, + keyData: result.data.key, + }); + } else if (result && result.key) { + // 直接返回了 key(没有包装在 data 中) + showSuccess(t('密钥获取成功')); + setKeyDisplayState({ + showModal: true, + keyData: result.key, + }); + } + }, + }); + + // 重置密钥显示状态 + const resetKeyDisplayState = () => { + setKeyDisplayState({ + showModal: false, + keyData: '', + }); + }; + + // 重置2FA验证状态 + const reset2FAVerifyState = () => { + setShow2FAVerifyModal(false); + setVerifyCode(''); + setVerifyLoading(false); + }; + + const handleApiConfigSecretClick = () => { + if (inputs.type !== 45) return; + const next = doubaoApiClickCountRef.current + 1; + doubaoApiClickCountRef.current = next; + if (next >= 10) { + setDoubaoApiEditUnlocked((unlocked) => { + if (!unlocked) { + showInfo(t('已解锁豆包自定义 API 地址编辑')); + } + return true; + }); + } + }; + + // 渠道额外设置状态 + const [channelSettings, setChannelSettings] = useState({ + force_format: false, + thinking_to_content: false, + proxy: '', + pass_through_body_enabled: false, + system_prompt: '', + }); + const showApiConfigCard = true; // 控制是否显示 API 配置卡片 + const getInitValues = () => ({ ...originInputs }); + + // 处理渠道额外设置的更新 + const handleChannelSettingsChange = (key, value) => { + // 更新内部状态 + setChannelSettings((prev) => ({ ...prev, [key]: value })); + + // 同步更新到表单字段 + if (formApiRef.current) { + formApiRef.current.setValue(key, value); + } + + // 同步更新inputs状态 + setInputs((prev) => ({ ...prev, [key]: value })); + + // 生成setting JSON并更新 + const newSettings = { ...channelSettings, [key]: value }; + const settingsJson = JSON.stringify(newSettings); + handleInputChange('setting', settingsJson); + }; + + const handleChannelOtherSettingsChange = (key, value) => { + // 更新内部状态 + setChannelSettings((prev) => ({ ...prev, [key]: value })); + + // 同步更新到表单字段 + if (formApiRef.current) { + formApiRef.current.setValue(key, value); + } + + // 同步更新inputs状态 + setInputs((prev) => ({ ...prev, [key]: value })); + + // 需要更新settings,是一个json,例如{"azure_responses_version": "preview"} + let settings = {}; + if (inputs.settings) { + try { + settings = JSON.parse(inputs.settings); + } catch (error) { + console.error('解析设置失败:', error); + } + } + settings[key] = value; + const settingsJson = JSON.stringify(settings); + handleInputChange('settings', settingsJson); + }; + + const applyClipboardConfig = (config) => { + if (!config) return; + setInputs((prev) => ({ + ...prev, + key: config.key, + base_url: config.url, + })); + if (formApiRef.current) { + formApiRef.current.setValue('key', config.key); + formApiRef.current.setValue('base_url', config.url); + } + setClipboardConfig(null); + showSuccess(t('连接信息已填入')); + }; + + const pasteFromClipboard = async () => { + if (!navigator?.clipboard?.readText) { + showError(t('无法读取剪贴板')); + return; + } + try { + const text = await navigator.clipboard.readText(); + const parsed = parseChannelConnectionString(text); + if (parsed) { + applyClipboardConfig(parsed); + } else { + showInfo(t('剪贴板中未检测到连接信息')); + } + } catch { + showError(t('无法读取剪贴板')); + } + }; + + const isIonetLocked = isIonetChannel && isEdit; + + const handleInputChange = (name, value) => { + if ( + isIonetChannel && + isEdit && + ['type', 'key', 'base_url'].includes(name) + ) { + return; + } + if (formApiRef.current) { + formApiRef.current.setValue(name, value); + } + if (name === 'models' && Array.isArray(value)) { + value = Array.from(new Set(value.map((m) => (m || '').trim()))); + } + + if (name === 'base_url' && value.endsWith('/v1')) { + Modal.confirm({ + title: '警告', + content: + '不需要在末尾加/v1,New API会自动处理,添加后可能导致请求失败,是否继续?', + onOk: () => { + setInputs((inputs) => ({ ...inputs, [name]: value })); + }, + }); + return; + } + setInputs((inputs) => ({ ...inputs, [name]: value })); + if (name === 'type') { + let localModels = []; + switch (value) { + case 2: + localModels = [ + 'mj_imagine', + 'mj_variation', + 'mj_reroll', + 'mj_blend', + 'mj_upscale', + 'mj_describe', + 'mj_uploads', + ]; + break; + case 5: + localModels = [ + 'swap_face', + 'mj_imagine', + 'mj_video', + 'mj_edits', + 'mj_variation', + 'mj_reroll', + 'mj_blend', + 'mj_upscale', + 'mj_describe', + 'mj_zoom', + 'mj_shorten', + 'mj_modal', + 'mj_inpaint', + 'mj_custom_zoom', + 'mj_high_variation', + 'mj_low_variation', + 'mj_pan', + 'mj_uploads', + ]; + break; + case 36: + localModels = ['suno_music', 'suno_lyrics']; + break; + case 45: + localModels = getChannelModels(value); + setInputs((prevInputs) => ({ + ...prevInputs, + base_url: 'https://ark.cn-beijing.volces.com', + })); + break; + default: + localModels = getChannelModels(value); + break; + } + if (inputs.models.length === 0) { + setInputs((inputs) => ({ ...inputs, models: localModels })); + } + setBasicModels(localModels); + + // 重置手动输入模式状态 + setUseManualInput(false); + + if (value === 57) { + setBatch(false); + setMultiToSingle(false); + setMultiKeyMode('random'); + setVertexKeys([]); + setVertexFileList([]); + if (formApiRef.current) { + formApiRef.current.setValue('vertex_files', []); + } + setInputs((prev) => ({ ...prev, vertex_files: [] })); + } + } + //setAutoBan + }; + + const formatJsonField = (fieldName) => { + const rawValue = (inputs?.[fieldName] ?? '').trim(); + if (!rawValue) return; + + try { + const parsed = JSON.parse(rawValue); + handleInputChange(fieldName, JSON.stringify(parsed, null, 2)); + } catch (error) { + showError(`${t('JSON格式错误')}: ${error.message}`); + } + }; + + const formatUnixTime = (timestamp) => { + const value = Number(timestamp || 0); + if (!value) { + return t('暂无'); + } + return new Date(value * 1000).toLocaleString(); + }; + + const copyParamOverrideJson = async () => { + const raw = + typeof inputs.param_override === 'string' + ? inputs.param_override.trim() + : ''; + if (!raw) { + showInfo(t('暂无可复制 JSON')); + return; + } + + let content = raw; + if (verifyJSON(raw)) { + try { + content = JSON.stringify(JSON.parse(raw), null, 2); + } catch (error) { + content = raw; + } + } + + const ok = await copy(content); + if (ok) { + showSuccess(t('参数覆盖 JSON 已复制')); + } else { + showError(t('复制失败')); + } + }; + + const parseParamOverrideInput = () => { + const raw = + typeof inputs.param_override === 'string' + ? inputs.param_override.trim() + : ''; + if (!raw) return null; + if (!verifyJSON(raw)) { + throw new Error(t('当前参数覆盖不是合法的 JSON')); + } + return JSON.parse(raw); + }; + + const applyParamOverrideTemplate = ( + templateType = 'operations', + applyMode = 'fill', + ) => { + try { + const parsedCurrent = parseParamOverrideInput(); + if (templateType === 'legacy') { + if (applyMode === 'fill') { + handleInputChange( + 'param_override', + JSON.stringify(PARAM_OVERRIDE_LEGACY_TEMPLATE, null, 2), + ); + return; + } + const currentLegacy = + parsedCurrent && + typeof parsedCurrent === 'object' && + !Array.isArray(parsedCurrent) && + !Array.isArray(parsedCurrent.operations) + ? parsedCurrent + : {}; + const merged = { + ...PARAM_OVERRIDE_LEGACY_TEMPLATE, + ...currentLegacy, + }; + handleInputChange('param_override', JSON.stringify(merged, null, 2)); + return; + } + + if (applyMode === 'fill') { + handleInputChange( + 'param_override', + JSON.stringify(PARAM_OVERRIDE_OPERATIONS_TEMPLATE, null, 2), + ); + return; + } + const currentOperations = + parsedCurrent && + typeof parsedCurrent === 'object' && + !Array.isArray(parsedCurrent) && + Array.isArray(parsedCurrent.operations) + ? parsedCurrent.operations + : []; + const merged = { + operations: [ + ...currentOperations, + ...PARAM_OVERRIDE_OPERATIONS_TEMPLATE.operations, + ], + }; + handleInputChange('param_override', JSON.stringify(merged, null, 2)); + } catch (error) { + showError(error.message || t('模板应用失败')); + } + }; + + const clearParamOverride = () => { + handleInputChange('param_override', ''); + }; + + const loadChannel = async () => { + setLoading(true); + let res = await API.get(`/api/channel/${channelId}`); + if (res === undefined) { + return; + } + const { success, message, data } = res.data; + if (success) { + if (data.models === '') { + data.models = []; + } else { + data.models = data.models.split(','); + } + if (data.group === '') { + data.groups = []; + } else { + data.groups = data.group.split(','); + } + if (data.model_mapping !== '') { + data.model_mapping = JSON.stringify( + JSON.parse(data.model_mapping), + null, + 2, + ); + } + const chInfo = data.channel_info || {}; + const isMulti = chInfo.is_multi_key === true; + setIsMultiKeyChannel(isMulti); + if (isMulti) { + setBatch(true); + setMultiToSingle(true); + const modeVal = chInfo.multi_key_mode || 'random'; + setMultiKeyMode(modeVal); + data.multi_key_mode = modeVal; + } else { + setBatch(false); + setMultiToSingle(false); + } + // 解析渠道额外设置并合并到data中 + if (data.setting) { + try { + const parsedSettings = JSON.parse(data.setting); + data.force_format = parsedSettings.force_format || false; + data.thinking_to_content = + parsedSettings.thinking_to_content || false; + data.proxy = parsedSettings.proxy || ''; + data.pass_through_body_enabled = + parsedSettings.pass_through_body_enabled || false; + data.system_prompt = parsedSettings.system_prompt || ''; + data.system_prompt_override = + parsedSettings.system_prompt_override || false; + } catch (error) { + console.error('解析渠道设置失败:', error); + data.force_format = false; + data.thinking_to_content = false; + data.proxy = ''; + data.pass_through_body_enabled = false; + data.system_prompt = ''; + data.system_prompt_override = false; + } + } else { + data.force_format = false; + data.thinking_to_content = false; + data.proxy = ''; + data.pass_through_body_enabled = false; + data.system_prompt = ''; + data.system_prompt_override = false; + } + + if (data.settings) { + try { + const parsedSettings = JSON.parse(data.settings); + data.azure_responses_version = + parsedSettings.azure_responses_version || ''; + // 读取 Vertex 密钥格式 + data.vertex_key_type = parsedSettings.vertex_key_type || 'json'; + // 读取 AWS 密钥格式和区域 + data.aws_key_type = parsedSettings.aws_key_type || 'ak_sk'; + // 读取企业账户设置 + data.is_enterprise_account = + parsedSettings.openrouter_enterprise === true; + // 读取字段透传控制设置 + data.allow_service_tier = parsedSettings.allow_service_tier || false; + data.disable_store = parsedSettings.disable_store || false; + data.allow_safety_identifier = + parsedSettings.allow_safety_identifier || false; + data.allow_include_obfuscation = + parsedSettings.allow_include_obfuscation || false; + data.allow_inference_geo = + parsedSettings.allow_inference_geo || false; + data.allow_speed = parsedSettings.allow_speed || false; + data.claude_beta_query = parsedSettings.claude_beta_query || false; + data.upstream_model_update_check_enabled = + parsedSettings.upstream_model_update_check_enabled === true; + data.upstream_model_update_auto_sync_enabled = + parsedSettings.upstream_model_update_auto_sync_enabled === true; + data.upstream_model_update_last_check_time = + Number(parsedSettings.upstream_model_update_last_check_time) || 0; + data.upstream_model_update_last_detected_models = Array.isArray( + parsedSettings.upstream_model_update_last_detected_models, + ) + ? parsedSettings.upstream_model_update_last_detected_models + : []; + data.upstream_model_update_ignored_models = Array.isArray( + parsedSettings.upstream_model_update_ignored_models, + ) + ? parsedSettings.upstream_model_update_ignored_models.join(',') + : ''; + } catch (error) { + console.error('解析其他设置失败:', error); + data.azure_responses_version = ''; + data.region = ''; + data.vertex_key_type = 'json'; + data.aws_key_type = 'ak_sk'; + data.is_enterprise_account = false; + data.allow_service_tier = false; + data.disable_store = false; + data.allow_safety_identifier = false; + data.allow_include_obfuscation = false; + data.allow_inference_geo = false; + data.allow_speed = false; + data.claude_beta_query = false; + data.upstream_model_update_check_enabled = false; + data.upstream_model_update_auto_sync_enabled = false; + data.upstream_model_update_last_check_time = 0; + data.upstream_model_update_last_detected_models = []; + data.upstream_model_update_ignored_models = ''; + } + } else { + // 兼容历史数据:老渠道没有 settings 时,默认按 json 展示 + data.vertex_key_type = 'json'; + data.aws_key_type = 'ak_sk'; + data.is_enterprise_account = false; + data.allow_service_tier = false; + data.disable_store = false; + data.allow_safety_identifier = false; + data.allow_include_obfuscation = false; + data.allow_inference_geo = false; + data.allow_speed = false; + data.claude_beta_query = false; + data.upstream_model_update_check_enabled = false; + data.upstream_model_update_auto_sync_enabled = false; + data.upstream_model_update_last_check_time = 0; + data.upstream_model_update_last_detected_models = []; + data.upstream_model_update_ignored_models = ''; + } + + if ( + data.type === 45 && + (!data.base_url || + (typeof data.base_url === 'string' && data.base_url.trim() === '')) + ) { + data.base_url = 'https://ark.cn-beijing.volces.com'; + } + + initialBaseUrlRef.current = data.base_url || ''; + setInputs(data); + if (formApiRef.current) { + formApiRef.current.setValues(data); + } + if (data.auto_ban === 0) { + setAutoBan(false); + } else { + setAutoBan(true); + } + // 同步企业账户状态 + setIsEnterpriseAccount(data.is_enterprise_account || false); + setBasicModels(getChannelModels(data.type)); + // 同步更新channelSettings状态显示 + setChannelSettings({ + force_format: data.force_format, + thinking_to_content: data.thinking_to_content, + proxy: data.proxy, + pass_through_body_enabled: data.pass_through_body_enabled, + system_prompt: data.system_prompt, + system_prompt_override: data.system_prompt_override || false, + }); + initialModelsRef.current = (data.models || []) + .map((model) => (model || '').trim()) + .filter(Boolean); + initialModelMappingRef.current = data.model_mapping || ''; + initialStatusCodeMappingRef.current = data.status_code_mapping || ''; + + let parsedIonet = null; + if (data.other_info) { + try { + const maybeMeta = JSON.parse(data.other_info); + if ( + maybeMeta && + typeof maybeMeta === 'object' && + maybeMeta.source === 'ionet' + ) { + parsedIonet = maybeMeta; + } + } catch (error) { + // ignore parse error + } + } + const managedByIonet = !!parsedIonet; + setIsIonetChannel(managedByIonet); + setIonetMetadata(parsedIonet); + + // Smart expand: auto-open advanced settings if any advanced field has a value + const hasAdvancedValues = + (data.model_mapping && data.model_mapping.trim()) || + (data.param_override && data.param_override.trim()) || + (data.status_code_mapping && data.status_code_mapping.trim()) || + (data.header_override && data.header_override.trim()) || + (data.tag && data.tag.trim()) || + (data.remark && data.remark.trim()) || + (data.priority && data.priority !== 0) || + (data.weight && data.weight !== 0) || + (data.proxy && data.proxy.trim()) || + (data.system_prompt && data.system_prompt.trim()) || + data.thinking_to_content || + data.pass_through_body_enabled || + data.force_format || + data.claude_beta_query || + data.system_prompt_override; + if (hasAdvancedValues) { + setAdvancedSettingsOpen(true); + } + } else { + showError(message); + } + setLoading(false); + }; + + const fetchUpstreamModelList = async (name, options = {}) => { + const silent = !!options.silent; + // if (inputs['type'] !== 1) { + // showError(t('仅支持 OpenAI 接口格式')); + // return; + // } + setLoading(true); + const models = []; + let err = false; + + if (isEdit) { + // 如果是编辑模式,使用已有的 channelId 获取模型列表 + const res = await API.get('/api/channel/fetch_models/' + channelId, { + skipErrorHandler: true, + }); + if (res && res.data && res.data.success) { + models.push(...res.data.data); + } else { + err = true; + } + } else { + // 如果是新建模式,通过后端代理获取模型列表 + if (!inputs?.['key']) { + showError(t('请填写密钥')); + err = true; + } else { + try { + const res = await API.post( + '/api/channel/fetch_models', + { + base_url: inputs['base_url'], + type: inputs['type'], + key: inputs['key'], + }, + { skipErrorHandler: true }, + ); + + if (res && res.data && res.data.success) { + models.push(...res.data.data); + } else { + err = true; + } + } catch (error) { + console.error('Error fetching models:', error); + err = true; + } + } + } + + if (!err) { + const uniqueModels = Array.from(new Set(models)); + setFetchedModels(uniqueModels); + if (!silent) { + setModelModalVisible(true); + } + setLoading(false); + return uniqueModels; + } else { + showError(t('获取模型列表失败')); + } + setLoading(false); + return null; + }; + + const openModelMappingValueModal = async ({ pairKey, value }) => { + const mappingKey = String(pairKey ?? '').trim(); + if (!mappingKey) return; + + if (!MODEL_FETCHABLE_CHANNEL_TYPES.has(inputs.type)) { + return; + } + + let modelsToUse = fetchedModels; + if (!Array.isArray(modelsToUse) || modelsToUse.length === 0) { + const fetched = await fetchUpstreamModelList('models', { silent: true }); + if (Array.isArray(fetched)) { + modelsToUse = fetched; + } + } + + if (!Array.isArray(modelsToUse) || modelsToUse.length === 0) { + showInfo(t('暂无模型')); + return; + } + + const normalizedModelsToUse = Array.from( + new Set( + modelsToUse.map((model) => String(model ?? '').trim()).filter(Boolean), + ), + ); + const currentValue = String(value ?? '').trim(); + + setModelMappingValueModalModels(normalizedModelsToUse); + setModelMappingValueKey(mappingKey); + setModelMappingValueSelected( + normalizedModelsToUse.includes(currentValue) ? currentValue : '', + ); + setModelMappingValueModalVisible(true); + }; + + const fetchModels = async () => { + try { + let res = await API.get(`/api/channel/models`); + const localModelOptions = res.data.data.map((model) => { + const id = (model.id || '').trim(); + return { + key: id, + label: id, + value: id, + }; + }); + setOriginModelOptions(localModelOptions); + setFullModels(res.data.data.map((model) => model.id)); + setBasicModels( + res.data.data + .filter((model) => { + return model.id.startsWith('gpt-') || model.id.startsWith('text-'); + }) + .map((model) => model.id), + ); + } catch (error) { + showError(error.message); + } + }; + + const fetchGroups = async () => { + try { + let res = await API.get(`/api/group/`); + if (res === undefined) { + return; + } + setGroupOptions( + res.data.data.map((group) => ({ + label: group, + value: group, + })), + ); + } catch (error) { + showError(error.message); + } + }; + + const fetchModelGroups = async () => { + try { + const res = await API.get('/api/prefill_group?type=model'); + if (res?.data?.success) { + setModelGroups(res.data.data || []); + } + } catch (error) { + // ignore + } + }; + + // 查看渠道密钥(透明验证) + const handleShow2FAModal = async () => { + try { + // 使用 withVerification 包装,会自动处理需要验证的情况 + const result = await withVerification( + createApiCalls.viewChannelKey(channelId), + { + title: t('查看渠道密钥'), + description: t('为了保护账户安全,请验证您的身份。'), + preferredMethod: 'passkey', // 优先使用 Passkey + }, + ); + + // 如果直接返回了结果(已验证),显示密钥 + if (result && result.success && result.data?.key) { + showSuccess(t('密钥获取成功')); + setKeyDisplayState({ + showModal: true, + keyData: result.data.key, + }); + } + } catch (error) { + console.error('Failed to view channel key:', error); + showError(error.message || t('获取密钥失败')); + } + }; + + const handleCodexOAuthGenerated = (key) => { + handleInputChange('key', key); + formatJsonField('key'); + }; + + const handleRefreshCodexCredential = async () => { + if (!isEdit) return; + + setCodexCredentialRefreshing(true); + try { + const res = await API.post( + `/api/channel/${channelId}/codex/refresh`, + {}, + { skipErrorHandler: true }, + ); + if (!res?.data?.success) { + throw new Error(res?.data?.message || 'Failed to refresh credential'); + } + showSuccess(t('凭证已刷新')); + } catch (error) { + showError(error.message || t('刷新失败')); + } finally { + setCodexCredentialRefreshing(false); + } + }; + + useEffect(() => { + if (inputs.type !== 45) { + doubaoApiClickCountRef.current = 0; + setDoubaoApiEditUnlocked(false); + } + }, [inputs.type]); + + useEffect(() => { + const modelMap = new Map(); + + originModelOptions.forEach((option) => { + const v = (option.value || '').trim(); + if (!modelMap.has(v)) { + modelMap.set(v, option); + } + }); + + inputs.models.forEach((model) => { + const v = (model || '').trim(); + if (!modelMap.has(v)) { + modelMap.set(v, { + key: v, + label: v, + value: v, + }); + } + }); + + const categories = getModelCategories(t); + const optionsWithIcon = Array.from(modelMap.values()).map((opt) => { + const modelName = opt.value; + let icon = null; + for (const [key, category] of Object.entries(categories)) { + if (key !== 'all' && category.filter({ model_name: modelName })) { + icon = category.icon; + break; + } + } + return { + ...opt, + label: ( + + {icon} + {modelName} + + ), + }; + }); + + setModelOptions(optionsWithIcon); + }, [originModelOptions, inputs.models, t]); + + useEffect(() => { + fetchModels().then(); + fetchGroups().then(); + if (!isEdit) { + initialBaseUrlRef.current = ''; + setInputs(originInputs); + if (formApiRef.current) { + formApiRef.current.setValues(originInputs); + } + let localModels = getChannelModels(inputs.type); + setBasicModels(localModels); + setInputs((inputs) => ({ ...inputs, models: localModels })); + } + }, [props.editingChannel.id]); + + useEffect(() => { + if (formApiRef.current) { + formApiRef.current.setValues(inputs); + } + }, [inputs]); + + useEffect(() => { + setModelSearchValue(''); + if (props.visible) { + if (isEdit) { + loadChannel(); + } else { + formApiRef.current?.setValues(getInitValues()); + try { + navigator?.clipboard?.readText()?.then((text) => { + const parsed = parseChannelConnectionString(text); + if (parsed) { + setClipboardConfig(parsed); + } + }).catch(() => {}); + } catch {} + } + fetchModelGroups(); + // 重置手动输入模式状态 + setUseManualInput(false); + // 编辑模式下恢复用户偏好,创建模式一律折叠 + setAdvancedSettingsOpen( + isEdit && localStorage.getItem(ADVANCED_SETTINGS_EXPANDED_KEY) === 'true' + ); + } else { + // 统一的模态框关闭重置逻辑 + resetModalState(); + } + }, [props.visible, channelId]); + + useEffect(() => { + if (!isEdit) { + initialModelsRef.current = []; + initialModelMappingRef.current = ''; + initialStatusCodeMappingRef.current = ''; + } + }, [isEdit, props.visible]); + + useEffect(() => { + return () => { + if (statusCodeRiskConfirmResolverRef.current) { + statusCodeRiskConfirmResolverRef.current(false); + statusCodeRiskConfirmResolverRef.current = null; + } + }; + }, []); + + // 统一的模态框重置函数 + const resetModalState = () => { + resolveStatusCodeRiskConfirm(false); + formApiRef.current?.reset(); + // 重置渠道设置状态 + setChannelSettings({ + force_format: false, + thinking_to_content: false, + proxy: '', + pass_through_body_enabled: false, + system_prompt: '', + system_prompt_override: false, + }); + // 重置密钥模式状态 + setKeyMode('append'); + // 重置企业账户状态 + setIsEnterpriseAccount(false); + // 重置豆包隐藏入口状态 + setDoubaoApiEditUnlocked(false); + doubaoApiClickCountRef.current = 0; + setModelSearchValue(''); + // 重置高级设置折叠状态 + setAdvancedSettingsOpen(false); + // 清空表单中的key_mode字段 + if (formApiRef.current) { + formApiRef.current.setValue('key_mode', undefined); + } + // 重置本地输入,避免下次打开残留上一次的 JSON 字段值 + setInputs(getInitValues()); + // 重置密钥显示状态 + resetKeyDisplayState(); + // 重置剪贴板检测状态 + setClipboardConfig(null); + }; + + const handleVertexUploadChange = ({ fileList }) => { + vertexErroredNames.current.clear(); + (async () => { + let validFiles = []; + let keys = []; + const errorNames = []; + for (const item of fileList) { + const fileObj = item.fileInstance; + if (!fileObj) continue; + try { + const txt = await fileObj.text(); + keys.push(JSON.parse(txt)); + validFiles.push(item); + } catch (err) { + if (!vertexErroredNames.current.has(item.name)) { + errorNames.push(item.name); + vertexErroredNames.current.add(item.name); + } + } + } + + // 非批量模式下只保留一个文件(最新选择的),避免重复叠加 + if (!batch && validFiles.length > 1) { + validFiles = [validFiles[validFiles.length - 1]]; + keys = [keys[keys.length - 1]]; + } + + setVertexKeys(keys); + setVertexFileList(validFiles); + if (formApiRef.current) { + formApiRef.current.setValue('vertex_files', validFiles); + } + setInputs((prev) => ({ ...prev, vertex_files: validFiles })); + + if (errorNames.length > 0) { + showError( + t('以下文件解析失败,已忽略:{{list}}', { + list: errorNames.join(', '), + }), + ); + } + })(); + }; + + const confirmMissingModelMappings = (missingModels) => + new Promise((resolve) => { + const modal = Modal.confirm({ + title: t('模型未加入列表,可能无法调用'), + content: ( +
    +
    + {t( + '模型重定向里的下列模型尚未添加到“模型”列表,调用时会因为缺少可用模型而失败:', + )} +
    +
    + {missingModels.join(', ')} +
    +
    + {t( + '你可以在“自定义模型名称”处手动添加它们,然后点击填入后再提交,或者直接使用下方操作自动处理。', + )} +
    +
    + ), + centered: true, + footer: ( + + + + + + ), + }); + }); + + const resolveStatusCodeRiskConfirm = (confirmed) => { + setStatusCodeRiskConfirmVisible(false); + setStatusCodeRiskDetailItems([]); + if (statusCodeRiskConfirmResolverRef.current) { + statusCodeRiskConfirmResolverRef.current(confirmed); + statusCodeRiskConfirmResolverRef.current = null; + } + }; + + const confirmStatusCodeRisk = (detailItems) => + new Promise((resolve) => { + statusCodeRiskConfirmResolverRef.current = resolve; + setStatusCodeRiskDetailItems(detailItems); + setStatusCodeRiskConfirmVisible(true); + }); + + const hasModelConfigChanged = (normalizedModels, modelMappingStr) => { + if (!isEdit) return true; + const initialModels = initialModelsRef.current; + if (normalizedModels.length !== initialModels.length) { + return true; + } + for (let i = 0; i < normalizedModels.length; i++) { + if (normalizedModels[i] !== initialModels[i]) { + return true; + } + } + const normalizedMapping = (modelMappingStr || '').trim(); + const initialMapping = (initialModelMappingRef.current || '').trim(); + return normalizedMapping !== initialMapping; + }; + + const submit = async () => { + const formValues = formApiRef.current ? formApiRef.current.getValues() : {}; + let localInputs = { ...formValues }; + localInputs.param_override = inputs.param_override; + + if (localInputs.type === 57) { + if (batch) { + showInfo(t('Codex 渠道不支持批量创建')); + return; + } + + const rawKey = (localInputs.key || '').trim(); + if (!isEdit && rawKey === '') { + showInfo(t('请输入密钥!')); + return; + } + + if (rawKey !== '') { + if (!verifyJSON(rawKey)) { + showInfo(t('密钥必须是合法的 JSON 格式!')); + return; + } + try { + const parsed = JSON.parse(rawKey); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + showInfo(t('密钥必须是 JSON 对象')); + return; + } + const accessToken = String(parsed.access_token || '').trim(); + const accountId = String(parsed.account_id || '').trim(); + if (!accessToken) { + showInfo(t('密钥 JSON 必须包含 access_token')); + return; + } + if (!accountId) { + showInfo(t('密钥 JSON 必须包含 account_id')); + return; + } + localInputs.key = JSON.stringify(parsed); + } catch (error) { + showInfo(t('密钥必须是合法的 JSON 格式!')); + return; + } + } + } + + if (localInputs.type === 41) { + const keyType = localInputs.vertex_key_type || 'json'; + if (keyType === 'api_key') { + // 直接作为普通字符串密钥处理 + if (!isEdit && (!localInputs.key || localInputs.key.trim() === '')) { + showInfo(t('请输入密钥!')); + return; + } + } else { + // JSON 服务账号密钥 + if (useManualInput) { + if (localInputs.key && localInputs.key.trim() !== '') { + try { + const parsedKey = JSON.parse(localInputs.key); + localInputs.key = JSON.stringify(parsedKey); + } catch (err) { + showError(t('密钥格式无效,请输入有效的 JSON 格式密钥')); + return; + } + } else if (!isEdit) { + showInfo(t('请输入密钥!')); + return; + } + } else { + // 文件上传模式 + let keys = vertexKeys; + if (keys.length === 0 && vertexFileList.length > 0) { + try { + const parsed = await Promise.all( + vertexFileList.map(async (item) => { + const fileObj = item.fileInstance; + if (!fileObj) return null; + const txt = await fileObj.text(); + return JSON.parse(txt); + }), + ); + keys = parsed.filter(Boolean); + } catch (err) { + showError(t('解析密钥文件失败: {{msg}}', { msg: err.message })); + return; + } + } + if (keys.length === 0) { + if (!isEdit) { + showInfo(t('请上传密钥文件!')); + return; + } else { + delete localInputs.key; + } + } else { + localInputs.key = batch + ? JSON.stringify(keys) + : JSON.stringify(keys[0]); + } + } + } + } + + // 如果是编辑模式且 key 为空字符串,避免提交空值覆盖旧密钥 + if (isEdit && (!localInputs.key || localInputs.key.trim() === '')) { + delete localInputs.key; + } + delete localInputs.vertex_files; + + if (!isEdit && (!localInputs.name || !localInputs.key)) { + showInfo(t('请填写渠道名称和渠道密钥!')); + return; + } + if (!Array.isArray(localInputs.models) || localInputs.models.length === 0) { + showInfo(t('请至少选择一个模型!')); + return; + } + if ( + localInputs.type === 45 && + (!localInputs.base_url || localInputs.base_url.trim() === '') + ) { + showInfo(t('请输入API地址!')); + return; + } + const hasModelMapping = + typeof localInputs.model_mapping === 'string' && + localInputs.model_mapping.trim() !== ''; + let parsedModelMapping = null; + if (hasModelMapping) { + if (!verifyJSON(localInputs.model_mapping)) { + showInfo(t('模型映射必须是合法的 JSON 格式!')); + return; + } + try { + parsedModelMapping = JSON.parse(localInputs.model_mapping); + } catch (error) { + showInfo(t('模型映射必须是合法的 JSON 格式!')); + return; + } + } + + const normalizedModels = (localInputs.models || []) + .map((model) => (model || '').trim()) + .filter(Boolean); + localInputs.models = normalizedModels; + + if ( + parsedModelMapping && + typeof parsedModelMapping === 'object' && + !Array.isArray(parsedModelMapping) + ) { + const modelSet = new Set(normalizedModels); + const missingModels = Object.keys(parsedModelMapping) + .map((key) => (key || '').trim()) + .filter((key) => key && !modelSet.has(key)); + const shouldPromptMissing = + missingModels.length > 0 && + hasModelConfigChanged(normalizedModels, localInputs.model_mapping); + if (shouldPromptMissing) { + const confirmAction = await confirmMissingModelMappings(missingModels); + if (confirmAction === 'cancel') { + return; + } + if (confirmAction === 'add') { + const updatedModels = Array.from( + new Set([...normalizedModels, ...missingModels]), + ); + localInputs.models = updatedModels; + handleInputChange('models', updatedModels); + } + } + } + + const invalidStatusCodeEntries = collectInvalidStatusCodeEntries( + localInputs.status_code_mapping, + ); + if (invalidStatusCodeEntries.length > 0) { + showError( + `${t('状态码复写包含无效的状态码')}: ${invalidStatusCodeEntries.join(', ')}`, + ); + return; + } + + const riskyStatusCodeRedirects = collectNewDisallowedStatusCodeRedirects( + initialStatusCodeMappingRef.current, + localInputs.status_code_mapping, + ); + if (riskyStatusCodeRedirects.length > 0) { + const confirmed = await confirmStatusCodeRisk(riskyStatusCodeRedirects); + if (!confirmed) { + return; + } + } + + if (localInputs.base_url && localInputs.base_url.endsWith('/')) { + localInputs.base_url = localInputs.base_url.slice( + 0, + localInputs.base_url.length - 1, + ); + } + if (localInputs.type === 18 && localInputs.other === '') { + localInputs.other = 'v2.1'; + } + + // 生成渠道额外设置JSON + const channelExtraSettings = { + force_format: localInputs.force_format || false, + thinking_to_content: localInputs.thinking_to_content || false, + proxy: localInputs.proxy || '', + pass_through_body_enabled: localInputs.pass_through_body_enabled || false, + system_prompt: localInputs.system_prompt || '', + system_prompt_override: localInputs.system_prompt_override || false, + }; + localInputs.setting = JSON.stringify(channelExtraSettings); + + // 处理 settings 字段(包括企业账户设置和字段透传控制) + let settings = {}; + if (localInputs.settings) { + try { + settings = JSON.parse(localInputs.settings); + } catch (error) { + console.error('解析settings失败:', error); + } + } + + // type === 20: 设置企业账户标识,无论是true还是false都要传到后端 + if (localInputs.type === 20) { + settings.openrouter_enterprise = + localInputs.is_enterprise_account === true; + } + + // type === 33 (AWS): 保存 aws_key_type 到 settings + if (localInputs.type === 33) { + settings.aws_key_type = localInputs.aws_key_type || 'ak_sk'; + } + + // type === 41 (Vertex): 始终保存 vertex_key_type 到 settings,避免编辑时被重置 + if (localInputs.type === 41) { + settings.vertex_key_type = localInputs.vertex_key_type || 'json'; + } else if ('vertex_key_type' in settings) { + delete settings.vertex_key_type; + } + + // type === 1 (OpenAI) 或 type === 14 (Claude): 设置字段透传控制(显式保存布尔值) + if (localInputs.type === 1 || localInputs.type === 14) { + settings.allow_service_tier = localInputs.allow_service_tier === true; + // 仅 OpenAI 渠道需要 store / safety_identifier / include_obfuscation + if (localInputs.type === 1) { + settings.disable_store = localInputs.disable_store === true; + settings.allow_safety_identifier = + localInputs.allow_safety_identifier === true; + settings.allow_include_obfuscation = + localInputs.allow_include_obfuscation === true; + } + if (localInputs.type === 14) { + settings.allow_inference_geo = localInputs.allow_inference_geo === true; + settings.allow_speed = localInputs.allow_speed === true; + settings.claude_beta_query = localInputs.claude_beta_query === true; + } + } + + settings.upstream_model_update_check_enabled = + localInputs.upstream_model_update_check_enabled === true; + settings.upstream_model_update_auto_sync_enabled = + settings.upstream_model_update_check_enabled && + localInputs.upstream_model_update_auto_sync_enabled === true; + settings.upstream_model_update_ignored_models = Array.from( + new Set( + String(localInputs.upstream_model_update_ignored_models || '') + .split(',') + .map((model) => model.trim()) + .filter(Boolean), + ), + ); + if ( + !Array.isArray(settings.upstream_model_update_last_detected_models) || + !settings.upstream_model_update_check_enabled + ) { + settings.upstream_model_update_last_detected_models = []; + } + if (typeof settings.upstream_model_update_last_check_time !== 'number') { + settings.upstream_model_update_last_check_time = 0; + } + + localInputs.settings = JSON.stringify(settings); + + // 清理不需要发送到后端的字段 + delete localInputs.force_format; + delete localInputs.thinking_to_content; + delete localInputs.proxy; + delete localInputs.pass_through_body_enabled; + delete localInputs.system_prompt; + delete localInputs.system_prompt_override; + delete localInputs.is_enterprise_account; + // 顶层的 vertex_key_type 不应发送给后端 + delete localInputs.vertex_key_type; + // 顶层的 aws_key_type 不应发送给后端 + delete localInputs.aws_key_type; + // 清理字段透传控制的临时字段 + delete localInputs.allow_service_tier; + delete localInputs.disable_store; + delete localInputs.allow_safety_identifier; + delete localInputs.allow_include_obfuscation; + delete localInputs.allow_inference_geo; + delete localInputs.allow_speed; + delete localInputs.claude_beta_query; + delete localInputs.upstream_model_update_check_enabled; + delete localInputs.upstream_model_update_auto_sync_enabled; + delete localInputs.upstream_model_update_last_check_time; + delete localInputs.upstream_model_update_last_detected_models; + delete localInputs.upstream_model_update_ignored_models; + + let res; + localInputs.auto_ban = localInputs.auto_ban ? 1 : 0; + localInputs.models = localInputs.models.join(','); + localInputs.group = (localInputs.groups || []).join(','); + + let mode = 'single'; + if (batch) { + mode = multiToSingle ? 'multi_to_single' : 'batch'; + } + + if (isEdit) { + res = await API.put(`/api/channel/`, { + ...localInputs, + id: parseInt(channelId), + key_mode: isMultiKeyChannel ? keyMode : undefined, // 只在多key模式下传递 + }); + } else { + res = await API.post(`/api/channel/`, { + mode: mode, + multi_key_mode: mode === 'multi_to_single' ? multiKeyMode : undefined, + channel: localInputs, + }); + } + const { success, message } = res.data; + if (success) { + if (isEdit) { + showSuccess(t('渠道更新成功!')); + } else { + showSuccess(t('渠道创建成功!')); + setInputs(originInputs); + } + props.refresh(); + props.handleClose(); + } else { + showError(message); + } + }; + + // 密钥去重函数 + const deduplicateKeys = () => { + const currentKey = formApiRef.current?.getValue('key') || inputs.key || ''; + + if (!currentKey.trim()) { + showInfo(t('请先输入密钥')); + return; + } + + // 按行分割密钥 + const keyLines = currentKey.split('\n'); + const beforeCount = keyLines.length; + + // 使用哈希表去重,保持原有顺序 + const keySet = new Set(); + const deduplicatedKeys = []; + + keyLines.forEach((line) => { + const trimmedLine = line.trim(); + if (trimmedLine && !keySet.has(trimmedLine)) { + keySet.add(trimmedLine); + deduplicatedKeys.push(trimmedLine); + } + }); + + const afterCount = deduplicatedKeys.length; + const deduplicatedKeyText = deduplicatedKeys.join('\n'); + + // 更新表单和状态 + if (formApiRef.current) { + formApiRef.current.setValue('key', deduplicatedKeyText); + } + handleInputChange('key', deduplicatedKeyText); + + // 显示去重结果 + const message = t( + '去重完成:去重前 {{before}} 个密钥,去重后 {{after}} 个密钥', + { + before: beforeCount, + after: afterCount, + }, + ); + + if (beforeCount === afterCount) { + showInfo(t('未发现重复密钥')); + } else { + showSuccess(message); + } + }; + + const addCustomModels = () => { + if (customModel.trim() === '') return; + const modelArray = customModel.split(',').map((model) => model.trim()); + + let localModels = [...inputs.models]; + let localModelOptions = [...modelOptions]; + const addedModels = []; + + modelArray.forEach((model) => { + if (model && !localModels.includes(model)) { + localModels.push(model); + localModelOptions.push({ + key: model, + label: model, + value: model, + }); + addedModels.push(model); + } + }); + + setModelOptions(localModelOptions); + setCustomModel(''); + handleInputChange('models', localModels); + + if (addedModels.length > 0) { + showSuccess( + t('已新增 {{count}} 个模型:{{list}}', { + count: addedModels.length, + list: addedModels.join(', '), + }), + ); + } else { + showInfo(t('未发现新增模型')); + } + }; + + const batchAllowed = (!isEdit || isMultiKeyChannel) && inputs.type !== 57; + const batchExtra = batchAllowed ? ( + + {!isEdit && ( + { + const checked = e.target.checked; + + if (!checked && vertexFileList.length > 1) { + Modal.confirm({ + title: t('切换为单密钥模式'), + content: t( + '将仅保留第一个密钥文件,其余文件将被移除,是否继续?', + ), + onOk: () => { + const firstFile = vertexFileList[0]; + const firstKey = vertexKeys[0] ? [vertexKeys[0]] : []; + + setVertexFileList([firstFile]); + setVertexKeys(firstKey); + + formApiRef.current?.setValue('vertex_files', [firstFile]); + setInputs((prev) => ({ ...prev, vertex_files: [firstFile] })); + + setBatch(false); + setMultiToSingle(false); + setMultiKeyMode('random'); + }, + onCancel: () => { + setBatch(true); + }, + centered: true, + }); + return; + } + + setBatch(checked); + if (!checked) { + setMultiToSingle(false); + setMultiKeyMode('random'); + } else { + // 批量模式下禁用手动输入,并清空手动输入的内容 + setUseManualInput(false); + if (inputs.type === 41) { + // 清空手动输入的密钥内容 + if (formApiRef.current) { + formApiRef.current.setValue('key', ''); + } + handleInputChange('key', ''); + } + } + }} + > + {t('批量创建')} + + )} + {batch && ( + <> + { + setMultiToSingle((prev) => { + const nextValue = !prev; + setInputs((prevInputs) => { + const newInputs = { ...prevInputs }; + if (nextValue) { + newInputs.multi_key_mode = multiKeyMode; + } else { + delete newInputs.multi_key_mode; + } + return newInputs; + }); + return nextValue; + }); + }} + > + {t('密钥聚合模式')} + + + {inputs.type !== 41 && ( + + )} + + )} + + ) : null; + + const channelOptionList = useMemo( + () => + CHANNEL_OPTIONS.map((opt) => ({ + ...opt, + // 保持 label 为纯文本以支持搜索 + label: opt.label, + })), + [], + ); + + const renderChannelOption = (renderProps) => { + const { + disabled, + selected, + label, + value, + focused, + className, + style, + onMouseEnter, + onClick, + ...rest + } = renderProps; + + const searchWords = channelSearchValue ? [channelSearchValue] : []; + + // 构建样式类名 + const optionClassName = [ + 'flex items-center gap-3 px-3 py-2 transition-all duration-200 rounded-lg mx-2 my-1', + focused && 'bg-blue-50 shadow-sm', + selected && + 'bg-blue-100 text-blue-700 shadow-lg ring-2 ring-blue-200 ring-opacity-50', + disabled && 'opacity-50 cursor-not-allowed', + !disabled && 'hover:bg-gray-50 hover:shadow-md cursor-pointer', + className, + ] + .filter(Boolean) + .join(' '); + + return ( +
    !disabled && onClick()} + onMouseEnter={(e) => onMouseEnter()} + > +
    +
    + {getChannelIcon(value)} +
    +
    + +
    + {selected && ( +
    + + + +
    + )} +
    +
    + ); + }; + + return ( + <> + + + + {isEdit ? t('编辑') : t('新建')} + + + {isEdit ? t('更新渠道信息') : t('创建新的渠道')} + + + {!isEdit && ( + + )} + + } + bodyStyle={{ padding: '0' }} + visible={props.visible} + width={isMobile ? '100%' : 600} + footer={ +
    + + +
    + } + closeIcon={null} + onCancel={() => handleCancel()} + > +
    (formApiRef.current = api)} + onSubmit={submit} + > + {() => { + const advancedSettingsContent = ( +
    + {/* Upstream Model Management Section */} + {MODEL_FETCHABLE_CHANNEL_TYPES.has(inputs.type) && ( +
    + + {t('上游模型管理')} + + + + handleChannelOtherSettingsChange( + 'upstream_model_update_check_enabled', + value, + ) + } + extraText={t( + '开启后由后端定时任务检测该渠道上游模型变化', + )} + /> + + handleChannelOtherSettingsChange('upstream_model_update_auto_sync_enabled', value) + } + extraText={t('开启后检测到新增模型会自动加入当前渠道模型列表')} + /> + + handleInputChange( + 'upstream_model_update_ignored_models', + value, + ) + } + showClear + /> +
    + {t('上次检测时间')}:  + {formatUnixTime( + inputs.upstream_model_update_last_check_time, + )} +
    +
    + {t('上次检测到可加入模型')}:  + {upstreamDetectedModels.length === 0 ? ( + t('暂无') + ) : ( + <> + + {upstreamDetectedModels.join(', ')} +
    + } + > + + {upstreamDetectedModelsPreview.join(', ')} + + + + {upstreamDetectedModelsOmittedCount > 0 + ? t('(共 {{total}} 个,省略 {{omit}} 个)', { + total: upstreamDetectedModels.length, + omit: upstreamDetectedModelsOmittedCount, + }) + : t('(共 {{total}} 个)', { + total: upstreamDetectedModels.length, + })} + + + )} +
    +
    + )} + + {/* Request Config Section */} +
    + + {t('请求配置')} + + +
    +
    + {t('参数覆盖')} + + + applyParamOverrideTemplate('operations', 'fill') }, + { node: 'item', name: t('填充旧模板'), onClick: () => applyParamOverrideTemplate('legacy', 'fill') }, + { node: 'item', name: t('清空'), onClick: clearParamOverride }, + ]} + > + + + +
    + + {t('此项可选,用于覆盖请求参数。不支持覆盖 stream 参数')} + +
    +
    + + {paramOverrideMeta.tagLabel} + + +
    +
    +                        {paramOverrideMeta.preview}
    +                      
    +
    +
    + + + handleInputChange('header_override', value) + } + extraText={ +
    +
    + + handleInputChange( + 'header_override', + JSON.stringify({ '*': true, 're:^X-Trace-.*$': true, 'X-Foo': '{client_header:X-Foo}', Authorization: 'Bearer {api_key}', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0' }, null, 2), + ) + } + > + {t('填入模板')} + + + handleInputChange('header_override', JSON.stringify({ '*': true }, null, 2)) + } + > + {t('填入透传模版')} + + formatJsonField('header_override')} + > + {t('格式化')} + +
    +
    + + {t('支持变量:')} + +
    +
    + {t('渠道密钥')}: {'{api_key}'} +
    +
    +
    +
    + } + showClear + /> + + handleInputChange('status_code_mapping', value) + } + template={STATUS_CODE_MAPPING_EXAMPLE} + templateLabel={t('填入模板')} + editorType='keyValue' + formApi={formApiRef.current} + extraText={t('键为原状态码,值为要复写的状态码,仅影响本地判断')} + /> +
    + + {/* Channel Behavior Section */} +
    + + {t('渠道行为')} + + + handleInputChange('tag', value)} + /> + handleInputChange('remark', value)} + /> + + + + handleInputChange('priority', value)} + style={{ width: '100%' }} + /> + + + handleInputChange('weight', value)} + style={{ width: '100%' }} + /> + + + + {inputs.type === 1 && ( + <> +
    + {t('字段透传控制')} +
    + handleChannelOtherSettingsChange('allow_service_tier', value)} extraText={t('service_tier 字段用于指定服务层级,允许透传可能导致实际计费高于预期。默认关闭以避免额外费用')} /> + handleChannelOtherSettingsChange('disable_store', value)} extraText={t('store 字段用于授权 OpenAI 存储请求数据以评估和优化产品。默认关闭,开启后可能导致 Codex 无法正常使用')} /> + handleChannelOtherSettingsChange('allow_safety_identifier', value)} extraText={t('safety_identifier 字段用于帮助 OpenAI 识别可能违反使用政策的应用程序用户。默认关闭以保护用户隐私')} /> + handleChannelOtherSettingsChange('allow_include_obfuscation', value)} extraText={t('include_obfuscation 用于控制 Responses 流混淆字段。默认关闭以避免客户端关闭该安全保护')} /> + + )} + + {inputs.type === 14 && ( + <> +
    + {t('字段透传控制')} +
    + handleChannelOtherSettingsChange('allow_service_tier', value)} extraText={t('service_tier 字段用于指定服务层级,允许透传可能导致实际计费高于预期。默认关闭以避免额外费用')} /> + handleChannelOtherSettingsChange('allow_inference_geo', value)} extraText={t('inference_geo 字段用于控制 Claude 数据驻留推理区域。默认关闭以避免未经授权透传地域信息')} /> + handleChannelOtherSettingsChange('allow_speed', value)} extraText={t('speed 字段用于控制 Claude 推理速度模式。默认关闭以避免意外切换到 fast 模式')} /> + + )} +
    + + {/* Extra Settings Section */} +
    + + {t('额外设置')} + + + {inputs.type === 14 && ( + handleChannelOtherSettingsChange('claude_beta_query', value)} extraText={t('开启后,该渠道请求 Claude 时将强制追加 ?beta=true(无需客户端手动传参)')} /> + )} + + {inputs.type === 1 && ( + handleChannelSettingsChange('force_format', value)} extraText={t('强制将响应格式化为 OpenAI 标准格式(只适用于OpenAI渠道类型)')} /> + )} + + handleChannelSettingsChange('thinking_to_content', value)} extraText={t('将 reasoning_content 转换为 标签拼接到内容中')} /> + handleChannelSettingsChange('pass_through_body_enabled', value)} extraText={t('启用请求体透传功能')} /> + + handleChannelSettingsChange('proxy', value)} showClear extraText={t('用于配置网络代理,支持 socks5 协议')} /> + + handleChannelSettingsChange('system_prompt', value)} autosize showClear extraText={t('用户优先:如果用户在请求中指定了系统提示词,将优先使用用户的设置')} /> + handleChannelSettingsChange('system_prompt_override', value)} extraText={t('如果用户请求中包含系统提示词,则使用此设置拼接到用户的系统提示词前面')} /> +
    + + ); + + return ( + <> + +
    + {!isEdit && clipboardConfig && ( + + {t('检测到剪贴板中的连接信息')} +
    + + +
    +
    + } + /> + )} + {/* Core Configuration Card - Always Visible */} + + {/* Header */} +
    + + + +
    + + {t('核心配置')} + +
    + {t('创建渠道所需的基本信息')} +
    +
    +
    + + {isIonetChannel && ( + + + {ionetMetadata?.deployment_id && ( + + )} + + + )} + + setChannelSearchValue(value)} + renderOptionItem={renderChannelOption} + onChange={(value) => handleInputChange('type', value)} + disabled={isIonetLocked} + /> + + {inputs.type === 57 && ( + + )} + + {inputs.type === 20 && ( + { + setIsEnterpriseAccount(value); + handleInputChange('is_enterprise_account', value); + }} + extraText={t( + '企业账户为特殊返回格式,需要特殊处理,如果非企业账户,请勿勾选', + )} + initValue={inputs.is_enterprise_account} + /> + )} + + handleInputChange('name', value)} + autoComplete='new-password' + /> + + {inputs.type === 33 && ( + <> + { + handleChannelOtherSettingsChange( + 'aws_key_type', + value, + ); + }} + extraText={t( + 'AK/SK 模式:使用 AccessKey 和 SecretAccessKey;API Key 模式:使用 API Key', + )} + /> + + )} + + {inputs.type === 41 && ( + { + // 更新设置中的 vertex_key_type + handleChannelOtherSettingsChange( + 'vertex_key_type', + value, + ); + // 切换为 api_key 时,关闭批量与手动/文件切换,并清理已选文件 + if (value === 'api_key') { + setBatch(false); + setUseManualInput(false); + setVertexKeys([]); + setVertexFileList([]); + if (formApiRef.current) { + formApiRef.current.setValue('vertex_files', []); + } + } + }} + extraText={ + inputs.vertex_key_type === 'api_key' + ? t('API Key 模式下不支持批量创建') + : t('JSON 模式支持手动输入或上传服务账号 JSON') + } + /> + )} + {batch ? ( + inputs.type === 41 && + (inputs.vertex_key_type || 'json') === 'json' ? ( + } + dragMainText={t('点击上传文件或拖拽文件到这里')} + dragSubText={t('仅支持 JSON 文件,支持多文件')} + style={{ marginTop: 10 }} + uploadTrigger='custom' + beforeUpload={() => false} + onChange={handleVertexUploadChange} + fileList={vertexFileList} + rules={ + isEdit + ? [] + : [ + { + required: true, + message: t('请上传密钥文件'), + }, + ] + } + extraText={batchExtra} + /> + ) : ( + handleInputChange('key', value)} + disabled={isIonetLocked} + extraText={ +
    + {isEdit && + isMultiKeyChannel && + keyMode === 'append' && ( + + {t( + '追加模式:新密钥将添加到现有密钥列表的末尾', + )} + + )} + {isEdit && ( + + )} + {batchExtra} +
    + } + showClear + /> + ) + ) : ( + <> + {inputs.type === 57 ? ( + <> + + handleInputChange('key', value) + } + disabled={isIonetLocked} + extraText={ +
    + + {t( + '仅支持 JSON 对象,必须包含 access_token 与 account_id', + )} + + + + + {isEdit && ( + + )} + + {isEdit && ( + + )} + {batchExtra} + +
    + } + autosize + showClear + /> + + setCodexOAuthModalVisible(false)} + onSuccess={handleCodexOAuthGenerated} + /> + + ) : inputs.type === 41 && + (inputs.vertex_key_type || 'json') === 'json' ? ( + <> + {!batch && ( +
    + + {t('密钥输入方式')} + + + + + +
    + )} + + {batch && ( + + )} + + {useManualInput && !batch ? ( + + handleInputChange('key', value) + } + extraText={ +
    + + {t('请输入完整的 JSON 格式密钥内容')} + + {isEdit && + isMultiKeyChannel && + keyMode === 'append' && ( + + {t( + '追加模式:新密钥将添加到现有密钥列表的末尾', + )} + + )} + {isEdit && ( + + )} + {batchExtra} +
    + } + autosize + showClear + /> + ) : ( + } + dragMainText={t('点击上传文件或拖拽文件到这里')} + dragSubText={t('仅支持 JSON 文件')} + style={{ marginTop: 10 }} + uploadTrigger='custom' + beforeUpload={() => false} + onChange={handleVertexUploadChange} + fileList={vertexFileList} + rules={ + isEdit + ? [] + : [ + { + required: true, + message: t('请上传密钥文件'), + }, + ] + } + extraText={batchExtra} + /> + )} + + ) : ( + + handleInputChange('key', value) + } + extraText={ +
    + {isEdit && + isMultiKeyChannel && + keyMode === 'append' && ( + + {t( + '追加模式:新密钥将添加到现有密钥列表的末尾', + )} + + )} + {isEdit && ( + + )} + {batchExtra} +
    + } + showClear + /> + )} + + )} + + {isEdit && isMultiKeyChannel && ( + setKeyMode(value)} + extraText={ + + {keyMode === 'replace' + ? t('覆盖模式:将完全替换现有的所有密钥') + : t('追加模式:将新密钥添加到现有密钥列表末尾')} + + } + /> + )} + {batch && multiToSingle && ( + <> + { + setMultiKeyMode(value); + handleInputChange('multi_key_mode', value); + }} + /> + {inputs.multi_key_mode === 'polling' && ( + + )} + + )} + + {inputs.type === 18 && ( + handleInputChange('other', value)} + showClear + /> + )} + + {inputs.type === 41 && ( + handleInputChange('other', value)} + rules={[ + { required: true, message: t('请填写部署地区') }, + ]} + template={REGION_EXAMPLE} + templateLabel={t('填入模板')} + editorType='region' + formApi={formApiRef.current} + extraText={t('设置默认地区和特定模型的专用地区')} + /> + )} + + {inputs.type === 21 && ( + handleInputChange('other', value)} + showClear + /> + )} + + {inputs.type === 39 && ( + handleInputChange('other', value)} + showClear + /> + )} + + {inputs.type === 49 && ( + handleInputChange('other', value)} + showClear + /> + )} + + {inputs.type === 1 && ( + + handleInputChange('openai_organization', value) + } + /> + )} + + {/* API Configuration Section */} + {showApiConfigCard && ( +
    + + {inputs.type === 40 && ( + + {t('邀请链接')}: + + window.open( + 'https://cloud.siliconflow.cn/i/hij0YNTZ', + ) + } + > + https://cloud.siliconflow.cn/i/hij0YNTZ + +
    + } + className='!rounded-lg' + /> + )} + + {inputs.type === 3 && ( + <> + +
    + + handleInputChange('base_url', value) + } + showClear + disabled={isIonetLocked} + /> +
    +
    + + handleInputChange('other', value) + } + showClear + /> +
    +
    + + handleChannelOtherSettingsChange( + 'azure_responses_version', + value, + ) + } + showClear + /> +
    + + )} + + {inputs.type === 8 && ( + <> + +
    + + handleInputChange('base_url', value) + } + showClear + disabled={isIonetLocked} + /> +
    + + )} + + {inputs.type === 37 && ( + + )} + + {inputs.type !== 3 && + inputs.type !== 8 && + inputs.type !== 22 && + inputs.type !== 36 && + (inputs.type !== 45 || doubaoApiEditUnlocked) && ( +
    + + handleInputChange('base_url', value) + } + showClear + disabled={isIonetLocked} + extraText={t( + '对于官方渠道,new-api已经内置地址,除非是第三方代理站点或者Azure的特殊接入地址,否则不需要填写', + )} + /> +
    + )} + + {inputs.type === 22 && ( +
    + + handleInputChange('base_url', value) + } + showClear + disabled={isIonetLocked} + /> +
    + )} + + {inputs.type === 36 && ( +
    + + handleInputChange('base_url', value) + } + showClear + disabled={isIonetLocked} + /> +
    + )} + + {inputs.type === 45 && !doubaoApiEditUnlocked && ( +
    + + handleInputChange('base_url', value) + } + optionList={[ + { + value: 'https://ark.cn-beijing.volces.com', + label: 'https://ark.cn-beijing.volces.com', + }, + { + value: + 'https://ark.ap-southeast.bytepluses.com', + label: + 'https://ark.ap-southeast.bytepluses.com', + }, + { + value: DEPRECATED_DOUBAO_CODING_PLAN_BASE_URL, + label: doubaoCodingPlanOptionLabel, + disabled: !canKeepDeprecatedDoubaoCodingPlan, + }, + ]} + defaultValue='https://ark.cn-beijing.volces.com' + disabled={isIonetLocked} + /> +
    + )} + + )} + + {/* Model Selection - Part of Core Config */} + setModelSearchValue(value)} + innerBottomSlot={ + modelSearchHintText ? ( + + {modelSearchHintText} + + ) : null + } + style={{ width: '100%' }} + onChange={(value) => handleInputChange('models', value)} + renderSelectedItem={(optionNode) => { + const modelName = String(optionNode?.value ?? ''); + return { + isRenderInTag: true, + content: ( + { + e.stopPropagation(); + const ok = await copy(modelName); + if (ok) { + showSuccess( + t('已复制:{{name}}', { name: modelName }), + ); + } else { + showError(t('复制失败')); + } + }} + > + {optionNode.label || modelName} + + ), + }; + }} + extraText={ + + + {MODEL_FETCHABLE_CHANNEL_TYPES.has(inputs.type) && ( + + )} + handleInputChange('models', fullModels) }, + ...(inputs.type === 4 && isEdit ? [{ node: 'item', name: t('Ollama 模型管理'), onClick: () => setOllamaModalVisible(true) }] : []), + { node: 'divider' }, + { node: 'item', name: t('复制所有模型'), onClick: () => { + if (inputs.models.length === 0) { showInfo(t('没有模型可以复制')); return; } + try { copy(inputs.models.join(',')); showSuccess(t('模型列表已复制到剪贴板')); } catch (error) { showError(t('复制失败')); } + }}, + { node: 'item', name: t('清除所有模型'), type: 'danger', onClick: () => handleInputChange('models', []) }, + ...((modelGroups && modelGroups.length > 0) ? [ + { node: 'divider' }, + ...modelGroups.map((group) => ({ + node: 'item', + name: group.name, + onClick: () => { + let items = []; + try { + if (Array.isArray(group.items)) { items = group.items; } + else if (typeof group.items === 'string') { + const parsed = JSON.parse(group.items || '[]'); + if (Array.isArray(parsed)) items = parsed; + } + } catch {} + const current = formApiRef.current?.getValue('models') || inputs.models || []; + const merged = Array.from(new Set([...current, ...items].map((m) => (m || '').trim()).filter(Boolean))); + handleInputChange('models', merged); + }, + })), + ] : []), + ]} + > + + + + } + /> + + {/* Custom Model Name - Core Config */} + setCustomModel(value.trim())} + value={customModel} + suffix={ + + } + /> + + {/* Groups - Core Config */} + handleInputChange('groups', value)} + /> + + {/* Model Mapping - Core Config */} + + handleInputChange('model_mapping', value) + } + template={MODEL_MAPPING_EXAMPLE} + templateLabel={t('填入模板')} + editorType='keyValue' + formApi={formApiRef.current} + renderStringValueSuffix={({ pairKey, value }) => { + if (!MODEL_FETCHABLE_CHANNEL_TYPES.has(inputs.type)) { + return null; + } + const disabled = !String(pairKey ?? '').trim(); + return ( + + + } + width={700} + style={{ maxWidth: '90vw' }} + > + + + + setParamOverrideEditorVisible(false)} + onSave={(nextValue) => { + handleInputChange('param_override', nextValue); + setParamOverrideEditorVisible(false); + }} + /> + + { + handleInputChange('models', selectedModels); + showSuccess(t('模型列表已更新')); + setModelModalVisible(false); + }} + onCancel={() => setModelModalVisible(false)} + /> + + { + const modelName = String(selectedModel ?? '').trim(); + if (!modelName) { + showError(t('请先选择模型!')); + return; + } + + const mappingKey = String(modelMappingValueKey ?? '').trim(); + if (!mappingKey) { + setModelMappingValueModalVisible(false); + return; + } + + let parsed = {}; + const currentMapping = inputs.model_mapping; + if (typeof currentMapping === 'string' && currentMapping.trim()) { + try { + parsed = JSON.parse(currentMapping); + } catch (error) { + parsed = {}; + } + } else if ( + currentMapping && + typeof currentMapping === 'object' && + !Array.isArray(currentMapping) + ) { + parsed = currentMapping; + } + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + parsed = {}; + } + + parsed[mappingKey] = modelName; + const nextMapping = JSON.stringify(parsed, null, 2); + handleInputChange('model_mapping', nextMapping); + if (formApiRef.current) { + formApiRef.current.setValue('model_mapping', nextMapping); + } + setModelMappingValueModalVisible(false); + }} + onCancel={() => setModelMappingValueModalVisible(false)} + /> + + setOllamaModalVisible(false)} + channelId={channelId} + channelInfo={inputs} + onModelsUpdate={(options = {}) => { + // 当模型更新后,重新获取模型列表以更新表单 + fetchUpstreamModelList('models', { silent: !!options.silent }); + }} + onApplyModels={({ mode, modelIds } = {}) => { + if (!Array.isArray(modelIds) || modelIds.length === 0) { + return; + } + const existingModels = Array.isArray(inputs.models) + ? inputs.models.map(String) + : []; + const incoming = modelIds.map(String); + const nextModels = Array.from( + new Set([...existingModels, ...incoming]), + ); + + handleInputChange('models', nextModels); + if (formApiRef.current) { + formApiRef.current.setValue('models', nextModels); + } + showSuccess(t('模型列表已追加更新')); + }} + /> + + ); +}; + +export default EditChannelModal; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/table/model-deployments/DeploymentsTable.jsx b/_all-in-one-upload/new-api/web/classic/src/components/table/model-deployments/DeploymentsTable.jsx new file mode 100644 index 0000000..7a7eb98 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/table/model-deployments/DeploymentsTable.jsx @@ -0,0 +1,247 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React, { useMemo, useState } from 'react'; +import { Empty } from '@douyinfe/semi-ui'; +import CardTable from '../../common/ui/CardTable'; +import { + IllustrationNoResult, + IllustrationNoResultDark, +} from '@douyinfe/semi-illustrations'; +import { getDeploymentsColumns } from './DeploymentsColumnDefs'; + +// Import all the new modals +import ViewLogsModal from './modals/ViewLogsModal'; +import ExtendDurationModal from './modals/ExtendDurationModal'; +import ViewDetailsModal from './modals/ViewDetailsModal'; +import UpdateConfigModal from './modals/UpdateConfigModal'; +import ConfirmationDialog from './modals/ConfirmationDialog'; + +const DeploymentsTable = (deploymentsData) => { + const { + deployments, + loading, + searching, + activePage, + pageSize, + deploymentCount, + compactMode, + visibleColumns, + rowSelection, + batchOperationsEnabled = true, + handlePageChange, + handlePageSizeChange, + handleRow, + t, + COLUMN_KEYS, + // Column functions and data + startDeployment, + restartDeployment, + deleteDeployment, + syncDeploymentToChannel, + setEditingDeployment, + setShowEdit, + refresh, + } = deploymentsData; + + // Modal states + const [selectedDeployment, setSelectedDeployment] = useState(null); + const [showLogsModal, setShowLogsModal] = useState(false); + const [showExtendModal, setShowExtendModal] = useState(false); + const [showDetailsModal, setShowDetailsModal] = useState(false); + const [showConfigModal, setShowConfigModal] = useState(false); + const [showConfirmDialog, setShowConfirmDialog] = useState(false); + const [confirmOperation, setConfirmOperation] = useState('delete'); + + // Enhanced modal handlers + const handleViewLogs = (deployment) => { + setSelectedDeployment(deployment); + setShowLogsModal(true); + }; + + const handleExtendDuration = (deployment) => { + setSelectedDeployment(deployment); + setShowExtendModal(true); + }; + + const handleViewDetails = (deployment) => { + setSelectedDeployment(deployment); + setShowDetailsModal(true); + }; + + const handleUpdateConfig = (deployment, operation = 'update') => { + setSelectedDeployment(deployment); + if (operation === 'delete' || operation === 'destroy') { + setConfirmOperation(operation); + setShowConfirmDialog(true); + } else { + setShowConfigModal(true); + } + }; + + const handleConfirmAction = () => { + if ( + selectedDeployment && + (confirmOperation === 'delete' || confirmOperation === 'destroy') + ) { + deleteDeployment(selectedDeployment.id); + } + setShowConfirmDialog(false); + setSelectedDeployment(null); + }; + + const handleModalSuccess = (updatedDeployment) => { + // Refresh the deployments list + refresh?.(); + }; + + // Get all columns + const allColumns = useMemo(() => { + return getDeploymentsColumns({ + t, + COLUMN_KEYS, + startDeployment, + restartDeployment, + deleteDeployment, + setEditingDeployment, + setShowEdit, + refresh, + activePage, + deployments, + // Enhanced handlers + onViewLogs: handleViewLogs, + onExtendDuration: handleExtendDuration, + onViewDetails: handleViewDetails, + onUpdateConfig: handleUpdateConfig, + onSyncToChannel: syncDeploymentToChannel, + }); + }, [ + t, + COLUMN_KEYS, + startDeployment, + restartDeployment, + deleteDeployment, + syncDeploymentToChannel, + setEditingDeployment, + setShowEdit, + refresh, + activePage, + deployments, + ]); + + // Filter columns based on visibility settings + const getVisibleColumns = () => { + return allColumns.filter((column) => visibleColumns[column.key]); + }; + + const visibleColumnsList = useMemo(() => { + return getVisibleColumns(); + }, [visibleColumns, allColumns]); + + const tableColumns = useMemo(() => { + if (compactMode) { + // In compact mode, remove fixed columns and adjust widths + return visibleColumnsList.map(({ fixed, width, ...rest }) => ({ + ...rest, + width: width ? Math.max(width * 0.8, 80) : undefined, // Reduce width by 20% but keep minimum + })); + } + return visibleColumnsList; + }, [compactMode, visibleColumnsList]); + + return ( + <> + } + darkModeImage={ + + } + description={t('搜索无结果')} + style={{ padding: 30 }} + /> + } + className='rounded-xl overflow-hidden' + size='middle' + loading={loading || searching} + /> + + {/* Enhanced Modals */} + setShowLogsModal(false)} + deployment={selectedDeployment} + t={t} + /> + + setShowExtendModal(false)} + deployment={selectedDeployment} + onSuccess={handleModalSuccess} + t={t} + /> + + setShowDetailsModal(false)} + deployment={selectedDeployment} + t={t} + /> + + setShowConfigModal(false)} + deployment={selectedDeployment} + onSuccess={handleModalSuccess} + t={t} + /> + + setShowConfirmDialog(false)} + onConfirm={handleConfirmAction} + title={t('确认操作')} + type='danger' + deployment={selectedDeployment} + operation={confirmOperation} + t={t} + /> + + ); +}; + +export default DeploymentsTable; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/filter/PricingTags.jsx b/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/filter/PricingTags.jsx new file mode 100644 index 0000000..4dee913 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/filter/PricingTags.jsx @@ -0,0 +1,109 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React from 'react'; +import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup'; + +/** + * 模型标签筛选组件 + * @param {string|'all'} filterTag 当前选中的标签 + * @param {Function} setFilterTag setter + * @param {Array} models 当前过滤后模型列表(用于计数) + * @param {Array} allModels 所有模型列表(用于获取所有标签) + * @param {boolean} loading 是否加载中 + * @param {Function} t i18n + */ +const PricingTags = ({ + filterTag, + setFilterTag, + models = [], + allModels = [], + loading = false, + t, +}) => { + // 提取系统所有标签 + const getAllTags = React.useMemo(() => { + const tagSet = new Set(); + + (allModels.length > 0 ? allModels : models).forEach((model) => { + if (model.tags) { + model.tags + .split(/[,;|]+/) // 逗号、分号或竖线(保留空格,允许多词标签如 "open weights") + .map((tag) => tag.trim()) + .filter(Boolean) + .forEach((tag) => tagSet.add(tag.toLowerCase())); + } + }); + + return Array.from(tagSet).sort((a, b) => a.localeCompare(b)); + }, [allModels, models]); + + // 计算标签对应的模型数量 + const getTagCount = React.useCallback( + (tag) => { + if (tag === 'all') return models.length; + + const tagLower = tag.toLowerCase(); + return models.filter((model) => { + if (!model.tags) return false; + return model.tags + .toLowerCase() + .split(/[,;|]+/) + .map((tg) => tg.trim()) + .includes(tagLower); + }).length; + }, + [models], + ); + + const items = React.useMemo(() => { + const result = [ + { + value: 'all', + label: t('全部标签'), + tagCount: getTagCount('all'), + }, + ]; + + getAllTags.forEach((tag) => { + const count = getTagCount(tag); + result.push({ + value: tag, + label: tag, + tagCount: count, + }); + }); + + return result; + }, [getAllTags, getTagCount, t, models.length]); + + return ( + + ); +}; + +export default PricingTags; diff --git a/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/modal/ModelDetailSideSheet.jsx b/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/modal/ModelDetailSideSheet.jsx new file mode 100644 index 0000000..f187339 --- /dev/null +++ b/_all-in-one-upload/new-api/web/classic/src/components/table/model-pricing/modal/ModelDetailSideSheet.jsx @@ -0,0 +1,132 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +import React from 'react'; +import { SideSheet, Typography, Button, Divider } from '@douyinfe/semi-ui'; +import { IconClose } from '@douyinfe/semi-icons'; + +import { useIsMobile } from '../../../../hooks/common/useIsMobile'; +import ModelHeader from './components/ModelHeader'; +import ModelBasicInfo from './components/ModelBasicInfo'; +import ModelEndpoints from './components/ModelEndpoints'; +import ModelPricingTable from './components/ModelPricingTable'; +import DynamicPricingBreakdown from './components/DynamicPricingBreakdown'; + +const { Text } = Typography; + +const ModelDetailSideSheet = ({ + visible, + onClose, + modelData, + groupRatio, + currency, + siteDisplayType, + tokenUnit, + displayPrice, + showRatio, + usableGroup, + vendorsMap, + endpointMap, + autoGroups, + t, +}) => { + const isMobile = useIsMobile(); + + return ( + + } + bodyStyle={{ + padding: '0', + display: 'flex', + flexDirection: 'column', + borderBottom: '1px solid var(--semi-color-border)', + }} + visible={visible} + width={isMobile ? '100%' : 600} + closeIcon={ + + ) : ( + + )} + + + + + + + + ); + }, + }, + ]; + }, [t, planTitleMap]); + + return ( + + + {t('管理')} + + + {t('用户订阅管理')} + + + {user?.username || '-'} (ID: {user?.id || '-'}) + + + } + > +
    + {/* 顶部操作栏:新增订阅 */} +
    +
    + + ) +} + +function InputGroupTextarea({ + className, + ...props +}: React.ComponentProps<'textarea'>) { + return ( +

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%0DT^L_=`4IB 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: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