@taj-special/dravix-code 1.1.28 → 1.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.
@@ -1,8 +1,8 @@
1
1
  import { execFileSync } from 'child_process';
2
2
  import { buildContext } from '../services/context.js';
3
- import chalk from 'chalk';
4
3
  import { banner, printHelp, printInfo, colors } from '../utils/display.js';
5
4
  import { logout, getSavedUser, checkPlan } from '../services/auth.js';
5
+ import { undoLastSession, listUndoSessions } from '../services/undo.js';
6
6
  export async function handleCommand(cmd, cwd, clearHistory, addFileToContext, getLastAI, retryLast) {
7
7
  const parts = cmd.trim().split(/\s+/);
8
8
  const name = parts[0].toLowerCase();
@@ -23,11 +23,11 @@ export async function handleCommand(cmd, cwd, clearHistory, addFileToContext, ge
23
23
  }
24
24
  const plan = email ? await checkPlan(email) : 'Free';
25
25
  const planBadge = plan === 'Plus'
26
- ? chalk.hex('#fcd34d').bold('Plus')
27
- : chalk.hex('#4b5563')('Free');
28
- const W = chalk.hex('#e2e8f0');
26
+ ? colors.accent.bold('Plus')
27
+ : colors.muted('Free');
28
+ const W = colors.text;
29
29
  process.stdout.write('\n ' + colors.success('✓') + ' ' + W(n) +
30
- chalk.hex('#4b5563')(' · ') + colors.muted(email ?? '') +
30
+ colors.subtext(' · ') + colors.muted(email ?? '') +
31
31
  '\n ' + colors.muted(' Plan ') + planBadge + '\n\n');
32
32
  return true;
33
33
  }
@@ -40,9 +40,9 @@ export async function handleCommand(cmd, cwd, clearHistory, addFileToContext, ge
40
40
  console.clear();
41
41
  banner();
42
42
  const { name: userName } = getSavedUser();
43
- const C = chalk.hex('#818cf8');
44
- const DIM = chalk.hex('#4b5563');
45
- const W = chalk.hex('#e2e8f0');
43
+ const C = colors.primary;
44
+ const DIM = colors.subtext;
45
+ const W = colors.text;
46
46
  console.log(DIM(' ─────────────────────────────────────────────'));
47
47
  console.log(colors.success(' ✓') + W(' New session started — your chat history is saved'));
48
48
  console.log(colors.muted(' ') + colors.muted('Use ') + C('/resume') + colors.muted(' to return to any previous conversation'));
@@ -95,6 +95,32 @@ export async function handleCommand(cmd, cwd, clearHistory, addFileToContext, ge
95
95
  colors.muted(' · by Taj Special\n\n'));
96
96
  return true;
97
97
  }
98
+ if (name === '/undo') {
99
+ const result = undoLastSession(cwd);
100
+ if (result.success) {
101
+ console.log('\n ' + colors.success('✓') + ' ' + colors.text(result.message) + '\n');
102
+ }
103
+ else {
104
+ console.log('\n ' + colors.error('✗') + ' ' + colors.muted(result.message) + '\n');
105
+ }
106
+ return true;
107
+ }
108
+ if (name === '/history') {
109
+ const sessions = listUndoSessions();
110
+ if (sessions.length === 0) {
111
+ printInfo('No undo history found.');
112
+ }
113
+ else {
114
+ console.log('\n ' + colors.primary('Undo History'));
115
+ console.log(' ' + colors.dim('─'.repeat(40)));
116
+ for (const s of sessions.slice(0, 10)) {
117
+ const time = new Date(s.timestamp).toLocaleString();
118
+ console.log(' ' + colors.muted('·') + ' ' + colors.text(time) + ' ' + colors.muted(`${s.ops} operation(s)`));
119
+ }
120
+ console.log('');
121
+ }
122
+ return true;
123
+ }
98
124
  printInfo(`Unknown command: ${cmd} (type /help for list)`);
99
125
  return true;
100
126
  }
package/dist/cli/index.js CHANGED
@@ -3,27 +3,15 @@ import * as path from 'path';
3
3
  import { randomBytes } from 'crypto';
