helix-assistant-cli 0.0.0-stage → 0.2.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.
Files changed (51) hide show
  1. package/bin/helix.js +3 -0
  2. package/dist/client/agent-client.d.ts +60 -0
  3. package/dist/client/agent-client.js +322 -0
  4. package/dist/client/agent-launcher.d.ts +30 -0
  5. package/dist/client/agent-launcher.js +339 -0
  6. package/dist/client/types.d.ts +88 -0
  7. package/dist/client/types.js +2 -0
  8. package/dist/commands/apikey.d.ts +3 -0
  9. package/dist/commands/apikey.js +123 -0
  10. package/dist/commands/browser.d.ts +2 -0
  11. package/dist/commands/browser.js +35 -0
  12. package/dist/commands/mcp.d.ts +3 -0
  13. package/dist/commands/mcp.js +102 -0
  14. package/dist/commands/mic.d.ts +2 -0
  15. package/dist/commands/mic.js +57 -0
  16. package/dist/commands/skills.d.ts +3 -0
  17. package/dist/commands/skills.js +105 -0
  18. package/dist/config/env.d.ts +6 -0
  19. package/dist/config/env.js +71 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +126 -0
  22. package/dist/ui/autocomplete.d.ts +25 -0
  23. package/dist/ui/autocomplete.js +142 -0
  24. package/dist/ui/banner.d.ts +24 -0
  25. package/dist/ui/banner.js +207 -0
  26. package/dist/ui/chat.d.ts +1 -0
  27. package/dist/ui/chat.js +5 -0
  28. package/dist/ui/colors.d.ts +34 -0
  29. package/dist/ui/colors.js +69 -0
  30. package/dist/ui/repl.d.ts +31 -0
  31. package/dist/ui/repl.js +402 -0
  32. package/package.json +31 -4
  33. package/src/client/agent-client.ts +387 -0
  34. package/src/client/agent-launcher.ts +374 -0
  35. package/src/client/types.ts +95 -0
  36. package/src/commands/apikey.ts +129 -0
  37. package/src/commands/browser.ts +39 -0
  38. package/src/commands/mcp.ts +105 -0
  39. package/src/commands/mic.ts +57 -0
  40. package/src/commands/skills.ts +109 -0
  41. package/src/config/env.ts +63 -0
  42. package/src/index.ts +139 -0
  43. package/src/ui/autocomplete.ts +153 -0
  44. package/src/ui/banner.ts +240 -0
  45. package/src/ui/chat.ts +1 -0
  46. package/src/ui/colors.ts +70 -0
  47. package/src/ui/repl.ts +473 -0
  48. package/tests/cli.test.ts +141 -0
  49. package/tsconfig.json +18 -0
  50. package/tsconfig.test.json +7 -0
  51. package/README.md +0 -3
