miii-cli 1.0.1 → 1.0.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/README.md +72 -49
- package/dist/config.js +18 -1
- package/dist/init.js +17 -1
- package/dist/llm/stream.js +41 -0
- package/dist/mcp/client.js +110 -0
- package/dist/setup.js +183 -0
- package/dist/tools/index.js +3 -2
- package/dist/tui/InputBar.js +27 -12
- package/dist/tui/components/ConfigPicker.js +178 -0
- package/dist/tui/components/InputArea.js +58 -40
- package/dist/tui/hooks/useRunLoop.js +61 -2
- package/dist/tui/hooks/useSession.js +6 -6
- package/dist/tui/hooks/useSubmit.js +62 -25
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useCallback, useRef } from 'react';
|
|
2
2
|
import { readFile, guardPath } from '../../files/ops.js';
|
|
3
3
|
import { getSystemPrompt } from '../../tools/index.js';
|
|
4
|
+
import { saveConfig } from '../../config.js';
|
|
4
5
|
import { loadSession, saveSession, listSessions, deleteSession, deleteAllSessions } from '../../sessions.js';
|
|
5
6
|
import { runDeepThink } from '../deepThink.js';
|
|
6
7
|
import { buildGitContext, looksCodeRelated } from '../git-context.js';
|
|
7
|
-
import { getTavilyKey, saveTavilyKey } from '../../tavily/client.js';
|
|
8
8
|
import { buildIndex } from '../../index/indexer.js';
|
|
9
9
|
import { indexStats, clearIndex } from '../../index/store.js';
|
|
10
10
|
import { embed } from '../../index/embedder.js';
|
|
@@ -34,7 +34,7 @@ export function useSubmit(deps) {
|
|
|
34
34
|
const depsRef = useRef(deps);
|
|
35
35
|
depsRef.current = deps;
|
|
36
36
|
const handleSubmit = useCallback(async (text) => {
|
|
37
|
-
const { config, skills, cwd, version, currentModelRef, setCurrentModel, historyRef, sessionNameRef, saveTimerRef, systemPromptRef, abortRef,
|
|
37
|
+
const { config, skills, cwd, version, currentModelRef, setCurrentModel, historyRef, sessionNameRef, saveTimerRef, systemPromptRef, abortRef, setPlanningMode, runLoop, buildContext, pushHistory, setSessionName, renameFromMessage, setStatus, setTaskLabel, setCurrentTool, runRefactor, handleGit, lastGitStatusRef, mcpTools, setConfig, setConfigOpen, } = depsRef.current;
|
|
38
38
|
const cmd = text.trim();
|
|
39
39
|
if (cmd === '?') {
|
|
40
40
|
printer.systemMsg('shortcuts:\n' +
|
|
@@ -56,21 +56,6 @@ export function useSubmit(deps) {
|
|
|
56
56
|
printer.systemMsg(`miii v${version ?? 'unknown'}`);
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
|
-
if (cmd === '/tavily-key' || cmd.startsWith('/tavily-key ')) {
|
|
60
|
-
const key = cmd.slice(11).trim();
|
|
61
|
-
if (!key) {
|
|
62
|
-
const existing = getTavilyKey();
|
|
63
|
-
printer.systemMsg(existing ? 'Tavily key set (use /tavily-key <key> to update)' : 'No Tavily key set. Usage: /tavily-key tvly-...');
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (!key.startsWith('tvly-')) {
|
|
67
|
-
printer.systemMsg('Key should start with tvly-. Get yours at https://tavily.com');
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
saveTavilyKey(key);
|
|
71
|
-
printer.systemMsg('Tavily API key saved to ~/.config/miii/tavily.key (mode 600)');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
59
|
if (cmd === '/skills' || cmd.startsWith('/skills ')) {
|
|
75
60
|
const sub = cmd.slice(7).trim();
|
|
76
61
|
if (!sub || sub === 'list') {
|
|
@@ -110,6 +95,62 @@ export function useSubmit(deps) {
|
|
|
110
95
|
printer.systemMsg('usage: /skills install <name> | /skills uninstall <name> | /skills list');
|
|
111
96
|
return;
|
|
112
97
|
}
|
|
98
|
+
if (cmd === '/config' || cmd.startsWith('/config ')) {
|
|
99
|
+
const sub = cmd.slice(7).trim();
|
|
100
|
+
if (!sub) {
|
|
101
|
+
setConfigOpen(true);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (sub.startsWith('provider ')) {
|
|
105
|
+
const val = sub.slice(9).trim();
|
|
106
|
+
const valid = ['ollama', 'anthropic', 'openai-compat'];
|
|
107
|
+
if (!valid.includes(val)) {
|
|
108
|
+
printer.systemMsg(`valid providers: ${valid.join(', ')}`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
setConfig(c => ({ ...c, provider: val }));
|
|
112
|
+
saveConfig({ provider: val });
|
|
113
|
+
printer.systemMsg(`provider → ${val}`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (sub.startsWith('model ')) {
|
|
117
|
+
const val = sub.slice(6).trim();
|
|
118
|
+
if (!val) {
|
|
119
|
+
printer.systemMsg('usage: /config model <name>');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
setConfig(c => ({ ...c, model: val }));
|
|
123
|
+
saveConfig({ model: val });
|
|
124
|
+
setCurrentModel(val);
|
|
125
|
+
currentModelRef.current = val;
|
|
126
|
+
printer.systemMsg(`model → ${val}`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (sub.startsWith('key ')) {
|
|
130
|
+
const val = sub.slice(4).trim();
|
|
131
|
+
if (!val) {
|
|
132
|
+
printer.systemMsg('usage: /config key <api-key>');
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
setConfig(c => ({ ...c, apiKey: val }));
|
|
136
|
+
saveConfig({ apiKey: val });
|
|
137
|
+
printer.systemMsg(`apiKey → ${val.slice(0, 8)}…`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (sub.startsWith('url ')) {
|
|
141
|
+
const val = sub.slice(4).trim();
|
|
142
|
+
if (!val) {
|
|
143
|
+
printer.systemMsg('usage: /config url <base-url>');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
setConfig(c => ({ ...c, baseUrl: val }));
|
|
147
|
+
saveConfig({ baseUrl: val });
|
|
148
|
+
printer.systemMsg(`baseUrl → ${val}`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
printer.systemMsg('usage: /config [provider|model|key|url] <value>');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
113
154
|
if (cmd === '/model' || cmd.startsWith('/model ')) {
|
|
114
155
|
const name = cmd.slice(6).trim();
|
|
115
156
|
if (!name) {
|
|
@@ -121,10 +162,6 @@ export function useSubmit(deps) {
|
|
|
121
162
|
printer.systemMsg(`model → ${name}`);
|
|
122
163
|
return;
|
|
123
164
|
}
|
|
124
|
-
if (cmd === '/models') {
|
|
125
|
-
await openPicker();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
165
|
if (cmd === '/new') {
|
|
129
166
|
if (saveTimerRef.current) {
|
|
130
167
|
clearTimeout(saveTimerRef.current);
|
|
@@ -135,7 +172,7 @@ export function useSubmit(deps) {
|
|
|
135
172
|
historyRef.current = [];
|
|
136
173
|
setSessionName(newName);
|
|
137
174
|
setPlanningMode(false);
|
|
138
|
-
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}
|
|
175
|
+
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}`, mcpTools);
|
|
139
176
|
printer.systemMsg(`new session → ${newName}`);
|
|
140
177
|
return;
|
|
141
178
|
}
|
|
@@ -143,7 +180,7 @@ export function useSubmit(deps) {
|
|
|
143
180
|
historyRef.current = [];
|
|
144
181
|
saveSession(sessionNameRef.current, []);
|
|
145
182
|
setPlanningMode(false);
|
|
146
|
-
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}
|
|
183
|
+
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}`, mcpTools);
|
|
147
184
|
printer.systemMsg('chat cleared');
|
|
148
185
|
return;
|
|
149
186
|
}
|
|
@@ -201,7 +238,7 @@ export function useSubmit(deps) {
|
|
|
201
238
|
if (cmd === '/plan' || cmd.startsWith('/plan ')) {
|
|
202
239
|
const topic = cmd.slice(5).trim();
|
|
203
240
|
setPlanningMode(true);
|
|
204
|
-
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}\n- MODE: Planning assistant. Help the user plan step by step. Ask clarifying questions. Suggest concrete next steps. Use plain text only — no markdown, no headers, no bold, no bullets with asterisks, no backtick blocks. Use numbered lists and plain indentation for structure
|
|
241
|
+
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}\n- MODE: Planning assistant. Help the user plan step by step. Ask clarifying questions. Suggest concrete next steps. Use plain text only — no markdown, no headers, no bold, no bullets with asterisks, no backtick blocks. Use numbered lists and plain indentation for structure.`, mcpTools);
|
|
205
242
|
const msg = topic ? `I want to plan: ${topic}` : 'I want to start planning. Help me think through my goals step by step.';
|
|
206
243
|
printer.userMsg(msg);
|
|
207
244
|
pushHistory({ role: 'user', content: msg });
|
|
@@ -210,7 +247,7 @@ export function useSubmit(deps) {
|
|
|
210
247
|
}
|
|
211
248
|
if (cmd === '/plan:done') {
|
|
212
249
|
setPlanningMode(false);
|
|
213
|
-
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}
|
|
250
|
+
systemPromptRef.current = getSystemPrompt(`\n- CWD: ${cwd}`, mcpTools);
|
|
214
251
|
printer.systemMsg('planning mode off');
|
|
215
252
|
return;
|
|
216
253
|
}
|