From 28781ff5378c8e9dedc750c04316eadf39a858d5 Mon Sep 17 00:00:00 2001 From: ktmage Date: Fri, 8 May 2026 23:03:32 +0900 Subject: [PATCH 01/25] topic From 54bf54bfa7312b89a66c50a05bb17e0cdeab55cb Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 12:03:38 +0900 Subject: [PATCH 02/25] =?UTF-8?q?=E3=83=87=E3=82=A3=E3=83=AC=E3=82=AF?= =?UTF-8?q?=E3=83=88=E3=83=AA=E6=A7=8B=E9=80=A0=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 20 +- .github/workflows/test.yml | 10 +- .gitignore | 7 +- .npmrc | 1 - .vscode/launch.json | 4 +- .../vscode/.vscodeignore => .vscodeignore | 1 - README.md | 144 +- .../vscode/config.json => config.json | 0 docs/architecture.md | 372 +- .../vscode/esbuild.mjs => esbuild.mjs | 3 + .../platforms/vscode/media => media}/demo.gif | Bin .../platforms/vscode/media => media}/icon.png | Bin .../vscode/media => media}/icon_full.png | Bin package-lock.json | 7063 ++++++++++++++++- package.json | 95 +- ...package.nls.es.json => package.nls.es.json | 0 ...package.nls.ja.json => package.nls.ja.json | 0 .../package.nls.json => package.nls.json | 0 ...package.nls.ko.json => package.nls.ko.json | 0 ...e.nls.pt-br.json => package.nls.pt-br.json | 0 ...package.nls.ru.json => package.nls.ru.json | 0 ...e.nls.zh-cn.json => package.nls.zh-cn.json | 0 ...e.nls.zh-tw.json => package.nls.zh-tw.json | 0 packages/agents/opencode/package.json | 24 - packages/agents/opencode/src/index.ts | 4 - packages/agents/opencode/tsconfig.json | 20 - packages/agents/opencode/vitest.config.ts | 7 - packages/core/package.json | 17 - packages/core/src/agent.interface.ts | 136 - packages/core/src/index.ts | 6 - packages/core/src/platform.interface.ts | 58 - packages/core/tsconfig.json | 20 - packages/platforms/vscode/README.md | 156 - packages/platforms/vscode/package.json | 101 - pnpm-lock.yaml | 4445 ----------- pnpm-workspace.yaml | 6 - .../__tests__/chat-view-provider.test.ts | 64 +- .../__tests__/diff-review-manager.test.ts | 0 .../src => src}/__tests__/extension.test.ts | 2 +- .../src => src}/__tests__/mappers.test.ts | 0 .../src => src}/__tests__/mocks/vscode.ts | 0 .../__tests__/opencode-agent.test.ts | 24 - .../vscode/src => src}/__tests__/setup.ts | 0 .../vscode/src => src}/chat-view-provider.ts | 15 +- .../vscode/src => src}/diff-review-manager.ts | 2 +- .../platforms/vscode/src => src}/extension.ts | 2 +- .../agents/opencode/src => src}/mappers.ts | 8 +- .../opencode/src => src}/opencode-agent.ts | 37 +- {packages/core/src => src/shared}/domain.ts | 2 +- src/shared/index.ts | 4 + {packages/core/src => src/shared}/protocol.ts | 9 +- .../src => src}/vscode-platform-services.ts | 11 +- .../platforms/vscode => src}/webview/App.tsx | 2 +- .../components/atoms/ActionButton.test.tsx | 0 .../components/atoms/IconButton.test.tsx | 0 .../components/atoms/LinkButton.test.tsx | 0 .../components/atoms/ListItem.test.tsx | 0 .../components/atoms/Popover.test.tsx | 0 .../components/atoms/StatusItem.test.tsx | 0 .../atoms/StreamingIndicator.test.tsx | 0 .../components/atoms/file-type-icons.test.tsx | 0 .../__tests__/components/atoms/icons.test.tsx | 0 .../components/molecules/AgentPopup.test.tsx | 0 .../components/molecules/DiffView.test.tsx | 0 .../components/molecules/EmptyState.test.tsx | 0 .../molecules/FileAttachmentBar.test.tsx | 0 .../molecules/FileChangesHeader.test.tsx | 2 +- .../molecules/FileCreateView.test.tsx | 0 .../molecules/HashFilePopup.test.tsx | 0 .../molecules/ModelSelector.test.tsx | 0 .../molecules/ShellResultView.test.tsx | 0 .../components/molecules/SkillPopup.test.tsx | 0 .../molecules/TextPartView.test.tsx | 0 .../components/molecules/TodoHeader.test.tsx | 0 .../components/molecules/TodoView.test.tsx | 0 .../components/organisms/ChatHeader.test.tsx | 0 .../components/organisms/MessageItem.test.tsx | 0 .../organisms/MessagesArea.test.tsx | 0 .../organisms/PermissionView.test.tsx | 0 .../organisms/QuestionView.test.tsx | 2 +- .../components/organisms/SessionList.test.tsx | 0 .../organisms/SubtaskPartView.test.tsx | 0 .../organisms/ToolConfigPanel.test.tsx | 0 .../organisms/ToolPartView.test.tsx | 0 .../webview/__tests__/factories.ts | 10 +- .../webview/__tests__/helpers.tsx | 0 .../__tests__/hooks/useAutoScroll.test.ts | 0 .../__tests__/hooks/useClickOutside.test.ts | 0 .../__tests__/hooks/useFileChanges.test.ts | 2 +- .../__tests__/hooks/useInputHistory.test.ts | 0 .../webview/__tests__/hooks/useLocale.test.ts | 0 .../__tests__/hooks/useMessages.test.ts | 2 +- .../__tests__/hooks/usePermissions.test.ts | 2 +- .../__tests__/hooks/useProviders.test.ts | 0 .../__tests__/hooks/useQuestions.test.ts | 2 +- .../__tests__/hooks/useSession.test.ts | 2 +- .../hooks/useSoundNotification.test.ts | 2 +- .../scenarios/01-initialization.test.tsx | 0 .../scenarios/02-session-lifecycle.test.tsx | 0 .../__tests__/scenarios/03-messaging.test.tsx | 0 .../scenarios/04-message-editing.test.tsx | 0 .../scenarios/05-permissions.test.tsx | 0 .../scenarios/06-model-selection.test.tsx | 0 .../scenarios/07-file-context.test.tsx | 0 .../__tests__/scenarios/09-settings.test.tsx | 0 .../scenarios/10-tool-display.test.tsx | 0 .../__tests__/scenarios/11-todo.test.tsx | 0 .../scenarios/12-reasoning-display.test.tsx | 0 .../scenarios/13-keyboard-ime.test.tsx | 0 .../scenarios/14-shell-command.test.tsx | 0 .../scenarios/15-file-changes.test.tsx | 0 .../scenarios/16-session-fork.test.tsx | 0 .../scenarios/17-child-session-nav.test.tsx | 0 .../scenarios/18-agent-mention.test.tsx | 0 .../scenarios/19-session-share.test.tsx | 0 .../__tests__/scenarios/20-undo-redo.test.tsx | 0 .../scenarios/21-popup-tab-select.test.tsx | 0 .../22-auto-scroll-streaming.test.tsx | 0 .../scenarios/23-clip-context-menu.test.tsx | 0 .../scenarios/24-input-history.test.tsx | 0 .../scenarios/25-diff-review.test.tsx | 0 .../scenarios/25-sound-notification.test.tsx | 0 .../vscode => src}/webview/__tests__/setup.ts | 2 +- .../webview/__tests__/utils/diff.test.ts | 0 .../__tests__/utils/file-icons.test.ts | 0 .../webview/__tests__/utils/markdown.test.ts | 0 .../webview/__tests__/utils/todo.test.ts | 0 .../__tests__/utils/tool-categories.test.ts | 0 .../webview/bridges/VscodeBridge.ts | 2 +- .../ActionButton/ActionButton.module.css | 0 .../atoms/ActionButton/ActionButton.tsx | 0 .../components/atoms/ActionButton/index.ts | 0 .../atoms/IconButton/IconButton.module.css | 0 .../atoms/IconButton/IconButton.tsx | 0 .../components/atoms/IconButton/index.ts | 0 .../atoms/LinkButton/LinkButton.module.css | 0 .../atoms/LinkButton/LinkButton.tsx | 0 .../components/atoms/LinkButton/index.ts | 0 .../atoms/ListItem/ListItem.module.css | 0 .../components/atoms/ListItem/ListItem.tsx | 0 .../components/atoms/ListItem/index.ts | 0 .../atoms/Popover/Popover.module.css | 0 .../components/atoms/Popover/Popover.tsx | 0 .../webview/components/atoms/Popover/index.ts | 0 .../ScrollToBottomButton.module.css | 0 .../ScrollToBottomButton.tsx | 0 .../atoms/ScrollToBottomButton/index.ts | 0 .../atoms/StatusItem/StatusItem.module.css | 0 .../atoms/StatusItem/StatusItem.tsx | 0 .../components/atoms/StatusItem/index.ts | 0 .../StreamingIndicator.module.css | 0 .../StreamingIndicator/StreamingIndicator.tsx | 0 .../atoms/StreamingIndicator/index.ts | 0 .../icons/file-type-icons/file-type-icons.tsx | 0 .../atoms/icons/file-type-icons/index.ts | 0 .../webview/components/atoms/icons/icons.tsx | 0 .../webview/components/atoms/icons/index.ts | 0 .../AgentPopup/AgentPopup.module.css | 0 .../molecules/AgentPopup/AgentPopup.tsx | 2 +- .../components/molecules/AgentPopup/index.ts | 0 .../AgentSelector/AgentSelector.module.css | 0 .../molecules/AgentSelector/AgentSelector.tsx | 2 +- .../molecules/AgentSelector/index.ts | 0 .../molecules/DiffView/DiffView.module.css | 0 .../molecules/DiffView/DiffView.tsx | 0 .../components/molecules/DiffView/index.ts | 0 .../EmptyState/EmptyState.module.css | 0 .../molecules/EmptyState/EmptyState.tsx | 0 .../components/molecules/EmptyState/index.ts | 0 .../FileAttachmentBar.module.css | 0 .../FileAttachmentBar/FileAttachmentBar.tsx | 2 +- .../molecules/FileAttachmentBar/index.ts | 0 .../FileChangesHeader.module.css | 0 .../FileChangesHeader/FileChangesHeader.tsx | 2 +- .../molecules/FileChangesHeader/index.ts | 0 .../FileCreateView/FileCreateView.tsx | 0 .../molecules/FileCreateView/index.ts | 0 .../HashFilePopup/HashFilePopup.module.css | 0 .../molecules/HashFilePopup/HashFilePopup.tsx | 0 .../molecules/HashFilePopup/index.ts | 0 .../ModelSelector/ModelSelector.module.css | 0 .../molecules/ModelSelector/ModelSelector.tsx | 2 +- .../molecules/ModelSelector/index.ts | 0 .../ShellResultView.module.css | 0 .../ShellResultView/ShellResultView.tsx | 2 +- .../molecules/ShellResultView/index.ts | 0 .../SkillPopup/SkillPopup.module.css | 0 .../molecules/SkillPopup/SkillPopup.tsx | 2 +- .../components/molecules/SkillPopup/index.ts | 0 .../molecules/TextPartView/TextPartView.tsx | 2 +- .../molecules/TextPartView/index.ts | 0 .../TodoHeader/TodoHeader.module.css | 0 .../molecules/TodoHeader/TodoHeader.tsx | 2 +- .../components/molecules/TodoHeader/index.ts | 0 .../molecules/TodoView/TodoView.module.css | 0 .../molecules/TodoView/TodoView.tsx | 0 .../components/molecules/TodoView/index.ts | 0 .../ChatHeader/ChatHeader.module.css | 0 .../organisms/ChatHeader/ChatHeader.tsx | 2 +- .../components/organisms/ChatHeader/index.ts | 0 .../organisms/InputArea/InputArea.module.css | 0 .../organisms/InputArea/InputArea.tsx | 9 +- .../components/organisms/InputArea/index.ts | 0 .../MessageItem/MessageItem.module.css | 0 .../organisms/MessageItem/MessageItem.tsx | 2 +- .../components/organisms/MessageItem/index.ts | 0 .../MessagesArea/MessagesArea.module.css | 0 .../organisms/MessagesArea/MessagesArea.tsx | 2 +- .../organisms/MessagesArea/index.ts | 0 .../PermissionView/PermissionView.module.css | 0 .../PermissionView/PermissionView.tsx | 2 +- .../organisms/PermissionView/index.ts | 0 .../QuestionView/QuestionView.module.css | 0 .../organisms/QuestionView/QuestionView.tsx | 2 +- .../organisms/QuestionView/index.ts | 0 .../SessionList/SessionList.module.css | 0 .../organisms/SessionList/SessionList.tsx | 2 +- .../components/organisms/SessionList/index.ts | 0 .../SubtaskPartView.module.css | 0 .../SubtaskPartView/SubtaskPartView.tsx | 2 +- .../organisms/SubtaskPartView/index.ts | 0 .../ToolConfigPanel.module.css | 0 .../ToolConfigPanel/ToolConfigPanel.tsx | 2 +- .../organisms/ToolConfigPanel/index.ts | 0 .../ToolPartView/ToolPartView.module.css | 0 .../organisms/ToolPartView/ToolPartView.tsx | 2 +- .../organisms/ToolPartView/index.ts | 0 .../webview/contexts/AppContext.tsx | 2 +- .../vscode => src}/webview/css-modules.d.ts | 0 .../webview/hooks/useAutoScroll.ts | 0 .../webview/hooks/useClickOutside.ts | 0 .../webview/hooks/useFileChanges.ts | 2 +- .../webview/hooks/useInputHistory.ts | 0 .../vscode => src}/webview/hooks/useLocale.ts | 0 .../webview/hooks/useMessages.ts | 2 +- .../webview/hooks/usePermissions.ts | 2 +- .../webview/hooks/useProviders.ts | 2 +- .../webview/hooks/useQuestions.ts | 2 +- .../webview/hooks/useSession.ts | 2 +- .../webview/hooks/useSoundNotification.ts | 2 +- .../vscode => src}/webview/index.html | 0 .../vscode => src}/webview/locales/en.ts | 0 .../vscode => src}/webview/locales/es.ts | 0 .../vscode => src}/webview/locales/index.ts | 0 .../vscode => src}/webview/locales/ja.ts | 0 .../vscode => src}/webview/locales/ko.ts | 0 .../vscode => src}/webview/locales/pt-br.ts | 0 .../vscode => src}/webview/locales/ru.ts | 0 .../vscode => src}/webview/locales/zh-cn.ts | 0 .../vscode => src}/webview/locales/zh-tw.ts | 0 .../platforms/vscode => src}/webview/main.tsx | 0 .../vscode => src}/webview/styles.css | 0 .../vscode => src}/webview/tsconfig.json | 4 + .../vscode => src}/webview/utils/diff.ts | 0 .../webview/utils/file-icons.ts | 0 .../vscode => src}/webview/utils/markdown.ts | 0 .../vscode => src}/webview/utils/todo.ts | 0 .../webview/utils/tool-categories.ts | 0 .../vscode => src}/webview/vscode-api.ts | 12 +- .../vscode/tsconfig.json => tsconfig.json | 6 +- .../vscode/vite.config.ts => vite.config.ts | 10 +- ...test.config.ext.ts => vitest.config.ext.ts | 3 +- .../vitest.config.ts => vitest.config.ts | 10 +- 263 files changed, 7387 insertions(+), 5651 deletions(-) delete mode 100644 .npmrc rename packages/platforms/vscode/.vscodeignore => .vscodeignore (92%) rename packages/platforms/vscode/config.json => config.json (100%) rename packages/platforms/vscode/esbuild.mjs => esbuild.mjs (91%) rename {packages/platforms/vscode/media => media}/demo.gif (100%) rename {packages/platforms/vscode/media => media}/icon.png (100%) rename {packages/platforms/vscode/media => media}/icon_full.png (100%) rename packages/platforms/vscode/package.nls.es.json => package.nls.es.json (100%) rename packages/platforms/vscode/package.nls.ja.json => package.nls.ja.json (100%) rename packages/platforms/vscode/package.nls.json => package.nls.json (100%) rename packages/platforms/vscode/package.nls.ko.json => package.nls.ko.json (100%) rename packages/platforms/vscode/package.nls.pt-br.json => package.nls.pt-br.json (100%) rename packages/platforms/vscode/package.nls.ru.json => package.nls.ru.json (100%) rename packages/platforms/vscode/package.nls.zh-cn.json => package.nls.zh-cn.json (100%) rename packages/platforms/vscode/package.nls.zh-tw.json => package.nls.zh-tw.json (100%) delete mode 100644 packages/agents/opencode/package.json delete mode 100644 packages/agents/opencode/src/index.ts delete mode 100644 packages/agents/opencode/tsconfig.json delete mode 100644 packages/agents/opencode/vitest.config.ts delete mode 100644 packages/core/package.json delete mode 100644 packages/core/src/agent.interface.ts delete mode 100644 packages/core/src/index.ts delete mode 100644 packages/core/src/platform.interface.ts delete mode 100644 packages/core/tsconfig.json delete mode 100644 packages/platforms/vscode/README.md delete mode 100644 packages/platforms/vscode/package.json delete mode 100644 pnpm-lock.yaml delete mode 100644 pnpm-workspace.yaml rename {packages/platforms/vscode/src => src}/__tests__/chat-view-provider.test.ts (96%) rename {packages/platforms/vscode/src => src}/__tests__/diff-review-manager.test.ts (100%) rename {packages/platforms/vscode/src => src}/__tests__/extension.test.ts (99%) rename {packages/agents/opencode/src => src}/__tests__/mappers.test.ts (100%) rename {packages/platforms/vscode/src => src}/__tests__/mocks/vscode.ts (100%) rename {packages/agents/opencode/src => src}/__tests__/opencode-agent.test.ts (97%) rename {packages/platforms/vscode/src => src}/__tests__/setup.ts (100%) rename {packages/platforms/vscode/src => src}/chat-view-provider.ts (97%) rename {packages/platforms/vscode/src => src}/diff-review-manager.ts (98%) rename {packages/platforms/vscode/src => src}/extension.ts (98%) rename {packages/agents/opencode/src => src}/mappers.ts (95%) rename {packages/agents/opencode/src => src}/opencode-agent.ts (92%) rename {packages/core/src => src/shared}/domain.ts (99%) create mode 100644 src/shared/index.ts rename {packages/core/src => src/shared}/protocol.ts (93%) rename {packages/platforms/vscode/src => src}/vscode-platform-services.ts (90%) rename {packages/platforms/vscode => src}/webview/App.tsx (99%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/ActionButton.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/IconButton.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/LinkButton.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/ListItem.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/Popover.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/StatusItem.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/StreamingIndicator.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/file-type-icons.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/atoms/icons.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/AgentPopup.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/DiffView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/EmptyState.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/FileChangesHeader.test.tsx (99%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/FileCreateView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/HashFilePopup.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/ModelSelector.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/ShellResultView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/SkillPopup.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/TextPartView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/TodoHeader.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/molecules/TodoView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/ChatHeader.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/MessageItem.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/MessagesArea.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/PermissionView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/QuestionView.test.tsx (99%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/SessionList.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/SubtaskPartView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/components/organisms/ToolPartView.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/factories.ts (96%) rename {packages/platforms/vscode => src}/webview/__tests__/helpers.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useAutoScroll.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useClickOutside.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useFileChanges.test.ts (97%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useInputHistory.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useLocale.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useMessages.test.ts (99%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/usePermissions.test.ts (98%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useProviders.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useQuestions.test.ts (98%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useSession.test.ts (99%) rename {packages/platforms/vscode => src}/webview/__tests__/hooks/useSoundNotification.test.ts (99%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/01-initialization.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/02-session-lifecycle.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/03-messaging.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/04-message-editing.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/05-permissions.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/06-model-selection.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/07-file-context.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/09-settings.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/10-tool-display.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/11-todo.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/12-reasoning-display.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/13-keyboard-ime.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/14-shell-command.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/15-file-changes.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/16-session-fork.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/17-child-session-nav.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/18-agent-mention.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/19-session-share.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/20-undo-redo.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/21-popup-tab-select.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/23-clip-context-menu.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/24-input-history.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/25-diff-review.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/scenarios/25-sound-notification.test.tsx (100%) rename {packages/platforms/vscode => src}/webview/__tests__/setup.ts (95%) rename {packages/platforms/vscode => src}/webview/__tests__/utils/diff.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/utils/file-icons.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/utils/markdown.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/utils/todo.test.ts (100%) rename {packages/platforms/vscode => src}/webview/__tests__/utils/tool-categories.test.ts (100%) rename {packages/platforms/vscode => src}/webview/bridges/VscodeBridge.ts (96%) rename {packages/platforms/vscode => src}/webview/components/atoms/ActionButton/ActionButton.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ActionButton/ActionButton.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ActionButton/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/IconButton/IconButton.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/IconButton/IconButton.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/IconButton/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/LinkButton/LinkButton.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/LinkButton/LinkButton.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/LinkButton/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ListItem/ListItem.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ListItem/ListItem.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ListItem/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/Popover/Popover.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/Popover/Popover.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/Popover/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/ScrollToBottomButton/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StatusItem/StatusItem.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StatusItem/StatusItem.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StatusItem/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/StreamingIndicator/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/icons/file-type-icons/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/icons/icons.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/atoms/icons/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentPopup/AgentPopup.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentPopup/AgentPopup.tsx (94%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentPopup/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentSelector/AgentSelector.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentSelector/AgentSelector.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/molecules/AgentSelector/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/DiffView/DiffView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/DiffView/DiffView.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/DiffView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/EmptyState/EmptyState.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/EmptyState/EmptyState.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/EmptyState/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileAttachmentBar/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileChangesHeader/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileCreateView/FileCreateView.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/FileCreateView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/HashFilePopup/HashFilePopup.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/HashFilePopup/HashFilePopup.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/HashFilePopup/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/ModelSelector/ModelSelector.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/ModelSelector/ModelSelector.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/molecules/ModelSelector/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/ShellResultView/ShellResultView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/ShellResultView/ShellResultView.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/molecules/ShellResultView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/SkillPopup/SkillPopup.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/SkillPopup/SkillPopup.tsx (95%) rename {packages/platforms/vscode => src}/webview/components/molecules/SkillPopup/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TextPartView/TextPartView.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/molecules/TextPartView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoHeader/TodoHeader.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoHeader/TodoHeader.tsx (97%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoHeader/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoView/TodoView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoView/TodoView.tsx (100%) rename {packages/platforms/vscode => src}/webview/components/molecules/TodoView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ChatHeader/ChatHeader.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ChatHeader/ChatHeader.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/ChatHeader/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/InputArea/InputArea.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/InputArea/InputArea.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/organisms/InputArea/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessageItem/MessageItem.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessageItem/MessageItem.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessageItem/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessagesArea/MessagesArea.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessagesArea/MessagesArea.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/MessagesArea/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/PermissionView/PermissionView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/PermissionView/PermissionView.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/PermissionView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/QuestionView/QuestionView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/QuestionView/QuestionView.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/QuestionView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/SessionList/SessionList.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/SessionList/SessionList.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/SessionList/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx (98%) rename {packages/platforms/vscode => src}/webview/components/organisms/SubtaskPartView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolConfigPanel/index.ts (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolPartView/ToolPartView.module.css (100%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolPartView/ToolPartView.tsx (99%) rename {packages/platforms/vscode => src}/webview/components/organisms/ToolPartView/index.ts (100%) rename {packages/platforms/vscode => src}/webview/contexts/AppContext.tsx (99%) rename {packages/platforms/vscode => src}/webview/css-modules.d.ts (100%) rename {packages/platforms/vscode => src}/webview/hooks/useAutoScroll.ts (100%) rename {packages/platforms/vscode => src}/webview/hooks/useClickOutside.ts (100%) rename {packages/platforms/vscode => src}/webview/hooks/useFileChanges.ts (92%) rename {packages/platforms/vscode => src}/webview/hooks/useInputHistory.ts (100%) rename {packages/platforms/vscode => src}/webview/hooks/useLocale.ts (100%) rename {packages/platforms/vscode => src}/webview/hooks/useMessages.ts (99%) rename {packages/platforms/vscode => src}/webview/hooks/usePermissions.ts (95%) rename {packages/platforms/vscode => src}/webview/hooks/useProviders.ts (93%) rename {packages/platforms/vscode => src}/webview/hooks/useQuestions.ts (95%) rename {packages/platforms/vscode => src}/webview/hooks/useSession.ts (96%) rename {packages/platforms/vscode => src}/webview/hooks/useSoundNotification.ts (99%) rename {packages/platforms/vscode => src}/webview/index.html (100%) rename {packages/platforms/vscode => src}/webview/locales/en.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/es.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/index.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/ja.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/ko.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/pt-br.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/ru.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/zh-cn.ts (100%) rename {packages/platforms/vscode => src}/webview/locales/zh-tw.ts (100%) rename {packages/platforms/vscode => src}/webview/main.tsx (100%) rename {packages/platforms/vscode => src}/webview/styles.css (100%) rename {packages/platforms/vscode => src}/webview/tsconfig.json (81%) rename {packages/platforms/vscode => src}/webview/utils/diff.ts (100%) rename {packages/platforms/vscode => src}/webview/utils/file-icons.ts (100%) rename {packages/platforms/vscode => src}/webview/utils/markdown.ts (100%) rename {packages/platforms/vscode => src}/webview/utils/todo.ts (100%) rename {packages/platforms/vscode => src}/webview/utils/tool-categories.ts (100%) rename {packages/platforms/vscode => src}/webview/vscode-api.ts (76%) rename packages/platforms/vscode/tsconfig.json => tsconfig.json (74%) rename packages/platforms/vscode/vite.config.ts => vite.config.ts (73%) rename packages/platforms/vscode/vitest.config.ext.ts => vitest.config.ext.ts (62%) rename packages/platforms/vscode/vitest.config.ts => vitest.config.ts (59%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d09fbf..15b2d04 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,32 +18,24 @@ jobs: with: node-version: 22 - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Install dependencies - run: pnpm install + run: npm ci - name: Build - run: pnpm build + run: npm run build - name: Test - run: pnpm test:all - - - name: Copy root files for extension packaging - run: cp LICENSE CHANGELOG.md THIRD_PARTY_NOTICES.md packages/platforms/vscode/ + run: npm run test:all - name: Package extension - run: pnpm --filter opencodegui run package - working-directory: . + run: npm run package - name: Publish to Marketplace - run: pnpm --filter opencodegui run publish + run: npm run publish env: VSCE_PAT: ${{ secrets.VSCE_PAT }} - name: Upload .vsix to GitHub Release uses: softprops/action-gh-release@v2 with: - files: packages/platforms/vscode/*.vsix + files: "*.vsix" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e4aa8a6..161c90a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,15 +17,11 @@ jobs: with: node-version: 22 - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Install dependencies - run: pnpm install + run: npm ci - name: Lint & Format check - run: pnpm check + run: npm run check - name: Test - run: pnpm test:all + run: npm run test:all diff --git a/.gitignore b/.gitignore index 0c42119..b871206 100644 --- a/.gitignore +++ b/.gitignore @@ -14,11 +14,6 @@ Thumbs.db # VS Code extension package *.vsix -# Root files copied into extension dir for packaging -packages/platforms/vscode/LICENSE -packages/platforms/vscode/CHANGELOG.md -packages/platforms/vscode/THIRD_PARTY_NOTICES.md - # Environment .env -.env.* \ No newline at end of file +.env.* diff --git a/.npmrc b/.npmrc deleted file mode 100644 index bf2e764..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -shamefully-hoist=true diff --git a/.vscode/launch.json b/.vscode/launch.json index 6531f05..ddf6edc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,8 @@ "name": "Run Extension", "type": "extensionHost", "request": "launch", - "args": ["--extensionDevelopmentPath=${workspaceFolder}/packages/platforms/vscode"], - "outFiles": ["${workspaceFolder}/packages/platforms/vscode/dist/**/*.js"], + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/dist/**/*.js"], "preLaunchTask": "npm: build" } ] diff --git a/packages/platforms/vscode/.vscodeignore b/.vscodeignore similarity index 92% rename from packages/platforms/vscode/.vscodeignore rename to .vscodeignore index a5034f0..32a0f0d 100644 --- a/packages/platforms/vscode/.vscodeignore +++ b/.vscodeignore @@ -1,5 +1,4 @@ src/** -webview/** node_modules/** tsconfig.json vite.config.ts diff --git a/README.md b/README.md index 3e0864d..e9fd7c4 100644 --- a/README.md +++ b/README.md @@ -86,26 +86,26 @@ Search for **OpenCodeGUI** in the VS Code Extensions view (`Ctrl+Shift+X` / `Cmd #### Prerequisites - Node.js v22+ -- [pnpm](https://pnpm.io/) v10+ +- npm #### Setup ```sh -pnpm install -pnpm run build +npm install +npm run build ``` #### Build ```sh -# Full build (all packages) -pnpm run build +# Full build +npm run build -# Extension only (from packages/platforms/vscode) -pnpm --filter opencodegui run build:ext +# Extension only +npm run build:ext -# Webview only (from packages/platforms/vscode) -pnpm --filter opencodegui run build:webview +# Webview only +npm run build:webview ``` #### Watch Mode @@ -114,63 +114,49 @@ Open two terminals and run each: ```sh # Terminal 1: Extension watch -pnpm --filter opencodegui run watch:ext +npm run watch:ext # Terminal 2: Webview watch -pnpm --filter opencodegui run watch:webview +npm run watch:webview ``` #### Lint & Format ```sh -pnpm run check +npm run check ``` #### Debug -1. Run `pnpm run build` +1. Run `npm run build` 2. Press `F5` in VS Code to launch the Extension Development Host 3. Click the OpenCode icon in the sidebar to open the chat panel #### Test ```sh -pnpm test +npm test ``` ### Project Structure -This project is a pnpm monorepo with the following packages: +This project is a single VS Code extension package: ``` -packages/ - core/ # @opencodegui/core — Domain types, interfaces & protocol - src/ - domain.ts # Domain types (messages, sessions, tools, permissions) - agent.interface.ts # IAgent interface - platform.interface.ts # IPlatformServices interface - protocol.ts # Webview ↔ Extension messaging protocol - - agents/ - opencode/ # @opencodegui/agent-opencode — OpenCode SDK adapter - src/ - opencode-agent.ts # IAgent implementation for OpenCode - mappers.ts # SDK ↔ domain type mappers - - platforms/ - vscode/ # opencodegui — VS Code extension - src/ - extension.ts # Extension entry point - chat-view-provider.ts # Webview panel & messaging - vscode-platform-services.ts # IPlatformServices implementation - webview/ # Webview (Browser, React) - App.tsx # State management & SSE event handling - components/ # React components (Atoms / Molecules / Organisms) - hooks/ # Custom React hooks - contexts/ # React Context providers - locales/ # i18n locale files - utils/ # Utility functions - __tests__/ # Tests (unit, scenario) +src/ + extension.ts # Extension entry point + chat-view-provider.ts # Webview panel & messaging + opencode-agent.ts # OpenCode SDK integration + mappers.ts # SDK to UI/domain type mappers + shared/ # Shared types for extension host and webview + webview/ # Webview (React) + App.tsx # State management & SSE event handling + components/ # React components + hooks/ # Custom React hooks + contexts/ # React Context providers + locales/ # i18n locale files + utils/ # Utility functions + __tests__/ # Tests ``` ### Contributing @@ -258,26 +244,26 @@ VS Code の拡張機能ビュー(`Ctrl+Shift+X` / `Cmd+Shift+X`)で **OpenCo #### 前提条件 - Node.js v22+ -- [pnpm](https://pnpm.io/) v10+ +- npm #### セットアップ ```sh -pnpm install -pnpm run build +npm install +npm run build ``` #### ビルド ```sh -# 全体ビルド(全パッケージ) -pnpm run build +# 全体ビルド +npm run build -# Extension のみ(packages/platforms/vscode から) -pnpm --filter opencodegui run build:ext +# Extension のみ +npm run build:ext -# Webview のみ(packages/platforms/vscode から) -pnpm --filter opencodegui run build:webview +# Webview のみ +npm run build:webview ``` #### Watch モード @@ -286,63 +272,49 @@ pnpm --filter opencodegui run build:webview ```sh # Terminal 1: Extension watch -pnpm --filter opencodegui run watch:ext +npm run watch:ext # Terminal 2: Webview watch -pnpm --filter opencodegui run watch:webview +npm run watch:webview ``` #### リント & フォーマット ```sh -pnpm run check +npm run check ``` #### デバッグ実行 -1. `pnpm run build` でビルドする +1. `npm run build` でビルドする 2. VS Code で `F5` を押して Extension Development Host を起動する 3. サイドバーの OpenCode アイコンをクリックしてチャットパネルを開く #### テスト ```sh -pnpm test +npm test ``` ### プロジェクト構造 -本プロジェクトは pnpm モノレポ構成です。 +本プロジェクトは単一の VS Code 拡張パッケージです。 ``` -packages/ - core/ # @opencodegui/core — ドメイン型・インターフェース・プロトコル - src/ - domain.ts # ドメイン型(メッセージ、セッション、ツール、パーミッション) - agent.interface.ts # IAgent インターフェース - platform.interface.ts # IPlatformServices インターフェース - protocol.ts # Webview ↔ Extension メッセージングプロトコル - - agents/ - opencode/ # @opencodegui/agent-opencode — OpenCode SDK アダプター - src/ - opencode-agent.ts # OpenCode 用 IAgent 実装 - mappers.ts # SDK ↔ ドメイン型マッパー - - platforms/ - vscode/ # opencodegui — VS Code 拡張機能 - src/ - extension.ts # 拡張機能エントリーポイント - chat-view-provider.ts # Webview パネル & メッセージング - vscode-platform-services.ts # IPlatformServices 実装 - webview/ # Webview (Browser, React) - App.tsx # 状態管理 & SSE イベントハンドリング - components/ # React コンポーネント(Atoms / Molecules / Organisms) - hooks/ # カスタム React フック - contexts/ # React Context プロバイダー - locales/ # i18n ロケールファイル - utils/ # ユーティリティ関数 - __tests__/ # テスト(単体、シナリオ) +src/ + extension.ts # 拡張機能エントリーポイント + chat-view-provider.ts # Webview パネル & メッセージング + opencode-agent.ts # OpenCode SDK 連携 + mappers.ts # SDK から UI/ドメイン型へのマッパー + shared/ # Extension Host と Webview の共有型 + webview/ # Webview (React) + App.tsx # 状態管理 & SSE イベントハンドリング + components/ # React コンポーネント + hooks/ # カスタム React フック + contexts/ # React Context プロバイダー + locales/ # i18n locale files + utils/ # ユーティリティ関数 + __tests__/ # テスト ``` ### コントリビュート diff --git a/packages/platforms/vscode/config.json b/config.json similarity index 100% rename from packages/platforms/vscode/config.json rename to config.json diff --git a/docs/architecture.md b/docs/architecture.md index 9899b85..ae95808 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,322 +1,50 @@ -# OpenCodeGUI アーキテクチャ - -## 概要 - -OpenCodeGUI は、AI コーディングエージェントと対話するための VS Code 拡張機能を提供するマルチパッケージモノレポです。アーキテクチャは **Core**(共有型定義)、**Agents**(バックエンドアダプター)、**Platforms**(UI + プラットフォーム固有サービス)の3層に関心を分離しています。 - -``` -opencodegui-monorepo/ -├── packages/ -│ ├── core/ @opencodegui/core -│ ├── agents/ -│ │ └── opencode/ @opencodegui/agent-opencode -│ └── platforms/ -│ └── vscode/ @opencodegui/vscode -├── package.json ワークスペースルート -├── pnpm-workspace.yaml pnpm ワークスペース設定 -└── biome.json 共有リンター設定 -``` - -## 依存関係グラフ - -``` -@opencodegui/vscode - ├── @opencodegui/core (ドメイン型、インターフェース、プロトコル) - └── @opencodegui/agent-opencode - └── @opencodegui/core - @opencode-ai/sdk (OpenCode サーバー SDK) -``` - -重要な制約: **vscode パッケージは `@opencode-ai/sdk` を直接インポートしません**。SDK とのやり取りはすべてエージェントパッケージに隠蔽されています。 - ---- - -## パッケージ詳細 - -### `@opencodegui/core` - -依存ゼロの共有コントラクトパッケージ。ランタイムコードなし、型定義のみ。 - -| モジュール | 説明 | -|-----------|------| -| `domain.ts` | ドメイン型: `ChatSession`, `ChatMessage`, `ChatMessageWithParts`, `MessagePart`, `FileDiff`, `ProviderInfo`, `AgentInfo`, `TodoItem` 等 | -| `agent.interface.ts` | `IAgent` インターフェース + `AgentCapabilities` フラグ | -| `platform.interface.ts` | `IBridge`(UI-ホスト間通信)、`IPlatformServices`(プラットフォーム操作) | -| `protocol.ts` | `UIToHostMessage` / `HostToUIMessage` 判別共用体型 | - -### `@opencodegui/agent-opencode` - -`@opencode-ai/sdk` をラップし、`IAgent` を実装するアダプター。 - -| モジュール | 説明 | -|-----------|------| -| `opencode-agent.ts` | `IAgent` を実装する `OpenCodeAgent` クラス — ライフサイクル管理、イベント転送、全エージェント操作 | -| `mappers.ts` | SDK 型 → core ドメイン型への変換関数群 (`mapSession`, `mapMessage`, `mapParts` 等) | - -### `@opencodegui/vscode` - -Extension Host プロセスと React Webview の両方を含む VS Code 拡張機能。 - -| モジュール | レイヤー | 説明 | -|-----------|---------|------| -| `src/extension.ts` | Extension Host | エントリーポイント — `OpenCodeAgent`、`VscodePlatformServices` を作成し `ChatViewProvider` を登録 | -| `src/chat-view-provider.ts` | Extension Host | Webview とエージェント/プラットフォームサービス間のメッセージルーター(28以上のハンドラー) | -| `src/vscode-platform-services.ts` | Extension Host | VS Code API を使用した `IPlatformServices` 実装 | -| `webview/bridges/VscodeBridge.ts` | Webview | `acquireVsCodeApi()` をラップする `IBridge` 実装 | -| `webview/App.tsx` | Webview | ルート React コンポーネント | -| `webview/contexts/` | Webview | React コンテキストプロバイダー | -| `webview/hooks/` | Webview | カスタム React フック | -| `webview/components/` | Webview | UI コンポーネント (atoms / molecules / organisms) | - ---- - -## 主要インターフェース - -### IAgent - -AI コーディングエージェントバックエンドの中心的な抽象化。ケイパビリティ駆動設計により、エージェントがサポートする機能に応じて UI が適応します。 - -```typescript -interface IAgent { - getCapabilities(): AgentCapabilities; - - // ライフサイクル - connect(): Promise; - disconnect(): void; - onEvent(handler: (event: AgentEvent) => void): Disposable; - - // セッション - listSessions(): Promise; - createSession(title?: string): Promise; - getSession(id: string): Promise; - deleteSession(id: string): Promise; - forkSession(sessionId: string, messageId?: string): Promise; - // ... revert, unrevert, summarize, share, unshare - - // メッセージ - getMessages(sessionId: string): Promise; - sendMessage(sessionId: string, text: string, options?: SendMessageOptions): Promise; - abortSession(sessionId: string): Promise; - - // プロバイダーとモデル - getProviders(): Promise<{ providers: ProviderInfo[]; default: Record }>; - - // ツール、設定、MCP 等 - getToolIds(): Promise; - setModel?(model: string): Promise; -} -``` - -### AgentCapabilities - -各エージェント実装が宣言する機能フラグ。UI はこれを読み取って機能の表示/非表示を切り替えます。 - -```typescript -type AgentCapabilities = { - sessionDelete: boolean; // セッション削除 - sessionFork: boolean; // セッション分岐(任意のメッセージからブランチ) - sessionRevert: boolean; // セッション巻き戻し / 巻き戻し解除(Undo / Redo) - sessionShare: boolean; // セッション共有(URL 生成) - sessionSummarize: boolean; // セッション要約 / コンテキスト圧縮 - sessionDiff: boolean; // セッション単位のファイル差分 - todo: boolean; // Todo 管理 - multiProvider: boolean; // マルチプロバイダーモデル選択 - permission: boolean; // パーミッション管理(ツール実行承認フロー) - mcp: boolean; // MCP (Model Context Protocol) サポート - subAgent: boolean; // サブエージェント(子セッション) - shell: boolean; // シェルコマンド実行 - config: boolean; // 設定管理 API -}; -``` - -### IBridge - -Webview(React)とホストプロセス間の通信チャネル。 - -```typescript -interface IBridge { - postMessage(message: UIToHostMessage): void; - onMessage(handler: (message: HostToUIMessage) => void): Disposable; - getPersistedState(): UIPersistedState | null; - setPersistedState(state: UIPersistedState): void; -} -``` - -### IPlatformServices - -Extension Host から抽出されたプラットフォーム固有の操作。 - -```typescript -interface IPlatformServices { - openDiffEditor(filePath: string, before: string, after: string): Promise; - copyToClipboard(text: string): Promise; - openTerminal(serverUrl: string, sessionId?: string): Promise; - openConfigFile(filePath: string): Promise; - searchWorkspaceFiles(query: string): Promise; - getOpenEditors(): Promise; -} -``` - ---- - -## メッセージプロトコル - -Webview と Extension Host 間の通信は型付き判別共用体を使用します。 - -### UI -> Host (`UIToHostMessage`) - -| タイプ | 説明 | -|-------|------| -| `ready` | Webview の初期化完了 | -| `createSession` | 新規チャットセッション作成 | -| `selectSession` | アクティブセッションの切り替え | -| `deleteSession` | セッション削除 | -| `sendMessage` | エージェントへのユーザーメッセージ送信 | -| `abortSession` | 進行中の生成をキャンセル | -| `setModel` | AI モデルの変更 | -| `compressSession` | コンテキストの要約/圧縮 | -| `undoSession` / `redoSession` | セッション状態の Undo/Redo | -| `forkSession` | メッセージからの分岐 | -| `shareSession` / `unshareSession` | セッションの共有/共有解除 | -| `replyPermission` | ツール実行パーミッションへの応答 | -| `openDiff` | Diff ビューアを開く | -| `copyToClipboard` | テキストをクリップボードにコピー | -| `openTerminal` | エージェント用ターミナルを開く | -| `searchFiles` | ワークスペースファイル検索 | -| `getOpenEditors` | 開いているエディタファイルの取得 | -| `openConfig` | 設定ファイルを開く | -| `revertToMessage` | 特定メッセージへの巻き戻し(レガシー) | - -### Host -> UI (`HostToUIMessage`) - -| タイプ | 説明 | -|-------|------| -| `init` | 初期状態(ケイパビリティ、ロケール、パス、ツール) | -| `sessions` | セッション一覧 | -| `session` | 単一セッションの更新 | -| `messages` | セッションのメッセージ群 | -| `event` | リアルタイムエージェントイベント(ストリーミングトークン、ツール呼び出し等) | -| `providers` | 利用可能なモデルプロバイダー | -| `allProviders` | 全プロバイダーデータ | -| `agents` | 利用可能なサブエージェント | -| `childSessions` | 親セッションの子セッション | -| `diff` | セッションのファイル差分 | -| `todos` | セッションの Todo アイテム | -| `mcpStatus` | MCP 接続状態 | -| `toolIds` | 利用可能なツール識別子 | -| `searchResults` | ファイル検索結果 | -| `openEditors` | 現在開いているエディタファイル | -| `activeEditor` | フォーカス中のエディタ変更通知 | - ---- - -## データフロー - -``` -[Webview (React)] - | - | UIToHostMessage (IBridge.postMessage 経由) - v -[ChatViewProvider] -- メッセージルーター (message.type で switch) - | | - | エージェント操作 | プラットフォーム操作 - v v -[IAgent] [IPlatformServices] - | | - v v -[OpenCodeAgent] [VscodePlatformServices] - | | - v v -[@opencode-ai/sdk] [VS Code API] -``` - -### イベントフロー (エージェント -> UI) - -``` -[@opencode-ai/sdk] -- SSE イベント - | - v -[OpenCodeAgent.onEvent()] -- SDK イベントを AgentEvent にマッピング - | - v -[ChatViewProvider] -- 登録済みハンドラー - | - | HostToUIMessage (webview.postMessage 経由) - v -[Webview (React)] -- AppContext がフックにディスパッチ -``` - ---- - -## 拡張機能のライフサイクル - -1. VS Code が拡張機能をアクティベート (`extension.ts:activate`) -2. `OpenCodeAgent` を作成(モジュールスコープのシングルトン) -3. `VscodePlatformServices` を作成 -4. `ChatViewProvider` をエージェントとプラットフォームサービスの両方で登録 -5. Webview パネルが開いた時: - - React アプリがマウントされ、`ready` メッセージを送信 - - `ChatViewProvider` が `ready` を処理: `agent.connect()` を呼び出し、セッションを読み込み、`init` メッセージを送信 - - エージェントが OpenCode サーバー (localhost HTTP) に接続 - - エージェントイベントが `HostToUIMessage` 経由で Webview に転送される - ---- - -## ビルドシステム - -| コンポーネント | ツール | 設定 | -|-------------|-------|------| -| Core 型定義 | TypeScript (tsc) | `packages/core/tsconfig.json` (composite, declaration) | -| Agent-OpenCode | TypeScript (tsc) | `packages/agents/opencode/tsconfig.json` (composite, declaration) | -| Extension Host | esbuild | `packages/platforms/vscode/esbuild.mjs` | -| Webview (React) | Vite | `packages/platforms/vscode/vite.config.ts` | -| リンティング | Biome | `biome.json` (ルート) | - -### ビルド順序 - -``` -pnpm -r build - 1. @opencodegui/core (tsc) - 2. @opencodegui/agent-opencode (tsc、core に依存) - 3. @opencodegui/vscode (esbuild + vite、core + agent に依存) -``` - ---- - -## テスト構造 - -| スイート | ランナー | 設定 | テスト数 | -|---------|---------|------|---------| -| Agent-OpenCode | Vitest | `packages/agents/opencode/vitest.config.ts` | 85 | -| Webview | Vitest + jsdom | `packages/platforms/vscode/vitest.config.ts` | 1475 | -| Extension Host | Vitest | `packages/platforms/vscode/vitest.config.ext.ts` | 54 | -| **合計** | | `pnpm test:all` | **1614** | - -### Extension Host テストの注意点 - -- `vscode` モジュールは `vi.mock("vscode")` で完全にモック化(`src/__tests__/mocks/vscode.ts` 参照) -- モジュールスコープのシングルトン(例: `extension.ts` の `OpenCodeAgent`)はテスト分離のため `vi.resetModules()` + `vi.doMock()` + 動的 `import()` パターンが必要 -- 設定ファイルの読み書きテストでは `node:fs/promises` をモック化 - ---- - -## 新しいエージェントの追加方法 - -新しい AI コーディングエージェント(例: Claude Code, Codex)を追加する場合: - -1. `packages/agents//` を作成 -2. 適切な `AgentCapabilities` で `IAgent` インターフェースを実装 -3. エージェントの SDK 型から core ドメイン型へのマッパー関数を作成 -4. vscode パッケージの依存に `@opencodegui/agent-: workspace:*` を追加 -5. `extension.ts` を更新して新しいエージェントを作成(またはエージェント選択ロジックを追加) -6. UI は `AgentCapabilities` フラグにより自動的に適応 - -## 新しいプラットフォームの追加方法 - -新しいプラットフォーム(例: Electron, Web)を追加する場合: - -1. `packages/platforms//` を作成 -2. プラットフォームの UI-ホスト間通信用に `IBridge` を実装 -3. プラットフォーム固有の操作用に `IPlatformServices` を実装 -4. メッセージルーター(`ChatViewProvider` 相当)で `IAgent` と `IPlatformServices` を接続 -5. Webview の React コードは core プロトコル型を通じて共有可能 +# Architecture + +OpenCodeGUI is a single VS Code extension package. The extension host starts an +OpenCode server through `@opencode-ai/sdk`, forwards SDK events to the webview, +and handles VS Code-specific operations such as opening files, terminals, and +diff editors. + +## Structure + +``` +src/ + extension.ts VS Code activation entry point + chat-view-provider.ts Webview message router + opencode-agent.ts OpenCode SDK lifecycle and API calls + mappers.ts SDK type to UI/domain type mapping + vscode-platform-services.ts + VS Code API helpers + shared/ + domain.ts Shared session/message/tool/config types + protocol.ts Webview <-> extension host messages + webview/ + App.tsx React state and event handling + components/ UI components + hooks/ React hooks + contexts/ React contexts + locales/ Localization dictionaries + utils/ UI utilities + __tests__/ Webview tests +``` + +## Data Flow + +1. `extension.ts` creates `OpenCodeAgent` and calls `connect()`. +2. `OpenCodeAgent` starts the OpenCode server, creates the SDK client, and + subscribes to SDK events. +3. `ChatViewProvider` receives messages from the webview and calls + `OpenCodeAgent` or `VscodePlatformServices` directly. +4. SDK events are mapped in `mappers.ts` and forwarded to the webview as + `HostToUIMessage`. +5. The webview updates React state from host messages and sends user actions + back as `UIToHostMessage`. + +## Build And Test + +- Extension host bundle: `npm run build:ext` +- Webview bundle: `npm run build:webview` +- Full build: `npm run build` +- Webview tests: `npm test` +- Extension host tests: `npm run test:ext` +- All tests: `npm run test:all` diff --git a/packages/platforms/vscode/esbuild.mjs b/esbuild.mjs similarity index 91% rename from packages/platforms/vscode/esbuild.mjs rename to esbuild.mjs index 47d2c8f..1439f1d 100644 --- a/packages/platforms/vscode/esbuild.mjs +++ b/esbuild.mjs @@ -8,6 +8,9 @@ const buildOptions = { bundle: true, outfile: "dist/extension.js", external: ["vscode"], + alias: { + "@shared": "./src/shared/index.ts", + }, format: "cjs", platform: "node", target: "node22", diff --git a/packages/platforms/vscode/media/demo.gif b/media/demo.gif similarity index 100% rename from packages/platforms/vscode/media/demo.gif rename to media/demo.gif diff --git a/packages/platforms/vscode/media/icon.png b/media/icon.png similarity index 100% rename from packages/platforms/vscode/media/icon.png rename to media/icon.png diff --git a/packages/platforms/vscode/media/icon_full.png b/media/icon_full.png similarity index 100% rename from packages/platforms/vscode/media/icon_full.png rename to media/icon_full.png diff --git a/package-lock.json b/package-lock.json index caf150d..09c8f5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,592 @@ { - "name": "opencodegui-monorepo", - "version": "0.3.0", + "name": "opencodegui", + "version": "0.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "opencodegui-monorepo", - "version": "0.3.0", + "name": "opencodegui", + "version": "0.5.3", "license": "MIT", + "dependencies": { + "@opencode-ai/sdk": "^1.2.10", + "diff": "^8.0.0", + "dompurify": "^3.3.1", + "highlight.js": "^11.11.1", + "react-icons": "^5.5.0" + }, "devDependencies": { - "@biomejs/biome": "2.4.4" + "@biomejs/biome": "2.4.4", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", + "@types/dompurify": "^3.0.5", + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@types/vscode": "^1.100.0", + "@vitejs/plugin-react": "^5.1.4", + "@vscode/vsce": "^3.7.1", + "esbuild": "^0.25.0", + "jsdom": "^28.1.0", + "marked": "^17.0.3", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "typescript": "^5.7.0", + "vite": "^6.0.0", + "vitest": "^4.0.18" + }, + "engines": { + "vscode": "^1.100.0" + } + }, + "node_modules/@acemir/cssom": { + "version": "0.9.31", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", + "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.6" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz", + "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", + "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.1.tgz", + "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", + "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.23.0.tgz", + "integrity": "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.10.0.tgz", + "integrity": "sha512-2Y4TlG5mCfxviHutfW50i8Xd8xhGKTgieL02vMYOE5ZbZrVM+drKSGD//tweRAmlmqqp+F9vrKoHWri/buzxWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.6.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.6.0.tgz", + "integrity": "sha512-FemGljX0csPlBMUE5GUan7BfRn1emeMRUhHSARhqzLN6LA9nt+MgzmAQ1xVqdLm+6plVoxsq9mS5eoyKtpPSgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.0.tgz", + "integrity": "sha512-b/ak8XAqpnGk1N1nsyTVV0Remp48BP3QrGQZ1uCMcvg2S8X1eSXzhHQZEae2oX276Q4KFAqCUswanDtcvIKLrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.6.0", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@biomejs/biome": { @@ -174,6 +751,6482 @@ "engines": { "node": ">=14.21.3" } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz", + "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.0.tgz", + "integrity": "sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz", + "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@opencode-ai/sdk": { + "version": "1.14.41", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.14.41.tgz", + "integrity": "sha512-RYb2dCUv0TWIvBNnnO6ANbAPYri6rKuWizSoVFw/Pw+SCDj9ASHM5gAZ+jkskp8gYMfLLHe/Fpkun/9mr8m0IQ==", + "license": "MIT", + "dependencies": { + "cross-spawn": "7.0.6" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", + "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", + "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", + "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", + "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", + "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", + "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", + "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", + "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", + "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", + "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", + "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", + "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", + "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", + "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", + "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", + "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", + "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", + "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", + "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", + "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", + "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", + "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", + "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", + "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", + "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/formatter/-/formatter-10.2.2.tgz", + "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@secretlint/node": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/node/-/node-10.2.2.tgz", + "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/resolver/-/resolver-10.2.2.tgz", + "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-sarif-builder": "^3.2.0" + } + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@textlint/ast-node-types": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.6.0.tgz", + "integrity": "sha512-CxZHFbYAU7J0A4izz31wV2ZZfySR6aVj2OSR6/3tppZm7VV6hM7nA7sutsLwIiBL/v4lsB1RM79l4Dc/VrH4qw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-15.6.0.tgz", + "integrity": "sha512-IwHRhjwxs0a5t1eNAoKAdV224CDca38LyopPofXpwO/d0J75wBvzf/cBHXNl4TMsLKhYGtR83UprcLEKj/gZsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.6.0", + "@textlint/resolver": "15.6.0", + "@textlint/types": "15.6.0", + "chalk": "^4.1.2", + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "lodash": "^4.18.1", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", + "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/module-interop": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-15.6.0.tgz", + "integrity": "sha512-MHY6pJx9i5kOlrvUSK51887tYZjHAV2qnr6unBm7LtBLGDFo93utdYqHyWep8r9QLsilQdeijWtufJI46z4v4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/resolver": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@textlint/resolver/-/resolver-15.6.0.tgz", + "integrity": "sha512-T1l2Gd3455pwtm0cTewhX/LLy3bL9z6/Fu/am+jj+jjGfXVoknYkjfkZEKrjHlA7xzay0EfUKnu//teYemLeZw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@textlint/types/-/types-15.6.0.tgz", + "integrity": "sha512-CvgYb1PiqF4BGyoZebGWzAJCZ4ChJAZ9gtWjpQIMKE4Xe2KlSwDA8m8MsiZIV321f5Ibx38BMjC1Z/2ZYP2GQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@textlint/ast-node-types": "15.6.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.18.tgz", + "integrity": "sha512-9v00a+dn2yWVsYDEunWC4g/TcRKVq3r8N5FuZp7u0SGrPvdN9c2yXI9bBuf5Fl0hNCb+QTIePTn5pJs2pwBOQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", + "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.118.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.118.0.tgz", + "integrity": "sha512-Ah6eTlqDcwIMELEVwQMO++rJAFBRz/oLluLD/vWdYrH1KuI9kfpaM+7pg0OvvascgcJy+ghLCERAYouM4QbzGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.5.tgz", + "integrity": "sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz", + "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", + "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.5", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz", + "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz", + "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.5", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz", + "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "@vitest/utils": "4.1.5", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz", + "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz", + "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vscode/vsce": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.9.1.tgz", + "integrity": "sha512-MPn5p+DoudI+3GfJSpAZZraE1lgLv0LcwbH3+xy7RgEhty3UIkmUMUA+5jPTDaxXae00AnX5u77FxGM8FhfKKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.2", + "@secretlint/secretlint-formatter-sarif": "^10.1.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^11.0.0", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.2", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^3.2.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.28", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.28.tgz", + "integrity": "sha512-Ic44hnOtFIgravCunj1ifSoQPSUrkNiJuH9Mf6jr2jjoA74icqV8wU0KuadXeOR8zuIJMOoTv0GuQjZ9ZYNMeA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz", + "integrity": "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.0.1", + "@csstools/css-syntax-patches-for-csstree": "^1.0.28", + "css-tree": "^3.1.0", + "lru-cache": "^11.2.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cssstyle/node_modules/lru-cache": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz", + "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.353", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", + "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "28.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", + "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@acemir/cssom": "^0.9.31", + "@asamuzakjp/dom-selector": "^6.8.1", + "@bramus/specificity": "^2.4.2", + "@exodus/bytes": "^1.11.0", + "cssstyle": "^6.0.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "undici": "^7.21.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/marked": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz", + "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-sarif-builder": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz", + "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.4.tgz", + "integrity": "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "json5": "^2.2.3", + "require-from-string": "^2.0.2" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-icons": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz", + "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", + "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.3", + "@rollup/rollup-android-arm64": "4.60.3", + "@rollup/rollup-darwin-arm64": "4.60.3", + "@rollup/rollup-darwin-x64": "4.60.3", + "@rollup/rollup-freebsd-arm64": "4.60.3", + "@rollup/rollup-freebsd-x64": "4.60.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", + "@rollup/rollup-linux-arm-musleabihf": "4.60.3", + "@rollup/rollup-linux-arm64-gnu": "4.60.3", + "@rollup/rollup-linux-arm64-musl": "4.60.3", + "@rollup/rollup-linux-loong64-gnu": "4.60.3", + "@rollup/rollup-linux-loong64-musl": "4.60.3", + "@rollup/rollup-linux-ppc64-gnu": "4.60.3", + "@rollup/rollup-linux-ppc64-musl": "4.60.3", + "@rollup/rollup-linux-riscv64-gnu": "4.60.3", + "@rollup/rollup-linux-riscv64-musl": "4.60.3", + "@rollup/rollup-linux-s390x-gnu": "4.60.3", + "@rollup/rollup-linux-x64-gnu": "4.60.3", + "@rollup/rollup-linux-x64-musl": "4.60.3", + "@rollup/rollup-openbsd-x64": "4.60.3", + "@rollup/rollup-openharmony-arm64": "4.60.3", + "@rollup/rollup-win32-arm64-msvc": "4.60.3", + "@rollup/rollup-win32-ia32-msvc": "4.60.3", + "@rollup/rollup-win32-x64-gnu": "4.60.3", + "@rollup/rollup-win32-x64-msvc": "4.60.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", + "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.0.30", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.30.tgz", + "integrity": "sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.30" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.30", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.30.tgz", + "integrity": "sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", + "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vite": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", + "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.5", + "@vitest/browser-preview": "4.1.5", + "@vitest/browser-webdriverio": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/ui": "4.1.5", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", + "integrity": "sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } } } } diff --git a/package.json b/package.json index 2a369e7..d84da35 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,104 @@ { - "name": "opencodegui-monorepo", - "private": true, + "name": "opencodegui", + "displayName": "%displayName%", + "description": "%description%", "version": "0.5.3", + "publisher": "ktmage", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/ktmage/opencode-gui" }, + "homepage": "https://github.com/ktmage/opencode-gui#readme", + "bugs": { + "url": "https://github.com/ktmage/opencode-gui/issues" + }, + "keywords": [ + "opencode", + "ai", + "chat", + "llm", + "coding-assistant" + ], + "icon": "media/icon.png", + "preview": true, + "qna": false, + "galleryBanner": { + "color": "#1e1e1e", + "theme": "dark" + }, + "engines": { + "vscode": "^1.100.0" + }, + "categories": [ + "AI", + "Chat" + ], + "activationEvents": [], + "main": "./dist/extension.js", + "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "opencode", + "title": "OpenCode", + "icon": "$(comment-discussion)" + } + ] + }, + "views": { + "opencode": [ + { + "type": "webview", + "id": "opencode.chatView", + "name": "Chat" + } + ] + } + }, "scripts": { - "build": "pnpm -r build", + "build": "node esbuild.mjs && vite build", + "build:ext": "node esbuild.mjs", + "build:webview": "vite build", "check": "biome check .", "check:fix": "biome check --fix .", "format": "biome format --write .", - "test": "pnpm -r test", - "test:all": "pnpm -r run test:all" + "watch:ext": "node esbuild.mjs --watch", + "watch:webview": "vite build --watch", + "test": "vitest run --config vitest.config.ts", + "test:ext": "vitest run --config vitest.config.ext.ts", + "test:ext:watch": "vitest --config vitest.config.ext.ts", + "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.config.ext.ts", + "test:watch": "vitest --config vitest.config.ts", + "package": "vsce package --no-dependencies", + "publish": "vsce publish --no-dependencies" }, "devDependencies": { - "@biomejs/biome": "2.4.4" + "@biomejs/biome": "2.4.4", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", + "@types/dompurify": "^3.0.5", + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@types/vscode": "^1.100.0", + "@vitejs/plugin-react": "^5.1.4", + "@vscode/vsce": "^3.7.1", + "esbuild": "^0.25.0", + "jsdom": "^28.1.0", + "marked": "^17.0.3", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "typescript": "^5.7.0", + "vite": "^6.0.0", + "vitest": "^4.0.18" + }, + "dependencies": { + "@opencode-ai/sdk": "^1.2.10", + "diff": "^8.0.0", + "dompurify": "^3.3.1", + "highlight.js": "^11.11.1", + "react-icons": "^5.5.0" } } diff --git a/packages/platforms/vscode/package.nls.es.json b/package.nls.es.json similarity index 100% rename from packages/platforms/vscode/package.nls.es.json rename to package.nls.es.json diff --git a/packages/platforms/vscode/package.nls.ja.json b/package.nls.ja.json similarity index 100% rename from packages/platforms/vscode/package.nls.ja.json rename to package.nls.ja.json diff --git a/packages/platforms/vscode/package.nls.json b/package.nls.json similarity index 100% rename from packages/platforms/vscode/package.nls.json rename to package.nls.json diff --git a/packages/platforms/vscode/package.nls.ko.json b/package.nls.ko.json similarity index 100% rename from packages/platforms/vscode/package.nls.ko.json rename to package.nls.ko.json diff --git a/packages/platforms/vscode/package.nls.pt-br.json b/package.nls.pt-br.json similarity index 100% rename from packages/platforms/vscode/package.nls.pt-br.json rename to package.nls.pt-br.json diff --git a/packages/platforms/vscode/package.nls.ru.json b/package.nls.ru.json similarity index 100% rename from packages/platforms/vscode/package.nls.ru.json rename to package.nls.ru.json diff --git a/packages/platforms/vscode/package.nls.zh-cn.json b/package.nls.zh-cn.json similarity index 100% rename from packages/platforms/vscode/package.nls.zh-cn.json rename to package.nls.zh-cn.json diff --git a/packages/platforms/vscode/package.nls.zh-tw.json b/package.nls.zh-tw.json similarity index 100% rename from packages/platforms/vscode/package.nls.zh-tw.json rename to package.nls.zh-tw.json diff --git a/packages/agents/opencode/package.json b/packages/agents/opencode/package.json deleted file mode 100644 index bab04aa..0000000 --- a/packages/agents/opencode/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@opencodegui/agent-opencode", - "version": "0.0.1", - "private": true, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "build": "tsc -p tsconfig.json", - "test": "vitest run", - "test:all": "vitest run" - }, - "dependencies": { - "@opencode-ai/sdk": "^1.2.10", - "@opencodegui/core": "workspace:*" - }, - "devDependencies": { - "typescript": "^5.7.0", - "vitest": "^4.0.18" - } -} diff --git a/packages/agents/opencode/src/index.ts b/packages/agents/opencode/src/index.ts deleted file mode 100644 index 2716809..0000000 --- a/packages/agents/opencode/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @opencodegui/agent-opencode - OpenCode agent implementation - -export * from "./mappers"; -export { OpenCodeAgent } from "./opencode-agent"; diff --git a/packages/agents/opencode/tsconfig.json b/packages/agents/opencode/tsconfig.json deleted file mode 100644 index 2276adc..0000000 --- a/packages/agents/opencode/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", - "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/packages/agents/opencode/vitest.config.ts b/packages/agents/opencode/vitest.config.ts deleted file mode 100644 index 8696084..0000000 --- a/packages/agents/opencode/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["src/__tests__/**/*.test.ts"], - }, -}); diff --git a/packages/core/package.json b/packages/core/package.json deleted file mode 100644 index 0cdfd44..0000000 --- a/packages/core/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@opencodegui/core", - "version": "0.0.1", - "private": true, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "build": "tsc -p tsconfig.json" - }, - "devDependencies": { - "typescript": "^5.7.0" - } -} diff --git a/packages/core/src/agent.interface.ts b/packages/core/src/agent.interface.ts deleted file mode 100644 index f8e841e..0000000 --- a/packages/core/src/agent.interface.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @opencodegui/core - Agent Interface - * - * Defines the contract between the UI/platform layer and any coding agent. - * Each agent implementation (OpenCode, Claude Code, Codex, etc.) implements - * this interface, hiding transport details (HTTP, stdio, WebSocket, etc.). - */ - -import type { - AgentEvent, - AgentInfo, - AllProvidersData, - AppConfig, - AppPaths, - ChatMessageWithParts, - ChatSession, - Disposable, - FileDiff, - McpStatus, - ModelRef, - PermissionResponse, - ProviderInfo, - QuestionAnswer, - SendMessageOptions, - SkillInfo, - TodoItem, - ToolListItem, -} from "./domain"; - -/** Agent capability declarations */ -export type AgentCapabilities = { - /** Session deletion */ - sessionDelete: boolean; - /** Session fork (branch from any message) */ - sessionFork: boolean; - /** Session revert / unrevert (undo / redo) */ - sessionRevert: boolean; - /** Session sharing (URL generation) */ - sessionShare: boolean; - /** Session summarization / context compression */ - sessionSummarize: boolean; - /** Per-session file diffs */ - sessionDiff: boolean; - /** Todo management */ - todo: boolean; - /** Multi-provider model selection */ - multiProvider: boolean; - /** Permission management (tool execution approval flow) */ - permission: boolean; - /** Question interaction (AI asks user questions with options) */ - question: boolean; - /** MCP (Model Context Protocol) support */ - mcp: boolean; - /** Sub-agents (child sessions) */ - subAgent: boolean; - /** Shell command execution */ - shell: boolean; - /** Config management API */ - config: boolean; -}; - -export interface IAgent { - // --- Capability declaration --- - getCapabilities(): AgentCapabilities; - - // --- Lifecycle --- - connect(): Promise; - disconnect(): void; - - // --- Event subscription --- - onEvent(handler: (event: AgentEvent) => void): Disposable; - - // --- Sessions (common: all agents implement) --- - listSessions(): Promise; - createSession(title?: string): Promise; - getSession(id: string): Promise; - - // --- Sessions (capabilities-dependent) --- - deleteSession(id: string): Promise; - forkSession(sessionId: string, messageId?: string): Promise; - revertSession(sessionId: string, messageId: string): Promise; - unrevertSession(sessionId: string): Promise; - summarizeSession(sessionId: string, model?: ModelRef): Promise; - shareSession(sessionId: string): Promise; - unshareSession(sessionId: string): Promise; - - // --- Messages (common: all agents implement) --- - getMessages(sessionId: string): Promise; - sendMessage(sessionId: string, text: string, options?: SendMessageOptions): Promise; - abortSession(sessionId: string): Promise; - - // --- Shell (capabilities.shell) --- - executeShell(sessionId: string, command: string, model?: ModelRef): Promise; - - // --- Providers & models (capabilities.multiProvider) --- - getProviders(): Promise<{ - providers: ProviderInfo[]; - default: Record; - }>; - listAllProviders(): Promise; - - // --- Agent list (capabilities.subAgent) --- - getAgents(): Promise; - getSkills(): Promise; - getChildSessions(sessionId: string): Promise; - - // --- Permissions (capabilities.permission) --- - replyPermission(sessionId: string, permissionId: string, response: PermissionResponse): Promise; - - // --- Questions (capabilities.question) --- - replyQuestion(requestId: string, answers: QuestionAnswer[]): Promise; - rejectQuestion(requestId: string): Promise; - - // --- Session metadata (capabilities-dependent) --- - getSessionDiff(sessionId: string): Promise; - getSessionTodos(sessionId: string): Promise; - - // --- Config (capabilities.config) --- - getConfig(): Promise; - updateConfig(config: Partial): Promise; - getPath(): Promise; - - // --- MCP (capabilities.mcp) --- - getMcpStatus(): Promise; - connectMcp(server: string): Promise; - disconnectMcp(server: string): Promise; - - // --- Tools --- - getToolIds(): Promise; - - // --- Server URL (agent-specific, for terminal attachment etc.) --- - getServerUrl(): string | undefined; - - // --- Model management --- - setModel?(model: string): Promise; -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts deleted file mode 100644 index 0f69786..0000000 --- a/packages/core/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// @opencodegui/core - shared interfaces and domain types - -export * from "./agent.interface"; -export * from "./domain"; -export * from "./platform.interface"; -export * from "./protocol"; diff --git a/packages/core/src/platform.interface.ts b/packages/core/src/platform.interface.ts deleted file mode 100644 index fcbdfe3..0000000 --- a/packages/core/src/platform.interface.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @opencodegui/core - Platform Interface - * - * Defines the contract for platform-specific functionality. - * Each platform (VS Code, Electron, Web, etc.) implements these interfaces. - */ - -import type { Disposable, FileAttachment } from "./domain"; -import type { HostToUIMessage, UIToHostMessage } from "./protocol"; - -/** UI <-> Platform communication bridge */ -export interface IBridge { - postMessage(message: UIToHostMessage): void; - onMessage(handler: (message: HostToUIMessage) => void): Disposable; - getPersistedState(): UIPersistedState | null; - setPersistedState(state: UIPersistedState): void; -} - -export type SoundEventType = "responseComplete" | "permissionRequest" | "questionAsked" | "error"; - -export type SoundEventSetting = { - enabled?: boolean; - volume?: number; -}; - -export type SoundSettings = { - [K in SoundEventType]?: SoundEventSetting; -}; - -export type UIPersistedState = { - localeSetting?: "auto" | "en" | "ja"; - inputHistory?: string[]; - soundSettings?: SoundSettings; -}; - -/** Platform-specific services */ -export interface IPlatformServices { - /** Open a diff viewer */ - openDiffEditor(filePath: string, before: string, after: string): Promise; - - /** Copy text to clipboard */ - copyToClipboard(text: string): Promise; - - /** Open a terminal and connect to the agent's server */ - openTerminal(serverUrl: string, sessionId?: string): Promise; - - /** Open a config file in the editor */ - openConfigFile(filePath: string): Promise; - - /** Open a file in the editor, optionally at a specific line */ - openFile(filePath: string, line?: number): Promise; - - /** Search for files in the workspace */ - searchWorkspaceFiles(query: string): Promise; - - /** Get currently open editor files */ - getOpenEditors(): Promise; -} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json deleted file mode 100644 index 2276adc..0000000 --- a/packages/core/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", - "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/packages/platforms/vscode/README.md b/packages/platforms/vscode/README.md deleted file mode 100644 index 9b287d2..0000000 --- a/packages/platforms/vscode/README.md +++ /dev/null @@ -1,156 +0,0 @@ -# OpenCodeGUI - -An unofficial VS Code sidebar chat interface for [OpenCode](https://github.com/anomalyco/opencode). - -OpenCode の非公式 VS Code サイドバーチャットインターフェース。 - -## Table of Contents / 目次 - -- [English](#english) -- [日本語](#japanese) - - - -## English - -### OpenCodeGUI - -Use all OpenCode features from a familiar sidebar chat UI. - -> **This is an unofficial, community-developed extension. It is not affiliated with or endorsed by the OpenCode project.** - -> [!CAUTION] -> **Disclaimer:** -> This project is experimental and developed primarily through AI-assisted coding. It is provided "as-is" without warranty of any kind. It may contain unexpected behavior, unconventional implementations, or undiscovered defects. Use at your own risk. The authors assume no liability for any damages arising from the use of this software. - -### Demo - -![Demo](https://raw.githubusercontent.com/ktmage/opencode-gui/master/packages/platforms/vscode/media/demo.gif) - -### Features - -- Chat UI (send/receive messages, streaming display) -- Markdown rendering -- Tool call collapsible display -- Permission approval UI (Allow / Once / Deny) -- Session management (create, switch, fork, delete) -- Message editing & checkpoint restore -- Model selection -- Agent selector for primary agent selection -- File context attachment -- File changes diff view -- Session diff review via [difit](https://github.com/yoshiko-pg/difit) (opens in browser) -- Shell command execution -- Reasoning / thinking display -- Todo display -- Undo / Redo -- Session sharing -- Agent mention (`@` mention) -- Child session navigation (subtask) -- Settings panel -- Keyboard navigation for inline popups (Tab / Arrow keys) -- Subtask display -- Auto-scroll during streaming -- File type icons -- File path links (clickable file chips with extension-based icons) -- Syntax highlighting and copy button for code blocks -- Quick-add button with active editor file -- Input history navigation (ArrowUp / ArrowDown) -- Sound notification on assistant response completion -- Question interaction UI for agent-initiated questions -- i18n support (English, Japanese, Simplified Chinese, Korean, Traditional Chinese, Spanish, Brazilian Portuguese, Russian) - -### Requirements - -- [OpenCode](https://github.com/anomalyco/opencode) installed -- LLM provider authentication configured in OpenCode - -#### Optional - -- [difit](https://github.com/yoshiko-pg/difit) — enables the session diff review feature. Install with `npm install -g difit`. - -### Installation - -Search for **OpenCodeGUI** in the VS Code Extensions view (`Ctrl+Shift+X` / `Cmd+Shift+X`) and click **Install**. - -### Contributing - -Contributions are welcome! See [CONTRIBUTING.md](https://github.com/ktmage/opencode-gui/blob/master/CONTRIBUTING.md) for details. - -### License - -[MIT](https://github.com/ktmage/opencode-gui/blob/master/LICENSE) - ---- - - - -## 日本語 - -### OpenCodeGUI - -OpenCode の全機能をサイドバーのチャット UI から操作できます。 - -> **本拡張機能は非公式のコミュニティ開発プロジェクトです。OpenCode プロジェクトとは提携・推薦関係にありません。** - -> [!CAUTION] -> **免責事項:** -> 本プロジェクトは実験的な取り組みであり、主に AI を活用したコーディングにより開発されています。いかなる保証もなく「現状のまま」提供されます。予期しない動作、一般的でない実装、未発見の不具合が含まれる可能性があります。ご利用は自己責任でお願いいたします。本ソフトウェアの使用により生じたいかなる損害についても、作者は一切の責任を負いません。 - -### デモ - -![デモ](https://raw.githubusercontent.com/ktmage/opencode-gui/master/packages/platforms/vscode/media/demo.gif) - -### 機能 - -- チャット UI(メッセージ送受信、ストリーミング表示) -- Markdown レンダリング -- ツールコールの折りたたみ表示 -- パーミッション承認 UI(Allow / Once / Deny) -- セッション管理(作成、切替、フォーク、削除) -- メッセージ編集とチェックポイント復元 -- モデル選択 -- エージェントセレクター(プライマリエージェント選択) -- ファイルコンテキスト添付 -- ファイル変更差分表示 -- [difit](https://github.com/yoshiko-pg/difit) によるセッション差分レビュー(ブラウザで表示) -- シェルコマンド実行 -- 推論(思考過程)表示 -- Todo 表示 -- Undo / Redo -- セッション共有 -- エージェントメンション(`@` メンション) -- 子セッションナビゲーション(サブタスク) -- 設定パネル -- インラインポップアップのキーボードナビゲーション(Tab / 矢印キー) -- サブタスク表示 -- ストリーミング中の自動スクロール -- ファイルタイプアイコン -- ファイルパスリンク(拡張子別アイコン付きクリッカブルチップ) -- コードブロックのシンタックスハイライト・コピーボタン -- Quick-add ボタン(アクティブエディタのファイル表示) -- 入力履歴ナビゲーション(ArrowUp / ArrowDown) -- サウンド通知(アシスタント応答完了時) -- 質問インタラクション UI(エージェントからの質問対応) -- 多言語対応(英語、日本語、簡体字中国語、韓国語、繁体字中国語、スペイン語、ブラジルポルトガル語、ロシア語) - -### 必要条件 - -- [OpenCode](https://github.com/anomalyco/opencode) がインストール済みであること -- OpenCode 側で LLM プロバイダの認証が完了していること - -#### オプション - -- [difit](https://github.com/yoshiko-pg/difit) — セッション差分レビュー機能を有効にします。`npm install -g difit` でインストール。 - -### インストール - -VS Code の拡張機能ビュー(`Ctrl+Shift+X` / `Cmd+Shift+X`)で **OpenCodeGUI** を検索し、**Install** をクリック。 - -### コントリビュート - -このプロジェクトへの貢献を歓迎します。詳しくは [CONTRIBUTING.md](https://github.com/ktmage/opencode-gui/blob/master/CONTRIBUTING.md) を参照してください。 - -### ライセンス - -[MIT](https://github.com/ktmage/opencode-gui/blob/master/LICENSE) diff --git a/packages/platforms/vscode/package.json b/packages/platforms/vscode/package.json deleted file mode 100644 index 858eedc..0000000 --- a/packages/platforms/vscode/package.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "name": "opencodegui", - "displayName": "%displayName%", - "description": "%description%", - "version": "0.5.3", - "publisher": "ktmage", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/ktmage/opencode-gui" - }, - "homepage": "https://github.com/ktmage/opencode-gui#readme", - "bugs": { - "url": "https://github.com/ktmage/opencode-gui/issues" - }, - "keywords": [ - "opencode", - "ai", - "chat", - "llm", - "coding-assistant" - ], - "icon": "media/icon.png", - "preview": true, - "qna": false, - "galleryBanner": { - "color": "#1e1e1e", - "theme": "dark" - }, - "engines": { - "vscode": "^1.100.0" - }, - "categories": [ - "AI", - "Chat" - ], - "activationEvents": [], - "main": "./dist/extension.js", - "contributes": { - "viewsContainers": { - "activitybar": [ - { - "id": "opencode", - "title": "OpenCode", - "icon": "$(comment-discussion)" - } - ] - }, - "views": { - "opencode": [ - { - "type": "webview", - "id": "opencode.chatView", - "name": "Chat" - } - ] - } - }, - "scripts": { - "build": "node esbuild.mjs && vite build", - "build:ext": "node esbuild.mjs", - "build:webview": "vite build", - "watch:ext": "node esbuild.mjs --watch", - "watch:webview": "vite build --watch", - "test": "vitest run --config vitest.config.ts", - "test:ext": "vitest run --config vitest.config.ext.ts", - "test:ext:watch": "vitest --config vitest.config.ext.ts", - "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.config.ext.ts", - "test:watch": "vitest --config vitest.config.ts", - "package": "vsce package --no-dependencies", - "publish": "vsce publish --no-dependencies" - }, - "devDependencies": { - "@testing-library/jest-dom": "^6.9.1", - "@testing-library/react": "^16.3.2", - "@testing-library/user-event": "^14.6.1", - "@types/dompurify": "^3.0.5", - "@types/node": "^22.0.0", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@types/vscode": "^1.100.0", - "@vitejs/plugin-react": "^5.1.4", - "@vscode/vsce": "^3.7.1", - "esbuild": "^0.25.0", - "jsdom": "^28.1.0", - "marked": "^17.0.3", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "typescript": "^5.7.0", - "vite": "^6.0.0", - "vitest": "^4.0.18" - }, - "dependencies": { - "@opencodegui/agent-opencode": "workspace:*", - "@opencodegui/core": "workspace:*", - "diff": "^8.0.0", - "dompurify": "^3.3.1", - "highlight.js": "^11.11.1", - "react-icons": "^5.5.0" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 1b59ff2..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,4445 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@biomejs/biome': - specifier: 2.4.4 - version: 2.4.4 - - packages/agents/opencode: - dependencies: - '@opencode-ai/sdk': - specifier: ^1.2.10 - version: 1.2.17 - '@opencodegui/core': - specifier: workspace:* - version: link:../../core - devDependencies: - typescript: - specifier: ^5.7.0 - version: 5.9.3 - vitest: - specifier: ^4.0.18 - version: 4.0.18(@types/node@22.19.13)(jsdom@28.1.0) - - packages/core: - devDependencies: - typescript: - specifier: ^5.7.0 - version: 5.9.3 - - packages/platforms/vscode: - dependencies: - '@opencodegui/agent-opencode': - specifier: workspace:* - version: link:../../agents/opencode - '@opencodegui/core': - specifier: workspace:* - version: link:../../core - diff: - specifier: ^8.0.0 - version: 8.0.3 - dompurify: - specifier: ^3.3.1 - version: 3.3.1 - highlight.js: - specifier: ^11.11.1 - version: 11.11.1 - react-icons: - specifier: ^5.5.0 - version: 5.6.0(react@19.2.4) - devDependencies: - '@testing-library/jest-dom': - specifier: ^6.9.1 - version: 6.9.1 - '@testing-library/react': - specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@testing-library/user-event': - specifier: ^14.6.1 - version: 14.6.1(@testing-library/dom@10.4.1) - '@types/dompurify': - specifier: ^3.0.5 - version: 3.2.0 - '@types/node': - specifier: ^22.0.0 - version: 22.19.13 - '@types/react': - specifier: ^19.0.0 - version: 19.2.14 - '@types/react-dom': - specifier: ^19.0.0 - version: 19.2.3(@types/react@19.2.14) - '@types/vscode': - specifier: ^1.100.0 - version: 1.109.0 - '@vitejs/plugin-react': - specifier: ^5.1.4 - version: 5.1.4(vite@6.4.1(@types/node@22.19.13)) - '@vscode/vsce': - specifier: ^3.7.1 - version: 3.7.1 - esbuild: - specifier: ^0.25.0 - version: 0.25.12 - jsdom: - specifier: ^28.1.0 - version: 28.1.0 - marked: - specifier: ^17.0.3 - version: 17.0.4 - react: - specifier: ^19.0.0 - version: 19.2.4 - react-dom: - specifier: ^19.0.0 - version: 19.2.4(react@19.2.4) - typescript: - specifier: ^5.7.0 - version: 5.9.3 - vite: - specifier: ^6.0.0 - version: 6.4.1(@types/node@22.19.13) - vitest: - specifier: ^4.0.18 - version: 4.0.18(@types/node@22.19.13)(jsdom@28.1.0) - -packages: - - '@acemir/cssom@0.9.31': - resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} - - '@adobe/css-tools@4.4.4': - resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - - '@asamuzakjp/css-color@5.0.1': - resolution: {integrity: sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/dom-selector@6.8.1': - resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} - - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} - - '@azu/format-text@1.0.2': - resolution: {integrity: sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==} - - '@azu/style-format@1.0.1': - resolution: {integrity: sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==} - - '@azure/abort-controller@2.1.2': - resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} - engines: {node: '>=18.0.0'} - - '@azure/core-auth@1.10.1': - resolution: {integrity: sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==} - engines: {node: '>=20.0.0'} - - '@azure/core-client@1.10.1': - resolution: {integrity: sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==} - engines: {node: '>=20.0.0'} - - '@azure/core-rest-pipeline@1.22.2': - resolution: {integrity: sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==} - engines: {node: '>=20.0.0'} - - '@azure/core-tracing@1.3.1': - resolution: {integrity: sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==} - engines: {node: '>=20.0.0'} - - '@azure/core-util@1.13.1': - resolution: {integrity: sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==} - engines: {node: '>=20.0.0'} - - '@azure/identity@4.13.0': - resolution: {integrity: sha512-uWC0fssc+hs1TGGVkkghiaFkkS7NkTxfnCH+Hdg+yTehTpMcehpok4PgUKKdyCH+9ldu6FhiHRv84Ntqj1vVcw==} - engines: {node: '>=20.0.0'} - - '@azure/logger@1.3.0': - resolution: {integrity: sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==} - engines: {node: '>=20.0.0'} - - '@azure/msal-browser@4.29.0': - resolution: {integrity: sha512-/f3eHkSNUTl6DLQHm+bKecjBKcRQxbd/XLx8lvSYp8Nl/HRyPuIPOijt9Dt0sH50/SxOwQ62RnFCmFlGK+bR/w==} - engines: {node: '>=0.8.0'} - - '@azure/msal-common@15.15.0': - resolution: {integrity: sha512-/n+bN0AKlVa+AOcETkJSKj38+bvFs78BaP4rNtv3MJCmPH0YrHiskMRe74OhyZ5DZjGISlFyxqvf9/4QVEi2tw==} - engines: {node: '>=0.8.0'} - - '@azure/msal-node@3.8.8': - resolution: {integrity: sha512-+f1VrJH1iI517t4zgmuhqORja0bL6LDQXfBqkjuMmfTYXTQQnh1EvwwxO3UbKLT05N0obF72SRHFrC1RBDv5Gg==} - engines: {node: '>=16'} - - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/runtime@7.28.6': - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - - '@biomejs/biome@2.4.4': - resolution: {integrity: sha512-tigwWS5KfJf0cABVd52NVaXyAVv4qpUXOWJ1rxFL8xF1RVoeS2q/LK+FHgYoKMclJCuRoCWAPy1IXaN9/mS61Q==} - engines: {node: '>=14.21.3'} - hasBin: true - - '@biomejs/cli-darwin-arm64@2.4.4': - resolution: {integrity: sha512-jZ+Xc6qvD6tTH5jM6eKX44dcbyNqJHssfl2nnwT6vma6B1sj7ZLTGIk6N5QwVBs5xGN52r3trk5fgd3sQ9We9A==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [darwin] - - '@biomejs/cli-darwin-x64@2.4.4': - resolution: {integrity: sha512-Dh1a/+W+SUCXhEdL7TiX3ArPTFCQKJTI1mGncZNWfO+6suk+gYA4lNyJcBB+pwvF49uw0pEbUS49BgYOY4hzUg==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [darwin] - - '@biomejs/cli-linux-arm64-musl@2.4.4': - resolution: {integrity: sha512-+sPAXq3bxmFwhVFJnSwkSF5Rw2ZAJMH3MF6C9IveAEOdSpgajPhoQhbbAK12SehN9j2QrHpk4J/cHsa/HqWaYQ==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@biomejs/cli-linux-arm64@2.4.4': - resolution: {integrity: sha512-V/NFfbWhsUU6w+m5WYbBenlEAz8eYnSqRMDMAW3K+3v0tYVkNyZn8VU0XPxk/lOqNXLSCCrV7FmV/u3SjCBShg==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@biomejs/cli-linux-x64-musl@2.4.4': - resolution: {integrity: sha512-gGvFTGpOIQDb5CQ2VC0n9Z2UEqlP46c4aNgHmAMytYieTGEcfqhfCFnhs6xjt0S3igE6q5GLuIXtdQt3Izok+g==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@biomejs/cli-linux-x64@2.4.4': - resolution: {integrity: sha512-R4+ZCDtG9kHArasyBO+UBD6jr/FcFCTH8QkNTOCu0pRJzCWyWC4EtZa2AmUZB5h3e0jD7bRV2KvrENcf8rndBg==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@biomejs/cli-win32-arm64@2.4.4': - resolution: {integrity: sha512-trzCqM7x+Gn832zZHgr28JoYagQNX4CZkUZhMUac2YxvvyDRLJDrb5m9IA7CaZLlX6lTQmADVfLEKP1et1Ma4Q==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [win32] - - '@biomejs/cli-win32-x64@2.4.4': - resolution: {integrity: sha512-gnOHKVPFAAPrpoPt2t+Q6FZ7RPry/FDV3GcpU53P3PtLNnQjBmKyN2Vh/JtqXet+H4pme8CC76rScwdjDcT1/A==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [win32] - - '@bramus/specificity@2.4.2': - resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} - hasBin: true - - '@csstools/color-helpers@6.0.2': - resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} - engines: {node: '>=20.19.0'} - - '@csstools/css-calc@3.1.1': - resolution: {integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 - - '@csstools/css-color-parser@4.0.2': - resolution: {integrity: sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 - - '@csstools/css-parser-algorithms@4.0.0': - resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@csstools/css-tokenizer': ^4.0.0 - - '@csstools/css-syntax-patches-for-csstree@1.0.29': - resolution: {integrity: sha512-jx9GjkkP5YHuTmko2eWAvpPnb0mB4mGRr2U7XwVNwevm8nlpobZEVk+GNmiYMk2VuA75v+plfXWyroWKmICZXg==} - - '@csstools/css-tokenizer@4.0.0': - resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} - engines: {node: '>=20.19.0'} - - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@exodus/bytes@1.15.0': - resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - peerDependencies: - '@noble/hashes': ^1.8.0 || ^2.0.0 - peerDependenciesMeta: - '@noble/hashes': - optional: true - - '@isaacs/cliui@9.0.0': - resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} - engines: {node: '>=18'} - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@opencode-ai/sdk@1.2.17': - resolution: {integrity: sha512-HdeLeyJ2/Yl/NBHqw9pGFBnkIXuf0Id1kX1GMXDcnZwbJROUJ6TtrW/wLngTYW478E4CCm1jwknjxxmDuxzVMQ==} - - '@rolldown/pluginutils@1.0.0-rc.3': - resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} - - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} - cpu: [x64] - os: [win32] - - '@secretlint/config-creator@10.2.2': - resolution: {integrity: sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==} - engines: {node: '>=20.0.0'} - - '@secretlint/config-loader@10.2.2': - resolution: {integrity: sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==} - engines: {node: '>=20.0.0'} - - '@secretlint/core@10.2.2': - resolution: {integrity: sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==} - engines: {node: '>=20.0.0'} - - '@secretlint/formatter@10.2.2': - resolution: {integrity: sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==} - engines: {node: '>=20.0.0'} - - '@secretlint/node@10.2.2': - resolution: {integrity: sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==} - engines: {node: '>=20.0.0'} - - '@secretlint/profiler@10.2.2': - resolution: {integrity: sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==} - - '@secretlint/resolver@10.2.2': - resolution: {integrity: sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==} - - '@secretlint/secretlint-formatter-sarif@10.2.2': - resolution: {integrity: sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==} - - '@secretlint/secretlint-rule-no-dotenv@10.2.2': - resolution: {integrity: sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==} - engines: {node: '>=20.0.0'} - - '@secretlint/secretlint-rule-preset-recommend@10.2.2': - resolution: {integrity: sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==} - engines: {node: '>=20.0.0'} - - '@secretlint/source-creator@10.2.2': - resolution: {integrity: sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==} - engines: {node: '>=20.0.0'} - - '@secretlint/types@10.2.2': - resolution: {integrity: sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==} - engines: {node: '>=20.0.0'} - - '@sindresorhus/merge-streams@2.3.0': - resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} - engines: {node: '>=18'} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@testing-library/dom@10.4.1': - resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} - engines: {node: '>=18'} - - '@testing-library/jest-dom@6.9.1': - resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - - '@testing-library/react@16.3.2': - resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} - engines: {node: '>=18'} - peerDependencies: - '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 || ^19.0.0 - '@types/react-dom': ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@testing-library/user-event@14.6.1': - resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} - engines: {node: '>=12', npm: '>=6'} - peerDependencies: - '@testing-library/dom': '>=7.21.4' - - '@textlint/ast-node-types@15.5.2': - resolution: {integrity: sha512-fCaOxoup5LIyBEo7R1oYWE7V4bSX0KQeHh66twon9e9usaLE3ijgF8QjYsR6joCssdeCHVd0wHm7ppsEyTr6vg==} - - '@textlint/linter-formatter@15.5.2': - resolution: {integrity: sha512-jAw7jWM8+wU9cG6Uu31jGyD1B+PAVePCvnPKC/oov+2iBPKk3ao30zc/Itmi7FvXo4oPaL9PmzPPQhyniPVgVg==} - - '@textlint/module-interop@15.5.2': - resolution: {integrity: sha512-mg6rMQ3+YjwiXCYoQXbyVfDucpTa1q5mhspd/9qHBxUq4uY6W8GU42rmT3GW0V1yOfQ9z/iRrgPtkp71s8JzXg==} - - '@textlint/resolver@15.5.2': - resolution: {integrity: sha512-YEITdjRiJaQrGLUWxWXl4TEg+d2C7+TNNjbGPHPH7V7CCnXm+S9GTjGAL7Q2WSGJyFEKt88Jvx6XdJffRv4HEA==} - - '@textlint/types@15.5.2': - resolution: {integrity: sha512-sJOrlVLLXp4/EZtiWKWq9y2fWyZlI8GP+24rnU5avtPWBIMm/1w97yzKrAqYF8czx2MqR391z5akhnfhj2f/AQ==} - - '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - - '@types/dompurify@3.2.0': - resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} - deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/node@22.19.13': - resolution: {integrity: sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==} - - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 - - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - - '@types/sarif@2.1.7': - resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} - - '@types/trusted-types@2.0.7': - resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - - '@types/vscode@1.109.0': - resolution: {integrity: sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==} - - '@typespec/ts-http-runtime@0.3.3': - resolution: {integrity: sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA==} - engines: {node: '>=20.0.0'} - - '@vitejs/plugin-react@5.1.4': - resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - - '@vitest/expect@4.0.18': - resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} - - '@vitest/mocker@4.0.18': - resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.0.18': - resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} - - '@vitest/runner@4.0.18': - resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} - - '@vitest/snapshot@4.0.18': - resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} - - '@vitest/spy@4.0.18': - resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} - - '@vitest/utils@4.0.18': - resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} - - '@vscode/vsce-sign-alpine-arm64@2.0.6': - resolution: {integrity: sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==} - cpu: [arm64] - os: [alpine] - - '@vscode/vsce-sign-alpine-x64@2.0.6': - resolution: {integrity: sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==} - cpu: [x64] - os: [alpine] - - '@vscode/vsce-sign-darwin-arm64@2.0.6': - resolution: {integrity: sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==} - cpu: [arm64] - os: [darwin] - - '@vscode/vsce-sign-darwin-x64@2.0.6': - resolution: {integrity: sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==} - cpu: [x64] - os: [darwin] - - '@vscode/vsce-sign-linux-arm64@2.0.6': - resolution: {integrity: sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==} - cpu: [arm64] - os: [linux] - - '@vscode/vsce-sign-linux-arm@2.0.6': - resolution: {integrity: sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==} - cpu: [arm] - os: [linux] - - '@vscode/vsce-sign-linux-x64@2.0.6': - resolution: {integrity: sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==} - cpu: [x64] - os: [linux] - - '@vscode/vsce-sign-win32-arm64@2.0.6': - resolution: {integrity: sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==} - cpu: [arm64] - os: [win32] - - '@vscode/vsce-sign-win32-x64@2.0.6': - resolution: {integrity: sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==} - cpu: [x64] - os: [win32] - - '@vscode/vsce-sign@2.0.9': - resolution: {integrity: sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==} - - '@vscode/vsce@3.7.1': - resolution: {integrity: sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g==} - engines: {node: '>= 20'} - hasBin: true - - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} - - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - - ansi-escapes@7.3.0: - resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} - engines: {node: '>=18'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - azure-devops-node-api@12.5.0: - resolution: {integrity: sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - baseline-browser-mapping@2.10.0: - resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} - engines: {node: '>=6.0.0'} - hasBin: true - - bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - - binaryextensions@6.11.0: - resolution: {integrity: sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==} - engines: {node: '>=4'} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - boundary@2.0.0: - resolution: {integrity: sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==} - - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - - brace-expansion@5.0.4: - resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} - engines: {node: 18 || 20 || >=22} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - - buffer-equal-constant-time@1.0.1: - resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - caniuse-lite@1.0.30001776: - resolution: {integrity: sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==} - - chai@6.2.2: - resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} - engines: {node: '>=18'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - - cheerio@1.2.0: - resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} - engines: {node: '>=20.18.1'} - - chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - cockatiel@3.2.1: - resolution: {integrity: sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==} - engines: {node: '>=16'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - - css-tree@3.1.0: - resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} - - css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - - cssstyle@6.2.0: - resolution: {integrity: sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==} - engines: {node: '>=20'} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - data-urls@7.0.0: - resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - default-browser-id@5.0.1: - resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} - engines: {node: '>=18'} - - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} - engines: {node: '>=18'} - - define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - diff@8.0.3: - resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} - engines: {node: '>=0.3.1'} - - dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - - dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - - dompurify@3.3.1: - resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} - - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - - editions@6.22.0: - resolution: {integrity: sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==} - engines: {ecmascript: '>= es5', node: '>=4'} - - electron-to-chromium@1.5.307: - resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - encoding-sniffer@0.2.1: - resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} - - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} - - entities@7.0.1: - resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} - engines: {node: '>=0.12'} - - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} - engines: {node: '>=12.0.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} - - fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - fs-extra@11.3.4: - resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} - engines: {node: '>=14.14'} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@11.1.0: - resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} - engines: {node: 20 || >=22} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - hasBin: true - - globby@14.1.0: - resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} - engines: {node: '>=18'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - highlight.js@11.11.1: - resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} - engines: {node: '>=12.0.0'} - - hosted-git-info@4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} - engines: {node: '>=10'} - - hosted-git-info@7.0.2: - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} - engines: {node: ^16.14.0 || >=18.0.0} - - html-encoding-sniffer@6.0.0: - resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - htmlparser2@10.1.0: - resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - index-to-position@1.2.0: - resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} - engines: {node: '>=18'} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - - is-wsl@3.1.1: - resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} - engines: {node: '>=16'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - istextorbinary@9.5.0: - resolution: {integrity: sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==} - engines: {node: '>=4'} - - jackspeak@4.2.3: - resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} - engines: {node: 20 || >=22} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true - - jsdom@28.1.0: - resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonc-parser@3.3.1: - resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - - jsonwebtoken@9.0.3: - resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} - engines: {node: '>=12', npm: '>=6'} - - jwa@2.0.1: - resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - - jws@4.0.1: - resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} - - keytar@7.9.0: - resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} - - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - - lodash.includes@4.3.0: - resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} - - lodash.isboolean@3.0.3: - resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} - - lodash.isinteger@4.0.4: - resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} - - lodash.isnumber@3.0.3: - resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} - - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - - lodash.isstring@4.0.1: - resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - - lodash.once@4.1.1: - resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - - lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - - lodash@4.17.23: - resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@11.2.6: - resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} - engines: {node: 20 || >=22} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - markdown-it@14.1.1: - resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} - hasBin: true - - marked@17.0.4: - resolution: {integrity: sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==} - engines: {node: '>= 20'} - hasBin: true - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - mdn-data@2.12.2: - resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} - - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - - minimatch@10.2.4: - resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} - engines: {node: 18 || 20 || >=22} - - minimatch@3.1.5: - resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass@7.1.3: - resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} - engines: {node: '>=16 || 14 >=14.17'} - - mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - napi-build-utils@2.0.0: - resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - - node-abi@3.87.0: - resolution: {integrity: sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==} - engines: {node: '>=10'} - - node-addon-api@4.3.0: - resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} - - node-releases@2.0.36: - resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} - - node-sarif-builder@3.4.0: - resolution: {integrity: sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==} - engines: {node: '>=20'} - - normalize-package-data@6.0.2: - resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} - engines: {node: ^16.14.0 || >=18.0.0} - - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - open@10.2.0: - resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} - engines: {node: '>=18'} - - p-map@7.0.4: - resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} - engines: {node: '>=18'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - parse-json@8.3.0: - resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} - engines: {node: '>=18'} - - parse-semver@1.1.1: - resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} - - parse5-htmlparser2-tree-adapter@7.1.0: - resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} - - parse5-parser-stream@7.1.2: - resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} - - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - - parse5@8.0.0: - resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-scurry@2.0.2: - resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} - engines: {node: 18 || 20 || >=22} - - path-type@6.0.0: - resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} - engines: {node: '>=18'} - - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - - pluralize@2.0.0: - resolution: {integrity: sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==} - - pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - - prebuild-install@7.1.3: - resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} - engines: {node: '>=10'} - deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. - hasBin: true - - pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - qs@6.15.0: - resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} - engines: {node: '>=0.6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - rc-config-loader@4.1.4: - resolution: {integrity: sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} - peerDependencies: - react: ^19.2.4 - - react-icons@5.6.0: - resolution: {integrity: sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==} - peerDependencies: - react: '*' - - react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - - react-refresh@0.18.0: - resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} - engines: {node: '>=0.10.0'} - - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} - engines: {node: '>=0.10.0'} - - read-pkg@9.0.1: - resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} - engines: {node: '>=18'} - - read@1.0.7: - resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} - engines: {node: '>=0.8'} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-applescript@7.1.0: - resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} - engines: {node: '>=18'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - sax@1.5.0: - resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} - engines: {node: '>=11.0.0'} - - saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - secretlint@10.2.2: - resolution: {integrity: sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==} - engines: {node: '>=20.0.0'} - hasBin: true - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} - engines: {node: '>=10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - - slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - - spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.23: - resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} - - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - structured-source@4.0.0: - resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-hyperlinks@3.2.0: - resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} - engines: {node: '>=14.18'} - - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - - table@6.9.0: - resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} - engines: {node: '>=10.0.0'} - - tar-fs@2.1.4: - resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} - - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - - terminal-link@4.0.0: - resolution: {integrity: sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==} - engines: {node: '>=18'} - - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - textextensions@6.11.0: - resolution: {integrity: sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==} - engines: {node: '>=4'} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} - engines: {node: '>=18'} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - tinyrainbow@3.0.3: - resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} - engines: {node: '>=14.0.0'} - - tldts-core@7.0.24: - resolution: {integrity: sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw==} - - tldts@7.0.24: - resolution: {integrity: sha512-1r6vQTTt1rUiJkI5vX7KG8PR342Ru/5Oh13kEQP2SMbRSZpOey9SrBe27IDxkoWulx8ShWu4K6C0BkctP8Z1bQ==} - hasBin: true - - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} - engines: {node: '>=14.14'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tough-cookie@6.0.0: - resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} - engines: {node: '>=16'} - - tr46@6.0.0: - resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} - engines: {node: '>=20'} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - - tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - - typed-rest-client@1.8.11: - resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - - underscore@1.13.8: - resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} - - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - - undici@7.22.0: - resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} - engines: {node: '>=20.18.1'} - - unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} - - unicorn-magic@0.3.0: - resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} - engines: {node: '>=18'} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - url-join@4.0.1: - resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - version-range@4.15.0: - resolution: {integrity: sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==} - engines: {node: '>=4'} - - vite@6.4.1: - resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@4.0.18: - resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.18 - '@vitest/browser-preview': 4.0.18 - '@vitest/browser-webdriverio': 4.0.18 - '@vitest/ui': 4.0.18 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/browser-playwright': - optional: true - '@vitest/browser-preview': - optional: true - '@vitest/browser-webdriverio': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} - - webidl-conversions@8.0.1: - resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} - engines: {node: '>=20'} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - whatwg-mimetype@5.0.0: - resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} - engines: {node: '>=20'} - - whatwg-url@16.0.1: - resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - wsl-utils@0.1.0: - resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} - engines: {node: '>=18'} - - xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - - xml2js@0.5.0: - resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} - engines: {node: '>=4.0.0'} - - xmlbuilder@11.0.1: - resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} - engines: {node: '>=4.0'} - - xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - - yazl@2.5.1: - resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} - -snapshots: - - '@acemir/cssom@0.9.31': {} - - '@adobe/css-tools@4.4.4': {} - - '@asamuzakjp/css-color@5.0.1': - dependencies: - '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - lru-cache: 11.2.6 - - '@asamuzakjp/dom-selector@6.8.1': - dependencies: - '@asamuzakjp/nwsapi': 2.3.9 - bidi-js: 1.0.3 - css-tree: 3.1.0 - is-potential-custom-element-name: 1.0.1 - lru-cache: 11.2.6 - - '@asamuzakjp/nwsapi@2.3.9': {} - - '@azu/format-text@1.0.2': {} - - '@azu/style-format@1.0.1': - dependencies: - '@azu/format-text': 1.0.2 - - '@azure/abort-controller@2.1.2': - dependencies: - tslib: 2.8.1 - - '@azure/core-auth@1.10.1': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-util': 1.13.1 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-client@1.10.1': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1 - '@azure/core-rest-pipeline': 1.22.2 - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1 - '@azure/logger': 1.3.0 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-rest-pipeline@1.22.2': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1 - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1 - '@azure/logger': 1.3.0 - '@typespec/ts-http-runtime': 0.3.3 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-tracing@1.3.1': - dependencies: - tslib: 2.8.1 - - '@azure/core-util@1.13.1': - dependencies: - '@azure/abort-controller': 2.1.2 - '@typespec/ts-http-runtime': 0.3.3 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/identity@4.13.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1 - '@azure/core-client': 1.10.1 - '@azure/core-rest-pipeline': 1.22.2 - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1 - '@azure/logger': 1.3.0 - '@azure/msal-browser': 4.29.0 - '@azure/msal-node': 3.8.8 - open: 10.2.0 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/logger@1.3.0': - dependencies: - '@typespec/ts-http-runtime': 0.3.3 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/msal-browser@4.29.0': - dependencies: - '@azure/msal-common': 15.15.0 - - '@azure/msal-common@15.15.0': {} - - '@azure/msal-node@3.8.8': - dependencies: - '@azure/msal-common': 15.15.0 - jsonwebtoken: 9.0.3 - uuid: 8.3.2 - - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.0': {} - - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.28.6': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.0': - dependencies: - '@babel/types': 7.29.0 - - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/runtime@7.28.6': {} - - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - - '@babel/traverse@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@biomejs/biome@2.4.4': - optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.4.4 - '@biomejs/cli-darwin-x64': 2.4.4 - '@biomejs/cli-linux-arm64': 2.4.4 - '@biomejs/cli-linux-arm64-musl': 2.4.4 - '@biomejs/cli-linux-x64': 2.4.4 - '@biomejs/cli-linux-x64-musl': 2.4.4 - '@biomejs/cli-win32-arm64': 2.4.4 - '@biomejs/cli-win32-x64': 2.4.4 - - '@biomejs/cli-darwin-arm64@2.4.4': - optional: true - - '@biomejs/cli-darwin-x64@2.4.4': - optional: true - - '@biomejs/cli-linux-arm64-musl@2.4.4': - optional: true - - '@biomejs/cli-linux-arm64@2.4.4': - optional: true - - '@biomejs/cli-linux-x64-musl@2.4.4': - optional: true - - '@biomejs/cli-linux-x64@2.4.4': - optional: true - - '@biomejs/cli-win32-arm64@2.4.4': - optional: true - - '@biomejs/cli-win32-x64@2.4.4': - optional: true - - '@bramus/specificity@2.4.2': - dependencies: - css-tree: 3.1.0 - - '@csstools/color-helpers@6.0.2': {} - - '@csstools/css-calc@3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': - dependencies: - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-color-parser@4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': - dependencies: - '@csstools/color-helpers': 6.0.2 - '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': - dependencies: - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-syntax-patches-for-csstree@1.0.29': {} - - '@csstools/css-tokenizer@4.0.0': {} - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true - - '@esbuild/linux-arm@0.25.12': - optional: true - - '@esbuild/linux-ia32@0.25.12': - optional: true - - '@esbuild/linux-loong64@0.25.12': - optional: true - - '@esbuild/linux-mips64el@0.25.12': - optional: true - - '@esbuild/linux-ppc64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-s390x@0.25.12': - optional: true - - '@esbuild/linux-x64@0.25.12': - optional: true - - '@esbuild/netbsd-arm64@0.25.12': - optional: true - - '@esbuild/netbsd-x64@0.25.12': - optional: true - - '@esbuild/openbsd-arm64@0.25.12': - optional: true - - '@esbuild/openbsd-x64@0.25.12': - optional: true - - '@esbuild/openharmony-arm64@0.25.12': - optional: true - - '@esbuild/sunos-x64@0.25.12': - optional: true - - '@esbuild/win32-arm64@0.25.12': - optional: true - - '@esbuild/win32-ia32@0.25.12': - optional: true - - '@esbuild/win32-x64@0.25.12': - optional: true - - '@exodus/bytes@1.15.0': {} - - '@isaacs/cliui@9.0.0': {} - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 - - '@opencode-ai/sdk@1.2.17': {} - - '@rolldown/pluginutils@1.0.0-rc.3': {} - - '@rollup/rollup-android-arm-eabi@4.59.0': - optional: true - - '@rollup/rollup-android-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-x64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.59.0': - optional: true - - '@rollup/rollup-openbsd-x64@4.59.0': - optional: true - - '@rollup/rollup-openharmony-arm64@4.59.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.59.0': - optional: true - - '@secretlint/config-creator@10.2.2': - dependencies: - '@secretlint/types': 10.2.2 - - '@secretlint/config-loader@10.2.2': - dependencies: - '@secretlint/profiler': 10.2.2 - '@secretlint/resolver': 10.2.2 - '@secretlint/types': 10.2.2 - ajv: 8.18.0 - debug: 4.4.3 - rc-config-loader: 4.1.4 - transitivePeerDependencies: - - supports-color - - '@secretlint/core@10.2.2': - dependencies: - '@secretlint/profiler': 10.2.2 - '@secretlint/types': 10.2.2 - debug: 4.4.3 - structured-source: 4.0.0 - transitivePeerDependencies: - - supports-color - - '@secretlint/formatter@10.2.2': - dependencies: - '@secretlint/resolver': 10.2.2 - '@secretlint/types': 10.2.2 - '@textlint/linter-formatter': 15.5.2 - '@textlint/module-interop': 15.5.2 - '@textlint/types': 15.5.2 - chalk: 5.6.2 - debug: 4.4.3 - pluralize: 8.0.0 - strip-ansi: 7.2.0 - table: 6.9.0 - terminal-link: 4.0.0 - transitivePeerDependencies: - - supports-color - - '@secretlint/node@10.2.2': - dependencies: - '@secretlint/config-loader': 10.2.2 - '@secretlint/core': 10.2.2 - '@secretlint/formatter': 10.2.2 - '@secretlint/profiler': 10.2.2 - '@secretlint/source-creator': 10.2.2 - '@secretlint/types': 10.2.2 - debug: 4.4.3 - p-map: 7.0.4 - transitivePeerDependencies: - - supports-color - - '@secretlint/profiler@10.2.2': {} - - '@secretlint/resolver@10.2.2': {} - - '@secretlint/secretlint-formatter-sarif@10.2.2': - dependencies: - node-sarif-builder: 3.4.0 - - '@secretlint/secretlint-rule-no-dotenv@10.2.2': - dependencies: - '@secretlint/types': 10.2.2 - - '@secretlint/secretlint-rule-preset-recommend@10.2.2': {} - - '@secretlint/source-creator@10.2.2': - dependencies: - '@secretlint/types': 10.2.2 - istextorbinary: 9.5.0 - - '@secretlint/types@10.2.2': {} - - '@sindresorhus/merge-streams@2.3.0': {} - - '@standard-schema/spec@1.1.0': {} - - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/runtime': 7.28.6 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - picocolors: 1.1.1 - pretty-format: 27.5.1 - - '@testing-library/jest-dom@6.9.1': - dependencies: - '@adobe/css-tools': 4.4.4 - aria-query: 5.3.2 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - picocolors: 1.1.1 - redent: 3.0.0 - - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@babel/runtime': 7.28.6 - '@testing-library/dom': 10.4.1 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': - dependencies: - '@testing-library/dom': 10.4.1 - - '@textlint/ast-node-types@15.5.2': {} - - '@textlint/linter-formatter@15.5.2': - dependencies: - '@azu/format-text': 1.0.2 - '@azu/style-format': 1.0.1 - '@textlint/module-interop': 15.5.2 - '@textlint/resolver': 15.5.2 - '@textlint/types': 15.5.2 - chalk: 4.1.2 - debug: 4.4.3 - js-yaml: 4.1.1 - lodash: 4.17.23 - pluralize: 2.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - table: 6.9.0 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - '@textlint/module-interop@15.5.2': {} - - '@textlint/resolver@15.5.2': {} - - '@textlint/types@15.5.2': - dependencies: - '@textlint/ast-node-types': 15.5.2 - - '@types/aria-query@5.0.4': {} - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/chai@5.2.3': - dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 - - '@types/deep-eql@4.0.2': {} - - '@types/dompurify@3.2.0': - dependencies: - dompurify: 3.3.1 - - '@types/estree@1.0.8': {} - - '@types/node@22.19.13': - dependencies: - undici-types: 6.21.0 - - '@types/normalize-package-data@2.4.4': {} - - '@types/react-dom@19.2.3(@types/react@19.2.14)': - dependencies: - '@types/react': 19.2.14 - - '@types/react@19.2.14': - dependencies: - csstype: 3.2.3 - - '@types/sarif@2.1.7': {} - - '@types/trusted-types@2.0.7': - optional: true - - '@types/vscode@1.109.0': {} - - '@typespec/ts-http-runtime@0.3.3': - dependencies: - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@vitejs/plugin-react@5.1.4(vite@6.4.1(@types/node@22.19.13))': - dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-rc.3 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 - vite: 6.4.1(@types/node@22.19.13) - transitivePeerDependencies: - - supports-color - - '@vitest/expect@4.0.18': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 - chai: 6.2.2 - tinyrainbow: 3.0.3 - - '@vitest/mocker@4.0.18(vite@6.4.1(@types/node@22.19.13))': - dependencies: - '@vitest/spy': 4.0.18 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 6.4.1(@types/node@22.19.13) - - '@vitest/pretty-format@4.0.18': - dependencies: - tinyrainbow: 3.0.3 - - '@vitest/runner@4.0.18': - dependencies: - '@vitest/utils': 4.0.18 - pathe: 2.0.3 - - '@vitest/snapshot@4.0.18': - dependencies: - '@vitest/pretty-format': 4.0.18 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.0.18': {} - - '@vitest/utils@4.0.18': - dependencies: - '@vitest/pretty-format': 4.0.18 - tinyrainbow: 3.0.3 - - '@vscode/vsce-sign-alpine-arm64@2.0.6': - optional: true - - '@vscode/vsce-sign-alpine-x64@2.0.6': - optional: true - - '@vscode/vsce-sign-darwin-arm64@2.0.6': - optional: true - - '@vscode/vsce-sign-darwin-x64@2.0.6': - optional: true - - '@vscode/vsce-sign-linux-arm64@2.0.6': - optional: true - - '@vscode/vsce-sign-linux-arm@2.0.6': - optional: true - - '@vscode/vsce-sign-linux-x64@2.0.6': - optional: true - - '@vscode/vsce-sign-win32-arm64@2.0.6': - optional: true - - '@vscode/vsce-sign-win32-x64@2.0.6': - optional: true - - '@vscode/vsce-sign@2.0.9': - optionalDependencies: - '@vscode/vsce-sign-alpine-arm64': 2.0.6 - '@vscode/vsce-sign-alpine-x64': 2.0.6 - '@vscode/vsce-sign-darwin-arm64': 2.0.6 - '@vscode/vsce-sign-darwin-x64': 2.0.6 - '@vscode/vsce-sign-linux-arm': 2.0.6 - '@vscode/vsce-sign-linux-arm64': 2.0.6 - '@vscode/vsce-sign-linux-x64': 2.0.6 - '@vscode/vsce-sign-win32-arm64': 2.0.6 - '@vscode/vsce-sign-win32-x64': 2.0.6 - - '@vscode/vsce@3.7.1': - dependencies: - '@azure/identity': 4.13.0 - '@secretlint/node': 10.2.2 - '@secretlint/secretlint-formatter-sarif': 10.2.2 - '@secretlint/secretlint-rule-no-dotenv': 10.2.2 - '@secretlint/secretlint-rule-preset-recommend': 10.2.2 - '@vscode/vsce-sign': 2.0.9 - azure-devops-node-api: 12.5.0 - chalk: 4.1.2 - cheerio: 1.2.0 - cockatiel: 3.2.1 - commander: 12.1.0 - form-data: 4.0.5 - glob: 11.1.0 - hosted-git-info: 4.1.0 - jsonc-parser: 3.3.1 - leven: 3.1.0 - markdown-it: 14.1.1 - mime: 1.6.0 - minimatch: 3.1.5 - parse-semver: 1.1.1 - read: 1.0.7 - secretlint: 10.2.2 - semver: 7.7.4 - tmp: 0.2.5 - typed-rest-client: 1.8.11 - url-join: 4.0.1 - xml2js: 0.5.0 - yauzl: 2.10.0 - yazl: 2.5.1 - optionalDependencies: - keytar: 7.9.0 - transitivePeerDependencies: - - supports-color - - agent-base@7.1.4: {} - - ajv@8.18.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - argparse@2.0.1: {} - - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - - aria-query@5.3.2: {} - - assertion-error@2.0.1: {} - - astral-regex@2.0.0: {} - - asynckit@0.4.0: {} - - azure-devops-node-api@12.5.0: - dependencies: - tunnel: 0.0.6 - typed-rest-client: 1.8.11 - - balanced-match@1.0.2: {} - - balanced-match@4.0.4: {} - - base64-js@1.5.1: - optional: true - - baseline-browser-mapping@2.10.0: {} - - bidi-js@1.0.3: - dependencies: - require-from-string: 2.0.2 - - binaryextensions@6.11.0: - dependencies: - editions: 6.22.0 - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - optional: true - - boolbase@1.0.0: {} - - boundary@2.0.0: {} - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@5.0.4: - dependencies: - balanced-match: 4.0.4 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.10.0 - caniuse-lite: 1.0.30001776 - electron-to-chromium: 1.5.307 - node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - buffer-crc32@0.2.13: {} - - buffer-equal-constant-time@1.0.1: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - optional: true - - bundle-name@4.1.0: - dependencies: - run-applescript: 7.1.0 - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - caniuse-lite@1.0.30001776: {} - - chai@6.2.2: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - cheerio-select@2.1.0: - dependencies: - boolbase: 1.0.0 - css-select: 5.2.2 - css-what: 6.2.2 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - - cheerio@1.2.0: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - encoding-sniffer: 0.2.1 - htmlparser2: 10.1.0 - parse5: 7.3.0 - parse5-htmlparser2-tree-adapter: 7.1.0 - parse5-parser-stream: 7.1.2 - undici: 7.22.0 - whatwg-mimetype: 4.0.0 - - chownr@1.1.4: - optional: true - - cockatiel@3.2.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - commander@12.1.0: {} - - concat-map@0.0.1: {} - - convert-source-map@2.0.0: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-tree@3.1.0: - dependencies: - mdn-data: 2.12.2 - source-map-js: 1.2.1 - - css-what@6.2.2: {} - - css.escape@1.5.1: {} - - cssstyle@6.2.0: - dependencies: - '@asamuzakjp/css-color': 5.0.1 - '@csstools/css-syntax-patches-for-csstree': 1.0.29 - css-tree: 3.1.0 - lru-cache: 11.2.6 - - csstype@3.2.3: {} - - data-urls@7.0.0: - dependencies: - whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1 - transitivePeerDependencies: - - '@noble/hashes' - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decimal.js@10.6.0: {} - - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - optional: true - - deep-extend@0.6.0: - optional: true - - default-browser-id@5.0.1: {} - - default-browser@5.5.0: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.1 - - define-lazy-prop@3.0.0: {} - - delayed-stream@1.0.0: {} - - dequal@2.0.3: {} - - detect-libc@2.1.2: - optional: true - - diff@8.0.3: {} - - dom-accessibility-api@0.5.16: {} - - dom-accessibility-api@0.6.3: {} - - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - dompurify@3.3.1: - optionalDependencies: - '@types/trusted-types': 2.0.7 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - ecdsa-sig-formatter@1.0.11: - dependencies: - safe-buffer: 5.2.1 - - editions@6.22.0: - dependencies: - version-range: 4.15.0 - - electron-to-chromium@1.5.307: {} - - emoji-regex@8.0.0: {} - - encoding-sniffer@0.2.1: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding: 3.1.1 - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - optional: true - - entities@4.5.0: {} - - entities@6.0.1: {} - - entities@7.0.1: {} - - environment@1.1.0: {} - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@1.7.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - escalade@3.2.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - expand-template@2.0.3: - optional: true - - expect-type@1.3.0: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-uri@3.1.0: {} - - fastq@1.20.1: - dependencies: - reusify: 1.1.0 - - fd-slicer@1.1.0: - dependencies: - pend: 1.2.0 - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - fs-constants@1.0.0: - optional: true - - fs-extra@11.3.4: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - gensync@1.0.0-beta.2: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - github-from-package@0.0.0: - optional: true - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@11.1.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 4.2.3 - minimatch: 10.2.4 - minipass: 7.1.3 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.2 - - globby@14.1.0: - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.3 - ignore: 7.0.5 - path-type: 6.0.0 - slash: 5.1.0 - unicorn-magic: 0.3.0 - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - has-flag@4.0.0: {} - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - highlight.js@11.11.1: {} - - hosted-git-info@4.1.0: - dependencies: - lru-cache: 6.0.0 - - hosted-git-info@7.0.2: - dependencies: - lru-cache: 10.4.3 - - html-encoding-sniffer@6.0.0: - dependencies: - '@exodus/bytes': 1.15.0 - transitivePeerDependencies: - - '@noble/hashes' - - htmlparser2@10.1.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - entities: 7.0.1 - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: - optional: true - - ignore@7.0.5: {} - - indent-string@4.0.0: {} - - index-to-position@1.2.0: {} - - inherits@2.0.4: - optional: true - - ini@1.3.8: - optional: true - - is-docker@3.0.0: {} - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - - is-number@7.0.0: {} - - is-potential-custom-element-name@1.0.1: {} - - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - - isexe@2.0.0: {} - - istextorbinary@9.5.0: - dependencies: - binaryextensions: 6.11.0 - editions: 6.22.0 - textextensions: 6.11.0 - - jackspeak@4.2.3: - dependencies: - '@isaacs/cliui': 9.0.0 - - js-tokens@4.0.0: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - jsdom@28.1.0: - dependencies: - '@acemir/cssom': 0.9.31 - '@asamuzakjp/dom-selector': 6.8.1 - '@bramus/specificity': 2.4.2 - '@exodus/bytes': 1.15.0 - cssstyle: 6.2.0 - data-urls: 7.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 6.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - parse5: 8.0.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 6.0.0 - undici: 7.22.0 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 8.0.1 - whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - '@noble/hashes' - - supports-color - - jsesc@3.1.0: {} - - json-schema-traverse@1.0.0: {} - - json5@2.2.3: {} - - jsonc-parser@3.3.1: {} - - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsonwebtoken@9.0.3: - dependencies: - jws: 4.0.1 - lodash.includes: 4.3.0 - lodash.isboolean: 3.0.3 - lodash.isinteger: 4.0.4 - lodash.isnumber: 3.0.3 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.once: 4.1.1 - ms: 2.1.3 - semver: 7.7.4 - - jwa@2.0.1: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - - jws@4.0.1: - dependencies: - jwa: 2.0.1 - safe-buffer: 5.2.1 - - keytar@7.9.0: - dependencies: - node-addon-api: 4.3.0 - prebuild-install: 7.1.3 - optional: true - - leven@3.1.0: {} - - linkify-it@5.0.0: - dependencies: - uc.micro: 2.1.0 - - lodash.includes@4.3.0: {} - - lodash.isboolean@3.0.3: {} - - lodash.isinteger@4.0.4: {} - - lodash.isnumber@3.0.3: {} - - lodash.isplainobject@4.0.6: {} - - lodash.isstring@4.0.1: {} - - lodash.once@4.1.1: {} - - lodash.truncate@4.4.2: {} - - lodash@4.17.23: {} - - lru-cache@10.4.3: {} - - lru-cache@11.2.6: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - - lz-string@1.5.0: {} - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - markdown-it@14.1.1: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.0 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - - marked@17.0.4: {} - - math-intrinsics@1.1.0: {} - - mdn-data@2.12.2: {} - - mdurl@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@1.6.0: {} - - mimic-response@3.1.0: - optional: true - - min-indent@1.0.1: {} - - minimatch@10.2.4: - dependencies: - brace-expansion: 5.0.4 - - minimatch@3.1.5: - dependencies: - brace-expansion: 1.1.12 - - minimist@1.2.8: - optional: true - - minipass@7.1.3: {} - - mkdirp-classic@0.5.3: - optional: true - - ms@2.1.3: {} - - mute-stream@0.0.8: {} - - nanoid@3.3.11: {} - - napi-build-utils@2.0.0: - optional: true - - node-abi@3.87.0: - dependencies: - semver: 7.7.4 - optional: true - - node-addon-api@4.3.0: - optional: true - - node-releases@2.0.36: {} - - node-sarif-builder@3.4.0: - dependencies: - '@types/sarif': 2.1.7 - fs-extra: 11.3.4 - - normalize-package-data@6.0.2: - dependencies: - hosted-git-info: 7.0.2 - semver: 7.7.4 - validate-npm-package-license: 3.0.4 - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - object-inspect@1.13.4: {} - - obug@2.1.1: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - optional: true - - open@10.2.0: - dependencies: - default-browser: 5.5.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - wsl-utils: 0.1.0 - - p-map@7.0.4: {} - - package-json-from-dist@1.0.1: {} - - parse-json@8.3.0: - dependencies: - '@babel/code-frame': 7.29.0 - index-to-position: 1.2.0 - type-fest: 4.41.0 - - parse-semver@1.1.1: - dependencies: - semver: 5.7.2 - - parse5-htmlparser2-tree-adapter@7.1.0: - dependencies: - domhandler: 5.0.3 - parse5: 7.3.0 - - parse5-parser-stream@7.1.2: - dependencies: - parse5: 7.3.0 - - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - parse5@8.0.0: - dependencies: - entities: 6.0.1 - - path-key@3.1.1: {} - - path-scurry@2.0.2: - dependencies: - lru-cache: 11.2.6 - minipass: 7.1.3 - - path-type@6.0.0: {} - - pathe@2.0.3: {} - - pend@1.2.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - pluralize@2.0.0: {} - - pluralize@8.0.0: {} - - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prebuild-install@7.1.3: - dependencies: - detect-libc: 2.1.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 2.0.0 - node-abi: 3.87.0 - pump: 3.0.4 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.4 - tunnel-agent: 0.6.0 - optional: true - - pretty-format@27.5.1: - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - optional: true - - punycode.js@2.3.1: {} - - punycode@2.3.1: {} - - qs@6.15.0: - dependencies: - side-channel: 1.1.0 - - queue-microtask@1.2.3: {} - - rc-config-loader@4.1.4: - dependencies: - debug: 4.4.3 - js-yaml: 4.1.1 - json5: 2.2.3 - require-from-string: 2.0.2 - transitivePeerDependencies: - - supports-color - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - optional: true - - react-dom@19.2.4(react@19.2.4): - dependencies: - react: 19.2.4 - scheduler: 0.27.0 - - react-icons@5.6.0(react@19.2.4): - dependencies: - react: 19.2.4 - - react-is@17.0.2: {} - - react-refresh@0.18.0: {} - - react@19.2.4: {} - - read-pkg@9.0.1: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 6.0.2 - parse-json: 8.3.0 - type-fest: 4.41.0 - unicorn-magic: 0.1.0 - - read@1.0.7: - dependencies: - mute-stream: 0.0.8 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - optional: true - - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - - require-from-string@2.0.2: {} - - reusify@1.1.0: {} - - rollup@4.59.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 - fsevents: 2.3.3 - - run-applescript@7.1.0: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - sax@1.5.0: {} - - saxes@6.0.0: - dependencies: - xmlchars: 2.2.0 - - scheduler@0.27.0: {} - - secretlint@10.2.2: - dependencies: - '@secretlint/config-creator': 10.2.2 - '@secretlint/formatter': 10.2.2 - '@secretlint/node': 10.2.2 - '@secretlint/profiler': 10.2.2 - debug: 4.4.3 - globby: 14.1.0 - read-pkg: 9.0.1 - transitivePeerDependencies: - - supports-color - - semver@5.7.2: {} - - semver@6.3.1: {} - - semver@7.7.4: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - - simple-concat@1.0.1: - optional: true - - simple-get@4.0.1: - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - optional: true - - slash@5.1.0: {} - - slice-ansi@4.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - source-map-js@1.2.1: {} - - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.23 - - spdx-exceptions@2.5.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.23 - - spdx-license-ids@3.0.23: {} - - stackback@0.0.2: {} - - std-env@3.10.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - optional: true - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - - strip-json-comments@2.0.1: - optional: true - - structured-source@4.0.0: - dependencies: - boundary: 2.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-hyperlinks@3.2.0: - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - - symbol-tree@3.2.4: {} - - table@6.9.0: - dependencies: - ajv: 8.18.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - tar-fs@2.1.4: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.4 - tar-stream: 2.2.0 - optional: true - - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.5 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - optional: true - - terminal-link@4.0.0: - dependencies: - ansi-escapes: 7.3.0 - supports-hyperlinks: 3.2.0 - - text-table@0.2.0: {} - - textextensions@6.11.0: - dependencies: - editions: 6.22.0 - - tinybench@2.9.0: {} - - tinyexec@1.0.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinyrainbow@3.0.3: {} - - tldts-core@7.0.24: {} - - tldts@7.0.24: - dependencies: - tldts-core: 7.0.24 - - tmp@0.2.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - tough-cookie@6.0.0: - dependencies: - tldts: 7.0.24 - - tr46@6.0.0: - dependencies: - punycode: 2.3.1 - - tslib@2.8.1: {} - - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - optional: true - - tunnel@0.0.6: {} - - type-fest@4.41.0: {} - - typed-rest-client@1.8.11: - dependencies: - qs: 6.15.0 - tunnel: 0.0.6 - underscore: 1.13.8 - - typescript@5.9.3: {} - - uc.micro@2.1.0: {} - - underscore@1.13.8: {} - - undici-types@6.21.0: {} - - undici@7.22.0: {} - - unicorn-magic@0.1.0: {} - - unicorn-magic@0.3.0: {} - - universalify@2.0.1: {} - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 - - url-join@4.0.1: {} - - util-deprecate@1.0.2: - optional: true - - uuid@8.3.2: {} - - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - - version-range@4.15.0: {} - - vite@6.4.1(@types/node@22.19.13): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.8 - rollup: 4.59.0 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 22.19.13 - fsevents: 2.3.3 - - vitest@4.0.18(@types/node@22.19.13)(jsdom@28.1.0): - dependencies: - '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@6.4.1(@types/node@22.19.13)) - '@vitest/pretty-format': 4.0.18 - '@vitest/runner': 4.0.18 - '@vitest/snapshot': 4.0.18 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 - es-module-lexer: 1.7.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 6.4.1(@types/node@22.19.13) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 22.19.13 - jsdom: 28.1.0 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml - - w3c-xmlserializer@5.0.0: - dependencies: - xml-name-validator: 5.0.0 - - webidl-conversions@8.0.1: {} - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - - whatwg-mimetype@5.0.0: {} - - whatwg-url@16.0.1: - dependencies: - '@exodus/bytes': 1.15.0 - tr46: 6.0.0 - webidl-conversions: 8.0.1 - transitivePeerDependencies: - - '@noble/hashes' - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - wrappy@1.0.2: - optional: true - - wsl-utils@0.1.0: - dependencies: - is-wsl: 3.1.1 - - xml-name-validator@5.0.0: {} - - xml2js@0.5.0: - dependencies: - sax: 1.5.0 - xmlbuilder: 11.0.1 - - xmlbuilder@11.0.1: {} - - xmlchars@2.2.0: {} - - yallist@3.1.1: {} - - yallist@4.0.0: {} - - yauzl@2.10.0: - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - - yazl@2.5.1: - dependencies: - buffer-crc32: 0.2.13 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 332c086..0000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -packages: - - "packages/*" - - "packages/agents/*" - - "packages/platforms/*" -onlyBuiltDependencies: - - esbuild diff --git a/packages/platforms/vscode/src/__tests__/chat-view-provider.test.ts b/src/__tests__/chat-view-provider.test.ts similarity index 96% rename from packages/platforms/vscode/src/__tests__/chat-view-provider.test.ts rename to src/__tests__/chat-view-provider.test.ts index de2bd9a..0cbc947 100644 --- a/packages/platforms/vscode/src/__tests__/chat-view-provider.test.ts +++ b/src/__tests__/chat-view-provider.test.ts @@ -1,6 +1,6 @@ /** * ChatViewProvider のユニットテスト。 - * IAgent をモックし、webview メッセージハンドラの振る舞いを検証する。 + * OpenCodeAgent をモックし、webview メッセージハンドラの振る舞いを検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -12,32 +12,23 @@ vi.mock("node:fs/promises", () => ({ })); import * as fs from "node:fs/promises"; -import type { IAgent, IPlatformServices } from "@opencodegui/core"; import * as vscode from "vscode"; import { ChatViewProvider } from "../chat-view-provider"; import type { DiffReviewManager } from "../diff-review-manager"; +import type { OpenCodeAgent } from "../opencode-agent"; +import type { VscodePlatformServices } from "../vscode-platform-services"; -// --- Helper: IAgent のモック --- +// --- Helper: OpenCodeAgent のモック --- -function createMockAgent(): { - [K in keyof IAgent]: IAgent[K] extends (...args: never[]) => unknown ? ReturnType : IAgent[K]; -} { +type MockedMethods = { + [K in keyof T]: T[K] extends (...args: never[]) => unknown ? ReturnType : T[K]; +}; + +type MockOpenCodeAgent = MockedMethods; +type MockVscodePlatformServices = MockedMethods; + +function createMockAgent(): MockOpenCodeAgent { return { - getCapabilities: vi.fn().mockReturnValue({ - sessionDelete: true, - sessionFork: true, - sessionRevert: true, - sessionShare: true, - sessionSummarize: true, - sessionDiff: true, - todo: true, - multiProvider: true, - permission: true, - mcp: true, - subAgent: true, - shell: true, - config: true, - }), connect: vi.fn().mockResolvedValue(undefined), disconnect: vi.fn(), onEvent: vi.fn().mockReturnValue({ dispose: vi.fn() }), @@ -61,6 +52,8 @@ function createMockAgent(): { getSkills: vi.fn().mockResolvedValue([]), getChildSessions: vi.fn().mockResolvedValue([]), replyPermission: vi.fn().mockResolvedValue(undefined), + replyQuestion: vi.fn().mockResolvedValue(undefined), + rejectQuestion: vi.fn().mockResolvedValue(undefined), getSessionDiff: vi.fn().mockResolvedValue([]), getSessionTodos: vi.fn().mockResolvedValue([]), getConfig: vi.fn().mockResolvedValue({}), @@ -72,14 +65,12 @@ function createMockAgent(): { getToolIds: vi.fn().mockResolvedValue([]), getServerUrl: vi.fn().mockReturnValue("http://localhost:12345"), setModel: vi.fn().mockResolvedValue(undefined), - } as never; + } as MockOpenCodeAgent; } -// --- Helper: IPlatformServices のモック --- +// --- Helper: VscodePlatformServices のモック --- -function createMockPlatformServices(): { - [K in keyof IPlatformServices]: ReturnType; -} { +function createMockPlatformServices(): MockVscodePlatformServices { return { openDiffEditor: vi.fn().mockResolvedValue(undefined), copyToClipboard: vi.fn().mockResolvedValue(undefined), @@ -88,7 +79,7 @@ function createMockPlatformServices(): { openFile: vi.fn().mockResolvedValue(undefined), searchWorkspaceFiles: vi.fn().mockResolvedValue([]), getOpenEditors: vi.fn().mockResolvedValue([]), - }; + } as MockVscodePlatformServices; } // --- Helper: DiffReviewManager のモック --- @@ -322,21 +313,6 @@ describe("ChatViewProvider", () => { type: "init", locale: "en", paths: { config: "/home/.config/opencode", data: "/home/.data" }, - capabilities: expect.objectContaining({ - sessionDelete: true, - sessionFork: true, - sessionRevert: true, - sessionShare: true, - sessionSummarize: true, - sessionDiff: true, - todo: true, - multiProvider: true, - permission: true, - mcp: true, - subAgent: true, - shell: true, - config: true, - }), }), ); @@ -490,7 +466,7 @@ describe("ChatViewProvider", () => { // ============================================================ describe("sendMessage", () => { - it("should call agent.sendMessage with correct args (IAgent signature)", async () => { + it("should call agent.sendMessage with correct args", async () => { const { sendMessage } = setupProvider(mockAgent); await sendMessage({ @@ -724,7 +700,7 @@ describe("ChatViewProvider", () => { sessionId: "sess-1", messages: [], }); - // 3. send new message (IAgent signature with options) + // 3. send new message with options expect(mockAgent.sendMessage).toHaveBeenCalledWith("sess-1", "Updated text", { model: { providerID: "openai", modelID: "gpt-4" }, files: [{ filePath: "a.ts", fileName: "a.ts" }], diff --git a/packages/platforms/vscode/src/__tests__/diff-review-manager.test.ts b/src/__tests__/diff-review-manager.test.ts similarity index 100% rename from packages/platforms/vscode/src/__tests__/diff-review-manager.test.ts rename to src/__tests__/diff-review-manager.test.ts diff --git a/packages/platforms/vscode/src/__tests__/extension.test.ts b/src/__tests__/extension.test.ts similarity index 99% rename from packages/platforms/vscode/src/__tests__/extension.test.ts rename to src/__tests__/extension.test.ts index d11c32a..e606edb 100644 --- a/packages/platforms/vscode/src/__tests__/extension.test.ts +++ b/src/__tests__/extension.test.ts @@ -54,7 +54,7 @@ describe("extension", () => { async function importExtension() { vi.resetModules(); - vi.doMock("@opencodegui/agent-opencode", () => ({ + vi.doMock("../opencode-agent", () => ({ OpenCodeAgent: createMockAgentClass(), })); vi.doMock("../chat-view-provider", () => ({ diff --git a/packages/agents/opencode/src/__tests__/mappers.test.ts b/src/__tests__/mappers.test.ts similarity index 100% rename from packages/agents/opencode/src/__tests__/mappers.test.ts rename to src/__tests__/mappers.test.ts diff --git a/packages/platforms/vscode/src/__tests__/mocks/vscode.ts b/src/__tests__/mocks/vscode.ts similarity index 100% rename from packages/platforms/vscode/src/__tests__/mocks/vscode.ts rename to src/__tests__/mocks/vscode.ts diff --git a/packages/agents/opencode/src/__tests__/opencode-agent.test.ts b/src/__tests__/opencode-agent.test.ts similarity index 97% rename from packages/agents/opencode/src/__tests__/opencode-agent.test.ts rename to src/__tests__/opencode-agent.test.ts index 6e2b80c..162bc92 100644 --- a/packages/agents/opencode/src/__tests__/opencode-agent.test.ts +++ b/src/__tests__/opencode-agent.test.ts @@ -110,30 +110,6 @@ describe("OpenCodeAgent", () => { vi.clearAllMocks(); }); - // ============================================================ - // getCapabilities - // ============================================================ - - describe("getCapabilities()", () => { - it("should return all capabilities as true", () => { - const caps = agent.getCapabilities(); - - expect(caps.sessionDelete).toBe(true); - expect(caps.sessionFork).toBe(true); - expect(caps.sessionRevert).toBe(true); - expect(caps.sessionShare).toBe(true); - expect(caps.sessionSummarize).toBe(true); - expect(caps.sessionDiff).toBe(true); - expect(caps.todo).toBe(true); - expect(caps.multiProvider).toBe(true); - expect(caps.permission).toBe(true); - expect(caps.mcp).toBe(true); - expect(caps.subAgent).toBe(true); - expect(caps.shell).toBe(true); - expect(caps.config).toBe(true); - }); - }); - // ============================================================ // connect / disconnect / lifecycle // ============================================================ diff --git a/packages/platforms/vscode/src/__tests__/setup.ts b/src/__tests__/setup.ts similarity index 100% rename from packages/platforms/vscode/src/__tests__/setup.ts rename to src/__tests__/setup.ts diff --git a/packages/platforms/vscode/src/chat-view-provider.ts b/src/chat-view-provider.ts similarity index 97% rename from packages/platforms/vscode/src/chat-view-provider.ts rename to src/chat-view-provider.ts index 0dc4f21..cd8419c 100644 --- a/packages/platforms/vscode/src/chat-view-provider.ts +++ b/src/chat-view-provider.ts @@ -1,8 +1,10 @@ import * as fs from "node:fs/promises"; import * as path from "node:path"; -import type { ChatSession, HostToUIMessage, IAgent, IPlatformServices, UIToHostMessage } from "@opencodegui/core"; +import type { ChatSession, FileAttachment, HostToUIMessage, UIToHostMessage } from "@shared"; import * as vscode from "vscode"; import type { DiffReviewManager } from "./diff-review-manager"; +import type { OpenCodeAgent } from "./opencode-agent"; +import type { VscodePlatformServices } from "./vscode-platform-services"; export class ChatViewProvider implements vscode.WebviewViewProvider { public static readonly viewType = "opencode.chatView"; @@ -14,8 +16,8 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { constructor( private readonly extensionUri: vscode.Uri, - private readonly agent: IAgent, - private readonly platformServices: IPlatformServices, + private readonly agent: OpenCodeAgent, + private readonly platformServices: VscodePlatformServices, private readonly diffReviewManager: DiffReviewManager, private readonly difitAvailable: boolean, ) {} @@ -63,7 +65,6 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { const paths = await this.agent.getPath(); this.postMessage({ type: "init", - capabilities: this.agent.getCapabilities(), locale: vscode.env.language, paths, }); @@ -181,7 +182,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { }); break; } - // --- Platform operations delegated to IPlatformServices --- + // --- Platform operations --- case "getOpenEditors": { const files = await this.platformServices.getOpenEditors(); this.postMessage({ type: "openEditors", files }); @@ -347,9 +348,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } /** アクティブなテキストエディタから FileAttachment を生成する。エディタがない場合は null を返す。 */ - private getActiveEditorFile( - editor: vscode.TextEditor | undefined, - ): import("@opencodegui/core").FileAttachment | null { + private getActiveEditorFile(editor: vscode.TextEditor | undefined): FileAttachment | null { if (!editor) return null; const uri = editor.document.uri; // 出力パネルや設定画面など、file スキーム以外は対象外 diff --git a/packages/platforms/vscode/src/diff-review-manager.ts b/src/diff-review-manager.ts similarity index 98% rename from packages/platforms/vscode/src/diff-review-manager.ts rename to src/diff-review-manager.ts index b816e3d..02038d8 100644 --- a/packages/platforms/vscode/src/diff-review-manager.ts +++ b/src/diff-review-manager.ts @@ -1,6 +1,6 @@ import type { ChildProcess } from "node:child_process"; import { spawn } from "node:child_process"; -import type { FileDiff } from "@opencodegui/core"; +import type { FileDiff } from "@shared"; import { createTwoFilesPatch } from "diff"; import * as vscode from "vscode"; diff --git a/packages/platforms/vscode/src/extension.ts b/src/extension.ts similarity index 98% rename from packages/platforms/vscode/src/extension.ts rename to src/extension.ts index 10f2237..d6da7ce 100644 --- a/packages/platforms/vscode/src/extension.ts +++ b/src/extension.ts @@ -1,8 +1,8 @@ import { execFile } from "node:child_process"; -import { OpenCodeAgent } from "@opencodegui/agent-opencode"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; import { DiffReviewManager } from "./diff-review-manager"; +import { OpenCodeAgent } from "./opencode-agent"; import { VscodePlatformServices } from "./vscode-platform-services"; const agent = new OpenCodeAgent(); diff --git a/packages/agents/opencode/src/mappers.ts b/src/mappers.ts similarity index 95% rename from packages/agents/opencode/src/mappers.ts rename to src/mappers.ts index 750dd29..7eb1340 100644 --- a/packages/agents/opencode/src/mappers.ts +++ b/src/mappers.ts @@ -1,7 +1,7 @@ /** - * @opencodegui/agent-opencode - SDK→Domain Type Mappers + * ./opencode-agent - SDK→Domain Type Mappers * - * Converts types from @opencode-ai/sdk to @opencodegui/core domain types. + * Converts types from @opencode-ai/sdk to @shared domain types. * Each mapper is a pure function with no side effects. */ @@ -35,7 +35,7 @@ import type { SkillInfo, TodoItem, ToolListItem, -} from "@opencodegui/core"; +} from "@shared"; // ============================================================ // Session @@ -167,7 +167,7 @@ export function mapMcpStatus(status: Record): McpStatus { // ============================================================ /** - * SDK's tool.ids() returns string[], but IAgent.getToolIds() returns ToolListItem[]. + * SDK's tool.ids() returns string[], while the webview consumes ToolListItem[]. * Wrap each string ID into a ToolListItem. */ export function mapToolIds(ids: string[]): ToolListItem[] { diff --git a/packages/agents/opencode/src/opencode-agent.ts b/src/opencode-agent.ts similarity index 92% rename from packages/agents/opencode/src/opencode-agent.ts rename to src/opencode-agent.ts index 9740369..c9f78bd 100644 --- a/packages/agents/opencode/src/opencode-agent.ts +++ b/src/opencode-agent.ts @@ -1,18 +1,11 @@ /** - * @opencodegui/agent-opencode - OpenCodeAgent - * - * Implements the IAgent interface from @opencodegui/core, wrapping the - * @opencode-ai/sdk to communicate with an OpenCode server. - * - * This is a direct port of the original `opencode-client.ts` (OpenCodeConnection), - * adapted to the IAgent contract with SDK→domain type conversion via mappers. + * OpenCode SDK integration used by the VS Code extension host. */ import * as fs from "node:fs/promises"; import * as path from "node:path"; import { createOpencodeClient, createOpencodeServer, type Event, type OpencodeClient } from "@opencode-ai/sdk/v2"; import type { - AgentCapabilities, AgentEvent, AgentInfo, AllProvidersData, @@ -22,7 +15,6 @@ import type { ChatSession, Disposable, FileDiff, - IAgent, McpStatus, ModelRef, PermissionResponse, @@ -32,7 +24,7 @@ import type { SkillInfo, TodoItem, ToolListItem, -} from "@opencodegui/core"; +} from "@shared"; import { mapAgents, mapAllProvidersData, @@ -52,34 +44,13 @@ import { type EventHandler = (event: AgentEvent) => void; -export class OpenCodeAgent implements IAgent { +export class OpenCodeAgent { private client: OpencodeClient | undefined; private server: { url: string; close(): void } | undefined; private sseAbortController: AbortController | undefined; private listeners: Set = new Set(); public workspaceFolder: string | undefined; - // --- Capability declaration --- - - getCapabilities(): AgentCapabilities { - return { - sessionDelete: true, - sessionFork: true, - sessionRevert: true, - sessionShare: true, - sessionSummarize: true, - sessionDiff: true, - todo: true, - multiProvider: true, - permission: true, - question: true, - mcp: true, - subAgent: true, - shell: true, - config: true, - }; - } - // --- Lifecycle --- async connect(): Promise { @@ -168,7 +139,7 @@ export class OpenCodeAgent implements IAgent { return mapSession(response.data!); } - // --- Sessions (capabilities-dependent) --- + // --- Sessions --- async deleteSession(id: string): Promise { const client = this.requireClient(); diff --git a/packages/core/src/domain.ts b/src/shared/domain.ts similarity index 99% rename from packages/core/src/domain.ts rename to src/shared/domain.ts index d825bb6..dacc9b1 100644 --- a/packages/core/src/domain.ts +++ b/src/shared/domain.ts @@ -1,5 +1,5 @@ /** - * @opencodegui/core - Domain types + * @shared - Domain types * * Agent/platform-independent types representing the application's domain. * These types are shaped to match the actual data flowing through the system diff --git a/src/shared/index.ts b/src/shared/index.ts new file mode 100644 index 0000000..9234cc9 --- /dev/null +++ b/src/shared/index.ts @@ -0,0 +1,4 @@ +// Shared domain and protocol types used by the extension host and webview. + +export * from "./domain"; +export * from "./protocol"; diff --git a/packages/core/src/protocol.ts b/src/shared/protocol.ts similarity index 93% rename from packages/core/src/protocol.ts rename to src/shared/protocol.ts index cd80c6b..784a9fc 100644 --- a/packages/core/src/protocol.ts +++ b/src/shared/protocol.ts @@ -1,12 +1,6 @@ /** - * @opencodegui/core - Protocol Types - * - * Message types for UI <-> Host communication. - * These define the protocol used between the webview (React UI) and the - * host process (VS Code extension host, Electron main process, etc.). + * Message types for UI <-> VS Code extension host communication. */ - -import type { AgentCapabilities } from "./agent.interface"; import type { AgentEvent, AgentInfo, @@ -145,7 +139,6 @@ export type HostToUIMessage = // --- Initialization --- | { type: "init"; - capabilities: AgentCapabilities; locale: string; paths: AppPaths; } diff --git a/packages/platforms/vscode/src/vscode-platform-services.ts b/src/vscode-platform-services.ts similarity index 90% rename from packages/platforms/vscode/src/vscode-platform-services.ts rename to src/vscode-platform-services.ts index e5c74d9..45f6756 100644 --- a/packages/platforms/vscode/src/vscode-platform-services.ts +++ b/src/vscode-platform-services.ts @@ -1,15 +1,8 @@ -/** - * VscodePlatformServices - IPlatformServices implementation for VS Code. - * - * Encapsulates all VS Code-specific platform operations that were previously - * embedded in ChatViewProvider's message handlers. - */ - import * as path from "node:path"; -import type { FileAttachment, IPlatformServices } from "@opencodegui/core"; +import type { FileAttachment } from "@shared"; import * as vscode from "vscode"; -export class VscodePlatformServices implements IPlatformServices { +export class VscodePlatformServices { async openDiffEditor(filePath: string, before: string, after: string): Promise { // 仮想ドキュメントを使って VS Code のネイティブ diff エディタを開く const beforeUri = vscode.Uri.parse(`opencode-diff-before:${filePath}?${encodeURIComponent(before)}`); diff --git a/packages/platforms/vscode/webview/App.tsx b/src/webview/App.tsx similarity index 99% rename from packages/platforms/vscode/webview/App.tsx rename to src/webview/App.tsx index 1effc02..ffe8e4b 100644 --- a/packages/platforms/vscode/webview/App.tsx +++ b/src/webview/App.tsx @@ -1,4 +1,4 @@ -import type { AgentEvent, AgentInfo, ChatSession, SkillInfo, TodoItem } from "@opencodegui/core"; +import type { AgentEvent, AgentInfo, ChatSession, SkillInfo, TodoItem } from "@shared"; import { useCallback, useEffect, useRef, useState } from "react"; import { EmptyState } from "./components/molecules/EmptyState"; import { FileChangesHeader } from "./components/molecules/FileChangesHeader"; diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/ActionButton.test.tsx b/src/webview/__tests__/components/atoms/ActionButton.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/ActionButton.test.tsx rename to src/webview/__tests__/components/atoms/ActionButton.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/IconButton.test.tsx b/src/webview/__tests__/components/atoms/IconButton.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/IconButton.test.tsx rename to src/webview/__tests__/components/atoms/IconButton.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/LinkButton.test.tsx b/src/webview/__tests__/components/atoms/LinkButton.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/LinkButton.test.tsx rename to src/webview/__tests__/components/atoms/LinkButton.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/ListItem.test.tsx b/src/webview/__tests__/components/atoms/ListItem.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/ListItem.test.tsx rename to src/webview/__tests__/components/atoms/ListItem.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/Popover.test.tsx b/src/webview/__tests__/components/atoms/Popover.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/Popover.test.tsx rename to src/webview/__tests__/components/atoms/Popover.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/StatusItem.test.tsx b/src/webview/__tests__/components/atoms/StatusItem.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/StatusItem.test.tsx rename to src/webview/__tests__/components/atoms/StatusItem.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/StreamingIndicator.test.tsx b/src/webview/__tests__/components/atoms/StreamingIndicator.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/StreamingIndicator.test.tsx rename to src/webview/__tests__/components/atoms/StreamingIndicator.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/file-type-icons.test.tsx b/src/webview/__tests__/components/atoms/file-type-icons.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/file-type-icons.test.tsx rename to src/webview/__tests__/components/atoms/file-type-icons.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/atoms/icons.test.tsx b/src/webview/__tests__/components/atoms/icons.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/atoms/icons.test.tsx rename to src/webview/__tests__/components/atoms/icons.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/AgentPopup.test.tsx b/src/webview/__tests__/components/molecules/AgentPopup.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/AgentPopup.test.tsx rename to src/webview/__tests__/components/molecules/AgentPopup.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/DiffView.test.tsx b/src/webview/__tests__/components/molecules/DiffView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/DiffView.test.tsx rename to src/webview/__tests__/components/molecules/DiffView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/EmptyState.test.tsx b/src/webview/__tests__/components/molecules/EmptyState.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/EmptyState.test.tsx rename to src/webview/__tests__/components/molecules/EmptyState.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx b/src/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx rename to src/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/FileChangesHeader.test.tsx b/src/webview/__tests__/components/molecules/FileChangesHeader.test.tsx similarity index 99% rename from packages/platforms/vscode/webview/__tests__/components/molecules/FileChangesHeader.test.tsx rename to src/webview/__tests__/components/molecules/FileChangesHeader.test.tsx index 5bfd43e..7ea119c 100644 --- a/packages/platforms/vscode/webview/__tests__/components/molecules/FileChangesHeader.test.tsx +++ b/src/webview/__tests__/components/molecules/FileChangesHeader.test.tsx @@ -1,4 +1,4 @@ -import type { FileDiff } from "@opencodegui/core"; +import type { FileDiff } from "@shared"; import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { FileChangesHeader } from "../../../components/molecules/FileChangesHeader"; diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/FileCreateView.test.tsx b/src/webview/__tests__/components/molecules/FileCreateView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/FileCreateView.test.tsx rename to src/webview/__tests__/components/molecules/FileCreateView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/HashFilePopup.test.tsx b/src/webview/__tests__/components/molecules/HashFilePopup.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/HashFilePopup.test.tsx rename to src/webview/__tests__/components/molecules/HashFilePopup.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/ModelSelector.test.tsx b/src/webview/__tests__/components/molecules/ModelSelector.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/ModelSelector.test.tsx rename to src/webview/__tests__/components/molecules/ModelSelector.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/ShellResultView.test.tsx b/src/webview/__tests__/components/molecules/ShellResultView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/ShellResultView.test.tsx rename to src/webview/__tests__/components/molecules/ShellResultView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/SkillPopup.test.tsx b/src/webview/__tests__/components/molecules/SkillPopup.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/SkillPopup.test.tsx rename to src/webview/__tests__/components/molecules/SkillPopup.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/TextPartView.test.tsx b/src/webview/__tests__/components/molecules/TextPartView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/TextPartView.test.tsx rename to src/webview/__tests__/components/molecules/TextPartView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/TodoHeader.test.tsx b/src/webview/__tests__/components/molecules/TodoHeader.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/TodoHeader.test.tsx rename to src/webview/__tests__/components/molecules/TodoHeader.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/molecules/TodoView.test.tsx b/src/webview/__tests__/components/molecules/TodoView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/molecules/TodoView.test.tsx rename to src/webview/__tests__/components/molecules/TodoView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/ChatHeader.test.tsx b/src/webview/__tests__/components/organisms/ChatHeader.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/ChatHeader.test.tsx rename to src/webview/__tests__/components/organisms/ChatHeader.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/MessageItem.test.tsx b/src/webview/__tests__/components/organisms/MessageItem.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/MessageItem.test.tsx rename to src/webview/__tests__/components/organisms/MessageItem.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/MessagesArea.test.tsx b/src/webview/__tests__/components/organisms/MessagesArea.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/MessagesArea.test.tsx rename to src/webview/__tests__/components/organisms/MessagesArea.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/PermissionView.test.tsx b/src/webview/__tests__/components/organisms/PermissionView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/PermissionView.test.tsx rename to src/webview/__tests__/components/organisms/PermissionView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/QuestionView.test.tsx b/src/webview/__tests__/components/organisms/QuestionView.test.tsx similarity index 99% rename from packages/platforms/vscode/webview/__tests__/components/organisms/QuestionView.test.tsx rename to src/webview/__tests__/components/organisms/QuestionView.test.tsx index eec4ffc..4a44353 100644 --- a/packages/platforms/vscode/webview/__tests__/components/organisms/QuestionView.test.tsx +++ b/src/webview/__tests__/components/organisms/QuestionView.test.tsx @@ -1,4 +1,4 @@ -import type { QuestionRequest } from "@opencodegui/core"; +import type { QuestionRequest } from "@shared"; import { fireEvent, render } from "@testing-library/react"; import { describe, expect, it } from "vitest"; import { QuestionView } from "../../../components/organisms/QuestionView"; diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/SessionList.test.tsx b/src/webview/__tests__/components/organisms/SessionList.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/SessionList.test.tsx rename to src/webview/__tests__/components/organisms/SessionList.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/SubtaskPartView.test.tsx b/src/webview/__tests__/components/organisms/SubtaskPartView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/SubtaskPartView.test.tsx rename to src/webview/__tests__/components/organisms/SubtaskPartView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx b/src/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx rename to src/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/components/organisms/ToolPartView.test.tsx b/src/webview/__tests__/components/organisms/ToolPartView.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/components/organisms/ToolPartView.test.tsx rename to src/webview/__tests__/components/organisms/ToolPartView.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/factories.ts b/src/webview/__tests__/factories.ts similarity index 96% rename from packages/platforms/vscode/webview/__tests__/factories.ts rename to src/webview/__tests__/factories.ts index 50b9d5b..2287a74 100644 --- a/packages/platforms/vscode/webview/__tests__/factories.ts +++ b/src/webview/__tests__/factories.ts @@ -1,12 +1,4 @@ -import type { - AgentEvent, - ChatMessage, - ChatSession, - Permission, - ProviderInfo, - TextPart, - ToolPart, -} from "@opencodegui/core"; +import type { AgentEvent, ChatMessage, ChatSession, Permission, ProviderInfo, TextPart, ToolPart } from "@shared"; // --- Session --- diff --git a/packages/platforms/vscode/webview/__tests__/helpers.tsx b/src/webview/__tests__/helpers.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/helpers.tsx rename to src/webview/__tests__/helpers.tsx diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useAutoScroll.test.ts b/src/webview/__tests__/hooks/useAutoScroll.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/hooks/useAutoScroll.test.ts rename to src/webview/__tests__/hooks/useAutoScroll.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useClickOutside.test.ts b/src/webview/__tests__/hooks/useClickOutside.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/hooks/useClickOutside.test.ts rename to src/webview/__tests__/hooks/useClickOutside.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useFileChanges.test.ts b/src/webview/__tests__/hooks/useFileChanges.test.ts similarity index 97% rename from packages/platforms/vscode/webview/__tests__/hooks/useFileChanges.test.ts rename to src/webview/__tests__/hooks/useFileChanges.test.ts index d2dd584..c389902 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/useFileChanges.test.ts +++ b/src/webview/__tests__/hooks/useFileChanges.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, FileDiff } from "@opencodegui/core"; +import type { AgentEvent, FileDiff } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { describe, expect, it } from "vitest"; import { useFileChanges } from "../../hooks/useFileChanges"; diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useInputHistory.test.ts b/src/webview/__tests__/hooks/useInputHistory.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/hooks/useInputHistory.test.ts rename to src/webview/__tests__/hooks/useInputHistory.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useLocale.test.ts b/src/webview/__tests__/hooks/useLocale.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/hooks/useLocale.test.ts rename to src/webview/__tests__/hooks/useLocale.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useMessages.test.ts b/src/webview/__tests__/hooks/useMessages.test.ts similarity index 99% rename from packages/platforms/vscode/webview/__tests__/hooks/useMessages.test.ts rename to src/webview/__tests__/hooks/useMessages.test.ts index df95727..30d2032 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/useMessages.test.ts +++ b/src/webview/__tests__/hooks/useMessages.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, ChatSession } from "@opencodegui/core"; +import type { AgentEvent, ChatSession } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { createRef, type RefObject } from "react"; import { describe, expect, it } from "vitest"; diff --git a/packages/platforms/vscode/webview/__tests__/hooks/usePermissions.test.ts b/src/webview/__tests__/hooks/usePermissions.test.ts similarity index 98% rename from packages/platforms/vscode/webview/__tests__/hooks/usePermissions.test.ts rename to src/webview/__tests__/hooks/usePermissions.test.ts index e83476f..aba5480 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/usePermissions.test.ts +++ b/src/webview/__tests__/hooks/usePermissions.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@opencodegui/core"; +import type { AgentEvent } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { describe, expect, it } from "vitest"; import { usePermissions } from "../../hooks/usePermissions"; diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useProviders.test.ts b/src/webview/__tests__/hooks/useProviders.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/hooks/useProviders.test.ts rename to src/webview/__tests__/hooks/useProviders.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useQuestions.test.ts b/src/webview/__tests__/hooks/useQuestions.test.ts similarity index 98% rename from packages/platforms/vscode/webview/__tests__/hooks/useQuestions.test.ts rename to src/webview/__tests__/hooks/useQuestions.test.ts index aefca58..89ad479 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/useQuestions.test.ts +++ b/src/webview/__tests__/hooks/useQuestions.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@opencodegui/core"; +import type { AgentEvent } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { describe, expect, it } from "vitest"; import { useQuestions } from "../../hooks/useQuestions"; diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useSession.test.ts b/src/webview/__tests__/hooks/useSession.test.ts similarity index 99% rename from packages/platforms/vscode/webview/__tests__/hooks/useSession.test.ts rename to src/webview/__tests__/hooks/useSession.test.ts index ac2ea58..3452ad9 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/useSession.test.ts +++ b/src/webview/__tests__/hooks/useSession.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@opencodegui/core"; +import type { AgentEvent } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { useSession } from "../../hooks/useSession"; diff --git a/packages/platforms/vscode/webview/__tests__/hooks/useSoundNotification.test.ts b/src/webview/__tests__/hooks/useSoundNotification.test.ts similarity index 99% rename from packages/platforms/vscode/webview/__tests__/hooks/useSoundNotification.test.ts rename to src/webview/__tests__/hooks/useSoundNotification.test.ts index 620facf..2a26090 100644 --- a/packages/platforms/vscode/webview/__tests__/hooks/useSoundNotification.test.ts +++ b/src/webview/__tests__/hooks/useSoundNotification.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@opencodegui/core"; +import type { AgentEvent } from "@shared"; import { act, renderHook } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { useSoundNotification } from "../../hooks/useSoundNotification"; diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/01-initialization.test.tsx b/src/webview/__tests__/scenarios/01-initialization.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/01-initialization.test.tsx rename to src/webview/__tests__/scenarios/01-initialization.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/02-session-lifecycle.test.tsx b/src/webview/__tests__/scenarios/02-session-lifecycle.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/02-session-lifecycle.test.tsx rename to src/webview/__tests__/scenarios/02-session-lifecycle.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/03-messaging.test.tsx b/src/webview/__tests__/scenarios/03-messaging.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/03-messaging.test.tsx rename to src/webview/__tests__/scenarios/03-messaging.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/04-message-editing.test.tsx b/src/webview/__tests__/scenarios/04-message-editing.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/04-message-editing.test.tsx rename to src/webview/__tests__/scenarios/04-message-editing.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/05-permissions.test.tsx b/src/webview/__tests__/scenarios/05-permissions.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/05-permissions.test.tsx rename to src/webview/__tests__/scenarios/05-permissions.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/06-model-selection.test.tsx b/src/webview/__tests__/scenarios/06-model-selection.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/06-model-selection.test.tsx rename to src/webview/__tests__/scenarios/06-model-selection.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/07-file-context.test.tsx b/src/webview/__tests__/scenarios/07-file-context.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/07-file-context.test.tsx rename to src/webview/__tests__/scenarios/07-file-context.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/09-settings.test.tsx b/src/webview/__tests__/scenarios/09-settings.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/09-settings.test.tsx rename to src/webview/__tests__/scenarios/09-settings.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/10-tool-display.test.tsx b/src/webview/__tests__/scenarios/10-tool-display.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/10-tool-display.test.tsx rename to src/webview/__tests__/scenarios/10-tool-display.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/11-todo.test.tsx b/src/webview/__tests__/scenarios/11-todo.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/11-todo.test.tsx rename to src/webview/__tests__/scenarios/11-todo.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/12-reasoning-display.test.tsx b/src/webview/__tests__/scenarios/12-reasoning-display.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/12-reasoning-display.test.tsx rename to src/webview/__tests__/scenarios/12-reasoning-display.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/13-keyboard-ime.test.tsx b/src/webview/__tests__/scenarios/13-keyboard-ime.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/13-keyboard-ime.test.tsx rename to src/webview/__tests__/scenarios/13-keyboard-ime.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/14-shell-command.test.tsx b/src/webview/__tests__/scenarios/14-shell-command.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/14-shell-command.test.tsx rename to src/webview/__tests__/scenarios/14-shell-command.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/15-file-changes.test.tsx b/src/webview/__tests__/scenarios/15-file-changes.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/15-file-changes.test.tsx rename to src/webview/__tests__/scenarios/15-file-changes.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/16-session-fork.test.tsx b/src/webview/__tests__/scenarios/16-session-fork.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/16-session-fork.test.tsx rename to src/webview/__tests__/scenarios/16-session-fork.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/17-child-session-nav.test.tsx b/src/webview/__tests__/scenarios/17-child-session-nav.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/17-child-session-nav.test.tsx rename to src/webview/__tests__/scenarios/17-child-session-nav.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/18-agent-mention.test.tsx b/src/webview/__tests__/scenarios/18-agent-mention.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/18-agent-mention.test.tsx rename to src/webview/__tests__/scenarios/18-agent-mention.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/19-session-share.test.tsx b/src/webview/__tests__/scenarios/19-session-share.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/19-session-share.test.tsx rename to src/webview/__tests__/scenarios/19-session-share.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/20-undo-redo.test.tsx b/src/webview/__tests__/scenarios/20-undo-redo.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/20-undo-redo.test.tsx rename to src/webview/__tests__/scenarios/20-undo-redo.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/21-popup-tab-select.test.tsx b/src/webview/__tests__/scenarios/21-popup-tab-select.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/21-popup-tab-select.test.tsx rename to src/webview/__tests__/scenarios/21-popup-tab-select.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx b/src/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx rename to src/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/23-clip-context-menu.test.tsx b/src/webview/__tests__/scenarios/23-clip-context-menu.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/23-clip-context-menu.test.tsx rename to src/webview/__tests__/scenarios/23-clip-context-menu.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/24-input-history.test.tsx b/src/webview/__tests__/scenarios/24-input-history.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/24-input-history.test.tsx rename to src/webview/__tests__/scenarios/24-input-history.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/25-diff-review.test.tsx b/src/webview/__tests__/scenarios/25-diff-review.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/25-diff-review.test.tsx rename to src/webview/__tests__/scenarios/25-diff-review.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/scenarios/25-sound-notification.test.tsx b/src/webview/__tests__/scenarios/25-sound-notification.test.tsx similarity index 100% rename from packages/platforms/vscode/webview/__tests__/scenarios/25-sound-notification.test.tsx rename to src/webview/__tests__/scenarios/25-sound-notification.test.tsx diff --git a/packages/platforms/vscode/webview/__tests__/setup.ts b/src/webview/__tests__/setup.ts similarity index 95% rename from packages/platforms/vscode/webview/__tests__/setup.ts rename to src/webview/__tests__/setup.ts index c9b3036..7dc0a5f 100644 --- a/packages/platforms/vscode/webview/__tests__/setup.ts +++ b/src/webview/__tests__/setup.ts @@ -37,7 +37,7 @@ globalThis.AudioContext = vi.fn(function (this: Record) { }) as unknown as typeof AudioContext; // --- vscode-api モック --- -// acquireVsCodeApi はグローバル関数として宣言されており、webview/vscode-api.ts のモジュールスコープで呼ばれる。 +// acquireVsCodeApi はグローバル関数として宣言されており、src/webview/vscode-api.ts のモジュールスコープで呼ばれる。 // モジュール全体をモックにして postMessage / getPersistedState / setPersistedState をスパイ化する。 vi.mock("../vscode-api", () => ({ diff --git a/packages/platforms/vscode/webview/__tests__/utils/diff.test.ts b/src/webview/__tests__/utils/diff.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/utils/diff.test.ts rename to src/webview/__tests__/utils/diff.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/utils/file-icons.test.ts b/src/webview/__tests__/utils/file-icons.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/utils/file-icons.test.ts rename to src/webview/__tests__/utils/file-icons.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/utils/markdown.test.ts b/src/webview/__tests__/utils/markdown.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/utils/markdown.test.ts rename to src/webview/__tests__/utils/markdown.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/utils/todo.test.ts b/src/webview/__tests__/utils/todo.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/utils/todo.test.ts rename to src/webview/__tests__/utils/todo.test.ts diff --git a/packages/platforms/vscode/webview/__tests__/utils/tool-categories.test.ts b/src/webview/__tests__/utils/tool-categories.test.ts similarity index 100% rename from packages/platforms/vscode/webview/__tests__/utils/tool-categories.test.ts rename to src/webview/__tests__/utils/tool-categories.test.ts diff --git a/packages/platforms/vscode/webview/bridges/VscodeBridge.ts b/src/webview/bridges/VscodeBridge.ts similarity index 96% rename from packages/platforms/vscode/webview/bridges/VscodeBridge.ts rename to src/webview/bridges/VscodeBridge.ts index b6b31ac..50036af 100644 --- a/packages/platforms/vscode/webview/bridges/VscodeBridge.ts +++ b/src/webview/bridges/VscodeBridge.ts @@ -5,7 +5,7 @@ * platform-independent communication between UI and extension host. */ -import type { Disposable, HostToUIMessage, IBridge, UIPersistedState, UIToHostMessage } from "@opencodegui/core"; +import type { Disposable, HostToUIMessage, IBridge, UIPersistedState, UIToHostMessage } from "@shared"; interface VsCodeApi { postMessage(message: UIToHostMessage): void; diff --git a/packages/platforms/vscode/webview/components/atoms/ActionButton/ActionButton.module.css b/src/webview/components/atoms/ActionButton/ActionButton.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ActionButton/ActionButton.module.css rename to src/webview/components/atoms/ActionButton/ActionButton.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/ActionButton/ActionButton.tsx b/src/webview/components/atoms/ActionButton/ActionButton.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ActionButton/ActionButton.tsx rename to src/webview/components/atoms/ActionButton/ActionButton.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/ActionButton/index.ts b/src/webview/components/atoms/ActionButton/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ActionButton/index.ts rename to src/webview/components/atoms/ActionButton/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/IconButton/IconButton.module.css b/src/webview/components/atoms/IconButton/IconButton.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/IconButton/IconButton.module.css rename to src/webview/components/atoms/IconButton/IconButton.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/IconButton/IconButton.tsx b/src/webview/components/atoms/IconButton/IconButton.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/IconButton/IconButton.tsx rename to src/webview/components/atoms/IconButton/IconButton.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/IconButton/index.ts b/src/webview/components/atoms/IconButton/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/IconButton/index.ts rename to src/webview/components/atoms/IconButton/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/LinkButton/LinkButton.module.css b/src/webview/components/atoms/LinkButton/LinkButton.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/LinkButton/LinkButton.module.css rename to src/webview/components/atoms/LinkButton/LinkButton.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/LinkButton/LinkButton.tsx b/src/webview/components/atoms/LinkButton/LinkButton.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/LinkButton/LinkButton.tsx rename to src/webview/components/atoms/LinkButton/LinkButton.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/LinkButton/index.ts b/src/webview/components/atoms/LinkButton/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/LinkButton/index.ts rename to src/webview/components/atoms/LinkButton/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/ListItem/ListItem.module.css b/src/webview/components/atoms/ListItem/ListItem.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ListItem/ListItem.module.css rename to src/webview/components/atoms/ListItem/ListItem.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/ListItem/ListItem.tsx b/src/webview/components/atoms/ListItem/ListItem.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ListItem/ListItem.tsx rename to src/webview/components/atoms/ListItem/ListItem.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/ListItem/index.ts b/src/webview/components/atoms/ListItem/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ListItem/index.ts rename to src/webview/components/atoms/ListItem/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/Popover/Popover.module.css b/src/webview/components/atoms/Popover/Popover.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/Popover/Popover.module.css rename to src/webview/components/atoms/Popover/Popover.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/Popover/Popover.tsx b/src/webview/components/atoms/Popover/Popover.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/Popover/Popover.tsx rename to src/webview/components/atoms/Popover/Popover.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/Popover/index.ts b/src/webview/components/atoms/Popover/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/Popover/index.ts rename to src/webview/components/atoms/Popover/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css b/src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css rename to src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx b/src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx rename to src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/index.ts b/src/webview/components/atoms/ScrollToBottomButton/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/ScrollToBottomButton/index.ts rename to src/webview/components/atoms/ScrollToBottomButton/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/StatusItem/StatusItem.module.css b/src/webview/components/atoms/StatusItem/StatusItem.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StatusItem/StatusItem.module.css rename to src/webview/components/atoms/StatusItem/StatusItem.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/StatusItem/StatusItem.tsx b/src/webview/components/atoms/StatusItem/StatusItem.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StatusItem/StatusItem.tsx rename to src/webview/components/atoms/StatusItem/StatusItem.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/StatusItem/index.ts b/src/webview/components/atoms/StatusItem/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StatusItem/index.ts rename to src/webview/components/atoms/StatusItem/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css b/src/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css rename to src/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css diff --git a/packages/platforms/vscode/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx b/src/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx rename to src/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/StreamingIndicator/index.ts b/src/webview/components/atoms/StreamingIndicator/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/StreamingIndicator/index.ts rename to src/webview/components/atoms/StreamingIndicator/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx b/src/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx rename to src/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/icons/file-type-icons/index.ts b/src/webview/components/atoms/icons/file-type-icons/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/icons/file-type-icons/index.ts rename to src/webview/components/atoms/icons/file-type-icons/index.ts diff --git a/packages/platforms/vscode/webview/components/atoms/icons/icons.tsx b/src/webview/components/atoms/icons/icons.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/icons/icons.tsx rename to src/webview/components/atoms/icons/icons.tsx diff --git a/packages/platforms/vscode/webview/components/atoms/icons/index.ts b/src/webview/components/atoms/icons/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/atoms/icons/index.ts rename to src/webview/components/atoms/icons/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/AgentPopup/AgentPopup.module.css b/src/webview/components/molecules/AgentPopup/AgentPopup.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/AgentPopup/AgentPopup.module.css rename to src/webview/components/molecules/AgentPopup/AgentPopup.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/AgentPopup/AgentPopup.tsx b/src/webview/components/molecules/AgentPopup/AgentPopup.tsx similarity index 94% rename from packages/platforms/vscode/webview/components/molecules/AgentPopup/AgentPopup.tsx rename to src/webview/components/molecules/AgentPopup/AgentPopup.tsx index c64b2a4..1e66920 100644 --- a/packages/platforms/vscode/webview/components/molecules/AgentPopup/AgentPopup.tsx +++ b/src/webview/components/molecules/AgentPopup/AgentPopup.tsx @@ -1,4 +1,4 @@ -import type { AgentInfo } from "@opencodegui/core"; +import type { AgentInfo } from "@shared"; import { useLocale } from "../../../locales"; import { ListItem } from "../../atoms/ListItem"; import styles from "./AgentPopup.module.css"; diff --git a/packages/platforms/vscode/webview/components/molecules/AgentPopup/index.ts b/src/webview/components/molecules/AgentPopup/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/AgentPopup/index.ts rename to src/webview/components/molecules/AgentPopup/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/AgentSelector/AgentSelector.module.css b/src/webview/components/molecules/AgentSelector/AgentSelector.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/AgentSelector/AgentSelector.module.css rename to src/webview/components/molecules/AgentSelector/AgentSelector.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/AgentSelector/AgentSelector.tsx b/src/webview/components/molecules/AgentSelector/AgentSelector.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/molecules/AgentSelector/AgentSelector.tsx rename to src/webview/components/molecules/AgentSelector/AgentSelector.tsx index 62b4ff5..1c46a49 100644 --- a/packages/platforms/vscode/webview/components/molecules/AgentSelector/AgentSelector.tsx +++ b/src/webview/components/molecules/AgentSelector/AgentSelector.tsx @@ -1,4 +1,4 @@ -import type { AgentInfo } from "@opencodegui/core"; +import type { AgentInfo } from "@shared"; import { useMemo } from "react"; import { useLocale } from "../../../locales"; import { AgentIcon, ChevronRightIcon } from "../../atoms/icons"; diff --git a/packages/platforms/vscode/webview/components/molecules/AgentSelector/index.ts b/src/webview/components/molecules/AgentSelector/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/AgentSelector/index.ts rename to src/webview/components/molecules/AgentSelector/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/DiffView/DiffView.module.css b/src/webview/components/molecules/DiffView/DiffView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/DiffView/DiffView.module.css rename to src/webview/components/molecules/DiffView/DiffView.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/DiffView/DiffView.tsx b/src/webview/components/molecules/DiffView/DiffView.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/DiffView/DiffView.tsx rename to src/webview/components/molecules/DiffView/DiffView.tsx diff --git a/packages/platforms/vscode/webview/components/molecules/DiffView/index.ts b/src/webview/components/molecules/DiffView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/DiffView/index.ts rename to src/webview/components/molecules/DiffView/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/EmptyState/EmptyState.module.css b/src/webview/components/molecules/EmptyState/EmptyState.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/EmptyState/EmptyState.module.css rename to src/webview/components/molecules/EmptyState/EmptyState.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/EmptyState/EmptyState.tsx b/src/webview/components/molecules/EmptyState/EmptyState.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/EmptyState/EmptyState.tsx rename to src/webview/components/molecules/EmptyState/EmptyState.tsx diff --git a/packages/platforms/vscode/webview/components/molecules/EmptyState/index.ts b/src/webview/components/molecules/EmptyState/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/EmptyState/index.ts rename to src/webview/components/molecules/EmptyState/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css b/src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css rename to src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx b/src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx rename to src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx index 8daf58c..9fd643d 100644 --- a/packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx +++ b/src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx @@ -1,4 +1,4 @@ -import type { AgentInfo, SkillInfo } from "@opencodegui/core"; +import type { AgentInfo, SkillInfo } from "@shared"; import { useLocale } from "../../../locales"; import { getFileIcon } from "../../../utils/file-icons"; import type { FileAttachment } from "../../../vscode-api"; diff --git a/packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/index.ts b/src/webview/components/molecules/FileAttachmentBar/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileAttachmentBar/index.ts rename to src/webview/components/molecules/FileAttachmentBar/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css b/src/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css rename to src/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx b/src/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx rename to src/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx index d9fb49b..aaecb38 100644 --- a/packages/platforms/vscode/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx +++ b/src/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx @@ -1,4 +1,4 @@ -import type { FileDiff } from "@opencodegui/core"; +import type { FileDiff } from "@shared"; import { useState } from "react"; import { useLocale } from "../../../locales"; import { getFileIcon } from "../../../utils/file-icons"; diff --git a/packages/platforms/vscode/webview/components/molecules/FileChangesHeader/index.ts b/src/webview/components/molecules/FileChangesHeader/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileChangesHeader/index.ts rename to src/webview/components/molecules/FileChangesHeader/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/FileCreateView/FileCreateView.tsx b/src/webview/components/molecules/FileCreateView/FileCreateView.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileCreateView/FileCreateView.tsx rename to src/webview/components/molecules/FileCreateView/FileCreateView.tsx diff --git a/packages/platforms/vscode/webview/components/molecules/FileCreateView/index.ts b/src/webview/components/molecules/FileCreateView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/FileCreateView/index.ts rename to src/webview/components/molecules/FileCreateView/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/HashFilePopup/HashFilePopup.module.css b/src/webview/components/molecules/HashFilePopup/HashFilePopup.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/HashFilePopup/HashFilePopup.module.css rename to src/webview/components/molecules/HashFilePopup/HashFilePopup.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/HashFilePopup/HashFilePopup.tsx b/src/webview/components/molecules/HashFilePopup/HashFilePopup.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/HashFilePopup/HashFilePopup.tsx rename to src/webview/components/molecules/HashFilePopup/HashFilePopup.tsx diff --git a/packages/platforms/vscode/webview/components/molecules/HashFilePopup/index.ts b/src/webview/components/molecules/HashFilePopup/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/HashFilePopup/index.ts rename to src/webview/components/molecules/HashFilePopup/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/ModelSelector/ModelSelector.module.css b/src/webview/components/molecules/ModelSelector/ModelSelector.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/ModelSelector/ModelSelector.module.css rename to src/webview/components/molecules/ModelSelector/ModelSelector.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/ModelSelector/ModelSelector.tsx b/src/webview/components/molecules/ModelSelector/ModelSelector.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/molecules/ModelSelector/ModelSelector.tsx rename to src/webview/components/molecules/ModelSelector/ModelSelector.tsx index 85e9f14..136f603 100644 --- a/packages/platforms/vscode/webview/components/molecules/ModelSelector/ModelSelector.tsx +++ b/src/webview/components/molecules/ModelSelector/ModelSelector.tsx @@ -1,4 +1,4 @@ -import type { ProviderInfo as CoreProviderInfo } from "@opencodegui/core"; +import type { ProviderInfo as CoreProviderInfo } from "@shared"; import { useMemo, useState } from "react"; import { useLocale } from "../../../locales"; import type { AllProvidersData, ModelInfo, ProviderInfo } from "../../../vscode-api"; diff --git a/packages/platforms/vscode/webview/components/molecules/ModelSelector/index.ts b/src/webview/components/molecules/ModelSelector/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/ModelSelector/index.ts rename to src/webview/components/molecules/ModelSelector/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/ShellResultView/ShellResultView.module.css b/src/webview/components/molecules/ShellResultView/ShellResultView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/ShellResultView/ShellResultView.module.css rename to src/webview/components/molecules/ShellResultView/ShellResultView.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/ShellResultView/ShellResultView.tsx b/src/webview/components/molecules/ShellResultView/ShellResultView.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/molecules/ShellResultView/ShellResultView.tsx rename to src/webview/components/molecules/ShellResultView/ShellResultView.tsx index 85e2c73..ce919c3 100644 --- a/packages/platforms/vscode/webview/components/molecules/ShellResultView/ShellResultView.tsx +++ b/src/webview/components/molecules/ShellResultView/ShellResultView.tsx @@ -1,4 +1,4 @@ -import type { ToolPart } from "@opencodegui/core"; +import type { ToolPart } from "@shared"; import { useMemo, useState } from "react"; import { useLocale } from "../../../locales"; import { ChevronRightIcon, SpinnerIcon, TerminalIcon } from "../../atoms/icons"; diff --git a/packages/platforms/vscode/webview/components/molecules/ShellResultView/index.ts b/src/webview/components/molecules/ShellResultView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/ShellResultView/index.ts rename to src/webview/components/molecules/ShellResultView/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/SkillPopup/SkillPopup.module.css b/src/webview/components/molecules/SkillPopup/SkillPopup.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/SkillPopup/SkillPopup.module.css rename to src/webview/components/molecules/SkillPopup/SkillPopup.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/SkillPopup/SkillPopup.tsx b/src/webview/components/molecules/SkillPopup/SkillPopup.tsx similarity index 95% rename from packages/platforms/vscode/webview/components/molecules/SkillPopup/SkillPopup.tsx rename to src/webview/components/molecules/SkillPopup/SkillPopup.tsx index 4b0efb8..5ff0f39 100644 --- a/packages/platforms/vscode/webview/components/molecules/SkillPopup/SkillPopup.tsx +++ b/src/webview/components/molecules/SkillPopup/SkillPopup.tsx @@ -1,4 +1,4 @@ -import type { SkillInfo } from "@opencodegui/core"; +import type { SkillInfo } from "@shared"; import { useLocale } from "../../../locales"; import { GearIcon } from "../../atoms/icons"; import { ListItem } from "../../atoms/ListItem"; diff --git a/packages/platforms/vscode/webview/components/molecules/SkillPopup/index.ts b/src/webview/components/molecules/SkillPopup/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/SkillPopup/index.ts rename to src/webview/components/molecules/SkillPopup/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/TextPartView/TextPartView.tsx b/src/webview/components/molecules/TextPartView/TextPartView.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/molecules/TextPartView/TextPartView.tsx rename to src/webview/components/molecules/TextPartView/TextPartView.tsx index f0fa4f4..f6a8a45 100644 --- a/packages/platforms/vscode/webview/components/molecules/TextPartView/TextPartView.tsx +++ b/src/webview/components/molecules/TextPartView/TextPartView.tsx @@ -1,4 +1,4 @@ -import type { TextPart } from "@opencodegui/core"; +import type { TextPart } from "@shared"; import DOMPurify from "dompurify"; import hljs from "highlight.js/lib/common"; import { Marked, type Renderer, type Tokens } from "marked"; diff --git a/packages/platforms/vscode/webview/components/molecules/TextPartView/index.ts b/src/webview/components/molecules/TextPartView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TextPartView/index.ts rename to src/webview/components/molecules/TextPartView/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/TodoHeader/TodoHeader.module.css b/src/webview/components/molecules/TodoHeader/TodoHeader.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TodoHeader/TodoHeader.module.css rename to src/webview/components/molecules/TodoHeader/TodoHeader.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/TodoHeader/TodoHeader.tsx b/src/webview/components/molecules/TodoHeader/TodoHeader.tsx similarity index 97% rename from packages/platforms/vscode/webview/components/molecules/TodoHeader/TodoHeader.tsx rename to src/webview/components/molecules/TodoHeader/TodoHeader.tsx index 5f263cc..94da0eb 100644 --- a/packages/platforms/vscode/webview/components/molecules/TodoHeader/TodoHeader.tsx +++ b/src/webview/components/molecules/TodoHeader/TodoHeader.tsx @@ -1,4 +1,4 @@ -import type { TodoItem } from "@opencodegui/core"; +import type { TodoItem } from "@shared"; import { useState } from "react"; import { useLocale } from "../../../locales"; import { CheckboxIcon, ChevronRightIcon } from "../../atoms/icons"; diff --git a/packages/platforms/vscode/webview/components/molecules/TodoHeader/index.ts b/src/webview/components/molecules/TodoHeader/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TodoHeader/index.ts rename to src/webview/components/molecules/TodoHeader/index.ts diff --git a/packages/platforms/vscode/webview/components/molecules/TodoView/TodoView.module.css b/src/webview/components/molecules/TodoView/TodoView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TodoView/TodoView.module.css rename to src/webview/components/molecules/TodoView/TodoView.module.css diff --git a/packages/platforms/vscode/webview/components/molecules/TodoView/TodoView.tsx b/src/webview/components/molecules/TodoView/TodoView.tsx similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TodoView/TodoView.tsx rename to src/webview/components/molecules/TodoView/TodoView.tsx diff --git a/packages/platforms/vscode/webview/components/molecules/TodoView/index.ts b/src/webview/components/molecules/TodoView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/molecules/TodoView/index.ts rename to src/webview/components/molecules/TodoView/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/ChatHeader/ChatHeader.module.css b/src/webview/components/organisms/ChatHeader/ChatHeader.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ChatHeader/ChatHeader.module.css rename to src/webview/components/organisms/ChatHeader/ChatHeader.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/ChatHeader/ChatHeader.tsx b/src/webview/components/organisms/ChatHeader/ChatHeader.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/ChatHeader/ChatHeader.tsx rename to src/webview/components/organisms/ChatHeader/ChatHeader.tsx index 5a8a841..7d1e368 100644 --- a/packages/platforms/vscode/webview/components/organisms/ChatHeader/ChatHeader.tsx +++ b/src/webview/components/organisms/ChatHeader/ChatHeader.tsx @@ -1,4 +1,4 @@ -import type { ChatSession } from "@opencodegui/core"; +import type { ChatSession } from "@shared"; import { useLocale } from "../../../locales"; import { IconButton } from "../../atoms/IconButton"; import { AddIcon, BackIcon, ListIcon, RedoIcon, ShareIcon, UndoIcon, UnshareIcon } from "../../atoms/icons"; diff --git a/packages/platforms/vscode/webview/components/organisms/ChatHeader/index.ts b/src/webview/components/organisms/ChatHeader/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ChatHeader/index.ts rename to src/webview/components/organisms/ChatHeader/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/InputArea/InputArea.module.css b/src/webview/components/organisms/InputArea/InputArea.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/InputArea/InputArea.module.css rename to src/webview/components/organisms/InputArea/InputArea.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/InputArea/InputArea.tsx b/src/webview/components/organisms/InputArea/InputArea.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/organisms/InputArea/InputArea.tsx rename to src/webview/components/organisms/InputArea/InputArea.tsx index 3607753..1497cfb 100644 --- a/packages/platforms/vscode/webview/components/organisms/InputArea/InputArea.tsx +++ b/src/webview/components/organisms/InputArea/InputArea.tsx @@ -1,11 +1,4 @@ -import type { - AgentInfo, - ProviderInfo, - SkillInfo, - SoundEventSetting, - SoundEventType, - SoundSettings, -} from "@opencodegui/core"; +import type { AgentInfo, ProviderInfo, SkillInfo, SoundEventSetting, SoundEventType, SoundSettings } from "@shared"; import { type KeyboardEvent, useCallback, useEffect, useRef, useState } from "react"; import { useClickOutside } from "../../../hooks/useClickOutside"; import { useInputHistory } from "../../../hooks/useInputHistory"; diff --git a/packages/platforms/vscode/webview/components/organisms/InputArea/index.ts b/src/webview/components/organisms/InputArea/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/InputArea/index.ts rename to src/webview/components/organisms/InputArea/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/MessageItem/MessageItem.module.css b/src/webview/components/organisms/MessageItem/MessageItem.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/MessageItem/MessageItem.module.css rename to src/webview/components/organisms/MessageItem/MessageItem.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/MessageItem/MessageItem.tsx b/src/webview/components/organisms/MessageItem/MessageItem.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/organisms/MessageItem/MessageItem.tsx rename to src/webview/components/organisms/MessageItem/MessageItem.tsx index f13f629..2d08f85 100644 --- a/packages/platforms/vscode/webview/components/organisms/MessageItem/MessageItem.tsx +++ b/src/webview/components/organisms/MessageItem/MessageItem.tsx @@ -1,4 +1,4 @@ -import type { QuestionRequest, ReasoningPart as ReasoningPartType, TextPart, ToolPart } from "@opencodegui/core"; +import type { QuestionRequest, ReasoningPart as ReasoningPartType, TextPart, ToolPart } from "@shared"; import { useCallback, useEffect, useRef, useState } from "react"; import type { MessageWithParts } from "../../../App"; import { useAppContext } from "../../../contexts/AppContext"; diff --git a/packages/platforms/vscode/webview/components/organisms/MessageItem/index.ts b/src/webview/components/organisms/MessageItem/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/MessageItem/index.ts rename to src/webview/components/organisms/MessageItem/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/MessagesArea/MessagesArea.module.css b/src/webview/components/organisms/MessagesArea/MessagesArea.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/MessagesArea/MessagesArea.module.css rename to src/webview/components/organisms/MessagesArea/MessagesArea.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/MessagesArea/MessagesArea.tsx b/src/webview/components/organisms/MessagesArea/MessagesArea.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/MessagesArea/MessagesArea.tsx rename to src/webview/components/organisms/MessagesArea/MessagesArea.tsx index ebbe1ad..65bfb55 100644 --- a/packages/platforms/vscode/webview/components/organisms/MessagesArea/MessagesArea.tsx +++ b/src/webview/components/organisms/MessagesArea/MessagesArea.tsx @@ -1,4 +1,4 @@ -import type { QuestionRequest } from "@opencodegui/core"; +import type { QuestionRequest } from "@shared"; import type { MessageWithParts } from "../../../App"; import { useAutoScroll } from "../../../hooks/useAutoScroll"; import { useLocale } from "../../../locales"; diff --git a/packages/platforms/vscode/webview/components/organisms/MessagesArea/index.ts b/src/webview/components/organisms/MessagesArea/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/MessagesArea/index.ts rename to src/webview/components/organisms/MessagesArea/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/PermissionView/PermissionView.module.css b/src/webview/components/organisms/PermissionView/PermissionView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/PermissionView/PermissionView.module.css rename to src/webview/components/organisms/PermissionView/PermissionView.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/PermissionView/PermissionView.tsx b/src/webview/components/organisms/PermissionView/PermissionView.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/PermissionView/PermissionView.tsx rename to src/webview/components/organisms/PermissionView/PermissionView.tsx index 2133433..227b8cb 100644 --- a/packages/platforms/vscode/webview/components/organisms/PermissionView/PermissionView.tsx +++ b/src/webview/components/organisms/PermissionView/PermissionView.tsx @@ -1,4 +1,4 @@ -import type { Permission } from "@opencodegui/core"; +import type { Permission } from "@shared"; import { useState } from "react"; import { useLocale } from "../../../locales"; import { postMessage } from "../../../vscode-api"; diff --git a/packages/platforms/vscode/webview/components/organisms/PermissionView/index.ts b/src/webview/components/organisms/PermissionView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/PermissionView/index.ts rename to src/webview/components/organisms/PermissionView/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/QuestionView/QuestionView.module.css b/src/webview/components/organisms/QuestionView/QuestionView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/QuestionView/QuestionView.module.css rename to src/webview/components/organisms/QuestionView/QuestionView.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/QuestionView/QuestionView.tsx b/src/webview/components/organisms/QuestionView/QuestionView.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/QuestionView/QuestionView.tsx rename to src/webview/components/organisms/QuestionView/QuestionView.tsx index 3eb0a63..dc1f1a0 100644 --- a/packages/platforms/vscode/webview/components/organisms/QuestionView/QuestionView.tsx +++ b/src/webview/components/organisms/QuestionView/QuestionView.tsx @@ -1,4 +1,4 @@ -import type { QuestionAnswer, QuestionRequest } from "@opencodegui/core"; +import type { QuestionAnswer, QuestionRequest } from "@shared"; import { useCallback, useState } from "react"; import { useLocale } from "../../../locales"; import { postMessage } from "../../../vscode-api"; diff --git a/packages/platforms/vscode/webview/components/organisms/QuestionView/index.ts b/src/webview/components/organisms/QuestionView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/QuestionView/index.ts rename to src/webview/components/organisms/QuestionView/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/SessionList/SessionList.module.css b/src/webview/components/organisms/SessionList/SessionList.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/SessionList/SessionList.module.css rename to src/webview/components/organisms/SessionList/SessionList.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/SessionList/SessionList.tsx b/src/webview/components/organisms/SessionList/SessionList.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/SessionList/SessionList.tsx rename to src/webview/components/organisms/SessionList/SessionList.tsx index 0e936c8..77550b1 100644 --- a/packages/platforms/vscode/webview/components/organisms/SessionList/SessionList.tsx +++ b/src/webview/components/organisms/SessionList/SessionList.tsx @@ -1,4 +1,4 @@ -import type { ChatSession } from "@opencodegui/core"; +import type { ChatSession } from "@shared"; import { useLocale } from "../../../locales"; import type { en } from "../../../locales/en"; import { IconButton } from "../../atoms/IconButton"; diff --git a/packages/platforms/vscode/webview/components/organisms/SessionList/index.ts b/src/webview/components/organisms/SessionList/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/SessionList/index.ts rename to src/webview/components/organisms/SessionList/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css b/src/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css rename to src/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx b/src/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx similarity index 98% rename from packages/platforms/vscode/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx rename to src/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx index 9672a42..67d9681 100644 --- a/packages/platforms/vscode/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx +++ b/src/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx @@ -1,4 +1,4 @@ -import type { ChatSession, ToolPart } from "@opencodegui/core"; +import type { ChatSession, ToolPart } from "@shared"; import { useLocale } from "../../../locales"; import { AgentIcon, ChevronRightIcon, SpinnerIcon } from "../../atoms/icons"; import styles from "./SubtaskPartView.module.css"; diff --git a/packages/platforms/vscode/webview/components/organisms/SubtaskPartView/index.ts b/src/webview/components/organisms/SubtaskPartView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/SubtaskPartView/index.ts rename to src/webview/components/organisms/SubtaskPartView/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css b/src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css rename to src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx b/src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx rename to src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx index 25626fb..4a1244e 100644 --- a/packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx +++ b/src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx @@ -1,4 +1,4 @@ -import type { SoundEventSetting, SoundEventType, SoundSettings } from "@opencodegui/core"; +import type { SoundEventSetting, SoundEventType, SoundSettings } from "@shared"; import type { LocaleSetting } from "../../../locales"; import { useLocale } from "../../../locales"; import { IconButton } from "../../atoms/IconButton"; diff --git a/packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/index.ts b/src/webview/components/organisms/ToolConfigPanel/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ToolConfigPanel/index.ts rename to src/webview/components/organisms/ToolConfigPanel/index.ts diff --git a/packages/platforms/vscode/webview/components/organisms/ToolPartView/ToolPartView.module.css b/src/webview/components/organisms/ToolPartView/ToolPartView.module.css similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ToolPartView/ToolPartView.module.css rename to src/webview/components/organisms/ToolPartView/ToolPartView.module.css diff --git a/packages/platforms/vscode/webview/components/organisms/ToolPartView/ToolPartView.tsx b/src/webview/components/organisms/ToolPartView/ToolPartView.tsx similarity index 99% rename from packages/platforms/vscode/webview/components/organisms/ToolPartView/ToolPartView.tsx rename to src/webview/components/organisms/ToolPartView/ToolPartView.tsx index 53d4709..dbbfc0e 100644 --- a/packages/platforms/vscode/webview/components/organisms/ToolPartView/ToolPartView.tsx +++ b/src/webview/components/organisms/ToolPartView/ToolPartView.tsx @@ -1,4 +1,4 @@ -import type { ToolPart } from "@opencodegui/core"; +import type { ToolPart } from "@shared"; import { useCallback, useMemo, useState } from "react"; import { useAppContext } from "../../../contexts/AppContext"; import { useLocale } from "../../../locales"; diff --git a/packages/platforms/vscode/webview/components/organisms/ToolPartView/index.ts b/src/webview/components/organisms/ToolPartView/index.ts similarity index 100% rename from packages/platforms/vscode/webview/components/organisms/ToolPartView/index.ts rename to src/webview/components/organisms/ToolPartView/index.ts diff --git a/packages/platforms/vscode/webview/contexts/AppContext.tsx b/src/webview/contexts/AppContext.tsx similarity index 99% rename from packages/platforms/vscode/webview/contexts/AppContext.tsx rename to src/webview/contexts/AppContext.tsx index cc30179..3803356 100644 --- a/packages/platforms/vscode/webview/contexts/AppContext.tsx +++ b/src/webview/contexts/AppContext.tsx @@ -8,7 +8,7 @@ import type { SoundEventType, SoundSettings, TodoItem, -} from "@opencodegui/core"; +} from "@shared"; import { createContext, useContext } from "react"; import type { MessageWithParts } from "../hooks/useMessages"; import type { LocaleSetting } from "../locales"; diff --git a/packages/platforms/vscode/webview/css-modules.d.ts b/src/webview/css-modules.d.ts similarity index 100% rename from packages/platforms/vscode/webview/css-modules.d.ts rename to src/webview/css-modules.d.ts diff --git a/packages/platforms/vscode/webview/hooks/useAutoScroll.ts b/src/webview/hooks/useAutoScroll.ts similarity index 100% rename from packages/platforms/vscode/webview/hooks/useAutoScroll.ts rename to src/webview/hooks/useAutoScroll.ts diff --git a/packages/platforms/vscode/webview/hooks/useClickOutside.ts b/src/webview/hooks/useClickOutside.ts similarity index 100% rename from packages/platforms/vscode/webview/hooks/useClickOutside.ts rename to src/webview/hooks/useClickOutside.ts diff --git a/packages/platforms/vscode/webview/hooks/useFileChanges.ts b/src/webview/hooks/useFileChanges.ts similarity index 92% rename from packages/platforms/vscode/webview/hooks/useFileChanges.ts rename to src/webview/hooks/useFileChanges.ts index b466321..da45a73 100644 --- a/packages/platforms/vscode/webview/hooks/useFileChanges.ts +++ b/src/webview/hooks/useFileChanges.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, FileDiff } from "@opencodegui/core"; +import type { AgentEvent, FileDiff } from "@shared"; import { useCallback, useState } from "react"; /** diff --git a/packages/platforms/vscode/webview/hooks/useInputHistory.ts b/src/webview/hooks/useInputHistory.ts similarity index 100% rename from packages/platforms/vscode/webview/hooks/useInputHistory.ts rename to src/webview/hooks/useInputHistory.ts diff --git a/packages/platforms/vscode/webview/hooks/useLocale.ts b/src/webview/hooks/useLocale.ts similarity index 100% rename from packages/platforms/vscode/webview/hooks/useLocale.ts rename to src/webview/hooks/useLocale.ts diff --git a/packages/platforms/vscode/webview/hooks/useMessages.ts b/src/webview/hooks/useMessages.ts similarity index 99% rename from packages/platforms/vscode/webview/hooks/useMessages.ts rename to src/webview/hooks/useMessages.ts index 57b1ad1..062b7fb 100644 --- a/packages/platforms/vscode/webview/hooks/useMessages.ts +++ b/src/webview/hooks/useMessages.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, ChatMessage, ChatSession, MessagePart } from "@opencodegui/core"; +import type { AgentEvent, ChatMessage, ChatSession, MessagePart } from "@shared"; import { type RefObject, useCallback, useRef, useState } from "react"; export type MessageWithParts = { info: ChatMessage; parts: MessagePart[] }; diff --git a/packages/platforms/vscode/webview/hooks/usePermissions.ts b/src/webview/hooks/usePermissions.ts similarity index 95% rename from packages/platforms/vscode/webview/hooks/usePermissions.ts rename to src/webview/hooks/usePermissions.ts index 3d7b05b..e4aca6e 100644 --- a/packages/platforms/vscode/webview/hooks/usePermissions.ts +++ b/src/webview/hooks/usePermissions.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, Permission } from "@opencodegui/core"; +import type { AgentEvent, Permission } from "@shared"; import { useCallback, useState } from "react"; /** diff --git a/packages/platforms/vscode/webview/hooks/useProviders.ts b/src/webview/hooks/useProviders.ts similarity index 93% rename from packages/platforms/vscode/webview/hooks/useProviders.ts rename to src/webview/hooks/useProviders.ts index ae62068..c74593d 100644 --- a/packages/platforms/vscode/webview/hooks/useProviders.ts +++ b/src/webview/hooks/useProviders.ts @@ -1,4 +1,4 @@ -import type { ProviderInfo } from "@opencodegui/core"; +import type { ProviderInfo } from "@shared"; import { useCallback, useState } from "react"; import type { AllProvidersData } from "../vscode-api"; import { postMessage } from "../vscode-api"; diff --git a/packages/platforms/vscode/webview/hooks/useQuestions.ts b/src/webview/hooks/useQuestions.ts similarity index 95% rename from packages/platforms/vscode/webview/hooks/useQuestions.ts rename to src/webview/hooks/useQuestions.ts index 32292e2..fb8b4ff 100644 --- a/packages/platforms/vscode/webview/hooks/useQuestions.ts +++ b/src/webview/hooks/useQuestions.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, QuestionRequest } from "@opencodegui/core"; +import type { AgentEvent, QuestionRequest } from "@shared"; import { useCallback, useState } from "react"; /** diff --git a/packages/platforms/vscode/webview/hooks/useSession.ts b/src/webview/hooks/useSession.ts similarity index 96% rename from packages/platforms/vscode/webview/hooks/useSession.ts rename to src/webview/hooks/useSession.ts index 85be60b..a2b4d31 100644 --- a/packages/platforms/vscode/webview/hooks/useSession.ts +++ b/src/webview/hooks/useSession.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, ChatSession } from "@opencodegui/core"; +import type { AgentEvent, ChatSession } from "@shared"; import { useCallback, useState } from "react"; import { postMessage } from "../vscode-api"; diff --git a/packages/platforms/vscode/webview/hooks/useSoundNotification.ts b/src/webview/hooks/useSoundNotification.ts similarity index 99% rename from packages/platforms/vscode/webview/hooks/useSoundNotification.ts rename to src/webview/hooks/useSoundNotification.ts index a5177d2..03ba3d9 100644 --- a/packages/platforms/vscode/webview/hooks/useSoundNotification.ts +++ b/src/webview/hooks/useSoundNotification.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, SoundEventSetting, SoundEventType, SoundSettings } from "@opencodegui/core"; +import type { AgentEvent, SoundEventSetting, SoundEventType, SoundSettings } from "@shared"; import { useCallback, useRef, useState } from "react"; import { getPersistedState, setPersistedState } from "../vscode-api"; diff --git a/packages/platforms/vscode/webview/index.html b/src/webview/index.html similarity index 100% rename from packages/platforms/vscode/webview/index.html rename to src/webview/index.html diff --git a/packages/platforms/vscode/webview/locales/en.ts b/src/webview/locales/en.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/en.ts rename to src/webview/locales/en.ts diff --git a/packages/platforms/vscode/webview/locales/es.ts b/src/webview/locales/es.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/es.ts rename to src/webview/locales/es.ts diff --git a/packages/platforms/vscode/webview/locales/index.ts b/src/webview/locales/index.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/index.ts rename to src/webview/locales/index.ts diff --git a/packages/platforms/vscode/webview/locales/ja.ts b/src/webview/locales/ja.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/ja.ts rename to src/webview/locales/ja.ts diff --git a/packages/platforms/vscode/webview/locales/ko.ts b/src/webview/locales/ko.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/ko.ts rename to src/webview/locales/ko.ts diff --git a/packages/platforms/vscode/webview/locales/pt-br.ts b/src/webview/locales/pt-br.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/pt-br.ts rename to src/webview/locales/pt-br.ts diff --git a/packages/platforms/vscode/webview/locales/ru.ts b/src/webview/locales/ru.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/ru.ts rename to src/webview/locales/ru.ts diff --git a/packages/platforms/vscode/webview/locales/zh-cn.ts b/src/webview/locales/zh-cn.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/zh-cn.ts rename to src/webview/locales/zh-cn.ts diff --git a/packages/platforms/vscode/webview/locales/zh-tw.ts b/src/webview/locales/zh-tw.ts similarity index 100% rename from packages/platforms/vscode/webview/locales/zh-tw.ts rename to src/webview/locales/zh-tw.ts diff --git a/packages/platforms/vscode/webview/main.tsx b/src/webview/main.tsx similarity index 100% rename from packages/platforms/vscode/webview/main.tsx rename to src/webview/main.tsx diff --git a/packages/platforms/vscode/webview/styles.css b/src/webview/styles.css similarity index 100% rename from packages/platforms/vscode/webview/styles.css rename to src/webview/styles.css diff --git a/packages/platforms/vscode/webview/tsconfig.json b/src/webview/tsconfig.json similarity index 81% rename from packages/platforms/vscode/webview/tsconfig.json rename to src/webview/tsconfig.json index db82f5f..bf1bbf6 100644 --- a/packages/platforms/vscode/webview/tsconfig.json +++ b/src/webview/tsconfig.json @@ -5,6 +5,10 @@ "moduleResolution": "bundler", "lib": ["ES2022", "DOM", "DOM.Iterable"], "strict": true, + "baseUrl": "../..", + "paths": { + "@shared": ["src/shared/index.ts"] + }, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, diff --git a/packages/platforms/vscode/webview/utils/diff.ts b/src/webview/utils/diff.ts similarity index 100% rename from packages/platforms/vscode/webview/utils/diff.ts rename to src/webview/utils/diff.ts diff --git a/packages/platforms/vscode/webview/utils/file-icons.ts b/src/webview/utils/file-icons.ts similarity index 100% rename from packages/platforms/vscode/webview/utils/file-icons.ts rename to src/webview/utils/file-icons.ts diff --git a/packages/platforms/vscode/webview/utils/markdown.ts b/src/webview/utils/markdown.ts similarity index 100% rename from packages/platforms/vscode/webview/utils/markdown.ts rename to src/webview/utils/markdown.ts diff --git a/packages/platforms/vscode/webview/utils/todo.ts b/src/webview/utils/todo.ts similarity index 100% rename from packages/platforms/vscode/webview/utils/todo.ts rename to src/webview/utils/todo.ts diff --git a/packages/platforms/vscode/webview/utils/tool-categories.ts b/src/webview/utils/tool-categories.ts similarity index 100% rename from packages/platforms/vscode/webview/utils/tool-categories.ts rename to src/webview/utils/tool-categories.ts diff --git a/packages/platforms/vscode/webview/vscode-api.ts b/src/webview/vscode-api.ts similarity index 76% rename from packages/platforms/vscode/webview/vscode-api.ts rename to src/webview/vscode-api.ts index 34c9c86..3318d52 100644 --- a/packages/platforms/vscode/webview/vscode-api.ts +++ b/src/webview/vscode-api.ts @@ -2,8 +2,8 @@ * VSCode Webview API - backward-compatible re-export layer. * * This module re-exports the IBridge singleton from VscodeBridge and - * domain/protocol types from @opencodegui/core for backward compatibility. - * New code should import directly from @opencodegui/core for types and + * domain/protocol types from @shared for backward compatibility. + * New code should import directly from @shared for types and * use the bridge instance from ./bridges/VscodeBridge. */ @@ -16,9 +16,9 @@ export type { ProviderInfo, UIPersistedState, UIToHostMessage, -} from "@opencodegui/core"; +} from "@shared"; -import type { HostToUIMessage, UIToHostMessage } from "@opencodegui/core"; +import type { HostToUIMessage, UIToHostMessage } from "@shared"; /** @deprecated Use HostToUIMessage instead */ export type ExtToWebviewMessage = HostToUIMessage; @@ -26,8 +26,8 @@ export type ExtToWebviewMessage = HostToUIMessage; export type WebviewToExtMessage = UIToHostMessage; // Re-export UIPersistedState as WebviewPersistedState for backward compatibility -import type { UIPersistedState } from "@opencodegui/core"; -/** @deprecated Use UIPersistedState from @opencodegui/core instead */ +import type { UIPersistedState } from "@shared"; +/** @deprecated Use UIPersistedState from @shared instead */ export type WebviewPersistedState = UIPersistedState; // Re-export bridge functions for backward compatibility diff --git a/packages/platforms/vscode/tsconfig.json b/tsconfig.json similarity index 74% rename from packages/platforms/vscode/tsconfig.json rename to tsconfig.json index c2b161f..f66796f 100644 --- a/packages/platforms/vscode/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,10 @@ "outDir": "./dist", "rootDir": "./src", "strict": true, + "baseUrl": ".", + "paths": { + "@shared": ["src/shared/index.ts"] + }, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, @@ -15,5 +19,5 @@ "jsx": "react-jsx" }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "webview"] + "exclude": ["node_modules", "dist", "src/webview"] } diff --git a/packages/platforms/vscode/vite.config.ts b/vite.config.ts similarity index 73% rename from packages/platforms/vscode/vite.config.ts rename to vite.config.ts index 9481a14..94b5924 100644 --- a/packages/platforms/vscode/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,17 @@ +import path from "node:path"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [react()], - root: "webview", + root: "src/webview", + resolve: { + alias: { + "@shared": path.resolve(__dirname, "src/shared/index.ts"), + }, + }, build: { - outDir: "../dist/webview", + outDir: "../../dist/webview", emptyOutDir: true, // Webview では単一の JS/CSS ファイルにバンドルしたい cssCodeSplit: false, diff --git a/packages/platforms/vscode/vitest.config.ext.ts b/vitest.config.ext.ts similarity index 62% rename from packages/platforms/vscode/vitest.config.ext.ts rename to vitest.config.ext.ts index 8f5a6d5..6addf60 100644 --- a/packages/platforms/vscode/vitest.config.ext.ts +++ b/vitest.config.ext.ts @@ -4,8 +4,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ resolve: { alias: { - "@opencodegui/agent-opencode": path.resolve(__dirname, "../../agents/opencode/src/index.ts"), - "@opencodegui/core": path.resolve(__dirname, "../../core/src/index.ts"), + "@shared": path.resolve(__dirname, "src/shared/index.ts"), }, }, test: { diff --git a/packages/platforms/vscode/vitest.config.ts b/vitest.config.ts similarity index 59% rename from packages/platforms/vscode/vitest.config.ts rename to vitest.config.ts index 0d2b4b4..7335dfd 100644 --- a/packages/platforms/vscode/vitest.config.ts +++ b/vitest.config.ts @@ -1,12 +1,18 @@ +import path from "node:path"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vitest/config"; export default defineConfig({ plugins: [react()], + resolve: { + alias: { + "@shared": path.resolve(__dirname, "src/shared/index.ts"), + }, + }, test: { environment: "jsdom", - root: "webview", - setupFiles: ["./__tests__/setup.ts"], + root: "src/webview", + setupFiles: [path.resolve(__dirname, "src/webview/__tests__/setup.ts")], include: ["./__tests__/**/*.test.{ts,tsx}"], globals: true, css: { From fefad7b3f82253578b1c29fdcfe4e8f0a4c92b2c Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 14:05:53 +0900 Subject: [PATCH 03/25] =?UTF-8?q?nodejs=E3=81=AE=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=83=A7=E3=83=B3=E3=82=92=E5=9B=BA=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 6 ++---- README.md | 6 ++---- mise.toml | 2 ++ package-lock.json | 40 +--------------------------------------- package.json | 3 ++- 5 files changed, 9 insertions(+), 48 deletions(-) create mode 100644 mise.toml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2cb435d..0462d9e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,8 +22,7 @@ This project itself is developed primarily through AI-assisted coding, and we we #### Prerequisites -- Node.js v22+ -- npm +- Node.js v24+ and npm - [OpenCode](https://github.com/anomalyco/opencode) installed with LLM provider authentication configured #### Setup @@ -105,8 +104,7 @@ By submitting a pull request, you agree that your contributions are licensed und #### 前提条件 -- Node.js v22+ -- npm +- Node.js v24+ と npm - [OpenCode](https://github.com/anomalyco/opencode) がインストール済みで、LLM プロバイダの認証が完了していること #### セットアップ diff --git a/README.md b/README.md index e9fd7c4..e7d3bec 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,7 @@ Search for **OpenCodeGUI** in the VS Code Extensions view (`Ctrl+Shift+X` / `Cmd #### Prerequisites -- Node.js v22+ -- npm +- Node.js v24+ and npm #### Setup @@ -243,8 +242,7 @@ VS Code の拡張機能ビュー(`Ctrl+Shift+X` / `Cmd+Shift+X`)で **OpenCo #### 前提条件 -- Node.js v22+ -- npm +- Node.js v24+ と npm #### セットアップ diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..6ea5a7e --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] +node = "24" diff --git a/package-lock.json b/package-lock.json index 09c8f5a..984c36f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "vitest": "^4.0.18" }, "engines": { + "node": ">=24", "vscode": "^1.100.0" } }, @@ -1571,9 +1572,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1588,9 +1586,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1605,9 +1600,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1622,9 +1614,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1639,9 +1628,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1656,9 +1642,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1673,9 +1656,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1690,9 +1670,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1707,9 +1684,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1724,9 +1698,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1741,9 +1712,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1758,9 +1726,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1775,9 +1740,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ diff --git a/package.json b/package.json index d84da35..1d392cd 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "theme": "dark" }, "engines": { - "vscode": "^1.100.0" + "vscode": "^1.100.0", + "node": ">=24" }, "categories": [ "AI", From 2d51afc5503e6ed9f27e213ecef2be790ca5a405 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 15:38:59 +0900 Subject: [PATCH 04/25] =?UTF-8?q?update:=20vite=E9=96=A2=E9=80=A3=E3=81=AE?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=82=92=E4=B8=8A?= =?UTF-8?q?=E3=81=92=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 1597 +++++++++++++++++++-------------------------- package.json | 6 +- 2 files changed, 666 insertions(+), 937 deletions(-) diff --git a/package-lock.json b/package-lock.json index 984c36f..ffeba30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,15 +25,15 @@ "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@types/vscode": "^1.100.0", - "@vitejs/plugin-react": "^5.1.4", + "@vitejs/plugin-react": "^6.0.1", "@vscode/vsce": "^3.7.1", - "esbuild": "^0.25.0", + "esbuild": "^0.28.0", "jsdom": "^28.1.0", "marked": "^17.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", "typescript": "^5.7.0", - "vite": "^6.0.0", + "vite": "^8.0.11", "vitest": "^4.0.18" }, "engines": { @@ -313,143 +313,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", @@ -460,78 +323,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.29.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", @@ -542,54 +333,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@biomejs/biome": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.4.tgz", @@ -906,10 +649,44 @@ "node": ">=20.19.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "cpu": [ "ppc64" ], @@ -924,9 +701,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "cpu": [ "arm" ], @@ -941,9 +718,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "cpu": [ "arm64" ], @@ -958,9 +735,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "cpu": [ "x64" ], @@ -975,9 +752,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "cpu": [ "arm64" ], @@ -992,9 +769,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "cpu": [ "x64" ], @@ -1009,9 +786,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "cpu": [ "arm64" ], @@ -1026,9 +803,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "cpu": [ "x64" ], @@ -1043,9 +820,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "cpu": [ "arm" ], @@ -1060,9 +837,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "cpu": [ "arm64" ], @@ -1077,9 +854,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "cpu": [ "ia32" ], @@ -1094,9 +871,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "cpu": [ "loong64" ], @@ -1111,9 +888,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "cpu": [ "mips64el" ], @@ -1128,9 +905,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "cpu": [ "ppc64" ], @@ -1145,9 +922,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "cpu": [ "riscv64" ], @@ -1162,9 +939,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "cpu": [ "s390x" ], @@ -1179,9 +956,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "cpu": [ "x64" ], @@ -1196,9 +973,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "cpu": [ "arm64" ], @@ -1213,9 +990,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "cpu": [ "x64" ], @@ -1230,9 +1007,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "cpu": [ "arm64" ], @@ -1247,9 +1024,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "cpu": [ "x64" ], @@ -1264,9 +1041,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "cpu": [ "arm64" ], @@ -1281,9 +1058,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "cpu": [ "x64" ], @@ -1298,9 +1075,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "cpu": [ "arm64" ], @@ -1315,9 +1092,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "cpu": [ "ia32" ], @@ -1332,9 +1109,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "cpu": [ "x64" ], @@ -1376,38 +1153,6 @@ "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1415,15 +1160,23 @@ "dev": true, "license": "MIT" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, "node_modules/@nodelib/fs.scandir": { @@ -1473,31 +1226,20 @@ "cross-spawn": "7.0.6" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", - "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", - "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", - "cpu": [ - "arm" - ], + "node_modules/@oxc-project/types": { + "version": "0.128.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.128.0.tgz", + "integrity": "sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "funding": { + "url": "https://github.com/sponsors/Boshen" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", - "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==", "cpu": [ "arm64" ], @@ -1506,12 +1248,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", - "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==", "cpu": [ "arm64" ], @@ -1520,12 +1265,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", - "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==", "cpu": [ "x64" ], @@ -1534,26 +1282,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", - "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", - "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==", "cpu": [ "x64" ], @@ -1562,26 +1299,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", - "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", - "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.18.tgz", + "integrity": "sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==", "cpu": [ "arm" ], @@ -1590,180 +1316,135 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", - "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", - "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", - "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", - "cpu": [ - "loong64" + "libc": [ + "musl" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", - "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", - "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==", "cpu": [ "ppc64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", - "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", - "cpu": [ - "ppc64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", - "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", - "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", - "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", - "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", - "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", - "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", - "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==", "cpu": [ "arm64" ], @@ -1772,40 +1453,51 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", - "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.18.tgz", + "integrity": "sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==", "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", - "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", - "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==", "cpu": [ "x64" ], @@ -1814,21 +1506,17 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", - "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", - "cpu": [ - "x64" ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.7", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", + "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "MIT" }, "node_modules/@secretlint/config-creator": { "version": "10.2.2", @@ -2188,58 +1876,24 @@ "@textlint/ast-node-types": "15.6.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "tslib": "^2.4.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } + "peer": true }, "node_modules/@types/chai": { "version": "5.2.3", @@ -2350,24 +2004,29 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", - "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", + "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-rc.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" + "@rolldown/pluginutils": "1.0.0-rc.7" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } } }, "node_modules/@vitest/expect": { @@ -2841,19 +2500,6 @@ "license": "MIT", "optional": true }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.28", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.28.tgz", - "integrity": "sha512-Ic44hnOtFIgravCunj1ifSoQPSUrkNiJuH9Mf6jr2jjoA74icqV8wU0KuadXeOR8zuIJMOoTv0GuQjZ9ZYNMeA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -2931,40 +2577,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -3055,27 +2667,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001792", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", - "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -3466,7 +3057,6 @@ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -3598,13 +3188,6 @@ "url": "https://bevry.me/fund" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.353", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", - "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", - "dev": true, - "license": "ISC" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3720,9 +3303,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3733,42 +3316,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" } }, "node_modules/estree-walker": { @@ -3941,21 +3514,11 @@ "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { @@ -4613,19 +4176,6 @@ "node": ">=20" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -4748,6 +4298,279 @@ "node": ">=6" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -4821,16 +4644,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -5110,13 +4923,6 @@ "license": "MIT", "optional": true }, - "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", - "dev": true, - "license": "MIT" - }, "node_modules/node-sarif-builder": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", @@ -5676,16 +5482,6 @@ "license": "MIT", "peer": true }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -5783,50 +5579,46 @@ "node": ">=0.10.0" } }, - "node_modules/rollup": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", - "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", + "node_modules/rolldown": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.18.tgz", + "integrity": "sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@oxc-project/types": "=0.128.0", + "@rolldown/pluginutils": "1.0.0-rc.18" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.3", - "@rollup/rollup-android-arm64": "4.60.3", - "@rollup/rollup-darwin-arm64": "4.60.3", - "@rollup/rollup-darwin-x64": "4.60.3", - "@rollup/rollup-freebsd-arm64": "4.60.3", - "@rollup/rollup-freebsd-x64": "4.60.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", - "@rollup/rollup-linux-arm-musleabihf": "4.60.3", - "@rollup/rollup-linux-arm64-gnu": "4.60.3", - "@rollup/rollup-linux-arm64-musl": "4.60.3", - "@rollup/rollup-linux-loong64-gnu": "4.60.3", - "@rollup/rollup-linux-loong64-musl": "4.60.3", - "@rollup/rollup-linux-ppc64-gnu": "4.60.3", - "@rollup/rollup-linux-ppc64-musl": "4.60.3", - "@rollup/rollup-linux-riscv64-gnu": "4.60.3", - "@rollup/rollup-linux-riscv64-musl": "4.60.3", - "@rollup/rollup-linux-s390x-gnu": "4.60.3", - "@rollup/rollup-linux-x64-gnu": "4.60.3", - "@rollup/rollup-linux-x64-musl": "4.60.3", - "@rollup/rollup-openbsd-x64": "4.60.3", - "@rollup/rollup-openharmony-arm64": "4.60.3", - "@rollup/rollup-win32-arm64-msvc": "4.60.3", - "@rollup/rollup-win32-ia32-msvc": "4.60.3", - "@rollup/rollup-win32-x64-gnu": "4.60.3", - "@rollup/rollup-win32-x64-msvc": "4.60.3", - "fsevents": "~2.3.2" - } + "@rolldown/binding-android-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-x64": "1.0.0-rc.18", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.18", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.18", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.18", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.18", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.18", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.18", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz", + "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==", + "dev": true, + "license": "MIT" }, "node_modules/run-applescript": { "version": "7.1.0", @@ -5945,16 +5737,6 @@ "node": ">=20.0.0" } }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6721,37 +6503,6 @@ "node": ">= 10.0.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -6792,24 +6543,23 @@ } }, "node_modules/vite": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", - "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", + "integrity": "sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "rolldown": "1.0.0-rc.18", + "tinyglobby": "^0.2.16" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6818,14 +6568,15 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -6834,13 +6585,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -6866,24 +6620,6 @@ } } }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -7159,13 +6895,6 @@ "dev": true, "license": "MIT" }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, "node_modules/yauzl": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", diff --git a/package.json b/package.json index 1d392cd..ab50922 100644 --- a/package.json +++ b/package.json @@ -84,15 +84,15 @@ "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@types/vscode": "^1.100.0", - "@vitejs/plugin-react": "^5.1.4", + "@vitejs/plugin-react": "^6.0.1", "@vscode/vsce": "^3.7.1", - "esbuild": "^0.25.0", + "esbuild": "^0.28.0", "jsdom": "^28.1.0", "marked": "^17.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", "typescript": "^5.7.0", - "vite": "^6.0.0", + "vite": "^8.0.11", "vitest": "^4.0.18" }, "dependencies": { From ee54afbcc2a87ee121297c46f8ddac64772d0ee7 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 15:43:02 +0900 Subject: [PATCH 05/25] =?UTF-8?q?refactor:=20SVG=E3=82=A2=E3=82=A4?= =?UTF-8?q?=E3=82=B3=E3=83=B3=E3=82=92=E7=9B=B4=E6=8E=A5=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../molecules/TextPartView/TextPartView.tsx | 34 +++---------------- 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/webview/components/molecules/TextPartView/TextPartView.tsx b/src/webview/components/molecules/TextPartView/TextPartView.tsx index f6a8a45..ae51ade 100644 --- a/src/webview/components/molecules/TextPartView/TextPartView.tsx +++ b/src/webview/components/molecules/TextPartView/TextPartView.tsx @@ -2,38 +2,14 @@ import type { TextPart } from "@shared"; import DOMPurify from "dompurify"; import hljs from "highlight.js/lib/common"; import { Marked, type Renderer, type Tokens } from "marked"; -import { createElement, useCallback, useMemo } from "react"; -import { flushSync } from "react-dom"; -import { createRoot } from "react-dom/client"; -import { getFileIcon } from "../../../utils/file-icons"; +import { useCallback, useMemo } from "react"; import { preprocessNestedCodeBlocks } from "../../../utils/markdown"; import { postMessage } from "../../../vscode-api"; // --- SVG アイコン (VSC アイコン相当) --- const COPY_ICON = ``; const CHECK_ICON = ``; - -/** ファイルパスから拡張子に応じたアイコンの HTML 文字列を生成する(結果はキャッシュ) */ -const fileIconHtmlCache = new Map(); -function getFileIconHtml(filePath: string): string { - const fileName = filePath.split("/").pop() || filePath; - const FileTypeIcon = getFileIcon(fileName); - const key = FileTypeIcon.name; - - const cached = fileIconHtmlCache.get(key); - if (cached) return cached; - - const container = document.createElement("span"); - const root = createRoot(container); - flushSync(() => { - root.render(createElement(FileTypeIcon, { width: 12, height: 12, className: "file-chip-icon" })); - }); - const html = container.innerHTML; - root.unmount(); - - fileIconHtmlCache.set(key, html); - return html; -} +const FILE_ICON = ``; /** * コードブロック用カスタムレンダラー。 @@ -67,8 +43,7 @@ const linkRenderer: Partial = { const filePath = lineMatch ? href.slice(0, lineMatch.index) : href; const lineAttr = lineMatch ? ` data-file-line="${lineMatch[1]}"` : ""; const escapedPath = filePath.replace(/"/g, """); - const iconHtml = getFileIconHtml(filePath); - return `${iconHtml}${text}`; + return `${FILE_ICON}${text}`; } return `${text}`; }, @@ -147,8 +122,7 @@ function linkifyAbsolutePaths(html: string): string { const escapedPath = filePath.replace(/"/g, """); const lineAttr = lineNum ? ` data-file-line="${lineNum}"` : ""; const display = lineNum ? `${filePath}:${lineNum}` : filePath; - const iconHtml = getFileIconHtml(filePath); - return `${iconHtml}${display}`; + return `${FILE_ICON}${display}`; }); }); } From 7ef57e4cad7855347c7e08977d6ac33a104d6be0 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 15:44:23 +0900 Subject: [PATCH 06/25] delete: debug logger --- src/chat-view-provider.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/chat-view-provider.ts b/src/chat-view-provider.ts index cd8419c..0122079 100644 --- a/src/chat-view-provider.ts +++ b/src/chat-view-provider.ts @@ -319,15 +319,11 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } case "openDiffReview": { if (!this.activeSession) { - console.warn("[openDiffReview] No active session"); break; } try { - console.log("[openDiffReview] Getting diffs for session:", this.activeSession.id); const diffs = await this.agent.getSessionDiff(this.activeSession.id); - console.log("[openDiffReview] Got diffs:", diffs.length, "files"); if (diffs.length === 0) { - console.warn("[openDiffReview] No diffs returned from agent"); break; } await this.diffReviewManager.start(diffs, message.focusFile); From c5134b806f1d30b45d41fc3b0f801bfcc845d1cb Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 16:19:20 +0900 Subject: [PATCH 07/25] =?UTF-8?q?update:=20webview=E3=82=92=E3=83=95?= =?UTF-8?q?=E3=83=A9=E3=83=83=E3=83=88=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tsconfig.json | 2 +- vite.config.ts | 4 ++-- vitest.config.ts | 4 ++-- {src/webview => webview}/App.tsx | 0 .../__tests__/components/atoms/ActionButton.test.tsx | 0 .../__tests__/components/atoms/IconButton.test.tsx | 0 .../__tests__/components/atoms/LinkButton.test.tsx | 0 .../__tests__/components/atoms/ListItem.test.tsx | 0 .../__tests__/components/atoms/Popover.test.tsx | 0 .../__tests__/components/atoms/StatusItem.test.tsx | 0 .../__tests__/components/atoms/StreamingIndicator.test.tsx | 0 .../__tests__/components/atoms/file-type-icons.test.tsx | 0 .../__tests__/components/atoms/icons.test.tsx | 0 .../__tests__/components/molecules/AgentPopup.test.tsx | 0 .../__tests__/components/molecules/DiffView.test.tsx | 0 .../__tests__/components/molecules/EmptyState.test.tsx | 0 .../__tests__/components/molecules/FileAttachmentBar.test.tsx | 0 .../__tests__/components/molecules/FileChangesHeader.test.tsx | 0 .../__tests__/components/molecules/FileCreateView.test.tsx | 0 .../__tests__/components/molecules/HashFilePopup.test.tsx | 0 .../__tests__/components/molecules/ModelSelector.test.tsx | 0 .../__tests__/components/molecules/ShellResultView.test.tsx | 0 .../__tests__/components/molecules/SkillPopup.test.tsx | 0 .../__tests__/components/molecules/TextPartView.test.tsx | 0 .../__tests__/components/molecules/TodoHeader.test.tsx | 0 .../__tests__/components/molecules/TodoView.test.tsx | 0 .../__tests__/components/organisms/ChatHeader.test.tsx | 0 .../__tests__/components/organisms/MessageItem.test.tsx | 0 .../__tests__/components/organisms/MessagesArea.test.tsx | 0 .../__tests__/components/organisms/PermissionView.test.tsx | 0 .../__tests__/components/organisms/QuestionView.test.tsx | 0 .../__tests__/components/organisms/SessionList.test.tsx | 0 .../__tests__/components/organisms/SubtaskPartView.test.tsx | 0 .../__tests__/components/organisms/ToolConfigPanel.test.tsx | 0 .../__tests__/components/organisms/ToolPartView.test.tsx | 0 {src/webview => webview}/__tests__/factories.ts | 0 {src/webview => webview}/__tests__/helpers.tsx | 0 .../webview => webview}/__tests__/hooks/useAutoScroll.test.ts | 0 .../__tests__/hooks/useClickOutside.test.ts | 0 .../__tests__/hooks/useFileChanges.test.ts | 0 .../__tests__/hooks/useInputHistory.test.ts | 0 {src/webview => webview}/__tests__/hooks/useLocale.test.ts | 0 {src/webview => webview}/__tests__/hooks/useMessages.test.ts | 0 .../__tests__/hooks/usePermissions.test.ts | 0 {src/webview => webview}/__tests__/hooks/useProviders.test.ts | 0 {src/webview => webview}/__tests__/hooks/useQuestions.test.ts | 0 {src/webview => webview}/__tests__/hooks/useSession.test.ts | 0 .../__tests__/hooks/useSoundNotification.test.ts | 0 .../__tests__/scenarios/01-initialization.test.tsx | 0 .../__tests__/scenarios/02-session-lifecycle.test.tsx | 0 .../__tests__/scenarios/03-messaging.test.tsx | 0 .../__tests__/scenarios/04-message-editing.test.tsx | 0 .../__tests__/scenarios/05-permissions.test.tsx | 0 .../__tests__/scenarios/06-model-selection.test.tsx | 0 .../__tests__/scenarios/07-file-context.test.tsx | 0 .../__tests__/scenarios/09-settings.test.tsx | 0 .../__tests__/scenarios/10-tool-display.test.tsx | 0 {src/webview => webview}/__tests__/scenarios/11-todo.test.tsx | 0 .../__tests__/scenarios/12-reasoning-display.test.tsx | 0 .../__tests__/scenarios/13-keyboard-ime.test.tsx | 0 .../__tests__/scenarios/14-shell-command.test.tsx | 0 .../__tests__/scenarios/15-file-changes.test.tsx | 0 .../__tests__/scenarios/16-session-fork.test.tsx | 0 .../__tests__/scenarios/17-child-session-nav.test.tsx | 0 .../__tests__/scenarios/18-agent-mention.test.tsx | 0 .../__tests__/scenarios/19-session-share.test.tsx | 0 .../__tests__/scenarios/20-undo-redo.test.tsx | 0 .../__tests__/scenarios/21-popup-tab-select.test.tsx | 0 .../__tests__/scenarios/22-auto-scroll-streaming.test.tsx | 0 .../__tests__/scenarios/23-clip-context-menu.test.tsx | 0 .../__tests__/scenarios/24-input-history.test.tsx | 0 .../__tests__/scenarios/25-diff-review.test.tsx | 0 .../__tests__/scenarios/25-sound-notification.test.tsx | 0 {src/webview => webview}/__tests__/setup.ts | 2 +- {src/webview => webview}/__tests__/utils/diff.test.ts | 0 {src/webview => webview}/__tests__/utils/file-icons.test.ts | 0 {src/webview => webview}/__tests__/utils/markdown.test.ts | 0 {src/webview => webview}/__tests__/utils/todo.test.ts | 0 .../__tests__/utils/tool-categories.test.ts | 0 {src/webview => webview}/bridges/VscodeBridge.ts | 0 .../components/atoms/ActionButton/ActionButton.module.css | 0 .../components/atoms/ActionButton/ActionButton.tsx | 0 .../components/atoms/ActionButton/index.ts | 0 .../components/atoms/IconButton/IconButton.module.css | 0 .../components/atoms/IconButton/IconButton.tsx | 0 {src/webview => webview}/components/atoms/IconButton/index.ts | 0 .../components/atoms/LinkButton/LinkButton.module.css | 0 .../components/atoms/LinkButton/LinkButton.tsx | 0 {src/webview => webview}/components/atoms/LinkButton/index.ts | 0 .../components/atoms/ListItem/ListItem.module.css | 0 .../components/atoms/ListItem/ListItem.tsx | 0 {src/webview => webview}/components/atoms/ListItem/index.ts | 0 .../components/atoms/Popover/Popover.module.css | 0 {src/webview => webview}/components/atoms/Popover/Popover.tsx | 0 {src/webview => webview}/components/atoms/Popover/index.ts | 0 .../ScrollToBottomButton/ScrollToBottomButton.module.css | 0 .../atoms/ScrollToBottomButton/ScrollToBottomButton.tsx | 0 .../components/atoms/ScrollToBottomButton/index.ts | 0 .../components/atoms/StatusItem/StatusItem.module.css | 0 .../components/atoms/StatusItem/StatusItem.tsx | 0 {src/webview => webview}/components/atoms/StatusItem/index.ts | 0 .../atoms/StreamingIndicator/StreamingIndicator.module.css | 0 .../atoms/StreamingIndicator/StreamingIndicator.tsx | 0 .../components/atoms/StreamingIndicator/index.ts | 0 .../atoms/icons/file-type-icons/file-type-icons.tsx | 0 .../components/atoms/icons/file-type-icons/index.ts | 0 {src/webview => webview}/components/atoms/icons/icons.tsx | 0 {src/webview => webview}/components/atoms/icons/index.ts | 0 .../components/molecules/AgentPopup/AgentPopup.module.css | 0 .../components/molecules/AgentPopup/AgentPopup.tsx | 0 .../components/molecules/AgentPopup/index.ts | 0 .../molecules/AgentSelector/AgentSelector.module.css | 0 .../components/molecules/AgentSelector/AgentSelector.tsx | 0 .../components/molecules/AgentSelector/index.ts | 0 .../components/molecules/DiffView/DiffView.module.css | 0 .../components/molecules/DiffView/DiffView.tsx | 0 .../components/molecules/DiffView/index.ts | 0 .../components/molecules/EmptyState/EmptyState.module.css | 0 .../components/molecules/EmptyState/EmptyState.tsx | 0 .../components/molecules/EmptyState/index.ts | 0 .../molecules/FileAttachmentBar/FileAttachmentBar.module.css | 0 .../molecules/FileAttachmentBar/FileAttachmentBar.tsx | 0 .../components/molecules/FileAttachmentBar/index.ts | 0 .../molecules/FileChangesHeader/FileChangesHeader.module.css | 0 .../molecules/FileChangesHeader/FileChangesHeader.tsx | 0 .../components/molecules/FileChangesHeader/index.ts | 0 .../components/molecules/FileCreateView/FileCreateView.tsx | 0 .../components/molecules/FileCreateView/index.ts | 0 .../molecules/HashFilePopup/HashFilePopup.module.css | 0 .../components/molecules/HashFilePopup/HashFilePopup.tsx | 0 .../components/molecules/HashFilePopup/index.ts | 0 .../molecules/ModelSelector/ModelSelector.module.css | 0 .../components/molecules/ModelSelector/ModelSelector.tsx | 0 .../components/molecules/ModelSelector/index.ts | 0 .../molecules/ShellResultView/ShellResultView.module.css | 0 .../components/molecules/ShellResultView/ShellResultView.tsx | 0 .../components/molecules/ShellResultView/index.ts | 0 .../components/molecules/SkillPopup/SkillPopup.module.css | 0 .../components/molecules/SkillPopup/SkillPopup.tsx | 0 .../components/molecules/SkillPopup/index.ts | 0 .../components/molecules/TextPartView/TextPartView.tsx | 0 .../components/molecules/TextPartView/index.ts | 0 .../components/molecules/TodoHeader/TodoHeader.module.css | 0 .../components/molecules/TodoHeader/TodoHeader.tsx | 0 .../components/molecules/TodoHeader/index.ts | 0 .../components/molecules/TodoView/TodoView.module.css | 0 .../components/molecules/TodoView/TodoView.tsx | 0 .../components/molecules/TodoView/index.ts | 0 .../components/organisms/ChatHeader/ChatHeader.module.css | 0 .../components/organisms/ChatHeader/ChatHeader.tsx | 0 .../components/organisms/ChatHeader/index.ts | 0 .../components/organisms/InputArea/InputArea.module.css | 0 .../components/organisms/InputArea/InputArea.tsx | 0 .../components/organisms/InputArea/index.ts | 0 .../components/organisms/MessageItem/MessageItem.module.css | 0 .../components/organisms/MessageItem/MessageItem.tsx | 0 .../components/organisms/MessageItem/index.ts | 0 .../components/organisms/MessagesArea/MessagesArea.module.css | 0 .../components/organisms/MessagesArea/MessagesArea.tsx | 0 .../components/organisms/MessagesArea/index.ts | 0 .../organisms/PermissionView/PermissionView.module.css | 0 .../components/organisms/PermissionView/PermissionView.tsx | 0 .../components/organisms/PermissionView/index.ts | 0 .../components/organisms/QuestionView/QuestionView.module.css | 0 .../components/organisms/QuestionView/QuestionView.tsx | 0 .../components/organisms/QuestionView/index.ts | 0 .../components/organisms/SessionList/SessionList.module.css | 0 .../components/organisms/SessionList/SessionList.tsx | 0 .../components/organisms/SessionList/index.ts | 0 .../organisms/SubtaskPartView/SubtaskPartView.module.css | 0 .../components/organisms/SubtaskPartView/SubtaskPartView.tsx | 0 .../components/organisms/SubtaskPartView/index.ts | 0 .../organisms/ToolConfigPanel/ToolConfigPanel.module.css | 0 .../components/organisms/ToolConfigPanel/ToolConfigPanel.tsx | 0 .../components/organisms/ToolConfigPanel/index.ts | 0 .../components/organisms/ToolPartView/ToolPartView.module.css | 0 .../components/organisms/ToolPartView/ToolPartView.tsx | 0 .../components/organisms/ToolPartView/index.ts | 0 {src/webview => webview}/contexts/AppContext.tsx | 0 {src/webview => webview}/css-modules.d.ts | 0 {src/webview => webview}/hooks/useAutoScroll.ts | 0 {src/webview => webview}/hooks/useClickOutside.ts | 0 {src/webview => webview}/hooks/useFileChanges.ts | 0 {src/webview => webview}/hooks/useInputHistory.ts | 0 {src/webview => webview}/hooks/useLocale.ts | 0 {src/webview => webview}/hooks/useMessages.ts | 0 {src/webview => webview}/hooks/usePermissions.ts | 0 {src/webview => webview}/hooks/useProviders.ts | 0 {src/webview => webview}/hooks/useQuestions.ts | 0 {src/webview => webview}/hooks/useSession.ts | 0 {src/webview => webview}/hooks/useSoundNotification.ts | 0 {src/webview => webview}/index.html | 0 {src/webview => webview}/locales/en.ts | 0 {src/webview => webview}/locales/es.ts | 0 {src/webview => webview}/locales/index.ts | 0 {src/webview => webview}/locales/ja.ts | 0 {src/webview => webview}/locales/ko.ts | 0 {src/webview => webview}/locales/pt-br.ts | 0 {src/webview => webview}/locales/ru.ts | 0 {src/webview => webview}/locales/zh-cn.ts | 0 {src/webview => webview}/locales/zh-tw.ts | 0 {src/webview => webview}/main.tsx | 0 {src/webview => webview}/styles.css | 0 {src/webview => webview}/tsconfig.json | 2 +- {src/webview => webview}/utils/diff.ts | 0 {src/webview => webview}/utils/file-icons.ts | 0 {src/webview => webview}/utils/markdown.ts | 0 {src/webview => webview}/utils/todo.ts | 0 {src/webview => webview}/utils/tool-categories.ts | 0 {src/webview => webview}/vscode-api.ts | 0 210 files changed, 7 insertions(+), 7 deletions(-) rename {src/webview => webview}/App.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/ActionButton.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/IconButton.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/LinkButton.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/ListItem.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/Popover.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/StatusItem.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/StreamingIndicator.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/file-type-icons.test.tsx (100%) rename {src/webview => webview}/__tests__/components/atoms/icons.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/AgentPopup.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/DiffView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/EmptyState.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/FileAttachmentBar.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/FileChangesHeader.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/FileCreateView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/HashFilePopup.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/ModelSelector.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/ShellResultView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/SkillPopup.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/TextPartView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/TodoHeader.test.tsx (100%) rename {src/webview => webview}/__tests__/components/molecules/TodoView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/ChatHeader.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/MessageItem.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/MessagesArea.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/PermissionView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/QuestionView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/SessionList.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/SubtaskPartView.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/ToolConfigPanel.test.tsx (100%) rename {src/webview => webview}/__tests__/components/organisms/ToolPartView.test.tsx (100%) rename {src/webview => webview}/__tests__/factories.ts (100%) rename {src/webview => webview}/__tests__/helpers.tsx (100%) rename {src/webview => webview}/__tests__/hooks/useAutoScroll.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useClickOutside.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useFileChanges.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useInputHistory.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useLocale.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useMessages.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/usePermissions.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useProviders.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useQuestions.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useSession.test.ts (100%) rename {src/webview => webview}/__tests__/hooks/useSoundNotification.test.ts (100%) rename {src/webview => webview}/__tests__/scenarios/01-initialization.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/02-session-lifecycle.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/03-messaging.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/04-message-editing.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/05-permissions.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/06-model-selection.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/07-file-context.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/09-settings.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/10-tool-display.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/11-todo.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/12-reasoning-display.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/13-keyboard-ime.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/14-shell-command.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/15-file-changes.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/16-session-fork.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/17-child-session-nav.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/18-agent-mention.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/19-session-share.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/20-undo-redo.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/21-popup-tab-select.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/22-auto-scroll-streaming.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/23-clip-context-menu.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/24-input-history.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/25-diff-review.test.tsx (100%) rename {src/webview => webview}/__tests__/scenarios/25-sound-notification.test.tsx (100%) rename {src/webview => webview}/__tests__/setup.ts (95%) rename {src/webview => webview}/__tests__/utils/diff.test.ts (100%) rename {src/webview => webview}/__tests__/utils/file-icons.test.ts (100%) rename {src/webview => webview}/__tests__/utils/markdown.test.ts (100%) rename {src/webview => webview}/__tests__/utils/todo.test.ts (100%) rename {src/webview => webview}/__tests__/utils/tool-categories.test.ts (100%) rename {src/webview => webview}/bridges/VscodeBridge.ts (100%) rename {src/webview => webview}/components/atoms/ActionButton/ActionButton.module.css (100%) rename {src/webview => webview}/components/atoms/ActionButton/ActionButton.tsx (100%) rename {src/webview => webview}/components/atoms/ActionButton/index.ts (100%) rename {src/webview => webview}/components/atoms/IconButton/IconButton.module.css (100%) rename {src/webview => webview}/components/atoms/IconButton/IconButton.tsx (100%) rename {src/webview => webview}/components/atoms/IconButton/index.ts (100%) rename {src/webview => webview}/components/atoms/LinkButton/LinkButton.module.css (100%) rename {src/webview => webview}/components/atoms/LinkButton/LinkButton.tsx (100%) rename {src/webview => webview}/components/atoms/LinkButton/index.ts (100%) rename {src/webview => webview}/components/atoms/ListItem/ListItem.module.css (100%) rename {src/webview => webview}/components/atoms/ListItem/ListItem.tsx (100%) rename {src/webview => webview}/components/atoms/ListItem/index.ts (100%) rename {src/webview => webview}/components/atoms/Popover/Popover.module.css (100%) rename {src/webview => webview}/components/atoms/Popover/Popover.tsx (100%) rename {src/webview => webview}/components/atoms/Popover/index.ts (100%) rename {src/webview => webview}/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css (100%) rename {src/webview => webview}/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx (100%) rename {src/webview => webview}/components/atoms/ScrollToBottomButton/index.ts (100%) rename {src/webview => webview}/components/atoms/StatusItem/StatusItem.module.css (100%) rename {src/webview => webview}/components/atoms/StatusItem/StatusItem.tsx (100%) rename {src/webview => webview}/components/atoms/StatusItem/index.ts (100%) rename {src/webview => webview}/components/atoms/StreamingIndicator/StreamingIndicator.module.css (100%) rename {src/webview => webview}/components/atoms/StreamingIndicator/StreamingIndicator.tsx (100%) rename {src/webview => webview}/components/atoms/StreamingIndicator/index.ts (100%) rename {src/webview => webview}/components/atoms/icons/file-type-icons/file-type-icons.tsx (100%) rename {src/webview => webview}/components/atoms/icons/file-type-icons/index.ts (100%) rename {src/webview => webview}/components/atoms/icons/icons.tsx (100%) rename {src/webview => webview}/components/atoms/icons/index.ts (100%) rename {src/webview => webview}/components/molecules/AgentPopup/AgentPopup.module.css (100%) rename {src/webview => webview}/components/molecules/AgentPopup/AgentPopup.tsx (100%) rename {src/webview => webview}/components/molecules/AgentPopup/index.ts (100%) rename {src/webview => webview}/components/molecules/AgentSelector/AgentSelector.module.css (100%) rename {src/webview => webview}/components/molecules/AgentSelector/AgentSelector.tsx (100%) rename {src/webview => webview}/components/molecules/AgentSelector/index.ts (100%) rename {src/webview => webview}/components/molecules/DiffView/DiffView.module.css (100%) rename {src/webview => webview}/components/molecules/DiffView/DiffView.tsx (100%) rename {src/webview => webview}/components/molecules/DiffView/index.ts (100%) rename {src/webview => webview}/components/molecules/EmptyState/EmptyState.module.css (100%) rename {src/webview => webview}/components/molecules/EmptyState/EmptyState.tsx (100%) rename {src/webview => webview}/components/molecules/EmptyState/index.ts (100%) rename {src/webview => webview}/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css (100%) rename {src/webview => webview}/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx (100%) rename {src/webview => webview}/components/molecules/FileAttachmentBar/index.ts (100%) rename {src/webview => webview}/components/molecules/FileChangesHeader/FileChangesHeader.module.css (100%) rename {src/webview => webview}/components/molecules/FileChangesHeader/FileChangesHeader.tsx (100%) rename {src/webview => webview}/components/molecules/FileChangesHeader/index.ts (100%) rename {src/webview => webview}/components/molecules/FileCreateView/FileCreateView.tsx (100%) rename {src/webview => webview}/components/molecules/FileCreateView/index.ts (100%) rename {src/webview => webview}/components/molecules/HashFilePopup/HashFilePopup.module.css (100%) rename {src/webview => webview}/components/molecules/HashFilePopup/HashFilePopup.tsx (100%) rename {src/webview => webview}/components/molecules/HashFilePopup/index.ts (100%) rename {src/webview => webview}/components/molecules/ModelSelector/ModelSelector.module.css (100%) rename {src/webview => webview}/components/molecules/ModelSelector/ModelSelector.tsx (100%) rename {src/webview => webview}/components/molecules/ModelSelector/index.ts (100%) rename {src/webview => webview}/components/molecules/ShellResultView/ShellResultView.module.css (100%) rename {src/webview => webview}/components/molecules/ShellResultView/ShellResultView.tsx (100%) rename {src/webview => webview}/components/molecules/ShellResultView/index.ts (100%) rename {src/webview => webview}/components/molecules/SkillPopup/SkillPopup.module.css (100%) rename {src/webview => webview}/components/molecules/SkillPopup/SkillPopup.tsx (100%) rename {src/webview => webview}/components/molecules/SkillPopup/index.ts (100%) rename {src/webview => webview}/components/molecules/TextPartView/TextPartView.tsx (100%) rename {src/webview => webview}/components/molecules/TextPartView/index.ts (100%) rename {src/webview => webview}/components/molecules/TodoHeader/TodoHeader.module.css (100%) rename {src/webview => webview}/components/molecules/TodoHeader/TodoHeader.tsx (100%) rename {src/webview => webview}/components/molecules/TodoHeader/index.ts (100%) rename {src/webview => webview}/components/molecules/TodoView/TodoView.module.css (100%) rename {src/webview => webview}/components/molecules/TodoView/TodoView.tsx (100%) rename {src/webview => webview}/components/molecules/TodoView/index.ts (100%) rename {src/webview => webview}/components/organisms/ChatHeader/ChatHeader.module.css (100%) rename {src/webview => webview}/components/organisms/ChatHeader/ChatHeader.tsx (100%) rename {src/webview => webview}/components/organisms/ChatHeader/index.ts (100%) rename {src/webview => webview}/components/organisms/InputArea/InputArea.module.css (100%) rename {src/webview => webview}/components/organisms/InputArea/InputArea.tsx (100%) rename {src/webview => webview}/components/organisms/InputArea/index.ts (100%) rename {src/webview => webview}/components/organisms/MessageItem/MessageItem.module.css (100%) rename {src/webview => webview}/components/organisms/MessageItem/MessageItem.tsx (100%) rename {src/webview => webview}/components/organisms/MessageItem/index.ts (100%) rename {src/webview => webview}/components/organisms/MessagesArea/MessagesArea.module.css (100%) rename {src/webview => webview}/components/organisms/MessagesArea/MessagesArea.tsx (100%) rename {src/webview => webview}/components/organisms/MessagesArea/index.ts (100%) rename {src/webview => webview}/components/organisms/PermissionView/PermissionView.module.css (100%) rename {src/webview => webview}/components/organisms/PermissionView/PermissionView.tsx (100%) rename {src/webview => webview}/components/organisms/PermissionView/index.ts (100%) rename {src/webview => webview}/components/organisms/QuestionView/QuestionView.module.css (100%) rename {src/webview => webview}/components/organisms/QuestionView/QuestionView.tsx (100%) rename {src/webview => webview}/components/organisms/QuestionView/index.ts (100%) rename {src/webview => webview}/components/organisms/SessionList/SessionList.module.css (100%) rename {src/webview => webview}/components/organisms/SessionList/SessionList.tsx (100%) rename {src/webview => webview}/components/organisms/SessionList/index.ts (100%) rename {src/webview => webview}/components/organisms/SubtaskPartView/SubtaskPartView.module.css (100%) rename {src/webview => webview}/components/organisms/SubtaskPartView/SubtaskPartView.tsx (100%) rename {src/webview => webview}/components/organisms/SubtaskPartView/index.ts (100%) rename {src/webview => webview}/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css (100%) rename {src/webview => webview}/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx (100%) rename {src/webview => webview}/components/organisms/ToolConfigPanel/index.ts (100%) rename {src/webview => webview}/components/organisms/ToolPartView/ToolPartView.module.css (100%) rename {src/webview => webview}/components/organisms/ToolPartView/ToolPartView.tsx (100%) rename {src/webview => webview}/components/organisms/ToolPartView/index.ts (100%) rename {src/webview => webview}/contexts/AppContext.tsx (100%) rename {src/webview => webview}/css-modules.d.ts (100%) rename {src/webview => webview}/hooks/useAutoScroll.ts (100%) rename {src/webview => webview}/hooks/useClickOutside.ts (100%) rename {src/webview => webview}/hooks/useFileChanges.ts (100%) rename {src/webview => webview}/hooks/useInputHistory.ts (100%) rename {src/webview => webview}/hooks/useLocale.ts (100%) rename {src/webview => webview}/hooks/useMessages.ts (100%) rename {src/webview => webview}/hooks/usePermissions.ts (100%) rename {src/webview => webview}/hooks/useProviders.ts (100%) rename {src/webview => webview}/hooks/useQuestions.ts (100%) rename {src/webview => webview}/hooks/useSession.ts (100%) rename {src/webview => webview}/hooks/useSoundNotification.ts (100%) rename {src/webview => webview}/index.html (100%) rename {src/webview => webview}/locales/en.ts (100%) rename {src/webview => webview}/locales/es.ts (100%) rename {src/webview => webview}/locales/index.ts (100%) rename {src/webview => webview}/locales/ja.ts (100%) rename {src/webview => webview}/locales/ko.ts (100%) rename {src/webview => webview}/locales/pt-br.ts (100%) rename {src/webview => webview}/locales/ru.ts (100%) rename {src/webview => webview}/locales/zh-cn.ts (100%) rename {src/webview => webview}/locales/zh-tw.ts (100%) rename {src/webview => webview}/main.tsx (100%) rename {src/webview => webview}/styles.css (100%) rename {src/webview => webview}/tsconfig.json (94%) rename {src/webview => webview}/utils/diff.ts (100%) rename {src/webview => webview}/utils/file-icons.ts (100%) rename {src/webview => webview}/utils/markdown.ts (100%) rename {src/webview => webview}/utils/todo.ts (100%) rename {src/webview => webview}/utils/tool-categories.ts (100%) rename {src/webview => webview}/vscode-api.ts (100%) diff --git a/tsconfig.json b/tsconfig.json index f66796f..25fcab0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,5 @@ "jsx": "react-jsx" }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "src/webview"] + "exclude": ["node_modules", "dist", "webview"] } diff --git a/vite.config.ts b/vite.config.ts index 94b5924..12b19e3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,14 +4,14 @@ import { defineConfig } from "vite"; export default defineConfig({ plugins: [react()], - root: "src/webview", + root: "webview", resolve: { alias: { "@shared": path.resolve(__dirname, "src/shared/index.ts"), }, }, build: { - outDir: "../../dist/webview", + outDir: "../dist/webview", emptyOutDir: true, // Webview では単一の JS/CSS ファイルにバンドルしたい cssCodeSplit: false, diff --git a/vitest.config.ts b/vitest.config.ts index 7335dfd..4bd8f56 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,8 +11,8 @@ export default defineConfig({ }, test: { environment: "jsdom", - root: "src/webview", - setupFiles: [path.resolve(__dirname, "src/webview/__tests__/setup.ts")], + root: "webview", + setupFiles: [path.resolve(__dirname, "webview/__tests__/setup.ts")], include: ["./__tests__/**/*.test.{ts,tsx}"], globals: true, css: { diff --git a/src/webview/App.tsx b/webview/App.tsx similarity index 100% rename from src/webview/App.tsx rename to webview/App.tsx diff --git a/src/webview/__tests__/components/atoms/ActionButton.test.tsx b/webview/__tests__/components/atoms/ActionButton.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/ActionButton.test.tsx rename to webview/__tests__/components/atoms/ActionButton.test.tsx diff --git a/src/webview/__tests__/components/atoms/IconButton.test.tsx b/webview/__tests__/components/atoms/IconButton.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/IconButton.test.tsx rename to webview/__tests__/components/atoms/IconButton.test.tsx diff --git a/src/webview/__tests__/components/atoms/LinkButton.test.tsx b/webview/__tests__/components/atoms/LinkButton.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/LinkButton.test.tsx rename to webview/__tests__/components/atoms/LinkButton.test.tsx diff --git a/src/webview/__tests__/components/atoms/ListItem.test.tsx b/webview/__tests__/components/atoms/ListItem.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/ListItem.test.tsx rename to webview/__tests__/components/atoms/ListItem.test.tsx diff --git a/src/webview/__tests__/components/atoms/Popover.test.tsx b/webview/__tests__/components/atoms/Popover.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/Popover.test.tsx rename to webview/__tests__/components/atoms/Popover.test.tsx diff --git a/src/webview/__tests__/components/atoms/StatusItem.test.tsx b/webview/__tests__/components/atoms/StatusItem.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/StatusItem.test.tsx rename to webview/__tests__/components/atoms/StatusItem.test.tsx diff --git a/src/webview/__tests__/components/atoms/StreamingIndicator.test.tsx b/webview/__tests__/components/atoms/StreamingIndicator.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/StreamingIndicator.test.tsx rename to webview/__tests__/components/atoms/StreamingIndicator.test.tsx diff --git a/src/webview/__tests__/components/atoms/file-type-icons.test.tsx b/webview/__tests__/components/atoms/file-type-icons.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/file-type-icons.test.tsx rename to webview/__tests__/components/atoms/file-type-icons.test.tsx diff --git a/src/webview/__tests__/components/atoms/icons.test.tsx b/webview/__tests__/components/atoms/icons.test.tsx similarity index 100% rename from src/webview/__tests__/components/atoms/icons.test.tsx rename to webview/__tests__/components/atoms/icons.test.tsx diff --git a/src/webview/__tests__/components/molecules/AgentPopup.test.tsx b/webview/__tests__/components/molecules/AgentPopup.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/AgentPopup.test.tsx rename to webview/__tests__/components/molecules/AgentPopup.test.tsx diff --git a/src/webview/__tests__/components/molecules/DiffView.test.tsx b/webview/__tests__/components/molecules/DiffView.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/DiffView.test.tsx rename to webview/__tests__/components/molecules/DiffView.test.tsx diff --git a/src/webview/__tests__/components/molecules/EmptyState.test.tsx b/webview/__tests__/components/molecules/EmptyState.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/EmptyState.test.tsx rename to webview/__tests__/components/molecules/EmptyState.test.tsx diff --git a/src/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx b/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/FileAttachmentBar.test.tsx rename to webview/__tests__/components/molecules/FileAttachmentBar.test.tsx diff --git a/src/webview/__tests__/components/molecules/FileChangesHeader.test.tsx b/webview/__tests__/components/molecules/FileChangesHeader.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/FileChangesHeader.test.tsx rename to webview/__tests__/components/molecules/FileChangesHeader.test.tsx diff --git a/src/webview/__tests__/components/molecules/FileCreateView.test.tsx b/webview/__tests__/components/molecules/FileCreateView.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/FileCreateView.test.tsx rename to webview/__tests__/components/molecules/FileCreateView.test.tsx diff --git a/src/webview/__tests__/components/molecules/HashFilePopup.test.tsx b/webview/__tests__/components/molecules/HashFilePopup.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/HashFilePopup.test.tsx rename to webview/__tests__/components/molecules/HashFilePopup.test.tsx diff --git a/src/webview/__tests__/components/molecules/ModelSelector.test.tsx b/webview/__tests__/components/molecules/ModelSelector.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/ModelSelector.test.tsx rename to webview/__tests__/components/molecules/ModelSelector.test.tsx diff --git a/src/webview/__tests__/components/molecules/ShellResultView.test.tsx b/webview/__tests__/components/molecules/ShellResultView.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/ShellResultView.test.tsx rename to webview/__tests__/components/molecules/ShellResultView.test.tsx diff --git a/src/webview/__tests__/components/molecules/SkillPopup.test.tsx b/webview/__tests__/components/molecules/SkillPopup.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/SkillPopup.test.tsx rename to webview/__tests__/components/molecules/SkillPopup.test.tsx diff --git a/src/webview/__tests__/components/molecules/TextPartView.test.tsx b/webview/__tests__/components/molecules/TextPartView.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/TextPartView.test.tsx rename to webview/__tests__/components/molecules/TextPartView.test.tsx diff --git a/src/webview/__tests__/components/molecules/TodoHeader.test.tsx b/webview/__tests__/components/molecules/TodoHeader.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/TodoHeader.test.tsx rename to webview/__tests__/components/molecules/TodoHeader.test.tsx diff --git a/src/webview/__tests__/components/molecules/TodoView.test.tsx b/webview/__tests__/components/molecules/TodoView.test.tsx similarity index 100% rename from src/webview/__tests__/components/molecules/TodoView.test.tsx rename to webview/__tests__/components/molecules/TodoView.test.tsx diff --git a/src/webview/__tests__/components/organisms/ChatHeader.test.tsx b/webview/__tests__/components/organisms/ChatHeader.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/ChatHeader.test.tsx rename to webview/__tests__/components/organisms/ChatHeader.test.tsx diff --git a/src/webview/__tests__/components/organisms/MessageItem.test.tsx b/webview/__tests__/components/organisms/MessageItem.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/MessageItem.test.tsx rename to webview/__tests__/components/organisms/MessageItem.test.tsx diff --git a/src/webview/__tests__/components/organisms/MessagesArea.test.tsx b/webview/__tests__/components/organisms/MessagesArea.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/MessagesArea.test.tsx rename to webview/__tests__/components/organisms/MessagesArea.test.tsx diff --git a/src/webview/__tests__/components/organisms/PermissionView.test.tsx b/webview/__tests__/components/organisms/PermissionView.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/PermissionView.test.tsx rename to webview/__tests__/components/organisms/PermissionView.test.tsx diff --git a/src/webview/__tests__/components/organisms/QuestionView.test.tsx b/webview/__tests__/components/organisms/QuestionView.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/QuestionView.test.tsx rename to webview/__tests__/components/organisms/QuestionView.test.tsx diff --git a/src/webview/__tests__/components/organisms/SessionList.test.tsx b/webview/__tests__/components/organisms/SessionList.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/SessionList.test.tsx rename to webview/__tests__/components/organisms/SessionList.test.tsx diff --git a/src/webview/__tests__/components/organisms/SubtaskPartView.test.tsx b/webview/__tests__/components/organisms/SubtaskPartView.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/SubtaskPartView.test.tsx rename to webview/__tests__/components/organisms/SubtaskPartView.test.tsx diff --git a/src/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx b/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/ToolConfigPanel.test.tsx rename to webview/__tests__/components/organisms/ToolConfigPanel.test.tsx diff --git a/src/webview/__tests__/components/organisms/ToolPartView.test.tsx b/webview/__tests__/components/organisms/ToolPartView.test.tsx similarity index 100% rename from src/webview/__tests__/components/organisms/ToolPartView.test.tsx rename to webview/__tests__/components/organisms/ToolPartView.test.tsx diff --git a/src/webview/__tests__/factories.ts b/webview/__tests__/factories.ts similarity index 100% rename from src/webview/__tests__/factories.ts rename to webview/__tests__/factories.ts diff --git a/src/webview/__tests__/helpers.tsx b/webview/__tests__/helpers.tsx similarity index 100% rename from src/webview/__tests__/helpers.tsx rename to webview/__tests__/helpers.tsx diff --git a/src/webview/__tests__/hooks/useAutoScroll.test.ts b/webview/__tests__/hooks/useAutoScroll.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useAutoScroll.test.ts rename to webview/__tests__/hooks/useAutoScroll.test.ts diff --git a/src/webview/__tests__/hooks/useClickOutside.test.ts b/webview/__tests__/hooks/useClickOutside.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useClickOutside.test.ts rename to webview/__tests__/hooks/useClickOutside.test.ts diff --git a/src/webview/__tests__/hooks/useFileChanges.test.ts b/webview/__tests__/hooks/useFileChanges.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useFileChanges.test.ts rename to webview/__tests__/hooks/useFileChanges.test.ts diff --git a/src/webview/__tests__/hooks/useInputHistory.test.ts b/webview/__tests__/hooks/useInputHistory.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useInputHistory.test.ts rename to webview/__tests__/hooks/useInputHistory.test.ts diff --git a/src/webview/__tests__/hooks/useLocale.test.ts b/webview/__tests__/hooks/useLocale.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useLocale.test.ts rename to webview/__tests__/hooks/useLocale.test.ts diff --git a/src/webview/__tests__/hooks/useMessages.test.ts b/webview/__tests__/hooks/useMessages.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useMessages.test.ts rename to webview/__tests__/hooks/useMessages.test.ts diff --git a/src/webview/__tests__/hooks/usePermissions.test.ts b/webview/__tests__/hooks/usePermissions.test.ts similarity index 100% rename from src/webview/__tests__/hooks/usePermissions.test.ts rename to webview/__tests__/hooks/usePermissions.test.ts diff --git a/src/webview/__tests__/hooks/useProviders.test.ts b/webview/__tests__/hooks/useProviders.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useProviders.test.ts rename to webview/__tests__/hooks/useProviders.test.ts diff --git a/src/webview/__tests__/hooks/useQuestions.test.ts b/webview/__tests__/hooks/useQuestions.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useQuestions.test.ts rename to webview/__tests__/hooks/useQuestions.test.ts diff --git a/src/webview/__tests__/hooks/useSession.test.ts b/webview/__tests__/hooks/useSession.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useSession.test.ts rename to webview/__tests__/hooks/useSession.test.ts diff --git a/src/webview/__tests__/hooks/useSoundNotification.test.ts b/webview/__tests__/hooks/useSoundNotification.test.ts similarity index 100% rename from src/webview/__tests__/hooks/useSoundNotification.test.ts rename to webview/__tests__/hooks/useSoundNotification.test.ts diff --git a/src/webview/__tests__/scenarios/01-initialization.test.tsx b/webview/__tests__/scenarios/01-initialization.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/01-initialization.test.tsx rename to webview/__tests__/scenarios/01-initialization.test.tsx diff --git a/src/webview/__tests__/scenarios/02-session-lifecycle.test.tsx b/webview/__tests__/scenarios/02-session-lifecycle.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/02-session-lifecycle.test.tsx rename to webview/__tests__/scenarios/02-session-lifecycle.test.tsx diff --git a/src/webview/__tests__/scenarios/03-messaging.test.tsx b/webview/__tests__/scenarios/03-messaging.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/03-messaging.test.tsx rename to webview/__tests__/scenarios/03-messaging.test.tsx diff --git a/src/webview/__tests__/scenarios/04-message-editing.test.tsx b/webview/__tests__/scenarios/04-message-editing.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/04-message-editing.test.tsx rename to webview/__tests__/scenarios/04-message-editing.test.tsx diff --git a/src/webview/__tests__/scenarios/05-permissions.test.tsx b/webview/__tests__/scenarios/05-permissions.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/05-permissions.test.tsx rename to webview/__tests__/scenarios/05-permissions.test.tsx diff --git a/src/webview/__tests__/scenarios/06-model-selection.test.tsx b/webview/__tests__/scenarios/06-model-selection.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/06-model-selection.test.tsx rename to webview/__tests__/scenarios/06-model-selection.test.tsx diff --git a/src/webview/__tests__/scenarios/07-file-context.test.tsx b/webview/__tests__/scenarios/07-file-context.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/07-file-context.test.tsx rename to webview/__tests__/scenarios/07-file-context.test.tsx diff --git a/src/webview/__tests__/scenarios/09-settings.test.tsx b/webview/__tests__/scenarios/09-settings.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/09-settings.test.tsx rename to webview/__tests__/scenarios/09-settings.test.tsx diff --git a/src/webview/__tests__/scenarios/10-tool-display.test.tsx b/webview/__tests__/scenarios/10-tool-display.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/10-tool-display.test.tsx rename to webview/__tests__/scenarios/10-tool-display.test.tsx diff --git a/src/webview/__tests__/scenarios/11-todo.test.tsx b/webview/__tests__/scenarios/11-todo.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/11-todo.test.tsx rename to webview/__tests__/scenarios/11-todo.test.tsx diff --git a/src/webview/__tests__/scenarios/12-reasoning-display.test.tsx b/webview/__tests__/scenarios/12-reasoning-display.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/12-reasoning-display.test.tsx rename to webview/__tests__/scenarios/12-reasoning-display.test.tsx diff --git a/src/webview/__tests__/scenarios/13-keyboard-ime.test.tsx b/webview/__tests__/scenarios/13-keyboard-ime.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/13-keyboard-ime.test.tsx rename to webview/__tests__/scenarios/13-keyboard-ime.test.tsx diff --git a/src/webview/__tests__/scenarios/14-shell-command.test.tsx b/webview/__tests__/scenarios/14-shell-command.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/14-shell-command.test.tsx rename to webview/__tests__/scenarios/14-shell-command.test.tsx diff --git a/src/webview/__tests__/scenarios/15-file-changes.test.tsx b/webview/__tests__/scenarios/15-file-changes.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/15-file-changes.test.tsx rename to webview/__tests__/scenarios/15-file-changes.test.tsx diff --git a/src/webview/__tests__/scenarios/16-session-fork.test.tsx b/webview/__tests__/scenarios/16-session-fork.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/16-session-fork.test.tsx rename to webview/__tests__/scenarios/16-session-fork.test.tsx diff --git a/src/webview/__tests__/scenarios/17-child-session-nav.test.tsx b/webview/__tests__/scenarios/17-child-session-nav.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/17-child-session-nav.test.tsx rename to webview/__tests__/scenarios/17-child-session-nav.test.tsx diff --git a/src/webview/__tests__/scenarios/18-agent-mention.test.tsx b/webview/__tests__/scenarios/18-agent-mention.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/18-agent-mention.test.tsx rename to webview/__tests__/scenarios/18-agent-mention.test.tsx diff --git a/src/webview/__tests__/scenarios/19-session-share.test.tsx b/webview/__tests__/scenarios/19-session-share.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/19-session-share.test.tsx rename to webview/__tests__/scenarios/19-session-share.test.tsx diff --git a/src/webview/__tests__/scenarios/20-undo-redo.test.tsx b/webview/__tests__/scenarios/20-undo-redo.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/20-undo-redo.test.tsx rename to webview/__tests__/scenarios/20-undo-redo.test.tsx diff --git a/src/webview/__tests__/scenarios/21-popup-tab-select.test.tsx b/webview/__tests__/scenarios/21-popup-tab-select.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/21-popup-tab-select.test.tsx rename to webview/__tests__/scenarios/21-popup-tab-select.test.tsx diff --git a/src/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx b/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx rename to webview/__tests__/scenarios/22-auto-scroll-streaming.test.tsx diff --git a/src/webview/__tests__/scenarios/23-clip-context-menu.test.tsx b/webview/__tests__/scenarios/23-clip-context-menu.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/23-clip-context-menu.test.tsx rename to webview/__tests__/scenarios/23-clip-context-menu.test.tsx diff --git a/src/webview/__tests__/scenarios/24-input-history.test.tsx b/webview/__tests__/scenarios/24-input-history.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/24-input-history.test.tsx rename to webview/__tests__/scenarios/24-input-history.test.tsx diff --git a/src/webview/__tests__/scenarios/25-diff-review.test.tsx b/webview/__tests__/scenarios/25-diff-review.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/25-diff-review.test.tsx rename to webview/__tests__/scenarios/25-diff-review.test.tsx diff --git a/src/webview/__tests__/scenarios/25-sound-notification.test.tsx b/webview/__tests__/scenarios/25-sound-notification.test.tsx similarity index 100% rename from src/webview/__tests__/scenarios/25-sound-notification.test.tsx rename to webview/__tests__/scenarios/25-sound-notification.test.tsx diff --git a/src/webview/__tests__/setup.ts b/webview/__tests__/setup.ts similarity index 95% rename from src/webview/__tests__/setup.ts rename to webview/__tests__/setup.ts index 7dc0a5f..c9b3036 100644 --- a/src/webview/__tests__/setup.ts +++ b/webview/__tests__/setup.ts @@ -37,7 +37,7 @@ globalThis.AudioContext = vi.fn(function (this: Record) { }) as unknown as typeof AudioContext; // --- vscode-api モック --- -// acquireVsCodeApi はグローバル関数として宣言されており、src/webview/vscode-api.ts のモジュールスコープで呼ばれる。 +// acquireVsCodeApi はグローバル関数として宣言されており、webview/vscode-api.ts のモジュールスコープで呼ばれる。 // モジュール全体をモックにして postMessage / getPersistedState / setPersistedState をスパイ化する。 vi.mock("../vscode-api", () => ({ diff --git a/src/webview/__tests__/utils/diff.test.ts b/webview/__tests__/utils/diff.test.ts similarity index 100% rename from src/webview/__tests__/utils/diff.test.ts rename to webview/__tests__/utils/diff.test.ts diff --git a/src/webview/__tests__/utils/file-icons.test.ts b/webview/__tests__/utils/file-icons.test.ts similarity index 100% rename from src/webview/__tests__/utils/file-icons.test.ts rename to webview/__tests__/utils/file-icons.test.ts diff --git a/src/webview/__tests__/utils/markdown.test.ts b/webview/__tests__/utils/markdown.test.ts similarity index 100% rename from src/webview/__tests__/utils/markdown.test.ts rename to webview/__tests__/utils/markdown.test.ts diff --git a/src/webview/__tests__/utils/todo.test.ts b/webview/__tests__/utils/todo.test.ts similarity index 100% rename from src/webview/__tests__/utils/todo.test.ts rename to webview/__tests__/utils/todo.test.ts diff --git a/src/webview/__tests__/utils/tool-categories.test.ts b/webview/__tests__/utils/tool-categories.test.ts similarity index 100% rename from src/webview/__tests__/utils/tool-categories.test.ts rename to webview/__tests__/utils/tool-categories.test.ts diff --git a/src/webview/bridges/VscodeBridge.ts b/webview/bridges/VscodeBridge.ts similarity index 100% rename from src/webview/bridges/VscodeBridge.ts rename to webview/bridges/VscodeBridge.ts diff --git a/src/webview/components/atoms/ActionButton/ActionButton.module.css b/webview/components/atoms/ActionButton/ActionButton.module.css similarity index 100% rename from src/webview/components/atoms/ActionButton/ActionButton.module.css rename to webview/components/atoms/ActionButton/ActionButton.module.css diff --git a/src/webview/components/atoms/ActionButton/ActionButton.tsx b/webview/components/atoms/ActionButton/ActionButton.tsx similarity index 100% rename from src/webview/components/atoms/ActionButton/ActionButton.tsx rename to webview/components/atoms/ActionButton/ActionButton.tsx diff --git a/src/webview/components/atoms/ActionButton/index.ts b/webview/components/atoms/ActionButton/index.ts similarity index 100% rename from src/webview/components/atoms/ActionButton/index.ts rename to webview/components/atoms/ActionButton/index.ts diff --git a/src/webview/components/atoms/IconButton/IconButton.module.css b/webview/components/atoms/IconButton/IconButton.module.css similarity index 100% rename from src/webview/components/atoms/IconButton/IconButton.module.css rename to webview/components/atoms/IconButton/IconButton.module.css diff --git a/src/webview/components/atoms/IconButton/IconButton.tsx b/webview/components/atoms/IconButton/IconButton.tsx similarity index 100% rename from src/webview/components/atoms/IconButton/IconButton.tsx rename to webview/components/atoms/IconButton/IconButton.tsx diff --git a/src/webview/components/atoms/IconButton/index.ts b/webview/components/atoms/IconButton/index.ts similarity index 100% rename from src/webview/components/atoms/IconButton/index.ts rename to webview/components/atoms/IconButton/index.ts diff --git a/src/webview/components/atoms/LinkButton/LinkButton.module.css b/webview/components/atoms/LinkButton/LinkButton.module.css similarity index 100% rename from src/webview/components/atoms/LinkButton/LinkButton.module.css rename to webview/components/atoms/LinkButton/LinkButton.module.css diff --git a/src/webview/components/atoms/LinkButton/LinkButton.tsx b/webview/components/atoms/LinkButton/LinkButton.tsx similarity index 100% rename from src/webview/components/atoms/LinkButton/LinkButton.tsx rename to webview/components/atoms/LinkButton/LinkButton.tsx diff --git a/src/webview/components/atoms/LinkButton/index.ts b/webview/components/atoms/LinkButton/index.ts similarity index 100% rename from src/webview/components/atoms/LinkButton/index.ts rename to webview/components/atoms/LinkButton/index.ts diff --git a/src/webview/components/atoms/ListItem/ListItem.module.css b/webview/components/atoms/ListItem/ListItem.module.css similarity index 100% rename from src/webview/components/atoms/ListItem/ListItem.module.css rename to webview/components/atoms/ListItem/ListItem.module.css diff --git a/src/webview/components/atoms/ListItem/ListItem.tsx b/webview/components/atoms/ListItem/ListItem.tsx similarity index 100% rename from src/webview/components/atoms/ListItem/ListItem.tsx rename to webview/components/atoms/ListItem/ListItem.tsx diff --git a/src/webview/components/atoms/ListItem/index.ts b/webview/components/atoms/ListItem/index.ts similarity index 100% rename from src/webview/components/atoms/ListItem/index.ts rename to webview/components/atoms/ListItem/index.ts diff --git a/src/webview/components/atoms/Popover/Popover.module.css b/webview/components/atoms/Popover/Popover.module.css similarity index 100% rename from src/webview/components/atoms/Popover/Popover.module.css rename to webview/components/atoms/Popover/Popover.module.css diff --git a/src/webview/components/atoms/Popover/Popover.tsx b/webview/components/atoms/Popover/Popover.tsx similarity index 100% rename from src/webview/components/atoms/Popover/Popover.tsx rename to webview/components/atoms/Popover/Popover.tsx diff --git a/src/webview/components/atoms/Popover/index.ts b/webview/components/atoms/Popover/index.ts similarity index 100% rename from src/webview/components/atoms/Popover/index.ts rename to webview/components/atoms/Popover/index.ts diff --git a/src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css b/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css similarity index 100% rename from src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css rename to webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.module.css diff --git a/src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx b/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx similarity index 100% rename from src/webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx rename to webview/components/atoms/ScrollToBottomButton/ScrollToBottomButton.tsx diff --git a/src/webview/components/atoms/ScrollToBottomButton/index.ts b/webview/components/atoms/ScrollToBottomButton/index.ts similarity index 100% rename from src/webview/components/atoms/ScrollToBottomButton/index.ts rename to webview/components/atoms/ScrollToBottomButton/index.ts diff --git a/src/webview/components/atoms/StatusItem/StatusItem.module.css b/webview/components/atoms/StatusItem/StatusItem.module.css similarity index 100% rename from src/webview/components/atoms/StatusItem/StatusItem.module.css rename to webview/components/atoms/StatusItem/StatusItem.module.css diff --git a/src/webview/components/atoms/StatusItem/StatusItem.tsx b/webview/components/atoms/StatusItem/StatusItem.tsx similarity index 100% rename from src/webview/components/atoms/StatusItem/StatusItem.tsx rename to webview/components/atoms/StatusItem/StatusItem.tsx diff --git a/src/webview/components/atoms/StatusItem/index.ts b/webview/components/atoms/StatusItem/index.ts similarity index 100% rename from src/webview/components/atoms/StatusItem/index.ts rename to webview/components/atoms/StatusItem/index.ts diff --git a/src/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css b/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css similarity index 100% rename from src/webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css rename to webview/components/atoms/StreamingIndicator/StreamingIndicator.module.css diff --git a/src/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx b/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx similarity index 100% rename from src/webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx rename to webview/components/atoms/StreamingIndicator/StreamingIndicator.tsx diff --git a/src/webview/components/atoms/StreamingIndicator/index.ts b/webview/components/atoms/StreamingIndicator/index.ts similarity index 100% rename from src/webview/components/atoms/StreamingIndicator/index.ts rename to webview/components/atoms/StreamingIndicator/index.ts diff --git a/src/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx b/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx similarity index 100% rename from src/webview/components/atoms/icons/file-type-icons/file-type-icons.tsx rename to webview/components/atoms/icons/file-type-icons/file-type-icons.tsx diff --git a/src/webview/components/atoms/icons/file-type-icons/index.ts b/webview/components/atoms/icons/file-type-icons/index.ts similarity index 100% rename from src/webview/components/atoms/icons/file-type-icons/index.ts rename to webview/components/atoms/icons/file-type-icons/index.ts diff --git a/src/webview/components/atoms/icons/icons.tsx b/webview/components/atoms/icons/icons.tsx similarity index 100% rename from src/webview/components/atoms/icons/icons.tsx rename to webview/components/atoms/icons/icons.tsx diff --git a/src/webview/components/atoms/icons/index.ts b/webview/components/atoms/icons/index.ts similarity index 100% rename from src/webview/components/atoms/icons/index.ts rename to webview/components/atoms/icons/index.ts diff --git a/src/webview/components/molecules/AgentPopup/AgentPopup.module.css b/webview/components/molecules/AgentPopup/AgentPopup.module.css similarity index 100% rename from src/webview/components/molecules/AgentPopup/AgentPopup.module.css rename to webview/components/molecules/AgentPopup/AgentPopup.module.css diff --git a/src/webview/components/molecules/AgentPopup/AgentPopup.tsx b/webview/components/molecules/AgentPopup/AgentPopup.tsx similarity index 100% rename from src/webview/components/molecules/AgentPopup/AgentPopup.tsx rename to webview/components/molecules/AgentPopup/AgentPopup.tsx diff --git a/src/webview/components/molecules/AgentPopup/index.ts b/webview/components/molecules/AgentPopup/index.ts similarity index 100% rename from src/webview/components/molecules/AgentPopup/index.ts rename to webview/components/molecules/AgentPopup/index.ts diff --git a/src/webview/components/molecules/AgentSelector/AgentSelector.module.css b/webview/components/molecules/AgentSelector/AgentSelector.module.css similarity index 100% rename from src/webview/components/molecules/AgentSelector/AgentSelector.module.css rename to webview/components/molecules/AgentSelector/AgentSelector.module.css diff --git a/src/webview/components/molecules/AgentSelector/AgentSelector.tsx b/webview/components/molecules/AgentSelector/AgentSelector.tsx similarity index 100% rename from src/webview/components/molecules/AgentSelector/AgentSelector.tsx rename to webview/components/molecules/AgentSelector/AgentSelector.tsx diff --git a/src/webview/components/molecules/AgentSelector/index.ts b/webview/components/molecules/AgentSelector/index.ts similarity index 100% rename from src/webview/components/molecules/AgentSelector/index.ts rename to webview/components/molecules/AgentSelector/index.ts diff --git a/src/webview/components/molecules/DiffView/DiffView.module.css b/webview/components/molecules/DiffView/DiffView.module.css similarity index 100% rename from src/webview/components/molecules/DiffView/DiffView.module.css rename to webview/components/molecules/DiffView/DiffView.module.css diff --git a/src/webview/components/molecules/DiffView/DiffView.tsx b/webview/components/molecules/DiffView/DiffView.tsx similarity index 100% rename from src/webview/components/molecules/DiffView/DiffView.tsx rename to webview/components/molecules/DiffView/DiffView.tsx diff --git a/src/webview/components/molecules/DiffView/index.ts b/webview/components/molecules/DiffView/index.ts similarity index 100% rename from src/webview/components/molecules/DiffView/index.ts rename to webview/components/molecules/DiffView/index.ts diff --git a/src/webview/components/molecules/EmptyState/EmptyState.module.css b/webview/components/molecules/EmptyState/EmptyState.module.css similarity index 100% rename from src/webview/components/molecules/EmptyState/EmptyState.module.css rename to webview/components/molecules/EmptyState/EmptyState.module.css diff --git a/src/webview/components/molecules/EmptyState/EmptyState.tsx b/webview/components/molecules/EmptyState/EmptyState.tsx similarity index 100% rename from src/webview/components/molecules/EmptyState/EmptyState.tsx rename to webview/components/molecules/EmptyState/EmptyState.tsx diff --git a/src/webview/components/molecules/EmptyState/index.ts b/webview/components/molecules/EmptyState/index.ts similarity index 100% rename from src/webview/components/molecules/EmptyState/index.ts rename to webview/components/molecules/EmptyState/index.ts diff --git a/src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css b/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css similarity index 100% rename from src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css rename to webview/components/molecules/FileAttachmentBar/FileAttachmentBar.module.css diff --git a/src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx b/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx similarity index 100% rename from src/webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx rename to webview/components/molecules/FileAttachmentBar/FileAttachmentBar.tsx diff --git a/src/webview/components/molecules/FileAttachmentBar/index.ts b/webview/components/molecules/FileAttachmentBar/index.ts similarity index 100% rename from src/webview/components/molecules/FileAttachmentBar/index.ts rename to webview/components/molecules/FileAttachmentBar/index.ts diff --git a/src/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css b/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css similarity index 100% rename from src/webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css rename to webview/components/molecules/FileChangesHeader/FileChangesHeader.module.css diff --git a/src/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx b/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx similarity index 100% rename from src/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx rename to webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx diff --git a/src/webview/components/molecules/FileChangesHeader/index.ts b/webview/components/molecules/FileChangesHeader/index.ts similarity index 100% rename from src/webview/components/molecules/FileChangesHeader/index.ts rename to webview/components/molecules/FileChangesHeader/index.ts diff --git a/src/webview/components/molecules/FileCreateView/FileCreateView.tsx b/webview/components/molecules/FileCreateView/FileCreateView.tsx similarity index 100% rename from src/webview/components/molecules/FileCreateView/FileCreateView.tsx rename to webview/components/molecules/FileCreateView/FileCreateView.tsx diff --git a/src/webview/components/molecules/FileCreateView/index.ts b/webview/components/molecules/FileCreateView/index.ts similarity index 100% rename from src/webview/components/molecules/FileCreateView/index.ts rename to webview/components/molecules/FileCreateView/index.ts diff --git a/src/webview/components/molecules/HashFilePopup/HashFilePopup.module.css b/webview/components/molecules/HashFilePopup/HashFilePopup.module.css similarity index 100% rename from src/webview/components/molecules/HashFilePopup/HashFilePopup.module.css rename to webview/components/molecules/HashFilePopup/HashFilePopup.module.css diff --git a/src/webview/components/molecules/HashFilePopup/HashFilePopup.tsx b/webview/components/molecules/HashFilePopup/HashFilePopup.tsx similarity index 100% rename from src/webview/components/molecules/HashFilePopup/HashFilePopup.tsx rename to webview/components/molecules/HashFilePopup/HashFilePopup.tsx diff --git a/src/webview/components/molecules/HashFilePopup/index.ts b/webview/components/molecules/HashFilePopup/index.ts similarity index 100% rename from src/webview/components/molecules/HashFilePopup/index.ts rename to webview/components/molecules/HashFilePopup/index.ts diff --git a/src/webview/components/molecules/ModelSelector/ModelSelector.module.css b/webview/components/molecules/ModelSelector/ModelSelector.module.css similarity index 100% rename from src/webview/components/molecules/ModelSelector/ModelSelector.module.css rename to webview/components/molecules/ModelSelector/ModelSelector.module.css diff --git a/src/webview/components/molecules/ModelSelector/ModelSelector.tsx b/webview/components/molecules/ModelSelector/ModelSelector.tsx similarity index 100% rename from src/webview/components/molecules/ModelSelector/ModelSelector.tsx rename to webview/components/molecules/ModelSelector/ModelSelector.tsx diff --git a/src/webview/components/molecules/ModelSelector/index.ts b/webview/components/molecules/ModelSelector/index.ts similarity index 100% rename from src/webview/components/molecules/ModelSelector/index.ts rename to webview/components/molecules/ModelSelector/index.ts diff --git a/src/webview/components/molecules/ShellResultView/ShellResultView.module.css b/webview/components/molecules/ShellResultView/ShellResultView.module.css similarity index 100% rename from src/webview/components/molecules/ShellResultView/ShellResultView.module.css rename to webview/components/molecules/ShellResultView/ShellResultView.module.css diff --git a/src/webview/components/molecules/ShellResultView/ShellResultView.tsx b/webview/components/molecules/ShellResultView/ShellResultView.tsx similarity index 100% rename from src/webview/components/molecules/ShellResultView/ShellResultView.tsx rename to webview/components/molecules/ShellResultView/ShellResultView.tsx diff --git a/src/webview/components/molecules/ShellResultView/index.ts b/webview/components/molecules/ShellResultView/index.ts similarity index 100% rename from src/webview/components/molecules/ShellResultView/index.ts rename to webview/components/molecules/ShellResultView/index.ts diff --git a/src/webview/components/molecules/SkillPopup/SkillPopup.module.css b/webview/components/molecules/SkillPopup/SkillPopup.module.css similarity index 100% rename from src/webview/components/molecules/SkillPopup/SkillPopup.module.css rename to webview/components/molecules/SkillPopup/SkillPopup.module.css diff --git a/src/webview/components/molecules/SkillPopup/SkillPopup.tsx b/webview/components/molecules/SkillPopup/SkillPopup.tsx similarity index 100% rename from src/webview/components/molecules/SkillPopup/SkillPopup.tsx rename to webview/components/molecules/SkillPopup/SkillPopup.tsx diff --git a/src/webview/components/molecules/SkillPopup/index.ts b/webview/components/molecules/SkillPopup/index.ts similarity index 100% rename from src/webview/components/molecules/SkillPopup/index.ts rename to webview/components/molecules/SkillPopup/index.ts diff --git a/src/webview/components/molecules/TextPartView/TextPartView.tsx b/webview/components/molecules/TextPartView/TextPartView.tsx similarity index 100% rename from src/webview/components/molecules/TextPartView/TextPartView.tsx rename to webview/components/molecules/TextPartView/TextPartView.tsx diff --git a/src/webview/components/molecules/TextPartView/index.ts b/webview/components/molecules/TextPartView/index.ts similarity index 100% rename from src/webview/components/molecules/TextPartView/index.ts rename to webview/components/molecules/TextPartView/index.ts diff --git a/src/webview/components/molecules/TodoHeader/TodoHeader.module.css b/webview/components/molecules/TodoHeader/TodoHeader.module.css similarity index 100% rename from src/webview/components/molecules/TodoHeader/TodoHeader.module.css rename to webview/components/molecules/TodoHeader/TodoHeader.module.css diff --git a/src/webview/components/molecules/TodoHeader/TodoHeader.tsx b/webview/components/molecules/TodoHeader/TodoHeader.tsx similarity index 100% rename from src/webview/components/molecules/TodoHeader/TodoHeader.tsx rename to webview/components/molecules/TodoHeader/TodoHeader.tsx diff --git a/src/webview/components/molecules/TodoHeader/index.ts b/webview/components/molecules/TodoHeader/index.ts similarity index 100% rename from src/webview/components/molecules/TodoHeader/index.ts rename to webview/components/molecules/TodoHeader/index.ts diff --git a/src/webview/components/molecules/TodoView/TodoView.module.css b/webview/components/molecules/TodoView/TodoView.module.css similarity index 100% rename from src/webview/components/molecules/TodoView/TodoView.module.css rename to webview/components/molecules/TodoView/TodoView.module.css diff --git a/src/webview/components/molecules/TodoView/TodoView.tsx b/webview/components/molecules/TodoView/TodoView.tsx similarity index 100% rename from src/webview/components/molecules/TodoView/TodoView.tsx rename to webview/components/molecules/TodoView/TodoView.tsx diff --git a/src/webview/components/molecules/TodoView/index.ts b/webview/components/molecules/TodoView/index.ts similarity index 100% rename from src/webview/components/molecules/TodoView/index.ts rename to webview/components/molecules/TodoView/index.ts diff --git a/src/webview/components/organisms/ChatHeader/ChatHeader.module.css b/webview/components/organisms/ChatHeader/ChatHeader.module.css similarity index 100% rename from src/webview/components/organisms/ChatHeader/ChatHeader.module.css rename to webview/components/organisms/ChatHeader/ChatHeader.module.css diff --git a/src/webview/components/organisms/ChatHeader/ChatHeader.tsx b/webview/components/organisms/ChatHeader/ChatHeader.tsx similarity index 100% rename from src/webview/components/organisms/ChatHeader/ChatHeader.tsx rename to webview/components/organisms/ChatHeader/ChatHeader.tsx diff --git a/src/webview/components/organisms/ChatHeader/index.ts b/webview/components/organisms/ChatHeader/index.ts similarity index 100% rename from src/webview/components/organisms/ChatHeader/index.ts rename to webview/components/organisms/ChatHeader/index.ts diff --git a/src/webview/components/organisms/InputArea/InputArea.module.css b/webview/components/organisms/InputArea/InputArea.module.css similarity index 100% rename from src/webview/components/organisms/InputArea/InputArea.module.css rename to webview/components/organisms/InputArea/InputArea.module.css diff --git a/src/webview/components/organisms/InputArea/InputArea.tsx b/webview/components/organisms/InputArea/InputArea.tsx similarity index 100% rename from src/webview/components/organisms/InputArea/InputArea.tsx rename to webview/components/organisms/InputArea/InputArea.tsx diff --git a/src/webview/components/organisms/InputArea/index.ts b/webview/components/organisms/InputArea/index.ts similarity index 100% rename from src/webview/components/organisms/InputArea/index.ts rename to webview/components/organisms/InputArea/index.ts diff --git a/src/webview/components/organisms/MessageItem/MessageItem.module.css b/webview/components/organisms/MessageItem/MessageItem.module.css similarity index 100% rename from src/webview/components/organisms/MessageItem/MessageItem.module.css rename to webview/components/organisms/MessageItem/MessageItem.module.css diff --git a/src/webview/components/organisms/MessageItem/MessageItem.tsx b/webview/components/organisms/MessageItem/MessageItem.tsx similarity index 100% rename from src/webview/components/organisms/MessageItem/MessageItem.tsx rename to webview/components/organisms/MessageItem/MessageItem.tsx diff --git a/src/webview/components/organisms/MessageItem/index.ts b/webview/components/organisms/MessageItem/index.ts similarity index 100% rename from src/webview/components/organisms/MessageItem/index.ts rename to webview/components/organisms/MessageItem/index.ts diff --git a/src/webview/components/organisms/MessagesArea/MessagesArea.module.css b/webview/components/organisms/MessagesArea/MessagesArea.module.css similarity index 100% rename from src/webview/components/organisms/MessagesArea/MessagesArea.module.css rename to webview/components/organisms/MessagesArea/MessagesArea.module.css diff --git a/src/webview/components/organisms/MessagesArea/MessagesArea.tsx b/webview/components/organisms/MessagesArea/MessagesArea.tsx similarity index 100% rename from src/webview/components/organisms/MessagesArea/MessagesArea.tsx rename to webview/components/organisms/MessagesArea/MessagesArea.tsx diff --git a/src/webview/components/organisms/MessagesArea/index.ts b/webview/components/organisms/MessagesArea/index.ts similarity index 100% rename from src/webview/components/organisms/MessagesArea/index.ts rename to webview/components/organisms/MessagesArea/index.ts diff --git a/src/webview/components/organisms/PermissionView/PermissionView.module.css b/webview/components/organisms/PermissionView/PermissionView.module.css similarity index 100% rename from src/webview/components/organisms/PermissionView/PermissionView.module.css rename to webview/components/organisms/PermissionView/PermissionView.module.css diff --git a/src/webview/components/organisms/PermissionView/PermissionView.tsx b/webview/components/organisms/PermissionView/PermissionView.tsx similarity index 100% rename from src/webview/components/organisms/PermissionView/PermissionView.tsx rename to webview/components/organisms/PermissionView/PermissionView.tsx diff --git a/src/webview/components/organisms/PermissionView/index.ts b/webview/components/organisms/PermissionView/index.ts similarity index 100% rename from src/webview/components/organisms/PermissionView/index.ts rename to webview/components/organisms/PermissionView/index.ts diff --git a/src/webview/components/organisms/QuestionView/QuestionView.module.css b/webview/components/organisms/QuestionView/QuestionView.module.css similarity index 100% rename from src/webview/components/organisms/QuestionView/QuestionView.module.css rename to webview/components/organisms/QuestionView/QuestionView.module.css diff --git a/src/webview/components/organisms/QuestionView/QuestionView.tsx b/webview/components/organisms/QuestionView/QuestionView.tsx similarity index 100% rename from src/webview/components/organisms/QuestionView/QuestionView.tsx rename to webview/components/organisms/QuestionView/QuestionView.tsx diff --git a/src/webview/components/organisms/QuestionView/index.ts b/webview/components/organisms/QuestionView/index.ts similarity index 100% rename from src/webview/components/organisms/QuestionView/index.ts rename to webview/components/organisms/QuestionView/index.ts diff --git a/src/webview/components/organisms/SessionList/SessionList.module.css b/webview/components/organisms/SessionList/SessionList.module.css similarity index 100% rename from src/webview/components/organisms/SessionList/SessionList.module.css rename to webview/components/organisms/SessionList/SessionList.module.css diff --git a/src/webview/components/organisms/SessionList/SessionList.tsx b/webview/components/organisms/SessionList/SessionList.tsx similarity index 100% rename from src/webview/components/organisms/SessionList/SessionList.tsx rename to webview/components/organisms/SessionList/SessionList.tsx diff --git a/src/webview/components/organisms/SessionList/index.ts b/webview/components/organisms/SessionList/index.ts similarity index 100% rename from src/webview/components/organisms/SessionList/index.ts rename to webview/components/organisms/SessionList/index.ts diff --git a/src/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css b/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css similarity index 100% rename from src/webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css rename to webview/components/organisms/SubtaskPartView/SubtaskPartView.module.css diff --git a/src/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx b/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx similarity index 100% rename from src/webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx rename to webview/components/organisms/SubtaskPartView/SubtaskPartView.tsx diff --git a/src/webview/components/organisms/SubtaskPartView/index.ts b/webview/components/organisms/SubtaskPartView/index.ts similarity index 100% rename from src/webview/components/organisms/SubtaskPartView/index.ts rename to webview/components/organisms/SubtaskPartView/index.ts diff --git a/src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css b/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css similarity index 100% rename from src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css rename to webview/components/organisms/ToolConfigPanel/ToolConfigPanel.module.css diff --git a/src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx b/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx similarity index 100% rename from src/webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx rename to webview/components/organisms/ToolConfigPanel/ToolConfigPanel.tsx diff --git a/src/webview/components/organisms/ToolConfigPanel/index.ts b/webview/components/organisms/ToolConfigPanel/index.ts similarity index 100% rename from src/webview/components/organisms/ToolConfigPanel/index.ts rename to webview/components/organisms/ToolConfigPanel/index.ts diff --git a/src/webview/components/organisms/ToolPartView/ToolPartView.module.css b/webview/components/organisms/ToolPartView/ToolPartView.module.css similarity index 100% rename from src/webview/components/organisms/ToolPartView/ToolPartView.module.css rename to webview/components/organisms/ToolPartView/ToolPartView.module.css diff --git a/src/webview/components/organisms/ToolPartView/ToolPartView.tsx b/webview/components/organisms/ToolPartView/ToolPartView.tsx similarity index 100% rename from src/webview/components/organisms/ToolPartView/ToolPartView.tsx rename to webview/components/organisms/ToolPartView/ToolPartView.tsx diff --git a/src/webview/components/organisms/ToolPartView/index.ts b/webview/components/organisms/ToolPartView/index.ts similarity index 100% rename from src/webview/components/organisms/ToolPartView/index.ts rename to webview/components/organisms/ToolPartView/index.ts diff --git a/src/webview/contexts/AppContext.tsx b/webview/contexts/AppContext.tsx similarity index 100% rename from src/webview/contexts/AppContext.tsx rename to webview/contexts/AppContext.tsx diff --git a/src/webview/css-modules.d.ts b/webview/css-modules.d.ts similarity index 100% rename from src/webview/css-modules.d.ts rename to webview/css-modules.d.ts diff --git a/src/webview/hooks/useAutoScroll.ts b/webview/hooks/useAutoScroll.ts similarity index 100% rename from src/webview/hooks/useAutoScroll.ts rename to webview/hooks/useAutoScroll.ts diff --git a/src/webview/hooks/useClickOutside.ts b/webview/hooks/useClickOutside.ts similarity index 100% rename from src/webview/hooks/useClickOutside.ts rename to webview/hooks/useClickOutside.ts diff --git a/src/webview/hooks/useFileChanges.ts b/webview/hooks/useFileChanges.ts similarity index 100% rename from src/webview/hooks/useFileChanges.ts rename to webview/hooks/useFileChanges.ts diff --git a/src/webview/hooks/useInputHistory.ts b/webview/hooks/useInputHistory.ts similarity index 100% rename from src/webview/hooks/useInputHistory.ts rename to webview/hooks/useInputHistory.ts diff --git a/src/webview/hooks/useLocale.ts b/webview/hooks/useLocale.ts similarity index 100% rename from src/webview/hooks/useLocale.ts rename to webview/hooks/useLocale.ts diff --git a/src/webview/hooks/useMessages.ts b/webview/hooks/useMessages.ts similarity index 100% rename from src/webview/hooks/useMessages.ts rename to webview/hooks/useMessages.ts diff --git a/src/webview/hooks/usePermissions.ts b/webview/hooks/usePermissions.ts similarity index 100% rename from src/webview/hooks/usePermissions.ts rename to webview/hooks/usePermissions.ts diff --git a/src/webview/hooks/useProviders.ts b/webview/hooks/useProviders.ts similarity index 100% rename from src/webview/hooks/useProviders.ts rename to webview/hooks/useProviders.ts diff --git a/src/webview/hooks/useQuestions.ts b/webview/hooks/useQuestions.ts similarity index 100% rename from src/webview/hooks/useQuestions.ts rename to webview/hooks/useQuestions.ts diff --git a/src/webview/hooks/useSession.ts b/webview/hooks/useSession.ts similarity index 100% rename from src/webview/hooks/useSession.ts rename to webview/hooks/useSession.ts diff --git a/src/webview/hooks/useSoundNotification.ts b/webview/hooks/useSoundNotification.ts similarity index 100% rename from src/webview/hooks/useSoundNotification.ts rename to webview/hooks/useSoundNotification.ts diff --git a/src/webview/index.html b/webview/index.html similarity index 100% rename from src/webview/index.html rename to webview/index.html diff --git a/src/webview/locales/en.ts b/webview/locales/en.ts similarity index 100% rename from src/webview/locales/en.ts rename to webview/locales/en.ts diff --git a/src/webview/locales/es.ts b/webview/locales/es.ts similarity index 100% rename from src/webview/locales/es.ts rename to webview/locales/es.ts diff --git a/src/webview/locales/index.ts b/webview/locales/index.ts similarity index 100% rename from src/webview/locales/index.ts rename to webview/locales/index.ts diff --git a/src/webview/locales/ja.ts b/webview/locales/ja.ts similarity index 100% rename from src/webview/locales/ja.ts rename to webview/locales/ja.ts diff --git a/src/webview/locales/ko.ts b/webview/locales/ko.ts similarity index 100% rename from src/webview/locales/ko.ts rename to webview/locales/ko.ts diff --git a/src/webview/locales/pt-br.ts b/webview/locales/pt-br.ts similarity index 100% rename from src/webview/locales/pt-br.ts rename to webview/locales/pt-br.ts diff --git a/src/webview/locales/ru.ts b/webview/locales/ru.ts similarity index 100% rename from src/webview/locales/ru.ts rename to webview/locales/ru.ts diff --git a/src/webview/locales/zh-cn.ts b/webview/locales/zh-cn.ts similarity index 100% rename from src/webview/locales/zh-cn.ts rename to webview/locales/zh-cn.ts diff --git a/src/webview/locales/zh-tw.ts b/webview/locales/zh-tw.ts similarity index 100% rename from src/webview/locales/zh-tw.ts rename to webview/locales/zh-tw.ts diff --git a/src/webview/main.tsx b/webview/main.tsx similarity index 100% rename from src/webview/main.tsx rename to webview/main.tsx diff --git a/src/webview/styles.css b/webview/styles.css similarity index 100% rename from src/webview/styles.css rename to webview/styles.css diff --git a/src/webview/tsconfig.json b/webview/tsconfig.json similarity index 94% rename from src/webview/tsconfig.json rename to webview/tsconfig.json index bf1bbf6..03c2825 100644 --- a/src/webview/tsconfig.json +++ b/webview/tsconfig.json @@ -5,7 +5,7 @@ "moduleResolution": "bundler", "lib": ["ES2022", "DOM", "DOM.Iterable"], "strict": true, - "baseUrl": "../..", + "baseUrl": "..", "paths": { "@shared": ["src/shared/index.ts"] }, diff --git a/src/webview/utils/diff.ts b/webview/utils/diff.ts similarity index 100% rename from src/webview/utils/diff.ts rename to webview/utils/diff.ts diff --git a/src/webview/utils/file-icons.ts b/webview/utils/file-icons.ts similarity index 100% rename from src/webview/utils/file-icons.ts rename to webview/utils/file-icons.ts diff --git a/src/webview/utils/markdown.ts b/webview/utils/markdown.ts similarity index 100% rename from src/webview/utils/markdown.ts rename to webview/utils/markdown.ts diff --git a/src/webview/utils/todo.ts b/webview/utils/todo.ts similarity index 100% rename from src/webview/utils/todo.ts rename to webview/utils/todo.ts diff --git a/src/webview/utils/tool-categories.ts b/webview/utils/tool-categories.ts similarity index 100% rename from src/webview/utils/tool-categories.ts rename to webview/utils/tool-categories.ts diff --git a/src/webview/vscode-api.ts b/webview/vscode-api.ts similarity index 100% rename from src/webview/vscode-api.ts rename to webview/vscode-api.ts From 6a610af2bc83aa4b39a38b29136a4bde9ff111e5 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 16:29:28 +0900 Subject: [PATCH 08/25] chore: rename --- README.md | 18 ++++++++++-------- docs/architecture.md | 11 ++++++----- esbuild.mjs | 4 ++-- .../__tests__/chat-view-provider.test.ts | 0 .../__tests__/diff-review-manager.test.ts | 0 {src => extension}/__tests__/extension.test.ts | 0 {src => extension}/__tests__/mappers.test.ts | 0 {src => extension}/__tests__/mocks/vscode.ts | 0 .../__tests__/opencode-agent.test.ts | 0 {src => extension}/__tests__/setup.ts | 0 {src => extension}/chat-view-provider.ts | 0 {src => extension}/diff-review-manager.ts | 0 {src => extension}/extension.ts | 0 {src => extension}/mappers.ts | 0 {src => extension}/opencode-agent.ts | 0 {src => extension}/vscode-platform-services.ts | 0 {src/shared => shared}/domain.ts | 0 {src/shared => shared}/index.ts | 0 {src/shared => shared}/protocol.ts | 0 tsconfig.json | 6 +++--- vite.config.ts | 2 +- vitest.config.ext.ts | 6 +++--- vitest.config.ts | 2 +- webview/tsconfig.json | 2 +- 24 files changed, 27 insertions(+), 24 deletions(-) rename {src => extension}/__tests__/chat-view-provider.test.ts (100%) rename {src => extension}/__tests__/diff-review-manager.test.ts (100%) rename {src => extension}/__tests__/extension.test.ts (100%) rename {src => extension}/__tests__/mappers.test.ts (100%) rename {src => extension}/__tests__/mocks/vscode.ts (100%) rename {src => extension}/__tests__/opencode-agent.test.ts (100%) rename {src => extension}/__tests__/setup.ts (100%) rename {src => extension}/chat-view-provider.ts (100%) rename {src => extension}/diff-review-manager.ts (100%) rename {src => extension}/extension.ts (100%) rename {src => extension}/mappers.ts (100%) rename {src => extension}/opencode-agent.ts (100%) rename {src => extension}/vscode-platform-services.ts (100%) rename {src/shared => shared}/domain.ts (100%) rename {src/shared => shared}/index.ts (100%) rename {src/shared => shared}/protocol.ts (100%) diff --git a/README.md b/README.md index e7d3bec..d155931 100644 --- a/README.md +++ b/README.md @@ -142,20 +142,21 @@ npm test This project is a single VS Code extension package: ``` -src/ +extension/ extension.ts # Extension entry point chat-view-provider.ts # Webview panel & messaging opencode-agent.ts # OpenCode SDK integration mappers.ts # SDK to UI/domain type mappers - shared/ # Shared types for extension host and webview - webview/ # Webview (React) + __tests__/ # Extension host tests +shared/ # Shared types for extension host and webview +webview/ # Webview (React) App.tsx # State management & SSE event handling components/ # React components hooks/ # Custom React hooks contexts/ # React Context providers locales/ # i18n locale files utils/ # Utility functions - __tests__/ # Tests + __tests__/ # Webview tests ``` ### Contributing @@ -299,20 +300,21 @@ npm test 本プロジェクトは単一の VS Code 拡張パッケージです。 ``` -src/ +extension/ extension.ts # 拡張機能エントリーポイント chat-view-provider.ts # Webview パネル & メッセージング opencode-agent.ts # OpenCode SDK 連携 mappers.ts # SDK から UI/ドメイン型へのマッパー - shared/ # Extension Host と Webview の共有型 - webview/ # Webview (React) + __tests__/ # Extension Host テスト +shared/ # Extension Host と Webview の共有型 +webview/ # Webview (React) App.tsx # 状態管理 & SSE イベントハンドリング components/ # React コンポーネント hooks/ # カスタム React フック contexts/ # React Context プロバイダー locales/ # i18n locale files utils/ # ユーティリティ関数 - __tests__/ # テスト + __tests__/ # Webview テスト ``` ### コントリビュート diff --git a/docs/architecture.md b/docs/architecture.md index ae95808..d54fbce 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -8,17 +8,18 @@ diff editors. ## Structure ``` -src/ +extension/ extension.ts VS Code activation entry point chat-view-provider.ts Webview message router opencode-agent.ts OpenCode SDK lifecycle and API calls mappers.ts SDK type to UI/domain type mapping vscode-platform-services.ts VS Code API helpers - shared/ - domain.ts Shared session/message/tool/config types - protocol.ts Webview <-> extension host messages - webview/ + __tests__/ Extension host tests +shared/ + domain.ts Shared session/message/tool/config types + protocol.ts Webview <-> extension host messages +webview/ App.tsx React state and event handling components/ UI components hooks/ React hooks diff --git a/esbuild.mjs b/esbuild.mjs index 1439f1d..cf8ab7b 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -4,12 +4,12 @@ const watch = process.argv.includes("--watch"); /** @type {esbuild.BuildOptions} */ const buildOptions = { - entryPoints: ["src/extension.ts"], + entryPoints: ["extension/extension.ts"], bundle: true, outfile: "dist/extension.js", external: ["vscode"], alias: { - "@shared": "./src/shared/index.ts", + "@shared": "./shared/index.ts", }, format: "cjs", platform: "node", diff --git a/src/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-view-provider.test.ts similarity index 100% rename from src/__tests__/chat-view-provider.test.ts rename to extension/__tests__/chat-view-provider.test.ts diff --git a/src/__tests__/diff-review-manager.test.ts b/extension/__tests__/diff-review-manager.test.ts similarity index 100% rename from src/__tests__/diff-review-manager.test.ts rename to extension/__tests__/diff-review-manager.test.ts diff --git a/src/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts similarity index 100% rename from src/__tests__/extension.test.ts rename to extension/__tests__/extension.test.ts diff --git a/src/__tests__/mappers.test.ts b/extension/__tests__/mappers.test.ts similarity index 100% rename from src/__tests__/mappers.test.ts rename to extension/__tests__/mappers.test.ts diff --git a/src/__tests__/mocks/vscode.ts b/extension/__tests__/mocks/vscode.ts similarity index 100% rename from src/__tests__/mocks/vscode.ts rename to extension/__tests__/mocks/vscode.ts diff --git a/src/__tests__/opencode-agent.test.ts b/extension/__tests__/opencode-agent.test.ts similarity index 100% rename from src/__tests__/opencode-agent.test.ts rename to extension/__tests__/opencode-agent.test.ts diff --git a/src/__tests__/setup.ts b/extension/__tests__/setup.ts similarity index 100% rename from src/__tests__/setup.ts rename to extension/__tests__/setup.ts diff --git a/src/chat-view-provider.ts b/extension/chat-view-provider.ts similarity index 100% rename from src/chat-view-provider.ts rename to extension/chat-view-provider.ts diff --git a/src/diff-review-manager.ts b/extension/diff-review-manager.ts similarity index 100% rename from src/diff-review-manager.ts rename to extension/diff-review-manager.ts diff --git a/src/extension.ts b/extension/extension.ts similarity index 100% rename from src/extension.ts rename to extension/extension.ts diff --git a/src/mappers.ts b/extension/mappers.ts similarity index 100% rename from src/mappers.ts rename to extension/mappers.ts diff --git a/src/opencode-agent.ts b/extension/opencode-agent.ts similarity index 100% rename from src/opencode-agent.ts rename to extension/opencode-agent.ts diff --git a/src/vscode-platform-services.ts b/extension/vscode-platform-services.ts similarity index 100% rename from src/vscode-platform-services.ts rename to extension/vscode-platform-services.ts diff --git a/src/shared/domain.ts b/shared/domain.ts similarity index 100% rename from src/shared/domain.ts rename to shared/domain.ts diff --git a/src/shared/index.ts b/shared/index.ts similarity index 100% rename from src/shared/index.ts rename to shared/index.ts diff --git a/src/shared/protocol.ts b/shared/protocol.ts similarity index 100% rename from src/shared/protocol.ts rename to shared/protocol.ts diff --git a/tsconfig.json b/tsconfig.json index 25fcab0..4368591 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,11 +5,11 @@ "moduleResolution": "bundler", "lib": ["ES2022"], "outDir": "./dist", - "rootDir": "./src", + "rootDir": ".", "strict": true, "baseUrl": ".", "paths": { - "@shared": ["src/shared/index.ts"] + "@shared": ["shared/index.ts"] }, "esModuleInterop": true, "skipLibCheck": true, @@ -18,6 +18,6 @@ "sourceMap": true, "jsx": "react-jsx" }, - "include": ["src/**/*"], + "include": ["extension/**/*", "shared/**/*"], "exclude": ["node_modules", "dist", "webview"] } diff --git a/vite.config.ts b/vite.config.ts index 12b19e3..aef571a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ root: "webview", resolve: { alias: { - "@shared": path.resolve(__dirname, "src/shared/index.ts"), + "@shared": path.resolve(__dirname, "shared/index.ts"), }, }, build: { diff --git a/vitest.config.ext.ts b/vitest.config.ext.ts index 6addf60..e689cb7 100644 --- a/vitest.config.ext.ts +++ b/vitest.config.ext.ts @@ -4,13 +4,13 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ resolve: { alias: { - "@shared": path.resolve(__dirname, "src/shared/index.ts"), + "@shared": path.resolve(__dirname, "shared/index.ts"), }, }, test: { environment: "node", globals: true, - include: ["src/__tests__/**/*.test.ts"], - setupFiles: ["src/__tests__/setup.ts"], + include: ["extension/__tests__/**/*.test.ts"], + setupFiles: ["extension/__tests__/setup.ts"], }, }); diff --git a/vitest.config.ts b/vitest.config.ts index 4bd8f56..f777a9c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ plugins: [react()], resolve: { alias: { - "@shared": path.resolve(__dirname, "src/shared/index.ts"), + "@shared": path.resolve(__dirname, "shared/index.ts"), }, }, test: { diff --git a/webview/tsconfig.json b/webview/tsconfig.json index 03c2825..8dee650 100644 --- a/webview/tsconfig.json +++ b/webview/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, "baseUrl": "..", "paths": { - "@shared": ["src/shared/index.ts"] + "@shared": ["shared/index.ts"] }, "esModuleInterop": true, "skipLibCheck": true, From 5131daa1081855a12331ee9c02fbaaf3c1d79362 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 16:33:26 +0900 Subject: [PATCH 09/25] rename: ext -> extention --- README.md | 8 ++-- docs/architecture.md | 4 +- .../__tests__/chat-view-provider.test.ts | 4 +- extension/__tests__/extension.test.ts | 46 +++++++++---------- package.json | 10 ++-- ...onfig.ext.ts => vitest.config.extension.ts | 0 webview/utils/file-icons.ts | 6 +-- 7 files changed, 39 insertions(+), 39 deletions(-) rename vitest.config.ext.ts => vitest.config.extension.ts (100%) diff --git a/README.md b/README.md index d155931..a0ed6e2 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ npm run build npm run build # Extension only -npm run build:ext +npm run build:extension # Webview only npm run build:webview @@ -113,7 +113,7 @@ Open two terminals and run each: ```sh # Terminal 1: Extension watch -npm run watch:ext +npm run watch:extension # Terminal 2: Webview watch npm run watch:webview @@ -259,7 +259,7 @@ npm run build npm run build # Extension のみ -npm run build:ext +npm run build:extension # Webview のみ npm run build:webview @@ -271,7 +271,7 @@ npm run build:webview ```sh # Terminal 1: Extension watch -npm run watch:ext +npm run watch:extension # Terminal 2: Webview watch npm run watch:webview diff --git a/docs/architecture.md b/docs/architecture.md index d54fbce..8dd949b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -43,9 +43,9 @@ webview/ ## Build And Test -- Extension host bundle: `npm run build:ext` +- Extension host bundle: `npm run build:extension` - Webview bundle: `npm run build:webview` - Full build: `npm run build` - Webview tests: `npm test` -- Extension host tests: `npm run test:ext` +- Extension host tests: `npm run test:extension` - All tests: `npm run test:all` diff --git a/extension/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-view-provider.test.ts index 0cbc947..f26f51e 100644 --- a/extension/__tests__/chat-view-provider.test.ts +++ b/extension/__tests__/chat-view-provider.test.ts @@ -144,7 +144,7 @@ function setupProvider( mockDiffReviewManager?: ReturnType, difitAvailable = false, ) { - const extensionUri = { fsPath: "/ext" }; + const extensionUri = { fsPath: "/extension" }; const ps = mockPlatformServices ?? createMockPlatformServices(); const drm = mockDiffReviewManager ?? createMockDiffReviewManager(); const provider = new ChatViewProvider( @@ -1180,7 +1180,7 @@ describe("ChatViewProvider", () => { describe("postMessage null safety", () => { it("should not crash when view is not set", () => { // resolveWebviewView を呼ばずに provider を作成 - const extensionUri = { fsPath: "/ext" }; + const extensionUri = { fsPath: "/extension" }; const provider = new ChatViewProvider( extensionUri as never, mockAgent as never, diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index e606edb..42f67ad 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -70,14 +70,14 @@ describe("extension", () => { describe("activate() - normal", () => { it("should connect, register webview provider and diff providers", async () => { - const ext = await importExtension(); + const extensionModule = await importExtension(); const subscriptions: { dispose: () => void }[] = []; const context = { - extensionUri: { fsPath: "/ext" }, + extensionUri: { fsPath: "/extension" }, subscriptions, }; - await ext.activate(context as never); + await extensionModule.activate(context as never); // connect が呼ばれた expect(mockConnect).toHaveBeenCalled(); @@ -101,10 +101,10 @@ describe("extension", () => { }); it("should change cwd to workspace folder and restore it", async () => { - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; - await ext.activate(context as never); + await extensionModule.activate(context as never); // chdir が workspaceFolder で呼ばれ、その後元に戻されること const chdirCalls = chdirSpy.mock.calls.map((c: string[]) => c[0]); @@ -121,10 +121,10 @@ describe("extension", () => { describe("activate() - no workspace", () => { it("should show warning and return early", async () => { vi.mocked(vscode.workspace).workspaceFolders = undefined as never; - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; - await ext.activate(context as never); + await extensionModule.activate(context as never); expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("workspace")); expect(mockConnect).not.toHaveBeenCalled(); @@ -141,10 +141,10 @@ describe("extension", () => { error.code = "ENOENT"; mockConnect.mockRejectedValueOnce(error); - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; - await ext.activate(context as never); + await extensionModule.activate(context as never); expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("opencode")); // webview provider が登録されない @@ -155,10 +155,10 @@ describe("extension", () => { const error = new Error("ENOENT: command not found"); mockConnect.mockRejectedValueOnce(error); - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; - await ext.activate(context as never); + await extensionModule.activate(context as never); expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("opencode")); }); @@ -173,10 +173,10 @@ describe("extension", () => { const error = new Error("Connection refused"); mockConnect.mockRejectedValueOnce(error); - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; - await expect(ext.activate(context as never)).rejects.toThrow("Connection refused"); + await expect(extensionModule.activate(context as never)).rejects.toThrow("Connection refused"); }); }); @@ -186,9 +186,9 @@ describe("extension", () => { describe("deactivate()", () => { it("should call agent.disconnect()", async () => { - const ext = await importExtension(); + const extensionModule = await importExtension(); - ext.deactivate(); + extensionModule.deactivate(); expect(mockDisconnect).toHaveBeenCalled(); }); @@ -200,9 +200,9 @@ describe("extension", () => { describe("diff content provider", () => { it("should decode URI query to provide document content", async () => { - const ext = await importExtension(); - const context = { extensionUri: { fsPath: "/ext" }, subscriptions: [] }; - await ext.activate(context as never); + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; + await extensionModule.activate(context as never); // registerTextDocumentContentProvider に渡されたプロバイダーを取得 const registerCalls = vi.mocked(vscode.workspace.registerTextDocumentContentProvider).mock.calls; diff --git a/package.json b/package.json index ab50922..f4323c1 100644 --- a/package.json +++ b/package.json @@ -59,17 +59,17 @@ }, "scripts": { "build": "node esbuild.mjs && vite build", - "build:ext": "node esbuild.mjs", + "build:extension": "node esbuild.mjs", "build:webview": "vite build", "check": "biome check .", "check:fix": "biome check --fix .", "format": "biome format --write .", - "watch:ext": "node esbuild.mjs --watch", + "watch:extension": "node esbuild.mjs --watch", "watch:webview": "vite build --watch", "test": "vitest run --config vitest.config.ts", - "test:ext": "vitest run --config vitest.config.ext.ts", - "test:ext:watch": "vitest --config vitest.config.ext.ts", - "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.config.ext.ts", + "test:extension": "vitest run --config vitest.config.extension.ts", + "test:extension:watch": "vitest --config vitest.config.extension.ts", + "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.config.extension.ts", "test:watch": "vitest --config vitest.config.ts", "package": "vsce package --no-dependencies", "publish": "vsce publish --no-dependencies" diff --git a/vitest.config.ext.ts b/vitest.config.extension.ts similarity index 100% rename from vitest.config.ext.ts rename to vitest.config.extension.ts diff --git a/webview/utils/file-icons.ts b/webview/utils/file-icons.ts index 3bfa2aa..addd496 100644 --- a/webview/utils/file-icons.ts +++ b/webview/utils/file-icons.ts @@ -228,9 +228,9 @@ export function getFileIcon(fileName: string): FC { if (exact) return exact; // 2. 拡張子マッチ(最長一致) - for (const ext of sortedExtensions) { - if (lower.endsWith(ext)) { - return extensionMap[ext]; + for (const fileExtension of sortedExtensions) { + if (lower.endsWith(fileExtension)) { + return extensionMap[fileExtension]; } } From fd7bfd1429a2fe1b00497a3019409a4cd5871939 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 17:20:07 +0900 Subject: [PATCH 10/25] update: typescript --- package-lock.json | 8 ++++---- package.json | 5 ++++- tsconfig.base.json | 19 +++++++++++++++++++ tsconfig.json | 19 +++---------------- webview/tsconfig.json | 15 ++------------- 5 files changed, 32 insertions(+), 34 deletions(-) create mode 100644 tsconfig.base.json diff --git a/package-lock.json b/package-lock.json index ffeba30..70aff4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "marked": "^17.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", - "typescript": "^5.7.0", + "typescript": "^6.0.3", "vite": "^8.0.11", "vitest": "^4.0.18" }, @@ -6436,9 +6436,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index f4323c1..8d8fc71 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,9 @@ "build": "node esbuild.mjs && vite build", "build:extension": "node esbuild.mjs", "build:webview": "vite build", + "typecheck": "npm run typecheck:extension && npm run typecheck:webview", + "typecheck:extension": "tsc -p tsconfig.json", + "typecheck:webview": "tsc -p webview/tsconfig.json", "check": "biome check .", "check:fix": "biome check --fix .", "format": "biome format --write .", @@ -91,7 +94,7 @@ "marked": "^17.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", - "typescript": "^5.7.0", + "typescript": "^6.0.3", "vite": "^8.0.11", "vitest": "^4.0.18" }, diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..b750baf --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "moduleDetection": "force", + "paths": { + "@shared": ["./shared/index.ts"] + }, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react-jsx" + } +} diff --git a/tsconfig.json b/tsconfig.json index 4368591..64dc399 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,9 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": ".", - "strict": true, - "baseUrl": ".", - "paths": { - "@shared": ["shared/index.ts"] - }, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": false, - "sourceMap": true, - "jsx": "react-jsx" + "types": ["node", "vscode", "vitest/globals"], + "rootDir": "." }, "include": ["extension/**/*", "shared/**/*"], "exclude": ["node_modules", "dist", "webview"] diff --git a/webview/tsconfig.json b/webview/tsconfig.json index 8dee650..490c538 100644 --- a/webview/tsconfig.json +++ b/webview/tsconfig.json @@ -1,19 +1,8 @@ { + "extends": "../tsconfig.base.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", "lib": ["ES2022", "DOM", "DOM.Iterable"], - "strict": true, - "baseUrl": "..", - "paths": { - "@shared": ["shared/index.ts"] - }, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": false, - "jsx": "react-jsx" + "types": ["vite/client", "vitest/globals"] }, "include": ["./**/*"], "exclude": ["node_modules"] From 9ccb82d401c43efb495d85e2252ee509a3851f55 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 18:19:21 +0900 Subject: [PATCH 11/25] =?UTF-8?q?TypeScript=206=E5=AF=BE=E5=BF=9C=E3=81=AB?= =?UTF-8?q?=E5=90=91=E3=81=91=E3=81=A6=E5=85=B1=E6=9C=89=E5=9E=8B=E3=82=92?= =?UTF-8?q?=E5=8E=B3=E5=AF=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/mappers.test.ts | 16 ++++---- extension/__tests__/opencode-agent.test.ts | 4 +- extension/diff-review-manager.ts | 3 ++ extension/mappers.ts | 20 +++++++--- shared/domain.ts | 39 ++++++++++++++++++- .../components/molecules/TodoHeader.test.tsx | 8 ++-- .../components/molecules/TodoView.test.tsx | 2 +- .../hooks/useSoundNotification.test.ts | 12 +++--- .../scenarios/25-sound-notification.test.tsx | 12 +++++- webview/__tests__/utils/todo.test.ts | 11 ++++-- .../FileChangesHeader/FileChangesHeader.tsx | 17 ++++++-- .../ShellResultView/ShellResultView.tsx | 6 ++- .../molecules/TextPartView/TextPartView.tsx | 4 +- .../organisms/SessionList/SessionList.tsx | 4 +- .../organisms/ToolPartView/ToolPartView.tsx | 6 ++- webview/hooks/useSoundNotification.ts | 2 +- webview/locales/es.ts | 2 + webview/locales/index.ts | 9 +++-- webview/locales/ko.ts | 2 + webview/locales/pt-br.ts | 2 + webview/locales/ru.ts | 2 + webview/locales/zh-cn.ts | 2 + webview/locales/zh-tw.ts | 2 + webview/utils/todo.ts | 14 ++++++- 24 files changed, 150 insertions(+), 51 deletions(-) diff --git a/extension/__tests__/mappers.test.ts b/extension/__tests__/mappers.test.ts index c05085f..ff6c1d1 100644 --- a/extension/__tests__/mappers.test.ts +++ b/extension/__tests__/mappers.test.ts @@ -167,8 +167,8 @@ describe("mapProviders", () => { // ============================================================ describe("mapFileDiff", () => { - it("should pass through file diff data", () => { - const diff = { path: "src/index.ts", before: "old", after: "new" }; + it("should map SDK snapshot diff data", () => { + const diff = { file: "src/index.ts", patch: "diff --git a/src/index.ts b/src/index.ts", additions: 1, deletions: 1 }; const result = mapFileDiff(diff as never); expect(result).toEqual(diff); }); @@ -177,8 +177,8 @@ describe("mapFileDiff", () => { describe("mapFileDiffs", () => { it("should map an array of file diffs", () => { const diffs = [ - { path: "a.ts", before: "", after: "new" }, - { path: "b.ts", before: "old", after: "" }, + { file: "a.ts", patch: "diff --git a/a.ts b/a.ts", additions: 1, deletions: 0 }, + { file: "b.ts", patch: "diff --git a/b.ts b/b.ts", additions: 0, deletions: 1 }, ]; const result = mapFileDiffs(diffs as never); expect(result).toHaveLength(2); @@ -194,8 +194,8 @@ describe("mapFileDiffs", () => { // ============================================================ describe("mapTodo", () => { - it("should pass through todo data as TodoItem", () => { - const todo = { id: "t1", text: "Fix bug", done: false }; + it("should map SDK todo data as TodoItem", () => { + const todo = { content: "Fix bug", status: "pending", priority: "high" }; const result = mapTodo(todo as never); expect(result).toEqual(todo); }); @@ -204,8 +204,8 @@ describe("mapTodo", () => { describe("mapTodos", () => { it("should map an array of todos", () => { const todos = [ - { id: "t1", text: "A" }, - { id: "t2", text: "B" }, + { content: "A", status: "pending", priority: "medium" }, + { content: "B", status: "completed", priority: "low" }, ]; const result = mapTodos(todos as never); expect(result).toHaveLength(2); diff --git a/extension/__tests__/opencode-agent.test.ts b/extension/__tests__/opencode-agent.test.ts index 162bc92..c5a2009 100644 --- a/extension/__tests__/opencode-agent.test.ts +++ b/extension/__tests__/opencode-agent.test.ts @@ -484,7 +484,7 @@ describe("OpenCodeAgent", () => { describe("getSessionTodos()", () => { it("should call client.session.todo()", async () => { - const todos = [{ id: "t1", text: "Fix bug" }]; + const todos = [{ content: "Fix bug", status: "pending", priority: "high" }]; mockClient.session.todo.mockResolvedValue({ data: todos }); await agent.connect(); @@ -548,7 +548,7 @@ describe("OpenCodeAgent", () => { describe("getSessionDiff()", () => { it("should call client.session.diff()", async () => { - const diffs = [{ path: "file.ts", before: "a", after: "b" }]; + const diffs = [{ file: "file.ts", patch: "diff --git a/file.ts b/file.ts", additions: 1, deletions: 1 }]; mockClient.session.diff.mockResolvedValue({ data: diffs }); await agent.connect(); diff --git a/extension/diff-review-manager.ts b/extension/diff-review-manager.ts index 02038d8..0e9eb87 100644 --- a/extension/diff-review-manager.ts +++ b/extension/diff-review-manager.ts @@ -97,6 +97,9 @@ export class DiffReviewManager implements vscode.Disposable { export function fileDiffsToUnifiedDiff(diffs: FileDiff[]): string { return diffs .map((d) => { + if ("patch" in d) { + return d.patch; + } const patch = createTwoFilesPatch(`a/${d.file}`, `b/${d.file}`, d.before, d.after); // jsdiff は "===...===" ヘッダーを出力するが difit は "diff --git" を期待する return patch.replace(/^={10,}\n/, `diff --git a/${d.file} b/${d.file}\n`); diff --git a/extension/mappers.ts b/extension/mappers.ts index 7eb1340..d896cfc 100644 --- a/extension/mappers.ts +++ b/extension/mappers.ts @@ -12,10 +12,10 @@ import type { Message, Part, Provider, - FileDiff as SdkFileDiff, McpStatus as SdkMcpStatus, Path as SdkPath, Session, + SnapshotFileDiff, Todo, } from "@opencode-ai/sdk/v2"; @@ -98,11 +98,17 @@ export function mapProviders(providers: Provider[]): ProviderInfo[] { // FileDiff // ============================================================ -export function mapFileDiff(diff: SdkFileDiff): FileDiff { - return diff as unknown as FileDiff; +export function mapFileDiff(diff: SnapshotFileDiff): FileDiff { + return { + file: diff.file, + patch: diff.patch, + additions: diff.additions, + deletions: diff.deletions, + status: diff.status, + }; } -export function mapFileDiffs(diffs: SdkFileDiff[]): FileDiff[] { +export function mapFileDiffs(diffs: SnapshotFileDiff[]): FileDiff[] { return diffs.map(mapFileDiff); } @@ -111,7 +117,11 @@ export function mapFileDiffs(diffs: SdkFileDiff[]): FileDiff[] { // ============================================================ export function mapTodo(todo: Todo): TodoItem { - return todo as unknown as TodoItem; + return { + content: todo.content, + status: todo.status, + priority: todo.priority, + }; } export function mapTodos(todos: Todo[]): TodoItem[] { diff --git a/shared/domain.ts b/shared/domain.ts index dacc9b1..0e5642f 100644 --- a/shared/domain.ts +++ b/shared/domain.ts @@ -368,7 +368,7 @@ export type FileAttachment = { // File Diff // ============================================================ -export type FileDiff = { +export type FileContentDiff = { file: string; before: string; after: string; @@ -376,12 +376,21 @@ export type FileDiff = { deletions: number; }; +export type FilePatchDiff = { + file: string; + patch: string; + additions: number; + deletions: number; + status?: "added" | "deleted" | "modified"; +}; + +export type FileDiff = FileContentDiff | FilePatchDiff; + // ============================================================ // Todo // ============================================================ export type TodoItem = { - id: string; content: string; status: string; priority: string; @@ -492,3 +501,29 @@ export type ToolListItem = { export type Disposable = { dispose(): void; }; + +// ============================================================ +// Webview persisted UI state +// ============================================================ + +export type SoundEventType = "responseComplete" | "permissionRequest" | "questionAsked" | "error"; + +export type SoundEventSetting = { + enabled?: boolean; + volume?: number; +}; + +export type SoundSettings = Partial>; + +export type UIPersistedState = { + localeSetting?: string; + inputHistory?: string[]; + soundSettings?: SoundSettings; +}; + +export type IBridge = { + postMessage(message: import("./protocol").UIToHostMessage): void; + onMessage(handler: (message: import("./protocol").HostToUIMessage) => void): Disposable; + getPersistedState(): UIPersistedState | null; + setPersistedState(state: UIPersistedState): void; +}; diff --git a/webview/__tests__/components/molecules/TodoHeader.test.tsx b/webview/__tests__/components/molecules/TodoHeader.test.tsx index 19d4afa..34b3d95 100644 --- a/webview/__tests__/components/molecules/TodoHeader.test.tsx +++ b/webview/__tests__/components/molecules/TodoHeader.test.tsx @@ -4,9 +4,9 @@ import { TodoHeader } from "../../../components/molecules/TodoHeader"; import type { TodoItem } from "../../../utils/todo"; const sampleTodos: TodoItem[] = [ - { content: "Task 1", status: "completed", priority: undefined }, + { content: "Task 1", status: "completed", priority: "medium" }, { content: "Task 2", status: "in_progress", priority: "high" }, - { content: "Task 3", status: "pending", priority: undefined }, + { content: "Task 3", status: "pending", priority: "medium" }, ]; describe("TodoHeader", () => { @@ -53,8 +53,8 @@ describe("TodoHeader", () => { // shows full completion count it("全完了数を表示すること", () => { const allDone: TodoItem[] = [ - { content: "Done 1", status: "completed", priority: undefined }, - { content: "Done 2", status: "done", priority: undefined }, + { content: "Done 1", status: "completed", priority: "medium" }, + { content: "Done 2", status: "done", priority: "medium" }, ]; const { container } = render(); expect(container.querySelector(".count")?.textContent).toBe("2/2"); diff --git a/webview/__tests__/components/molecules/TodoView.test.tsx b/webview/__tests__/components/molecules/TodoView.test.tsx index a7dd911..df48209 100644 --- a/webview/__tests__/components/molecules/TodoView.test.tsx +++ b/webview/__tests__/components/molecules/TodoView.test.tsx @@ -4,7 +4,7 @@ import { TodoView } from "../../../components/molecules/TodoView"; import type { TodoItem } from "../../../utils/todo"; const sampleTodos: TodoItem[] = [ - { content: "Task 1", status: "completed", priority: undefined }, + { content: "Task 1", status: "completed", priority: "medium" }, { content: "Task 2", status: "in_progress", priority: "high" }, { content: "Task 3", status: "pending", priority: "low" }, ]; diff --git a/webview/__tests__/hooks/useSoundNotification.test.ts b/webview/__tests__/hooks/useSoundNotification.test.ts index 2a26090..268b873 100644 --- a/webview/__tests__/hooks/useSoundNotification.test.ts +++ b/webview/__tests__/hooks/useSoundNotification.test.ts @@ -95,16 +95,16 @@ describe("useSoundNotification", () => { }); }); - // permission.updated triggers permissionRequest - context("permission.updated イベントを受信した場合", () => { + // permission.asked triggers permissionRequest + context("permission.asked イベントを受信した場合", () => { // plays sound it("サウンドが再生されること", () => { const { result } = renderHook(() => useSoundNotification()); act(() => { result.current.handleSoundEvent({ - type: "permission.updated", - properties: { id: "perm1", title: "allow bash" }, + type: "permission.asked", + properties: { id: "perm1", sessionID: "s1", permission: "execute", patterns: ["bash"], metadata: {}, always: [] }, } as unknown as AgentEvent); }); @@ -140,8 +140,8 @@ describe("useSoundNotification", () => { act(() => { result.current.handleSoundEvent({ - type: "permission.updated", - properties: { id: "perm1", title: "allow bash" }, + type: "permission.asked", + properties: { id: "perm1", sessionID: "s1", permission: "execute", patterns: ["bash"], metadata: {}, always: [] }, } as unknown as AgentEvent); }); diff --git a/webview/__tests__/scenarios/25-sound-notification.test.tsx b/webview/__tests__/scenarios/25-sound-notification.test.tsx index 2a7d6bb..f353de0 100644 --- a/webview/__tests__/scenarios/25-sound-notification.test.tsx +++ b/webview/__tests__/scenarios/25-sound-notification.test.tsx @@ -95,8 +95,16 @@ describe("サウンド通知", () => { await sendExtMessage({ type: "event", event: { - type: "permission.updated", - properties: { id: "perm1", title: "allow bash", sessionID: "s1", messageID: "m1", type: "execute" }, + type: "permission.asked", + properties: { + id: "perm1", + sessionID: "s1", + permission: "execute", + patterns: ["bash"], + metadata: {}, + always: [], + tool: { messageID: "m1", callID: "c1" }, + }, }, }); diff --git a/webview/__tests__/utils/todo.test.ts b/webview/__tests__/utils/todo.test.ts index 0ad97a0..6c47a92 100644 --- a/webview/__tests__/utils/todo.test.ts +++ b/webview/__tests__/utils/todo.test.ts @@ -7,7 +7,10 @@ describe("parseTodos", () => { it("TodoItem 配列を返すこと", () => { const json = JSON.stringify([{ content: "task1" }, { content: "task2", status: "done" }]); const result = parseTodos(json); - expect(result).toEqual([{ content: "task1" }, { content: "task2", status: "done" }]); + expect(result).toEqual([ + { content: "task1", status: "pending", priority: "medium" }, + { content: "task2", status: "done", priority: "medium" }, + ]); }); }); @@ -15,7 +18,7 @@ describe("parseTodos", () => { context("オブジェクト配列を直接渡した場合", () => { it("TodoItem 配列を返すこと", () => { const arr = [{ content: "task1", priority: "high" }]; - expect(parseTodos(arr)).toEqual(arr); + expect(parseTodos(arr)).toEqual([{ content: "task1", status: "pending", priority: "high" }]); }); }); @@ -23,7 +26,7 @@ describe("parseTodos", () => { context("todos キーを持つラッパーオブジェクトの場合", () => { it("todos 配列を返すこと", () => { const data = { todos: [{ content: "a" }] }; - expect(parseTodos(data)).toEqual([{ content: "a" }]); + expect(parseTodos(data)).toEqual([{ content: "a", status: "pending", priority: "medium" }]); }); }); @@ -31,7 +34,7 @@ describe("parseTodos", () => { context("items キーを持つラッパーオブジェクトの場合", () => { it("items 配列を返すこと", () => { const data = { items: [{ content: "b" }] }; - expect(parseTodos(data)).toEqual([{ content: "b" }]); + expect(parseTodos(data)).toEqual([{ content: "b", status: "pending", priority: "medium" }]); }); }); diff --git a/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx b/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx index aaecb38..dd69916 100644 --- a/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx +++ b/webview/components/molecules/FileChangesHeader/FileChangesHeader.tsx @@ -11,7 +11,7 @@ import styles from "./FileChangesHeader.module.css"; type Props = { diffs: FileDiff[]; onOpenDiffEditor: (filePath: string, before: string, after: string) => void; - difitAvailable: boolean; + difitAvailable?: boolean; }; /** ファイルパスから basename を取得 */ @@ -29,11 +29,17 @@ function dirname(filePath: string): string { /** ファイルの変更種別を判定 */ function getFileStatus(diff: FileDiff): "added" | "deleted" | "modified" { + if ("status" in diff && diff.status) return diff.status; + if (!("before" in diff) || !("after" in diff)) return "modified"; if (diff.before === "" && diff.after !== "") return "added"; if (diff.before !== "" && diff.after === "") return "deleted"; return "modified"; } +function hasContentDiff(diff: FileDiff): diff is FileDiff & { before: string; after: string } { + return "before" in diff && "after" in diff; +} + function FileChangeItem({ diff, onOpenDiffEditor, @@ -84,9 +90,12 @@ function FileChangeItem({ className={styles.openButton} onClick={(e) => { e.stopPropagation(); - onOpenDiffEditor(diff.file, diff.before, diff.after); + if (hasContentDiff(diff)) { + onOpenDiffEditor(diff.file, diff.before, diff.after); + } }} title={t["fileChanges.openDiff"]} + disabled={!hasContentDiff(diff)} > @@ -105,14 +114,14 @@ function FileChangeItem({ {expanded && (
- + {hasContentDiff(diff) ? :
{diff.patch}
}
)} ); } -export function FileChangesHeader({ diffs, onOpenDiffEditor, difitAvailable }: Props) { +export function FileChangesHeader({ diffs, onOpenDiffEditor, difitAvailable = false }: Props) { const t = useLocale(); const [expanded, setExpanded] = useState(false); diff --git a/webview/components/molecules/ShellResultView/ShellResultView.tsx b/webview/components/molecules/ShellResultView/ShellResultView.tsx index ce919c3..0e83344 100644 --- a/webview/components/molecules/ShellResultView/ShellResultView.tsx +++ b/webview/components/molecules/ShellResultView/ShellResultView.tsx @@ -8,6 +8,10 @@ type Props = { parts: ToolPart[]; }; +function formatOutput(value: unknown): string { + return typeof value === "string" ? value : JSON.stringify(value, null, 2); +} + /** * ユーザーが ! プレフィクスで実行したシェルコマンドの結果をターミナル風に表示する。 * 通常の ToolPartView(折りたたみカード)ではなく、コマンドと出力を一体で見せる。 @@ -25,7 +29,7 @@ export function ShellResultView({ parts }: Props) { const command = (input?.command as string) ?? ""; const isRunning = state.status === "running" || state.status === "pending"; const isError = state.status === "error"; - const output = state.status === "completed" ? state.output : null; + const output = state.status === "completed" ? formatOutput(state.output) : null; const error = state.status === "error" ? state.error : null; return { command, output, error, isRunning, isError }; }); diff --git a/webview/components/molecules/TextPartView/TextPartView.tsx b/webview/components/molecules/TextPartView/TextPartView.tsx index ae51ade..0b4a0ff 100644 --- a/webview/components/molecules/TextPartView/TextPartView.tsx +++ b/webview/components/molecules/TextPartView/TextPartView.tsx @@ -1,5 +1,5 @@ import type { TextPart } from "@shared"; -import DOMPurify from "dompurify"; +import DOMPurify, { type Config as DOMPurifyConfig } from "dompurify"; import hljs from "highlight.js/lib/common"; import { Marked, type Renderer, type Tokens } from "marked"; import { useCallback, useMemo } from "react"; @@ -50,7 +50,7 @@ const linkRenderer: Partial = { }; // DOMPurify で SVG 要素とカスタム data 属性を許可する設定 -const PURIFY_CONFIG: DOMPurify.Config = { +const PURIFY_CONFIG: DOMPurifyConfig = { ADD_TAGS: ["svg", "path", "rect", "circle", "ellipse", "polygon", "text", "linearGradient", "stop", "defs"], ADD_ATTR: [ "viewBox", diff --git a/webview/components/organisms/SessionList/SessionList.tsx b/webview/components/organisms/SessionList/SessionList.tsx index 77550b1..1078b1a 100644 --- a/webview/components/organisms/SessionList/SessionList.tsx +++ b/webview/components/organisms/SessionList/SessionList.tsx @@ -1,6 +1,6 @@ import type { ChatSession } from "@shared"; import { useLocale } from "../../../locales"; -import type { en } from "../../../locales/en"; +import type { LocaleSchema } from "../../../locales/en"; import { IconButton } from "../../atoms/IconButton"; import { DeleteIcon, FileIcon } from "../../atoms/icons"; import styles from "./SessionList.module.css"; @@ -13,7 +13,7 @@ type Props = { onClose: () => void; }; -export function formatRelativeTime(timestamp: number, t: typeof en): string { +export function formatRelativeTime(timestamp: number, t: LocaleSchema): string { const now = Date.now(); const diff = now - timestamp; const seconds = Math.floor(diff / 1000); diff --git a/webview/components/organisms/ToolPartView/ToolPartView.tsx b/webview/components/organisms/ToolPartView/ToolPartView.tsx index dbbfc0e..8822d0a 100644 --- a/webview/components/organisms/ToolPartView/ToolPartView.tsx +++ b/webview/components/organisms/ToolPartView/ToolPartView.tsx @@ -47,6 +47,10 @@ function isFileCreateInput(input: Record): boolean { return typeof input.content === "string" && getFilePath(input) !== null && typeof input.oldString !== "string"; } +function formatOutput(value: unknown): string { + return typeof value === "string" ? value : JSON.stringify(value, null, 2); +} + function ActionIcon({ category }: { category: ToolCategory }) { switch (category) { case "read": @@ -190,7 +194,7 @@ export function ToolPartView({ part }: Props) { ) : ( <> - {isCompleted && state.output &&
{state.output}
} + {isCompleted && state.output &&
{formatOutput(state.output)}
} {isError &&
{state.error}
} {isActive && input &&
{JSON.stringify(input, null, 2)}
} diff --git a/webview/hooks/useSoundNotification.ts b/webview/hooks/useSoundNotification.ts index 03ba3d9..8af1949 100644 --- a/webview/hooks/useSoundNotification.ts +++ b/webview/hooks/useSoundNotification.ts @@ -93,7 +93,7 @@ export function useSoundNotification() { } break; } - case "permission.updated": + case "permission.asked": eventType = "permissionRequest"; break; case "question.asked": diff --git a/webview/locales/es.ts b/webview/locales/es.ts index def2883..310303d 100644 --- a/webview/locales/es.ts +++ b/webview/locales/es.ts @@ -145,8 +145,10 @@ export const es: LocaleSchema = { // Context menu sections "input.section.files": "Archivos", "input.section.agents": "Sub-agentes", + "input.section.skills": "Habilidades", "input.section.shell": "Modo Shell", // AgentMention "input.noAgents": "No hay sub-agentes disponibles", + "input.noSkills": "No hay habilidades disponibles", }; diff --git a/webview/locales/index.ts b/webview/locales/index.ts index ab79986..fc983c1 100644 --- a/webview/locales/index.ts +++ b/webview/locales/index.ts @@ -7,11 +7,12 @@ import { ptBr } from "./pt-br"; import { ru } from "./ru"; import { zhCn } from "./zh-cn"; import { zhTw } from "./zh-tw"; +import type { LocaleSchema } from "./en"; export type SupportedLocale = "en" | "ja" | "zh-cn" | "ko" | "zh-tw" | "es" | "pt-br" | "ru"; export type LocaleSetting = "auto" | SupportedLocale; -const locales: Record = { +const locales: Record = { en, ja, "zh-cn": zhCn, @@ -35,15 +36,15 @@ export function resolveLocale(setting: LocaleSetting, vscodeLanguage: string): S return "en"; } -export function getStrings(locale: SupportedLocale): typeof en { +export function getStrings(locale: SupportedLocale): LocaleSchema { return locales[locale] ?? locales.en; } // React Context -const LocaleContext = createContext(en); +const LocaleContext = createContext(en); export const LocaleProvider = LocaleContext.Provider; -export function useLocale(): typeof en { +export function useLocale(): LocaleSchema { return useContext(LocaleContext); } diff --git a/webview/locales/ko.ts b/webview/locales/ko.ts index c112eca..15adc53 100644 --- a/webview/locales/ko.ts +++ b/webview/locales/ko.ts @@ -145,8 +145,10 @@ export const ko: LocaleSchema = { // Context menu sections "input.section.files": "파일", "input.section.agents": "서브 에이전트", + "input.section.skills": "스킬", "input.section.shell": "셸 모드", // AgentMention "input.noAgents": "사용 가능한 서브 에이전트가 없습니다", + "input.noSkills": "사용 가능한 스킬이 없습니다", }; diff --git a/webview/locales/pt-br.ts b/webview/locales/pt-br.ts index 34d02c9..272e69a 100644 --- a/webview/locales/pt-br.ts +++ b/webview/locales/pt-br.ts @@ -145,8 +145,10 @@ export const ptBr: LocaleSchema = { // Context menu sections "input.section.files": "Arquivos", "input.section.agents": "Sub-agentes", + "input.section.skills": "Habilidades", "input.section.shell": "Modo Shell", // AgentMention "input.noAgents": "Nenhum sub-agente disponível", + "input.noSkills": "Nenhuma habilidade disponível", }; diff --git a/webview/locales/ru.ts b/webview/locales/ru.ts index c2a5f87..a5cae5e 100644 --- a/webview/locales/ru.ts +++ b/webview/locales/ru.ts @@ -145,8 +145,10 @@ export const ru: LocaleSchema = { // Context menu sections "input.section.files": "Файлы", "input.section.agents": "Субагенты", + "input.section.skills": "Навыки", "input.section.shell": "Режим Shell", // AgentMention "input.noAgents": "Нет доступных субагентов", + "input.noSkills": "Нет доступных навыков", }; diff --git a/webview/locales/zh-cn.ts b/webview/locales/zh-cn.ts index 1201245..aebdde4 100644 --- a/webview/locales/zh-cn.ts +++ b/webview/locales/zh-cn.ts @@ -145,8 +145,10 @@ export const zhCn: LocaleSchema = { // Context menu sections "input.section.files": "文件", "input.section.agents": "子智能体", + "input.section.skills": "技能", "input.section.shell": "Shell 模式", // AgentMention "input.noAgents": "没有可用的子智能体", + "input.noSkills": "没有可用的技能", }; diff --git a/webview/locales/zh-tw.ts b/webview/locales/zh-tw.ts index 218e095..d5bf186 100644 --- a/webview/locales/zh-tw.ts +++ b/webview/locales/zh-tw.ts @@ -145,8 +145,10 @@ export const zhTw: LocaleSchema = { // Context menu sections "input.section.files": "檔案", "input.section.agents": "子代理", + "input.section.skills": "技能", "input.section.shell": "Shell 模式", // AgentMention "input.noAgents": "沒有可用的子代理", + "input.noSkills": "沒有可用的技能", }; diff --git a/webview/utils/todo.ts b/webview/utils/todo.ts index 7ad4f0a..a372cbc 100644 --- a/webview/utils/todo.ts +++ b/webview/utils/todo.ts @@ -1,4 +1,12 @@ -export type TodoItem = { content: string; status?: string; priority?: string }; +import type { TodoItem } from "@shared"; + +function normalizeTodo(item: { content: string; status?: unknown; priority?: unknown }): TodoItem { + return { + content: item.content, + status: typeof item.status === "string" ? item.status : "pending", + priority: typeof item.priority === "string" ? item.priority : "medium", + }; +} export function parseTodos(raw: unknown): TodoItem[] | null { try { @@ -6,8 +14,10 @@ export function parseTodos(raw: unknown): TodoItem[] | null { const arr = Array.isArray(data) ? data : (data?.todos ?? data?.items ?? null); if (!Array.isArray(arr) || arr.length === 0) return null; if (!arr.every((item: unknown) => typeof item === "object" && item !== null && "content" in item)) return null; - return arr as TodoItem[]; + return arr.map((item) => normalizeTodo(item as { content: string; status?: unknown; priority?: unknown })); } catch { return null; } } + +export type { TodoItem }; From 892cee394ce318e1ac22f380bea194c25f7a4bb6 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 18:56:48 +0900 Subject: [PATCH 12/25] =?UTF-8?q?=20OpenCode=20client=20handle=20=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- docs/architecture.md | 12 +- .../__tests__/chat-view-provider.test.ts | 137 ++- extension/__tests__/extension.test.ts | 12 +- extension/__tests__/mappers.test.ts | 332 ------- extension/__tests__/opencode-agent.test.ts | 921 ------------------ .../__tests__/opencode-client-handle.test.ts | 169 ++++ extension/chat-view-provider.ts | 225 +++-- extension/extension.ts | 16 +- extension/mappers.ts | 197 ---- extension/opencode-agent.ts | 441 --------- extension/opencode-client-handle.ts | 75 ++ shared/domain.ts | 7 +- 13 files changed, 562 insertions(+), 1988 deletions(-) delete mode 100644 extension/__tests__/mappers.test.ts delete mode 100644 extension/__tests__/opencode-agent.test.ts create mode 100644 extension/__tests__/opencode-client-handle.test.ts delete mode 100644 extension/mappers.ts delete mode 100644 extension/opencode-agent.ts create mode 100644 extension/opencode-client-handle.ts diff --git a/README.md b/README.md index a0ed6e2..925190e 100644 --- a/README.md +++ b/README.md @@ -145,8 +145,7 @@ This project is a single VS Code extension package: extension/ extension.ts # Extension entry point chat-view-provider.ts # Webview panel & messaging - opencode-agent.ts # OpenCode SDK integration - mappers.ts # SDK to UI/domain type mappers + opencode-client-handle.ts # OpenCode client lifecycle __tests__/ # Extension host tests shared/ # Shared types for extension host and webview webview/ # Webview (React) @@ -303,8 +302,7 @@ npm test extension/ extension.ts # 拡張機能エントリーポイント chat-view-provider.ts # Webview パネル & メッセージング - opencode-agent.ts # OpenCode SDK 連携 - mappers.ts # SDK から UI/ドメイン型へのマッパー + opencode-client-handle.ts # OpenCode client lifecycle __tests__/ # Extension Host テスト shared/ # Extension Host と Webview の共有型 webview/ # Webview (React) diff --git a/docs/architecture.md b/docs/architecture.md index 8dd949b..fa68ebe 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -11,8 +11,7 @@ diff editors. extension/ extension.ts VS Code activation entry point chat-view-provider.ts Webview message router - opencode-agent.ts OpenCode SDK lifecycle and API calls - mappers.ts SDK type to UI/domain type mapping + opencode-client-handle.ts OpenCode client lifecycle vscode-platform-services.ts VS Code API helpers __tests__/ Extension host tests @@ -31,13 +30,12 @@ webview/ ## Data Flow -1. `extension.ts` creates `OpenCodeAgent` and calls `connect()`. -2. `OpenCodeAgent` starts the OpenCode server, creates the SDK client, and +1. `extension.ts` creates `OpenCodeClientHandle` and calls `connect()`. +2. `OpenCodeClientHandle` starts the OpenCode server, creates the SDK client, and subscribes to SDK events. 3. `ChatViewProvider` receives messages from the webview and calls - `OpenCodeAgent` or `VscodePlatformServices` directly. -4. SDK events are mapped in `mappers.ts` and forwarded to the webview as - `HostToUIMessage`. + the OpenCode SDK client or `VscodePlatformServices` directly. +4. SDK events are forwarded to the webview as `HostToUIMessage`. 5. The webview updates React state from host messages and sends user actions back as `UIToHostMessage`. diff --git a/extension/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-view-provider.test.ts index f26f51e..99bed3e 100644 --- a/extension/__tests__/chat-view-provider.test.ts +++ b/extension/__tests__/chat-view-provider.test.ts @@ -1,6 +1,6 @@ /** * ChatViewProvider のユニットテスト。 - * OpenCodeAgent をモックし、webview メッセージハンドラの振る舞いを検証する。 + * OpenCodeClientHandle をモックし、webview メッセージハンドラの振る舞いを検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -15,23 +15,25 @@ import * as fs from "node:fs/promises"; import * as vscode from "vscode"; import { ChatViewProvider } from "../chat-view-provider"; import type { DiffReviewManager } from "../diff-review-manager"; -import type { OpenCodeAgent } from "../opencode-agent"; +import type { OpenCodeClientHandle } from "../opencode-client-handle"; import type { VscodePlatformServices } from "../vscode-platform-services"; -// --- Helper: OpenCodeAgent のモック --- +// --- Helper: OpenCodeClientHandle のモック --- type MockedMethods = { [K in keyof T]: T[K] extends (...args: never[]) => unknown ? ReturnType : T[K]; }; -type MockOpenCodeAgent = MockedMethods; +type MockOpenCodeClientHandle = MockedMethods & Record>; type MockVscodePlatformServices = MockedMethods; -function createMockAgent(): MockOpenCodeAgent { - return { +function createMockAgent(): MockOpenCodeClientHandle { + const api = { connect: vi.fn().mockResolvedValue(undefined), disconnect: vi.fn(), onEvent: vi.fn().mockReturnValue({ dispose: vi.fn() }), + resubscribeEvents: vi.fn().mockResolvedValue(undefined), + getClient: vi.fn(), listSessions: vi.fn().mockResolvedValue([]), createSession: vi.fn().mockResolvedValue({ id: "new-sess", title: "New" }), getSession: vi.fn().mockResolvedValue({ id: "sess-1" }), @@ -65,7 +67,112 @@ function createMockAgent(): MockOpenCodeAgent { getToolIds: vi.fn().mockResolvedValue([]), getServerUrl: vi.fn().mockReturnValue("http://localhost:12345"), setModel: vi.fn().mockResolvedValue(undefined), - } as MockOpenCodeAgent; + } as any; + + api.getClient.mockReturnValue({ + session: { + list: vi.fn(async () => ({ data: await api.listSessions() })), + create: vi.fn(async ({ title }: { title?: string }) => ({ data: await api.createSession(title) })), + get: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.getSession(sessionID) })), + delete: vi.fn(async ({ sessionID }: { sessionID: string }) => api.deleteSession(sessionID)), + fork: vi.fn(async ({ sessionID, messageID }: { sessionID: string; messageID?: string }) => ({ + data: await api.forkSession(sessionID, messageID), + })), + revert: vi.fn(async ({ sessionID, messageID }: { sessionID: string; messageID: string }) => ({ + data: await api.revertSession(sessionID, messageID), + })), + unrevert: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ + data: await api.unrevertSession(sessionID), + })), + summarize: vi.fn( + async ({ + sessionID, + providerID, + modelID, + }: { + sessionID: string; + providerID?: string; + modelID?: string; + }) => api.summarizeSession(sessionID, providerID && modelID ? { providerID, modelID } : undefined), + ), + share: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.shareSession(sessionID) })), + unshare: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.unshareSession(sessionID) })), + messages: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.getMessages(sessionID) })), + promptAsync: vi.fn( + async ({ + sessionID, + parts, + model, + agent: primaryAgent, + }: { + sessionID: string; + parts: Array<{ type: string; text?: string; synthetic?: boolean; url?: string; filename?: string; name?: string }>; + model?: unknown; + agent?: string; + }) => { + const textPart = parts.find((part) => part.type === "text" && !part.synthetic); + const skillPart = parts.find((part) => part.type === "text" && part.synthetic); + const fileParts = parts.filter((part) => part.type === "file"); + const agentPart = parts.find((part) => part.type === "agent"); + const options: Record = {}; + if (model !== undefined) options.model = model; + if (fileParts.length > 0) { + options.files = fileParts.map((part) => ({ + filePath: part.url?.replace("file:///workspace/", "") ?? "", + fileName: part.filename ?? "", + })); + } + if (agentPart?.name) options.agent = agentPart.name; + if (primaryAgent) options.primaryAgent = primaryAgent; + if (skillPart?.text) options.skill = skillPart.text.replace(/^\//, ""); + return api.sendMessage(sessionID, textPart?.text ?? "", options as never); + }, + ), + abort: vi.fn(async ({ sessionID }: { sessionID: string }) => api.abortSession(sessionID)), + shell: vi.fn(async ({ sessionID, command, model }: { sessionID: string; command: string; model?: unknown }) => + api.executeShell(sessionID, command, model as never), + ), + children: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.getChildSessions(sessionID) })), + todo: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.getSessionTodos(sessionID) })), + diff: vi.fn(async ({ sessionID }: { sessionID: string }) => ({ data: await api.getSessionDiff(sessionID) })), + }, + config: { + providers: vi.fn(async () => ({ data: await api.getProviders() })), + get: vi.fn(async () => ({ data: await api.getConfig() })), + update: vi.fn(async ({ config }: { config: unknown }) => api.updateConfig(config as never)), + }, + provider: { + list: vi.fn(async () => ({ data: await api.listAllProviders() })), + }, + permission: { + reply: vi.fn(async ({ requestID, reply }: { requestID: string; reply: never }) => + api.replyPermission("", requestID, reply), + ), + }, + question: { + reply: vi.fn(async ({ requestID, answers }: { requestID: string; answers: string[] }) => + api.replyQuestion(requestID, answers), + ), + reject: vi.fn(async ({ requestID }: { requestID: string }) => api.rejectQuestion(requestID)), + }, + app: { + agents: vi.fn(async () => ({ data: await api.getAgents() })), + skills: vi.fn(async () => ({ data: await api.getSkills() })), + }, + path: { + get: vi.fn(async () => ({ data: await api.getPath() })), + }, + mcp: { + status: vi.fn(async () => ({ data: await api.getMcpStatus() })), + connect: vi.fn(async ({ name }: { name: string }) => api.connectMcp(name)), + disconnect: vi.fn(async ({ name }: { name: string }) => api.disconnectMcp(name)), + }, + tool: { + ids: vi.fn(async () => ({ data: (await api.getToolIds()).map((tool: { id: string }) => tool.id) })), + }, + }); + + return api as MockOpenCodeClientHandle; } // --- Helper: VscodePlatformServices のモック --- @@ -150,6 +257,7 @@ function setupProvider( const provider = new ChatViewProvider( extensionUri as never, mockAgent as never, + "/workspace", ps as never, drm as never, difitAvailable, @@ -513,8 +621,9 @@ describe("ChatViewProvider", () => { // ============================================================ describe("replyPermission", () => { - it("should call agent.replyPermission with 3 args", async () => { + it("should call SDK permission.reply", async () => { const { sendMessage } = setupProvider(mockAgent); + const client = (mockAgent as any).getClient(); await sendMessage({ type: "replyPermission", @@ -523,7 +632,7 @@ describe("ChatViewProvider", () => { response: "always", }); - expect(mockAgent.replyPermission).toHaveBeenCalledWith("sess-1", "perm-1", "always"); + expect(client.permission.reply).toHaveBeenCalledWith({ requestID: "perm-1", reply: "always" }); }); }); @@ -780,11 +889,16 @@ describe("ChatViewProvider", () => { // ============================================================ describe("setModel", () => { - it("should delegate to agent.setModel and send modelUpdated", async () => { + it("should update opencode config file and send modelUpdated", async () => { + vi.mocked(fs.readFile).mockResolvedValue('{"theme":"dark"}'); const { postMessage, sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "setModel", model: "anthropic/claude-4" }); - expect(mockAgent.setModel).toHaveBeenCalledWith("anthropic/claude-4"); + const writeCall = vi.mocked(fs.writeFile).mock.calls[0]; + expect(JSON.parse((writeCall[1] as string).trim())).toEqual({ + theme: "dark", + model: "anthropic/claude-4", + }); expect(postMessage).toHaveBeenCalledWith({ type: "modelUpdated", model: "anthropic/claude-4", @@ -1184,6 +1298,7 @@ describe("ChatViewProvider", () => { const provider = new ChatViewProvider( extensionUri as never, mockAgent as never, + "/workspace", createMockPlatformServices() as never, createMockDiffReviewManager() as never, false, diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index 42f67ad..d13bedc 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -1,6 +1,6 @@ /** * extension.ts (activate / deactivate) のユニットテスト。 - * ChatViewProvider と OpenCodeAgent をモックし、起動・停止の振る舞いを検証する。 + * ChatViewProvider と OpenCodeClientHandle をモックし、起動・停止の振る舞いを検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -9,10 +9,10 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const mockConnect = vi.fn().mockResolvedValue(undefined); const mockDisconnect = vi.fn(); -// モジュールスコープで `new OpenCodeAgent()` が呼ばれるため、 +// モジュールスコープで `new OpenCodeClientHandle()` が呼ばれるため、 // コンストラクタとして機能するクラスを返す必要がある。 function createMockAgentClass() { - return class MockOpenCodeAgent { + return class MockOpenCodeClientHandle { connect = mockConnect; disconnect = mockDisconnect; workspaceFolder: string | undefined = undefined; @@ -48,14 +48,14 @@ describe("extension", () => { }); /** - * extension.ts はモジュールスコープで `new OpenCodeAgent()` を実行する。 + * extension.ts はモジュールスコープで `new OpenCodeClientHandle()` を実行する。 * テストごとに新しいモジュールインスタンスが必要なので、毎回 resetModules して再 import する。 */ async function importExtension() { vi.resetModules(); - vi.doMock("../opencode-agent", () => ({ - OpenCodeAgent: createMockAgentClass(), + vi.doMock("../opencode-client-handle", () => ({ + OpenCodeClientHandle: createMockAgentClass(), })); vi.doMock("../chat-view-provider", () => ({ ChatViewProvider: createMockChatViewProviderClass(), diff --git a/extension/__tests__/mappers.test.ts b/extension/__tests__/mappers.test.ts deleted file mode 100644 index ff6c1d1..0000000 --- a/extension/__tests__/mappers.test.ts +++ /dev/null @@ -1,332 +0,0 @@ -/** - * mappers.ts のユニットテスト。 - * 各 mapper 関数が SDK 型からドメイン型に正しく変換することを検証する。 - */ -import { describe, expect, it } from "vitest"; -import { - mapAgent, - mapAgents, - mapAllProvidersData, - mapConfig, - mapEvent, - mapFileDiff, - mapFileDiffs, - mapMcpStatus, - mapMessage, - mapMessagesWithParts, - mapMessageWithParts, - mapPart, - mapPath, - mapProvider, - mapProviders, - mapSession, - mapSessions, - mapTodo, - mapTodos, - mapToolIds, -} from "../mappers"; - -// ============================================================ -// Session mappers -// ============================================================ - -describe("mapSession", () => { - it("should pass through session data as ChatSession", () => { - const sdkSession = { - id: "sess-1", - title: "Test Session", - createdAt: 1700000000, - updatedAt: 1700001000, - }; - const result = mapSession(sdkSession as never); - expect(result).toEqual(sdkSession); - }); -}); - -describe("mapSessions", () => { - it("should map an array of sessions", () => { - const sessions = [ - { id: "s1", title: "Session 1" }, - { id: "s2", title: "Session 2" }, - ]; - const result = mapSessions(sessions as never); - expect(result).toHaveLength(2); - expect(result[0]).toEqual(sessions[0]); - expect(result[1]).toEqual(sessions[1]); - }); - - it("should return empty array for empty input", () => { - expect(mapSessions([])).toEqual([]); - }); -}); - -// ============================================================ -// Message + Parts mappers -// ============================================================ - -describe("mapMessage", () => { - it("should pass through message data as ChatMessage", () => { - const sdkMessage = { - id: "msg-1", - role: "assistant", - content: "Hello", - createdAt: 1700000000, - }; - const result = mapMessage(sdkMessage as never); - expect(result).toEqual(sdkMessage); - }); -}); - -describe("mapPart", () => { - it("should pass through text part", () => { - const part = { type: "text", content: "Hello world" }; - const result = mapPart(part as never); - expect(result).toEqual(part); - }); - - it("should pass through tool-use part", () => { - const part = { type: "tool-use", toolName: "search", input: { query: "foo" } }; - const result = mapPart(part as never); - expect(result).toEqual(part); - }); -}); - -describe("mapMessageWithParts", () => { - it("should map info and parts together", () => { - const data = { - info: { id: "msg-1", role: "assistant" }, - parts: [ - { type: "text", content: "Hello" }, - { type: "tool-use", toolName: "search" }, - ], - }; - const result = mapMessageWithParts(data as never); - expect(result.info).toEqual(data.info); - expect(result.parts).toHaveLength(2); - expect(result.parts[0]).toEqual(data.parts[0]); - expect(result.parts[1]).toEqual(data.parts[1]); - }); -}); - -describe("mapMessagesWithParts", () => { - it("should map an array of messages with parts", () => { - const data = [ - { info: { id: "msg-1" }, parts: [{ type: "text" }] }, - { info: { id: "msg-2" }, parts: [] }, - ]; - const result = mapMessagesWithParts(data as never); - expect(result).toHaveLength(2); - expect(result[0].info).toEqual(data[0].info); - expect(result[1].parts).toEqual([]); - }); -}); - -// ============================================================ -// Event mapper -// ============================================================ - -describe("mapEvent", () => { - it("should pass through session.updated event", () => { - const event = { type: "session.updated", properties: { id: "sess-1" } }; - const result = mapEvent(event as never); - expect(result).toEqual(event); - }); - - it("should pass through message.created event", () => { - const event = { type: "message.created", properties: { sessionID: "sess-1", id: "msg-1" } }; - const result = mapEvent(event as never); - expect(result).toEqual(event); - }); -}); - -// ============================================================ -// Provider mapper -// ============================================================ - -describe("mapProvider", () => { - it("should pass through provider data as ProviderInfo", () => { - const provider = { id: "anthropic", name: "Anthropic", models: [] }; - const result = mapProvider(provider as never); - expect(result).toEqual(provider); - }); -}); - -describe("mapProviders", () => { - it("should map an array of providers", () => { - const providers = [ - { id: "p1", name: "Provider 1" }, - { id: "p2", name: "Provider 2" }, - ]; - const result = mapProviders(providers as never); - expect(result).toHaveLength(2); - }); -}); - -// ============================================================ -// FileDiff mapper -// ============================================================ - -describe("mapFileDiff", () => { - it("should map SDK snapshot diff data", () => { - const diff = { file: "src/index.ts", patch: "diff --git a/src/index.ts b/src/index.ts", additions: 1, deletions: 1 }; - const result = mapFileDiff(diff as never); - expect(result).toEqual(diff); - }); -}); - -describe("mapFileDiffs", () => { - it("should map an array of file diffs", () => { - const diffs = [ - { file: "a.ts", patch: "diff --git a/a.ts b/a.ts", additions: 1, deletions: 0 }, - { file: "b.ts", patch: "diff --git a/b.ts b/b.ts", additions: 0, deletions: 1 }, - ]; - const result = mapFileDiffs(diffs as never); - expect(result).toHaveLength(2); - }); - - it("should return empty array for empty input", () => { - expect(mapFileDiffs([])).toEqual([]); - }); -}); - -// ============================================================ -// Todo mapper -// ============================================================ - -describe("mapTodo", () => { - it("should map SDK todo data as TodoItem", () => { - const todo = { content: "Fix bug", status: "pending", priority: "high" }; - const result = mapTodo(todo as never); - expect(result).toEqual(todo); - }); -}); - -describe("mapTodos", () => { - it("should map an array of todos", () => { - const todos = [ - { content: "A", status: "pending", priority: "medium" }, - { content: "B", status: "completed", priority: "low" }, - ]; - const result = mapTodos(todos as never); - expect(result).toHaveLength(2); - }); -}); - -// ============================================================ -// Agent mapper -// ============================================================ - -describe("mapAgent", () => { - it("should pass through agent data as AgentInfo", () => { - const agentData = { id: "agent-1", name: "Default Agent" }; - const result = mapAgent(agentData as never); - expect(result).toEqual(agentData); - }); -}); - -describe("mapAgents", () => { - it("should map an array of agents", () => { - const agents = [{ id: "a1" }, { id: "a2" }]; - const result = mapAgents(agents as never); - expect(result).toHaveLength(2); - }); -}); - -// ============================================================ -// Config mapper -// ============================================================ - -describe("mapConfig", () => { - it("should pass through config data as AppConfig", () => { - const config = { model: "claude-4", theme: "dark" }; - const result = mapConfig(config as never); - expect(result).toEqual(config); - }); -}); - -// ============================================================ -// Path mapper -// ============================================================ - -describe("mapPath", () => { - it("should pass through path data as AppPaths", () => { - const pathData = { - config: "/home/.config/opencode", - data: "/home/.local/share/opencode", - home: "/home/user", - }; - const result = mapPath(pathData as never); - expect(result).toEqual(pathData); - }); - - it("should handle path without home field", () => { - const pathData = { - config: "/home/.config/opencode", - data: "/home/.local/share/opencode", - }; - const result = mapPath(pathData as never); - expect(result).toEqual(pathData); - }); -}); - -// ============================================================ -// MCP Status mapper -// ============================================================ - -describe("mapMcpStatus", () => { - it("should pass through MCP status data", () => { - const status = { - "server-1": { connected: true, tools: ["tool-a"] }, - "server-2": { connected: false, tools: [] }, - }; - const result = mapMcpStatus(status as never); - expect(result).toEqual(status); - }); - - it("should handle empty status", () => { - const result = mapMcpStatus({} as never); - expect(result).toEqual({}); - }); -}); - -// ============================================================ -// Tool IDs mapper -// ============================================================ - -describe("mapToolIds", () => { - it("should wrap each string ID into ToolListItem", () => { - const ids = ["tool-1", "tool-2", "tool-3"]; - const result = mapToolIds(ids); - expect(result).toEqual([{ id: "tool-1" }, { id: "tool-2" }, { id: "tool-3" }]); - }); - - it("should return empty array for empty input", () => { - expect(mapToolIds([])).toEqual([]); - }); - - it("should handle single ID", () => { - expect(mapToolIds(["only-one"])).toEqual([{ id: "only-one" }]); - }); -}); - -// ============================================================ -// AllProvidersData mapper -// ============================================================ - -describe("mapAllProvidersData", () => { - it("should pass through all providers data", () => { - const data = { - all: [{ id: "p1", name: "Provider 1", models: [] }], - default: { chat: "anthropic/claude-4" }, - connected: ["p1"], - }; - const result = mapAllProvidersData(data as never); - expect(result).toEqual(data); - }); - - it("should handle empty data", () => { - const data = { all: [], default: {}, connected: [] }; - const result = mapAllProvidersData(data); - expect(result).toEqual(data); - }); -}); diff --git a/extension/__tests__/opencode-agent.test.ts b/extension/__tests__/opencode-agent.test.ts deleted file mode 100644 index c5a2009..0000000 --- a/extension/__tests__/opencode-agent.test.ts +++ /dev/null @@ -1,921 +0,0 @@ -/** - * OpenCodeAgent のユニットテスト。 - * @opencode-ai/sdk/v2 をモックし、各パブリックメソッドが正しいパラメータで SDK を呼び出し、 - * mapper を通してドメイン型に変換されることを検証する。 - */ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; - -// --- SDK モック --- - -/** SDK クライアントのモックを生成する */ -function createMockSdkClient() { - return { - session: { - list: vi.fn().mockResolvedValue({ data: [] }), - create: vi.fn().mockResolvedValue({ data: { id: "sess-1", title: "Test" } }), - get: vi.fn().mockResolvedValue({ data: { id: "sess-1" } }), - delete: vi.fn().mockResolvedValue(undefined), - fork: vi.fn().mockResolvedValue({ data: { id: "sess-2" } }), - messages: vi.fn().mockResolvedValue({ data: [] }), - promptAsync: vi.fn().mockResolvedValue(undefined), - abort: vi.fn().mockResolvedValue(undefined), - shell: vi.fn().mockResolvedValue(undefined), - children: vi.fn().mockResolvedValue({ data: [] }), - todo: vi.fn().mockResolvedValue({ data: [] }), - share: vi.fn().mockResolvedValue({ data: { id: "sess-1", share: { url: "https://example.com" } } }), - unshare: vi.fn().mockResolvedValue({ data: { id: "sess-1" } }), - diff: vi.fn().mockResolvedValue({ data: [] }), - revert: vi.fn().mockResolvedValue({ data: { id: "sess-1" } }), - unrevert: vi.fn().mockResolvedValue({ data: { id: "sess-1" } }), - summarize: vi.fn().mockResolvedValue(undefined), - }, - config: { - providers: vi.fn().mockResolvedValue({ data: { providers: [], default: {} } }), - get: vi.fn().mockResolvedValue({ data: {} }), - update: vi.fn().mockResolvedValue(undefined), - }, - provider: { - list: vi.fn().mockResolvedValue({ data: { all: [], default: {}, connected: [] } }), - }, - permission: { - reply: vi.fn().mockResolvedValue(undefined), - }, - question: { - reply: vi.fn().mockResolvedValue(undefined), - reject: vi.fn().mockResolvedValue(undefined), - }, - app: { - agents: vi.fn().mockResolvedValue({ data: [] }), - skills: vi.fn().mockResolvedValue({ data: [] }), - }, - mcp: { - status: vi.fn().mockResolvedValue({ data: {} }), - connect: vi.fn().mockResolvedValue(undefined), - disconnect: vi.fn().mockResolvedValue(undefined), - }, - tool: { - ids: vi.fn().mockResolvedValue({ data: ["tool-1", "tool-2"] }), - }, - path: { - get: vi - .fn() - .mockResolvedValue({ data: { config: "/home/.config/opencode", data: "/home/.local/share/opencode" } }), - }, - event: { - subscribe: vi.fn().mockResolvedValue({ - stream: (async function* () { - // デフォルトは空ストリーム - })(), - }), - }, - }; -} - -let mockClient: ReturnType; -const mockServerClose = vi.fn(); - -vi.mock("node:fs/promises", () => ({ - readFile: vi.fn(), - writeFile: vi.fn().mockResolvedValue(undefined), - mkdir: vi.fn().mockResolvedValue(undefined), -})); - -vi.mock("@opencode-ai/sdk/v2", () => ({ - createOpencodeServer: vi.fn().mockImplementation(() => - Promise.resolve({ - url: "http://localhost:12345", - close: mockServerClose, - }), - ), - createOpencodeClient: vi.fn().mockImplementation(() => mockClient), -})); - -import * as fs from "node:fs/promises"; -import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; -// テスト対象 -import { OpenCodeAgent } from "../opencode-agent"; - -describe("OpenCodeAgent", () => { - let agent: OpenCodeAgent; - - beforeEach(() => { - mockClient = createMockSdkClient(); - // createOpencodeClient のモック実装を更新 - vi.mocked(createOpencodeClient).mockReturnValue(mockClient as never); - agent = new OpenCodeAgent(); - }); - - afterEach(() => { - agent.disconnect(); - vi.clearAllMocks(); - }); - - // ============================================================ - // connect / disconnect / lifecycle - // ============================================================ - - describe("connect()", () => { - it("should create server on port 0 and create client", async () => { - await agent.connect(); - - expect(createOpencodeServer).toHaveBeenCalledWith({ port: 0 }); - expect(createOpencodeClient).toHaveBeenCalledWith({ baseUrl: "http://localhost:12345" }); - }); - - it("should subscribe to SSE events after connecting", async () => { - await agent.connect(); - - expect(mockClient.event.subscribe).toHaveBeenCalled(); - }); - - it("should expose serverUrl via getServerUrl() after connecting", async () => { - expect(agent.getServerUrl()).toBeUndefined(); - await agent.connect(); - expect(agent.getServerUrl()).toBe("http://localhost:12345"); - }); - }); - - describe("disconnect()", () => { - it("should abort SSE, close server, and clear state", async () => { - await agent.connect(); - - agent.disconnect(); - - expect(mockServerClose).toHaveBeenCalled(); - expect(agent.getServerUrl()).toBeUndefined(); - }); - - it("should be idempotent (no crash when called without connect)", () => { - expect(() => agent.disconnect()).not.toThrow(); - }); - - it("should clear event listeners", async () => { - await agent.connect(); - const listener = vi.fn(); - agent.onEvent(listener); - - agent.disconnect(); - - // After disconnect, listeners should be cleared. - // Reconnect and fire events — old listener should NOT be called. - await agent.connect(); - // 新しいストリームからイベントを流しても、旧リスナーは呼ばれない - // (disconnect で listeners.clear() されているため) - }); - }); - - describe("requireClient() (via public methods)", () => { - it("should throw when not connected", async () => { - await expect(agent.listSessions()).rejects.toThrow("OpenCode client is not connected. Call connect() first."); - }); - }); - - // ============================================================ - // Session API - // ============================================================ - - describe("listSessions()", () => { - it("should call client.session.list() and return mapped data", async () => { - const sessions = [{ id: "s1" }, { id: "s2" }]; - mockClient.session.list.mockResolvedValue({ data: sessions }); - await agent.connect(); - - const result = await agent.listSessions(); - - expect(mockClient.session.list).toHaveBeenCalled(); - expect(result).toEqual(sessions); - }); - }); - - describe("createSession()", () => { - it("should call client.session.create() with title", async () => { - await agent.connect(); - - await agent.createSession("My Session"); - - expect(mockClient.session.create).toHaveBeenCalledWith({ - title: "My Session", - }); - }); - - it("should pass undefined title when not provided", async () => { - await agent.connect(); - - await agent.createSession(); - - expect(mockClient.session.create).toHaveBeenCalledWith({ - title: undefined, - }); - }); - }); - - describe("getSession()", () => { - it("should call client.session.get() with correct sessionID", async () => { - await agent.connect(); - - await agent.getSession("sess-1"); - - expect(mockClient.session.get).toHaveBeenCalledWith({ - sessionID: "sess-1", - }); - }); - }); - - describe("deleteSession()", () => { - it("should call client.session.delete() with correct sessionID", async () => { - await agent.connect(); - - await agent.deleteSession("sess-1"); - - expect(mockClient.session.delete).toHaveBeenCalledWith({ - sessionID: "sess-1", - }); - }); - }); - - describe("forkSession()", () => { - it("should call with messageId when provided", async () => { - await agent.connect(); - - await agent.forkSession("sess-1", "msg-5"); - - expect(mockClient.session.fork).toHaveBeenCalledWith({ - sessionID: "sess-1", - messageID: "msg-5", - }); - }); - - it("should call with undefined messageID when not provided", async () => { - await agent.connect(); - - await agent.forkSession("sess-1"); - - expect(mockClient.session.fork).toHaveBeenCalledWith({ - sessionID: "sess-1", - messageID: undefined, - }); - }); - }); - - // ============================================================ - // Message API - // ============================================================ - - describe("getMessages()", () => { - it("should call with correct sessionId", async () => { - await agent.connect(); - - await agent.getMessages("sess-1"); - - expect(mockClient.session.messages).toHaveBeenCalledWith({ - sessionID: "sess-1", - }); - }); - }); - - describe("sendMessage()", () => { - it("should send text-only message", async () => { - await agent.connect(); - - await agent.sendMessage("sess-1", "Hello"); - - expect(mockClient.session.promptAsync).toHaveBeenCalledWith({ - sessionID: "sess-1", - parts: [{ type: "text", text: "Hello" }], - model: undefined, - agent: undefined, - }); - }); - - it("should send message with model via options", async () => { - await agent.connect(); - const model = { providerID: "anthropic", modelID: "claude-4" }; - - await agent.sendMessage("sess-1", "Hello", { model }); - - expect(mockClient.session.promptAsync).toHaveBeenCalledWith({ - sessionID: "sess-1", - parts: [{ type: "text", text: "Hello" }], - model, - agent: undefined, - }); - }); - - it("should convert relative file paths to absolute using workspaceFolder", async () => { - await agent.connect(); - agent.workspaceFolder = "/workspace/project"; - const files = [{ filePath: "src/index.ts", fileName: "index.ts" }]; - - await agent.sendMessage("sess-1", "Check this", { files }); - - const call = mockClient.session.promptAsync.mock.calls[0][0]; - expect(call.parts).toHaveLength(2); - expect(call.parts[1]).toEqual({ - type: "file", - mime: "text/plain", - url: "file:///workspace/project/src/index.ts", - filename: "index.ts", - }); - }); - - it("should not modify absolute file paths", async () => { - await agent.connect(); - const files = [{ filePath: "/absolute/path/file.ts", fileName: "file.ts" }]; - - await agent.sendMessage("sess-1", "Check", { files }); - - const call = mockClient.session.promptAsync.mock.calls[0][0]; - expect(call.parts[1]).toEqual({ - type: "file", - mime: "text/plain", - url: "file:///absolute/path/file.ts", - filename: "file.ts", - }); - }); - - it("should add agent part when agent is provided via options", async () => { - await agent.connect(); - - await agent.sendMessage("sess-1", "Hello", { agent: "code-reviewer" }); - - const call = mockClient.session.promptAsync.mock.calls[0][0]; - expect(call.parts).toHaveLength(2); - expect(call.parts[1]).toEqual({ type: "agent", name: "code-reviewer" }); - }); - - it("should prepend synthetic skill command when skill is provided", async () => { - await agent.connect(); - - await agent.sendMessage("sess-1", "Hello", { skill: "coding-guidelines" } as never); - - const call = mockClient.session.promptAsync.mock.calls[0][0]; - expect(call.parts).toHaveLength(2); - expect(call.parts[0]).toEqual({ type: "text", text: "/coding-guidelines", synthetic: true }); - expect(call.parts[1]).toEqual({ type: "text", text: "Hello" }); - }); - - it("should include all parts when files and agent are provided", async () => { - await agent.connect(); - agent.workspaceFolder = "/ws"; - const model = { providerID: "openai", modelID: "gpt-4" }; - const files = [{ filePath: "a.ts", fileName: "a.ts" }]; - - await agent.sendMessage("sess-1", "Review", { model, files, agent: "reviewer" }); - - const call = mockClient.session.promptAsync.mock.calls[0][0]; - expect(call.parts).toHaveLength(3); - expect(call.parts[0]).toEqual({ type: "text", text: "Review" }); - expect(call.parts[1].type).toBe("file"); - expect(call.parts[2]).toEqual({ type: "agent", name: "reviewer" }); - expect(call.model).toEqual(model); - }); - }); - - describe("abortSession()", () => { - it("should call client.session.abort()", async () => { - await agent.connect(); - - await agent.abortSession("sess-1"); - - expect(mockClient.session.abort).toHaveBeenCalledWith({ - sessionID: "sess-1", - }); - }); - }); - - // ============================================================ - // Shell API - // ============================================================ - - describe("executeShell()", () => { - it("should call client.session.shell() with correct args", async () => { - await agent.connect(); - const model = { providerID: "openai", modelID: "gpt-4" }; - - await agent.executeShell("sess-1", "ls -la", model); - - expect(mockClient.session.shell).toHaveBeenCalledWith({ - sessionID: "sess-1", - agent: "default", - command: "ls -la", - model, - }); - }); - - it("should pass undefined model when not provided", async () => { - await agent.connect(); - - await agent.executeShell("sess-1", "pwd"); - - expect(mockClient.session.shell).toHaveBeenCalledWith({ - sessionID: "sess-1", - agent: "default", - command: "pwd", - model: undefined, - }); - }); - }); - - // ============================================================ - // Provider API - // ============================================================ - - describe("getProviders()", () => { - it("should return providers and default from config.providers()", async () => { - const data = { providers: [{ id: "p1" }], default: { model: "claude-4" } }; - mockClient.config.providers.mockResolvedValue({ data }); - await agent.connect(); - - const result = await agent.getProviders(); - - expect(result).toEqual(data); - }); - }); - - describe("listAllProviders()", () => { - it("should return provider list from provider.list()", async () => { - const data = { all: [{ id: "p1" }], default: {}, connected: ["p1"] }; - mockClient.provider.list.mockResolvedValue({ data }); - await agent.connect(); - - const result = await agent.listAllProviders(); - - expect(result).toEqual(data); - }); - }); - - // ============================================================ - // Permission API - // ============================================================ - - describe("replyPermission()", () => { - it("should call permission.reply with correct requestID and reply", async () => { - await agent.connect(); - - await agent.replyPermission("sess-1", "perm-1", "always"); - - expect(mockClient.permission.reply).toHaveBeenCalledWith({ - requestID: "perm-1", - reply: "always", - }); - }); - }); - - // ============================================================ - // Session Children API - // ============================================================ - - describe("getChildSessions()", () => { - it("should call client.session.children()", async () => { - const children = [{ id: "child-1" }]; - mockClient.session.children.mockResolvedValue({ data: children }); - await agent.connect(); - - const result = await agent.getChildSessions("sess-1"); - - expect(mockClient.session.children).toHaveBeenCalledWith({ sessionID: "sess-1" }); - expect(result).toEqual(children); - }); - }); - - // ============================================================ - // Session Todo API - // ============================================================ - - describe("getSessionTodos()", () => { - it("should call client.session.todo()", async () => { - const todos = [{ content: "Fix bug", status: "pending", priority: "high" }]; - mockClient.session.todo.mockResolvedValue({ data: todos }); - await agent.connect(); - - const result = await agent.getSessionTodos("sess-1"); - - expect(mockClient.session.todo).toHaveBeenCalledWith({ sessionID: "sess-1" }); - expect(result).toEqual(todos); - }); - }); - - // ============================================================ - // Session Share API - // ============================================================ - - describe("shareSession()", () => { - it("should call client.session.share() and return session", async () => { - const session = { id: "sess-1", share: { url: "https://share.example.com" } }; - mockClient.session.share.mockResolvedValue({ data: session }); - await agent.connect(); - - const result = await agent.shareSession("sess-1"); - - expect(mockClient.session.share).toHaveBeenCalledWith({ sessionID: "sess-1" }); - expect(result).toEqual(session); - }); - }); - - describe("unshareSession()", () => { - it("should call client.session.unshare() and return session", async () => { - const session = { id: "sess-1" }; - mockClient.session.unshare.mockResolvedValue({ data: session }); - await agent.connect(); - - const result = await agent.unshareSession("sess-1"); - - expect(mockClient.session.unshare).toHaveBeenCalledWith({ sessionID: "sess-1" }); - expect(result).toEqual(session); - }); - }); - - // ============================================================ - // Agent API - // ============================================================ - - describe("getAgents()", () => { - it("should call app.agents()", async () => { - const agents = [{ id: "agent-1" }]; - mockClient.app.agents.mockResolvedValue({ data: agents }); - await agent.connect(); - - const result = await agent.getAgents(); - - expect(mockClient.app.agents).toHaveBeenCalled(); - expect(result).toEqual(agents); - }); - }); - - // ============================================================ - // Session Diff API - // ============================================================ - - describe("getSessionDiff()", () => { - it("should call client.session.diff()", async () => { - const diffs = [{ file: "file.ts", patch: "diff --git a/file.ts b/file.ts", additions: 1, deletions: 1 }]; - mockClient.session.diff.mockResolvedValue({ data: diffs }); - await agent.connect(); - - const result = await agent.getSessionDiff("sess-1"); - - expect(mockClient.session.diff).toHaveBeenCalledWith({ sessionID: "sess-1" }); - expect(result).toEqual(diffs); - }); - }); - - // ============================================================ - // Revert / Unrevert API - // ============================================================ - - describe("revertSession()", () => { - it("should call client.session.revert() with sessionId and messageID", async () => { - await agent.connect(); - - await agent.revertSession("sess-1", "msg-3"); - - expect(mockClient.session.revert).toHaveBeenCalledWith({ - sessionID: "sess-1", - messageID: "msg-3", - }); - }); - }); - - describe("unrevertSession()", () => { - it("should call client.session.unrevert()", async () => { - await agent.connect(); - - await agent.unrevertSession("sess-1"); - - expect(mockClient.session.unrevert).toHaveBeenCalledWith({ - sessionID: "sess-1", - }); - }); - }); - - // ============================================================ - // Summarize API - // ============================================================ - - describe("summarizeSession()", () => { - it("should call with model when provided", async () => { - await agent.connect(); - const model = { providerID: "openai", modelID: "gpt-4" }; - - await agent.summarizeSession("sess-1", model); - - expect(mockClient.session.summarize).toHaveBeenCalledWith({ - sessionID: "sess-1", - providerID: "openai", - modelID: "gpt-4", - }); - }); - - it("should pass undefined model when not provided", async () => { - await agent.connect(); - - await agent.summarizeSession("sess-1"); - - expect(mockClient.session.summarize).toHaveBeenCalledWith({ - sessionID: "sess-1", - providerID: undefined, - modelID: undefined, - }); - }); - }); - - // ============================================================ - // MCP API - // ============================================================ - - describe("getMcpStatus()", () => { - it("should call mcp.status()", async () => { - const status = { server1: { connected: true } }; - mockClient.mcp.status.mockResolvedValue({ data: status }); - await agent.connect(); - - const result = await agent.getMcpStatus(); - - expect(mockClient.mcp.status).toHaveBeenCalled(); - expect(result).toEqual(status); - }); - }); - - describe("connectMcp()", () => { - it("should call mcp.connect() with name", async () => { - await agent.connect(); - - await agent.connectMcp("my-server"); - - expect(mockClient.mcp.connect).toHaveBeenCalledWith({ name: "my-server" }); - }); - }); - - describe("disconnectMcp()", () => { - it("should call mcp.disconnect() with name", async () => { - await agent.connect(); - - await agent.disconnectMcp("my-server"); - - expect(mockClient.mcp.disconnect).toHaveBeenCalledWith({ name: "my-server" }); - }); - }); - - // ============================================================ - // Tool API - // ============================================================ - - describe("getToolIds()", () => { - it("should call tool.ids() and return ToolListItem[] via mapper", async () => { - await agent.connect(); - - const result = await agent.getToolIds(); - - expect(mockClient.tool.ids).toHaveBeenCalled(); - // mapToolIds wraps each string into { id } - expect(result).toEqual([{ id: "tool-1" }, { id: "tool-2" }]); - }); - }); - - describe("getSkills()", () => { - it("should call app.skills() and return mapped skills", async () => { - mockClient.app.skills.mockResolvedValue({ - data: [{ name: "coding-guidelines", description: "desc", location: "/skills/coding-guidelines" }], - }); - await agent.connect(); - - const result = await agent.getSkills(); - - expect(mockClient.app.skills).toHaveBeenCalled(); - expect(result).toEqual([ - { name: "coding-guidelines", description: "desc", location: "/skills/coding-guidelines" }, - ]); - }); - }); - - // ============================================================ - // Config API - // ============================================================ - - describe("getConfig()", () => { - it("should call config.get()", async () => { - const config = { model: "claude-4" }; - mockClient.config.get.mockResolvedValue({ data: config }); - await agent.connect(); - - const result = await agent.getConfig(); - - expect(mockClient.config.get).toHaveBeenCalled(); - expect(result).toEqual(config); - }); - }); - - describe("updateConfig()", () => { - it("should call config.update() with config param", async () => { - await agent.connect(); - - await agent.updateConfig({ model: "gpt-4" } as never); - - expect(mockClient.config.update).toHaveBeenCalledWith({ - config: { model: "gpt-4" }, - }); - }); - }); - - // ============================================================ - // Path API - // ============================================================ - - describe("getPath()", () => { - it("should call path.get() and return mapped data", async () => { - await agent.connect(); - - const result = await agent.getPath(); - - expect(mockClient.path.get).toHaveBeenCalled(); - expect(result).toEqual({ - config: "/home/.config/opencode", - data: "/home/.local/share/opencode", - }); - }); - }); - - // ============================================================ - // Event System - // ============================================================ - - describe("onEvent()", () => { - it("should register listener and return Disposable", async () => { - await agent.connect(); - const listener = vi.fn(); - - const disposable = agent.onEvent(listener); - - expect(disposable).toBeDefined(); - expect(typeof disposable.dispose).toBe("function"); - }); - - it("should deliver events from SSE stream to listeners", async () => { - const events = [ - { type: "session.updated", properties: { id: "sess-1" } }, - { type: "message.created", properties: { id: "msg-1" } }, - ]; - let resolveStream!: () => void; - const streamDone = new Promise((r) => { - resolveStream = r; - }); - - mockClient.event.subscribe.mockResolvedValue({ - stream: (async function* () { - for (const event of events) { - yield event; - } - resolveStream(); - })(), - }); - - const listener = vi.fn(); - agent.onEvent(listener); - await agent.connect(); - - // ストリームの消費は非同期なので少し待つ - await streamDone; - // microtask を消化 - await new Promise((r) => setTimeout(r, 0)); - - expect(listener).toHaveBeenCalledTimes(2); - expect(listener).toHaveBeenCalledWith(events[0]); - expect(listener).toHaveBeenCalledWith(events[1]); - }); - - it("should remove listener when Disposable is disposed", async () => { - // ストリームを手動制御するためのセットアップ - let emitEvent: ((event: unknown) => void) | undefined; - let endStream: (() => void) | undefined; - - mockClient.event.subscribe.mockResolvedValue({ - stream: (async function* () { - const queue: unknown[] = []; - let resolve: (() => void) | undefined; - let done = false; - - emitEvent = (event: unknown) => { - queue.push(event); - resolve?.(); - }; - endStream = () => { - done = true; - resolve?.(); - }; - - while (!done) { - if (queue.length > 0) { - yield queue.shift()!; - } else { - await new Promise((r) => { - resolve = r; - }); - } - } - })(), - }); - - await agent.connect(); - const listener = vi.fn(); - const disposable = agent.onEvent(listener); - - // イベントを1つ送信 - emitEvent?.({ type: "test-event-1" }); - await new Promise((r) => setTimeout(r, 10)); - expect(listener).toHaveBeenCalledTimes(1); - - // Dispose してからイベントを送信 — 呼ばれないはず - disposable.dispose(); - emitEvent?.({ type: "test-event-2" }); - await new Promise((r) => setTimeout(r, 10)); - expect(listener).toHaveBeenCalledTimes(1); - - endStream?.(); - }); - }); - - describe("resubscribeEvents()", () => { - it("should abort old stream and create new subscription", async () => { - await agent.connect(); - - // 初回の subscribe 呼び出しを確認 - expect(mockClient.event.subscribe).toHaveBeenCalledTimes(1); - - await agent.resubscribeEvents(); - - // 2回目の subscribe 呼び出し(旧ストリームの abort + 新ストリーム開始) - expect(mockClient.event.subscribe).toHaveBeenCalledTimes(2); - }); - }); - - // ============================================================ - // workspaceFolder - // ============================================================ - - describe("workspaceFolder", () => { - it("should be settable and readable", () => { - agent.workspaceFolder = "/my/workspace"; - expect(agent.workspaceFolder).toBe("/my/workspace"); - }); - }); - - // ============================================================ - // getServerUrl - // ============================================================ - - describe("getServerUrl()", () => { - it("should return undefined before connect", () => { - expect(agent.getServerUrl()).toBeUndefined(); - }); - - it("should return server URL after connect", async () => { - await agent.connect(); - expect(agent.getServerUrl()).toBe("http://localhost:12345"); - }); - - it("should return undefined after disconnect", async () => { - await agent.connect(); - agent.disconnect(); - expect(agent.getServerUrl()).toBeUndefined(); - }); - }); - - // ============================================================ - // setModel - // ============================================================ - - describe("setModel()", () => { - beforeEach(async () => { - // Connect so that getPath() (requireClient) works - await agent.connect(); - }); - - it("should read existing config, set model, and write back", async () => { - vi.mocked(fs.readFile).mockResolvedValue('{"theme":"dark"}'); - - await agent.setModel!("anthropic/claude-4"); - - expect(fs.readFile).toHaveBeenCalledWith(expect.stringContaining("opencode.json"), "utf-8"); - expect(fs.mkdir).toHaveBeenCalled(); - // Verify the written JSON contains both the existing key and the new model - const writeCall = vi.mocked(fs.writeFile).mock.calls[0]; - const written = JSON.parse((writeCall[1] as string).trim()); - expect(written).toEqual({ theme: "dark", model: "anthropic/claude-4" }); - }); - - it("should create config from empty object when file does not exist", async () => { - vi.mocked(fs.readFile).mockRejectedValue(new Error("ENOENT")); - - await agent.setModel!("openai/gpt-4"); - - const writeCall = vi.mocked(fs.writeFile).mock.calls[0]; - const written = JSON.parse((writeCall[1] as string).trim()); - expect(written).toEqual({ model: "openai/gpt-4" }); - }); - - it("should throw if agent is not connected", async () => { - agent.disconnect(); - await expect(agent.setModel!("some-model")).rejects.toThrow("OpenCode client is not connected"); - }); - }); -}); diff --git a/extension/__tests__/opencode-client-handle.test.ts b/extension/__tests__/opencode-client-handle.test.ts new file mode 100644 index 0000000..dc88aae --- /dev/null +++ b/extension/__tests__/opencode-client-handle.test.ts @@ -0,0 +1,169 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +function createMockSdkClient() { + return { + event: { + subscribe: vi.fn().mockResolvedValue({ + stream: (async function* () { + // default empty stream + })(), + }), + }, + }; +} + +let mockClient: ReturnType; +const mockServerClose = vi.fn(); + +vi.mock("@opencode-ai/sdk/v2", () => ({ + createOpencodeServer: vi.fn().mockImplementation(() => + Promise.resolve({ + url: "http://localhost:12345", + close: mockServerClose, + }), + ), + createOpencodeClient: vi.fn().mockImplementation(() => mockClient), +})); + +import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; +import { OpenCodeClientHandle } from "../opencode-client-handle"; + +describe("OpenCodeClientHandle", () => { + let handle: OpenCodeClientHandle; + + beforeEach(() => { + mockClient = createMockSdkClient(); + vi.mocked(createOpencodeClient).mockReturnValue(mockClient as never); + handle = new OpenCodeClientHandle(); + }); + + afterEach(() => { + handle.disconnect(); + vi.clearAllMocks(); + }); + + describe("connect()", () => { + it("creates an OpenCode server on a free port and creates an SDK client", async () => { + await handle.connect(); + + expect(createOpencodeServer).toHaveBeenCalledWith({ port: 0 }); + expect(createOpencodeClient).toHaveBeenCalledWith({ baseUrl: "http://localhost:12345" }); + expect(handle.getClient()).toBe(mockClient); + expect(handle.getServerUrl()).toBe("http://localhost:12345"); + }); + + it("subscribes to SDK events after connecting", async () => { + await handle.connect(); + + expect(mockClient.event.subscribe).toHaveBeenCalled(); + }); + }); + + describe("disconnect()", () => { + it("closes the server and clears client state", async () => { + await handle.connect(); + + handle.disconnect(); + + expect(mockServerClose).toHaveBeenCalled(); + expect(handle.getServerUrl()).toBeUndefined(); + expect(() => handle.getClient()).toThrow("OpenCode client is not connected. Call connect() first."); + }); + + it("is idempotent", () => { + expect(() => handle.disconnect()).not.toThrow(); + }); + }); + + describe("events", () => { + it("delivers SSE events to listeners", async () => { + const events = [ + { type: "session.updated", properties: { id: "sess-1" } }, + { type: "message.created", properties: { id: "msg-1" } }, + ]; + let resolveStream!: () => void; + const streamDone = new Promise((resolve) => { + resolveStream = resolve; + }); + + mockClient.event.subscribe.mockResolvedValue({ + stream: (async function* () { + for (const event of events) { + yield event; + } + resolveStream(); + })(), + }); + + const listener = vi.fn(); + handle.onEvent(listener); + await handle.connect(); + await streamDone; + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(listener).toHaveBeenCalledTimes(2); + expect(listener).toHaveBeenCalledWith(events[0]); + expect(listener).toHaveBeenCalledWith(events[1]); + }); + + it("removes listeners when their disposable is disposed", async () => { + let emitEvent: ((event: unknown) => void) | undefined; + let endStream: (() => void) | undefined; + + mockClient.event.subscribe.mockResolvedValue({ + stream: (async function* () { + const queue: unknown[] = []; + let resolve: (() => void) | undefined; + let done = false; + + emitEvent = (event: unknown) => { + queue.push(event); + resolve?.(); + }; + endStream = () => { + done = true; + resolve?.(); + }; + + while (!done) { + if (queue.length > 0) { + const next = queue.shift(); + if (next !== undefined) { + yield next; + } + } else { + await new Promise((r) => { + resolve = r; + }); + } + } + })(), + }); + + await handle.connect(); + const listener = vi.fn(); + const disposable = handle.onEvent(listener); + + emitEvent?.({ type: "test-event-1" }); + await new Promise((resolve) => setTimeout(resolve, 10)); + expect(listener).toHaveBeenCalledTimes(1); + + disposable.dispose(); + emitEvent?.({ type: "test-event-2" }); + await new Promise((resolve) => setTimeout(resolve, 10)); + expect(listener).toHaveBeenCalledTimes(1); + + endStream?.(); + }); + + it("resubscribes by aborting the previous stream and creating a new subscription", async () => { + await handle.connect(); + + expect(mockClient.event.subscribe).toHaveBeenCalledTimes(1); + + await handle.resubscribeEvents(); + + expect(mockClient.event.subscribe).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/extension/chat-view-provider.ts b/extension/chat-view-provider.ts index 0122079..a42c7da 100644 --- a/extension/chat-view-provider.ts +++ b/extension/chat-view-provider.ts @@ -1,9 +1,23 @@ import * as fs from "node:fs/promises"; import * as path from "node:path"; -import type { ChatSession, FileAttachment, HostToUIMessage, UIToHostMessage } from "@shared"; +import type { + AgentInfo, + AllProvidersData, + AppPaths, + ChatMessageWithParts, + ChatSession, + FileAttachment, + FileDiff, + HostToUIMessage, + ProviderInfo, + SendMessageOptions, + SkillInfo, + TodoItem, + UIToHostMessage, +} from "@shared"; import * as vscode from "vscode"; import type { DiffReviewManager } from "./diff-review-manager"; -import type { OpenCodeAgent } from "./opencode-agent"; +import type { OpenCodeClientHandle } from "./opencode-client-handle"; import type { VscodePlatformServices } from "./vscode-platform-services"; export class ChatViewProvider implements vscode.WebviewViewProvider { @@ -16,7 +30,8 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { constructor( private readonly extensionUri: vscode.Uri, - private readonly agent: OpenCodeAgent, + private readonly openCodeClientHandle: OpenCodeClientHandle, + private readonly workspaceFolder: string, private readonly platformServices: VscodePlatformServices, private readonly diffReviewManager: DiffReviewManager, private readonly difitAvailable: boolean, @@ -39,7 +54,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { webviewView.webview.onDidReceiveMessage((message: UIToHostMessage) => this.handleWebviewMessage(message)); // SSE イベントを Webview に転送する - this.agent.onEvent((event) => { + this.openCodeClientHandle.onEvent((event) => { this.postMessage({ type: "event", event }); }); @@ -59,23 +74,27 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } private async handleWebviewMessageInner(message: UIToHostMessage): Promise { + const client = this.openCodeClientHandle.getClient(); + switch (message.type) { case "ready": { // Webview の初期化完了時に init メッセージを送信する(locale + toolConfig を統合) - const paths = await this.agent.getPath(); + const paths = (await client.path.get()).data! as unknown as AppPaths; this.postMessage({ type: "init", locale: vscode.env.language, paths, }); // セッション一覧、現在のセッション、プロバイダー一覧を送信する - const sessions = await this.agent.listSessions(); + const sessions = (await client.session.list()).data! as unknown as ChatSession[]; this.postMessage({ type: "sessions", sessions }); this.postMessage({ type: "activeSession", session: this.activeSession }); - const [providersData, allProviders] = await Promise.all([ - this.agent.getProviders(), - this.agent.listAllProviders(), + const [providersResponse, allProvidersResponse] = await Promise.all([ + client.config.providers(), + client.provider.list(), ]); + const providersData = providersResponse.data!; + const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; // config ファイルから model を直接読み取る(config.get API は model を正しく返さない) let configModel: string | undefined; try { @@ -87,7 +106,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } this.postMessage({ type: "providers", - providers: providersData.providers, + providers: providersData.providers as unknown as ProviderInfo[], allProviders, default: providersData.default, configModel, @@ -99,73 +118,83 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "sendMessage": { - await this.agent.sendMessage(message.sessionId, message.text, { + await client.session.promptAsync({ + sessionID: message.sessionId, + parts: this.toPromptParts(message.text, { + model: message.model, + files: message.files, + agent: message.agent, + primaryAgent: message.primaryAgent, + skill: message.skill, + }), model: message.model, - files: message.files, - agent: message.agent, - primaryAgent: message.primaryAgent, - skill: message.skill, + agent: message.primaryAgent, }); break; } case "createSession": { - const session = await this.agent.createSession(message.title); + const session = (await client.session.create({ title: message.title })).data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const sessions = await this.agent.listSessions(); + const sessions = (await client.session.list()).data! as unknown as ChatSession[]; this.postMessage({ type: "sessions", sessions }); break; } case "listSessions": { - const sessions = await this.agent.listSessions(); + const sessions = (await client.session.list()).data! as unknown as ChatSession[]; this.postMessage({ type: "sessions", sessions }); break; } case "selectSession": { - const session = await this.agent.getSession(message.sessionId); + const session = (await client.session.get({ sessionID: message.sessionId })).data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const messages = await this.agent.getMessages(message.sessionId); + const messages = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); break; } case "deleteSession": { - await this.agent.deleteSession(message.sessionId); + await client.session.delete({ sessionID: message.sessionId }); if (this.activeSession?.id === message.sessionId) { this.activeSession = null; this.postMessage({ type: "activeSession", session: null }); } - const sessions = await this.agent.listSessions(); + const sessions = (await client.session.list()).data! as unknown as ChatSession[]; this.postMessage({ type: "sessions", sessions }); break; } case "getMessages": { - const messages = await this.agent.getMessages(message.sessionId); + const messages = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); break; } case "replyPermission": { - await this.agent.replyPermission(message.sessionId, message.permissionId, message.response); + await client.permission.reply({ requestID: message.permissionId, reply: message.response }); break; } case "replyQuestion": { - await this.agent.replyQuestion(message.requestId, message.answers); + await client.question.reply({ requestID: message.requestId, answers: message.answers }); break; } case "rejectQuestion": { - await this.agent.rejectQuestion(message.requestId); + await client.question.reject({ requestID: message.requestId }); break; } case "abort": { - await this.agent.abortSession(message.sessionId); + await client.session.abort({ sessionID: message.sessionId }); break; } case "getProviders": { - const [providersData, allProviders, paths] = await Promise.all([ - this.agent.getProviders(), - this.agent.listAllProviders(), - this.agent.getPath(), + const [providersResponse, allProvidersResponse, pathsResponse] = await Promise.all([ + client.config.providers(), + client.provider.list(), + client.path.get(), ]); + const providersData = providersResponse.data!; + const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; + const paths = pathsResponse.data! as unknown as AppPaths; let configModel: string | undefined; try { const raw = await fs.readFile(path.join(paths.config, "opencode.json"), "utf-8"); @@ -175,7 +204,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } this.postMessage({ type: "providers", - providers: providersData.providers, + providers: providersData.providers as unknown as ProviderInfo[], allProviders, default: providersData.default, configModel, @@ -194,33 +223,51 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "compressSession": { - await this.agent.summarizeSession(message.sessionId, message.model); + await client.session.summarize({ + sessionID: message.sessionId, + providerID: message.model?.providerID, + modelID: message.model?.modelID, + }); break; } case "revertToMessage": { - const session = await this.agent.revertSession(message.sessionId, message.messageId); + const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) + .data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const messages = await this.agent.getMessages(message.sessionId); + const messages = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); break; } case "editAndResend": { // 1. 指定メッセージまで巻き戻す(そのメッセージ以降を削除) - const session = await this.agent.revertSession(message.sessionId, message.messageId); + const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) + .data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const msgs = await this.agent.getMessages(message.sessionId); + const msgs = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages: msgs }); // 2. 編集後のテキストを送信 - await this.agent.sendMessage(message.sessionId, message.text, { + await client.session.promptAsync({ + sessionID: message.sessionId, + parts: this.toPromptParts(message.text, { + model: message.model, + files: message.files, + }), model: message.model, - files: message.files, + agent: undefined, }); break; } case "executeShell": { - await this.agent.executeShell(message.sessionId, message.command, message.model); + await client.session.shell({ + sessionID: message.sessionId, + agent: "default", + command: message.command, + model: message.model, + }); break; } case "openConfigFile": { @@ -228,53 +275,56 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "openTerminal": { - const serverUrl = this.agent.getServerUrl(); + const serverUrl = this.openCodeClientHandle.getServerUrl(); if (!serverUrl) break; await this.platformServices.openTerminal(serverUrl, this.activeSession?.id); break; } case "setModel": { - // Delegate model persistence to the agent (OpenCode-specific config file workaround) - await this.agent.setModel!(message.model); + await this.setConfiguredModel(message.model); this.postMessage({ type: "modelUpdated", model: message.model, default: {} }); break; } case "forkSession": { // Fork で新しいセッションを作成し、アクティブセッションを切り替える - const forkedSession = await this.agent.forkSession(message.sessionId, message.messageId); + const forkedSession = (await client.session.fork({ + sessionID: message.sessionId, + messageID: message.messageId, + })).data! as unknown as ChatSession; this.activeSession = forkedSession; this.postMessage({ type: "activeSession", session: forkedSession }); - const forkedSessions = await this.agent.listSessions(); + const forkedSessions = (await client.session.list()).data! as unknown as ChatSession[]; this.postMessage({ type: "sessions", sessions: forkedSessions }); break; } case "getSessionDiff": { - const diffs = await this.agent.getSessionDiff(message.sessionId); + const diffs = (await client.session.diff({ sessionID: message.sessionId })).data! as unknown as FileDiff[]; this.postMessage({ type: "sessionDiff", sessionId: message.sessionId, diffs }); break; } case "getSessionTodos": { - const todos = await this.agent.getSessionTodos(message.sessionId); + const todos = (await client.session.todo({ sessionID: message.sessionId })).data! as unknown as TodoItem[]; this.postMessage({ type: "sessionTodos", sessionId: message.sessionId, todos }); break; } case "getChildSessions": { - const children = await this.agent.getChildSessions(message.sessionId); + const children = (await client.session.children({ sessionID: message.sessionId })) + .data! as unknown as ChatSession[]; this.postMessage({ type: "childSessions", sessionId: message.sessionId, children }); break; } case "getAgents": { - const agents = await this.agent.getAgents(); + const agents = (await client.app.agents()).data! as unknown as AgentInfo[]; this.postMessage({ type: "agents", agents }); break; } case "getSkills": { - const skills = await this.agent.getSkills(); + const skills = (await client.app.skills()).data! as unknown as SkillInfo[]; this.postMessage({ type: "skills", skills }); break; } case "shareSession": { - const session = await this.agent.shareSession(message.sessionId); + const session = (await client.session.share({ sessionID: message.sessionId })).data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); // 共有 URL をクリップボードにコピーする @@ -284,7 +334,8 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "unshareSession": { - const session = await this.agent.unshareSession(message.sessionId); + const session = (await client.session.unshare({ sessionID: message.sessionId })) + .data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); break; @@ -294,18 +345,21 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "undoSession": { - const session = await this.agent.revertSession(message.sessionId, message.messageId); + const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) + .data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const messages = await this.agent.getMessages(message.sessionId); + const messages = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); break; } case "redoSession": { - const session = await this.agent.unrevertSession(message.sessionId); + const session = (await client.session.unrevert({ sessionID: message.sessionId })).data! as unknown as ChatSession; this.activeSession = session; this.postMessage({ type: "activeSession", session }); - const messages = await this.agent.getMessages(message.sessionId); + const messages = (await client.session.messages({ sessionID: message.sessionId })) + .data! as unknown as ChatMessageWithParts[]; this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); break; } @@ -322,7 +376,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } try { - const diffs = await this.agent.getSessionDiff(this.activeSession.id); + const diffs = (await client.session.diff({ sessionID: this.activeSession.id })).data! as unknown as FileDiff[]; if (diffs.length === 0) { break; } @@ -343,6 +397,63 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } } + private toPromptParts( + text: string, + options?: SendMessageOptions, + ): Array< + | { type: "text"; text: string; synthetic?: boolean } + | { type: "file"; mime: string; url: string; filename: string } + | { type: "agent"; name: string } + > { + const parts: Array< + | { type: "text"; text: string; synthetic?: boolean } + | { type: "file"; mime: string; url: string; filename: string } + | { type: "agent"; name: string } + > = []; + + if (options?.skill) { + parts.push({ type: "text", text: `/${options.skill}`, synthetic: true }); + } + + parts.push({ type: "text", text }); + + if (options?.files) { + for (const file of options.files) { + const absPath = path.isAbsolute(file.filePath) + ? file.filePath + : path.resolve(this.workspaceFolder, file.filePath); + parts.push({ + type: "file", + mime: "text/plain", + url: `file://${absPath}`, + filename: file.fileName, + }); + } + } + + if (options?.agent) { + parts.push({ type: "agent", name: options.agent }); + } + + return parts; + } + + private async setConfiguredModel(model: string): Promise { + const client = this.openCodeClientHandle.getClient(); + const paths = (await client.path.get()).data! as unknown as AppPaths; + const configFilePath = path.join(paths.config, "opencode.json"); + let configJson: Record = {}; + try { + const raw = await fs.readFile(configFilePath, "utf-8"); + configJson = JSON.parse(raw); + } catch { + // File may not exist yet. + } + configJson.model = model; + await fs.mkdir(path.dirname(configFilePath), { recursive: true }); + await fs.writeFile(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); + } + /** アクティブなテキストエディタから FileAttachment を生成する。エディタがない場合は null を返す。 */ private getActiveEditorFile(editor: vscode.TextEditor | undefined): FileAttachment | null { if (!editor) return null; diff --git a/extension/extension.ts b/extension/extension.ts index d6da7ce..5760b04 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -2,13 +2,13 @@ import { execFile } from "node:child_process"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; import { DiffReviewManager } from "./diff-review-manager"; -import { OpenCodeAgent } from "./opencode-agent"; +import { OpenCodeClientHandle } from "./opencode-client-handle"; import { VscodePlatformServices } from "./vscode-platform-services"; -const agent = new OpenCodeAgent(); +const openCodeClientHandle = new OpenCodeClientHandle(); // Extension Host プロセスが強制終了された場合でもサーバーを停止する -process.on("exit", () => agent.disconnect()); +process.on("exit", () => openCodeClientHandle.disconnect()); export async function activate(context: vscode.ExtensionContext) { const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; @@ -22,8 +22,7 @@ export async function activate(context: vscode.ExtensionContext) { const originalCwd = process.cwd(); process.chdir(workspaceFolder); try { - agent.workspaceFolder = workspaceFolder; - await agent.connect(); + await openCodeClientHandle.connect(); } catch (error) { const isNotFound = error instanceof Error && @@ -50,7 +49,8 @@ export async function activate(context: vscode.ExtensionContext) { const diffReviewManager = new DiffReviewManager(); const chatViewProvider = new ChatViewProvider( context.extensionUri, - agent, + openCodeClientHandle, + workspaceFolder, platformServices, diffReviewManager, difitAvailable, @@ -70,11 +70,11 @@ export async function activate(context: vscode.ExtensionContext) { vscode.workspace.registerTextDocumentContentProvider("opencode-diff-after", diffContentProvider), ); - context.subscriptions.push(new vscode.Disposable(() => agent.disconnect())); + context.subscriptions.push(new vscode.Disposable(() => openCodeClientHandle.disconnect())); } export function deactivate() { - agent.disconnect(); + openCodeClientHandle.disconnect(); } /** PATH 上に difit コマンドが存在するかチェックする */ diff --git a/extension/mappers.ts b/extension/mappers.ts deleted file mode 100644 index d896cfc..0000000 --- a/extension/mappers.ts +++ /dev/null @@ -1,197 +0,0 @@ -/** - * ./opencode-agent - SDK→Domain Type Mappers - * - * Converts types from @opencode-ai/sdk to @shared domain types. - * Each mapper is a pure function with no side effects. - */ - -import type { - Agent, - Config, - Event, - Message, - Part, - Provider, - McpStatus as SdkMcpStatus, - Path as SdkPath, - Session, - SnapshotFileDiff, - Todo, -} from "@opencode-ai/sdk/v2"; - -import type { - AgentEvent, - AgentInfo, - AllProvidersData, - AppConfig, - AppPaths, - ChatMessage, - ChatMessageWithParts, - ChatSession, - FileDiff, - McpStatus, - MessagePart, - ProviderInfo, - SkillInfo, - TodoItem, - ToolListItem, -} from "@shared"; - -// ============================================================ -// Session -// ============================================================ - -export function mapSession(session: Session): ChatSession { - // SDK Session type is structurally compatible — pass through - return session as unknown as ChatSession; -} - -export function mapSessions(sessions: Session[]): ChatSession[] { - return sessions.map(mapSession); -} - -// ============================================================ -// Message + Parts -// ============================================================ - -export function mapMessage(message: Message): ChatMessage { - return message as unknown as ChatMessage; -} - -export function mapPart(part: Part): MessagePart { - return part as unknown as MessagePart; -} - -export function mapMessageWithParts(data: { info: Message; parts: Part[] }): ChatMessageWithParts { - return { - info: mapMessage(data.info), - parts: data.parts.map(mapPart), - }; -} - -export function mapMessagesWithParts(data: Array<{ info: Message; parts: Part[] }>): ChatMessageWithParts[] { - return data.map(mapMessageWithParts); -} - -// ============================================================ -// Event -// ============================================================ - -export function mapEvent(event: Event): AgentEvent { - // SDK Event is a discriminated union structurally compatible with AgentEvent - return event as unknown as AgentEvent; -} - -// ============================================================ -// Provider -// ============================================================ - -export function mapProvider(provider: Provider): ProviderInfo { - return provider as unknown as ProviderInfo; -} - -export function mapProviders(providers: Provider[]): ProviderInfo[] { - return providers.map(mapProvider); -} - -// ============================================================ -// FileDiff -// ============================================================ - -export function mapFileDiff(diff: SnapshotFileDiff): FileDiff { - return { - file: diff.file, - patch: diff.patch, - additions: diff.additions, - deletions: diff.deletions, - status: diff.status, - }; -} - -export function mapFileDiffs(diffs: SnapshotFileDiff[]): FileDiff[] { - return diffs.map(mapFileDiff); -} - -// ============================================================ -// Todo -// ============================================================ - -export function mapTodo(todo: Todo): TodoItem { - return { - content: todo.content, - status: todo.status, - priority: todo.priority, - }; -} - -export function mapTodos(todos: Todo[]): TodoItem[] { - return todos.map(mapTodo); -} - -// ============================================================ -// Agent -// ============================================================ - -export function mapAgent(agent: Agent): AgentInfo { - return agent as unknown as AgentInfo; -} - -export function mapAgents(agents: Agent[]): AgentInfo[] { - return agents.map(mapAgent); -} - -export function mapSkills(skills: Array<{ name: string; description: string; location: string }>): SkillInfo[] { - return skills.map((skill) => ({ - name: skill.name, - description: skill.description, - location: skill.location, - })); -} - -// ============================================================ -// Config -// ============================================================ - -export function mapConfig(config: Config): AppConfig { - return config as unknown as AppConfig; -} - -// ============================================================ -// Path -// ============================================================ - -export function mapPath(sdkPath: SdkPath): AppPaths { - return sdkPath as unknown as AppPaths; -} - -// ============================================================ -// MCP Status -// ============================================================ - -export function mapMcpStatus(status: Record): McpStatus { - return status as unknown as McpStatus; -} - -// ============================================================ -// Tool IDs -// ============================================================ - -/** - * SDK's tool.ids() returns string[], while the webview consumes ToolListItem[]. - * Wrap each string ID into a ToolListItem. - */ -export function mapToolIds(ids: string[]): ToolListItem[] { - return ids.map((id) => ({ id })); -} - -// ============================================================ -// AllProvidersData -// ============================================================ - -export function mapAllProvidersData(data: { - all: Array; - default: Record; - connected: string[]; -}): AllProvidersData { - return data as unknown as AllProvidersData; -} diff --git a/extension/opencode-agent.ts b/extension/opencode-agent.ts deleted file mode 100644 index c9f78bd..0000000 --- a/extension/opencode-agent.ts +++ /dev/null @@ -1,441 +0,0 @@ -/** - * OpenCode SDK integration used by the VS Code extension host. - */ - -import * as fs from "node:fs/promises"; -import * as path from "node:path"; -import { createOpencodeClient, createOpencodeServer, type Event, type OpencodeClient } from "@opencode-ai/sdk/v2"; -import type { - AgentEvent, - AgentInfo, - AllProvidersData, - AppConfig, - AppPaths, - ChatMessageWithParts, - ChatSession, - Disposable, - FileDiff, - McpStatus, - ModelRef, - PermissionResponse, - ProviderInfo, - QuestionAnswer, - SendMessageOptions, - SkillInfo, - TodoItem, - ToolListItem, -} from "@shared"; -import { - mapAgents, - mapAllProvidersData, - mapConfig, - mapEvent, - mapFileDiffs, - mapMcpStatus, - mapMessagesWithParts, - mapPath, - mapProviders, - mapSession, - mapSessions, - mapSkills, - mapTodos, - mapToolIds, -} from "./mappers"; - -type EventHandler = (event: AgentEvent) => void; - -export class OpenCodeAgent { - private client: OpencodeClient | undefined; - private server: { url: string; close(): void } | undefined; - private sseAbortController: AbortController | undefined; - private listeners: Set = new Set(); - public workspaceFolder: string | undefined; - - // --- Lifecycle --- - - async connect(): Promise { - // Port 0: let OS assign a free port to avoid conflicts - const server = await createOpencodeServer({ port: 0 }); - this.server = server; - this.client = createOpencodeClient({ - baseUrl: server.url, - }); - this.subscribeToEvents(); - } - - disconnect(): void { - this.sseAbortController?.abort(); - this.sseAbortController = undefined; - this.server?.close(); - this.server = undefined; - this.client = undefined; - this.listeners.clear(); - } - - // --- Event subscription --- - - onEvent(handler: (event: AgentEvent) => void): Disposable { - this.listeners.add(handler); - return { - dispose: () => { - this.listeners.delete(handler); - }, - }; - } - - /** Resubscribe to SSE stream (e.g. after config change) */ - async resubscribeEvents(): Promise { - await this.subscribeToEvents(); - } - - private async subscribeToEvents(): Promise { - const client = this.requireClient(); - // Abort existing stream before resubscribing - this.sseAbortController?.abort(); - this.sseAbortController = new AbortController(); - const result = await client.event.subscribe(undefined, { - signal: this.sseAbortController.signal, - }); - // Read SSE stream and dispatch to listeners - (async () => { - try { - for await (const event of result.stream) { - const mapped = mapEvent(event as Event); - for (const listener of this.listeners) { - listener(mapped); - } - } - } catch (error) { - // AbortError is normal stream termination - if (error instanceof DOMException && error.name === "AbortError") { - return; - } - throw error; - } - })(); - } - - // --- Sessions (common) --- - - async listSessions(): Promise { - const client = this.requireClient(); - const response = await client.session.list(); - return mapSessions(response.data!); - } - - async createSession(title?: string): Promise { - const client = this.requireClient(); - const response = await client.session.create({ - title, - }); - return mapSession(response.data!); - } - - async getSession(id: string): Promise { - const client = this.requireClient(); - const response = await client.session.get({ - sessionID: id, - }); - return mapSession(response.data!); - } - - // --- Sessions --- - - async deleteSession(id: string): Promise { - const client = this.requireClient(); - await client.session.delete({ - sessionID: id, - }); - } - - async forkSession(sessionId: string, messageId?: string): Promise { - const client = this.requireClient(); - const response = await client.session.fork({ - sessionID: sessionId, - messageID: messageId, - }); - return mapSession(response.data!); - } - - async revertSession(sessionId: string, messageId: string): Promise { - const client = this.requireClient(); - const response = await client.session.revert({ - sessionID: sessionId, - messageID: messageId, - }); - return mapSession(response.data!); - } - - async unrevertSession(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.unrevert({ - sessionID: sessionId, - }); - return mapSession(response.data!); - } - - async summarizeSession(sessionId: string, model?: ModelRef): Promise { - const client = this.requireClient(); - await client.session.summarize({ - sessionID: sessionId, - providerID: model?.providerID, - modelID: model?.modelID, - }); - } - - async shareSession(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.share({ - sessionID: sessionId, - }); - return mapSession(response.data!); - } - - async unshareSession(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.unshare({ - sessionID: sessionId, - }); - return mapSession(response.data!); - } - - // --- Messages --- - - async getMessages(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.messages({ - sessionID: sessionId, - }); - return mapMessagesWithParts(response.data!); - } - - async sendMessage(sessionId: string, text: string, options?: SendMessageOptions): Promise { - const client = this.requireClient(); - const parts: Array< - | { type: "text"; text: string; synthetic?: boolean } - | { type: "file"; mime: string; url: string; filename: string } - | { type: "agent"; name: string } - > = []; - - if (options?.skill) { - parts.push({ type: "text", text: `/${options.skill}`, synthetic: true }); - } - - parts.push({ type: "text", text }); - - if (options?.files) { - for (const file of options.files) { - // filePath is workspace-relative; resolve to absolute via cwd - const absPath = path.isAbsolute(file.filePath) - ? file.filePath - : path.resolve(this.workspaceFolder ?? ".", file.filePath); - parts.push({ - type: "file", - mime: "text/plain", - url: `file://${absPath}`, - filename: file.fileName, - }); - } - } - - // @agent mention triggers sub-agent invocation via AgentPartInput - if (options?.agent) { - parts.push({ type: "agent", name: options.agent }); - } - - await client.session.promptAsync({ - sessionID: sessionId, - parts, - model: options?.model, - agent: options?.primaryAgent, - }); - } - - async abortSession(sessionId: string): Promise { - const client = this.requireClient(); - await client.session.abort({ - sessionID: sessionId, - }); - } - - // --- Shell --- - - async executeShell(sessionId: string, command: string, model?: ModelRef): Promise { - const client = this.requireClient(); - await client.session.shell({ - sessionID: sessionId, - agent: "default", - command, - model, - }); - } - - // --- Providers & models --- - - async getProviders(): Promise<{ - providers: ProviderInfo[]; - default: Record; - }> { - const client = this.requireClient(); - const response = await client.config.providers(); - const data = response.data!; - return { - providers: mapProviders(data.providers), - default: data.default, - }; - } - - async listAllProviders(): Promise { - const client = this.requireClient(); - const response = await client.provider.list(); - return mapAllProvidersData(response.data!); - } - - // --- Agent list --- - - async getAgents(): Promise { - const client = this.requireClient(); - const response = await client.app.agents(); - return mapAgents(response.data!); - } - - async getSkills(): Promise { - const client = this.requireClient(); - const response = await client.app.skills(); - return mapSkills(response.data!); - } - - async getChildSessions(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.children({ - sessionID: sessionId, - }); - return mapSessions(response.data!); - } - - // --- Permissions --- - - async replyPermission(sessionId: string, permissionId: string, response: PermissionResponse): Promise { - const client = this.requireClient(); - await client.permission.reply({ - requestID: permissionId, - reply: response as "once" | "always" | "reject", - }); - } - - // --- Questions --- - - async replyQuestion(requestId: string, answers: QuestionAnswer[]): Promise { - const client = this.requireClient(); - await client.question.reply({ - requestID: requestId, - answers, - }); - } - - async rejectQuestion(requestId: string): Promise { - const client = this.requireClient(); - await client.question.reject({ - requestID: requestId, - }); - } - - // --- Session metadata --- - - async getSessionDiff(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.diff({ - sessionID: sessionId, - }); - return mapFileDiffs(response.data!); - } - - async getSessionTodos(sessionId: string): Promise { - const client = this.requireClient(); - const response = await client.session.todo({ - sessionID: sessionId, - }); - return mapTodos(response.data!); - } - - // --- Config --- - - async getConfig(): Promise { - const client = this.requireClient(); - const response = await client.config.get(); - return mapConfig(response.data!); - } - - async updateConfig(config: Partial): Promise { - const client = this.requireClient(); - await client.config.update({ config: config as Record }); - } - - async getPath(): Promise { - const client = this.requireClient(); - const response = await client.path.get(); - return mapPath(response.data!); - } - - // --- MCP --- - - async getMcpStatus(): Promise { - const client = this.requireClient(); - const response = await client.mcp.status(); - return mapMcpStatus(response.data!); - } - - async connectMcp(server: string): Promise { - const client = this.requireClient(); - await client.mcp.connect({ name: server }); - } - - async disconnectMcp(server: string): Promise { - const client = this.requireClient(); - await client.mcp.disconnect({ name: server }); - } - - // --- Tools --- - - async getToolIds(): Promise { - const client = this.requireClient(); - const response = await client.tool.ids(); - return mapToolIds(response.data!); - } - - // --- Server URL --- - - getServerUrl(): string | undefined { - return this.server?.url; - } - - // --- Model management (setModel) --- - - /** - * setModel is an OpenCode-specific workaround: the config.update API doesn't - * persist model changes, so we edit the opencode.json config file directly. - */ - async setModel(model: string): Promise { - const paths = await this.getPath(); - const configFilePath = path.join(paths.config, "opencode.json"); - let configJson: Record = {}; - try { - const raw = await fs.readFile(configFilePath, "utf-8"); - configJson = JSON.parse(raw); - } catch { - // File may not exist yet — start from empty object - } - configJson.model = model; - await fs.mkdir(path.dirname(configFilePath), { recursive: true }); - await fs.writeFile(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); - } - - // --- Private --- - - private requireClient(): OpencodeClient { - if (!this.client) { - throw new Error("OpenCode client is not connected. Call connect() first."); - } - return this.client; - } -} diff --git a/extension/opencode-client-handle.ts b/extension/opencode-client-handle.ts new file mode 100644 index 0000000..b17e4be --- /dev/null +++ b/extension/opencode-client-handle.ts @@ -0,0 +1,75 @@ +import { createOpencodeClient, createOpencodeServer, type OpencodeClient } from "@opencode-ai/sdk/v2"; +import type { AgentEvent, Disposable } from "@shared"; + +type EventHandler = (event: AgentEvent) => void; + +export class OpenCodeClientHandle { + private client: OpencodeClient | undefined; + private server: { url: string; close(): void } | undefined; + private sseAbortController: AbortController | undefined; + private listeners: Set = new Set(); + + async connect(): Promise { + const server = await createOpencodeServer({ port: 0 }); + this.server = server; + this.client = createOpencodeClient({ baseUrl: server.url }); + this.subscribeToEvents(); + } + + disconnect(): void { + this.sseAbortController?.abort(); + this.sseAbortController = undefined; + this.server?.close(); + this.server = undefined; + this.client = undefined; + this.listeners.clear(); + } + + getClient(): OpencodeClient { + if (!this.client) { + throw new Error("OpenCode client is not connected. Call connect() first."); + } + return this.client; + } + + getServerUrl(): string | undefined { + return this.server?.url; + } + + onEvent(handler: EventHandler): Disposable { + this.listeners.add(handler); + return { + dispose: () => { + this.listeners.delete(handler); + }, + }; + } + + async resubscribeEvents(): Promise { + await this.subscribeToEvents(); + } + + private async subscribeToEvents(): Promise { + const client = this.getClient(); + this.sseAbortController?.abort(); + this.sseAbortController = new AbortController(); + const result = await client.event.subscribe(undefined, { + signal: this.sseAbortController.signal, + }); + + (async () => { + try { + for await (const event of result.stream) { + for (const listener of this.listeners) { + listener(event as unknown as AgentEvent); + } + } + } catch (error) { + if (error instanceof DOMException && error.name === "AbortError") { + return; + } + throw error; + } + })(); + } +} diff --git a/shared/domain.ts b/shared/domain.ts index 0e5642f..209d390 100644 --- a/shared/domain.ts +++ b/shared/domain.ts @@ -1,10 +1,9 @@ /** * @shared - Domain types * - * Agent/platform-independent types representing the application's domain. - * These types are shaped to match the actual data flowing through the system - * (originally from @opencode-ai/sdk) so that the webview can consume them - * without depending on any specific agent SDK. + * Shared types representing data passed between the extension host and webview. + * These types intentionally follow the OpenCode SDK payloads closely; the + * extension host forwards most SDK data without a separate mapping layer. */ // ============================================================ From a1ee396106c8f429e85e5a8b31417b0bbafc8784 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 19:05:40 +0900 Subject: [PATCH 13/25] =?UTF-8?q?chore:=20.gitignore=20=E3=81=AB=E3=82=A8?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=A7=E3=83=B3=E3=83=88=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index b871206..d7c9a1d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ Thumbs.db # Environment .env .env.* + +# Agents +AGENTS.md +CLAUDE.md \ No newline at end of file From 004c4baace66230d1747f670afefcd435a863ccf Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 19:22:33 +0900 Subject: [PATCH 14/25] =?UTF-8?q?refactor:=20=20TSDoc=20=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/opencode-client-handle.test.ts | 7 ++-- extension/opencode-client-handle.ts | 32 ++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/extension/__tests__/opencode-client-handle.test.ts b/extension/__tests__/opencode-client-handle.test.ts index dc88aae..4373f12 100644 --- a/extension/__tests__/opencode-client-handle.test.ts +++ b/extension/__tests__/opencode-client-handle.test.ts @@ -26,7 +26,7 @@ vi.mock("@opencode-ai/sdk/v2", () => ({ })); import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; -import { OpenCodeClientHandle } from "../opencode-client-handle"; +import { OpenCodeClientHandle, OpenCodeClientNotConnectedError } from "../opencode-client-handle"; describe("OpenCodeClientHandle", () => { let handle: OpenCodeClientHandle; @@ -67,7 +67,10 @@ describe("OpenCodeClientHandle", () => { expect(mockServerClose).toHaveBeenCalled(); expect(handle.getServerUrl()).toBeUndefined(); - expect(() => handle.getClient()).toThrow("OpenCode client is not connected. Call connect() first."); + expect(() => handle.getClient()).toThrow(OpenCodeClientNotConnectedError); + expect(() => handle.getClient()).toThrow( + "OpenCode クライアントが接続されていません。先に connect() を呼び出してください。", + ); }); it("is idempotent", () => { diff --git a/extension/opencode-client-handle.ts b/extension/opencode-client-handle.ts index b17e4be..7136a81 100644 --- a/extension/opencode-client-handle.ts +++ b/extension/opencode-client-handle.ts @@ -1,14 +1,29 @@ import { createOpencodeClient, createOpencodeServer, type OpencodeClient } from "@opencode-ai/sdk/v2"; import type { AgentEvent, Disposable } from "@shared"; +/** OpenCode から受信したエージェントイベントを処理するコールバック。 */ type EventHandler = (event: AgentEvent) => void; +/** OpenCode クライアントが未接続の状態で要求された場合のエラー。 */ +export class OpenCodeClientNotConnectedError extends Error { + /** エラー名とメッセージを初期化する。 */ + constructor() { + super("OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"); + this.name = "OpenCodeClientNotConnectedError"; + } +} + +/** + * OpenCode サーバーと SDK クライアントのライフサイクルを管理する。 + * VS Code 拡張側からクライアント取得と SSE イベント購読を提供する。 + */ export class OpenCodeClientHandle { private client: OpencodeClient | undefined; private server: { url: string; close(): void } | undefined; private sseAbortController: AbortController | undefined; private listeners: Set = new Set(); + /** OpenCode サーバーを起動し、SDK クライアントとイベント購読を初期化する。 */ async connect(): Promise { const server = await createOpencodeServer({ port: 0 }); this.server = server; @@ -16,6 +31,7 @@ export class OpenCodeClientHandle { this.subscribeToEvents(); } + /** イベント購読を停止し、サーバーとクライアントを破棄する。 */ disconnect(): void { this.sseAbortController?.abort(); this.sseAbortController = undefined; @@ -25,17 +41,29 @@ export class OpenCodeClientHandle { this.listeners.clear(); } + /** + * 接続済みの OpenCode SDK クライアントを返す。 + * + * @throws {@link OpenCodeClientNotConnectedError} OpenCode クライアントが未接続の場合。 + */ getClient(): OpencodeClient { if (!this.client) { - throw new Error("OpenCode client is not connected. Call connect() first."); + throw new OpenCodeClientNotConnectedError(); } return this.client; } + /** 起動中の OpenCode サーバー URL を返す。未接続の場合は undefined を返す。 */ getServerUrl(): string | undefined { return this.server?.url; } + /** + * OpenCode のエージェントイベントを購読する。 + * + * @param handler 受信イベントを処理するコールバック。 + * @returns 購読解除に使う Disposable。 + */ onEvent(handler: EventHandler): Disposable { this.listeners.add(handler); return { @@ -45,10 +73,12 @@ export class OpenCodeClientHandle { }; } + /** 現在の SSE 購読を張り直す。 */ async resubscribeEvents(): Promise { await this.subscribeToEvents(); } + /** 既存の SSE 購読を停止してから、新しいイベントストリームを購読する。 */ private async subscribeToEvents(): Promise { const client = this.getClient(); this.sseAbortController?.abort(); From 4ddf151f80cc97b77c7482220e5378ec03e466e1 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 20:28:21 +0900 Subject: [PATCH 15/25] =?UTF-8?q?i18n=E3=81=AE=E4=BB=95=E7=B5=84=E3=81=BF?= =?UTF-8?q?=E3=82=92=E6=95=B4=E5=82=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/i18n.test.ts | 38 +++++++++++++++++++++++++++ extension/extension.ts | 18 ++++++++----- extension/i18n/index.ts | 45 ++++++++++++++++++++++++++++++++ extension/i18n/source.ts | 12 +++++++++ l10n/bundle.l10n.es.json | 4 +++ l10n/bundle.l10n.ja.json | 4 +++ l10n/bundle.l10n.json | 4 +++ l10n/bundle.l10n.ko.json | 4 +++ l10n/bundle.l10n.pt-br.json | 4 +++ l10n/bundle.l10n.ru.json | 4 +++ l10n/bundle.l10n.zh-cn.json | 4 +++ l10n/bundle.l10n.zh-tw.json | 4 +++ package.json | 1 + 13 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 extension/__tests__/i18n.test.ts create mode 100644 extension/i18n/index.ts create mode 100644 extension/i18n/source.ts create mode 100644 l10n/bundle.l10n.es.json create mode 100644 l10n/bundle.l10n.ja.json create mode 100644 l10n/bundle.l10n.json create mode 100644 l10n/bundle.l10n.ko.json create mode 100644 l10n/bundle.l10n.pt-br.json create mode 100644 l10n/bundle.l10n.ru.json create mode 100644 l10n/bundle.l10n.zh-cn.json create mode 100644 l10n/bundle.l10n.zh-tw.json diff --git a/extension/__tests__/i18n.test.ts b/extension/__tests__/i18n.test.ts new file mode 100644 index 0000000..b319111 --- /dev/null +++ b/extension/__tests__/i18n.test.ts @@ -0,0 +1,38 @@ +/** + * i18n モジュールのユニットテスト。 + * `t()` が source.ts の英文を引いて vscode.l10n.t に渡し、 + * バンドルヒット時は翻訳、未ヒット時は英文へフォールバックすることを検証する。 + */ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import * as vscode from "vscode"; +import { I18nKeyNotFoundError, type MessageKey, t } from "../i18n"; +import { messages } from "../i18n/source"; + +describe("t", () => { + beforeEach(() => { + // 既定のモック: 入力をそのまま返す(= バンドル未ヒット相当)。 + // l10n.t は複数のオーバーロードを持つため as never 経由で差し替える。 + vi.mocked(vscode.l10n.t).mockImplementation(((s: string) => s) as never); + }); + + it("source.ts に定義された英文を vscode.l10n.t に渡す", () => { + const result = t("warnings.noWorkspace"); + expect(vscode.l10n.t).toHaveBeenCalledWith(messages.warnings.noWorkspace); + expect(result).toBe(messages.warnings.noWorkspace); + }); + + it("vscode.l10n.t が翻訳を返した場合はその翻訳を返す(バンドルヒット)", () => { + vi.mocked(vscode.l10n.t).mockReturnValueOnce("ワークスペースを開いてください。"); + expect(t("warnings.noWorkspace")).toBe("ワークスペースを開いてください。"); + }); + + it("vscode.l10n.t が引数をそのまま返した場合は英文フォールバックになる", () => { + expect(t("warnings.opencodeNotFound")).toBe(messages.warnings.opencodeNotFound); + }); + + it("source.ts に存在しないキーが渡された場合は I18nKeyNotFoundError を投げる", () => { + // 通常は MessageKey 型で弾かれる経路。型キャストでバイパスして検証する。 + expect(() => t("warnings.unknown" as MessageKey)).toThrow(I18nKeyNotFoundError); + expect(() => t("nonexistent.key" as MessageKey)).toThrow(/i18n のソースにキーが存在しません/); + }); +}); diff --git a/extension/extension.ts b/extension/extension.ts index 5760b04..5f71dbb 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -2,6 +2,7 @@ import { execFile } from "node:child_process"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; import { DiffReviewManager } from "./diff-review-manager"; +import { t } from "./i18n"; import { OpenCodeClientHandle } from "./opencode-client-handle"; import { VscodePlatformServices } from "./vscode-platform-services"; @@ -10,10 +11,14 @@ const openCodeClientHandle = new OpenCodeClientHandle(); // Extension Host プロセスが強制終了された場合でもサーバーを停止する process.on("exit", () => openCodeClientHandle.disconnect()); +/** + * VS Code から呼ばれる拡張機能のエントリポイント。 + * 呼び出し契機は `package.json` の `activationEvents` および `contributes` 宣言で定義されている。 + */ export async function activate(context: vscode.ExtensionContext) { const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; if (!workspaceFolder) { - vscode.window.showWarningMessage(vscode.l10n.t("OpenCodeGUI requires an open workspace folder.")); + vscode.window.showWarningMessage(t("warnings.noWorkspace")); return; } @@ -28,11 +33,7 @@ export async function activate(context: vscode.ExtensionContext) { error instanceof Error && (("code" in error && (error as NodeJS.ErrnoException).code === "ENOENT") || error.message.includes("ENOENT")); if (isNotFound) { - vscode.window.showWarningMessage( - vscode.l10n.t( - 'OpenCodeGUI: "opencode" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode', - ), - ); + vscode.window.showWarningMessage(t("warnings.opencodeNotFound")); return; } throw error; @@ -73,6 +74,11 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(new vscode.Disposable(() => openCodeClientHandle.disconnect())); } +/** + * VS Code から呼ばれる拡張機能の終了フック。 + * ウィンドウを閉じる・拡張を無効化する・リロードするタイミングで呼ばれる。 + * `context.subscriptions` 管理外のリソースはここで解放する必要がある。 + */ export function deactivate() { openCodeClientHandle.disconnect(); } diff --git a/extension/i18n/index.ts b/extension/i18n/index.ts new file mode 100644 index 0000000..18710bb --- /dev/null +++ b/extension/i18n/index.ts @@ -0,0 +1,45 @@ +import * as vscode from "vscode"; +import { messages } from "./source"; + +/** + * `messages` の構造から `"warnings.noWorkspace"` のようなドット区切りキー集合を導出する型。 + */ +type Leaves = { + [K in keyof T & string]: T[K] extends string ? `${P}${K}` : Leaves; +}[keyof T & string]; + +export type MessageKey = Leaves; + +/** + * `t()` に渡されたキーが `source.ts` の構造に存在しなかった場合に投げられる例外。 + * 通常は `MessageKey` 型でコンパイル時に弾かれるため、これが投げられた場合は + * 型キャストの誤用などで型の保護が外れたバグとみなせる。 + */ +export class I18nKeyNotFoundError extends Error { + constructor(public readonly key: string) { + super(`i18n のソースにキーが存在しません: ${key}`); + this.name = "I18nKeyNotFoundError"; + } +} + +/** + * Rails I18n 風のキーベース翻訳取得。 + * `source.ts` から英文を引き、それをバンドルキーとして `vscode.l10n.t` に渡す。 + * バンドル未ヒット時は英文がそのまま返るため、フォールバックは自動で機能する。 + */ +export function t(key: MessageKey): string { + return vscode.l10n.t(resolveSource(key)); +} + +function resolveSource(key: string): string { + const value = key.split(".").reduce((current, segment) => { + if (current && typeof current === "object" && segment in current) { + return (current as Record)[segment]; + } + return undefined; + }, messages); + if (typeof value !== "string") { + throw new I18nKeyNotFoundError(key); + } + return value; +} diff --git a/extension/i18n/source.ts b/extension/i18n/source.ts new file mode 100644 index 0000000..bc21b51 --- /dev/null +++ b/extension/i18n/source.ts @@ -0,0 +1,12 @@ +/** + * メッセージの英語ソース。すべての翻訳キーの正本。 + * `bundle.l10n..json` は本ファイルのキー(ドット区切り表記)を JSON のキーとして持つ。 + * 各言語バンドルにキーが無い場合、`t()` はここに定義された英文へフォールバックする。 + */ +export const messages = { + warnings: { + noWorkspace: "OpenCodeGUI requires an open workspace folder.", + opencodeNotFound: + 'OpenCodeGUI: "opencode" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode', + }, +} as const; diff --git a/l10n/bundle.l10n.es.json b/l10n/bundle.l10n.es.json new file mode 100644 index 0000000..d7662b2 --- /dev/null +++ b/l10n/bundle.l10n.es.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requiere una carpeta de espacio de trabajo abierta.", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: no se encontró el comando \"opencode\". Instale OpenCode primero: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json new file mode 100644 index 0000000..52940b5 --- /dev/null +++ b/l10n/bundle.l10n.ja.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI を使用するにはワークスペースフォルダーを開いてください。", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" コマンドが見つかりません。先に OpenCode をインストールしてください: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json new file mode 100644 index 0000000..cf6cc8f --- /dev/null +++ b/l10n/bundle.l10n.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requires an open workspace folder.", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.ko.json b/l10n/bundle.l10n.ko.json new file mode 100644 index 0000000..f1e9d9f --- /dev/null +++ b/l10n/bundle.l10n.ko.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI를 사용하려면 작업 영역 폴더를 여세요.", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" 명령을 찾을 수 없습니다. 먼저 OpenCode를 설치하세요: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.pt-br.json b/l10n/bundle.l10n.pt-br.json new file mode 100644 index 0000000..3b8e51e --- /dev/null +++ b/l10n/bundle.l10n.pt-br.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "O OpenCodeGUI requer uma pasta de espaço de trabalho aberta.", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: comando \"opencode\" não encontrado. Instale o OpenCode primeiro: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.ru.json b/l10n/bundle.l10n.ru.json new file mode 100644 index 0000000..76db34c --- /dev/null +++ b/l10n/bundle.l10n.ru.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "Для работы OpenCodeGUI требуется открытая папка рабочей области.", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: команда \"opencode\" не найдена. Сначала установите OpenCode: https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json new file mode 100644 index 0000000..c6d1a64 --- /dev/null +++ b/l10n/bundle.l10n.zh-cn.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要打开工作区文件夹。", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:未找到 \"opencode\" 命令。请先安装 OpenCode:https://github.com/anomalyco/opencode" +} diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json new file mode 100644 index 0000000..cb4bebd --- /dev/null +++ b/l10n/bundle.l10n.zh-tw.json @@ -0,0 +1,4 @@ +{ + "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要開啟工作區資料夾。", + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:找不到 \"opencode\" 命令。請先安裝 OpenCode:https://github.com/anomalyco/opencode" +} diff --git a/package.json b/package.json index 8d8fc71..95a2315 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ ], "activationEvents": [], "main": "./dist/extension.js", + "l10n": "./l10n", "contributes": { "viewsContainers": { "activitybar": [ From e12095422bb534a29f6f8fc5e2085a076ff4ed85 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 20:42:59 +0900 Subject: [PATCH 16/25] =?UTF-8?q?refactor:=20OpenCodeBinaryNotFoundError?= =?UTF-8?q?=20=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/extension.test.ts | 28 +++++------------ .../__tests__/opencode-client-handle.test.ts | 24 +++++++++++++- extension/errors.ts | 24 ++++++++++++++ extension/extension.ts | 6 ++-- extension/opencode-client-handle.ts | 31 +++++++++++++------ 5 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 extension/errors.ts diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index d13bedc..a56a34b 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -132,35 +132,23 @@ describe("extension", () => { }); // ============================================================ - // activate - ENOENT エラー(opencode コマンドが見つからない) + // activate - opencode バイナリ未検出 // ============================================================ - describe("activate() - ENOENT error", () => { - it("should show warning for ENOENT code", async () => { - const error = new Error("spawn opencode ENOENT") as NodeJS.ErrnoException; - error.code = "ENOENT"; - mockConnect.mockRejectedValueOnce(error); - + describe("activate() - OpenCodeBinaryNotFoundError", () => { + it("OpenCodeBinaryNotFoundError を受けたら警告を表示し webview を登録しない", async () => { + // importExtension() 内で vi.resetModules() が走るため、 + // 同一クラス識別子になるよう importExtension() の後で errors を読み込む。 const extensionModule = await importExtension(); - const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; + const { OpenCodeBinaryNotFoundError } = await import("../errors"); + mockConnect.mockRejectedValueOnce(new OpenCodeBinaryNotFoundError(new Error("spawn opencode ENOENT"))); - await extensionModule.activate(context as never); - - expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("opencode")); - // webview provider が登録されない - expect(vscode.window.registerWebviewViewProvider).not.toHaveBeenCalled(); - }); - - it("should show warning for ENOENT in message", async () => { - const error = new Error("ENOENT: command not found"); - mockConnect.mockRejectedValueOnce(error); - - const extensionModule = await importExtension(); const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; await extensionModule.activate(context as never); expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("opencode")); + expect(vscode.window.registerWebviewViewProvider).not.toHaveBeenCalled(); }); }); diff --git a/extension/__tests__/opencode-client-handle.test.ts b/extension/__tests__/opencode-client-handle.test.ts index 4373f12..bd43563 100644 --- a/extension/__tests__/opencode-client-handle.test.ts +++ b/extension/__tests__/opencode-client-handle.test.ts @@ -26,7 +26,8 @@ vi.mock("@opencode-ai/sdk/v2", () => ({ })); import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; -import { OpenCodeClientHandle, OpenCodeClientNotConnectedError } from "../opencode-client-handle"; +import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError } from "../errors"; +import { OpenCodeClientHandle } from "../opencode-client-handle"; describe("OpenCodeClientHandle", () => { let handle: OpenCodeClientHandle; @@ -57,6 +58,27 @@ describe("OpenCodeClientHandle", () => { expect(mockClient.event.subscribe).toHaveBeenCalled(); }); + + it("createOpencodeServer が ENOENT を投げた場合は OpenCodeBinaryNotFoundError に変換する", async () => { + const enoent = Object.assign(new Error("spawn opencode ENOENT"), { code: "ENOENT" }); + vi.mocked(createOpencodeServer).mockRejectedValueOnce(enoent); + + await expect(handle.connect()).rejects.toBeInstanceOf(OpenCodeBinaryNotFoundError); + }); + + it("code が落ちていても message に ENOENT を含めば OpenCodeBinaryNotFoundError に変換する", async () => { + // SDK 側でラップされて code フィールドが失われるケースを再現する。 + vi.mocked(createOpencodeServer).mockRejectedValueOnce(new Error("Failed to spawn: ENOENT")); + + await expect(handle.connect()).rejects.toBeInstanceOf(OpenCodeBinaryNotFoundError); + }); + + it("ENOENT 以外のエラーはそのまま伝播する", async () => { + const other = new Error("port already in use"); + vi.mocked(createOpencodeServer).mockRejectedValueOnce(other); + + await expect(handle.connect()).rejects.toBe(other); + }); }); describe("disconnect()", () => { diff --git a/extension/errors.ts b/extension/errors.ts new file mode 100644 index 0000000..9c3ed1c --- /dev/null +++ b/extension/errors.ts @@ -0,0 +1,24 @@ +/** + * 拡張機能内で利用するドメイン例外クラスの集約。 + * 複数モジュールから参照されるため、本ファイルに集めてモジュール間の依存を一方向に保つ。 + */ + +/** OpenCode クライアントが未接続の状態で要求された場合のエラー。 */ +export class OpenCodeClientNotConnectedError extends Error { + constructor() { + super("OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"); + this.name = "OpenCodeClientNotConnectedError"; + } +} + +/** + * `opencode` バイナリが PATH 上に見つからず、サーバーを起動できなかった場合のエラー。 + * 子プロセス spawn 時の ENOENT を本クラスに変換することで、 + * 呼び出し側は `instanceof` で「未インストール」を識別できる。 + */ +export class OpenCodeBinaryNotFoundError extends Error { + constructor(public readonly cause: unknown) { + super('"opencode" コマンドが PATH 上に見つかりませんでした。OpenCode をインストールしてください。'); + this.name = "OpenCodeBinaryNotFoundError"; + } +} diff --git a/extension/extension.ts b/extension/extension.ts index 5f71dbb..22c12c0 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -2,6 +2,7 @@ import { execFile } from "node:child_process"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; import { DiffReviewManager } from "./diff-review-manager"; +import { OpenCodeBinaryNotFoundError } from "./errors"; import { t } from "./i18n"; import { OpenCodeClientHandle } from "./opencode-client-handle"; import { VscodePlatformServices } from "./vscode-platform-services"; @@ -29,10 +30,7 @@ export async function activate(context: vscode.ExtensionContext) { try { await openCodeClientHandle.connect(); } catch (error) { - const isNotFound = - error instanceof Error && - (("code" in error && (error as NodeJS.ErrnoException).code === "ENOENT") || error.message.includes("ENOENT")); - if (isNotFound) { + if (error instanceof OpenCodeBinaryNotFoundError) { vscode.window.showWarningMessage(t("warnings.opencodeNotFound")); return; } diff --git a/extension/opencode-client-handle.ts b/extension/opencode-client-handle.ts index 7136a81..d127b5f 100644 --- a/extension/opencode-client-handle.ts +++ b/extension/opencode-client-handle.ts @@ -1,16 +1,17 @@ import { createOpencodeClient, createOpencodeServer, type OpencodeClient } from "@opencode-ai/sdk/v2"; import type { AgentEvent, Disposable } from "@shared"; +import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError } from "./errors"; /** OpenCode から受信したエージェントイベントを処理するコールバック。 */ type EventHandler = (event: AgentEvent) => void; -/** OpenCode クライアントが未接続の状態で要求された場合のエラー。 */ -export class OpenCodeClientNotConnectedError extends Error { - /** エラー名とメッセージを初期化する。 */ - constructor() { - super("OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"); - this.name = "OpenCodeClientNotConnectedError"; - } +/** spawn 失敗が ENOENT(実行ファイル未検出)を示しているか判定する。 */ +function isBinaryNotFoundError(error: unknown): boolean { + if (!(error instanceof Error)) return false; + // Node 標準の NodeJS.ErrnoException は code フィールドを持つ。 + // SDK 側でラップされて code が落ちているケースに備えて message も見る。 + const code = (error as NodeJS.ErrnoException).code; + return code === "ENOENT" || error.message.includes("ENOENT"); } /** @@ -23,9 +24,21 @@ export class OpenCodeClientHandle { private sseAbortController: AbortController | undefined; private listeners: Set = new Set(); - /** OpenCode サーバーを起動し、SDK クライアントとイベント購読を初期化する。 */ + /** + * OpenCode サーバーを起動し、SDK クライアントとイベント購読を初期化する。 + * + * @throws {@link OpenCodeBinaryNotFoundError} `opencode` バイナリが PATH 上に存在しない場合。 + */ async connect(): Promise { - const server = await createOpencodeServer({ port: 0 }); + let server: { url: string; close(): void }; + try { + server = await createOpencodeServer({ port: 0 }); + } catch (error) { + if (isBinaryNotFoundError(error)) { + throw new OpenCodeBinaryNotFoundError(error); + } + throw error; + } this.server = server; this.client = createOpencodeClient({ baseUrl: server.url }); this.subscribeToEvents(); From f6eff3411ae557521bb3bf498f112939f5e6ab85 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 20:51:56 +0900 Subject: [PATCH 17/25] =?UTF-8?q?refactor:=20OpenCodeError=20=E3=82=AF?= =?UTF-8?q?=E3=83=A9=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/opencode-client-handle.test.ts | 26 +++++++++++--- extension/errors.ts | 34 ++++++++++++++++--- extension/opencode-client-handle.ts | 5 +-- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/extension/__tests__/opencode-client-handle.test.ts b/extension/__tests__/opencode-client-handle.test.ts index bd43563..40bcd2e 100644 --- a/extension/__tests__/opencode-client-handle.test.ts +++ b/extension/__tests__/opencode-client-handle.test.ts @@ -26,7 +26,12 @@ vi.mock("@opencode-ai/sdk/v2", () => ({ })); import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; -import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError } from "../errors"; +import { + OpenCodeBinaryNotFoundError, + OpenCodeClientNotConnectedError, + OpenCodeError, + OpenCodeServerStartError, +} from "../errors"; import { OpenCodeClientHandle } from "../opencode-client-handle"; describe("OpenCodeClientHandle", () => { @@ -73,11 +78,22 @@ describe("OpenCodeClientHandle", () => { await expect(handle.connect()).rejects.toBeInstanceOf(OpenCodeBinaryNotFoundError); }); - it("ENOENT 以外のエラーはそのまま伝播する", async () => { - const other = new Error("port already in use"); - vi.mocked(createOpencodeServer).mockRejectedValueOnce(other); + it("ENOENT 以外のエラーは OpenCodeServerStartError でラップされ、cause に元エラーを保持する", async () => { + const original = new Error("port already in use"); + vi.mocked(createOpencodeServer).mockRejectedValueOnce(original); - await expect(handle.connect()).rejects.toBe(other); + const rejection = await handle.connect().catch((e: unknown) => e); + + expect(rejection).toBeInstanceOf(OpenCodeServerStartError); + expect(rejection).toBeInstanceOf(OpenCodeError); + expect((rejection as OpenCodeServerStartError).cause).toBe(original); + }); + + it("OpenCodeBinaryNotFoundError も OpenCodeError として識別できる(基底クラスでまとめて catch 可能)", async () => { + const enoent = Object.assign(new Error("spawn opencode ENOENT"), { code: "ENOENT" }); + vi.mocked(createOpencodeServer).mockRejectedValueOnce(enoent); + + await expect(handle.connect()).rejects.toBeInstanceOf(OpenCodeError); }); }); diff --git a/extension/errors.ts b/extension/errors.ts index 9c3ed1c..40322c8 100644 --- a/extension/errors.ts +++ b/extension/errors.ts @@ -3,8 +3,23 @@ * 複数モジュールから参照されるため、本ファイルに集めてモジュール間の依存を一方向に保つ。 */ +/** + * OpenCode 関連エラーの抽象基底クラス。 + * 直接インスタンス化はできず、必ず具体的な失敗モードを表すサブクラスを継承して使う。 + * 呼び出し側は `instanceof OpenCodeError` で OpenCode 由来の失敗をまとめて受けられる。 + */ +export abstract class OpenCodeError extends Error { + protected constructor( + message: string, + public readonly cause?: unknown, + ) { + super(message); + this.name = "OpenCodeError"; + } +} + /** OpenCode クライアントが未接続の状態で要求された場合のエラー。 */ -export class OpenCodeClientNotConnectedError extends Error { +export class OpenCodeClientNotConnectedError extends OpenCodeError { constructor() { super("OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"); this.name = "OpenCodeClientNotConnectedError"; @@ -16,9 +31,20 @@ export class OpenCodeClientNotConnectedError extends Error { * 子プロセス spawn 時の ENOENT を本クラスに変換することで、 * 呼び出し側は `instanceof` で「未インストール」を識別できる。 */ -export class OpenCodeBinaryNotFoundError extends Error { - constructor(public readonly cause: unknown) { - super('"opencode" コマンドが PATH 上に見つかりませんでした。OpenCode をインストールしてください。'); +export class OpenCodeBinaryNotFoundError extends OpenCodeError { + constructor(cause: unknown) { + super('"opencode" コマンドが PATH 上に見つかりませんでした。OpenCode をインストールしてください。', cause); this.name = "OpenCodeBinaryNotFoundError"; } } + +/** + * OpenCode サーバーの起動に失敗した(ENOENT 以外の原因による)場合のエラー。 + * ポート衝突や SDK 側の予期せぬ失敗など、特定の失敗モードに分類されない起動失敗を表す。 + */ +export class OpenCodeServerStartError extends OpenCodeError { + constructor(cause: unknown) { + super("OpenCode サーバーの起動に失敗しました。", cause); + this.name = "OpenCodeServerStartError"; + } +} diff --git a/extension/opencode-client-handle.ts b/extension/opencode-client-handle.ts index d127b5f..41cb5ed 100644 --- a/extension/opencode-client-handle.ts +++ b/extension/opencode-client-handle.ts @@ -1,6 +1,6 @@ import { createOpencodeClient, createOpencodeServer, type OpencodeClient } from "@opencode-ai/sdk/v2"; import type { AgentEvent, Disposable } from "@shared"; -import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError } from "./errors"; +import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError, OpenCodeServerStartError } from "./errors"; /** OpenCode から受信したエージェントイベントを処理するコールバック。 */ type EventHandler = (event: AgentEvent) => void; @@ -28,6 +28,7 @@ export class OpenCodeClientHandle { * OpenCode サーバーを起動し、SDK クライアントとイベント購読を初期化する。 * * @throws {@link OpenCodeBinaryNotFoundError} `opencode` バイナリが PATH 上に存在しない場合。 + * @throws {@link OpenCodeServerStartError} それ以外の理由でサーバー起動に失敗した場合。 */ async connect(): Promise { let server: { url: string; close(): void }; @@ -37,7 +38,7 @@ export class OpenCodeClientHandle { if (isBinaryNotFoundError(error)) { throw new OpenCodeBinaryNotFoundError(error); } - throw error; + throw new OpenCodeServerStartError(error); } this.server = server; this.client = createOpencodeClient({ baseUrl: server.url }); From fbd6ea6018bf22a37b0ab1177b2029440006025b Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 20:59:45 +0900 Subject: [PATCH 18/25] =?UTF-8?q?refactor:=20OpenCodeError=20=E3=82=AF?= =?UTF-8?q?=E3=83=A9=E3=82=B9=E3=81=AE=E6=94=B9=E5=96=84=E3=81=A8=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=81=AE=E5=BC=B7=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/extension.test.ts | 20 ++++++++++++ extension/__tests__/mocks/vscode.ts | 1 + .../__tests__/opencode-client-handle.test.ts | 14 +++------ extension/errors.ts | 31 ++++++------------- extension/extension.ts | 7 ++++- extension/i18n/source.ts | 4 +++ extension/opencode-client-handle.ts | 6 ++-- l10n/bundle.l10n.es.json | 3 +- l10n/bundle.l10n.ja.json | 3 +- l10n/bundle.l10n.json | 3 +- l10n/bundle.l10n.ko.json | 3 +- l10n/bundle.l10n.pt-br.json | 3 +- l10n/bundle.l10n.ru.json | 3 +- l10n/bundle.l10n.zh-cn.json | 3 +- l10n/bundle.l10n.zh-tw.json | 3 +- 15 files changed, 65 insertions(+), 42 deletions(-) diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index a56a34b..3d625c7 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -150,6 +150,26 @@ describe("extension", () => { expect(vscode.window.showWarningMessage).toHaveBeenCalledWith(expect.stringContaining("opencode")); expect(vscode.window.registerWebviewViewProvider).not.toHaveBeenCalled(); }); + + it("汎用 OpenCodeError を受けたらエラー通知 + ログ出力し webview を登録しない", async () => { + const extensionModule = await importExtension(); + const { OpenCodeError } = await import("../errors"); + const original = new Error("port already in use"); + mockConnect.mockRejectedValueOnce(new OpenCodeError(original)); + + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; + + await extensionModule.activate(context as never); + + expect(vscode.window.showErrorMessage).toHaveBeenCalled(); + // OpenCodeError をそのまま console.error に渡す(cause は error 自身に含まれる)。 + expect(consoleErrorSpy).toHaveBeenCalledWith(expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0]?.[0]).toMatchObject({ cause: original }); + expect(vscode.window.registerWebviewViewProvider).not.toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); + }); }); // ============================================================ diff --git a/extension/__tests__/mocks/vscode.ts b/extension/__tests__/mocks/vscode.ts index 9402ebd..5dd5c30 100644 --- a/extension/__tests__/mocks/vscode.ts +++ b/extension/__tests__/mocks/vscode.ts @@ -22,6 +22,7 @@ export const workspace = { export const window = { registerWebviewViewProvider: vi.fn(() => ({ dispose: vi.fn() })), showWarningMessage: vi.fn(), + showErrorMessage: vi.fn(), showTextDocument: vi.fn().mockResolvedValue(undefined), activeTextEditor: undefined as unknown, onDidChangeActiveTextEditor: vi.fn(() => ({ dispose: vi.fn() })), diff --git a/extension/__tests__/opencode-client-handle.test.ts b/extension/__tests__/opencode-client-handle.test.ts index 40bcd2e..a7f1ebd 100644 --- a/extension/__tests__/opencode-client-handle.test.ts +++ b/extension/__tests__/opencode-client-handle.test.ts @@ -26,12 +26,7 @@ vi.mock("@opencode-ai/sdk/v2", () => ({ })); import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"; -import { - OpenCodeBinaryNotFoundError, - OpenCodeClientNotConnectedError, - OpenCodeError, - OpenCodeServerStartError, -} from "../errors"; +import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError, OpenCodeError } from "../errors"; import { OpenCodeClientHandle } from "../opencode-client-handle"; describe("OpenCodeClientHandle", () => { @@ -78,15 +73,16 @@ describe("OpenCodeClientHandle", () => { await expect(handle.connect()).rejects.toBeInstanceOf(OpenCodeBinaryNotFoundError); }); - it("ENOENT 以外のエラーは OpenCodeServerStartError でラップされ、cause に元エラーを保持する", async () => { + it("ENOENT 以外のエラーは OpenCodeError でラップされ、cause に元エラーを保持する", async () => { const original = new Error("port already in use"); vi.mocked(createOpencodeServer).mockRejectedValueOnce(original); const rejection = await handle.connect().catch((e: unknown) => e); - expect(rejection).toBeInstanceOf(OpenCodeServerStartError); expect(rejection).toBeInstanceOf(OpenCodeError); - expect((rejection as OpenCodeServerStartError).cause).toBe(original); + // ラップ後はサブクラスではなく基底の OpenCodeError として投げられる。 + expect(rejection).not.toBeInstanceOf(OpenCodeBinaryNotFoundError); + expect((rejection as OpenCodeError).cause).toBe(original); }); it("OpenCodeBinaryNotFoundError も OpenCodeError として識別できる(基底クラスでまとめて catch 可能)", async () => { diff --git a/extension/errors.ts b/extension/errors.ts index 40322c8..e0f259a 100644 --- a/extension/errors.ts +++ b/extension/errors.ts @@ -4,16 +4,14 @@ */ /** - * OpenCode 関連エラーの抽象基底クラス。 - * 直接インスタンス化はできず、必ず具体的な失敗モードを表すサブクラスを継承して使う。 + * OpenCode 関連エラーの汎用クラス兼基底クラス。 + * 特定の失敗モードに分類されない OpenCode 由来の失敗を表すと同時に、 + * `OpenCodeBinaryNotFoundError` などのサブクラスの基底としても機能する。 * 呼び出し側は `instanceof OpenCodeError` で OpenCode 由来の失敗をまとめて受けられる。 */ -export abstract class OpenCodeError extends Error { - protected constructor( - message: string, - public readonly cause?: unknown, - ) { - super(message); +export class OpenCodeError extends Error { + constructor(public readonly cause?: unknown) { + super("OpenCode で予期しないエラーが発生しました。"); this.name = "OpenCodeError"; } } @@ -21,7 +19,8 @@ export abstract class OpenCodeError extends Error { /** OpenCode クライアントが未接続の状態で要求された場合のエラー。 */ export class OpenCodeClientNotConnectedError extends OpenCodeError { constructor() { - super("OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"); + super(); + this.message = "OpenCode クライアントが接続されていません。先に connect() を呼び出してください。"; this.name = "OpenCodeClientNotConnectedError"; } } @@ -33,18 +32,8 @@ export class OpenCodeClientNotConnectedError extends OpenCodeError { */ export class OpenCodeBinaryNotFoundError extends OpenCodeError { constructor(cause: unknown) { - super('"opencode" コマンドが PATH 上に見つかりませんでした。OpenCode をインストールしてください。', cause); + super(cause); + this.message = '"opencode" コマンドが PATH 上に見つかりませんでした。OpenCode をインストールしてください。'; this.name = "OpenCodeBinaryNotFoundError"; } } - -/** - * OpenCode サーバーの起動に失敗した(ENOENT 以外の原因による)場合のエラー。 - * ポート衝突や SDK 側の予期せぬ失敗など、特定の失敗モードに分類されない起動失敗を表す。 - */ -export class OpenCodeServerStartError extends OpenCodeError { - constructor(cause: unknown) { - super("OpenCode サーバーの起動に失敗しました。", cause); - this.name = "OpenCodeServerStartError"; - } -} diff --git a/extension/extension.ts b/extension/extension.ts index 22c12c0..21dcc21 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -2,7 +2,7 @@ import { execFile } from "node:child_process"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; import { DiffReviewManager } from "./diff-review-manager"; -import { OpenCodeBinaryNotFoundError } from "./errors"; +import { OpenCodeBinaryNotFoundError, OpenCodeError } from "./errors"; import { t } from "./i18n"; import { OpenCodeClientHandle } from "./opencode-client-handle"; import { VscodePlatformServices } from "./vscode-platform-services"; @@ -34,6 +34,11 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window.showWarningMessage(t("warnings.opencodeNotFound")); return; } + if (error instanceof OpenCodeError) { + console.error(error); + vscode.window.showErrorMessage(t("errors.unexpected")); + return; + } throw error; } finally { process.chdir(originalCwd); diff --git a/extension/i18n/source.ts b/extension/i18n/source.ts index bc21b51..19217f4 100644 --- a/extension/i18n/source.ts +++ b/extension/i18n/source.ts @@ -9,4 +9,8 @@ export const messages = { opencodeNotFound: 'OpenCodeGUI: "opencode" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode', }, + errors: { + unexpected: + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.", + }, } as const; diff --git a/extension/opencode-client-handle.ts b/extension/opencode-client-handle.ts index 41cb5ed..1f8c162 100644 --- a/extension/opencode-client-handle.ts +++ b/extension/opencode-client-handle.ts @@ -1,6 +1,6 @@ import { createOpencodeClient, createOpencodeServer, type OpencodeClient } from "@opencode-ai/sdk/v2"; import type { AgentEvent, Disposable } from "@shared"; -import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError, OpenCodeServerStartError } from "./errors"; +import { OpenCodeBinaryNotFoundError, OpenCodeClientNotConnectedError, OpenCodeError } from "./errors"; /** OpenCode から受信したエージェントイベントを処理するコールバック。 */ type EventHandler = (event: AgentEvent) => void; @@ -28,7 +28,7 @@ export class OpenCodeClientHandle { * OpenCode サーバーを起動し、SDK クライアントとイベント購読を初期化する。 * * @throws {@link OpenCodeBinaryNotFoundError} `opencode` バイナリが PATH 上に存在しない場合。 - * @throws {@link OpenCodeServerStartError} それ以外の理由でサーバー起動に失敗した場合。 + * @throws {@link OpenCodeError} それ以外の理由でサーバー起動に失敗した場合。 */ async connect(): Promise { let server: { url: string; close(): void }; @@ -38,7 +38,7 @@ export class OpenCodeClientHandle { if (isBinaryNotFoundError(error)) { throw new OpenCodeBinaryNotFoundError(error); } - throw new OpenCodeServerStartError(error); + throw new OpenCodeError(error); } this.server = server; this.client = createOpencodeClient({ baseUrl: server.url }); diff --git a/l10n/bundle.l10n.es.json b/l10n/bundle.l10n.es.json index d7662b2..2758a9b 100644 --- a/l10n/bundle.l10n.es.json +++ b/l10n/bundle.l10n.es.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requiere una carpeta de espacio de trabajo abierta.", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: no se encontró el comando \"opencode\". Instale OpenCode primero: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: no se encontró el comando \"opencode\". Instale OpenCode primero: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocurrió un error inesperado al iniciar OpenCode. Consulte el registro del desarrollador para más detalles." } diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index 52940b5..3fe3d48 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI を使用するにはワークスペースフォルダーを開いてください。", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" コマンドが見つかりません。先に OpenCode をインストールしてください: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" コマンドが見つかりません。先に OpenCode をインストールしてください: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode の起動中に予期しないエラーが発生しました。詳細は開発者ログを参照してください。" } diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index cf6cc8f..1f93460 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requires an open workspace folder.", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details." } diff --git a/l10n/bundle.l10n.ko.json b/l10n/bundle.l10n.ko.json index f1e9d9f..6f93bbb 100644 --- a/l10n/bundle.l10n.ko.json +++ b/l10n/bundle.l10n.ko.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI를 사용하려면 작업 영역 폴더를 여세요.", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" 명령을 찾을 수 없습니다. 먼저 OpenCode를 설치하세요: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" 명령을 찾을 수 없습니다. 먼저 OpenCode를 설치하세요: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode 시작 중에 예기치 않은 오류가 발생했습니다. 자세한 내용은 개발자 로그를 참조하세요." } diff --git a/l10n/bundle.l10n.pt-br.json b/l10n/bundle.l10n.pt-br.json index 3b8e51e..961ab29 100644 --- a/l10n/bundle.l10n.pt-br.json +++ b/l10n/bundle.l10n.pt-br.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "O OpenCodeGUI requer uma pasta de espaço de trabalho aberta.", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: comando \"opencode\" não encontrado. Instale o OpenCode primeiro: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: comando \"opencode\" não encontrado. Instale o OpenCode primeiro: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocorreu um erro inesperado ao iniciar o OpenCode. Consulte o log do desenvolvedor para obter detalhes." } diff --git a/l10n/bundle.l10n.ru.json b/l10n/bundle.l10n.ru.json index 76db34c..166fc7c 100644 --- a/l10n/bundle.l10n.ru.json +++ b/l10n/bundle.l10n.ru.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "Для работы OpenCodeGUI требуется открытая папка рабочей области.", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: команда \"opencode\" не найдена. Сначала установите OpenCode: https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: команда \"opencode\" не найдена. Сначала установите OpenCode: https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: при запуске OpenCode произошла непредвиденная ошибка. Подробности см. в журнале разработчика." } diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index c6d1a64..f14a217 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要打开工作区文件夹。", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:未找到 \"opencode\" 命令。请先安装 OpenCode:https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:未找到 \"opencode\" 命令。请先安装 OpenCode:https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:启动 OpenCode 时发生意外错误。详情请查看开发者日志。" } diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json index cb4bebd..a6be4a5 100644 --- a/l10n/bundle.l10n.zh-tw.json +++ b/l10n/bundle.l10n.zh-tw.json @@ -1,4 +1,5 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要開啟工作區資料夾。", - "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:找不到 \"opencode\" 命令。請先安裝 OpenCode:https://github.com/anomalyco/opencode" + "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:找不到 \"opencode\" 命令。請先安裝 OpenCode:https://github.com/anomalyco/opencode", + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:啟動 OpenCode 時發生未預期的錯誤。詳情請查看開發者記錄。" } From b2b5a15855d056bbe4da6870006e55adb5e74de6 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:04:43 +0900 Subject: [PATCH 19/25] =?UTF-8?q?refactor:=20connectOpenCode=20=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/extension.ts | 52 +++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/extension/extension.ts b/extension/extension.ts index 21dcc21..1f53723 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -23,25 +23,8 @@ export async function activate(context: vscode.ExtensionContext) { return; } - // SDK の createOpencodeServer は cwd オプションを持たないため、 - // プロセスのカレントディレクトリを変更してからサーバーを起動する。 - const originalCwd = process.cwd(); - process.chdir(workspaceFolder); - try { - await openCodeClientHandle.connect(); - } catch (error) { - if (error instanceof OpenCodeBinaryNotFoundError) { - vscode.window.showWarningMessage(t("warnings.opencodeNotFound")); - return; - } - if (error instanceof OpenCodeError) { - console.error(error); - vscode.window.showErrorMessage(t("errors.unexpected")); - return; - } - throw error; - } finally { - process.chdir(originalCwd); + if (!(await connectOpenCode(workspaceFolder))) { + return; } const platformServices = new VscodePlatformServices(); @@ -86,6 +69,37 @@ export function deactivate() { openCodeClientHandle.disconnect(); } +/** + * 指定したワークスペースフォルダで OpenCode サーバーへ接続する。 + * 失敗種別に応じてユーザー通知を出し、`activate` を続行すべきかを真偽値で返す。 + * + * @returns 接続成功時 true。通知済みで activate を中止すべき場合 false。 + * @throws OpenCode に由来しない想定外のエラー。 + */ +async function connectOpenCode(workspaceFolder: string): Promise { + // SDK の createOpencodeServer は cwd オプションを持たないため、 + // プロセスのカレントディレクトリを変更してからサーバーを起動する。 + const originalCwd = process.cwd(); + process.chdir(workspaceFolder); + try { + await openCodeClientHandle.connect(); + return true; + } catch (error) { + if (error instanceof OpenCodeBinaryNotFoundError) { + vscode.window.showWarningMessage(t("warnings.opencodeNotFound")); + return false; + } + if (error instanceof OpenCodeError) { + console.error(error); + vscode.window.showErrorMessage(t("errors.unexpected")); + return false; + } + throw error; + } finally { + process.chdir(originalCwd); + } +} + /** PATH 上に difit コマンドが存在するかチェックする */ function checkDifitAvailable(): Promise { return new Promise((resolve) => { From 514c1ddbcbdef76c315c92ddaca3124a9a23aad9 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:31:15 +0900 Subject: [PATCH 20/25] =?UTF-8?q?refactor:=20VscodePlatformServices=20?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4=E3=81=97=E3=80=81ChatViewProvider?= =?UTF-8?q?=20=E3=81=AB=E6=A9=9F=E8=83=BD=E3=82=92=E7=B5=B1=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/chat-view-provider.test.ts | 173 +++++++++--------- extension/__tests__/mocks/vscode.ts | 29 +++ extension/chat-view-provider.ts | 101 +++++++++- extension/extension.ts | 4 - extension/vscode-platform-services.ts | 86 --------- 5 files changed, 211 insertions(+), 182 deletions(-) delete mode 100644 extension/vscode-platform-services.ts diff --git a/extension/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-view-provider.test.ts index 99bed3e..e4e4477 100644 --- a/extension/__tests__/chat-view-provider.test.ts +++ b/extension/__tests__/chat-view-provider.test.ts @@ -16,7 +16,6 @@ import * as vscode from "vscode"; import { ChatViewProvider } from "../chat-view-provider"; import type { DiffReviewManager } from "../diff-review-manager"; import type { OpenCodeClientHandle } from "../opencode-client-handle"; -import type { VscodePlatformServices } from "../vscode-platform-services"; // --- Helper: OpenCodeClientHandle のモック --- @@ -25,7 +24,6 @@ type MockedMethods = { }; type MockOpenCodeClientHandle = MockedMethods & Record>; -type MockVscodePlatformServices = MockedMethods; function createMockAgent(): MockOpenCodeClientHandle { const api = { @@ -175,20 +173,6 @@ function createMockAgent(): MockOpenCodeClientHandle { return api as MockOpenCodeClientHandle; } -// --- Helper: VscodePlatformServices のモック --- - -function createMockPlatformServices(): MockVscodePlatformServices { - return { - openDiffEditor: vi.fn().mockResolvedValue(undefined), - copyToClipboard: vi.fn().mockResolvedValue(undefined), - openTerminal: vi.fn().mockResolvedValue(undefined), - openConfigFile: vi.fn().mockResolvedValue(undefined), - openFile: vi.fn().mockResolvedValue(undefined), - searchWorkspaceFiles: vi.fn().mockResolvedValue([]), - getOpenEditors: vi.fn().mockResolvedValue([]), - } as MockVscodePlatformServices; -} - // --- Helper: DiffReviewManager のモック --- function createMockDiffReviewManager(): { @@ -247,18 +231,15 @@ function createMockWebviewView() { function setupProvider( mockAgent: ReturnType, - mockPlatformServices?: ReturnType, mockDiffReviewManager?: ReturnType, difitAvailable = false, ) { const extensionUri = { fsPath: "/extension" }; - const ps = mockPlatformServices ?? createMockPlatformServices(); const drm = mockDiffReviewManager ?? createMockDiffReviewManager(); const provider = new ChatViewProvider( extensionUri as never, mockAgent as never, "/workspace", - ps as never, drm as never, difitAvailable, ); @@ -268,7 +249,7 @@ function setupProvider( {} as never, { isCancellationRequested: false, onCancellationRequested: vi.fn() } as never, ); - return { provider, platformServices: ps, diffReviewManager: drm, ...mock }; + return { provider, diffReviewManager: drm, ...mock }; } describe("ChatViewProvider", () => { @@ -700,17 +681,16 @@ describe("ChatViewProvider", () => { // ============================================================ describe("getOpenEditors", () => { - it("should delegate to platformServices.getOpenEditors and send result", async () => { - const mockPS = createMockPlatformServices(); - mockPS.getOpenEditors.mockResolvedValue([ - { filePath: "src/index.ts", fileName: "index.ts" }, - { filePath: "src/app.ts", fileName: "app.ts" }, - ]); + it("タブ一覧から FileAttachment[] を組み立てて postMessage する", async () => { + // workspaceFolders を設定。/workspace 以下の相対パスを取りたい。 + vi.mocked(vscode.workspace).workspaceFolders = [{ uri: { fsPath: "/workspace" } }] as never; + const tabA = { input: new vscode.TabInputText({ fsPath: "/workspace/src/index.ts", scheme: "file" } as never) }; + const tabB = { input: new vscode.TabInputText({ fsPath: "/workspace/src/app.ts", scheme: "file" } as never) }; + vi.mocked(vscode.window).tabGroups = { all: [{ tabs: [tabA, tabB] }] } as never; - const { postMessage, sendMessage } = setupProvider(mockAgent, mockPS); + const { postMessage, sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "getOpenEditors" }); - expect(mockPS.getOpenEditors).toHaveBeenCalled(); expect(postMessage).toHaveBeenCalledWith({ type: "openEditors", files: [ @@ -726,14 +706,16 @@ describe("ChatViewProvider", () => { // ============================================================ describe("searchWorkspaceFiles", () => { - it("should delegate to platformServices.searchWorkspaceFiles and send result", async () => { - const mockPS = createMockPlatformServices(); - mockPS.searchWorkspaceFiles.mockResolvedValue([{ filePath: "src/index.ts", fileName: "index.ts" }]); + it("findFiles の結果を FileAttachment[] に変換して postMessage する", async () => { + vi.mocked(vscode.workspace).workspaceFolders = [{ uri: { fsPath: "/workspace" } }] as never; + vi.mocked(vscode.workspace.findFiles).mockResolvedValueOnce([ + { fsPath: "/workspace/src/index.ts" } as never, + ]); - const { postMessage, sendMessage } = setupProvider(mockAgent, mockPS); + const { postMessage, sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "searchWorkspaceFiles", query: "index" }); - expect(mockPS.searchWorkspaceFiles).toHaveBeenCalledWith("index"); + expect(vscode.workspace.findFiles).toHaveBeenCalledWith("**/*index*", "**/node_modules/**", 20); expect(postMessage).toHaveBeenCalledWith({ type: "workspaceFiles", files: [{ filePath: "src/index.ts", fileName: "index.ts" }], @@ -837,12 +819,27 @@ describe("ChatViewProvider", () => { // ============================================================ describe("openConfigFile", () => { - it("should delegate to platformServices.openConfigFile", async () => { - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + it("既存のファイルを開く(stat 成功時は新規作成しない)", async () => { + vi.mocked(vscode.workspace.fs.stat).mockResolvedValueOnce(undefined as never); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openConfigFile", filePath: "/home/.config/opencode/opencode.json" }); - expect(mockPS.openConfigFile).toHaveBeenCalledWith("/home/.config/opencode/opencode.json"); + expect(vscode.workspace.fs.stat).toHaveBeenCalled(); + expect(vscode.workspace.fs.createDirectory).not.toHaveBeenCalled(); + expect(vscode.workspace.fs.writeFile).not.toHaveBeenCalled(); + expect(vscode.workspace.openTextDocument).toHaveBeenCalled(); + expect(vscode.window.showTextDocument).toHaveBeenCalled(); + }); + + it("ファイル未存在時はディレクトリ作成 + 初期内容の書き込みを行ってから開く", async () => { + vi.mocked(vscode.workspace.fs.stat).mockRejectedValueOnce(new Error("not found")); + const { sendMessage } = setupProvider(mockAgent); + await sendMessage({ type: "openConfigFile", filePath: "/home/.config/opencode/opencode.json" }); + + expect(vscode.workspace.fs.createDirectory).toHaveBeenCalled(); + expect(vscode.workspace.fs.writeFile).toHaveBeenCalled(); + expect(vscode.workspace.openTextDocument).toHaveBeenCalled(); + expect(vscode.window.showTextDocument).toHaveBeenCalled(); }); }); @@ -851,36 +848,36 @@ describe("ChatViewProvider", () => { // ============================================================ describe("openTerminal", () => { - it("should do nothing when serverUrl is undefined", async () => { + it("serverUrl が未取得なら何もしない", async () => { mockAgent.getServerUrl.mockReturnValue(undefined); - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openTerminal" }); - expect(mockPS.openTerminal).not.toHaveBeenCalled(); + expect(vscode.window.createTerminal).not.toHaveBeenCalled(); }); - it("should delegate to platformServices.openTerminal with serverUrl", async () => { - const mockPS = createMockPlatformServices(); + it("serverUrl が取得できれば opencode attach コマンドを送る", async () => { + const sendText = vi.fn(); + vi.mocked(vscode.window.createTerminal).mockReturnValueOnce({ show: vi.fn(), sendText } as never); - const { sendMessage } = setupProvider(mockAgent, mockPS); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openTerminal" }); - expect(mockPS.openTerminal).toHaveBeenCalledWith("http://localhost:12345", undefined); + expect(vscode.window.createTerminal).toHaveBeenCalledWith({ name: "OpenCode", cwd: "/workspace" }); + expect(sendText).toHaveBeenCalledWith('opencode "attach" "http://localhost:12345"'); }); - it("should include sessionId when activeSession exists", async () => { - const mockPS = createMockPlatformServices(); + it("activeSession がある場合は --session も渡す", async () => { + const sendText = vi.fn(); + vi.mocked(vscode.window.createTerminal).mockReturnValueOnce({ show: vi.fn(), sendText } as never); mockAgent.createSession.mockResolvedValue({ id: "sess-1" }); - const { sendMessage } = setupProvider(mockAgent, mockPS); - // まずアクティブセッションを設定 + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "createSession" }); - await sendMessage({ type: "openTerminal" }); - expect(mockPS.openTerminal).toHaveBeenCalledWith("http://localhost:12345", "sess-1"); + expect(sendText).toHaveBeenCalledWith('opencode "attach" "http://localhost:12345" "--session" "sess-1"'); }); }); @@ -1019,27 +1016,25 @@ describe("ChatViewProvider", () => { // ============================================================ describe("shareSession", () => { - it("should update activeSession and copy share URL via platformServices", async () => { + it("activeSession を更新し share URL をクリップボードにコピーする", async () => { const session = { id: "sess-1", share: { url: "https://share.example.com/abc" } }; mockAgent.shareSession.mockResolvedValue(session); - const mockPS = createMockPlatformServices(); - const { postMessage, sendMessage } = setupProvider(mockAgent, mockPS); + const { postMessage, sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "shareSession", sessionId: "sess-1" }); expect(postMessage).toHaveBeenCalledWith({ type: "activeSession", session }); - expect(mockPS.copyToClipboard).toHaveBeenCalledWith("https://share.example.com/abc"); + expect(vscode.env.clipboard.writeText).toHaveBeenCalledWith("https://share.example.com/abc"); }); - it("should not copy to clipboard when share.url is absent", async () => { + it("share.url が無ければクリップボードにコピーしない", async () => { const session = { id: "sess-1" }; mockAgent.shareSession.mockResolvedValue(session); - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "shareSession", sessionId: "sess-1" }); - expect(mockPS.copyToClipboard).not.toHaveBeenCalled(); + expect(vscode.env.clipboard.writeText).not.toHaveBeenCalled(); }); }); @@ -1112,9 +1107,8 @@ describe("ChatViewProvider", () => { // ============================================================ describe("openDiffEditor", () => { - it("should delegate to platformServices.openDiffEditor", async () => { - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + it("vscode.diff コマンドを実行する", async () => { + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openDiffEditor", @@ -1123,7 +1117,12 @@ describe("ChatViewProvider", () => { after: "const a = 2;", }); - expect(mockPS.openDiffEditor).toHaveBeenCalledWith("src/index.ts", "const a = 1;", "const a = 2;"); + expect(vscode.commands.executeCommand).toHaveBeenCalledWith( + "vscode.diff", + expect.objectContaining({ scheme: "opencode-diff-before" }), + expect.objectContaining({ scheme: "opencode-diff-after" }), + "index.ts (Changes)", + ); }); }); @@ -1132,29 +1131,41 @@ describe("ChatViewProvider", () => { // ============================================================ describe("openFile", () => { - it("should delegate to platformServices.openFile", async () => { - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + it("line 指定時はテキストエディタの選択範囲を更新し中央へリビールする", async () => { + const editor = { + selection: undefined as unknown, + revealRange: vi.fn(), + }; + vi.mocked(vscode.window.showTextDocument).mockResolvedValueOnce(editor as never); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openFile", filePath: "/home/user/project/src/main.ts", line: 42, }); - expect(mockPS.openFile).toHaveBeenCalledWith("/home/user/project/src/main.ts", 42); + expect(vscode.workspace.openTextDocument).toHaveBeenCalled(); + expect(vscode.window.showTextDocument).toHaveBeenCalled(); + expect(editor.selection).toBeInstanceOf(vscode.Selection); + expect(editor.revealRange).toHaveBeenCalled(); }); - it("should delegate to platformServices.openFile without line", async () => { - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + it("line 未指定時は選択範囲やリビールを行わない", async () => { + const editor = { + selection: undefined as unknown, + revealRange: vi.fn(), + }; + vi.mocked(vscode.window.showTextDocument).mockResolvedValueOnce(editor as never); + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "openFile", filePath: "/home/user/project/src/main.ts", }); - expect(mockPS.openFile).toHaveBeenCalledWith("/home/user/project/src/main.ts", undefined); + expect(vscode.window.showTextDocument).toHaveBeenCalled(); + expect(editor.revealRange).not.toHaveBeenCalled(); }); }); @@ -1163,13 +1174,12 @@ describe("ChatViewProvider", () => { // ============================================================ describe("copyToClipboard", () => { - it("should delegate to platformServices.copyToClipboard", async () => { - const mockPS = createMockPlatformServices(); - const { sendMessage } = setupProvider(mockAgent, mockPS); + it("クリップボードにテキストを書き込む", async () => { + const { sendMessage } = setupProvider(mockAgent); await sendMessage({ type: "copyToClipboard", text: "Hello World" }); - expect(mockPS.copyToClipboard).toHaveBeenCalledWith("Hello World"); + expect(vscode.env.clipboard.writeText).toHaveBeenCalledWith("Hello World"); }); }); @@ -1206,7 +1216,7 @@ describe("ChatViewProvider", () => { const diffs = [{ file: "a.ts", before: "old", after: "new", additions: 1, deletions: 1 }]; mockAgent.getSessionDiff.mockResolvedValue(diffs); const drm = createMockDiffReviewManager(); - const { sendMessage, postMessage } = setupProvider(mockAgent, undefined, drm); + const { sendMessage, postMessage } = setupProvider(mockAgent, drm); // activeSession を設定 const session = { id: "s1", title: "S1" }; @@ -1226,7 +1236,7 @@ describe("ChatViewProvider", () => { const diffs = [{ file: "a.ts", before: "old", after: "new", additions: 1, deletions: 1 }]; mockAgent.getSessionDiff.mockResolvedValue(diffs); const drm = createMockDiffReviewManager(); - const { sendMessage } = setupProvider(mockAgent, undefined, drm); + const { sendMessage } = setupProvider(mockAgent, drm); const session = { id: "s1", title: "S1" }; mockAgent.createSession.mockResolvedValue(session); @@ -1241,7 +1251,7 @@ describe("ChatViewProvider", () => { // should not call start when no activeSession it("activeSession がない場合は start を呼ばないこと", async () => { const drm = createMockDiffReviewManager(); - const { sendMessage } = setupProvider(mockAgent, undefined, drm); + const { sendMessage } = setupProvider(mockAgent, drm); await sendMessage({ type: "openDiffReview" }); @@ -1254,7 +1264,7 @@ describe("ChatViewProvider", () => { // should call diffReviewManager.stop it("diffReviewManager.stop を呼ぶこと", async () => { const drm = createMockDiffReviewManager(); - const { sendMessage, postMessage } = setupProvider(mockAgent, undefined, drm); + const { sendMessage, postMessage } = setupProvider(mockAgent, drm); await sendMessage({ type: "stopDiffReview" }); @@ -1270,7 +1280,7 @@ describe("ChatViewProvider", () => { describe("difitAvailable", () => { // should send difitAvailable on ready it("ready 時に difitAvailable メッセージを送信すること", async () => { - const { postMessage, sendMessage } = setupProvider(mockAgent, undefined, undefined, true); + const { postMessage, sendMessage } = setupProvider(mockAgent, undefined, true); await sendMessage({ type: "ready" }); @@ -1279,7 +1289,7 @@ describe("ChatViewProvider", () => { // should send false when difit is not available it("difit 未インストール時は available=false を送信すること", async () => { - const { postMessage, sendMessage } = setupProvider(mockAgent, undefined, undefined, false); + const { postMessage, sendMessage } = setupProvider(mockAgent, undefined, false); await sendMessage({ type: "ready" }); @@ -1299,7 +1309,6 @@ describe("ChatViewProvider", () => { extensionUri as never, mockAgent as never, "/workspace", - createMockPlatformServices() as never, createMockDiffReviewManager() as never, false, ); diff --git a/extension/__tests__/mocks/vscode.ts b/extension/__tests__/mocks/vscode.ts index 5dd5c30..468d103 100644 --- a/extension/__tests__/mocks/vscode.ts +++ b/extension/__tests__/mocks/vscode.ts @@ -105,3 +105,32 @@ export const ViewColumn = { Two: 2, Three: 3, }; + +// --- Position / Selection / Range / TextEditorRevealType --- +export class Position { + constructor( + public line: number, + public character: number, + ) {} +} + +export class Selection { + constructor( + public anchor: Position, + public active: Position, + ) {} +} + +export class Range { + constructor( + public start: Position, + public end: Position, + ) {} +} + +export const TextEditorRevealType = { + Default: 0, + InCenter: 1, + InCenterIfOutsideViewport: 2, + AtTop: 3, +}; diff --git a/extension/chat-view-provider.ts b/extension/chat-view-provider.ts index a42c7da..fcdbe7c 100644 --- a/extension/chat-view-provider.ts +++ b/extension/chat-view-provider.ts @@ -18,7 +18,6 @@ import type { import * as vscode from "vscode"; import type { DiffReviewManager } from "./diff-review-manager"; import type { OpenCodeClientHandle } from "./opencode-client-handle"; -import type { VscodePlatformServices } from "./vscode-platform-services"; export class ChatViewProvider implements vscode.WebviewViewProvider { public static readonly viewType = "opencode.chatView"; @@ -32,7 +31,6 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { private readonly extensionUri: vscode.Uri, private readonly openCodeClientHandle: OpenCodeClientHandle, private readonly workspaceFolder: string, - private readonly platformServices: VscodePlatformServices, private readonly diffReviewManager: DiffReviewManager, private readonly difitAvailable: boolean, ) {} @@ -213,12 +211,12 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { } // --- Platform operations --- case "getOpenEditors": { - const files = await this.platformServices.getOpenEditors(); + const files = await this.getOpenEditors(); this.postMessage({ type: "openEditors", files }); break; } case "searchWorkspaceFiles": { - const files = await this.platformServices.searchWorkspaceFiles(message.query); + const files = await this.searchWorkspaceFiles(message.query); this.postMessage({ type: "workspaceFiles", files }); break; } @@ -271,13 +269,13 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "openConfigFile": { - await this.platformServices.openConfigFile(message.filePath); + await this.openConfigFile(message.filePath); break; } case "openTerminal": { const serverUrl = this.openCodeClientHandle.getServerUrl(); if (!serverUrl) break; - await this.platformServices.openTerminal(serverUrl, this.activeSession?.id); + await this.openTerminal(serverUrl, this.activeSession?.id); break; } case "setModel": { @@ -329,7 +327,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { this.postMessage({ type: "activeSession", session }); // 共有 URL をクリップボードにコピーする if (session.share?.url) { - await this.platformServices.copyToClipboard(session.share.url); + await this.copyToClipboard(session.share.url); } break; } @@ -341,7 +339,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "copyToClipboard": { - await this.platformServices.copyToClipboard(message.text); + await this.copyToClipboard(message.text); break; } case "undoSession": { @@ -364,11 +362,11 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "openDiffEditor": { - await this.platformServices.openDiffEditor(message.filePath, message.before, message.after); + await this.openDiffEditor(message.filePath, message.before, message.after); break; } case "openFile": { - await this.platformServices.openFile(message.filePath, message.line); + await this.openFile(message.filePath, message.line); break; } case "openDiffReview": { @@ -467,6 +465,89 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; } + // --- VS Code API 呼び出し(webview 依頼の処理用) --- + + /** 仮想ドキュメントを使って VS Code のネイティブ diff エディタを開く。 */ + private async openDiffEditor(filePath: string, before: string, after: string): Promise { + const beforeUri = vscode.Uri.parse(`opencode-diff-before:${filePath}?${encodeURIComponent(before)}`); + const afterUri = vscode.Uri.parse(`opencode-diff-after:${filePath}?${encodeURIComponent(after)}`); + const fileName = path.basename(filePath); + await vscode.commands.executeCommand("vscode.diff", beforeUri, afterUri, `${fileName} (Changes)`); + } + + private async copyToClipboard(text: string): Promise { + await vscode.env.clipboard.writeText(text); + } + + private async openTerminal(serverUrl: string, sessionId?: string): Promise { + const args = ["attach", serverUrl]; + if (sessionId) { + args.push("--session", sessionId); + } + const wsFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + const terminal = vscode.window.createTerminal({ + name: "OpenCode", + cwd: wsFolder, + }); + terminal.show(); + terminal.sendText(`opencode ${args.map((a) => JSON.stringify(a)).join(" ")}`); + } + + /** 設定ファイルを開く。存在しない場合は初期内容で新規作成する。 */ + private async openConfigFile(filePath: string): Promise { + const uri = vscode.Uri.file(filePath); + try { + await vscode.workspace.fs.stat(uri); + } catch { + const dir = vscode.Uri.file(filePath.substring(0, filePath.lastIndexOf("/"))); + await vscode.workspace.fs.createDirectory(dir); + await vscode.workspace.fs.writeFile(uri, Buffer.from('{\n "$schema": "https://opencode.ai/config.json"\n}\n')); + } + const doc = await vscode.workspace.openTextDocument(uri); + await vscode.window.showTextDocument(doc); + } + + /** ファイルを開く。`line` 指定時は該当行へジャンプする。 */ + private async openFile(filePath: string, line?: number): Promise { + const uri = vscode.Uri.file(filePath); + const doc = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument(doc); + if (line !== undefined && line >= 1) { + const position = new vscode.Position(line - 1, 0); + editor.selection = new vscode.Selection(position, position); + editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); + } + } + + /** ワークスペース内のファイルを部分一致で検索する。 */ + private async searchWorkspaceFiles(query: string): Promise { + const pattern = query ? `**/*${query}*` : "**/*"; + const uris = await vscode.workspace.findFiles(pattern, "**/node_modules/**", 20); + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; + return uris.map((uri) => { + const relativePath = workspaceFolder + ? path.relative(workspaceFolder.fsPath, uri.fsPath) + : path.basename(uri.fsPath); + return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; + }); + } + + /** 現在開かれているテキストエディタの一覧を取得する(重複除去あり)。 */ + private async getOpenEditors(): Promise { + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; + return vscode.window.tabGroups.all + .flatMap((group) => group.tabs) + .filter((tab) => tab.input instanceof vscode.TabInputText) + .map((tab) => { + const uri = (tab.input as vscode.TabInputText).uri; + const relativePath = workspaceFolder + ? path.relative(workspaceFolder.fsPath, uri.fsPath) + : path.basename(uri.fsPath); + return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; + }) + .filter((f, i, arr) => arr.findIndex((a) => a.filePath === f.filePath) === i); + } + private postMessage(message: HostToUIMessage): void { this.view?.webview.postMessage(message); } diff --git a/extension/extension.ts b/extension/extension.ts index 1f53723..5ffa85f 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -5,7 +5,6 @@ import { DiffReviewManager } from "./diff-review-manager"; import { OpenCodeBinaryNotFoundError, OpenCodeError } from "./errors"; import { t } from "./i18n"; import { OpenCodeClientHandle } from "./opencode-client-handle"; -import { VscodePlatformServices } from "./vscode-platform-services"; const openCodeClientHandle = new OpenCodeClientHandle(); @@ -27,8 +26,6 @@ export async function activate(context: vscode.ExtensionContext) { return; } - const platformServices = new VscodePlatformServices(); - // PATH 上に difit が存在するか確認する。 // 存在しない場合はレビューボタンを非表示にするだけでエラーは出さない。 const difitAvailable = await checkDifitAvailable(); @@ -38,7 +35,6 @@ export async function activate(context: vscode.ExtensionContext) { context.extensionUri, openCodeClientHandle, workspaceFolder, - platformServices, diffReviewManager, difitAvailable, ); diff --git a/extension/vscode-platform-services.ts b/extension/vscode-platform-services.ts deleted file mode 100644 index 45f6756..0000000 --- a/extension/vscode-platform-services.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as path from "node:path"; -import type { FileAttachment } from "@shared"; -import * as vscode from "vscode"; - -export class VscodePlatformServices { - async openDiffEditor(filePath: string, before: string, after: string): Promise { - // 仮想ドキュメントを使って VS Code のネイティブ diff エディタを開く - const beforeUri = vscode.Uri.parse(`opencode-diff-before:${filePath}?${encodeURIComponent(before)}`); - const afterUri = vscode.Uri.parse(`opencode-diff-after:${filePath}?${encodeURIComponent(after)}`); - const fileName = path.basename(filePath); - await vscode.commands.executeCommand("vscode.diff", beforeUri, afterUri, `${fileName} (Changes)`); - } - - async copyToClipboard(text: string): Promise { - await vscode.env.clipboard.writeText(text); - } - - async openTerminal(serverUrl: string, sessionId?: string): Promise { - const args = ["attach", serverUrl]; - if (sessionId) { - args.push("--session", sessionId); - } - const wsFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; - const terminal = vscode.window.createTerminal({ - name: "OpenCode", - cwd: wsFolder, - }); - terminal.show(); - terminal.sendText(`opencode ${args.map((a) => JSON.stringify(a)).join(" ")}`); - } - - async openConfigFile(filePath: string): Promise { - const uri = vscode.Uri.file(filePath); - try { - await vscode.workspace.fs.stat(uri); - } catch { - // ファイルが存在しない場合は初期内容で作成する - const dir = vscode.Uri.file(filePath.substring(0, filePath.lastIndexOf("/"))); - await vscode.workspace.fs.createDirectory(dir); - await vscode.workspace.fs.writeFile(uri, Buffer.from('{\n "$schema": "https://opencode.ai/config.json"\n}\n')); - } - const doc = await vscode.workspace.openTextDocument(uri); - await vscode.window.showTextDocument(doc); - } - - async openFile(filePath: string, line?: number): Promise { - const uri = vscode.Uri.file(filePath); - const doc = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(doc); - if (line !== undefined && line >= 1) { - const position = new vscode.Position(line - 1, 0); - editor.selection = new vscode.Selection(position, position); - editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); - } - } - - async searchWorkspaceFiles(query: string): Promise { - const pattern = query ? `**/*${query}*` : "**/*"; - const uris = await vscode.workspace.findFiles(pattern, "**/node_modules/**", 20); - const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; - return uris.map((uri) => { - const relativePath = workspaceFolder - ? path.relative(workspaceFolder.fsPath, uri.fsPath) - : path.basename(uri.fsPath); - return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; - }); - } - - async getOpenEditors(): Promise { - const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; - return ( - vscode.window.tabGroups.all - .flatMap((group) => group.tabs) - .filter((tab) => tab.input instanceof vscode.TabInputText) - .map((tab) => { - const uri = (tab.input as vscode.TabInputText).uri; - const relativePath = workspaceFolder - ? path.relative(workspaceFolder.fsPath, uri.fsPath) - : path.basename(uri.fsPath); - return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; - }) - // 重複除去 - .filter((f, i, arr) => arr.findIndex((a) => a.filePath === f.filePath) === i) - ); - } -} From 168b7c0aef780fb030be106a1585064575052c56 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:37:20 +0900 Subject: [PATCH 21/25] =?UTF-8?q?refactor:=20difit=20=E3=81=AE=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E7=A2=BA=E8=AA=8D=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=E3=80=81=E6=83=85=E5=A0=B1=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/extension.test.ts | 39 +++++++++++++++++++++++++++ extension/__tests__/mocks/vscode.ts | 1 + extension/extension.ts | 5 ++-- extension/i18n/source.ts | 4 +++ l10n/bundle.l10n.es.json | 3 ++- l10n/bundle.l10n.ja.json | 3 ++- l10n/bundle.l10n.json | 3 ++- l10n/bundle.l10n.ko.json | 3 ++- l10n/bundle.l10n.pt-br.json | 3 ++- l10n/bundle.l10n.ru.json | 3 ++- l10n/bundle.l10n.zh-cn.json | 3 ++- l10n/bundle.l10n.zh-tw.json | 3 ++- 12 files changed, 63 insertions(+), 10 deletions(-) diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index 3d625c7..6618f2c 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -6,6 +6,16 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; // --- モックの準備 --- +// difit の存在確認 (`which difit`) をモックで制御する。 +// 既定では「見つかった」相当(callback に error なしで応答)にしておき、 +// 必要なテストで `mockExecFile.mockImplementationOnce(...)` で個別に上書きする。 +const mockExecFile = vi.fn((_cmd: string, _args: string[], cb: (error: unknown) => void) => { + cb(null); +}); +vi.mock("node:child_process", () => ({ + execFile: (cmd: string, args: string[], cb: (error: unknown) => void) => mockExecFile(cmd, args, cb), +})); + const mockConnect = vi.fn().mockResolvedValue(undefined); const mockDisconnect = vi.fn(); @@ -172,6 +182,35 @@ describe("extension", () => { }); }); + // ============================================================ + // activate - difit の有無による分岐 + // ============================================================ + + describe("activate() - difit availability", () => { + it("difit が見つからない場合は info メッセージを表示する", async () => { + // `which difit` が失敗(exit code 非 0)した状況を模す。 + mockExecFile.mockImplementationOnce((_cmd, _args, cb) => cb(new Error("not found"))); + + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; + + await extensionModule.activate(context as never); + + expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining("difit")); + }); + + it("difit が見つかった場合は info メッセージを表示しない", async () => { + mockExecFile.mockImplementationOnce((_cmd, _args, cb) => cb(null)); + + const extensionModule = await importExtension(); + const context = { extensionUri: { fsPath: "/extension" }, subscriptions: [] }; + + await extensionModule.activate(context as never); + + expect(vscode.window.showInformationMessage).not.toHaveBeenCalled(); + }); + }); + // ============================================================ // activate - 非 ENOENT エラー // ============================================================ diff --git a/extension/__tests__/mocks/vscode.ts b/extension/__tests__/mocks/vscode.ts index 468d103..2ba90dc 100644 --- a/extension/__tests__/mocks/vscode.ts +++ b/extension/__tests__/mocks/vscode.ts @@ -23,6 +23,7 @@ export const window = { registerWebviewViewProvider: vi.fn(() => ({ dispose: vi.fn() })), showWarningMessage: vi.fn(), showErrorMessage: vi.fn(), + showInformationMessage: vi.fn(), showTextDocument: vi.fn().mockResolvedValue(undefined), activeTextEditor: undefined as unknown, onDidChangeActiveTextEditor: vi.fn(() => ({ dispose: vi.fn() })), diff --git a/extension/extension.ts b/extension/extension.ts index 5ffa85f..122fc06 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -26,9 +26,10 @@ export async function activate(context: vscode.ExtensionContext) { return; } - // PATH 上に difit が存在するか確認する。 - // 存在しない場合はレビューボタンを非表示にするだけでエラーは出さない。 const difitAvailable = await checkDifitAvailable(); + if (!difitAvailable) { + vscode.window.showInformationMessage(t("info.difitNotAvailable")); + } const diffReviewManager = new DiffReviewManager(); const chatViewProvider = new ChatViewProvider( diff --git a/extension/i18n/source.ts b/extension/i18n/source.ts index 19217f4..39d3840 100644 --- a/extension/i18n/source.ts +++ b/extension/i18n/source.ts @@ -13,4 +13,8 @@ export const messages = { unexpected: "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.", }, + info: { + difitNotAvailable: + 'OpenCodeGUI: "difit" command not found. The diff review feature will be disabled. Install difit to enable it.', + }, } as const; diff --git a/l10n/bundle.l10n.es.json b/l10n/bundle.l10n.es.json index 2758a9b..0550e9f 100644 --- a/l10n/bundle.l10n.es.json +++ b/l10n/bundle.l10n.es.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requiere una carpeta de espacio de trabajo abierta.", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: no se encontró el comando \"opencode\". Instale OpenCode primero: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocurrió un error inesperado al iniciar OpenCode. Consulte el registro del desarrollador para más detalles." + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocurrió un error inesperado al iniciar OpenCode. Consulte el registro del desarrollador para más detalles.", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: no se encontró el comando \"difit\". La función de revisión de diff se deshabilitará. Instale difit para habilitarla." } diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index 3fe3d48..dc5a611 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI を使用するにはワークスペースフォルダーを開いてください。", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" コマンドが見つかりません。先に OpenCode をインストールしてください: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode の起動中に予期しないエラーが発生しました。詳細は開発者ログを参照してください。" + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode の起動中に予期しないエラーが発生しました。詳細は開発者ログを参照してください。", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: \"difit\" コマンドが見つかりません。diff レビュー機能は無効化されます。difit をインストールすると利用できます。" } diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 1f93460..a2810ca 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI requires an open workspace folder.", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details." + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it." } diff --git a/l10n/bundle.l10n.ko.json b/l10n/bundle.l10n.ko.json index 6f93bbb..b32d514 100644 --- a/l10n/bundle.l10n.ko.json +++ b/l10n/bundle.l10n.ko.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI를 사용하려면 작업 영역 폴더를 여세요.", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: \"opencode\" 명령을 찾을 수 없습니다. 먼저 OpenCode를 설치하세요: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode 시작 중에 예기치 않은 오류가 발생했습니다. 자세한 내용은 개발자 로그를 참조하세요." + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: OpenCode 시작 중에 예기치 않은 오류가 발생했습니다. 자세한 내용은 개발자 로그를 참조하세요.", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: \"difit\" 명령을 찾을 수 없습니다. diff 리뷰 기능이 비활성화됩니다. difit를 설치하면 사용할 수 있습니다." } diff --git a/l10n/bundle.l10n.pt-br.json b/l10n/bundle.l10n.pt-br.json index 961ab29..1ef6ff3 100644 --- a/l10n/bundle.l10n.pt-br.json +++ b/l10n/bundle.l10n.pt-br.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "O OpenCodeGUI requer uma pasta de espaço de trabalho aberta.", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: comando \"opencode\" não encontrado. Instale o OpenCode primeiro: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocorreu um erro inesperado ao iniciar o OpenCode. Consulte o log do desenvolvedor para obter detalhes." + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: ocorreu um erro inesperado ao iniciar o OpenCode. Consulte o log do desenvolvedor para obter detalhes.", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: comando \"difit\" não encontrado. O recurso de revisão de diff será desabilitado. Instale o difit para habilitá-lo." } diff --git a/l10n/bundle.l10n.ru.json b/l10n/bundle.l10n.ru.json index 166fc7c..3018609 100644 --- a/l10n/bundle.l10n.ru.json +++ b/l10n/bundle.l10n.ru.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "Для работы OpenCodeGUI требуется открытая папка рабочей области.", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI: команда \"opencode\" не найдена. Сначала установите OpenCode: https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: при запуске OpenCode произошла непредвиденная ошибка. Подробности см. в журнале разработчика." + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI: при запуске OpenCode произошла непредвиденная ошибка. Подробности см. в журнале разработчика.", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI: команда \"difit\" не найдена. Функция просмотра diff будет отключена. Установите difit, чтобы включить её." } diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index f14a217..b0b5719 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要打开工作区文件夹。", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:未找到 \"opencode\" 命令。请先安装 OpenCode:https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:启动 OpenCode 时发生意外错误。详情请查看开发者日志。" + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:启动 OpenCode 时发生意外错误。详情请查看开发者日志。", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI:未找到 \"difit\" 命令。diff 审阅功能将被禁用。安装 difit 后即可使用。" } diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json index a6be4a5..0347e5f 100644 --- a/l10n/bundle.l10n.zh-tw.json +++ b/l10n/bundle.l10n.zh-tw.json @@ -1,5 +1,6 @@ { "OpenCodeGUI requires an open workspace folder.": "OpenCodeGUI 需要開啟工作區資料夾。", "OpenCodeGUI: \"opencode\" command not found. Please install OpenCode first: https://github.com/anomalyco/opencode": "OpenCodeGUI:找不到 \"opencode\" 命令。請先安裝 OpenCode:https://github.com/anomalyco/opencode", - "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:啟動 OpenCode 時發生未預期的錯誤。詳情請查看開發者記錄。" + "OpenCodeGUI: An unexpected error occurred while starting OpenCode. See the developer log for details.": "OpenCodeGUI:啟動 OpenCode 時發生未預期的錯誤。詳情請查看開發者記錄。", + "OpenCodeGUI: \"difit\" command not found. The diff review feature will be disabled. Install difit to enable it.": "OpenCodeGUI:找不到 \"difit\" 命令。diff 檢閱功能將被停用。安裝 difit 後即可使用。" } From 4c54a097c8ebb85f0749c232646897141366f13a Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:41:03 +0900 Subject: [PATCH 22/25] =?UTF-8?q?refactor:=20DiffReviewManager=20=E3=82=92?= =?UTF-8?q?=20DifitHandle=20=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88?= =?UTF-8?q?=E3=80=81=E9=96=A2=E9=80=A3=E3=81=99=E3=82=8B=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/chat-view-provider.test.ts | 51 ++++++------- ...w-manager.test.ts => difit-handle.test.ts} | 73 +++++++++++++------ extension/chat-view-provider.ts | 11 ++- ...diff-review-manager.ts => difit-handle.ts} | 32 ++++++-- extension/extension.ts | 22 ++---- 5 files changed, 113 insertions(+), 76 deletions(-) rename extension/__tests__/{diff-review-manager.test.ts => difit-handle.test.ts} (76%) rename extension/{diff-review-manager.ts => difit-handle.ts} (72%) diff --git a/extension/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-view-provider.test.ts index e4e4477..d0fae1a 100644 --- a/extension/__tests__/chat-view-provider.test.ts +++ b/extension/__tests__/chat-view-provider.test.ts @@ -14,7 +14,7 @@ vi.mock("node:fs/promises", () => ({ import * as fs from "node:fs/promises"; import * as vscode from "vscode"; import { ChatViewProvider } from "../chat-view-provider"; -import type { DiffReviewManager } from "../diff-review-manager"; +import type { DifitHandle } from "../difit-handle"; import type { OpenCodeClientHandle } from "../opencode-client-handle"; // --- Helper: OpenCodeClientHandle のモック --- @@ -173,12 +173,14 @@ function createMockAgent(): MockOpenCodeClientHandle { return api as MockOpenCodeClientHandle; } -// --- Helper: DiffReviewManager のモック --- +// --- Helper: DifitHandle のモック --- -function createMockDiffReviewManager(): { - [K in keyof DiffReviewManager]: ReturnType; +function createMockDifitHandle(difitAvailable = false): { + [K in keyof DifitHandle]: ReturnType; } { return { + init: vi.fn().mockResolvedValue(undefined), + isAvailable: vi.fn().mockReturnValue(difitAvailable), start: vi.fn().mockResolvedValue(undefined), stop: vi.fn(), dispose: vi.fn(), @@ -231,25 +233,19 @@ function createMockWebviewView() { function setupProvider( mockAgent: ReturnType, - mockDiffReviewManager?: ReturnType, + mockDifitHandle?: ReturnType, difitAvailable = false, ) { const extensionUri = { fsPath: "/extension" }; - const drm = mockDiffReviewManager ?? createMockDiffReviewManager(); - const provider = new ChatViewProvider( - extensionUri as never, - mockAgent as never, - "/workspace", - drm as never, - difitAvailable, - ); + const dh = mockDifitHandle ?? createMockDifitHandle(difitAvailable); + const provider = new ChatViewProvider(extensionUri as never, mockAgent as never, "/workspace", dh as never); const mock = createMockWebviewView(); provider.resolveWebviewView( mock.webviewView as never, {} as never, { isCancellationRequested: false, onCancellationRequested: vi.fn() } as never, ); - return { provider, diffReviewManager: drm, ...mock }; + return { provider, difitHandle: dh, ...mock }; } describe("ChatViewProvider", () => { @@ -1215,8 +1211,8 @@ describe("ChatViewProvider", () => { it("agent.getSessionDiff と diffReviewManager.start を呼ぶこと", async () => { const diffs = [{ file: "a.ts", before: "old", after: "new", additions: 1, deletions: 1 }]; mockAgent.getSessionDiff.mockResolvedValue(diffs); - const drm = createMockDiffReviewManager(); - const { sendMessage, postMessage } = setupProvider(mockAgent, drm); + const dh = createMockDifitHandle(); + const { sendMessage, postMessage } = setupProvider(mockAgent, dh); // activeSession を設定 const session = { id: "s1", title: "S1" }; @@ -1227,7 +1223,7 @@ describe("ChatViewProvider", () => { await sendMessage({ type: "openDiffReview" }); expect(mockAgent.getSessionDiff).toHaveBeenCalledWith("s1"); - expect(drm.start).toHaveBeenCalledWith(diffs, undefined); + expect(dh.start).toHaveBeenCalledWith(diffs, undefined); expect(postMessage).toHaveBeenCalledWith({ type: "diffReviewStarted" }); }); @@ -1235,8 +1231,8 @@ describe("ChatViewProvider", () => { it("focusFile を diffReviewManager.start に渡すこと", async () => { const diffs = [{ file: "a.ts", before: "old", after: "new", additions: 1, deletions: 1 }]; mockAgent.getSessionDiff.mockResolvedValue(diffs); - const drm = createMockDiffReviewManager(); - const { sendMessage } = setupProvider(mockAgent, drm); + const dh = createMockDifitHandle(); + const { sendMessage } = setupProvider(mockAgent, dh); const session = { id: "s1", title: "S1" }; mockAgent.createSession.mockResolvedValue(session); @@ -1245,30 +1241,30 @@ describe("ChatViewProvider", () => { await sendMessage({ type: "openDiffReview", focusFile: "a.ts" }); - expect(drm.start).toHaveBeenCalledWith(diffs, "a.ts"); + expect(dh.start).toHaveBeenCalledWith(diffs, "a.ts"); }); // should not call start when no activeSession it("activeSession がない場合は start を呼ばないこと", async () => { - const drm = createMockDiffReviewManager(); - const { sendMessage } = setupProvider(mockAgent, drm); + const dh = createMockDifitHandle(); + const { sendMessage } = setupProvider(mockAgent, dh); await sendMessage({ type: "openDiffReview" }); expect(mockAgent.getSessionDiff).not.toHaveBeenCalled(); - expect(drm.start).not.toHaveBeenCalled(); + expect(dh.start).not.toHaveBeenCalled(); }); }); describe("stopDiffReview", () => { // should call diffReviewManager.stop it("diffReviewManager.stop を呼ぶこと", async () => { - const drm = createMockDiffReviewManager(); - const { sendMessage, postMessage } = setupProvider(mockAgent, drm); + const dh = createMockDifitHandle(); + const { sendMessage, postMessage } = setupProvider(mockAgent, dh); await sendMessage({ type: "stopDiffReview" }); - expect(drm.stop).toHaveBeenCalled(); + expect(dh.stop).toHaveBeenCalled(); expect(postMessage).toHaveBeenCalledWith({ type: "diffReviewStopped" }); }); }); @@ -1309,8 +1305,7 @@ describe("ChatViewProvider", () => { extensionUri as never, mockAgent as never, "/workspace", - createMockDiffReviewManager() as never, - false, + createMockDifitHandle() as never, ); // view が undefined のまま postMessage を呼ぶ(内部的に) diff --git a/extension/__tests__/diff-review-manager.test.ts b/extension/__tests__/difit-handle.test.ts similarity index 76% rename from extension/__tests__/diff-review-manager.test.ts rename to extension/__tests__/difit-handle.test.ts index e31bae2..5fb5fac 100644 --- a/extension/__tests__/diff-review-manager.test.ts +++ b/extension/__tests__/difit-handle.test.ts @@ -1,6 +1,7 @@ /** - * DiffReviewManager のユニットテスト。 - * child_process.spawn をモックし、difit プロセスの起動・URL 検出・停止を検証する。 + * DifitHandle のユニットテスト。 + * child_process.spawn / execFile をモックし、 + * difit の存在確認 (init/isAvailable) と difit プロセスの起動・URL 検出・停止を検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -9,10 +10,10 @@ vi.mock("node:child_process", () => ({ execFile: vi.fn(), })); -import { spawn } from "node:child_process"; +import { execFile, spawn } from "node:child_process"; import { EventEmitter, Readable, Writable } from "node:stream"; import * as vscode from "vscode"; -import { DiffReviewManager, fileDiffsToUnifiedDiff } from "../diff-review-manager"; +import { DifitHandle, fileDiffsToUnifiedDiff } from "../difit-handle"; /** stdin / stdout / stderr を持つ擬似 ChildProcess を生成する */ function createMockProcess() { @@ -35,16 +36,46 @@ function createMockProcess() { return proc; } -describe("DiffReviewManager", () => { - let manager: DiffReviewManager; +describe("DifitHandle", () => { + let handle: DifitHandle; beforeEach(() => { - manager = new DiffReviewManager(); + handle = new DifitHandle(); vi.clearAllMocks(); }); afterEach(() => { - manager.dispose(); + handle.dispose(); + }); + + // ============================================================ + // init() / isAvailable() + // ============================================================ + + describe("init() / isAvailable()", () => { + it("which difit が成功すれば isAvailable は true", async () => { + vi.mocked(execFile).mockImplementationOnce(((_cmd: string, _args: string[], cb: (e: unknown) => void) => { + cb(null); + }) as never); + + await handle.init(); + + expect(handle.isAvailable()).toBe(true); + }); + + it("which difit が失敗すれば isAvailable は false", async () => { + vi.mocked(execFile).mockImplementationOnce(((_cmd: string, _args: string[], cb: (e: unknown) => void) => { + cb(new Error("not found")); + }) as never); + + await handle.init(); + + expect(handle.isAvailable()).toBe(false); + }); + + it("init() を呼ばずに isAvailable を呼んでも false(フェイルセーフ)", () => { + expect(handle.isAvailable()).toBe(false); + }); }); // ============================================================ @@ -57,7 +88,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([ + const startPromise = handle.start([ { file: "src/index.ts", before: "old", after: "new", additions: 1, deletions: 1 }, ]); @@ -75,7 +106,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start( + const startPromise = handle.start( [{ file: "src/index.ts", before: "old", after: "new", additions: 1, deletions: 1 }], "src/index.ts", ); @@ -92,7 +123,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([ + const startPromise = handle.start([ { file: "src/index.ts", before: "old", after: "new", additions: 1, deletions: 1 }, ]); @@ -108,7 +139,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([ + const startPromise = handle.start([ { file: "src/index.ts", before: "old", after: "new", additions: 1, deletions: 1 }, ]); @@ -127,11 +158,11 @@ describe("DiffReviewManager", () => { .mockReturnValueOnce(proc1 as never) .mockReturnValueOnce(proc2 as never); - const start1 = manager.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + const start1 = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); proc1.stdout.push("http://127.0.0.1:4966\n"); await start1; - const start2 = manager.start([{ file: "b.ts", before: "", after: "y", additions: 1, deletions: 0 }]); + const start2 = handle.start([{ file: "b.ts", before: "", after: "y", additions: 1, deletions: 0 }]); proc2.stdout.push("http://127.0.0.1:4967\n"); await start2; @@ -143,7 +174,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); mockProc.emit("close", 1); @@ -155,7 +186,7 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); mockProc.emit("error", new Error("ENOENT")); @@ -173,18 +204,18 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); mockProc.stdout.push("http://127.0.0.1:4966\n"); await startPromise; - manager.stop(); + handle.stop(); expect(mockProc.kill).toHaveBeenCalled(); }); // should not throw when no process is running it("プロセスが起動していない場合でもエラーにならないこと", () => { - expect(() => manager.stop()).not.toThrow(); + expect(() => handle.stop()).not.toThrow(); }); }); @@ -198,11 +229,11 @@ describe("DiffReviewManager", () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); - const startPromise = manager.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); mockProc.stdout.push("http://127.0.0.1:4966\n"); await startPromise; - manager.dispose(); + handle.dispose(); expect(mockProc.kill).toHaveBeenCalled(); }); diff --git a/extension/chat-view-provider.ts b/extension/chat-view-provider.ts index fcdbe7c..b22f5e6 100644 --- a/extension/chat-view-provider.ts +++ b/extension/chat-view-provider.ts @@ -16,7 +16,7 @@ import type { UIToHostMessage, } from "@shared"; import * as vscode from "vscode"; -import type { DiffReviewManager } from "./diff-review-manager"; +import type { DifitHandle } from "./difit-handle"; import type { OpenCodeClientHandle } from "./opencode-client-handle"; export class ChatViewProvider implements vscode.WebviewViewProvider { @@ -31,8 +31,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { private readonly extensionUri: vscode.Uri, private readonly openCodeClientHandle: OpenCodeClientHandle, private readonly workspaceFolder: string, - private readonly diffReviewManager: DiffReviewManager, - private readonly difitAvailable: boolean, + private readonly difitHandle: DifitHandle, ) {} resolveWebviewView( @@ -112,7 +111,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { // 初期アクティブエディタを送信する this.postMessage({ type: "activeEditor", file: this.getActiveEditorFile(vscode.window.activeTextEditor) }); // difit の利用可否を Webview に通知する - this.postMessage({ type: "difitAvailable", available: this.difitAvailable }); + this.postMessage({ type: "difitAvailable", available: this.difitHandle.isAvailable() }); break; } case "sendMessage": { @@ -378,7 +377,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { if (diffs.length === 0) { break; } - await this.diffReviewManager.start(diffs, message.focusFile); + await this.difitHandle.start(diffs, message.focusFile); this.postMessage({ type: "diffReviewStarted" }); } catch (e) { const errorMsg = e instanceof Error ? e.message : String(e); @@ -388,7 +387,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider { break; } case "stopDiffReview": { - this.diffReviewManager.stop(); + this.difitHandle.stop(); this.postMessage({ type: "diffReviewStopped" }); break; } diff --git a/extension/diff-review-manager.ts b/extension/difit-handle.ts similarity index 72% rename from extension/diff-review-manager.ts rename to extension/difit-handle.ts index 0e9eb87..c37f84a 100644 --- a/extension/diff-review-manager.ts +++ b/extension/difit-handle.ts @@ -1,17 +1,39 @@ import type { ChildProcess } from "node:child_process"; -import { spawn } from "node:child_process"; +import { execFile, spawn } from "node:child_process"; import type { FileDiff } from "@shared"; import { createTwoFilesPatch } from "diff"; import * as vscode from "vscode"; /** - * difit プロセスのライフサイクル管理を担当する。 - * ワークスペースごとに 1 つの difit プロセスを保持し、 - * システムブラウザで差分レビュー画面を開く。 + * difit という外部プロセスとのやり取りを集約するハンドル。 + * `OpenCodeClientHandle` と同じく「外部プロセスの存在確認 + ライフサイクル管理」を 1 クラスに閉じる。 + * + * 使い方: + * 1. `init()` で PATH 上の存在を確認する(結果はキャッシュされる) + * 2. `isAvailable()` で利用可否を取得する + * 3. `start()` でレビュー画面を起動、`stop()` / `dispose()` で停止 */ -export class DiffReviewManager implements vscode.Disposable { +export class DifitHandle implements vscode.Disposable { private process: ChildProcess | null = null; private serverUrl: string | null = null; + private available: boolean | undefined; + + /** PATH 上に difit コマンドが存在するか確認する。結果は内部にキャッシュされる。 */ + async init(): Promise { + this.available = await new Promise((resolve) => { + execFile("which", ["difit"], (error) => { + resolve(!error); + }); + }); + } + + /** + * `init()` で確認した利用可否を返す。 + * `init()` 未実行の場合は `false` を返す(フェイルセーフ)。 + */ + isAvailable(): boolean { + return this.available === true; + } /** * difit プロセスを起動しシステムブラウザでレビュー画面を開く。 diff --git a/extension/extension.ts b/extension/extension.ts index 122fc06..75b4ae5 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -1,7 +1,6 @@ -import { execFile } from "node:child_process"; import * as vscode from "vscode"; import { ChatViewProvider } from "./chat-view-provider"; -import { DiffReviewManager } from "./diff-review-manager"; +import { DifitHandle } from "./difit-handle"; import { OpenCodeBinaryNotFoundError, OpenCodeError } from "./errors"; import { t } from "./i18n"; import { OpenCodeClientHandle } from "./opencode-client-handle"; @@ -26,21 +25,20 @@ export async function activate(context: vscode.ExtensionContext) { return; } - const difitAvailable = await checkDifitAvailable(); - if (!difitAvailable) { + const difitHandle = new DifitHandle(); + await difitHandle.init(); + if (!difitHandle.isAvailable()) { vscode.window.showInformationMessage(t("info.difitNotAvailable")); } - const diffReviewManager = new DiffReviewManager(); const chatViewProvider = new ChatViewProvider( context.extensionUri, openCodeClientHandle, workspaceFolder, - diffReviewManager, - difitAvailable, + difitHandle, ); context.subscriptions.push(vscode.window.registerWebviewViewProvider(ChatViewProvider.viewType, chatViewProvider)); - context.subscriptions.push(diffReviewManager); + context.subscriptions.push(difitHandle); // diff エディタ用の仮想ドキュメントプロバイダー。 // URI のクエリ部分にエンコードされたコンテンツを返す。 @@ -97,11 +95,3 @@ async function connectOpenCode(workspaceFolder: string): Promise { } } -/** PATH 上に difit コマンドが存在するかチェックする */ -function checkDifitAvailable(): Promise { - return new Promise((resolve) => { - execFile("which", ["difit"], (error) => { - resolve(!error); - }); - }); -} From 3481474775336c8045612895f61869e02d716adb Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:48:54 +0900 Subject: [PATCH 23/25] =?UTF-8?q?refactor:=20DifitError=20=E3=81=A8=20Difi?= =?UTF-8?q?tBinaryNotFoundError=20=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0=E3=82=92?= =?UTF-8?q?=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/__tests__/difit-handle.test.ts | 31 ++++++++++++++++++------ extension/difit-handle.ts | 21 +++++++++++++--- extension/errors.ts | 24 ++++++++++++++++++ 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/extension/__tests__/difit-handle.test.ts b/extension/__tests__/difit-handle.test.ts index 5fb5fac..0f39ce1 100644 --- a/extension/__tests__/difit-handle.test.ts +++ b/extension/__tests__/difit-handle.test.ts @@ -14,6 +14,7 @@ import { execFile, spawn } from "node:child_process"; import { EventEmitter, Readable, Writable } from "node:stream"; import * as vscode from "vscode"; import { DifitHandle, fileDiffsToUnifiedDiff } from "../difit-handle"; +import { DifitBinaryNotFoundError, DifitError } from "../errors"; /** stdin / stdout / stderr を持つ擬似 ChildProcess を生成する */ function createMockProcess() { @@ -169,8 +170,7 @@ describe("DifitHandle", () => { expect(proc1.kill).toHaveBeenCalled(); }); - // should reject when difit exits before emitting URL - it("URL 出力前に difit が終了した場合 reject すること", async () => { + it("URL 出力前に difit が終了した場合 DifitError で reject する(cause に元エラー)", async () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); @@ -178,19 +178,36 @@ describe("DifitHandle", () => { mockProc.emit("close", 1); - await expect(startPromise).rejects.toThrow("difit exited with code 1 before emitting URL"); + const rejection = await startPromise.catch((e: unknown) => e); + expect(rejection).toBeInstanceOf(DifitError); + expect(rejection).not.toBeInstanceOf(DifitBinaryNotFoundError); + expect((rejection as DifitError).cause).toBeInstanceOf(Error); }); - // should reject on spawn error - it("spawn エラー時に reject すること", async () => { + it("spawn が ENOENT エラーを emit した場合 DifitBinaryNotFoundError で reject する", async () => { const mockProc = createMockProcess(); vi.mocked(spawn).mockReturnValue(mockProc as never); const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); - mockProc.emit("error", new Error("ENOENT")); + mockProc.emit("error", Object.assign(new Error("spawn ENOENT"), { code: "ENOENT" })); - await expect(startPromise).rejects.toThrow("ENOENT"); + await expect(startPromise).rejects.toBeInstanceOf(DifitBinaryNotFoundError); + }); + + it("spawn が ENOENT 以外のエラーを emit した場合 DifitError で reject する", async () => { + const mockProc = createMockProcess(); + vi.mocked(spawn).mockReturnValue(mockProc as never); + + const startPromise = handle.start([{ file: "a.ts", before: "", after: "x", additions: 1, deletions: 0 }]); + + const original = new Error("EACCES"); + mockProc.emit("error", original); + + const rejection = await startPromise.catch((e: unknown) => e); + expect(rejection).toBeInstanceOf(DifitError); + expect(rejection).not.toBeInstanceOf(DifitBinaryNotFoundError); + expect((rejection as DifitError).cause).toBe(original); }); }); diff --git a/extension/difit-handle.ts b/extension/difit-handle.ts index c37f84a..6011570 100644 --- a/extension/difit-handle.ts +++ b/extension/difit-handle.ts @@ -3,6 +3,14 @@ import { execFile, spawn } from "node:child_process"; import type { FileDiff } from "@shared"; import { createTwoFilesPatch } from "diff"; import * as vscode from "vscode"; +import { DifitBinaryNotFoundError, DifitError } from "./errors"; + +/** spawn 失敗が ENOENT(実行ファイル未検出)を示しているか判定する。 */ +function isBinaryNotFoundError(error: unknown): boolean { + if (!(error instanceof Error)) return false; + const code = (error as NodeJS.ErrnoException).code; + return code === "ENOENT" || error.message.includes("ENOENT"); +} /** * difit という外部プロセスとのやり取りを集約するハンドル。 @@ -67,6 +75,9 @@ export class DifitHandle implements vscode.Disposable { /** * difit を子プロセスとして起動し、stdin に unified diff を書き込む。 * stdout から http://... の URL を検出して返す。 + * + * @throws {@link DifitBinaryNotFoundError} `difit` バイナリが PATH 上に存在しない場合。 + * @throws {@link DifitError} それ以外の理由で difit の起動に失敗した場合。 */ private spawnDifit(unifiedDiff: string): Promise { return new Promise((resolve, reject) => { @@ -75,7 +86,7 @@ export class DifitHandle implements vscode.Disposable { const { stdout, stderr, stdin } = child; if (!stdout || !stderr || !stdin) { - reject(new Error("Failed to create stdio streams")); + reject(new DifitError(new Error("Failed to create stdio streams"))); return; } @@ -96,13 +107,17 @@ export class DifitHandle implements vscode.Disposable { child.on("error", (err) => { this.process = null; - reject(err); + if (isBinaryNotFoundError(err)) { + reject(new DifitBinaryNotFoundError(err)); + } else { + reject(new DifitError(err)); + } }); child.on("close", (code) => { this.process = null; if (!this.serverUrl) { - reject(new Error(`difit exited with code ${code} before emitting URL`)); + reject(new DifitError(new Error(`difit exited with code ${code} before emitting URL`))); } }); diff --git a/extension/errors.ts b/extension/errors.ts index e0f259a..dc6d198 100644 --- a/extension/errors.ts +++ b/extension/errors.ts @@ -37,3 +37,27 @@ export class OpenCodeBinaryNotFoundError extends OpenCodeError { this.name = "OpenCodeBinaryNotFoundError"; } } + +/** + * difit 関連エラーの汎用クラス兼基底クラス。 + * 特定の失敗モードに分類されない difit 由来の失敗を表すと同時に、サブクラスの基底としても機能する。 + * 呼び出し側は `instanceof DifitError` で difit 由来の失敗をまとめて受けられる。 + */ +export class DifitError extends Error { + constructor(public readonly cause?: unknown) { + super("difit で予期しないエラーが発生しました。"); + this.name = "DifitError"; + } +} + +/** + * `difit` バイナリが PATH 上に見つからず、起動できなかった場合のエラー。 + * 子プロセス spawn 時の ENOENT を本クラスに変換する。 + */ +export class DifitBinaryNotFoundError extends DifitError { + constructor(cause: unknown) { + super(cause); + this.message = '"difit" コマンドが PATH 上に見つかりませんでした。difit をインストールしてください。'; + this.name = "DifitBinaryNotFoundError"; + } +} From eca6cfb793cf64aeee834f4ac98ca76deb2f9246 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 21:56:12 +0900 Subject: [PATCH 24/25] feat: rename ChatPanel --- ...chat-view-provider.test.ts => chat-panel.test.ts} | 10 +++++----- extension/__tests__/extension.test.ts | 12 ++++++------ extension/{chat-view-provider.ts => chat-panel.ts} | 2 +- extension/extension.ts | 11 +++-------- webview/__tests__/helpers.tsx | 2 +- 5 files changed, 16 insertions(+), 21 deletions(-) rename extension/__tests__/{chat-view-provider.test.ts => chat-panel.test.ts} (99%) rename extension/{chat-view-provider.ts => chat-panel.ts} (99%) diff --git a/extension/__tests__/chat-view-provider.test.ts b/extension/__tests__/chat-panel.test.ts similarity index 99% rename from extension/__tests__/chat-view-provider.test.ts rename to extension/__tests__/chat-panel.test.ts index d0fae1a..516c2da 100644 --- a/extension/__tests__/chat-view-provider.test.ts +++ b/extension/__tests__/chat-panel.test.ts @@ -1,5 +1,5 @@ /** - * ChatViewProvider のユニットテスト。 + * ChatPanel のユニットテスト。 * OpenCodeClientHandle をモックし、webview メッセージハンドラの振る舞いを検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -13,7 +13,7 @@ vi.mock("node:fs/promises", () => ({ import * as fs from "node:fs/promises"; import * as vscode from "vscode"; -import { ChatViewProvider } from "../chat-view-provider"; +import { ChatPanel } from "../chat-panel"; import type { DifitHandle } from "../difit-handle"; import type { OpenCodeClientHandle } from "../opencode-client-handle"; @@ -238,7 +238,7 @@ function setupProvider( ) { const extensionUri = { fsPath: "/extension" }; const dh = mockDifitHandle ?? createMockDifitHandle(difitAvailable); - const provider = new ChatViewProvider(extensionUri as never, mockAgent as never, "/workspace", dh as never); + const provider = new ChatPanel(extensionUri as never, mockAgent as never, "/workspace", dh as never); const mock = createMockWebviewView(); provider.resolveWebviewView( mock.webviewView as never, @@ -248,7 +248,7 @@ function setupProvider( return { provider, difitHandle: dh, ...mock }; } -describe("ChatViewProvider", () => { +describe("ChatPanel", () => { let mockAgent: ReturnType; beforeEach(() => { @@ -1301,7 +1301,7 @@ describe("ChatViewProvider", () => { it("should not crash when view is not set", () => { // resolveWebviewView を呼ばずに provider を作成 const extensionUri = { fsPath: "/extension" }; - const provider = new ChatViewProvider( + const provider = new ChatPanel( extensionUri as never, mockAgent as never, "/workspace", diff --git a/extension/__tests__/extension.test.ts b/extension/__tests__/extension.test.ts index 6618f2c..938f1c3 100644 --- a/extension/__tests__/extension.test.ts +++ b/extension/__tests__/extension.test.ts @@ -1,6 +1,6 @@ /** * extension.ts (activate / deactivate) のユニットテスト。 - * ChatViewProvider と OpenCodeClientHandle をモックし、起動・停止の振る舞いを検証する。 + * ChatPanel と OpenCodeClientHandle をモックし、起動・停止の振る舞いを検証する。 */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; @@ -29,9 +29,9 @@ function createMockAgentClass() { }; } -// ChatViewProvider のモック — コンストラクタとして使われる -function createMockChatViewProviderClass() { - return Object.assign(class MockChatViewProvider {}, { viewType: "opencode.chatView" }); +// ChatPanel のモック — コンストラクタとして使われる +function createMockChatPanelClass() { + return Object.assign(class MockChatPanel {}, { viewType: "opencode.chatView" }); } import * as vscode from "vscode"; @@ -67,8 +67,8 @@ describe("extension", () => { vi.doMock("../opencode-client-handle", () => ({ OpenCodeClientHandle: createMockAgentClass(), })); - vi.doMock("../chat-view-provider", () => ({ - ChatViewProvider: createMockChatViewProviderClass(), + vi.doMock("../chat-panel", () => ({ + ChatPanel: createMockChatPanelClass(), })); return import("../extension"); diff --git a/extension/chat-view-provider.ts b/extension/chat-panel.ts similarity index 99% rename from extension/chat-view-provider.ts rename to extension/chat-panel.ts index b22f5e6..449f3b4 100644 --- a/extension/chat-view-provider.ts +++ b/extension/chat-panel.ts @@ -19,7 +19,7 @@ import * as vscode from "vscode"; import type { DifitHandle } from "./difit-handle"; import type { OpenCodeClientHandle } from "./opencode-client-handle"; -export class ChatViewProvider implements vscode.WebviewViewProvider { +export class ChatPanel implements vscode.WebviewViewProvider { public static readonly viewType = "opencode.chatView"; private view: vscode.WebviewView | undefined; diff --git a/extension/extension.ts b/extension/extension.ts index 75b4ae5..2962b45 100644 --- a/extension/extension.ts +++ b/extension/extension.ts @@ -1,5 +1,5 @@ import * as vscode from "vscode"; -import { ChatViewProvider } from "./chat-view-provider"; +import { ChatPanel } from "./chat-panel"; import { DifitHandle } from "./difit-handle"; import { OpenCodeBinaryNotFoundError, OpenCodeError } from "./errors"; import { t } from "./i18n"; @@ -31,13 +31,8 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage(t("info.difitNotAvailable")); } - const chatViewProvider = new ChatViewProvider( - context.extensionUri, - openCodeClientHandle, - workspaceFolder, - difitHandle, - ); - context.subscriptions.push(vscode.window.registerWebviewViewProvider(ChatViewProvider.viewType, chatViewProvider)); + const chatPanel = new ChatPanel(context.extensionUri, openCodeClientHandle, workspaceFolder, difitHandle); + context.subscriptions.push(vscode.window.registerWebviewViewProvider(ChatPanel.viewType, chatPanel)); context.subscriptions.push(difitHandle); // diff エディタ用の仮想ドキュメントプロバイダー。 diff --git a/webview/__tests__/helpers.tsx b/webview/__tests__/helpers.tsx index 1c66313..8c9fb88 100644 --- a/webview/__tests__/helpers.tsx +++ b/webview/__tests__/helpers.tsx @@ -4,7 +4,7 @@ import type { HostToUIMessage } from "../vscode-api"; /** * Extension Host → Webview メッセージを擬似送信する。 - * chat-view-provider.ts が panel.webview.postMessage() で送るメッセージを再現する。 + * chat-panel.ts が panel.webview.postMessage() で送るメッセージを再現する。 */ export async function sendExtMessage(msg: HostToUIMessage): Promise { await act(async () => { From b9398d45ff471c1c493d026c2cdb8b1d7357b5f3 Mon Sep 17 00:00:00 2001 From: ktmage Date: Sat, 9 May 2026 22:17:23 +0900 Subject: [PATCH 25/25] =?UTF-8?q?=E5=88=86=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/chat-handlers/context.ts | 27 + extension/chat-handlers/init.ts | 50 ++ extension/chat-handlers/messaging.ts | 96 ++++ extension/chat-handlers/meta.ts | 76 +++ extension/chat-handlers/session.ts | 119 +++++ extension/chat-handlers/utils.ts | 18 + extension/chat-handlers/vscode-actions.ts | 94 ++++ extension/chat-panel.ts | 599 ++++------------------ 8 files changed, 588 insertions(+), 491 deletions(-) create mode 100644 extension/chat-handlers/context.ts create mode 100644 extension/chat-handlers/init.ts create mode 100644 extension/chat-handlers/messaging.ts create mode 100644 extension/chat-handlers/meta.ts create mode 100644 extension/chat-handlers/session.ts create mode 100644 extension/chat-handlers/utils.ts create mode 100644 extension/chat-handlers/vscode-actions.ts diff --git a/extension/chat-handlers/context.ts b/extension/chat-handlers/context.ts new file mode 100644 index 0000000..40a385a --- /dev/null +++ b/extension/chat-handlers/context.ts @@ -0,0 +1,27 @@ +import type { OpencodeClient } from "@opencode-ai/sdk/v2"; +import type { ChatSession, HostToUIMessage, UIToHostMessage } from "@shared"; +import type { DifitHandle } from "../difit-handle"; +import type { OpenCodeClientHandle } from "../opencode-client-handle"; + +/** + * 個別のメッセージハンドラーが共通で使うコンテキスト。 + * `ChatPanel.handleWebviewMessageInner` がリクエストごとに組み立てて渡す。 + */ +export interface ChatHandlerContext { + /** 接続済みの OpenCode SDK クライアント。 */ + readonly client: OpencodeClient; + /** OpenCode サーバーの URL 取得など、クライアント以外の用途用。 */ + readonly openCodeClientHandle: OpenCodeClientHandle; + readonly difitHandle: DifitHandle; + /** path 解決などで使うワークスペースフォルダの絶対パス。 */ + readonly workspaceFolder: string; + /** Webview にメッセージを送信する。 */ + postMessage(message: HostToUIMessage): void; + /** UI 側で持つ「現在アクティブなセッション」状態の取得。 */ + getActiveSession(): ChatSession | null; + /** UI 側で持つ「現在アクティブなセッション」状態の更新。 */ + setActiveSession(session: ChatSession | null): void; +} + +/** `UIToHostMessage` の中から特定 `type` のメッセージだけを取り出すユーティリティ型。 */ +export type Msg = Extract; diff --git a/extension/chat-handlers/init.ts b/extension/chat-handlers/init.ts new file mode 100644 index 0000000..bf91278 --- /dev/null +++ b/extension/chat-handlers/init.ts @@ -0,0 +1,50 @@ +import * as fs from "node:fs/promises"; +import * as path from "node:path"; +import type { AllProvidersData, AppPaths, ChatSession, ProviderInfo } from "@shared"; +import * as vscode from "vscode"; +import type { ChatHandlerContext } from "./context"; +import { getActiveEditorFile } from "./utils"; + +/** + * Webview の初期化完了通知に応じて、UI が起動時に必要とする情報を一括送信する。 + */ +export async function ready(ctx: ChatHandlerContext): Promise { + const { client, postMessage } = ctx; + + const paths = (await client.path.get()).data! as unknown as AppPaths; + postMessage({ + type: "init", + locale: vscode.env.language, + paths, + }); + + const sessions = (await client.session.list()).data! as unknown as ChatSession[]; + postMessage({ type: "sessions", sessions }); + postMessage({ type: "activeSession", session: ctx.getActiveSession() }); + + const [providersResponse, allProvidersResponse] = await Promise.all([ + client.config.providers(), + client.provider.list(), + ]); + const providersData = providersResponse.data!; + const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; + + // config ファイルから model を直接読み取る(config.get API は model を正しく返さない) + let configModel: string | undefined; + try { + const raw = await fs.readFile(path.join(paths.config, "opencode.json"), "utf-8"); + configModel = JSON.parse(raw).model; + } catch { + // ファイルが存在しない場合は undefined のまま + } + postMessage({ + type: "providers", + providers: providersData.providers as unknown as ProviderInfo[], + allProviders, + default: providersData.default, + configModel, + }); + + postMessage({ type: "activeEditor", file: getActiveEditorFile(vscode.window.activeTextEditor) }); + postMessage({ type: "difitAvailable", available: ctx.difitHandle.isAvailable() }); +} diff --git a/extension/chat-handlers/messaging.ts b/extension/chat-handlers/messaging.ts new file mode 100644 index 0000000..adae67f --- /dev/null +++ b/extension/chat-handlers/messaging.ts @@ -0,0 +1,96 @@ +import * as path from "node:path"; +import type { ChatMessageWithParts, ChatSession, SendMessageOptions } from "@shared"; +import type { ChatHandlerContext, Msg } from "./context"; + +type PromptPart = + | { type: "text"; text: string; synthetic?: boolean } + | { type: "file"; mime: string; url: string; filename: string } + | { type: "agent"; name: string }; + +/** prompt 送信用のパーツ配列を組み立てる。 */ +function toPromptParts(text: string, workspaceFolder: string, options?: SendMessageOptions): PromptPart[] { + const parts: PromptPart[] = []; + + if (options?.skill) { + parts.push({ type: "text", text: `/${options.skill}`, synthetic: true }); + } + + parts.push({ type: "text", text }); + + if (options?.files) { + for (const file of options.files) { + const absPath = path.isAbsolute(file.filePath) ? file.filePath : path.resolve(workspaceFolder, file.filePath); + parts.push({ + type: "file", + mime: "text/plain", + url: `file://${absPath}`, + filename: file.fileName, + }); + } + } + + if (options?.agent) { + parts.push({ type: "agent", name: options.agent }); + } + + return parts; +} + +export async function sendMessage(ctx: ChatHandlerContext, msg: Msg<"sendMessage">): Promise { + await ctx.client.session.promptAsync({ + sessionID: msg.sessionId, + parts: toPromptParts(msg.text, ctx.workspaceFolder, { + model: msg.model, + files: msg.files, + agent: msg.agent, + primaryAgent: msg.primaryAgent, + skill: msg.skill, + }), + model: msg.model, + agent: msg.primaryAgent, + }); +} + +export async function editAndResend(ctx: ChatHandlerContext, msg: Msg<"editAndResend">): Promise { + // 1. 指定メッセージまで巻き戻す(そのメッセージ以降を削除) + const session = (await ctx.client.session.revert({ sessionID: msg.sessionId, messageID: msg.messageId })) + .data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); + // 2. 編集後のテキストを送信 + await ctx.client.session.promptAsync({ + sessionID: msg.sessionId, + parts: toPromptParts(msg.text, ctx.workspaceFolder, { model: msg.model, files: msg.files }), + model: msg.model, + agent: undefined, + }); +} + +export async function executeShell(ctx: ChatHandlerContext, msg: Msg<"executeShell">): Promise { + await ctx.client.session.shell({ + sessionID: msg.sessionId, + agent: "default", + command: msg.command, + model: msg.model, + }); +} + +export async function abort(ctx: ChatHandlerContext, msg: Msg<"abort">): Promise { + await ctx.client.session.abort({ sessionID: msg.sessionId }); +} + +export async function replyPermission(ctx: ChatHandlerContext, msg: Msg<"replyPermission">): Promise { + await ctx.client.permission.reply({ requestID: msg.permissionId, reply: msg.response }); +} + +export async function replyQuestion(ctx: ChatHandlerContext, msg: Msg<"replyQuestion">): Promise { + await ctx.client.question.reply({ requestID: msg.requestId, answers: msg.answers }); +} + +export async function rejectQuestion(ctx: ChatHandlerContext, msg: Msg<"rejectQuestion">): Promise { + await ctx.client.question.reject({ requestID: msg.requestId }); +} + diff --git a/extension/chat-handlers/meta.ts b/extension/chat-handlers/meta.ts new file mode 100644 index 0000000..b1f1704 --- /dev/null +++ b/extension/chat-handlers/meta.ts @@ -0,0 +1,76 @@ +import * as fs from "node:fs/promises"; +import * as path from "node:path"; +import type { OpencodeClient } from "@opencode-ai/sdk/v2"; +import type { AgentInfo, AllProvidersData, AppPaths, ProviderInfo, SkillInfo } from "@shared"; +import * as vscode from "vscode"; +import type { ChatHandlerContext, Msg } from "./context"; + +/** opencode.json に model を書き込む。ファイルが無ければ新規作成する。 */ +async function setConfiguredModel(client: OpencodeClient, model: string): Promise { + const paths = (await client.path.get()).data! as unknown as AppPaths; + const configFilePath = path.join(paths.config, "opencode.json"); + let configJson: Record = {}; + try { + const raw = await fs.readFile(configFilePath, "utf-8"); + configJson = JSON.parse(raw); + } catch { + // File may not exist yet. + } + configJson.model = model; + await fs.mkdir(path.dirname(configFilePath), { recursive: true }); + await fs.writeFile(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); +} + +export async function getProviders(ctx: ChatHandlerContext): Promise { + const [providersResponse, allProvidersResponse, pathsResponse] = await Promise.all([ + ctx.client.config.providers(), + ctx.client.provider.list(), + ctx.client.path.get(), + ]); + const providersData = providersResponse.data!; + const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; + const paths = pathsResponse.data! as unknown as AppPaths; + let configModel: string | undefined; + try { + const raw = await fs.readFile(path.join(paths.config, "opencode.json"), "utf-8"); + configModel = JSON.parse(raw).model; + } catch { + // ignore + } + ctx.postMessage({ + type: "providers", + providers: providersData.providers as unknown as ProviderInfo[], + allProviders, + default: providersData.default, + configModel, + }); +} + +export async function getAgents(ctx: ChatHandlerContext): Promise { + const agents = (await ctx.client.app.agents()).data! as unknown as AgentInfo[]; + ctx.postMessage({ type: "agents", agents }); +} + +export async function getSkills(ctx: ChatHandlerContext): Promise { + const skills = (await ctx.client.app.skills()).data! as unknown as SkillInfo[]; + ctx.postMessage({ type: "skills", skills }); +} + +export async function setModel(ctx: ChatHandlerContext, msg: Msg<"setModel">): Promise { + await setConfiguredModel(ctx.client, msg.model); + ctx.postMessage({ type: "modelUpdated", model: msg.model, default: {} }); +} + +/** 設定ファイルを開く。存在しない場合は初期内容で新規作成する。 */ +export async function openConfigFile(_ctx: ChatHandlerContext, msg: Msg<"openConfigFile">): Promise { + const uri = vscode.Uri.file(msg.filePath); + try { + await vscode.workspace.fs.stat(uri); + } catch { + const dir = vscode.Uri.file(msg.filePath.substring(0, msg.filePath.lastIndexOf("/"))); + await vscode.workspace.fs.createDirectory(dir); + await vscode.workspace.fs.writeFile(uri, Buffer.from('{\n "$schema": "https://opencode.ai/config.json"\n}\n')); + } + const doc = await vscode.workspace.openTextDocument(uri); + await vscode.window.showTextDocument(doc); +} diff --git a/extension/chat-handlers/session.ts b/extension/chat-handlers/session.ts new file mode 100644 index 0000000..8a48fa8 --- /dev/null +++ b/extension/chat-handlers/session.ts @@ -0,0 +1,119 @@ +import type { ChatMessageWithParts, ChatSession, FileDiff, TodoItem } from "@shared"; +import * as vscode from "vscode"; +import type { ChatHandlerContext, Msg } from "./context"; + +export async function createSession(ctx: ChatHandlerContext, msg: Msg<"createSession">): Promise { + const session = (await ctx.client.session.create({ title: msg.title })).data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const sessions = (await ctx.client.session.list()).data! as unknown as ChatSession[]; + ctx.postMessage({ type: "sessions", sessions }); +} + +export async function listSessions(ctx: ChatHandlerContext): Promise { + const sessions = (await ctx.client.session.list()).data! as unknown as ChatSession[]; + ctx.postMessage({ type: "sessions", sessions }); +} + +export async function selectSession(ctx: ChatHandlerContext, msg: Msg<"selectSession">): Promise { + const session = (await ctx.client.session.get({ sessionID: msg.sessionId })).data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); +} + +export async function deleteSession(ctx: ChatHandlerContext, msg: Msg<"deleteSession">): Promise { + await ctx.client.session.delete({ sessionID: msg.sessionId }); + if (ctx.getActiveSession()?.id === msg.sessionId) { + ctx.setActiveSession(null); + ctx.postMessage({ type: "activeSession", session: null }); + } + const sessions = (await ctx.client.session.list()).data! as unknown as ChatSession[]; + ctx.postMessage({ type: "sessions", sessions }); +} + +export async function getMessages(ctx: ChatHandlerContext, msg: Msg<"getMessages">): Promise { + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); +} + +export async function compressSession(ctx: ChatHandlerContext, msg: Msg<"compressSession">): Promise { + await ctx.client.session.summarize({ + sessionID: msg.sessionId, + providerID: msg.model?.providerID, + modelID: msg.model?.modelID, + }); +} + +export async function revertToMessage(ctx: ChatHandlerContext, msg: Msg<"revertToMessage">): Promise { + const session = (await ctx.client.session.revert({ sessionID: msg.sessionId, messageID: msg.messageId })) + .data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); +} + +export async function forkSession(ctx: ChatHandlerContext, msg: Msg<"forkSession">): Promise { + const forked = (await ctx.client.session.fork({ sessionID: msg.sessionId, messageID: msg.messageId })) + .data! as unknown as ChatSession; + ctx.setActiveSession(forked); + ctx.postMessage({ type: "activeSession", session: forked }); + const sessions = (await ctx.client.session.list()).data! as unknown as ChatSession[]; + ctx.postMessage({ type: "sessions", sessions }); +} + +export async function getSessionDiff(ctx: ChatHandlerContext, msg: Msg<"getSessionDiff">): Promise { + const diffs = (await ctx.client.session.diff({ sessionID: msg.sessionId })).data! as unknown as FileDiff[]; + ctx.postMessage({ type: "sessionDiff", sessionId: msg.sessionId, diffs }); +} + +export async function getSessionTodos(ctx: ChatHandlerContext, msg: Msg<"getSessionTodos">): Promise { + const todos = (await ctx.client.session.todo({ sessionID: msg.sessionId })).data! as unknown as TodoItem[]; + ctx.postMessage({ type: "sessionTodos", sessionId: msg.sessionId, todos }); +} + +export async function getChildSessions(ctx: ChatHandlerContext, msg: Msg<"getChildSessions">): Promise { + const children = (await ctx.client.session.children({ sessionID: msg.sessionId })) + .data! as unknown as ChatSession[]; + ctx.postMessage({ type: "childSessions", sessionId: msg.sessionId, children }); +} + +export async function shareSession(ctx: ChatHandlerContext, msg: Msg<"shareSession">): Promise { + const session = (await ctx.client.session.share({ sessionID: msg.sessionId })).data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + // 共有 URL をクリップボードにコピーする + if (session.share?.url) { + await vscode.env.clipboard.writeText(session.share.url); + } +} + +export async function unshareSession(ctx: ChatHandlerContext, msg: Msg<"unshareSession">): Promise { + const session = (await ctx.client.session.unshare({ sessionID: msg.sessionId })).data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); +} + +export async function undoSession(ctx: ChatHandlerContext, msg: Msg<"undoSession">): Promise { + const session = (await ctx.client.session.revert({ sessionID: msg.sessionId, messageID: msg.messageId })) + .data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); +} + +export async function redoSession(ctx: ChatHandlerContext, msg: Msg<"redoSession">): Promise { + const session = (await ctx.client.session.unrevert({ sessionID: msg.sessionId })).data! as unknown as ChatSession; + ctx.setActiveSession(session); + ctx.postMessage({ type: "activeSession", session }); + const messages = (await ctx.client.session.messages({ sessionID: msg.sessionId })) + .data! as unknown as ChatMessageWithParts[]; + ctx.postMessage({ type: "messages", sessionId: msg.sessionId, messages }); +} diff --git a/extension/chat-handlers/utils.ts b/extension/chat-handlers/utils.ts new file mode 100644 index 0000000..00622dd --- /dev/null +++ b/extension/chat-handlers/utils.ts @@ -0,0 +1,18 @@ +import * as path from "node:path"; +import type { FileAttachment } from "@shared"; +import * as vscode from "vscode"; + +/** + * アクティブなテキストエディタから FileAttachment を生成する。 + * エディタが無い、または file スキーム以外(出力パネル等)の場合は null を返す。 + */ +export function getActiveEditorFile(editor: vscode.TextEditor | undefined): FileAttachment | null { + if (!editor) return null; + const uri = editor.document.uri; + if (uri.scheme !== "file") return null; + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; + const relativePath = workspaceFolder + ? path.relative(workspaceFolder.fsPath, uri.fsPath) + : path.basename(uri.fsPath); + return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; +} diff --git a/extension/chat-handlers/vscode-actions.ts b/extension/chat-handlers/vscode-actions.ts new file mode 100644 index 0000000..eea0422 --- /dev/null +++ b/extension/chat-handlers/vscode-actions.ts @@ -0,0 +1,94 @@ +import * as path from "node:path"; +import type { FileAttachment, FileDiff } from "@shared"; +import * as vscode from "vscode"; +import type { ChatHandlerContext, Msg } from "./context"; + +/** 現在開かれているテキストエディタの一覧を取得する(重複除去あり)。 */ +export async function getOpenEditors(ctx: ChatHandlerContext): Promise { + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; + const files = vscode.window.tabGroups.all + .flatMap((group) => group.tabs) + .filter((tab) => tab.input instanceof vscode.TabInputText) + .map((tab): FileAttachment => { + const uri = (tab.input as vscode.TabInputText).uri; + const relativePath = workspaceFolder + ? path.relative(workspaceFolder.fsPath, uri.fsPath) + : path.basename(uri.fsPath); + return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; + }) + .filter((f, i, arr) => arr.findIndex((a) => a.filePath === f.filePath) === i); + ctx.postMessage({ type: "openEditors", files }); +} + +/** ワークスペース内のファイルを部分一致で検索する。 */ +export async function searchWorkspaceFiles(ctx: ChatHandlerContext, msg: Msg<"searchWorkspaceFiles">): Promise { + const pattern = msg.query ? `**/*${msg.query}*` : "**/*"; + const uris = await vscode.workspace.findFiles(pattern, "**/node_modules/**", 20); + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; + const files = uris.map((uri): FileAttachment => { + const relativePath = workspaceFolder + ? path.relative(workspaceFolder.fsPath, uri.fsPath) + : path.basename(uri.fsPath); + return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; + }); + ctx.postMessage({ type: "workspaceFiles", files }); +} + +/** OpenCode サーバーへ attach するためのターミナルを開く。 */ +export async function openTerminal(ctx: ChatHandlerContext): Promise { + const serverUrl = ctx.openCodeClientHandle.getServerUrl(); + if (!serverUrl) return; + const args = ["attach", serverUrl]; + const sessionId = ctx.getActiveSession()?.id; + if (sessionId) { + args.push("--session", sessionId); + } + const wsFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + const terminal = vscode.window.createTerminal({ name: "OpenCode", cwd: wsFolder }); + terminal.show(); + terminal.sendText(`opencode ${args.map((a) => JSON.stringify(a)).join(" ")}`); +} + +/** 仮想ドキュメントを使って VS Code のネイティブ diff エディタを開く。 */ +export async function openDiffEditor(_ctx: ChatHandlerContext, msg: Msg<"openDiffEditor">): Promise { + const beforeUri = vscode.Uri.parse(`opencode-diff-before:${msg.filePath}?${encodeURIComponent(msg.before)}`); + const afterUri = vscode.Uri.parse(`opencode-diff-after:${msg.filePath}?${encodeURIComponent(msg.after)}`); + const fileName = path.basename(msg.filePath); + await vscode.commands.executeCommand("vscode.diff", beforeUri, afterUri, `${fileName} (Changes)`); +} + +/** ファイルを開く。`line` 指定時は該当行へジャンプする。 */ +export async function openFile(_ctx: ChatHandlerContext, msg: Msg<"openFile">): Promise { + const uri = vscode.Uri.file(msg.filePath); + const doc = await vscode.workspace.openTextDocument(uri); + const editor = await vscode.window.showTextDocument(doc); + if (msg.line !== undefined && msg.line >= 1) { + const position = new vscode.Position(msg.line - 1, 0); + editor.selection = new vscode.Selection(position, position); + editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); + } +} + +export async function copyToClipboard(_ctx: ChatHandlerContext, msg: Msg<"copyToClipboard">): Promise { + await vscode.env.clipboard.writeText(msg.text); +} + +export async function openDiffReview(ctx: ChatHandlerContext, msg: Msg<"openDiffReview">): Promise { + const session = ctx.getActiveSession(); + if (!session) return; + try { + const diffs = (await ctx.client.session.diff({ sessionID: session.id })).data! as unknown as FileDiff[]; + if (diffs.length === 0) return; + await ctx.difitHandle.start(diffs, msg.focusFile); + ctx.postMessage({ type: "diffReviewStarted" }); + } catch (e) { + const errorMsg = e instanceof Error ? e.message : String(e); + console.error("[openDiffReview]", errorMsg); + ctx.postMessage({ type: "diffReviewError", error: errorMsg }); + } +} + +export async function stopDiffReview(ctx: ChatHandlerContext): Promise { + ctx.difitHandle.stop(); + ctx.postMessage({ type: "diffReviewStopped" }); +} diff --git a/extension/chat-panel.ts b/extension/chat-panel.ts index 449f3b4..cbfaee8 100644 --- a/extension/chat-panel.ts +++ b/extension/chat-panel.ts @@ -1,24 +1,20 @@ -import * as fs from "node:fs/promises"; -import * as path from "node:path"; -import type { - AgentInfo, - AllProvidersData, - AppPaths, - ChatMessageWithParts, - ChatSession, - FileAttachment, - FileDiff, - HostToUIMessage, - ProviderInfo, - SendMessageOptions, - SkillInfo, - TodoItem, - UIToHostMessage, -} from "@shared"; +import type { ChatSession, HostToUIMessage, UIToHostMessage } from "@shared"; import * as vscode from "vscode"; +import type { ChatHandlerContext } from "./chat-handlers/context"; +import * as init from "./chat-handlers/init"; +import * as messaging from "./chat-handlers/messaging"; +import * as meta from "./chat-handlers/meta"; +import * as session from "./chat-handlers/session"; +import { getActiveEditorFile } from "./chat-handlers/utils"; +import * as vscodeActions from "./chat-handlers/vscode-actions"; import type { DifitHandle } from "./difit-handle"; import type { OpenCodeClientHandle } from "./opencode-client-handle"; +/** + * OpenCode のチャット UI を表示するサイドバーパネル。 + * Webview のライフサイクル管理と、UI から受信したメッセージを各ハンドラーへ振り分ける役割を持つ。 + * 個々の処理は `chat-handlers/` 配下のモジュールに分離されている。 + */ export class ChatPanel implements vscode.WebviewViewProvider { public static readonly viewType = "opencode.chatView"; @@ -58,493 +54,114 @@ export class ChatPanel implements vscode.WebviewViewProvider { // アクティブエディタが変わるたびに Webview に通知する // (プッシュ型通知はメッセージルーターの責務として残す) vscode.window.onDidChangeActiveTextEditor((editor) => { - this.postMessage({ type: "activeEditor", file: this.getActiveEditorFile(editor) }); + this.postMessage({ type: "activeEditor", file: getActiveEditorFile(editor) }); }); } private async handleWebviewMessage(message: UIToHostMessage): Promise { try { - await this.handleWebviewMessageInner(message); + await this.dispatch(message); } catch (err) { console.error(`[OpenCode] Error handling message '${message.type}':`, err); } } - private async handleWebviewMessageInner(message: UIToHostMessage): Promise { - const client = this.openCodeClientHandle.getClient(); + private async dispatch(message: UIToHostMessage): Promise { + const ctx: ChatHandlerContext = { + client: this.openCodeClientHandle.getClient(), + openCodeClientHandle: this.openCodeClientHandle, + difitHandle: this.difitHandle, + workspaceFolder: this.workspaceFolder, + postMessage: (msg) => this.postMessage(msg), + getActiveSession: () => this.activeSession, + setActiveSession: (s) => { + this.activeSession = s; + }, + }; switch (message.type) { - case "ready": { - // Webview の初期化完了時に init メッセージを送信する(locale + toolConfig を統合) - const paths = (await client.path.get()).data! as unknown as AppPaths; - this.postMessage({ - type: "init", - locale: vscode.env.language, - paths, - }); - // セッション一覧、現在のセッション、プロバイダー一覧を送信する - const sessions = (await client.session.list()).data! as unknown as ChatSession[]; - this.postMessage({ type: "sessions", sessions }); - this.postMessage({ type: "activeSession", session: this.activeSession }); - const [providersResponse, allProvidersResponse] = await Promise.all([ - client.config.providers(), - client.provider.list(), - ]); - const providersData = providersResponse.data!; - const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; - // config ファイルから model を直接読み取る(config.get API は model を正しく返さない) - let configModel: string | undefined; - try { - const raw = await fs.readFile(path.join(paths.config, "opencode.json"), "utf-8"); - const configJson = JSON.parse(raw); - configModel = configJson.model; - } catch { - // ファイルが存在しない場合は undefined のまま - } - this.postMessage({ - type: "providers", - providers: providersData.providers as unknown as ProviderInfo[], - allProviders, - default: providersData.default, - configModel, - }); - // 初期アクティブエディタを送信する - this.postMessage({ type: "activeEditor", file: this.getActiveEditorFile(vscode.window.activeTextEditor) }); - // difit の利用可否を Webview に通知する - this.postMessage({ type: "difitAvailable", available: this.difitHandle.isAvailable() }); - break; - } - case "sendMessage": { - await client.session.promptAsync({ - sessionID: message.sessionId, - parts: this.toPromptParts(message.text, { - model: message.model, - files: message.files, - agent: message.agent, - primaryAgent: message.primaryAgent, - skill: message.skill, - }), - model: message.model, - agent: message.primaryAgent, - }); - break; - } - case "createSession": { - const session = (await client.session.create({ title: message.title })).data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const sessions = (await client.session.list()).data! as unknown as ChatSession[]; - this.postMessage({ type: "sessions", sessions }); - break; - } - case "listSessions": { - const sessions = (await client.session.list()).data! as unknown as ChatSession[]; - this.postMessage({ type: "sessions", sessions }); - break; - } - case "selectSession": { - const session = (await client.session.get({ sessionID: message.sessionId })).data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const messages = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); - break; - } - case "deleteSession": { - await client.session.delete({ sessionID: message.sessionId }); - if (this.activeSession?.id === message.sessionId) { - this.activeSession = null; - this.postMessage({ type: "activeSession", session: null }); - } - const sessions = (await client.session.list()).data! as unknown as ChatSession[]; - this.postMessage({ type: "sessions", sessions }); - break; - } - case "getMessages": { - const messages = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); - break; - } - case "replyPermission": { - await client.permission.reply({ requestID: message.permissionId, reply: message.response }); - break; - } - case "replyQuestion": { - await client.question.reply({ requestID: message.requestId, answers: message.answers }); - break; - } - case "rejectQuestion": { - await client.question.reject({ requestID: message.requestId }); - break; - } - case "abort": { - await client.session.abort({ sessionID: message.sessionId }); - break; - } - case "getProviders": { - const [providersResponse, allProvidersResponse, pathsResponse] = await Promise.all([ - client.config.providers(), - client.provider.list(), - client.path.get(), - ]); - const providersData = providersResponse.data!; - const allProviders = allProvidersResponse.data! as unknown as AllProvidersData; - const paths = pathsResponse.data! as unknown as AppPaths; - let configModel: string | undefined; - try { - const raw = await fs.readFile(path.join(paths.config, "opencode.json"), "utf-8"); - configModel = JSON.parse(raw).model; - } catch { - // ignore - } - this.postMessage({ - type: "providers", - providers: providersData.providers as unknown as ProviderInfo[], - allProviders, - default: providersData.default, - configModel, - }); - break; - } - // --- Platform operations --- - case "getOpenEditors": { - const files = await this.getOpenEditors(); - this.postMessage({ type: "openEditors", files }); - break; - } - case "searchWorkspaceFiles": { - const files = await this.searchWorkspaceFiles(message.query); - this.postMessage({ type: "workspaceFiles", files }); - break; - } - case "compressSession": { - await client.session.summarize({ - sessionID: message.sessionId, - providerID: message.model?.providerID, - modelID: message.model?.modelID, - }); - break; - } - case "revertToMessage": { - const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) - .data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const messages = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); - break; - } - case "editAndResend": { - // 1. 指定メッセージまで巻き戻す(そのメッセージ以降を削除) - const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) - .data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const msgs = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages: msgs }); - // 2. 編集後のテキストを送信 - await client.session.promptAsync({ - sessionID: message.sessionId, - parts: this.toPromptParts(message.text, { - model: message.model, - files: message.files, - }), - model: message.model, - agent: undefined, - }); - break; - } - case "executeShell": { - await client.session.shell({ - sessionID: message.sessionId, - agent: "default", - command: message.command, - model: message.model, - }); - break; - } - case "openConfigFile": { - await this.openConfigFile(message.filePath); - break; - } - case "openTerminal": { - const serverUrl = this.openCodeClientHandle.getServerUrl(); - if (!serverUrl) break; - await this.openTerminal(serverUrl, this.activeSession?.id); - break; - } - case "setModel": { - await this.setConfiguredModel(message.model); - this.postMessage({ type: "modelUpdated", model: message.model, default: {} }); - break; - } - case "forkSession": { - // Fork で新しいセッションを作成し、アクティブセッションを切り替える - const forkedSession = (await client.session.fork({ - sessionID: message.sessionId, - messageID: message.messageId, - })).data! as unknown as ChatSession; - this.activeSession = forkedSession; - this.postMessage({ type: "activeSession", session: forkedSession }); - const forkedSessions = (await client.session.list()).data! as unknown as ChatSession[]; - this.postMessage({ type: "sessions", sessions: forkedSessions }); - break; - } - case "getSessionDiff": { - const diffs = (await client.session.diff({ sessionID: message.sessionId })).data! as unknown as FileDiff[]; - this.postMessage({ type: "sessionDiff", sessionId: message.sessionId, diffs }); - break; - } - case "getSessionTodos": { - const todos = (await client.session.todo({ sessionID: message.sessionId })).data! as unknown as TodoItem[]; - this.postMessage({ type: "sessionTodos", sessionId: message.sessionId, todos }); - break; - } - case "getChildSessions": { - const children = (await client.session.children({ sessionID: message.sessionId })) - .data! as unknown as ChatSession[]; - this.postMessage({ type: "childSessions", sessionId: message.sessionId, children }); - break; - } - case "getAgents": { - const agents = (await client.app.agents()).data! as unknown as AgentInfo[]; - this.postMessage({ type: "agents", agents }); - break; - } - case "getSkills": { - const skills = (await client.app.skills()).data! as unknown as SkillInfo[]; - this.postMessage({ type: "skills", skills }); - break; - } - case "shareSession": { - const session = (await client.session.share({ sessionID: message.sessionId })).data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - // 共有 URL をクリップボードにコピーする - if (session.share?.url) { - await this.copyToClipboard(session.share.url); - } - break; - } - case "unshareSession": { - const session = (await client.session.unshare({ sessionID: message.sessionId })) - .data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - break; - } - case "copyToClipboard": { - await this.copyToClipboard(message.text); - break; - } - case "undoSession": { - const session = (await client.session.revert({ sessionID: message.sessionId, messageID: message.messageId })) - .data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const messages = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); - break; - } - case "redoSession": { - const session = (await client.session.unrevert({ sessionID: message.sessionId })).data! as unknown as ChatSession; - this.activeSession = session; - this.postMessage({ type: "activeSession", session }); - const messages = (await client.session.messages({ sessionID: message.sessionId })) - .data! as unknown as ChatMessageWithParts[]; - this.postMessage({ type: "messages", sessionId: message.sessionId, messages }); - break; - } - case "openDiffEditor": { - await this.openDiffEditor(message.filePath, message.before, message.after); - break; - } - case "openFile": { - await this.openFile(message.filePath, message.line); - break; - } - case "openDiffReview": { - if (!this.activeSession) { - break; - } - try { - const diffs = (await client.session.diff({ sessionID: this.activeSession.id })).data! as unknown as FileDiff[]; - if (diffs.length === 0) { - break; - } - await this.difitHandle.start(diffs, message.focusFile); - this.postMessage({ type: "diffReviewStarted" }); - } catch (e) { - const errorMsg = e instanceof Error ? e.message : String(e); - console.error("[openDiffReview]", errorMsg); - this.postMessage({ type: "diffReviewError", error: errorMsg }); - } - break; - } - case "stopDiffReview": { - this.difitHandle.stop(); - this.postMessage({ type: "diffReviewStopped" }); - break; - } - } - } - - private toPromptParts( - text: string, - options?: SendMessageOptions, - ): Array< - | { type: "text"; text: string; synthetic?: boolean } - | { type: "file"; mime: string; url: string; filename: string } - | { type: "agent"; name: string } - > { - const parts: Array< - | { type: "text"; text: string; synthetic?: boolean } - | { type: "file"; mime: string; url: string; filename: string } - | { type: "agent"; name: string } - > = []; - - if (options?.skill) { - parts.push({ type: "text", text: `/${options.skill}`, synthetic: true }); - } - - parts.push({ type: "text", text }); - - if (options?.files) { - for (const file of options.files) { - const absPath = path.isAbsolute(file.filePath) - ? file.filePath - : path.resolve(this.workspaceFolder, file.filePath); - parts.push({ - type: "file", - mime: "text/plain", - url: `file://${absPath}`, - filename: file.fileName, - }); - } - } - - if (options?.agent) { - parts.push({ type: "agent", name: options.agent }); - } - - return parts; - } - - private async setConfiguredModel(model: string): Promise { - const client = this.openCodeClientHandle.getClient(); - const paths = (await client.path.get()).data! as unknown as AppPaths; - const configFilePath = path.join(paths.config, "opencode.json"); - let configJson: Record = {}; - try { - const raw = await fs.readFile(configFilePath, "utf-8"); - configJson = JSON.parse(raw); - } catch { - // File may not exist yet. - } - configJson.model = model; - await fs.mkdir(path.dirname(configFilePath), { recursive: true }); - await fs.writeFile(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); - } - - /** アクティブなテキストエディタから FileAttachment を生成する。エディタがない場合は null を返す。 */ - private getActiveEditorFile(editor: vscode.TextEditor | undefined): FileAttachment | null { - if (!editor) return null; - const uri = editor.document.uri; - // 出力パネルや設定画面など、file スキーム以外は対象外 - if (uri.scheme !== "file") return null; - const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; - const relativePath = workspaceFolder - ? path.relative(workspaceFolder.fsPath, uri.fsPath) - : path.basename(uri.fsPath); - return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; - } - - // --- VS Code API 呼び出し(webview 依頼の処理用) --- - - /** 仮想ドキュメントを使って VS Code のネイティブ diff エディタを開く。 */ - private async openDiffEditor(filePath: string, before: string, after: string): Promise { - const beforeUri = vscode.Uri.parse(`opencode-diff-before:${filePath}?${encodeURIComponent(before)}`); - const afterUri = vscode.Uri.parse(`opencode-diff-after:${filePath}?${encodeURIComponent(after)}`); - const fileName = path.basename(filePath); - await vscode.commands.executeCommand("vscode.diff", beforeUri, afterUri, `${fileName} (Changes)`); - } - - private async copyToClipboard(text: string): Promise { - await vscode.env.clipboard.writeText(text); - } - - private async openTerminal(serverUrl: string, sessionId?: string): Promise { - const args = ["attach", serverUrl]; - if (sessionId) { - args.push("--session", sessionId); + // --- 初期化 --- + case "ready": + return init.ready(ctx); + + // --- session 操作 --- + case "createSession": + return session.createSession(ctx, message); + case "listSessions": + return session.listSessions(ctx); + case "selectSession": + return session.selectSession(ctx, message); + case "deleteSession": + return session.deleteSession(ctx, message); + case "getMessages": + return session.getMessages(ctx, message); + case "compressSession": + return session.compressSession(ctx, message); + case "revertToMessage": + return session.revertToMessage(ctx, message); + case "forkSession": + return session.forkSession(ctx, message); + case "getSessionDiff": + return session.getSessionDiff(ctx, message); + case "getSessionTodos": + return session.getSessionTodos(ctx, message); + case "getChildSessions": + return session.getChildSessions(ctx, message); + case "shareSession": + return session.shareSession(ctx, message); + case "unshareSession": + return session.unshareSession(ctx, message); + case "undoSession": + return session.undoSession(ctx, message); + case "redoSession": + return session.redoSession(ctx, message); + + // --- メッセージ送信・割り込み --- + case "sendMessage": + return messaging.sendMessage(ctx, message); + case "editAndResend": + return messaging.editAndResend(ctx, message); + case "executeShell": + return messaging.executeShell(ctx, message); + case "abort": + return messaging.abort(ctx, message); + case "replyPermission": + return messaging.replyPermission(ctx, message); + case "replyQuestion": + return messaging.replyQuestion(ctx, message); + case "rejectQuestion": + return messaging.rejectQuestion(ctx, message); + + // --- 設定・メタ情報 --- + case "getProviders": + return meta.getProviders(ctx); + case "getAgents": + return meta.getAgents(ctx); + case "getSkills": + return meta.getSkills(ctx); + case "setModel": + return meta.setModel(ctx, message); + case "openConfigFile": + return meta.openConfigFile(ctx, message); + + // --- VS Code 操作 --- + case "getOpenEditors": + return vscodeActions.getOpenEditors(ctx); + case "searchWorkspaceFiles": + return vscodeActions.searchWorkspaceFiles(ctx, message); + case "openTerminal": + return vscodeActions.openTerminal(ctx); + case "openDiffEditor": + return vscodeActions.openDiffEditor(ctx, message); + case "openFile": + return vscodeActions.openFile(ctx, message); + case "copyToClipboard": + return vscodeActions.copyToClipboard(ctx, message); + case "openDiffReview": + return vscodeActions.openDiffReview(ctx, message); + case "stopDiffReview": + return vscodeActions.stopDiffReview(ctx); } - const wsFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; - const terminal = vscode.window.createTerminal({ - name: "OpenCode", - cwd: wsFolder, - }); - terminal.show(); - terminal.sendText(`opencode ${args.map((a) => JSON.stringify(a)).join(" ")}`); - } - - /** 設定ファイルを開く。存在しない場合は初期内容で新規作成する。 */ - private async openConfigFile(filePath: string): Promise { - const uri = vscode.Uri.file(filePath); - try { - await vscode.workspace.fs.stat(uri); - } catch { - const dir = vscode.Uri.file(filePath.substring(0, filePath.lastIndexOf("/"))); - await vscode.workspace.fs.createDirectory(dir); - await vscode.workspace.fs.writeFile(uri, Buffer.from('{\n "$schema": "https://opencode.ai/config.json"\n}\n')); - } - const doc = await vscode.workspace.openTextDocument(uri); - await vscode.window.showTextDocument(doc); - } - - /** ファイルを開く。`line` 指定時は該当行へジャンプする。 */ - private async openFile(filePath: string, line?: number): Promise { - const uri = vscode.Uri.file(filePath); - const doc = await vscode.workspace.openTextDocument(uri); - const editor = await vscode.window.showTextDocument(doc); - if (line !== undefined && line >= 1) { - const position = new vscode.Position(line - 1, 0); - editor.selection = new vscode.Selection(position, position); - editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); - } - } - - /** ワークスペース内のファイルを部分一致で検索する。 */ - private async searchWorkspaceFiles(query: string): Promise { - const pattern = query ? `**/*${query}*` : "**/*"; - const uris = await vscode.workspace.findFiles(pattern, "**/node_modules/**", 20); - const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; - return uris.map((uri) => { - const relativePath = workspaceFolder - ? path.relative(workspaceFolder.fsPath, uri.fsPath) - : path.basename(uri.fsPath); - return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; - }); - } - - /** 現在開かれているテキストエディタの一覧を取得する(重複除去あり)。 */ - private async getOpenEditors(): Promise { - const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri; - return vscode.window.tabGroups.all - .flatMap((group) => group.tabs) - .filter((tab) => tab.input instanceof vscode.TabInputText) - .map((tab) => { - const uri = (tab.input as vscode.TabInputText).uri; - const relativePath = workspaceFolder - ? path.relative(workspaceFolder.fsPath, uri.fsPath) - : path.basename(uri.fsPath); - return { filePath: relativePath, fileName: path.basename(uri.fsPath) }; - }) - .filter((f, i, arr) => arr.findIndex((a) => a.filePath === f.filePath) === i); } private postMessage(message: HostToUIMessage): void {