@hemacharanpyla/infinitycli 1.0.5 → 1.0.6

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 (3) hide show
  1. package/README.md +143 -0
  2. package/chat.js +46 -25
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # ∞ Infinity CLI
2
+
3
+ **Terminal AI chat with ChatGPT via Puppeteer — real-time response timing, box-drawn UI, zero-config setup.**
4
+
5
+ ![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)
6
+ ![npm](https://img.shields.io/npm/v/@hemacharanpyla/infinitycli)
7
+ ![License](https://img.shields.io/npm/l/@hemacharanpyla/infinitycli)
8
+
9
+ ---
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ npm install -g @hemacharanpyla/infinitycli
15
+ infinity
16
+ ```
17
+
18
+ The server **auto-starts** on first launch — no manual `node server.js`.
19
+
20
+ ## Requirements
21
+
22
+ - **Node.js >= 18**
23
+ - **Chrome** at default path: `C:\Program Files\Google\Chrome\Application\chrome.exe`
24
+ - **ChatGPT cookies** (see [Cookie Setup](#cookie-setup))
25
+
26
+ ## Cookie Setup
27
+
28
+ Infinity CLI uses your ChatGPT session cookies to interact with ChatGPT on your behalf.
29
+
30
+ ### Export your cookies
31
+
32
+ 1. Install a cookie export extension (e.g. [EditThisCookie](https://www.editthiscookie.com/))
33
+ 2. Log in to [chatgpt.com](https://chatgpt.com)
34
+ 3. Export cookies as JSON
35
+ 4. Save the file to one of these locations:
36
+
37
+ **Recommended (home dir):**
38
+ ```
39
+ %USERPROFILE%\.infinitycli\cookies\chatgpt.json
40
+ ```
41
+
42
+ **Or via environment variable:**
43
+ ```bash
44
+ set COOKIES_PATH=C:\path\to\chatgpt.json
45
+ infinity
46
+ ```
47
+
48
+ ## Features
49
+
50
+ ### Dashboard
51
+ - Welcome message with username
52
+ - Current model (GPT-4o), plan, and working directory
53
+ - Tips list and recent activity
54
+
55
+ ### Chat
56
+ - Send messages to ChatGPT via the terminal
57
+ - Response timing displayed per message (`╰ 1.4s`)
58
+ - Message history with scrolling
59
+ - Loading spinner during responses
60
+
61
+ ### Commands
62
+
63
+ | Command | Description |
64
+ |---------|-------------|
65
+ | `/help` or `/h` or `/?` | Show help panel |
66
+ | `/clear` or `/cls` | Clear conversation |
67
+ | `/exit` or `/quit` | Exit session |
68
+ | `/status` | Show session & connection info |
69
+ | `?` | Toggle help panel |
70
+
71
+ ### Keyboard Shortcuts
72
+
73
+ | Key | Action |
74
+ |-----|--------|
75
+ | `Enter` | Send message |
76
+ | `Shift+Enter` | Newline in input |
77
+ | `↑` / `↓` | History navigation |
78
+ | `Ctrl+L` | Clear chat |
79
+ | `Ctrl+U` | Clear current input |
80
+ | `Ctrl+C` | Exit application |
81
+
82
+ ## Environment Variables
83
+
84
+ | Variable | Default | Description |
85
+ |----------|---------|-------------|
86
+ | `API_BASE` | `http://localhost:3000` | Backend server URL |
87
+ | `MODEL` | `GPT-4o` | Displayed model name |
88
+ | `COOKIES_PATH` | — | Path to ChatGPT cookies JSON |
89
+ | `CHROME_PATH` | `C:\Program Files\...\chrome.exe` | Chrome executable path |
90
+ | `CHROME_DEBUG_PORT` | `9222` | Remote debugging port |
91
+ | `PORT` | `3000` | Server port |
92
+ | `MAX_SESSIONS` | `20` | Max concurrent ChatGPT sessions |
93
+ | `MAX_CONCURRENT_PAGE_CREATES` | `3` | Max concurrent page opens |
94
+ | `MAX_CONCURRENT_MESSAGES` | `5` | Max concurrent messages |
95
+
96
+ ## Architecture
97
+
98
+ ```
99
+ ┌─────────────────────────────────────────────┐
100
+ │ CLI (Node.js) │
101
+ │ ┌──────────────┐ ┌──────────────────┐ │
102
+ │ │ bin/ │───▶│ express + │ │
103
+ │ │ infinity.js │ │ puppeteer-core │ │
104
+ │ │ (auto-start) │ │ server │ │
105
+ │ └──────────────┘ └────────┬─────────┘ │
106
+ │ │ │
107
+ │ ┌──────────────────┐ │ │
108
+ │ │ chat.js │◀────────┘ │
109
+ │ │ (TTY UI) │ │
110
+ │ └──────────────────┘ │
111
+ │ │ │
112
+ └───────────────────────────────┼──────────────┘
113
+
114
+ ┌───────────▼───────────┐
115
+ │ Chrome (headless) │
116
+ │ → chatgpt.com │
117
+ └───────────────────────┘
118
+ ```
119
+
120
+ - `bin/infinity.js` — Entry point; auto-starts the server
121
+ - `chat.js` — Full-screen box-drawn TTY UI (zero dependencies)
122
+ - `server.js` — Express + Puppeteer backend for ChatGPT
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ git clone https://github.com/hemacharanpyla/infinity-cli.git
128
+ cd infinity-cli
129
+ npm install
130
+ node bin/infinity.js # run CLI (auto-starts server)
131
+ ```
132
+
133
+ ## Package
134
+
135
+ ```bash
136
+ npm install -g @hemacharanpyla/infinitycli
137
+ ```
138
+
139
+ Published to [npm](https://www.npmjs.com/package/@hemacharanpyla/infinitycli).
140
+
141
+ ## License
142
+
143
+ MIT © [Charan](https://github.com/hemacharanpyla)
package/chat.js CHANGED
@@ -112,23 +112,35 @@ const SEP = `${GR}${"─".repeat(W)}${R}`;
112
112
  // ─── Dashboard content ────────────────────────────────────
113
113
  function buildDashboard() {
114
114
  const lines = [];
115
+ const logoW = Math.min(W - 4, 38);
116
+ const padL = " ".repeat(Math.floor((W - 4 - logoW) / 2));
117
+
118
+ // ── Logo banner ──
115
119
  lines.push("");
116
- lines.push(` ${BO}Welcome back ${G}${USER}${R}${BO}${R}`);
117
- lines.push("");
118
- lines.push(` ${D}∞${R} ${BP}Infinity CLI${R}`);
119
- lines.push(` ${GR}Model:${R} ${BO}${MODEL}${R}`);
120
- lines.push(` ${GR}Plan:${R} ${P}Pro${R}`);
121
- lines.push(` ${GR}Path:${R} ${C}${process.cwd()}${R}`);
120
+ lines.push(` ${padL}${BO}╔${"═".repeat(logoW)}╗${R}`);
121
+ lines.push(` ${padL}${BO}║${R} ${O}∞${R} ${B}I N F I N I T Y${R} ${O}∞${R} ${BO}║${R}`);
122
+ lines.push(` ${padL}${BO}║${R} ${GR}Terminal AI Chat${R} ${BO}║${R}`);
123
+ lines.push(` ${padL}${BO}╚${"═".repeat(logoW)}╝${R}`);
122
124
  lines.push("");
123
- lines.push(` ${GR}${SEP}${R}`);
125
+
126
+ // ── User info row ──
127
+ lines.push(` ${GR}Welcome,${R} ${BC}${USER}${R}`);
128
+ lines.push(` ${GR}Model:${R} ${BO}${MODEL}${R} ${GR}Plan:${R} ${BP}Pro${R} ${GR}v1.0.5${R}`);
129
+ lines.push(` ${GR}Path:${R} ${C}${process.cwd()}${R}`);
124
130
  lines.push("");
125
- lines.push(` ${B}Tips for getting started${R}`);
126
- lines.push(` ${O}•${R} ${G}/help${R} Show available commands`);
127
- lines.push(` ${O}•${R} ${G}/clear${R} Clear conversation`);
128
- lines.push(` ${O}•${R} ${G}/exit${R} Exit the session`);
129
- lines.push(` ${O}•${R} ${G}/status${R} Show session info`);
131
+
132
+ // ── Tips section ──
133
+ lines.push(` ${O}${"─".repeat(Math.min(W - 2, 54))}${R}`);
134
+ lines.push(` ${B}Quick Tips${R}`);
135
+ lines.push(` ${O}●${R} ${G}/help${R} ${GR}Show available commands${R}`);
136
+ lines.push(` ${O}●${R} ${G}/clear${R} ${GR}Clear conversation${R}`);
137
+ lines.push(` ${O}●${R} ${G}/exit${R} ${GR}Exit the session${R}`);
138
+ lines.push(` ${O}●${R} ${G}/status${R} ${GR}Show session & connection info${R}`);
130
139
  lines.push("");
131
- lines.push(` ${B}Recent activity${R}`);
140
+
141
+ // ── Activity section ──
142
+ lines.push(` ${O}${"─".repeat(Math.min(W - 2, 54))}${R}`);
143
+ lines.push(` ${B}Recent Activity${R}`);
132
144
  lines.push(` ${GR} No recent activity${R}`);
133
145
  lines.push("");
134
146
 
@@ -156,18 +168,21 @@ function buildHelpPanel() {
156
168
 
157
169
  const lines = [];
158
170
  lines.push("");
159
- lines.push(` ${BO}${"".repeat(28)}${R}`);
160
- lines.push(` ${B}Commands${R}`);
171
+ lines.push(` ${O}${"".repeat(30)}${R}`);
172
+ lines.push(` ${BO}╔═ Commands ═══════════════════╗${R}`);
161
173
  for (const [k, v] of cmds) {
162
- lines.push(` ${O}●${R} ${G}${k}${R} ${GR}${v}${R}`);
174
+ lines.push(` ${BO}║${R} ${O}●${R} ${G}${k.padEnd(10)}${R}${GR}${v}${R} ${BO}║${R}`);
163
175
  }
176
+ lines.push(` ${BO}╚══════════════════════════════╝${R}`);
164
177
  lines.push("");
165
- lines.push(` ${B}Shortcuts${R}`);
178
+ lines.push(` ${BO}╔═ Shortcuts ══════════════════╗${R}`);
166
179
  for (const [k, v] of sc) {
167
- lines.push(` ${O}●${R} ${BC}${k}${R} ${GR}${v}${R}`);
180
+ lines.push(` ${BO}║${R} ${O}●${R} ${BC}${k.padEnd(14)}${R}${GR}${v}${R} ${BO}║${R}`);
168
181
  }
182
+ lines.push(` ${BO}╚══════════════════════════════╝${R}`);
169
183
  lines.push("");
170
- lines.push(` ${GR}Press ${O}?${R}${GR} again or type a command to close${R}`);
184
+ lines.push(` ${O}${"═".repeat(30)}${R}`);
185
+ lines.push(` ${GR}Press ${O}?${R}${GR} again or type a message to close${R}`);
171
186
  lines.push("");
172
187
 
173
188
  while (lines.length < CONTENT_H) lines.push("");
@@ -179,14 +194,20 @@ function buildHelpPanel() {
179
194
  function buildChat() {
180
195
  const entries = [];
181
196
 
182
- for (const msg of state.messages) {
197
+ for (let i = 0; i < state.messages.length; i++) {
198
+ const msg = state.messages[i];
183
199
  const role = msg.role === "user" ? `${BC}You${R}` : `${BP}Infinity${R}`;
184
- entries.push(` ${role} (${GR}${msg.ts}${R})`);
200
+
201
+ if (i > 0) {
202
+ entries.push(` ${GR}${"─".repeat(Math.min(W - 2, 56))}${R}`);
203
+ }
204
+
205
+ entries.push(` ${role} ${GR}${msg.ts}${R}`);
185
206
  for (const line of msg.content.split("\n")) {
186
207
  entries.push(` ${line}`);
187
208
  }
188
209
  if (msg.meta) {
189
- entries.push(` ${GR} ${msg.meta}${R}`);
210
+ entries.push(` ${O}╰${R}${GR} ${msg.meta}${R}`);
190
211
  }
191
212
  entries.push("");
192
213
  }
@@ -209,7 +230,7 @@ function buildChat() {
209
230
  // ─── Full render ──────────────────────────────────────────
210
231
  function render(focusInput = true) {
211
232
  const content = state.showHelp ? buildHelpPanel() : (state.view === "dashboard" ? buildDashboard() : buildChat());
212
- const title = `${BO}Infinity CLI${R} ${GR}v1.0${R}`;
233
+ const title = `${D}∞${R} ${BO}Infinity CLI${R} ${GR}v1.0.5${R}`;
213
234
 
214
235
  const statusIcon = state.loading ? `${Y}●${R}` : state.connected ? `${G}●${R}` : `${R2}○${R}`;
215
236
  const statusRight = `${GR}${MODEL}${R} ${statusIcon} ${GR}${state.status}${R}`;
@@ -231,7 +252,7 @@ function render(focusInput = true) {
231
252
  const promptText = `${P}>${R} ${state.input}`;
232
253
  out += pos(R_PROMPT) + BOX.line(promptText);
233
254
 
234
- const shortcuts = `${GR}?${R} ${GR}for help${R} ${GR}│${R} ${GR}↑↓${R} ${GR}history${R} ${GR}│${R} ${GR}Ctrl+C${R} ${GR}exit${R}`;
255
+ const shortcuts = `${D}∞${R} ${GR}? help${R} ${GR}│${R} ${GR}↑↓ history${R} ${GR}│${R} ${GR}Ctrl+C exit${R}`;
235
256
  out += pos(R_SHORTCUTS) + BOX.lineR(shortcuts, state.loading ? `${Y}● ${state.status}${R}` : `${GR}${state.messages.length} msgs${R}`);
236
257
 
237
258
  out += pos(R_BOTTOM) + BOX.bot;
@@ -256,7 +277,7 @@ function renderPrompt() {
256
277
  function updateStatus() {
257
278
  const statusIcon = state.loading ? `${Y}●${R}` : state.connected ? `${G}●${R}` : `${R2}○${R}`;
258
279
  const statusRight = `${GR}${MODEL}${R} ${statusIcon} ${GR}${state.status}${R}`;
259
- const title = `${BO}Infinity CLI${R} ${GR}v1.0${R}`;
280
+ const title = `${D}∞${R} ${BO}Infinity CLI${R} ${GR}v1.0.5${R}`;
260
281
  const titleLine = `${" ".repeat(1)}${title}${" ".repeat(Math.max(0, W - vis(title).length - vis(statusRight).length))}${statusRight}`;
261
282
  stdout.write(`${pos(R_TITLE)}${CL}${BOX.line(titleLine)}`);
262
283
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hemacharanpyla/infinitycli",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "∞ Infinity CLI — terminal AI chat with real-time response timing",
5
5
  "type": "module",
6
6
  "bin": {