@make-u-free/migi 0.3.8 → 0.4.0
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 +92 -17
- package/package.json +1 -1
package/bin/migi.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import '../src/tls.js' // 企業CA(Zscaler等)を起動直後に読み込む
|
|
3
|
-
import readline from 'readline'
|
|
3
|
+
import readline, { emitKeypressEvents } from 'readline'
|
|
4
4
|
import chalk from 'chalk'
|
|
5
5
|
import dotenv from 'dotenv'
|
|
6
6
|
import { MigiAgent } from '../src/agent.js'
|
|
@@ -78,24 +78,99 @@ function sepWithLabel(label) {
|
|
|
78
78
|
return chalk.dim(left + right)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
// ----
|
|
82
|
-
async function
|
|
83
|
-
const lines = []
|
|
81
|
+
// ---- チャット入力(Enter送信 / Shift+Enter改行)----
|
|
82
|
+
async function readChatInput() {
|
|
84
83
|
return new Promise((resolve) => {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
const PFIRST = ' > '
|
|
85
|
+
const PCONT = ' '
|
|
86
|
+
const lines = ['']
|
|
87
|
+
let curLine = 0
|
|
88
|
+
let drawnLines = 0
|
|
89
|
+
|
|
90
|
+
emitKeypressEvents(process.stdin)
|
|
91
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(true)
|
|
92
|
+
|
|
93
|
+
function draw() {
|
|
94
|
+
const w = process.stdout.columns || 80
|
|
95
|
+
|
|
96
|
+
// 前回描画分をクリア
|
|
97
|
+
if (drawnLines > 0) {
|
|
98
|
+
process.stdout.write(`\x1b[${drawnLines}A\x1b[1G`)
|
|
99
|
+
for (let i = 0; i < drawnLines; i++) {
|
|
100
|
+
process.stdout.write('\x1b[2K\n')
|
|
101
|
+
}
|
|
102
|
+
process.stdout.write(`\x1b[${drawnLines}A\x1b[1G`)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 入力行 + セパレーター + ガイド を描画
|
|
106
|
+
const allLines = [
|
|
107
|
+
...lines.map((l, i) => chalk.cyan(i === 0 ? PFIRST : PCONT) + l),
|
|
108
|
+
chalk.dim('─'.repeat(w)),
|
|
109
|
+
chalk.dim(` ✦ ${model} · Shift+Enterで改行 / Enterで送信`)
|
|
110
|
+
]
|
|
111
|
+
drawnLines = allLines.length
|
|
112
|
+
process.stdout.write(allLines.join('\n') + '\n')
|
|
113
|
+
|
|
114
|
+
// カーソルを入力行の末尾に移動
|
|
115
|
+
const linesBelow = drawnLines - curLine
|
|
116
|
+
if (linesBelow > 0) process.stdout.write(`\x1b[${linesBelow}A`)
|
|
117
|
+
const col = (curLine === 0 ? PFIRST : PCONT).length + lines[curLine].length + 1
|
|
118
|
+
process.stdout.write(`\x1b[${col}G`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
draw()
|
|
122
|
+
|
|
123
|
+
const onKey = (str, key) => {
|
|
124
|
+
if (!key) {
|
|
125
|
+
if (str) { lines[curLine] += str; draw() }
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (key.ctrl && key.name === 'c') {
|
|
130
|
+
process.stdout.write(`\x1b[${drawnLines - curLine}B\n`)
|
|
131
|
+
process.stdin.removeListener('keypress', onKey)
|
|
132
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false)
|
|
133
|
+
console.log(chalk.cyan('\n お疲れ様でした!またね。\n'))
|
|
134
|
+
process.exit(0)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (key.name === 'return') {
|
|
138
|
+
if (key.shift) {
|
|
139
|
+
// Shift+Enter → 改行
|
|
140
|
+
lines.splice(curLine + 1, 0, '')
|
|
141
|
+
curLine++
|
|
142
|
+
draw()
|
|
143
|
+
} else {
|
|
144
|
+
// Enter → 送信
|
|
145
|
+
const content = lines.join('\n').trim()
|
|
146
|
+
if (!content) return
|
|
147
|
+
process.stdout.write(`\x1b[${drawnLines - curLine}B\n`)
|
|
148
|
+
process.stdin.removeListener('keypress', onKey)
|
|
149
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false)
|
|
150
|
+
resolve(content)
|
|
151
|
+
}
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (key.name === 'backspace') {
|
|
156
|
+
if (lines[curLine].length > 0) {
|
|
157
|
+
lines[curLine] = lines[curLine].slice(0, -1)
|
|
158
|
+
draw()
|
|
159
|
+
} else if (curLine > 0) {
|
|
160
|
+
lines.splice(curLine, 1)
|
|
161
|
+
curLine--
|
|
162
|
+
draw()
|
|
163
|
+
}
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (str && !key.ctrl && !key.meta) {
|
|
168
|
+
lines[curLine] += str
|
|
169
|
+
draw()
|
|
95
170
|
}
|
|
96
171
|
}
|
|
97
|
-
|
|
98
|
-
|
|
172
|
+
|
|
173
|
+
process.stdin.on('keypress', onKey)
|
|
99
174
|
})
|
|
100
175
|
}
|
|
101
176
|
|
|
@@ -104,7 +179,7 @@ async function prompt() {
|
|
|
104
179
|
// 入力ボックス上辺(ユーザー名をセパレーターに埋め込む)
|
|
105
180
|
console.log('\n' + sepWithLabel(chalk.bold.cyan(userName || 'あなた')))
|
|
106
181
|
|
|
107
|
-
const input = (await
|
|
182
|
+
const input = (await readChatInput()).trim()
|
|
108
183
|
if (!input) return prompt()
|
|
109
184
|
|
|
110
185
|
// --- ビルトインコマンド ---
|