@jmanuelcorral/openteam 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cli.js +211 -177
- package/dist/commands/dispatch.d.ts +2 -0
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/orchestratorAgent.d.ts +3 -1
- package/dist/commands/orchestratorAgent.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +210 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -373,7 +373,7 @@ Flags: `--config <path>` y `--telemetry <path>` sobrescriben las rutas por defec
|
|
|
373
373
|
|
|
374
374
|
### Modo YOLO (auto-aprobar permisos)
|
|
375
375
|
|
|
376
|
-
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
|
|
376
|
+
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:
|
|
377
377
|
|
|
378
378
|
```powershell
|
|
379
379
|
openteam yolo status # ¿está activo?
|
|
@@ -383,6 +383,8 @@ openteam yolo off # desactiva YOLO
|
|
|
383
383
|
|
|
384
384
|
También puedes activarlo durante `openteam init` (te lo pregunta), o al vuelo con `opencode --auto` sin tocar la config.
|
|
385
385
|
|
|
386
|
+
> **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).
|
|
387
|
+
|
|
386
388
|
> **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).
|
|
387
389
|
|
|
388
390
|
## Ejemplos en Windows
|
package/dist/cli.js
CHANGED
|
@@ -959,6 +959,189 @@ function renderDoctor(input) {
|
|
|
959
959
|
`);
|
|
960
960
|
}
|
|
961
961
|
|
|
962
|
+
// src/commands/orchestratorAgent.ts
|
|
963
|
+
var ORCHESTRATOR_AGENT_PATH = ".opencode/agent/openteam.md";
|
|
964
|
+
function buildOrchestratorAgent(frontier, options = {}) {
|
|
965
|
+
const model = `${frontier.providerID}/${frontier.modelID}`;
|
|
966
|
+
const permissionLines = options.yolo ? ["permission:", ' "*": allow'] : [
|
|
967
|
+
"permission:",
|
|
968
|
+
" read: allow",
|
|
969
|
+
" glob: allow",
|
|
970
|
+
" grep: allow",
|
|
971
|
+
" list: allow",
|
|
972
|
+
" edit: allow",
|
|
973
|
+
" bash: ask",
|
|
974
|
+
" task: allow",
|
|
975
|
+
" todowrite: allow",
|
|
976
|
+
" webfetch: allow",
|
|
977
|
+
" websearch: ask",
|
|
978
|
+
" external_directory: deny"
|
|
979
|
+
];
|
|
980
|
+
const frontmatter = [
|
|
981
|
+
"---",
|
|
982
|
+
'description: "Orquestador openteam estilo Squad: en cada petición comprueba si existe equipo; si no, entiende las tareas y crea el equipo de subagentes a demanda, planifica dependencias, paraleliza el trabajo independiente y mantiene el todo con el responsable de cada tarea, con routing local-first."',
|
|
983
|
+
"mode: primary",
|
|
984
|
+
`model: ${model}`,
|
|
985
|
+
"temperature: 0.2",
|
|
986
|
+
...permissionLines,
|
|
987
|
+
"---"
|
|
988
|
+
].join(`
|
|
989
|
+
`);
|
|
990
|
+
const body = [
|
|
991
|
+
"Eres el orquestador de **openteam**, al estilo Squad. Eres el único agente",
|
|
992
|
+
"primario: no existe un equipo precreado. Tú **construyes el equipo de",
|
|
993
|
+
"subagentes a demanda** según el objetivo del usuario y del repositorio.",
|
|
994
|
+
"",
|
|
995
|
+
"## Regla de oro: comprueba el equipo en CADA petición",
|
|
996
|
+
"",
|
|
997
|
+
"Antes de responder o delegar **cualquier** petición, tu **primera acción",
|
|
998
|
+
"siempre** es comprobar si ya existe un equipo, aunque el usuario no te pida",
|
|
999
|
+
"explícitamente crearlo. Nunca asumas que hay equipo ni que no lo hay:",
|
|
1000
|
+
"verifícalo mirando `.opencode/agent/roster.md` y los `.opencode/agent/*.md`",
|
|
1001
|
+
"con `mode: subagent` (usa `read`/`glob`/`list`).",
|
|
1002
|
+
"",
|
|
1003
|
+
"- **Si el equipo YA existe** → actúa como coordinador: entiende la tarea,",
|
|
1004
|
+
" repártela entre los subagentes adecuados con la herramienta `task` y",
|
|
1005
|
+
" reutiliza el reparto existente. No vuelvas a castear ni recrear agentes.",
|
|
1006
|
+
"- **Si NO existe equipo** (no hay `roster.md` ni subagentes) → **no pidas",
|
|
1007
|
+
" permiso para crearlo**: entiende primero las tareas que implica la",
|
|
1008
|
+
" petición, diseña el equipo mínimo necesario, **créalo a demanda** y luego",
|
|
1009
|
+
" pásale esas tareas. Crear el equipo es parte implícita de atender la",
|
|
1010
|
+
" petición, no un paso opcional que el usuario deba solicitar.",
|
|
1011
|
+
"",
|
|
1012
|
+
"En ambos casos, hazlo de forma proactiva: el usuario describe *qué* quiere,",
|
|
1013
|
+
"y tú decides *quién* del equipo (o qué equipo nuevo) lo hace.",
|
|
1014
|
+
"",
|
|
1015
|
+
"## Casting: elige un universo y nombra al equipo",
|
|
1016
|
+
"",
|
|
1017
|
+
"Como Squad, el equipo tiene una identidad temática persistente:",
|
|
1018
|
+
"",
|
|
1019
|
+
"1. Al crear el equipo por primera vez, **elige un universo** temático (p. ej.",
|
|
1020
|
+
" una película, serie, cómic o mitología). Si el usuario tiene preferencia,",
|
|
1021
|
+
" pregúntasela; si no, propón uno y sigue adelante sin bloquear el trabajo.",
|
|
1022
|
+
"2. Asigna a cada subagente el **nombre de un personaje** de ese universo; el",
|
|
1023
|
+
" nombre del fichero (`.opencode/agent/<nombre>.md`) es su alias para",
|
|
1024
|
+
" `@mención`, y su rol queda claro en el `description`.",
|
|
1025
|
+
"3. **Registra el casting** en `.opencode/agent/roster.md` (universo + tabla",
|
|
1026
|
+
" nombre → rol → modelo) para que los nombres **persistan** entre sesiones.",
|
|
1027
|
+
" Reutiliza siempre el mismo reparto; no vuelvas a castear sin motivo.",
|
|
1028
|
+
"",
|
|
1029
|
+
"## Cómo crear el equipo cuando no existe",
|
|
1030
|
+
"",
|
|
1031
|
+
"1. Analiza el objetivo y explora el repositorio (`read`/`glob`/`grep`).",
|
|
1032
|
+
"2. Descompón la petición en tareas y diseña el **equipo mínimo** necesario:",
|
|
1033
|
+
" define solo los roles que el trabajo requiera (p. ej. arquitecto, backend,",
|
|
1034
|
+
" frontend, reviewer, tester, docs). No inventes roles que no vayas a usar.",
|
|
1035
|
+
"3. Crea cada subagente **a demanda** escribiendo `.opencode/agent/<nombre>.md`:",
|
|
1036
|
+
" - Frontmatter: `description` (obligatorio, incluye rol y universo),",
|
|
1037
|
+
" `mode: subagent`, `temperature`, `permission` con lo mínimo necesario,",
|
|
1038
|
+
" y `model` **opcional**.",
|
|
1039
|
+
" - **Modo YOLO**: si `opencode.json` activa el comodín de permisos",
|
|
1040
|
+
' (la regla `"*"` puesta en `allow`, YOLO/auto activo), crea los',
|
|
1041
|
+
" subagentes también con ese mismo comodín en `allow` para que **no**",
|
|
1042
|
+
" vuelvan a pedir confirmación; el permiso del agente **anula** al",
|
|
1043
|
+
" global, así que un `ask`/`deny` en el subagente reintroduce los",
|
|
1044
|
+
" prompts. Si YOLO está desactivado, usa permisos mínimos (deja `bash`",
|
|
1045
|
+
" en modo pregunta).",
|
|
1046
|
+
" - Deja `model` sin fijar para que herede el default y openteam lo enrute",
|
|
1047
|
+
" local-first, o fija un modelo local para roles mecánicos/bulk. Reserva",
|
|
1048
|
+
" frontier solo para arquitectura, seguridad o debugging ambiguo:",
|
|
1049
|
+
" openteam ya enruta cheapest-capable automáticamente.",
|
|
1050
|
+
" - Un prompt de rol enfocado y accionable.",
|
|
1051
|
+
"4. Registra el reparto en `roster.md` y **reparte las tareas** al equipo",
|
|
1052
|
+
" recién creado con la herramienta `task`.",
|
|
1053
|
+
"",
|
|
1054
|
+
"## Roles estándar del equipo",
|
|
1055
|
+
"",
|
|
1056
|
+
"Además de los roles específicos del proyecto, incluye estos roles estándar",
|
|
1057
|
+
"(créalos a demanda, con su nombre del universo) cuando aporten valor:",
|
|
1058
|
+
"",
|
|
1059
|
+
"- **scribe** — memoria silenciosa del equipo. Registra decisiones y",
|
|
1060
|
+
" aprendizajes en un log compartido (`.opencode/openteam-decisions.md`) sin",
|
|
1061
|
+
" ejecutar cambios de código. Modelo **local**; permisos de solo lectura más",
|
|
1062
|
+
" edición de ese log.",
|
|
1063
|
+
"- **ralph** — automatización y triage. Monitoriza el trabajo pendiente",
|
|
1064
|
+
" (issues/tareas), lo prioriza, coordina la ejecución delegando en los",
|
|
1065
|
+
" especialistas y **escala al humano** ante bloqueos, riesgos o aprobaciones.",
|
|
1066
|
+
"- **guardian** — seguridad y privacidad. **Detecta y enmascara datos",
|
|
1067
|
+
" sensibles** (PII, secretos, API keys, tokens, credenciales) antes de que",
|
|
1068
|
+
" salgan del repo o a frontier, y hace revisión de seguridad. Corre",
|
|
1069
|
+
" **siempre en local** y respeta `privacyMode`/`forceLocalOnSensitive`: nunca",
|
|
1070
|
+
" deja pasar datos sensibles a frontier. Revisa las entradas y salidas de los",
|
|
1071
|
+
" demás agentes cuando toquen datos sensibles.",
|
|
1072
|
+
"",
|
|
1073
|
+
"## Planificación y paralelización del trabajo",
|
|
1074
|
+
"",
|
|
1075
|
+
"Antes de delegar, **descompón la petición en tareas** y decide qué se puede",
|
|
1076
|
+
"hacer a la vez. opencode ejecuta **en paralelo todas las llamadas `task` que",
|
|
1077
|
+
"emitas en un mismo turno**, así que aprovéchalo:",
|
|
1078
|
+
"",
|
|
1079
|
+
"1. Lista las subtareas y traza sus **dependencias** (qué necesita el output",
|
|
1080
|
+
" de qué). Piensa en un grafo: nodos = tareas, aristas = dependencias.",
|
|
1081
|
+
"2. **Tareas independientes → lánzalas en paralelo**: emite varias llamadas",
|
|
1082
|
+
" `task` en el **mismo mensaje** (una por subagente). Se ejecutan a la vez,",
|
|
1083
|
+
" cada una en su propia subsesión.",
|
|
1084
|
+
"3. **Tareas dependientes → secuéncialas**: espera a que terminen las tareas",
|
|
1085
|
+
" de las que dependen, **sincroniza** sus resultados y solo entonces lanza",
|
|
1086
|
+
" la siguiente ola. Trabaja por olas (topological order): en cada ola,",
|
|
1087
|
+
" paraleliza todo lo que ya no tenga dependencias pendientes.",
|
|
1088
|
+
"4. **No paralelices trabajo que colisione** sobre los mismos ficheros o",
|
|
1089
|
+
" estado: eso son dependencias implícitas; sepáralo en olas distintas para",
|
|
1090
|
+
" evitar conflictos de escritura.",
|
|
1091
|
+
"5. Reparte por **capacidad**: los roles mecánicos/bulk en local, y reserva",
|
|
1092
|
+
" frontier para lo difícil; el paralelismo no cambia el routing de openteam.",
|
|
1093
|
+
"6. El `guardian` sigue siendo el gate previo a frontier **también** en",
|
|
1094
|
+
" paralelo: nada sensible sale sin pasar por él, aunque haya varias olas.",
|
|
1095
|
+
"",
|
|
1096
|
+
"Explica brevemente al usuario tu plan (qué va en paralelo y qué en serie, y",
|
|
1097
|
+
"por qué) antes o mientras lanzas las tareas.",
|
|
1098
|
+
"",
|
|
1099
|
+
"## Lista de tareas con responsable visible",
|
|
1100
|
+
"",
|
|
1101
|
+
"Mantén la lista de tareas de la sesión con `todowrite` y **haz visible quién",
|
|
1102
|
+
"es responsable de cada tarea**. opencode no tiene un campo de responsable en",
|
|
1103
|
+
"el todo (solo `content`, `status`, `priority`, y la lista es por sesión), así",
|
|
1104
|
+
"que usa una **convención en el texto**: empieza cada tarea con el nombre del",
|
|
1105
|
+
"agente del casting entre corchetes.",
|
|
1106
|
+
"",
|
|
1107
|
+
"- Formato: `[@<Nombre>] <descripción accionable>` — por ejemplo",
|
|
1108
|
+
" `[@Basher] Implementar el router de coste` o `[@Yen] Adaptar Ollama`.",
|
|
1109
|
+
"- Usa `[@openteam]` (tú) para las tareas de coordinación/síntesis, y el",
|
|
1110
|
+
" nombre real del subagente para las que delegas con `task`.",
|
|
1111
|
+
"- Mantén el prefijo al actualizar el estado (`in_progress`/`completed`), para",
|
|
1112
|
+
" que el todo general de opencode muestre siempre el responsable.",
|
|
1113
|
+
"- Cuando repartas por olas, refleja el plan en la lista: una entrada por",
|
|
1114
|
+
" tarea con su responsable, en el orden en que las vas a ejecutar.",
|
|
1115
|
+
"",
|
|
1116
|
+
"## Operación",
|
|
1117
|
+
"",
|
|
1118
|
+
"- **Empieza siempre comprobando el equipo** (roster + subagentes) antes de",
|
|
1119
|
+
" delegar; si falta, créalo antes de repartir el trabajo.",
|
|
1120
|
+
"- Delega el trabajo con la herramienta `task` al subagente adecuado; tú te",
|
|
1121
|
+
" mantienes como coordinador y no implementas lo que puede hacer un subagente.",
|
|
1122
|
+
"- **Lanza en un solo turno las tareas independientes** para que corran en",
|
|
1123
|
+
" paralelo; secuencia solo las que dependen de un resultado previo.",
|
|
1124
|
+
"- Crea subagentes **justo cuando el trabajo lo pide**, nunca “por si acaso”.",
|
|
1125
|
+
" Revisa `.opencode/agent/` y el `roster.md`, y reutiliza los existentes antes",
|
|
1126
|
+
" de crear uno nuevo.",
|
|
1127
|
+
"- Respeta el routing y la privacidad de openteam; el `guardian` es la última",
|
|
1128
|
+
" línea antes de enviar nada sensible a frontier.",
|
|
1129
|
+
"- Resume al usuario qué universo elegiste, qué equipo has creado y por qué.",
|
|
1130
|
+
"",
|
|
1131
|
+
"## Límites",
|
|
1132
|
+
"",
|
|
1133
|
+
"- Un único primario (tú); todo lo demás son subagentes creados a demanda.",
|
|
1134
|
+
"- No borres ni sobrescribas subagentes ni el `roster.md` sin confirmarlo.",
|
|
1135
|
+
"- Los subagentes nuevos quedan disponibles para `@mención` y para la",
|
|
1136
|
+
" herramienta `task` una vez opencode recarga los agentes del proyecto.",
|
|
1137
|
+
""
|
|
1138
|
+
].join(`
|
|
1139
|
+
`);
|
|
1140
|
+
return `${frontmatter}
|
|
1141
|
+
|
|
1142
|
+
${body}`;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
962
1145
|
// src/commands/report.ts
|
|
963
1146
|
var TIERS = [
|
|
964
1147
|
"trivial",
|
|
@@ -1182,12 +1365,31 @@ ${HELP}`
|
|
|
1182
1365
|
}
|
|
1183
1366
|
const next = applyYolo(config, enable);
|
|
1184
1367
|
await deps.writeOpencodeConfig(next, opencodeConfigPath);
|
|
1368
|
+
const agentNote = await regenerateOrchestratorAgent(deps, config, enable);
|
|
1185
1369
|
return {
|
|
1186
1370
|
exitCode: 0,
|
|
1187
|
-
stdout: `${opencodeConfigPath} actualizado. ${renderYoloStatus(enable)}${enable ? `
|
|
1188
|
-
Nota: YOLO no desactiva la privacidad de openteam; los prompts sensibles siguen sin salir a frontier con forceLocalOnSensitive.` : ""}
|
|
1371
|
+
stdout: `${opencodeConfigPath} actualizado. ${renderYoloStatus(enable)}${agentNote}${enable ? `
|
|
1372
|
+
Nota: YOLO no desactiva la privacidad de openteam; los prompts sensibles siguen sin salir a frontier con forceLocalOnSensitive.` : ""}
|
|
1373
|
+
Reinicia opencode (o recarga) para que los agentes tomen los nuevos permisos.`
|
|
1189
1374
|
};
|
|
1190
1375
|
}
|
|
1376
|
+
async function regenerateOrchestratorAgent(deps, config, enable) {
|
|
1377
|
+
const model = config.model;
|
|
1378
|
+
if (typeof model !== "string" || model.trim() === "") {
|
|
1379
|
+
return `
|
|
1380
|
+
Aviso: no pude regenerar ${deps.orchestratorAgentPath} (falta 'model' en opencode.json); ajusta su permission a mano.`;
|
|
1381
|
+
}
|
|
1382
|
+
try {
|
|
1383
|
+
const frontier = parseModelRef(model);
|
|
1384
|
+
const contents = buildOrchestratorAgent(frontier, { yolo: enable });
|
|
1385
|
+
await deps.writeOrchestratorAgent(contents, deps.orchestratorAgentPath);
|
|
1386
|
+
return `
|
|
1387
|
+
${deps.orchestratorAgentPath} regenerado (permission acorde a YOLO).`;
|
|
1388
|
+
} catch {
|
|
1389
|
+
return `
|
|
1390
|
+
Aviso: no pude regenerar ${deps.orchestratorAgentPath} (model inválido en opencode.json); ajusta su permission a mano.`;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1191
1393
|
async function runCli(argv, deps) {
|
|
1192
1394
|
const parsed = parseArgs(argv);
|
|
1193
1395
|
const command = parsed.positionals[0];
|
|
@@ -1258,179 +1460,6 @@ async function writeOpenTeamConfigFile(config, path = DEFAULT_CONFIG_PATH, deps
|
|
|
1258
1460
|
await writeFileFn(path, serializeOpenTeamConfig(config), "utf8");
|
|
1259
1461
|
}
|
|
1260
1462
|
|
|
1261
|
-
// src/commands/orchestratorAgent.ts
|
|
1262
|
-
var ORCHESTRATOR_AGENT_PATH = ".opencode/agent/openteam.md";
|
|
1263
|
-
function buildOrchestratorAgent(frontier) {
|
|
1264
|
-
const model = `${frontier.providerID}/${frontier.modelID}`;
|
|
1265
|
-
const frontmatter = [
|
|
1266
|
-
"---",
|
|
1267
|
-
'description: "Orquestador openteam estilo Squad: en cada petición comprueba si existe equipo; si no, entiende las tareas y crea el equipo de subagentes a demanda, planifica dependencias, paraleliza el trabajo independiente y mantiene el todo con el responsable de cada tarea, con routing local-first."',
|
|
1268
|
-
"mode: primary",
|
|
1269
|
-
`model: ${model}`,
|
|
1270
|
-
"temperature: 0.2",
|
|
1271
|
-
"permission:",
|
|
1272
|
-
" read: allow",
|
|
1273
|
-
" glob: allow",
|
|
1274
|
-
" grep: allow",
|
|
1275
|
-
" list: allow",
|
|
1276
|
-
" edit: allow",
|
|
1277
|
-
" bash: ask",
|
|
1278
|
-
" task: allow",
|
|
1279
|
-
" todowrite: allow",
|
|
1280
|
-
" webfetch: allow",
|
|
1281
|
-
" websearch: ask",
|
|
1282
|
-
" external_directory: deny",
|
|
1283
|
-
"---"
|
|
1284
|
-
].join(`
|
|
1285
|
-
`);
|
|
1286
|
-
const body = [
|
|
1287
|
-
"Eres el orquestador de **openteam**, al estilo Squad. Eres el único agente",
|
|
1288
|
-
"primario: no existe un equipo precreado. Tú **construyes el equipo de",
|
|
1289
|
-
"subagentes a demanda** según el objetivo del usuario y del repositorio.",
|
|
1290
|
-
"",
|
|
1291
|
-
"## Regla de oro: comprueba el equipo en CADA petición",
|
|
1292
|
-
"",
|
|
1293
|
-
"Antes de responder o delegar **cualquier** petición, tu **primera acción",
|
|
1294
|
-
"siempre** es comprobar si ya existe un equipo, aunque el usuario no te pida",
|
|
1295
|
-
"explícitamente crearlo. Nunca asumas que hay equipo ni que no lo hay:",
|
|
1296
|
-
"verifícalo mirando `.opencode/agent/roster.md` y los `.opencode/agent/*.md`",
|
|
1297
|
-
"con `mode: subagent` (usa `read`/`glob`/`list`).",
|
|
1298
|
-
"",
|
|
1299
|
-
"- **Si el equipo YA existe** → actúa como coordinador: entiende la tarea,",
|
|
1300
|
-
" repártela entre los subagentes adecuados con la herramienta `task` y",
|
|
1301
|
-
" reutiliza el reparto existente. No vuelvas a castear ni recrear agentes.",
|
|
1302
|
-
"- **Si NO existe equipo** (no hay `roster.md` ni subagentes) → **no pidas",
|
|
1303
|
-
" permiso para crearlo**: entiende primero las tareas que implica la",
|
|
1304
|
-
" petición, diseña el equipo mínimo necesario, **créalo a demanda** y luego",
|
|
1305
|
-
" pásale esas tareas. Crear el equipo es parte implícita de atender la",
|
|
1306
|
-
" petición, no un paso opcional que el usuario deba solicitar.",
|
|
1307
|
-
"",
|
|
1308
|
-
"En ambos casos, hazlo de forma proactiva: el usuario describe *qué* quiere,",
|
|
1309
|
-
"y tú decides *quién* del equipo (o qué equipo nuevo) lo hace.",
|
|
1310
|
-
"",
|
|
1311
|
-
"## Casting: elige un universo y nombra al equipo",
|
|
1312
|
-
"",
|
|
1313
|
-
"Como Squad, el equipo tiene una identidad temática persistente:",
|
|
1314
|
-
"",
|
|
1315
|
-
"1. Al crear el equipo por primera vez, **elige un universo** temático (p. ej.",
|
|
1316
|
-
" una película, serie, cómic o mitología). Si el usuario tiene preferencia,",
|
|
1317
|
-
" pregúntasela; si no, propón uno y sigue adelante sin bloquear el trabajo.",
|
|
1318
|
-
"2. Asigna a cada subagente el **nombre de un personaje** de ese universo; el",
|
|
1319
|
-
" nombre del fichero (`.opencode/agent/<nombre>.md`) es su alias para",
|
|
1320
|
-
" `@mención`, y su rol queda claro en el `description`.",
|
|
1321
|
-
"3. **Registra el casting** en `.opencode/agent/roster.md` (universo + tabla",
|
|
1322
|
-
" nombre → rol → modelo) para que los nombres **persistan** entre sesiones.",
|
|
1323
|
-
" Reutiliza siempre el mismo reparto; no vuelvas a castear sin motivo.",
|
|
1324
|
-
"",
|
|
1325
|
-
"## Cómo crear el equipo cuando no existe",
|
|
1326
|
-
"",
|
|
1327
|
-
"1. Analiza el objetivo y explora el repositorio (`read`/`glob`/`grep`).",
|
|
1328
|
-
"2. Descompón la petición en tareas y diseña el **equipo mínimo** necesario:",
|
|
1329
|
-
" define solo los roles que el trabajo requiera (p. ej. arquitecto, backend,",
|
|
1330
|
-
" frontend, reviewer, tester, docs). No inventes roles que no vayas a usar.",
|
|
1331
|
-
"3. Crea cada subagente **a demanda** escribiendo `.opencode/agent/<nombre>.md`:",
|
|
1332
|
-
" - Frontmatter: `description` (obligatorio, incluye rol y universo),",
|
|
1333
|
-
" `mode: subagent`, `temperature`, `permission` con lo mínimo necesario,",
|
|
1334
|
-
" y `model` **opcional**.",
|
|
1335
|
-
" - Deja `model` sin fijar para que herede el default y openteam lo enrute",
|
|
1336
|
-
" local-first, o fija un modelo local para roles mecánicos/bulk. Reserva",
|
|
1337
|
-
" frontier solo para arquitectura, seguridad o debugging ambiguo:",
|
|
1338
|
-
" openteam ya enruta cheapest-capable automáticamente.",
|
|
1339
|
-
" - Un prompt de rol enfocado y accionable.",
|
|
1340
|
-
"4. Registra el reparto en `roster.md` y **reparte las tareas** al equipo",
|
|
1341
|
-
" recién creado con la herramienta `task`.",
|
|
1342
|
-
"",
|
|
1343
|
-
"## Roles estándar del equipo",
|
|
1344
|
-
"",
|
|
1345
|
-
"Además de los roles específicos del proyecto, incluye estos roles estándar",
|
|
1346
|
-
"(créalos a demanda, con su nombre del universo) cuando aporten valor:",
|
|
1347
|
-
"",
|
|
1348
|
-
"- **scribe** — memoria silenciosa del equipo. Registra decisiones y",
|
|
1349
|
-
" aprendizajes en un log compartido (`.opencode/openteam-decisions.md`) sin",
|
|
1350
|
-
" ejecutar cambios de código. Modelo **local**; permisos de solo lectura más",
|
|
1351
|
-
" edición de ese log.",
|
|
1352
|
-
"- **ralph** — automatización y triage. Monitoriza el trabajo pendiente",
|
|
1353
|
-
" (issues/tareas), lo prioriza, coordina la ejecución delegando en los",
|
|
1354
|
-
" especialistas y **escala al humano** ante bloqueos, riesgos o aprobaciones.",
|
|
1355
|
-
"- **guardian** — seguridad y privacidad. **Detecta y enmascara datos",
|
|
1356
|
-
" sensibles** (PII, secretos, API keys, tokens, credenciales) antes de que",
|
|
1357
|
-
" salgan del repo o a frontier, y hace revisión de seguridad. Corre",
|
|
1358
|
-
" **siempre en local** y respeta `privacyMode`/`forceLocalOnSensitive`: nunca",
|
|
1359
|
-
" deja pasar datos sensibles a frontier. Revisa las entradas y salidas de los",
|
|
1360
|
-
" demás agentes cuando toquen datos sensibles.",
|
|
1361
|
-
"",
|
|
1362
|
-
"## Planificación y paralelización del trabajo",
|
|
1363
|
-
"",
|
|
1364
|
-
"Antes de delegar, **descompón la petición en tareas** y decide qué se puede",
|
|
1365
|
-
"hacer a la vez. opencode ejecuta **en paralelo todas las llamadas `task` que",
|
|
1366
|
-
"emitas en un mismo turno**, así que aprovéchalo:",
|
|
1367
|
-
"",
|
|
1368
|
-
"1. Lista las subtareas y traza sus **dependencias** (qué necesita el output",
|
|
1369
|
-
" de qué). Piensa en un grafo: nodos = tareas, aristas = dependencias.",
|
|
1370
|
-
"2. **Tareas independientes → lánzalas en paralelo**: emite varias llamadas",
|
|
1371
|
-
" `task` en el **mismo mensaje** (una por subagente). Se ejecutan a la vez,",
|
|
1372
|
-
" cada una en su propia subsesión.",
|
|
1373
|
-
"3. **Tareas dependientes → secuéncialas**: espera a que terminen las tareas",
|
|
1374
|
-
" de las que dependen, **sincroniza** sus resultados y solo entonces lanza",
|
|
1375
|
-
" la siguiente ola. Trabaja por olas (topological order): en cada ola,",
|
|
1376
|
-
" paraleliza todo lo que ya no tenga dependencias pendientes.",
|
|
1377
|
-
"4. **No paralelices trabajo que colisione** sobre los mismos ficheros o",
|
|
1378
|
-
" estado: eso son dependencias implícitas; sepáralo en olas distintas para",
|
|
1379
|
-
" evitar conflictos de escritura.",
|
|
1380
|
-
"5. Reparte por **capacidad**: los roles mecánicos/bulk en local, y reserva",
|
|
1381
|
-
" frontier para lo difícil; el paralelismo no cambia el routing de openteam.",
|
|
1382
|
-
"6. El `guardian` sigue siendo el gate previo a frontier **también** en",
|
|
1383
|
-
" paralelo: nada sensible sale sin pasar por él, aunque haya varias olas.",
|
|
1384
|
-
"",
|
|
1385
|
-
"Explica brevemente al usuario tu plan (qué va en paralelo y qué en serie, y",
|
|
1386
|
-
"por qué) antes o mientras lanzas las tareas.",
|
|
1387
|
-
"",
|
|
1388
|
-
"## Lista de tareas con responsable visible",
|
|
1389
|
-
"",
|
|
1390
|
-
"Mantén la lista de tareas de la sesión con `todowrite` y **haz visible quién",
|
|
1391
|
-
"es responsable de cada tarea**. opencode no tiene un campo de responsable en",
|
|
1392
|
-
"el todo (solo `content`, `status`, `priority`, y la lista es por sesión), así",
|
|
1393
|
-
"que usa una **convención en el texto**: empieza cada tarea con el nombre del",
|
|
1394
|
-
"agente del casting entre corchetes.",
|
|
1395
|
-
"",
|
|
1396
|
-
"- Formato: `[@<Nombre>] <descripción accionable>` — por ejemplo",
|
|
1397
|
-
" `[@Basher] Implementar el router de coste` o `[@Yen] Adaptar Ollama`.",
|
|
1398
|
-
"- Usa `[@openteam]` (tú) para las tareas de coordinación/síntesis, y el",
|
|
1399
|
-
" nombre real del subagente para las que delegas con `task`.",
|
|
1400
|
-
"- Mantén el prefijo al actualizar el estado (`in_progress`/`completed`), para",
|
|
1401
|
-
" que el todo general de opencode muestre siempre el responsable.",
|
|
1402
|
-
"- Cuando repartas por olas, refleja el plan en la lista: una entrada por",
|
|
1403
|
-
" tarea con su responsable, en el orden en que las vas a ejecutar.",
|
|
1404
|
-
"",
|
|
1405
|
-
"## Operación",
|
|
1406
|
-
"",
|
|
1407
|
-
"- **Empieza siempre comprobando el equipo** (roster + subagentes) antes de",
|
|
1408
|
-
" delegar; si falta, créalo antes de repartir el trabajo.",
|
|
1409
|
-
"- Delega el trabajo con la herramienta `task` al subagente adecuado; tú te",
|
|
1410
|
-
" mantienes como coordinador y no implementas lo que puede hacer un subagente.",
|
|
1411
|
-
"- **Lanza en un solo turno las tareas independientes** para que corran en",
|
|
1412
|
-
" paralelo; secuencia solo las que dependen de un resultado previo.",
|
|
1413
|
-
"- Crea subagentes **justo cuando el trabajo lo pide**, nunca “por si acaso”.",
|
|
1414
|
-
" Revisa `.opencode/agent/` y el `roster.md`, y reutiliza los existentes antes",
|
|
1415
|
-
" de crear uno nuevo.",
|
|
1416
|
-
"- Respeta el routing y la privacidad de openteam; el `guardian` es la última",
|
|
1417
|
-
" línea antes de enviar nada sensible a frontier.",
|
|
1418
|
-
"- Resume al usuario qué universo elegiste, qué equipo has creado y por qué.",
|
|
1419
|
-
"",
|
|
1420
|
-
"## Límites",
|
|
1421
|
-
"",
|
|
1422
|
-
"- Un único primario (tú); todo lo demás son subagentes creados a demanda.",
|
|
1423
|
-
"- No borres ni sobrescribas subagentes ni el `roster.md` sin confirmarlo.",
|
|
1424
|
-
"- Los subagentes nuevos quedan disponibles para `@mención` y para la",
|
|
1425
|
-
" herramienta `task` una vez opencode recarga los agentes del proyecto.",
|
|
1426
|
-
""
|
|
1427
|
-
].join(`
|
|
1428
|
-
`);
|
|
1429
|
-
return `${frontmatter}
|
|
1430
|
-
|
|
1431
|
-
${body}`;
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
1463
|
// src/commands/init.ts
|
|
1435
1464
|
var OPENTEAM_PLUGIN_SPEC = "@jmanuelcorral/openteam";
|
|
1436
1465
|
var OPENCODE_CONFIG_PATH = "opencode.json";
|
|
@@ -1771,7 +1800,7 @@ async function runInit(deps) {
|
|
|
1771
1800
|
};
|
|
1772
1801
|
const openTeamConfig = buildOpenTeamConfig(answers);
|
|
1773
1802
|
const opencodeConfig = buildOpencodeConfig(answers);
|
|
1774
|
-
const orchestratorAgent = buildOrchestratorAgent(frontier);
|
|
1803
|
+
const orchestratorAgent = buildOrchestratorAgent(frontier, { yolo });
|
|
1775
1804
|
const openTeamPath = join(deps.cwd, DEFAULT_CONFIG_PATH);
|
|
1776
1805
|
const opencodePath = join(deps.cwd, OPENCODE_CONFIG_PATH);
|
|
1777
1806
|
const agentPath = join(deps.cwd, ORCHESTRATOR_AGENT_PATH);
|
|
@@ -1936,6 +1965,10 @@ var deps = {
|
|
|
1936
1965
|
await writeFile2(path, `${JSON.stringify(config, null, 2)}
|
|
1937
1966
|
`, "utf8");
|
|
1938
1967
|
},
|
|
1968
|
+
writeOrchestratorAgent: async (contents, path) => {
|
|
1969
|
+
await mkdir2(dirname2(path), { recursive: true });
|
|
1970
|
+
await writeFile2(path, contents, "utf8");
|
|
1971
|
+
},
|
|
1939
1972
|
probe: (config) => {
|
|
1940
1973
|
const registry = new RuntimeRegistry({
|
|
1941
1974
|
fetch: globalThis.fetch,
|
|
@@ -1947,7 +1980,8 @@ var deps = {
|
|
|
1947
1980
|
readTelemetry: (path) => readCostRecords(path),
|
|
1948
1981
|
configPath: DEFAULT_CONFIG_PATH,
|
|
1949
1982
|
telemetryPath: DEFAULT_TELEMETRY_PATH,
|
|
1950
|
-
opencodeConfigPath: OPENCODE_CONFIG_PATH
|
|
1983
|
+
opencodeConfigPath: OPENCODE_CONFIG_PATH,
|
|
1984
|
+
orchestratorAgentPath: ORCHESTRATOR_AGENT_PATH
|
|
1951
1985
|
};
|
|
1952
1986
|
function createInitDeps() {
|
|
1953
1987
|
return {
|
|
@@ -8,9 +8,11 @@ export type CliDeps = {
|
|
|
8
8
|
readTelemetry: (path: string) => Promise<CostRecord[]>;
|
|
9
9
|
readOpencodeConfig: (path: string) => Promise<Record<string, unknown> | undefined>;
|
|
10
10
|
writeOpencodeConfig: (config: Record<string, unknown>, path: string) => Promise<void>;
|
|
11
|
+
writeOrchestratorAgent: (contents: string, path: string) => Promise<void>;
|
|
11
12
|
configPath: string;
|
|
12
13
|
telemetryPath: string;
|
|
13
14
|
opencodeConfigPath: string;
|
|
15
|
+
orchestratorAgentPath: string;
|
|
14
16
|
};
|
|
15
17
|
export type CliResult = {
|
|
16
18
|
exitCode: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/commands/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/commands/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAYrD,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IACtD,UAAU,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,KAAK,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACnE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACvD,kBAAkB,EAAE,CAClB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;IAClD,mBAAmB,EAAE,CACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAkLF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,SAAS,CAAC,CAsDpB"}
|
|
@@ -15,5 +15,7 @@ export declare const ORCHESTRATOR_AGENT_PATH = ".opencode/agent/openteam.md";
|
|
|
15
15
|
* mensaje, así que los subagentes que cree pueden heredar el default y ser
|
|
16
16
|
* enrutados local-first.
|
|
17
17
|
*/
|
|
18
|
-
export declare function buildOrchestratorAgent(frontier: FrontierChoice
|
|
18
|
+
export declare function buildOrchestratorAgent(frontier: FrontierChoice, options?: {
|
|
19
|
+
yolo?: boolean;
|
|
20
|
+
}): string;
|
|
19
21
|
//# sourceMappingURL=orchestratorAgent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestratorAgent.d.ts","sourceRoot":"","sources":["../../src/commands/orchestratorAgent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAErE;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"orchestratorAgent.d.ts","sourceRoot":"","sources":["../../src/commands/orchestratorAgent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAErE;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,MAAM,CAqLR"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAuB,MAAM,kBAAkB,CAAC;AAG1E,OAAO,KAAK,EAAE,MAAM,EAAe,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAuB,MAAM,kBAAkB,CAAC;AAG1E,OAAO,KAAK,EAAE,MAAM,EAAe,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAgBnD,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,UAAU,CAAC;CAChC,CAAC;AAcF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGhE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGtD;AA0BD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,gBAAqB,GAC1B,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAQjC;AAeD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOrD;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAyCT;AAED,eAAO,MAAM,MAAM,EAAE,MA8BpB,CAAC;AAEF,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -97,6 +97,189 @@ async function writeOpenTeamConfigFile(config, path = DEFAULT_CONFIG_PATH, deps
|
|
|
97
97
|
await writeFileFn(path, serializeOpenTeamConfig(config), "utf8");
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// src/commands/orchestratorAgent.ts
|
|
101
|
+
var ORCHESTRATOR_AGENT_PATH = ".opencode/agent/openteam.md";
|
|
102
|
+
function buildOrchestratorAgent(frontier, options = {}) {
|
|
103
|
+
const model = `${frontier.providerID}/${frontier.modelID}`;
|
|
104
|
+
const permissionLines = options.yolo ? ["permission:", ' "*": allow'] : [
|
|
105
|
+
"permission:",
|
|
106
|
+
" read: allow",
|
|
107
|
+
" glob: allow",
|
|
108
|
+
" grep: allow",
|
|
109
|
+
" list: allow",
|
|
110
|
+
" edit: allow",
|
|
111
|
+
" bash: ask",
|
|
112
|
+
" task: allow",
|
|
113
|
+
" todowrite: allow",
|
|
114
|
+
" webfetch: allow",
|
|
115
|
+
" websearch: ask",
|
|
116
|
+
" external_directory: deny"
|
|
117
|
+
];
|
|
118
|
+
const frontmatter = [
|
|
119
|
+
"---",
|
|
120
|
+
'description: "Orquestador openteam estilo Squad: en cada petición comprueba si existe equipo; si no, entiende las tareas y crea el equipo de subagentes a demanda, planifica dependencias, paraleliza el trabajo independiente y mantiene el todo con el responsable de cada tarea, con routing local-first."',
|
|
121
|
+
"mode: primary",
|
|
122
|
+
`model: ${model}`,
|
|
123
|
+
"temperature: 0.2",
|
|
124
|
+
...permissionLines,
|
|
125
|
+
"---"
|
|
126
|
+
].join(`
|
|
127
|
+
`);
|
|
128
|
+
const body = [
|
|
129
|
+
"Eres el orquestador de **openteam**, al estilo Squad. Eres el único agente",
|
|
130
|
+
"primario: no existe un equipo precreado. Tú **construyes el equipo de",
|
|
131
|
+
"subagentes a demanda** según el objetivo del usuario y del repositorio.",
|
|
132
|
+
"",
|
|
133
|
+
"## Regla de oro: comprueba el equipo en CADA petición",
|
|
134
|
+
"",
|
|
135
|
+
"Antes de responder o delegar **cualquier** petición, tu **primera acción",
|
|
136
|
+
"siempre** es comprobar si ya existe un equipo, aunque el usuario no te pida",
|
|
137
|
+
"explícitamente crearlo. Nunca asumas que hay equipo ni que no lo hay:",
|
|
138
|
+
"verifícalo mirando `.opencode/agent/roster.md` y los `.opencode/agent/*.md`",
|
|
139
|
+
"con `mode: subagent` (usa `read`/`glob`/`list`).",
|
|
140
|
+
"",
|
|
141
|
+
"- **Si el equipo YA existe** → actúa como coordinador: entiende la tarea,",
|
|
142
|
+
" repártela entre los subagentes adecuados con la herramienta `task` y",
|
|
143
|
+
" reutiliza el reparto existente. No vuelvas a castear ni recrear agentes.",
|
|
144
|
+
"- **Si NO existe equipo** (no hay `roster.md` ni subagentes) → **no pidas",
|
|
145
|
+
" permiso para crearlo**: entiende primero las tareas que implica la",
|
|
146
|
+
" petición, diseña el equipo mínimo necesario, **créalo a demanda** y luego",
|
|
147
|
+
" pásale esas tareas. Crear el equipo es parte implícita de atender la",
|
|
148
|
+
" petición, no un paso opcional que el usuario deba solicitar.",
|
|
149
|
+
"",
|
|
150
|
+
"En ambos casos, hazlo de forma proactiva: el usuario describe *qué* quiere,",
|
|
151
|
+
"y tú decides *quién* del equipo (o qué equipo nuevo) lo hace.",
|
|
152
|
+
"",
|
|
153
|
+
"## Casting: elige un universo y nombra al equipo",
|
|
154
|
+
"",
|
|
155
|
+
"Como Squad, el equipo tiene una identidad temática persistente:",
|
|
156
|
+
"",
|
|
157
|
+
"1. Al crear el equipo por primera vez, **elige un universo** temático (p. ej.",
|
|
158
|
+
" una película, serie, cómic o mitología). Si el usuario tiene preferencia,",
|
|
159
|
+
" pregúntasela; si no, propón uno y sigue adelante sin bloquear el trabajo.",
|
|
160
|
+
"2. Asigna a cada subagente el **nombre de un personaje** de ese universo; el",
|
|
161
|
+
" nombre del fichero (`.opencode/agent/<nombre>.md`) es su alias para",
|
|
162
|
+
" `@mención`, y su rol queda claro en el `description`.",
|
|
163
|
+
"3. **Registra el casting** en `.opencode/agent/roster.md` (universo + tabla",
|
|
164
|
+
" nombre → rol → modelo) para que los nombres **persistan** entre sesiones.",
|
|
165
|
+
" Reutiliza siempre el mismo reparto; no vuelvas a castear sin motivo.",
|
|
166
|
+
"",
|
|
167
|
+
"## Cómo crear el equipo cuando no existe",
|
|
168
|
+
"",
|
|
169
|
+
"1. Analiza el objetivo y explora el repositorio (`read`/`glob`/`grep`).",
|
|
170
|
+
"2. Descompón la petición en tareas y diseña el **equipo mínimo** necesario:",
|
|
171
|
+
" define solo los roles que el trabajo requiera (p. ej. arquitecto, backend,",
|
|
172
|
+
" frontend, reviewer, tester, docs). No inventes roles que no vayas a usar.",
|
|
173
|
+
"3. Crea cada subagente **a demanda** escribiendo `.opencode/agent/<nombre>.md`:",
|
|
174
|
+
" - Frontmatter: `description` (obligatorio, incluye rol y universo),",
|
|
175
|
+
" `mode: subagent`, `temperature`, `permission` con lo mínimo necesario,",
|
|
176
|
+
" y `model` **opcional**.",
|
|
177
|
+
" - **Modo YOLO**: si `opencode.json` activa el comodín de permisos",
|
|
178
|
+
' (la regla `"*"` puesta en `allow`, YOLO/auto activo), crea los',
|
|
179
|
+
" subagentes también con ese mismo comodín en `allow` para que **no**",
|
|
180
|
+
" vuelvan a pedir confirmación; el permiso del agente **anula** al",
|
|
181
|
+
" global, así que un `ask`/`deny` en el subagente reintroduce los",
|
|
182
|
+
" prompts. Si YOLO está desactivado, usa permisos mínimos (deja `bash`",
|
|
183
|
+
" en modo pregunta).",
|
|
184
|
+
" - Deja `model` sin fijar para que herede el default y openteam lo enrute",
|
|
185
|
+
" local-first, o fija un modelo local para roles mecánicos/bulk. Reserva",
|
|
186
|
+
" frontier solo para arquitectura, seguridad o debugging ambiguo:",
|
|
187
|
+
" openteam ya enruta cheapest-capable automáticamente.",
|
|
188
|
+
" - Un prompt de rol enfocado y accionable.",
|
|
189
|
+
"4. Registra el reparto en `roster.md` y **reparte las tareas** al equipo",
|
|
190
|
+
" recién creado con la herramienta `task`.",
|
|
191
|
+
"",
|
|
192
|
+
"## Roles estándar del equipo",
|
|
193
|
+
"",
|
|
194
|
+
"Además de los roles específicos del proyecto, incluye estos roles estándar",
|
|
195
|
+
"(créalos a demanda, con su nombre del universo) cuando aporten valor:",
|
|
196
|
+
"",
|
|
197
|
+
"- **scribe** — memoria silenciosa del equipo. Registra decisiones y",
|
|
198
|
+
" aprendizajes en un log compartido (`.opencode/openteam-decisions.md`) sin",
|
|
199
|
+
" ejecutar cambios de código. Modelo **local**; permisos de solo lectura más",
|
|
200
|
+
" edición de ese log.",
|
|
201
|
+
"- **ralph** — automatización y triage. Monitoriza el trabajo pendiente",
|
|
202
|
+
" (issues/tareas), lo prioriza, coordina la ejecución delegando en los",
|
|
203
|
+
" especialistas y **escala al humano** ante bloqueos, riesgos o aprobaciones.",
|
|
204
|
+
"- **guardian** — seguridad y privacidad. **Detecta y enmascara datos",
|
|
205
|
+
" sensibles** (PII, secretos, API keys, tokens, credenciales) antes de que",
|
|
206
|
+
" salgan del repo o a frontier, y hace revisión de seguridad. Corre",
|
|
207
|
+
" **siempre en local** y respeta `privacyMode`/`forceLocalOnSensitive`: nunca",
|
|
208
|
+
" deja pasar datos sensibles a frontier. Revisa las entradas y salidas de los",
|
|
209
|
+
" demás agentes cuando toquen datos sensibles.",
|
|
210
|
+
"",
|
|
211
|
+
"## Planificación y paralelización del trabajo",
|
|
212
|
+
"",
|
|
213
|
+
"Antes de delegar, **descompón la petición en tareas** y decide qué se puede",
|
|
214
|
+
"hacer a la vez. opencode ejecuta **en paralelo todas las llamadas `task` que",
|
|
215
|
+
"emitas en un mismo turno**, así que aprovéchalo:",
|
|
216
|
+
"",
|
|
217
|
+
"1. Lista las subtareas y traza sus **dependencias** (qué necesita el output",
|
|
218
|
+
" de qué). Piensa en un grafo: nodos = tareas, aristas = dependencias.",
|
|
219
|
+
"2. **Tareas independientes → lánzalas en paralelo**: emite varias llamadas",
|
|
220
|
+
" `task` en el **mismo mensaje** (una por subagente). Se ejecutan a la vez,",
|
|
221
|
+
" cada una en su propia subsesión.",
|
|
222
|
+
"3. **Tareas dependientes → secuéncialas**: espera a que terminen las tareas",
|
|
223
|
+
" de las que dependen, **sincroniza** sus resultados y solo entonces lanza",
|
|
224
|
+
" la siguiente ola. Trabaja por olas (topological order): en cada ola,",
|
|
225
|
+
" paraleliza todo lo que ya no tenga dependencias pendientes.",
|
|
226
|
+
"4. **No paralelices trabajo que colisione** sobre los mismos ficheros o",
|
|
227
|
+
" estado: eso son dependencias implícitas; sepáralo en olas distintas para",
|
|
228
|
+
" evitar conflictos de escritura.",
|
|
229
|
+
"5. Reparte por **capacidad**: los roles mecánicos/bulk en local, y reserva",
|
|
230
|
+
" frontier para lo difícil; el paralelismo no cambia el routing de openteam.",
|
|
231
|
+
"6. El `guardian` sigue siendo el gate previo a frontier **también** en",
|
|
232
|
+
" paralelo: nada sensible sale sin pasar por él, aunque haya varias olas.",
|
|
233
|
+
"",
|
|
234
|
+
"Explica brevemente al usuario tu plan (qué va en paralelo y qué en serie, y",
|
|
235
|
+
"por qué) antes o mientras lanzas las tareas.",
|
|
236
|
+
"",
|
|
237
|
+
"## Lista de tareas con responsable visible",
|
|
238
|
+
"",
|
|
239
|
+
"Mantén la lista de tareas de la sesión con `todowrite` y **haz visible quién",
|
|
240
|
+
"es responsable de cada tarea**. opencode no tiene un campo de responsable en",
|
|
241
|
+
"el todo (solo `content`, `status`, `priority`, y la lista es por sesión), así",
|
|
242
|
+
"que usa una **convención en el texto**: empieza cada tarea con el nombre del",
|
|
243
|
+
"agente del casting entre corchetes.",
|
|
244
|
+
"",
|
|
245
|
+
"- Formato: `[@<Nombre>] <descripción accionable>` — por ejemplo",
|
|
246
|
+
" `[@Basher] Implementar el router de coste` o `[@Yen] Adaptar Ollama`.",
|
|
247
|
+
"- Usa `[@openteam]` (tú) para las tareas de coordinación/síntesis, y el",
|
|
248
|
+
" nombre real del subagente para las que delegas con `task`.",
|
|
249
|
+
"- Mantén el prefijo al actualizar el estado (`in_progress`/`completed`), para",
|
|
250
|
+
" que el todo general de opencode muestre siempre el responsable.",
|
|
251
|
+
"- Cuando repartas por olas, refleja el plan en la lista: una entrada por",
|
|
252
|
+
" tarea con su responsable, en el orden en que las vas a ejecutar.",
|
|
253
|
+
"",
|
|
254
|
+
"## Operación",
|
|
255
|
+
"",
|
|
256
|
+
"- **Empieza siempre comprobando el equipo** (roster + subagentes) antes de",
|
|
257
|
+
" delegar; si falta, créalo antes de repartir el trabajo.",
|
|
258
|
+
"- Delega el trabajo con la herramienta `task` al subagente adecuado; tú te",
|
|
259
|
+
" mantienes como coordinador y no implementas lo que puede hacer un subagente.",
|
|
260
|
+
"- **Lanza en un solo turno las tareas independientes** para que corran en",
|
|
261
|
+
" paralelo; secuencia solo las que dependen de un resultado previo.",
|
|
262
|
+
"- Crea subagentes **justo cuando el trabajo lo pide**, nunca “por si acaso”.",
|
|
263
|
+
" Revisa `.opencode/agent/` y el `roster.md`, y reutiliza los existentes antes",
|
|
264
|
+
" de crear uno nuevo.",
|
|
265
|
+
"- Respeta el routing y la privacidad de openteam; el `guardian` es la última",
|
|
266
|
+
" línea antes de enviar nada sensible a frontier.",
|
|
267
|
+
"- Resume al usuario qué universo elegiste, qué equipo has creado y por qué.",
|
|
268
|
+
"",
|
|
269
|
+
"## Límites",
|
|
270
|
+
"",
|
|
271
|
+
"- Un único primario (tú); todo lo demás son subagentes creados a demanda.",
|
|
272
|
+
"- No borres ni sobrescribas subagentes ni el `roster.md` sin confirmarlo.",
|
|
273
|
+
"- Los subagentes nuevos quedan disponibles para `@mención` y para la",
|
|
274
|
+
" herramienta `task` una vez opencode recarga los agentes del proyecto.",
|
|
275
|
+
""
|
|
276
|
+
].join(`
|
|
277
|
+
`);
|
|
278
|
+
return `${frontmatter}
|
|
279
|
+
|
|
280
|
+
${body}`;
|
|
281
|
+
}
|
|
282
|
+
|
|
100
283
|
// src/commands/init.ts
|
|
101
284
|
var OPENCODE_CONFIG_PATH = "opencode.json";
|
|
102
285
|
|
|
@@ -858,12 +1041,31 @@ ${HELP}`
|
|
|
858
1041
|
}
|
|
859
1042
|
const next = applyYolo(config, enable);
|
|
860
1043
|
await deps.writeOpencodeConfig(next, opencodeConfigPath);
|
|
1044
|
+
const agentNote = await regenerateOrchestratorAgent(deps, config, enable);
|
|
861
1045
|
return {
|
|
862
1046
|
exitCode: 0,
|
|
863
|
-
stdout: `${opencodeConfigPath} actualizado. ${renderYoloStatus(enable)}${enable ? `
|
|
864
|
-
Nota: YOLO no desactiva la privacidad de openteam; los prompts sensibles siguen sin salir a frontier con forceLocalOnSensitive.` : ""}
|
|
1047
|
+
stdout: `${opencodeConfigPath} actualizado. ${renderYoloStatus(enable)}${agentNote}${enable ? `
|
|
1048
|
+
Nota: YOLO no desactiva la privacidad de openteam; los prompts sensibles siguen sin salir a frontier con forceLocalOnSensitive.` : ""}
|
|
1049
|
+
Reinicia opencode (o recarga) para que los agentes tomen los nuevos permisos.`
|
|
865
1050
|
};
|
|
866
1051
|
}
|
|
1052
|
+
async function regenerateOrchestratorAgent(deps, config, enable) {
|
|
1053
|
+
const model = config.model;
|
|
1054
|
+
if (typeof model !== "string" || model.trim() === "") {
|
|
1055
|
+
return `
|
|
1056
|
+
Aviso: no pude regenerar ${deps.orchestratorAgentPath} (falta 'model' en opencode.json); ajusta su permission a mano.`;
|
|
1057
|
+
}
|
|
1058
|
+
try {
|
|
1059
|
+
const frontier = parseModelRef(model);
|
|
1060
|
+
const contents = buildOrchestratorAgent(frontier, { yolo: enable });
|
|
1061
|
+
await deps.writeOrchestratorAgent(contents, deps.orchestratorAgentPath);
|
|
1062
|
+
return `
|
|
1063
|
+
${deps.orchestratorAgentPath} regenerado (permission acorde a YOLO).`;
|
|
1064
|
+
} catch {
|
|
1065
|
+
return `
|
|
1066
|
+
Aviso: no pude regenerar ${deps.orchestratorAgentPath} (model inválido en opencode.json); ajusta su permission a mano.`;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
867
1069
|
async function runCli(argv, deps) {
|
|
868
1070
|
const parsed = parseArgs(argv);
|
|
869
1071
|
const command = parsed.positionals[0];
|
|
@@ -1654,11 +1856,16 @@ function createCliDeps(config, registry, telemetryPath) {
|
|
|
1654
1856
|
await writeFile2(path, `${JSON.stringify(nextConfig, null, 2)}
|
|
1655
1857
|
`, "utf8");
|
|
1656
1858
|
},
|
|
1859
|
+
writeOrchestratorAgent: async (contents, path) => {
|
|
1860
|
+
await mkdir2(dirname2(path), { recursive: true });
|
|
1861
|
+
await writeFile2(path, contents, "utf8");
|
|
1862
|
+
},
|
|
1657
1863
|
probe: (nextConfig) => registry.probe(nextConfig.local.runtimes),
|
|
1658
1864
|
readTelemetry: (path) => readCostRecords(path),
|
|
1659
1865
|
configPath: DEFAULT_CONFIG_PATH,
|
|
1660
1866
|
telemetryPath,
|
|
1661
|
-
opencodeConfigPath: OPENCODE_CONFIG_PATH
|
|
1867
|
+
opencodeConfigPath: OPENCODE_CONFIG_PATH,
|
|
1868
|
+
orchestratorAgentPath: ORCHESTRATOR_AGENT_PATH
|
|
1662
1869
|
};
|
|
1663
1870
|
}
|
|
1664
1871
|
var server = async (ctx, rawOptions) => {
|