agen-vektor 0.3.0 → 0.3.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 +9 -0
- package/dist/tui/app.js +25 -6
- package/dist/tui/chat.js +30 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
**AI Coding Agent for Linux & Termux** — a terminal-native coding agent that inspects your project, plans, edits code, runs commands and tests, and iterates until the task is done.
|
|
4
4
|
|
|
5
|
+
```
|
|
6
|
+
██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ ██╗ ██╗███████╗ █████╗ ██████╗
|
|
7
|
+
██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗██║ ██║██╔════╝██╔══██╗██╔══██╗
|
|
8
|
+
██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝███████║█████╗ ███████║██║ ██║
|
|
9
|
+
╚██╗ ██╔╝██╔══╝ ██║ ██║ ██║ ██║██╔══██╗██╔══██║██╔══╝ ██╔══██║██║ ██║
|
|
10
|
+
╚████╔╝ ███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║██║ ██║███████╗██║ ██║██████╔╝
|
|
11
|
+
╚═══╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝
|
|
12
|
+
```
|
|
13
|
+
|
|
5
14
|
```
|
|
6
15
|
╭──────────────────────────────────────────────────────────────╮
|
|
7
16
|
│ VectorHead ● Ready openrouter · deepseek/deepseek-chat │
|
package/dist/tui/app.js
CHANGED
|
@@ -395,6 +395,7 @@ class App {
|
|
|
395
395
|
this.modal = { type: 'model', selected: 0 };
|
|
396
396
|
break;
|
|
397
397
|
case '/provider':
|
|
398
|
+
case '/setup':
|
|
398
399
|
this.modal = { type: 'provider', selected: 0 };
|
|
399
400
|
break;
|
|
400
401
|
case '/session':
|
|
@@ -499,6 +500,11 @@ class App {
|
|
|
499
500
|
this.agent.rebuildProvider();
|
|
500
501
|
(0, config_1.saveConfig)(this.agent.config);
|
|
501
502
|
this.addSystem(`Provider set to ${opt.label}.`);
|
|
503
|
+
if (pid === 'custom' && !this.agent.config.apiUrl) {
|
|
504
|
+
// Wizard: ask base URL first, then API token
|
|
505
|
+
this.modal = { type: 'custom-url', value: '' };
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
502
508
|
if (!(0, credentials_1.hasApiKey)(pid) && pid !== 'ollama') {
|
|
503
509
|
this.modal = { type: 'apikey', provider: pid, value: '' };
|
|
504
510
|
return;
|
|
@@ -604,7 +610,12 @@ class App {
|
|
|
604
610
|
this.agent.config.apiUrl = value;
|
|
605
611
|
(0, config_1.saveConfig)(this.agent.config);
|
|
606
612
|
this.addSystem('Custom API URL set.');
|
|
607
|
-
|
|
613
|
+
if (!(0, credentials_1.hasApiKey)('custom')) {
|
|
614
|
+
this.modal = { type: 'custom-key', value: '' };
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
this.modal = { type: 'none' };
|
|
618
|
+
}
|
|
608
619
|
});
|
|
609
620
|
break;
|
|
610
621
|
case 'custom-key':
|
|
@@ -763,9 +774,9 @@ class App {
|
|
|
763
774
|
' Ctrl+C stop agent / quit',
|
|
764
775
|
' Ctrl+L clear conversation',
|
|
765
776
|
'',
|
|
766
|
-
'Commands: /model /provider /session
|
|
767
|
-
'/status /clear /continue /diff
|
|
768
|
-
'/yolo /exit',
|
|
777
|
+
'Commands: /setup /model /provider /session',
|
|
778
|
+
'/settings /status /clear /continue /diff',
|
|
779
|
+
'/git /compact /yolo /exit',
|
|
769
780
|
],
|
|
770
781
|
}, rows, cols);
|
|
771
782
|
case 'commands':
|
|
@@ -773,6 +784,7 @@ class App {
|
|
|
773
784
|
title: 'Commands',
|
|
774
785
|
body: [
|
|
775
786
|
'/help show help',
|
|
787
|
+
'/setup setup provider (base URL + token)',
|
|
776
788
|
'/model select model',
|
|
777
789
|
'/provider select provider',
|
|
778
790
|
'/session manage sessions',
|
|
@@ -898,8 +910,15 @@ class App {
|
|
|
898
910
|
}, rows, cols);
|
|
899
911
|
case 'custom-url':
|
|
900
912
|
return (0, components_1.renderModal)({
|
|
901
|
-
title: 'Custom API URL',
|
|
902
|
-
body: [
|
|
913
|
+
title: 'Custom API Base URL',
|
|
914
|
+
body: [
|
|
915
|
+
'Base URL (OpenAI-compatible), e.g.',
|
|
916
|
+
'https://example.com/v1',
|
|
917
|
+
'',
|
|
918
|
+
m.value || '_',
|
|
919
|
+
'',
|
|
920
|
+
'Enter to save · Esc to cancel',
|
|
921
|
+
],
|
|
903
922
|
}, rows, cols);
|
|
904
923
|
case 'custom-key':
|
|
905
924
|
return (0, components_1.renderModal)({
|
package/dist/tui/chat.js
CHANGED
|
@@ -4,12 +4,18 @@ exports.renderMessages = renderMessages;
|
|
|
4
4
|
exports.defaultScroll = defaultScroll;
|
|
5
5
|
exports.clampScroll = clampScroll;
|
|
6
6
|
/**
|
|
7
|
-
* Chat view — renders conversation messages with scrolling.
|
|
7
|
+
* Chat view — renders conversation messages as boxed blocks with scrolling.
|
|
8
8
|
* Message types: user, assistant (streamed), tool, system/status, plan.
|
|
9
|
+
* Each message renders as a bordered box (Freebuff-style):
|
|
10
|
+
* ╭───────────────────────────╮
|
|
11
|
+
* │ ● VectorHead · model │
|
|
12
|
+
* │ content │
|
|
13
|
+
* ╰───────────────────────────╯
|
|
9
14
|
*/
|
|
10
15
|
const theme_1 = require("./theme");
|
|
16
|
+
const terminal_1 = require("../utils/terminal");
|
|
11
17
|
const KIND_STYLE = {
|
|
12
|
-
user: { prefix: 'YOU', color: theme_1.THEME.
|
|
18
|
+
user: { prefix: 'YOU', color: theme_1.THEME.gold },
|
|
13
19
|
assistant: { prefix: 'VectorHead', color: theme_1.THEME.accent },
|
|
14
20
|
tool: { prefix: 'TOOL', color: theme_1.THEME.warn },
|
|
15
21
|
system: { prefix: '···', color: theme_1.THEME.muted },
|
|
@@ -17,37 +23,36 @@ const KIND_STYLE = {
|
|
|
17
23
|
success: { prefix: '✓', color: theme_1.THEME.success },
|
|
18
24
|
warning: { prefix: '⚠', color: theme_1.THEME.warn },
|
|
19
25
|
};
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
/** Render one message as a boxed block. Box width = `width` (whole chat area). */
|
|
27
|
+
function boxMessage(m, width) {
|
|
28
|
+
const style = KIND_STYLE[m.kind];
|
|
29
|
+
const prefix = m.prefix || style.prefix;
|
|
30
|
+
const dot = m.streaming ? `${theme_1.THEME.warn}◐${theme_1.THEME.reset} ` : `${style.color}●${theme_1.THEME.reset} `;
|
|
31
|
+
const title = `${dot}${theme_1.THEME.bold}${style.color}${prefix}${theme_1.THEME.reset}`;
|
|
32
|
+
const meta = m.meta ? ` ${theme_1.THEME.dim}${m.meta}${theme_1.THEME.reset}` : '';
|
|
33
|
+
const toolName = m.tool ? ` ${theme_1.THEME.warn}${m.tool}${theme_1.THEME.reset}` : '';
|
|
34
|
+
const inner = Math.max(8, width - 4);
|
|
35
|
+
const border = style.color;
|
|
22
36
|
const out = [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
37
|
+
// Top border
|
|
38
|
+
out.push(border + terminal_1.BOX.tl + terminal_1.BOX.h.repeat(inner + 2) + terminal_1.BOX.tr + theme_1.THEME.reset);
|
|
39
|
+
// Title row: ● prefix · model / tool badge
|
|
40
|
+
out.push(`${border}${terminal_1.BOX.v}${theme_1.THEME.reset} ` + (0, terminal_1.pad)(title + toolName + meta, inner) + ` ${border}${terminal_1.BOX.v}${theme_1.THEME.reset}`);
|
|
41
|
+
// Content rows
|
|
42
|
+
const body = m.content || '(no content)';
|
|
43
|
+
for (const line of (0, terminal_1.wrapText)(body, inner)) {
|
|
44
|
+
out.push(`${border}${terminal_1.BOX.v}${theme_1.THEME.reset} ` + (0, terminal_1.pad)(line, inner) + ` ${border}${terminal_1.BOX.v}${theme_1.THEME.reset}`);
|
|
31
45
|
}
|
|
46
|
+
// Bottom border + blank separator
|
|
47
|
+
out.push(border + terminal_1.BOX.bl + terminal_1.BOX.h.repeat(inner + 2) + terminal_1.BOX.br + theme_1.THEME.reset);
|
|
48
|
+
out.push('');
|
|
32
49
|
return out;
|
|
33
50
|
}
|
|
34
51
|
/** Precompute the full list of rendered lines for all messages. */
|
|
35
52
|
function renderMessages(messages, width) {
|
|
36
53
|
const out = [];
|
|
37
54
|
for (const m of messages) {
|
|
38
|
-
|
|
39
|
-
const prefix = m.prefix || style.prefix;
|
|
40
|
-
const dot = m.streaming ? `${theme_1.THEME.warn}◐${theme_1.THEME.reset} ` : `${style.color}●${theme_1.THEME.reset} `;
|
|
41
|
-
const header = `${dot}${theme_1.THEME.bold}${style.color}${prefix}${theme_1.THEME.reset}`;
|
|
42
|
-
const meta = m.meta ? ` ${theme_1.THEME.dim}${m.meta}${theme_1.THEME.reset}` : '';
|
|
43
|
-
const toolName = m.tool ? ` ${theme_1.THEME.warn}${m.tool}${theme_1.THEME.reset}` : '';
|
|
44
|
-
out.push(header + toolName + meta);
|
|
45
|
-
const body = m.content || '(no content)';
|
|
46
|
-
const bar = `${style.color}│${theme_1.THEME.reset} `;
|
|
47
|
-
for (const line of plainLines(body, width)) {
|
|
48
|
-
out.push(`${bar}${line}`);
|
|
49
|
-
}
|
|
50
|
-
out.push(''); // blank line between messages
|
|
55
|
+
out.push(...boxMessage(m, width));
|
|
51
56
|
}
|
|
52
57
|
return out;
|
|
53
58
|
}
|
package/package.json
CHANGED