@jmanuelcorral/openteam 0.1.0 → 0.1.2
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/.opencode/command/openteam.md +15 -0
- package/AGENTS.md +41 -41
- package/LICENSE +21 -21
- package/README.md +358 -315
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +883 -0
- package/dist/commands/baseline.d.ts +12 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/dispatch.d.ts +17 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/doctor.d.ts +10 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/report.d.ts +22 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/types.d.ts +6 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/config/persist.d.ts +14 -0
- package/dist/config/persist.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +407 -6
- package/dist/plugin/commandTool.d.ts +10 -0
- package/dist/plugin/commandTool.d.ts.map +1 -0
- package/dist/telemetry/read.d.ts +14 -0
- package/dist/telemetry/read.d.ts.map +1 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -1,315 +1,358 @@
|
|
|
1
|
-
# openteam
|
|
2
|
-
|
|
3
|
-
**openteam — plugin de opencode con routing coste-consciente local-first, fallback FRONTIER cheapest-capable y orquestación multiagente tipo Squad.**
|
|
4
|
-
|
|
5
|
-
## Tabla de contenidos
|
|
6
|
-
|
|
7
|
-
- [Qué es y por qué existe](#qué-es-y-por-qué-existe)
|
|
8
|
-
- [Características](#características)
|
|
9
|
-
- [Requisitos](#requisitos)
|
|
10
|
-
- [Instalación](#instalación)
|
|
11
|
-
- [Configuración](#configuración)
|
|
12
|
-
- [Uso](#uso)
|
|
13
|
-
- [Ejemplos en Windows](#ejemplos-en-windows)
|
|
14
|
-
- [Privacidad](#privacidad)
|
|
15
|
-
- [Calidad](#calidad)
|
|
16
|
-
- [Compatibilidad](#compatibilidad)
|
|
17
|
-
- [Roadmap](#roadmap)
|
|
18
|
-
- [Licencia](#licencia)
|
|
19
|
-
|
|
20
|
-
## Qué es y por qué existe
|
|
21
|
-
|
|
22
|
-
openteam añade a opencode una capa de routing y orquestación para ahorrar tokens y coste frontier sin perder calidad ni privacidad. La estrategia por defecto es **local-first**: tareas triviales, resúmenes, documentación sencilla y diffs pequeños intentan usar runtimes locales; tareas de arquitectura, seguridad, refactors multiarchivo, tool calling crítico o debugging ambiguo escalan a **FRONTIER cheapest-capable**.
|
|
23
|
-
|
|
24
|
-
El router mantiene una garantía de privacidad: con `privacyMode: "forceLocalOnSensitive"`, una tarea marcada como `privacySensitive` no escala a frontier.
|
|
25
|
-
|
|
26
|
-
## Características
|
|
27
|
-
|
|
28
|
-
- Routing por turno desde el hook `chat.message`, mutando `output.message.model` antes de que opencode persista el mensaje.
|
|
29
|
-
- Registro de runtimes locales OpenAI-compatible: Ollama, LM Studio y Foundry Local.
|
|
30
|
-
- Clasificador local JSON con fallback heurístico determinista.
|
|
31
|
-
- Perfiles de capacidad desde Models.dev, con cache y fallback curado cuando el catálogo no está disponible.
|
|
32
|
-
- Selección frontier **cheapest-capable** por coste blended `0.75 * inputUSD + 0.25 * outputUSD`.
|
|
33
|
-
- Presupuestos por sesión, mes y tokens frontier por sesión.
|
|
34
|
-
- Telemetría `CostRecord` JSONL hash-only: guarda `promptHash`, métricas de coste y decisión, nunca prompts crudos.
|
|
35
|
-
- Orquestación Squad con `runRoleTask` / `runRoleTasks`, subsesiones SDK y modelo explícito en `client.session.prompt({ body: { model } })`.
|
|
36
|
-
- Refresh de disponibilidad local al arrancar y en eventos `session.created` / `session.idle`.
|
|
37
|
-
|
|
38
|
-
## Requisitos
|
|
39
|
-
|
|
40
|
-
- opencode compatible con `@opencode-ai/plugin` `1.17.13`.
|
|
41
|
-
- Bun `>=1.3` para desarrollo y tests.
|
|
42
|
-
- Runtimes locales opcionales:
|
|
43
|
-
- Ollama en `http://localhost:11434/v1`.
|
|
44
|
-
- LM Studio en `http://localhost:1234/v1`.
|
|
45
|
-
- Foundry Local con puerto dinámico descubierto por CLI en Windows.
|
|
46
|
-
|
|
47
|
-
## Instalación
|
|
48
|
-
|
|
49
|
-
### Opción A: paquete npm
|
|
50
|
-
|
|
51
|
-
El paquete se publica como `@jmanuelcorral/openteam`. opencode instala los plugins declarados en el array `plugin` de `opencode.json`; basta con referenciar el nombre del paquete:
|
|
52
|
-
|
|
53
|
-
```jsonc
|
|
54
|
-
{
|
|
55
|
-
"$schema": "https://opencode.ai/config.json",
|
|
56
|
-
"model": "anthropic/claude-sonnet-4-5",
|
|
57
|
-
"small_model": "ollama/qwen3:8b",
|
|
58
|
-
"plugin": [
|
|
59
|
-
[
|
|
60
|
-
"@jmanuelcorral/openteam",
|
|
61
|
-
{
|
|
62
|
-
"baseline": {
|
|
63
|
-
"mode": "auto",
|
|
64
|
-
"pinnedModel": null,
|
|
65
|
-
"hardDefault": {
|
|
66
|
-
"providerID": "anthropic",
|
|
67
|
-
"modelID": "claude-sonnet-4-5"
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
"router": {
|
|
71
|
-
"mode": "balanced",
|
|
72
|
-
"localDefault": {
|
|
73
|
-
"providerID": "ollama",
|
|
74
|
-
"modelID": "qwen3:8b"
|
|
75
|
-
},
|
|
76
|
-
"trivialPromptMaxChars": 280,
|
|
77
|
-
"frontierPromptMinChars": 2000
|
|
78
|
-
},
|
|
79
|
-
"local": {
|
|
80
|
-
"runtimes": [
|
|
81
|
-
{
|
|
82
|
-
"id": "ollama",
|
|
83
|
-
"enabled": true,
|
|
84
|
-
"baseURL": "http://localhost:11434/v1",
|
|
85
|
-
"defaultModel": {
|
|
86
|
-
"providerID": "ollama",
|
|
87
|
-
"modelID": "qwen3:8b"
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
"id": "lmstudio",
|
|
92
|
-
"enabled": true,
|
|
93
|
-
"baseURL": "http://localhost:1234/v1",
|
|
94
|
-
"defaultModel": {
|
|
95
|
-
"providerID": "lmstudio",
|
|
96
|
-
"modelID": "qwen2.5-coder-local"
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
},
|
|
101
|
-
"budgets": {
|
|
102
|
-
"sessionUSD": 2,
|
|
103
|
-
"monthlyUSD": 30,
|
|
104
|
-
"frontierTokensPerSession": 250000,
|
|
105
|
-
"hardStopOnBudgetExhaustion": false
|
|
106
|
-
},
|
|
107
|
-
"privacyMode": "forceLocalOnSensitive",
|
|
108
|
-
"telemetry": {
|
|
109
|
-
"enabled": true,
|
|
110
|
-
"path": ".opencode/openteam-telemetry.jsonl"
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
]
|
|
114
|
-
],
|
|
115
|
-
"provider": {
|
|
116
|
-
"ollama": {
|
|
117
|
-
"npm": "@ai-sdk/openai-compatible",
|
|
118
|
-
"name": "Ollama (local)",
|
|
119
|
-
"options": {
|
|
120
|
-
"baseURL": "http://localhost:11434/v1",
|
|
121
|
-
"apiKey": "ollama",
|
|
122
|
-
"chunkTimeout": 60000
|
|
123
|
-
},
|
|
124
|
-
"models": {
|
|
125
|
-
"qwen3:8b": {
|
|
126
|
-
"name": "Qwen3 8B (Ollama)",
|
|
127
|
-
"tool_call": true,
|
|
128
|
-
"limit": { "context": 32768, "output": 8192 }
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
"lmstudio": {
|
|
133
|
-
"npm": "@ai-sdk/openai-compatible",
|
|
134
|
-
"name": "LM Studio (local)",
|
|
135
|
-
"options": {
|
|
136
|
-
"baseURL": "http://localhost:1234/v1",
|
|
137
|
-
"apiKey": "lm-studio"
|
|
138
|
-
},
|
|
139
|
-
"models": {
|
|
140
|
-
"qwen2.5-coder-local": {
|
|
141
|
-
"name": "Qwen2.5 Coder Local",
|
|
142
|
-
"tool_call": true,
|
|
143
|
-
"limit": { "context": 32768, "output": 8192 }
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Opción B: ruta de desarrollo
|
|
152
|
-
|
|
153
|
-
Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/openteam.ts`:
|
|
154
|
-
|
|
155
|
-
```jsonc
|
|
156
|
-
{
|
|
157
|
-
"$schema": "https://opencode.ai/config.json",
|
|
158
|
-
"plugin": [
|
|
159
|
-
[
|
|
160
|
-
"./.opencode/plugins/openteam.ts",
|
|
161
|
-
{
|
|
162
|
-
"router": {
|
|
163
|
-
"mode": "balanced",
|
|
164
|
-
"localDefault": {
|
|
165
|
-
"providerID": "ollama",
|
|
166
|
-
"modelID": "qwen3:8b"
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
"telemetry": {
|
|
170
|
-
"path": ".opencode/openteam-telemetry.jsonl"
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
]
|
|
174
|
-
]
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Configuración
|
|
179
|
-
|
|
180
|
-
La configuración runtime canónica vive en `.opencode/openteam.json`; este repositorio incluye `.opencode/openteam.example.json` como ejemplo completo. La forma validada por Zod es la de `src/config/schema.ts`. `telemetry` es una opción del plugin leída por `src/index.ts`, no parte del objeto `OpenTeamConfig` persistido.
|
|
181
|
-
|
|
182
|
-
| Key | Tipo | Default | Descripción |
|
|
183
|
-
| --- | --- | --- | --- |
|
|
184
|
-
| `baseline.mode` | `"auto" \| "pinned"` | `"auto"` | En `auto`, usa perfiles frontier cheapest-capable cuando se pasan al router; en `pinned`, usa `baseline.pinnedModel` si existe. |
|
|
185
|
-
| `baseline.pinnedModel` | `ModelRef \| null` | `null` | Modelo frontier fijado explícitamente. `ModelRef` usa `{ "providerID": string, "modelID": string }`. |
|
|
186
|
-
| `baseline.hardDefault` | `ModelRef` | `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }` | Fallback frontier si no hay perfiles cheapest-capable o pin válido. |
|
|
187
|
-
| `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Modo de routing validado y reservado para política. |
|
|
188
|
-
| `router.localDefault` | `ModelRef` | `{ "providerID": "ollama", "modelID": "qwen3:8b" }` | Modelo local principal. |
|
|
189
|
-
| `router.trivialPromptMaxChars` | `number` entero positivo | `280` | Prompts sin código hasta este tamaño prefieren local. |
|
|
190
|
-
| `router.frontierPromptMinChars` | `number` entero positivo | `2000` | Prompts desde este tamaño se tratan como candidatos a frontier si no aplican guards. |
|
|
191
|
-
| `local.runtimes` | `LocalRuntime[]` | Ollama enabled en `http://localhost:11434/v1` con `qwen3:8b` | Lista mínima de un runtime local. |
|
|
192
|
-
| `local.runtimes[].id` | `"ollama" \| "lmstudio" \| "foundry-local"` | requerido | Runtime local. |
|
|
193
|
-
| `local.runtimes[].enabled` | `boolean` | `true` | Habilita o deshabilita ese runtime. |
|
|
194
|
-
| `local.runtimes[].baseURL` | URL opcional | según runtime/config | Endpoint OpenAI-compatible `/v1`; Foundry Local puede omitirlo si usa discovery. |
|
|
195
|
-
| `local.runtimes[].discovery` | `"cli" \| "sdk" \| "manual"` opcional | sin default por item | Discovery de Foundry Local; el registry usa CLI si está configurado y no es `manual`. |
|
|
196
|
-
| `local.runtimes[].defaultModel` | `ModelRef` | requerido | Modelo por defecto de ese runtime. |
|
|
197
|
-
| `budgets.sessionUSD` | `number` positivo opcional | sin límite | Presupuesto frontier por sesión. |
|
|
198
|
-
| `budgets.monthlyUSD` | `number` positivo opcional | sin límite | Presupuesto frontier mensual. |
|
|
199
|
-
| `budgets.frontierTokensPerSession` | `number` entero positivo opcional | sin límite | Límite de tokens frontier por sesión. |
|
|
200
|
-
| `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Si es `true`, agotar presupuesto devuelve `blockFrontier`; si es `false`, fuerza local. |
|
|
201
|
-
| `privacyMode` | `"forceLocalOnSensitive" \| "consentBeforeFrontier" \| "off"` | `"forceLocalOnSensitive"` | Política de privacidad para tareas sensibles. |
|
|
202
|
-
| `telemetry.enabled` | `boolean` plugin option | `true` | Activa/desactiva escritura JSONL. |
|
|
203
|
-
| `telemetry.path` | `string` plugin option | `.opencode/openteam-telemetry.jsonl` | Ruta del log `CostRecord` JSONL. |
|
|
204
|
-
|
|
205
|
-
## Uso
|
|
206
|
-
|
|
207
|
-
En cada turno, openteam deriva señales del prompt (`promptChars`, `hasCode`, `privacySensitive`, `requiresTools` y override de modelo si existe), ejecuta `chooseModel` y asigna `output.message.model`.
|
|
208
|
-
|
|
209
|
-
La orquestación Squad usa roles estáticos y subsesiones opencode:
|
|
210
|
-
|
|
211
|
-
| Rol | Agent opencode | Tier base | Política |
|
|
212
|
-
| --- | --- | --- | --- |
|
|
213
|
-
| `rusty` | `architect` | `hard` | Arquitectura y decisiones de alto riesgo; frontier auto. |
|
|
214
|
-
| `livingston` | `integration` | `moderate` | Integración TS/opencode; tool calling por defecto. |
|
|
215
|
-
| `yen` | `local-runtime` | `moderate` | Runtimes locales; local-first con fallback frontier. |
|
|
216
|
-
| `basher` | `routing-cost` | `moderate` | Router, coste y presupuesto; local-first. |
|
|
217
|
-
| `scribe` | `scribe` | `trivial` | Documentación y resúmenes; local-first. |
|
|
218
|
-
| `linus` | `tester` | `simple` | Tests y contratos; local-first con tools. |
|
|
219
|
-
|
|
220
|
-
`runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con `batchID`. Los roles con `destructive` o `multiFileEdit` elevan el tier antes de elegir modelo.
|
|
221
|
-
|
|
222
|
-
Para ver ahorro y decisiones, revisa el JSONL de telemetría. Campos clave: `promptHash`, `promptChars`, `tier`, `routeKind`, `selected`, `rationale`, `estimatedCostUSD`, `baselineCostUSD`, `estimatedSavingsUSD`, `budgetAction`, `tokensIn` y `tokensOut`.
|
|
223
|
-
|
|
224
|
-
##
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
###
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
##
|
|
314
|
-
|
|
315
|
-
|
|
1
|
+
# openteam
|
|
2
|
+
|
|
3
|
+
**openteam — plugin de opencode con routing coste-consciente local-first, fallback FRONTIER cheapest-capable y orquestación multiagente tipo Squad.**
|
|
4
|
+
|
|
5
|
+
## Tabla de contenidos
|
|
6
|
+
|
|
7
|
+
- [Qué es y por qué existe](#qué-es-y-por-qué-existe)
|
|
8
|
+
- [Características](#características)
|
|
9
|
+
- [Requisitos](#requisitos)
|
|
10
|
+
- [Instalación](#instalación)
|
|
11
|
+
- [Configuración](#configuración)
|
|
12
|
+
- [Uso](#uso)
|
|
13
|
+
- [Ejemplos en Windows](#ejemplos-en-windows)
|
|
14
|
+
- [Privacidad](#privacidad)
|
|
15
|
+
- [Calidad](#calidad)
|
|
16
|
+
- [Compatibilidad](#compatibilidad)
|
|
17
|
+
- [Roadmap](#roadmap)
|
|
18
|
+
- [Licencia](#licencia)
|
|
19
|
+
|
|
20
|
+
## Qué es y por qué existe
|
|
21
|
+
|
|
22
|
+
openteam añade a opencode una capa de routing y orquestación para ahorrar tokens y coste frontier sin perder calidad ni privacidad. La estrategia por defecto es **local-first**: tareas triviales, resúmenes, documentación sencilla y diffs pequeños intentan usar runtimes locales; tareas de arquitectura, seguridad, refactors multiarchivo, tool calling crítico o debugging ambiguo escalan a **FRONTIER cheapest-capable**.
|
|
23
|
+
|
|
24
|
+
El router mantiene una garantía de privacidad: con `privacyMode: "forceLocalOnSensitive"`, una tarea marcada como `privacySensitive` no escala a frontier.
|
|
25
|
+
|
|
26
|
+
## Características
|
|
27
|
+
|
|
28
|
+
- Routing por turno desde el hook `chat.message`, mutando `output.message.model` antes de que opencode persista el mensaje.
|
|
29
|
+
- Registro de runtimes locales OpenAI-compatible: Ollama, LM Studio y Foundry Local.
|
|
30
|
+
- Clasificador local JSON con fallback heurístico determinista.
|
|
31
|
+
- Perfiles de capacidad desde Models.dev, con cache y fallback curado cuando el catálogo no está disponible.
|
|
32
|
+
- Selección frontier **cheapest-capable** por coste blended `0.75 * inputUSD + 0.25 * outputUSD`.
|
|
33
|
+
- Presupuestos por sesión, mes y tokens frontier por sesión.
|
|
34
|
+
- Telemetría `CostRecord` JSONL hash-only: guarda `promptHash`, métricas de coste y decisión, nunca prompts crudos.
|
|
35
|
+
- Orquestación Squad con `runRoleTask` / `runRoleTasks`, subsesiones SDK y modelo explícito en `client.session.prompt({ body: { model } })`.
|
|
36
|
+
- Refresh de disponibilidad local al arrancar y en eventos `session.created` / `session.idle`.
|
|
37
|
+
|
|
38
|
+
## Requisitos
|
|
39
|
+
|
|
40
|
+
- opencode compatible con `@opencode-ai/plugin` `1.17.13`.
|
|
41
|
+
- Bun `>=1.3` para desarrollo y tests.
|
|
42
|
+
- Runtimes locales opcionales:
|
|
43
|
+
- Ollama en `http://localhost:11434/v1`.
|
|
44
|
+
- LM Studio en `http://localhost:1234/v1`.
|
|
45
|
+
- Foundry Local con puerto dinámico descubierto por CLI en Windows.
|
|
46
|
+
|
|
47
|
+
## Instalación
|
|
48
|
+
|
|
49
|
+
### Opción A: paquete npm
|
|
50
|
+
|
|
51
|
+
El paquete se publica como `@jmanuelcorral/openteam`. opencode instala los plugins declarados en el array `plugin` de `opencode.json`; basta con referenciar el nombre del paquete:
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
{
|
|
55
|
+
"$schema": "https://opencode.ai/config.json",
|
|
56
|
+
"model": "anthropic/claude-sonnet-4-5",
|
|
57
|
+
"small_model": "ollama/qwen3:8b",
|
|
58
|
+
"plugin": [
|
|
59
|
+
[
|
|
60
|
+
"@jmanuelcorral/openteam",
|
|
61
|
+
{
|
|
62
|
+
"baseline": {
|
|
63
|
+
"mode": "auto",
|
|
64
|
+
"pinnedModel": null,
|
|
65
|
+
"hardDefault": {
|
|
66
|
+
"providerID": "anthropic",
|
|
67
|
+
"modelID": "claude-sonnet-4-5"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"router": {
|
|
71
|
+
"mode": "balanced",
|
|
72
|
+
"localDefault": {
|
|
73
|
+
"providerID": "ollama",
|
|
74
|
+
"modelID": "qwen3:8b"
|
|
75
|
+
},
|
|
76
|
+
"trivialPromptMaxChars": 280,
|
|
77
|
+
"frontierPromptMinChars": 2000
|
|
78
|
+
},
|
|
79
|
+
"local": {
|
|
80
|
+
"runtimes": [
|
|
81
|
+
{
|
|
82
|
+
"id": "ollama",
|
|
83
|
+
"enabled": true,
|
|
84
|
+
"baseURL": "http://localhost:11434/v1",
|
|
85
|
+
"defaultModel": {
|
|
86
|
+
"providerID": "ollama",
|
|
87
|
+
"modelID": "qwen3:8b"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "lmstudio",
|
|
92
|
+
"enabled": true,
|
|
93
|
+
"baseURL": "http://localhost:1234/v1",
|
|
94
|
+
"defaultModel": {
|
|
95
|
+
"providerID": "lmstudio",
|
|
96
|
+
"modelID": "qwen2.5-coder-local"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"budgets": {
|
|
102
|
+
"sessionUSD": 2,
|
|
103
|
+
"monthlyUSD": 30,
|
|
104
|
+
"frontierTokensPerSession": 250000,
|
|
105
|
+
"hardStopOnBudgetExhaustion": false
|
|
106
|
+
},
|
|
107
|
+
"privacyMode": "forceLocalOnSensitive",
|
|
108
|
+
"telemetry": {
|
|
109
|
+
"enabled": true,
|
|
110
|
+
"path": ".opencode/openteam-telemetry.jsonl"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
],
|
|
115
|
+
"provider": {
|
|
116
|
+
"ollama": {
|
|
117
|
+
"npm": "@ai-sdk/openai-compatible",
|
|
118
|
+
"name": "Ollama (local)",
|
|
119
|
+
"options": {
|
|
120
|
+
"baseURL": "http://localhost:11434/v1",
|
|
121
|
+
"apiKey": "ollama",
|
|
122
|
+
"chunkTimeout": 60000
|
|
123
|
+
},
|
|
124
|
+
"models": {
|
|
125
|
+
"qwen3:8b": {
|
|
126
|
+
"name": "Qwen3 8B (Ollama)",
|
|
127
|
+
"tool_call": true,
|
|
128
|
+
"limit": { "context": 32768, "output": 8192 }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"lmstudio": {
|
|
133
|
+
"npm": "@ai-sdk/openai-compatible",
|
|
134
|
+
"name": "LM Studio (local)",
|
|
135
|
+
"options": {
|
|
136
|
+
"baseURL": "http://localhost:1234/v1",
|
|
137
|
+
"apiKey": "lm-studio"
|
|
138
|
+
},
|
|
139
|
+
"models": {
|
|
140
|
+
"qwen2.5-coder-local": {
|
|
141
|
+
"name": "Qwen2.5 Coder Local",
|
|
142
|
+
"tool_call": true,
|
|
143
|
+
"limit": { "context": 32768, "output": 8192 }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Opción B: ruta de desarrollo
|
|
152
|
+
|
|
153
|
+
Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/openteam.ts`:
|
|
154
|
+
|
|
155
|
+
```jsonc
|
|
156
|
+
{
|
|
157
|
+
"$schema": "https://opencode.ai/config.json",
|
|
158
|
+
"plugin": [
|
|
159
|
+
[
|
|
160
|
+
"./.opencode/plugins/openteam.ts",
|
|
161
|
+
{
|
|
162
|
+
"router": {
|
|
163
|
+
"mode": "balanced",
|
|
164
|
+
"localDefault": {
|
|
165
|
+
"providerID": "ollama",
|
|
166
|
+
"modelID": "qwen3:8b"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"telemetry": {
|
|
170
|
+
"path": ".opencode/openteam-telemetry.jsonl"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Configuración
|
|
179
|
+
|
|
180
|
+
La configuración runtime canónica vive en `.opencode/openteam.json`; este repositorio incluye `.opencode/openteam.example.json` como ejemplo completo. La forma validada por Zod es la de `src/config/schema.ts`. `telemetry` es una opción del plugin leída por `src/index.ts`, no parte del objeto `OpenTeamConfig` persistido.
|
|
181
|
+
|
|
182
|
+
| Key | Tipo | Default | Descripción |
|
|
183
|
+
| --- | --- | --- | --- |
|
|
184
|
+
| `baseline.mode` | `"auto" \| "pinned"` | `"auto"` | En `auto`, usa perfiles frontier cheapest-capable cuando se pasan al router; en `pinned`, usa `baseline.pinnedModel` si existe. |
|
|
185
|
+
| `baseline.pinnedModel` | `ModelRef \| null` | `null` | Modelo frontier fijado explícitamente. `ModelRef` usa `{ "providerID": string, "modelID": string }`. |
|
|
186
|
+
| `baseline.hardDefault` | `ModelRef` | `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }` | Fallback frontier si no hay perfiles cheapest-capable o pin válido. |
|
|
187
|
+
| `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Modo de routing validado y reservado para política. |
|
|
188
|
+
| `router.localDefault` | `ModelRef` | `{ "providerID": "ollama", "modelID": "qwen3:8b" }` | Modelo local principal. |
|
|
189
|
+
| `router.trivialPromptMaxChars` | `number` entero positivo | `280` | Prompts sin código hasta este tamaño prefieren local. |
|
|
190
|
+
| `router.frontierPromptMinChars` | `number` entero positivo | `2000` | Prompts desde este tamaño se tratan como candidatos a frontier si no aplican guards. |
|
|
191
|
+
| `local.runtimes` | `LocalRuntime[]` | Ollama enabled en `http://localhost:11434/v1` con `qwen3:8b` | Lista mínima de un runtime local. |
|
|
192
|
+
| `local.runtimes[].id` | `"ollama" \| "lmstudio" \| "foundry-local"` | requerido | Runtime local. |
|
|
193
|
+
| `local.runtimes[].enabled` | `boolean` | `true` | Habilita o deshabilita ese runtime. |
|
|
194
|
+
| `local.runtimes[].baseURL` | URL opcional | según runtime/config | Endpoint OpenAI-compatible `/v1`; Foundry Local puede omitirlo si usa discovery. |
|
|
195
|
+
| `local.runtimes[].discovery` | `"cli" \| "sdk" \| "manual"` opcional | sin default por item | Discovery de Foundry Local; el registry usa CLI si está configurado y no es `manual`. |
|
|
196
|
+
| `local.runtimes[].defaultModel` | `ModelRef` | requerido | Modelo por defecto de ese runtime. |
|
|
197
|
+
| `budgets.sessionUSD` | `number` positivo opcional | sin límite | Presupuesto frontier por sesión. |
|
|
198
|
+
| `budgets.monthlyUSD` | `number` positivo opcional | sin límite | Presupuesto frontier mensual. |
|
|
199
|
+
| `budgets.frontierTokensPerSession` | `number` entero positivo opcional | sin límite | Límite de tokens frontier por sesión. |
|
|
200
|
+
| `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Si es `true`, agotar presupuesto devuelve `blockFrontier`; si es `false`, fuerza local. |
|
|
201
|
+
| `privacyMode` | `"forceLocalOnSensitive" \| "consentBeforeFrontier" \| "off"` | `"forceLocalOnSensitive"` | Política de privacidad para tareas sensibles. |
|
|
202
|
+
| `telemetry.enabled` | `boolean` plugin option | `true` | Activa/desactiva escritura JSONL. |
|
|
203
|
+
| `telemetry.path` | `string` plugin option | `.opencode/openteam-telemetry.jsonl` | Ruta del log `CostRecord` JSONL. |
|
|
204
|
+
|
|
205
|
+
## Uso
|
|
206
|
+
|
|
207
|
+
En cada turno, openteam deriva señales del prompt (`promptChars`, `hasCode`, `privacySensitive`, `requiresTools` y override de modelo si existe), ejecuta `chooseModel` y asigna `output.message.model`.
|
|
208
|
+
|
|
209
|
+
La orquestación Squad usa roles estáticos y subsesiones opencode:
|
|
210
|
+
|
|
211
|
+
| Rol | Agent opencode | Tier base | Política |
|
|
212
|
+
| --- | --- | --- | --- |
|
|
213
|
+
| `rusty` | `architect` | `hard` | Arquitectura y decisiones de alto riesgo; frontier auto. |
|
|
214
|
+
| `livingston` | `integration` | `moderate` | Integración TS/opencode; tool calling por defecto. |
|
|
215
|
+
| `yen` | `local-runtime` | `moderate` | Runtimes locales; local-first con fallback frontier. |
|
|
216
|
+
| `basher` | `routing-cost` | `moderate` | Router, coste y presupuesto; local-first. |
|
|
217
|
+
| `scribe` | `scribe` | `trivial` | Documentación y resúmenes; local-first. |
|
|
218
|
+
| `linus` | `tester` | `simple` | Tests y contratos; local-first con tools. |
|
|
219
|
+
|
|
220
|
+
`runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con `batchID`. Los roles con `destructive` o `multiFileEdit` elevan el tier antes de elegir modelo.
|
|
221
|
+
|
|
222
|
+
Para ver ahorro y decisiones, revisa el JSONL de telemetría. Campos clave: `promptHash`, `promptChars`, `tier`, `routeKind`, `selected`, `rationale`, `estimatedCostUSD`, `baselineCostUSD`, `estimatedSavingsUSD`, `budgetAction`, `tokensIn` y `tokensOut`.
|
|
223
|
+
|
|
224
|
+
## Comandos runtime
|
|
225
|
+
|
|
226
|
+
openteam expone comandos para inspeccionar y cambiar el routing sin editar JSON a mano. Hay tres superficies equivalentes:
|
|
227
|
+
|
|
228
|
+
### 1. Tool en la conversación
|
|
229
|
+
|
|
230
|
+
El plugin registra la herramienta `openteam`. Pídele al agente que la use, o instala el comando `/openteam` (ver más abajo). Acciones:
|
|
231
|
+
|
|
232
|
+
- `show` — muestra el baseline efectivo.
|
|
233
|
+
- `set` (con `model` en formato `provider/model`) — fija el baseline (modo `pinned`).
|
|
234
|
+
- `auto` — vuelve a cheapest-capable (modo `auto`).
|
|
235
|
+
- `doctor` — diagnóstico de runtimes locales, privacidad y telemetría.
|
|
236
|
+
- `report` — resumen de coste y ahorro desde la telemetría.
|
|
237
|
+
|
|
238
|
+
Los cambios de `set`/`auto` se persisten en `.opencode/openteam.json` y aplican en el siguiente arranque del plugin.
|
|
239
|
+
|
|
240
|
+
### 2. Slash command `/openteam`
|
|
241
|
+
|
|
242
|
+
Copia [`.opencode/command/openteam.md`](.opencode/command/openteam.md) a tu proyecto (o a `~/.config/opencode/command/`). Después:
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
/openteam baseline show
|
|
246
|
+
/openteam baseline set anthropic/claude-sonnet-4-5
|
|
247
|
+
/openteam baseline auto
|
|
248
|
+
/openteam doctor
|
|
249
|
+
/openteam report
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 3. CLI (`bin`)
|
|
253
|
+
|
|
254
|
+
El paquete expone el binario `openteam`. Con instalación global:
|
|
255
|
+
|
|
256
|
+
```powershell
|
|
257
|
+
npm i -g @jmanuelcorral/openteam
|
|
258
|
+
openteam baseline show
|
|
259
|
+
openteam baseline set openai/gpt-5-mini
|
|
260
|
+
openteam doctor --config .opencode/openteam.json
|
|
261
|
+
openteam report --telemetry .opencode/openteam-telemetry.jsonl
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Flags: `--config <path>` y `--telemetry <path>` sobrescriben las rutas por defecto.
|
|
265
|
+
|
|
266
|
+
## Ejemplos en Windows
|
|
267
|
+
|
|
268
|
+
### Ollama
|
|
269
|
+
|
|
270
|
+
```powershell
|
|
271
|
+
ollama serve
|
|
272
|
+
ollama pull qwen3:8b
|
|
273
|
+
Invoke-RestMethod -Uri "http://localhost:11434/v1/models" -Method Get
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### LM Studio
|
|
277
|
+
|
|
278
|
+
1. Abre LM Studio.
|
|
279
|
+
2. Carga un modelo compatible.
|
|
280
|
+
3. Activa el servidor local OpenAI-compatible en el puerto `1234`.
|
|
281
|
+
|
|
282
|
+
```powershell
|
|
283
|
+
Invoke-RestMethod -Uri "http://localhost:1234/v1/models" -Method Get
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Foundry Local
|
|
287
|
+
|
|
288
|
+
```powershell
|
|
289
|
+
foundry service status
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
openteam extrae el puerto de la salida del CLI y normaliza el endpoint a `http://localhost:<PORT>/v1`.
|
|
293
|
+
|
|
294
|
+
### Telemetría
|
|
295
|
+
|
|
296
|
+
```powershell
|
|
297
|
+
$telemetryPath = "C:\gitrepos\openteam\.opencode\openteam-telemetry.jsonl"
|
|
298
|
+
Get-Content -Path $telemetryPath -Tail 5
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Verificación local
|
|
302
|
+
|
|
303
|
+
```powershell
|
|
304
|
+
Set-Location -Path "C:\gitrepos\openteam"
|
|
305
|
+
bun test
|
|
306
|
+
bun run typecheck
|
|
307
|
+
bun run lint
|
|
308
|
+
bun run format:check
|
|
309
|
+
# Cuando el empaquetado de Fase 4 exponga el script:
|
|
310
|
+
bun run build
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Privacidad
|
|
314
|
+
|
|
315
|
+
Con `privacyMode: "forceLocalOnSensitive"`, si `TaskSignals.privacySensitive` es `true`, `chooseModel` usa local y no permite fallback frontier. Si no hay local utilizable, la decisión conserva la ruta local y registra la razón en `rationale`.
|
|
316
|
+
|
|
317
|
+
La telemetría usa `hashPrompt`, actualmente `fnv1a32:<hash>`, y no serializa el prompt completo.
|
|
318
|
+
|
|
319
|
+
## Calidad
|
|
320
|
+
|
|
321
|
+
Gates no negociables:
|
|
322
|
+
|
|
323
|
+
- `bun test`
|
|
324
|
+
- Coverage global: líneas `>= 85%`, branches `>= 80%`.
|
|
325
|
+
- Coverage de `src/router/**`: `100%` lines, branches, statements y functions.
|
|
326
|
+
- `bun run typecheck`
|
|
327
|
+
- `biome check .` o `bun run lint` + `bun run format:check`
|
|
328
|
+
- Test de determinismo del router.
|
|
329
|
+
- Tests de contrato si cambian hooks opencode, agents, comandos, providers o SDK.
|
|
330
|
+
|
|
331
|
+
Estado actual de Fases 0-3: **202 tests verdes**.
|
|
332
|
+
|
|
333
|
+
## Compatibilidad
|
|
334
|
+
|
|
335
|
+
Consulta [docs/compatibility.md](docs/compatibility.md). Resumen verificado el `2026-07-06`:
|
|
336
|
+
|
|
337
|
+
| Superficie | Versión / contrato |
|
|
338
|
+
| --- | --- |
|
|
339
|
+
| openteam | `0.1.0` para Fase 4 npm + docs |
|
|
340
|
+
| `@opencode-ai/plugin` | `1.17.13` |
|
|
341
|
+
| `@opencode-ai/sdk` | `1.17.13` |
|
|
342
|
+
| Hook de routing | `chat.message`; no `chat.params` para cambiar modelo |
|
|
343
|
+
| Subsesiones | `client.session.create` + `client.session.prompt({ body: { model } })` |
|
|
344
|
+
|
|
345
|
+
## Roadmap
|
|
346
|
+
|
|
347
|
+
| Fase | Estado | Entregables |
|
|
348
|
+
| --- | --- | --- |
|
|
349
|
+
| 0. Scaffold/PoC | Hecha | TS/Bun, plugin mínimo, hook `chat.message`. |
|
|
350
|
+
| 1. Local registry + router heurístico | Hecha | Ollama/LM Studio/Foundry, probes y `chooseModel` determinista. |
|
|
351
|
+
| 2. Clasificador + perfiles + presupuesto + telemetría | Hecha | Clasificador local, `ModelCapabilityProfile`, budgets y `CostRecord`. |
|
|
352
|
+
| 3. Orquestación multiagente | Hecha | Coordinator, roles, child sessions y permisos. |
|
|
353
|
+
| 4. Empaquetado npm + docs | Hecha | Package exportable, README, ejemplos Windows y matriz de compatibilidad. |
|
|
354
|
+
| 5. Comandos runtime | Hecha | `baseline show/set/auto`, `doctor` y `report` vía tool, `/openteam` y CLI `bin`. |
|
|
355
|
+
|
|
356
|
+
## Licencia
|
|
357
|
+
|
|
358
|
+
MIT. Consulta [LICENSE](LICENSE).
|