From 81a5d31f6e80dad6a2740f33f338a8b874c6b0ff Mon Sep 17 00:00:00 2001 From: d-kimsuon Date: Mon, 20 Oct 2025 01:03:13 +0900 Subject: [PATCH] feat: integrate @anthropic-ai/claude-agent-sdk for latest version - Added @anthropic-ai/claude-agent-sdk as a dependency for improved functionality. - Updated controllablePromise to include a status property, allowing tracking of promise states (pending, resolved, rejected). - Adjusted query function to utilize the new agent SDK for enhanced query capabilities. - Updated i18n message files for better formatting and consistency. --- biome.json | 3 +- package.json | 1 + pnpm-lock.yaml | 20 +++++++ src/lib/controllablePromise.ts | 31 ++++++---- src/lib/i18n/locales/en/messages.ts | 5 +- src/lib/i18n/locales/ja/messages.ts | 5 +- .../core/claude-code/models/ClaudeCode.ts | 58 ++++++++++++++----- .../services/ClaudeCodeLifeCycleService.ts | 22 +++++++ 8 files changed, 113 insertions(+), 32 deletions(-) diff --git a/biome.json b/biome.json index db0e7f6..ea54ad9 100644 --- a/biome.json +++ b/biome.json @@ -14,7 +14,8 @@ "!src/lib/$path.ts", "!**/*.css", "!dist", - "!playwright.config.ts" + "!playwright.config.ts", + "!src/lib/i18n/locales/*/messages.ts" ] }, "formatter": { diff --git a/package.json b/package.json index 6d8cfa4..32f1c9f 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "lingui:compile": "lingui compile --typescript" }, "dependencies": { + "@anthropic-ai/claude-agent-sdk": "^0.1.22", "@anthropic-ai/claude-code": "^2.0.22", "@effect/platform": "^0.92.1", "@effect/platform-node": "^0.98.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54a24a9..570a5bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@anthropic-ai/claude-agent-sdk': + specifier: ^0.1.22 + version: 0.1.22(zod@4.1.12) '@anthropic-ai/claude-code': specifier: ^2.0.22 version: 2.0.22 @@ -187,6 +190,12 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@anthropic-ai/claude-agent-sdk@0.1.22': + resolution: {integrity: sha512-lDwbcwh5goRVUHRRqvX9v6Vj38VME1L+QIaLWzdqbK3Lwkkz9PVLNQFRDEyUOSNd9Fm4cAlfQZ0RCVe8tuo9TA==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.24.1 + '@anthropic-ai/claude-code@2.0.22': resolution: {integrity: sha512-3FVySgr2zYrHnQ0deOeCzXdLSa/JkCBm1QR7x4j07puNnvHrFhBo6whv/IMOcSvxL62RRW3csRcGsQhUGPNc/w==} engines: {node: '>=18.0.0'} @@ -4327,6 +4336,17 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@anthropic-ai/claude-agent-sdk@0.1.22(zod@4.1.12)': + dependencies: + zod: 4.1.12 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + '@anthropic-ai/claude-code@2.0.22': optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 diff --git a/src/lib/controllablePromise.ts b/src/lib/controllablePromise.ts index 98d44b0..5aa0d61 100644 --- a/src/lib/controllablePromise.ts +++ b/src/lib/controllablePromise.ts @@ -1,25 +1,36 @@ export type ControllablePromise = { - readonly promise: Promise; - readonly resolve: (value: T) => void; - readonly reject: (reason?: unknown) => void; + promise: Promise; + resolve: (value: T) => void; + reject: (reason?: unknown) => void; + status: "pending" | "resolved" | "rejected"; }; export const controllablePromise = (): ControllablePromise => { let promiseResolve: ((value: T) => void) | undefined; let promiseReject: ((reason?: unknown) => void) | undefined; + const promiseRef = { + status: "pending", + } as ControllablePromise; + const promise = new Promise((resolve, reject) => { - promiseResolve = resolve; - promiseReject = reject; + promiseResolve = (value) => { + promiseRef.status = "resolved"; + resolve(value); + }; + promiseReject = (reason) => { + promiseRef.status = "rejected"; + reject(reason); + }; }); if (!promiseResolve || !promiseReject) { throw new Error("Illegal state: Promise not created"); } - return { - promise, - resolve: promiseResolve, - reject: promiseReject, - } as const; + promiseRef.promise = promise; + promiseRef.resolve = promiseResolve; + promiseRef.reject = promiseReject; + + return promiseRef; }; diff --git a/src/lib/i18n/locales/en/messages.ts b/src/lib/i18n/locales/en/messages.ts index 3028a3d..aafb3a2 100644 --- a/src/lib/i18n/locales/en/messages.ts +++ b/src/lib/i18n/locales/en/messages.ts @@ -1,4 +1 @@ -/*eslint-disable*/ import type { Messages } from "@lingui/core"; -export const messages = JSON.parse( - '{"Available commands":["Available commands"],"Available files and directories":["Available files and directories"],"Close sidebar":["Close sidebar"],"Compare from":["Compare from"],"Compare to":["Compare to"],"Failed to commit":["Failed to commit"],"Failed to commit and push":["Failed to commit and push"],"Failed to push":["Failed to push"],"Message input with completion support":["Message input with completion support"],"Reload MCP servers":["Reload MCP servers"],"Retry Push":["Retry Push"],"Select enter key behavior":["Select enter key behavior"],"Select language":["Select language"],"Select permission mode":["Select permission mode"],"Select theme":["Select theme"],"Type your message here... (Start with / for commands, @ for files, Command+Enter to send)":["Type your message here... (Start with / for commands, @ for files, Command+Enter to send)"],"Type your message here... (Start with / for commands, @ for files, Enter to send)":["Type your message here... (Start with / for commands, @ for files, Enter to send)"],"Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)":["Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)"],"Type your message... (Start with / for commands, @ for files, Command+Enter to send)":["Type your message... (Start with / for commands, @ for files, Command+Enter to send)"],"Type your message... (Start with / for commands, @ for files, Enter to send)":["Type your message... (Start with / for commands, @ for files, Enter to send)"],"Type your message... (Start with / for commands, @ for files, Shift+Enter to send)":["Type your message... (Start with / for commands, @ for files, Shift+Enter to send)"],"Uncommitted changes":["Uncommitted changes"],"assistant.thinking":["Thinking"],"assistant.tool.input_parameters":["Input Parameters"],"assistant.tool.result":["Tool Result"],"assistant.tool_use":["Tool Use"],"chat.autocomplete.active":["Autocomplete active"],"chat.button.start":["Start Chat"],"chat.error.send_failed":["Failed to send message. Please try again."],"chat.modal.title":["Start New Chat"],"chat.resume":["Resume"],"chat.send":["Send"],"chat.status.processing":["Processing..."],"common.action.cancel":["Cancel"],"common.error":["Error"],"common.loading":["Loading..."],"conversation.error.raw_content":["Raw Content:"],"conversation.error.report_issue":["Report this issue"],"conversation.error.schema":["Schema Error"],"conversation.error.schema_validation":["Schema Validation Error"],"conversation.error.schema_validation.description":["This conversation entry failed to parse correctly. This might indicate a format change or parsing issue."],"diff.commit":["Commit"],"diff.commit.changes":["Commit Changes"],"diff.commit.message":["Commit message"],"diff.commit.push":["Commit & Push"],"diff.committing":["Committing..."],"diff.committing.pushing":["Committing & Pushing..."],"diff.deselect.all":["Deselect All"],"diff.enter.message":["Enter a commit message"],"diff.files":["files"],"diff.files.changed":["files changed"],"diff.loading":["Loading diff..."],"diff.push":["Push"],"diff.pushing":["Pushing..."],"diff.select.all":["Select All"],"diff.select.file":["Select at least one file"],"directory_picker.current":["Current:"],"directory_picker.loading":["Loading..."],"directory_picker.no_directories":["No directories found"],"directory_picker.select":["Select This Directory"],"mcp.error.load_failed":["Failed to load MCP servers: ",["error"]],"mcp.no.servers":["No MCP servers found"],"mcp.title":["MCP Servers"],"notification.beep":["Beep"],"notification.chime":["Chime"],"notification.description":["Select a sound to play when a task completes"],"notification.none":["None"],"notification.ping":["Ping"],"notification.pop":["Pop"],"notification.test":["Test"],"project.create.action.create":["Create Project"],"project.create.action.creating":["Creating..."],"project.create.description":["Select a directory to initialize as a Claude Code project. This will run <0>/init in the selected directory."],"project.create.selected_directory":["Selected directory:"],"project.create.title":["Create New Project"],"project.error.back_to_projects":["Back to Projects"],"project.error.description":["We encountered an error while loading this project"],"project.error.details_title":["Error Details"],"project.error.error_id":["Error ID:"],"project.error.title":["Failed to load project"],"project.error.try_again":["Try Again"],"project.new":["New Project"],"project.not_found.back_to_projects":["Back to Projects"],"project.not_found.description":["The project you are looking for does not exist or has been removed"],"project.not_found.title":["Project Not Found"],"project_list.last_modified":["Last modified:"],"project_list.messages":["Messages:"],"project_list.no_projects.description":["No Claude Code projects found in your ~/.claude/projects directory. Start a conversation with Claude Code to create your first project."],"project_list.no_projects.title":["No projects found"],"project_list.view_conversations":["View Conversations"],"projects.page.description":["Browse your Claude Code conversation history and project interactions"],"projects.page.loading":["Loading projects..."],"projects.page.title":["Your Projects"],"session.conversation.abort":["Abort"],"session.conversation.in.progress":["Conversation is in progress..."],"session.conversation.paused":["Conversation is paused..."],"session.processing":["Claude Code is processing..."],"session.status.paused":["Paused"],"session.status.running":["Running"],"sessions.load.more":["Load More"],"sessions.new":["New"],"sessions.title":["Sessions"],"sessions.total":["total"],"settings.description":["Display and behavior preferences"],"settings.input.enter_key_behavior":["Enter Key Behavior"],"settings.input.enter_key_behavior.command_enter":["Command+Enter to send"],"settings.input.enter_key_behavior.description":["Choose how the Enter key behaves in message input"],"settings.input.enter_key_behavior.enter":["Enter to send"],"settings.input.enter_key_behavior.shift_enter":["Shift+Enter to send (default)"],"settings.loading":["Loading settings..."],"settings.locale":["Language"],"settings.locale.description":["Choose your preferred language"],"settings.locale.en":["English"],"settings.locale.ja":["日本語"],"settings.notifications":["Notifications"],"settings.permission.mode":["Permission Mode"],"settings.permission.mode.accept_edits":["Accept Edits (Auto-approve file edits)"],"settings.permission.mode.bypass_permissions":["Bypass Permissions (No prompts)"],"settings.permission.mode.default":["Default (Ask permission)"],"settings.permission.mode.description":["Control how Claude Code handles permission requests for file operations"],"settings.permission.mode.plan":["Plan Mode (Planning only)"],"settings.section.notifications":["Notifications"],"settings.section.session_display":["Session Display"],"settings.session.display":["Session Display"],"settings.session.hide_no_user_message":["Hide sessions without user messages"],"settings.session.hide_no_user_message.description":["Only show sessions that contain user commands or messages"],"settings.session.unify_same_title":["Unify sessions with same title"],"settings.session.unify_same_title.description":["Show only the latest session when multiple sessions have the same title"],"settings.tab.title":["Settings for display and notifications"],"settings.theme":["Theme"],"settings.theme.dark":["Dark"],"settings.theme.description":["Choose your preferred color theme"],"settings.theme.light":["Light"],"settings.theme.system":["System"],"settings.title":["Settings"],"sidebar.back.to.projects":["Back to projects"],"sidebar.show.mcp.settings":["Show MCP server settings"],"sidebar.show.session.list":["Show session list"],"user.content.image":["Image"],"user.content.image.description":["User uploaded image content"],"user.content.unsupported_media":["Unsupported Media"],"user.content.unsupported_media.description":["Media type not supported for display"]}', -) as Messages; +/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"Available commands\":[\"Available commands\"],\"Available files and directories\":[\"Available files and directories\"],\"Close sidebar\":[\"Close sidebar\"],\"Compare from\":[\"Compare from\"],\"Compare to\":[\"Compare to\"],\"Failed to commit\":[\"Failed to commit\"],\"Failed to commit and push\":[\"Failed to commit and push\"],\"Failed to push\":[\"Failed to push\"],\"Message input with completion support\":[\"Message input with completion support\"],\"Reload MCP servers\":[\"Reload MCP servers\"],\"Retry Push\":[\"Retry Push\"],\"Select enter key behavior\":[\"Select enter key behavior\"],\"Select language\":[\"Select language\"],\"Select permission mode\":[\"Select permission mode\"],\"Select theme\":[\"Select theme\"],\"Type your message here... (Start with / for commands, @ for files, Command+Enter to send)\":[\"Type your message here... (Start with / for commands, @ for files, Command+Enter to send)\"],\"Type your message here... (Start with / for commands, @ for files, Enter to send)\":[\"Type your message here... (Start with / for commands, @ for files, Enter to send)\"],\"Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)\":[\"Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)\"],\"Type your message... (Start with / for commands, @ for files, Command+Enter to send)\":[\"Type your message... (Start with / for commands, @ for files, Command+Enter to send)\"],\"Type your message... (Start with / for commands, @ for files, Enter to send)\":[\"Type your message... (Start with / for commands, @ for files, Enter to send)\"],\"Type your message... (Start with / for commands, @ for files, Shift+Enter to send)\":[\"Type your message... (Start with / for commands, @ for files, Shift+Enter to send)\"],\"Uncommitted changes\":[\"Uncommitted changes\"],\"assistant.thinking\":[\"Thinking\"],\"assistant.tool.input_parameters\":[\"Input Parameters\"],\"assistant.tool.result\":[\"Tool Result\"],\"assistant.tool_use\":[\"Tool Use\"],\"chat.autocomplete.active\":[\"Autocomplete active\"],\"chat.button.start\":[\"Start Chat\"],\"chat.error.send_failed\":[\"Failed to send message. Please try again.\"],\"chat.modal.title\":[\"Start New Chat\"],\"chat.resume\":[\"Resume\"],\"chat.send\":[\"Send\"],\"chat.status.processing\":[\"Processing...\"],\"common.action.cancel\":[\"Cancel\"],\"common.error\":[\"Error\"],\"common.loading\":[\"Loading...\"],\"conversation.error.raw_content\":[\"Raw Content:\"],\"conversation.error.report_issue\":[\"Report this issue\"],\"conversation.error.schema\":[\"Schema Error\"],\"conversation.error.schema_validation\":[\"Schema Validation Error\"],\"conversation.error.schema_validation.description\":[\"This conversation entry failed to parse correctly. This might indicate a format change or parsing issue.\"],\"diff.commit\":[\"Commit\"],\"diff.commit.changes\":[\"Commit Changes\"],\"diff.commit.message\":[\"Commit message\"],\"diff.commit.push\":[\"Commit & Push\"],\"diff.committing\":[\"Committing...\"],\"diff.committing.pushing\":[\"Committing & Pushing...\"],\"diff.deselect.all\":[\"Deselect All\"],\"diff.enter.message\":[\"Enter a commit message\"],\"diff.files\":[\"files\"],\"diff.files.changed\":[\"files changed\"],\"diff.loading\":[\"Loading diff...\"],\"diff.push\":[\"Push\"],\"diff.pushing\":[\"Pushing...\"],\"diff.select.all\":[\"Select All\"],\"diff.select.file\":[\"Select at least one file\"],\"directory_picker.current\":[\"Current:\"],\"directory_picker.loading\":[\"Loading...\"],\"directory_picker.no_directories\":[\"No directories found\"],\"directory_picker.select\":[\"Select This Directory\"],\"mcp.error.load_failed\":[\"Failed to load MCP servers: \",[\"error\"]],\"mcp.no.servers\":[\"No MCP servers found\"],\"mcp.title\":[\"MCP Servers\"],\"notification.beep\":[\"Beep\"],\"notification.chime\":[\"Chime\"],\"notification.description\":[\"Select a sound to play when a task completes\"],\"notification.none\":[\"None\"],\"notification.ping\":[\"Ping\"],\"notification.pop\":[\"Pop\"],\"notification.test\":[\"Test\"],\"project.create.action.create\":[\"Create Project\"],\"project.create.action.creating\":[\"Creating...\"],\"project.create.description\":[\"Select a directory to initialize as a Claude Code project. This will run <0>/init in the selected directory.\"],\"project.create.selected_directory\":[\"Selected directory:\"],\"project.create.title\":[\"Create New Project\"],\"project.error.back_to_projects\":[\"Back to Projects\"],\"project.error.description\":[\"We encountered an error while loading this project\"],\"project.error.details_title\":[\"Error Details\"],\"project.error.error_id\":[\"Error ID:\"],\"project.error.title\":[\"Failed to load project\"],\"project.error.try_again\":[\"Try Again\"],\"project.new\":[\"New Project\"],\"project.not_found.back_to_projects\":[\"Back to Projects\"],\"project.not_found.description\":[\"The project you are looking for does not exist or has been removed\"],\"project.not_found.title\":[\"Project Not Found\"],\"project_list.last_modified\":[\"Last modified:\"],\"project_list.messages\":[\"Messages:\"],\"project_list.no_projects.description\":[\"No Claude Code projects found in your ~/.claude/projects directory. Start a conversation with Claude Code to create your first project.\"],\"project_list.no_projects.title\":[\"No projects found\"],\"project_list.view_conversations\":[\"View Conversations\"],\"projects.page.description\":[\"Browse your Claude Code conversation history and project interactions\"],\"projects.page.loading\":[\"Loading projects...\"],\"projects.page.title\":[\"Your Projects\"],\"session.conversation.abort\":[\"Abort\"],\"session.conversation.in.progress\":[\"Conversation is in progress...\"],\"session.conversation.paused\":[\"Conversation is paused...\"],\"session.processing\":[\"Claude Code is processing...\"],\"session.status.paused\":[\"Paused\"],\"session.status.running\":[\"Running\"],\"sessions.load.more\":[\"Load More\"],\"sessions.new\":[\"New\"],\"sessions.title\":[\"Sessions\"],\"sessions.total\":[\"total\"],\"settings.description\":[\"Display and behavior preferences\"],\"settings.input.enter_key_behavior\":[\"Enter Key Behavior\"],\"settings.input.enter_key_behavior.command_enter\":[\"Command+Enter to send\"],\"settings.input.enter_key_behavior.description\":[\"Choose how the Enter key behaves in message input\"],\"settings.input.enter_key_behavior.enter\":[\"Enter to send\"],\"settings.input.enter_key_behavior.shift_enter\":[\"Shift+Enter to send (default)\"],\"settings.loading\":[\"Loading settings...\"],\"settings.locale\":[\"Language\"],\"settings.locale.description\":[\"Choose your preferred language\"],\"settings.locale.en\":[\"English\"],\"settings.locale.ja\":[\"日本語\"],\"settings.notifications\":[\"Notifications\"],\"settings.permission.mode\":[\"Permission Mode\"],\"settings.permission.mode.accept_edits\":[\"Accept Edits (Auto-approve file edits)\"],\"settings.permission.mode.bypass_permissions\":[\"Bypass Permissions (No prompts)\"],\"settings.permission.mode.default\":[\"Default (Ask permission)\"],\"settings.permission.mode.description\":[\"Control how Claude Code handles permission requests for file operations\"],\"settings.permission.mode.plan\":[\"Plan Mode (Planning only)\"],\"settings.section.notifications\":[\"Notifications\"],\"settings.section.session_display\":[\"Session Display\"],\"settings.session.display\":[\"Session Display\"],\"settings.session.hide_no_user_message\":[\"Hide sessions without user messages\"],\"settings.session.hide_no_user_message.description\":[\"Only show sessions that contain user commands or messages\"],\"settings.session.unify_same_title\":[\"Unify sessions with same title\"],\"settings.session.unify_same_title.description\":[\"Show only the latest session when multiple sessions have the same title\"],\"settings.tab.title\":[\"Settings for display and notifications\"],\"settings.theme\":[\"Theme\"],\"settings.theme.dark\":[\"Dark\"],\"settings.theme.description\":[\"Choose your preferred color theme\"],\"settings.theme.light\":[\"Light\"],\"settings.theme.system\":[\"System\"],\"settings.title\":[\"Settings\"],\"sidebar.back.to.projects\":[\"Back to projects\"],\"sidebar.show.mcp.settings\":[\"Show MCP server settings\"],\"sidebar.show.session.list\":[\"Show session list\"],\"user.content.image\":[\"Image\"],\"user.content.image.description\":[\"User uploaded image content\"],\"user.content.unsupported_media\":[\"Unsupported Media\"],\"user.content.unsupported_media.description\":[\"Media type not supported for display\"]}")as Messages; \ No newline at end of file diff --git a/src/lib/i18n/locales/ja/messages.ts b/src/lib/i18n/locales/ja/messages.ts index 93c2fcb..dc9cf88 100644 --- a/src/lib/i18n/locales/ja/messages.ts +++ b/src/lib/i18n/locales/ja/messages.ts @@ -1,4 +1 @@ -/*eslint-disable*/ import type { Messages } from "@lingui/core"; -export const messages = JSON.parse( - '{"Available commands":["利用可能なコマンド"],"Available files and directories":["利用可能なファイルとディレクトリ"],"Close sidebar":["サイドバーを閉じる"],"Compare from":["比較元"],"Compare to":["比較先"],"Failed to commit":["コミットに失敗しました"],"Failed to commit and push":["コミットとプッシュに失敗しました"],"Failed to push":["プッシュに失敗しました"],"Message input with completion support":["補完機能付きメッセージ入力"],"Reload MCP servers":["MCPサーバーを再読み込み"],"Retry Push":["プッシュを再試行"],"Select enter key behavior":["Enterキーの動作を選択"],"Select language":["言語を選択"],"Select permission mode":["権限モードを選択"],"Select theme":["テーマを選択"],"Type your message here... (Start with / for commands, @ for files, Command+Enter to send)":["ここにメッセージを入力... (/でコマンド、@でファイル、Command+Enterで送信)"],"Type your message here... (Start with / for commands, @ for files, Enter to send)":["ここにメッセージを入力... (/でコマンド、@でファイル、Enterで送信)"],"Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)":["ここにメッセージを入力... (/でコマンド、@でファイル、Shift+Enterで送信)"],"Type your message... (Start with / for commands, @ for files, Command+Enter to send)":["メッセージを入力... (/でコマンド、@でファイル、Command+Enterで送信)"],"Type your message... (Start with / for commands, @ for files, Enter to send)":["メッセージを入力... (/でコマンド、@でファイル、Enterで送信)"],"Type your message... (Start with / for commands, @ for files, Shift+Enter to send)":["メッセージを入力... (/でコマンド、@でファイル、Shift+Enterで送信)"],"Uncommitted changes":["未コミットの変更"],"assistant.thinking":["思考中"],"assistant.tool.input_parameters":["入力パラメータ"],"assistant.tool.result":["ツール実行結果"],"assistant.tool_use":["ツール使用"],"chat.autocomplete.active":["オートコンプリート有効"],"chat.button.start":["チャット開始"],"chat.error.send_failed":["メッセージの送信に失敗しました。もう一度お試しください。"],"chat.modal.title":["新しいチャットを開始"],"chat.resume":["再開"],"chat.send":["送信"],"chat.status.processing":["処理中..."],"common.action.cancel":["キャンセル"],"common.error":["エラー"],"common.loading":["読み込み中..."],"conversation.error.raw_content":["生データ:"],"conversation.error.report_issue":["この問題を報告"],"conversation.error.schema":["スキーマエラー"],"conversation.error.schema_validation":["スキーマ検証エラー"],"conversation.error.schema_validation.description":["この会話エントリの解析に失敗しました。フォーマットの変更または解析の問題が考えられます。"],"diff.commit":["コミット"],"diff.commit.changes":["変更をコミット"],"diff.commit.message":["コミットメッセージ"],"diff.commit.push":["コミット&プッシュ"],"diff.committing":["コミット中..."],"diff.committing.pushing":["コミット&プッシュ中..."],"diff.deselect.all":["すべて選択解除"],"diff.enter.message":["コミットメッセージを入力"],"diff.files":["ファイル"],"diff.files.changed":["ファイルが変更されました"],"diff.loading":["差分を読み込み中..."],"diff.push":["プッシュ"],"diff.pushing":["プッシュ中..."],"diff.select.all":["すべて選択"],"diff.select.file":["少なくとも1つのファイルを選択してください"],"directory_picker.current":["現在:"],"directory_picker.loading":["読み込み中..."],"directory_picker.no_directories":["ディレクトリが見つかりません"],"directory_picker.select":["このディレクトリを選択"],"mcp.error.load_failed":["MCPサーバーの読み込みに失敗しました: ",["error"]],"mcp.no.servers":["MCPサーバーが見つかりません"],"mcp.title":["MCPサーバー"],"notification.beep":["ビープ音"],"notification.chime":["チャイム"],"notification.description":["Claude Code のタスクが完了した時に再生する音を選択してください"],"notification.none":["なし"],"notification.ping":["ピン"],"notification.pop":["ポップ"],"notification.test":["テスト"],"project.create.action.create":["プロジェクトを作成"],"project.create.action.creating":["作成中..."],"project.create.description":["Claude Codeプロジェクトとして初期化するディレクトリを選択してください。選択したディレクトリで<0>/initが実行されます。"],"project.create.selected_directory":["選択したディレクトリ:"],"project.create.title":["新規プロジェクトを作成"],"project.error.back_to_projects":["プロジェクト一覧に戻る"],"project.error.description":["このプロジェクトの読み込み中にエラーが発生しました"],"project.error.details_title":["エラー詳細"],"project.error.error_id":["エラーID:"],"project.error.title":["プロジェクトの読み込みに失敗しました"],"project.error.try_again":["再試行"],"project.new":["新規プロジェクト"],"project.not_found.back_to_projects":["プロジェクト一覧に戻る"],"project.not_found.description":["お探しのプロジェクトは存在しないか、削除されています"],"project.not_found.title":["プロジェクトが見つかりません"],"project_list.last_modified":["最終更新:"],"project_list.messages":["メッセージ:"],"project_list.no_projects.description":["~/.claude/projectsディレクトリにClaude Codeプロジェクトが見つかりません。Claude Codeとの会話を開始して、最初のプロジェクトを作成してください。"],"project_list.no_projects.title":["プロジェクトが見つかりません"],"project_list.view_conversations":["会話を表示"],"projects.page.description":["Claude Codeの会話履歴とプロジェクトの操作を閲覧"],"projects.page.loading":["プロジェクトを読み込み中..."],"projects.page.title":["プロジェクト"],"session.conversation.abort":["中止"],"session.conversation.in.progress":["会話を進行中..."],"session.conversation.paused":["会話を一時停止中..."],"session.processing":["Claude Codeが処理中..."],"session.status.paused":["一時停止"],"session.status.running":["実行中"],"sessions.load.more":["さらに読み込む"],"sessions.new":["新規"],"sessions.title":["セッション"],"sessions.total":["合計"],"settings.description":["表示と動作の設定"],"settings.input.enter_key_behavior":["Enterキーの動作"],"settings.input.enter_key_behavior.command_enter":["Command+Enterで送信"],"settings.input.enter_key_behavior.description":["メッセージ入力でのEnterキーの動作を選択"],"settings.input.enter_key_behavior.enter":["Enterで送信"],"settings.input.enter_key_behavior.shift_enter":["Shift+Enterで送信(デフォルト)"],"settings.loading":["設定を読み込み中..."],"settings.locale":["言語"],"settings.locale.description":["お好みの言語を選択"],"settings.locale.en":["English"],"settings.locale.ja":["日本語"],"settings.notifications":["通知"],"settings.permission.mode":["権限モード"],"settings.permission.mode.accept_edits":["編集を承認(ファイル編集を自動承認)"],"settings.permission.mode.bypass_permissions":["権限をバイパス(プロンプトなし)"],"settings.permission.mode.default":["デフォルト(権限を確認)"],"settings.permission.mode.description":["ファイル操作の権限リクエストの処理方法を制御"],"settings.permission.mode.plan":["プランモード(計画のみ)"],"settings.section.notifications":["通知"],"settings.section.session_display":["セッション表示"],"settings.session.display":["セッション表示"],"settings.session.hide_no_user_message":["ユーザーメッセージのないセッションを非表示"],"settings.session.hide_no_user_message.description":["ユーザーコマンドまたはメッセージを含むセッションのみを表示"],"settings.session.unify_same_title":["同じタイトルのセッションを統合"],"settings.session.unify_same_title.description":["同じタイトルの複数のセッションがある場合、最新のセッションのみを表示"],"settings.tab.title":["表示と通知の設定"],"settings.theme":["テーマ"],"settings.theme.dark":["ダーク"],"settings.theme.description":["お好みのカラーテーマを選択"],"settings.theme.light":["ライト"],"settings.theme.system":["システム"],"settings.title":["設定"],"sidebar.back.to.projects":["プロジェクト一覧に戻る"],"sidebar.show.mcp.settings":["MCPサーバー設定を表示"],"sidebar.show.session.list":["セッション一覧を表示"],"user.content.image":["画像"],"user.content.image.description":["ユーザーがアップロードした画像コンテンツ"],"user.content.unsupported_media":["サポートされていないメディア"],"user.content.unsupported_media.description":["表示がサポートされていないメディア形式です"]}', -) as Messages; +/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"Available commands\":[\"利用可能なコマンド\"],\"Available files and directories\":[\"利用可能なファイルとディレクトリ\"],\"Close sidebar\":[\"サイドバーを閉じる\"],\"Compare from\":[\"比較元\"],\"Compare to\":[\"比較先\"],\"Failed to commit\":[\"コミットに失敗しました\"],\"Failed to commit and push\":[\"コミットとプッシュに失敗しました\"],\"Failed to push\":[\"プッシュに失敗しました\"],\"Message input with completion support\":[\"補完機能付きメッセージ入力\"],\"Reload MCP servers\":[\"MCPサーバーを再読み込み\"],\"Retry Push\":[\"プッシュを再試行\"],\"Select enter key behavior\":[\"Enterキーの動作を選択\"],\"Select language\":[\"言語を選択\"],\"Select permission mode\":[\"権限モードを選択\"],\"Select theme\":[\"テーマを選択\"],\"Type your message here... (Start with / for commands, @ for files, Command+Enter to send)\":[\"ここにメッセージを入力... (/でコマンド、@でファイル、Command+Enterで送信)\"],\"Type your message here... (Start with / for commands, @ for files, Enter to send)\":[\"ここにメッセージを入力... (/でコマンド、@でファイル、Enterで送信)\"],\"Type your message here... (Start with / for commands, @ for files, Shift+Enter to send)\":[\"ここにメッセージを入力... (/でコマンド、@でファイル、Shift+Enterで送信)\"],\"Type your message... (Start with / for commands, @ for files, Command+Enter to send)\":[\"メッセージを入力... (/でコマンド、@でファイル、Command+Enterで送信)\"],\"Type your message... (Start with / for commands, @ for files, Enter to send)\":[\"メッセージを入力... (/でコマンド、@でファイル、Enterで送信)\"],\"Type your message... (Start with / for commands, @ for files, Shift+Enter to send)\":[\"メッセージを入力... (/でコマンド、@でファイル、Shift+Enterで送信)\"],\"Uncommitted changes\":[\"未コミットの変更\"],\"assistant.thinking\":[\"思考中\"],\"assistant.tool.input_parameters\":[\"入力パラメータ\"],\"assistant.tool.result\":[\"ツール実行結果\"],\"assistant.tool_use\":[\"ツール使用\"],\"chat.autocomplete.active\":[\"オートコンプリート有効\"],\"chat.button.start\":[\"チャット開始\"],\"chat.error.send_failed\":[\"メッセージの送信に失敗しました。もう一度お試しください。\"],\"chat.modal.title\":[\"新しいチャットを開始\"],\"chat.resume\":[\"再開\"],\"chat.send\":[\"送信\"],\"chat.status.processing\":[\"処理中...\"],\"common.action.cancel\":[\"キャンセル\"],\"common.error\":[\"エラー\"],\"common.loading\":[\"読み込み中...\"],\"conversation.error.raw_content\":[\"生データ:\"],\"conversation.error.report_issue\":[\"この問題を報告\"],\"conversation.error.schema\":[\"スキーマエラー\"],\"conversation.error.schema_validation\":[\"スキーマ検証エラー\"],\"conversation.error.schema_validation.description\":[\"この会話エントリの解析に失敗しました。フォーマットの変更または解析の問題が考えられます。\"],\"diff.commit\":[\"コミット\"],\"diff.commit.changes\":[\"変更をコミット\"],\"diff.commit.message\":[\"コミットメッセージ\"],\"diff.commit.push\":[\"コミット&プッシュ\"],\"diff.committing\":[\"コミット中...\"],\"diff.committing.pushing\":[\"コミット&プッシュ中...\"],\"diff.deselect.all\":[\"すべて選択解除\"],\"diff.enter.message\":[\"コミットメッセージを入力\"],\"diff.files\":[\"ファイル\"],\"diff.files.changed\":[\"ファイルが変更されました\"],\"diff.loading\":[\"差分を読み込み中...\"],\"diff.push\":[\"プッシュ\"],\"diff.pushing\":[\"プッシュ中...\"],\"diff.select.all\":[\"すべて選択\"],\"diff.select.file\":[\"少なくとも1つのファイルを選択してください\"],\"directory_picker.current\":[\"現在:\"],\"directory_picker.loading\":[\"読み込み中...\"],\"directory_picker.no_directories\":[\"ディレクトリが見つかりません\"],\"directory_picker.select\":[\"このディレクトリを選択\"],\"mcp.error.load_failed\":[\"MCPサーバーの読み込みに失敗しました: \",[\"error\"]],\"mcp.no.servers\":[\"MCPサーバーが見つかりません\"],\"mcp.title\":[\"MCPサーバー\"],\"notification.beep\":[\"ビープ音\"],\"notification.chime\":[\"チャイム\"],\"notification.description\":[\"Claude Code のタスクが完了した時に再生する音を選択してください\"],\"notification.none\":[\"なし\"],\"notification.ping\":[\"ピン\"],\"notification.pop\":[\"ポップ\"],\"notification.test\":[\"テスト\"],\"project.create.action.create\":[\"プロジェクトを作成\"],\"project.create.action.creating\":[\"作成中...\"],\"project.create.description\":[\"Claude Codeプロジェクトとして初期化するディレクトリを選択してください。選択したディレクトリで<0>/initが実行されます。\"],\"project.create.selected_directory\":[\"選択したディレクトリ:\"],\"project.create.title\":[\"新規プロジェクトを作成\"],\"project.error.back_to_projects\":[\"プロジェクト一覧に戻る\"],\"project.error.description\":[\"このプロジェクトの読み込み中にエラーが発生しました\"],\"project.error.details_title\":[\"エラー詳細\"],\"project.error.error_id\":[\"エラーID:\"],\"project.error.title\":[\"プロジェクトの読み込みに失敗しました\"],\"project.error.try_again\":[\"再試行\"],\"project.new\":[\"新規プロジェクト\"],\"project.not_found.back_to_projects\":[\"プロジェクト一覧に戻る\"],\"project.not_found.description\":[\"お探しのプロジェクトは存在しないか、削除されています\"],\"project.not_found.title\":[\"プロジェクトが見つかりません\"],\"project_list.last_modified\":[\"最終更新:\"],\"project_list.messages\":[\"メッセージ:\"],\"project_list.no_projects.description\":[\"~/.claude/projectsディレクトリにClaude Codeプロジェクトが見つかりません。Claude Codeとの会話を開始して、最初のプロジェクトを作成してください。\"],\"project_list.no_projects.title\":[\"プロジェクトが見つかりません\"],\"project_list.view_conversations\":[\"会話を表示\"],\"projects.page.description\":[\"Claude Codeの会話履歴とプロジェクトの操作を閲覧\"],\"projects.page.loading\":[\"プロジェクトを読み込み中...\"],\"projects.page.title\":[\"プロジェクト\"],\"session.conversation.abort\":[\"中止\"],\"session.conversation.in.progress\":[\"会話を進行中...\"],\"session.conversation.paused\":[\"会話を一時停止中...\"],\"session.processing\":[\"Claude Codeが処理中...\"],\"session.status.paused\":[\"一時停止\"],\"session.status.running\":[\"実行中\"],\"sessions.load.more\":[\"さらに読み込む\"],\"sessions.new\":[\"新規\"],\"sessions.title\":[\"セッション\"],\"sessions.total\":[\"合計\"],\"settings.description\":[\"表示と動作の設定\"],\"settings.input.enter_key_behavior\":[\"Enterキーの動作\"],\"settings.input.enter_key_behavior.command_enter\":[\"Command+Enterで送信\"],\"settings.input.enter_key_behavior.description\":[\"メッセージ入力でのEnterキーの動作を選択\"],\"settings.input.enter_key_behavior.enter\":[\"Enterで送信\"],\"settings.input.enter_key_behavior.shift_enter\":[\"Shift+Enterで送信(デフォルト)\"],\"settings.loading\":[\"設定を読み込み中...\"],\"settings.locale\":[\"言語\"],\"settings.locale.description\":[\"お好みの言語を選択\"],\"settings.locale.en\":[\"English\"],\"settings.locale.ja\":[\"日本語\"],\"settings.notifications\":[\"通知\"],\"settings.permission.mode\":[\"権限モード\"],\"settings.permission.mode.accept_edits\":[\"編集を承認(ファイル編集を自動承認)\"],\"settings.permission.mode.bypass_permissions\":[\"権限をバイパス(プロンプトなし)\"],\"settings.permission.mode.default\":[\"デフォルト(権限を確認)\"],\"settings.permission.mode.description\":[\"ファイル操作の権限リクエストの処理方法を制御\"],\"settings.permission.mode.plan\":[\"プランモード(計画のみ)\"],\"settings.section.notifications\":[\"通知\"],\"settings.section.session_display\":[\"セッション表示\"],\"settings.session.display\":[\"セッション表示\"],\"settings.session.hide_no_user_message\":[\"ユーザーメッセージのないセッションを非表示\"],\"settings.session.hide_no_user_message.description\":[\"ユーザーコマンドまたはメッセージを含むセッションのみを表示\"],\"settings.session.unify_same_title\":[\"同じタイトルのセッションを統合\"],\"settings.session.unify_same_title.description\":[\"同じタイトルの複数のセッションがある場合、最新のセッションのみを表示\"],\"settings.tab.title\":[\"表示と通知の設定\"],\"settings.theme\":[\"テーマ\"],\"settings.theme.dark\":[\"ダーク\"],\"settings.theme.description\":[\"お好みのカラーテーマを選択\"],\"settings.theme.light\":[\"ライト\"],\"settings.theme.system\":[\"システム\"],\"settings.title\":[\"設定\"],\"sidebar.back.to.projects\":[\"プロジェクト一覧に戻る\"],\"sidebar.show.mcp.settings\":[\"MCPサーバー設定を表示\"],\"sidebar.show.session.list\":[\"セッション一覧を表示\"],\"user.content.image\":[\"画像\"],\"user.content.image.description\":[\"ユーザーがアップロードした画像コンテンツ\"],\"user.content.unsupported_media\":[\"サポートされていないメディア\"],\"user.content.unsupported_media.description\":[\"表示がサポートされていないメディア形式です\"]}")as Messages; \ No newline at end of file diff --git a/src/server/core/claude-code/models/ClaudeCode.ts b/src/server/core/claude-code/models/ClaudeCode.ts index bc35522..ffddbd0 100644 --- a/src/server/core/claude-code/models/ClaudeCode.ts +++ b/src/server/core/claude-code/models/ClaudeCode.ts @@ -1,13 +1,24 @@ -import { query as originalQuery } from "@anthropic-ai/claude-code"; +import { query as agentSdkQuery } from "@anthropic-ai/claude-agent-sdk"; +import { query as claudeCodeQuery } from "@anthropic-ai/claude-code"; import { Command, Path } from "@effect/platform"; import { Effect } from "effect"; import { EnvService } from "../../platform/services/EnvService"; import * as ClaudeCodeVersion from "./ClaudeCodeVersion"; -type CCQuery = typeof originalQuery; +type CCQuery = typeof claudeCodeQuery; type CCQueryPrompt = Parameters[0]["prompt"]; type CCQueryOptions = NonNullable[0]["options"]>; +type AgentSdkQuery = typeof agentSdkQuery; +type AgentSdkQueryOptions = NonNullable< + Parameters[0]["options"] +>; + +type SharedOptions = Pick< + CCQueryOptions, + Extract +>; + export const Config = Effect.gen(function* () { const path = yield* Path.Path; const envService = yield* EnvService; @@ -73,26 +84,47 @@ export const getAvailableFeatures = ( patch: 86, }) : false, + agentSdk: + claudeCodeVersion !== null + ? ClaudeCodeVersion.greaterThanOrEqual(claudeCodeVersion, { + major: 1, + minor: 0, + patch: 125, // ClaudeCodeAgentSDK is available since v1.0.125 + }) + : false, }); -export const query = (prompt: CCQueryPrompt, options: CCQueryOptions) => { +export const query = (prompt: CCQueryPrompt, options: SharedOptions) => { const { canUseTool, permissionMode, ...baseOptions } = options; return Effect.gen(function* () { const { claudeCodeExecutablePath, claudeCodeVersion } = yield* Config; const availableFeatures = getAvailableFeatures(claudeCodeVersion); - return originalQuery({ + const options: SharedOptions = { + pathToClaudeCodeExecutable: claudeCodeExecutablePath, + ...baseOptions, + ...(availableFeatures.canUseTool + ? { canUseTool, permissionMode } + : { + permissionMode: "bypassPermissions", + }), + }; + + if (availableFeatures.agentSdk) { + return agentSdkQuery({ + prompt, + options: { + systemPrompt: { type: "preset", preset: "claude_code" }, + settingSources: ["user", "project", "local"], + ...options, + }, + }); + } + + return claudeCodeQuery({ prompt, - options: { - pathToClaudeCodeExecutable: claudeCodeExecutablePath, - ...baseOptions, - ...(availableFeatures.canUseTool - ? { canUseTool, permissionMode } - : { - permissionMode: "bypassPermissions", - }), - }, + options: options, }); }); }; diff --git a/src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts b/src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts index 0bab352..8511ecb 100644 --- a/src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts +++ b/src/server/core/claude-code/services/ClaudeCodeLifeCycleService.ts @@ -293,6 +293,14 @@ const LayerImpl = Effect.gen(function* () { }), ); + if (sessionInitializedPromise.status === "pending") { + sessionInitializedPromise.reject(error); + } + + if (sessionFileCreatedPromise.status === "pending") { + sessionFileCreatedPromise.reject(error); + } + return "continue" as const; }); @@ -302,6 +310,14 @@ const LayerImpl = Effect.gen(function* () { } } } catch (error) { + if (sessionInitializedPromise.status === "pending") { + sessionInitializedPromise.reject(error); + } + + if (sessionFileCreatedPromise.status === "pending") { + sessionFileCreatedPromise.reject(error); + } + await Effect.runPromise( sessionProcessService.changeTaskState({ sessionProcessId: sessionProcess.def.sessionProcessId, @@ -319,6 +335,12 @@ const LayerImpl = Effect.gen(function* () { const daemonPromise = handleSessionProcessDaemon() .catch((error) => { console.error("Error occur in task daemon process", error); + if (sessionInitializedPromise.status === "pending") { + sessionInitializedPromise.reject(error); + } + if (sessionFileCreatedPromise.status === "pending") { + sessionFileCreatedPromise.reject(error); + } throw error; }) .finally(() => {