bizboost 6.6.8 → 6.6.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/auth/InteractiveLogin.d.ts.map +1 -1
- package/dist/auth/InteractiveLogin.js +3 -1
- package/dist/auth/InteractiveLogin.js.map +1 -1
- package/dist/auth/PortalAuthClient.js +3 -1
- package/dist/auth/TokenManager.d.ts +22 -0
- package/dist/auth/TokenManager.d.ts.map +1 -1
- package/dist/auth/TokenManager.js +3 -1
- package/dist/auth/TokenManager.js.map +1 -1
- package/dist/bin/bluelamp-secret.mjs +2 -0
- package/dist/bin/bluelamp-vscode-base.mjs +3 -1
- package/dist/i18n/en.d.ts +1 -2
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ja.d.ts +1 -2
- package/dist/i18n/ja.d.ts.map +1 -1
- package/dist/i18n/ja.js +1 -1
- package/dist/i18n/ja.js.map +1 -1
- package/dist/lib/claudeAccount.d.ts +3 -2
- package/dist/lib/claudeAccount.d.ts.map +1 -1
- package/dist/lib/claudeAccount.js.map +1 -1
- package/dist/lib/claudeAccountLine.d.ts +24 -0
- package/dist/lib/claudeAccountLine.d.ts.map +1 -0
- package/dist/lib/claudeAccountLine.js +1 -0
- package/dist/lib/claudeAccountLine.js.map +1 -0
- package/dist/lib/connectResilience.d.ts +43 -0
- package/dist/lib/connectResilience.d.ts.map +1 -0
- package/dist/lib/connectResilience.js +1 -0
- package/dist/lib/connectResilience.js.map +1 -0
- package/dist/lib/headlessLaunch.d.ts +27 -0
- package/dist/lib/headlessLaunch.d.ts.map +1 -1
- package/dist/lib/headlessLaunch.js +1 -1
- package/dist/lib/headlessLaunch.js.map +1 -1
- package/dist/lib/mcp-server/index.cjs +1 -1
- package/dist/lib/mcp-server/install-package.cjs +1 -1
- package/dist/lib/mcp-server/portal-api-client.cjs +1 -1
- package/dist/lib/secretExec.d.ts +86 -0
- package/dist/lib/secretExec.d.ts.map +1 -0
- package/dist/lib/secretExec.js +1 -0
- package/dist/lib/secretExec.js.map +1 -0
- package/dist/lib/slotKeywordResolve.d.ts +21 -24
- package/dist/lib/slotKeywordResolve.d.ts.map +1 -1
- package/dist/lib/slotKeywordResolve.js +1 -1
- package/dist/lib/slotKeywordResolve.js.map +1 -1
- package/dist/lib/sysPromptHandoff.d.ts +9 -0
- package/dist/lib/sysPromptHandoff.d.ts.map +1 -0
- package/dist/lib/sysPromptHandoff.js +1 -0
- package/dist/lib/sysPromptHandoff.js.map +1 -0
- package/dist/lib/whoami.d.ts +2 -3
- package/dist/lib/whoami.d.ts.map +1 -1
- package/dist/lib/whoami.js.map +1 -1
- package/package.json +4 -1
- package/dist/lib/accountAssurance.d.ts +0 -41
- package/dist/lib/accountAssurance.d.ts.map +0 -1
- package/dist/lib/accountAssurance.js +0 -1
- package/dist/lib/accountAssurance.js.map +0 -1
package/dist/i18n/en.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export declare const en: {
|
|
|
7
7
|
readonly loadedEnv: "Loaded .env";
|
|
8
8
|
readonly undefinedCommand: "Undefined command: {commandName}";
|
|
9
9
|
readonly customSlotConfig: "Custom slot config: slot{slotNumber} → \"{keyword}\"";
|
|
10
|
-
readonly slotConfigError: "Slot config error, using default: {error}";
|
|
11
10
|
readonly brandTitle: "B i z B o o s t";
|
|
12
11
|
readonly commandInfo: "Command: {commandName}{slotInfo}";
|
|
13
12
|
readonly debugMode: "Debug mode: enabled";
|
|
@@ -38,7 +37,6 @@ export declare const en: {
|
|
|
38
37
|
readonly extendedMode: "Connected to BizBoost";
|
|
39
38
|
readonly claudeAccountLabel: "Claude: {email}";
|
|
40
39
|
readonly claudeAccountNotLoggedIn: "Claude: not logged in (the login screen appears on first launch)";
|
|
41
|
-
readonly claudeAccountMismatch: "You are logged in to BizBoost and Claude with different accounts — this is why a paid plan can show as Free. Open claude.ai with the Claude address above to check your plan, or run /login to switch to the BizBoost address.";
|
|
42
40
|
};
|
|
43
41
|
readonly auth: {
|
|
44
42
|
readonly portalAuthTitle: "BizBoost - Portal Auth";
|
|
@@ -46,6 +44,7 @@ export declare const en: {
|
|
|
46
44
|
readonly validationResult: "Validation result:";
|
|
47
45
|
readonly existingTokenValid: "Existing token is valid";
|
|
48
46
|
readonly savedTokenInvalid: "Saved token is invalid";
|
|
47
|
+
readonly savedTokenUnverifiable: "Could not verify the saved token ({error}). Keeping it and continuing with the saved token";
|
|
49
48
|
readonly enterCredentials: "Enter your Portal login credentials";
|
|
50
49
|
readonly invalidEmail: "Invalid email address format";
|
|
51
50
|
readonly emptyPassword: "Password was not entered";
|
package/dist/i18n/en.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GL,CAAC"}
|
package/dist/i18n/en.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.en=void 0,exports.en={base:{loadedEnvLocal:"Loaded .env.local",loadedEnv:"Loaded .env",undefinedCommand:"Undefined command: {commandName}",customSlotConfig:'Custom slot config: slot{slotNumber} → "{keyword}"',
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.en=void 0,exports.en={base:{loadedEnvLocal:"Loaded .env.local",loadedEnv:"Loaded .env",undefinedCommand:"Undefined command: {commandName}",customSlotConfig:'Custom slot config: slot{slotNumber} → "{keyword}"',brandTitle:"B i z B o o s t",commandInfo:"Command: {commandName}{slotInfo}",debugMode:"Debug mode: enabled",logFile:"Log file: {path}",promptInfo:"Prompt: {keyword}",initialPromptTitle:"Let's get started",initialPromptInputHint:'Type your request in the "❯" box below and press Enter (if typing does nothing, click this panel once).',initialPromptLoadContext:'BizBoost MCP reference materials "{keyword}" are available for this session.\nPlease use the load_knowledge tool to load "{keyword}" before starting.',initialPromptKeywordNote:"If MCP tools are not yet loaded, please wait a moment and try again.",initialPromptReady:"",launchingClaude:"Launching Claude...",startInstruction:"Your main prompt has already been loaded. Follow its definition and begin naturally by greeting the user.",mcpServer:"MCP Server: BizBoost",knowledge:"Knowledge: {keyword}",debugInfo:"Debug info:",debugCommand:"Command: {command}",debugArgs:"Args: {args}",debugConfigFile:"MCP config file: {path}",debugEnvKeyword:"Env BLUELAMP_KEYWORD: {keyword}",debugEnvToken:"CLI token (portal-token.enc): {token}...",debugEnvPortal:"Env PORTAL_URL: {url}",debugConfigContent:"MCP config file contents:",claudeStartError:"Claude launch error: {error}",sessionEnd:"BizBoost session ended",shuttingDown:"Shutting down BizBoost...",unexpectedError:"Unexpected error: {error}",authActivated:"Connected to BizBoost",extendedMode:"Connected to BizBoost",claudeAccountLabel:"Claude: {email}",claudeAccountNotLoggedIn:"Claude: not logged in (the login screen appears on first launch)"},auth:{portalAuthTitle:"BizBoost - Portal Auth",checkingSavedToken:"Checking saved token...",validationResult:"Validation result:",existingTokenValid:"Existing token is valid",savedTokenInvalid:"Saved token is invalid",savedTokenUnverifiable:"Could not verify the saved token ({error}). Keeping it and continuing with the saved token",enterCredentials:"Enter your Portal login credentials",invalidEmail:"Invalid email address format",emptyPassword:"Password was not entered",kiLimitExceeded:"Knowledge injection usage limit reached",kiLimitCheckPortal:"Check your usage on the Portal",authError:"Auth error: {error}",savingToken:"Saving token...",tokenSaveFailed:"Token save failed (auth succeeded)",tokenSaved:"Token saved securely",unexpectedError:"Unexpected error: {error}",authSuccess:"Portal auth successful",userLabel:"User: {name}",emailLabel:"Email: {email}",roleLabel:"Role: {role}",usingCachedToken:"Using cached token",firstLoginComplete:"First login complete",logoutTitle:"BizBoost - Logout",confirmLogout:"Delete login credentials? (y/N): ",logoutSuccess:"Login credentials deleted",logoutNotFound:"No login credentials found",logoutCancelled:"Cancelled",envUpdateFailed:"Failed to update .env file: {error}",authAttempt:"Auth attempt {attempt}/{max}...",authOk:"Portal auth successful",tokenOk:"Token acquired",authRetry:"Retrying in {delay}ms...",portalAuthError:"Portal auth error: {error}",portalAuthHelp1:"1. Check your internet connection",portalAuthHelp2:"2. Verify your Portal credentials",portalAuthHelp3:"3. Check if {url} is accessible",portalAuthHelpTitle:"Troubleshooting:",tokenSaveComplete:"Token saved",tokenSaveError:"Token save error: {error}",tokenLoadError:"Token load error: {error}",tokenDeleteError:"Token delete error: {error}",invalidTokenFormat:"Only Portal-issued cli_ format tokens are supported",networkError:"Network error: {error}",requestTimeout:"Request timed out",responseParseError:"Response parse error: {error}"},mcp:{toolDescriptionLoadKnowledge:"Retrieve project reference materials from BizBoost",keywordDescription:"Keyword (e.g. @相談 — use as-is, no prefix needed)",knowledgeLoadSuccess:"BizBoost Specialized Context Loaded",knowledgeApplied:"Reference information loaded. Please refer to the above content for assistance.",knowledgeNotFound:'No knowledge found for keyword "{keyword}"',knowledgeLoadError:"Error loading knowledge: {error}",promptNotFoundForKeyword:'No prompt found for keyword "{keyword}"',apiReturnedError:"API returned an error",portalApiError:"Portal API error (HTTP {status})",portalApiFailed:"Failed to retrieve knowledge from Portal API: {error}",portalCommunicationError:"Portal API communication error: {error}",noAuthToken:"No auth token set. Run any of bluelamp1-300 in a terminal to open the login screen (this creates ~/.musuhi/portal-token.enc).",listMcpsFailed:"Failed to list MCPs: {error}",getMcpInfoFailed:"Failed to get MCP info: {error}",callToolFailed:"Tool execution failed: {error}",violationNoToken:"No auth token set",violationApiError:"Violation report error (HTTP {status})",violationCommunicationError:"Violation report communication error: {error}"}};
|
package/dist/i18n/en.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,EAAE,GAAG;IAChB,IAAI,EAAE;QACJ,cAAc,EAAE,mBAAmB;QACnC,SAAS,EAAE,aAAa;QACxB,gBAAgB,EAAE,kCAAkC;QACpD,gBAAgB,EAAE,oDAAoD;QACtE,
|
|
1
|
+
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/ja.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export declare const ja: {
|
|
|
8
8
|
readonly loadedEnv: "Loaded .env";
|
|
9
9
|
readonly undefinedCommand: "未定義のコマンド: {commandName}";
|
|
10
10
|
readonly customSlotConfig: "カスタムスロット設定: slot{slotNumber} → \"{keyword}\"";
|
|
11
|
-
readonly slotConfigError: "スロット設定取得エラー、デフォルトを使用: {error}";
|
|
12
11
|
readonly brandTitle: "B i z B o o s t";
|
|
13
12
|
readonly commandInfo: "コマンド: {commandName}{slotInfo}";
|
|
14
13
|
readonly debugMode: "デバッグモード: 有効";
|
|
@@ -39,7 +38,6 @@ export declare const ja: {
|
|
|
39
38
|
readonly extendedMode: "BizBoost に接続しました";
|
|
40
39
|
readonly claudeAccountLabel: "Claude: {email}";
|
|
41
40
|
readonly claudeAccountNotLoggedIn: "Claude: 未ログイン(初回起動時にログイン画面が出ます)";
|
|
42
|
-
readonly claudeAccountMismatch: "BizBoost と Claude で別のアカウントにログインしています——「払っているのに無料プランと出る」原因はこれです。claude.ai を上の Claude 側アドレスで開いて契約を確認するか、/login で BizBoost 側アドレスに切り替えてください。";
|
|
43
41
|
};
|
|
44
42
|
readonly auth: {
|
|
45
43
|
readonly portalAuthTitle: "BizBoost ─ 認証";
|
|
@@ -47,6 +45,7 @@ export declare const ja: {
|
|
|
47
45
|
readonly validationResult: "検証結果:";
|
|
48
46
|
readonly existingTokenValid: "既存のトークンが有効です";
|
|
49
47
|
readonly savedTokenInvalid: "保存されたトークンが無効です";
|
|
48
|
+
readonly savedTokenUnverifiable: "保存されたトークンを確かめられませんでした({error})。消さずに、保存済みのトークンで続けます";
|
|
50
49
|
readonly enterCredentials: "Portalログイン情報を入力してください";
|
|
51
50
|
readonly invalidEmail: "無効なメールアドレス形式です";
|
|
52
51
|
readonly emptyPassword: "パスワードが入力されていません";
|
package/dist/i18n/ja.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/i18n/ja.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/i18n/ja.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GL,CAAC"}
|
package/dist/i18n/ja.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ja=void 0,exports.ja={base:{loadedEnvLocal:"Loaded .env.local",loadedEnv:"Loaded .env",undefinedCommand:"未定義のコマンド: {commandName}",customSlotConfig:'カスタムスロット設定: slot{slotNumber} → "{keyword}"',
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ja=void 0,exports.ja={base:{loadedEnvLocal:"Loaded .env.local",loadedEnv:"Loaded .env",undefinedCommand:"未定義のコマンド: {commandName}",customSlotConfig:'カスタムスロット設定: slot{slotNumber} → "{keyword}"',brandTitle:"B i z B o o s t",commandInfo:"コマンド: {commandName}{slotInfo}",debugMode:"デバッグモード: 有効",logFile:"ログファイル: {path}",promptInfo:"プロンプト: {keyword}",initialPromptTitle:"さあ始めましょう",initialPromptInputHint:"ご用件は、この下の「❯」の欄に日本語で入力して Enter を押してください(文字が打てない時は、この画面を一度クリックしてください)。",initialPromptLoadContext:'このセッションではBizBoost MCPの参考資料 "{keyword}" が利用可能です。\nload_knowledge ツールで "{keyword}" を読み込んでから始めてください。',initialPromptKeywordNote:"MCPツールがまだ読み込まれていない場合は、少し待ってから再度お試しください。",initialPromptReady:"",launchingClaude:"Claude 起動中...",startInstruction:"あなたの本体プロンプトは読み込み済みです。本体の定義に従い、ユーザーへの挨拶から自然に開始してください。",mcpServer:"MCP Server: BizBoost",knowledge:"Knowledge: {keyword}",debugInfo:"デバッグ情報:",debugCommand:"コマンド: {command}",debugArgs:"引数: {args}",debugConfigFile:"MCP設定ファイル: {path}",debugEnvKeyword:"環境変数 MUSUHI_KEYWORD: {keyword}",debugEnvToken:"CLI トークン (portal-token.enc): {token}...",debugEnvPortal:"環境変数 PORTAL_URL: {url}",debugConfigContent:"MCP設定ファイル内容:",claudeStartError:"Claude 起動エラー: {error}",sessionEnd:"BizBoost セッション終了",shuttingDown:"BizBoost を終了しています...",unexpectedError:"予期しないエラー: {error}",authActivated:"BizBoost に接続しました",extendedMode:"BizBoost に接続しました",claudeAccountLabel:"Claude: {email}",claudeAccountNotLoggedIn:"Claude: 未ログイン(初回起動時にログイン画面が出ます)"},auth:{portalAuthTitle:"BizBoost ─ 認証",checkingSavedToken:"保存されたトークンを確認中...",validationResult:"検証結果:",existingTokenValid:"既存のトークンが有効です",savedTokenInvalid:"保存されたトークンが無効です",savedTokenUnverifiable:"保存されたトークンを確かめられませんでした({error})。消さずに、保存済みのトークンで続けます",enterCredentials:"Portalログイン情報を入力してください",invalidEmail:"無効なメールアドレス形式です",emptyPassword:"パスワードが入力されていません",kiLimitExceeded:"ナレッジインジェクション使用回数が上限に達しています",kiLimitCheckPortal:"Portalで使用状況を確認してください",authError:"認証エラー: {error}",savingToken:"トークンを保存中...",tokenSaveFailed:"トークン保存に失敗しました(認証は成功)",tokenSaved:"トークンを安全に保存しました",unexpectedError:"予期しないエラー: {error}",authSuccess:"Portal認証成功",userLabel:"ユーザー: {name}",emailLabel:"Email: {email}",roleLabel:"ロール: {role}",usingCachedToken:"保存済みトークンを使用",firstLoginComplete:"初回ログイン完了",logoutTitle:"BizBoost - ログアウト",confirmLogout:"ログイン情報を削除しますか? (y/N): ",logoutSuccess:"ログイン情報を削除しました",logoutNotFound:"ログイン情報が見つかりません",logoutCancelled:"キャンセルしました",envUpdateFailed:"envファイルの更新に失敗: {error}",authAttempt:"認証試行 {attempt}/{max}...",authOk:"Portal認証成功",tokenOk:"トークン取得成功",authRetry:"{delay}ms後にリトライ...",portalAuthError:"Portal認証エラー: {error}",portalAuthHelp1:"1. インターネット接続を確認してください",portalAuthHelp2:"2. Portal認証情報が正しいか確認してください",portalAuthHelp3:"3. {url} にアクセスできるか確認してください",portalAuthHelpTitle:"解決方法:",tokenSaveComplete:"トークン保存完了",tokenSaveError:"トークン保存エラー: {error}",tokenLoadError:"トークン読み込みエラー: {error}",tokenDeleteError:"トークン削除エラー: {error}",invalidTokenFormat:"CLI形式トークンのみサポートされています(CLI_xxx形式)",networkError:"ネットワークエラー: {error}",requestTimeout:"リクエストタイムアウト",responseParseError:"レスポンス解析エラー: {error}"},mcp:{toolDescriptionLoadKnowledge:"プロジェクトの参考資料を取得します",keywordDescription:"キーワード(@相談 など、そのまま指定してください。プレフィックスの追加は不要です)",knowledgeLoadSuccess:"BizBoost 専門コンテキスト読み込み完了",knowledgeApplied:"参考情報の読み込みが完了しました。上記の内容を参考にしてご支援ください。",knowledgeNotFound:'キーワード "{keyword}" に対応する知識が見つかりませんでした',knowledgeLoadError:"知識の読み込み中にエラーが発生しました: {error}",promptNotFoundForKeyword:'キーワード "{keyword}" に対応するプロンプトが見つかりませんでした',apiReturnedError:"APIがエラーを返しました",portalApiError:"Portal APIエラー (HTTP {status})",portalApiFailed:"Portal APIから知識を取得できませんでした: {error}",portalCommunicationError:"Portal API通信エラー: {error}",noAuthToken:"認証トークンが設定されていません。ターミナルで bluelamp1〜300 のいずれかを実行するとログイン画面が出ます(~/.musuhi/portal-token.enc が作成されます)。",listMcpsFailed:"MCP一覧の取得に失敗しました: {error}",getMcpInfoFailed:"MCP情報の取得に失敗しました: {error}",callToolFailed:"ツール実行に失敗しました: {error}",violationNoToken:"認証トークンが設定されていません",violationApiError:"違反報告エラー (HTTP {status})",violationCommunicationError:"違反報告通信エラー: {error}"}};
|
package/dist/i18n/ja.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ja.js","sourceRoot":"","sources":["../../src/i18n/ja.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,EAAE,GAAG;IAChB,IAAI,EAAE;QACJ,cAAc,EAAE,mBAAmB;QACnC,SAAS,EAAE,aAAa;QACxB,gBAAgB,EAAE,yBAAyB;QAC3C,gBAAgB,EAAE,4CAA4C;QAC9D,
|
|
1
|
+
{"version":3,"file":"ja.js","sourceRoot":"","sources":["../../src/i18n/ja.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* Claude Code は claude.ai のログイン情報を `~/.claude.json` のトップレベル `oauthAccount` に平文で持つ。
|
|
6
6
|
* 実在キーは `accountUuid / emailAddress / organizationUuid / ... / organizationType` 等で、
|
|
7
7
|
* **`emailAddress` がまさに「claude.ai にログインしているアドレス」**。
|
|
8
|
-
* BlueLamp 側のアドレス(`LoginResult.user.email
|
|
9
|
-
*
|
|
8
|
+
* ⛔ BlueLamp 側のアドレス(`LoginResult.user.email`)との一致は**求めない**——別アカウントでの
|
|
9
|
+
* 併用は正常な使い方であり、不具合の原因ではない(主君裁定 2026-09-21・箱 n=1915)。
|
|
10
|
+
* ⇒ 読んだ値は **表示(`claudeAccountLine.ts`)にしか使わない**。
|
|
10
11
|
*
|
|
11
12
|
* 置き場所は環境変数 `CLAUDE_CONFIG_DIR` で移動する(実測)。⇒ `CLAUDE_CONFIG_DIR ?? homedir` を見る。
|
|
12
13
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claudeAccount.d.ts","sourceRoot":"","sources":["../../src/lib/claudeAccount.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claudeAccount.d.ts","sourceRoot":"","sources":["../../src/lib/claudeAccount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE;IAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EACxD,OAAO,EAAE,MAAM,GACd,MAAM,CAGR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CASvE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EACtC,GAAG,EAAE;IAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EACxD,OAAO,EAAE,MAAM,GACd,aAAa,GAAG,IAAI,CAMtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claudeAccount.js","sourceRoot":"","sources":["../../src/lib/claudeAccount.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"claudeAccount.js","sourceRoot":"","sources":["../../src/lib/claudeAccount.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWH,4CAMC;AAOD,oDASC;AAMD,wDAUC;AA/CD,gDAAkC;AAQlC,6EAA6E;AAC7E,SAAgB,gBAAgB,CAC9B,GAAwD,EACxD,OAAe;IAEf,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAC/E,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,GAAY;IAC/C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,OAAO,GAAI,GAAkC,CAAC,YAAY,CAAC;IACjE,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,KAAK,GAAI,OAAsC,CAAC,YAAY,CAAC;IACnE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAgB,sBAAsB,CACpC,QAAsC,EACtC,GAAwD,EACxD,OAAe;IAEf,IAAI,CAAC;QACH,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 起動時に Claude 側のログインアカウントを見せる 1 行を組み立てる(板 #526 F3・純関数)。
|
|
3
|
+
*
|
|
4
|
+
* 仕様(要件書 `docs/requirements-cli-onboarding-f345.md` §3 + 主君裁定 2026-09-21・箱 n=1915):
|
|
5
|
+
* 1. **常時 1 行**: 既存 `📧 Email:`(BlueLamp) の並びに `🤖 Claude:` を**毎回**出す
|
|
6
|
+
* 2. Claude 未ログイン(`.claude.json` 無し/壊れ/`oauthAccount` 無し)は
|
|
7
|
+
* `🤖 Claude: 未ログイン(初回起動時にログイン画面が出ます)`
|
|
8
|
+
* 3. ⛔ **BlueLamp 側と食い違っても警告しない**(主君裁定 2026-09-21)。
|
|
9
|
+
* 別アカウントでの併用は正常な使い方であり不具合の原因ではない
|
|
10
|
+
* (旧実装は不一致を不具合の原因として案内していたが、その因果は否定された)。
|
|
11
|
+
* ⇒ 不一致の判定そのものを持たない(判定だけ残すと表示が復活する余地が残る)
|
|
12
|
+
* 4. ⛔ プラン名(無料/Pro/Max)を断定しない——`organizationType` を表示に使わない
|
|
13
|
+
* 5. ⛔ ブロックしない(例外・遅延・戻り値で起動を止めない)
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ 本モジュールは `console` を持たない。**行を組み立てて返すだけ**で、出力は `bin/` 側が行う
|
|
16
|
+
* (出力順の検証は実出力で行い、ここは文字列として単体で測れる状態に保つ)。
|
|
17
|
+
*/
|
|
18
|
+
import type { ClaudeAccount } from './claudeAccount.js';
|
|
19
|
+
/**
|
|
20
|
+
* 常時 1 行を組み立てる。表示には**読み取った綴りをそのまま**使う。
|
|
21
|
+
* `null`(未ログイン/読めない)は案内の 1 行に倒す=行が消えることはない。
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildClaudeAccountLine(claudeAccount: ClaudeAccount | null): string;
|
|
24
|
+
//# sourceMappingURL=claudeAccountLine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeAccountLine.d.ts","sourceRoot":"","sources":["../../src/lib/claudeAccountLine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAGlF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.buildClaudeAccountLine=buildClaudeAccountLine;const index_js_1=require("../i18n/index.js");function buildClaudeAccountLine(e){return e?`🤖 ${(0,index_js_1.t)("base.claudeAccountLabel",{email:e.emailAddress})}`:`🤖 ${(0,index_js_1.t)("base.claudeAccountNotLoggedIn")}`}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeAccountLine.js","sourceRoot":"","sources":["../../src/lib/claudeAccountLine.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;AASH,wDAGC;AAVD,+CAAqC;AAGrC;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,aAAmC;IACxE,IAAI,CAAC,aAAa;QAAE,OAAO,MAAM,IAAA,YAAC,EAAC,+BAA+B,CAAC,EAAE,CAAC;IACtE,OAAO,MAAM,IAAA,YAAC,EAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 負荷下でも portal へつながるための、接続まわりの耐性(箱 n=1959)。
|
|
3
|
+
*
|
|
4
|
+
* 🩸 塞いでいる穴(2026-09-23 実測・ami機 node v24.5.0):
|
|
5
|
+
* node 20+ の既定は `autoSelectFamily=true`・`autoSelectFamilyAttemptTimeout=250ms`。
|
|
6
|
+
* api.motohi.jp は A と AAAA を返し、IPv6 の経路が無い機体では IPv4 の 1 本だけが頼りになる。
|
|
7
|
+
* CPU 負荷で event loop が 250ms 以上止まると、**その IPv4 の試行がタイマーで打ち切られ**、
|
|
8
|
+
* IPv6 は EHOSTUNREACH で落ちて `AggregateError ETIMEDOUT`(**message が空**)になる。
|
|
9
|
+
* ⇒ 起動子は slot 設定を取れず `process.exit(1)` し、tmux session ごと消えていた。
|
|
10
|
+
* gateway は目録を取れず「Starting with no services」で立ち、本体プロンプトも載らなかった。
|
|
11
|
+
* 🔬 再現: DNS 解決の直後に loop を 400ms 塞ぐと 0/5・塞がないと 5/5(tests/connect-resilience.test.mjs)。
|
|
12
|
+
*
|
|
13
|
+
* 🔑 直し方は「試行の打ち切りを負荷の揺れより長くする」。`autoSelectFamily` 自体は切らない
|
|
14
|
+
* ——切ると IPv6 が先に返る網で IPv4 へ落ちられなくなる(直したい障害の裏返しを作る)。
|
|
15
|
+
*
|
|
16
|
+
* 2 本目の防御として、起動の前に失敗すると致命な呼び出しだけ「通信の失敗」に限って撃ち直す
|
|
17
|
+
* (判断と間隔はここの純関数・撃つのは呼び出し側)。404 / 403 のような**答えが返った失敗**は撃ち直さない。
|
|
18
|
+
*/
|
|
19
|
+
/** 1 回の接続試行を打ち切るまでの時間(ms)。既定 250ms では負荷の揺れに負ける。 */
|
|
20
|
+
export declare const CONNECT_ATTEMPT_TIMEOUT_MS = 5000;
|
|
21
|
+
/** 撃ち直しを含めた最大の試行回数(初回を含む)。 */
|
|
22
|
+
export declare const NETWORK_RETRY_ATTEMPTS = 3;
|
|
23
|
+
/** n 回目の失敗のあとに待つ時間(ms)。長さ = NETWORK_RETRY_ATTEMPTS - 1。 */
|
|
24
|
+
export declare const NETWORK_RETRY_DELAYS_MS: readonly number[];
|
|
25
|
+
/** `node:net` のうち、ここで使う口だけ。 */
|
|
26
|
+
export interface NetDefaultsLike {
|
|
27
|
+
setDefaultAutoSelectFamilyAttemptTimeout?: (value: number) => void;
|
|
28
|
+
getDefaultAutoSelectFamilyAttemptTimeout?: () => number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* プロセス全体の接続試行の打ち切りを伸ばす。**最初の socket より前に**呼ぶこと。
|
|
32
|
+
* API が無い node(< 20)では何もしない(その版は happy eyeballs を持たない=この穴も無い)。
|
|
33
|
+
* @returns 適用後の値。適用できなかったときは null
|
|
34
|
+
*/
|
|
35
|
+
export declare function applyConnectResilience(net: NetDefaultsLike): number | null;
|
|
36
|
+
/**
|
|
37
|
+
* 通信の失敗に限って撃ち直す。`isNetworkFailure` が偽の結果(成功・404 等)はそのまま返す。
|
|
38
|
+
* @param attempt 1 回撃つ関数
|
|
39
|
+
* @param isNetworkFailure 撃ち直すべき結果か
|
|
40
|
+
* @param sleep 待ち(テストから差し替える)
|
|
41
|
+
*/
|
|
42
|
+
export declare function retryOnNetworkFailure<T>(attempt: () => Promise<T>, isNetworkFailure: (result: T) => boolean, sleep?: (ms: number) => Promise<void>): Promise<T>;
|
|
43
|
+
//# sourceMappingURL=connectResilience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectResilience.d.ts","sourceRoot":"","sources":["../../src/lib/connectResilience.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,mDAAmD;AACnD,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,8BAA8B;AAC9B,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,2DAA2D;AAC3D,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAiB,CAAC;AAEvE,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,wCAAwC,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,wCAAwC,CAAC,EAAE,MAAM,MAAM,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAa1E;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,EACxC,KAAK,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAiD,GACnF,OAAO,CAAC,CAAC,CAAC,CAOZ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function applyConnectResilience(e){return"function"!=typeof e.setDefaultAutoSelectFamilyAttemptTimeout?null:(("function"==typeof e.getDefaultAutoSelectFamilyAttemptTimeout?e.getDefaultAutoSelectFamilyAttemptTimeout():0)<exports.CONNECT_ATTEMPT_TIMEOUT_MS&&e.setDefaultAutoSelectFamilyAttemptTimeout(exports.CONNECT_ATTEMPT_TIMEOUT_MS),"function"==typeof e.getDefaultAutoSelectFamilyAttemptTimeout?e.getDefaultAutoSelectFamilyAttemptTimeout():exports.CONNECT_ATTEMPT_TIMEOUT_MS)}async function retryOnNetworkFailure(e,t,T=e=>new Promise(t=>setTimeout(t,e))){let o=await e();for(let E=1;E<exports.NETWORK_RETRY_ATTEMPTS&&t(o);E++)await T(exports.NETWORK_RETRY_DELAYS_MS[E-1]??exports.NETWORK_RETRY_DELAYS_MS[exports.NETWORK_RETRY_DELAYS_MS.length-1]),o=await e();return o}Object.defineProperty(exports,"__esModule",{value:!0}),exports.NETWORK_RETRY_DELAYS_MS=exports.NETWORK_RETRY_ATTEMPTS=exports.CONNECT_ATTEMPT_TIMEOUT_MS=void 0,exports.applyConnectResilience=applyConnectResilience,exports.retryOnNetworkFailure=retryOnNetworkFailure,exports.CONNECT_ATTEMPT_TIMEOUT_MS=5e3,exports.NETWORK_RETRY_ATTEMPTS=3,exports.NETWORK_RETRY_DELAYS_MS=[1e3,2e3];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectResilience.js","sourceRoot":"","sources":["../../src/lib/connectResilience.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAsBH,wDAaC;AAQD,sDAWC;AApDD,mDAAmD;AACtC,QAAA,0BAA0B,GAAG,IAAI,CAAC;AAE/C,8BAA8B;AACjB,QAAA,sBAAsB,GAAG,CAAC,CAAC;AAExC,2DAA2D;AAC9C,QAAA,uBAAuB,GAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAQvE;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,GAAoB;IACzD,IAAI,OAAO,GAAG,CAAC,wCAAwC,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACpF,MAAM,OAAO,GACX,OAAO,GAAG,CAAC,wCAAwC,KAAK,UAAU;QAChE,CAAC,CAAC,GAAG,CAAC,wCAAwC,EAAE;QAChD,CAAC,CAAC,CAAC,CAAC;IACR,wBAAwB;IACxB,IAAI,OAAO,GAAG,kCAA0B,EAAE,CAAC;QACzC,GAAG,CAAC,wCAAwC,CAAC,kCAA0B,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,OAAO,GAAG,CAAC,wCAAwC,KAAK,UAAU;QACvE,CAAC,CAAC,GAAG,CAAC,wCAAwC,EAAE;QAChD,CAAC,CAAC,kCAA0B,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,qBAAqB,CACzC,OAAyB,EACzB,gBAAwC,EACxC,QAAuC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpF,IAAI,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,8BAAsB,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5E,MAAM,KAAK,CAAC,+BAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,+BAAuB,CAAC,+BAAuB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3G,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
* launcher が読んだうえで**自前の一時 config を組み直して**渡している。素通ししてしまうと
|
|
26
26
|
* claude 側で bluelamp サーバー定義が二重になり、#432 で直したテナント引き継ぎを壊す。
|
|
27
27
|
*/
|
|
28
|
+
/**
|
|
29
|
+
* 箱 n=1984: 無人の起動元(scheduler)が、席の最初の prompt そのものとして task を渡す flag。
|
|
30
|
+
* 背景(2026-09-20 実測): scheduler は席が立ってから tmux で task を打ち込んでいたが、その前に席が
|
|
31
|
+
* 「本体の定義に従い開始してください」で自走し、別の便の手順を撃って閉じた(task は 1 度も届かなかった)。
|
|
32
|
+
* ⇒ task を起動引数にして、最初の prompt を task にする=届く前に動く隙間を無くす。
|
|
33
|
+
*/
|
|
34
|
+
export declare const TASK_FILE_FLAG = "--task-file";
|
|
28
35
|
/**
|
|
29
36
|
* 利用者がヘッドレス起動を要求しているか。
|
|
30
37
|
* ⚠️ 判定は `-p` / `--print` の**現れ方**だけで行い、値は見ない
|
|
@@ -60,4 +67,24 @@ export interface BuildClaudeArgsResult {
|
|
|
60
67
|
* ⇒ 挨拶定型が無いので、利用者の `-p "<指示>"` が唯一の prompt になる。
|
|
61
68
|
*/
|
|
62
69
|
export declare function buildClaudeArgs(input: BuildClaudeArgsInput): BuildClaudeArgsResult;
|
|
70
|
+
export type LauncherTask =
|
|
71
|
+
/** `--task-file` 無し=従来どおり(挨拶定型で開始) */
|
|
72
|
+
{
|
|
73
|
+
kind: 'none';
|
|
74
|
+
}
|
|
75
|
+
/** task を最初の prompt にする */
|
|
76
|
+
| {
|
|
77
|
+
kind: 'task';
|
|
78
|
+
text: string;
|
|
79
|
+
}
|
|
80
|
+
/** 指定されたのに読めない/空=**起動しない**(task の無い席を自走させない) */
|
|
81
|
+
| {
|
|
82
|
+
kind: 'invalid';
|
|
83
|
+
error: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* `--task-file <path>` / `--task-file=<path>` を読む(純関数・読み込みは注入)。
|
|
87
|
+
* ⛔ 指定があるのに読めない・空なら invalid。呼び出し側は claude を起動せずに止める。
|
|
88
|
+
*/
|
|
89
|
+
export declare function readLauncherTask(argv: readonly string[], readFile: (p: string) => string): LauncherTask;
|
|
63
90
|
//# sourceMappingURL=headlessLaunch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/headlessLaunch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;
|
|
1
|
+
{"version":3,"file":"headlessLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/headlessLaunch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAS5C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE/D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAwBzE;AAED,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAclF;AAED,MAAM,MAAM,YAAY;AACtB,sCAAsC;AACpC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,2BAA2B;GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChC,gDAAgD;GAC9C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,YAAY,CAwBvG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.isHeadlessArgv=isHeadlessArgv,exports.stripLauncherOwnedFlags=stripLauncherOwnedFlags,exports.buildClaudeArgs=buildClaudeArgs;const LAUNCHER_OWNED_VALUE_FLAGS=["--mcp-config"],LAUNCHER_OWNED_BOOLEAN_FLAGS=["--debug"],HEADLESS_FLAGS=["-p","--print"];function isHeadlessArgv(
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TASK_FILE_FLAG=void 0,exports.isHeadlessArgv=isHeadlessArgv,exports.stripLauncherOwnedFlags=stripLauncherOwnedFlags,exports.buildClaudeArgs=buildClaudeArgs,exports.readLauncherTask=readLauncherTask,exports.TASK_FILE_FLAG="--task-file";const LAUNCHER_OWNED_VALUE_FLAGS=["--mcp-config",exports.TASK_FILE_FLAG],LAUNCHER_OWNED_BOOLEAN_FLAGS=["--debug"],HEADLESS_FLAGS=["-p","--print"];function isHeadlessArgv(e){return e.some(e=>"string"==typeof e&&HEADLESS_FLAGS.includes(e))}function stripLauncherOwnedFlags(e){const s=[];for(let r=0;r<e.length;r+=1){const t=e[r];if("string"!=typeof t)continue;if(LAUNCHER_OWNED_BOOLEAN_FLAGS.includes(t))continue;const n=LAUNCHER_OWNED_VALUE_FLAGS.find(e=>t===e||t.startsWith(`${e}=`));if(n){if(t===n){const s=e[r+1];"string"!=typeof s||s.startsWith("-")||(r+=1)}}else s.push(t)}return s}function buildClaudeArgs(e){const s=isHeadlessArgv(e.userArgs),r=stripLauncherOwnedFlags(e.userArgs);return{args:[...s?[]:[e.initialPrompt],"--dangerously-skip-permissions",...e.sysArgs,"--mcp-config",e.configPath,...r],headless:s}}function readLauncherTask(e,s){let r,t,n=!1;for(let s=0;s<e.length;s+=1){const t=e[s];if(t===exports.TASK_FILE_FLAG){n=!0;const t=e[s+1];r="string"!=typeof t||t.startsWith("-")?void 0:t}else"string"==typeof t&&t.startsWith(`${exports.TASK_FILE_FLAG}=`)&&(n=!0,r=t.slice(exports.TASK_FILE_FLAG.length+1)||void 0)}if(!n)return{kind:"none"};if(void 0===r)return{kind:"invalid",error:`${exports.TASK_FILE_FLAG} にファイルの path がありません`};try{t=s(r)}catch(e){return{kind:"invalid",error:`${exports.TASK_FILE_FLAG} ${r} を読めません: ${e instanceof Error?e.message:String(e)}`}}return 0===t.trim().length?{kind:"invalid",error:`${exports.TASK_FILE_FLAG} ${r} が空です`}:{kind:"task",text:t.trim()}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessLaunch.js","sourceRoot":"","sources":["../../src/lib/headlessLaunch.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG
|
|
1
|
+
{"version":3,"file":"headlessLaunch.js","sourceRoot":"","sources":["../../src/lib/headlessLaunch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const{Server:Server}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:StdioServerTransport}=require("@modelcontextprotocol/sdk/server/stdio.js"),{CallToolRequestSchema:CallToolRequestSchema,ListToolsRequestSchema:ListToolsRequestSchema}=require("@modelcontextprotocol/sdk/types.js"),{getPromptFromPortal:getPromptFromPortal,listAvailableMcps:listAvailableMcps,downloadMcpPackage:downloadMcpPackage,getGatewayConfig:getGatewayConfig,searchMcpServices:searchMcpServices,installMcpService:installMcpService,setServiceDeactivated:setServiceDeactivated,uninstallMcpService:uninstallMcpService,updateMcpEnv:updateMcpEnv,callMcpToolProxy:callMcpToolProxy}=require("./portal-api-client.cjs"),{requireFromPackage:requireFromPackage}=require("../requireFromPackage.cjs"),{logger:logger}=requireFromPackage(require,"../../utils/logger"),{t:t,setLanguage:setLanguage}=requireFromPackage(require,"../../i18n"),{describeTokenForDebug:describeTokenForDebug}=requireFromPackage(require,"../../lib/debugRedaction"),{collectUpdateNotices:collectUpdateNotices,buildUpdateNoticeText:buildUpdateNoticeText}=require("./mcp-version-advisor.cjs"),{installPackageFiles:installPackageFiles,formatInstallFailure:formatInstallFailure}=require("./install-package.cjs"),spawn=require("cross-spawn"),{StringDecoder:StringDecoder}=require("string_decoder"),path=require("path"),fs=require("fs"),os=require("os"),dotenvLocalPath=path.join(__dirname,"../../.env.local"),dotenvPath=path.join(__dirname,"../../.env");fs.existsSync(dotenvLocalPath)?(require("dotenv").config({path:dotenvLocalPath}),logger.debug("[MCP Server] Loaded .env.local")):fs.existsSync(dotenvPath)&&(require("dotenv").config({path:dotenvPath}),logger.debug("[MCP Server] Loaded .env"));const KEYWORD=process.env.MUSUHI_KEYWORD||"BL-要件定義",{TokenManager:TokenManager}=requireFromPackage(require,"../../auth/TokenManager");function resolveToken(){return TokenManager.loadTokenStringSync()}const PORTAL_URL_ENV=process.env.BLUELAMP_PORTAL_API_BASE_URL||process.env.PORTAL_URL||"",isDevEnv=PORTAL_URL_ENV.includes("localhost"),PORTAL_URL=PORTAL_URL_ENV||(isDevEnv?"http://localhost:8430/api/bluelamp":"https://api.motohi.jp/api/bluelamp"),LANGUAGE=process.env.MUSUHI_LANGUAGE||"ja",CATALOG_CACHE_FILE=path.join(os.homedir(),".bluelamp-vscode","gateway-catalog.json"),CATALOG_CACHE_VERSION=1,CHILD_READY_TIMEOUT_MS=3e4,CHILD_NOT_READY_TEXT="起動中です。数秒後に再試行してください";setLanguage(LANGUAGE);const LOG_DIR=path.join(os.homedir(),".bluelamp-vscode","logs"),LOG_FILE=path.join(LOG_DIR,"mcp.log");function log(e){const t=`[${(new Date).toISOString()}] ${e}\n`;fs.appendFileSync(LOG_FILE,t),logger.info(`[MCP Server] ${e}`)}fs.existsSync(LOG_DIR)||fs.mkdirSync(LOG_DIR,{recursive:!0}),log(`MCP Server started - Log file: ${LOG_FILE}`),log("Environment variables:"),log(` KEYWORD: ${KEYWORD}`),log(` TOKEN (起動時スナップショット): ${describeTokenForDebug(resolveToken())}`),log(` PORTAL_URL: ${PORTAL_URL}`),log(` LANGUAGE: ${LANGUAGE}`);const LEGACY_REGISTRY=path.join(os.homedir(),".bluelamp","registry.json");if(fs.existsSync(LEGACY_REGISTRY))try{fs.unlinkSync(LEGACY_REGISTRY),log(`[startup] Legacy registry.json removed: ${LEGACY_REGISTRY}`)}catch(e){log(`[startup] Failed to remove legacy registry.json: ${e.message}`)}class ChildMcpProcess{constructor(e,t,r,o){this.serviceId=e,this.command=t,this.args=(r||[]).map(e=>"string"==typeof e?e.replace(/^~\//,os.homedir()+"/"):e),this.env={...process.env,...o},this.process=null,this.tools=[],this.requestId=0,this.pending=new Map,this.buffer="",this.stdoutDecoder=new StringDecoder("utf8"),this.stderrDecoder=new StringDecoder("utf8"),this.stderrTail="",this._decodersEnded=!1}async start(){return new Promise((e,t)=>{let r=!1;const o=(e,t)=>{r||(r=!0,clearTimeout(s),e(t))},s=setTimeout(()=>{o(t,new Error(`Timeout: "${this.serviceId}" failed to start within 90s`)),this.stop()},9e4);try{this.process=spawn(this.command,this.args,{env:this.env,stdio:["pipe","pipe","pipe"]}),this.process.on("error",e=>{o(t,new Error(`Spawn error for "${this.serviceId}": ${e.message}`))}),this.process.stdin.on("error",e=>{log(`[ChildMcp:${this.serviceId}:stdin] ${e.message}`)}),this.process.on("exit",(e,r)=>{log(`[ChildMcp] "${this.serviceId}" exited (code=${e}, signal=${r})`);const s=this.stderrTail.trim();o(t,new Error(`"${this.serviceId}" exited before ready (code=${e}, signal=${r})${s?` | stderr: ${s}`:""}`)),this.pending.forEach(e=>e.reject(new Error("Process exited"))),this.pending.clear()}),this.process.on("close",()=>{if(this._decodersEnded)return;this._decodersEnded=!0;const e=this.stdoutDecoder.end(),t=this.stderrDecoder.end();e&&(this.buffer+=e,log(`[ChildMcp] "${this.serviceId}" stdout に半端なバイトが ${Buffer.byteLength(e)} バイト残っていた(子が多バイト文字の途中で終了)⇒ buffer へ流した。⛔ これは「壊れた文字」であって「失われた文字」ではない`)),t&&log(`[ChildMcp] "${this.serviceId}" stderr に半端なバイトが ${Buffer.byteLength(t)} バイト残っていた ⇒ ${JSON.stringify(t)}`)}),this.process.stderr.on("data",e=>{const t=this.stderrDecoder.write(e);this.stderrTail=sliceTailPreservingSurrogates(this.stderrTail+t,500),log(`[ChildMcp:${this.serviceId}:stderr] ${t.trim()}`)}),this.process.stdout.on("data",e=>{this.buffer+=this.stdoutDecoder.write(e),this._processBuffer()}),this._sendRequest("initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"bluelamp-gateway",version:"1.0.0"}}).then(e=>(log(`[ChildMcp] "${this.serviceId}" initialized: ${JSON.stringify(e.serverInfo||{})}`),this._sendNotification("notifications/initialized",{}),this._sendRequest("tools/list",{}))).then(t=>{const r=t.tools||[];this.tools=r.map(e=>({...e,name:`${this.serviceId}__${e.name}`,_originalName:e.name})),log(`[ChildMcp] "${this.serviceId}" ready: ${this.tools.length} tools`),o(e,this.tools)}).catch(e=>{o(t,e)})}catch(e){o(t,e)}})}async callTool(e,t){return await this._sendRequest("tools/call",{name:e,arguments:t})}stop(){this.process&&(this.process.kill(),this.process=null),this.pending.forEach(e=>e.reject(new Error("Process stopped"))),this.pending.clear()}_sendRequest(e,t){return new Promise((r,o)=>{const s=++this.requestId,i=JSON.stringify({jsonrpc:"2.0",id:s,method:e,params:t})+"\n";this.pending.set(s,{resolve:r,reject:o});try{this.process.stdin.write(i)}catch(e){this.pending.delete(s),o(new Error(`Write error: ${e.message}`))}})}_sendNotification(e,t){const r=JSON.stringify({jsonrpc:"2.0",method:e,params:t})+"\n";try{this.process.stdin.write(r)}catch(e){log(`[ChildMcp] Notification write error: ${e.message}`)}}_processBuffer(){const e=this.buffer.split("\n");this.buffer=e.pop();for(const t of e){const e=t.trim();if(e)try{const t=JSON.parse(e);if(t.id&&this.pending.has(t.id)){const e=this.pending.get(t.id);this.pending.delete(t.id),t.error?e.reject(new Error(`JSON-RPC error: ${JSON.stringify(t.error)}`)):e.resolve(t.result)}}catch(t){log(`[ChildMcp:${this.serviceId}] Parse error: ${t.message} | line: ${e.substring(0,200)}`)}}}}class ChildMcpManager{constructor(){this.children=new Map,this.starting=new Map}async activateExternal(e,t){const r=new ChildMcpProcess(e,t.command,t.args||[],t.env||{}),o=await r.start();return this.children.set(e,{type:"external",process:r,tools:o,service:t}),o}beginActivateExternal(e,t){const r=this.children.get(e);if(r)return Promise.resolve({ok:!0,tools:r.tools||[]});const o=this.starting.get(e);if(o)return o;const s=this.activateExternal(e,t).then(e=>({ok:!0,tools:e}),e=>({ok:!1,error:e})).then(t=>(this.starting.delete(e),t));return this.starting.set(e,s),s}isStarting(e){return this.starting.has(e)}async waitForReady(e,t){if(this.children.has(e))return{ready:!0};const r=this.starting.get(e);if(!r)return{ready:!1,reason:"unknown"};let o=null;const s=new Promise(e=>{o=setTimeout(()=>e({timedOut:!0}),t),"function"==typeof o.unref&&o.unref()});try{const e=await Promise.race([r,s]);return e.timedOut?{ready:!1,reason:"timeout"}:e.ok?{ready:!0}:{ready:!1,reason:"failed",error:e.error}}finally{o&&clearTimeout(o)}}deactivate(e){const t=this.children.get(e);t&&("external"===t.type&&t.process&&t.process.stop(),this.children.delete(e))}isActive(e){return this.children.has(e)}getActiveTools(){const e=[];for(const t of this.children.values())e.push(...t.tools||[]);return e}async callTool(e,t){for(const[r,o]of this.children)if("external"===o.type){const r=o.tools.find(t=>t.name===e);if(r)return{found:!0,result:await o.process.callTool(r._originalName,t)}}return{found:!1}}getActiveServiceIds(){return[...this.children.keys()]}}class BizBoostServer{constructor(){this.childManager=new ChildMcpManager,this.updateNoticeText=null,this._catalogTools=new Map,this._cloudProxyTools=new Map,this._catalogServices=new Map,this._needChildForSchema=new Set,this._catalogFromCache=!1,this._configRefresh=null,this.server=new Server({name:"bluelamp",version:"2.0.0"},{capabilities:{tools:{listChanged:!0}}}),this.setupHandlers()}checkAuth(){return resolveToken()?{ok:!0}:{ok:!1,error:"BizBoost にログインしてください。ターミナルで `bizboost1` を一度実行すると ~/.musuhi/portal-token.enc が作成されます。"}}buildToolList(){return buildGatewayToolList([{name:"load_knowledge",description:t("mcp.toolDescriptionLoadKnowledge"),annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{keyword:{type:"string",description:t("mcp.keywordDescription")}},required:["keyword"]}},{name:"search_mcp",description:'キーワードでインストール済みMCPサービスを検索します。使いたい機能を自然言語で説明してください。(例: "ブラウザ操作", "メール送信", "画像生成")',inputSchema:{type:"object",properties:{query:{type:"string",description:"検索キーワード(自然言語OK)"}},required:["query"]}},{name:"activate_service",description:"deactivate_service で一覧から外した MCP を、道具一覧に戻します(deactivate を戻すだけ)。権限のある MCP は最初から一覧に出ているので、通常このツールを撃つ必要はありません。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"},always_on:{type:"boolean",description:"後方互換のため受け付けますが、一覧の可否には使いません(無視されます)"}},required:["service_id"]}},{name:"deactivate_service",description:"指定した MCP を道具一覧から外します(deactivated=true)。次の接続でも一覧に出なくなります。権限は変わらないので activate_service でいつでも戻せます。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"}},required:["service_id"]}},{name:"restart_service",description:"MCPサービスのプロセスを再起動します。コード更新や設定変更の反映に使用します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"}},required:["service_id"]}},{name:"unregister_service",description:"MCPサービスをレジストリから完全に削除します。プロセスも停止します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"削除するサービスID"}},required:["service_id"]}},{name:"register_service",description:"新しいMCPサービスをゲートウェイに登録します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:'サービスID(英数字、例: "microcms")'},name:{type:"string",description:"サービス表示名"},description:{type:"string",description:"サービスの説明"},tags:{type:"array",items:{type:"string"},description:"検索用タグ"},command:{type:"string",description:'実行コマンド("npx" or "node")'},args:{type:"array",items:{type:"string"},description:"コマンド引数"},env:{type:"object",description:"環境変数"}},required:["service_id","name","description","tags"]}},{name:"browse_mcp_store",description:"MCPストア(Portal)からインストール可能なMCP一覧を取得します。",inputSchema:{type:"object",properties:{},required:[]}},{name:"install_from_store",description:"MCP ストアから MCP を取得してこの機体に展開し、env と導入版をサーバに記録します。browse_mcp_store で見つけた mcp_id を指定してください。道具一覧に出るかどうかは権限で決まるので、権限の無い MCP をこれで一覧に出すことはできません(自分で作った MCP・共有された MCP は権限に含まれるため、何もしなくても一覧に出ます)。",inputSchema:{type:"object",properties:{mcp_id:{type:"string",description:"インストールするMCPのID"}},required:["mcp_id"]}},{name:"save_mcp_env",description:"MCPの環境変数(APIキー等)をサーバーに安全に保存します。ローカルには保存されません。次回起動時にサーバーから自動取得されます。解約時はアクセスできなくなります。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"MCP サービスID(例: heygen, gemini-image)"},env:{type:"object",description:'環境変数のキーと値(例: {"HEYGEN_API_KEY": "sk_xxx"})',additionalProperties:{type:"string"}}},required:["service_id","env"]}}],this._catalogTools,this.childManager.getActiveTools())}applyCatalog(e,t={}){const{catalog:r,cloudProxy:o,warnings:s,needChildForSchema:i}=buildCatalogRegistry(e);this._catalogTools=r,this._cloudProxyTools=o,this._catalogServices=new Map,this._needChildForSchema=new Set(i),this._catalogFromCache=!0===t.fromCache;for(const t of Array.isArray(e)?e:[])t&&t.mcpId&&this._catalogServices.set(t.mcpId,t);let n=0;for(const e of s)"no-input-schema"===e.reason?(n+=e.count,log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}): ${e.count}/${e.total} tools have no inputSchema — 一覧には出す(空 schema)。子を起こして実 schema で上書きする`)):log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}) skipped: ${e.reason}`);return n>0&&log(`[catalog] inputSchema 欠損の合計: ${n} 本 / ${this._needChildForSchema.size} service(一覧には出す。子を起こして実 schema で上書きする)`),log(`[catalog] ${r.size} tools registered from ${this._catalogServices.size} services (cloud_proxy: ${o.size})`),r}registerServiceInCatalog(e){const{catalog:t,cloudProxy:r,warnings:o}=buildCatalogRegistry([e]);for(const[e,r]of t)this._catalogTools.set(e,r);for(const[e,t]of r)this._cloudProxyTools.set(e,t);for(const e of o)log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}) skipped: ${e.reason}`);return e&&e.mcpId&&this._catalogServices.set(e.mcpId,e),t.size}unregisterServiceFromCatalog(e){const t=`${e}__`;let r=0;for(const e of[...this._catalogTools.keys()])e.startsWith(t)&&(this._catalogTools.delete(e),this._cloudProxyTools.delete(e),r++);return r}buildChildService(e,t){const r=path.join(os.homedir(),".claude","mcp-servers",e),o=t.entryPoint||"dist/index.js";return{name:t.name,description:t.description,type:"external",command:t.command||"node",args:t.args&&t.args.length?t.args:[path.join(r,o)],env:t.env||{}}}setupHandlers(){this.server.setRequestHandler(ListToolsRequestSchema,async()=>{const e=this.buildToolList(),t=this.childManager.getActiveServiceIds();return log(`[ListTools] ${e.length} tools (active: ${t.join(", ")||"none"})`),{tools:e}}),this.server.setRequestHandler(CallToolRequestSchema,async e=>{const{name:r,arguments:o}=e.params;log(`[CallTool] ${r}`);const s=resolveToken();if("load_knowledge"===r){const{keyword:e}=o;log(`[load_knowledge] keyword: ${e}`);try{const r=await getPromptFromPortal(e,s,LANGUAGE);if(!r||!r.success){const o=r?.error||t("mcp.knowledgeNotFound",{keyword:e});return{content:[{type:"text",text:`❌ ${t("mcp.portalApiFailed",{error:o})}`}],isError:!0}}const o="ja"!==LANGUAGE?"\n\n[Note] The user's preferred language is English.":"",i=this.updateNoticeText?`\n\n${this.updateNoticeText}`:"";return{content:[{type:"text",text:`✅ ${t("mcp.knowledgeLoadSuccess")}\n\n${r.knowledge}${o}\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n${t("mcp.knowledgeApplied")}${i}`}]}}catch(e){return log(`[load_knowledge] Exception: ${e.message}`),{content:[{type:"text",text:`❌ ${t("mcp.knowledgeLoadError",{error:e.message})}`}],isError:!0}}}if("search_mcp"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};if(!s)return{content:[{type:"text",text:"❌ 未認証です。MCPカタログの検索にはログインが必要です。"}],isError:!0};let t=[];try{const e=await searchMcpServices(o.query,s);if(!e.success)return{content:[{type:"text",text:`❌ MCPカタログ検索に失敗: ${e.error||"Unknown"}`}],isError:!0};t=(e.data||[]).map(e=>({id:e.mcp_id,service:{name:e.name,description:e.description,tags:[],alwaysOn:e.alwaysOn||!1},isInstalled:e.isInstalled||!1}))}catch(e){return log(`[search_mcp] Server search failed: ${e.message}`),{content:[{type:"text",text:`❌ MCPカタログ検索に失敗: ${e.message}`}],isError:!0}}if(0===t.length)return{content:[{type:"text",text:`🔍 「${o.query}」に一致するサービスはありません。\n\n別のキーワードで試すか、browse_mcp_storeでカタログを確認してください。`}]};let r=`🔍 「${o.query}」の検索結果(${t.length}件)\n\n`;for(const e of t.slice(0,10)){const t=e.id,o=e.service,s=this.childManager.isActive(t),i=!0===o.deactivated,n=e.isInstalled?"":" [未インストール]",a=i?" [一覧から外し中]":"";r+=`${i?"🚫":s?"🟢":"⚪"} **${o.name}**${a}${n} (id: \`${t}\`)\n`,r+=` ${o.description}\n\n`}return r+="一覧に戻す: activate_service | ストアから導入: install_from_store",{content:[{type:"text",text:r}]}}if("activate_service"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t}=o,r=await getGatewayConfig(s);if(!r.success)return{content:[{type:"text",text:`❌ サーバー設定の取得に失敗: ${r.error||"Unknown"}`}],isError:!0};const i=(r.data?.services||[]).find(e=>e.mcpId===t);if(!i)return{content:[{type:"text",text:`❌ サービス "${t}" はあなたの権限の中にありません(権限のある MCP は何もしなくても一覧に出ます)。`}],isError:!0};const n=await setServiceDeactivated(t,!1,s);if(!n.success)return{content:[{type:"text",text:`❌ "${t}" を一覧に戻せませんでした: ${n.error||"Unknown"}`}],isError:!0};log(`[activate] "${t}" deactivated=false (一覧に戻した)`);const a=this.registerServiceInCatalog({...i,deactivated:!1});if(0===a)return{content:[{type:"text",text:`❌ "${t}" には目録にツール定義がありません(tools が空)。`}],isError:!0};if("cloud_proxy"===i.hostingType){log(`[activate] "${t}" (cloud_proxy) → ${a} proxy tools registered`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${i.name}" を一覧に戻しました(cloud_proxy ツール${a}個)`}]}}if(this.childManager.isActive(t)){try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${t}" を一覧に戻しました(子プロセスは既に起動済み)。`}]}}log(`[activate] "${t}" (${i.hostingType}) → ${a} catalog tools restored. Sending list_changed.`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${i.name}" を一覧に戻しました(ツール${a}個)。最初に呼ばれた時に自動で起動します。`}]}}if("deactivate_service"===r){const{service_id:e}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};const t=await setServiceDeactivated(e,!0,s);if(!t.success)return{content:[{type:"text",text:`❌ "${e}" を一覧から外せませんでした: ${t.error||"Unknown"}`}],isError:!0};log(`[deactivate] "${e}" deactivated=true (一覧から外した)`);const r=this.unregisterServiceFromCatalog(e);r>0&&log(`[deactivate] "${e}" → ${r} catalog tools removed`),this._catalogServices.delete(e);let i=!1;if(this.childManager.isActive(e)&&(this.childManager.deactivate(e),log(`[deactivate] "${e}" child process stopped`),i=!0),r>0||i)try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[deactivate] notification error: ${e.message}`)}let n=`✅ "${e}" を道具一覧から外しました(deactivated=true)。`;return r>0&&(n+=` ツール${r}個を一覧から削除しました。`),i&&(n+=" 子プロセスを停止しました。"),n+=" 次の接続でも一覧に出ません。権限は変わっていないので activate_service で戻せます。",{content:[{type:"text",text:n}]}}if("restart_service"===r){const{service_id:e}=o,t=this.childManager.children.get(e),r=t?.service;if(!r)return isCloudProxyService(this._cloudProxyTools,e)?{content:[{type:"text",text:`ℹ️ "${e}" は cloud_proxy 方式のため、ローカルの再起動対象ではありません(子プロセスを持ちません)。\nサーバ側のツール更新は deploy で全利用者に反映されるので、再起動は不要です。\nツール一覧を取り直したいだけなら deactivate_service → activate_service を実行してください。`}]}:{content:[{type:"text",text:`❌ "${e}" の子プロセスは現在動いていません。道具を呼べば自動で起動します(restart は起動済みの子にだけ効きます)。`}],isError:!0};let i,n=r;if(s)try{const t=await getGatewayConfig(s);if(t.success){const o=(t.data?.services||[]).find(t=>t.mcpId===e);o&&o.env&&(n={...r,env:o.env},log(`[restart] "${e}" env refreshed from server (keys=${Object.keys(o.env).join(",")||"none"})`))}}catch(e){log(`[restart] env refresh failed (using cached): ${e.message}`)}this.childManager.deactivate(e),log(`[restart] "${e}" stopped`);try{i=await this.childManager.activateExternal(e,n)}catch(t){return log(`[restart] Failed "${e}": ${t.message}`),{content:[{type:"text",text:`❌ "${e}" の再起動に失敗しました: ${t.message}`}],isError:!0}}log(`[restart] "${e}" → ${i.length} tools. Sending list_changed.`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[restart] notification error: ${e.message}`)}const a=i.map(e=>e.name).join(", ");return{content:[{type:"text",text:`🔄 "${n.name}" を再起動しました(ツール${i.length}個)\n\nツール: ${a||"(なし)"}`}]}}if("unregister_service"===r){const{service_id:e}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};this.childManager.isActive(e)&&(this.childManager.deactivate(e),log(`[unregister] "${e}" stopped`));const t=await uninstallMcpService(e,s);if(!t.success)return{content:[{type:"text",text:`❌ "${e}" のサーバー削除に失敗: ${t.error||"Unknown"}`}],isError:!0};log(`[unregister] "${e}" uninstalled from server`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[unregister] notification error: ${e.message}`)}return{content:[{type:"text",text:`🗑️ "${e}" を削除しました。プロセスも停止済みです。`}]}}if("register_service"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t,env:r}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};const i=r||{},n=await installMcpService(t,!1,s,i);return n.success?(log(`[register] "${t}" installed on server`),{content:[{type:"text",text:`✅ サービス "${t}" をサーバーに登録しました。\n\n次のステップ:\n- save_mcp_env で APIキー等を設定\n- 次の接続で道具一覧に出ます(activate は不要です)`}]}):{content:[{type:"text",text:`❌ "${t}" の登録に失敗しました: ${n.error||"Unknown"}\n\n※ MCP はサーバーカタログに登録されている必要があります。browse_mcp_store で確認してください。`}],isError:!0}}if("save_mcp_env"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t,env:r}=o;if(!t||!r||0===Object.keys(r).length)return{content:[{type:"text",text:"❌ service_id と env(キー/値のペア)が必要です"}],isError:!0};log(`[save_mcp_env] ${t}: ${Object.keys(r).join(", ")}`);try{const e=await updateMcpEnv(t,r,s);if(!e.success)return{content:[{type:"text",text:`❌ サーバー保存失敗: ${e.error}`}],isError:!0};const o=Object.keys(r).join(", ");return e.warning?{content:[{type:"text",text:`🔐 環境変数をサーバーに保存しました\n\nサービス: ${t}\n保存キー: ${o}\n\n${e.warning}`}]}:{content:[{type:"text",text:`🔐 環境変数をサーバーに保存しました\n\nサービス: ${t}\n保存キー: ${o}\n\n※ ローカルには保存されません。次回起動時にサーバーから自動取得されます。`}]}}catch(e){return log(`[save_mcp_env] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if("browse_mcp_store"===r){log("[browse_mcp_store]");try{const e=await listAvailableMcps({},s,LANGUAGE);if(!e||!e.success)return{content:[{type:"text",text:`❌ MCPカタログの取得に失敗: ${e?.error||"Unknown"}`}],isError:!0};const t=e.data||[];if(0===t.length)return{content:[{type:"text",text:"📦 インストール可能なMCPはありません。"}]};let r=`📦 MCPストア一覧 (${t.length}件)\n\n`;return t.forEach(e=>{const t=e.isOfficial?" [公式]":"";r+=`**${e.name}**${t}\n`,r+=` ID: ${e.mcpId}\n`,r+=` ${e.description}\n`,r+=` ツール数: ${e.toolCount}\n\n`}),r+='\nインストールするには: install_from_store(mcp_id: "MCP_ID")',{content:[{type:"text",text:r}]}}catch(e){return log(`[browse_mcp_store] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if("install_from_store"===r){const{mcp_id:e}=o;log(`[install_from_store] mcp_id=${e}`);try{const t=await downloadMcpPackage(e,s);if(!t||!t.success)return{content:[{type:"text",text:`❌ MCPダウンロードに失敗: ${t?.error||"Unknown"}`}],isError:!0};const r=t.data,o=r.packageSource||{},i=r.files||[];let n=o.hostingType||o.hosting&&o.hosting.type||null;if(s){let t=!1;try{const r=await getGatewayConfig(s);if(r.success){const o=(r.data?.services||[]).find(t=>t.mcpId===e);o&&(t=!0===o.alwaysOn,n||(n=o.hostingType))}}catch(e){}const r=await installMcpService(e,t,s);if(!r.success)return{content:[{type:"text",text:`❌ サーバー登録失敗: ${r.error||"Unknown"}`}],isError:!0};log(`[install_from_store] Server sync OK: ${e} (alwaysOn=${t})`)}if("cloud_proxy"===n){log(`[install_from_store] "${e}" is cloud_proxy, skipping local extract`);let t=`✅ MCP「${o.name||e}」をインストールしました(cloud_proxy)\n\n`;return t+="☁ クラウド実行のためローカル展開は不要です\n",o.installNotes&&(t+=`\n📝 ${o.installNotes}\n`),t+="\n権限に含まれていれば、次の接続で道具一覧に出ます(activate_service を撃つ必要はありません)。",{content:[{type:"text",text:t}]}}if(0===i.length)return{content:[{type:"text",text:"❌ MCPパッケージにファイルが含まれていません。"}],isError:!0};const a=path.join(os.homedir(),".claude","mcp-servers",e),c=installPackageFiles({installDir:a,files:i,needsNpmInstall:!!o.needsNpmInstall,runNpmInstall:e=>{const{execSync:t}=require("child_process");t("npm install --production",{cwd:e,timeout:6e4,stdio:"pipe"})}});if(!c.ok)return log(`[install_from_store] ${e} failed at ${c.stage}: ${c.error.message}`),{content:[{type:"text",text:formatInstallFailure(o.name||e,c)}],isError:!0};log(`[install_from_store] ${i.length} files written to ${a}`);let l=`✅ MCP「${o.name||e}」をインストールしました\n\n`;l+=`📁 インストール先: ${a}\n`,l+=`📄 ファイル数: ${i.length}\n`,o.installNotes&&(l+=`\n📝 ${o.installNotes}\n`);const d=(o.requiredEnvVars||[]).filter(e=>!process.env[e]);return d.length>0&&(l+="\n⚠️ 以下の環境変数を save_mcp_env で設定してください:\n",d.forEach(e=>{l+=` - ${e}\n`})),l+="\n権限に含まれていれば、次の接続で道具一覧に出ます(activate_service を撃つ必要はありません)。",{content:[{type:"text",text:l}]}}catch(e){return log(`[install_from_store] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if(this._cloudProxyTools&&this._cloudProxyTools.has(r)){const e=this._cloudProxyTools.get(r);log(`[callTool] Cloud proxy: ${r} → ${e.mcpId}/${e.toolName}`);try{const t=await callMcpToolProxy(e.mcpId,e.toolName,o,s);return t.success&&t.data?t.data.content?t.data:{content:[{type:"text",text:JSON.stringify(t.data,null,2)}]}:{content:[{type:"text",text:`❌ プロキシエラー: ${t.error||"Unknown"}`}],isError:!0}}catch(e){return log(`[callTool] Cloud proxy error "${r}": ${e.message}`),{content:[{type:"text",text:`❌ クラウドプロキシエラー: ${e.message}`}],isError:!0}}}try{const{found:e,result:t}=await this.childManager.callTool(r,o);if(e)return t&&t.content?t:{content:[{type:"text",text:String(t)}]}}catch(e){return log(`[callTool] Error proxying "${r}": ${e.message}`),{content:[{type:"text",text:`❌ ツール実行エラー: ${e.message}`}],isError:!0}}const i=this._catalogTools.get(r);if(i&&"cloud_proxy"!==i.hostingType){const e=i.mcpId;this._catalogFromCache&&this._configRefresh&&(log(`[callTool] "${e}" は目録キャッシュ由来。起動仕様の到着を待つ。`),await this._configRefresh),this.startChildOnDemand(e);const t=await this.childManager.waitForReady(e,3e4);if(!t.ready){if("failed"===t.reason){const r=t.error?.message||String(t.error||"Unknown");return log(`[callTool] "${e}" failed to start: ${r}`),{content:[{type:"text",text:`❌ "${e}" の起動に失敗しました: ${r}`}],isError:!0}}return"timeout"===t.reason?(log(`[callTool] "${e}" not ready within 30000ms for "${r}".`),{content:[{type:"text",text:CHILD_NOT_READY_TEXT}],isError:!0}):(log(`[callTool] "${e}" could not be started for "${r}" (reason=${t.reason}).`),{content:[{type:"text",text:`❌ "${e}" を起動できませんでした(設定が見つかりません)。`}],isError:!0})}try{const{found:t,result:s}=await this.childManager.callTool(r,o);if(t)return s&&s.content?s:{content:[{type:"text",text:String(s)}]};log(`[callTool] "${r}" is in catalog but child "${e}" does not have it.`)}catch(e){return log(`[callTool] Error proxying "${r}" after ready: ${e.message}`),{content:[{type:"text",text:`❌ ツール実行エラー: ${e.message}`}],isError:!0}}}return{content:[{type:"text",text:`❌ Unknown tool: ${r}`}],isError:!0}})}startChildrenForMissingSchema(){let e=0;for(const t of this._needChildForSchema){const r=this._catalogServices.get(t);if(r)if("cloud_proxy"!==r.hostingType){if(!this.childManager.isActive(t)&&!this.childManager.isStarting(t)){log(`[schemaChild] "${t}" (${r.hostingType}) を起こして実 schema を取りに行く`);try{this.startChildOnDemand(t),e++}catch(e){log(`[schemaChild] "${t}" の起動に失敗: ${e.message}(⛔ 席は落とさない)`)}}}else log(`[schemaChild] "${t}" は cloud_proxy のため子を起こせない。schema 欠損の道具は一覧に出ない。`)}return log(`[schemaChild] ${e} service(=目録に schema が無い道具を持つ service の数)`),e}async loadCatalog(e){if(!e)return log("[catalog] No token, starting with no catalog tools."),[];let t=[];try{const r=await getGatewayConfig(e);if(!r.success)return log(`[catalog] Server config failed: ${r.error||"Unknown"}. Starting with no services.`),[];t=r.data?.services||[],log(`[catalog] Server config: ${t.length} services`),this.applyCatalog(t),writeCatalogCache(CATALOG_CACHE_FILE,t,catalogCacheFingerprint(e),log)}catch(e){return log(`[catalog] Server config error: ${e.message}. Starting with no services.`),[]}try{const e=collectUpdateNotices(t);this.updateNoticeText=buildUpdateNoticeText(e);for(const t of e)"not-applicable"!==t.status&&log(`[versionCheck] ${t.mcpId}: ${t.status} (${t.reason}) catalog=${t.catalogVersion} local=${t.localVersion}`)}catch(e){log(`[versionCheck] skipped: ${e.message}`)}return t}startChildOnDemand(e){const t=this._catalogServices.get(e);if(!t||!0===t.deactivated)return null;if("cloud_proxy"===t.hostingType)return null;if(this.childManager.isActive(e))return null;const r=this.childManager.isStarting(e),o=this.childManager.beginActivateExternal(e,this.buildChildService(e,t));return r||log(`[startChild] "${e}" (${t.hostingType}) starting on demand...`),o.then(t=>this.reconcileChildWithCatalog(e,t)).catch(t=>log(`[startChild] "${e}" post-start error: ${t.message}`)),o}async reconcileChildWithCatalog(e,t){const r=decideCatalogReconciliation(this._catalogTools,e,t);if(!r.ready){const o=t&&t.error?`: ${t.error.message||t.error}`:"";return log(`[versionDrift] "${e}" not ready (${r.reason})${o} → 剪定も通知もしない`),r}if(!r.notify)return log(`[versionDrift] "${e}" matches catalog (${t.tools.length} tools) → no list_changed`),r;for(const e of r.prune)this._catalogTools.delete(e),this._cloudProxyTools.delete(e);const o=r.diff;log(`[versionDrift] "${e}" differs from catalog: +${o.added.length} -${o.removed.length} ~${o.changed.length} → list_changed`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[versionDrift] notification error: ${e.message}`)}return r}toolListSignature(){return stableJson(this.buildToolList().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema})))}async refreshCatalogInBackground(e){const t=this.toolListSignature();try{await this.loadCatalog(e)}catch(e){return log(`[catalogRefresh] failed, keeping cached catalog: ${e.message}`),{notified:!1,reason:"failed"}}if(t===this.toolListSignature())return log("[catalogRefresh] server catalog matches cache → no list_changed"),{notified:!1,reason:"same"};log("[catalogRefresh] server catalog differs from cache → list_changed");try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[catalogRefresh] notification error: ${e.message}`)}return{notified:!0,reason:"diff"}}async run(){const e=resolveToken(),t=catalogCacheFingerprint(e),r=readCatalogCache(CATALOG_CACHE_FILE,t,log);r?(this.applyCatalog(r,{fromCache:!0}),log(`[catalogCache] ${this._catalogTools.size} tools from cache (HTTP は待たない)`)):(log("[catalogCache] no usable cache, waiting for server config"),await this.loadCatalog(e));const o=new StdioServerTransport;await this.server.connect(o),log(`[Gateway] BizBoost Gateway v2.0.0 started. (${this._catalogTools.size} catalog tools available at connect)`),r?(this._configRefresh=this.refreshCatalogInBackground(e).catch(e=>(log(`[catalogRefresh] unexpected: ${e.message}`),{notified:!1,reason:"failed"})),this._configRefresh.then(()=>this.startChildrenForMissingSchema()).catch(e=>log(`[schemaChild] deferred start failed: ${e.message}`))):this.startChildrenForMissingSchema();const s=resolveToken();if(KEYWORD&&s){log(`[Gateway] Auto-loading knowledge for keyword: ${KEYWORD}`);const e=await getPromptFromPortal(KEYWORD,s,LANGUAGE);e&&e.success?log(`[Gateway] Auto-load successful: ${e.title}`):log(`[Gateway] Auto-load failed for keyword: ${KEYWORD}`)}}}function buildCatalogRegistry(e){const t=new Map,r=new Map,o=[],s=[];for(const i of Array.isArray(e)?e:[]){if(!i||"string"!=typeof i.mcpId||!i.mcpId)continue;const e=i.hostingType||null;if(!0===i.deactivated)continue;const n=Array.isArray(i.tools)?i.tools:[];if(0===n.length){o.push({mcpId:i.mcpId,hostingType:e,reason:"no-tools"});continue}const a=[];for(const s of n){if(!s||"string"!=typeof s.name||!s.name){o.push({mcpId:i.mcpId,hostingType:e,reason:"unnamed-tool"});continue}s.inputSchema&&"object"==typeof s.inputSchema||a.push(s.name);const n=`${i.mcpId}__${s.name}`,c={name:n,mcpId:i.mcpId,toolName:s.name,hostingType:e,description:s.description,inputSchema:s.inputSchema};t.set(n,c),"cloud_proxy"===e&&r.set(n,{mcpId:i.mcpId,toolName:s.name,description:s.description,inputSchema:s.inputSchema})}a.length>0&&(o.push({mcpId:i.mcpId,hostingType:e,reason:"no-input-schema",count:a.length,total:n.length,tools:a}),s.push(i.mcpId))}return{catalog:t,cloudProxy:r,warnings:o,needChildForSchema:s}}function catalogEntryToTool(e){return{name:e.name,description:e.description||`[${e.mcpId}] ${e.toolName}`,inputSchema:e.inputSchema||{type:"object",properties:{}}}}function buildGatewayToolList(e,t,r){const o=new Map;for(const t of Array.isArray(e)?e:[])t&&t.name&&o.set(t.name,t);if(t&&"function"==typeof t.values)for(const e of t.values())o.has(e.name)||o.set(e.name,catalogEntryToTool(e));for(const e of Array.isArray(r)?r:[])e&&e.name&&o.set(e.name,e);return[...o.values()]}function sanitizeServicesForCache(e){return(Array.isArray(e)?e:[]).filter(e=>e&&"string"==typeof e.mcpId&&e.mcpId).map(e=>({mcpId:e.mcpId,name:e.name,description:e.description,hostingType:e.hostingType||null,deactivated:!0===e.deactivated,tools:(Array.isArray(e.tools)?e.tools:[]).filter(e=>e&&"string"==typeof e.name&&e.name).map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}))}))}function catalogCacheFingerprint(e){return e?require("crypto").createHash("sha256").update(String(e)).digest("hex").slice(0,16):null}function sliceTailPreservingSurrogates(e,t){const r=String(null==e?"":e);if(r.length<=t)return r;const o=r.slice(-t),s=o.charCodeAt(0);return s>=56320&&s<=57343?o.slice(1):o}function stableJson(e){return void 0===e?"null":null===e||"object"!=typeof e?JSON.stringify(e):Array.isArray(e)?`[${e.map(stableJson).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${stableJson(e[t])}`).join(",")}}`}function diffChildToolsAgainstCatalog(e,t,r){const o=`${t}__`,s=new Set;if(e&&"function"==typeof e.keys)for(const t of e.keys())"string"==typeof t&&t.startsWith(o)&&s.add(t);const i=[],n=[],a=new Set;for(const t of Array.isArray(r)?r:[]){if(!t||!t.name)continue;a.add(t.name);const r=e&&"function"==typeof e.get?e.get(t.name):void 0;r?stableJson(r.description)===stableJson(t.description)&&stableJson(r.inputSchema)===stableJson(t.inputSchema)||n.push(t.name):i.push(t.name)}const c=[...s].filter(e=>!a.has(e));return{added:i,removed:c,changed:n,hasDiff:i.length+c.length+n.length>0}}function decideCatalogReconciliation(e,t,r){if(!r||!0!==r.ok||!Array.isArray(r.tools))return{ready:!1,prune:[],notify:!1,reason:r&&r.reason||"not-ready",diff:null};const o=diffChildToolsAgainstCatalog(e,t,r.tools);return{ready:!0,prune:o.removed,notify:o.hasDiff,reason:"ready",diff:o}}function readCatalogCache(e,t,r){const o=r||(()=>{});if(!t)return null;let s,i;try{s=fs.readFileSync(e,"utf8")}catch(e){return"ENOENT"!==e.code&&o(`[catalogCache] read failed: ${e.message}`),null}try{i=JSON.parse(s)}catch(e){return o(`[catalogCache] broken JSON, ignoring: ${e.message}`),null}return i&&1===i.version?i.tokenFingerprint!==t?(o("[catalogCache] fingerprint mismatch (口座が違う), ignoring"),null):Array.isArray(i.services)?i.services:(o("[catalogCache] services が配列でない, ignoring"),null):(o(`[catalogCache] version mismatch (${i&&i.version}), ignoring`),null)}function writeCatalogCache(e,t,r,o){const s=o||(()=>{});if(!r)return!1;try{fs.mkdirSync(path.dirname(e),{recursive:!0});const o={version:1,tokenFingerprint:r,savedAt:(new Date).toISOString(),services:sanitizeServicesForCache(t)},s=`${e}.${process.pid}.tmp`;return fs.writeFileSync(s,JSON.stringify(o),{mode:384}),fs.renameSync(s,e),!0}catch(e){return s(`[catalogCache] write failed: ${e.message}`),!1}}function isCloudProxyService(e,t){if(!e||"function"!=typeof e.keys)return!1;const r=`${t}__`;for(const t of e.keys())if("string"==typeof t&&t.startsWith(r))return!0;return!1}if(module.exports={ChildMcpProcess:ChildMcpProcess,ChildMcpManager:ChildMcpManager,BizBoostServer:BizBoostServer,isCloudProxyService:isCloudProxyService,buildCatalogRegistry:buildCatalogRegistry,buildGatewayToolList:buildGatewayToolList,catalogEntryToTool:catalogEntryToTool,diffChildToolsAgainstCatalog:diffChildToolsAgainstCatalog,decideCatalogReconciliation:decideCatalogReconciliation,sanitizeServicesForCache:sanitizeServicesForCache,catalogCacheFingerprint:catalogCacheFingerprint,readCatalogCache:readCatalogCache,writeCatalogCache:writeCatalogCache,CATALOG_CACHE_FILE:CATALOG_CACHE_FILE,CATALOG_CACHE_VERSION:1,stableJson:stableJson,sliceTailPreservingSurrogates:sliceTailPreservingSurrogates,CHILD_READY_TIMEOUT_MS:3e4,CHILD_NOT_READY_TEXT:CHILD_NOT_READY_TEXT},require.main===module){const e=new BizBoostServer;let t=!1;const r=r=>{if(!t){t=!0;try{log(`[Gateway] Shutdown (${r}) - cleaning up children...`)}catch(e){}if(e&&e.childManager&&e.childManager.children)for(const[t,r]of e.childManager.children)try{try{log(`[Gateway] Stopping child: ${t}`)}catch(e){}r&&"external"===r.type&&r.process&&"function"==typeof r.process.stop&&r.process.stop()}catch(e){}setTimeout(()=>process.exit(0),200).unref()}};process.on("SIGTERM",()=>r("SIGTERM")),process.on("SIGINT",()=>r("SIGINT")),process.on("SIGHUP",()=>r("SIGHUP")),process.stdin.on("end",()=>r("stdin-end")),process.stdin.on("close",()=>r("stdin-close")),process.on("exit",()=>{if(e&&e.childManager&&e.childManager.children)for(const[t,r]of e.childManager.children)try{r&&r.process&&r.process.process&&"function"==typeof r.process.process.kill&&r.process.process.kill("SIGKILL")}catch(e){}}),e.run().catch(e=>{log(`[Gateway] Fatal: ${e.message}`),process.exit(1)})}
|
|
2
|
+
const{Server:Server}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:StdioServerTransport}=require("@modelcontextprotocol/sdk/server/stdio.js"),{CallToolRequestSchema:CallToolRequestSchema,ListToolsRequestSchema:ListToolsRequestSchema}=require("@modelcontextprotocol/sdk/types.js"),{getPromptFromPortal:getPromptFromPortal,listAvailableMcps:listAvailableMcps,downloadMcpPackage:downloadMcpPackage,getGatewayConfig:getGatewayConfig,searchMcpServices:searchMcpServices,installMcpService:installMcpService,setServiceDeactivated:setServiceDeactivated,uninstallMcpService:uninstallMcpService,updateMcpEnv:updateMcpEnv,callMcpToolProxy:callMcpToolProxy}=require("./portal-api-client.cjs"),{requireFromPackage:requireFromPackage}=require("../requireFromPackage.cjs"),{logger:logger}=requireFromPackage(require,"../../utils/logger"),{t:t,setLanguage:setLanguage}=requireFromPackage(require,"../../i18n");requireFromPackage(require,"../../lib/connectResilience").applyConnectResilience(require("node:net"));{const{SYS_PROMPT_ENV:e,isOwnSysPromptPath:t}=requireFromPackage(require,"../../lib/sysPromptHandoff"),r=process.env[e];if(t(r,require("node:os").tmpdir()))try{require("node:fs").unlinkSync(r)}catch{}}const{describeTokenForDebug:describeTokenForDebug}=requireFromPackage(require,"../../lib/debugRedaction"),{collectUpdateNotices:collectUpdateNotices,buildUpdateNoticeText:buildUpdateNoticeText}=require("./mcp-version-advisor.cjs"),{installPackageFiles:installPackageFiles,formatInstallFailure:formatInstallFailure,runProductionNpmInstall:runProductionNpmInstall}=require("./install-package.cjs"),spawn=require("cross-spawn"),{StringDecoder:StringDecoder}=require("string_decoder"),path=require("path"),fs=require("fs"),os=require("os"),dotenvLocalPath=path.join(__dirname,"../../.env.local"),dotenvPath=path.join(__dirname,"../../.env");fs.existsSync(dotenvLocalPath)?(require("dotenv").config({path:dotenvLocalPath}),logger.debug("[MCP Server] Loaded .env.local")):fs.existsSync(dotenvPath)&&(require("dotenv").config({path:dotenvPath}),logger.debug("[MCP Server] Loaded .env"));const KEYWORD=process.env.MUSUHI_KEYWORD||"BL-要件定義",{TokenManager:TokenManager}=requireFromPackage(require,"../../auth/TokenManager");function resolveToken(){return TokenManager.loadTokenStringSync()}const PORTAL_URL_ENV=process.env.BLUELAMP_PORTAL_API_BASE_URL||process.env.PORTAL_URL||"",isDevEnv=PORTAL_URL_ENV.includes("localhost"),PORTAL_URL=PORTAL_URL_ENV||(isDevEnv?"http://localhost:8430/api/bluelamp":"https://api.motohi.jp/api/bluelamp"),LANGUAGE=process.env.MUSUHI_LANGUAGE||"ja",CATALOG_CACHE_FILE=path.join(os.homedir(),".bluelamp-vscode","gateway-catalog.json"),CATALOG_CACHE_VERSION=1,CHILD_READY_TIMEOUT_MS=3e4,CHILD_NOT_READY_TEXT="起動中です。数秒後に再試行してください";setLanguage(LANGUAGE);const LOG_DIR=path.join(os.homedir(),".bluelamp-vscode","logs"),LOG_FILE=path.join(LOG_DIR,"mcp.log");function log(e){const t=`[${(new Date).toISOString()}] ${e}\n`;fs.appendFileSync(LOG_FILE,t),logger.info(`[MCP Server] ${e}`)}fs.existsSync(LOG_DIR)||fs.mkdirSync(LOG_DIR,{recursive:!0}),log(`MCP Server started - Log file: ${LOG_FILE}`),log("Environment variables:"),log(` KEYWORD: ${KEYWORD}`),log(` TOKEN (起動時スナップショット): ${describeTokenForDebug(resolveToken())}`),log(` PORTAL_URL: ${PORTAL_URL}`),log(` LANGUAGE: ${LANGUAGE}`);const LEGACY_REGISTRY=path.join(os.homedir(),".bluelamp","registry.json");if(fs.existsSync(LEGACY_REGISTRY))try{fs.unlinkSync(LEGACY_REGISTRY),log(`[startup] Legacy registry.json removed: ${LEGACY_REGISTRY}`)}catch(e){log(`[startup] Failed to remove legacy registry.json: ${e.message}`)}class ChildMcpProcess{constructor(e,t,r,o){this.serviceId=e,this.command=t,this.args=(r||[]).map(e=>"string"==typeof e?e.replace(/^~\//,os.homedir()+"/"):e),this.env={...process.env,...o},this.process=null,this.tools=[],this.requestId=0,this.pending=new Map,this.buffer="",this.stdoutDecoder=new StringDecoder("utf8"),this.stderrDecoder=new StringDecoder("utf8"),this.stderrTail="",this._decodersEnded=!1}async start(){return new Promise((e,t)=>{let r=!1;const o=(e,t)=>{r||(r=!0,clearTimeout(s),e(t))},s=setTimeout(()=>{o(t,new Error(`Timeout: "${this.serviceId}" failed to start within 90s`)),this.stop()},9e4);try{this.process=spawn(this.command,this.args,{env:this.env,stdio:["pipe","pipe","pipe"]}),this.process.on("error",e=>{o(t,new Error(`Spawn error for "${this.serviceId}": ${e.message}`))}),this.process.stdin.on("error",e=>{log(`[ChildMcp:${this.serviceId}:stdin] ${e.message}`)}),this.process.on("close",()=>{this._flushDecoders("close")}),this.process.on("exit",(e,r)=>{log(`[ChildMcp] "${this.serviceId}" exited (code=${e}, signal=${r})`);const s=this.stderrTail.trim();o(t,new Error(`"${this.serviceId}" exited before ready (code=${e}, signal=${r})${s?` | stderr: ${s}`:""}`)),this.pending.forEach(e=>e.reject(new Error("Process exited"))),this.pending.clear()}),this.process.on("close",()=>{if(this._decodersEnded)return;this._decodersEnded=!0;const e=this.stdoutDecoder.end(),t=this.stderrDecoder.end();e&&(this.buffer+=e,log(`[ChildMcp] "${this.serviceId}" stdout に半端なバイトが ${Buffer.byteLength(e)} バイト残っていた(子が多バイト文字の途中で終了)⇒ buffer へ流した。⛔ これは「壊れた文字」であって「失われた文字」ではない`)),t&&log(`[ChildMcp] "${this.serviceId}" stderr に半端なバイトが ${Buffer.byteLength(t)} バイト残っていた ⇒ ${JSON.stringify(t)}`)}),this.process.stderr.on("data",e=>{const t=this.stderrDecoder.write(e);this.stderrTail=sliceTailPreservingSurrogates(this.stderrTail+t,500),log(`[ChildMcp:${this.serviceId}:stderr] ${t.trim()}`)}),this.process.stdout.on("data",e=>{this.buffer+=this.stdoutDecoder.write(e),this._processBuffer()}),this._sendRequest("initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"bluelamp-gateway",version:"1.0.0"}}).then(e=>(log(`[ChildMcp] "${this.serviceId}" initialized: ${JSON.stringify(e.serverInfo||{})}`),this._sendNotification("notifications/initialized",{}),this._sendRequest("tools/list",{}))).then(t=>{const r=t.tools||[];this.tools=r.map(e=>({...e,name:`${this.serviceId}__${e.name}`,_originalName:e.name})),log(`[ChildMcp] "${this.serviceId}" ready: ${this.tools.length} tools`),o(e,this.tools)}).catch(e=>{o(t,e)})}catch(e){o(t,e)}})}async callTool(e,t){return await this._sendRequest("tools/call",{name:e,arguments:t})}_flushDecoders(e){for(const[t,r]of[["stdout",this.stdoutDecoder],["stderr",this.stderrDecoder]]){let o="";try{o=r.end()}catch(e){log(`[ChildMcp:${this.serviceId}:${t}] decoder.end() が落ちた: ${e.message}`);continue}o&&log(`[ChildMcp:${this.serviceId}:${t}] 🚨 未完の多バイト列を ${e} 時に検出: ${JSON.stringify(o)}(${o.length} 文字・⛔ 黙って捨てていない)`)}}stop(){this.process&&(this.process.kill(),this.process=null),this.pending.forEach(e=>e.reject(new Error("Process stopped"))),this.pending.clear()}_sendRequest(e,t){return new Promise((r,o)=>{const s=++this.requestId,i=JSON.stringify({jsonrpc:"2.0",id:s,method:e,params:t})+"\n";this.pending.set(s,{resolve:r,reject:o});try{this.process.stdin.write(i)}catch(e){this.pending.delete(s),o(new Error(`Write error: ${e.message}`))}})}_sendNotification(e,t){const r=JSON.stringify({jsonrpc:"2.0",method:e,params:t})+"\n";try{this.process.stdin.write(r)}catch(e){log(`[ChildMcp] Notification write error: ${e.message}`)}}_processBuffer(){const e=this.buffer.split("\n");this.buffer=e.pop();for(const t of e){const e=t.trim();if(e)try{const t=JSON.parse(e);if(t.id&&this.pending.has(t.id)){const e=this.pending.get(t.id);this.pending.delete(t.id),t.error?e.reject(new Error(`JSON-RPC error: ${JSON.stringify(t.error)}`)):e.resolve(t.result)}}catch(t){log(`[ChildMcp:${this.serviceId}] Parse error: ${t.message} | line: ${e.substring(0,200)}`)}}}}class ChildMcpManager{constructor(){this.children=new Map,this.starting=new Map}async activateExternal(e,t){const r=new ChildMcpProcess(e,t.command,t.args||[],t.env||{}),o=await r.start();return this.children.set(e,{type:"external",process:r,tools:o,service:t}),o}beginActivateExternal(e,t){const r=this.children.get(e);if(r)return Promise.resolve({ok:!0,tools:r.tools||[]});const o=this.starting.get(e);if(o)return o;const s=this.activateExternal(e,t).then(e=>({ok:!0,tools:e}),e=>({ok:!1,error:e})).then(t=>(this.starting.delete(e),t));return this.starting.set(e,s),s}isStarting(e){return this.starting.has(e)}async waitForReady(e,t){if(this.children.has(e))return{ready:!0};const r=this.starting.get(e);if(!r)return{ready:!1,reason:"unknown"};let o=null;const s=new Promise(e=>{o=setTimeout(()=>e({timedOut:!0}),t),"function"==typeof o.unref&&o.unref()});try{const e=await Promise.race([r,s]);return e.timedOut?{ready:!1,reason:"timeout"}:e.ok?{ready:!0}:{ready:!1,reason:"failed",error:e.error}}finally{o&&clearTimeout(o)}}deactivate(e){const t=this.children.get(e);t&&("external"===t.type&&t.process&&t.process.stop(),this.children.delete(e))}isActive(e){return this.children.has(e)}getActiveTools(){const e=[];for(const t of this.children.values())e.push(...t.tools||[]);return e}async callTool(e,t){for(const[r,o]of this.children)if("external"===o.type){const r=o.tools.find(t=>t.name===e);if(r)return{found:!0,result:await o.process.callTool(r._originalName,t)}}return{found:!1}}getActiveServiceIds(){return[...this.children.keys()]}}class BizBoostServer{constructor(){this.childManager=new ChildMcpManager,this.updateNoticeText=null,this._catalogTools=new Map,this._cloudProxyTools=new Map,this._catalogServices=new Map,this._needChildForSchema=new Set,this._catalogFromCache=!1,this._configRefresh=null,this.server=new Server({name:"bluelamp",version:"2.0.0"},{capabilities:{tools:{listChanged:!0}}}),this.setupHandlers()}checkAuth(){return resolveToken()?{ok:!0}:{ok:!1,error:"BizBoost にログインしてください。ターミナルで `bizboost1` を一度実行すると ~/.musuhi/portal-token.enc が作成されます。"}}buildToolList(){return buildGatewayToolList([{name:"load_knowledge",description:t("mcp.toolDescriptionLoadKnowledge"),annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{keyword:{type:"string",description:t("mcp.keywordDescription")}},required:["keyword"]}},{name:"search_mcp",description:'キーワードでインストール済みMCPサービスを検索します。使いたい機能を自然言語で説明してください。(例: "ブラウザ操作", "メール送信", "画像生成")',inputSchema:{type:"object",properties:{query:{type:"string",description:"検索キーワード(自然言語OK)"}},required:["query"]}},{name:"activate_service",description:"deactivate_service で一覧から外した MCP を、道具一覧に戻します(deactivate を戻すだけ)。権限のある MCP は最初から一覧に出ているので、通常このツールを撃つ必要はありません。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"},always_on:{type:"boolean",description:"後方互換のため受け付けますが、一覧の可否には使いません(無視されます)"}},required:["service_id"]}},{name:"deactivate_service",description:"指定した MCP を道具一覧から外します(deactivated=true)。次の接続でも一覧に出なくなります。権限は変わらないので activate_service でいつでも戻せます。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"}},required:["service_id"]}},{name:"restart_service",description:"MCPサービスのプロセスを再起動します。コード更新や設定変更の反映に使用します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"サービスID"}},required:["service_id"]}},{name:"unregister_service",description:"MCPサービスをレジストリから完全に削除します。プロセスも停止します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"削除するサービスID"}},required:["service_id"]}},{name:"register_service",description:"新しいMCPサービスをゲートウェイに登録します。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:'サービスID(英数字、例: "microcms")'},name:{type:"string",description:"サービス表示名"},description:{type:"string",description:"サービスの説明"},tags:{type:"array",items:{type:"string"},description:"検索用タグ"},command:{type:"string",description:'実行コマンド("npx" or "node")'},args:{type:"array",items:{type:"string"},description:"コマンド引数"},env:{type:"object",description:"環境変数"}},required:["service_id","name","description","tags"]}},{name:"browse_mcp_store",description:"MCPストア(Portal)からインストール可能なMCP一覧を取得します。",inputSchema:{type:"object",properties:{},required:[]}},{name:"install_from_store",description:"MCP ストアから MCP を取得してこの機体に展開し、env と導入版をサーバに記録します。browse_mcp_store で見つけた mcp_id を指定してください。道具一覧に出るかどうかは権限で決まるので、権限の無い MCP をこれで一覧に出すことはできません(自分で作った MCP・共有された MCP は権限に含まれるため、何もしなくても一覧に出ます)。",inputSchema:{type:"object",properties:{mcp_id:{type:"string",description:"インストールするMCPのID"}},required:["mcp_id"]}},{name:"save_mcp_env",description:"MCPの環境変数(APIキー等)をサーバーに安全に保存します。ローカルには保存されません。次回起動時にサーバーから自動取得されます。解約時はアクセスできなくなります。",inputSchema:{type:"object",properties:{service_id:{type:"string",description:"MCP サービスID(例: heygen, gemini-image)"},env:{type:"object",description:'環境変数のキーと値(例: {"HEYGEN_API_KEY": "sk_xxx"})',additionalProperties:{type:"string"}}},required:["service_id","env"]}}],this._catalogTools,this.childManager.getActiveTools())}applyCatalog(e,t={}){const{catalog:r,cloudProxy:o,warnings:s,needChildForSchema:i}=buildCatalogRegistry(e);this._catalogTools=r,this._cloudProxyTools=o,this._catalogServices=new Map,this._needChildForSchema=new Set(i),this._catalogFromCache=!0===t.fromCache;for(const t of Array.isArray(e)?e:[])t&&t.mcpId&&this._catalogServices.set(t.mcpId,t);let n=0;for(const e of s)"no-input-schema"===e.reason?(n+=e.count,log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}): ${e.count}/${e.total} tools have no inputSchema — 一覧には出す(空 schema)。子を起こして実 schema で上書きする`)):log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}) skipped: ${e.reason}`);return n>0&&log(`[catalog] inputSchema 欠損の合計: ${n} 本 / ${this._needChildForSchema.size} service(一覧には出す。子を起こして実 schema で上書きする)`),log(`[catalog] ${r.size} tools registered from ${this._catalogServices.size} services (cloud_proxy: ${o.size})`),r}registerServiceInCatalog(e){const{catalog:t,cloudProxy:r,warnings:o}=buildCatalogRegistry([e]);for(const[e,r]of t)this._catalogTools.set(e,r);for(const[e,t]of r)this._cloudProxyTools.set(e,t);for(const e of o)log(`[catalog] "${e.mcpId}" (${e.hostingType||"unknown"}) skipped: ${e.reason}`);return e&&e.mcpId&&this._catalogServices.set(e.mcpId,e),t.size}unregisterServiceFromCatalog(e){const t=`${e}__`;let r=0;for(const e of[...this._catalogTools.keys()])e.startsWith(t)&&(this._catalogTools.delete(e),this._cloudProxyTools.delete(e),r++);return r}buildChildService(e,t){const r=path.join(os.homedir(),".claude","mcp-servers",e),o=t.entryPoint||"dist/index.js";return{name:t.name,description:t.description,type:"external",command:t.command||"node",args:t.args&&t.args.length?t.args:[path.join(r,o)],env:t.env||{}}}setupHandlers(){this.server.setRequestHandler(ListToolsRequestSchema,async()=>{const e=this.buildToolList(),t=this.childManager.getActiveServiceIds();return log(`[ListTools] ${e.length} tools (active: ${t.join(", ")||"none"})`),{tools:e}}),this.server.setRequestHandler(CallToolRequestSchema,async e=>{const{name:r,arguments:o}=e.params;log(`[CallTool] ${r}`);const s=resolveToken();if("load_knowledge"===r){const{keyword:e}=o;log(`[load_knowledge] keyword: ${e}`);try{const r=await getPromptFromPortal(e,s,LANGUAGE);if(!r||!r.success){const o=r?.error||t("mcp.knowledgeNotFound",{keyword:e});return{content:[{type:"text",text:`❌ ${t("mcp.portalApiFailed",{error:o})}`}],isError:!0}}const o="ja"!==LANGUAGE?"\n\n[Note] The user's preferred language is English.":"",i=this.updateNoticeText?`\n\n${this.updateNoticeText}`:"";return{content:[{type:"text",text:`✅ ${t("mcp.knowledgeLoadSuccess")}\n\n${r.knowledge}${o}\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n${t("mcp.knowledgeApplied")}${i}`}]}}catch(e){return log(`[load_knowledge] Exception: ${e.message}`),{content:[{type:"text",text:`❌ ${t("mcp.knowledgeLoadError",{error:e.message})}`}],isError:!0}}}if("search_mcp"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};if(!s)return{content:[{type:"text",text:"❌ 未認証です。MCPカタログの検索にはログインが必要です。"}],isError:!0};let t=[];try{const e=await searchMcpServices(o.query,s);if(!e.success)return{content:[{type:"text",text:`❌ MCPカタログ検索に失敗: ${e.error||"Unknown"}`}],isError:!0};t=(e.data||[]).map(e=>({id:e.mcp_id,service:{name:e.name,description:e.description,tags:[],alwaysOn:e.alwaysOn||!1},isInstalled:e.isInstalled||!1}))}catch(e){return log(`[search_mcp] Server search failed: ${e.message}`),{content:[{type:"text",text:`❌ MCPカタログ検索に失敗: ${e.message}`}],isError:!0}}if(0===t.length)return{content:[{type:"text",text:`🔍 「${o.query}」に一致するサービスはありません。\n\n別のキーワードで試すか、browse_mcp_storeでカタログを確認してください。`}]};let r=`🔍 「${o.query}」の検索結果(${t.length}件)\n\n`;for(const e of t.slice(0,10)){const t=e.id,o=e.service,s=this.childManager.isActive(t),i=!0===o.deactivated,n=e.isInstalled?"":" [未インストール]",a=i?" [一覧から外し中]":"";r+=`${i?"🚫":s?"🟢":"⚪"} **${o.name}**${a}${n} (id: \`${t}\`)\n`,r+=` ${o.description}\n\n`}return r+="一覧に戻す: activate_service | ストアから導入: install_from_store",{content:[{type:"text",text:r}]}}if("activate_service"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t}=o,r=await getGatewayConfig(s);if(!r.success)return{content:[{type:"text",text:`❌ サーバー設定の取得に失敗: ${r.error||"Unknown"}`}],isError:!0};const i=(r.data?.services||[]).find(e=>e.mcpId===t);if(!i)return{content:[{type:"text",text:`❌ サービス "${t}" はあなたの権限の中にありません(権限のある MCP は何もしなくても一覧に出ます)。`}],isError:!0};const n=await setServiceDeactivated(t,!1,s);if(!n.success)return{content:[{type:"text",text:`❌ "${t}" を一覧に戻せませんでした: ${n.error||"Unknown"}`}],isError:!0};log(`[activate] "${t}" deactivated=false (一覧に戻した)`);const a=this.registerServiceInCatalog({...i,deactivated:!1});if(0===a)return{content:[{type:"text",text:`❌ "${t}" には目録にツール定義がありません(tools が空)。`}],isError:!0};if("cloud_proxy"===i.hostingType){log(`[activate] "${t}" (cloud_proxy) → ${a} proxy tools registered`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${i.name}" を一覧に戻しました(cloud_proxy ツール${a}個)`}]}}if(this.childManager.isActive(t)){try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${t}" を一覧に戻しました(子プロセスは既に起動済み)。`}]}}log(`[activate] "${t}" (${i.hostingType}) → ${a} catalog tools restored. Sending list_changed.`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[activate] notification error: ${e.message}`)}return{content:[{type:"text",text:`✅ "${i.name}" を一覧に戻しました(ツール${a}個)。最初に呼ばれた時に自動で起動します。`}]}}if("deactivate_service"===r){const{service_id:e}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};const t=await setServiceDeactivated(e,!0,s);if(!t.success)return{content:[{type:"text",text:`❌ "${e}" を一覧から外せませんでした: ${t.error||"Unknown"}`}],isError:!0};log(`[deactivate] "${e}" deactivated=true (一覧から外した)`);const r=this.unregisterServiceFromCatalog(e);r>0&&log(`[deactivate] "${e}" → ${r} catalog tools removed`),this._catalogServices.delete(e);let i=!1;if(this.childManager.isActive(e)&&(this.childManager.deactivate(e),log(`[deactivate] "${e}" child process stopped`),i=!0),r>0||i)try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[deactivate] notification error: ${e.message}`)}let n=`✅ "${e}" を道具一覧から外しました(deactivated=true)。`;return r>0&&(n+=` ツール${r}個を一覧から削除しました。`),i&&(n+=" 子プロセスを停止しました。"),n+=" 次の接続でも一覧に出ません。権限は変わっていないので activate_service で戻せます。",{content:[{type:"text",text:n}]}}if("restart_service"===r){const{service_id:e}=o,t=this.childManager.children.get(e),r=t?.service;if(!r)return isCloudProxyService(this._cloudProxyTools,e)?{content:[{type:"text",text:`ℹ️ "${e}" は cloud_proxy 方式のため、ローカルの再起動対象ではありません(子プロセスを持ちません)。\nサーバ側のツール更新は deploy で全利用者に反映されるので、再起動は不要です。\nツール一覧を取り直したいだけなら deactivate_service → activate_service を実行してください。`}]}:{content:[{type:"text",text:`❌ "${e}" の子プロセスは現在動いていません。道具を呼べば自動で起動します(restart は起動済みの子にだけ効きます)。`}],isError:!0};let i,n=r;if(s)try{const t=await getGatewayConfig(s);if(t.success){const o=(t.data?.services||[]).find(t=>t.mcpId===e);o&&o.env&&(n={...r,env:o.env},log(`[restart] "${e}" env refreshed from server (keys=${Object.keys(o.env).join(",")||"none"})`))}}catch(e){log(`[restart] env refresh failed (using cached): ${e.message}`)}this.childManager.deactivate(e),log(`[restart] "${e}" stopped`);try{i=await this.childManager.activateExternal(e,n)}catch(t){return log(`[restart] Failed "${e}": ${t.message}`),{content:[{type:"text",text:`❌ "${e}" の再起動に失敗しました: ${t.message}`}],isError:!0}}log(`[restart] "${e}" → ${i.length} tools. Sending list_changed.`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[restart] notification error: ${e.message}`)}const a=i.map(e=>e.name).join(", ");return{content:[{type:"text",text:`🔄 "${n.name}" を再起動しました(ツール${i.length}個)\n\nツール: ${a||"(なし)"}`}]}}if("unregister_service"===r){const{service_id:e}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};this.childManager.isActive(e)&&(this.childManager.deactivate(e),log(`[unregister] "${e}" stopped`));const t=await uninstallMcpService(e,s);if(!t.success)return{content:[{type:"text",text:`❌ "${e}" のサーバー削除に失敗: ${t.error||"Unknown"}`}],isError:!0};log(`[unregister] "${e}" uninstalled from server`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[unregister] notification error: ${e.message}`)}return{content:[{type:"text",text:`🗑️ "${e}" を削除しました。プロセスも停止済みです。`}]}}if("register_service"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t,env:r}=o;if(!s)return{content:[{type:"text",text:"🔒 未認証です。ログインが必要です。"}],isError:!0};const i=r||{},n=await installMcpService(t,!1,s,i);return n.success?(log(`[register] "${t}" installed on server`),{content:[{type:"text",text:`✅ サービス "${t}" をサーバーに登録しました。\n\n次のステップ:\n- save_mcp_env で APIキー等を設定\n- 次の接続で道具一覧に出ます(activate は不要です)`}]}):{content:[{type:"text",text:`❌ "${t}" の登録に失敗しました: ${n.error||"Unknown"}\n\n※ MCP はサーバーカタログに登録されている必要があります。browse_mcp_store で確認してください。`}],isError:!0}}if("save_mcp_env"===r){const e=this.checkAuth();if(!e.ok)return{content:[{type:"text",text:`🔒 ${e.error}`}],isError:!0};const{service_id:t,env:r}=o;if(!t||!r||0===Object.keys(r).length)return{content:[{type:"text",text:"❌ service_id と env(キー/値のペア)が必要です"}],isError:!0};log(`[save_mcp_env] ${t}: ${Object.keys(r).join(", ")}`);try{const e=await updateMcpEnv(t,r,s);if(!e.success)return{content:[{type:"text",text:`❌ サーバー保存失敗: ${e.error}`}],isError:!0};const o=Object.keys(r).join(", ");return e.warning?{content:[{type:"text",text:`🔐 環境変数をサーバーに保存しました\n\nサービス: ${t}\n保存キー: ${o}\n\n${e.warning}`}]}:{content:[{type:"text",text:`🔐 環境変数をサーバーに保存しました\n\nサービス: ${t}\n保存キー: ${o}\n\n※ ローカルには保存されません。次回起動時にサーバーから自動取得されます。`}]}}catch(e){return log(`[save_mcp_env] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if("browse_mcp_store"===r){log("[browse_mcp_store]");try{const e=await listAvailableMcps({},s,LANGUAGE);if(!e||!e.success)return{content:[{type:"text",text:`❌ MCPカタログの取得に失敗: ${e?.error||"Unknown"}`}],isError:!0};const t=e.data||[];if(0===t.length)return{content:[{type:"text",text:"📦 インストール可能なMCPはありません。"}]};let r=`📦 MCPストア一覧 (${t.length}件)\n\n`;return t.forEach(e=>{const t=e.isOfficial?" [公式]":"";r+=`**${e.name}**${t}\n`,r+=` ID: ${e.mcpId}\n`,r+=` ${e.description}\n`,r+=` ツール数: ${e.toolCount}\n\n`}),r+='\nインストールするには: install_from_store(mcp_id: "MCP_ID")',{content:[{type:"text",text:r}]}}catch(e){return log(`[browse_mcp_store] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if("install_from_store"===r){const{mcp_id:e}=o;log(`[install_from_store] mcp_id=${e}`);try{const t=await downloadMcpPackage(e,s);if(!t||!t.success)return{content:[{type:"text",text:`❌ MCPダウンロードに失敗: ${t?.error||"Unknown"}`}],isError:!0};const r=t.data,o=r.packageSource||{},i=r.files||[];let n=o.hostingType||o.hosting&&o.hosting.type||null;if(s){let t=!1;try{const r=await getGatewayConfig(s);if(r.success){const o=(r.data?.services||[]).find(t=>t.mcpId===e);o&&(t=!0===o.alwaysOn,n||(n=o.hostingType))}}catch(e){}const r=await installMcpService(e,t,s);if(!r.success)return{content:[{type:"text",text:`❌ サーバー登録失敗: ${r.error||"Unknown"}`}],isError:!0};log(`[install_from_store] Server sync OK: ${e} (alwaysOn=${t})`)}if("cloud_proxy"===n){log(`[install_from_store] "${e}" is cloud_proxy, skipping local extract`);let t=`✅ MCP「${o.name||e}」をインストールしました(cloud_proxy)\n\n`;return t+="☁ クラウド実行のためローカル展開は不要です\n",o.installNotes&&(t+=`\n📝 ${o.installNotes}\n`),t+="\n権限に含まれていれば、次の接続で道具一覧に出ます(activate_service を撃つ必要はありません)。",{content:[{type:"text",text:t}]}}if(0===i.length)return{content:[{type:"text",text:"❌ MCPパッケージにファイルが含まれていません。"}],isError:!0};const a=path.join(os.homedir(),".claude","mcp-servers",e),c=installPackageFiles({installDir:a,files:i,needsNpmInstall:!!o.needsNpmInstall,runNpmInstall:e=>runProductionNpmInstall(e)});if(!c.ok)return log(`[install_from_store] ${e} failed at ${c.stage}: ${c.error.message}`),{content:[{type:"text",text:formatInstallFailure(o.name||e,c)}],isError:!0};log(`[install_from_store] ${i.length} files written to ${a}`);let l=`✅ MCP「${o.name||e}」をインストールしました\n\n`;l+=`📁 インストール先: ${a}\n`,l+=`📄 ファイル数: ${i.length}\n`,o.installNotes&&(l+=`\n📝 ${o.installNotes}\n`);const d=(o.requiredEnvVars||[]).filter(e=>!process.env[e]);return d.length>0&&(l+="\n⚠️ 以下の環境変数を save_mcp_env で設定してください:\n",d.forEach(e=>{l+=` - ${e}\n`})),l+="\n権限に含まれていれば、次の接続で道具一覧に出ます(activate_service を撃つ必要はありません)。",{content:[{type:"text",text:l}]}}catch(e){return log(`[install_from_store] error: ${e.message}`),{content:[{type:"text",text:`❌ ${e.message}`}],isError:!0}}}if(this._cloudProxyTools&&this._cloudProxyTools.has(r)){const e=this._cloudProxyTools.get(r);log(`[callTool] Cloud proxy: ${r} → ${e.mcpId}/${e.toolName}`);try{const t=await callMcpToolProxy(e.mcpId,e.toolName,o,s);return t.success&&t.data?t.data.content?t.data:{content:[{type:"text",text:JSON.stringify(t.data,null,2)}]}:{content:[{type:"text",text:`❌ プロキシエラー: ${t.error||"Unknown"}`}],isError:!0}}catch(e){return log(`[callTool] Cloud proxy error "${r}": ${e.message}`),{content:[{type:"text",text:`❌ クラウドプロキシエラー: ${e.message}`}],isError:!0}}}try{const{found:e,result:t}=await this.childManager.callTool(r,o);if(e)return t&&t.content?t:{content:[{type:"text",text:String(t)}]}}catch(e){return log(`[callTool] Error proxying "${r}": ${e.message}`),{content:[{type:"text",text:`❌ ツール実行エラー: ${e.message}`}],isError:!0}}const i=this._catalogTools.get(r);if(i&&"cloud_proxy"!==i.hostingType){const e=i.mcpId;this._catalogFromCache&&this._configRefresh&&(log(`[callTool] "${e}" は目録キャッシュ由来。起動仕様の到着を待つ。`),await this._configRefresh),this.startChildOnDemand(e);const t=await this.childManager.waitForReady(e,3e4);if(!t.ready){if("failed"===t.reason){const r=t.error?.message||String(t.error||"Unknown");return log(`[callTool] "${e}" failed to start: ${r}`),{content:[{type:"text",text:`❌ "${e}" の起動に失敗しました: ${r}`}],isError:!0}}return"timeout"===t.reason?(log(`[callTool] "${e}" not ready within 30000ms for "${r}".`),{content:[{type:"text",text:CHILD_NOT_READY_TEXT}],isError:!0}):(log(`[callTool] "${e}" could not be started for "${r}" (reason=${t.reason}).`),{content:[{type:"text",text:`❌ "${e}" を起動できませんでした(設定が見つかりません)。`}],isError:!0})}try{const{found:t,result:s}=await this.childManager.callTool(r,o);if(t)return s&&s.content?s:{content:[{type:"text",text:String(s)}]};log(`[callTool] "${r}" is in catalog but child "${e}" does not have it.`)}catch(e){return log(`[callTool] Error proxying "${r}" after ready: ${e.message}`),{content:[{type:"text",text:`❌ ツール実行エラー: ${e.message}`}],isError:!0}}}return{content:[{type:"text",text:`❌ Unknown tool: ${r}`}],isError:!0}})}startChildrenForMissingSchema(){let e=0;for(const t of this._needChildForSchema){const r=this._catalogServices.get(t);if(r)if("cloud_proxy"!==r.hostingType){if(!this.childManager.isActive(t)&&!this.childManager.isStarting(t)){log(`[schemaChild] "${t}" (${r.hostingType}) を起こして実 schema を取りに行く`);try{this.startChildOnDemand(t),e++}catch(e){log(`[schemaChild] "${t}" の起動に失敗: ${e.message}(⛔ 席は落とさない)`)}}}else log(`[schemaChild] "${t}" は cloud_proxy のため子を起こせない。schema 欠損の道具は一覧に出ない。`)}return log(`[schemaChild] ${e} service(=目録に schema が無い道具を持つ service の数)`),e}async loadCatalog(e){if(!e)return log("[catalog] No token, starting with no catalog tools."),[];let t=[];try{const r=await getGatewayConfig(e);if(!r.success)return log(`[catalog] Server config failed: ${r.error||"Unknown"}. Starting with no services.`),[];t=r.data?.services||[],log(`[catalog] Server config: ${t.length} services`),this.applyCatalog(t),writeCatalogCache(CATALOG_CACHE_FILE,t,catalogCacheFingerprint(e),log)}catch(e){return log(`[catalog] Server config error: ${e.message}. Starting with no services.`),[]}try{const e=collectUpdateNotices(t);this.updateNoticeText=buildUpdateNoticeText(e);for(const t of e)"not-applicable"!==t.status&&log(`[versionCheck] ${t.mcpId}: ${t.status} (${t.reason}) catalog=${t.catalogVersion} local=${t.localVersion}`)}catch(e){log(`[versionCheck] skipped: ${e.message}`)}return t}startChildOnDemand(e){const t=this._catalogServices.get(e);if(!t||!0===t.deactivated)return null;if("cloud_proxy"===t.hostingType)return null;if(this.childManager.isActive(e))return null;const r=this.childManager.isStarting(e),o=this.childManager.beginActivateExternal(e,this.buildChildService(e,t));return r||log(`[startChild] "${e}" (${t.hostingType}) starting on demand...`),o.then(t=>this.reconcileChildWithCatalog(e,t)).catch(t=>log(`[startChild] "${e}" post-start error: ${t.message}`)),o}async reconcileChildWithCatalog(e,t){const r=decideCatalogReconciliation(this._catalogTools,e,t);if(!r.ready){const o=t&&t.error?`: ${t.error.message||t.error}`:"";return log(`[versionDrift] "${e}" not ready (${r.reason})${o} → 剪定も通知もしない`),r}if(!r.notify)return log(`[versionDrift] "${e}" matches catalog (${t.tools.length} tools) → no list_changed`),r;for(const e of r.prune)this._catalogTools.delete(e),this._cloudProxyTools.delete(e);const o=r.diff;log(`[versionDrift] "${e}" differs from catalog: +${o.added.length} -${o.removed.length} ~${o.changed.length} → list_changed`);try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[versionDrift] notification error: ${e.message}`)}return r}toolListSignature(){return stableJson(this.buildToolList().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema})))}async refreshCatalogInBackground(e){const t=this.toolListSignature();try{await this.loadCatalog(e)}catch(e){return log(`[catalogRefresh] failed, keeping cached catalog: ${e.message}`),{notified:!1,reason:"failed"}}if(t===this.toolListSignature())return log("[catalogRefresh] server catalog matches cache → no list_changed"),{notified:!1,reason:"same"};log("[catalogRefresh] server catalog differs from cache → list_changed");try{await this.server.notification({method:"notifications/tools/list_changed"})}catch(e){log(`[catalogRefresh] notification error: ${e.message}`)}return{notified:!0,reason:"diff"}}async run(){const e=resolveToken(),t=catalogCacheFingerprint(e),r=readCatalogCache(CATALOG_CACHE_FILE,t,log);r?(this.applyCatalog(r,{fromCache:!0}),log(`[catalogCache] ${this._catalogTools.size} tools from cache (HTTP は待たない)`)):(log("[catalogCache] no usable cache, waiting for server config"),await this.loadCatalog(e));const o=new StdioServerTransport;await this.server.connect(o),log(`[Gateway] BizBoost Gateway v2.0.0 started. (${this._catalogTools.size} catalog tools available at connect)`),r?(this._configRefresh=this.refreshCatalogInBackground(e).catch(e=>(log(`[catalogRefresh] unexpected: ${e.message}`),{notified:!1,reason:"failed"})),this._configRefresh.then(()=>this.startChildrenForMissingSchema()).catch(e=>log(`[schemaChild] deferred start failed: ${e.message}`))):this.startChildrenForMissingSchema();const s=resolveToken();if(KEYWORD&&s){log(`[Gateway] Auto-loading knowledge for keyword: ${KEYWORD}`);const e=await getPromptFromPortal(KEYWORD,s,LANGUAGE);e&&e.success?log(`[Gateway] Auto-load successful: ${e.title}`):log(`[Gateway] Auto-load failed for keyword: ${KEYWORD}`)}}}function buildCatalogRegistry(e){const t=new Map,r=new Map,o=[],s=[];for(const i of Array.isArray(e)?e:[]){if(!i||"string"!=typeof i.mcpId||!i.mcpId)continue;const e=i.hostingType||null;if(!0===i.deactivated)continue;const n=Array.isArray(i.tools)?i.tools:[];if(0===n.length){o.push({mcpId:i.mcpId,hostingType:e,reason:"no-tools"});continue}const a=[];for(const s of n){if(!s||"string"!=typeof s.name||!s.name){o.push({mcpId:i.mcpId,hostingType:e,reason:"unnamed-tool"});continue}s.inputSchema&&"object"==typeof s.inputSchema||a.push(s.name);const n=`${i.mcpId}__${s.name}`,c={name:n,mcpId:i.mcpId,toolName:s.name,hostingType:e,description:s.description,inputSchema:s.inputSchema};t.set(n,c),"cloud_proxy"===e&&r.set(n,{mcpId:i.mcpId,toolName:s.name,description:s.description,inputSchema:s.inputSchema})}a.length>0&&(o.push({mcpId:i.mcpId,hostingType:e,reason:"no-input-schema",count:a.length,total:n.length,tools:a}),s.push(i.mcpId))}return{catalog:t,cloudProxy:r,warnings:o,needChildForSchema:s}}function catalogEntryToTool(e){return{name:e.name,description:e.description||`[${e.mcpId}] ${e.toolName}`,inputSchema:e.inputSchema||{type:"object",properties:{}}}}function buildGatewayToolList(e,t,r){const o=new Map;for(const t of Array.isArray(e)?e:[])t&&t.name&&o.set(t.name,t);if(t&&"function"==typeof t.values)for(const e of t.values())o.has(e.name)||o.set(e.name,catalogEntryToTool(e));for(const e of Array.isArray(r)?r:[])e&&e.name&&o.set(e.name,e);return[...o.values()]}function sanitizeServicesForCache(e){return(Array.isArray(e)?e:[]).filter(e=>e&&"string"==typeof e.mcpId&&e.mcpId).map(e=>({mcpId:e.mcpId,name:e.name,description:e.description,hostingType:e.hostingType||null,deactivated:!0===e.deactivated,tools:(Array.isArray(e.tools)?e.tools:[]).filter(e=>e&&"string"==typeof e.name&&e.name).map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}))}))}function catalogCacheFingerprint(e){return e?require("crypto").createHash("sha256").update(String(e)).digest("hex").slice(0,16):null}function sliceTailPreservingSurrogates(e,t){const r=String(null==e?"":e);if(r.length<=t)return r;const o=r.slice(-t),s=o.charCodeAt(0);return s>=56320&&s<=57343?o.slice(1):o}function stableJson(e){return void 0===e?"null":null===e||"object"!=typeof e?JSON.stringify(e):Array.isArray(e)?`[${e.map(stableJson).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${stableJson(e[t])}`).join(",")}}`}function diffChildToolsAgainstCatalog(e,t,r){const o=`${t}__`,s=new Set;if(e&&"function"==typeof e.keys)for(const t of e.keys())"string"==typeof t&&t.startsWith(o)&&s.add(t);const i=[],n=[],a=new Set;for(const t of Array.isArray(r)?r:[]){if(!t||!t.name)continue;a.add(t.name);const r=e&&"function"==typeof e.get?e.get(t.name):void 0;r?stableJson(r.description)===stableJson(t.description)&&stableJson(r.inputSchema)===stableJson(t.inputSchema)||n.push(t.name):i.push(t.name)}const c=[...s].filter(e=>!a.has(e));return{added:i,removed:c,changed:n,hasDiff:i.length+c.length+n.length>0}}function decideCatalogReconciliation(e,t,r){if(!r||!0!==r.ok||!Array.isArray(r.tools))return{ready:!1,prune:[],notify:!1,reason:r&&r.reason||"not-ready",diff:null};const o=diffChildToolsAgainstCatalog(e,t,r.tools);return{ready:!0,prune:o.removed,notify:o.hasDiff,reason:"ready",diff:o}}function readCatalogCache(e,t,r){const o=r||(()=>{});if(!t)return null;let s,i;try{s=fs.readFileSync(e,"utf8")}catch(e){return"ENOENT"!==e.code&&o(`[catalogCache] read failed: ${e.message}`),null}try{i=JSON.parse(s)}catch(e){return o(`[catalogCache] broken JSON, ignoring: ${e.message}`),null}return i&&1===i.version?i.tokenFingerprint!==t?(o("[catalogCache] fingerprint mismatch (口座が違う), ignoring"),null):Array.isArray(i.services)?i.services:(o("[catalogCache] services が配列でない, ignoring"),null):(o(`[catalogCache] version mismatch (${i&&i.version}), ignoring`),null)}function writeCatalogCache(e,t,r,o){const s=o||(()=>{});if(!r)return!1;try{fs.mkdirSync(path.dirname(e),{recursive:!0});const o={version:1,tokenFingerprint:r,savedAt:(new Date).toISOString(),services:sanitizeServicesForCache(t)},s=`${e}.${process.pid}.tmp`;return fs.writeFileSync(s,JSON.stringify(o),{mode:384}),fs.renameSync(s,e),!0}catch(e){return s(`[catalogCache] write failed: ${e.message}`),!1}}function isCloudProxyService(e,t){if(!e||"function"!=typeof e.keys)return!1;const r=`${t}__`;for(const t of e.keys())if("string"==typeof t&&t.startsWith(r))return!0;return!1}if(module.exports={ChildMcpProcess:ChildMcpProcess,ChildMcpManager:ChildMcpManager,BizBoostServer:BizBoostServer,isCloudProxyService:isCloudProxyService,buildCatalogRegistry:buildCatalogRegistry,buildGatewayToolList:buildGatewayToolList,catalogEntryToTool:catalogEntryToTool,diffChildToolsAgainstCatalog:diffChildToolsAgainstCatalog,decideCatalogReconciliation:decideCatalogReconciliation,sanitizeServicesForCache:sanitizeServicesForCache,catalogCacheFingerprint:catalogCacheFingerprint,readCatalogCache:readCatalogCache,writeCatalogCache:writeCatalogCache,CATALOG_CACHE_FILE:CATALOG_CACHE_FILE,CATALOG_CACHE_VERSION:1,stableJson:stableJson,sliceTailPreservingSurrogates:sliceTailPreservingSurrogates,CHILD_READY_TIMEOUT_MS:3e4,CHILD_NOT_READY_TEXT:CHILD_NOT_READY_TEXT},require.main===module){const e=new BizBoostServer;let t=!1;const r=r=>{if(!t){t=!0;try{log(`[Gateway] Shutdown (${r}) - cleaning up children...`)}catch(e){}if(e&&e.childManager&&e.childManager.children)for(const[t,r]of e.childManager.children)try{try{log(`[Gateway] Stopping child: ${t}`)}catch(e){}r&&"external"===r.type&&r.process&&"function"==typeof r.process.stop&&r.process.stop()}catch(e){}setTimeout(()=>process.exit(0),200).unref()}};process.on("SIGTERM",()=>r("SIGTERM")),process.on("SIGINT",()=>r("SIGINT")),process.on("SIGHUP",()=>r("SIGHUP")),process.stdin.on("end",()=>r("stdin-end")),process.stdin.on("close",()=>r("stdin-close")),process.on("exit",()=>{if(e&&e.childManager&&e.childManager.children)for(const[t,r]of e.childManager.children)try{r&&r.process&&r.process.process&&"function"==typeof r.process.process.kill&&r.process.process.kill("SIGKILL")}catch(e){}}),e.run().catch(e=>{log(`[Gateway] Fatal: ${e.message}`),process.exit(1)})}
|