@xingjisoft/neutrino 0.1.6 → 0.2.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/README.md +137 -28
- package/assets/planner.txt +35 -0
- package/assets/prompt.txt +56 -21
- package/assets/step.txt +14 -0
- package/assets/subagent.txt +20 -0
- package/dist/app.js +44 -2
- package/dist/bin.js +38 -13
- package/dist/config.js +45 -1
- package/dist/header.js +5 -0
- package/dist/llm/client.js +64 -140
- package/dist/llm/plan.js +403 -0
- package/dist/llm/retry.js +209 -0
- package/dist/llm/subagent.js +134 -0
- package/dist/llm/tools.js +43 -1
- package/dist/screens/chat.js +439 -78
- package/dist/screens/settings.js +30 -1
- package/dist/state.js +1 -0
- package/dist/web/session.js +211 -22
- package/package.json +2 -2
- package/web/README.md +49 -13
- package/web/app.js +79 -31
- package/web/index.html +55 -17
- package/web/style.css +2070 -1088
- package/web/turns.js +25 -11
package/web/turns.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
//
|
|
3
3
|
// A conversation is a sequence of turns: each one starts at a user message and
|
|
4
4
|
// runs until the next one. Once the agent has finished a turn, the browser folds
|
|
5
|
-
// it
|
|
6
|
-
//
|
|
5
|
+
// away the work it took — the prompt body, the thinking and the tool calls — and
|
|
6
|
+
// keeps the final reply on screen, so a finished exchange always ends on its
|
|
7
|
+
// answer. The complete round is still one click away.
|
|
7
8
|
//
|
|
8
9
|
// The thresholds mirror TURN_FOLD_MIN_BLOCKS / TURN_FOLD_MIN_CHARS in
|
|
9
10
|
// src/screens/chat.ts, so the terminal and the browser fold the same turns.
|
|
@@ -22,25 +23,38 @@ export function turnRanges(messages) {
|
|
|
22
23
|
return turns;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
/**
|
|
26
|
+
/** Index of the turn's reply — its last assistant message (-1 when it has none). */
|
|
27
|
+
export function turnAnswerIndex(messages) {
|
|
28
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
29
|
+
if (messages[i].role === "assistant") return i;
|
|
30
|
+
}
|
|
31
|
+
return -1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* True when folding the work behind this turn saves more room than it costs.
|
|
36
|
+
* The reply is never folded away, so it is not counted: a long answer on its own
|
|
37
|
+
* must never collapse the turn that carries it.
|
|
38
|
+
*/
|
|
26
39
|
export function turnFolds(messages) {
|
|
40
|
+
const reply = turnAnswerIndex(messages);
|
|
27
41
|
let blocks = 0;
|
|
28
42
|
let chars = 0;
|
|
29
|
-
|
|
30
|
-
if (
|
|
43
|
+
messages.forEach((message, index) => {
|
|
44
|
+
if (index === reply) return;
|
|
45
|
+
if (message.role !== "user" && message.role !== "assistant") return;
|
|
31
46
|
blocks++;
|
|
32
47
|
chars += String(message.content ?? "").length;
|
|
33
|
-
}
|
|
48
|
+
});
|
|
34
49
|
return blocks >= TURN_FOLD_MIN_BLOCKS || chars >= TURN_FOLD_MIN_CHARS;
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
/**
|
|
38
|
-
* The first line of the first
|
|
39
|
-
*
|
|
53
|
+
* The first line of the first message in `role`. One line only: the header is a
|
|
54
|
+
* signpost, and the full text is one click away.
|
|
40
55
|
*/
|
|
41
|
-
export function turnPreview(messages, role
|
|
42
|
-
const
|
|
43
|
-
for (const message of ordered) {
|
|
56
|
+
export function turnPreview(messages, role) {
|
|
57
|
+
for (const message of messages) {
|
|
44
58
|
if (message.role !== role) continue;
|
|
45
59
|
const line = String(message.content ?? "")
|
|
46
60
|
.split(/\r?\n/)
|