@cli-use/tui 0.1.0 → 0.1.3
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 +68 -33
- package/dist/ai-worker.cjs +65 -0
- package/dist/ai-worker.cjs.map +1 -0
- package/dist/ai-worker.d.cts +2 -0
- package/dist/ai-worker.d.ts +2 -0
- package/dist/ai-worker.js +42 -0
- package/dist/ai-worker.js.map +1 -0
- package/dist/bin/ratatui-demo +0 -0
- package/dist/cli/index.cjs +126 -36
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +126 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/hooks/index.cjs +32 -18
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +26 -28
- package/dist/hooks/index.js.map +1 -1
- package/dist/{index-DAO84gkm.d.cts → index-B4IaUxvU.d.cts} +4 -3
- package/dist/{index-DAO84gkm.d.ts → index-B4IaUxvU.d.ts} +4 -3
- package/dist/index.cjs +37 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +44 -42
- package/dist/index.js.map +1 -1
- package/package.json +15 -10
package/README.md
CHANGED
|
@@ -1,40 +1,75 @@
|
|
|
1
1
|
# cli-use
|
|
2
2
|
|
|
3
|
-
> Build beautiful terminal user interfaces with
|
|
3
|
+
> Build beautiful terminal user interfaces with React & Native Rust
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**cli-use** is a powerful framework for building stunning terminal applications. It combines the ease of **React** for standard TUIs with a high-performance **Native Rust/Ratatui** engine for advanced, AI-powered interfaces.
|
|
6
6
|
|
|
7
7
|
## 🎯 Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **React**: Build interactive CLIs using React components (Tables, Lists, Markdown, Flexbox).
|
|
10
|
+
- **Rust/Ratatui**: Experience ultra-fast, native TUI performance for specialized tools like our AI terminal.
|
|
10
11
|
|
|
11
12
|
## ✨ Features
|
|
12
13
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- **🔧 TypeScript** - Full type safety and excellent IDE support
|
|
19
|
-
- **⚡ Cross-Platform** - Works on macOS, Linux, and Windows
|
|
14
|
+
- **🤖 AI-Powered Terminal** - Integrated Google Gemini AI chat client (Native Rust).
|
|
15
|
+
- **🎨 Beautiful Styling** - CSS-like properties for stunning interfaces.
|
|
16
|
+
- **📊 Rich Components** - Tables, Lists, Markdown, and Layouts out of the box.
|
|
17
|
+
- **⚡ Hybrid Architecture** - Uses Node.js for flexibility and Rust for raw TUI performance.
|
|
18
|
+
- **🔧 TypeScript** - Full type safety and excellent IDE support.
|
|
20
19
|
|
|
21
20
|
## 🚀 Quick Start
|
|
22
21
|
|
|
22
|
+
### 1. Install via NPM
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g cli-use
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. Configure AI (Optional)
|
|
29
|
+
|
|
30
|
+
To use the AI features (`cli-use code`), you need to set your Google Gemini API key.
|
|
31
|
+
|
|
32
|
+
1. Get a [Google AI Studio API Key](https://aistudio.google.com/app/apikey).
|
|
33
|
+
2. Set it in your environment:
|
|
34
|
+
|
|
23
35
|
```bash
|
|
24
|
-
#
|
|
25
|
-
|
|
36
|
+
# Set in your current session
|
|
37
|
+
export GOOGLE_API_KEY=your_key_here
|
|
26
38
|
|
|
27
|
-
#
|
|
28
|
-
|
|
39
|
+
# OR create a .env file in the directory where you run the command
|
|
40
|
+
echo "GOOGLE_API_KEY=your_key_here" > .env
|
|
29
41
|
```
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
### 3. Run the AI Terminal
|
|
44
|
+
|
|
45
|
+
Launch the high-performance AI chat interface:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cli-use code
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🤖 CLI CODE (AI Terminal)
|
|
52
|
+
|
|
53
|
+
The `cli-use code` command launches a native Rust application that integrates with **Google Gemini**.
|
|
54
|
+
|
|
55
|
+
- **Splash Screen**: Instant startup with a stylized "CLI CODE" ASCII art.
|
|
56
|
+
- **Instant Input**: Start typing your query immediately on the home screen.
|
|
57
|
+
- **Streaming Responses**: Real-time AI streaming powered by Vercel AI SDK (Node.js) and Ratatui (Rust).
|
|
58
|
+
- **Performance**: Zero-latency UI rendering thanks to the native Rust backend.
|
|
59
|
+
|
|
60
|
+
**Prerequisites for Native Features:**
|
|
61
|
+
|
|
62
|
+
- [Rust installed](https://rustup.rs/) (automatically detected and built during install).
|
|
63
|
+
|
|
64
|
+
## 💡 React Examples
|
|
65
|
+
|
|
66
|
+
You can also build standard React-based CLIs.
|
|
32
67
|
|
|
33
68
|
### Basic App
|
|
34
69
|
|
|
35
70
|
```tsx
|
|
36
71
|
import React from 'react';
|
|
37
|
-
import { render, Box, Text } from '
|
|
72
|
+
import { render, Box, Text } from 'cli-use';
|
|
38
73
|
|
|
39
74
|
const App = () => (
|
|
40
75
|
<Box borderStyle="round" padding={1}>
|
|
@@ -49,13 +84,13 @@ render(<App />);
|
|
|
49
84
|
|
|
50
85
|
```tsx
|
|
51
86
|
import React, { useState } from 'react';
|
|
52
|
-
import { render, Box, Text, useInput } from '
|
|
87
|
+
import { render, Box, Text, useInput } from 'cli-use';
|
|
53
88
|
|
|
54
89
|
const Counter = () => {
|
|
55
90
|
const [count, setCount] = useState(0);
|
|
56
91
|
|
|
57
92
|
useInput((input, key) => {
|
|
58
|
-
if (key.return) setCount(c => c + 1);
|
|
93
|
+
if (key.return) setCount((c) => c + 1);
|
|
59
94
|
});
|
|
60
95
|
|
|
61
96
|
return (
|
|
@@ -75,7 +110,7 @@ render(<Counter />);
|
|
|
75
110
|
|
|
76
111
|
- **`Box`** - Container component for layout and styling
|
|
77
112
|
- **`Text`** - Text rendering with colors and styles
|
|
78
|
-
- **`render()`** - Render
|
|
113
|
+
- **`render()`** - Render cli-use apps to terminal
|
|
79
114
|
- **`useInput()`** - Handle keyboard input
|
|
80
115
|
- **`useApp()`** - App instance management
|
|
81
116
|
|
|
@@ -85,30 +120,30 @@ render(<Counter />);
|
|
|
85
120
|
# Install dependencies
|
|
86
121
|
npm install
|
|
87
122
|
|
|
88
|
-
# Build
|
|
123
|
+
# Build the project (including Rust native binary)
|
|
89
124
|
npm run build
|
|
90
125
|
|
|
91
|
-
# Run
|
|
92
|
-
npm run
|
|
93
|
-
|
|
94
|
-
# Type check
|
|
95
|
-
npm run typecheck
|
|
126
|
+
# Run the AI Terminal (Dev Mode)
|
|
127
|
+
npm run demo:rust
|
|
96
128
|
|
|
97
|
-
# Run
|
|
98
|
-
npm run
|
|
129
|
+
# Run React Examples
|
|
130
|
+
npm run demo:cli-use
|
|
99
131
|
```
|
|
100
132
|
|
|
101
133
|
## 📁 Project Structure
|
|
102
134
|
|
|
103
135
|
```
|
|
104
136
|
cli-use/
|
|
137
|
+
├── native/ # Rust/Ratatui source code
|
|
138
|
+
│ └── src/
|
|
139
|
+
│ └── main.rs # Native TUI entry point
|
|
105
140
|
├── src/
|
|
106
|
-
│ ├──
|
|
107
|
-
│
|
|
108
|
-
│
|
|
109
|
-
│
|
|
141
|
+
│ ├── ai-worker.ts # Node.js AI Bridge (Vercel AI SDK)
|
|
142
|
+
│ ├── cli/ # CLI Entry point
|
|
143
|
+
│ ├── components/ # React components
|
|
144
|
+
│ └── examples/ # Example apps
|
|
145
|
+
│ └── cli-use-demo.tsx # React/cli-use Demo
|
|
110
146
|
├── package.json
|
|
111
|
-
├── tsconfig.json
|
|
112
147
|
└── README.md
|
|
113
148
|
```
|
|
114
149
|
|
|
@@ -122,4 +157,4 @@ MIT © 2025 cli-use contributors
|
|
|
122
157
|
|
|
123
158
|
---
|
|
124
159
|
|
|
125
|
-
**Built with
|
|
160
|
+
**Built with ❤️, React, and Rust**
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license MIT
|
|
3
|
+
* cli-use - React-based Terminal UI Framework
|
|
4
|
+
* Inspired by Ratatui (https://ratatui.rs)
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
var __create = Object.create;
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
12
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
|
|
30
|
+
// src/ai-worker.ts
|
|
31
|
+
var import_google = require("@ai-sdk/google");
|
|
32
|
+
var import_ai = require("ai");
|
|
33
|
+
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
34
|
+
var import_readline = __toESM(require("readline"), 1);
|
|
35
|
+
import_dotenv.default.config();
|
|
36
|
+
var apiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
37
|
+
if (!apiKey) {
|
|
38
|
+
console.error(
|
|
39
|
+
"Error: No API Key found. Set GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY in .env"
|
|
40
|
+
);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
var google = (0, import_google.createGoogleGenerativeAI)({
|
|
44
|
+
apiKey
|
|
45
|
+
});
|
|
46
|
+
var rl = import_readline.default.createInterface({
|
|
47
|
+
input: process.stdin,
|
|
48
|
+
output: process.stdout,
|
|
49
|
+
terminal: false
|
|
50
|
+
});
|
|
51
|
+
rl.on("line", async (line) => {
|
|
52
|
+
const prompt = line.trim();
|
|
53
|
+
if (!prompt) return;
|
|
54
|
+
try {
|
|
55
|
+
const { text } = await (0, import_ai.generateText)({
|
|
56
|
+
model: google("models/gemini-2.0-flash"),
|
|
57
|
+
// Updated to available model
|
|
58
|
+
prompt
|
|
59
|
+
});
|
|
60
|
+
console.log(text.replace(/\n/g, "\\n"));
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("AI Error:", error);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=ai-worker.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ai-worker.ts"],"sourcesContent":["import { createGoogleGenerativeAI } from '@ai-sdk/google';\nimport { generateText } from 'ai';\nimport dotenv from 'dotenv';\nimport readline from 'readline';\n\ndotenv.config();\n\n// Support multiple potential env var names for flexibility\nconst apiKey =\n process.env.GOOGLE_GENERATIVE_AI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY;\n\nif (!apiKey) {\n console.error(\n 'Error: No API Key found. Set GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY in .env'\n );\n process.exit(1);\n}\n\nconst google = createGoogleGenerativeAI({\n apiKey: apiKey,\n});\n\nconst rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n});\n\nrl.on('line', async (line) => {\n const prompt = line.trim();\n if (!prompt) return;\n\n try {\n const { text } = await generateText({\n model: google('models/gemini-2.0-flash'), // Updated to available model\n prompt: prompt,\n });\n\n // Output text handling for Rust consumption\n console.log(text.replace(/\\n/g, '\\\\n'));\n } catch (error) {\n console.error('AI Error:', error);\n }\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oBAAyC;AACzC,gBAA6B;AAC7B,oBAAmB;AACnB,sBAAqB;AAErB,cAAAA,QAAO,OAAO;AAGd,IAAM,SACJ,QAAQ,IAAI,gCACZ,QAAQ,IAAI,kBACZ,QAAQ,IAAI;AAEd,IAAI,CAAC,QAAQ;AACX,UAAQ;AAAA,IACN;AAAA,EACF;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,aAAS,wCAAyB;AAAA,EACtC;AACF,CAAC;AAED,IAAM,KAAK,gBAAAC,QAAS,gBAAgB;AAAA,EAClC,OAAO,QAAQ;AAAA,EACf,QAAQ,QAAQ;AAAA,EAChB,UAAU;AACZ,CAAC;AAED,GAAG,GAAG,QAAQ,OAAO,SAAS;AAC5B,QAAM,SAAS,KAAK,KAAK;AACzB,MAAI,CAAC,OAAQ;AAEb,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,UAAM,wBAAa;AAAA,MAClC,OAAO,OAAO,yBAAyB;AAAA;AAAA,MACvC;AAAA,IACF,CAAC;AAGD,YAAQ,IAAI,KAAK,QAAQ,OAAO,KAAK,CAAC;AAAA,EACxC,SAAS,OAAO;AACd,YAAQ,MAAM,aAAa,KAAK;AAAA,EAClC;AACF,CAAC;","names":["dotenv","readline"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license MIT
|
|
3
|
+
* cli-use - React-based Terminal UI Framework
|
|
4
|
+
* Inspired by Ratatui (https://ratatui.rs)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// src/ai-worker.ts
|
|
8
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
9
|
+
import { generateText } from "ai";
|
|
10
|
+
import dotenv from "dotenv";
|
|
11
|
+
import readline from "readline";
|
|
12
|
+
dotenv.config();
|
|
13
|
+
var apiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
14
|
+
if (!apiKey) {
|
|
15
|
+
console.error(
|
|
16
|
+
"Error: No API Key found. Set GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY in .env"
|
|
17
|
+
);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
var google = createGoogleGenerativeAI({
|
|
21
|
+
apiKey
|
|
22
|
+
});
|
|
23
|
+
var rl = readline.createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
terminal: false
|
|
27
|
+
});
|
|
28
|
+
rl.on("line", async (line) => {
|
|
29
|
+
const prompt = line.trim();
|
|
30
|
+
if (!prompt) return;
|
|
31
|
+
try {
|
|
32
|
+
const { text } = await generateText({
|
|
33
|
+
model: google("models/gemini-2.0-flash"),
|
|
34
|
+
// Updated to available model
|
|
35
|
+
prompt
|
|
36
|
+
});
|
|
37
|
+
console.log(text.replace(/\n/g, "\\n"));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("AI Error:", error);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=ai-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ai-worker.ts"],"sourcesContent":["import { createGoogleGenerativeAI } from '@ai-sdk/google';\nimport { generateText } from 'ai';\nimport dotenv from 'dotenv';\nimport readline from 'readline';\n\ndotenv.config();\n\n// Support multiple potential env var names for flexibility\nconst apiKey =\n process.env.GOOGLE_GENERATIVE_AI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY;\n\nif (!apiKey) {\n console.error(\n 'Error: No API Key found. Set GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY in .env'\n );\n process.exit(1);\n}\n\nconst google = createGoogleGenerativeAI({\n apiKey: apiKey,\n});\n\nconst rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n});\n\nrl.on('line', async (line) => {\n const prompt = line.trim();\n if (!prompt) return;\n\n try {\n const { text } = await generateText({\n model: google('models/gemini-2.0-flash'), // Updated to available model\n prompt: prompt,\n });\n\n // Output text handling for Rust consumption\n console.log(text.replace(/\\n/g, '\\\\n'));\n } catch (error) {\n console.error('AI Error:', error);\n }\n});\n"],"mappings":";;;;;;;AAAA,SAAS,gCAAgC;AACzC,SAAS,oBAAoB;AAC7B,OAAO,YAAY;AACnB,OAAO,cAAc;AAErB,OAAO,OAAO;AAGd,IAAM,SACJ,QAAQ,IAAI,gCACZ,QAAQ,IAAI,kBACZ,QAAQ,IAAI;AAEd,IAAI,CAAC,QAAQ;AACX,UAAQ;AAAA,IACN;AAAA,EACF;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,yBAAyB;AAAA,EACtC;AACF,CAAC;AAED,IAAM,KAAK,SAAS,gBAAgB;AAAA,EAClC,OAAO,QAAQ;AAAA,EACf,QAAQ,QAAQ;AAAA,EAChB,UAAU;AACZ,CAAC;AAED,GAAG,GAAG,QAAQ,OAAO,SAAS;AAC5B,QAAM,SAAS,KAAK,KAAK;AACzB,MAAI,CAAC,OAAQ;AAEb,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,aAAa;AAAA,MAClC,OAAO,OAAO,yBAAyB;AAAA;AAAA,MACvC;AAAA,IACF,CAAC;AAGD,YAAQ,IAAI,KAAK,QAAQ,OAAO,KAAK,CAAC;AAAA,EACxC,SAAS,OAAO;AACd,YAAQ,MAAM,aAAa,KAAK;AAAA,EAClC;AACF,CAAC;","names":[]}
|
|
Binary file
|
package/dist/cli/index.cjs
CHANGED
|
@@ -41,47 +41,132 @@ var init_cjs_shims = __esm({
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
// src/examples/
|
|
45
|
-
var
|
|
46
|
-
var import_react, import_ink, import_jsx_runtime,
|
|
47
|
-
var
|
|
48
|
-
"src/examples/
|
|
44
|
+
// src/examples/cli-use-demo.tsx
|
|
45
|
+
var cli_use_demo_exports = {};
|
|
46
|
+
var import_react, import_ink, import_jsx_runtime, CLAUDE_ORANGE, FOOTER_TEXT, FOOTER_HIGHLIGHT, LOGO_TEXT, Splash, Chat, App;
|
|
47
|
+
var init_cli_use_demo = __esm({
|
|
48
|
+
"src/examples/cli-use-demo.tsx"() {
|
|
49
49
|
"use strict";
|
|
50
50
|
init_cjs_shims();
|
|
51
51
|
import_react = require("react");
|
|
52
52
|
import_ink = require("ink");
|
|
53
53
|
import_jsx_runtime = require("react/jsx-runtime");
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
CLAUDE_ORANGE = "#D97757";
|
|
55
|
+
FOOTER_TEXT = "#708090";
|
|
56
|
+
FOOTER_HIGHLIGHT = "#FFFFFF";
|
|
57
|
+
LOGO_TEXT = `
|
|
58
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557
|
|
59
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
60
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
61
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
62
|
+
\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
63
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
64
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
65
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
|
|
66
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557
|
|
67
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D
|
|
68
|
+
\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
69
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
70
|
+
`;
|
|
71
|
+
Splash = ({ input }) => {
|
|
72
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", alignItems: "center", height: "100%", justifyContent: "space-between", children: [
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 2, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { borderStyle: "round", borderColor: CLAUDE_ORANGE, paddingX: 2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: CLAUDE_ORANGE, bold: true, children: "Welcome to the Claude Code research preview!" }) }) }),
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginBottom: 2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: CLAUDE_ORANGE, children: LOGO_TEXT }) }),
|
|
75
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
76
|
+
import_ink.Box,
|
|
77
|
+
{
|
|
78
|
+
width: "100%",
|
|
79
|
+
borderStyle: "single",
|
|
80
|
+
borderColor: "gray",
|
|
81
|
+
paddingX: 1,
|
|
82
|
+
marginBottom: 1,
|
|
83
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", bold: true, children: [
|
|
84
|
+
">",
|
|
85
|
+
" ",
|
|
86
|
+
input,
|
|
87
|
+
"_"
|
|
88
|
+
] })
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginBottom: 2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: FOOTER_TEXT, children: [
|
|
92
|
+
"\u{1F389} Login successful. Press",
|
|
93
|
+
" ",
|
|
94
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: FOOTER_HIGHLIGHT, bold: true, children: "Enter" }),
|
|
95
|
+
" ",
|
|
96
|
+
"to continue"
|
|
97
|
+
] }) })
|
|
98
|
+
] });
|
|
99
|
+
};
|
|
100
|
+
Chat = ({ messages, input }) => {
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", height: "100%", children: [
|
|
102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { flexDirection: "column", flexGrow: 1, children: messages.map((msg, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { flexDirection: "column", marginLeft: msg.type === "output" ? 2 : 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { children: [
|
|
103
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
104
|
+
import_ink.Text,
|
|
105
|
+
{
|
|
106
|
+
color: msg.type === "user" ? "cyan" : msg.type === "thinking" ? "yellow" : msg.type === "tool" ? "blue" : msg.type === "system" ? "magenta" : "gray",
|
|
107
|
+
bold: msg.type === "user",
|
|
108
|
+
children: msg.symbol
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: msg.type === "output" ? "gray" : "white", children: [
|
|
112
|
+
" ",
|
|
113
|
+
msg.content
|
|
114
|
+
] })
|
|
115
|
+
] }) }, i)) }),
|
|
116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", bold: true, children: [
|
|
117
|
+
">",
|
|
118
|
+
" ",
|
|
119
|
+
input,
|
|
120
|
+
"_"
|
|
121
|
+
] }) })
|
|
122
|
+
] });
|
|
123
|
+
};
|
|
124
|
+
App = () => {
|
|
125
|
+
const [mode, setMode] = (0, import_react.useState)("splash");
|
|
126
|
+
const [input, setInput] = (0, import_react.useState)("");
|
|
127
|
+
const [messages, setMessages] = (0, import_react.useState)([
|
|
128
|
+
{ type: "system", symbol: "*", content: "Welcome to CLI CODE." },
|
|
129
|
+
{ type: "system", symbol: "*", content: "I am ready to assist. Type anything to chat." }
|
|
130
|
+
]);
|
|
131
|
+
(0, import_ink.useInput)((keyInput, key) => {
|
|
132
|
+
if (key.escape || key.ctrl && keyInput === "c") {
|
|
58
133
|
process.exit(0);
|
|
59
134
|
}
|
|
60
135
|
if (key.return) {
|
|
61
|
-
|
|
136
|
+
if (mode === "splash") {
|
|
137
|
+
setMode("chat");
|
|
138
|
+
if (input.trim()) {
|
|
139
|
+
addMessage("user", ">", input);
|
|
140
|
+
addMessage("thinking", "\u23FA", "Processing...");
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
addMessage("output", "\u23BF", "This is a simulated response in the cli-use demo.");
|
|
143
|
+
}, 1e3);
|
|
144
|
+
setInput("");
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
if (input.trim()) {
|
|
148
|
+
addMessage("user", ">", input);
|
|
149
|
+
addMessage("thinking", "\u23FA", "Processing...");
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
addMessage("output", "\u23BF", "This is a simulated response in the cli-use demo.");
|
|
152
|
+
}, 1e3);
|
|
153
|
+
setInput("");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (key.delete || key.backspace) {
|
|
159
|
+
setInput((prev) => prev.slice(0, -1));
|
|
160
|
+
} else {
|
|
161
|
+
setInput((prev) => prev + keyInput);
|
|
62
162
|
}
|
|
63
163
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: "\u2022 Cross-platform (macOS, Linux, Windows)" }),
|
|
69
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: "\u2022 React-based components" }),
|
|
70
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: "\u2022 Beautiful styling out of the box" }),
|
|
71
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: "\u2022 TypeScript support" })
|
|
72
|
-
] }) }),
|
|
73
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { borderStyle: "round", borderColor: "green", padding: 1, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", alignItems: "center", gap: 1, children: [
|
|
74
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { bold: true, color: "green", children: "\u{1F522} Interactive Counter" }),
|
|
75
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { children: [
|
|
76
|
-
"Count: ",
|
|
77
|
-
count
|
|
78
|
-
] }),
|
|
79
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { dim: true, children: "Press Enter to increment, ESC to exit" })
|
|
80
|
-
] }) }),
|
|
81
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { dim: true, color: "gray", children: "Built with \u2764\uFE0F for beautiful terminal interfaces" }) })
|
|
82
|
-
] });
|
|
164
|
+
const addMessage = (type, symbol, content) => {
|
|
165
|
+
setMessages((prev) => [...prev, { type, symbol, content }]);
|
|
166
|
+
};
|
|
167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { flexDirection: "column", minHeight: 20, children: mode === "splash" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Splash, { input, onEnter: () => setMode("chat") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chat, { messages, input }) });
|
|
83
168
|
};
|
|
84
|
-
(0, import_ink.render)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
169
|
+
(0, import_ink.render)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(App, {}));
|
|
85
170
|
}
|
|
86
171
|
});
|
|
87
172
|
|
|
@@ -89,11 +174,10 @@ var init_ink_demo = __esm({
|
|
|
89
174
|
init_cjs_shims();
|
|
90
175
|
var import_commander = require("commander");
|
|
91
176
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
92
|
-
var import_module = require("module");
|
|
93
177
|
var import_child_process = require("child_process");
|
|
94
178
|
var import_url = require("url");
|
|
95
179
|
var import_path = __toESM(require("path"), 1);
|
|
96
|
-
var
|
|
180
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
97
181
|
var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
|
|
98
182
|
var __dirname = import_path.default.dirname(__filename2);
|
|
99
183
|
var program = new import_commander.Command();
|
|
@@ -117,11 +201,14 @@ program.command("run <example>").description("Run an example application").actio
|
|
|
117
201
|
program.command("examples").description("List available examples").action(() => {
|
|
118
202
|
showExamplesTUI();
|
|
119
203
|
});
|
|
120
|
-
program.
|
|
204
|
+
program.command("code").description("Launch the AI-powered CLI Code interface").action(() => {
|
|
205
|
+
showRustDemo();
|
|
206
|
+
});
|
|
207
|
+
program.option("-d, --demo", "Run the cli-use demo").action(() => {
|
|
121
208
|
});
|
|
122
209
|
var options = program.parse(process.argv);
|
|
123
210
|
if (options.opts().demo) {
|
|
124
|
-
Promise.resolve().then(() => (
|
|
211
|
+
Promise.resolve().then(() => (init_cli_use_demo(), cli_use_demo_exports)).catch((err) => {
|
|
125
212
|
console.error("Failed to run demo:", err);
|
|
126
213
|
process.exit(1);
|
|
127
214
|
});
|
|
@@ -129,12 +216,15 @@ if (options.opts().demo) {
|
|
|
129
216
|
function showRustDemo() {
|
|
130
217
|
const isWindows = process.platform === "win32";
|
|
131
218
|
const extension = isWindows ? ".exe" : "";
|
|
132
|
-
const
|
|
219
|
+
const prodBinaryPath = import_path.default.resolve(__dirname, `../bin/ratatui-demo${extension}`);
|
|
220
|
+
const devBinaryPath = import_path.default.resolve(
|
|
133
221
|
__dirname,
|
|
134
222
|
`../../native/target/release/ratatui-demo${extension}`
|
|
135
223
|
);
|
|
224
|
+
const binaryPath = import_fs.default.existsSync(prodBinaryPath) ? prodBinaryPath : devBinaryPath;
|
|
225
|
+
const workerPath = import_path.default.resolve(__dirname, "../ai-worker.js");
|
|
136
226
|
console.log(import_chalk.default.cyan("Starting Ratatui Demo..."));
|
|
137
|
-
const child = (0, import_child_process.spawn)(binaryPath, [], {
|
|
227
|
+
const child = (0, import_child_process.spawn)(binaryPath, [workerPath], {
|
|
138
228
|
stdio: "inherit"
|
|
139
229
|
});
|
|
140
230
|
child.on("error", (err) => {
|