@make-u-free/migi 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/migi.js CHANGED
@@ -20,6 +20,7 @@ let apiKey = process.env.OPENAI_API_KEY
20
20
  let model = 'gpt-4.1-2025-04-14'
21
21
  let agentName = 'Migi'
22
22
  let userName = ''
23
+ let teamsWebhookUrl = ''
23
24
 
24
25
  if (!apiKey) {
25
26
  const config = loadGlobalConfig()
@@ -28,12 +29,14 @@ if (!apiKey) {
28
29
  model = config.model || 'gpt-4.1-2025-04-14'
29
30
  agentName = config.name || 'Migi'
30
31
  userName = config.user_name || ''
32
+ teamsWebhookUrl = config.teams_webhook_url || ''
31
33
  } else {
32
34
  const config = await runSetup(promptFn)
33
35
  apiKey = config.openai_api_key
34
36
  model = config.model || 'gpt-4.1-2025-04-14'
35
37
  agentName = config.name || 'Migi'
36
38
  userName = config.user_name || ''
39
+ teamsWebhookUrl = config.teams_webhook_url || ''
37
40
  }
38
41
  }
39
42
 
@@ -61,7 +64,7 @@ console.log(chalk.dim('\n /secretary 秘書モード'))
61
64
  console.log(chalk.dim(' /config 設定変更'))
62
65
  console.log(chalk.dim(' /exit 終了\n'))
63
66
 
64
- const agent = new MigiAgent({ context, promptFn, apiKey, model, name: agentName, userName })
67
+ const agent = new MigiAgent({ context, promptFn, apiKey, model, name: agentName, userName, teamsWebhookUrl })
65
68
 
66
69
  // ---- メインループ ----
67
70
  function prompt() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Your AI right-hand agent. Works anywhere, with any LLM API.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/agent.js CHANGED
@@ -1,18 +1,20 @@
1
1
  import OpenAI from 'openai'
2
2
  import chalk from 'chalk'
3
3
  import { homedir } from 'os'
4
- import { toolSchemas, executeTool } from './tools.js'
4
+ import { toolSchemas, teamsToolSchema, executeTool } from './tools.js'
5
5
  import { createPermissionChecker } from './permissions.js'
6
6
  import { httpsAgent } from './tls.js'
7
7
 
8
8
  export class MigiAgent {
9
- constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi', userName = '' } = {}) {
9
+ constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi', userName = '', teamsWebhookUrl = '' } = {}) {
10
10
  this.client = new OpenAI({
11
11
  apiKey: apiKey || process.env.OPENAI_API_KEY,
12
12
  ...(httpsAgent ? { httpAgent: httpsAgent } : {})
13
13
  })
14
14
  this.model = model
15
15
  this.history = []
16
+ this.teamsWebhookUrl = teamsWebhookUrl
17
+ this.tools = teamsWebhookUrl ? [...toolSchemas, teamsToolSchema] : toolSchemas
16
18
  this.checkPermission = createPermissionChecker(promptFn || (() => Promise.resolve('y')))
17
19
 
18
20
  const cwd = process.cwd()
@@ -56,7 +58,10 @@ ${userNameLine}
56
58
  - ファイルパスは必ずこのディレクトリを基準に構築すること
57
59
  - 相対パスは使わず、常に絶対パスでツールを呼び出すこと
58
60
  `
59
- this.systemPrompt = BASE_SYSTEM_PROMPT +
61
+ const teamsPrompt = teamsWebhookUrl
62
+ ? `\n## Teams通知\n- 改善要望・不具合報告・重要な共有事項があれば notify_teams ツールでTeamsに通知する\n- ユーザーが「改善要望」「フィードバック」「不具合」「共有して」などと言ったら、内容をまとめてTeamsに通知することを提案する`
63
+ : ''
64
+ this.systemPrompt = BASE_SYSTEM_PROMPT + teamsPrompt +
60
65
  (context ? `\n## ロードされたコンテキスト\n${context}` : '')
61
66
  }
62
67
 
@@ -72,7 +77,7 @@ ${userNameLine}
72
77
  const response = await this.client.chat.completions.create({
73
78
  model: this.model,
74
79
  messages,
75
- tools: toolSchemas,
80
+ tools: this.tools,
76
81
  tool_choice: 'auto'
77
82
  })
78
83
 
@@ -99,7 +104,7 @@ ${userNameLine}
99
104
  let result
100
105
 
