@jmanuelcorral/openteam 0.1.38 → 0.1.41
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 +5 -5
- package/AGENTS.md +50 -35
- package/README.es.md +759 -0
- package/README.md +213 -480
- package/dist/capabilities/types.d.ts +1 -1
- package/dist/cli/consoleServe.d.ts.map +1 -1
- package/dist/cli.js +1123 -232
- package/dist/commands/frontierCatalog.d.ts +27 -0
- package/dist/commands/frontierCatalog.d.ts.map +1 -0
- package/dist/commands/graph.d.ts +65 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/orchestratorAgent.d.ts +2 -1
- package/dist/commands/orchestratorAgent.d.ts.map +1 -1
- package/dist/commands/setup.d.ts +3 -18
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/migrations.d.ts +27 -0
- package/dist/config/migrations.d.ts.map +1 -0
- package/dist/config/resolve.d.ts +34 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/schema.d.ts +235 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/console/assets.d.ts +9 -0
- package/dist/console/assets.d.ts.map +1 -0
- package/dist/console/render.d.ts.map +1 -1
- package/dist/context/redaction.d.ts +48 -0
- package/dist/context/redaction.d.ts.map +1 -0
- package/dist/context/schema.d.ts +115 -0
- package/dist/context/schema.d.ts.map +1 -0
- package/dist/context/types.d.ts +8 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/contract/opencode.d.ts +1 -1
- package/dist/contract/opencode.d.ts.map +1 -1
- package/dist/graph/events.d.ts +25 -0
- package/dist/graph/events.d.ts.map +1 -0
- package/dist/graph/ids.d.ts +5 -0
- package/dist/graph/ids.d.ts.map +1 -0
- package/dist/graph/planner.d.ts +15 -0
- package/dist/graph/planner.d.ts.map +1 -0
- package/dist/graph/policies.d.ts +34 -0
- package/dist/graph/policies.d.ts.map +1 -0
- package/dist/graph/privacyPolicy.d.ts +29 -0
- package/dist/graph/privacyPolicy.d.ts.map +1 -0
- package/dist/graph/reducer.d.ts +27 -0
- package/dist/graph/reducer.d.ts.map +1 -0
- package/dist/graph/replay.d.ts +20 -0
- package/dist/graph/replay.d.ts.map +1 -0
- package/dist/graph/reviewerPolicy.d.ts +27 -0
- package/dist/graph/reviewerPolicy.d.ts.map +1 -0
- package/dist/graph/schema.d.ts +220 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/types.d.ts +40 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/validate.d.ts +19 -0
- package/dist/graph/validate.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +873 -88
- package/dist/local/embeddings.d.ts +29 -0
- package/dist/local/embeddings.d.ts.map +1 -0
- package/dist/local/extractClient.d.ts +31 -0
- package/dist/local/extractClient.d.ts.map +1 -0
- package/dist/local/openai-compatible.d.ts +1 -0
- package/dist/local/openai-compatible.d.ts.map +1 -1
- package/dist/mcp/semanticRecall.d.ts +25 -0
- package/dist/mcp/semanticRecall.d.ts.map +1 -0
- package/dist/mcp/server.d.ts +22 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/memory/consolidate.d.ts +21 -0
- package/dist/memory/consolidate.d.ts.map +1 -0
- package/dist/memory/extract.d.ts +68 -0
- package/dist/memory/extract.d.ts.map +1 -0
- package/dist/memory/fold.d.ts +24 -0
- package/dist/memory/fold.d.ts.map +1 -0
- package/dist/memory/index.d.ts +18 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/inject.d.ts +29 -0
- package/dist/memory/inject.d.ts.map +1 -0
- package/dist/memory/log.d.ts +16 -0
- package/dist/memory/log.d.ts.map +1 -0
- package/dist/memory/merge.d.ts +38 -0
- package/dist/memory/merge.d.ts.map +1 -0
- package/dist/memory/rank.d.ts +32 -0
- package/dist/memory/rank.d.ts.map +1 -0
- package/dist/memory/recall.d.ts +30 -0
- package/dist/memory/recall.d.ts.map +1 -0
- package/dist/memory/temporal.d.ts +39 -0
- package/dist/memory/temporal.d.ts.map +1 -0
- package/dist/memory/types.d.ts +159 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/vector.d.ts +18 -0
- package/dist/memory/vector.d.ts.map +1 -0
- package/dist/orchestrator/graphCancellation.d.ts +84 -0
- package/dist/orchestrator/graphCancellation.d.ts.map +1 -0
- package/dist/orchestrator/graphEffects.d.ts +63 -0
- package/dist/orchestrator/graphEffects.d.ts.map +1 -0
- package/dist/orchestrator/graphReview.d.ts +84 -0
- package/dist/orchestrator/graphReview.d.ts.map +1 -0
- package/dist/orchestrator/graphRuntime.d.ts +69 -0
- package/dist/orchestrator/graphRuntime.d.ts.map +1 -0
- package/dist/orchestrator/opencodeSessionAdapter.d.ts +117 -0
- package/dist/orchestrator/opencodeSessionAdapter.d.ts.map +1 -0
- package/dist/orchestrator/roles.d.ts +1 -1
- package/dist/orchestrator/roles.d.ts.map +1 -1
- package/dist/orchestrator/sdd.d.ts +38 -2
- package/dist/orchestrator/sdd.d.ts.map +1 -1
- package/dist/orchestrator/sddCompiler.d.ts +44 -0
- package/dist/orchestrator/sddCompiler.d.ts.map +1 -0
- package/dist/orchestrator/sessionReconciler.d.ts +74 -0
- package/dist/orchestrator/sessionReconciler.d.ts.map +1 -0
- package/dist/orchestrator/shadowComparator.d.ts +62 -0
- package/dist/orchestrator/shadowComparator.d.ts.map +1 -0
- package/dist/plugin/hooks.d.ts +13 -0
- package/dist/plugin/hooks.d.ts.map +1 -1
- package/dist/plugin/memoryInject.d.ts +25 -0
- package/dist/plugin/memoryInject.d.ts.map +1 -0
- package/dist/router/chooseModel.d.ts.map +1 -1
- package/dist/router/cost.d.ts +4 -0
- package/dist/router/cost.d.ts.map +1 -0
- package/dist/router/frontierBaseline.d.ts +13 -0
- package/dist/router/frontierBaseline.d.ts.map +1 -0
- package/dist/router/modelSelection.d.ts +18 -0
- package/dist/router/modelSelection.d.ts.map +1 -0
- package/dist/storage/graph/codec.d.ts +52 -0
- package/dist/storage/graph/codec.d.ts.map +1 -0
- package/dist/storage/graph/fsGraphJournal.d.ts +3 -0
- package/dist/storage/graph/fsGraphJournal.d.ts.map +1 -0
- package/dist/storage/graph/importLegacy.d.ts +62 -0
- package/dist/storage/graph/importLegacy.d.ts.map +1 -0
- package/dist/storage/graph/memoryGraphJournal.d.ts +11 -0
- package/dist/storage/graph/memoryGraphJournal.d.ts.map +1 -0
- package/dist/storage/graph/migrateLegacyBriefs.d.ts +32 -0
- package/dist/storage/graph/migrateLegacyBriefs.d.ts.map +1 -0
- package/dist/storage/graph/projections.d.ts +31 -0
- package/dist/storage/graph/projections.d.ts.map +1 -0
- package/dist/storage/graph/provider.d.ts +52 -0
- package/dist/storage/graph/provider.d.ts.map +1 -0
- package/dist/storage/graph/recovery.d.ts +38 -0
- package/dist/storage/graph/recovery.d.ts.map +1 -0
- package/dist/storage/graph/runRegistry.d.ts +17 -0
- package/dist/storage/graph/runRegistry.d.ts.map +1 -0
- package/dist/storage/graph/snapshot.d.ts +44 -0
- package/dist/storage/graph/snapshot.d.ts.map +1 -0
- package/dist/storage/graph/workspaceLease.d.ts +36 -0
- package/dist/storage/graph/workspaceLease.d.ts.map +1 -0
- package/dist/storage/graph/writer.d.ts +20 -0
- package/dist/storage/graph/writer.d.ts.map +1 -0
- package/dist/storage/index/memoryConsolidate.d.ts +24 -0
- package/dist/storage/index/memoryConsolidate.d.ts.map +1 -0
- package/dist/storage/index/memoryIndex.d.ts +52 -0
- package/dist/storage/index/memoryIndex.d.ts.map +1 -0
- package/dist/storage/index/memoryRecall.d.ts +23 -0
- package/dist/storage/index/memoryRecall.d.ts.map +1 -0
- package/dist/storage/index/memoryRuntime.d.ts +41 -0
- package/dist/storage/index/memoryRuntime.d.ts.map +1 -0
- package/dist/telemetry/events.d.ts +3 -1
- package/dist/telemetry/events.d.ts.map +1 -1
- package/dist/telemetry/graphProjection.d.ts +36 -0
- package/dist/telemetry/graphProjection.d.ts.map +1 -0
- package/dist/telemetry/hash.d.ts.map +1 -1
- package/dist/web/server.d.ts +4 -0
- package/dist/web/server.d.ts.map +1 -1
- package/package.json +14 -6
package/README.es.md
ADDED
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
# openteam
|
|
2
|
+
|
|
3
|
+
> 🌐 **Language / Idioma:** [English](README.md) · **Español** (este documento)
|
|
4
|
+
|
|
5
|
+
**openteam — plugin de opencode con routing coste-consciente local-first, fallback FRONTIER cheapest-capable y orquestación multiagente a demanda.**
|
|
6
|
+
|
|
7
|
+
> 📖 **Sitio de documentación:** <https://jmanuelcorral.github.io/openteam/es/> (también en [English](https://jmanuelcorral.github.io/openteam/))
|
|
8
|
+
|
|
9
|
+
## Tabla de contenidos
|
|
10
|
+
|
|
11
|
+
- [Qué es y por qué existe](#qué-es-y-por-qué-existe)
|
|
12
|
+
- [Características](#características)
|
|
13
|
+
- [Requisitos](#requisitos)
|
|
14
|
+
- [Instalación](#instalación)
|
|
15
|
+
- [Quickstart: `openteam setup`](#quickstart-openteam-setup)
|
|
16
|
+
- [Probar en otra máquina](#probar-en-otra-máquina)
|
|
17
|
+
- [Actualizar openteam](#actualizar-openteam)
|
|
18
|
+
- [Configuración](#configuración)
|
|
19
|
+
- [Uso](#uso)
|
|
20
|
+
- [Ejemplos en Windows](#ejemplos-en-windows)
|
|
21
|
+
- [Publicación segura](#publicación-segura)
|
|
22
|
+
- [Privacidad](#privacidad)
|
|
23
|
+
- [Calidad](#calidad)
|
|
24
|
+
- [Compatibilidad](#compatibilidad)
|
|
25
|
+
- [Roadmap](#roadmap)
|
|
26
|
+
- [Licencia](#licencia)
|
|
27
|
+
- [Agradecimientos e inspiración](#agradecimientos-e-inspiración)
|
|
28
|
+
|
|
29
|
+
## Qué es y por qué existe
|
|
30
|
+
|
|
31
|
+
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**.
|
|
32
|
+
|
|
33
|
+
El router mantiene una garantía de privacidad: con `privacyMode: "forceLocalOnSensitive"`, una tarea marcada como `privacySensitive` no escala a frontier.
|
|
34
|
+
|
|
35
|
+
## Características
|
|
36
|
+
|
|
37
|
+
- Routing por turno desde el hook `chat.message`, mutando `output.message.model` antes de que opencode persista el mensaje.
|
|
38
|
+
- Registro de runtimes locales OpenAI-compatible: Ollama, LM Studio y Foundry Local.
|
|
39
|
+
- Clasificador local JSON con fallback heurístico determinista.
|
|
40
|
+
- Perfiles de capacidad desde Models.dev, con cache y fallback curado cuando el catálogo no está disponible.
|
|
41
|
+
- Selección frontier **cheapest-capable** por coste blended `0.75 * inputUSD + 0.25 * outputUSD`.
|
|
42
|
+
- Presupuestos por sesión, mes y tokens frontier por sesión.
|
|
43
|
+
- Telemetría `CostRecord` JSONL hash-only: guarda `promptHash`, métricas de coste y decisión, nunca prompts crudos.
|
|
44
|
+
- Orquestación multiagente con `runRoleTask` / `runRoleTasks`, subsesiones SDK y modelo explícito en `client.session.prompt({ body: { model } })`.
|
|
45
|
+
- Refresh de disponibilidad local al arrancar y en eventos `session.created` / `session.idle`.
|
|
46
|
+
|
|
47
|
+
## Requisitos
|
|
48
|
+
|
|
49
|
+
- opencode compatible con `@opencode-ai/plugin` `1.17.13`.
|
|
50
|
+
- Bun `1.3.14` para instalaciones, desarrollo y tests reproducibles.
|
|
51
|
+
- Node.js `^22.22.2 || ^24.15.0 || >=26.0.0` para la CLI y el plugin publicados.
|
|
52
|
+
- Runtimes locales opcionales:
|
|
53
|
+
- Ollama en `http://localhost:11434/v1`.
|
|
54
|
+
- LM Studio en `http://localhost:1234/v1`.
|
|
55
|
+
- Foundry Local con puerto dinámico descubierto por CLI en Windows.
|
|
56
|
+
|
|
57
|
+
## Instalación
|
|
58
|
+
|
|
59
|
+
### Opción A: paquete npm
|
|
60
|
+
|
|
61
|
+
El paquete se publica como `@jmanuelcorral/openteam`. Estas son las rutas de instalación soportadas:
|
|
62
|
+
|
|
63
|
+
| Necesidad | Método soportado |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Cargar el plugin en opencode | Añadir `@jmanuelcorral/openteam` al array `plugin` de `opencode.json`. opencode resuelve el paquete; no hace falta instalar la CLI globalmente. |
|
|
66
|
+
| Ejecutar setup una vez | `bunx --package @jmanuelcorral/openteam@latest openteam setup` |
|
|
67
|
+
| Mantener la CLI `openteam` en el `PATH` | `bun add --global @jmanuelcorral/openteam@latest` y después `openteam setup` |
|
|
68
|
+
|
|
69
|
+
La instalación global con npm **no está soportada**. Bun es el único instalador de paquetes soportado. Node.js ejecuta la CLI y el plugin publicados dentro del rango declarado de engines; npm se limita a operaciones de mantenedor: `pack`, Trusted Publishing y `link:local`.
|
|
70
|
+
|
|
71
|
+
Para la carga directa desde opencode, basta con referenciar el paquete:
|
|
72
|
+
|
|
73
|
+
```jsonc
|
|
74
|
+
{
|
|
75
|
+
"$schema": "https://opencode.ai/config.json",
|
|
76
|
+
"model": "anthropic/claude-sonnet-4-5",
|
|
77
|
+
"small_model": "ollama/qwen3:8b",
|
|
78
|
+
"plugin": [
|
|
79
|
+
[
|
|
80
|
+
"@jmanuelcorral/openteam",
|
|
81
|
+
{
|
|
82
|
+
"baseline": {
|
|
83
|
+
"mode": "auto",
|
|
84
|
+
"pinnedModel": null,
|
|
85
|
+
"hardDefault": {
|
|
86
|
+
"providerID": "anthropic",
|
|
87
|
+
"modelID": "claude-sonnet-4-5"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"router": {
|
|
91
|
+
"mode": "balanced",
|
|
92
|
+
"localDefault": {
|
|
93
|
+
"providerID": "ollama",
|
|
94
|
+
"modelID": "qwen3:8b"
|
|
95
|
+
},
|
|
96
|
+
"trivialPromptMaxChars": 280,
|
|
97
|
+
"frontierPromptMinChars": 2000
|
|
98
|
+
},
|
|
99
|
+
"local": {
|
|
100
|
+
"runtimes": [
|
|
101
|
+
{
|
|
102
|
+
"id": "ollama",
|
|
103
|
+
"enabled": true,
|
|
104
|
+
"baseURL": "http://localhost:11434/v1",
|
|
105
|
+
"defaultModel": {
|
|
106
|
+
"providerID": "ollama",
|
|
107
|
+
"modelID": "qwen3:8b"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "lmstudio",
|
|
112
|
+
"enabled": true,
|
|
113
|
+
"baseURL": "http://localhost:1234/v1",
|
|
114
|
+
"defaultModel": {
|
|
115
|
+
"providerID": "lmstudio",
|
|
116
|
+
"modelID": "qwen2.5-coder-local"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"budgets": {
|
|
122
|
+
"sessionUSD": 2,
|
|
123
|
+
"monthlyUSD": 30,
|
|
124
|
+
"frontierTokensPerSession": 250000,
|
|
125
|
+
"hardStopOnBudgetExhaustion": false
|
|
126
|
+
},
|
|
127
|
+
"privacyMode": "forceLocalOnSensitive",
|
|
128
|
+
"telemetry": {
|
|
129
|
+
"enabled": true,
|
|
130
|
+
"path": ".opencode/openteam-telemetry.jsonl"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
],
|
|
135
|
+
"provider": {
|
|
136
|
+
"ollama": {
|
|
137
|
+
"npm": "@ai-sdk/openai-compatible",
|
|
138
|
+
"name": "Ollama (local)",
|
|
139
|
+
"options": {
|
|
140
|
+
"baseURL": "http://localhost:11434/v1",
|
|
141
|
+
"apiKey": "ollama",
|
|
142
|
+
"chunkTimeout": 60000
|
|
143
|
+
},
|
|
144
|
+
"models": {
|
|
145
|
+
"qwen3:8b": {
|
|
146
|
+
"name": "Qwen3 8B (Ollama)",
|
|
147
|
+
"tool_call": true,
|
|
148
|
+
"limit": { "context": 32768, "output": 8192 }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"lmstudio": {
|
|
153
|
+
"npm": "@ai-sdk/openai-compatible",
|
|
154
|
+
"name": "LM Studio (local)",
|
|
155
|
+
"options": {
|
|
156
|
+
"baseURL": "http://localhost:1234/v1",
|
|
157
|
+
"apiKey": "lm-studio"
|
|
158
|
+
},
|
|
159
|
+
"models": {
|
|
160
|
+
"qwen2.5-coder-local": {
|
|
161
|
+
"name": "Qwen2.5 Coder Local",
|
|
162
|
+
"tool_call": true,
|
|
163
|
+
"limit": { "context": 32768, "output": 8192 }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Opción B: ruta de desarrollo
|
|
172
|
+
|
|
173
|
+
Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/openteam.ts`:
|
|
174
|
+
|
|
175
|
+
```jsonc
|
|
176
|
+
{
|
|
177
|
+
"$schema": "https://opencode.ai/config.json",
|
|
178
|
+
"plugin": [
|
|
179
|
+
[
|
|
180
|
+
"./.opencode/plugins/openteam.ts",
|
|
181
|
+
{
|
|
182
|
+
"router": {
|
|
183
|
+
"mode": "balanced",
|
|
184
|
+
"localDefault": {
|
|
185
|
+
"providerID": "ollama",
|
|
186
|
+
"modelID": "qwen3:8b"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"telemetry": {
|
|
190
|
+
"path": ".opencode/openteam-telemetry.jsonl"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Quickstart: `openteam setup`
|
|
199
|
+
|
|
200
|
+
La forma más rápida de dejar un repositorio listo para opencode + openteam es el comando interactivo `openteam setup`. Detecta los runtimes locales instalados (Ollama, LM Studio, Foundry Local) —que son **opcionales**: puedes usar openteam **solo con frontier**, o apuntar a un Ollama/LM Studio que corra en **otra máquina de la red local**—, te deja elegir los modelos locales y el modelo **frontier baseline** (ordenados de más barato-capaz a más caro), y genera tres ficheros:
|
|
201
|
+
|
|
202
|
+
- `opencode.json` en la raíz: declara el plugin `@jmanuelcorral/openteam`, los `provider` locales OpenAI-compatible, el `model` frontier y el `small_model` local.
|
|
203
|
+
- `.opencode/openteam.json`: la configuración runtime validada de openteam (baseline, routing, runtimes locales y privacidad).
|
|
204
|
+
- `.opencode/agent/openteam.md`: el **agente primario `openteam`**, visible en el Tab-switcher.
|
|
205
|
+
|
|
206
|
+
```powershell
|
|
207
|
+
# Ejecución puntual, sin instalación global
|
|
208
|
+
bunx --package @jmanuelcorral/openteam@latest openteam setup
|
|
209
|
+
# O después de la instalación global soportada con Bun
|
|
210
|
+
openteam setup
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
> El antiguo comando `openteam init` sigue funcionando como **alias obsoleto** de `openteam setup`.
|
|
214
|
+
|
|
215
|
+
El asistente:
|
|
216
|
+
|
|
217
|
+
1. Sondea los runtimes locales y marca los detectados.
|
|
218
|
+
2. Te deja habilitar runtimes (o **ninguno**: puedes usar openteam **solo con modelos frontier**) y, por cada runtime que habilites, elegir si corre **en esta máquina** o **en otra máquina de la red local** (introduciendo su URL, p. ej. `http://192.168.1.50:11434/v1`); luego eliges el modelo por defecto de cada uno (o lo escribes si no se detectan modelos).
|
|
219
|
+
3. Ofrece el modelo frontier baseline a partir del **catálogo completo de [Models.dev](https://models.dev)** que openteam ya integra: una lista rápida con los más **baratos-capaces primero** (incluidos los **gratuitos**, etiquetados como `gratis`), una opción **«Ver todos los modelos por proveedor…»** para navegar el catálogo completo, y **«Otro (custom)»** para escribir un `provider/model`. Si el catálogo no se puede cargar (offline), cae a la lista curada.
|
|
220
|
+
4. Pregunta el modo de routing (`balanced`/`economy`/`quality`), la política de privacidad y si quieres activar el **modo YOLO** (auto-aprobar permisos de opencode). Si no habilitas ningún runtime local, avisa de que estás en **modo solo frontier** y recomienda `consentBeforeFrontier` (porque `forceLocalOnSensitive` no tendría destino local).
|
|
221
|
+
5. Si ya existe `opencode.json` o `.opencode/openteam.json`, pide confirmación antes de sobrescribir.
|
|
222
|
+
|
|
223
|
+
Tras `setup`, autentica el provider frontier (`opencode auth login`), asegúrate de que tu runtime local (en esta máquina o en la red) esté accesible si lo habilitaste, y abre opencode en el repositorio: openteam enruta local-first automáticamente. Puedes reajustar el baseline después con `openteam baseline set <provider/model>` o `openteam baseline auto`.
|
|
224
|
+
|
|
225
|
+
### El agente `openteam`
|
|
226
|
+
|
|
227
|
+
`openteam setup` genera un único **agente primario** llamado `openteam` (`.opencode/agent/openteam.md`). Pulsa **Tab** en opencode para seleccionarlo: así sabes explícitamente que estás en modo openteam, mientras el plugin sigue optimizando el modelo por debajo.
|
|
228
|
+
|
|
229
|
+
Ese orquestador **no trae subagentes precreados**. En **cada petición** su primera acción es comprobar si ya existe equipo (`.opencode/openteam-roster.md` + subagentes en `.opencode/agent/`). Si **existe**, reparte el trabajo entre los especialistas adecuados; si **no existe**, entiende las tareas que implica tu petición, diseña el equipo mínimo y **lo crea a demanda** —sin que tengas que pedírselo explícitamente— antes de pasarle esas tareas (escribiendo `.opencode/agent/<nombre>.md` con `mode: subagent`), reutilizando los existentes antes de crear nuevos. Los roles mecánicos/bulk se dejan enrutar a modelos locales y solo se escala a frontier para arquitectura, seguridad o debugging ambiguo. (Este modelo de equipo temático creado a demanda está inspirado en [Squad](https://bradygaster.github.io/squad/); ver [Agradecimientos](#agradecimientos-e-inspiración).)
|
|
230
|
+
|
|
231
|
+
El equipo tiene **identidad temática**: el orquestador elige (o te pregunta) un **universo** y nombra a cada agente con un personaje de ese universo, registrando el reparto en `.opencode/openteam-roster.md` (fuera de `.opencode/agent/`, para que opencode no lo cargue como un agente fantasma) para que los nombres **persistan** entre sesiones. Además de los roles específicos del proyecto, contempla tres **roles estándar** creados a demanda:
|
|
232
|
+
|
|
233
|
+
- **scribe** — memoria silenciosa: registra decisiones y aprendizajes en `.opencode/openteam-decisions.md` sin tocar el código (modelo local).
|
|
234
|
+
- **ralph** — automatización y triage: monitoriza el trabajo pendiente, lo prioriza, coordina la ejecución y **escala al humano** ante bloqueos o aprobaciones.
|
|
235
|
+
- **guardian** — seguridad y privacidad: **detecta y enmascara datos sensibles** (PII, secretos, API keys, tokens) antes de que salgan a frontier y hace revisión de seguridad; corre siempre en local y respeta `forceLocalOnSensitive`.
|
|
236
|
+
|
|
237
|
+
Antes de delegar, el orquestador **planifica dependencias y paraleliza**: descompone la petición en tareas, y como opencode ejecuta en paralelo todas las llamadas `task` emitidas en un mismo turno (Vercel AI SDK), lanza a la vez las tareas independientes y secuencia por olas solo las que dependen de un resultado previo. El trabajo que colisiona sobre los mismos ficheros se separa en olas distintas para evitar conflictos.
|
|
238
|
+
|
|
239
|
+
En la **lista de tareas** (`todowrite`, la que ves en el todo general de opencode) cada entrada lleva **visible el responsable**. opencode no tiene un campo de "agente" en sus todos (solo `content`/`status`/`priority`, y la lista es por sesión), así que el orquestador usa una convención en el texto: prefija cada tarea con el nombre del casting, p. ej. `[@Basher] Implementar el router` o `[@openteam] Sintetizar resultados`. Así, de un vistazo, sabes quién es responsable de cada tarea.
|
|
240
|
+
|
|
241
|
+
## Probar en otra máquina
|
|
242
|
+
|
|
243
|
+
Para instalar y probar openteam en otro equipo que ya tenga [opencode](https://opencode.ai) y [Bun](https://bun.sh):
|
|
244
|
+
|
|
245
|
+
1. **Ejecuta o instala la CLI.** Elige una de estas rutas soportadas:
|
|
246
|
+
|
|
247
|
+
```powershell
|
|
248
|
+
# Opción global (deja el comando `openteam` en el PATH)
|
|
249
|
+
bun add --global @jmanuelcorral/openteam@latest
|
|
250
|
+
|
|
251
|
+
# Opción puntual (no instala globalmente)
|
|
252
|
+
bunx --package @jmanuelcorral/openteam@latest openteam setup
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
2. **Inicializa el repositorio** donde vayas a trabajar. Genera `opencode.json`, `.opencode/openteam.json` y `.opencode/agent/openteam.md`:
|
|
256
|
+
|
|
257
|
+
```powershell
|
|
258
|
+
cd C:\ruta\a\tu\repo
|
|
259
|
+
openteam setup # global
|
|
260
|
+
# La opción puntual ya ejecutó setup en el paso anterior.
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
El asistente detecta Ollama / LM Studio / Foundry Local, te deja elegir los modelos locales (locales o en otra máquina de la red) o **ninguno** para funcionar solo con frontier, y el frontier baseline, y escribe la configuración.
|
|
264
|
+
|
|
265
|
+
3. **Autentica el provider frontier** que hayas elegido:
|
|
266
|
+
|
|
267
|
+
```powershell
|
|
268
|
+
opencode auth login
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
4. **Arranca tu runtime local** si lo habilitaste y no estaba activo (p. ej. `ollama serve`, o abre LM Studio / Foundry Local). Si apuntaste a un runtime en **otra máquina de la red**, asegúrate de que sea accesible desde este equipo (host expuesto y puerto abierto); para Ollama esto normalmente implica arrancarlo con `OLLAMA_HOST=0.0.0.0 ollama serve` en la máquina remota. Si configuraste **solo frontier**, sáltate este paso.
|
|
272
|
+
|
|
273
|
+
5. **Abre opencode en el repo**, pulsa **Tab** y elige el agente `openteam`. Dale el primer prompt: creará el equipo de subagentes a demanda y enrutará local-first automáticamente.
|
|
274
|
+
|
|
275
|
+
Comprueba el estado con `openteam doctor` (runtimes + config) y el ahorro con `openteam report`.
|
|
276
|
+
|
|
277
|
+
## Actualizar openteam
|
|
278
|
+
|
|
279
|
+
openteam se publica en npm al publicar una GitHub Release. Para traer la última versión:
|
|
280
|
+
|
|
281
|
+
```powershell
|
|
282
|
+
# Instalación global
|
|
283
|
+
bun add --global @jmanuelcorral/openteam@latest
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Comprobar versiones:
|
|
287
|
+
|
|
288
|
+
```powershell
|
|
289
|
+
bun pm ls --global # paquetes globales instalados
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
La versión publicada más reciente aparece en
|
|
293
|
+
<https://www.npmjs.com/package/@jmanuelcorral/openteam>.
|
|
294
|
+
|
|
295
|
+
Notas al actualizar:
|
|
296
|
+
|
|
297
|
+
- **No necesitas volver a ejecutar `openteam setup`** para actualizar el plugin: opencode resuelve el paquete `@jmanuelcorral/openteam` declarado en `opencode.json` a la versión instalada. Reinicia opencode para que recargue el plugin.
|
|
298
|
+
- Vuelve a ejecutar `openteam setup` **solo** si quieres regenerar la configuración (cambiar runtimes, modelos o baseline). Pedirá confirmación antes de sobrescribir `opencode.json`, `.opencode/openteam.json` o `.opencode/agent/openteam.md`; **no toca los subagentes** que el orquestador haya creado a demanda.
|
|
299
|
+
- Ajustes puntuales sin reinit: `openteam baseline set <provider/model>` o `openteam baseline auto`.
|
|
300
|
+
|
|
301
|
+
## Configuración
|
|
302
|
+
|
|
303
|
+
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.
|
|
304
|
+
|
|
305
|
+
| Key | Tipo | Default | Descripción |
|
|
306
|
+
| --- | --- | --- | --- |
|
|
307
|
+
| `baseline.mode` | `"auto" \| "pinned"` | `"auto"` | En `auto`, usa perfiles frontier cheapest-capable cuando se pasan al router; en `pinned`, usa `baseline.pinnedModel` si existe. |
|
|
308
|
+
| `baseline.pinnedModel` | `ModelRef \| null` | `null` | Modelo frontier fijado explícitamente. `ModelRef` usa `{ "providerID": string, "modelID": string }`. |
|
|
309
|
+
| `baseline.hardDefault` | `ModelRef` | `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }` | Fallback frontier si no hay perfiles cheapest-capable o pin válido. |
|
|
310
|
+
| `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Modo de routing validado y reservado para política. |
|
|
311
|
+
| `router.localDefault` | `ModelRef` | `{ "providerID": "ollama", "modelID": "qwen3:8b" }` | Modelo local principal. |
|
|
312
|
+
| `router.trivialPromptMaxChars` | `number` entero positivo | `280` | Prompts sin código hasta este tamaño prefieren local. |
|
|
313
|
+
| `router.frontierPromptMinChars` | `number` entero positivo | `2000` | Prompts desde este tamaño se tratan como candidatos a frontier si no aplican guards. |
|
|
314
|
+
| `local.runtimes` | `LocalRuntime[]` | Ollama enabled en `http://localhost:11434/v1` con `qwen3:8b` | Lista mínima de un runtime local. |
|
|
315
|
+
| `local.runtimes[].id` | `"ollama" \| "lmstudio" \| "foundry-local"` | requerido | Runtime local. |
|
|
316
|
+
| `local.runtimes[].enabled` | `boolean` | `true` | Habilita o deshabilita ese runtime. |
|
|
317
|
+
| `local.runtimes[].baseURL` | URL opcional | según runtime/config | Endpoint OpenAI-compatible `/v1`; Foundry Local puede omitirlo si usa discovery. |
|
|
318
|
+
| `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`. |
|
|
319
|
+
| `local.runtimes[].defaultModel` | `ModelRef` | requerido | Modelo por defecto de ese runtime. |
|
|
320
|
+
| `budgets.sessionUSD` | `number` positivo opcional | sin límite | Presupuesto frontier por sesión. |
|
|
321
|
+
| `budgets.monthlyUSD` | `number` positivo opcional | sin límite | Presupuesto frontier mensual. |
|
|
322
|
+
| `budgets.frontierTokensPerSession` | `number` entero positivo opcional | sin límite | Límite de tokens frontier por sesión. |
|
|
323
|
+
| `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Si es `true`, agotar presupuesto devuelve `blockFrontier`; si es `false`, fuerza local. |
|
|
324
|
+
| `privacyMode` | `"forceLocalOnSensitive" \| "consentBeforeFrontier" \| "off"` | `"forceLocalOnSensitive"` | Política de privacidad para tareas sensibles. |
|
|
325
|
+
| `telemetry.enabled` | `boolean` plugin option | `true` | Activa/desactiva escritura JSONL. |
|
|
326
|
+
| `telemetry.path` | `string` plugin option | `.opencode/openteam-telemetry.jsonl` | Ruta del log `CostRecord` JSONL. |
|
|
327
|
+
|
|
328
|
+
## Uso
|
|
329
|
+
|
|
330
|
+
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`.
|
|
331
|
+
|
|
332
|
+
La orquestación multiagente usa roles estáticos y subsesiones opencode:
|
|
333
|
+
|
|
334
|
+
| Rol | Agent opencode | Tier base | Política |
|
|
335
|
+
| --- | --- | --- | --- |
|
|
336
|
+
| `rusty` | `architect` | `hard` | Arquitectura y decisiones de alto riesgo; frontier auto. |
|
|
337
|
+
| `livingston` | `integration` | `moderate` | Integración TS/opencode; tool calling por defecto. |
|
|
338
|
+
| `yen` | `local-runtime` | `moderate` | Runtimes locales; local-first con fallback frontier. |
|
|
339
|
+
| `basher` | `routing-cost` | `moderate` | Router, coste y presupuesto; local-first. |
|
|
340
|
+
| `scribe` | `scribe` | `trivial` | Documentación y resúmenes; local-first. |
|
|
341
|
+
| `linus` | `tester` | `simple` | Tests y contratos; local-first con tools. |
|
|
342
|
+
|
|
343
|
+
`runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con `batchID`. Los roles con `destructive` o `multiFileEdit` elevan el tier antes de elegir modelo.
|
|
344
|
+
|
|
345
|
+
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`.
|
|
346
|
+
|
|
347
|
+
## Comandos runtime
|
|
348
|
+
|
|
349
|
+
openteam expone comandos para inspeccionar y cambiar el routing sin editar JSON a mano. Hay tres superficies equivalentes:
|
|
350
|
+
|
|
351
|
+
### 1. Tool en la conversación
|
|
352
|
+
|
|
353
|
+
El plugin registra la herramienta `openteam`. Pídele al agente que la use, o instala el comando `/openteam` (ver más abajo). Acciones:
|
|
354
|
+
|
|
355
|
+
- `show` — muestra el baseline efectivo.
|
|
356
|
+
- `set` (con `model` en formato `provider/model`) — fija el baseline (modo `pinned`).
|
|
357
|
+
- `auto` — vuelve a cheapest-capable (modo `auto`).
|
|
358
|
+
- `doctor` — diagnóstico de runtimes locales, privacidad y telemetría.
|
|
359
|
+
- `report` — resumen de coste y ahorro desde la telemetría.
|
|
360
|
+
|
|
361
|
+
Los cambios de `set`/`auto` se persisten en `.opencode/openteam.json` y aplican en el siguiente arranque del plugin.
|
|
362
|
+
|
|
363
|
+
### 2. Slash command `/openteam`
|
|
364
|
+
|
|
365
|
+
`openteam setup` **genera automáticamente** `.opencode/command/openteam.md`, así que el comando `/openteam` aparece en opencode sin pasos manuales. (Si vienes de una versión anterior, vuelve a ejecutar `openteam setup` para crearlo, o cópialo a mano a tu proyecto o a `~/.config/opencode/command/`.) Después:
|
|
366
|
+
|
|
367
|
+
```text
|
|
368
|
+
/openteam baseline show
|
|
369
|
+
/openteam baseline set anthropic/claude-sonnet-4-5
|
|
370
|
+
/openteam baseline auto
|
|
371
|
+
/openteam doctor
|
|
372
|
+
/openteam agents
|
|
373
|
+
/openteam console
|
|
374
|
+
/openteam report
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
> ¿No ves `/openteam` en opencode? Asegúrate de que existe `.opencode/command/openteam.md` (lo crea `openteam setup`) y **reinicia/recarga opencode** para que descubra el comando.
|
|
378
|
+
|
|
379
|
+
### 3. CLI (`bin`)
|
|
380
|
+
|
|
381
|
+
El paquete expone el binario `openteam`. Con instalación global:
|
|
382
|
+
|
|
383
|
+
```powershell
|
|
384
|
+
bun add --global @jmanuelcorral/openteam@latest
|
|
385
|
+
openteam baseline show
|
|
386
|
+
openteam baseline set openai/gpt-5-mini
|
|
387
|
+
openteam doctor --config .opencode/openteam.json
|
|
388
|
+
openteam agents
|
|
389
|
+
openteam console
|
|
390
|
+
openteam report --telemetry .opencode/openteam-telemetry.jsonl
|
|
391
|
+
openteam yolo status
|
|
392
|
+
openteam yolo on
|
|
393
|
+
openteam local status
|
|
394
|
+
openteam local off
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Flags: `--config <path>` y `--telemetry <path>` sobrescriben las rutas por defecto; `--opencode <path>` apunta el comando `yolo` a un `opencode.json` concreto.
|
|
398
|
+
|
|
399
|
+
### Ver el LLM de cada agente: `openteam agents`
|
|
400
|
+
|
|
401
|
+
Lista los agentes de `.opencode/agent/` indicando **qué LLM usa cada uno**: si es **local** (Ollama/LM Studio/Foundry, sin coste de tokens) o **frontier** (consume tu suscripción), y el **proveedor** (Anthropic, OpenAI, GitHub Copilot, Google…). Los agentes sin `model` propio **heredan** el default de `opencode.json` (que openteam enruta local-first por mensaje).
|
|
402
|
+
|
|
403
|
+
```powershell
|
|
404
|
+
openteam agents
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
```text
|
|
408
|
+
openteam agents — LLM por agente:
|
|
409
|
+
|
|
410
|
+
● openteam [primary ] frontier · Anthropic (consume tu suscripción) (anthropic/claude-sonnet-4-5)
|
|
411
|
+
○ basher [subagent] local · Ollama (sin coste de tokens) (ollama/qwen3:8b)
|
|
412
|
+
○ scribe [subagent] hereda default → frontier · Anthropic (consume tu suscripción) · openteam enruta local-first por mensaje
|
|
413
|
+
|
|
414
|
+
Default de opencode.json: anthropic/claude-sonnet-4-5 (frontier · Anthropic)
|
|
415
|
+
Leyenda: ● primary · ○ subagent · local = sin coste de tokens · frontier = consume tu suscripción.
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
También está disponible **dentro de opencode**: pídele a openteam la lista de agentes y ejecutará la acción `agents` de su herramienta de comandos.
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
### Modo YOLO (auto-aprobar permisos)
|
|
422
|
+
|
|
423
|
+
El **modo YOLO** hace que opencode auto-apruebe **todos** los permisos (equivale al flag nativo `opencode --auto`, pero persistente). Escribe la regla global `permission: { "*": "allow" }` en `opencode.json` y **regenera el agente `openteam`** (`.opencode/agent/openteam.md`) con el mismo comodín, conservando el resto de tu configuración:
|
|
424
|
+
|
|
425
|
+
```powershell
|
|
426
|
+
openteam yolo status # ¿está activo?
|
|
427
|
+
openteam yolo on # activa YOLO
|
|
428
|
+
openteam yolo off # desactiva YOLO
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
También puedes activarlo durante `openteam setup` (te lo pregunta), o al vuelo con `opencode --auto` sin tocar la config.
|
|
432
|
+
|
|
433
|
+
> **Importante: el permiso del agente anula al global.** opencode fusiona el permiso del frontmatter de cada agente **después** del global y gana la última regla que casa; por eso `openteam yolo on/off` regenera `.opencode/agent/openteam.md` para que su `permission` coincida con el estado YOLO. Sin esto, un `bash: ask`/`external_directory: deny` en el agente seguiría pidiendo confirmación aunque el global fuese `"*": allow`. Tras cambiar el modo, **reinicia o recarga opencode** para que los agentes tomen los nuevos permisos, y crea los subagentes con el mismo comodín cuando YOLO esté activo (el orquestador ya lo hace).
|
|
434
|
+
|
|
435
|
+
> **YOLO no desactiva la privacidad de openteam.** Solo afecta a las aprobaciones de permisos de opencode; con `privacyMode: "forceLocalOnSensitive"`, los prompts sensibles siguen sin salir a frontier. Úsalo solo en entornos de confianza: auto-aprueba también `bash`, escrituras y accesos fuera del workspace (salvo reglas `deny` explícitas).
|
|
436
|
+
|
|
437
|
+
### Solo frontier (sin runtime local): `openteam local`
|
|
438
|
+
|
|
439
|
+
Si **no tienes ningún runtime local** (Ollama/LM Studio/Foundry Local) o prefieres no usarlo, puedes forzar que openteam enrute **siempre a modelos frontier**. `openteam setup` ya activa este modo automáticamente cuando no habilitas ningún runtime, pero puedes alternarlo en cualquier momento sin repetir el setup:
|
|
440
|
+
|
|
441
|
+
```powershell
|
|
442
|
+
openteam local status # ¿local-first o solo frontier? + runtimes configurados
|
|
443
|
+
openteam local off # solo frontier (desactiva el routing local-first)
|
|
444
|
+
openteam local on # vuelve al routing local-first
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Esto persiste el flag `router.frontierOnly` en `.opencode/openteam.json`. Con `frontierOnly` activo, el router escoge el **frontier cheapest-capable** en lugar de la heurística local-first, pero **respeta la privacidad, los presupuestos y los overrides explícitos por tarea**: los prompts sensibles con `forceLocalOnSensitive` no salen a frontier, y `local off` degrada esa política a `consentBeforeFrontier` (imposible forzar local sin runtime) informándote del cambio.
|
|
448
|
+
|
|
449
|
+
### Modo desatendido: `openteam loop` (patrón Ralph) 🎯 *(diseño)*
|
|
450
|
+
|
|
451
|
+
Segundo modo de operación: un **bucle externo** que invoca `opencode run` contra un backlog persistente hasta vaciarlo, con contexto fresco por iteración y topes de seguridad (presupuesto, máx. iteraciones, sin-progreso). Complementa al orquestador interactivo, no lo sustituye. Consulta el diseño y los ejemplos en **[docs/loop.md](docs/loop.md)**.
|
|
452
|
+
|
|
453
|
+
### Console web multi-sesión (se lanza desde la CLI) — alfa
|
|
454
|
+
|
|
455
|
+
> ⚠️ **Alfa — sin terminar.** La Console (y el comando `tunnel` de más abajo) es
|
|
456
|
+
> una funcionalidad **experimental** que todavía puede **rehacerse o
|
|
457
|
+
> reconstruirse**, con cambios incompatibles en su UI, endpoints, config (bloque
|
|
458
|
+
> `console`) y formato de eventos. El router, presupuestos, telemetría y el core
|
|
459
|
+
> de memoria son estables; la superficie web aún no. Úsala para observación
|
|
460
|
+
> local, no como API estable.
|
|
461
|
+
|
|
462
|
+
openteam expone una **Console web local** que **lanzas tú desde la CLI** con
|
|
463
|
+
`openteam console`.
|
|
464
|
+
Agrega **todas** las sesiones de opencode a la vez: puedes tener varias pestañas
|
|
465
|
+
de opencode abiertas y todas aparecen en la **misma** Console, con una pestaña por
|
|
466
|
+
sesión (más "Todas"), porque cada plugin **escribe eventos redactados** en logs
|
|
467
|
+
JSONL por sesión y la Console los vigila (`fs.watch`) y **agrega**.
|
|
468
|
+
|
|
469
|
+
Muestra en vivo: **coste y tokens reales por mensaje** (input/output/reasoning/
|
|
470
|
+
cache), **toolcalls con duración** y ok/fallo, ruteo reciente (coste/ahorro y
|
|
471
|
+
modelo elegido, **solo hashes de prompt, nunca el texto**), **decisiones** de los
|
|
472
|
+
agentes (scribe) y **reuniones** (batches multi-agente del orquestador), progreso
|
|
473
|
+
del backlog del loop, el equipo de agentes (LLM local/frontier de cada uno) y
|
|
474
|
+
últimos commits. Se actualiza por **SSE** (con *polling* de respaldo).
|
|
475
|
+
|
|
476
|
+
Cada pestaña de sesión incluye además una **vista "Sesión"**: una consola por la
|
|
477
|
+
que puedes **ver la salida en vivo** (SSE) y **enviar prompts** o **responder
|
|
478
|
+
permisos** a esa sesión de opencode, autenticada con un **token efímero** por
|
|
479
|
+
arranque. Opcionalmente, con el flag `terminal.pty`, una **vista "Terminal"** abre
|
|
480
|
+
una **shell real** en el workspace vía la API de PTY de opencode (sin `node-pty`).
|
|
481
|
+
|
|
482
|
+
Lánzala contra el repo actual; escucha en loopback y corre hasta **Ctrl+C**:
|
|
483
|
+
|
|
484
|
+
```powershell
|
|
485
|
+
openteam console # imprime la URL y sirve la Console multi-sesión
|
|
486
|
+
openteam console --open # además abre el navegador
|
|
487
|
+
openteam console --status # solo imprime la config (no lanza el servidor)
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Las sesiones se leen de:
|
|
491
|
+
|
|
492
|
+
```text
|
|
493
|
+
.opencode/openteam/sessions/*.jsonl
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Puedes ajustar host/puerto y la terminal en `.opencode/openteam.json` (bloque
|
|
497
|
+
`console`):
|
|
498
|
+
|
|
499
|
+
```json
|
|
500
|
+
{
|
|
501
|
+
"console": {
|
|
502
|
+
"host": "127.0.0.1",
|
|
503
|
+
"port": 4599,
|
|
504
|
+
"autoPortFallback": true,
|
|
505
|
+
"refreshMs": 2000,
|
|
506
|
+
"recentRoutes": 50,
|
|
507
|
+
"openBrowser": false,
|
|
508
|
+
"terminal": { "enabled": true, "pty": false }
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
> **Seguridad**: el servidor escucha **solo en loopback** (`127.0.0.1`/`localhost`, validado por Zod) y **nunca expone prompts** (solo `promptHash`), args de toolcall ni contenido de mensajes: solo contadores, costes y resúmenes redactados. La vista "Sesión"/"Terminal" exige el token efímero. Si el puerto está ocupado y `autoPortFallback` es `true`, prueba el siguiente libre.
|
|
514
|
+
|
|
515
|
+
### Acceso remoto seguro: `openteam tunnel` — alfa
|
|
516
|
+
|
|
517
|
+
> ⚠️ **Alfa — sin terminar.** Igual que la Console, `tunnel` es experimental y
|
|
518
|
+
> puede rehacerse o reconstruirse. Trata sus flags y comportamiento como
|
|
519
|
+
> inestables.
|
|
520
|
+
|
|
521
|
+
Para acceder a la Console (y, opcionalmente, operar la terminal) **desde fuera**,
|
|
522
|
+
`openteam tunnel` la expone vía **Microsoft Dev Tunnels** en lugar de bindear a
|
|
523
|
+
`0.0.0.0`. Comprueba que `devtunnel` esté instalado y con sesión iniciada,
|
|
524
|
+
hospeda el puerto de la Console e imprime la URL pública hasta **Ctrl+C**:
|
|
525
|
+
|
|
526
|
+
```powershell
|
|
527
|
+
openteam tunnel # expone solo la Console (observación), autenticado
|
|
528
|
+
openteam tunnel --terminal # además expone opencode para la terminal remota
|
|
529
|
+
openteam tunnel --allow-anonymous --yes # túnel anónimo (requiere doble confirmación)
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
> **Seguridad del túnel**: autenticado por defecto. La **terminal remota** exige
|
|
533
|
+
> `OPENCODE_SERVER_PASSWORD` definido; sin ella, `--terminal` se ignora y solo se
|
|
534
|
+
> expone la Console (observación). El túnel **anónimo** requiere `--yes` (doble
|
|
535
|
+
> confirmación) y avisa de que opencode puede ejecutar comandos y editar ficheros.
|
|
536
|
+
> Instala devtunnel con `winget install Microsoft.devtunnel` e inicia sesión con
|
|
537
|
+
> `devtunnel user login`.
|
|
538
|
+
|
|
539
|
+
### Memoria del equipo por MCP (solo lectura): `openteam mcp`
|
|
540
|
+
|
|
541
|
+
`openteam mcp` arranca un **servidor MCP de solo lectura** (JSON-RPC 2.0 sobre
|
|
542
|
+
stdio, sin dependencias) que expone la memoria del equipo agregada desde los
|
|
543
|
+
eventos por sesión para que agentes/herramientas la consulten. Se apoya en el
|
|
544
|
+
mismo `StorageProvider` que la Console y **nunca** expone prompts crudos, solo el
|
|
545
|
+
estado ya redactado. Tools disponibles: `list_decisions` (filtrable por
|
|
546
|
+
`agent`/`tag`), `list_meetings`, `list_sessions` y `cost_summary` (coste/tokens
|
|
547
|
+
reales + ahorro estimado vs baseline all-frontier).
|
|
548
|
+
|
|
549
|
+
Regístralo en `opencode.json` como cualquier MCP server local:
|
|
550
|
+
|
|
551
|
+
```json
|
|
552
|
+
{
|
|
553
|
+
"mcp": {
|
|
554
|
+
"openteam-memory": {
|
|
555
|
+
"type": "local",
|
|
556
|
+
"command": ["openteam", "mcp"]
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
#### Recall semántico (opt-in): `recall_facts`, `recall_preferences`, `similar_tasks`
|
|
563
|
+
|
|
564
|
+
Además de la memoria de equipo, `openteam mcp` puede exponer **recall semántico**
|
|
565
|
+
de la memoria de conocimiento long-term (hechos, preferencias, tareas similares).
|
|
566
|
+
Está **desactivado por defecto**; se activa con el bloque `memory.semantic` en
|
|
567
|
+
`.opencode/openteam.json`:
|
|
568
|
+
|
|
569
|
+
```json
|
|
570
|
+
{
|
|
571
|
+
"memory": {
|
|
572
|
+
"semantic": { "enabled": true }
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Al activarlo, y si hay un runtime local con `baseURL`, el servidor añade tres
|
|
578
|
+
tools: `recall_facts`, `recall_preferences` y `similar_tasks`. La query se embebe
|
|
579
|
+
**en local** (nunca sale a frontier) y los records están **redactados en origen**
|
|
580
|
+
(`storeContent=false` por defecto), por lo que las tools nunca devuelven prompts
|
|
581
|
+
crudos. Si falta `bun:sqlite` o el índice no puede abrirse, `openteam mcp`
|
|
582
|
+
**degrada con seguridad** y sigue exponiendo solo la memoria de equipo.
|
|
583
|
+
|
|
584
|
+
#### Consolidación / olvido: `openteam memory consolidate`
|
|
585
|
+
|
|
586
|
+
La memoria long-term **olvida** por decay: la confianza de cada record decae con
|
|
587
|
+
el tiempo y, al caer bajo el umbral, se marca como soft-invalidated (sin borrar:
|
|
588
|
+
el histórico se conserva para auditoría "as-of"). Ejecuta la pasada de olvido con:
|
|
589
|
+
|
|
590
|
+
```powershell
|
|
591
|
+
openteam memory consolidate
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Anexa *tombstones* al log de memoria y reporta cuántos records se olvidaron. Es
|
|
595
|
+
idempotente y no destructivo.
|
|
596
|
+
|
|
597
|
+
#### Push automático a contexto (opt-in)
|
|
598
|
+
|
|
599
|
+
Con la inyección activada, openteam **prepende** memoria relevante al prompt en
|
|
600
|
+
cada turno (`chat.message`), respetando un presupuesto de tokens:
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"memory": {
|
|
605
|
+
"semantic": {
|
|
606
|
+
"enabled": true,
|
|
607
|
+
"injection": { "enabled": true, "maxChars": 1200, "maxItems": 8 }
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Está **desactivado por defecto**. La inyección ocurre **después** de decidir el
|
|
614
|
+
modelo, así que no altera el routing ni la telemetría, y **nunca rompe el turno**
|
|
615
|
+
si el recall falla. Solo inyecta lo que ya está en los records (redactado en
|
|
616
|
+
origen si `storeContent=false`).
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
### Ollama
|
|
621
|
+
|
|
622
|
+
```powershell
|
|
623
|
+
ollama serve
|
|
624
|
+
ollama pull qwen3:8b
|
|
625
|
+
Invoke-RestMethod -Uri "http://localhost:11434/v1/models" -Method Get
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### LM Studio
|
|
629
|
+
|
|
630
|
+
1. Abre LM Studio.
|
|
631
|
+
2. Carga un modelo compatible.
|
|
632
|
+
3. Activa el servidor local OpenAI-compatible en el puerto `1234`.
|
|
633
|
+
|
|
634
|
+
```powershell
|
|
635
|
+
Invoke-RestMethod -Uri "http://localhost:1234/v1/models" -Method Get
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Foundry Local
|
|
639
|
+
|
|
640
|
+
```powershell
|
|
641
|
+
foundry service status
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
openteam extrae el puerto de la salida del CLI y normaliza el endpoint a `http://localhost:<PORT>/v1`.
|
|
645
|
+
|
|
646
|
+
### Telemetría
|
|
647
|
+
|
|
648
|
+
```powershell
|
|
649
|
+
$telemetryPath = "C:\gitrepos\openteam\.opencode\openteam-telemetry.jsonl"
|
|
650
|
+
Get-Content -Path $telemetryPath -Tail 5
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### Verificación local
|
|
654
|
+
|
|
655
|
+
```powershell
|
|
656
|
+
Set-Location -Path "C:\gitrepos\openteam"
|
|
657
|
+
bun test
|
|
658
|
+
bun run typecheck
|
|
659
|
+
bun run lint
|
|
660
|
+
bun run format:check
|
|
661
|
+
# Cuando el empaquetado de Fase 4 exponga el script:
|
|
662
|
+
bun run build
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
### Desarrollo local en modo dev (sin registry)
|
|
666
|
+
|
|
667
|
+
Para que la CLI global `openteam` y opencode usen la build local de este repo en
|
|
668
|
+
lugar de la versión publicada (sin pasar por ningún registry), se enlaza el
|
|
669
|
+
paquete con un symlink global:
|
|
670
|
+
|
|
671
|
+
```powershell
|
|
672
|
+
Set-Location -Path "C:\gitrepos\openteam"
|
|
673
|
+
bun run link:local # = bun run build && npm link
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
`npm link` crea un enlace global (junction/symlink) hacia este repo, así que tras
|
|
677
|
+
cada `bun run build` la CLI global refleja el código local.
|
|
678
|
+
|
|
679
|
+
Un hook `pre-push` versionado (`.githooks/pre-push`) puede ejecutar
|
|
680
|
+
`bun run link:local` antes de cada `git push`, manteniendo la instalación local al
|
|
681
|
+
día. La instalación de dependencias **no** modifica Git. Activa el hook
|
|
682
|
+
explícitamente, una vez por clone:
|
|
683
|
+
|
|
684
|
+
```powershell
|
|
685
|
+
bun run hooks:install
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
El hook avisa si el build o el link fallan, pero **no bloquea** el push.
|
|
689
|
+
|
|
690
|
+
## Publicación segura
|
|
691
|
+
|
|
692
|
+
El workflow de release construye y verifica un único tarball sin permisos de
|
|
693
|
+
escritura ni OIDC. Otro job publica exactamente ese artefacto, después de validar
|
|
694
|
+
su integridad, mediante npm Trusted Publishing; un último job con solo
|
|
695
|
+
`contents: write` lo adjunta a la GitHub Release. No existe fallback a credenciales
|
|
696
|
+
persistentes y el CI normal no necesita configuración de npm.
|
|
697
|
+
|
|
698
|
+
Antes de la primera release real, el propietario debe registrar en npm un Trusted
|
|
699
|
+
Publisher para `@jmanuelcorral/openteam` con owner `jmanuelcorral`, repositorio
|
|
700
|
+
`openteam`, workflow `release.yml`, acción permitida `npm publish` y sin
|
|
701
|
+
environment. Hasta completar ese alta única, la publicación falla de forma
|
|
702
|
+
cerrada. Tras la primera publicación OIDC correcta, hay que exigir 2FA sin tokens,
|
|
703
|
+
revocar el antiguo token de automatización y eliminar su secreto heredado de
|
|
704
|
+
GitHub Actions.
|
|
705
|
+
|
|
706
|
+
## Privacidad
|
|
707
|
+
|
|
708
|
+
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`.
|
|
709
|
+
|
|
710
|
+
La telemetría usa `hashPrompt`, actualmente `fnv1a32:<hash>`, y no serializa el prompt completo.
|
|
711
|
+
|
|
712
|
+
## Calidad
|
|
713
|
+
|
|
714
|
+
Gates no negociables:
|
|
715
|
+
|
|
716
|
+
- `bun test`
|
|
717
|
+
- Coverage global: líneas `>= 85%`, branches `>= 80%`.
|
|
718
|
+
- Coverage de `src/router/**`: `100%` lines, branches, statements y functions.
|
|
719
|
+
- `bun run typecheck`
|
|
720
|
+
- `biome check .` o `bun run lint` + `bun run format:check`
|
|
721
|
+
- Test de determinismo del router.
|
|
722
|
+
- Tests de contrato si cambian hooks opencode, agents, comandos, providers o SDK.
|
|
723
|
+
|
|
724
|
+
## Compatibilidad
|
|
725
|
+
|
|
726
|
+
Consulta [docs/compatibility.md](docs/compatibility.md). Resumen verificado el `2026-08-19`:
|
|
727
|
+
|
|
728
|
+
| Superficie | Versión / contrato |
|
|
729
|
+
| --- | --- |
|
|
730
|
+
| openteam | `0.1.41`; versión actual del paquete |
|
|
731
|
+
| `@opencode-ai/plugin` | `1.17.13` |
|
|
732
|
+
| `@opencode-ai/sdk` | `1.17.13` |
|
|
733
|
+
| Hook de routing | `chat.message`; no `chat.params` para cambiar modelo |
|
|
734
|
+
| Subsesiones | `client.session.create` + `client.session.prompt({ body: { model } })` |
|
|
735
|
+
|
|
736
|
+
## Roadmap
|
|
737
|
+
|
|
738
|
+
| Fase | Estado | Entregables |
|
|
739
|
+
| --- | --- | --- |
|
|
740
|
+
| 0. Scaffold/PoC | Hecha | TS/Bun, plugin mínimo, hook `chat.message`. |
|
|
741
|
+
| 1. Local registry + router heurístico | Hecha | Ollama/LM Studio/Foundry, probes y `chooseModel` determinista. |
|
|
742
|
+
| 2. Clasificador + perfiles + presupuesto + telemetría | Hecha | Clasificador local, `ModelCapabilityProfile`, budgets y `CostRecord`. |
|
|
743
|
+
| 3. Orquestación multiagente | Hecha | Coordinator, roles, child sessions y permisos. |
|
|
744
|
+
| 4. Empaquetado npm + docs | Hecha | Package exportable, README, ejemplos Windows y matriz de compatibilidad. |
|
|
745
|
+
| 5. Comandos runtime | Hecha | `baseline show/set/auto`, `doctor` y `report` vía tool, `/openteam` y CLI `bin`. |
|
|
746
|
+
|
|
747
|
+
## Licencia
|
|
748
|
+
|
|
749
|
+
MIT. Consulta [LICENSE](LICENSE).
|
|
750
|
+
|
|
751
|
+
## Agradecimientos e inspiración
|
|
752
|
+
|
|
753
|
+
openteam se apoya en trabajo previo. Estos proyectos han inspirado su diseño: tomamos ideas de ellos, las adaptamos a opencode y las reimplementamos desde cero en TypeScript:
|
|
754
|
+
|
|
755
|
+
- **[Squad](https://bradygaster.github.io/squad/)** ([bradygaster/squad](https://github.com/bradygaster/squad)) — el modelo de equipo multiagente temático creado a demanda: un único orquestador que castea subagentes especialistas según lo pide el trabajo. Inspiró el agente orquestador `openteam` y la convención de equipo/roster.
|
|
756
|
+
- **[Superpowers](https://github.com/obra/superpowers)** de Jesse Vincent — una metodología componible basada en *skills* para agentes de código. Inspiró las convenciones de agentes basadas en skills y el flujo spec-first / subagent-driven.
|
|
757
|
+
- **[agent-memory-dotnet](https://github.com/joslat/agent-memory-dotnet)** de José Luis Latorre — un modelo de memoria semántica a largo plazo para agentes. Inspiró el subsistema de memoria (extraer → rankear → consolidar → recuperar) con almacenamiento local-first y hash-redactado.
|
|
758
|
+
|
|
759
|
+
Todas las marcas y nombres de proyecto pertenecen a sus respectivos dueños; los enlaces anteriores son atribución, no un aval.
|