@make-u-free/migi 0.1.9 → 0.2.1

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,18 +20,21 @@ const promptFn = (q) => new Promise((resolve) => rl.question(q, resolve))
20
20
  let apiKey = process.env.OPENAI_API_KEY
21
21
  let model = 'gpt-4.1-2025-04-14'
22
22
  let agentName = 'Migi'
23
+ let userName = ''
23
24
 
24
25
  if (!apiKey) {
25
26
  const config = loadGlobalConfig()
26
27
  if (config?.openai_api_key) {
27
28
  apiKey = config.openai_api_key
28
- model = config.model || 'gpt-4o'
29
+ model = config.model || 'gpt-4.1-2025-04-14'
29
30
  agentName = config.name || 'Migi'
31
+ userName = config.user_name || ''
30
32
  } else {
31
33
  const config = await runSetup(promptFn)
32
34
  apiKey = config.openai_api_key
33
- model = config.model || 'gpt-4o'
35
+ model = config.model || 'gpt-4.1-2025-04-14'
34
36
  agentName = config.name || 'Migi'
37
+ userName = config.user_name || ''
35
38
  }
36
39
  }
37
40
 
@@ -59,7 +62,7 @@ console.log(chalk.dim('\n /secretary 秘書モード'))
59
62
  console.log(chalk.dim(' /config 設定変更'))
60
63
  console.log(chalk.dim(' /exit 終了\n'))
61
64
 
62
- const agent = new MigiAgent({ context, promptFn, apiKey, model, name: agentName })
65
+ const agent = new MigiAgent({ context, promptFn, apiKey, model, name: agentName, userName })
63
66
 
64
67
  // ---- メインループ ----