4
4
  import { execSync } from 'child_process';
5
5
  import chalk from 'chalk';
6
- import { banner, printHelp, printError, colors, VERSION } from '../utils/display.js';
6
+ import { banner, printHelp, printError, colors } from '../utils/display.js';
7
7
  import { startRepl } from './repl.js';
8
8
  import { isLoggedIn, logout, getSavedUser, saveConfig, checkPlan, AUTH_URL } from '../services/auth.js';
9
9
  import { checkUsage, usageBar, fmtNum, formatResetTime } from '../services/usage.js';
10
- const POLL_URL = 'https://dravix.app/cli-auth';
10
+ const POLL_URL = 'https://dravix.app/cli-auth.php';
11
11
  const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
12
- // OSC 8 terminal hyperlink — clickable in modern terminals
13
12
  function link(url) {
14
13
  return `\x1b]8;;${url}\x1b\\${url}\x1b]8;;\x1b\\`;
15
14
  }
16
- function openBrowser(url) {
17
- try {
18
- if (process.platform === 'win32')
19
- execSync(`start "" "${url}"`, { stdio: 'ignore' });
20
- else if (process.platform === 'darwin')
21
- execSync(`open "${url}"`, { stdio: 'ignore' });
22
- else
23
- execSync(`xdg-open "${url}"`, { stdio: 'ignore' });
24
- }
25
- catch { /* ignore — user sees the URL */ }
26
- }
27
15
  async function pollSession(sessionId) {
28
16
  try {
29
17
  const res = await fetch(`${POLL_URL}?action=poll&session=${sessionId}`);
@@ -38,34 +26,18 @@ async function pollSession(sessionId) {
38
26
  async function showWelcome() {
39
27
  const cols = process.stdout.columns ?? 80;
40
28
  const W = Math.min(cols, 64);
41
- const P = chalk.hex('#818cf8');
42
- const PB = chalk.hex('#6366f1').bold;
43
- const DIM = chalk.hex('#4b5563');
44
- const G = chalk.hex('#34d399');
45
- const White = chalk.hex('#e2e8f0');
46
- const Muted = chalk.hex('#6b7280');
29
+ const P = colors.primary;
30
+ const PB = colors.primary.bold;
31
+ const DIM = colors.muted;
32
+ const G = colors.success;
33
+ const White = colors.text;
34
+ const Muted = colors.muted;
47
35
  const line = () => DIM(' ' + '─'.repeat(W - 4));
48
36
  const pad = (s, w) => s + ' '.repeat(Math.max(w - s.length, 0));
49
37
  console.clear();
50
- // ── Logo ──────────────────────────────────────────────────────
51
- console.log(chalk.hex('#6366f1').bold(`
52
- ██████╗ ██████╗ █████╗ ██╗ ██╗██╗██╗ ██╗
53
- ██╔══██╗██╔══██╗██╔══██╗██║ ██║██║╚██╗██╔╝
54
- ██║ ██║██████╔╝███████║██║ ██║██║ ╚███╔╝
55
- ██║ ██║██╔══██╗██╔══██║╚██╗ ██╔╝██║ ██╔██╗
56
- ██████╔╝██║ ██║██║ ██║ ╚████╔╝ ██║██╔╝ ██╗
57
- ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝`));
58
- console.log(PB(' Code') +
59
- DIM(` v${VERSION}`) +
60
- DIM(' ·') +
61
- P(' AI-powered coding assistant') +
62
- DIM(' ·') +
63
- Muted(' by Taj Special'));
64
- console.log(line() + '\n');
65
- // ── Welcome ───────────────────────────────────────────────────
38
+ banner();
66
39
  console.log(' ' + White.bold('Welcome to Dravix Code') + Muted(' — your AI coding partner'));
67
40
  console.log(' ' + Muted('Works like Claude Code, Cursor, Copilot — but in your terminal.') + '\n');
68
- // ── Features box ──────────────────────────────────────────────
69
41
  const boxW = Math.min(W - 4, 58);
70
42
  const inner = boxW - 2;
71
43
  const BC = DIM;
@@ -83,13 +55,11 @@ async function showWelcome() {
83
55
  console.log(row(G('✓'), 'Read files, folders and project structure'));
84
56
  console.log(row(G('✓'), 'Works with TypeScript, Python, Go and more'));
85
57
  console.log(' ' + BC('╰' + '─'.repeat(boxW - 2) + '╯') + '\n');
86
- // ── Models ────────────────────────────────────────────────────
87
58
  console.log(' ' + Muted('Powered by ') +
88
59
  P.bold('Dravix 3 Titanium') +
89
60
  Muted(' + ') +
90
61
  P.bold('Dravix 3.5 Quantum'));
91
62
  console.log(line() + '\n');
92
- // ── CTA ───────────────────────────────────────────────────────
93
63
  console.log(' ' + Muted('Sign in with your Google account to get started.') + '\n');
94
64
  const enterKey = chalk.bgHex('#312e81').hex('#c7d2fe').bold(' Enter ');
95
65
  const escKey = chalk.hex('#374151').bold(' Esc ');
@@ -121,21 +91,13 @@ async function showWelcome() {
121
91
  async function browserAuth() {
122
92
  const sessionId = randomBytes(16).toString('hex');
123
93
  const authUrl = `${AUTH_URL}?session=${sessionId}`;
124
- const DIM = chalk.hex('#4b5563');
125
- const W = chalk.hex('#e2e8f0');
126
- const P = chalk.hex('#818cf8');
94
+ const DIM = colors.muted;
95
+ const W = colors.text;
96
+ const P = colors.primary;
127
97
  const cols = process.stdout.columns ?? 80;
128
98
  const line = DIM(' ' + '─'.repeat(Math.min(cols - 4, 51)));
129
99
  console.clear();
130
- console.log(chalk.hex('#6366f1').bold(`
131
- ██████╗ ██████╗ █████╗ ██╗ ██╗██╗██╗ ██╗
132
- ██╔══██╗██╔══██╗██╔══██╗██║ ██║██║╚██╗██╔╝
133
- ██║ ██║██████╔╝███████║██║ ██║██║ ╚███╔╝
134
- ██║ ██║██╔══██╗██╔══██║╚██╗ ██╔╝██║ ██╔██╗
135
- ██████╔╝██║ ██║██║ ██║ ╚████╔╝ ██║██╔╝ ██╗
136
- ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝`));
137
- console.log(chalk.hex('#6366f1').bold(' Code') + DIM(` v${VERSION} · `) + P('AI-powered coding assistant'));
138
- console.log(line + '\n');
100
+ banner();
139
101
  console.log(line);
140
102
  console.log('\n ' + DIM('Step 1 — ') + W('Open this link in your browser:') + '\n');
141
103
  console.log(' ' + colors.primary(link(authUrl)) + '\n');
@@ -145,14 +107,12 @@ async function browserAuth() {
145
107
  let frameIdx = 0;
146
108
  await new Promise((resolve, reject) => {
147
109
  let done = false;
148
- // Spinner runs fast (80ms)
149
110
  const spinnerInterval = setInterval(() => {
150
111
  if (done)
151
112
  return;
152
113
  process.stdout.write(`\r ${colors.muted(SPINNER[frameIdx % SPINNER.length])} ${colors.muted('Waiting for authentication...')}`);
153
114
  frameIdx++;
154
115
  }, 80);
155
- // Polling runs every 2s
156
116
  const poll = async () => {
157
117
  if (done)
158
118
  return;
@@ -162,10 +122,8 @@ async function browserAuth() {
162
122
  clearInterval(spinnerInterval);
163
123
  process.stdout.write('\r\x1b[K');
164
124
  saveConfig({ token: result.token, name: result.name, email: result.email });
165
- const DIM2 = chalk.hex('#4b5563');
166
- const W2 = chalk.hex('#e2e8f0');
167
- console.log(' ' + colors.success('✓') + ' ' + W2('Signed in as ') + colors.primary.bold(result.name) + DIM2(' · ') + colors.muted(result.email));
168
- console.log(DIM2('\n ' + '─'.repeat(47)) + '\n');
125
+ console.log(' ' + colors.success('✓') + ' ' + W('Signed in as ') + colors.primary.bold(result.name) + DIM(' · ') + colors.muted(result.email));
126
+ console.log(DIM('\n ' + '─'.repeat(47)) + '\n');
169
127
  resolve();
170
128
  return;
171
129
  }
@@ -183,7 +141,6 @@ async function browserAuth() {
183
141
  });
184
142
  }
185
143
  async function main() {
186
- // Ensure UTF-8 output on Windows
187
144
  if (process.platform === 'win32') {
188
145
  try {
189
146
  execSync('chcp 65001', { stdio: 'ignore' });
@@ -218,48 +175,31 @@ async function main() {
218
175
  else {
219
176
  banner();
220
177
  }
221
- if (justAuthenticated) {
222
- const _DIM = chalk.hex('#4b5563');
223
- const _P = chalk.hex('#818cf8');
224
- const _cols = process.stdout.columns ?? 80;
225
- const _line = _DIM(' ' + '─'.repeat(Math.min(_cols - 4, 51)));
226
- console.clear();
227
- console.log(chalk.hex('#6366f1').bold(`
228
- ██████╗ ██████╗ █████╗ ██╗ ██╗██╗██╗ ██╗
229
- ██╔══██╗██╔══██╗██╔══██╗██║ ██║██║╚██╗██╔╝
230
- ██║ ██║██████╔╝███████║██║ ██║██║ ╚███╔╝
231
- ██║ ██║██╔══██╗██╔══██║╚██╗ ██╔╝██║ ██╔██╗
232
- ██████╔╝██║ ██║██║ ██║ ╚████╔╝ ██║██╔╝ ██╗
233
- ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝`));
234
- console.log(chalk.hex('#6366f1').bold(' Code') + _DIM(` v${VERSION} · `) + _P('AI-powered coding assistant'));
235
- console.log(_line + '\n');
236
- }
237
178
  const { name, email } = getSavedUser();
238
179
  const cwd = (arg && !arg.startsWith('--')) ? path.resolve(arg) : process.cwd();
239
- // Fetch plan + usage in parallel
240
180
  const token = (await import('../services/auth.js')).getToken() ?? '';
241
181
  const [plan, usage] = await Promise.all([
242
182
  email ? checkPlan(email) : Promise.resolve('Free'),
243
183
  token ? checkUsage(token) : Promise.resolve(null),
244
184
  ]);
245
- const C = chalk.hex('#818cf8');
246
- const DIM = chalk.hex('#4b5563');
247
- const W = chalk.hex('#e2e8f0');
185
+ const C = colors.primary;
186
+ const DIM = colors.muted;
187
+ const W = colors.text;
248
188
  const planBadge = plan === 'Plus'
249
- ? chalk.hex('#fcd34d').bold('Plus')
250
- : chalk.hex('#4b5563')('Free');
189
+ ? colors.accent.bold('Plus')
190
+ : colors.muted('Free');
251
191
  console.log(DIM(' ' + '─'.repeat(45)));
252
192
  console.log(colors.muted(' User ') + W(name ?? 'Unknown') + DIM(' · ') + colors.muted(email ?? ''));
253
193
  console.log(colors.muted(' Plan ') + planBadge);
254
194
  if (usage) {
255
195
  const { bar, pct } = usageBar(usage.tokens_used, usage.limit);
256
- const barColor = pct >= 80 ? chalk.hex('#f87171')
257
- : pct >= 50 ? chalk.hex('#fbbf24')
258
- : chalk.hex('#34d399');
196
+ const barColor = pct >= 80 ? colors.error
197
+ : pct >= 50 ? colors.warn
198
+ : colors.success;
259
199
  const resetStr = formatResetTime(usage);
260
200
  console.log(colors.muted(' Tokens ') +
261
201
  barColor(bar) + ' ' +
262
- chalk.hex('#94a3b8')(fmtNum(usage.tokens_used) + ' / ' + fmtNum(usage.limit)) +
202
+ colors.subtext(fmtNum(usage.tokens_used) + ' / ' + fmtNum(usage.limit)) +
263
203
  DIM(' · resets in ' + resetStr));
264
204
  }
265
205
  console.log(colors.muted(' Project ') + W(path.basename(cwd)));