@make-u-free/migi 0.3.6 → 0.3.8
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 +16 -12
- package/package.json +1 -1
- package/src/agent.js +12 -5
- package/src/spinner.js +34 -0
package/bin/migi.js
CHANGED
|
@@ -66,7 +66,17 @@ 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
|
-
function sep() {
|
|
69
|
+
function sep() {
|
|
70
|
+
const w = process.stdout.columns || 80
|
|
71
|
+
return chalk.dim('─'.repeat(w))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function sepWithLabel(label) {
|
|
75
|
+
const w = process.stdout.columns || 80
|
|
76
|
+
const left = '── ' + label + ' '
|
|
77
|
+
const right = '─'.repeat(Math.max(0, w - left.length))
|
|
78
|
+
return chalk.dim(left + right)
|
|
79
|
+
}
|
|
70
80
|
|
|
71
81
|
// ---- 複数行入力(空行で送信)----
|
|
72
82
|
async function readMultiLine() {
|
|
@@ -75,7 +85,7 @@ async function readMultiLine() {
|
|
|
75
85
|
const onLine = (line) => {
|
|
76
86
|
if (line === '' && lines.length > 0) {
|
|
77
87
|
rl.removeListener('line', onLine)
|
|
78
|
-
//
|
|
88
|
+
// 入力ボックス下辺(欄の閉じ)+ 欄外ガイド
|
|
79
89
|
console.log(sep())
|
|
80
90
|
console.log(chalk.dim(` ✦ ${model} · Enterで改行 / 空行で送信`))
|
|
81
91
|
resolve(lines.join('\n'))
|
|
@@ -91,10 +101,8 @@ async function readMultiLine() {
|
|
|
91
101
|
|
|
92
102
|
// ---- メインループ ----
|
|
93
103
|
async function prompt() {
|
|
94
|
-
//
|
|
95
|
-
console.log('\n' +
|
|
96
|
-
console.log(chalk.bold.cyan(` ${userName || 'あなた'}`))
|
|
97
|
-
console.log(sep())
|
|
104
|
+
// 入力ボックス上辺(ユーザー名をセパレーターに埋め込む)
|
|
105
|
+
console.log('\n' + sepWithLabel(chalk.bold.cyan(userName || 'あなた')))
|
|
98
106
|
|
|
99
107
|
const input = (await readMultiLine()).trim()
|
|
100
108
|
if (!input) return prompt()
|
|
@@ -139,9 +147,7 @@ async function prompt() {
|
|
|
139
147
|
if (parsed) {
|
|
140
148
|
const skill = resolveSkill(parsed.name, process.cwd())
|
|
141
149
|
if (skill) {
|
|
142
|
-
console.log('\n' +
|
|
143
|
-
console.log(chalk.bold.cyan(` ${agentName}`) + chalk.dim(` [スキル: ${parsed.name}]`))
|
|
144
|
-
console.log(sep())
|
|
150
|
+
console.log('\n' + sepWithLabel(chalk.bold.cyan(agentName) + chalk.dim(` [スキル: ${parsed.name}]`)))
|
|
145
151
|
const expanded = expandSkill(skill.content, parsed.args)
|
|
146
152
|
try {
|
|
147
153
|
const reply = await agent.chat(expanded)
|
|
@@ -158,9 +164,7 @@ async function prompt() {
|
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
// --- 通常チャット ---
|
|
161
|
-
console.log('\n' +
|
|
162
|
-
console.log(chalk.bold.cyan(` ${agentName}`))
|
|
163
|
-
console.log(sep())
|
|
167
|
+
console.log('\n' + sepWithLabel(chalk.bold.cyan(agentName)))
|
|
164
168
|
try {
|
|
165
169
|
const reply = await agent.chat(input)
|
|
166
170
|
console.log('\n' + reply + '\n')
|
package/package.json
CHANGED
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(
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
+
}
|