bluelamp 4.0.5 → 4.0.6

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.
Files changed (47) hide show
  1. package/bin/bluelamp-vscode-base +258 -0
  2. package/bin/bluelamp-vscode1 +2 -0
  3. package/bin/bluelamp-vscode10 +2 -0
  4. package/bin/bluelamp-vscode11 +2 -0
  5. package/bin/bluelamp-vscode12 +2 -0
  6. package/bin/bluelamp-vscode13 +2 -0
  7. package/bin/bluelamp-vscode14 +2 -0
  8. package/bin/bluelamp-vscode15 +2 -0
  9. package/bin/bluelamp-vscode16 +2 -0
  10. package/bin/bluelamp-vscode17 +2 -0
  11. package/bin/bluelamp-vscode18 +2 -0
  12. package/bin/bluelamp-vscode2 +2 -0
  13. package/bin/bluelamp-vscode3 +2 -0
  14. package/bin/bluelamp-vscode4 +2 -0
  15. package/bin/bluelamp-vscode5 +2 -0
  16. package/bin/bluelamp-vscode6 +2 -0
  17. package/bin/bluelamp-vscode7 +2 -0
  18. package/bin/bluelamp-vscode8 +2 -0
  19. package/bin/bluelamp-vscode9 +2 -0
  20. package/lib/auth/PortalAuthClient.js +1 -1
  21. package/lib/mcp-server/index.cjs +57 -25
  22. package/lib/mcp-server/portal-api-client.cjs +37 -10
  23. package/lib/utils/logger.js +83 -0
  24. package/package.json +33 -25
  25. package/scripts/generate-commands.js +10 -15
  26. package/bin/bluelamp-base +0 -200
  27. package/bin/bluelamp-hook +0 -49
  28. package/bin/bluelamp1 +0 -2
  29. package/bin/bluelamp10 +0 -2
  30. package/bin/bluelamp11 +0 -2
  31. package/bin/bluelamp12 +0 -2
  32. package/bin/bluelamp13 +0 -2
  33. package/bin/bluelamp14 +0 -2
  34. package/bin/bluelamp15 +0 -2
  35. package/bin/bluelamp16 +0 -2
  36. package/bin/bluelamp17 +0 -2
  37. package/bin/bluelamp18 +0 -2
  38. package/bin/bluelamp2 +0 -2
  39. package/bin/bluelamp3 +0 -2
  40. package/bin/bluelamp4 +0 -2
  41. package/bin/bluelamp5 +0 -2
  42. package/bin/bluelamp6 +0 -2
  43. package/bin/bluelamp7 +0 -2
  44. package/bin/bluelamp8 +0 -2
  45. package/bin/bluelamp9 +0 -2
  46. package/lib/mcp-server/fetch-prompt.js +0 -61
  47. package/scripts/setup-hook.js +0 -98
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * BlueLamp VSCode MCP Integration
5
+ * Base script for VSCode extension prompt injection
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const path = require('path');
10
+ const fs = require('fs');
11
+ const os = require('os');
12
+
13
+ // パッケージのルートディレクトリを取得
14
+ const packageRoot = path.dirname(__dirname);
15
+
16
+ // .envファイルを読み込み(.env.localを優先)
17
+ const dotenvLocalPath = path.join(packageRoot, '.env.local');
18
+ const dotenvPath = path.join(packageRoot, '.env');
19
+
20
+ if (fs.existsSync(dotenvLocalPath)) {
21
+ require('dotenv').config({ path: dotenvLocalPath });
22
+ console.log('📁 Loaded .env.local');
23
+ } else if (fs.existsSync(dotenvPath)) {
24
+ require('dotenv').config({ path: dotenvPath });
25
+ console.log('📁 Loaded .env');
26
+ }
27
+
28
+ // コマンドマッピング(18個のプロンプト - 新BlueLamp 18エージェント体制)
29
+ const PROMPT_MAPPING = {
30
+ 'bluelamp-vscode1': '@要件定義', // Phase @1: 要件定義エンジニア
31
+ 'bluelamp-vscode2': '@Git管理', // Phase @2: Git/GitHub管理
32
+ 'bluelamp-vscode3': '@フロントエンド基盤', // Phase @3: フロントエンド基盤オーケストレーター
33
+ 'bluelamp-vscode4': '@ページ実装オーケストレーター', // Phase @4: ページ実装統括
34
+ 'bluelamp-vscode5': '@環境構築オーケストレーター', // Phase @5: 環境構築
35
+ 'bluelamp-vscode6': '@バックエンド計画オーケストレーター', // Phase @6: バックエンド実装計画
36
+ 'bluelamp-vscode7': '@バックエンド実装オーケストレーター', // Phase @7: バックエンド実装統括
37
+ 'bluelamp-vscode8': '@フロントエンド実装オーケストレーター', // Phase @8: API統合統括
38
+ 'bluelamp-vscode9': '@E2Eテストオーケストレーター', // Phase @9: E2Eテスト統括
39
+ 'bluelamp-vscode10': '@本番運用診断オーケストレーター', // Phase @10: CVSS 3.1準拠本番運用診断
40
+ 'bluelamp-vscode11': '@デプロイオーケストレーター', // Phase @11: デプロイメント統括
41
+ 'bluelamp-vscode12': '@拡張要件定義', // Tools @12: 拡張要件定義オーケストレーター
42
+ 'bluelamp-vscode13': '@拡張機能実装', // Tools @13: 拡張機能実装オーケストレーター
43
+ 'bluelamp-vscode14': '@デバッグ技術', // Tools @14: 自己完結型デバッグマスター
44
+ 'bluelamp-vscode15': '@リファクタリング', // Tools @15: 超並列リファクタリング
45
+ 'bluelamp-vscode16': '@ドキュメント生成', // Tools @16: ドキュメント生成統括
46
+ 'bluelamp-vscode17': '@相談', // Tools @17: 相談対応
47
+ 'bluelamp-vscode18': '@MCP追加' // Tools @18: MCP追加エージェント
48
+ };
49
+
50
+ /**
51
+ * コマンド名から対応するキーワードを取得
52
+ */
53
+ function getKeywordFromCommand() {
54
+ const commandPath = process.argv[1];
55
+ const commandName = path.basename(commandPath);
56
+
57
+ if (!PROMPT_MAPPING[commandName]) {
58
+ console.error(`❌ 未定義のコマンド: ${commandName}`);
59
+ process.exit(1);
60
+ }
61
+
62
+ return PROMPT_MAPPING[commandName];
63
+ }
64
+
65
+ /**
66
+ * MCPサーバー設定を作成
67
+ */
68
+ function createMCPConfig(keyword, cliToken) {
69
+ const mcpServerPath = path.join(packageRoot, 'lib/mcp-server/index.cjs');
70
+ const tempConfigPath = path.join(os.tmpdir(), `bluelamp-vscode-${Date.now()}.json`);
71
+
72
+ // .env.localからPORTAL_URLを取得(デフォルトは本番)
73
+ const portalUrl = process.env.PORTAL_URL || "https://bluelamp-6clpzmy5pa-an.a.run.app";
74
+
75
+ const config = {
76
+ mcpServers: {
77
+ "bluelamp-vscode": {
78
+ command: "node",
79
+ args: [mcpServerPath],
80
+ env: {
81
+ BLUELAMP_KEYWORD: keyword,
82
+ BLUELAMP_TOKEN: cliToken,
83
+ PORTAL_URL: portalUrl
84
+ }
85
+ }
86
+ }
87
+ };
88
+
89
+ fs.writeFileSync(tempConfigPath, JSON.stringify(config, null, 2));
90
+ return tempConfigPath;
91
+ }
92
+
93
+ /**
94
+ * Portal認証の実行(BlueLamp VSCode独自の認証システム)
95
+ */
96
+ async function performPortalAuth() {
97
+ try {
98
+ // BlueLamp VSCode用の認証モジュールを使用
99
+ const { InteractiveLogin } = require('../lib/auth/InteractiveLogin');
100
+
101
+ const authResult = await InteractiveLogin.performLogin();
102
+
103
+ InteractiveLogin.displayLoginSuccess(authResult);
104
+
105
+ return authResult.token;
106
+
107
+ } catch (error) {
108
+ console.error('❌ Portal認証エラー:', error.message);
109
+ console.error('');
110
+ console.error('解決方法:');
111
+ console.error('1. インターネット接続を確認してください');
112
+ console.error('2. Portal認証情報が正しいか確認してください');
113
+ console.error('3. https://bluelamp-6clpzmy5pa-an.a.run.app にアクセスできるか確認してください');
114
+ process.exit(1);
115
+ }
116
+ }
117
+
118
+ /**
119
+ * メイン処理
120
+ */
121
+ async function main() {
122
+ const keyword = getKeywordFromCommand();
123
+
124
+ // --debugフラグの確認
125
+ const isDebugMode = process.argv.includes('--debug');
126
+
127
+ console.log('🔵 BlueLamp VSCode MCP Integration');
128
+ console.log(`📚 プロンプト: ${keyword}`);
129
+ if (isDebugMode) {
130
+ console.log('🐛 デバッグモード: 有効');
131
+ console.log(` ログファイル: ${path.join(os.tmpdir(), 'bluelamp-vscode-mcp-latest.log')}`);
132
+ }
133
+ console.log('');
134
+
135
+ // Portal認証の実行
136
+ const cliToken = await performPortalAuth();
137
+
138
+ // MCP設定ファイルを作成(認証トークンを含む)
139
+ const configPath = createMCPConfig(keyword, cliToken);
140
+
141
+ // 初期プロンプトメッセージ
142
+ const initialPrompt = `> 拡張モードで起動
143
+
144
+ 🔵 BlueLamp 統合認証システム が有効化されました
145
+
146
+ \x1b[34m╭─────────────────────────────────────────────────────────────────╮\x1b[0m
147
+ \x1b[34m│ │\x1b[0m
148
+ \x1b[34m│ B l u e L a m p │\x1b[0m
149
+ \x1b[34m│ ───────────────── │\x1b[0m
150
+ \x1b[34m│ さあ始めましょう │\x1b[0m
151
+ \x1b[34m│ │\x1b[0m
152
+ \x1b[34m╰─────────────────────────────────────────────────────────────────╯\x1b[0m
153
+
154
+ **最初に必ず専門知識を注入してください**
155
+ inject_knowledge ツールで keyword: "${keyword}" を実行してから開始してください。(初回必須)
156
+
157
+ 重要:キーワードは "${keyword}" をそのまま使用してください。変換や推測は不要です。
158
+
159
+ 準備完了です。まず知識注入を実行してから、タスクを開始してください。`;
160
+
161
+ // Claude を起動
162
+ console.log('🚀 Claude 起動中...');
163
+ console.log(' - MCP Server: BlueLamp VSCode');
164
+ console.log(` - Knowledge: ${keyword}`);
165
+ console.log('');
166
+
167
+ // Windows対応: PowerShell経由でclaude.ps1を実行
168
+ const isWindows = process.platform === 'win32';
169
+ let claudeCommand, claudeArgs;
170
+
171
+ if (isWindows) {
172
+ // Windows: PowerShell経由でclaude.ps1を実行
173
+ claudeCommand = 'powershell.exe';
174
+ claudeArgs = [
175
+ '-NoProfile',
176
+ '-Command',
177
+ 'claude',
178
+ initialPrompt,
179
+ '--dangerously-skip-permissions',
180
+ '--mcp-config', configPath
181
+ ];
182
+ } else {
183
+ // Mac/Linux: 直接実行
184
+ claudeCommand = 'claude';
185
+ claudeArgs = [
186
+ initialPrompt,
187
+ '--dangerously-skip-permissions',
188
+ '--mcp-config', configPath
189
+ ];
190
+ }
191
+
192
+ // デバッグモードの場合、詳細情報を表示
193
+ if (isDebugMode) {
194
+ console.log('🐛 デバッグ情報:');
195
+ console.log(` コマンド: ${claudeCommand}`);
196
+ console.log(` 引数: ${JSON.stringify(claudeArgs, null, 2)}`);
197
+ console.log(` MCP設定ファイル: ${configPath}`);
198
+ console.log(` 環境変数 BLUELAMP_KEYWORD: ${keyword}`);
199
+ console.log(` 環境変数 BLUELAMP_TOKEN: ${cliToken.substring(0, 20)}...`);
200
+ console.log(` 環境変数 PORTAL_URL: ${process.env.PORTAL_URL || 'https://bluelamp-6clpzmy5pa-an.a.run.app'}`);
201
+ console.log('');
202
+
203
+ // MCP設定ファイルの内容を表示
204
+ const configContent = fs.readFileSync(configPath, 'utf-8');
205
+ console.log('📄 MCP設定ファイル内容:');
206
+ console.log(configContent);
207
+ console.log('');
208
+ }
209
+
210
+ const child = spawn(claudeCommand, claudeArgs, {
211
+ stdio: 'inherit',
212
+ env: {
213
+ ...process.env,
214
+ BLUELAMP_VSCODE_KEYWORD: keyword
215
+ }
216
+ });
217
+
218
+ // エラーハンドリング
219
+ child.on('error', (error) => {
220
+ console.error('❌ Claude 起動エラー:', error.message);
221
+
222
+ // 一時ファイルをクリーンアップ
223
+ try {
224
+ fs.unlinkSync(configPath);
225
+ } catch (e) {
226
+ // ignore
227
+ }
228
+
229
+ process.exit(1);
230
+ });
231
+
232
+ // 終了時のクリーンアップ
233
+ child.on('exit', (code) => {
234
+ console.log('');
235
+ console.log('🔵 BlueLamp VSCode セッション終了');
236
+
237
+ // 一時ファイルをクリーンアップ
238
+ try {
239
+ fs.unlinkSync(configPath);
240
+ } catch (e) {
241
+ // ignore
242
+ }
243
+
244
+ process.exit(code || 0);
245
+ });
246
+
247
+ // SIGINT (Ctrl+C) ハンドリング
248
+ process.on('SIGINT', () => {
249
+ console.log('\n🔵 BlueLamp VSCode を終了しています...');
250
+ child.kill('SIGINT');
251
+ });
252
+ }
253
+
254
+ // メイン処理の実行
255
+ main().catch((error) => {
256
+ console.error('❌ 予期しないエラー:', error.message);
257
+ process.exit(1);
258
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./bluelamp-vscode-base');
@@ -113,7 +113,7 @@ class PortalAuthClient {
113
113
  'Accept': 'application/json'
114
114
  },
115
115
  timeout: this.REQUEST_TIMEOUT,
116
- rejectUnauthorized: false // 自己署名証明書を許可
116
+ rejectUnauthorized: !this.isLocalDev() // 開発環境のみ自己署名証明書を許可
117
117
  };
118
118
 
119
119
  const client = url.protocol === 'https:' ? https : http;
@@ -12,6 +12,7 @@ const {
12
12
  ListToolsRequestSchema,
13
13
  } = require('@modelcontextprotocol/sdk/types.js');
14
14
  const { getPromptFromPortal } = require('./portal-api-client.cjs');
15
+ const { logger } = require('../utils/logger');
15
16
  const path = require('path');
16
17
  const fs = require('fs');
17
18
  const os = require('os');
@@ -22,10 +23,10 @@ const dotenvPath = path.join(__dirname, '../../.env');
22
23
 
23
24
  if (fs.existsSync(dotenvLocalPath)) {
24
25
  require('dotenv').config({ path: dotenvLocalPath });
25
- console.error('[MCP Server] Loaded .env.local');
26
+ logger.debug('[MCP Server] Loaded .env.local');
26
27
  } else if (fs.existsSync(dotenvPath)) {
27
28
  require('dotenv').config({ path: dotenvPath });
28
- console.error('[MCP Server] Loaded .env');
29
+ logger.debug('[MCP Server] Loaded .env');
29
30
  }
30
31
 
31
32
  // 環境変数から取得
@@ -33,14 +34,24 @@ const KEYWORD = process.env.BLUELAMP_KEYWORD || 'BL-要件定義';
33
34
  const TOKEN = process.env.BLUELAMP_TOKEN;
34
35
  const PORTAL_URL = process.env.PORTAL_URL || 'https://bluelamp-6clpzmy5pa-an.a.run.app';
35
36
 
36
- // ログファイル設定(固定名にして見つけやすくする)
37
- const LOG_FILE = path.join(os.tmpdir(), 'bluelamp-vscode-mcp-latest.log');
37
+ // ログファイル設定(ユーザーホームディレクトリに保存)
38
+ const LOG_DIR = path.join(os.homedir(), '.bluelamp-vscode', 'logs');
39
+ const LOG_FILE = path.join(LOG_DIR, 'mcp.log');
38
40
 
41
+ // ログディレクトリが存在しない場合は作成
42
+ if (!fs.existsSync(LOG_DIR)) {
43
+ fs.mkdirSync(LOG_DIR, { recursive: true });
44
+ }
45
+
46
+ /**
47
+ * ファイルとコンソールにログを出力
48
+ * @param {string} message - ログメッセージ
49
+ */
39
50
  function log(message) {
40
51
  const timestamp = new Date().toISOString();
41
52
  const logMessage = `[${timestamp}] ${message}\n`;
42
53
  fs.appendFileSync(LOG_FILE, logMessage);
43
- console.error(`[MCP Server] ${message}`);
54
+ logger.info(`[MCP Server] ${message}`);
44
55
  }
45
56
 
46
57
  log(`MCP Server started - Log file: ${LOG_FILE}`);
@@ -50,6 +61,10 @@ log(` TOKEN: ${TOKEN ? TOKEN.substring(0, 20) + '...' : 'NOT SET'}`);
50
61
  log(` PORTAL_URL: ${PORTAL_URL}`);
51
62
  log(` .env file exists: ${fs.existsSync(dotenvPath)}`);
52
63
 
64
+ /**
65
+ * BlueLamp VSCode MCPサーバークラス
66
+ * @class BlueLampVSCodeServer
67
+ */
53
68
  class BlueLampVSCodeServer {
54
69
  constructor() {
55
70
  this.server = new Server(
@@ -100,34 +115,50 @@ class BlueLampVSCodeServer {
100
115
  log(`[MCP Server] TOKEN: ${TOKEN ? TOKEN.substring(0, 20) + '...' : 'missing'}`);
101
116
  log(`[MCP Server] PORTAL_URL: ${PORTAL_URL}`);
102
117
 
103
- // Portal APIから認証付きで知識を取得
104
- const result = await getPromptFromPortal(keyword, TOKEN);
118
+ try {
119
+ // Portal APIから認証付きで知識を取得
120
+ const result = await getPromptFromPortal(keyword, TOKEN);
121
+
122
+ if (!result || !result.success) {
123
+ const errorMessage = result?.error || `キーワード "${keyword}" に対応する知識が見つかりませんでした`;
124
+ log(`[MCP Server] Knowledge injection failed: ${errorMessage}`);
125
+ return {
126
+ content: [
127
+ {
128
+ type: 'text',
129
+ text: `❌ Portal APIから知識を取得できませんでした: ${errorMessage}`,
130
+ },
131
+ ],
132
+ isError: true,
133
+ };
134
+ }
105
135
 
106
- if (!result || !result.success) {
136
+ // 知識注入メッセージを返す
107
137
  return {
108
138
  content: [
109
139
  {
110
140
  type: 'text',
111
- text: `❌ Portal APIから知識を取得できませんでした: "${keyword}"`,
112
- },
113
- ],
114
- };
115
- }
116
-
117
- // 知識注入メッセージを返す
118
- return {
119
- content: [
120
- {
121
- type: 'text',
122
- text: `✅ BlueLamp VSCode 知識注入完了
141
+ text: `✅ BlueLamp VSCode 知識注入完了
123
142
 
124
143
  ${result.knowledge}
125
144
 
126
145
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
127
146
  専門知識が注入されました。このロールで支援を開始します。`,
128
- },
129
- ],
130
- };
147
+ },
148
+ ],
149
+ };
150
+ } catch (error) {
151
+ log(`[MCP Server] Exception in inject_knowledge: ${error.message}`);
152
+ return {
153
+ content: [
154
+ {
155
+ type: 'text',
156
+ text: `❌ 知識注入中にエラーが発生しました: ${error.message}`,
157
+ },
158
+ ],
159
+ isError: true,
160
+ };
161
+ }
131
162
  }
132
163
 
133
164
  return {
@@ -137,6 +168,7 @@ ${result.knowledge}
137
168
  text: `Unknown tool: ${request.params.name}`,
138
169
  },
139
170
  ],
171
+ isError: true,
140
172
  };
141
173
  });
142
174
  }
@@ -144,7 +176,7 @@ ${result.knowledge}
144
176
  async run() {
145
177
  const transport = new StdioServerTransport();
146
178
  await this.server.connect(transport);
147
- console.error('BlueLamp VSCode MCP server started');
179
+ logger.info('BlueLamp VSCode MCP server started');
148
180
 
149
181
  // 起動時に自動的に知識を注入(環境変数で指定されたキーワード)
150
182
  if (KEYWORD && TOKEN) {
@@ -161,4 +193,4 @@ ${result.knowledge}
161
193
 
162
194
  // サーバー起動
163
195
  const server = new BlueLampVSCodeServer();
164
- server.run().catch(console.error);
196
+ server.run().catch((err) => logger.error(err.message));
@@ -8,31 +8,46 @@ const https = require('https');
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
10
  const os = require('os');
11
+ const { logger } = require('../utils/logger');
11
12
 
12
- // 自己署名証明書を許可するHTTPSエージェント
13
+ // HTTPS検証設定(本番環境では有効化、開発環境のみ自己署名証明書を許可)
14
+ const isDevEnvironment = process.env.NODE_ENV === 'development' ||
15
+ (process.env.PORTAL_URL && process.env.PORTAL_URL.includes('localhost'));
13
16
  const httpsAgent = new https.Agent({
14
- rejectUnauthorized: false
17
+ rejectUnauthorized: !isDevEnvironment
15
18
  });
16
19
 
17
20
  const PORTAL_URL = process.env.PORTAL_URL || 'https://bluelamp-6clpzmy5pa-an.a.run.app';
18
21
 
19
22
  // ログファイル(index.cjsと同じファイルに書き込む)
20
- const LOG_FILE = path.join(os.tmpdir(), 'bluelamp-vscode-mcp-latest.log');
23
+ const LOG_DIR = path.join(os.homedir(), '.bluelamp-vscode', 'logs');
24
+ const LOG_FILE = path.join(LOG_DIR, 'mcp.log');
25
+
26
+ // ログディレクトリが存在しない場合は作成
27
+ if (!fs.existsSync(LOG_DIR)) {
28
+ fs.mkdirSync(LOG_DIR, { recursive: true });
29
+ }
21
30
 
22
31
  // 共通設定のキャッシュ(5分間有効)
23
32
  let globalConfigCache = null;
24
33
  let cacheExpiry = 0;
25
34
 
35
+ /**
36
+ * ファイルとコンソールにログを出力
37
+ * @param {string} message - ログメッセージ
38
+ */
26
39
  function log(message) {
27
40
  const timestamp = new Date().toISOString();
28
41
  const logMessage = `[${timestamp}] ${message}\n`;
29
42
  fs.appendFileSync(LOG_FILE, logMessage);
30
- console.error(message);
43
+ logger.debug(message);
31
44
  }
32
45
 
33
46
  /**
34
47
  * 共通CLAUDE.MD設定を取得(オプショナル)
35
48
  * エラーが発生してもnullを返して処理を継続
49
+ * @param {string} token - CLI認証トークン
50
+ * @returns {Promise<string|null>} 共通設定文字列またはnull
36
51
  */
37
52
  async function getGlobalConfig(token) {
38
53
  try {
@@ -82,6 +97,9 @@ async function getGlobalConfig(token) {
82
97
 
83
98
  /**
84
99
  * Portal APIから認証付きでプロンプトを取得
100
+ * @param {string} keyword - 検索キーワード(例: "@要件定義")
101
+ * @param {string} token - CLI認証トークン
102
+ * @returns {Promise<{success: boolean, knowledge?: string, title?: string, tags?: string[], error?: string}>}
85
103
  */
86
104
  async function getPromptFromPortal(keyword, token) {
87
105
  try {
@@ -89,7 +107,7 @@ async function getPromptFromPortal(keyword, token) {
89
107
 
90
108
  if (!token) {
91
109
  log('[portal-api-client] No authentication token provided');
92
- return null;
110
+ return { success: false, error: '認証トークンが設定されていません。bluelamp login コマンドでログインしてください。' };
93
111
  }
94
112
 
95
113
  // キーワードをそのまま使用
@@ -117,7 +135,16 @@ async function getPromptFromPortal(keyword, token) {
117
135
  log(`[portal-api-client] Portal API error: ${response.status}`);
118
136
  const errorText = await response.text();
119
137
  log(`[portal-api-client] Error response: ${errorText}`);
120
- return null;
138
+ let errorMessage = `Portal APIエラー (HTTP ${response.status})`;
139
+ try {
140
+ const errorData = JSON.parse(errorText);
141
+ if (errorData.message) {
142
+ errorMessage = errorData.message;
143
+ }
144
+ } catch (e) {
145
+ // JSONパースエラーは無視
146
+ }
147
+ return { success: false, error: errorMessage };
121
148
  }
122
149
 
123
150
  const data = await response.json();
@@ -125,7 +152,7 @@ async function getPromptFromPortal(keyword, token) {
125
152
 
126
153
  if (!data.success) {
127
154
  log(`[portal-api-client] API returned success: false`);
128
- return null;
155
+ return { success: false, error: data.message || 'APIがエラーを返しました' };
129
156
  }
130
157
 
131
158
  // 直接プロンプトデータを取得(検索不要)
@@ -133,7 +160,7 @@ async function getPromptFromPortal(keyword, token) {
133
160
 
134
161
  if (!prompt) {
135
162
  log(`[portal-api-client] No prompt found for keyword: ${keyword}`);
136
- return null;
163
+ return { success: false, error: `キーワード "${keyword}" に対応するプロンプトが見つかりませんでした` };
137
164
  }
138
165
 
139
166
  log(`[portal-api-client] Found prompt: ${prompt.title}`);
@@ -202,8 +229,8 @@ async function getPromptFromPortal(keyword, token) {
202
229
  } catch (error) {
203
230
  log(`[portal-api-client] FATAL ERROR in getPromptFromPortal: ${error.message}`);
204
231
  log(`[portal-api-client] Error stack: ${error.stack}`);
205
- console.error('Failed to get prompt from Portal:', error);
206
- return null;
232
+ logger.error(`Failed to get prompt from Portal: ${error.message}`);
233
+ return { success: false, error: `Portal API通信エラー: ${error.message}` };
207
234
  }
208
235
  }
209
236