pokt-cli 1.0.6 → 1.0.8
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 +112 -119
- package/dist/bin/pokt.js +1 -1
- package/dist/chat/loop.js +231 -6
- package/dist/chat/sessions.d.ts +18 -0
- package/dist/chat/sessions.js +120 -0
- package/dist/commands/chat.js +1 -1
- package/dist/ui.d.ts +6 -1
- package/dist/ui.js +114 -21
- package/package.json +61 -62
package/README.md
CHANGED
|
@@ -1,119 +1,112 @@
|
|
|
1
|
-
# Pokt CLI
|
|
2
|
-
|
|
3
|
-
CLI de **Vibe Coding** com IA: OpenRouter, Ollama (local e cloud), Gemini e provedor Pokt (controller).
|
|
4
|
-
|
|
5
|
-
## Requisitos
|
|
6
|
-
|
|
7
|
-
- **Node.js** >= 18.0.0
|
|
8
|
-
|
|
9
|
-
## Instalação
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
pokt
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
pokt
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- `pokt
|
|
77
|
-
- `pokt
|
|
78
|
-
- `pokt
|
|
79
|
-
- `pokt
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# Executar após o build
|
|
114
|
-
npm start
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Licença
|
|
118
|
-
|
|
119
|
-
ISC · **PoktWeb**
|
|
1
|
+
# Pokt CLI
|
|
2
|
+
|
|
3
|
+
CLI de **Vibe Coding** com IA: OpenRouter, Ollama (local e cloud), Gemini e provedor Pokt (controller).
|
|
4
|
+
|
|
5
|
+
## Requisitos
|
|
6
|
+
|
|
7
|
+
- **Node.js** >= 18.0.0
|
|
8
|
+
|
|
9
|
+
## Instalação
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Instalação principal (global)
|
|
13
|
+
npm install -g pokt-cli
|
|
14
|
+
|
|
15
|
+
# Alternativa: usar sem instalar
|
|
16
|
+
npx pokt-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Uso
|
|
20
|
+
|
|
21
|
+
Sem argumentos, o Pokt abre um menu interativo:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pokt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Se o `pokt` não for reconhecido (Windows)
|
|
28
|
+
|
|
29
|
+
Se você instalou com `npm install -g pokt-cli` mas o PowerShell diz que `pokt` não existe, normalmente é **PATH do prefixo global do npm**.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Veja onde o npm instala pacotes globais
|
|
33
|
+
npm config get prefix
|
|
34
|
+
|
|
35
|
+
# Verifique se o comando foi criado (PowerShell)
|
|
36
|
+
where pokt
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- **Garanta no PATH**: adicione o `prefix` acima (geralmente algo como `%AppData%\\npm`) ao PATH do Windows.
|
|
40
|
+
- **Reinicie o terminal**: feche e abra o PowerShell/Terminal novamente.
|
|
41
|
+
- **Reinstale**: `npm uninstall -g pokt-cli && npm install -g pokt-cli`
|
|
42
|
+
|
|
43
|
+
Ou use os comandos diretamente:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pokt chat # Iniciar chat (Vibe Coding)
|
|
47
|
+
pokt models list # Listar modelos
|
|
48
|
+
pokt provider use openrouter
|
|
49
|
+
pokt config show
|
|
50
|
+
pokt --help
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Comandos
|
|
54
|
+
|
|
55
|
+
| Comando | Descrição |
|
|
56
|
+
|--------|-----------|
|
|
57
|
+
| `pokt` | Menu interativo |
|
|
58
|
+
| `pokt chat` | Iniciar sessão de chat com a IA |
|
|
59
|
+
| `pokt config <action>` | Configurar chaves e tokens |
|
|
60
|
+
| `pokt models <action>` | Gerenciar modelos (listar, adicionar, trocar) |
|
|
61
|
+
| `pokt provider use <provider>` | Trocar provedor de API |
|
|
62
|
+
| `pokt mcp [action]` | Gerenciar servidores MCP (ferramentas externas) |
|
|
63
|
+
|
|
64
|
+
### Config (`config`)
|
|
65
|
+
|
|
66
|
+
- `pokt config show` — Mostra a configuração atual (tokens mascarados).
|
|
67
|
+
- `pokt config set-openrouter -v <token>` — Token OpenRouter.
|
|
68
|
+
- `pokt config set-ollama -v <url>` — URL base do Ollama local.
|
|
69
|
+
- `pokt config set-ollama-cloud -v <key>` — API key Ollama Cloud.
|
|
70
|
+
- `pokt config set-gemini -v <key>` — API key Google Gemini.
|
|
71
|
+
- `pokt config set-pokt-token -v <token>` — Token do controller Pokt.
|
|
72
|
+
- `pokt config clear-openrouter` — Remove o token OpenRouter.
|
|
73
|
+
|
|
74
|
+
### Modelos (`models`)
|
|
75
|
+
|
|
76
|
+
- `pokt models list` — Lista modelos registrados e o ativo.
|
|
77
|
+
- `pokt models fetch-openrouter` — Busca modelos disponíveis no OpenRouter.
|
|
78
|
+
- `pokt models fetch-ollama` — Busca modelos do Ollama local.
|
|
79
|
+
- `pokt models fetch-ollama-cloud` — Busca modelos do Ollama Cloud.
|
|
80
|
+
- `pokt models add-openrouter`, `add-ollama`, `add-ollama-cloud` — Adiciona modelo (use `-i <id>`).
|
|
81
|
+
- `pokt models use -i <id> -p <provider>` — Define o modelo ativo.
|
|
82
|
+
|
|
83
|
+
### Provedores (`provider`)
|
|
84
|
+
|
|
85
|
+
Provedores suportados: `controller` (Pokt), `openrouter`, `gemini`, `ollama`, `ollama-cloud`.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pokt provider use openrouter
|
|
89
|
+
pokt provider use ollama
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Desenvolvimento
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Clonar e instalar
|
|
96
|
+
git clone https://github.com/PoktWeb/Pokt_CLI.git
|
|
97
|
+
cd Pokt_CLI
|
|
98
|
+
npm install
|
|
99
|
+
|
|
100
|
+
# Desenvolvimento (executa o TypeScript direto)
|
|
101
|
+
npm run dev
|
|
102
|
+
|
|
103
|
+
# Build
|
|
104
|
+
npm run build
|
|
105
|
+
|
|
106
|
+
# Executar após o build
|
|
107
|
+
npm start
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Licença
|
|
111
|
+
|
|
112
|
+
ISC · **PoktWeb**
|
package/dist/bin/pokt.js
CHANGED
|
@@ -37,7 +37,7 @@ async function showMenu() {
|
|
|
37
37
|
const active = getEffectiveActiveModel();
|
|
38
38
|
const providerLabel = active ? (PROVIDER_LABELS[active.provider] ?? active.provider) : 'No provider';
|
|
39
39
|
console.log('');
|
|
40
|
-
|
|
40
|
+
await ui.printBanner({ animate: true });
|
|
41
41
|
console.log(ui.statusLine(providerLabel));
|
|
42
42
|
console.log('');
|
|
43
43
|
console.log(ui.separator());
|
package/dist/chat/loop.js
CHANGED
|
@@ -2,9 +2,11 @@ import prompts from 'prompts';
|
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import { ui } from '../ui.js';
|
|
4
4
|
import { runProFlow } from '../commands/pro.js';
|
|
5
|
+
import { PROVIDER_LABELS, ALL_PROVIDERS } from '../config.js';
|
|
5
6
|
import { config } from '../config.js';
|
|
6
7
|
import { getClient } from './client.js';
|
|
7
8
|
import { tools, executeTool } from './tools.js';
|
|
9
|
+
import { saveAuto, loadAuto, listCheckpoints, saveCheckpoint, loadCheckpoint, deleteCheckpoint, exportConversation, getSessionsDir } from './sessions.js';
|
|
8
10
|
import { connectMcpServer, getAllMcpToolsOpenAI, callMcpTool, isMcpTool, disconnectAllMcp, } from '../mcp/client.js';
|
|
9
11
|
const SYSTEM_PROMPT = `You are Pokt CLI, an elite AI Software Engineer.
|
|
10
12
|
Your goal is to help the user build, fix, and maintain software projects with high quality.
|
|
@@ -46,7 +48,8 @@ async function loadProjectStructure() {
|
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
export async function startChatLoop(modelConfig) {
|
|
49
|
-
|
|
51
|
+
let activeModel = modelConfig;
|
|
52
|
+
let client = await getClient(activeModel);
|
|
50
53
|
// Conectar servidores MCP configurados e montar lista de tools (nativas + MCP)
|
|
51
54
|
const mcpServers = config.get('mcpServers') ?? [];
|
|
52
55
|
for (const server of mcpServers) {
|
|
@@ -59,14 +62,174 @@ export async function startChatLoop(modelConfig) {
|
|
|
59
62
|
...tools,
|
|
60
63
|
...getAllMcpToolsOpenAI(),
|
|
61
64
|
];
|
|
62
|
-
const messages = [
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
const messages = [{ role: 'system', content: SYSTEM_PROMPT }];
|
|
66
|
+
// Auto-resume do projeto (estilo gemini): se existir, adiciona mensagens anteriores (sem duplicar system prompt)
|
|
67
|
+
const prev = loadAuto();
|
|
68
|
+
if (prev && prev.length > 0) {
|
|
69
|
+
for (const m of prev) {
|
|
70
|
+
if (m.role === 'system')
|
|
71
|
+
continue;
|
|
72
|
+
messages.push({ role: m.role, content: m.content });
|
|
73
|
+
}
|
|
74
|
+
console.log(ui.dim(`Sessão anterior carregada (projeto). Use /chat list | /chat save <tag>.`));
|
|
75
|
+
}
|
|
76
|
+
function modelLabel(m) {
|
|
77
|
+
const provider = PROVIDER_LABELS[m.provider] ?? m.provider;
|
|
78
|
+
return `[${provider}] ${m.id}`;
|
|
79
|
+
}
|
|
80
|
+
async function switchModelFlow(mode = 'model') {
|
|
81
|
+
const models = config.get('registeredModels') ?? [];
|
|
82
|
+
if (!Array.isArray(models) || models.length === 0) {
|
|
83
|
+
console.log(ui.error('Nenhum modelo registrado. Rode: pokt models list'));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const providerChoices = ALL_PROVIDERS.map((p) => {
|
|
87
|
+
const label = PROVIDER_LABELS[p] ?? p;
|
|
88
|
+
const hasAny = models.some((m) => m.provider === p);
|
|
89
|
+
const star = activeModel.provider === p ? '★ ' : '';
|
|
90
|
+
return {
|
|
91
|
+
title: `${star}${label}${hasAny ? '' : ' (sem modelos)'}`,
|
|
92
|
+
value: p,
|
|
93
|
+
disabled: !hasAny,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
const providerPick = await prompts({
|
|
97
|
+
type: 'select',
|
|
98
|
+
name: 'provider',
|
|
99
|
+
message: mode === 'provider' ? 'Trocar provedor:' : 'Selecione o provedor:',
|
|
100
|
+
choices: [...providerChoices, { title: '🔙 Cancelar', value: 'cancel' }],
|
|
101
|
+
});
|
|
102
|
+
if (!providerPick.provider || providerPick.provider === 'cancel')
|
|
103
|
+
return;
|
|
104
|
+
const provider = providerPick.provider;
|
|
105
|
+
const providerModels = models.filter((m) => m.provider === provider);
|
|
106
|
+
if (providerModels.length === 0) {
|
|
107
|
+
console.log(ui.error(`Sem modelos para ${PROVIDER_LABELS[provider] ?? provider}.`));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let selected = null;
|
|
111
|
+
if (mode === 'provider') {
|
|
112
|
+
selected = providerModels[0];
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const pick = await prompts({
|
|
116
|
+
type: 'select',
|
|
117
|
+
name: 'idx',
|
|
118
|
+
message: `Modelos em ${PROVIDER_LABELS[provider] ?? provider}:`,
|
|
119
|
+
choices: [
|
|
120
|
+
...providerModels.map((m, i) => ({
|
|
121
|
+
title: `${activeModel.provider === m.provider && activeModel.id === m.id ? '★ ' : ''}${m.id}`,
|
|
122
|
+
value: i,
|
|
123
|
+
})),
|
|
124
|
+
{ title: '🔙 Cancelar', value: 'cancel' },
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
if (pick.idx === 'cancel' || typeof pick.idx !== 'number')
|
|
128
|
+
return;
|
|
129
|
+
selected = providerModels[pick.idx] ?? null;
|
|
130
|
+
}
|
|
131
|
+
if (!selected)
|
|
132
|
+
return;
|
|
133
|
+
// Validar chaves/credenciais necessárias (reaproveita mesma lógica do providerCommand / getClient)
|
|
134
|
+
try {
|
|
135
|
+
const newClient = await getClient(selected);
|
|
136
|
+
client = newClient;
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
console.log(ui.error(e?.message ?? String(e)));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
activeModel = selected;
|
|
143
|
+
config.set('activeModel', selected);
|
|
144
|
+
console.log(ui.success(`Modelo ativo atualizado: ${modelLabel(selected)}`));
|
|
145
|
+
console.log(ui.dim('Dica: o histórico do chat foi mantido; apenas o modelo/provedor mudou.'));
|
|
146
|
+
}
|
|
147
|
+
function printHelp() {
|
|
148
|
+
console.log(ui.dim(`
|
|
149
|
+
Comandos do chat:
|
|
150
|
+
${ui.accent('/help')} — mostra esta ajuda
|
|
151
|
+
${ui.accent('/clear')} — limpa a tela
|
|
152
|
+
${ui.accent('/status')} — mostra modelo/provider atual
|
|
153
|
+
${ui.accent('/model')} — trocar modelo (menu interativo)
|
|
154
|
+
${ui.accent('/provider')} — trocar provedor (usa o 1º modelo disponível)
|
|
155
|
+
${ui.accent('/chat')} — checkpoints/sessões (list/save/resume/delete/share)
|
|
156
|
+
${ui.accent('/resume')} — alias de /chat
|
|
157
|
+
${ui.accent('/copy')} — copia a última resposta do Pokt (Windows: clip)
|
|
158
|
+
${ui.accent('/pro')} — abrir Pokt Pro no navegador
|
|
159
|
+
${ui.accent('/quit')} ou ${ui.accent('exit')} — sair do chat
|
|
160
|
+
`));
|
|
161
|
+
}
|
|
162
|
+
let lastAssistantText = '';
|
|
163
|
+
async function handleChatCommand(raw) {
|
|
164
|
+
const parts = raw.trim().split(/\s+/);
|
|
165
|
+
const cmd = parts[0].toLowerCase();
|
|
166
|
+
const sub = (parts[1] ?? 'list').toLowerCase();
|
|
167
|
+
const arg = parts.slice(2).join(' ').trim();
|
|
168
|
+
if (sub === 'dir') {
|
|
169
|
+
console.log(ui.dim(`Sessões: ${getSessionsDir()}`));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (sub === 'list') {
|
|
173
|
+
const items = listCheckpoints();
|
|
174
|
+
if (items.length === 0) {
|
|
175
|
+
console.log(ui.dim('Nenhum checkpoint salvo ainda. Use: /chat save <tag>'));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
console.log(ui.dim('Checkpoints:'));
|
|
179
|
+
for (const it of items) {
|
|
180
|
+
console.log(`- ${ui.accent(it.tag)} ${it.updatedAt ? ui.dim(`(${it.updatedAt})`) : ''}`);
|
|
181
|
+
}
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (sub === 'save') {
|
|
185
|
+
if (!arg) {
|
|
186
|
+
console.log(ui.error('Uso: /chat save <tag>'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
saveCheckpoint(arg, messages);
|
|
190
|
+
console.log(ui.success(`Checkpoint salvo: ${arg}`));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (sub === 'resume' || sub === 'load') {
|
|
194
|
+
if (!arg) {
|
|
195
|
+
console.log(ui.error('Uso: /chat resume <tag>'));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const loaded = loadCheckpoint(arg);
|
|
199
|
+
// mantém system prompt; substitui resto
|
|
200
|
+
const sys = messages[0];
|
|
201
|
+
messages.length = 0;
|
|
202
|
+
messages.push(sys);
|
|
203
|
+
for (const m of loaded) {
|
|
204
|
+
if (m.role === 'system')
|
|
205
|
+
continue;
|
|
206
|
+
messages.push({ role: m.role, content: m.content });
|
|
207
|
+
}
|
|
208
|
+
console.log(ui.success(`Checkpoint carregado: ${arg}`));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (sub === 'delete' || sub === 'rm') {
|
|
212
|
+
if (!arg) {
|
|
213
|
+
console.log(ui.error('Uso: /chat delete <tag>'));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
deleteCheckpoint(arg);
|
|
217
|
+
console.log(ui.success(`Checkpoint removido: ${arg}`));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (sub === 'share' || sub === 'export') {
|
|
221
|
+
const filename = arg || `pokt-chat-${Date.now()}.md`;
|
|
222
|
+
const out = exportConversation(filename, messages);
|
|
223
|
+
console.log(ui.success(`Exportado: ${out}`));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
console.log(ui.warn(`Subcomando desconhecido: ${sub}. Use /chat list|save|resume|delete|share`));
|
|
227
|
+
}
|
|
65
228
|
while (true) {
|
|
66
229
|
console.log('');
|
|
67
230
|
const cwd = process.cwd();
|
|
68
231
|
console.log(ui.dim(`Diretório atual: ${cwd}`));
|
|
69
|
-
console.log(ui.shortcutsLine(
|
|
232
|
+
console.log(ui.shortcutsLine(undefined, '? · /help · /pro'));
|
|
70
233
|
const response = await prompts({
|
|
71
234
|
type: 'text',
|
|
72
235
|
name: 'input',
|
|
@@ -82,6 +245,55 @@ export async function startChatLoop(modelConfig) {
|
|
|
82
245
|
}
|
|
83
246
|
const trimmed = userInput.trim();
|
|
84
247
|
const low = trimmed.toLowerCase();
|
|
248
|
+
if (low === '/help' || low === '/?' || low === 'help') {
|
|
249
|
+
printHelp();
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (low === '/clear') {
|
|
253
|
+
console.clear();
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (low === '/status') {
|
|
257
|
+
console.log(ui.statusBar({ cwd: process.cwd(), model: `/model ${activeModel.provider} (${activeModel.id})` }));
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (low.startsWith('/chat') || low.startsWith('/resume')) {
|
|
261
|
+
await handleChatCommand(trimmed.replace(/^\/resume/i, '/chat'));
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (low === '/copy') {
|
|
265
|
+
try {
|
|
266
|
+
if (!lastAssistantText) {
|
|
267
|
+
console.log(ui.warn('Nada para copiar ainda.'));
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
// Sem interpolar conteúdo no comando (evita quebra por aspas/newlines).
|
|
271
|
+
// Escreve para um arquivo temporário e copia via Get-Content | clip (Windows).
|
|
272
|
+
const tmp = `.pokt_copy_${Date.now()}.txt`;
|
|
273
|
+
await executeTool('write_file', JSON.stringify({ path: tmp, content: lastAssistantText }));
|
|
274
|
+
await executeTool('run_command', JSON.stringify({ command: `powershell -NoProfile -Command "Get-Content -Raw '${tmp}' | clip"` }));
|
|
275
|
+
// best-effort cleanup
|
|
276
|
+
try {
|
|
277
|
+
await executeTool('delete_file', JSON.stringify({ path: tmp }));
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// ignore
|
|
281
|
+
}
|
|
282
|
+
console.log(ui.success('Copiado para a área de transferência.'));
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
console.log(ui.warn('Falha ao copiar. Se estiver no Windows, verifique se o comando "clip" está disponível.'));
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (low === '/model') {
|
|
290
|
+
await switchModelFlow('model');
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (low === '/provider') {
|
|
294
|
+
await switchModelFlow('provider');
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
85
297
|
if (low === '/pro' || low === '/torne-se-pro' || low === 'torne-se pro') {
|
|
86
298
|
runProFlow();
|
|
87
299
|
continue;
|
|
@@ -91,10 +303,12 @@ export async function startChatLoop(modelConfig) {
|
|
|
91
303
|
Atalhos:
|
|
92
304
|
${ui.accent('/pro')} ou ${ui.accent('/torne-se-pro')} — abrir Pokt Pro no navegador (pagamento + chave)
|
|
93
305
|
exit, ${ui.accent('/quit')} — sair do chat
|
|
306
|
+
${ui.accent('/help')} — ver comandos do chat
|
|
94
307
|
`));
|
|
95
308
|
continue;
|
|
96
309
|
}
|
|
97
310
|
messages.push({ role: 'user', content: userInput });
|
|
311
|
+
saveAuto(messages);
|
|
98
312
|
// Primeiro o modelo vê o pedido; depois carregamos a estrutura do projeto para ele entender e então criar/editar
|
|
99
313
|
const isFirstUserMessage = messages.filter(m => m.role === 'user').length === 1;
|
|
100
314
|
if (isFirstUserMessage) {
|
|
@@ -103,7 +317,18 @@ Atalhos:
|
|
|
103
317
|
loadSpinner.stop();
|
|
104
318
|
messages.push({ role: 'system', content: `Current Project Structure:\n${projectStructure}` });
|
|
105
319
|
}
|
|
106
|
-
await processLLMResponse(client,
|
|
320
|
+
await processLLMResponse(client, activeModel.id, messages, allTools);
|
|
321
|
+
// Atualiza auto-save após resposta
|
|
322
|
+
saveAuto(messages);
|
|
323
|
+
// Captura última resposta do assistente para /copy (melhor esforço)
|
|
324
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
325
|
+
const m = messages[i];
|
|
326
|
+
if (m?.role === 'assistant') {
|
|
327
|
+
const c = m.content;
|
|
328
|
+
lastAssistantText = typeof c === 'string' ? c : Array.isArray(c) ? c.map((p) => (p && p.text ? p.text : String(p))).join('') : String(c ?? '');
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
107
332
|
}
|
|
108
333
|
await disconnectAllMcp();
|
|
109
334
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions/completions.js';
|
|
2
|
+
type PersistedMessage = {
|
|
3
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
4
|
+
content: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function getProjectHash(cwd?: string): string;
|
|
7
|
+
export declare function getSessionsDir(): string;
|
|
8
|
+
export declare function saveAuto(messages: ChatCompletionMessageParam[]): void;
|
|
9
|
+
export declare function loadAuto(): PersistedMessage[] | null;
|
|
10
|
+
export declare function listCheckpoints(): Array<{
|
|
11
|
+
tag: string;
|
|
12
|
+
updatedAt?: string;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function saveCheckpoint(tag: string, messages: ChatCompletionMessageParam[]): void;
|
|
15
|
+
export declare function loadCheckpoint(tag: string): PersistedMessage[];
|
|
16
|
+
export declare function deleteCheckpoint(tag: string): void;
|
|
17
|
+
export declare function exportConversation(filename: string, messages: ChatCompletionMessageParam[]): string;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
function toPersisted(messages) {
|
|
6
|
+
return messages
|
|
7
|
+
.filter((m) => !!m && typeof m === 'object' && 'role' in m)
|
|
8
|
+
.map((m) => {
|
|
9
|
+
const role = m.role;
|
|
10
|
+
const content = m.content;
|
|
11
|
+
if (typeof content === 'string')
|
|
12
|
+
return { role, content };
|
|
13
|
+
if (Array.isArray(content)) {
|
|
14
|
+
const text = content
|
|
15
|
+
.map((part) => (part && typeof part === 'object' && 'text' in part ? String(part.text) : String(part)))
|
|
16
|
+
.join('');
|
|
17
|
+
return { role, content: text };
|
|
18
|
+
}
|
|
19
|
+
return { role, content: content != null ? String(content) : '' };
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function ensureDir(p) {
|
|
23
|
+
fs.mkdirSync(p, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
function safeTag(tag) {
|
|
26
|
+
return tag.trim().replace(/[<>:"/\\|?*\x00-\x1F]/g, '_').slice(0, 80);
|
|
27
|
+
}
|
|
28
|
+
export function getProjectHash(cwd = process.cwd()) {
|
|
29
|
+
const h = crypto.createHash('sha1');
|
|
30
|
+
h.update(path.resolve(cwd));
|
|
31
|
+
return h.digest('hex').slice(0, 12);
|
|
32
|
+
}
|
|
33
|
+
export function getSessionsDir() {
|
|
34
|
+
// compatível Windows/mac/linux
|
|
35
|
+
const base = path.join(os.homedir(), '.pokt', 'tmp');
|
|
36
|
+
const proj = getProjectHash();
|
|
37
|
+
const dir = path.join(base, proj);
|
|
38
|
+
ensureDir(dir);
|
|
39
|
+
return dir;
|
|
40
|
+
}
|
|
41
|
+
function getAutoPath() {
|
|
42
|
+
return path.join(getSessionsDir(), 'auto.json');
|
|
43
|
+
}
|
|
44
|
+
export function saveAuto(messages) {
|
|
45
|
+
const payload = {
|
|
46
|
+
updatedAt: new Date().toISOString(),
|
|
47
|
+
cwd: process.cwd(),
|
|
48
|
+
messages: toPersisted(messages),
|
|
49
|
+
};
|
|
50
|
+
fs.writeFileSync(getAutoPath(), JSON.stringify(payload, null, 2), 'utf8');
|
|
51
|
+
}
|
|
52
|
+
export function loadAuto() {
|
|
53
|
+
try {
|
|
54
|
+
const raw = fs.readFileSync(getAutoPath(), 'utf8');
|
|
55
|
+
const parsed = JSON.parse(raw);
|
|
56
|
+
return Array.isArray(parsed?.messages) ? parsed.messages : null;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function tagPath(tag) {
|
|
63
|
+
return path.join(getSessionsDir(), `checkpoint.${safeTag(tag)}.json`);
|
|
64
|
+
}
|
|
65
|
+
export function listCheckpoints() {
|
|
66
|
+
const dir = getSessionsDir();
|
|
67
|
+
const files = fs.readdirSync(dir).filter((f) => f.startsWith('checkpoint.') && f.endsWith('.json'));
|
|
68
|
+
return files
|
|
69
|
+
.map((f) => {
|
|
70
|
+
const tag = f.replace(/^checkpoint\./, '').replace(/\.json$/, '');
|
|
71
|
+
try {
|
|
72
|
+
const raw = fs.readFileSync(path.join(dir, f), 'utf8');
|
|
73
|
+
const parsed = JSON.parse(raw);
|
|
74
|
+
return { tag, updatedAt: parsed.updatedAt };
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return { tag };
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
.sort((a, b) => String(b.updatedAt ?? '').localeCompare(String(a.updatedAt ?? '')));
|
|
81
|
+
}
|
|
82
|
+
export function saveCheckpoint(tag, messages) {
|
|
83
|
+
const t = safeTag(tag);
|
|
84
|
+
if (!t)
|
|
85
|
+
throw new Error('Tag inválida.');
|
|
86
|
+
const payload = {
|
|
87
|
+
tag: t,
|
|
88
|
+
updatedAt: new Date().toISOString(),
|
|
89
|
+
cwd: process.cwd(),
|
|
90
|
+
messages: toPersisted(messages),
|
|
91
|
+
};
|
|
92
|
+
fs.writeFileSync(tagPath(t), JSON.stringify(payload, null, 2), 'utf8');
|
|
93
|
+
}
|
|
94
|
+
export function loadCheckpoint(tag) {
|
|
95
|
+
const t = safeTag(tag);
|
|
96
|
+
const raw = fs.readFileSync(tagPath(t), 'utf8');
|
|
97
|
+
const parsed = JSON.parse(raw);
|
|
98
|
+
if (!Array.isArray(parsed?.messages))
|
|
99
|
+
throw new Error('Checkpoint inválido.');
|
|
100
|
+
return parsed.messages;
|
|
101
|
+
}
|
|
102
|
+
export function deleteCheckpoint(tag) {
|
|
103
|
+
const t = safeTag(tag);
|
|
104
|
+
fs.unlinkSync(tagPath(t));
|
|
105
|
+
}
|
|
106
|
+
export function exportConversation(filename, messages) {
|
|
107
|
+
const out = path.isAbsolute(filename) ? filename : path.join(process.cwd(), filename);
|
|
108
|
+
const ext = path.extname(out).toLowerCase();
|
|
109
|
+
if (ext === '.json') {
|
|
110
|
+
fs.writeFileSync(out, JSON.stringify({ exportedAt: new Date().toISOString(), messages: toPersisted(messages) }, null, 2), 'utf8');
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
// markdown
|
|
114
|
+
const md = toPersisted(messages)
|
|
115
|
+
.filter((m) => m.role !== 'system')
|
|
116
|
+
.map((m) => `## ${m.role}\n\n${m.content}\n`)
|
|
117
|
+
.join('\n');
|
|
118
|
+
fs.writeFileSync(out, `# Pokt CLI chat export\n\nExportado em: ${new Date().toISOString()}\n\n${md}`, 'utf8');
|
|
119
|
+
return out;
|
|
120
|
+
}
|
package/dist/commands/chat.js
CHANGED
|
@@ -27,7 +27,7 @@ export const chatCommand = {
|
|
|
27
27
|
}
|
|
28
28
|
// Se veio do menu interativo, não repetir banner/tips (já foram exibidos)
|
|
29
29
|
if (!fromMenu) {
|
|
30
|
-
|
|
30
|
+
await ui.printBanner({ animate: true });
|
|
31
31
|
console.log(ui.statusLine(`[${activeModel.provider}] ${activeModel.id}`));
|
|
32
32
|
console.log('');
|
|
33
33
|
console.log(ui.tips());
|
package/dist/ui.d.ts
CHANGED
|
@@ -9,8 +9,13 @@ export declare const ui: {
|
|
|
9
9
|
labelPokt: () => any;
|
|
10
10
|
accent: (text: string) => any;
|
|
11
11
|
muted: (text: string) => any;
|
|
12
|
-
/** Banner principal
|
|
12
|
+
/** Banner principal em ASCII (Pokt CLI) */
|
|
13
13
|
banner: (customVersion?: string) => string;
|
|
14
|
+
/** Imprime o banner com “typewriter” (letra por letra) */
|
|
15
|
+
printBanner: (opts?: {
|
|
16
|
+
animate?: boolean;
|
|
17
|
+
version?: string;
|
|
18
|
+
}) => Promise<void>;
|
|
14
19
|
/** Status de login / provider (uma linha) */
|
|
15
20
|
statusLine: (providerLabel: string, configPath?: string) => any;
|
|
16
21
|
/** Seção "Tips for getting started" */
|
package/dist/ui.js
CHANGED
|
@@ -2,15 +2,101 @@ import chalk from 'chalk';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
function sleep(ms) {
|
|
6
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
7
|
+
}
|
|
8
|
+
function lerp(a, b, t) {
|
|
9
|
+
return a + (b - a) * t;
|
|
10
|
+
}
|
|
11
|
+
function gradientColor(idx, len, start, end) {
|
|
12
|
+
if (len <= 1)
|
|
13
|
+
return start;
|
|
14
|
+
const t = idx / (len - 1);
|
|
15
|
+
return [
|
|
16
|
+
Math.round(lerp(start[0], end[0], t)),
|
|
17
|
+
Math.round(lerp(start[1], end[1], t)),
|
|
18
|
+
Math.round(lerp(start[2], end[2], t)),
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
function gradientChars(text, start, end) {
|
|
22
|
+
const chars = [...text];
|
|
23
|
+
return chars.map((ch, i) => {
|
|
24
|
+
if (ch === ' ')
|
|
25
|
+
return ' ';
|
|
26
|
+
const [r, g, b] = gradientColor(i, chars.length, start, end);
|
|
27
|
+
return chalk.rgb(r, g, b).bold(ch);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function getVersion() {
|
|
31
|
+
// Prioridade: env de empacotamento → package.json → fallback
|
|
32
|
+
const envVer = process.env.POKT_CLI_VERSION || process.env.npm_package_version;
|
|
33
|
+
if (envVer)
|
|
34
|
+
return envVer;
|
|
35
|
+
try {
|
|
36
|
+
const pkgPath = path.resolve(process.cwd(), 'package.json');
|
|
37
|
+
if (fs.existsSync(pkgPath)) {
|
|
38
|
+
const raw = fs.readFileSync(pkgPath, 'utf8');
|
|
39
|
+
const parsed = JSON.parse(raw);
|
|
40
|
+
if (parsed?.version)
|
|
41
|
+
return parsed.version;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
return 'dev';
|
|
48
|
+
}
|
|
49
|
+
function bannerLines(ver) {
|
|
50
|
+
const left = [
|
|
51
|
+
'██████╗ ██████╗ ██╗ ██╗████████╗',
|
|
52
|
+
'██╔══██╗██╔═══██╗██║ ██╔╝╚══██╔══╝',
|
|
53
|
+
'██████╔╝██║ ██║█████╔╝ ██║',
|
|
54
|
+
'██╔═══╝ ██║ ██║██╔═██╗ ██║',
|
|
55
|
+
'██║ ╚██████╔╝██║ ██╗ ██║',
|
|
56
|
+
'╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝',
|
|
57
|
+
];
|
|
58
|
+
const right = [
|
|
59
|
+
' ██████╗██╗ ██╗',
|
|
60
|
+
' ██╔════╝██║ ██║',
|
|
61
|
+
' ██║ ██║ ██║',
|
|
62
|
+
' ██║ ██║ ██║',
|
|
63
|
+
' ╚██████╗███████╗██║',
|
|
64
|
+
' ╚═════╝╚══════╝╚═╝',
|
|
65
|
+
];
|
|
66
|
+
const lines = left.map((l, i) => `${l}${right[i] ?? ''}`);
|
|
67
|
+
lines.push(' '.repeat(18) + `CLI Version v${ver}`);
|
|
68
|
+
return lines;
|
|
69
|
+
}
|
|
70
|
+
function bannerAscii(ver) {
|
|
71
|
+
const start = [0, 205, 255]; // azul/ciano
|
|
72
|
+
const end = [155, 89, 255]; // roxo
|
|
73
|
+
const lines = bannerLines(ver);
|
|
74
|
+
return lines
|
|
75
|
+
.map((line, i) => {
|
|
76
|
+
if (i === lines.length - 1)
|
|
77
|
+
return chalk.gray(line);
|
|
78
|
+
return gradientChars(line, start, end).join('');
|
|
79
|
+
})
|
|
80
|
+
.join('\n');
|
|
81
|
+
}
|
|
82
|
+
async function printBannerAnimated(customVersion) {
|
|
83
|
+
const ver = customVersion ?? getVersion();
|
|
84
|
+
const start = [0, 205, 255];
|
|
85
|
+
const end = [155, 89, 255];
|
|
86
|
+
const lines = bannerLines(ver);
|
|
87
|
+
for (let li = 0; li < lines.length; li++) {
|
|
88
|
+
const line = lines[li] ?? '';
|
|
89
|
+
if (li === lines.length - 1) {
|
|
90
|
+
process.stdout.write(chalk.gray(line) + '\n');
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const colored = gradientChars(line, start, end);
|
|
94
|
+
for (let i = 0; i <= colored.length; i++) {
|
|
95
|
+
process.stdout.write('\r' + colored.slice(0, i).join(''));
|
|
96
|
+
await sleep(1);
|
|
97
|
+
}
|
|
98
|
+
process.stdout.write('\n');
|
|
99
|
+
}
|
|
14
100
|
}
|
|
15
101
|
export const ui = {
|
|
16
102
|
title: (text) => chalk.whiteBright.bold(text),
|
|
@@ -19,33 +105,40 @@ export const ui = {
|
|
|
19
105
|
error: (text) => chalk.red(text),
|
|
20
106
|
warn: (text) => chalk.yellow(text),
|
|
21
107
|
dim: (text) => chalk.gray(text),
|
|
22
|
-
labelYou: () => chalk.cyan('
|
|
108
|
+
labelYou: () => chalk.cyan('Você:'),
|
|
23
109
|
labelPokt: () => chalk.green('Pokt:'),
|
|
24
110
|
accent: (text) => chalk.blue(text),
|
|
25
111
|
muted: (text) => chalk.gray(text),
|
|
26
|
-
/** Banner principal
|
|
112
|
+
/** Banner principal em ASCII (Pokt CLI) */
|
|
27
113
|
banner: (customVersion) => {
|
|
28
|
-
const ver = customVersion ??
|
|
29
|
-
|
|
30
|
-
|
|
114
|
+
const ver = customVersion ?? getVersion();
|
|
115
|
+
return bannerAscii(ver);
|
|
116
|
+
},
|
|
117
|
+
/** Imprime o banner com “typewriter” (letra por letra) */
|
|
118
|
+
printBanner: async (opts) => {
|
|
119
|
+
if (opts?.animate) {
|
|
120
|
+
await printBannerAnimated(opts.version);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
console.log(ui.banner(opts?.version));
|
|
31
124
|
},
|
|
32
125
|
/** Status de login / provider (uma linha) */
|
|
33
126
|
statusLine: (providerLabel, configPath = '/config') => {
|
|
34
|
-
const auth = chalk.gray(`
|
|
127
|
+
const auth = chalk.gray(`Ativo: ${providerLabel} ${chalk.underline(configPath)}`);
|
|
35
128
|
return auth;
|
|
36
129
|
},
|
|
37
130
|
/** Seção "Tips for getting started" */
|
|
38
131
|
tips: () => {
|
|
39
|
-
const title = chalk.white('
|
|
132
|
+
const title = chalk.white('Dicas para começar:');
|
|
40
133
|
const tips = [
|
|
41
|
-
chalk.gray('1. /help
|
|
42
|
-
chalk.gray('2.
|
|
43
|
-
chalk.gray('3.
|
|
134
|
+
chalk.gray('1. Digite /help para ver comandos'),
|
|
135
|
+
chalk.gray('2. Peça ajuda para codar, editar arquivos ou rodar comandos'),
|
|
136
|
+
chalk.gray('3. Seja específico para melhores resultados'),
|
|
44
137
|
].join('\n');
|
|
45
138
|
return title + '\n' + tips;
|
|
46
139
|
},
|
|
47
140
|
/** Linha de atalhos acima do input */
|
|
48
|
-
shortcutsLine: (left = 'shift+tab
|
|
141
|
+
shortcutsLine: (left = 'shift+tab para aceitar edições', right = '? para atalhos', center) => {
|
|
49
142
|
const l = chalk.gray(left);
|
|
50
143
|
const r = chalk.gray(right);
|
|
51
144
|
const c = center ? chalk.gray(center) : '';
|
|
@@ -55,7 +148,7 @@ export const ui = {
|
|
|
55
148
|
return l + ' '.repeat(Math.max(0, 60 - left.length - right.length)) + r;
|
|
56
149
|
},
|
|
57
150
|
/** Placeholder do input */
|
|
58
|
-
inputPlaceholder: () => chalk.gray('
|
|
151
|
+
inputPlaceholder: () => chalk.gray('Digite sua mensagem (ou /help)'),
|
|
59
152
|
/** Barra de status inferior: path, branch, sandbox, model */
|
|
60
153
|
statusBar: (opts) => {
|
|
61
154
|
const cwd = opts.cwd ?? process.cwd();
|
package/package.json
CHANGED
|
@@ -1,62 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pokt-cli",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Vibe Coding AI CLI for OpenRouter and Ollama",
|
|
5
|
-
"main": "./dist/bin/pokt.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"pokt": "dist/bin/pokt.js"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"@types/
|
|
56
|
-
"@types/
|
|
57
|
-
"@types/
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pokt-cli",
|
|
3
|
+
"version": "1.0.8",
|
|
4
|
+
"description": "Vibe Coding AI CLI for OpenRouter and Ollama",
|
|
5
|
+
"main": "./dist/bin/pokt.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"pokt": "dist/bin/pokt.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node ./dist/bin/pokt.js",
|
|
13
|
+
"dev": "tsx ./src/bin/pokt.ts",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"package.json",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"ai",
|
|
23
|
+
"cli",
|
|
24
|
+
"coding",
|
|
25
|
+
"agent",
|
|
26
|
+
"openrouter",
|
|
27
|
+
"ollama"
|
|
28
|
+
],
|
|
29
|
+
"author": "PoktWeb",
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/PoktWeb/Pokt_CLI.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/PoktWeb/Pokt_CLI#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/PoktWeb/Pokt_CLI/issues"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
44
|
+
"chalk": "^5.3.0",
|
|
45
|
+
"conf": "^12.0.0",
|
|
46
|
+
"diff": "^8.0.3",
|
|
47
|
+
"openai": "^4.28.4",
|
|
48
|
+
"ora": "^8.0.1",
|
|
49
|
+
"prompts": "^2.4.2",
|
|
50
|
+
"yargs": "^17.7.2",
|
|
51
|
+
"zod": "^3.23.8"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/diff": "^7.0.2",
|
|
55
|
+
"@types/node": "^20.11.24",
|
|
56
|
+
"@types/prompts": "^2.4.9",
|
|
57
|
+
"@types/yargs": "^17.0.32",
|
|
58
|
+
"tsx": "^4.7.1",
|
|
59
|
+
"typescript": "^5.3.3"
|
|
60
|
+
}
|
|
61
|
+
}
|