pokt-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ import type * as Yargs from 'yargs';
2
+ interface ModelsArgs {
3
+ action?: string;
4
+ id?: string;
5
+ provider?: string;
6
+ }
7
+ export declare const modelsCommand: Yargs.CommandModule<{}, ModelsArgs>;
8
+ export {};
@@ -0,0 +1,195 @@
1
+ import { config, getEffectiveActiveModel, PROVIDER_LABELS } from '../config.js';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { ui } from '../ui.js';
5
+ export const modelsCommand = {
6
+ command: 'models <action>',
7
+ describe: 'Manage AI models',
8
+ builder: (yargs) => yargs
9
+ .positional('action', {
10
+ describe: 'Action to perform',
11
+ type: 'string',
12
+ choices: ['add', 'add-ollama', 'add-ollama-cloud', 'add-openrouter', 'use', 'list', 'fetch-openrouter', 'fetch-ollama', 'fetch-ollama-cloud']
13
+ })
14
+ .option('id', {
15
+ describe: 'Model ID (e.g., llama3, google/gemini-2.5-flash)',
16
+ type: 'string',
17
+ alias: 'i'
18
+ })
19
+ .option('provider', {
20
+ describe: 'Provider (for "add" or "use": openrouter, ollama, ollama-cloud, gemini, controller)',
21
+ type: 'string',
22
+ choices: ['openrouter', 'ollama', 'ollama-cloud', 'gemini', 'controller'],
23
+ alias: 'p'
24
+ }),
25
+ handler: async (argv) => {
26
+ const { action, id, provider } = argv;
27
+ if (action === 'list') {
28
+ const models = config.get('registeredModels');
29
+ const active = getEffectiveActiveModel();
30
+ console.log(chalk.blue('\nRegistered Models:'));
31
+ models.forEach((m) => {
32
+ const isActive = active?.id === m.id && active?.provider === m.provider;
33
+ const label = PROVIDER_LABELS[m.provider] ?? m.provider;
34
+ console.log(`${isActive ? chalk.green('★') : ' '} [${label}] ${m.id}`);
35
+ });
36
+ console.log('');
37
+ return;
38
+ }
39
+ if (action === 'fetch-openrouter') {
40
+ const spinner = ora('Fetching OpenRouter models...').start();
41
+ try {
42
+ const response = await fetch('https://openrouter.ai/api/v1/models');
43
+ if (!response.ok) {
44
+ spinner.fail(ui.error(`Failed to fetch OpenRouter models: HTTP ${response.status}`));
45
+ const body = await response.text();
46
+ if (body)
47
+ console.log(ui.dim(body.slice(0, 200)));
48
+ console.log(ui.warn('Check your network and OpenRouter token. Run: pokt config show'));
49
+ return;
50
+ }
51
+ const data = await response.json();
52
+ const openrouterModels = (data.data || []).map((m) => ({ provider: 'openrouter', id: m.id }));
53
+ const currentModels = config.get('registeredModels');
54
+ const otherModels = currentModels.filter((m) => m.provider !== 'openrouter');
55
+ config.set('registeredModels', [...otherModels, ...openrouterModels]);
56
+ spinner.succeed(ui.success(`Synchronized ${openrouterModels.length} OpenRouter models.`));
57
+ }
58
+ catch (error) {
59
+ spinner.fail(ui.error(`Failed to fetch OpenRouter models: ${error.message}`));
60
+ console.log(ui.warn('Check your network. Run: pokt config show'));
61
+ }
62
+ return;
63
+ }
64
+ if (action === 'fetch-ollama') {
65
+ const baseUrl = (config.get('ollamaBaseUrl') || 'http://localhost:11434').replace(/\/$/, '');
66
+ const url = `${baseUrl}/api/tags`;
67
+ const spinner = ora(`Fetching Ollama models (${url})...`).start();
68
+ try {
69
+ const response = await fetch(url);
70
+ if (!response.ok) {
71
+ spinner.fail(ui.error(`Failed to fetch Ollama models: HTTP ${response.status}`));
72
+ console.log(ui.warn('Check Ollama is running and ollamaBaseUrl. Run: pokt config show'));
73
+ return;
74
+ }
75
+ const data = await response.json();
76
+ const names = (data.models || []).map((m) => m.name);
77
+ const ollamaModels = names.map((name) => ({ provider: 'ollama', id: name }));
78
+ const currentModels = config.get('registeredModels');
79
+ const otherModels = currentModels.filter((m) => m.provider !== 'ollama');
80
+ config.set('registeredModels', [...otherModels, ...ollamaModels]);
81
+ spinner.succeed(ui.success(`Synchronized ${ollamaModels.length} Ollama (local) models.`));
82
+ }
83
+ catch (error) {
84
+ spinner.fail(ui.error(`Failed to fetch Ollama models: ${error.message}`));
85
+ console.log(ui.warn('Check Ollama is running. Run: pokt config show'));
86
+ }
87
+ return;
88
+ }
89
+ if (action === 'fetch-ollama-cloud') {
90
+ const apiKey = config.get('ollamaCloudApiKey');
91
+ if (!apiKey) {
92
+ console.log(ui.error('Ollama Cloud API key not set. Run: pokt config set-ollama-cloud -v <key>'));
93
+ console.log(ui.dim('Create keys at: https://ollama.com/settings/keys'));
94
+ return;
95
+ }
96
+ const spinner = ora('Fetching Ollama Cloud models (https://ollama.com/api/tags)...').start();
97
+ try {
98
+ const response = await fetch('https://ollama.com/api/tags', {
99
+ headers: { Authorization: `Bearer ${apiKey}` }
100
+ });
101
+ if (!response.ok) {
102
+ spinner.fail(ui.error(`Failed to fetch Ollama Cloud models: HTTP ${response.status}`));
103
+ const body = await response.text();
104
+ if (body)
105
+ console.log(ui.dim(body.slice(0, 200)));
106
+ console.log(ui.warn('Check your API key. Run: pokt config show'));
107
+ return;
108
+ }
109
+ const data = await response.json();
110
+ const names = (data.models || []).map((m) => m.name);
111
+ const ollamaCloudModels = names.map((name) => ({ provider: 'ollama-cloud', id: name }));
112
+ const currentModels = config.get('registeredModels');
113
+ const otherModels = currentModels.filter((m) => m.provider !== 'ollama-cloud');
114
+ config.set('registeredModels', [...otherModels, ...ollamaCloudModels]);
115
+ spinner.succeed(ui.success(`Synchronized ${ollamaCloudModels.length} Ollama Cloud models.`));
116
+ }
117
+ catch (error) {
118
+ spinner.fail(ui.error(`Failed to fetch Ollama Cloud models: ${error.message}`));
119
+ console.log(ui.warn('Check your network and API key. Run: pokt config show'));
120
+ }
121
+ return;
122
+ }
123
+ if (action === 'add') {
124
+ const allowed = ['openrouter', 'ollama', 'ollama-cloud'];
125
+ if (!id)
126
+ return console.log(ui.error('Error: --id is required for add. Example: pokt models add -p openrouter -i google/gemini-2.5-flash'));
127
+ if (!provider || !allowed.includes(provider)) {
128
+ return console.log(ui.error(`Error: --provider is required and must be one of: ${allowed.join(', ')}. Example: pokt models add -p openrouter -i <model-id>`));
129
+ }
130
+ const p = provider;
131
+ const models = config.get('registeredModels');
132
+ if (!models.find((m) => m.id === id && m.provider === p)) {
133
+ models.push({ provider: p, id: id });
134
+ config.set('registeredModels', models);
135
+ const label = PROVIDER_LABELS[p];
136
+ console.log(ui.success(`Added ${label} model: ${id}`));
137
+ }
138
+ else {
139
+ console.log(ui.warn(`Model ${id} already exists for ${PROVIDER_LABELS[p]}.`));
140
+ }
141
+ }
142
+ else if (action === 'add-ollama') {
143
+ if (!id)
144
+ return console.log(ui.error('Error: --id is required for add-ollama'));
145
+ const models = config.get('registeredModels');
146
+ if (!models.find((m) => m.id === id && m.provider === 'ollama')) {
147
+ models.push({ provider: 'ollama', id: id });
148
+ config.set('registeredModels', models);
149
+ console.log(ui.success(`Added Ollama model: ${id}`));
150
+ }
151
+ else {
152
+ console.log(ui.warn(`Model ${id} already exists for Ollama.`));
153
+ }
154
+ }
155
+ else if (action === 'add-ollama-cloud') {
156
+ if (!id)
157
+ return console.log(ui.error('Error: --id is required for add-ollama-cloud'));
158
+ const models = config.get('registeredModels');
159
+ if (!models.find((m) => m.id === id && m.provider === 'ollama-cloud')) {
160
+ models.push({ provider: 'ollama-cloud', id: id });
161
+ config.set('registeredModels', models);
162
+ console.log(ui.success(`Added Ollama Cloud model: ${id}`));
163
+ }
164
+ else {
165
+ console.log(ui.warn(`Model ${id} already exists for Ollama Cloud.`));
166
+ }
167
+ }
168
+ else if (action === 'add-openrouter') {
169
+ if (!id)
170
+ return console.log(ui.error('Error: --id is required for add-openrouter. Example: pokt models add-openrouter -i google/gemini-2.5-flash'));
171
+ const models = config.get('registeredModels');
172
+ if (!models.find((m) => m.id === id && m.provider === 'openrouter')) {
173
+ models.push({ provider: 'openrouter', id: id });
174
+ config.set('registeredModels', models);
175
+ console.log(ui.success(`Added OpenRouter model: ${id}`));
176
+ }
177
+ else {
178
+ console.log(ui.warn(`Model ${id} already exists for OpenRouter.`));
179
+ }
180
+ }
181
+ else if (action === 'use') {
182
+ if (!id || !provider)
183
+ return console.log(ui.error('Error: --id and --provider are required for use'));
184
+ const models = config.get('registeredModels');
185
+ const model = models.find((m) => m.id === id && m.provider === provider);
186
+ if (model) {
187
+ config.set('activeModel', model);
188
+ console.log(ui.success(`Active model set to [${provider}] ${id}`));
189
+ }
190
+ else {
191
+ console.log(ui.error(`Model ${id} for provider ${provider} not found. Run: pokt models list`));
192
+ }
193
+ }
194
+ }
195
+ };
@@ -0,0 +1,6 @@
1
+ import type * as Yargs from 'yargs';
2
+ interface ProviderArgs {
3
+ provider?: string;
4
+ }
5
+ export declare const providerCommand: Yargs.CommandModule<{}, ProviderArgs>;
6
+ export {};
@@ -0,0 +1,53 @@
1
+ import { config, ALL_PROVIDERS } from '../config.js';
2
+ import { ui } from '../ui.js';
3
+ export const providerCommand = {
4
+ command: 'provider use <provider>',
5
+ describe: 'Switch API provider (casa de API): controller (Pokt), openrouter, gemini, ollama, ollama-cloud',
6
+ builder: (yargs) => yargs
7
+ .positional('provider', {
8
+ describe: 'Provider to use as primary',
9
+ type: 'string',
10
+ choices: [...ALL_PROVIDERS]
11
+ }),
12
+ handler: (argv) => {
13
+ const provider = argv.provider;
14
+ const models = config.get('registeredModels');
15
+ const model = models.find((m) => m.provider === provider);
16
+ if (!model) {
17
+ if (provider === 'controller') {
18
+ console.log(ui.error('Controller model not found. Add it with: pokt config set-pokt-token -v <token>'));
19
+ }
20
+ else if (provider === 'openrouter') {
21
+ console.log(ui.error('No OpenRouter model. Run: pokt models fetch-openrouter then pokt models list'));
22
+ }
23
+ else if (provider === 'ollama') {
24
+ console.log(ui.error('No Ollama (local) model. Run: pokt models fetch-ollama then pokt models list'));
25
+ }
26
+ else if (provider === 'ollama-cloud') {
27
+ console.log(ui.error('No Ollama Cloud model. Run: pokt models fetch-ollama-cloud then pokt models list'));
28
+ }
29
+ else {
30
+ console.log(ui.error(`No model for provider "${provider}". Run: pokt models list and add one.`));
31
+ }
32
+ return;
33
+ }
34
+ if (provider === 'openrouter' && !config.get('openrouterToken')) {
35
+ console.log(ui.error('OpenRouter token not set. Use: pokt config set-openrouter -v <token>'));
36
+ return;
37
+ }
38
+ if (provider === 'gemini' && !config.get('geminiApiKey')) {
39
+ console.log(ui.error('Gemini API key not set. Use: pokt config set-gemini -v <key>'));
40
+ return;
41
+ }
42
+ if (provider === 'controller' && !config.get('poktToken')) {
43
+ console.log(ui.error('Pokt token not set. Use: pokt config set-pokt-token -v <token>'));
44
+ return;
45
+ }
46
+ if (provider === 'ollama-cloud' && !config.get('ollamaCloudApiKey')) {
47
+ console.log(ui.error('Ollama Cloud API key not set. Use: pokt config set-ollama-cloud -v <key>'));
48
+ return;
49
+ }
50
+ config.set('activeModel', model);
51
+ console.log(ui.success(`Primary provider set to [${provider}] (model: ${model.id}). Use "pokt chat" to start.`));
52
+ }
53
+ };
@@ -0,0 +1,35 @@
1
+ import Conf from 'conf';
2
+ export type Provider = 'openrouter' | 'ollama' | 'ollama-cloud' | 'gemini' | 'controller';
3
+ export declare const PROVIDER_LABELS: Record<Provider, string>;
4
+ /** Lista de todos os provedores disponíveis (único lugar para incluir novos no futuro) */
5
+ export declare const ALL_PROVIDERS: readonly Provider[];
6
+ export interface ModelConfig {
7
+ provider: Provider;
8
+ id: string;
9
+ }
10
+ export interface McpServerConfig {
11
+ name: string;
12
+ type: 'stdio' | 'http';
13
+ /** Para stdio: comando a executar (ex: "npx", "node") */
14
+ command?: string;
15
+ /** Para stdio: argumentos (ex: ["-y", "mcp-server-filesystem"]) */
16
+ args?: string[];
17
+ /** Para http: URL do servidor MCP (Streamable HTTP ou SSE) */
18
+ url?: string;
19
+ }
20
+ interface AppConfig {
21
+ openrouterToken: string;
22
+ geminiApiKey: string;
23
+ ollamaBaseUrl: string;
24
+ ollamaCloudApiKey: string;
25
+ controllerBaseUrl: string;
26
+ poktToken: string;
27
+ registeredModels: ModelConfig[];
28
+ activeModel: ModelConfig | null;
29
+ mcpServers: McpServerConfig[];
30
+ }
31
+ export declare const config: Conf<AppConfig>;
32
+ export declare const getControllerBaseUrl: () => string;
33
+ /** Prioridade: modelo ativo explícito → Pokt (controller) se token setado → OpenRouter → Gemini → Ollama Cloud → Ollama local */
34
+ export declare function getEffectiveActiveModel(): ModelConfig | null;
35
+ export {};
package/dist/config.js ADDED
@@ -0,0 +1,66 @@
1
+ import Conf from 'conf';
2
+ export const PROVIDER_LABELS = {
3
+ controller: 'Pokt API (Controller)',
4
+ openrouter: 'OpenRouter',
5
+ gemini: 'Gemini',
6
+ ollama: 'Ollama (local)',
7
+ 'ollama-cloud': 'Ollama Cloud'
8
+ };
9
+ /** Lista de todos os provedores disponíveis (único lugar para incluir novos no futuro) */
10
+ export const ALL_PROVIDERS = Object.keys(PROVIDER_LABELS);
11
+ const DEFAULT_CONTROLLER_URL = 'https://pokt-cli-controller.vercel.app';
12
+ export const config = new Conf({
13
+ projectName: 'pokt-cli',
14
+ defaults: {
15
+ openrouterToken: '',
16
+ geminiApiKey: '',
17
+ ollamaBaseUrl: 'http://localhost:11434',
18
+ ollamaCloudApiKey: '',
19
+ controllerBaseUrl: DEFAULT_CONTROLLER_URL,
20
+ poktToken: '',
21
+ registeredModels: [
22
+ { provider: 'controller', id: 'default' },
23
+ { provider: 'openrouter', id: 'google/gemini-2.0-flash-001' },
24
+ { provider: 'openrouter', id: 'anthropic/claude-3.5-sonnet' },
25
+ { provider: 'gemini', id: 'gemini-1.5-flash' },
26
+ { provider: 'gemini', id: 'gemini-1.5-pro' }
27
+ ],
28
+ activeModel: null,
29
+ mcpServers: [],
30
+ }
31
+ });
32
+ export const getControllerBaseUrl = () => {
33
+ const url = config.get('controllerBaseUrl') || DEFAULT_CONTROLLER_URL;
34
+ return url.replace(/\/$/, '');
35
+ };
36
+ /** Prioridade: modelo ativo explícito → Pokt (controller) se token setado → OpenRouter → Gemini → Ollama Cloud → Ollama local */
37
+ export function getEffectiveActiveModel() {
38
+ const explicit = config.get('activeModel');
39
+ if (explicit)
40
+ return explicit;
41
+ const models = config.get('registeredModels');
42
+ if (config.get('poktToken')) {
43
+ const c = models.find((m) => m.provider === 'controller');
44
+ if (c)
45
+ return c;
46
+ }
47
+ if (config.get('openrouterToken')) {
48
+ const o = models.find((m) => m.provider === 'openrouter');
49
+ if (o)
50
+ return o;
51
+ }
52
+ if (config.get('geminiApiKey')) {
53
+ const g = models.find((m) => m.provider === 'gemini');
54
+ if (g)
55
+ return g;
56
+ }
57
+ if (config.get('ollamaCloudApiKey')) {
58
+ const oc = models.find((m) => m.provider === 'ollama-cloud');
59
+ if (oc)
60
+ return oc;
61
+ }
62
+ const ollama = models.find((m) => m.provider === 'ollama');
63
+ if (ollama)
64
+ return ollama;
65
+ return models[0] ?? null;
66
+ }
@@ -0,0 +1,59 @@
1
+ import type { McpServerConfig } from '../config.js';
2
+ import type { ChatCompletionTool } from 'openai/resources/chat/completions/completions.js';
3
+ export interface McpToolDef {
4
+ serverName: string;
5
+ name: string;
6
+ /** Nome exposto ao LLM (com prefixo para evitar colisão) */
7
+ exposedName: string;
8
+ description: string;
9
+ inputSchema: Record<string, unknown>;
10
+ }
11
+ export interface McpClientSession {
12
+ serverName: string;
13
+ client: {
14
+ listTools: () => Promise<{
15
+ tools: Array<{
16
+ name: string;
17
+ description?: string;
18
+ inputSchema?: Record<string, unknown>;
19
+ }>;
20
+ }>;
21
+ callTool: (params: {
22
+ name: string;
23
+ arguments?: Record<string, unknown>;
24
+ }) => Promise<{
25
+ content: Array<{
26
+ type?: string;
27
+ text?: string;
28
+ }>;
29
+ }>;
30
+ };
31
+ tools: McpToolDef[];
32
+ transport?: {
33
+ close?: () => void;
34
+ };
35
+ }
36
+ /**
37
+ * Converte tool MCP para formato OpenAI ChatCompletionTool.
38
+ */
39
+ export declare function mcpToolToOpenAI(t: McpToolDef): ChatCompletionTool;
40
+ /**
41
+ * Conecta a um servidor MCP (stdio) e retorna a sessão com tools listados.
42
+ */
43
+ export declare function connectMcpServer(serverConfig: McpServerConfig): Promise<McpClientSession | null>;
44
+ /**
45
+ * Desconecta todos os clientes MCP.
46
+ */
47
+ export declare function disconnectAllMcp(): Promise<void>;
48
+ /**
49
+ * Retorna todas as tools MCP de todas as sessões ativas em formato OpenAI.
50
+ */
51
+ export declare function getAllMcpToolsOpenAI(): ChatCompletionTool[];
52
+ /**
53
+ * Executa uma tool pelo nome exposto (mcp_<server>_<tool>). Retorna o resultado em string.
54
+ */
55
+ export declare function callMcpTool(exposedName: string, argsStr: string): Promise<string>;
56
+ /**
57
+ * Verifica se um nome de tool é de MCP (deve ser roteado ao cliente MCP).
58
+ */
59
+ export declare function isMcpTool(name: string): boolean;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Cliente MCP (Model Context Protocol) para conectar a servidores MCP
3
+ * e expor tools como funções disponíveis no chat.
4
+ */
5
+ import path from 'path';
6
+ import { pathToFileURL } from 'url';
7
+ import { createRequire } from 'module';
8
+ const require = createRequire(import.meta.url);
9
+ const sdkPath = path.dirname(require.resolve('@modelcontextprotocol/sdk/package.json'));
10
+ const stdioModulePath = pathToFileURL(path.join(sdkPath, 'dist/esm/client/stdio.js')).href;
11
+ const MCP_PREFIX = 'mcp_';
12
+ let sessions = [];
13
+ /**
14
+ * Converte tool MCP para formato OpenAI ChatCompletionTool.
15
+ */
16
+ export function mcpToolToOpenAI(t) {
17
+ const params = t.inputSchema?.type === 'object' ? t.inputSchema : { type: 'object', properties: t.inputSchema ?? {} };
18
+ return {
19
+ type: 'function',
20
+ function: {
21
+ name: t.exposedName,
22
+ description: t.description,
23
+ parameters: params,
24
+ },
25
+ };
26
+ }
27
+ /**
28
+ * Conecta a um servidor MCP (stdio) e retorna a sessão com tools listados.
29
+ */
30
+ export async function connectMcpServer(serverConfig) {
31
+ try {
32
+ const { Client } = await import('@modelcontextprotocol/sdk/client');
33
+ const { StdioClientTransport } = await import(stdioModulePath);
34
+ if (serverConfig.type !== 'stdio' || !serverConfig.command) {
35
+ return null;
36
+ }
37
+ const transport = new StdioClientTransport({
38
+ command: serverConfig.command,
39
+ args: serverConfig.args ?? [],
40
+ env: process.env,
41
+ });
42
+ const client = new Client({ name: 'pokt-cli', version: '1.0.0' });
43
+ await client.connect(transport);
44
+ const list = await client.listTools();
45
+ const tools = (list.tools ?? []).map((t) => ({
46
+ serverName: serverConfig.name,
47
+ name: t.name,
48
+ exposedName: `${MCP_PREFIX}${serverConfig.name}_${t.name}`.replace(/\s+/g, '_'),
49
+ description: t.description ?? `MCP tool: ${t.name}`,
50
+ inputSchema: t.inputSchema ?? { type: 'object', properties: {} },
51
+ }));
52
+ const session = {
53
+ serverName: serverConfig.name,
54
+ client: client,
55
+ tools,
56
+ transport: transport,
57
+ };
58
+ sessions.push(session);
59
+ return session;
60
+ }
61
+ catch (err) {
62
+ console.error(`[MCP] Failed to connect to ${serverConfig.name}:`, err);
63
+ return null;
64
+ }
65
+ }
66
+ /**
67
+ * Desconecta todos os clientes MCP.
68
+ */
69
+ export async function disconnectAllMcp() {
70
+ for (const s of sessions) {
71
+ try {
72
+ if (s.transport?.close)
73
+ s.transport.close();
74
+ }
75
+ catch (_) { }
76
+ }
77
+ sessions = [];
78
+ }
79
+ /**
80
+ * Retorna todas as tools MCP de todas as sessões ativas em formato OpenAI.
81
+ */
82
+ export function getAllMcpToolsOpenAI() {
83
+ const out = [];
84
+ for (const s of sessions) {
85
+ for (const t of s.tools) {
86
+ out.push(mcpToolToOpenAI(t));
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ /**
92
+ * Executa uma tool pelo nome exposto (mcp_<server>_<tool>). Retorna o resultado em string.
93
+ */
94
+ export async function callMcpTool(exposedName, argsStr) {
95
+ if (!exposedName.startsWith(MCP_PREFIX)) {
96
+ return `[MCP] Not an MCP tool: ${exposedName}`;
97
+ }
98
+ const session = sessions.find(s => s.tools.some(t => t.exposedName === exposedName));
99
+ const tool = session?.tools.find(t => t.exposedName === exposedName);
100
+ if (!session || !tool) {
101
+ return `[MCP] Tool not found: ${exposedName}`;
102
+ }
103
+ try {
104
+ let args = {};
105
+ if (argsStr?.trim()) {
106
+ try {
107
+ args = JSON.parse(argsStr);
108
+ }
109
+ catch {
110
+ args = {};
111
+ }
112
+ }
113
+ const result = await session.client.callTool({ name: tool.name, arguments: args });
114
+ const content = result.content;
115
+ if (Array.isArray(content)) {
116
+ return content.map((c) => (c.type === 'text' && typeof c.text === 'string' ? c.text : JSON.stringify(c))).join('\n');
117
+ }
118
+ return typeof content === 'string' ? content : JSON.stringify(content);
119
+ }
120
+ catch (err) {
121
+ const msg = err instanceof Error ? err.message : String(err);
122
+ return `[MCP] Error calling ${exposedName}: ${msg}`;
123
+ }
124
+ }
125
+ /**
126
+ * Verifica se um nome de tool é de MCP (deve ser roteado ao cliente MCP).
127
+ */
128
+ export function isMcpTool(name) {
129
+ return name.startsWith(MCP_PREFIX);
130
+ }
package/dist/ui.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ export declare const ui: {
2
+ title: (text: string) => any;
3
+ subtitle: (text: string) => any;
4
+ success: (text: string) => any;
5
+ error: (text: string) => any;
6
+ warn: (text: string) => any;
7
+ dim: (text: string) => any;
8
+ labelYou: () => any;
9
+ labelPokt: () => any;
10
+ accent: (text: string) => any;
11
+ muted: (text: string) => any;
12
+ /** Banner principal estilo Gemini CLI: logo + nome + versão */
13
+ banner: (customVersion?: string) => string;
14
+ /** Status de login / provider (uma linha) */
15
+ statusLine: (providerLabel: string, configPath?: string) => any;
16
+ /** Seção "Tips for getting started" */
17
+ tips: () => string;
18
+ /** Linha de atalhos acima do input */
19
+ shortcutsLine: (left?: string, right?: string, center?: string) => string;
20
+ /** Placeholder do input */
21
+ inputPlaceholder: () => any;
22
+ /** Barra de status inferior: path, branch, sandbox, model */
23
+ statusBar: (opts: {
24
+ cwd?: string;
25
+ branch?: string;
26
+ sandbox?: string;
27
+ model?: string;
28
+ }) => string;
29
+ /** Separador visual sutil */
30
+ separator: () => any;
31
+ };