@make-u-free/migi 0.3.5 → 0.3.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
@@ -66,16 +66,18 @@ console.log(chalk.dim(' /exit 終了\n'))
66
66
 
67
67
  const agent = new MigiAgent({ context, promptFn, apiKey, model, name: agentName, userName, teamsWebhookUrl })
68
68
 
69
- const SEP = chalk.dim('─'.repeat(50))
69
+ function sep() { return chalk.dim('─'.repeat(process.stdout.columns || 80)) }
70
70
 
71
- // ---- 複数行入力(空行で送信) ----
71
+ // ---- 複数行入力(空行で送信)----
72
72
  async function readMultiLine() {
73
73
  const lines = []
74
- process.stdout.write(chalk.dim(' Enter で改行 / 空行で送信\n'))
75
74
  return new Promise((resolve) => {
76
75
  const onLine = (line) => {
77
76
  if (line === '' && lines.length > 0) {
78
77
  rl.removeListener('line', onLine)
78
+ // 入力ボックス下辺 + 欄外ステータス
79
+ console.log(sep())
80
+ console.log(chalk.dim(` ✦ ${model} · Enterで改行 / 空行で送信`))
79
81
  resolve(lines.join('\n'))
80
82
  } else {
81
83
  lines.push(line)
@@ -89,8 +91,10 @@ async function readMultiLine() {
89
91
 
90
92
  // ---- メインループ ----
91
93
  async function prompt() {
92
- console.log('\n' + SEP)
93
- process.stdout.write(chalk.bold.cyan(` ${userName || 'あなた'}\n`) + SEP + '\n')
94
+ // 入力ボックス上辺
95
+ console.log('\n' + sep())
96
+ console.log(chalk.bold.cyan(` ${userName || 'あなた'}`))
97
+ console.log(sep())
94
98
 
95
99
  const input = (await readMultiLine()).trim()
96
100
  if (!input) return prompt()
@@ -135,9 +139,9 @@ async function prompt() {
135
139
  if (parsed) {
136
140
  const skill = resolveSkill(parsed.name, process.cwd())
137
141
  if (skill) {
138
- console.log('\n' + SEP)
142
+ console.log('\n' + sep())
139
143
  console.log(chalk.bold.cyan(` ${agentName}`) + chalk.dim(` [スキル: ${parsed.name}]`))
140
- console.log(SEP)
144
+ console.log(sep())
141
145
  const expanded = expandSkill(skill.content, parsed.args)
142
146
  try {
143
147
  const reply = await agent.chat(expanded)
@@ -154,9 +158,9 @@ async function prompt() {
154
158
  }
155
159
 
156
160
  // --- 通常チャット ---
157
- console.log('\n' + SEP)
161
+ console.log('\n' + sep())
158
162
  console.log(chalk.bold.cyan(` ${agentName}`))
159
- console.log(SEP)
163
+ console.log(sep())
160
164
  try {
161
165
  const reply = await agent.chat(input)
162
166
  console.log('\n' + reply + '\n')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.3.5",
3
+ "version": "0.3.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
@@ -4,6 +4,7 @@ import { homedir } from 'os'
4
4
  import { toolSchemas, teamsToolSchema, executeTool } from './tools.js'
5
5
  import { createPermissionChecker } from './permissions.js'
6
6
  import { httpsAgent } from './tls.js'
7
+ import { Spinner } from './spinner.js'
7
8
 
8
9
  export class MigiAgent {
9
10
  constructor({ context = '', promptFn = null, apiKey = null, model = 'gpt-4.1-2025-04-14', name = 'Migi', userName = '', teamsWebhookUrl = '' } = {}) {
@@ -92,13 +93,17 @@ ${userNameLine}
92
93
  ...this.history
93
94
  ]
94
95
 
96
+ const spinner = new Spinner()
97
+
95
98
  while (true) {
99
+ spinner.start('考え中…')
96
100
  const response = await this.client.chat.completions.create({
97
101
  model: this.model,
98
102
  messages,
99
103
  tools: this.tools,
100
104
  tool_choice: 'auto'
101
105
  })
106
+ spinner.stop()
102
107
 
103
108
  const choice = response.choices[0]
104
109
  messages.push(choice.message)
@@ -117,21 +122,23 @@ ${userNameLine}
117
122
  const args = JSON.parse(toolCall.function.arguments)
118
123
  const name = toolCall.function.name
119
124
 
120
- console.log(chalk.dim(`\n [${name}]`))
125
+ console.log(chalk.dim(` ${name}`))
121
126
 
122
127
  const approved = await this.checkPermission(name, args)
123
128
  let result
124
129
 
125
130
  if (approved) {
131
+ spinner.start(`実行中: ${name}`)
126
132
  try {
127
133
  result = await executeTool(name, args, {
128
- teamsWebhookUrl: this.teamsWebhookUrl,
129
- apiKey: this.apiKey,
130
- model: this.model
131
- })
134
+ teamsWebhookUrl: this.teamsWebhookUrl,
135
+ apiKey: this.apiKey,
136
+ model: this.model
137
+ })
132
138
  } catch (err) {
133
139
  result = `エラー: ${err.message}`
134
140
  }
141
+ spinner.stop()
135
142
  } else {
136
143
  result = 'ユーザーによりキャンセルされました'
137
144
  console.log(chalk.dim(' → キャンセル'))
package/src/spinner.js ADDED
@@ -0,0 +1,34 @@
1
+ import chalk from 'chalk'
2
+
3
+ const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
4
+
5
+ export class Spinner {
6
+ constructor() {
7
+ this._frame = 0
8
+ this._timer = null
9
+ this._text = ''
10
+ }
11
+
12
+ start(text = '考え中…') {
13
+ this._text = text
14
+ this._frame = 0
15
+ this._timer = setInterval(() => {
16
+ const icon = chalk.cyan(FRAMES[this._frame % FRAMES.length])
17
+ process.stdout.write(`\r ${icon} ${chalk.dim(this._text)} `)
18
+ this._frame++
19
+ }, 80)
20
+ }
21
+
22
+ update(text) {
23
+ this._text = text
24
+ }
25
+
26
+ stop() {
27
+ if (this._timer) {
28
+ clearInterval(this._timer)
29
+ this._timer = null
30
+ // 行をクリア
31
+ process.stdout.write('\r' + ' '.repeat((process.stdout.columns || 80)) + '\r')
32
+ }
33
+ }
34
+ }