@@ -0,0 +1,24 @@
1
+ export interface BannerStatusOptions {
2
+ connected: boolean;
3
+ wsUrl: string;
4
+ voiceEnabled: boolean;
5
+ isCapturingVoice?: boolean;
6
+ currentModel?: string | null;
7
+ activeTasksCount?: number;
8
+ }
9
+ export declare function getAsciiLogo(terminalWidth?: number): string;
10
+ /**
11
+ * Compact, badge-style status bar.
12
+ */
13
+ export declare function getStatusBar(options: BannerStatusOptions): string;
14
+ /**
15
+ * Renders the persistent header. Clears screen only if clearScreen is explicitly true.
16
+ */
17
+ export declare function renderHeader(options: BannerStatusOptions, clearScreen?: boolean): void;
18
+ /**
19
+ * Voice-capture indicator badge (for inline use in prompts).
20
+ */
21
+ export declare function getVoiceIndicator(isCapturing: boolean, voiceEnabled: boolean): string;
22
+ export declare const HELIX_LOGO_ASCII: number[][][];
23
+ export declare const HELIX_BIG_ART: number[][][];
24
+ export declare const HELIX_HARD_BLOCKS: number[][][];
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HELIX_HARD_BLOCKS = exports.HELIX_BIG_ART = exports.HELIX_LOGO_ASCII = void 0;
7
+ exports.getAsciiLogo = getAsciiLogo;
8
+ exports.getStatusBar = getStatusBar;
9
+ exports.renderHeader = renderHeader;
10
+ exports.getVoiceIndicator = getVoiceIndicator;
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ // ═══════════════════════════════════════════════════════════════
13
+ // HELIX — Pixel-art dot-matrix logo.
14
+ // Each letter is drawn on an 8-row × 5-col grid.
15
+ // "On" pixels → "██" block, "off" pixels → " " (space).
16
+ // Gradient runs top → bottom:
17
+ // rows 0-1 : bright white/cream
18
+ // rows 2-3 : bright yellow
19
+ // rows 4-5 : orange
20
+ // rows 6-7 : deep red
21
+ // Matches the pixel-art HELIX image with yellow→orange→red gradient.
22
+ // ═══════════════════════════════════════════════════════════════
23
+ // ── Letter bitmaps — 1=on, 0=off, 8 rows × 5 cols each ────────
24
+ const H = [
25
+ [1, 0, 0, 0, 1],
26
+ [1, 0, 0, 0, 1],
27
+ [1, 1, 1, 1, 1],
28
+ [1, 1, 1, 1, 1],
29
+ [1, 1, 1, 1, 1],
30
+ [1, 0, 0, 0, 1],
31
+ [1, 0, 0, 0, 1],
32
+ [1, 0, 0, 0, 1],
33
+ ];
34
+ const E = [
35
+ [1, 1, 1, 1, 1],
36
+ [1, 0, 0, 0, 0],
37
+ [1, 1, 1, 1, 0],
38
+ [1, 1, 1, 1, 0],
39
+ [1, 1, 1, 1, 0],
40
+ [1, 0, 0, 0, 0],
41
+ [1, 0, 0, 0, 0],
42
+ [1, 1, 1, 1, 1],
43
+ ];
44
+ const L = [
45
+ [1, 0, 0, 0, 0],
46
+ [1, 0, 0, 0, 0],
47
+ [1, 0, 0, 0, 0],
48
+ [1, 0, 0, 0, 0],
49
+ [1, 0, 0, 0, 0],
50
+ [1, 0, 0, 0, 0],
51
+ [1, 0, 0, 0, 0],
52
+ [1, 1, 1, 1, 1],
53
+ ];
54
+ const I = [
55
+ [1, 1, 1, 1, 1],
56
+ [0, 0, 1, 0, 0],
57
+ [0, 0, 1, 0, 0],
58
+ [0, 0, 1, 0, 0],
59
+ [0, 0, 1, 0, 0],
60
+ [0, 0, 1, 0, 0],
61
+ [0, 0, 1, 0, 0],
62
+ [1, 1, 1, 1, 1],
63
+ ];
64
+ const X = [
65
+ [1, 0, 0, 0, 1],
66
+ [1, 1, 0, 1, 1],
67
+ [0, 1, 1, 1, 0],
68
+ [0, 0, 1, 0, 0],
69
+ [0, 0, 1, 0, 0],
70
+ [0, 1, 1, 1, 0],
71
+ [1, 1, 0, 1, 1],
72
+ [1, 0, 0, 0, 1],
73
+ ];
74
+ const LETTERS = [H, E, L, I, X];
75
+ const LETTER_GAP = 1; // 1 empty col between letters
76
+ const ROWS = 8;
77
+ const COLS_PER_LETTER = 5;
78
+ // ── Top-to-bottom gradient — cream/white → yellow → orange → red ──
79
+ // Row 0 = top, row 7 = bottom
80
+ const ROW_COLORS = [
81
+ '#FFF9E0', // 0 — near-white cream
82
+ '#FFE84D', // 1 — bright yellow
83
+ '#FFD200', // 2 — gold yellow
84
+ '#FFB300', // 3 — amber
85
+ '#FF8C00', // 4 — orange
86
+ '#FF6600', // 5 — deep orange
87
+ '#E63000', // 6 — red-orange
88
+ '#CC1A00', // 7 — deep red
89
+ ];
90
+ const BLOCK_ON = '██'; // filled square block
91
+ const BLOCK_OFF = ' '; // empty (black background)
92
+ // ───────────────────────────────────────────────────────────────
93
+ // Public API
94
+ // ───────────────────────────────────────────────────────────────
95
+ function getAsciiLogo(terminalWidth = 80) {
96
+ // total character width: each cell = 2 chars
97
+ const totalCols = LETTERS.length * COLS_PER_LETTER + (LETTERS.length - 1) * LETTER_GAP;
98
+ const totalChars = totalCols * 2;
99
+ const leftPad = Math.max(0, Math.floor((terminalWidth - totalChars) / 2));
100
+ const pad = ' '.repeat(leftPad);
101
+ const lines = [];
102
+ for (let row = 0; row < ROWS; row++) {
103
+ let line = pad;
104
+ for (let li = 0; li < LETTERS.length; li++) {
105
+ const letter = LETTERS[li];
106
+ for (let col = 0; col < COLS_PER_LETTER; col++) {
107
+ if (letter[row][col]) {
108
+ line += chalk_1.default.hex(ROW_COLORS[row]).bold(BLOCK_ON);
109
+ }
110
+ else {
111
+ line += BLOCK_OFF;
112
+ }
113
+ }
114
+ // gap between letters
115
+ if (li < LETTERS.length - 1) {
116
+ line += BLOCK_OFF.repeat(LETTER_GAP);
117
+ }
118
+ }
119
+ lines.push(line);
120
+ }
121
+ return lines.join('\n');
122
+ }
123
+ /**
124
+ * Compact, badge-style status bar.
125
+ */
126
+ function getStatusBar(options) {
127
+ // ── Connection ──
128
+ const conn = options.connected
129
+ ? `${chalk_1.default.green('●')} ${chalk_1.default.greenBright.bold('CONECTADO')} ${chalk_1.default.gray(options.wsUrl)}`
130
+ : `${chalk_1.default.red('●')} ${chalk_1.default.redBright.bold('DESCONECTADO')} ${chalk_1.default.gray(options.wsUrl)}`;
131
+ // ── Microphone ──
132
+ let mic;
133
+ if (options.isCapturingVoice) {
134
+ mic = chalk_1.default.bgRed.white.bold(' 🎙️ CAPTURANDO ');
135
+ }
136
+ else if (options.voiceEnabled) {
137
+ mic = `${chalk_1.default.green('●')} ${chalk_1.default.white('Mic')} ${chalk_1.default.gray('"hey helix"')}`;
138
+ }
139
+ else {
140
+ mic = `${chalk_1.default.red('●')} ${chalk_1.default.gray('Mic Off')}`;
141
+ }
142
+ // ── Model ──
143
+ const model = options.currentModel
144
+ ? `${chalk_1.default.hex('#FF9F1C')('⚡')} ${chalk_1.default.white(options.currentModel)}`
145
+ : `${chalk_1.default.hex('#FF9F1C')('⚡')} ${chalk_1.default.white('Local ReAct')}`;
146
+ // ── Active tasks ──
147
+ const tasks = (options.activeTasksCount ?? 0) > 0
148
+ ? ` ${chalk_1.default.yellow('⏳')} ${chalk_1.default.yellowBright(String(options.activeTasksCount))}`
149
+ : '';
150
+ const sep = chalk_1.default.gray(' │ ');
151
+ return ` ${conn}${sep}${mic}${sep}${model}${tasks}`;
152
+ }
153
+ /**
154
+ * Renders the persistent header. Clears screen only if clearScreen is explicitly true.
155
+ */
156
+ function renderHeader(options, clearScreen = false) {
157
+ if (clearScreen) {
158
+ // Clear screen + move cursor to top-left
159
+ process.stdout.write('\x1bc');
160
+ }
161
+ const width = process.stdout.columns || 80;
162
+ // ── Logo ──
163
+ const logo = getAsciiLogo(width);
164
+ // ── Tagline ──
165
+ const tagline = 'Persistent AI Desktop Agent';
166
+ const tagPad = Math.max(0, Math.floor((width - tagline.length - 8) / 2));
167
+ const subtitle = ' '.repeat(tagPad) +
168
+ chalk_1.default.gray('╶───') +
169
+ ' ' +
170
+ chalk_1.default.hex('#FF9F1C')(tagline) +
171
+ ' ' +
172
+ chalk_1.default.gray('───╴');
173
+ // ── Status bar ──
174
+ const statusBar = getStatusBar(options);
175
+ // ── Visual lines ──
176
+ const thinLine = chalk_1.default.gray('─'.repeat(width));
177
+ // ── Render ──
178
+ console.log('');
179
+ console.log(logo);
180
+ console.log('');
181
+ console.log(subtitle);
182
+ console.log('');
183
+ console.log(thinLine);
184
+ console.log(statusBar);
185
+ console.log(thinLine);
186
+ console.log(` ${chalk_1.default.hex('#FF8C00')('@skill')} ${chalk_1.default.gray('Skills')} ${chalk_1.default.gray('│')} ` +
187
+ `${chalk_1.default.cyan('#mcp')} ${chalk_1.default.gray('Herramientas')} ${chalk_1.default.gray('│')} ` +
188
+ `${chalk_1.default.magenta('/help')} ${chalk_1.default.gray('Comandos')}`);
189
+ console.log(thinLine);
190
+ console.log('');
191
+ }
192
+ /**
193
+ * Voice-capture indicator badge (for inline use in prompts).
194
+ */
195
+ function getVoiceIndicator(isCapturing, voiceEnabled) {
196
+ if (isCapturing) {
197
+ return chalk_1.default.bgRed.white.bold(' 🎙️ VOZ DETECTADA [HEY HELIX] 🔊 ');
198
+ }
199
+ if (voiceEnabled) {
200
+ return chalk_1.default.green('🟢 [Mic Activo]');
201
+ }
202
+ return chalk_1.default.red('🔴 [Mic Inactivo]');
203
+ }
204
+ // Legacy named exports kept for compatibility with other modules
205
+ exports.HELIX_LOGO_ASCII = LETTERS;
206
+ exports.HELIX_BIG_ART = LETTERS;
207
+ exports.HELIX_HARD_BLOCKS = LETTERS;
@@ -0,0 +1 @@
1
+ export { HelixRepl, type ReplOptions } from './repl';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HelixRepl = void 0;
4
+ var repl_1 = require("./repl");
5
+ Object.defineProperty(exports, "HelixRepl", { enumerable: true, get: function () { return repl_1.HelixRepl; } });
@@ -0,0 +1,34 @@
1
+ import chalk from 'chalk';
2
+ export declare const customChalk: chalk.Chalk;
3
+ export declare const ORANGE: chalk.Chalk;
4
+ export declare const ORANGE_BOLD: chalk.Chalk;
5
+ export declare const ORANGE_BG: chalk.Chalk;
6
+ export declare const CYAN: chalk.Chalk;
7
+ export declare const CYAN_BOLD: chalk.Chalk;
8
+ export declare const MAGENTA: chalk.Chalk;
9
+ export declare const MAGENTA_BOLD: chalk.Chalk;
10
+ export declare const GREEN: chalk.Chalk;
11
+ export declare const GREEN_BOLD: chalk.Chalk;
12
+ export declare const RED: chalk.Chalk;
13
+ export declare const RED_BOLD: chalk.Chalk;
14
+ export declare const YELLOW: chalk.Chalk;
15
+ export declare const YELLOW_BOLD: chalk.Chalk;
16
+ export declare const GRAY: chalk.Chalk;
17
+ export declare const BOLD: chalk.Chalk;
18
+ export declare const DIM: chalk.Chalk;
19
+ /**
20
+ * Highlights skill names with strong orange (#FF8C00).
21
+ */
22
+ export declare function formatSkill(name: string): string;
23
+ /**
24
+ * Highlights MCP tool/server names.
25
+ */
26
+ export declare function formatMcp(name: string): string;
27
+ /**
28
+ * Highlights slash commands.
29
+ */
30
+ export declare function formatCommand(cmd: string): string;
31
+ /**
32
+ * Formats user input text highlighting @skills in orange and #mcps in cyan.
33
+ */
34
+ export declare function highlightMentions(text: string, knownSkills?: string[]): string;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DIM = exports.BOLD = exports.GRAY = exports.YELLOW_BOLD = exports.YELLOW = exports.RED_BOLD = exports.RED = exports.GREEN_BOLD = exports.GREEN = exports.MAGENTA_BOLD = exports.MAGENTA = exports.CYAN_BOLD = exports.CYAN = exports.ORANGE_BG = exports.ORANGE_BOLD = exports.ORANGE = exports.customChalk = void 0;
7
+ exports.formatSkill = formatSkill;
8
+ exports.formatMcp = formatMcp;
9
+ exports.formatCommand = formatCommand;
10
+ exports.highlightMentions = highlightMentions;
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ exports.customChalk = new chalk_1.default.Instance({ level: 3 });
13
+ // Brand colors
14
+ exports.ORANGE = exports.customChalk.hex('#FF8C00');
15
+ exports.ORANGE_BOLD = exports.customChalk.hex('#FF8C00').bold;
16
+ exports.ORANGE_BG = exports.customChalk.bgHex('#FF8C00').black.bold;
17
+ exports.CYAN = exports.customChalk.cyan;
18
+ exports.CYAN_BOLD = exports.customChalk.cyan.bold;
19
+ exports.MAGENTA = exports.customChalk.magenta;
20
+ exports.MAGENTA_BOLD = exports.customChalk.magenta.bold;
21
+ exports.GREEN = exports.customChalk.green;
22
+ exports.GREEN_BOLD = exports.customChalk.green.bold;
23
+ exports.RED = exports.customChalk.red;
24
+ exports.RED_BOLD = exports.customChalk.red.bold;
25
+ exports.YELLOW = exports.customChalk.yellow;
26
+ exports.YELLOW_BOLD = exports.customChalk.yellow.bold;
27
+ exports.GRAY = exports.customChalk.gray;
28
+ exports.BOLD = exports.customChalk.bold;
29
+ exports.DIM = exports.customChalk.dim;
30
+ /**
31
+ * Highlights skill names with strong orange (#FF8C00).
32
+ */
33
+ function formatSkill(name) {
34
+ const clean = name.startsWith('@') ? name : `@${name}`;
35
+ return (0, exports.ORANGE_BOLD)(clean);
36
+ }
37
+ /**
38
+ * Highlights MCP tool/server names.
39
+ */
40
+ function formatMcp(name) {
41
+ const clean = name.startsWith('#') ? name : `#${name}`;
42
+ return (0, exports.CYAN_BOLD)(clean);
43
+ }
44
+ /**
45
+ * Highlights slash commands.
46
+ */
47
+ function formatCommand(cmd) {
48
+ const clean = cmd.startsWith('/') ? cmd : `/${cmd}`;
49
+ return (0, exports.MAGENTA_BOLD)(clean);
50
+ }
51
+ /**
52
+ * Formats user input text highlighting @skills in orange and #mcps in cyan.
53
+ */
54
+ function highlightMentions(text, knownSkills = []) {
55
+ let result = text;
56
+ // Highlight @skill in orange
57
+ result = result.replace(/(^|\s)(@[a-zA-Z0-9_-]+)/g, (_match, prefix, mention) => {
58
+ return `${prefix}${(0, exports.ORANGE_BOLD)(mention)}`;
59
+ });
60
+ // Highlight #mcp in cyan
61
+ result = result.replace(/(^|\s)(#[a-zA-Z0-9_-]+)/g, (_match, prefix, mention) => {
62
+ return `${prefix}${(0, exports.CYAN_BOLD)(mention)}`;
63
+ });
64
+ // Highlight /commands in magenta
65
+ result = result.replace(/(^|\s)(\/[a-zA-Z0-9_-]+)/g, (_match, prefix, mention) => {
66
+ return `${prefix}${(0, exports.MAGENTA_BOLD)(mention)}`;
67
+ });
68
+ return result;
69
+ }
@@ -0,0 +1,31 @@
1
+ export interface ReplOptions {
2
+ wsUrl: string;
3
+ wsToken?: string;
4
+ }
5
+ export declare class HelixRepl {
6
+ private options;
7
+ private rl;
8
+ private client;
9
+ private autocompleter;
10
+ private conversationId;
11
+ private conversationHistory;
12
+ private voiceEnabled;
13
+ private isCapturingVoice;
14
+ private currentModel;
15
+ private activeTaskId;
16
+ private activeTasksCount;
17
+ private isProcessingPrompt;
18
+ constructor(options: ReplOptions);
19
+ start(): Promise<void>;
20
+ private _syncSettings;
21
+ refreshBanner(clearScreen?: boolean): void;
22
+ private waitingLogged;
23
+ private _setupClientEvents;
24
+ private _handleConfirmationDialog;
25
+ private _startReadline;
26
+ private _promptUser;
27
+ private _handleInputLine;
28
+ private _handleListTasks;
29
+ private _handleListModels;
30
+ private _handleStatus;
31
+ }