101
106
  if (approved) {
102
- result = await executeTool(name, args)
107
+ result = await executeTool(name, args, { teamsWebhookUrl: this.teamsWebhookUrl })
103
108
  } else {
104
109
  result = 'ユーザーによりキャンセルされました'
105
110
  console.log(chalk.dim(' → キャンセル'))
package/src/setup.js CHANGED
@@ -145,10 +145,22 @@ export async function runSetup(promptFn = null, existingConfig = null) {
145
145
  const userNameInput = await ask(userNamePrompt)
146
146
  const userName = userNameInput.trim() || currentUserName
147
147
 
148
+ // ---- Teams Webhook URL ----
149
+ console.log('')
150
+ const currentTeamsUrl = isUpdate ? existingConfig.teams_webhook_url || '' : ''
151
+ const teamsPrompt = isUpdate && currentTeamsUrl
152
+ ? chalk.cyan(` Teams Webhook URL [設定済み] > `)
153
+ : chalk.cyan(' Teams Webhook URL(任意・Enterでスキップ) > ')
154
+ if (!isUpdate) {
155
+ console.log(chalk.dim(' Microsoft Teams への通知を使う場合は Webhook URL を入力してください。\n'))
156
+ }
157
+ const teamsInput = await ask(teamsPrompt)
158
+ const teamsWebhookUrl = teamsInput.trim() || currentTeamsUrl
159
+
148
160
  console.log(chalk.green(`\n ${name} です。${userName ? userName + 'さん、' : ''}よろしくお願いします!\n`))
149
161
 
150
162
  // ---- 保存 ----
151
- const config = { name, user_name: userName, openai_api_key: apiKey, model }
163
+ const config = { name, user_name: userName, openai_api_key: apiKey, model, teams_webhook_url: teamsWebhookUrl }
152
164
  saveGlobalConfig(config)
153
165
  if (rl) rl.close()
154
166
 
package/src/tls.js CHANGED
@@ -1,19 +1,30 @@
1
- import { existsSync, readFileSync } from 'fs'
2
- import { join } from 'path'
1
+ import { existsSync, readFileSync, readdirSync } from 'fs'
2
+ import { join, extname } from 'path'
3
3
  import { homedir } from 'os'
4
4
  import https from 'https'
5
5
  import tls from 'tls'
6
6
 
7
- // CA ファイルの検索順(単体 .crt / bundle.pem どちらでも可)
8
- const CA_CANDIDATES = [
9
- process.env.NODE_EXTRA_CA_CERTS,
10
- join(homedir(), '.migi', 'zscaler-ca.pem'),
11
- join(homedir(), '.migi', 'zscaler-ca.crt'),
12
- join(homedir(), '.migi', 'ca-bundle.pem'),
13
- ].filter(Boolean)
7
+ // .migi/ ディレクトリ内の .crt / .pem を名前不問でスキャン
8
+ function scanDir(dir) {
9
+ if (!existsSync(dir)) return []
10
+ try {
11
+ return readdirSync(dir)
12
+ .filter(f => ['.crt', '.pem'].includes(extname(f).toLowerCase()))
13
+ .map(f => join(dir, f))
14
+ } catch {
15
+ return []
16
+ }
17
+ }
14
18
 
15
19
  function findCA() {
16
- for (const p of CA_CANDIDATES) {
20
+ // 優先順: 環境変数 カレント.migi/ → ホーム.migi/
21
+ const candidates = [
22
+ process.env.NODE_EXTRA_CA_CERTS,
23
+ ...scanDir(join(process.cwd(), '.migi')),
24
+ ...scanDir(join(homedir(), '.migi')),
25
+ ].filter(Boolean)
26
+
27
+ for (const p of candidates) {
17
28
  if (existsSync(p)) return p
18
29
  }
19
30
  return null
@@ -47,7 +58,7 @@ if (caPath) {
47
58
 
48
59
  console.log(` [TLS] CA loaded: ${caPath}`)
49
60
  } else {
50
- console.log(' [TLS] CA未設定 (社内エラー時は ~/.migi/zscaler-ca.pem を配置)')
61
+ console.log(' [TLS] CA未設定 (社内エラー時は .migi/.crt/.pem を配置)')
51
62
  }
52
63
 
53
64
  export const httpsAgent = _httpsAgent
package/src/tools.js CHANGED
@@ -98,9 +98,26 @@ export const toolSchemas = [
98
98
  }
99
99
  ]
100
100
 
101
+ // ---- Teams 通知ツールスキーマ(Webhook URL が設定済みの場合のみ使用) ----
102
+
103
+ export const teamsToolSchema = {
104
+ type: 'function',
105
+ function: {
106
+ name: 'notify_teams',
107
+ description: 'Microsoft Teams のチャンネルに通知を送る。改善要望・不具合報告・重要な共有事項があるときに使う。',
108
+ parameters: {
109
+ type: 'object',
110
+ properties: {
111
+ message: { type: 'string', description: '送信するメッセージ' }
112
+ },
113
+ required: ['message']
114
+ }
115
+ }
116
+ }
117
+
101
118
  // ---- ツール実行 ----
102
119
 
103
- export async function executeTool(name, args) {
120
+ export async function executeTool(name, args, opts = {}) {
104
121
  switch (name) {
105
122
  case 'read_file': {
106
123
  if (!existsSync(args.path)) return `エラー: ファイルが見つかりません: ${args.path}`
@@ -158,6 +175,19 @@ export async function executeTool(name, args) {
158
175
  }
159
176
  }
160
177
 
178
+ case 'notify_teams': {
179
+ const url = opts.teamsWebhookUrl
180
+ if (!url) return 'エラー: Teams Webhook URL が設定されていません'
181
+ const body = JSON.stringify({ text: args.message })
182
+ const res = await fetch(url, {
183
+ method: 'POST',
184
+ headers: { 'Content-Type': 'application/json' },
185
+ body
186
+ })
187
+ if (!res.ok) return `エラー: Teams への送信に失敗しました (${res.status})`
188
+ return 'Teams に通知しました'
189
+ }
190
+
161
191
  default:
162
192
  return `不明なツール: ${name}`
163
193
  }