@xingjisoft/neutrino 0.1.0 → 0.1.1
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 +16 -2
- package/dist/app.js +20 -0
- package/dist/colors.js +1 -0
- package/dist/header.js +11 -6
- package/dist/markdown.js +630 -0
- package/dist/screens/agentConversation.js +12 -14
- package/dist/screens/agentHistory.js +76 -24
- package/dist/screens/agentSelect.js +54 -7
- package/dist/screens/chat.js +42 -21
- package/dist/screens/history.js +73 -20
- package/dist/screens/modelSelect.js +66 -7
- package/dist/screens/settings.js +64 -2
- package/dist/screens/start.js +96 -10
- package/dist/state.js +1 -0
- package/dist/terminal/input.js +14 -0
- package/dist/terminal/renderer.js +6 -2
- package/dist/ui.js +70 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A CLI coding agent that lives in your terminal. Neutrino gives you an interactiv
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Interactive terminal UI** — logo screen, chat, model select, history, and settings screens.
|
|
8
|
+
- **Full mouse support** — hover to highlight, click to select/open/position the cursor, wheel to scroll, right-click to go back (like OpenCode).
|
|
8
9
|
- **LLM providers** — ships with DeepSeek, OpenAI, and Anthropic presets; works with any OpenAI-compatible endpoint.
|
|
9
10
|
- **Tool calling** — the agent can run shell commands, read files, write files, and list directories in your working directory.
|
|
10
11
|
- **Streaming responses** — token-by-token output with pause/resume (`ESC ESC`).
|
|
@@ -52,10 +53,21 @@ Type a message on the start screen and press `Enter` to begin a new chat.
|
|
|
52
53
|
| `Ctrl+B` | Back to menu (from chat) |
|
|
53
54
|
| `Ctrl+L` | Clear conversation (from chat) |
|
|
54
55
|
| `Esc Esc` | Pause / resume streaming |
|
|
55
|
-
| `PgUp` / `PgDn
|
|
56
|
-
| Click `ⓘ` (chat header) | Toggle token usage stats |
|
|
56
|
+
| `PgUp` / `PgDn` | Scroll chat history |
|
|
57
57
|
| `Ctrl+C` / `Ctrl+Q` | Quit |
|
|
58
58
|
|
|
59
|
+
### Mouse
|
|
60
|
+
|
|
61
|
+
| Action | Effect |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| Hover over an item | Highlight / select it in lists and menus |
|
|
64
|
+
| Click an item | Select and confirm (open a screen, load a session, apply a setting…) |
|
|
65
|
+
| Click the input box | Focus it and place the cursor at the clicked position |
|
|
66
|
+
| Click the header (left of `ⓘ`) | Open the model selector |
|
|
67
|
+
| Click `ⓘ` (chat header) | Toggle token usage stats |
|
|
68
|
+
| Scroll wheel | Scroll the chat/log, or move through lists |
|
|
69
|
+
| Right-click | Go back (like `Esc`) |
|
|
70
|
+
|
|
59
71
|
## Configuration
|
|
60
72
|
|
|
61
73
|
Settings are stored under `~/.neutrino/`:
|
|
@@ -89,6 +101,8 @@ The agent can call the following tools during a conversation:
|
|
|
89
101
|
|
|
90
102
|
```sh
|
|
91
103
|
npm run build # compile TypeScript to dist/
|
|
104
|
+
node scripts/test-mouse.mjs # verify mouse escape-sequence parsing
|
|
105
|
+
node scripts/test-cursor.mjs # verify click-to-position-cursor math
|
|
92
106
|
```
|
|
93
107
|
|
|
94
108
|
## License
|
package/dist/app.js
CHANGED
|
@@ -19,6 +19,7 @@ export class App {
|
|
|
19
19
|
input = new InputReader();
|
|
20
20
|
running = false;
|
|
21
21
|
sizeTimer = null;
|
|
22
|
+
blinkTimer = null;
|
|
22
23
|
resizeHandler = () => this.onResize();
|
|
23
24
|
constructor() {
|
|
24
25
|
this.width = process.stdout.columns || 80;
|
|
@@ -80,6 +81,21 @@ export class App {
|
|
|
80
81
|
this.render();
|
|
81
82
|
}
|
|
82
83
|
render() {
|
|
84
|
+
// Start/stop the "thinking" blink animation. While the agent is thinking,
|
|
85
|
+
// a timer toggles the blink phase and re-renders so the top status bar
|
|
86
|
+
// flashes to draw the user's attention.
|
|
87
|
+
if (this.state.isThinking && !this.blinkTimer) {
|
|
88
|
+
this.state.blinkOn = true;
|
|
89
|
+
this.blinkTimer = setInterval(() => {
|
|
90
|
+
this.state.blinkOn = !this.state.blinkOn;
|
|
91
|
+
this.render();
|
|
92
|
+
}, 500);
|
|
93
|
+
}
|
|
94
|
+
else if (!this.state.isThinking && this.blinkTimer) {
|
|
95
|
+
clearInterval(this.blinkTimer);
|
|
96
|
+
this.blinkTimer = null;
|
|
97
|
+
this.state.blinkOn = false;
|
|
98
|
+
}
|
|
83
99
|
const buf = new Buffer(this.width, this.height);
|
|
84
100
|
this.top?.render(buf);
|
|
85
101
|
this.renderer.render(buf);
|
|
@@ -162,6 +178,10 @@ export class App {
|
|
|
162
178
|
this.running = true;
|
|
163
179
|
if (this.sizeTimer)
|
|
164
180
|
clearInterval(this.sizeTimer);
|
|
181
|
+
if (this.blinkTimer) {
|
|
182
|
+
clearInterval(this.blinkTimer);
|
|
183
|
+
this.blinkTimer = null;
|
|
184
|
+
}
|
|
165
185
|
this.input.stop();
|
|
166
186
|
this.renderer.dispose();
|
|
167
187
|
process.exit(0);
|
package/dist/colors.js
CHANGED
package/dist/header.js
CHANGED
|
@@ -2,14 +2,19 @@ import { C } from "./colors.js";
|
|
|
2
2
|
import { truncateByWidth } from "./width.js";
|
|
3
3
|
export function drawHeader(buf, state) {
|
|
4
4
|
const w = buf.width;
|
|
5
|
-
buf.fillRect(0, 0, w, 1, { bg: C.highlightBg });
|
|
6
|
-
let text;
|
|
7
5
|
if (state.isThinking) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
// Flashing indicator: the whole bar alternates between highlighted and
|
|
7
|
+
// dark while the agent is working, so the user always notices it.
|
|
8
|
+
const on = state.blinkOn;
|
|
9
|
+
const bg = on ? C.highlightBg : C.black;
|
|
10
|
+
const fg = on ? C.accent : C.dim;
|
|
11
|
+
const text = "⚡ thinking";
|
|
12
|
+
buf.fillRect(0, 0, w, 1, { bg });
|
|
13
|
+
buf.centerText(0, text, { fg, bg, bold: true });
|
|
14
|
+
return;
|
|
12
15
|
}
|
|
16
|
+
buf.fillRect(0, 0, w, 1, { bg: C.highlightBg });
|
|
17
|
+
let text = `${state.selectedProvider}/${state.selectedModelName} | ${state.selectedIntensity}`;
|
|
13
18
|
text = truncateByWidth(text, w);
|
|
14
19
|
buf.centerText(0, text, { fg: C.accent, bg: C.highlightBg, bold: true });
|
|
15
20
|
}
|