sapplanta 1.0.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/.github/workflows/publish.yml +25 -0
- package/README.md +84 -0
- package/bin/sapplanta.js +307 -0
- package/package.json +34 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- 'sapplanta-cli/**'
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
defaults:
|
|
14
|
+
run:
|
|
15
|
+
working-directory: sapplanta-cli
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '20'
|
|
21
|
+
registry-url: 'https://registry.npmjs.org'
|
|
22
|
+
- run: npm install
|
|
23
|
+
- run: npm publish --access public
|
|
24
|
+
env:
|
|
25
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# SAPPLANTA AI CLI ๐ฐ๐ช
|
|
2
|
+
|
|
3
|
+
The All-in-One AI Platform โ now in your terminal.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g sapplanta
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Get your API key from [sapplanta.site/developer](https://www.sapplanta.site/developer)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
sapplanta login --key sk-or-v1-your-key-here
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### Interactive Chat
|
|
22
|
+
```bash
|
|
23
|
+
sapplanta chat
|
|
24
|
+
sapplanta chat --domain trading
|
|
25
|
+
sapplanta chat --domain laravel --mode elite
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Single Question
|
|
29
|
+
```bash
|
|
30
|
+
sapplanta ask "Write a Python function to calculate fibonacci"
|
|
31
|
+
sapplanta ask "Build an MQL4 EA with EMA crossover" --domain trading --mode elite
|
|
32
|
+
sapplanta ask "What is React?" --output answer.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Analyze a File
|
|
36
|
+
```bash
|
|
37
|
+
sapplanta analyze my_bot.mq4
|
|
38
|
+
sapplanta analyze app.py --instruction "Find bugs and fix them" --mode elite
|
|
39
|
+
sapplanta analyze database.sql --instruction "Optimize these queries"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Generate Code to Files
|
|
43
|
+
```bash
|
|
44
|
+
sapplanta generate "Build a restaurant website with HTML, CSS, JS" --output ./my-website
|
|
45
|
+
sapplanta generate "Create a Laravel API for a todo app" --domain laravel --output ./todo-api
|
|
46
|
+
sapplanta generate "Write an MT4 EA with RSI strategy" --domain trading --mode elite
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## AI Modes
|
|
50
|
+
|
|
51
|
+
| Mode | Model | Cost |
|
|
52
|
+
|------|-------|------|
|
|
53
|
+
| `standard` | Free AI | 0 credits |
|
|
54
|
+
| `premium` | Claude Sonnet 4.6 | 5 credits/msg |
|
|
55
|
+
| `elite` | Claude Opus 4.6 | 15 credits/msg |
|
|
56
|
+
|
|
57
|
+
## Domains
|
|
58
|
+
|
|
59
|
+
`general` ยท `laravel` ยท `nextjs` ยท `python` ยท `react` ยท `node` ยท `trading` ยท `mobile`
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Build a full website
|
|
65
|
+
sapplanta generate "Build a Nairobi restaurant website with M-Pesa payment form, menu page, about page, contact page" --domain nextjs --mode elite --output ./restaurant-site
|
|
66
|
+
|
|
67
|
+
# Fix a trading bot
|
|
68
|
+
sapplanta analyze my_ea.mq4 --instruction "This EA has a bug - it opens too many trades. Find and fix it" --mode elite
|
|
69
|
+
|
|
70
|
+
# Quick Python help
|
|
71
|
+
sapplanta ask "Write a backtesting script for RSI strategy using pandas" --domain trading
|
|
72
|
+
|
|
73
|
+
# Interactive Laravel development
|
|
74
|
+
sapplanta chat --domain laravel --mode premium
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Links
|
|
78
|
+
|
|
79
|
+
- ๐ Website: [www.sapplanta.site](https://www.sapplanta.site)
|
|
80
|
+
- ๐ค Telegram: [@SapplantaAIBot](https://t.me/SapplantaAIBot)
|
|
81
|
+
- ๐ API Keys: [sapplanta.site/developer](https://www.sapplanta.site/developer)
|
|
82
|
+
- ๐ Docs: [sapplanta.site/docs/api](https://www.sapplanta.site/docs/api)
|
|
83
|
+
|
|
84
|
+
Built in Kenya ๐ฐ๐ช by SAPPLANTA ENTERPRISE
|
package/bin/sapplanta.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
const { program } = require('commander')
|
|
6
|
+
const chalk = require('chalk')
|
|
7
|
+
const ora = require('ora')
|
|
8
|
+
const readline = require('readline')
|
|
9
|
+
const fs = require('fs')
|
|
10
|
+
const path = require('path')
|
|
11
|
+
const Conf = require('conf')
|
|
12
|
+
const axios = require('axios')
|
|
13
|
+
|
|
14
|
+
const config = new Conf({ projectName: 'sapplanta' })
|
|
15
|
+
const API_URL = 'https://www.sapplanta.site/api'
|
|
16
|
+
const VERSION = '1.0.0'
|
|
17
|
+
|
|
18
|
+
// โโ Banner โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
19
|
+
function showBanner() {
|
|
20
|
+
console.log(chalk.white.bold('\n โโโโโโโ โโโโโ โโโโโโ โโโโโโ โโ โโโโโ โโโ โโ โโโโโโโโ โโโโโ '))
|
|
21
|
+
console.log(chalk.white.bold(' โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโโโ โโ โโ โโ โโ '))
|
|
22
|
+
console.log(chalk.white(' โโโโโโโ โโโโโโโ โโโโโโ โโโโโโ โโ โโโโโโโ โโ โโ โโ โโ โโโโโโโ '))
|
|
23
|
+
console.log(chalk.white(' โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ '))
|
|
24
|
+
console.log(chalk.white.bold(' โโโโโโโ โโ โโ โโ โโ โโโโโโโ โโ โโ โโ โโโโ โโ โโ โโ '))
|
|
25
|
+
console.log(chalk.gray(`\n The All-in-One AI Platform ยท Built in Kenya ๐ฐ๐ช ยท v${VERSION}\n`))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// โโ Auth helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
29
|
+
function getApiKey() {
|
|
30
|
+
const key = config.get('apiKey') || process.env.SAPPLANTA_API_KEY
|
|
31
|
+
if (!key) {
|
|
32
|
+
console.log(chalk.yellow('\nโ ๏ธ No API key found. Run: sapplanta login\n'))
|
|
33
|
+
process.exit(1)
|
|
34
|
+
}
|
|
35
|
+
return key
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// โโ API call โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
39
|
+
async function callAPI(messages, domain = 'general', model = 'standard') {
|
|
40
|
+
const apiKey = getApiKey()
|
|
41
|
+
|
|
42
|
+
const modelMap = {
|
|
43
|
+
standard: 'nvidia/nemotron-3-super-120b-a12b:free',
|
|
44
|
+
premium: 'anthropic/claude-sonnet-4.6',
|
|
45
|
+
elite: 'anthropic/claude-opus-4.6',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const res = await axios.post(
|
|
49
|
+
'https://openrouter.ai/api/v1/chat/completions',
|
|
50
|
+
{
|
|
51
|
+
model: modelMap[model] || modelMap.standard,
|
|
52
|
+
messages: [
|
|
53
|
+
{
|
|
54
|
+
role: 'system',
|
|
55
|
+
content: `You are SAPPLANTA AI operating in a CLI terminal. The user is a developer using you from their command line. Be concise, technical, and output clean code when requested. Domain: ${domain}. When generating multiple files, list each file clearly with its filename.`,
|
|
56
|
+
},
|
|
57
|
+
...messages,
|
|
58
|
+
],
|
|
59
|
+
max_tokens: 2000,
|
|
60
|
+
temperature: 0.7,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
headers: {
|
|
64
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
'HTTP-Referer': 'https://www.sapplanta.site',
|
|
67
|
+
'X-Title': 'SAPPLANTA AI CLI',
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return res.data.choices?.[0]?.message?.content || ''
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// โโ Format AI response for terminal โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
76
|
+
function formatResponse(text) {
|
|
77
|
+
// Color code blocks
|
|
78
|
+
const lines = text.split('\n')
|
|
79
|
+
let inCode = false
|
|
80
|
+
let codeLines = []
|
|
81
|
+
const output = []
|
|
82
|
+
|
|
83
|
+
for (const line of lines) {
|
|
84
|
+
if (line.startsWith('```')) {
|
|
85
|
+
if (inCode) {
|
|
86
|
+
// End of code block
|
|
87
|
+
output.push(chalk.bgGray.black(' CODE ') + ' ' + chalk.gray(codeLines[0] || ''))
|
|
88
|
+
output.push(...codeLines.slice(1).map(l => chalk.green(l)))
|
|
89
|
+
output.push('')
|
|
90
|
+
codeLines = []
|
|
91
|
+
inCode = false
|
|
92
|
+
} else {
|
|
93
|
+
inCode = true
|
|
94
|
+
codeLines = [line.replace(/```/, '').trim()]
|
|
95
|
+
}
|
|
96
|
+
} else if (inCode) {
|
|
97
|
+
codeLines.push(line)
|
|
98
|
+
} else {
|
|
99
|
+
// Format markdown
|
|
100
|
+
const formatted = line
|
|
101
|
+
.replace(/\*\*(.*?)\*\*/g, chalk.bold('$1'))
|
|
102
|
+
.replace(/\*(.*?)\*/g, chalk.italic('$1'))
|
|
103
|
+
.replace(/`(.*?)`/g, chalk.cyan('$1'))
|
|
104
|
+
.replace(/^### (.+)/, chalk.yellow.bold('$1'))
|
|
105
|
+
.replace(/^## (.+)/, chalk.yellow.bold('$1'))
|
|
106
|
+
.replace(/^# (.+)/, chalk.white.bold('$1'))
|
|
107
|
+
.replace(/^- /, chalk.gray(' โข '))
|
|
108
|
+
.replace(/^(\d+)\. /, chalk.gray(' $1. '))
|
|
109
|
+
output.push(formatted)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return output.join('\n')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// โโ Commands โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
117
|
+
program
|
|
118
|
+
.name('sapplanta')
|
|
119
|
+
.description(chalk.white('SAPPLANTA AI CLI โ The All-in-One AI Platform'))
|
|
120
|
+
.version(VERSION)
|
|
121
|
+
|
|
122
|
+
// Login command
|
|
123
|
+
program
|
|
124
|
+
.command('login')
|
|
125
|
+
.description('Set your OpenRouter API key')
|
|
126
|
+
.option('-k, --key <key>', 'API key (sk-or-v1-...)')
|
|
127
|
+
.action(async (opts) => {
|
|
128
|
+
showBanner()
|
|
129
|
+
let apiKey = opts.key
|
|
130
|
+
|
|
131
|
+
if (!apiKey) {
|
|
132
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
|
|
133
|
+
apiKey = await new Promise(resolve => {
|
|
134
|
+
rl.question(chalk.cyan('Enter your SAPPLANTA API key (from sapplanta.site/developer): '), answer => {
|
|
135
|
+
rl.close(); resolve(answer.trim())
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!apiKey) { console.log(chalk.red('No key provided')); process.exit(1) }
|
|
141
|
+
config.set('apiKey', apiKey)
|
|
142
|
+
console.log(chalk.green('\nโ
API key saved! You can now use sapplanta chat\n'))
|
|
143
|
+
console.log(chalk.gray('Get your API key at: https://www.sapplanta.site/developer\n'))
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// Chat command โ interactive mode
|
|
147
|
+
program
|
|
148
|
+
.command('chat')
|
|
149
|
+
.description('Start an interactive AI chat session')
|
|
150
|
+
.option('-d, --domain <domain>', 'AI domain (general/laravel/python/trading/nextjs/react/node/mobile)', 'general')
|
|
151
|
+
.option('-m, --mode <mode>', 'AI mode (standard/premium/elite)', 'standard')
|
|
152
|
+
.action(async (opts) => {
|
|
153
|
+
showBanner()
|
|
154
|
+
const { domain, mode } = opts
|
|
155
|
+
|
|
156
|
+
console.log(chalk.gray(`Domain: ${domain} | Mode: ${mode}`))
|
|
157
|
+
console.log(chalk.gray('Type your message and press Enter. Type "exit" to quit.\n'))
|
|
158
|
+
console.log(chalk.yellow('โ'.repeat(60)))
|
|
159
|
+
|
|
160
|
+
const messages = []
|
|
161
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
|
|
162
|
+
|
|
163
|
+
const ask = () => {
|
|
164
|
+
rl.question(chalk.cyan('\nYou: '), async (input) => {
|
|
165
|
+
const text = input.trim()
|
|
166
|
+
if (!text) { ask(); return }
|
|
167
|
+
if (text.toLowerCase() === 'exit' || text.toLowerCase() === 'quit') {
|
|
168
|
+
console.log(chalk.gray('\nGoodbye! ๐\n'))
|
|
169
|
+
rl.close(); process.exit(0)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
messages.push({ role: 'user', content: text })
|
|
173
|
+
|
|
174
|
+
const spinner = ora(chalk.gray('Thinking...')).start()
|
|
175
|
+
try {
|
|
176
|
+
const reply = await callAPI(messages, domain, mode)
|
|
177
|
+
spinner.stop()
|
|
178
|
+
messages.push({ role: 'assistant', content: reply })
|
|
179
|
+
console.log(chalk.yellow('\nSAPPLANTA AI:'))
|
|
180
|
+
console.log(formatResponse(reply))
|
|
181
|
+
} catch (err) {
|
|
182
|
+
spinner.stop()
|
|
183
|
+
console.log(chalk.red(`\nError: ${err.response?.data?.error?.message || err.message}`))
|
|
184
|
+
}
|
|
185
|
+
ask()
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
ask()
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// Ask command โ single question
|
|
192
|
+
program
|
|
193
|
+
.command('ask <question...>')
|
|
194
|
+
.description('Ask a single question and get an answer')
|
|
195
|
+
.option('-d, --domain <domain>', 'AI domain', 'general')
|
|
196
|
+
.option('-m, --mode <mode>', 'AI mode (standard/premium/elite)', 'standard')
|
|
197
|
+
.option('-o, --output <file>', 'Save response to file')
|
|
198
|
+
.action(async (questionParts, opts) => {
|
|
199
|
+
const question = questionParts.join(' ')
|
|
200
|
+
const spinner = ora(chalk.gray('Thinking...')).start()
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
const reply = await callAPI([{ role: 'user', content: question }], opts.domain, opts.mode)
|
|
204
|
+
spinner.stop()
|
|
205
|
+
console.log(formatResponse(reply))
|
|
206
|
+
|
|
207
|
+
if (opts.output) {
|
|
208
|
+
fs.writeFileSync(opts.output, reply, 'utf8')
|
|
209
|
+
console.log(chalk.green(`\nโ
Saved to ${opts.output}`))
|
|
210
|
+
}
|
|
211
|
+
} catch (err) {
|
|
212
|
+
spinner.stop()
|
|
213
|
+
console.log(chalk.red(`Error: ${err.response?.data?.error?.message || err.message}`))
|
|
214
|
+
process.exit(1)
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
// Analyze file command
|
|
219
|
+
program
|
|
220
|
+
.command('analyze <file>')
|
|
221
|
+
.description('Analyze a file with AI')
|
|
222
|
+
.option('-m, --mode <mode>', 'AI mode (standard/premium/elite)', 'standard')
|
|
223
|
+
.option('-i, --instruction <text>', 'What to do with the file', 'Analyze this file and explain what it does. Suggest improvements.')
|
|
224
|
+
.action(async (filePath, opts) => {
|
|
225
|
+
if (!fs.existsSync(filePath)) {
|
|
226
|
+
console.log(chalk.red(`File not found: ${filePath}`))
|
|
227
|
+
process.exit(1)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const content = fs.readFileSync(filePath, 'utf8')
|
|
231
|
+
const fileName = path.basename(filePath)
|
|
232
|
+
const prompt = `File: ${fileName}\n\n\`\`\`\n${content.slice(0, 10000)}\n\`\`\`\n\n${opts.instruction}`
|
|
233
|
+
|
|
234
|
+
console.log(chalk.gray(`Analyzing ${fileName}...\n`))
|
|
235
|
+
const spinner = ora(chalk.gray('Processing...')).start()
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const reply = await callAPI([{ role: 'user', content: prompt }], 'general', opts.mode)
|
|
239
|
+
spinner.stop()
|
|
240
|
+
console.log(formatResponse(reply))
|
|
241
|
+
} catch (err) {
|
|
242
|
+
spinner.stop()
|
|
243
|
+
console.log(chalk.red(`Error: ${err.message}`))
|
|
244
|
+
process.exit(1)
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// Generate command โ save to files
|
|
249
|
+
program
|
|
250
|
+
.command('generate <prompt...>')
|
|
251
|
+
.description('Generate code and save to files automatically')
|
|
252
|
+
.option('-d, --domain <domain>', 'AI domain', 'general')
|
|
253
|
+
.option('-m, --mode <mode>', 'AI mode', 'premium')
|
|
254
|
+
.option('-o, --output <dir>', 'Output directory', '.')
|
|
255
|
+
.action(async (promptParts, opts) => {
|
|
256
|
+
const prompt = promptParts.join(' ') + '\n\nGenerate complete, working code. For each file, start with "=== filename.ext ===" on its own line.'
|
|
257
|
+
const spinner = ora(chalk.gray('Generating...')).start()
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
const reply = await callAPI([{ role: 'user', content: prompt }], opts.domain, opts.mode)
|
|
261
|
+
spinner.stop()
|
|
262
|
+
|
|
263
|
+
// Parse files from response
|
|
264
|
+
const fileRegex = /===\s*(.+?)\s*===([\s\S]*?)(?====|$)/g
|
|
265
|
+
let match
|
|
266
|
+
let filesFound = 0
|
|
267
|
+
|
|
268
|
+
while ((match = fileRegex.exec(reply)) !== null) {
|
|
269
|
+
const fileName = match[1].trim()
|
|
270
|
+
const content = match[2].trim()
|
|
271
|
+
const filePath = path.join(opts.output, fileName)
|
|
272
|
+
|
|
273
|
+
// Create directories if needed
|
|
274
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
275
|
+
fs.writeFileSync(filePath, content, 'utf8')
|
|
276
|
+
console.log(chalk.green(`โ
Created: ${filePath}`))
|
|
277
|
+
filesFound++
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (filesFound === 0) {
|
|
281
|
+
// No structured files โ just show the response
|
|
282
|
+
console.log(formatResponse(reply))
|
|
283
|
+
} else {
|
|
284
|
+
console.log(chalk.green(`\nโ
Generated ${filesFound} file(s) in ${opts.output}\n`))
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
spinner.stop()
|
|
288
|
+
console.log(chalk.red(`Error: ${err.message}`))
|
|
289
|
+
process.exit(1)
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
// Config command
|
|
294
|
+
program
|
|
295
|
+
.command('config')
|
|
296
|
+
.description('Show current configuration')
|
|
297
|
+
.action(() => {
|
|
298
|
+
const apiKey = config.get('apiKey')
|
|
299
|
+
console.log(chalk.white('\nSAPPLANTA AI CLI Configuration:'))
|
|
300
|
+
console.log(chalk.gray(`API Key: ${apiKey ? apiKey.slice(0, 15) + '...' : 'Not set'}`))
|
|
301
|
+
console.log(chalk.gray(`Get API key: https://www.sapplanta.site/developer\n`))
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
// Show banner on help
|
|
305
|
+
program.addHelpText('beforeAll', '\n ๐ฐ๐ช SAPPLANTA AI โ Built in Kenya\n')
|
|
306
|
+
|
|
307
|
+
program.parse()
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sapplanta",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "SAPPLANTA AI - The All-in-One AI Platform CLI. Chat, generate code, and more from your terminal.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sapplanta": "bin/sapplanta.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/sapplanta.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"AI",
|
|
14
|
+
"Claude",
|
|
15
|
+
"GPT",
|
|
16
|
+
"Kenya",
|
|
17
|
+
"Sapplanta",
|
|
18
|
+
"CLI",
|
|
19
|
+
"coding",
|
|
20
|
+
"trading"
|
|
21
|
+
],
|
|
22
|
+
"author": "SAPPLANTA ENTERPRISE",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"axios": "^1.6.0",
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
|
+
"commander": "^11.0.0",
|
|
28
|
+
"inquirer": "^8.2.6",
|
|
29
|
+
"ora": "^5.4.1",
|
|
30
|
+
"conf": "^10.2.0",
|
|
31
|
+
"marked": "^9.0.0",
|
|
32
|
+
"marked-terminal": "^6.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|