ratacode 0.2.5
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/CREDITS.md +80 -0
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/apreton/README.md +54 -0
- package/apreton/handshake.md +33 -0
- package/apreton/headless.md +58 -0
- package/apreton/mcp.md +221 -0
- package/apreton/navegador.md +58 -0
- package/bin/instalacion.js +148 -0
- package/bin/ratacode.js +1251 -0
- package/fabrica/settings.yaml +247 -0
- package/mcp/README.md +253 -0
- package/mcp/bin/ratacode-mcp.js +215 -0
- package/mcp/lib/actividad.js +49 -0
- package/mcp/lib/casa.js +126 -0
- package/mcp/lib/claves.js +148 -0
- package/mcp/lib/espacios.js +117 -0
- package/mcp/lib/http.js +184 -0
- package/mcp/lib/lectura.js +210 -0
- package/mcp/lib/modelos.js +235 -0
- package/mcp/lib/nucleo.js +332 -0
- package/mcp/lib/registro.js +21 -0
- package/mcp/lib/seguridad.js +283 -0
- package/mcp/lib/servidor.js +397 -0
- package/mcp/lib/tareas.js +406 -0
- package/mcp/package.json +22 -0
- package/mcp/tunel.mjs +209 -0
- package/modos/arquitecto/agent.cordis.yml +120 -0
- package/modos/arquitecto/preset.yml +3 -0
- package/modos/capataz/agent.cordis.yml +120 -0
- package/modos/capataz/preset.yml +3 -0
- package/modos/faro/agent.cordis.yml +120 -0
- package/modos/faro/preset.yml +3 -0
- package/modos/gepeto/agent.cordis.yml +191 -0
- package/modos/gepeto/preset.yml +3 -0
- package/modos/hero/agent.cordis.yml +198 -0
- package/modos/hero/preset.yml +3 -0
- package/modos/modo-rata/agent.cordis.yml +198 -0
- package/modos/modo-rata/preset.yml +3 -0
- package/modos/nex/agent.cordis.yml +213 -0
- package/modos/nex/preset.yml +3 -0
- package/modos/nex/skills/cordis-plugin-development/SKILL.md +420 -0
- package/modos/nex/skills/editing-cordis-compositions/SKILL.md +165 -0
- package/modos/pix/agent.cordis.yml +207 -0
- package/modos/pix/preset.yml +3 -0
- package/modos/tirita/agent.cordis.yml +130 -0
- package/modos/tirita/preset.yml +3 -0
- package/package.json +49 -0
- package/piel/activos/ratacode-emblema.svg +14 -0
- package/piel/activos/ratacode-es.js +1331 -0
- package/piel/activos/ratacode-identidad.css +50 -0
- package/piel/activos/ratacode-piel.css +217 -0
- package/piel/activos/ratacode-piel.js +487 -0
- package/piel/activos/ratacode-vida.js +424 -0
- package/piel/cordis.patch.yml +6 -0
- package/piel/lib/cliente.js +1020 -0
- package/piel/lib/index.js +1230 -0
- package/piel/package.json +36 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# RATACODE · Settings de fábrica.
|
|
2
|
+
# Lo copia `bin/ratacode.js` a `<casa>/settings.yaml` la PRIMERA vez que se
|
|
3
|
+
# estrena una casa; si la casa ya existe, no se toca lo que haya puesto el usuario.
|
|
4
|
+
#
|
|
5
|
+
# 0 claves dentro. El usuario pone las suyas la primera vez y quedan en
|
|
6
|
+
# <casa>\.credentials.yaml (la web Ajustes > Models las escribe) o bien
|
|
7
|
+
# exportando la variable de entorno que declara cada proveedor.
|
|
8
|
+
#
|
|
9
|
+
# Proveedores: en Ajustes > Models salen las 8 APIs con clave (B.AI, OpenRouter,
|
|
10
|
+
# DeepSeek, Groq, Google Gemini, NVIDIA NIM, SambaNova y Cloudflare Workers AI).
|
|
11
|
+
# Los DOS LOCALES sin clave y sin coste — Ollama (http://127.0.0.1:11434/v1) y
|
|
12
|
+
# LM Studio (http://127.0.0.1:1234/v1) — siguen declarados AQUÍ (para que sus
|
|
13
|
+
# modelos salgan en el selector de modelos de la caja), pero la piel los esconde
|
|
14
|
+
# de esa lista: tienen su propia pestaña, Ajustes > «Modelos locales» (R18).
|
|
15
|
+
# Los locales no piden clave: no llevan `apiKeyEnv`.
|
|
16
|
+
# B.AI y OpenRouter se declaran aquí (llm-pi-ai) y los cinco gratuitos que
|
|
17
|
+
# recomendó el informe R11 también. Cada baseURL y cada id de modelo está
|
|
18
|
+
# comprobado en su documentación oficial (enlaces en los comentarios).
|
|
19
|
+
#
|
|
20
|
+
# DeepSeek NO se declara a propósito: DSH ya trae su adaptador nativo
|
|
21
|
+
# (@deepseek-ai/dsh-llm-deepseek), que registra la ruta "deepseek-official"
|
|
22
|
+
# contra https://api.deepseek.com y lee DEEPSEEK_API_KEY. Declarar además un
|
|
23
|
+
# "deepseek" en llm-pi-ai.providers no choca por id (el nativo no se llama
|
|
24
|
+
# "deepseek"), pero duplicaría el proveedor en el selector y sustituiría su
|
|
25
|
+
# catálogo real por una lista de modelos escrita a mano. Se usa el nativo.
|
|
26
|
+
|
|
27
|
+
agent-presets:
|
|
28
|
+
default: modo-rata
|
|
29
|
+
|
|
30
|
+
permission:
|
|
31
|
+
defaultPreset: danger-full-access
|
|
32
|
+
|
|
33
|
+
agent-default-model:
|
|
34
|
+
provider: b-ai
|
|
35
|
+
model: "deepseek-v4.1-flash"
|
|
36
|
+
|
|
37
|
+
ui-onboarding:
|
|
38
|
+
welcomeNoticeVersion: 2026-08-13.1
|
|
39
|
+
|
|
40
|
+
llm-pi-ai:
|
|
41
|
+
providers:
|
|
42
|
+
# ── B.AI ──────────────────────────────────────────────────────────
|
|
43
|
+
b-ai:
|
|
44
|
+
displayName: B.AI
|
|
45
|
+
api: openai-completions
|
|
46
|
+
baseURL: https://api.b.ai/v1
|
|
47
|
+
apiKeyEnv: B_AI_API_KEY
|
|
48
|
+
timeoutMs: 120000
|
|
49
|
+
models:
|
|
50
|
+
- id: deepseek-v4.1-flash
|
|
51
|
+
name: deepseek-v4.1-flash
|
|
52
|
+
contextWindow: 1000000
|
|
53
|
+
maxTokens: 32000
|
|
54
|
+
input:
|
|
55
|
+
- text
|
|
56
|
+
- image
|
|
57
|
+
compat:
|
|
58
|
+
maxTokensField: max_tokens
|
|
59
|
+
chatTemplateKwargs: {}
|
|
60
|
+
chatTemplateArgs: {}
|
|
61
|
+
- id: hy3
|
|
62
|
+
name: hy3
|
|
63
|
+
- id: glm-5.3-flash
|
|
64
|
+
name: glm-5.3-flash
|
|
65
|
+
- id: mimo-v2.5
|
|
66
|
+
name: mimo-v2.5
|
|
67
|
+
- id: qwen3.8-flash
|
|
68
|
+
name: qwen3.8-flash
|
|
69
|
+
|
|
70
|
+
# ── OpenRouter ────────────────────────────────────────────────────
|
|
71
|
+
openrouter:
|
|
72
|
+
displayName: OpenRouter
|
|
73
|
+
api: openai-completions
|
|
74
|
+
baseURL: https://openrouter.ai/api/v1
|
|
75
|
+
apiKeyEnv: OPENROUTER_API_KEY
|
|
76
|
+
timeoutMs: 120000
|
|
77
|
+
models:
|
|
78
|
+
- id: upstage/solar-mini4
|
|
79
|
+
name: Solar Mini 4
|
|
80
|
+
contextWindow: 524288
|
|
81
|
+
maxTokens: 131072
|
|
82
|
+
input:
|
|
83
|
+
- text
|
|
84
|
+
- id: qwen/qwen3.8-flash
|
|
85
|
+
name: Qwen3.8 Flash
|
|
86
|
+
contextWindow: 1000000
|
|
87
|
+
maxTokens: 131072
|
|
88
|
+
input:
|
|
89
|
+
- text
|
|
90
|
+
- image
|
|
91
|
+
- id: z-ai/glm-5.3-flash
|
|
92
|
+
name: GLM 5.3 Flash
|
|
93
|
+
contextWindow: 1310720
|
|
94
|
+
maxTokens: 131072
|
|
95
|
+
input:
|
|
96
|
+
- text
|
|
97
|
+
- image
|
|
98
|
+
- id: deepseek/deepseek-v4-flash-vision-exp
|
|
99
|
+
name: DeepSeek V4 Flash Vision
|
|
100
|
+
contextWindow: 1048576
|
|
101
|
+
maxTokens: 131072
|
|
102
|
+
input:
|
|
103
|
+
- text
|
|
104
|
+
- image
|
|
105
|
+
|
|
106
|
+
# ── Groq · gratis 30 RPM / 1.000 RPD / 200K TPD ─────────────────────
|
|
107
|
+
# baseURL: https://console.groq.com/docs/openai
|
|
108
|
+
# modelos: https://console.groq.com/docs/models
|
|
109
|
+
groq:
|
|
110
|
+
displayName: Groq
|
|
111
|
+
api: openai-completions
|
|
112
|
+
baseURL: https://api.groq.com/openai/v1
|
|
113
|
+
apiKeyEnv: GROQ_API_KEY
|
|
114
|
+
timeoutMs: 120000
|
|
115
|
+
models:
|
|
116
|
+
- id: openai/gpt-oss-120b
|
|
117
|
+
name: GPT-OSS 120B (Groq)
|
|
118
|
+
contextWindow: 131072
|
|
119
|
+
maxTokens: 65536
|
|
120
|
+
- id: qwen/qwen3.8-27b
|
|
121
|
+
name: Qwen3.8 27B (Groq, preview)
|
|
122
|
+
contextWindow: 131072
|
|
123
|
+
maxTokens: 16384
|
|
124
|
+
|
|
125
|
+
# ── Google Gemini (AI Studio) · gratis, pero ENTRENA CON TUS DATOS ──
|
|
126
|
+
# baseURL: https://ai.google.dev/gemini-api/docs/openai
|
|
127
|
+
# modelos: https://ai.google.dev/gemini-api/docs/models
|
|
128
|
+
gemini:
|
|
129
|
+
displayName: "Google Gemini (gratis: entrena con tus datos)"
|
|
130
|
+
api: openai-completions
|
|
131
|
+
baseURL: https://generativelanguage.googleapis.com/v1beta/openai/
|
|
132
|
+
apiKeyEnv: GEMINI_API_KEY
|
|
133
|
+
timeoutMs: 120000
|
|
134
|
+
models:
|
|
135
|
+
- id: gemini-3.8-flash
|
|
136
|
+
name: Gemini 3.8 Flash
|
|
137
|
+
contextWindow: 1048576
|
|
138
|
+
maxTokens: 65536
|
|
139
|
+
- id: gemini-3.7-flash
|
|
140
|
+
name: Gemini 3.7 Flash
|
|
141
|
+
|
|
142
|
+
# ── NVIDIA NIM · gratis sólo para prototipar (NO uso comercial) ─────
|
|
143
|
+
# URL y endpoint: https://docs.api.nvidia.com/nim/docs/models
|
|
144
|
+
# («URL: https://integrate.api.nvidia.com · Endpoint: POST /v1/chat/completions»)
|
|
145
|
+
# ids: https://docs.api.nvidia.com/nim/reference/llm-apis
|
|
146
|
+
# No publica ventana de contexto: por eso no se declara contextWindow.
|
|
147
|
+
nvidia-nim:
|
|
148
|
+
displayName: NVIDIA NIM (gratis para prototipar, no comercial)
|
|
149
|
+
api: openai-completions
|
|
150
|
+
baseURL: https://integrate.api.nvidia.com/v1
|
|
151
|
+
apiKeyEnv: NVIDIA_API_KEY
|
|
152
|
+
timeoutMs: 120000
|
|
153
|
+
models:
|
|
154
|
+
- id: deepseek-ai/deepseek-v4-flash
|
|
155
|
+
name: DeepSeek V4 Flash (NIM)
|
|
156
|
+
- id: deepseek-ai/deepseek-v4-pro
|
|
157
|
+
name: DeepSeek V4 Pro (NIM)
|
|
158
|
+
|
|
159
|
+
# ── SambaNova · gratis permanente 20 RPM / 20 RPD / 200K TPD ────────
|
|
160
|
+
# baseURL: https://docs.sambanova.ai/docs/en/get-started/api-keys-urls
|
|
161
|
+
# modelos: https://docs.sambanova.ai/docs/en/models/sambacloud-models
|
|
162
|
+
sambanova:
|
|
163
|
+
displayName: SambaNova
|
|
164
|
+
api: openai-completions
|
|
165
|
+
baseURL: https://api.sambanova.ai/v1
|
|
166
|
+
apiKeyEnv: SAMBANOVA_API_KEY
|
|
167
|
+
timeoutMs: 120000
|
|
168
|
+
models:
|
|
169
|
+
- id: MiniMax-M2.7
|
|
170
|
+
name: MiniMax M2.7 (SambaNova)
|
|
171
|
+
contextWindow: 196608
|
|
172
|
+
- id: DeepSeek-V3.1
|
|
173
|
+
name: DeepSeek V3.1 (SambaNova)
|
|
174
|
+
contextWindow: 131072
|
|
175
|
+
|
|
176
|
+
# ── Cloudflare Workers AI · lleva tu account_id EN LA URL ───────────
|
|
177
|
+
# baseURL: https://developers.cloudflare.com/workers-ai/configuration/open-ai-compatibility/
|
|
178
|
+
# modelos: https://developers.cloudflare.com/workers-ai/models/
|
|
179
|
+
# OJO: {account_id} NO es un hueco que rellene RATACODE. Hay que cambiarlo
|
|
180
|
+
# a mano en Ajustes > Models > este proveedor > «Customized settings > Base URL»,
|
|
181
|
+
# poniendo el id de cuenta de Cloudflare (el token va en su campo API key).
|
|
182
|
+
cloudflare-workers-ai:
|
|
183
|
+
displayName: "Cloudflare Workers AI (cambia {account_id} en «Customized settings > Base URL»)"
|
|
184
|
+
api: openai-completions
|
|
185
|
+
baseURL: https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1
|
|
186
|
+
apiKeyEnv: CLOUDFLARE_API_KEY
|
|
187
|
+
timeoutMs: 120000
|
|
188
|
+
models:
|
|
189
|
+
- id: '@cf/openai/gpt-oss-120b'
|
|
190
|
+
name: GPT-OSS 120B (Cloudflare)
|
|
191
|
+
contextWindow: 128000
|
|
192
|
+
- id: '@cf/qwen/qwen2.5-coder-32b-instruct'
|
|
193
|
+
name: Qwen2.5 Coder 32B (Cloudflare)
|
|
194
|
+
contextWindow: 32768
|
|
195
|
+
|
|
196
|
+
# ── Ollama · LOCAL, sin clave y sin coste ───────────────────────────
|
|
197
|
+
# El motor de tu ordenador. No lleva `apiKeyEnv` A PROPÓSITO: sin esa
|
|
198
|
+
# línea la ruta queda sin autenticar (`dsh-llm-pi-ai`: `namesCredential`
|
|
199
|
+
# sólo es true si el perfil nombra una credencial), que es justo lo que
|
|
200
|
+
# hace Ollama por defecto en http://127.0.0.1:11434.
|
|
201
|
+
# Runtime: https://ollama.com/download · modelo: `ollama pull qwen3:8b`
|
|
202
|
+
# Los ids de aquí son los que recomienda el informe R15 (tabla del README:
|
|
203
|
+
# «qué modelo local según tu tarjeta»). Si tu modelo se llama de otra
|
|
204
|
+
# forma, se cambia aquí o en Ajustes > Models.
|
|
205
|
+
# OJO: `qwen2.5-coder:7b` devuelve las herramientas como TEXTO dentro del
|
|
206
|
+
# mensaje y NO funciona como agente (medido en R15): no lo pongas.
|
|
207
|
+
ollama:
|
|
208
|
+
displayName: Ollama (local, sin clave)
|
|
209
|
+
api: openai-completions
|
|
210
|
+
baseURL: http://127.0.0.1:11434/v1
|
|
211
|
+
timeoutMs: 600000
|
|
212
|
+
models:
|
|
213
|
+
- id: "qwen3:8b"
|
|
214
|
+
name: Qwen3 8B (local)
|
|
215
|
+
contextWindow: 40960
|
|
216
|
+
maxTokens: 8192
|
|
217
|
+
compat:
|
|
218
|
+
supportsDeveloperRole: false
|
|
219
|
+
supportsReasoningEffort: false
|
|
220
|
+
- id: "lfm2.5:8b"
|
|
221
|
+
name: LFM2.5 8B (local, 125K)
|
|
222
|
+
contextWindow: 32768
|
|
223
|
+
maxTokens: 8192
|
|
224
|
+
compat:
|
|
225
|
+
supportsDeveloperRole: false
|
|
226
|
+
supportsReasoningEffort: false
|
|
227
|
+
|
|
228
|
+
# ── LM Studio · LOCAL, sin clave ────────────────────────────────────
|
|
229
|
+
# Arranca su servidor ANTES de usar este proveedor: `lms server start`
|
|
230
|
+
# (escucha en 1234). Tampoco lleva `apiKeyEnv`, por lo mismo que Ollama.
|
|
231
|
+
# El id de modelo lo pone LM Studio: míralo con
|
|
232
|
+
# curl http://127.0.0.1:1234/v1/models
|
|
233
|
+
# y escribe ese id AQUÍ o en Ajustes > Models (el que trae puesto es un
|
|
234
|
+
# hueco que hay que cambiar: ningún modelo se llama así).
|
|
235
|
+
lmstudio:
|
|
236
|
+
displayName: LM Studio (local, sin clave)
|
|
237
|
+
api: openai-completions
|
|
238
|
+
baseURL: http://127.0.0.1:1234/v1
|
|
239
|
+
timeoutMs: 600000
|
|
240
|
+
models:
|
|
241
|
+
- id: "<el id que devuelva GET http://127.0.0.1:1234/v1/models>"
|
|
242
|
+
name: LM Studio (cambia el id por el de tu modelo)
|
|
243
|
+
contextWindow: 32768
|
|
244
|
+
maxTokens: 8192
|
|
245
|
+
compat:
|
|
246
|
+
supportsDeveloperRole: false
|
|
247
|
+
supportsReasoningEffort: false
|
package/mcp/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# RATACODE-MCP · el servidor MCP de RATACODE
|
|
2
|
+
|
|
3
|
+
Deja que **el agente que ya usas** (ChatGPT web, Codex, Claude Code, Rowboat,
|
|
4
|
+
OpenClaw, o cualquier cliente MCP) mande trabajo a **los modelos que ya tienes
|
|
5
|
+
configurados en RATACODE**.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
ChatGPT / Codex / Claude Code / Rowboat / OpenClaw
|
|
9
|
+
↓ MCP
|
|
10
|
+
RATACODE-MCP (esta capa)
|
|
11
|
+
↓ JSON-RPC stdio (el protocolo que DSH ya publica)
|
|
12
|
+
core DSH (mismo binario, misma casa, mismos proveedores y claves)
|
|
13
|
+
↓
|
|
14
|
+
proveedor elegido → modelo elegido → resultado
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
RATACODE **no es otro agente** y no se reescribe nada del núcleo: esto es una
|
|
18
|
+
capa fina encima. El trabajo lo hace el core por medio del perfil `sdk` de DSH,
|
|
19
|
+
que es su entrada oficial para conductores externos.
|
|
20
|
+
|
|
21
|
+
## Arrancarlo
|
|
22
|
+
|
|
23
|
+
Es un **subcomando del binario principal**, así que no hay que buscar rutas:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
ratacode mcp # habla MCP por stdio (lo que espera un cliente)
|
|
27
|
+
ratacode mcp --status # estado y sale, sin arrancar el motor
|
|
28
|
+
ratacode mcp --http # además, Streamable HTTP en 127.0.0.1:<puerto>/mcp/<clave>
|
|
29
|
+
ratacode mcp --help # la ayuda del MCP
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
El puerto por defecto del HTTP es **3778** (se cambia con `--port`). `--http` exige
|
|
33
|
+
`mcp.workspaces` declarado. Con `--nueva-clave` se estrena una clave nueva en vez de
|
|
34
|
+
reutilizar la guardada.
|
|
35
|
+
|
|
36
|
+
Si `ratacode` no está en el PATH (o trabajas desde el repositorio), vale la ruta
|
|
37
|
+
directa: `node <ruta>\bin\ratacode.js mcp`.
|
|
38
|
+
|
|
39
|
+
Por stdio, **stdout es del protocolo**: todo lo que contamos va a stderr.
|
|
40
|
+
|
|
41
|
+
## Conectar un cliente
|
|
42
|
+
|
|
43
|
+
Cualquier cliente MCP local (stdio):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"ratacode": {
|
|
49
|
+
"command": "ratacode",
|
|
50
|
+
"args": [
|
|
51
|
+
"mcp",
|
|
52
|
+
"--home",
|
|
53
|
+
"C:\\Users\\tu-usuario\\.ratacode"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Las sintaxis exactas por app (Claude Code, Codex, OpenClaw, Rowboat y el genérico)
|
|
61
|
+
están en [`..\apreton\mcp.md`](../apreton/mcp.md).
|
|
62
|
+
|
|
63
|
+
> **Las claves están en UN solo sitio: RATACODE › Ajustes › Models.** Este servidor
|
|
64
|
+
> no mira las variables de entorno del cliente ni abre ficheros de claves: le
|
|
65
|
+
> pregunta al motor si la credencial de esa ruta está puesta en la casa
|
|
66
|
+
> (`<casa>\.credentials.yaml`). Si no lo está, **se para y lo dice**:
|
|
67
|
+
> `Falta la clave de B.AI. Pégala en RATACODE › Ajustes › Models.`
|
|
68
|
+
>
|
|
69
|
+
> Por eso su alta es `ratacode mcp` y nada más: no hay ninguna variable que
|
|
70
|
+
> pasarle, y la clave no queda escrita en la configuración de tu app.
|
|
71
|
+
>
|
|
72
|
+
> En ningún caso la clave sale por MCP: el servidor la usa, no la cuenta.
|
|
73
|
+
|
|
74
|
+
## ChatGPT web: el túnel (`mcp/tunel.mjs`)
|
|
75
|
+
|
|
76
|
+
ChatGPT web (y cualquier app que hable MCP por URL) necesita HTTP. El túnel es **sólo
|
|
77
|
+
transporte**: expone el MCP local con Cloudflare mientras corre y no cambia nada del servidor.
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
ratacode mcp --http # el MCP por HTTP (local)
|
|
81
|
+
node mcp/tunel.mjs --home <casa> # el túnel, en otra ventana
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`tunel.mjs` imprime la **URL pública completa** (dominio + `/mcp/<clave>`) para pegar en el
|
|
85
|
+
cliente. Al abrirlo estrena clave (`--misma-clave` para reutilizar la que había); el servidor
|
|
86
|
+
**adopta la clave nueva sin reiniciar** (relee `<casa>\mcp\http-secret.txt` cada dos segundos) y
|
|
87
|
+
reescribe la URL en `<casa>\mcp\http-url.txt`. A cloudflared se le pasa sólo el origen: la clave
|
|
88
|
+
no viaja en los argumentos de ningún proceso. Si el túnel nombrado `mcp.mod-rat.com` existe en tu
|
|
89
|
+
Cloudflare, lo usa con hostname fijo mediante un fichero de configuración
|
|
90
|
+
(`<casa>\mcp\cloudflared.yml`); si no, un quick tunnel con URL efímera. Ctrl+C lo cierra.
|
|
91
|
+
|
|
92
|
+
Y **ya no hay nada que aceptar**: cada tarea va encerrada en las carpetas de
|
|
93
|
+
`mcp.workspaces` (lee y escribe sólo ahí, sin terminal y sin red), así que la
|
|
94
|
+
bandera `--acepto-lectura-total` de antes es un no-op: se acepta para no romper
|
|
95
|
+
los comandos viejos, y no hace nada (más abajo, «La LECTURA, encerrada»).
|
|
96
|
+
|
|
97
|
+
## Las herramientas
|
|
98
|
+
|
|
99
|
+
| Herramienta | Para qué |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `list_providers` | Proveedores configurados y si tienen la credencial puesta en la casa (Ajustes → Models). Nunca la clave. |
|
|
102
|
+
| `list_models` | Modelos con proveedor, id, contexto, capacidades, coste declarado y estado. Se llama **antes** de `run_task`. |
|
|
103
|
+
| `run_task` | Lanza el encargo. Sin `esperar_segundos`, devuelve `task_id` al momento y el trabajo sigue en segundo plano. Con `esperar_segundos` (1-600), la llamada **espera y devuelve el resultado completo** en esa misma respuesta. |
|
|
104
|
+
| `get_task_status` | `queued` · `running` · `completed` · `failed` · `cancelled`. |
|
|
105
|
+
| `get_task_result` | Respuesta, modelo, proveedor, tokens, coste (si está declarado), duración y errores. |
|
|
106
|
+
| `cancel_task` | Detiene la tarea de inmediato (se mata el proceso que la ejecuta). |
|
|
107
|
+
| `ratacode_status` | Estado del propio servidor: casa, motor, tareas vivas, clientes y últimas líneas del cuaderno. |
|
|
108
|
+
|
|
109
|
+
`run_task` acepta: `prompt`, `esperar_segundos`, `provider`, `model`,
|
|
110
|
+
`working_directory`, `context`, `max_tokens`, `timeout`, `allow_dangerous`.
|
|
111
|
+
|
|
112
|
+
**Esperar dentro de la llamada (tropiezo 17).** Por stdio, la tarea vive lo que
|
|
113
|
+
vive el cliente: si el cliente se cierra, el servidor se va y el fichero se queda
|
|
114
|
+
a medias. Un cliente de una sola vuelta (`claude -p`, `codex exec`, una llamada
|
|
115
|
+
suelta) no puede volver a preguntar por el estado, así que tiene dos salidas:
|
|
116
|
+
`run_task` con `esperar_segundos` (máximo 600 s) y el resultado en la misma
|
|
117
|
+
respuesta, o no terminar el turno hasta que `get_task_status` diga `completed` o
|
|
118
|
+
`failed`. Si el plazo se agota, la respuesta lo dice (`espera.agotada: true`) y
|
|
119
|
+
queda el `task_id` para seguir preguntando.
|
|
120
|
+
|
|
121
|
+
**Sin routing oculto.** Si no dices modelo, se usa el `agent-default-model` de
|
|
122
|
+
la casa **y se te dice cuál** (`ruta_elegida: "por_defecto"`). El humano o el
|
|
123
|
+
agente deciden el modelo; esta capa no elige por nadie.
|
|
124
|
+
|
|
125
|
+
## Seguridad
|
|
126
|
+
|
|
127
|
+
- **Espacio cerrado, para LEER y para ESCRIBIR.** Una tarea trabaja sólo dentro de las
|
|
128
|
+
raíces autorizadas (`mcp.workspaces`). Si la casa no las declara, la única raíz
|
|
129
|
+
permitida es el espacio por defecto (o la carpeta desde la que arrancó el servidor).
|
|
130
|
+
Cualquier otra ruta se rechaza, y el agente ve una línea: **«Fuera de la carpeta
|
|
131
|
+
autorizada: `<ruta>`».**
|
|
132
|
+
- **La LECTURA, encerrada con un gancho.** El motor no sabe acotar la lectura (`read-only`
|
|
133
|
+
deniega toda MUTACIÓN, no toda lectura: `dsh-fs-sandbox/lib/types/index.d.ts:7-8`,
|
|
134
|
+
«Reads pass through untouched: every mode permits reading»; y la única lista de raíces
|
|
135
|
+
que existe es la de ESCRITURA, `dsh-sandbox/lib/types/roots.d.ts:28-36`). Se acota con
|
|
136
|
+
el gancho de permiso por herramienta `tools/pre-execute` (`dsh-tools`), que ve cada
|
|
137
|
+
llamada antes de ejecutarse y puede denegarla. El plugin que lo engancha es
|
|
138
|
+
`mcp/lib/lectura.js`, y el MCP lo monta en cada tarea por parche. Normaliza de verdad:
|
|
139
|
+
rutas relativas, `..`, mayúsculas/minúsculas de Windows, enlaces (realpath del trozo que
|
|
140
|
+
existe), UNC y el prefijo `\\?\`.
|
|
141
|
+
- **Sin vías de escape.** En la tarea no hay terminal (`tool-pwsh`, `tool-bash`), ni
|
|
142
|
+
trabajos en segundo plano (`tool-jobs`), ni red (`tool-web`), ni subagentes
|
|
143
|
+
(`tool-subagent*`), ni guiones (`tool-workflow`) ni bucles de agentes (`tool-ralph`).
|
|
144
|
+
Se apagan una a una en el parche de cada tarea, con su motivo escrito al lado.
|
|
145
|
+
- **El sandbox lo impone el core.** Cada tarea arranca en `workspace-write` con su cwd
|
|
146
|
+
como frontera de escritura, y el MCP le pasa al hijo un parche que **fija** el modo.
|
|
147
|
+
Ojo con el detalle que costó una ronda: la casa de fábrica trae
|
|
148
|
+
`permission.defaultPreset: danger-full-access` (es lo que el panel necesita), y ese
|
|
149
|
+
ajuste se aplica AL CREAR la sesión, así que ganaba al parche. Por eso el parche apaga
|
|
150
|
+
la fila `permission` en el hijo del MCP: sin ese servicio, manda el modo del MCP. El
|
|
151
|
+
panel del usuario no se toca: sigue con el preset que él elija.
|
|
152
|
+
- **Lo peligroso se pide dos veces.** `allow_dangerous` en la llamada **no
|
|
153
|
+
basta**: hace falta que el humano haya puesto `mcp.permitir_peligroso: true`.
|
|
154
|
+
Si no, se deniega y se explica. Nunca se queda esperando una aprobación que
|
|
155
|
+
en un servidor MCP no existe: falla cerrado. Y aun con `allow_dangerous`, la
|
|
156
|
+
lectura sigue encerrada en `mcp.workspaces`: lo que se abre es la ESCRITURA.
|
|
157
|
+
- **Claves.** Nunca se devuelven, nunca se escriben en el cuaderno, nunca van
|
|
158
|
+
al agente cliente. El servidor las usa y hace la llamada. Además, el propio
|
|
159
|
+
DSH lava el entorno de los shells de sus agentes
|
|
160
|
+
(`dsh-subprocess`: `/KEY|PASSWORD|SECRET|TOKEN/i`), así que la tarea
|
|
161
|
+
delegada tampoco las ve desde dentro. **De dónde salen:** de la casa —las que
|
|
162
|
+
guardaste con Ajustes → Models—, que es la única fuente; el servidor le
|
|
163
|
+
pregunta al motor si están puestas (con su `describe`: configurada sí/no, sin
|
|
164
|
+
leer ningún valor) y el hijo del motor arranca SIN las variables de claves,
|
|
165
|
+
para que resuelva las de la casa y no una vieja del entorno.
|
|
166
|
+
|
|
167
|
+
## Ajustes (en `<casa>\settings.yaml`)
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
mcp:
|
|
171
|
+
workspaces: # obligatorio en modo HTTP (--http/túnel)
|
|
172
|
+
- C:\Users\tu-usuario\Projects\mi-app
|
|
173
|
+
workspace_por_defecto: C:\Users\tu-usuario\Projects\mi-app
|
|
174
|
+
permitir_peligroso: false
|
|
175
|
+
timeout_por_defecto_ms: 1800000 # 30 min: lo que dura una tarea si no dices otra cosa
|
|
176
|
+
timeout_maximo_ms: 3600000 # 1 h: techo, aunque el cliente pida más
|
|
177
|
+
tareas_a_la_vez: 3 # cuántas pueden estar en marcha a la vez
|
|
178
|
+
prompt_max_caracteres: 100000 # tope del encargo
|
|
179
|
+
precios: # opcional: el core no trae precios de texto
|
|
180
|
+
b-ai:
|
|
181
|
+
deepseek-v4.1-flash:
|
|
182
|
+
entrada_por_millon: 0.14
|
|
183
|
+
salida_por_millon: 0.28
|
|
184
|
+
moneda: EUR
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
El coste sólo aparece si lo declaras aquí. **RATACODE no se inventa precios**:
|
|
188
|
+
si no está, devuelve `null` y lo dice.
|
|
189
|
+
|
|
190
|
+
## Qué deja escrito
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
<casa>\mcp\
|
|
194
|
+
estado.json estado del servidor (para el panel y para --status)
|
|
195
|
+
actividad.jsonl una línea por tarea: hora, cliente, modelo, proveedor,
|
|
196
|
+
tarea (recortada), duración, tokens, coste, estado
|
|
197
|
+
marcas.json las marcas del tope de tareas por hora (sobreviven al reinicio)
|
|
198
|
+
http-secret.txt la clave del MCP por HTTP (sólo dueño)
|
|
199
|
+
http-url.txt la URL completa con la clave (sólo dueño)
|
|
200
|
+
cloudflared.yml la config del túnel nombrado, si se usa (sólo dueño)
|
|
201
|
+
tareas\<id>.json el registro completo de cada tarea
|
|
202
|
+
tmp\ parches de política de una tarea (se borran al terminar)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Las pruebas
|
|
206
|
+
|
|
207
|
+
Estas pruebas viven en el **repositorio** (`mcp/prueba/` viaja excluido del `.tgz`,
|
|
208
|
+
así que en una instalación desde el paquete no las encontrarás).
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
# el camino entero: list_models → run_task → get_task_result, con PONG
|
|
212
|
+
node mcp/prueba/cliente-prueba.mjs --home <casa> --provider b-ai --model deepseek-v4.1-flash
|
|
213
|
+
|
|
214
|
+
# UNA sola llamada: run_task con esperar_segundos, y el resultado (PONG) en esa
|
|
215
|
+
# misma respuesta, sin get_task_status.
|
|
216
|
+
node mcp/prueba/cliente-espera.mjs --home <casa> --provider b-ai --model deepseek-v4.1-flash --esperar 300
|
|
217
|
+
|
|
218
|
+
# las promesas de seguridad: credencial sin enseñarla, espacio cerrado,
|
|
219
|
+
# allow_dangerous denegado y cancelación de verdad
|
|
220
|
+
node mcp/prueba/prueba-cancelar-y-espacio.mjs --home <casa> --provider b-ai --model deepseek-v4.1-flash
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`cliente-prueba.mjs` arranca el servidor **como lo haría un cliente real** (con
|
|
224
|
+
el entorno recortado del SDK), lanza `Responde solamente PONG`, vigila el estado
|
|
225
|
+
y recoge el resultado. Sale con código 0 sólo si la respuesta trae PONG.
|
|
226
|
+
|
|
227
|
+
`cliente-espera.mjs` es la prueba del tropiezo 17: enseña `run_task` tal como lo
|
|
228
|
+
lista el servidor (con `esperar_segundos` y su descripción), lanza el encargo UNA
|
|
229
|
+
vez con `esperar_segundos` y exige que esa misma respuesta traiga el resultado
|
|
230
|
+
completo con PONG. Se le puede pasar un entorno o no: da igual, porque las claves
|
|
231
|
+
salen de la casa.
|
|
232
|
+
|
|
233
|
+
`prueba-cancelar-y-espacio.mjs` comprueba cuatro cosas por escrito: que
|
|
234
|
+
`list_providers` no enseña ninguna clave, que una carpeta fuera de los espacios
|
|
235
|
+
autorizados se rechaza, que `allow_dangerous` sin permiso de la casa se deniega
|
|
236
|
+
y que `cancel_task` deja la tarea en `cancelled` de verdad.
|
|
237
|
+
|
|
238
|
+
> Las dos pruebas escriben su carpeta de trabajo en `mcp/prueba/espacio` salvo
|
|
239
|
+
> que les pases `--espacio`. No tocan la casa salvo el cuaderno (`<casa>\mcp\`).
|
|
240
|
+
|
|
241
|
+
## Lo que falta (a propósito)
|
|
242
|
+
|
|
243
|
+
- **Del MCP:** nada de transporte. El stdio y el Streamable HTTP están hechos, y el túnel
|
|
244
|
+
(`mcp/tunel.mjs`) también; las siete herramientas y sus topes, en marcha.
|
|
245
|
+
- **Del lanzador:** arranque/parada del MCP desde el panel con `MCP: ON/OFF`, la sección
|
|
246
|
+
**Connections** en Ajustes (puerto, clientes, última actividad) y el botón que explique el MCP
|
|
247
|
+
dentro de la web. Hoy eso se hace por línea de órdenes y se mira en `<casa>\mcp\`.
|
|
248
|
+
- **Y una frontera que ya SÍ está puesta (R25):** la LECTURA de las tareas. DSH no la
|
|
249
|
+
sabe acotar (mira «La LECTURA, encerrada con un gancho»), así que RATACODE la encierra
|
|
250
|
+
con el gancho `tools/pre-execute`: cada herramienta con una ruta fuera de
|
|
251
|
+
`mcp.workspaces` se para y lo dice. Lo que queda fuera de nuestras manos es lo que DSH
|
|
252
|
+
no exponga por una herramienta (no hay ninguna: sin terminal, sin red y sin subagentes,
|
|
253
|
+
no hay puerta). Si algún día DSH trae raíces de lectura, esto se aprieta todavía más.
|