@make-u-free/migi 0.3.0 → 0.3.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Your AI right-hand agent. Works anywhere, with any LLM API.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,6 +13,7 @@
13
13
  "chalk": "^5.3.0",
14
14
  "dotenv": "^16.4.0",
15
15
  "glob": "^11.0.0",
16
+ "officeparser": "^6.0.7",
16
17
  "openai": "^4.0.0",
17
18
  "xlsx": "^0.18.5"
18
19
  },
package/src/agent.js CHANGED
@@ -7,8 +7,9 @@ import { httpsAgent } from './tls.js'
7
7
 
8
8
  export class MigiAgent {
9
9
  constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi', userName = '', teamsWebhookUrl = '' } = {}) {
10
+ this.apiKey = apiKey || process.env.OPENAI_API_KEY
10
11
  this.client = new OpenAI({
11
- apiKey: apiKey || process.env.OPENAI_API_KEY,
12
+ apiKey: this.apiKey,
12
13
  ...(httpsAgent ? { httpAgent: httpsAgent } : {})
13
14
  })
14
15
  this.model = model
@@ -123,7 +124,11 @@ ${userNameLine}
123
124
 
124
125
  if (approved) {
125
126
  try {
126
- result = await executeTool(name, args, { teamsWebhookUrl: this.teamsWebhookUrl })
127
+ result = await executeTool(name, args, {
128
+ teamsWebhookUrl: this.teamsWebhookUrl,
129
+ apiKey: this.apiKey,
130
+ model: this.model
131
+ })
127
132
  } catch (err) {
128
133
  result = `エラー: ${err.message}`
129
134
  }
package/src/tls.js CHANGED
@@ -41,13 +41,13 @@ if (caPath) {
41
41
 
42
42
  // ① tls.createSecureContext パッチ
43
43
  // Node 18+ built-in fetch (undici) を含む全TLS接続に効く
44
+ // デフォルトのCA(tls.rootCertificates)に追加する形にする
44
45
  const _origCreate = tls.createSecureContext
45
46
  tls.createSecureContext = (options = {}) => {
46
- const extra = [caCert]
47
- const existing = options.ca
47
+ const base = options.ca
48
48
  ? (Array.isArray(options.ca) ? options.ca : [options.ca])
49
- : []
50
- return _origCreate({ ...options, ca: [...existing, ...extra] })
49
+ : tls.rootCertificates // デフォルトCAを引き継ぐ
50
+ return _origCreate({ ...options, ca: [...base, caCert] })
51
51
  }
52
52
 
53
53
  // ② NODE_EXTRA_CA_CERTS(環境変数で起動する場合のフォールバック)
@@ -55,8 +55,8 @@ if (caPath) {
55
55
  process.env.NODE_EXTRA_CA_CERTS = caPath
56
56
  }
57
57
 
58
- // ③ https.Agent(node-fetch 系フォールバック)
59
- _httpsAgent = new https.Agent({ ca: caCert })
58
+ // ③ https.Agent: デフォルトCA + Zscaler CA を合わせて渡す
59
+ _httpsAgent = new https.Agent({ ca: [...tls.rootCertificates, caCert] })
60
60
 
61
61
  console.log(` [TLS] CA loaded: ${caPath}`)
62
62
  } else {
package/src/tools.js CHANGED
@@ -4,9 +4,15 @@ import { dirname, extname } from 'path'
4
4
  import { request } from 'https'
5
5
  import { glob } from 'glob'
6
6
  import xlsxPkg from 'xlsx'
7
+ import officeParser from 'officeparser'
8
+ import OpenAI from 'openai'
7
9
  import { httpsAgent } from './tls.js'
8
10
  const { readFile: xlsxReadFile, utils: xlsxUtils } = xlsxPkg
9
11
 
12
+ const IMAGE_EXTS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp'])
13
+ const OFFICE_EXTS = new Set(['.pdf', '.pptx', '.ppt', '.docx', '.doc', '.odp', '.odt'])
14
+ const MIME = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif', '.webp': 'image/webp' }
15
+
10
16
  // ---- OpenAI ツールスキーマ定義 ----
11
17
 
12
18
  export const toolSchemas = [
@@ -14,7 +20,7 @@ export const toolSchemas = [
14
20
  type: 'function',
15
21
  function: {
16
22
  name: 'read_file',
17
- description: 'ファイルの内容を読み込む',
23
+ description: 'ファイルの内容を読み込む。テキスト・Excel・PDF・Word・PowerPoint・画像に対応',
18
24
  parameters: {
19
25
  type: 'object',
20
26
  properties: {
@@ -124,6 +130,8 @@ export async function executeTool(name, args, opts = {}) {
124
130
  case 'read_file': {
125
131
  if (!existsSync(args.path)) return `エラー: ファイルが見つかりません: ${args.path}`
126
132
  const ext = extname(args.path).toLowerCase()
133
+
134
+ // Excel
127
135
  if (ext === '.xlsx' || ext === '.xls') {
128
136
  const workbook = xlsxReadFile(args.path)
129
137
  const result = []
@@ -134,6 +142,40 @@ export async function executeTool(name, args, opts = {}) {
134
142
  }
135
143
  return result.join('\n\n')
136
144
  }
145
+
146
+ // PDF / PowerPoint / Word
147
+ if (OFFICE_EXTS.has(ext)) {
148
+ try {
149
+ const text = await officeParser.parseOfficeAsync(args.path)
150
+ return text?.trim() || '(テキストが抽出できませんでした)'
151
+ } catch (err) {
152
+ return `エラー: ファイルの解析に失敗しました: ${err.message}`
153
+ }
154
+ }
155
+
156
+ // 画像 → Vision API で内容を説明させる
157
+ if (IMAGE_EXTS.has(ext)) {
158
+ if (!opts.apiKey) return 'エラー: 画像読み込みにはAPIキーが必要です'
159
+ const base64 = readFileSync(args.path).toString('base64')
160
+ const mimeType = MIME[ext] || 'image/jpeg'
161
+ const client = new OpenAI({
162
+ apiKey: opts.apiKey,
163
+ ...(httpsAgent ? { httpAgent: httpsAgent } : {})
164
+ })
165
+ const res = await client.chat.completions.create({
166
+ model: opts.model || 'gpt-4.1-2025-04-14',
167
+ messages: [{
168
+ role: 'user',
169
+ content: [
170
+ { type: 'image_url', image_url: { url: `data:${mimeType};base64,${base64}` } },
171
+ { type: 'text', text: 'この画像の内容を詳しく説明してください。テキストが含まれている場合はすべて書き起こしてください。' }
172
+ ]
173
+ }],
174
+ max_tokens: 2000
175
+ })
176
+ return res.choices[0].message.content
177
+ }
178
+
137
179
  return readFileSync(args.path, 'utf-8')
138
180
  }
139
181