├── .bedrock-engineer
├── agents
│ └── developer-for-bedrock-engineer.yaml
└── rules
│ └── add-tool-instruction.md
├── .editorconfig
├── .env.example
├── .eslintignore
├── .eslintrc.cjs
├── .github
├── ISSUE_TEMPLATE
│ └── feature_request.md
└── workflows
│ └── build.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.yaml
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README-ja.md
├── README.md
├── assets
├── agent-chat-diagram.png
├── agent-chat-search.png
├── agent-directory.png
├── custom-agents.png
├── custom-tools.png
├── diagram-generator.png
├── select-agents.png
├── select-tools.png
├── step-functions-generator.png
├── voice-chat-page.png
├── website-generator-data-visualization.png
├── website-generator-healthcare.png
└── website-generator.png
├── build
├── entitlements.mac.plist
├── icon.icns
├── icon.ico
├── icon.iconset
│ ├── README.md
│ ├── icon_128x128.png
│ ├── icon_128x128@2x.png
│ ├── icon_16x16.png
│ ├── icon_16x16@2x.png
│ ├── icon_256x256.png
│ ├── icon_256x256@2x.png
│ ├── icon_32x32.png
│ ├── icon_32x32@2x.png
│ ├── icon_512x512.png
│ └── icon_512x512@2x.png
├── icon.png
└── make-icon.sh
├── dev-app-update.yml
├── electron-builder.yml
├── electron.vite.config.ts
├── jest.config.js
├── jest.integration.config.js
├── jest.integration.setup.js
├── package-lock.json
├── package.json
├── src
├── common
│ └── logger
│ │ ├── config.ts
│ │ ├── formatters.ts
│ │ ├── index.ts
│ │ └── transports
│ │ ├── console.ts
│ │ └── file.ts
├── main
│ ├── api
│ │ ├── bedrock
│ │ │ ├── __tests__
│ │ │ │ ├── agentService.integration.test.ts
│ │ │ │ ├── flowService.integration.test.ts
│ │ │ │ ├── guardrailService.integration.test.ts
│ │ │ │ ├── imageService.integration.test.ts
│ │ │ │ └── test-assets
│ │ │ │ │ └── icon.png
│ │ │ ├── client.ts
│ │ │ ├── index.ts
│ │ │ ├── models.ts
│ │ │ ├── services
│ │ │ │ ├── agentService.ts
│ │ │ │ ├── converseService.ts
│ │ │ │ ├── flowService.ts
│ │ │ │ ├── guardrailService.ts
│ │ │ │ ├── imageRecognitionService.ts
│ │ │ │ ├── imageService.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── modelService.ts
│ │ │ │ └── translateService.ts
│ │ │ ├── types.ts
│ │ │ ├── types
│ │ │ │ ├── claude.ts
│ │ │ │ └── image.ts
│ │ │ └── utils
│ │ │ │ ├── awsUtils.ts
│ │ │ │ └── imageUtils.ts
│ │ ├── command
│ │ │ ├── commandService.ts
│ │ │ └── types.ts
│ │ ├── index.ts
│ │ └── sonic
│ │ │ ├── SONIC_TOOL_INTEGRATION.md
│ │ │ ├── client.ts
│ │ │ ├── consts.ts
│ │ │ ├── tool-executor
│ │ │ ├── SonicToolExecutor.ts
│ │ │ └── index.ts
│ │ │ └── types.ts
│ ├── handlers
│ │ ├── agent-handlers.ts
│ │ ├── bedrock-handlers.ts
│ │ ├── file-handlers.ts
│ │ ├── util-handlers.ts
│ │ └── window-handlers.ts
│ ├── index.ts
│ ├── lib
│ │ └── ipc-handler.ts
│ └── store
│ │ └── chatSession.ts
├── preload
│ ├── api.ts
│ ├── appWindow.ts
│ ├── chat-history.ts
│ ├── file.ts
│ ├── helpers
│ │ └── agent-helpers.ts
│ ├── index.ts
│ ├── ipc-client.ts
│ ├── lib
│ │ ├── contentChunker.ts
│ │ ├── gitignore-like-matcher.test.ts
│ │ ├── gitignore-like-matcher.ts
│ │ ├── line-range-utils.ts
│ │ └── random-port.ts
│ ├── logger.ts
│ ├── mcp
│ │ ├── claude_desktop_config.sample.json
│ │ ├── command-resolver.ts
│ │ ├── index.integration.test.ts
│ │ ├── index.test.ts
│ │ ├── index.ts
│ │ ├── mcp-client.integration.test.ts
│ │ └── mcp-client.ts
│ ├── store.ts
│ └── tools
│ │ ├── base
│ │ ├── BaseTool.ts
│ │ ├── errors.ts
│ │ └── types.ts
│ │ ├── common
│ │ ├── Logger.ts
│ │ ├── StoreManager.ts
│ │ └── ToolMetadataHelper.ts
│ │ ├── handlers
│ │ ├── bedrock
│ │ │ ├── GenerateImageTool.ts
│ │ │ ├── InvokeBedrockAgentTool.ts
│ │ │ ├── InvokeFlowTool.ts
│ │ │ ├── RecognizeImageTool.ts
│ │ │ ├── RetrieveTool.ts
│ │ │ └── index.ts
│ │ ├── command
│ │ │ ├── ExecuteCommandTool.ts
│ │ │ └── index.ts
│ │ ├── filesystem
│ │ │ ├── ApplyDiffEditTool.ts
│ │ │ ├── CopyFileTool.ts
│ │ │ ├── CreateFolderTool.ts
│ │ │ ├── ListFilesTool.ts
│ │ │ ├── MoveFileTool.ts
│ │ │ ├── ReadFilesTool.ts
│ │ │ ├── WriteToFileTool.ts
│ │ │ └── index.ts
│ │ ├── interpreter
│ │ │ ├── CodeInterpreterTool.integration.test.ts
│ │ │ ├── CodeInterpreterTool.test.ts
│ │ │ ├── CodeInterpreterTool.ts
│ │ │ ├── DockerExecutor.integration.test.ts
│ │ │ ├── DockerExecutor.test.ts
│ │ │ ├── DockerExecutor.ts
│ │ │ ├── FileManager.ts
│ │ │ ├── SecurityManager.ts
│ │ │ ├── TaskManager.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── mcp
│ │ │ ├── McpToolAdapter.ts
│ │ │ └── index.ts
│ │ ├── thinking
│ │ │ ├── ThinkTool.ts
│ │ │ └── index.ts
│ │ └── web
│ │ │ ├── FetchWebsiteTool.ts
│ │ │ ├── TavilySearchTool.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── registry.ts
├── renderer
│ ├── index.css
│ ├── index.html
│ ├── public
│ │ └── worklets
│ │ │ └── audio-player-processor.js
│ └── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ ├── base.css
│ │ ├── directory-agents
│ │ │ ├── amazon-bedrock-agents-builder.yaml
│ │ │ ├── aws-cost-analyzer.yaml
│ │ │ ├── aws-document-researcher.yaml
│ │ │ ├── aws-resource-explorer.yaml
│ │ │ ├── data-analyst.yaml
│ │ │ ├── developer-for-bedrock-engineer.yaml
│ │ │ ├── github-implement-planner.yaml
│ │ │ ├── github-pull-request-reviewer.yaml
│ │ │ ├── japanese-english-lesson.yaml
│ │ │ ├── knowledge-base-rag-agent.yaml
│ │ │ ├── nova-canvas-agent.yaml
│ │ │ ├── nova-sonic-voice-chat.yaml
│ │ │ ├── picture-books-creator.yaml
│ │ │ ├── playwright-browser-use.yaml
│ │ │ ├── room-prompt-engineer.yaml
│ │ │ ├── senior-frontend-developer.yaml
│ │ │ ├── simulation-engineer.yaml
│ │ │ └── web-deepsearcher.yaml
│ │ ├── images
│ │ │ └── icons
│ │ │ │ └── ai.svg
│ │ ├── lottie
│ │ │ ├── loading-database.json
│ │ │ ├── loading-dots.json
│ │ │ ├── loading-voice-with-ai.json
│ │ │ └── loading-website.json
│ │ └── main.css
│ │ ├── command-palette.tsx
│ │ ├── components
│ │ ├── DeepSearchButton.tsx
│ │ ├── JSONViewer
│ │ │ ├── JSONEditor.tsx
│ │ │ └── index.tsx
│ │ ├── Loader.tsx
│ │ ├── LocalImage
│ │ │ └── index.tsx
│ │ ├── Markdown
│ │ │ ├── MD.tsx
│ │ │ ├── styles.module.css
│ │ │ └── styles.module.css.d.ts
│ │ ├── Versions.tsx
│ │ ├── ViewToggleButton.tsx
│ │ ├── VoiceAI
│ │ │ ├── VoiceAILottie.tsx
│ │ │ └── index.ts
│ │ ├── WebLoader.tsx
│ │ ├── common
│ │ │ └── MonacoJSONEditor.tsx
│ │ └── icons
│ │ │ ├── AgentIcons.tsx
│ │ │ └── ToolIcons.tsx
│ │ ├── constants
│ │ ├── defaultToolSets.ts
│ │ └── voiceIds.ts
│ │ ├── contexts
│ │ ├── AgentDirectoryContext.tsx
│ │ ├── ChatHistoryContext.tsx
│ │ ├── SettingsContext.tsx
│ │ └── WebsiteGeneratorContext.tsx
│ │ ├── hooks
│ │ ├── use-debounse.ts
│ │ ├── useAutoScroll.ts
│ │ ├── useChat.ts
│ │ ├── useModal.tsx
│ │ ├── useScroll.ts
│ │ ├── useSetting.ts
│ │ ├── useTheme.ts
│ │ └── useWebsiteGeneratorSetting.ts
│ │ ├── i18n
│ │ ├── config.ts
│ │ └── locales
│ │ │ ├── agentDirectory
│ │ │ ├── en.ts
│ │ │ ├── index.ts
│ │ │ └── ja.ts
│ │ │ ├── awsDiagramGenerator
│ │ │ └── index.ts
│ │ │ ├── chat
│ │ │ ├── agent.ts
│ │ │ ├── examples.ts
│ │ │ ├── guardrails.ts
│ │ │ ├── history.ts
│ │ │ ├── index.ts
│ │ │ ├── messages.ts
│ │ │ └── tools.ts
│ │ │ ├── en.ts
│ │ │ ├── ja.ts
│ │ │ ├── planActMode.ts
│ │ │ ├── settings
│ │ │ ├── agentSettings.ts
│ │ │ ├── agentToolsSettings.ts
│ │ │ ├── bedrock
│ │ │ │ └── index.ts
│ │ │ ├── iamPolicy.ts
│ │ │ ├── index.ts
│ │ │ ├── lightModelSettings.ts
│ │ │ ├── notification.ts
│ │ │ ├── promptCache.ts
│ │ │ └── tokenAnalytics.ts
│ │ │ └── thinkingMode.ts
│ │ ├── lib
│ │ ├── api.ts
│ │ ├── contextLength
│ │ │ ├── __tests__
│ │ │ │ └── index.test.ts
│ │ │ └── index.ts
│ │ ├── modelSelection.ts
│ │ ├── pricing
│ │ │ ├── modelPricing.test.ts
│ │ │ └── modelPricing.ts
│ │ ├── promptCacheUtils.ts
│ │ └── util.ts
│ │ ├── main.tsx
│ │ ├── pages
│ │ ├── AgentDirectoryPage
│ │ │ ├── AgentDirectoryPage.tsx
│ │ │ ├── components
│ │ │ │ ├── AgentDetailModal.tsx
│ │ │ │ ├── AgentList.tsx
│ │ │ │ ├── ContributorModal
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useContributorModal.tsx
│ │ │ │ └── TagFilter.tsx
│ │ │ └── index.ts
│ │ ├── ChatPage
│ │ │ ├── ChatPage.tsx
│ │ │ ├── components
│ │ │ │ ├── AgentForm
│ │ │ │ │ ├── AgentForm.tsx
│ │ │ │ │ ├── BasicSection.tsx
│ │ │ │ │ ├── BedrockAgentsSection.tsx
│ │ │ │ │ ├── CommandsSection.tsx
│ │ │ │ │ ├── KnowledgeBasesSection.tsx
│ │ │ │ │ ├── McpServerSection
│ │ │ │ │ │ ├── ConnectionTestResults.tsx
│ │ │ │ │ │ ├── McpServerForm.tsx
│ │ │ │ │ │ ├── McpServerList.tsx
│ │ │ │ │ │ ├── ServerListItem.tsx
│ │ │ │ │ │ ├── hooks
│ │ │ │ │ │ │ └── useMcpServerState.ts
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ ├── types
│ │ │ │ │ │ │ └── mcpServer.types.ts
│ │ │ │ │ │ └── utils
│ │ │ │ │ │ │ ├── connectionTestUtils.ts
│ │ │ │ │ │ │ ├── eventUtils.ts
│ │ │ │ │ │ │ └── mcpServerUtils.ts
│ │ │ │ │ ├── ScenariosSection.tsx
│ │ │ │ │ ├── SystemPromptSection.tsx
│ │ │ │ │ ├── TagsSection.tsx
│ │ │ │ │ ├── ToolsSection
│ │ │ │ │ │ ├── ToolsSection.tsx
│ │ │ │ │ │ ├── ToolsSectionContainer.tsx
│ │ │ │ │ │ ├── components
│ │ │ │ │ │ │ ├── AvailableToolsTab
│ │ │ │ │ │ │ │ ├── CategorySelector.tsx
│ │ │ │ │ │ │ │ ├── ToolCategorySection.tsx
│ │ │ │ │ │ │ │ ├── ToolItem.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── DetailsTab
│ │ │ │ │ │ │ │ ├── BedrockAgentsContent.tsx
│ │ │ │ │ │ │ │ ├── CommandsContent.tsx
│ │ │ │ │ │ │ │ ├── FlowsContent.tsx
│ │ │ │ │ │ │ │ ├── KnowledgeBasesContent.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ └── ToolInfoModal.tsx
│ │ │ │ │ │ ├── hooks
│ │ │ │ │ │ │ ├── useMcpToolsIntegration.ts
│ │ │ │ │ │ │ ├── useToolsFormatter.ts
│ │ │ │ │ │ │ └── useToolsState.ts
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ └── utils
│ │ │ │ │ │ │ ├── eventUtils.ts
│ │ │ │ │ │ │ ├── toolCategories.ts
│ │ │ │ │ │ │ └── toolFilters.ts
│ │ │ │ │ ├── components
│ │ │ │ │ │ ├── AgentFormContent.tsx
│ │ │ │ │ │ ├── AgentFormSidebar.tsx
│ │ │ │ │ │ ├── AgentFormTabs.tsx
│ │ │ │ │ │ └── FormActionButtons.tsx
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── types
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── useAgentForm.ts
│ │ │ │ │ ├── usePromptGeneration.ts
│ │ │ │ │ └── utils
│ │ │ │ │ │ └── formEventUtils.ts
│ │ │ │ ├── AgentList
│ │ │ │ │ ├── AgentCard.tsx
│ │ │ │ │ ├── AgentList.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useAgentFilter.ts
│ │ │ │ ├── AgentSelector
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── ChatHistory
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── Code
│ │ │ │ │ ├── CodeRenderer.tsx
│ │ │ │ │ └── Mermaid.tsx
│ │ │ │ ├── CodeBlocks
│ │ │ │ │ ├── BedrockAgent
│ │ │ │ │ │ └── BedrockAgentResult.tsx
│ │ │ │ │ ├── CodeInterpreter
│ │ │ │ │ │ ├── CodeInterpreterResult.tsx
│ │ │ │ │ │ ├── ErrorDisplay.tsx
│ │ │ │ │ │ ├── ExecutedCodeBlock.tsx
│ │ │ │ │ │ ├── ExecutionMetadata.tsx
│ │ │ │ │ │ ├── FileDisplay.tsx
│ │ │ │ │ │ ├── ImagePreview.tsx
│ │ │ │ │ │ ├── OutputDisplay.tsx
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── ExecuteCommand
│ │ │ │ │ │ └── ExecuteCommandResult.tsx
│ │ │ │ │ ├── GenerateImage
│ │ │ │ │ │ └── GenerateImageResult.tsx
│ │ │ │ │ ├── GuardContent
│ │ │ │ │ │ ├── GuardContent.tsx
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── JSONCodeBlock.tsx
│ │ │ │ │ ├── Reasoning
│ │ │ │ │ │ └── ReasoningContent.tsx
│ │ │ │ │ ├── RecognizeImage
│ │ │ │ │ │ └── RecognizeImageResult.tsx
│ │ │ │ │ ├── RetrievalResult
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── TavilySearch
│ │ │ │ │ │ ├── SearchImage.tsx
│ │ │ │ │ │ ├── SearchResult.tsx
│ │ │ │ │ │ └── TavilySearchResult.tsx
│ │ │ │ │ └── TextCodeBlock.tsx
│ │ │ │ ├── CodeInterpreter
│ │ │ │ │ ├── AsyncTaskCard.tsx
│ │ │ │ │ └── TaskListCard.tsx
│ │ │ │ ├── ExampleScenarios
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── InputForm
│ │ │ │ │ ├── DirectorySelector.tsx
│ │ │ │ │ ├── PlanActToggle.tsx
│ │ │ │ │ ├── TextArea.tsx
│ │ │ │ │ ├── ToolSettings.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── InputFormContainer
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── InterleaveThinkingToggle
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── MessageList
│ │ │ │ │ ├── Avatar.tsx
│ │ │ │ │ ├── Message.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── MetadataViewer
│ │ │ │ │ ├── MetadataViewer.tsx
│ │ │ │ │ ├── StructuredJsonView.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── ModelSelector
│ │ │ │ │ ├── claude-color.svg
│ │ │ │ │ ├── deepseek-color.svg
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ ├── meta-color.svg
│ │ │ │ │ └── nova-color.svg
│ │ │ │ ├── Recommendations
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── ThinkingModeSelector
│ │ │ │ │ └── index.tsx
│ │ │ │ └── Tool
│ │ │ │ │ └── ToolIcons.tsx
│ │ │ ├── constants
│ │ │ │ ├── AGENTS_ENVIRONMENT_CONTEXT.ts
│ │ │ │ └── DEFAULT_AGENTS.ts
│ │ │ ├── hooks
│ │ │ │ ├── useAgentChat.ts
│ │ │ │ ├── useAgentTools.ts
│ │ │ │ └── useScenarioGenerator.ts
│ │ │ ├── modals
│ │ │ │ ├── useAgentSettingsModal.tsx
│ │ │ │ ├── useIgnoreFileModal.tsx
│ │ │ │ ├── useSystemPromptModal.tsx
│ │ │ │ ├── useTokenAnalyticsModal.tsx
│ │ │ │ └── useToolSettingModal
│ │ │ │ │ ├── BedrockAgentSettingForm.tsx
│ │ │ │ │ ├── CodeInterpreterSettingForm.tsx
│ │ │ │ │ ├── CommandForm.tsx
│ │ │ │ │ ├── FlowSettingForm.tsx
│ │ │ │ │ ├── GenerateImageSettingForm.tsx
│ │ │ │ │ ├── KnowledgeBaseSettingForm.tsx
│ │ │ │ │ ├── PlanModeCompatibilityBadge.tsx
│ │ │ │ │ ├── RecognizeImageSettingForm.tsx
│ │ │ │ │ ├── TavilySearchSettingForm.tsx
│ │ │ │ │ ├── ThinkToolSettingForm.tsx
│ │ │ │ │ ├── ToolSpecJsonModal.tsx
│ │ │ │ │ └── index.tsx
│ │ │ └── utils
│ │ │ │ ├── placeholder.ts
│ │ │ │ └── titleGenerator.ts
│ │ ├── DiagramGeneratorPage
│ │ │ ├── DiagramGeneratorPage.tsx
│ │ │ ├── components
│ │ │ │ ├── LoaderWithReasoning.tsx
│ │ │ │ ├── ReasoningTextDisplay.tsx
│ │ │ │ └── RecommendDiagrams.tsx
│ │ │ ├── example-diagrams.tsx
│ │ │ ├── hooks
│ │ │ │ └── useRecommendDiagrams.tsx
│ │ │ └── utils
│ │ │ │ ├── __tests__
│ │ │ │ └── xmlParser.test.ts
│ │ │ │ └── xmlParser.ts
│ │ ├── ErrorPage
│ │ │ └── ErrorPage.tsx
│ │ ├── HomePage
│ │ │ ├── HomePage.tsx
│ │ │ └── Robot.json
│ │ ├── SettingPage
│ │ │ ├── SettingPage.tsx
│ │ │ ├── components
│ │ │ │ ├── IAMPolicyModal.tsx
│ │ │ │ ├── LightModelSettings.tsx
│ │ │ │ ├── SettingInput.tsx
│ │ │ │ ├── SettingSection.tsx
│ │ │ │ ├── SettingSelect.tsx
│ │ │ │ ├── ThinkingModeSettings.tsx
│ │ │ │ └── sections
│ │ │ │ │ ├── AWSSection.tsx
│ │ │ │ │ ├── AdvancedSection.tsx
│ │ │ │ │ ├── AgentChatSection.tsx
│ │ │ │ │ ├── ConfigDirSection.tsx
│ │ │ │ │ ├── GuardrailSettings.tsx
│ │ │ │ │ ├── LanguageSection.tsx
│ │ │ │ │ ├── NotificationSection.tsx
│ │ │ │ │ ├── ProjectSection.tsx
│ │ │ │ │ └── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── SpeakPage
│ │ │ ├── components
│ │ │ │ ├── AIIcon.tsx
│ │ │ │ ├── AudioControls.tsx
│ │ │ │ ├── ChatDisplay.tsx
│ │ │ │ ├── ConnectionStatus.tsx
│ │ │ │ ├── PermissionHelpModal
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── usePermissionHelpModal.tsx
│ │ │ │ ├── SampleTextCarousel.tsx
│ │ │ │ ├── ThinkingIndicator.tsx
│ │ │ │ ├── ToolResultDisplay.tsx
│ │ │ │ ├── TranslatedMessage.tsx
│ │ │ │ └── VoiceSelector
│ │ │ │ │ ├── VoiceSelector.tsx
│ │ │ │ │ ├── VoiceVisual.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── index.tsx
│ │ │ ├── constants
│ │ │ │ ├── translationLanguages.ts
│ │ │ │ └── voices.ts
│ │ │ ├── hooks
│ │ │ │ ├── useAudioPlayer.ts
│ │ │ │ ├── useAudioRecorder.ts
│ │ │ │ ├── useSocketConnection.ts
│ │ │ │ ├── useSpeakChat.ts
│ │ │ │ └── useTranslation.ts
│ │ │ ├── index.tsx
│ │ │ ├── lib
│ │ │ │ ├── AudioPlayer.ts
│ │ │ │ ├── AudioPlayerProcessor.worklet.ts
│ │ │ │ ├── ChatHistoryManager.ts
│ │ │ │ └── ObjectsExt.ts
│ │ │ └── modals
│ │ │ │ └── useSystemPromptModal.tsx
│ │ ├── StepFunctionsGeneratorPage
│ │ │ ├── ASLEditor.tsx
│ │ │ ├── SAMPLE_ASL.tsx
│ │ │ ├── StepFunctionsGeneratorPage.tsx
│ │ │ └── aws-sfn-graph.d.ts
│ │ └── WebsiteGeneratorPage
│ │ │ ├── DEFAULT_CODES.tsx
│ │ │ ├── LazyVisibleMessage.tsx
│ │ │ ├── LoadingDataBase.lottie.tsx
│ │ │ ├── LoadingDots.lottie.tsx
│ │ │ ├── LoadingWebsite.lottie.tsx
│ │ │ ├── VoiceAI.lottie.tsx
│ │ │ ├── WebsiteGeneratorPage.tsx
│ │ │ ├── components
│ │ │ ├── KnowledgeBaseConnectButton.tsx
│ │ │ ├── LoaderWithReasoning.tsx
│ │ │ ├── Preview.tsx
│ │ │ ├── RagLoader.tsx
│ │ │ ├── ReasoningTextDisplay.tsx
│ │ │ ├── RecommendChanges.tsx
│ │ │ ├── StyleSelector.tsx
│ │ │ └── TemplateButton.tsx
│ │ │ ├── hooks
│ │ │ └── useRecommendChanges.tsx
│ │ │ ├── templates.tsx
│ │ │ ├── useDataSourceConnectModal.tsx
│ │ │ └── util.ts
│ │ ├── prompts
│ │ ├── diagram-prompt.ts
│ │ └── prompts.ts
│ │ ├── routes.tsx
│ │ ├── services
│ │ └── NotificationService.ts
│ │ └── types
│ │ └── images.d.ts
├── test
│ ├── sandbox
│ │ └── sts.client.test.ts
│ └── src
│ │ └── preload
│ │ └── tools.test.ts
└── types
│ ├── agent-chat.ts
│ ├── agent.ts
│ ├── aws-regions.ts
│ ├── chat
│ ├── history.ts
│ ├── message.ts
│ └── metadata.ts
│ ├── electron.ts
│ ├── ipc.ts
│ ├── llm.ts
│ ├── plan-mode-tools.ts
│ ├── preload
│ └── index.ts
│ └── tools.ts
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.test.json
└── tsconfig.web.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # AWS Credentials
2 | AWS_ACCESS_KEY_ID=your_access_key_here
3 | AWS_SECRET_ACCESS_KEY=your_secret_key_here
4 | AWS_REGION=us-east-1
5 |
6 | # Test Configuration
7 | INTEGRATION_TEST=true
8 |
9 | # Example of how to use these environment variables
10 | # 1. Copy this file to .env
11 | # 2. Replace the placeholder values with your actual credentials
12 | # 3. Run npm run test:integration
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | out
4 | .gitignore
5 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'eslint:recommended',
4 | 'plugin:react/recommended',
5 | 'plugin:react/jsx-runtime',
6 | '@electron-toolkit/eslint-config-ts/recommended',
7 | '@electron-toolkit/eslint-config-prettier'
8 | ],
9 | settings: {
10 | react: {
11 | version: 'detect' // React のバージョンを自動検出
12 | }
13 | },
14 | rules: {
15 | '@typescript-eslint/explicit-function-return-type': 'off',
16 | '@typescript-eslint/no-explicit-any': 'off',
17 | '@typescript-eslint/no-unused-vars': [
18 | 'error',
19 | { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }
20 | ],
21 | 'react/prop-types': 'off',
22 | 'no-control-regex': 0
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE REQUEST] "
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Is your feature request related to a problem? / この機能リクエストは何か問題に関連していますか?
11 |
12 | **English**
13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
14 |
15 | **日本語**
16 | 問題の内容を簡潔に説明してください。例:「いつも〜の時に困っています」
17 |
18 | ## Describe the solution you'd like / 希望する解決策を説明してください。
19 |
20 | **English**
21 | A clear and concise description of what you want to happen.
22 |
23 | **日本語**
24 | どのようなことが実現されることを望むのか、具体的に説明してください。
25 |
26 | ## Describe alternatives you've considered / 検討した代替案について説明してください。
27 |
28 | **English**
29 | A clear and concise description of any alternative solutions or features you've considered.
30 |
31 | **日本語**
32 | 検討した他の解決策や機能について簡潔に説明してください。
33 |
34 | ## Additional context / 補足情報
35 |
36 | **English**
37 | Add any other context or screenshots about the feature request here.
38 |
39 | **日本語**
40 | 機能リクエストに関する他の情報やスクリーンショットがあれば、ここに追加してください。
41 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | pull_request:
5 | branches: ['**']
6 |
7 | jobs:
8 | build:
9 | strategy:
10 | matrix:
11 | os: [macos-latest, windows-latest]
12 |
13 | runs-on: ${{ matrix.os }}
14 |
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Use Node.js
18 | uses: actions/setup-node@v3
19 | with:
20 | node-version: 20
21 |
22 | - name: Install dependencies
23 | run: npm ci
24 |
25 | - name: Lint
26 | run: npm run lint
27 |
28 | - name: Run unit tests
29 | run: npm test -- --coverage
30 |
31 | - name: Build app
32 | run: npm run build:${{ matrix.os == 'windows-latest' && 'win' || 'mac' }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | out
4 | .DS_Store
5 | *.log*
6 | .env
7 |
8 | ash_output/
9 | .bedrock-engineer/workspaces/
10 |
11 | test-outputs
12 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | pnpm-lock.yaml
4 | LICENSE.md
5 | tsconfig.json
6 | tsconfig.*.json
7 |
--------------------------------------------------------------------------------
/.prettierrc.yaml:
--------------------------------------------------------------------------------
1 | singleQuote: true
2 | semi: false
3 | printWidth: 100
4 | trailingComma: none
5 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["dbaeumer.vscode-eslint", "lokalise.i18n-ally"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Debug Main Process",
6 | "type": "node",
7 | "request": "launch",
8 | "cwd": "${workspaceRoot}",
9 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite",
10 | "windows": {
11 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd"
12 | },
13 | "runtimeArgs": ["--sourcemap"],
14 | "env": {
15 | "REMOTE_DEBUGGING_PORT": "9222"
16 | }
17 | },
18 | {
19 | "name": "Debug Renderer Process",
20 | "port": 9222,
21 | "request": "attach",
22 | "type": "chrome",
23 | "webRoot": "${workspaceFolder}/src/renderer",
24 | "timeout": 60000,
25 | "presentation": {
26 | "hidden": true
27 | }
28 | }
29 | ],
30 | "compounds": [
31 | {
32 | "name": "Debug All",
33 | "configurations": ["Debug Main Process", "Debug Renderer Process"],
34 | "presentation": {
35 | "order": 1
36 | }
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "[typescript]": {
3 | "editor.defaultFormatter": "esbenp.prettier-vscode"
4 | },
5 | "[javascript]": {
6 | "editor.defaultFormatter": "esbenp.prettier-vscode"
7 | },
8 | "[json]": {
9 | "editor.defaultFormatter": "esbenp.prettier-vscode"
10 | },
11 | "CodeGPT.apiKey": "CodeGPT Plus Beta",
12 | "CodeGPT.Autocomplete.enabled": true,
13 | "i18n-ally.localesPaths": [
14 | "src/renderer/src/i18n",
15 | "src/renderer/src/i18n/locales"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT No Attribution
2 |
3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 |
18 |
--------------------------------------------------------------------------------
/assets/agent-chat-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/agent-chat-diagram.png
--------------------------------------------------------------------------------
/assets/agent-chat-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/agent-chat-search.png
--------------------------------------------------------------------------------
/assets/agent-directory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/agent-directory.png
--------------------------------------------------------------------------------
/assets/custom-agents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/custom-agents.png
--------------------------------------------------------------------------------
/assets/custom-tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/custom-tools.png
--------------------------------------------------------------------------------
/assets/diagram-generator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/diagram-generator.png
--------------------------------------------------------------------------------
/assets/select-agents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/select-agents.png
--------------------------------------------------------------------------------
/assets/select-tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/select-tools.png
--------------------------------------------------------------------------------
/assets/step-functions-generator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/step-functions-generator.png
--------------------------------------------------------------------------------
/assets/voice-chat-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/voice-chat-page.png
--------------------------------------------------------------------------------
/assets/website-generator-data-visualization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/website-generator-data-visualization.png
--------------------------------------------------------------------------------
/assets/website-generator-healthcare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/website-generator-healthcare.png
--------------------------------------------------------------------------------
/assets/website-generator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/assets/website-generator.png
--------------------------------------------------------------------------------
/build/entitlements.mac.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.allow-unsigned-executable-memory
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.device.camera
10 |
11 | com.apple.security.device.microphone
12 |
13 | com.apple.security.device.audio-input
14 |
15 | com.apple.security.cs.allow-dyld-environment-variables
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/build/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.icns
--------------------------------------------------------------------------------
/build/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.ico
--------------------------------------------------------------------------------
/build/icon.iconset/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | $ iconutil -c icns icon.iconset
3 | ```
4 |
--------------------------------------------------------------------------------
/build/icon.iconset/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_128x128.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_128x128@2x.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_16x16.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_256x256.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_256x256@2x.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_32x32.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_32x32@2x.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_512x512.png
--------------------------------------------------------------------------------
/build/icon.iconset/icon_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.iconset/icon_512x512@2x.png
--------------------------------------------------------------------------------
/build/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/build/icon.png
--------------------------------------------------------------------------------
/build/make-icon.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Electron用にアプリアイコンを一括作成
5 | # https://blog.katsubemakito.net/nodejs/electron/app-icon
6 | #
7 | # 実行方法
8 | # $ ./makeIcon.sh icon.png
9 | #
10 |
11 | #--------------------------------#
12 | # 定数
13 | #--------------------------------#
14 | #-- 元画像 (512x512px) --#
15 | readonly ORG_FILE=$1;
16 |
17 | #-- Windows用アイコンの生成先 --#
18 | readonly ICON_DIR_WIN='./'
19 |
20 | #-- macOS用アイコン --#
21 | readonly ICONSET_DIR='icon.iconset'
22 | readonly ICON_DIR_MAC='./'
23 |
24 | #--------------------------------#
25 | # macOS用
26 | #--------------------------------#
27 | mkdir -p $ICONSET_DIR
28 |
29 | #-- 元画像をリサイズしてコピー --#
30 | convert -resize 16x16! $ORG_FILE $ICONSET_DIR/icon_16x16.png
31 | convert -resize 32x32! $ORG_FILE $ICONSET_DIR/icon_16x16@2x.png
32 | convert -resize 32x32! $ORG_FILE $ICONSET_DIR/icon_32x32.png
33 | convert -resize 64x64! $ORG_FILE $ICONSET_DIR/icon_32x32@2x.png
34 | convert -resize 128x128! $ORG_FILE $ICONSET_DIR/icon_128x128.png
35 | convert -resize 256x256! $ORG_FILE $ICONSET_DIR/icon_128x128@2x.png
36 | convert -resize 256x256! $ORG_FILE $ICONSET_DIR/icon_256x256.png
37 | convert -resize 512x512! $ORG_FILE $ICONSET_DIR/icon_256x256@2x.png
38 | convert -resize 512x512! $ORG_FILE $ICONSET_DIR/icon_512x512.png
39 |
40 | #-- icns形式のファイルに変換 --$
41 | iconutil -c icns $ICONSET_DIR -o $ICON_DIR_MAC/icon.icns
42 |
43 | #---------------------------------------
44 | # Windows用
45 | #---------------------------------------
46 | convert $ORG_FILE -define icon:auto-resize $ICON_DIR_WIN/icon.ico
47 |
--------------------------------------------------------------------------------
/dev-app-update.yml:
--------------------------------------------------------------------------------
1 | provider: generic
2 | url: https://example.com/auto-updates
3 | updaterCacheDirName: bedrock-engineer-updater
4 |
--------------------------------------------------------------------------------
/electron-builder.yml:
--------------------------------------------------------------------------------
1 | appId: com.electron.app
2 | productName: Bedrock Engineer
3 | directories:
4 | buildResources: build
5 | files:
6 | - '!**/.vscode/*'
7 | - '!src/*'
8 | - '!electron.vite.config.{js,ts,mjs,cjs}'
9 | - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
10 | - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
11 | - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
12 | asarUnpack:
13 | - resources/**
14 | extraResources:
15 | - from: 'src/renderer/src/assets/directory-agents'
16 | to: 'directory-agents'
17 | - from: 'public/worklets'
18 | to: 'worklets'
19 | win:
20 | executableName: Bedrock Engineer
21 | nsis:
22 | artifactName: ${name}-${version}-setup.${ext}
23 | shortcutName: ${productName}
24 | uninstallDisplayName: ${productName}
25 | createDesktopShortcut: always
26 | mac:
27 | identity: '-'
28 | entitlementsInherit: build/entitlements.mac.plist
29 | extendInfo:
30 | - NSCameraUsageDescription: Application requests access to the device's camera.
31 | - NSMicrophoneUsageDescription: Application requests access to the device's microphone.
32 | - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
33 | - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
34 | notarize: false
35 | target:
36 | - dmg
37 | - pkg
38 | dmg:
39 | artifactName: ${name}-${version}.${ext}
40 | pkg:
41 | artifactName: ${name}-${version}.${ext}
42 | linux:
43 | target:
44 | - AppImage
45 | - snap
46 | - deb
47 | maintainer: electronjs.org
48 | category: Utility
49 | appImage:
50 | artifactName: ${name}-${version}.${ext}
51 | npmRebuild: false
52 | publish:
53 | provider: generic
54 | url: https://example.com/auto-updates
55 |
--------------------------------------------------------------------------------
/electron.vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path'
2 | import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
3 | import react from '@vitejs/plugin-react'
4 | import svgr from 'vite-plugin-svgr'
5 | import tailwindcss from 'tailwindcss'
6 |
7 | export default defineConfig({
8 | main: {
9 | plugins: [externalizeDepsPlugin()]
10 | },
11 | preload: {
12 | plugins: [externalizeDepsPlugin()]
13 | },
14 | renderer: {
15 | resolve: {
16 | alias: {
17 | '@renderer': resolve('src/renderer/src'),
18 | '@': resolve('src')
19 | }
20 | },
21 | plugins: [
22 | react(),
23 | svgr({
24 | svgrOptions: {
25 | exportType: 'default',
26 | ref: true,
27 | svgo: false,
28 | titleProp: true
29 | },
30 | include: '**/*.svg'
31 | })
32 | ],
33 | css: {
34 | postcss: {
35 | plugins: [tailwindcss() as any]
36 | }
37 | }
38 | }
39 | })
40 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest').JestConfigWithTsJest} **/
2 | module.exports = {
3 | testEnvironment: 'node',
4 | transform: {
5 | '^.+.tsx?$': ['ts-jest', {}]
6 | },
7 | testMatch: ['**/*.test.ts'],
8 | testPathIgnorePatterns: [
9 | '/node_modules/',
10 | '\\.integration\\.test\\.ts$' // .integration.test.ts で終わるファイルを除外
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/jest.integration.config.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | /** @type {import('ts-jest').JestConfigWithTsJest} */
4 | module.exports = {
5 | preset: 'ts-jest',
6 | testEnvironment: 'node',
7 | testTimeout: 90000,
8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9 | transform: {
10 | '^.+\\.tsx?$': [
11 | 'ts-jest',
12 | {
13 | tsconfig: 'tsconfig.test.json'
14 | }
15 | ]
16 | },
17 | testMatch: ['**/*.integration.test.ts'],
18 | setupFiles: ['/jest.integration.setup.js']
19 | }
20 |
--------------------------------------------------------------------------------
/jest.integration.setup.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | // Add any additional setup code here
4 | console.log('Integration test environment variables loaded:', {
5 | AWS_REGION: process.env.AWS_REGION,
6 | INTEGRATION_TEST: process.env.INTEGRATION_TEST,
7 | // Mask sensitive credentials in logs
8 | AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID ? '***' : undefined,
9 | AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY ? '***' : undefined
10 | })
11 |
--------------------------------------------------------------------------------
/src/common/logger/config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Logger configuration
3 | */
4 |
5 | export const LOG_LEVELS = {
6 | ERROR: 'error',
7 | WARN: 'warn',
8 | INFO: 'info',
9 | DEBUG: 'debug',
10 | VERBOSE: 'verbose'
11 | }
12 |
13 | export type LogLevel = (typeof LOG_LEVELS)[keyof typeof LOG_LEVELS]
14 |
15 | export interface LoggerConfig {
16 | level: LogLevel
17 | fileLogEnabled: boolean
18 | consoleLogEnabled: boolean
19 | maxSize: string
20 | maxFiles: number
21 | logDir: string
22 | logFilePrefix: string
23 | }
24 |
25 | /**
26 | * Default logger configuration
27 | */
28 | export const defaultLoggerConfig: LoggerConfig = {
29 | level: (process.env.NODE_ENV === 'development' ? LOG_LEVELS.DEBUG : LOG_LEVELS.INFO) as LogLevel,
30 | fileLogEnabled: true,
31 | consoleLogEnabled: true,
32 | maxSize: '10m',
33 | maxFiles: 5,
34 | logDir: '', // Will be set during initialization
35 | logFilePrefix: 'bedrock-engineer'
36 | }
37 |
--------------------------------------------------------------------------------
/src/common/logger/formatters.ts:
--------------------------------------------------------------------------------
1 | import { format } from 'winston'
2 |
3 | /**
4 | * Custom log format that includes timestamp, log level, process, category and message
5 | */
6 | export const customFormat = format.printf(({ level, message, timestamp, ...metadata }) => {
7 | const process = metadata.process || 'main'
8 | const category = metadata.category || 'general'
9 |
10 | // Format additional metadata
11 | let extraInfo = ''
12 | if (Object.keys(metadata).length > 0) {
13 | const metaObj = { ...metadata }
14 | delete metaObj.process
15 | delete metaObj.category
16 |
17 | if (Object.keys(metaObj).length > 0) {
18 | try {
19 | extraInfo = `\n${JSON.stringify(metaObj, null, 2)}`
20 | } catch (e) {
21 | extraInfo = `\n[Metadata serialization error]`
22 | }
23 | }
24 | }
25 |
26 | return `${timestamp} [${level}] [${process}:${category}] ${message}${extraInfo}`
27 | })
28 |
29 | /**
30 | * Main log format combining timestamp, error handling, and custom format
31 | */
32 | export const mainLogFormat = format.combine(
33 | format.timestamp(),
34 | format.errors({ stack: true }),
35 | customFormat
36 | )
37 |
38 | /**
39 | * Console log format with colors for better readability
40 | */
41 | export const consoleLogFormat = format.combine(format.colorize(), format.timestamp(), customFormat)
42 |
--------------------------------------------------------------------------------
/src/common/logger/transports/console.ts:
--------------------------------------------------------------------------------
1 | import { transports } from 'winston'
2 | import { LoggerConfig } from '../config'
3 | import { consoleLogFormat } from '../formatters'
4 |
5 | /**
6 | * Create console transport for winston logger
7 | * With colorized output for better readability
8 | */
9 | export const createConsoleTransport = (config: LoggerConfig) => {
10 | return new transports.Console({
11 | level: config.level,
12 | format: consoleLogFormat
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/src/common/logger/transports/file.ts:
--------------------------------------------------------------------------------
1 | import DailyRotateFile from 'winston-daily-rotate-file'
2 | import path from 'path'
3 | import fs from 'fs'
4 | import { LoggerConfig } from '../config'
5 | import { mainLogFormat } from '../formatters'
6 |
7 | /**
8 | * Create file transport for winston logger
9 | * Uses daily rotate file to manage log rotation
10 | */
11 | export const createFileTransport = (config: LoggerConfig) => {
12 | // Ensure log directory exists
13 | if (!fs.existsSync(config.logDir)) {
14 | fs.mkdirSync(config.logDir, { recursive: true })
15 | }
16 |
17 | return new DailyRotateFile({
18 | dirname: config.logDir,
19 | filename: `${config.logFilePrefix}-%DATE%.log`,
20 | datePattern: 'YYYY-MM-DD',
21 | maxSize: config.maxSize,
22 | maxFiles: config.maxFiles,
23 | level: config.level,
24 | format: mainLogFormat
25 | })
26 | }
27 |
28 | /**
29 | * Get log file paths for the current day and previous days
30 | */
31 | export const getLogFilePaths = (config: LoggerConfig): string[] => {
32 | if (!fs.existsSync(config.logDir)) {
33 | return []
34 | }
35 |
36 | const files = fs.readdirSync(config.logDir)
37 | return files
38 | .filter((file) => file.startsWith(config.logFilePrefix) && file.endsWith('.log'))
39 | .map((file) => path.join(config.logDir, file))
40 | .sort()
41 | .reverse() // Most recent first
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/__tests__/test-assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/bedrock-engineer/0c5f6256c5aa48c62052a1bf50a7705923aa7fbe/src/main/api/bedrock/__tests__/test-assets/icon.png
--------------------------------------------------------------------------------
/src/main/api/bedrock/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './converseService'
2 | export * from './imageRecognitionService'
3 | export * from './flowService'
4 | export * from './translateService'
5 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/services/modelService.ts:
--------------------------------------------------------------------------------
1 | import { getDefaultPromptRouter, getModelsForRegion } from '../models'
2 | import { getAccountId } from '../utils/awsUtils'
3 | import type { ServiceContext, AWSCredentials } from '../types'
4 | import { BedrockSupportRegion } from '../../../../types/llm'
5 |
6 | export class ModelService {
7 | constructor(private context: ServiceContext) {}
8 |
9 | async listModels() {
10 | const awsCredentials = this.context.store.get('aws') as AWSCredentials
11 | const { region, accessKeyId, useProfile } = awsCredentials
12 |
13 | // AWS認証情報のバリデーション
14 | if (!region || (!useProfile && !accessKeyId)) {
15 | console.warn('AWS credentials not configured properly')
16 | return []
17 | }
18 |
19 | try {
20 | const models = getModelsForRegion(region as BedrockSupportRegion)
21 | const accountId = await getAccountId(awsCredentials)
22 | const promptRouterModels = accountId ? getDefaultPromptRouter(accountId, region) : []
23 | const result = [...models, ...promptRouterModels]
24 |
25 | return result
26 | } catch (error) {
27 | console.error('Error in listModels:', error)
28 | return []
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/types.ts:
--------------------------------------------------------------------------------
1 | import {
2 | GuardrailConfiguration,
3 | InferenceConfiguration,
4 | Message,
5 | SystemContentBlock,
6 | ToolConfiguration
7 | } from '@aws-sdk/client-bedrock-runtime'
8 | import { ConfigStore } from '../../../preload/store'
9 |
10 | export type CallConverseAPIProps = {
11 | modelId: string
12 | messages: Message[]
13 | system: SystemContentBlock[]
14 | toolConfig?: ToolConfiguration
15 | guardrailConfig?: GuardrailConfiguration
16 | inferenceConfig?: InferenceConfiguration
17 | }
18 |
19 | export type AWSCredentials = {
20 | accessKeyId: string
21 | secretAccessKey: string
22 | sessionToken?: string
23 | region: string
24 | profile?: string
25 | useProfile?: boolean
26 | }
27 |
28 | export interface ThinkingMode {
29 | type: 'enabled' | 'disabled'
30 | budget_tokens?: number
31 | }
32 |
33 | export type InferenceParams = {
34 | maxTokens: number
35 | temperature: number
36 | topP?: number
37 | thinking?: ThinkingMode
38 | }
39 |
40 | export type ServiceContext = {
41 | store: ConfigStore
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/types/claude.ts:
--------------------------------------------------------------------------------
1 | import { ConverseCommandOutput } from '@aws-sdk/client-bedrock-runtime'
2 |
3 | // Claude モデルの Content Block 型定義
4 | export interface ClaudeContentBlock {
5 | type: 'text' | 'image'
6 | text?: string
7 | source?: {
8 | type: 'base64'
9 | media_type: string
10 | data: string
11 | }
12 | }
13 |
14 | // Claude モデルの Message 型定義
15 | export interface ClaudeMessage {
16 | role: 'user' | 'assistant'
17 | content: ClaudeContentBlock[]
18 | }
19 |
20 | // Claude モデルの応答型定義
21 | export interface ClaudeConverseResponse extends ConverseCommandOutput {
22 | content: ClaudeContentBlock[]
23 | }
24 |
25 | // Claude モデルの画像認識リクエスト型定義
26 | export interface ClaudeImageRecognitionRequest {
27 | modelId: string
28 | messages: ClaudeMessage[]
29 | max_tokens: number
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/types/image.ts:
--------------------------------------------------------------------------------
1 | export interface ImageGenerationOptions {
2 | aspect_ratio: AspectRatio
3 | /** Seed for deterministic generation */
4 | seed?: number
5 | output_format: OutputFormat
6 | }
7 |
8 | export type ImageGeneratorModel =
9 | | 'stability.sd3-large-v1:0'
10 | | 'stability.sd3-5-large-v1:0'
11 | | 'stability.stable-image-core-v1:0'
12 | | 'stability.stable-image-core-v1:1'
13 | | 'stability.stable-image-ultra-v1:0'
14 | | 'stability.stable-image-ultra-v1:1'
15 | | 'amazon.nova-canvas-v1:0'
16 | | 'amazon.titan-image-generator-v2:0'
17 | | 'amazon.titan-image-generator-v1'
18 |
19 | export type AspectRatio = '1:1' | '16:9' | '2:3' | '3:2' | '4:5' | '5:4' | '9:16' | '9:21'
20 | export type OutputFormat = 'png' | 'jpeg' | 'webp'
21 |
22 | export interface GenerateImageRequest {
23 | modelId: ImageGeneratorModel
24 | prompt: string
25 | negativePrompt?: string
26 | aspect_ratio?: AspectRatio
27 | /** Seed for deterministic generation */
28 | seed?: number
29 | /** Default png */
30 | output_format?: OutputFormat
31 | }
32 |
33 | export interface GeneratedImage {
34 | seeds?: number[]
35 | finish_reasons?: string[]
36 | images: string[]
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/api/bedrock/utils/imageUtils.ts:
--------------------------------------------------------------------------------
1 | import { ContentBlock } from '@aws-sdk/client-bedrock-runtime'
2 |
3 | // Helper function to reconstruct Uint8Array from serialized object
4 | function reconstructUint8Array(obj: any): Uint8Array {
5 | if (obj && typeof obj === 'object' && Object.keys(obj).every((key) => !isNaN(Number(key)))) {
6 | return new Uint8Array(Object.values(obj))
7 | }
8 | return obj
9 | }
10 |
11 | // Helper function to ensure image data is in the correct format
12 | export function processImageContent(content: ContentBlock[]): ContentBlock[] {
13 | return content.map((block) => {
14 | if ('image' in block && block.image) {
15 | const imageBlock = block.image
16 | if (imageBlock.source && typeof imageBlock.source === 'object') {
17 | const source = imageBlock.source as any
18 | if (source.bytes) {
19 | // Reconstruct Uint8Array if it was serialized
20 | const bytes = reconstructUint8Array(source.bytes)
21 | if (bytes instanceof Uint8Array) {
22 | return {
23 | image: {
24 | format: imageBlock.format,
25 | source: { bytes }
26 | }
27 | }
28 | }
29 | // If bytes is a base64 string
30 | if (typeof bytes === 'string') {
31 | return {
32 | image: {
33 | format: imageBlock.format,
34 | source: {
35 | bytes: new Uint8Array(Buffer.from(bytes, 'base64'))
36 | }
37 | }
38 | }
39 | }
40 | }
41 | }
42 | }
43 | return block
44 | })
45 | }
46 |
47 | export function debugImageContent(content: ContentBlock[]) {
48 | return content.map((content) => {
49 | if ('image' in content && content.image?.source?.bytes instanceof Uint8Array) {
50 | return {
51 | ...content,
52 | image: {
53 | ...content.image,
54 | source: {
55 | bytes: `[Uint8Array:${content.image.source.bytes.length}bytes]`
56 | }
57 | }
58 | }
59 | }
60 | return content
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/api/command/types.ts:
--------------------------------------------------------------------------------
1 | export interface CommandPatternConfig {
2 | pattern: string
3 | description: string
4 | }
5 |
6 | export interface CommandConfig {
7 | allowedCommands?: CommandPatternConfig[]
8 | shell: string
9 | }
10 |
11 | export interface ProcessInfo {
12 | pid: number
13 | command: string
14 | detached: boolean
15 | }
16 |
17 | export interface DetachedProcessInfo {
18 | pid: number
19 | command: string
20 | timestamp: number
21 | }
22 |
23 | export interface CommandInput {
24 | command: string
25 | cwd: string
26 | }
27 |
28 | export interface CommandStdinInput {
29 | pid: number
30 | stdin: string
31 | }
32 |
33 | export interface CommandExecutionResult {
34 | stdout: string
35 | stderr: string
36 | exitCode: number
37 | processInfo?: ProcessInfo
38 | requiresInput?: boolean
39 | prompt?: string
40 | }
41 |
42 | export interface CommandPattern {
43 | command: string
44 | args: string[]
45 | wildcard: boolean
46 | }
47 |
48 | export interface ProcessOutput {
49 | stdout: string
50 | stderr: string
51 | code: number | null
52 | }
53 |
54 | export interface ProcessState {
55 | isRunning: boolean
56 | hasError: boolean
57 | output: ProcessOutput
58 | process?: any // childProcess instance
59 | }
60 |
61 | export interface InputDetectionPattern {
62 | pattern: string | RegExp
63 | promptExtractor?: (output: string) => string
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/api/sonic/consts.ts:
--------------------------------------------------------------------------------
1 | import { AudioType, AudioMediaType, TextMediaType } from './types'
2 |
3 | export const DefaultInferenceConfiguration = {
4 | maxTokens: 1024,
5 | topP: 0.9,
6 | temperature: 0.7
7 | }
8 |
9 | export const DefaultAudioInputConfiguration = {
10 | audioType: 'SPEECH' as AudioType,
11 | encoding: 'base64',
12 | mediaType: 'audio/lpcm' as AudioMediaType,
13 | sampleRateHertz: 16000,
14 | sampleSizeBits: 16,
15 | channelCount: 1
16 | }
17 |
18 | export const DefaultToolSchema = JSON.stringify({
19 | type: 'object',
20 | properties: {},
21 | required: []
22 | })
23 |
24 | export const WeatherToolSchema = JSON.stringify({
25 | type: 'object',
26 | properties: {
27 | latitude: {
28 | type: 'string',
29 | description: 'Geographical WGS84 latitude of the location.'
30 | },
31 | longitude: {
32 | type: 'string',
33 | description: 'Geographical WGS84 longitude of the location.'
34 | }
35 | },
36 | required: ['latitude', 'longitude']
37 | })
38 |
39 | export const DefaultTextConfiguration = { mediaType: 'text/plain' as TextMediaType }
40 |
41 | export const DefaultSystemPrompt =
42 | 'You are a friend. The user and you will engage in a spoken ' +
43 | 'dialog exchanging the transcripts of a natural real-time conversation. Keep your responses short, ' +
44 | 'generally two or three sentences for chatty scenarios.'
45 |
46 | export const DefaultAudioOutputConfiguration = {
47 | ...DefaultAudioInputConfiguration,
48 | sampleRateHertz: 24000
49 | }
50 |
51 | // 音声設定を取得する関数
52 | export const getAudioOutputConfiguration = (voiceId?: string) => ({
53 | ...DefaultAudioOutputConfiguration,
54 | voiceId: voiceId || 'amy' // デフォルトはAmy
55 | })
56 |
--------------------------------------------------------------------------------
/src/main/api/sonic/tool-executor/index.ts:
--------------------------------------------------------------------------------
1 | export { SonicToolExecutor } from './SonicToolExecutor'
2 | export type { ToolExecutionResponse, ToolExecutionRequest } from './SonicToolExecutor'
3 |
--------------------------------------------------------------------------------
/src/main/api/sonic/types.ts:
--------------------------------------------------------------------------------
1 | export interface InferenceConfig {
2 | readonly maxTokens: number
3 | readonly topP: number
4 | readonly temperature: number
5 | }
6 |
7 | export type ContentType = 'AUDIO' | 'TEXT' | 'TOOL'
8 | export type AudioType = 'SPEECH'
9 | export type AudioMediaType = 'audio/lpcm'
10 | export type TextMediaType = 'text/plain' | 'application/json'
11 |
12 | export interface AudioConfiguration {
13 | readonly audioType: AudioType
14 | readonly mediaType: AudioMediaType
15 | readonly sampleRateHertz: number
16 | readonly sampleSizeBits: number
17 | readonly channelCount: number
18 | readonly encoding: string
19 | readonly voiceId?: string
20 | }
21 |
22 | export interface TextConfiguration {
23 | readonly mediaType: TextMediaType
24 | }
25 |
26 | export interface ToolConfiguration {
27 | readonly toolUseId: string
28 | readonly type: 'TEXT'
29 | readonly textInputConfiguration: {
30 | readonly mediaType: 'text/plain'
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/handlers/file-handlers.ts:
--------------------------------------------------------------------------------
1 | import { IpcMainInvokeEvent } from 'electron'
2 | import { handleFileOpen } from '../../preload/file'
3 | import fs from 'fs'
4 | import { log } from '../../common/logger'
5 | import { store } from '../../preload/store'
6 |
7 | export const fileHandlers = {
8 | 'open-file': async (_event: IpcMainInvokeEvent) => {
9 | return handleFileOpen({
10 | title: 'openFile...',
11 | properties: ['openFile']
12 | })
13 | },
14 |
15 | 'open-directory': async (_event: IpcMainInvokeEvent) => {
16 | const path = await handleFileOpen({
17 | title: 'Select Directory',
18 | properties: ['openDirectory', 'createDirectory'],
19 | message: 'Select a directory for your project',
20 | buttonLabel: 'Select Directory'
21 | })
22 |
23 | // If path was selected and it differs from the current project path,
24 | // update the project path in store
25 | if (path) {
26 | if (path !== store.get('projectPath')) {
27 | store.set('projectPath', path)
28 | log.info('Project path changed', { newPath: path })
29 | }
30 | }
31 |
32 | return path
33 | },
34 |
35 | 'get-local-image': async (_event: IpcMainInvokeEvent, path: string) => {
36 | try {
37 | const data = await fs.promises.readFile(path)
38 | const ext = path.split('.').pop()?.toLowerCase() || 'png'
39 | const base64 = data.toString('base64')
40 | return `data:image/${ext};base64,${base64}`
41 | } catch (error) {
42 | log.error('Failed to read image', {
43 | path,
44 | error: error instanceof Error ? error.message : String(error)
45 | })
46 | throw error
47 | }
48 | }
49 | } as const
50 |
--------------------------------------------------------------------------------
/src/main/handlers/window-handlers.ts:
--------------------------------------------------------------------------------
1 | import { IpcMainInvokeEvent, BrowserWindow } from 'electron'
2 |
3 | export const windowHandlers = {
4 | 'window:isFocused': async (event: IpcMainInvokeEvent) => {
5 | const window = BrowserWindow.fromWebContents(event.sender)
6 | return window?.isFocused() ?? false
7 | }
8 | } as const
9 |
--------------------------------------------------------------------------------
/src/preload/appWindow.ts:
--------------------------------------------------------------------------------
1 | import { ipcRenderer } from 'electron'
2 |
3 | export const appWindow = {
4 | isFocused: (): Promise => ipcRenderer.invoke('window:isFocused')
5 | }
6 |
--------------------------------------------------------------------------------
/src/preload/chat-history.ts:
--------------------------------------------------------------------------------
1 | import { ChatMessage } from '../types/chat/history'
2 | import { SessionMetadata } from '../types/chat/history'
3 | import { ChatSessionManager } from '../main/store/chatSession'
4 |
5 | const chatSessionManager = new ChatSessionManager()
6 |
7 | export const chatHistory = {
8 | async createSession(agentId: string, modelId: string, systemPrompt?: string) {
9 | return await chatSessionManager.createSession(agentId, modelId, systemPrompt)
10 | },
11 |
12 | async addMessage(sessionId: string, message: ChatMessage) {
13 | return await chatSessionManager.addMessage(sessionId, message)
14 | },
15 |
16 | getSession(sessionId: string) {
17 | return chatSessionManager.getSession(sessionId)
18 | },
19 |
20 | async updateSessionTitle(sessionId: string, title: string) {
21 | return await chatSessionManager.updateSessionTitle(sessionId, title)
22 | },
23 |
24 | deleteSession(sessionId: string) {
25 | return chatSessionManager.deleteSession(sessionId)
26 | },
27 |
28 | deleteAllSessions() {
29 | return chatSessionManager.deleteAllSessions()
30 | },
31 |
32 | getRecentSessions(): SessionMetadata[] {
33 | return chatSessionManager.getRecentSessions()
34 | },
35 |
36 | getAllSessionMetadata(): SessionMetadata[] {
37 | return chatSessionManager.getAllSessionMetadata()
38 | },
39 |
40 | setActiveSession(sessionId: string | undefined) {
41 | return chatSessionManager.setActiveSession(sessionId)
42 | },
43 |
44 | getActiveSessionId() {
45 | return chatSessionManager.getActiveSessionId()
46 | },
47 |
48 | async updateMessageContent(sessionId: string, messageIndex: number, updatedMessage: ChatMessage) {
49 | return await chatSessionManager.updateMessageContent(sessionId, messageIndex, updatedMessage)
50 | },
51 |
52 | async deleteMessage(sessionId: string, messageIndex: number) {
53 | return await chatSessionManager.deleteMessage(sessionId, messageIndex)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/preload/helpers/agent-helpers.ts:
--------------------------------------------------------------------------------
1 | import { store } from '../store'
2 | import { CustomAgent } from '../../types/agent-chat'
3 |
4 | /**
5 | * カスタムエージェントと共有エージェントを組み合わせて返す関数
6 | * 注: directoryAgentsは含まれません
7 | */
8 | export function getAllAgents(): CustomAgent[] {
9 | const customAgents = store.get('customAgents') || []
10 | const sharedAgents = store.get('sharedAgents') || []
11 | return [...customAgents, ...sharedAgents]
12 | }
13 |
14 | /**
15 | * IDを指定してエージェントを検索する関数
16 | * カスタムエージェントと共有エージェントから検索します
17 | */
18 | export function findAgentById(agentId: string): CustomAgent | undefined {
19 | return getAllAgents().find((agent) => agent.id === agentId)
20 | }
21 |
--------------------------------------------------------------------------------
/src/preload/ipc-client.ts:
--------------------------------------------------------------------------------
1 | import { ipcRenderer } from 'electron'
2 | import { IPCChannels, IPCParams, IPCResult } from '../types/ipc'
3 |
4 | /**
5 | * 型安全なIPC呼び出し関数
6 | */
7 | export function createIpcClient() {
8 | return {
9 | invoke: (
10 | channel: C,
11 | ...args: IPCParams extends void
12 | ? []
13 | : IPCParams extends any[]
14 | ? IPCParams
15 | : [IPCParams]
16 | ): Promise> => {
17 | return ipcRenderer.invoke(channel, ...args)
18 | }
19 | }
20 | }
21 |
22 | /**
23 | * Preload用の型安全なIPC呼び出し関数
24 | * シンプルで使いやすいAPI
25 | */
26 | export function ipc(
27 | channel: C,
28 | params: IPCParams
29 | ): Promise> {
30 | return ipcRenderer.invoke(channel, params) as Promise>
31 | }
32 |
33 | // renderer用に公開するAPIオブジェクト
34 | export const ipcClient = createIpcClient()
35 |
--------------------------------------------------------------------------------
/src/preload/lib/contentChunker.ts:
--------------------------------------------------------------------------------
1 | export interface ContentChunk {
2 | index: number
3 | total: number
4 | content: string
5 | metadata?: {
6 | url?: string
7 | filePath?: string
8 | timestamp: number
9 | }
10 | }
11 |
12 | export class ContentChunker {
13 | private static readonly MAX_CHUNK_SIZE = 50000 // 約50,000文字(Claude 3 Haikuの制限を考慮)
14 |
15 | static splitContent(
16 | content: string,
17 | metadata: { url?: string },
18 | option?: { cleaning?: boolean }
19 | ): ContentChunk[] {
20 | const chunks: ContentChunk[] = []
21 | const timestamp = Date.now()
22 |
23 | // option のデフォルトは false
24 | if (option?.cleaning) {
25 | content = this.extractMainContent(content)
26 | }
27 |
28 | // コンテンツを適切なサイズに分割
29 | const totalChunks = Math.ceil(content.length / this.MAX_CHUNK_SIZE)
30 |
31 | for (let i = 0; i < totalChunks; i++) {
32 | const start = i * this.MAX_CHUNK_SIZE
33 | const end = Math.min((i + 1) * this.MAX_CHUNK_SIZE, content.length)
34 |
35 | chunks.push({
36 | index: i + 1,
37 | total: totalChunks,
38 | content: content.slice(start, end),
39 | metadata: {
40 | ...metadata,
41 | timestamp
42 | }
43 | })
44 | }
45 |
46 | return chunks
47 | }
48 |
49 | public static extractMainContent(html: string): string {
50 | // 基本的なHTMLクリーニング
51 | const content = html
52 | .replace(/
16 |