@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 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`, scroll | Scroll chat history |
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
@@ -10,5 +10,6 @@ export const C = {
10
10
  white: [226, 232, 240],
11
11
  green: [115, 218, 202],
12
12
  red: [247, 118, 142],
13
+ codeBg: [27, 35, 49], // dark blue-grey used behind code blocks
13
14
  };
14
15
  export const EMPTY_STYLE = {};
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
- text = "thinking";
9
- }
10
- else {
11
- text = `${state.selectedProvider}/${state.selectedModelName} | ${state.selectedIntensity}`;
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
  }