miii-agent 0.1.16 → 0.1.17
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/LICENSE +21 -0
- package/dist/cli.js +57 -21
- package/package.json +22 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 maruakshay
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/cli.js
CHANGED
|
@@ -2119,7 +2119,7 @@ function messageText(m) {
|
|
|
2119
2119
|
function firstUserText(messages) {
|
|
2120
2120
|
const first = messages.find((m) => m.role === "user");
|
|
2121
2121
|
if (!first) return "untitled";
|
|
2122
|
-
return messageText(first)
|
|
2122
|
+
return flattenForTitle(messageText(first)).slice(0, 80) || "untitled";
|
|
2123
2123
|
}
|
|
2124
2124
|
function readMeta(id) {
|
|
2125
2125
|
try {
|
|
@@ -2151,6 +2151,10 @@ function persistSession(id, messages, title) {
|
|
|
2151
2151
|
}
|
|
2152
2152
|
writeFileSync2(sessionPath(id), lines.join("\n") + "\n", "utf-8");
|
|
2153
2153
|
}
|
|
2154
|
+
function setSessionTitle(id, title) {
|
|
2155
|
+
if (!readMeta(id)) return;
|
|
2156
|
+
persistSession(id, loadSession(id), title);
|
|
2157
|
+
}
|
|
2154
2158
|
function listSessions() {
|
|
2155
2159
|
if (!existsSync2(SESSION_DIR)) return [];
|
|
2156
2160
|
const metas = [];
|
|
@@ -2213,12 +2217,35 @@ function toDisplayMessages(history) {
|
|
|
2213
2217
|
}
|
|
2214
2218
|
return out;
|
|
2215
2219
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2220
|
+
function flattenForTitle(text) {
|
|
2221
|
+
return text.replace(/<[^>]*>/g, " ").replace(/[`*_#>|]/g, " ").replace(/https?:\/\/\S+/g, " ").replace(/\s+/g, " ").trim();
|
|
2222
|
+
}
|
|
2223
|
+
function looksLikeJunkTitle(title) {
|
|
2224
|
+
return !title || /[<>]/.test(title) || title.length > 80;
|
|
2225
|
+
}
|
|
2226
|
+
async function summarizeConversation(model, messages) {
|
|
2227
|
+
const parts = [];
|
|
2228
|
+
let sawUser = false;
|
|
2229
|
+
let sawAssistant = false;
|
|
2230
|
+
for (const m of messages) {
|
|
2231
|
+
if (m.role === "system") continue;
|
|
2232
|
+
const t = flattenForTitle(messageText(m));
|
|
2233
|
+
if (!t) continue;
|
|
2234
|
+
if (m.role === "user" && !sawUser) {
|
|
2235
|
+
parts.push(`User: ${t}`);
|
|
2236
|
+
sawUser = true;
|
|
2237
|
+
} else if (m.role === "assistant" && !sawAssistant) {
|
|
2238
|
+
parts.push(`Assistant: ${t}`);
|
|
2239
|
+
sawAssistant = true;
|
|
2240
|
+
}
|
|
2241
|
+
if (sawUser && sawAssistant) break;
|
|
2242
|
+
}
|
|
2243
|
+
const convo = parts.join("\n").slice(0, 2e3);
|
|
2244
|
+
const fallback = (parts[0]?.replace(/^User: /, "") ?? "").slice(0, 80) || "untitled";
|
|
2245
|
+
const prompt = `Summarize this conversation as a short title, 3-6 words, no punctuation. Reply with the title only.
|
|
2219
2246
|
|
|
2220
|
-
|
|
2221
|
-
${
|
|
2247
|
+
Conversation:
|
|
2248
|
+
${convo}`;
|
|
2222
2249
|
try {
|
|
2223
2250
|
let out = "";
|
|
2224
2251
|
for await (const chunk of chat3(
|
|
@@ -2229,7 +2256,8 @@ ${text.slice(0, 2e3)}`;
|
|
|
2229
2256
|
)) {
|
|
2230
2257
|
if (chunk.content) out += chunk.content;
|
|
2231
2258
|
}
|
|
2232
|
-
|
|
2259
|
+
const title = out.trim().split("\n").filter(Boolean)[0]?.trim() ?? "";
|
|
2260
|
+
return looksLikeJunkTitle(title) ? fallback : title;
|
|
2233
2261
|
} catch {
|
|
2234
2262
|
return fallback;
|
|
2235
2263
|
}
|
|
@@ -2495,7 +2523,7 @@ function FileEditBlock({
|
|
|
2495
2523
|
Text9,
|
|
2496
2524
|
{
|
|
2497
2525
|
wrap: "truncate",
|
|
2498
|
-
backgroundColor: ln.sign === "
|
|
2526
|
+
backgroundColor: ln.sign === "-" ? "#3b1414" : ln.sign === "+" && label !== "Write" ? "#13351f" : void 0,
|
|
2499
2527
|
dimColor: ln.sign === " ",
|
|
2500
2528
|
children: [
|
|
2501
2529
|
`${ln.sign} `,
|
|
@@ -3018,6 +3046,7 @@ function useKeyboard(opts) {
|
|
|
3018
3046
|
setFilePickerCursor,
|
|
3019
3047
|
sessionId,
|
|
3020
3048
|
setSessionId,
|
|
3049
|
+
onResumeSession,
|
|
3021
3050
|
sessions,
|
|
3022
3051
|
setSessions,
|
|
3023
3052
|
setNotice,
|
|
@@ -3190,6 +3219,7 @@ function useKeyboard(opts) {
|
|
|
3190
3219
|
setActiveToolResults([]);
|
|
3191
3220
|
setError(null);
|
|
3192
3221
|
setSessionId(meta.id);
|
|
3222
|
+
onResumeSession(meta.id);
|
|
3193
3223
|
setNotice(`resumed \xB7 ${meta.title}`);
|
|
3194
3224
|
setState("ready");
|
|
3195
3225
|
}
|
|
@@ -3288,17 +3318,6 @@ function useKeyboard(opts) {
|
|
|
3288
3318
|
} else if (trimmed) {
|
|
3289
3319
|
setNotice(null);
|
|
3290
3320
|
const message = expandPastes(trimmed);
|
|
3291
|
-
if (!agentHistory.length && cfg.model) {
|
|
3292
|
-
const id = sessionId;
|
|
3293
|
-
const model = cfg.model;
|
|
3294
|
-
void (async () => {
|
|
3295
|
-
try {
|
|
3296
|
-
const title = await summarizeMessage(model, message);
|
|
3297
|
-
persistSession(id, [{ role: "user", content: message }], title);
|
|
3298
|
-
} catch {
|
|
3299
|
-
}
|
|
3300
|
-
})();
|
|
3301
|
-
}
|
|
3302
3321
|
sendMessage(message);
|
|
3303
3322
|
}
|
|
3304
3323
|
clearPasteStore();
|
|
@@ -3393,9 +3412,25 @@ function App() {
|
|
|
3393
3412
|
if (v) setUpdateAvailable(v);
|
|
3394
3413
|
});
|
|
3395
3414
|
}, []);
|
|
3415
|
+
const titledSessions = useRef2(/* @__PURE__ */ new Set());
|
|
3396
3416
|
useEffect4(() => {
|
|
3397
|
-
|
|
3398
|
-
|
|
3417
|
+
const history = agent.agentHistory;
|
|
3418
|
+
if (!history.length) return;
|
|
3419
|
+
persistSession(sessionId, history);
|
|
3420
|
+
if (!titledSessions.current.has(sessionId) && cfg.model && history.some((m) => m.role === "assistant")) {
|
|
3421
|
+
titledSessions.current.add(sessionId);
|
|
3422
|
+
const id = sessionId;
|
|
3423
|
+
const model = cfg.model;
|
|
3424
|
+
const snapshot = history;
|
|
3425
|
+
void (async () => {
|
|
3426
|
+
try {
|
|
3427
|
+
const title = await summarizeConversation(model, snapshot);
|
|
3428
|
+
setSessionTitle(id, title);
|
|
3429
|
+
} catch {
|
|
3430
|
+
}
|
|
3431
|
+
})();
|
|
3432
|
+
}
|
|
3433
|
+
}, [agent.agentHistory, sessionId, cfg.model]);
|
|
3399
3434
|
const loadGen = useRef2(0);
|
|
3400
3435
|
const loadModels = (afterProvider = false) => {
|
|
3401
3436
|
const gen = ++loadGen.current;
|
|
@@ -3466,6 +3501,7 @@ function App() {
|
|
|
3466
3501
|
setFilePickerCursor,
|
|
3467
3502
|
sessionId,
|
|
3468
3503
|
setSessionId,
|
|
3504
|
+
onResumeSession: (id) => titledSessions.current.add(id),
|
|
3469
3505
|
sessions,
|
|
3470
3506
|
setSessions,
|
|
3471
3507
|
setNotice,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miii-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Terminal AI coding agent powered by Ollama",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
12
13
|
],
|
|
13
14
|
"engines": {
|
|
14
15
|
"node": ">=18"
|
|
@@ -28,13 +29,30 @@
|
|
|
28
29
|
"type": "git",
|
|
29
30
|
"url": "git+https://github.com/maruakshay/miii-cli.git"
|
|
30
31
|
},
|
|
32
|
+
"homepage": "https://github.com/maruakshay/miii-cli#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/maruakshay/miii-cli/issues"
|
|
35
|
+
},
|
|
31
36
|
"keywords": [
|
|
32
37
|
"cli",
|
|
33
38
|
"ai",
|
|
39
|
+
"ai-agent",
|
|
40
|
+
"coding-agent",
|
|
41
|
+
"ai-coding-assistant",
|
|
34
42
|
"ollama",
|
|
35
|
-
"
|
|
43
|
+
"llm",
|
|
44
|
+
"local-llm",
|
|
45
|
+
"local-first",
|
|
46
|
+
"offline",
|
|
47
|
+
"privacy",
|
|
48
|
+
"terminal",
|
|
49
|
+
"tui",
|
|
36
50
|
"ink",
|
|
37
|
-
"
|
|
51
|
+
"agent",
|
|
52
|
+
"pair-programming",
|
|
53
|
+
"code-generation",
|
|
54
|
+
"llama-cpp",
|
|
55
|
+
"lm-studio"
|
|
38
56
|
],
|
|
39
57
|
"license": "MIT",
|
|
40
58
|
"dependencies": {
|