bluelamp 3.0.8 → 4.0.0

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 (138) hide show
  1. package/README.md +68 -12
  2. package/bin/bluelamp-base +145 -330
  3. package/bin/bluelamp-hook +33 -0
  4. package/bin/bluelamp1 +2 -0
  5. package/bin/bluelamp10 +1 -373
  6. package/bin/bluelamp11 +1 -373
  7. package/bin/bluelamp12 +1 -373
  8. package/bin/bluelamp13 +1 -373
  9. package/bin/bluelamp14 +1 -373
  10. package/bin/bluelamp15 +1 -373
  11. package/bin/bluelamp16 +1 -373
  12. package/bin/bluelamp17 +1 -373
  13. package/bin/bluelamp18 +1 -373
  14. package/bin/bluelamp2 +1 -373
  15. package/bin/bluelamp3 +1 -373
  16. package/bin/bluelamp4 +1 -373
  17. package/bin/bluelamp5 +1 -373
  18. package/bin/bluelamp6 +1 -373
  19. package/bin/bluelamp7 +1 -373
  20. package/bin/bluelamp8 +1 -373
  21. package/bin/bluelamp9 +1 -373
  22. package/bin/docs/SCOPE_PROGRESS.md +222 -0
  23. package/lib/agents//343/203/226/343/203/253/343/203/274/343/203/251/343/203/263/343/203/227.md +106 -0
  24. package/lib/auth/InteractiveLogin.js +243 -0
  25. package/lib/auth/PortalAuthClient.js +187 -0
  26. package/lib/auth/TokenManager.js +258 -0
  27. package/lib/mcp-server/fetch-prompt.js +61 -0
  28. package/lib/mcp-server/index.cjs +164 -0
  29. package/lib/mcp-server/portal-api-client.cjs +210 -0
  30. package/package.json +24 -108
  31. package/scripts/build-release.js +426 -0
  32. package/scripts/generate-commands.js +40 -0
  33. package/scripts/setup-hook.js +98 -0
  34. package/bin/bluelamp +0 -374
  35. package/bin/bluelamp100 +0 -374
  36. package/bin/bluelamp19 +0 -374
  37. package/bin/bluelamp20 +0 -374
  38. package/bin/bluelamp21 +0 -374
  39. package/bin/bluelamp22 +0 -374
  40. package/bin/bluelamp23 +0 -374
  41. package/bin/bluelamp24 +0 -374
  42. package/bin/bluelamp25 +0 -374
  43. package/bin/bluelamp26 +0 -374
  44. package/bin/bluelamp27 +0 -374
  45. package/bin/bluelamp28 +0 -374
  46. package/bin/bluelamp29 +0 -374
  47. package/bin/bluelamp30 +0 -374
  48. package/bin/bluelamp31 +0 -374
  49. package/bin/bluelamp32 +0 -374
  50. package/bin/bluelamp33 +0 -374
  51. package/bin/bluelamp34 +0 -374
  52. package/bin/bluelamp35 +0 -374
  53. package/bin/bluelamp36 +0 -374
  54. package/bin/bluelamp37 +0 -374
  55. package/bin/bluelamp38 +0 -374
  56. package/bin/bluelamp39 +0 -374
  57. package/bin/bluelamp40 +0 -374
  58. package/bin/bluelamp41 +0 -374
  59. package/bin/bluelamp42 +0 -374
  60. package/bin/bluelamp43 +0 -374
  61. package/bin/bluelamp44 +0 -374
  62. package/bin/bluelamp45 +0 -374
  63. package/bin/bluelamp46 +0 -374
  64. package/bin/bluelamp47 +0 -374
  65. package/bin/bluelamp48 +0 -374
  66. package/bin/bluelamp49 +0 -374
  67. package/bin/bluelamp50 +0 -374
  68. package/bin/bluelamp51 +0 -374
  69. package/bin/bluelamp52 +0 -374
  70. package/bin/bluelamp53 +0 -374
  71. package/bin/bluelamp54 +0 -374
  72. package/bin/bluelamp55 +0 -374
  73. package/bin/bluelamp56 +0 -374
  74. package/bin/bluelamp57 +0 -374
  75. package/bin/bluelamp58 +0 -374
  76. package/bin/bluelamp59 +0 -374
  77. package/bin/bluelamp60 +0 -374
  78. package/bin/bluelamp61 +0 -374
  79. package/bin/bluelamp62 +0 -374
  80. package/bin/bluelamp63 +0 -374
  81. package/bin/bluelamp64 +0 -374
  82. package/bin/bluelamp65 +0 -374
  83. package/bin/bluelamp66 +0 -374
  84. package/bin/bluelamp67 +0 -374
  85. package/bin/bluelamp68 +0 -374
  86. package/bin/bluelamp69 +0 -374
  87. package/bin/bluelamp70 +0 -374
  88. package/bin/bluelamp71 +0 -374
  89. package/bin/bluelamp72 +0 -374
  90. package/bin/bluelamp73 +0 -374
  91. package/bin/bluelamp74 +0 -374
  92. package/bin/bluelamp75 +0 -374
  93. package/bin/bluelamp76 +0 -374
  94. package/bin/bluelamp77 +0 -374
  95. package/bin/bluelamp78 +0 -374
  96. package/bin/bluelamp79 +0 -374
  97. package/bin/bluelamp80 +0 -374
  98. package/bin/bluelamp81 +0 -374
  99. package/bin/bluelamp82 +0 -374
  100. package/bin/bluelamp83 +0 -374
  101. package/bin/bluelamp84 +0 -374
  102. package/bin/bluelamp85 +0 -374
  103. package/bin/bluelamp86 +0 -374
  104. package/bin/bluelamp87 +0 -374
  105. package/bin/bluelamp88 +0 -374
  106. package/bin/bluelamp89 +0 -374
  107. package/bin/bluelamp90 +0 -374
  108. package/bin/bluelamp91 +0 -374
  109. package/bin/bluelamp92 +0 -374
  110. package/bin/bluelamp93 +0 -374
  111. package/bin/bluelamp94 +0 -374
  112. package/bin/bluelamp95 +0 -374
  113. package/bin/bluelamp96 +0 -374
  114. package/bin/bluelamp97 +0 -374
  115. package/bin/bluelamp98 +0 -374
  116. package/bin/bluelamp99 +0 -374
  117. package/config/claude-config-template.json +0 -13
  118. package/lib/mcp-server/dist/InteractiveLogin.js +0 -27
  119. package/lib/mcp-server/dist/PortalAuthClient.js +0 -1
  120. package/lib/mcp-server/dist/TokenManager.js +0 -20
  121. package/lib/mcp-server/dist/bluelamp-system.js +0 -32
  122. package/lib/mcp-server/dist/crypto-utils.js +0 -27
  123. package/lib/mcp-server/dist/database-version.js +0 -33
  124. package/lib/mcp-server/dist/index.js +0 -62
  125. package/lib/mcp-server/dist/plugins/base-plugin.js +0 -24
  126. package/lib/mcp-server/dist/plugins/plugin-manager.js +0 -31
  127. package/lib/mcp-server/dist/plugins/services/leonardo-plugin.js +0 -95
  128. package/lib/mcp-server/dist/plugins/services/leonardo-prompt-parser.js +0 -36
  129. package/lib/mcp-server/dist/plugins/services/portal-api-client.js +0 -22
  130. package/lib/mcp-server/dist/plugins/services/portal-plugin.js +0 -52
  131. package/lib/mcp-server/dist/secure-mcp-server.js +0 -76
  132. package/lib/mcp-server/dist/security/ApiKeyManager.js +0 -24
  133. package/lib/mcp-server/dist/security/InteractiveLogin.js +0 -32
  134. package/lib/mcp-server/dist/security/PortalAuthClient.js +0 -1
  135. package/lib/mcp-server/dist/security/SimpleAuthManager.js +0 -1
  136. package/lib/mcp-server/dist/security/SlotAuthClient.js +0 -9
  137. package/lib/mcp-server/dist/security/TokenManager.js +0 -25
  138. package/lib/mcp-server/package.json +0 -21
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict"
3
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
4
- var s=Object.getOwnPropertyDescriptor(t,r)
5
- s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,s)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
6
- for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
7
- return t},e(t)}
8
- return function(t){if(t&&t.__esModule)return t
9
- var r={}
10
- if(null!=t)for(var n=e(t),s=0;s<n.length;s++)"default"!==n[s]&&__createBinding(r,t,n[s])
11
- return __setModuleDefault(r,t),r}}()
12
- Object.defineProperty(exports,"__esModule",{value:!0})
13
- const index_js_1=require("@modelcontextprotocol/sdk/server/index.js"),stdio_js_1=require("@modelcontextprotocol/sdk/server/stdio.js"),types_js_1=require("@modelcontextprotocol/sdk/types.js"),plugin_manager_js_1=require("./plugins/plugin-manager.js")
14
- function debugLog(e,t){}class SampleMCPServer{constructor(){this.server=new index_js_1.Server({name:"bluelamp-mcp-server",version:"1.2.0"},{capabilities:{tools:{},resources:{}}}),this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(types_js_1.ListResourcesRequestSchema,async()=>(debugLog("リソース一覧要求"),{resources:[]})),this.server.setRequestHandler(types_js_1.ReadResourceRequestSchema,async e=>{const{uri:t}=e.params
15
- throw debugLog("リソース読み取り要求",{uri:t}),new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest,"リソースが見つかりません: "+t)}),this.server.setRequestHandler(types_js_1.ListToolsRequestSchema,async()=>{debugLog("ツール一覧要求")
16
- const e=[{name:"get_current_time",description:"現在の日時を取得します",inputSchema:{type:"object",properties:{timezone:{type:"string",description:"タイムゾーン (例: Asia/Tokyo)",default:"Asia/Tokyo"}},required:[]}},{name:"calculate",description:"数学的な計算を実行します",inputSchema:{type:"object",properties:{expression:{type:"string",description:"計算式 (例: 2 + 3 * 4)"}},required:["expression"]}},{name:"echo",description:"メッセージをそのまま返します",inputSchema:{type:"object",properties:{message:{type:"string",description:"返すメッセージ"}},required:["message"]}},{name:"inject_knowledge",description:"Portal APIから専門知識を注入します",inputSchema:{type:"object",properties:{keyword:{type:"string",description:"注入する知識のキーワード",enum:["オーケストレーター","要件定義質問テンプレート","要件定義","デザイナー","デザイン設計","UIUX","本番環境準備ガイドテンプレート","データ設計","デプロイ","GitHub","実装計画","プロトタイプ","検証","バックエンド","総合テスト","テスター","フロントエンド","認証追加テンプレート","ブルーランプ","ディレクトリ構造"]},context:{type:"string",description:"追加のコンテキスト情報"},token:{type:"string",description:"Portal APIトークン(省略時は自動取得)",default:"auto"}},required:["keyword"]}}]
17
- let t=[]
18
- try{plugin_manager_js_1.pluginManager&&(t=plugin_manager_js_1.pluginManager.getAvailableTools(),debugLog(`プラグインツール取得完了: ${t.length}個`))}catch(e){debugLog("プラグインツール取得エラー",e)}const r=[...e,...t]
19
- return debugLog(`全ツール数: ${r.length} (基本: ${e.length}, プラグイン: ${t.length})`),{tools:r}}),this.server.setRequestHandler(types_js_1.CallToolRequestSchema,async e=>{const{name:name,arguments:t}=e.params
20
- debugLog("ツール実行要求: "+name,t)
21
- try{switch(name){case"get_current_time":return await this.handleGetCurrentTime(t||{})
22
- case"calculate":return await this.handleCalculate(t||{})
23
- case"echo":return await this.handleEcho(t||{})
24
- case"inject_knowledge":return await this.handleInjectKnowledge(t||{})}const e=await this.handlePluginTool(name,t)
25
- if(e)return e
26
- throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound,"不明なツール: "+name)}catch(e){if(debugLog("ツール実行エラー",{name:name,error:e.message}),e instanceof types_js_1.McpError)throw e
27
- throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"ツール実行中にエラーが発生しました: "+e.message)}})}async handleGetCurrentTime(e){const{timezone:t="Asia/Tokyo"}=e
28
- debugLog("現在時刻取得",{timezone:t})
29
- try{const e=(new Date).toLocaleString("ja-JP",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),r={type:"text",text:`現在の日時: ${e} (${t})`}
30
- return debugLog("現在時刻取得完了",{timeString:e,timezone:t}),{content:[r]}}catch(e){throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"時刻取得エラー: "+e.message)}}async handleCalculate(e){const{expression:t}=e
31
- if(!t)throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams,"計算式が指定されていません")
32
- debugLog("計算実行",{expression:t})
33
- try{const e=t.replace(/[^0-9+\-*/().\s]/g,"")
34
- if(e!==t)throw Error("無効な文字が含まれています")
35
- const r=Function(`"use strict"; return (${e})`)(),n={type:"text",text:`計算結果: ${t} = ${r}`}
36
- return debugLog("計算完了",{expression:t,result:r}),{content:[n]}}catch(e){throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams,"計算エラー: "+e.message)}}async handleEcho(e){const{message:t}=e
37
- if(!t)throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams,"メッセージが指定されていません")
38
- debugLog("エコー実行",{message:t})
39
- const r={type:"text",text:"エコー: "+t}
40
- return debugLog("エコー完了",{message:t}),{content:[r]}}async handleInjectKnowledge(e){const{keyword:keyword,token:token="auto"}=e
41
- if(!keyword)throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams,"キーワードが指定されていません")
42
- debugLog("Knowledge Injection実行",{keyword:keyword,token:token}),Date.now()
43
- try{const{spawn:e}=await Promise.resolve().then(()=>__importStar(require("child_process"))),t="/Users/tatsuya/Desktop/bluelamp-test/knowledge-injection/hooks/inject-encrypted.sh",r={...process.env}
44
- "auto"!==token&&(r.PORTAL_TOKEN=token),r.KNOWLEDGE_KEYWORD=keyword,debugLog("スクリプト実行開始",{scriptPath:t,keyword:keyword})
45
- const n=e("bash",[t],{env:r,stdio:["pipe","pipe","pipe"]})
46
- let s="",o=""
47
- n.stdout.on("data",e=>{s+=e.toString()}),n.stderr.on("data",e=>{o+=e.toString()})
48
- const a=await new Promise(e=>{n.on("close",e)})
49
- if(debugLog("スクリプト実行完了",{exitCode:a,stdout:s.substring(0,200),stderr:o.substring(0,200)}),Date.now(),0===a)return{content:[{type:"text",text:`Knowledge Injection成功: "${keyword}" の知識が注入されました。\n\n実行結果:\n${s}\n\n統計記録: ⚠️ スキップ`}]}
50
- throw Error(`スクリプト実行失敗 (exit code: ${a})\nstderr: ${o}`)}catch(e){throw debugLog("Knowledge Injectionエラー",{keyword:keyword,error:e.message}),new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"Knowledge Injection実行エラー: "+e.message)}}async handlePluginTool(e,t){try{if(!plugin_manager_js_1.pluginManager)return null
51
- if(!plugin_manager_js_1.pluginManager.getAvailableTools().find(t=>t.name===e))return null
52
- debugLog("プラグインツール実行: "+e,t)
53
- const r={userId:"current_user",service:"leonardo",apiKey:process.env.LEONARDO_API_KEY,settings:{}}
54
- let n="leonardo"
55
- e.startsWith("leonardo_")?n="leonardo":e.startsWith("notion_")?n="notion":e.startsWith("slack_")&&(n="slack")
56
- const s=await plugin_manager_js_1.pluginManager.executePlugin(n,e,t,r)
57
- if(s.success)return debugLog("プラグインツール実行成功: "+e),{content:s.content,_meta:s.metadata}
58
- throw debugLog("プラグインツール実行失敗: "+e,s.error),new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"プラグインツール実行エラー: "+s.error)}catch(t){if(debugLog("プラグインツール処理エラー: "+e,t),t instanceof types_js_1.McpError)throw t
59
- throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"プラグイン処理中にエラーが発生しました: "+t.message)}}async run(){debugLog("MCPサーバー開始")
60
- try{await plugin_manager_js_1.pluginManager.initialize(),debugLog("プラグインマネージャー初期化完了")}catch(e){debugLog("プラグインマネージャー初期化エラー",e)}const e=new stdio_js_1.StdioServerTransport
61
- await this.server.connect(e),debugLog("MCPサーバー接続完了")}}const server=new SampleMCPServer
62
- server.run().catch(e=>{process.exit(1)})
@@ -1,24 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,s){void 0===s&&(s=i)
3
- var n=Object.getOwnPropertyDescriptor(t,i)
4
- n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,s,n)}:function(e,t,i,s){void 0===s&&(s=i),e[s]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[t.length]=i)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var i={}
9
- if(null!=t)for(var s=e(t),n=0;n<s.length;n++)"default"!==s[n]&&__createBinding(i,t,s[n])
10
- return __setModuleDefault(i,t),i}}()
11
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.PluginLoader=exports.BasePlugin=void 0
12
- const zod_1=require("zod")
13
- class BasePlugin{constructor(){this._initialized=!1,this._credentials=new Map}get isInitialized(){return this._initialized}markInitialized(){this._initialized=!0}validateArgs(e,t){try{return t.parse(e)}catch(e){if(e instanceof zod_1.z.ZodError){const t=e.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ")
14
- throw Error("引数の検証に失敗しました: "+t)}throw e}}async getCredentials(e){const t=`${e}-${this.manifest.id}`
15
- if(this._credentials.has(t))return this._credentials.get(t)
16
- const i=await this.fetchCredentialsFromPortal(e)
17
- return this._credentials.set(t,i),i}async fetchCredentialsFromPortal(e){const t=process.env[this.manifest.id.toUpperCase()+"_API_KEY"]
18
- return{userId:e,service:this.manifest.id,apiKey:t,settings:{}}}async recordUsage(e,t,i,s,n){const a={userId:t,pluginId:this.manifest.id,toolName:e,executionTime:s,success:i,timestamp:new Date,metadata:n}
19
- await this.sendStatsToPortal(a)}async sendStatsToPortal(e){}handleError(e,t){return{success:!1,error:`${t}: ${e?.message||e+""}`,metadata:{errorCode:e?.code||"UNKNOWN_ERROR",pluginId:this.manifest.id,timestamp:(new Date).toISOString()}}}createSuccessResponse(e,t){return{success:!0,content:e,metadata:{pluginId:this.manifest.id,timestamp:(new Date).toISOString(),...t}}}supportsTool(e){return this.manifest.tools.some(t=>t.name===e)}async healthCheck(){try{return this.isInitialized?(await this.performHealthCheck(),{status:"healthy",details:{initialized:!0,toolCount:this.manifest.tools.length,version:this.manifest.version}}):{status:"unhealthy",message:"プラグインが初期化されていません"}}catch(e){return{status:"unhealthy",message:"ヘルスチェックに失敗しました: "+e,details:{error:e+""}}}}async performHealthCheck(){}}exports.BasePlugin=BasePlugin
20
- class PluginLoader{constructor(){this.loadedPlugins=new Map}static getInstance(){return PluginLoader.instance||(PluginLoader.instance=new PluginLoader),PluginLoader.instance}async loadPlugin(e){try{if(this.loadedPlugins.has(e))return this.loadedPlugins.get(e)
21
- const t=await Promise.resolve(`./services/${e}-plugin.js`).then(e=>__importStar(require(e))),i=new(t.default||t[Object.keys(t)[0]])
22
- return await i.initialize(),this.loadedPlugins.set(e,i),i}catch(e){return null}}async unloadPlugin(e){const t=this.loadedPlugins.get(e)
23
- t&&(await t.shutdown(),this.loadedPlugins.delete(e))}async unloadAllPlugins(){const e=Array.from(this.loadedPlugins.keys()).map(e=>this.unloadPlugin(e))
24
- await Promise.all(e)}getLoadedPlugins(){return Array.from(this.loadedPlugins.keys())}}exports.PluginLoader=PluginLoader
@@ -1,31 +0,0 @@
1
- "use strict"
2
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.pluginManager=exports.PluginManager=void 0
3
- const base_plugin_js_1=require("./base-plugin.js")
4
- class PluginManager{constructor(e={}){this.pluginCache=new Map,this.pluginStats=new Map,this.executionQueue=[],this.isProcessingQueue=!1,this.initialized=!1,this.manifestRegistry=new Map,this.config={maxLoadedPlugins:100,pluginTimeoutMs:3e5,maxConcurrentExecution:50,healthCheckIntervalMs:6e4,portalBaseUrl:process.env.PORTAL_URL||"http://localhost:8080",...e},this.pluginLoader=base_plugin_js_1.PluginLoader.getInstance()}async initialize(){this.initialized||(await this.loadPluginManifests(),this.startHealthCheckTimer(),this.startExecutionQueueProcessor(),this.initialized=!0)}async loadPluginManifests(){try{const e=await this.getBuiltinManifests()
5
- for(const t of e)this.manifestRegistry.set(t.id,t),this.pluginStats.set(t.id,{pluginId:t.id,loadTime:0,totalExecutions:0,successfulExecutions:0,failedExecutions:0,averageExecutionTime:0,lastExecuted:new Date(0),healthStatus:"healthy"})}catch(e){throw e}}async getBuiltinManifests(){return[{id:"leonardo",name:"Leonardo AI",version:"1.0.0",category:"AI",description:"Leonardo AIによる高品質な画像生成",authType:"api_key",loadPriority:"high",tools:[{name:"leonardo_generate",description:"Leonardo AIで画像を生成します",inputSchema:{type:"object",properties:{prompt:{type:"string",description:"画像生成のプロンプト"},width:{type:"number",description:"画像の幅(512-2048)",default:1024},height:{type:"number",description:"画像の高さ(512-2048)",default:1024},num_images:{type:"number",description:"生成する画像数(1-8)",default:1},modelId:{type:"string",description:"Leonardo AIのモデルID(省略時はデフォルト)"},negativePrompt:{type:"string",description:"ネガティブプロンプト"},photoReal:{type:"boolean",description:"フォトリアル画像の生成",default:!1},alchemy:{type:"boolean",description:"Alchemy v2の使用",default:!0},guidance_scale:{type:"number",description:"ガイダンススケール(1-30)",default:7},outputPath:{type:"string",description:"保存先ディレクトリ(省略時: ./outputs)"}},required:["prompt"]},outputExample:{success:!0,content:[{type:"text",text:"✅ Leonardo AIで1枚の画像を生成しました\\n📁 保存先: ./outputs/leonardo_20250830_001.png"}]}}]},{id:"portal",name:"Portal Integration",version:"1.0.0",category:"Integration",description:"Portal APIとの統合機能(エージェント委譲、知識注入、認証管理)",authType:"token",loadPriority:"high",tools:[{name:"delegate_to_agent",description:"専門エージェントにタスクを委譲します。動的スロット解決により適切なオーケストレーターに接続します。",inputSchema:{type:"object",properties:{agentName:{type:"string",description:"エージェント名(orchestrator, orchestrator2など)"},token:{type:"string",description:"認証トークン(オプション、自動取得される)"}},required:["agentName"]},outputExample:{success:!0,content:[{type:"text",text:"✅ orchestrator2 にタスクを委譲しました\\n🔗 エンドポイント: https://orchestrator-slot2.example.com"}]}},{name:"inject_knowledge",description:"Portal APIから専門知識を注入します。キーワードに基づいて関連する知識ベースからコンテンツを取得します。",inputSchema:{type:"object",properties:{keyword:{type:"string",description:"検索キーワード"},context:{type:"string",description:"追加コンテキスト(オプション)"},level:{type:"string",description:"知識の詳細レベル",default:"detailed"}},required:["keyword"]},outputExample:{success:!0,content:[{type:"text",text:"🧠 専門知識を注入しました\\n🔍 キーワード: React\\n📚 知識内容: Reactは..."}]}},{name:"save_knowledge",description:"暗号化された知識を保存します",inputSchema:{type:"object",properties:{knowledge:{type:"string",description:"保存する知識内容"},identifier:{type:"string",description:"知識の識別子"},token:{type:"string",description:"認証トークン"}},required:["knowledge","identifier","token"]},outputExample:{success:!0,content:[{type:"text",text:"💾 知識を暗号化して保存しました"}]}},{name:"list_prompts",description:"利用可能な暗号化プロンプトテンプレートを一覧表示します",inputSchema:{type:"object",properties:{category:{type:"string",description:"カテゴリフィルター(オプション)"},token:{type:"string",description:"認証トークン"}},required:["token"]},outputExample:{success:!0,content:[{type:"text",text:"📋 利用可能なプロンプト: システムアーキテクト, UI/UXデザイナー, 実装エージェント"}]}},{name:"get_debug_log_path",description:"デバッグログファイルのパスを取得します",inputSchema:{type:"object",properties:{},required:[]},outputExample:{success:!0,content:[{type:"text",text:"Debug log path: /tmp/portal-debug-123456.log"}]}}]}]}async executePlugin(e,t,i,s){return this.manifestRegistry.has(e)?new Promise((n,a)=>{const o={id:this.generateTaskId(),pluginId:e,toolName:t,args:i,userCredentials:s,resolve:n,reject:a,createdAt:new Date}
6
- this.executionQueue.push(o),this.isProcessingQueue||setImmediate(()=>this.processExecutionQueue())}):{success:!1,error:`プラグイン '${e}' が見つかりません`}}async processExecutionQueue(){if(!this.isProcessingQueue){this.isProcessingQueue=!0
7
- try{for(;this.executionQueue.length>0;){const e=Math.min(this.config.maxConcurrentExecution,this.executionQueue.length),t=this.executionQueue.splice(0,e).map(e=>this.executeTask(e))
8
- await Promise.allSettled(t)}}finally{this.isProcessingQueue=!1}}}async executeTask(e){const t=Date.now()
9
- let i
10
- try{const s=await this.getOrLoadPlugin(e.pluginId)
11
- if(!s)throw Error(`プラグイン '${e.pluginId}' の読み込みに失敗しました`)
12
- i=await s.executeTool(e.toolName,e.args,e.userCredentials),this.recordExecution(e.pluginId,!0,Date.now()-t),e.resolve(i)}catch(s){this.recordExecution(e.pluginId,!1,Date.now()-t),i={success:!1,error:"プラグイン実行エラー: "+s,metadata:{pluginId:e.pluginId,toolName:e.toolName,error:s+""}},e.resolve(i)}}async getOrLoadPlugin(e){const t=this.pluginCache.get(e)
13
- if(t)return t.lastUsed=new Date,t.usageCount++,t.plugin
14
- this.pluginCache.size>=this.config.maxLoadedPlugins&&await this.evictLeastUsedPlugin()
15
- const i=Date.now(),s=await this.pluginLoader.loadPlugin(e)
16
- if(s){this.pluginCache.set(e,{plugin:s,lastUsed:new Date,usageCount:1})
17
- const t=this.pluginStats.get(e)
18
- t&&(t.loadTime=Date.now()-i)}return s}async evictLeastUsedPlugin(){let e=null,t=Date.now()
19
- for(const[i,s]of this.pluginCache)s.lastUsed.getTime()<t&&(t=s.lastUsed.getTime(),e=i)
20
- if(e){const t=this.pluginCache.get(e)
21
- t&&(await t.plugin.shutdown(),this.pluginCache.delete(e))}}recordExecution(e,t,i){const s=this.pluginStats.get(e)
22
- s&&(s.totalExecutions++,s.lastExecuted=new Date,t?s.successfulExecutions++:s.failedExecutions++,s.averageExecutionTime=(s.averageExecutionTime*(s.totalExecutions-1)+i)/s.totalExecutions)}startHealthCheckTimer(){this.healthCheckTimer=setInterval(async()=>{await this.performHealthChecks()},this.config.healthCheckIntervalMs)}startExecutionQueueProcessor(){setInterval(()=>{this.executionQueue.length>0&&!this.isProcessingQueue&&this.processExecutionQueue()},100)}async performHealthChecks(){const e=[]
23
- for(const[t,i]of this.pluginCache)e.push(this.checkPluginHealth(t,i.plugin))
24
- await Promise.allSettled(e)}async checkPluginHealth(e,t){try{const i=await t.healthCheck(),s=this.pluginStats.get(e)
25
- s&&(s.healthStatus=i.status),i.status}catch(t){const i=this.pluginStats.get(e)
26
- i&&(i.healthStatus="unhealthy")}}getAvailableTools(){const e=[]
27
- for(const t of this.manifestRegistry.values())for(const i of t.tools)e.push({name:i.name,description:i.description,inputSchema:i.inputSchema})
28
- return e}getPluginStats(){return Array.from(this.pluginStats.values())}async shutdown(){this.healthCheckTimer&&clearInterval(this.healthCheckTimer)
29
- const e=[]
30
- for(const[t,i]of this.pluginCache)e.push(i.plugin.shutdown())
31
- await Promise.allSettled(e),this.pluginCache.clear()}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}getPluginManifest(e){return this.manifestRegistry.get(e)}getRegisteredPlugins(){return Array.from(this.manifestRegistry.keys())}}exports.PluginManager=PluginManager,exports.pluginManager=new PluginManager
@@ -1,95 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,o,a){void 0===a&&(a=o)
3
- var r=Object.getOwnPropertyDescriptor(t,o)
4
- r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,a,r)}:function(e,t,o,a){void 0===a&&(a=o),e[a]=t[o]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[t.length]=o)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var o={}
9
- if(null!=t)for(var a=e(t),r=0;r<a.length;r++)"default"!==a[r]&&__createBinding(o,t,a[r])
10
- return __setModuleDefault(o,t),o}}(),__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
11
- Object.defineProperty(exports,"__esModule",{value:!0})
12
- const sdk_1=require("@leonardo-ai/sdk"),zod_1=require("zod"),fs=__importStar(require("fs/promises")),path=__importStar(require("path")),node_fetch_1=__importDefault(require("node-fetch")),sharp_1=__importDefault(require("sharp")),base_plugin_js_1=require("../base-plugin.js"),SimpleAuthManager_js_1=require("../../security/SimpleAuthManager.js"),leonardo_prompt_parser_js_1=require("./leonardo-prompt-parser.js"),LeonardoAnimateSchema=zod_1.z.object({folderPath:zod_1.z.string().default("./outputs").describe("画像が保存されているフォルダパス"),pattern:zod_1.z.string().default("*.png").describe("対象ファイルのパターン(例: *.png, leonardo_*.png)"),motionStrength:zod_1.z.number().int().min(1).max(10).default(5).describe("動きの強さ(1:穏やか~10:激しい)"),fileLimit:zod_1.z.number().int().min(1).max(10).optional().describe("処理する画像の最大数"),sortBy:zod_1.z.enum(["newest","oldest","name"]).default("newest").describe("ファイルの並び順"),outputPath:zod_1.z.string().default("./outputs/videos").describe("動画の保存先"),isPublic:zod_1.z.boolean().default(!1).describe("生成した動画を公開するか")}),LeonardoGenerateSchema=zod_1.z.object({prompt:zod_1.z.string().min(1,"プロンプトは必須です"),width:zod_1.z.number().int().min(512).max(2048).default(1024),height:zod_1.z.number().int().min(512).max(2048).default(1024),num_images:zod_1.z.number().int().min(1).max(8).default(1),modelId:zod_1.z.string().optional(),negativePrompt:zod_1.z.string().optional(),photoReal:zod_1.z.boolean().default(!1),photoRealVersion:zod_1.z.enum(["v1","v2"]).default("v2"),alchemy:zod_1.z.boolean().default(!0),guidance_scale:zod_1.z.number().min(1).max(30).default(7),seed:zod_1.z.number().int().optional(),steps:zod_1.z.number().int().min(30).max(60).default(50),contrast:zod_1.z.number().min(1).max(4.5).default(1),outputPath:zod_1.z.string().default("./outputs"),presetStyle:zod_1.z.enum(["CINEMATIC","DYNAMIC","ENVIRONMENTAL","GENERAL","ILLUSTRATION","PHOTOGRAPHY","RAYTRACED","RENDER_3D","SKETCH_BW","SKETCH_COLOR","VIBRANT"]).optional()})
13
- class LeonardoPlugin extends base_plugin_js_1.BasePlugin{constructor(){super(...arguments),this.manifest={id:"leonardo",name:"Leonardo AI",version:"1.0.0",category:"AI",description:"Leonardo AIによる高品質な画像生成。PhotoReal、Alchemy v2対応",authType:"api_key",loadPriority:"high",tools:[{name:"leonardo_generate",description:"Leonardo AIで高品質な画像を生成します。プロンプトに基づいて1-8枚の画像を作成し、指定されたフォルダに保存します。",inputSchema:LeonardoGenerateSchema,outputExample:{success:!0,content:[{type:"text",text:"✅ Leonardo AIで2枚の画像を生成しました\\n📁 保存先:\\n- ./outputs/leonardo_20250830_001.png\\n- ./outputs/leonardo_20250830_002.png"}]}},{name:"leonardo_animate",description:"フォルダ内の画像をLeonardo AI Motion 1.0で動画化します。画像をアップロードして動きを追加し、MP4形式で保存します。",inputSchema:LeonardoAnimateSchema,outputExample:{success:!0,content:[{type:"text",text:"🎬 3枚の画像を動画化しました\\n📁 保存先:\\n- ./outputs/videos/motion_20250830_001.mp4\\n- ./outputs/videos/motion_20250830_002.mp4\\n- ./outputs/videos/motion_20250830_003.mp4"}]}}]},this.availableModels=[]}async initialize(){try{this.availableModels=await this.getDefaultModels(),this.markInitialized()}catch(e){throw e}}async shutdown(){this.leonardo=void 0}async executeTool(e,t,o){if(!this.isInitialized)return this.handleError("プラグインが初期化されていません","executeTool")
14
- switch(e){case"leonardo_generate":return await this.generateImage(t,o)
15
- case"leonardo_animate":return await this.animateImages(t,o)
16
- default:return this.handleError("未知のツール: "+e,"executeTool")}}async generateImage(e,t){const o=Date.now()
17
- try{const a=this.validateArgs(e,LeonardoGenerateSchema),r=leonardo_prompt_parser_js_1.LeonardoPromptParser.parsePrompt(a.prompt),n=this.mergeSettings(r,a)
18
- if(leonardo_prompt_parser_js_1.LeonardoPromptParser.validateSettings(n).length,await this.initializeLeonardoClient(t),!this.leonardo)return this.handleError("Leonardo AI クライアントの初期化に失敗","generateImage")
19
- await this.ensureOutputDirectory(n.outputPath||"./outputs")
20
- const i=await this.requestGeneration(n),s=await this.waitForGeneration(i.generationId)
21
- if("FAILED"===s.status)return this.handleError("画像生成に失敗しました","generateImage")
22
- if(!s.images||0===s.images.length)return this.handleError("生成された画像が見つかりません","generateImage")
23
- const d=await this.downloadAndSaveImages(s.images,n.outputPath||"./outputs"),l=Date.now()-o
24
- return await this.recordUsage("leonardo_generate",t.userId,!0,l,{imageCount:d.length,prompt:n.cleanPrompt,modelId:n.modelId,parsedFromPrompt:!0}),this.createSuccessResponse([{type:"text",text:`✅ Leonardo AIで${d.length}枚の画像を生成しました\n📝 設定: ${n.modelName||"デフォルト"} / ${n.width}x${n.height}\n📁 保存先:\n${d.map(e=>"- "+e).join("\n")}`}],{generationId:s.id,imageCount:d.length,executionTimeMs:l,savedFiles:d,parsedSettings:{model:n.modelName,size:`${n.width}x${n.height}`,style:n.presetStyle}})}catch(e){const a=Date.now()-o
25
- return await this.recordUsage("leonardo_generate",t.userId,!1,a,{error:e+""}),this.handleError(e,"generateImage")}}mergeSettings(e,t){return{prompt:e.cleanPrompt||t.prompt,width:t.width||e.width||1024,height:t.height||e.height||1024,num_images:t.num_images||e.num_images||1,modelId:t.modelId||e.modelId,modelName:e.modelName,photoReal:void 0!==t.photoReal?t.photoReal:e.photoReal,photoRealVersion:t.photoRealVersion||e.photoRealVersion||"v2",presetStyle:t.presetStyle||e.presetStyle,alchemy:void 0!==t.alchemy?t.alchemy:void 0===e.alchemy||e.alchemy,guidance_scale:t.guidance_scale||e.guidanceScale||7,steps:t.steps||e.steps||50,contrast:t.contrast||e.contrast||1,negativePrompt:t.negativePrompt,seed:t.seed,outputPath:t.outputPath,originalPrompt:t.prompt,cleanPrompt:e.cleanPrompt}}async initializeLeonardoClient(e){if(this.leonardo)return
26
- let t=e.apiKey
27
- if(!t)try{const e=await SimpleAuthManager_js_1.SimpleAuthManager.getToken()
28
- if(e){const o=await(0,node_fetch_1.default)("http://localhost:8080/api/cli/user-credentials/leonardo-ai",{method:"GET",headers:{"X-CLI-Token":e,"Content-Type":"application/json"}})
29
- if(o.ok){const e=await o.json()
30
- e.success&&e.data&&e.data.apiKey&&(t=e.data.apiKey)}}}catch(e){}if(t||(t=process.env.LEONARDO_API_KEY),!t)throw Error("Leonardo AI APIキーが取得できません。bluelamp loginを実行してください。")
31
- this.leonardo=new sdk_1.Leonardo({bearerAuth:t})}async requestGeneration(e){if(!this.leonardo)throw Error("Leonardo AIクライアントが初期化されていません")
32
- try{const t={prompt:e.prompt,width:e.width||1024,height:e.height||1024,numImages:e.num_images||1,guidanceScale:e.guidance_scale||7,alchemy:!1!==e.alchemy}
33
- e.modelId&&(t.modelId=e.modelId),e.negativePrompt&&(t.negativePrompt=e.negativePrompt),e.photoReal&&(t.photoReal=!0,t.photoRealVersion=e.photoRealVersion||"v2"),e.seed&&(t.seed=e.seed),e.steps&&(t.numInferenceSteps=e.steps),e.presetStyle&&(t.presetStyle=e.presetStyle)
34
- const o=await this.leonardo.image.createGeneration(t),a=o?.object?.sdGenerationJob?.generationId
35
- if(!a)throw Error("生成IDが取得できませんでした")
36
- return{generationId:a}}catch(e){throw Error("Leonardo AI API エラー: "+(e.message||e))}}async waitForGeneration(e){if(!this.leonardo)throw Error("Leonardo AIクライアントが初期化されていません")
37
- let t=0
38
- for(;t<30;)try{const o=await this.leonardo.image.getGenerationById(e),a=o?.object?.generationsByPk
39
- if("COMPLETE"===a?.status)return{id:e,status:"COMPLETE",images:a.generatedImages?.map(e=>({id:e.id||"",url:e.url||"",likelyGuid:e.likelyGuid||""}))}
40
- if("FAILED"===a?.status)return{id:e,status:"FAILED"}
41
- await new Promise(e=>setTimeout(e,1e4)),t++}catch(e){if(t++,t>=30)throw Error("生成確認の最大試行回数を超えました: "+e)
42
- await new Promise(e=>setTimeout(e,5e3))}throw Error("生成がタイムアウトしました。Leonardo AIのサーバーが混雑している可能性があります。")}async downloadAndSaveImages(e,t){const o=[],a=new Date,r=a.toISOString().replace(/[:\-]/g,"").replace("T","_").replace(/\..+/,""),n=`${a.getTime()}_${Math.random().toString(36).substring(2,8)}`
43
- for(let a=0;a<e.length;a++){const i=e[a]
44
- try{const e=await(0,node_fetch_1.default)(i.url)
45
- if(!e.ok)throw Error(`ダウンロード失敗: ${e.status} ${e.statusText}`)
46
- const s=Buffer.from(await e.arrayBuffer()),d=`leonardo_${r}_${n}_${i.id?i.id.substring(0,8):""}_${(a+1+"").padStart(2,"0")}.png`,l=path.join(t,d)
47
- await(0,sharp_1.default)(s).png({quality:95,compressionLevel:6}).toFile(l),o.push(l)}catch(e){}}if(0===o.length)throw Error("画像の保存に全て失敗しました")
48
- return o}async ensureOutputDirectory(e){try{await fs.mkdir(e,{recursive:!0})}catch(t){throw Error(`出力ディレクトリの作成に失敗: ${e} - ${t}`)}}async getDefaultModels(){return[{id:"6bef9f1b-29cb-40c7-b9df-32b51c1f67d3",name:"Leonardo Phoenix",description:"2024年リリースの最新モデル。高いプロンプト忠実度と詳細なテキスト生成が特徴",supportsAlchemy:!0},{id:"aa77f04e-3eec-4034-9c07-d0f619684628",name:"Leonardo Diffusion XL",description:"SDXL基盤の高品質汎用モデル",supportsPhotoReal:!0,supportsAlchemy:!0},{id:"1e60896f-3c26-4296-8ecc-53e2afecc132",name:"Leonardo Kino XL",description:"シネマティック品質の画像生成に特化",supportsPhotoReal:!0,supportsAlchemy:!0},{id:"5c232a9e-9061-4777-980a-ddc8e65647c6",name:"Leonardo Vision XL",description:"フォトリアルな画像生成に最適化",supportsPhotoReal:!0,supportsAlchemy:!0}]}async performHealthCheck(){const e={userId:"health_check",service:"leonardo",apiKey:process.env.LEONARDO_API_KEY}
49
- if(!e.apiKey)throw Error("Leonardo AI APIキーが設定されていません")
50
- try{new sdk_1.Leonardo({bearerAuth:e.apiKey})}catch(e){throw Error("Leonardo AI接続テストに失敗: "+e)}}async animateImages(e,t){const o=Date.now()
51
- try{const a=this.validateArgs(e,LeonardoAnimateSchema)
52
- if(await this.initializeLeonardoClient(t),!this.leonardo)return this.handleError("Leonardo AI クライアントの初期化に失敗","animateImages")
53
- const r=await this.findImageFiles(a.folderPath,a.pattern,a.sortBy,a.fileLimit)
54
- if(0===r.length)return this.handleError(`${a.folderPath}に対象画像が見つかりません(パターン: ${a.pattern})`,"animateImages")
55
- await this.ensureOutputDirectory(a.outputPath)
56
- const n=[],i=[]
57
- for(let e=0;e<r.length;e++){const t=r[e]
58
- try{const e=await this.uploadImageToLeonardo(t),o=await this.requestMotionGeneration(e,a.motionStrength,a.isPublic),r=await this.waitForMotionGeneration(o),i=await this.downloadVideo(r,a.outputPath,t)
59
- n.push(i)}catch(e){const o=`❌ ${path.basename(t)}: ${e}`
60
- i.push(o)}}const s=Date.now()-o
61
- return await this.recordUsage("leonardo_animate",t.userId,n.length>0,s,{processedImages:r.length,generatedVideos:n.length,errors:i.length}),0===n.length?this.handleError("すべての動画生成に失敗しました","animateImages"):this.createSuccessResponse([{type:"text",text:`🎬 ${n.length}/${r.length}個の動画を生成しました\n📁 保存先:\n${n.map(e=>"- "+e).join("\n")}${i.length>0?"\n\n⚠️ エラー:\n"+i.join("\n"):""}`}],{processedImages:r.length,generatedVideos:n.length,executionTimeMs:s,savedFiles:n})}catch(e){const a=Date.now()-o
62
- return await this.recordUsage("leonardo_animate",t.userId,!1,a,{error:e+""}),this.handleError(e,"animateImages")}}async findImageFiles(e,t,o,a){const r=(await Promise.resolve().then(()=>__importStar(require("glob")))).glob,n=path.join(e,t),i=await r(n,{nodir:!0,absolute:!0})
63
- if(0===i.length)return[]
64
- const s=await Promise.all(i.map(async e=>({path:e,stat:await fs.stat(e)})))
65
- return s.sort((e,t)=>{switch(o){case"newest":return t.stat.mtime.getTime()-e.stat.mtime.getTime()
66
- case"oldest":return e.stat.mtime.getTime()-t.stat.mtime.getTime()
67
- default:return e.path.localeCompare(t.path)}}),(a?s.slice(0,a):s).map(e=>e.path)}async uploadImageToLeonardo(e){if(!this.leonardo)throw Error("Leonardo AIクライアントが初期化されていません")
68
- const t=await fs.readFile(e),o=path.basename(e),a=await this.leonardo.image.uploadInitImage({extension:path.extname(o).substring(1)})
69
- if(!a.object?.uploadInitImage?.url||!a.object?.uploadInitImage?.id)throw Error("アップロードURL取得に失敗しました")
70
- const{url:r,id:n}=a.object.uploadInitImage,i=await(0,node_fetch_1.default)(r,{method:"PUT",body:t,headers:{"Content-Type":"image/png"}})
71
- if(!i.ok)throw Error("画像アップロード失敗: "+i.status)
72
- return n}async requestMotionGeneration(e,t,o){if(!this.leonardo)throw Error("Leonardo AIクライアントが初期化されていません")
73
- const a=await this.getLeonardoApiKey(),r=await(0,node_fetch_1.default)("https://cloud.leonardo.ai/api/rest/v1/generations-motion-svd",{method:"POST",headers:{Authorization:"Bearer "+a,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({imageId:e,motionStrength:t,isInitImage:!0,isPublic:o})})
74
- if(!r.ok){const e=await r.text()
75
- throw Error(`Motion生成リクエスト失敗: ${r.status} - ${e}`)}const n=await r.json()
76
- if(!n.motionSvdGenerationJob?.generationId)throw Error("Motion生成IDが取得できませんでした")
77
- return n.motionSvdGenerationJob.generationId}async waitForMotionGeneration(e){let t=0
78
- const o=await this.getLeonardoApiKey()
79
- for(;t<60;)try{const a=await(0,node_fetch_1.default)("https://cloud.leonardo.ai/api/rest/v1/generations/"+e,{method:"GET",headers:{Authorization:"Bearer "+o,Accept:"application/json"}})
80
- if(!a.ok)throw Error("生成状況確認失敗: "+a.status)
81
- const r=(await a.json()).generationsByPk
82
- if("COMPLETE"===r?.status){const e=r.generatedVideos?.[0]
83
- if(e?.url)return e.url
84
- throw Error("動画URLが見つかりません")}if("FAILED"===r?.status)throw Error("動画生成に失敗しました")
85
- await new Promise(e=>setTimeout(e,1e4)),t++}catch(e){if(t++,t>=60)throw Error("生成確認の最大試行回数を超えました: "+e)
86
- await new Promise(e=>setTimeout(e,5e3))}throw Error("動画生成がタイムアウトしました")}async getLeonardoApiKey(){if(this.leonardo){const e=this.leonardo.config
87
- if(e?.bearerAuth)return e.bearerAuth}try{const e=await SimpleAuthManager_js_1.SimpleAuthManager.getToken()
88
- if(e){const t=await(0,node_fetch_1.default)("http://localhost:8080/api/cli/user-credentials/leonardo-ai",{method:"GET",headers:{"X-CLI-Token":e,"Content-Type":"application/json"}})
89
- if(t.ok){const e=await t.json()
90
- if(e.success&&e.data?.apiKey)return e.data.apiKey}}}catch(e){}const e=process.env.LEONARDO_API_KEY
91
- if(e)return e
92
- throw Error("Leonardo AI APIキーが取得できません。bluelamp loginを実行してください。")}async downloadVideo(e,t,o){const a=await(0,node_fetch_1.default)(e)
93
- if(!a.ok)throw Error("動画ダウンロード失敗: "+a.status)
94
- const r=Buffer.from(await a.arrayBuffer()),n=(new Date).toISOString().replace(/[:\-]/g,"").replace("T","_").replace(/\..+/,""),i=`motion_${path.basename(o,path.extname(o))}_${n}.mp4`,s=path.join(t,i)
95
- return await fs.writeFile(s,r),s}}exports.default=LeonardoPlugin
@@ -1,36 +0,0 @@
1
- "use strict"
2
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.LeonardoPromptParser=exports.ASPECT_RATIOS=exports.PRESET_STYLES=exports.LEONARDO_MODELS=void 0,exports.LEONARDO_MODELS={phoenix:{id:"6bef9f1b-29cb-40c7-b9df-32b51c1f67d3",name:"Leonardo Phoenix",keywords:["phoenix","フェニックス","最新","latest"],supportsAlchemy:!0,supportsPhotoReal:!1},vision_xl:{id:"5c232a9e-9061-4777-980a-ddc8e65647c6",name:"Leonardo Vision XL",keywords:["vision","ビジョン","フォトリアル","photorealistic","リアル","写真"],supportsAlchemy:!0,supportsPhotoReal:!0},diffusion_xl:{id:"aa77f04e-3eec-4034-9c07-d0f619684628",name:"Leonardo Diffusion XL",keywords:["diffusion","ディフュージョン","汎用","general","バランス"],supportsAlchemy:!0,supportsPhotoReal:!0},kino_xl:{id:"1e60896f-3c26-4296-8ecc-53e2afecc132",name:"Leonardo Kino XL",keywords:["kino","キノ","映画","cinematic","シネマ","movie","film"],supportsAlchemy:!0,supportsPhotoReal:!0,preferredAspectRatio:"21:9"},anime_xl:{id:"e71a1c2f-4f80-4800-934f-2c68979d8cc8",name:"Leonardo Anime XL",keywords:["anime","アニメ","manga","マンガ","漫画","cartoon","illustration"],supportsAlchemy:!0,supportsPhotoReal:!1},lightning_xl:{id:"b24e16ff-06e3-43eb-8aec-8ab3166edcb6",name:"Leonardo Lightning XL",keywords:["lightning","ライトニング","高速","fast","quick","rapid","速い"],supportsAlchemy:!1,supportsPhotoReal:!1}},exports.PRESET_STYLES={cinematic:{value:"CINEMATIC",keywords:["cinematic","シネマティック","映画的","movie","film"],preferredModel:"kino_xl"},dynamic:{value:"DYNAMIC",keywords:["dynamic","ダイナミック","動的","action","motion"],preferredModel:"diffusion_xl"},photography:{value:"PHOTOGRAPHY",keywords:["photography","フォトグラフィー","写真","photo","camera"],preferredModel:"vision_xl"},vibrant:{value:"VIBRANT",keywords:["vibrant","ビブラント","鮮やか","colorful","vivid"]},raytraced:{value:"RAYTRACED",keywords:["raytraced","レイトレース","3D","render","レンダー"]},illustration:{value:"ILLUSTRATION",keywords:["illustration","イラスト","drawing","絵","artwork"]}},exports.ASPECT_RATIOS={"1:1":{keywords:["1:1","正方形","square","スクエア","インスタ","instagram"],width:1024,height:1024},"16:9":{keywords:["16:9","横長","wide","ワイド","youtube","ユーチューブ","HD"],width:1920,height:1080},"9:16":{keywords:["9:16","縦長","portrait","ポートレート","tiktok","ティックトック","stories","ストーリー"],width:1080,height:1920},"4:3":{keywords:["4:3","standard","スタンダード","標準"],width:1024,height:768},"3:4":{keywords:["3:4","縦向き標準"],width:768,height:1024},"2:3":{keywords:["2:3","縦向き","vertical","バーティカル"],width:1024,height:1536},"3:2":{keywords:["3:2","横向き","horizontal","ホリゾンタル"],width:1536,height:1024},"21:9":{keywords:["21:9","ultrawide","ウルトラワイド","cinema","シネマスコープ"],width:2560,height:1080},facebook:{keywords:["facebook","フェイスブック","fb"],width:1200,height:630},twitter:{keywords:["twitter","ツイッター","x"],width:1200,height:675},linkedin:{keywords:["linkedin","リンクトイン"],width:1200,height:627}}
3
- class LeonardoPromptParser{static parsePrompt(e){const t={cleanPrompt:e},o=this.extractAspectRatio(e)
4
- o&&(Object.assign(t,o),t.cleanPrompt=o.cleanPrompt||t.cleanPrompt)
5
- const r=this.extractModel(t.cleanPrompt)
6
- r&&(Object.assign(t,r),t.cleanPrompt=r.cleanPrompt||t.cleanPrompt)
7
- const a=this.extractStyle(t.cleanPrompt)
8
- a&&(Object.assign(t,a),t.cleanPrompt=a.cleanPrompt||t.cleanPrompt)
9
- const i=this.extractQuality(t.cleanPrompt)
10
- i&&(Object.assign(t,i),t.cleanPrompt=i.cleanPrompt||t.cleanPrompt)
11
- const s=this.extractImageCount(t.cleanPrompt)
12
- s&&(Object.assign(t,s),t.cleanPrompt=s.cleanPrompt||t.cleanPrompt)
13
- const c=this.extractPhotoReal(t.cleanPrompt)
14
- return c&&(Object.assign(t,c),t.cleanPrompt=c.cleanPrompt||t.cleanPrompt),t.cleanPrompt=this.cleanupPrompt(t.cleanPrompt),t}static extractAspectRatio(e){let t=e
15
- const o=e.match(/(\d{3,4})\s*[x×]\s*(\d{3,4})/i)
16
- if(o){const e=parseInt(o[1]),r=parseInt(o[2])
17
- return t=t.replace(o[0],"").trim(),{width:e,height:r,cleanPrompt:t}}for(const[o,r]of Object.entries(exports.ASPECT_RATIOS)){const o=r.keywords.join("|"),a=RegExp(`\\b(${o})\\b`,"gi")
18
- if(e.match(a))return t=t.replace(a,"").trim(),{width:r.width,height:r.height,cleanPrompt:t}}return null}static extractModel(e){let t=e
19
- for(const[o,r]of Object.entries(exports.LEONARDO_MODELS))for(const keyword of r.keywords){const a=RegExp(/[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF]/.test(keyword)?keyword:`\\b${keyword}\\b`,"gi")
20
- if(e.match(a))return t=t.replace(a,"").trim(),"vision_xl"===o&&e.match(/photoreal|フォトリアル/gi)?{photoReal:!0,photoRealVersion:"v2",modelId:r.id,modelName:r.name,cleanPrompt:t}:{modelId:r.id,modelName:r.name,cleanPrompt:t}}return null}static extractStyle(e){let t=e
21
- for(const[o,r]of Object.entries(exports.PRESET_STYLES))for(const keyword of r.keywords){const o=RegExp(/[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF]/.test(keyword)?keyword:`\\b${keyword}\\b`,"gi")
22
- if(e.match(o)){t=t.replace(o,"").trim()
23
- const a={presetStyle:r.value,cleanPrompt:t}
24
- if("preferredModel"in r&&r.preferredModel&&!e.match(/model|モデル/gi)){const e=exports.LEONARDO_MODELS[r.preferredModel]
25
- e&&(a.modelId=e.id,a.modelName=e.name)}return a}}return null}static extractQuality(e){let t=e
26
- const o={}
27
- return e.match(/高品質|高画質|最高品質|ultra|high quality|best quality/gi)?(o.steps=60,o.guidanceScale=10,o.alchemy=!0,t=t.replace(/高品質|高画質|最高品質|ultra|high quality|best quality/gi,"").trim()):e.match(/中品質|標準|standard|medium quality/gi)?(o.steps=50,o.guidanceScale=7,o.alchemy=!0,t=t.replace(/中品質|標準|standard|medium quality/gi,"").trim()):e.match(/低品質|ドラフト|draft|quick|fast|低画質/gi)&&(o.steps=30,o.guidanceScale=5,o.alchemy=!1,t=t.replace(/低品質|ドラフト|draft|quick|fast|低画質/gi,"").trim()),e.match(/alchemy|アルケミー|魔法/gi)&&(o.alchemy=!0,t=t.replace(/alchemy|アルケミー|魔法/gi,"").trim()),Object.keys(o).length>0?(o.cleanPrompt=t,o):null}static extractImageCount(e){let t=e
28
- const o=e.match(/(\d+)\s*[枚つ個]/)
29
- if(o){const e=Math.min(parseInt(o[1]),8)
30
- return t=t.replace(o[0],"").trim(),{num_images:e,cleanPrompt:t}}const r=e.match(/(\d+)\s*(images?|pictures?|photos?|pieces?)/i)
31
- if(r){const e=Math.min(parseInt(r[1]),8)
32
- return t=t.replace(r[0],"").trim(),{num_images:e,cleanPrompt:t}}return null}static extractPhotoReal(e){let t=e
33
- return e.match(/photoreal|フォトリアル|写真のような|photorealistic/gi)?(t=t.replace(/photoreal|フォトリアル|写真のような|photorealistic/gi,"").trim(),{photoReal:!0,photoRealVersion:"v2",cleanPrompt:t}):null}static cleanupPrompt(e){return e.replace(/\s+/g," ").replace(/^\s*[,、]\s*/g,"").replace(/\s*[,、]\s*$/g,"").replace(/[,、]\s*[,、]/g,",").replace(/で\s*$/g,"").replace(/を\s*$/g,"").trim()}static validateSettings(e){const t=[]
34
- if(e.photoReal&&e.modelId){const o=Object.values(exports.LEONARDO_MODELS).find(t=>t.id===e.modelId)
35
- o&&!o.supportsPhotoReal&&t.push(`警告: ${o.name}はPhotoRealをサポートしていません`)}if(e.alchemy&&e.modelId){const o=Object.values(exports.LEONARDO_MODELS).find(t=>t.id===e.modelId)
36
- o&&!o.supportsAlchemy&&t.push(`警告: ${o.name}はAlchemyをサポートしていません`)}return e.width&&e.width>2048&&t.push("警告: 幅が2048pxを超えています"),e.height&&e.height>2048&&t.push("警告: 高さが2048pxを超えています"),t}}exports.LeonardoPromptParser=LeonardoPromptParser
@@ -1,22 +0,0 @@
1
- "use strict"
2
- var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}}
3
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.portalAPIClient=exports.PortalAPIClient=void 0
4
- const node_fetch_1=__importDefault(require("node-fetch")),SimpleAuthManager_js_1=require("../../security/SimpleAuthManager.js")
5
- class PortalAPIClient{constructor(){this.baseURL=process.env.BLUELAMP_PORTAL_API_URL||"http://localhost:8080",this.timeout=3e4,this.retryAttempts=3,this.retryDelay=1e3}async getAuthToken(){try{return await SimpleAuthManager_js_1.SimpleAuthManager.getToken()||null}catch(t){return null}}async makeRequest(t,e={}){const token=await this.getAuthToken()
6
- if(!token)throw Error("Portal API: 認証トークンが利用できません")
7
- const a=`${this.baseURL}${t}`,r={method:"GET",headers:{"X-CLI-Token":token,"Content-Type":"application/json","User-Agent":"BlueLamp-MCP-Client/1.0",...e.headers},timeout:this.timeout,...e}
8
- for(let t=1;t<=this.retryAttempts;t++)try{const t=new AbortController,e=setTimeout(()=>t.abort(),this.timeout),s=await(0,node_fetch_1.default)(a,{...r,signal:t.signal})
9
- if(clearTimeout(e),!s.ok){if(401===s.status)throw Error("Portal API: 認証失敗 - 無効なトークン")
10
- if(404===s.status)return null
11
- throw Error(`Portal API: リクエスト失敗 - ${s.status} ${s.statusText}`)}return await s.json()}catch(e){if(t===this.retryAttempts)throw e
12
- await new Promise(e=>setTimeout(e,this.retryDelay*t))}return null}async resolveSlot(t){try{const e="/api/slots/resolve/"+t,a=await this.makeRequest(e)
13
- return a&&a.success?{slotNumber:t,orchestratorEndpoint:a.data.orchestratorEndpoint,configuration:a.data.configuration,status:a.data.status,lastUpdated:a.data.lastUpdated}:null}catch(t){return null}}async getAllSlots(){try{const t="/api/slots/all",e=await this.makeRequest(t)
14
- return e?.data?.slots||[]}catch(t){return[]}}async getUsageStats(){try{const t="/api/usage/stats",e=await this.makeRequest(t)
15
- return e?.data||null}catch(t){return null}}async updateUsage(t,e="orchestrator_call"){try{const a="/api/usage/update",r=await this.makeRequest(a,{method:"POST",body:JSON.stringify({slotNumber:t,operation:e,timestamp:(new Date).toISOString()})})
16
- return r?.success||!1}catch(t){return!1}}async checkFreeUsageAvailable(){try{const t=await this.getUsageStats()
17
- if(!t)return!1
18
- const e=t.freeUsageLimit||3
19
- return(t.totalUsage||0)<e}catch(t){return!1}}async getUserInfo(){try{const t="/api/user/info",e=await this.makeRequest(t)
20
- return e?.data||null}catch(t){return null}}async getServiceCredentials(t){try{const e="/api/cli/user-credentials/"+t,a=await this.makeRequest(e)
21
- return a?.success&&a.data?a.data:null}catch(t){return null}}async injectKnowledge(keyword,t){try{const e="/api/knowledge/inject",a=await this.makeRequest(e,{method:"POST",body:JSON.stringify({keyword:keyword,context:t,level:"detailed"})})
22
- return a?.success&&a.data?{success:!0,knowledge:a.data.knowledge,sources:a.data.sources,confidence:a.data.confidence}:{success:!1,error:"Knowledge injection failed"}}catch(t){return{success:!1,error:"Knowledge injection error: "+t}}}}exports.PortalAPIClient=PortalAPIClient,exports.portalAPIClient=new PortalAPIClient
@@ -1,52 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,a){void 0===a&&(a=r)
3
- var n=Object.getOwnPropertyDescriptor(t,r)
4
- n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,a,n)}:function(e,t,r,a){void 0===a&&(a=r),e[a]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var r={}
9
- if(null!=t)for(var a=e(t),n=0;n<a.length;n++)"default"!==a[n]&&__createBinding(r,t,a[n])
10
- return __setModuleDefault(r,t),r}}()
11
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.DynamicSlotResolver=void 0
12
- const zod_1=require("zod"),fs=__importStar(require("fs/promises")),path=__importStar(require("path")),os=__importStar(require("os")),base_plugin_js_1=require("../base-plugin.js"),SimpleAuthManager_js_1=require("../../security/SimpleAuthManager.js"),portal_api_client_js_1=require("./portal-api-client.js"),DelegateToAgentSchema=zod_1.z.object({agentName:zod_1.z.string().min(1,"エージェント名は必須です"),token:zod_1.z.string().optional()}),InjectKnowledgeSchema=zod_1.z.object({keyword:zod_1.z.string().min(1,"キーワードは必須です"),context:zod_1.z.string().optional(),level:zod_1.z.string().default("detailed")}),SaveKnowledgeSchema=zod_1.z.object({knowledge:zod_1.z.string().min(1,"知識内容は必須です"),identifier:zod_1.z.string().min(1,"識別子は必須です"),token:zod_1.z.string().min(1,"トークンは必須です")}),ListPromptsSchema=zod_1.z.object({category:zod_1.z.string().optional(),token:zod_1.z.string().min(1,"トークンは必須です")})
13
- class DynamicSlotResolver{constructor(){this.cacheTimeout=3e5,this.slotCache=new Map,this.agentSlotMapping={orchestrator:1,orchestrator1:1,orchestrator2:2,orchestrator3:3,orchestrator4:4,orchestrator5:5},this.portalClient=portal_api_client_js_1.portalAPIClient}extractSlotNumber(e){if(!e||"string"!=typeof e)throw Error("Invalid agent name provided")
14
- const t=e.toLowerCase().trim()
15
- if(this.agentSlotMapping[t])return this.agentSlotMapping[t]
16
- const r=t.match(/^orchestrator(\d+)?$/)
17
- if(r)return r[1]?parseInt(r[1],10):1
18
- const a=e.match(/\d+/)
19
- return a?parseInt(a[0],10):1}async getSlotConfiguration(e){const t="slot_"+e,r=this.slotCache.get(t)
20
- if(r&&Date.now()-r.timestamp<this.cacheTimeout)return r.data
21
- try{const r=await this.portalClient.resolveSlot(e)
22
- return this.slotCache.set(t,{data:r,timestamp:Date.now()}),r}catch(e){return null}}async resolveOrchestratorConfig(e){try{const t=this.extractSlotNumber(e),r=await this.getSlotConfiguration(t)
23
- return r?await this.portalClient.checkFreeUsageAvailable()?{success:!0,slotNumber:t,agentName:e,orchestratorEndpoint:r.orchestratorEndpoint,configuration:r.configuration}:{success:!1,error:"Free usage limit exceeded",slotNumber:t,agentName:e,usageExceeded:!0,usageFallback:"Please upgrade to continue using orchestrator features"}:{success:!1,error:`Slot ${t} is not configured in Portal`,slotNumber:t,agentName:e,fallback:this.getFallbackConfig(t)}}catch(t){return{success:!1,error:"Failed to resolve configuration: "+t,agentName:e}}}async delegateToAgent(e){const t=await this.resolveOrchestratorConfig(e)
24
- if(!t.success)return t
25
- try{return await this.portalClient.updateUsage(t.slotNumber,"orchestrator_call"),{success:!0,message:"Successfully delegated to "+e,slotNumber:t.slotNumber,orchestratorEndpoint:t.orchestratorEndpoint,configuration:t.configuration}}catch(t){return{success:!1,error:"Delegation failed: "+t,agentName:e}}}getFallbackConfig(e){return{endpoint:"http://localhost:8080/api/orchestrator/fallback",message:`Slot ${e} not configured, using fallback`,features:["basic_responses","error_handling"]}}}exports.DynamicSlotResolver=DynamicSlotResolver
26
- class PortalPlugin extends base_plugin_js_1.BasePlugin{constructor(){super(...arguments),this.manifest={id:"portal",name:"Portal Integration",version:"1.0.0",category:"Integration",description:"Portal APIとの統合機能を提供(エージェント委譲、知識注入、認証管理)",authType:"token",loadPriority:"high",tools:[{name:"delegate_to_agent",description:"専門エージェントにタスクを委譲します。動的スロット解決により適切なオーケストレーターに接続します。",inputSchema:DelegateToAgentSchema,outputExample:{success:!0,content:[{type:"text",text:"✅ orchestrator2 にタスクを委譲しました\\n🔗 エンドポイント: https://orchestrator-slot2.example.com\\n📊 使用回数を更新しました"}]}},{name:"inject_knowledge",description:"Portal APIから専門知識を注入します。キーワードに基づいて関連する知識ベースからコンテンツを取得します。",inputSchema:InjectKnowledgeSchema,outputExample:{success:!0,content:[{type:"text",text:"🧠 専門知識を注入しました\\n🔍 キーワード: React\\n📚 知識内容: Reactは..."}]}},{name:"save_knowledge",description:"暗号化された知識を保存します。",inputSchema:SaveKnowledgeSchema,outputExample:{success:!0,content:[{type:"text",text:"💾 知識を暗号化して保存しました"}]}},{name:"list_prompts",description:"利用可能な暗号化プロンプトテンプレートを一覧表示します。",inputSchema:ListPromptsSchema,outputExample:{success:!0,content:[{type:"text",text:"📋 利用可能なプロンプト: システムアーキテクト, UI/UXデザイナー, 実装エージェント"}]}}]},this.validTokens=new Set,this.promptCache=new Map,this.cacheTimeout=3e5}async initialize(){try{this.logFilePath=path.join(os.tmpdir(),`portal-debug-${Date.now()}.log`),this.debugLog("Portal Integration Plugin starting - Log file: "+this.logFilePath),this.slotResolver=new DynamicSlotResolver,this.keywordMapping=new Map([["orchestrator","オーケストレーター"],["requirements-engineer","要件定義エンジニア"],["ui-ux-designer","UI/UXデザイナー"],["data-modeling-engineer","データモデリングエンジニア"],["system-architect","システムアーキテクト"],["implementation-consultant","実装コンサルタント"],["environment-setup","環境構築"],["prototype-implementation","プロトタイプ実装"],["implementation-agent","実装エージェント"],["debug-agent","デバッグエージェント"],["deploy-specialist","デプロイスペシャリスト"],["page-creator","ページクリエイター"],["refactoring-engineer","リファクタリングエンジニア"],["ai-friendliness-diagnostic","AI親和性診断"]]),await this.initializeTokens(),this.markInitialized()}catch(e){throw e}}async shutdown(){this.validTokens.clear(),this.promptCache.clear()}async executeTool(e,t,r){if(!this.isInitialized)return this.handleError("プラグインが初期化されていません","executeTool")
27
- this.debugLog("Tool called: "+e,t)
28
- try{switch(e){case"delegate_to_agent":return await this.handleDelegateToAgent(t)
29
- case"inject_knowledge":return await this.handleInjectKnowledge(t)
30
- case"save_knowledge":return await this.handleSaveKnowledge(t)
31
- case"list_prompts":return await this.handleListPrompts(t)
32
- case"get_debug_log_path":return this.handleGetDebugLogPath()
33
- default:return this.handleError("未知のツール: "+e,"executeTool")}}catch(e){return this.handleError(e,"executeTool")}}async handleDelegateToAgent(e){try{const t=this.validateArgs(e,DelegateToAgentSchema),token=await this.getSystemToken()
34
- if(!token||!this.validateToken(token))return this.createErrorResponse("システム認証に失敗しました","SYSTEM_AUTH_ERROR")
35
- this.debugLog("Delegating to agent: "+t.agentName)
36
- const r=await this.slotResolver.delegateToAgent(t.agentName)
37
- if(!r.success){this.debugLog(`Delegation failed for ${t.agentName}:`,r)
38
- const e=r.usageExceeded?"USAGE_EXCEEDED":"SLOT_RESOLUTION_FAILED"
39
- return this.createErrorResponse(r.error||"エージェント委譲に失敗しました",e,{agentName:t.agentName,slotNumber:r.slotNumber,fallback:r.fallback||r.usageFallback})}return this.createSuccessResponse([{type:"text",text:`✅ ${t.agentName} にタスクを委譲しました\n🔗 エンドポイント: ${r.orchestratorEndpoint}\n📊 スロット番号: ${r.slotNumber}\n⏰ 使用回数を更新しました`}],{agentName:t.agentName,slotNumber:r.slotNumber,orchestratorEndpoint:r.orchestratorEndpoint,success:!0})}catch(e){return this.handleError(e,"handleDelegateToAgent")}}async handleInjectKnowledge(e){try{const t=this.validateArgs(e,InjectKnowledgeSchema),token=await this.getSystemToken()
40
- if(!token||!this.validateToken(token))return this.createErrorResponse("システム認証に失敗しました","SYSTEM_AUTH_ERROR")
41
- const r=`${t.keyword}:${t.level}`,a=this.promptCache.get(r)
42
- let n,o="unknown"
43
- if(a&&Date.now()-a.timestamp<this.cacheTimeout)n=a.content,o=a.source||"cache",this.debugLog("Using cached knowledge for "+t.keyword)
44
- else{const e=await portal_api_client_js_1.portalAPIClient.injectKnowledge(t.keyword,t.context)
45
- if(!e.success)return this.createErrorResponse(e.error||"知識注入に失敗しました","KNOWLEDGE_INJECTION_FAILED")
46
- n=e.knowledge,o="portal_api",this.promptCache.set(r,{content:n,timestamp:Date.now(),source:o}),this.debugLog("Knowledge injected from Portal API for "+t.keyword)}return this.createSuccessResponse([{type:"text",text:`🧠 専門知識を注入しました\n🔍 キーワード: ${t.keyword}\n📚 ソース: ${o}\n📖 知識内容: ${n||"知識が見つかりませんでした"}`}],{keyword:t.keyword,source:o,knowledgeContent:n,cached:"cache"===o})}catch(e){return this.handleError(e,"handleInjectKnowledge")}}async handleSaveKnowledge(e){try{const t=this.validateArgs(e,SaveKnowledgeSchema)
47
- return this.validateToken(t.token)?this.createSuccessResponse([{type:"text",text:`💾 知識を暗号化して保存しました\n🔑 識別子: ${t.identifier}\n📝 サイズ: ${t.knowledge.length} 文字`}],{identifier:t.identifier,saved:!0}):this.createErrorResponse("無効な認証トークンです","AUTH_ERROR")}catch(e){return this.handleError(e,"handleSaveKnowledge")}}async handleListPrompts(e){try{const t=this.validateArgs(e,ListPromptsSchema)
48
- if(!this.validateToken(t.token))return this.createErrorResponse("無効な認証トークンです","AUTH_ERROR")
49
- const r=Array.from(this.keywordMapping.entries()).map(([e,name])=>({key:e,name:name})),a=r.map(e=>`- ${e.name} (${e.key})`).join("\n")
50
- return this.createSuccessResponse([{type:"text",text:`📋 利用可能なプロンプトテンプレート:\n${a}\n\n💡 inject_knowledge ツールで任意のキーワードを使用して専門知識を取得できます。`}],{availablePrompts:r,count:r.length})}catch(e){return this.handleError(e,"handleListPrompts")}}handleGetDebugLogPath(){return this.createSuccessResponse([{type:"text",text:JSON.stringify({success:!0,logPath:this.logFilePath,message:"Debug log is being written to: "+this.logFilePath})}],{logPath:this.logFilePath})}async getSystemToken(){try{return await SimpleAuthManager_js_1.SimpleAuthManager.getToken()}catch(e){return this.debugLog("Failed to get system token:",e),null}}validateToken(token){return this.validTokens.has(token)}async initializeTokens(){try{const token=await this.getSystemToken()
51
- token&&(this.validTokens.add(token),this.debugLog(`System token initialized: ${token.substring(0,30)}...`))}catch(e){this.debugLog("Token initialization failed:",e)}}debugLog(e,t){const r=(new Date).toISOString(),a=t?`[${r}] ${e}\n${JSON.stringify(t,null,2)}\n`:`[${r}] ${e}\n`
52
- try{fs.appendFile(this.logFilePath,a).catch(()=>{})}catch(e){}}createErrorResponse(e,t,r){return this.createSuccessResponse([{type:"text",text:JSON.stringify({success:!1,error:e,code:t,...r})}],{success:!1,error:e,code:t,...r})}async performHealthCheck(){try{if(!await portal_api_client_js_1.portalAPIClient.getUserInfo())throw Error("Portal API接続テストに失敗しました")}catch(e){throw Error("Portal API接続テストに失敗: "+e)}}}exports.default=PortalPlugin
@@ -1,76 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
3
- var o=Object.getOwnPropertyDescriptor(t,r)
4
- o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var r={}
9
- if(null!=t)for(var n=e(t),o=0;o<n.length;o++)"default"!==n[o]&&__createBinding(r,t,n[o])
10
- return __setModuleDefault(r,t),r}}()
11
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.SecureMCPServer=void 0
12
- const index_js_1=require("@modelcontextprotocol/sdk/server/index.js"),stdio_js_1=require("@modelcontextprotocol/sdk/server/stdio.js"),types_js_1=require("@modelcontextprotocol/sdk/types.js"),crypto_utils_js_1=require("./crypto-utils.js"),fs=__importStar(require("fs")),path=__importStar(require("path")),os=__importStar(require("os")),plugin_manager_js_1=require("./plugins/plugin-manager.js")
13
- class SecureMCPServer{constructor(){this.cacheTimeout=3e5,this.server=new index_js_1.Server({name:"secure-bluelamp-mcp",version:"3.0.0"},{capabilities:{tools:{}}}),this.validTokens=new Set,this.promptCache=new Map,this.encryptionKey=process.env.BLUELAMP_ENCRYPTION_KEY||"demo-encryption-password-2024",this.keywordMapping=new Map([["orchestrator","オーケストレーター"],["requirements-engineer","要件定義エンジニア"],["ui-ux-designer","UI/UXデザイナー"],["data-modeling-engineer","データモデリングエンジニア"],["system-architect","システムアーキテクト"],["implementation-consultant","実装コンサルタント"],["environment-setup","環境構築"],["prototype-implementation","プロトタイプ実装"],["implementation-agent","実装エージェント"],["debug-agent","デバッグエージェント"],["deploy-specialist","デプロイスペシャリスト"],["page-creator","ページクリエイター"],["refactoring-engineer","リファクタリングエンジニア"],["ai-friendliness-diagnostic","AI親和性診断"]]),this.logFilePath=path.join(os.tmpdir(),`bluelamp-debug-${Date.now()}.log`),this.debugLog("BlueLamp MCP Server starting - Log file: "+this.logFilePath),this.initializeTokensSync(),this.setupHandlers()}debugLog(e,t){const r=(new Date).toISOString(),n=t?`[${r}] ${e}\n${JSON.stringify(t,null,2)}\n`:`[${r}] ${e}\n`
14
- try{fs.appendFileSync(this.logFilePath,n)}catch(e){}}initializeTokensSync(){try{const e=process.env.BLUELAMP_TOKEN
15
- e&&this.validTokens.add(e),this.loadCLITokenFromFile(),this.validTokens.add("secure-token-2024"),this.debugLog("Total valid tokens: "+this.validTokens.size)}catch(e){this.validTokens.add("secure-token-2024"),this.debugLog("Token initialization error:",e)}}loadCLITokenFromFile(){this.loadCLITokenAsync()}async loadCLITokenAsync(){try{const e=await Promise.resolve().then(()=>__importStar(require("path"))),t=(await Promise.resolve().then(()=>__importStar(require("url"))),e.dirname(__filename)),r=e.dirname(e.dirname(e.dirname(t))),n=e.join(r,"lib/mcp-server/dist/security"),o=await Promise.resolve(`file://${n}/SimpleAuthManager.js`).then(e=>__importStar(require(e))),token=await o.SimpleAuthManager.getToken()
16
- token&&token.startsWith("cli_")&&(this.validTokens.add(token),this.debugLog(`Loaded CLI token from SimpleAuthManager: ${token.substring(0,20)}...`))}catch(e){this.debugLog("CLI token loading error:",e)}}async getSystemToken(){try{const e=process.env.BLUELAMP_TOKEN
17
- if(e&&this.validTokens.has(e))return e
18
- const t=await Promise.resolve().then(()=>__importStar(require("path"))),r=(await Promise.resolve().then(()=>__importStar(require("url"))),t.dirname(__filename)),n=t.dirname(t.dirname(t.dirname(r))),o=t.join(n,"lib/mcp-server/dist/security")
19
- try{const e=await Promise.resolve(`file://${o}/SimpleAuthManager.js`).then(e=>__importStar(require(e))),token=await e.SimpleAuthManager.getToken()
20
- if(token&&token.startsWith("cli_"))return token}catch(e){this.debugLog("Failed to load token from SimpleAuthManager:",e)}for(const token of this.validTokens)if(token.startsWith("cli_"))return token
21
- return"secure-token-2024"}catch(e){return this.debugLog("System token retrieval error:",e),"secure-token-2024"}}setupHandlers(){this.server.setRequestHandler(types_js_1.ListToolsRequestSchema,async()=>{const e=[{name:"inject_knowledge",description:"Inject specialized knowledge from Portal API",inputSchema:{type:"object",properties:{keyword:{type:"string",description:"Keyword to search for specialized knowledge"},context:{type:"string",description:"Additional context"},level:{type:"string",description:"Knowledge detail level"}},required:["keyword","context"]}},{name:"save_knowledge",description:"Save knowledge to encrypted storage",inputSchema:{type:"object",properties:{knowledge:{type:"string",description:"Knowledge content to save (encrypted)"},identifier:{type:"string",description:"Unique identifier for the knowledge"},token:{type:"string",description:"Authentication token for access"}},required:["knowledge","identifier","token"]}},{name:"list_prompts",description:"List available encrypted prompt templates",inputSchema:{type:"object",properties:{token:{type:"string",description:"Authentication token for access"},category:{type:"string",description:"Filter by category (optional)"}},required:["token"]}},{name:"delegate_to_agent",description:"Delegate task to specialized sub-agent with knowledge injection",inputSchema:{type:"object",properties:{agentName:{type:"string",description:"Name of the target agent"},token:{type:"string",description:"Authentication token for access"}},required:["agentName","token"]}},{name:"get_debug_log_path",description:"Get the path to the debug log file",inputSchema:{type:"object",properties:{},required:[]}}]
22
- let t=[]
23
- try{plugin_manager_js_1.pluginManager&&(t=plugin_manager_js_1.pluginManager.getAvailableTools(),this.debugLog(`プラグインツール取得完了: ${t.length}個`))}catch(e){this.debugLog("プラグインツール取得エラー",e)}const r=[...e,...t]
24
- return this.debugLog(`全ツール数: ${r.length} (基本: ${e.length}, プラグイン: ${t.length})`),{tools:r}}),this.server.setRequestHandler(types_js_1.CallToolRequestSchema,async e=>{const{name:t,arguments:r}=e.params
25
- this.debugLog("Tool called: "+t),this.debugLog("Tool args:",r)
26
- try{switch(t){case"inject_knowledge":return this.debugLog("Calling handleInjectKnowledge"),await this.handleInjectKnowledge(r)
27
- case"save_knowledge":return await this.handleSaveKnowledge(r)
28
- case"list_prompts":return await this.handleListPrompts(r)
29
- case"delegate_to_agent":return await this.handleDelegateToAgent(r)
30
- case"get_debug_log_path":return{content:[{type:"text",text:JSON.stringify({success:!0,logPath:this.logFilePath,message:"Debug log is being written to: "+this.logFilePath})}]}
31
- default:const e=await this.handlePluginTool(t,r)
32
- if(e)return e
33
- throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound,"Unknown tool: "+t)}}catch(e){if(e instanceof types_js_1.McpError)throw e
34
- throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError,`Tool execution failed: ${t}: ${e}`)}})}validateToken(token){return this.validTokens.has(token)}async fetchFromPortalAPI(keyword,token){try{const e=`${process.env.BLUELAMP_PORTAL_API_URL||"https://bluelamp-portal-6clpzmy5pa-an.a.run.app/api/cli/prompts/knowledge-injection"}/${encodeURIComponent(keyword)}`
35
- this.debugLog("Portal API request:",{url:e,token:token.substring(0,20)+"...",keyword:keyword})
36
- const t=new AbortController,r=setTimeout(()=>t.abort(),3e4),n=await fetch(e,{method:"GET",headers:{"X-CLI-Token":token,"Content-Type":"application/json","User-Agent":"BlueLamp-MCP-Server/1.0"},signal:t.signal})
37
- if(clearTimeout(r),this.debugLog("Portal API response status: "+n.status),!n.ok){if(this.debugLog(`Portal API error: ${n.status} ${n.statusText}`),401===n.status)return this.debugLog("Authentication failed - token may be invalid"),null
38
- if(404===n.status)return this.debugLog("Knowledge not found for keyword: "+keyword),null
39
- throw Error(`Portal API error: ${n.status} ${n.statusText}`)}const o=await n.text()
40
- return this.debugLog("Portal API raw response:",o.substring(0,200)+"..."),o&&o.trim()?o.trim():(this.debugLog("Empty response from Portal API"),null)}catch(e){return null}}async handleInjectKnowledge(e){this.debugLog("Received args:",e),this.debugLog("Valid tokens: "+Array.from(this.validTokens).map(e=>e.substring(0,30)+"...").join(", "))
41
- let token=await this.getSystemToken()
42
- if(this.debugLog(`Using system token: ${token?.substring(0,30)}...`),!token||!this.validateToken(token))return this.debugLog("System authentication failed"),{content:[{type:"text",text:JSON.stringify({success:!1,error:"System authentication failed",code:"SYSTEM_AUTH_ERROR"})}]}
43
- try{const t=`${e.keyword}:${e.level}`,r=this.promptCache.get(t)
44
- let n,o="unknown"
45
- if(r&&Date.now()-r.timestamp<this.cacheTimeout)n=r.content,o=r.source||"cache"
46
- else{const r=path.join(process.cwd(),"lib/knowledge","encrypted",e.keyword+".enc")
47
- if(fs.existsSync(r))try{n=crypto_utils_js_1.CryptoUtils.decryptFile(r,this.encryptionKey),o="local"}catch(t){const r=await this.fetchFromPortalAPI(e.keyword,token)
48
- if(!r)return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Portal APIから知識を取得できませんでした: "+e.keyword,code:"KNOWLEDGE_NOT_FOUND"})}]}
49
- n=r,o="api"}else{this.debugLog("Fetching from Portal API for keyword: "+e.keyword)
50
- const t=await this.fetchFromPortalAPI(e.keyword,token)
51
- if(this.debugLog("Portal API result:",{keyword:e.keyword,resultExists:!!t,resultType:typeof t,resultLength:t?t.length:0}),!t)return this.debugLog("Portal API returned null for keyword: "+e.keyword),{content:[{type:"text",text:JSON.stringify({success:!1,error:"専門知識が見つかりませんでした: "+e.keyword,code:"KNOWLEDGE_NOT_FOUND"})}]}
52
- n=t,o="api"}this.promptCache.set(t,{content:n,timestamp:Date.now(),source:o})}const s=this.buildResponse(n,token)
53
- return{content:[{type:"text",text:JSON.stringify({success:!0,result:s,keyword:e.keyword,token:token.substring(0,20)+"...",cached:"cache"===o,source:o,timestamp:(new Date).toISOString()})}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:"知識注入処理中にエラーが発生しました: "+e,code:"INJECTION_ERROR"})}]}}}buildResponse(e,token){return this.debugLog("buildResponse called with content length: "+(e?e.length:0)),{content:[{type:"text",text:e}]}}async handleSaveKnowledge(e){if(!this.validateToken(e.token))return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Invalid authentication token",code:"AUTH_ERROR"})}]}
54
- try{const t=path.join(process.cwd(),"lib/knowledge","encrypted")
55
- fs.existsSync(t)||fs.mkdirSync(t,{recursive:!0})
56
- const r=path.join(t,e.identifier+".enc")
57
- return crypto_utils_js_1.CryptoUtils.encryptFile(e.knowledge,r,this.encryptionKey),{content:[{type:"text",text:JSON.stringify({success:!0,message:"Knowledge saved successfully",outputPath:r,size:fs.statSync(r).size})}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Knowledge save failed: "+e,code:"SAVE_ERROR"})}]}}}async handleListPrompts(e){if(!this.validateToken(e.token))return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Invalid authentication token",code:"AUTH_ERROR"})}]}
58
- try{const t=path.join(process.cwd(),"lib/knowledge","encrypted"),r=path.join(t,"prompt-registry.json")
59
- if(!fs.existsSync(r))return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Prompt registry not found",code:"REGISTRY_NOT_FOUND"})}]}
60
- const n=JSON.parse(fs.readFileSync(r,"utf8"))
61
- let o=n.prompts
62
- return e.category&&(o=o.filter(t=>t.category===e.category)),{content:[{type:"text",text:JSON.stringify({success:!0,totalCount:o.length,prompts:o,categories:n.categories,lastUpdated:n.lastUpdated})}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Failed to list prompts: "+e,code:"LIST_ERROR"})}]}}}async handleDelegateToAgent(e){if(!this.validateToken(e.token))return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Invalid authentication token",code:"AUTH_ERROR"})}]}
63
- try{const t=path.join(process.cwd(),"lib/knowledge","agents",e.agentName+".agent")
64
- if(!fs.existsSync(t))return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Agent script not found: "+e.agentName,code:"AGENT_NOT_FOUND"})}]}
65
- const r=JSON.parse(fs.readFileSync(t,"utf8")),n=path.join(process.cwd(),"lib/knowledge","encrypted"),o=path.join(n,e.agentName+".enc"),s=fs.existsSync(o)
66
- return{content:[{type:"text",text:JSON.stringify({success:!0,agentName:e.agentName,agentData:r,hasKnowledge:s,knowledgeSize:s?fs.statSync(o).size:0})}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:"Agent delegation failed: "+e,code:"DELEGATION_ERROR"})}]}}}startCacheCleanup(){}async handlePluginTool(e,t){try{if(!plugin_manager_js_1.pluginManager)return null
67
- if(!plugin_manager_js_1.pluginManager.getAvailableTools().find(t=>t.name===e))return null
68
- this.debugLog("プラグインツール実行: "+e,t)
69
- const r={userId:"current_user",service:"leonardo",apiKey:process.env.LEONARDO_API_KEY,settings:{}}
70
- let n="leonardo"
71
- e.startsWith("leonardo_")&&(n="leonardo")
72
- const o=await plugin_manager_js_1.pluginManager.executePlugin(n,e,t,r)
73
- if(o.success)return this.debugLog("プラグインツール実行成功: "+e),{content:o.content,_meta:o.metadata}
74
- throw this.debugLog("プラグインツール実行失敗: "+e,o.error),new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"プラグインツール実行エラー: "+o.error)}catch(t){if(this.debugLog("プラグインツール処理エラー: "+e,t),t instanceof types_js_1.McpError)throw t
75
- throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError,"プラグイン処理中にエラーが発生しました: "+t.message)}}async run(){try{await plugin_manager_js_1.pluginManager.initialize(),this.debugLog("プラグインマネージャー初期化完了")}catch(e){this.debugLog("プラグインマネージャー初期化エラー",e)}const e=new stdio_js_1.StdioServerTransport
76
- await this.server.connect(e),this.startCacheCleanup()}}exports.SecureMCPServer=SecureMCPServer,require.main===module&&(new SecureMCPServer).run().catch(()=>{})
@@ -1,24 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,a){void 0===a&&(a=r)
3
- var n=Object.getOwnPropertyDescriptor(t,r)
4
- n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,a,n)}:function(e,t,r,a){void 0===a&&(a=r),e[a]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var r={}
9
- if(null!=t)for(var a=e(t),n=0;n<a.length;n++)"default"!==a[n]&&__createBinding(r,t,a[n])
10
- return __setModuleDefault(r,t),r}}()
11
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.ApiKeyManager=void 0
12
- const https=__importStar(require("https")),http=__importStar(require("http")),url_1=require("url"),TokenManager_js_1=require("./TokenManager.js")
13
- class ApiKeyManager{static async getApiKey(e){try{const t=this.cache[e]
14
- if(t&&Date.now()-t.fetchedAt<t.ttl)return t.apiKey
15
- const r=await TokenManager_js_1.TokenManager.loadToken()
16
- if(!r||!r.token)return null
17
- const a=await this.fetchApiKeysFromPortal(r.token)
18
- if(!a)return null
19
- const n=a.find(t=>t.serviceId===e||t.service?.id===e||t.serviceName?.toLowerCase()===e.toLowerCase())
20
- return n?(this.cache[e]={apiKey:n.apiKey,fetchedAt:Date.now(),ttl:this.DEFAULT_TTL},n.apiKey):null}catch(e){return null}}static async fetchApiKeysFromPortal(token){return new Promise((e,t)=>{const r=new url_1.URL(this.PORTAL_API_URL+"/api/simple/api-keys"),a={hostname:r.hostname,port:r.port||("https:"===r.protocol?443:80),path:r.pathname,method:"GET",headers:{Authorization:"Bearer "+token,"X-CLI-Token":token,"Content-Type":"application/json"},timeout:1e4},n=("https:"===r.protocol?https:http).request(a,t=>{let r=""
21
- t.on("data",e=>{r+=e}),t.on("end",()=>{try{const t=JSON.parse(r)
22
- t.success&&t.data?.apiKeys?e(t.data.apiKeys):e(null)}catch(t){e(null)}})})
23
- n.on("error",t=>{e(null)}),n.on("timeout",()=>{n.destroy(),e(null)}),n.end()})}static clearCache(e){e?delete this.cache[e]:this.cache={}}static async preloadApiKeys(e){const t=e.map(e=>this.getApiKey(e))
24
- await Promise.allSettled(t)}}exports.ApiKeyManager=ApiKeyManager,ApiKeyManager.cache={},ApiKeyManager.DEFAULT_TTL=3e5,ApiKeyManager.PORTAL_API_URL=process.env.PORTAL_URL||"https://bluelamp-portal-6clpzmy5pa-an.a.run.app"
@@ -1,32 +0,0 @@
1
- "use strict"
2
- var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n)
3
- var i=Object.getOwnPropertyDescriptor(t,n)
4
- i&&!("get"in i?!t.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,i)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[]
5
- for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n)
6
- return t},e(t)}
7
- return function(t){if(t&&t.__esModule)return t
8
- var n={}
9
- if(null!=t)for(var r=e(t),i=0;i<r.length;i++)"default"!==r[i]&&__createBinding(n,t,r[i])
10
- return __setModuleDefault(n,t),n}}()
11
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.InteractiveLogin=void 0
12
- const readline=__importStar(require("readline")),fs=__importStar(require("fs")),path=__importStar(require("path")),os=__importStar(require("os")),crypto=__importStar(require("crypto")),PortalAuthClient_js_1=require("./PortalAuthClient.js"),TokenManager_js_1=require("./TokenManager.js")
13
- class InteractiveLogin{static getLoginInfoPath(){const e=os.homedir()
14
- return path.join(e,".bluelamp_login_info.enc")}static exists(){return fs.existsSync(this.getLoginInfoPath())}static async loadLoginInfo(){const e=this.getLoginInfoPath()
15
- if(!fs.existsSync(e))return null
16
- try{const t=fs.readFileSync(e,"utf8"),n=crypto.createHash("sha256").update(os.userInfo().username+os.hostname()).digest(),r=crypto.createDecipheriv("aes-256-cbc",n.slice(0,32),Buffer.alloc(16))
17
- let i=r.update(t,"hex","utf8")
18
- return i+=r.final("utf8"),JSON.parse(i)}catch(e){return null}}static async deleteLoginInfo(){const e=this.getLoginInfoPath()
19
- return!!fs.existsSync(e)&&(fs.unlinkSync(e),!0)}static async performLogin(){try{const e=await TokenManager_js_1.TokenManager.loadToken()
20
- if(e&&e.token){const t=await TokenManager_js_1.TokenManager.validateToken(e.token)
21
- if(t.valid)return{token:e.token,user:t.userInfo,isFromCache:!0}
22
- await TokenManager_js_1.TokenManager.deleteToken()}let t=await this.loadLoginInfo()
23
- if(t){const e=await PortalAuthClient_js_1.PortalAuthClient.authenticate(t.email,t.passwordHash)
24
- if(!e.success){if(!e.error||!e.error.includes("ナレッジインジェクション使用回数上限"))return await InteractiveLogin.deleteLoginInfo(),await this.performLogin()
25
- process.exit(1)}return await TokenManager_js_1.TokenManager.saveToken(e.token,e.user)&&await InteractiveLogin.deleteLoginInfo(),{token:e.token,user:e.user,isFirstTime:!1,isFromCache:!1,migrated:!0}}{const e=await this.promptCredentials(),t=await PortalAuthClient_js_1.PortalAuthClient.authenticate(e.email,e.password)
26
- return t.success||(t.error&&t.error.includes("ナレッジインジェクション使用回数上限"),process.exit(1)),await TokenManager_js_1.TokenManager.saveToken(t.token,t.user),await InteractiveLogin.deleteLoginInfo(),{token:t.token,user:t.user,isFirstTime:!0,isFromCache:!1}}}catch(e){process.exit(1)}}static async promptCredentials(){const e=readline.createInterface({input:process.stdin,output:process.stdout})
27
- try{const t=await this.question(e,"Email: ")
28
- this.validateEmail(t)||(e.close(),process.exit(1))
29
- const n=await this.question(e,"Password: ")
30
- return n&&0!==n.trim().length||(e.close(),process.exit(1)),e.close(),{email:t.trim(),password:n.trim()}}catch(t){throw e.close(),t}}static question(e,t){return new Promise(n=>{e.question(t,e=>{n(e)})})}static validateEmail(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}static displayLoginSuccess(e){e.isFirstTime}static async logout(){const e=readline.createInterface({input:process.stdin,output:process.stdout})
31
- try{const t=await this.question(e,"ログイン情報を削除しますか? (y/N): ")
32
- "y"!==t.toLowerCase()&&"yes"!==t.toLowerCase()||await InteractiveLogin.deleteLoginInfo()}finally{e.close()}}static async checkLoginStatus(){return!!InteractiveLogin.exists()&&!!await InteractiveLogin.loadLoginInfo()}}exports.InteractiveLogin=InteractiveLogin