65
68
  function prompt() {
@@ -74,7 +77,8 @@ function prompt() {
74
77
  }
75
78
 
76
79
  if (input === '/config') {
77
- await runSetup(promptFn)
80
+ const current = loadGlobalConfig()
81
+ await runSetup(promptFn, current)
78
82
  console.log(chalk.yellow(' 再起動して設定を反映してください。\n'))
79
83
  return prompt()
80
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
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
@@ -5,16 +5,20 @@ import { toolSchemas, executeTool } from './tools.js'
5
5
  import { createPermissionChecker } from './permissions.js'
6
6
 
7
7
  export class MigiAgent {
8
- constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi' } = {}) {
8
+ constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi', userName = '' } = {}) {
9
9
  this.client = new OpenAI({ apiKey: apiKey || process.env.OPENAI_API_KEY })
10
10
  this.model = model
11
11
  this.history = []
12
12
  this.checkPermission = createPermissionChecker(promptFn || (() => Promise.resolve('y')))
13
13
 
14
14
  const cwd = process.cwd()
15
+ const userNameLine = userName
16
+ ? `ユーザーの名前は「${userName}」です。会話の中でこの名前で呼んでください。「さん」などの敬称は不要です。`
17
+ : ''
15
18
  const BASE_SYSTEM_PROMPT = `\
16
19
  あなたの名前は「${name}」です。ユーザーがつけてくれた名前です。
17
20
  自己紹介や会話の中で、この名前を自分の名前として使ってください。
21
+ ${userNameLine}
18
22
 
19
23
  あなたはユーザーの右腕として動くAIエージェントです。
20
24
  仕事も人生も、何でも一緒に動きます。
package/src/setup.js CHANGED
@@ -35,12 +35,20 @@ async function extractName(apiKey, model, input) {
35
35
  }
36
36
  }
37
37
 
38
+ function maskApiKey(key) {
39
+ if (!key || key.length < 8) return '****'
40
+ return key.slice(0, 7) + '...' + key.slice(-4)
41
+ }
42
+
38
43
  export function saveGlobalConfig(config) {
39
44
  mkdirSync(MIGI_DIR, { recursive: true })
40
45
  writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')
41
46
  }
42
47
 
43
- export async function runSetup(promptFn = null) {
48
+ // existingConfig を渡すと「更新モード」になり、各項目を Enter でスキップできる
49
+ export async function runSetup(promptFn = null, existingConfig = null) {
50
+ const isUpdate = !!existingConfig
51
+
44
52
  // readline を外から受け取るか、自前で作る
45
53
  let rl = null
46
54
  let ask = promptFn
@@ -49,22 +57,36 @@ export async function runSetup(promptFn = null) {
49
57
  ask = (q) => new Promise((resolve) => rl.question(q, resolve))
50
58
  }
51
59
 
52
- // ---- 自己紹介 ----
53
- console.log(chalk.bold.cyan('\n ╔══════════════════════════════════════╗'))
54
- console.log(chalk.bold.cyan(' ║ Migi — by MAKE U FREE ║'))
55
- console.log(chalk.bold.cyan(' ╚══════════════════════════════════════╝\n'))
56
- console.log(chalk.white(' はじめまして!'))
57
- console.log(chalk.white(' 私はあなたの右腕として動く AI エージェントです。\n'))
58
- console.log(chalk.dim(' タスク管理・壁打ち・ファイル操作・コマンド実行...'))
59
- console.log(chalk.dim(' 仕事も人生も、何でも一緒に動きます。\n'))
60
- console.log(chalk.dim(' ─────────────────────────────────────\n'))
60
+ if (isUpdate) {
61
+ // ---- 更新モード ----
62
+ console.log(chalk.bold.cyan('\n ╔══════════════════════════════════════╗'))
63
+ console.log(chalk.bold.cyan(' ║ 設定を変更します ║'))
64
+ console.log(chalk.bold.cyan(' ╚══════════════════════════════════════╝'))
65
+ console.log(chalk.dim(' Enter でスキップ(現在値を維持)\n'))
66
+ } else {
67
+ // ---- 初回セットアップ ----
68
+ console.log(chalk.bold.cyan('\n ╔══════════════════════════════════════╗'))
69
+ console.log(chalk.bold.cyan(' ║ Migi — by MAKE U FREE ║'))
70
+ console.log(chalk.bold.cyan(' ╚══════════════════════════════════════╝\n'))
71
+ console.log(chalk.white(' はじめまして!'))
72
+ console.log(chalk.white(' 私はあなたの右腕として動く AI エージェントです。\n'))
73
+ console.log(chalk.dim(' タスク管理・壁打ち・ファイル操作・コマンド実行...'))
74
+ console.log(chalk.dim(' 仕事も人生も、何でも一緒に動きます。\n'))
75
+ console.log(chalk.dim(' ─────────────────────────────────────\n'))
76
+ }
61
77
 
62
78
  // ---- API キー ----
63
- console.log(chalk.dim(' まず OpenAI API キーを設定しましょう。'))
64
- console.log(chalk.dim(' 取得: https://platform.openai.com/api-keys\n'))
65
- const apiKey = await ask(chalk.white(' API キー > '))
79
+ if (!isUpdate) {
80
+ console.log(chalk.dim(' まず OpenAI API キーを設定しましょう。'))
81
+ console.log(chalk.dim(' 取得: https://platform.openai.com/api-keys\n'))
82
+ }
83
+ const apiKeyPrompt = isUpdate
84
+ ? chalk.white(` API キー [${maskApiKey(existingConfig.openai_api_key)}] > `)
85
+ : chalk.white(' API キー > ')
86
+ const apiKeyInput = await ask(apiKeyPrompt)
87
+ const apiKey = apiKeyInput.trim() || (isUpdate ? existingConfig.openai_api_key : '')
66
88
 
67
- if (!apiKey.trim()) {
89
+ if (!apiKey) {
68
90
  console.log(chalk.red('\n API キーが入力されていません。終了します。\n'))
69
91
  if (rl) rl.close()
70
92
  process.exit(1)
@@ -76,38 +98,61 @@ export async function runSetup(promptFn = null) {
76
98
  console.log(chalk.dim(' 1) gpt-4.1-2025-04-14 (推奨・エージェント特化)'))
77
99
  console.log(chalk.dim(' 2) gpt-4o (汎用)'))
78
100
  console.log(chalk.dim(' 3) gpt-4o-mini (高速・低コスト)'))
79
- console.log(chalk.dim(' 4) その他 (直接入力)\n'))
101
+ console.log(chalk.dim(' 4) その他 (直接入力)'))
102
+ if (isUpdate) console.log(chalk.dim(` 現在: ${existingConfig.model}`))
103
+ console.log('')
80
104
  const modelChoice = await ask(chalk.white(' 選択 [1] > '))
81
105
 
82
- let model = 'gpt-4.1-2025-04-14'
83
- if (modelChoice.trim() === '2') {
106
+ let model = isUpdate ? existingConfig.model : 'gpt-4.1-2025-04-14'
107
+ if (modelChoice.trim() === '1') {
108
+ model = 'gpt-4.1-2025-04-14'
109
+ } else if (modelChoice.trim() === '2') {
84
110
  model = 'gpt-4o'
85
111
  } else if (modelChoice.trim() === '3') {
86
112
  model = 'gpt-4o-mini'
87
113
  } else if (modelChoice.trim() === '4') {
88
114
  const custom = await ask(chalk.white(' モデル名 > '))
89
- model = custom.trim() || 'gpt-4.1-2025-04-14'
115
+ model = custom.trim() || model
90
116
  }
117
+ // 空Enter → 既存値のまま(modelはすでに既存値がセットされている)
91
118
 
92
- // ---- 名前(AIで解釈) ----
119
+ // ---- みぎの名前(AIで解釈) ----
93
120
  console.log('')
94
- console.log(chalk.white(' ひとつお願いがあります。'))
95
- console.log(chalk.white(' ─── 名前をつけてもらえますか? ───\n'))
96
- console.log(chalk.dim(' あなただけの右腕として、その名前で動きます。'))
97
- console.log(chalk.dim(' 例: ミギ、アシ、レン、なんでも OK\n'))
98
-
99
- const nameInput = await ask(chalk.cyan(' 名前 > '))
100
- const name = await extractName(apiKey.trim(), model, nameInput.trim())
121
+ if (!isUpdate) {
122
+ console.log(chalk.white(' ひとつお願いがあります。'))
123
+ console.log(chalk.white(' ─── 名前をつけてもらえますか? ───\n'))
124
+ console.log(chalk.dim(' あなただけの右腕として、その名前で動きます。'))
125
+ console.log(chalk.dim(' 例: ミギ、アシ、レン、なんでも OK\n'))
126
+ }
127
+ const namePrompt = isUpdate
128
+ ? chalk.cyan(` みぎの名前 [${existingConfig.name}] > `)
129
+ : chalk.cyan(' 名前 > ')
130
+ const nameInput = await ask(namePrompt)
131
+ const name = nameInput.trim()
132
+ ? await extractName(apiKey, model, nameInput.trim())
133
+ : (isUpdate ? existingConfig.name : 'Migi')
134
+
135
+ // ---- ユーザー名 ----
136
+ console.log('')
137
+ const currentUserName = isUpdate ? existingConfig.user_name || '' : ''
138
+ const userNamePrompt = isUpdate && currentUserName
139
+ ? chalk.cyan(` あなたのお名前 [${currentUserName}] > `)
140
+ : chalk.cyan(' あなたのことは何とお呼びすればいいですか? > ')
141
+ if (!isUpdate) {
142
+ console.log(chalk.dim(' お名前(ニックネームでもOK)を教えてください。\n'))
143
+ }
144
+ const userNameInput = await ask(userNamePrompt)
145
+ const userName = userNameInput.trim() || currentUserName
101
146
 
102
- console.log(chalk.green(`\n ${name} です。よろしくお願いします!\n`))
147
+ console.log(chalk.green(`\n ${name} です。${userName ? userName + 'さん、' : ''}よろしくお願いします!\n`))
103
148
 
104
149
  // ---- 保存 ----
105
- const config = { name, openai_api_key: apiKey.trim(), model }
150
+ const config = { name, user_name: userName, openai_api_key: apiKey, model }
106
151
  saveGlobalConfig(config)
107
152
  if (rl) rl.close()
108
153
 
109
154
  console.log(chalk.dim(` 設定を保存しました: ${CONFIG_PATH}`))
110
- console.log(chalk.dim(` 名前: ${name} / モデル: ${model}\n`))
155
+ console.log(chalk.dim(` 名前: ${name}${userName ? ' / ユーザー: ' + userName : ''} / モデル: ${model}\n`))
111
156
  console.log(chalk.cyan(' ─────────────────────────────────────\n'))
112
157
 
113
158
  return config