@liriraid/agentflow-ai 1.0.26 → 1.0.28
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/bin/agentflow.mjs +0 -0
- package/orchestrator.js +10 -82
- package/package.json +64 -65
- package/templates/en/.claude/skills/orchestrator-explore/SKILL.md +1 -1
- package/templates/en/ORCHESTRATOR.md +7 -5
- package/templates/es/.claude/skills/orchestrator-explore/SKILL.md +1 -1
- package/templates/es/ORCHESTRATOR.md +8 -6
package/bin/agentflow.mjs
CHANGED
|
File without changes
|
package/orchestrator.js
CHANGED
|
@@ -1013,35 +1013,6 @@ function parseCompletedFromFile() {
|
|
|
1013
1013
|
}
|
|
1014
1014
|
|
|
1015
1015
|
const loggedUnknownAgents = new Set();
|
|
1016
|
-
let queueWatcher = null;
|
|
1017
|
-
|
|
1018
|
-
function setupQueueWatcher() {
|
|
1019
|
-
if (!fs.existsSync(QUEUE_FILE)) return;
|
|
1020
|
-
|
|
1021
|
-
if (queueWatcher) {
|
|
1022
|
-
try { queueWatcher.close(); } catch {}
|
|
1023
|
-
queueWatcher = null;
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
try {
|
|
1027
|
-
queueWatcher = fs.watch(QUEUE_FILE, { persistent: false }, (eventType, filename) => {
|
|
1028
|
-
if (eventType === 'change' && filename === path.basename(QUEUE_FILE)) {
|
|
1029
|
-
log('DEBUG', `QUEUE.md changed, reloading queue immediately`);
|
|
1030
|
-
reloadQueue();
|
|
1031
|
-
scheduleNext();
|
|
1032
|
-
renderDashboard();
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1035
|
-
queueWatcher.on('error', (err) => {
|
|
1036
|
-
log('WARN', `fs.watch failed for QUEUE.md: ${err.message}, falling back to polling`);
|
|
1037
|
-
queueWatcher = null;
|
|
1038
|
-
});
|
|
1039
|
-
log('INFO', 'Realtime QUEUE.md watcher enabled');
|
|
1040
|
-
} catch (err) {
|
|
1041
|
-
log('WARN', `Failed to setup QUEUE.md watcher: ${err.message}, using polling`);
|
|
1042
|
-
queueWatcher = null;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
1016
|
|
|
1046
1017
|
function reloadQueue() {
|
|
1047
1018
|
state.queue = parseQueue();
|
|
@@ -1183,16 +1154,8 @@ function generateBrief(task) {
|
|
|
1183
1154
|
if (taskMatch) taskEntry = taskMatch[0];
|
|
1184
1155
|
}
|
|
1185
1156
|
|
|
1186
|
-
//
|
|
1187
|
-
//
|
|
1188
|
-
let globalStandards = "";
|
|
1189
|
-
const globalClaude = path.join(GLOBAL_CLAUDE_DIR, "CLAUDE.md");
|
|
1190
|
-
if (fs.existsSync(globalClaude)) {
|
|
1191
|
-
globalStandards = fs.readFileSync(globalClaude, "utf-8").trim();
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
// Project plan — if `<projectName>-plan.md` or `PLAN.md` exists in the workspace,
|
|
1195
|
-
// inject it as shared context so every agent sees the big-picture plan.
|
|
1157
|
+
// Project plan — only inject the first 60 lines as orientation context.
|
|
1158
|
+
// Worker agents don't need the full plan to execute a single task.
|
|
1196
1159
|
let projectPlan = "";
|
|
1197
1160
|
const planCandidates = [
|
|
1198
1161
|
path.join(
|
|
@@ -1204,7 +1167,9 @@ function generateBrief(task) {
|
|
|
1204
1167
|
];
|
|
1205
1168
|
for (const p of planCandidates) {
|
|
1206
1169
|
if (fs.existsSync(p)) {
|
|
1207
|
-
|
|
1170
|
+
const lines = fs.readFileSync(p, "utf-8").split("\n");
|
|
1171
|
+
projectPlan = lines.slice(0, 60).join("\n");
|
|
1172
|
+
if (lines.length > 60) projectPlan += "\n\n[Plan truncated — full plan in PLAN.md]";
|
|
1208
1173
|
break;
|
|
1209
1174
|
}
|
|
1210
1175
|
}
|
|
@@ -1230,10 +1195,8 @@ function generateBrief(task) {
|
|
|
1230
1195
|
# Priority: ${task.priority}
|
|
1231
1196
|
# Workspace: ${WORKSPACE}
|
|
1232
1197
|
# Progress file: ${progressFile}
|
|
1233
|
-
# Global supply chain: ${GLOBAL_CLAUDE_DIR}
|
|
1234
1198
|
|
|
1235
|
-
${
|
|
1236
|
-
${projectPlan ? `## Project Plan (big picture — use as context, don't try to do everything)\n${projectPlan}\n` : ""}
|
|
1199
|
+
${projectPlan ? `## Project Plan (orientation only — focus on your task)\n${projectPlan}\n` : ""}
|
|
1237
1200
|
${agentInstructions ? `## Agent Instructions\n${agentInstructions}` : ""}
|
|
1238
1201
|
${protocolRules ? `## Protocol Rules\n${protocolRules}` : ""}
|
|
1239
1202
|
|
|
@@ -1444,7 +1407,7 @@ function launchAgent(task) {
|
|
|
1444
1407
|
if (txt) {
|
|
1445
1408
|
for (const l of txt.split("\n").slice(-3))
|
|
1446
1409
|
appendToAgent(agentName, l.slice(0, 120));
|
|
1447
|
-
ag.lastLine = txt.split("\n").pop().slice(0, 80);
|
|
1410
|
+
ag.lastLine = (txt.split("\n").pop() || "").slice(0, 80);
|
|
1448
1411
|
}
|
|
1449
1412
|
}
|
|
1450
1413
|
if (block.type === "tool_use") {
|
|
@@ -1708,6 +1671,7 @@ function failTask(task, agentName, code) {
|
|
|
1708
1671
|
task.status = "failed";
|
|
1709
1672
|
ag.lastLine = L.lastFailed(task.id);
|
|
1710
1673
|
log("ERROR", L.logPermanentFail(task.id, retries));
|
|
1674
|
+
updateQueueFile(task);
|
|
1711
1675
|
writeNotifyFile(L.notifyPermanentFail(timestamp(), task.id, agentName));
|
|
1712
1676
|
} else {
|
|
1713
1677
|
task.status = "pending";
|
|
@@ -1893,6 +1857,7 @@ function getClaudeFallbackAgent(task) {
|
|
|
1893
1857
|
|
|
1894
1858
|
function getAlternativeSupportAgent(failedAgentName) {
|
|
1895
1859
|
if (failedAgentName === "OpenCode") return "Codex";
|
|
1860
|
+
if (failedAgentName === "Codex") return "OpenCode";
|
|
1896
1861
|
return null;
|
|
1897
1862
|
}
|
|
1898
1863
|
|
|
@@ -1930,45 +1895,9 @@ function tryFallbackToAlternative(task, failedAgentName, reason) {
|
|
|
1930
1895
|
log("WARN", L.logReassignWarn(task.id, targetAgent));
|
|
1931
1896
|
}
|
|
1932
1897
|
|
|
1933
|
-
// Notificar a Claude (sesión principal) cuando hay fallback
|
|
1934
|
-
notifyClaudeOfFallback(task, failedAgentName, targetAgent, reason);
|
|
1935
1898
|
return true;
|
|
1936
1899
|
}
|
|
1937
1900
|
|
|
1938
|
-
// ============================================================================
|
|
1939
|
-
// CLAUDE FALLBACK NOTIFIER — avisa a Claude principal cuando hay reasignación
|
|
1940
|
-
// ============================================================================
|
|
1941
|
-
function notifyClaudeOfFallback(task, fromAgent, toAgent, reason) {
|
|
1942
|
-
const lang = WORKSPACE_LANGUAGE;
|
|
1943
|
-
const prompt = lang === 'es'
|
|
1944
|
-
? `⚠️ FALLBACK: La tarea "${task.id}: ${task.title}" falló en ${fromAgent} (${reason}) y fue reasignada a ${toAgent}.
|
|
1945
|
-
|
|
1946
|
-
Estado actual:
|
|
1947
|
-
- QUEUE.md tiene ahora la tarea asignada a ${toAgent}
|
|
1948
|
-
- El agente ${toAgent} está procediendo automáticamente
|
|
1949
|
-
|
|
1950
|
-
Acción: No necesitas hacer nada — solo toma nota del cambio. El orquestador将继续 automáticamente.
|
|
1951
|
-
Si quieres revisar el progreso, lee INBOX.md o STATUS.md.`
|
|
1952
|
-
: `⚠️ FALLBACK: Task "${task.id}: ${task.title}" failed on ${fromAgent} (${reason}) and was reassigned to ${toAgent}.
|
|
1953
|
-
|
|
1954
|
-
Current state:
|
|
1955
|
-
- QUEUE.md now has the task assigned to ${toAgent}
|
|
1956
|
-
- Agent ${toAgent} is proceeding automatically
|
|
1957
|
-
|
|
1958
|
-
Action: You don't need to do anything — just take note of the change. The orchestrator will continue automatically.
|
|
1959
|
-
If you want to check progress, read INBOX.md or STATUS.md.`;
|
|
1960
|
-
|
|
1961
|
-
const logPath = path.join(LOG_DIR, `fallback-notify-${Date.now()}.log`);
|
|
1962
|
-
try {
|
|
1963
|
-
const logFd = fs.openSync(logPath, 'a');
|
|
1964
|
-
const child = spawn('claude', ['-p', prompt, '--add-dir', WORKSPACE, '--dangerously-skip-permissions'], {
|
|
1965
|
-
cwd: WORKSPACE, stdio: ['ignore', logFd, logFd], shell: true, windowsHide: true, detached: true
|
|
1966
|
-
});
|
|
1967
|
-
fs.closeSync(logFd);
|
|
1968
|
-
child.unref();
|
|
1969
|
-
} catch {}
|
|
1970
|
-
}
|
|
1971
|
-
|
|
1972
1901
|
// ============================================================================
|
|
1973
1902
|
// KEYBOARD
|
|
1974
1903
|
// ============================================================================
|
|
@@ -2073,7 +2002,6 @@ function setupFallbackQueueWatcher() {
|
|
|
2073
2002
|
}
|
|
2074
2003
|
|
|
2075
2004
|
startQueueWatcher();
|
|
2076
|
-
setupQueueWatcher();
|
|
2077
2005
|
|
|
2078
2006
|
// Slow fallback (5 min) — only runs if there is actually pending work or busy agents
|
|
2079
2007
|
// fs.watch handles real-time; this is just a safety net
|
|
@@ -2112,7 +2040,7 @@ function runAwayModeCheck() {
|
|
|
2112
2040
|
const completedCount = (state.completed || []).length;
|
|
2113
2041
|
const hasWork = pendingTasks.length > 0 || inProgressTasks.length > 0 || busy;
|
|
2114
2042
|
|
|
2115
|
-
if (!hasWork
|
|
2043
|
+
if (!hasWork) {
|
|
2116
2044
|
try { fs.unlinkSync(AWAY_MODE_FILE); } catch {}
|
|
2117
2045
|
deactivateAwayMode();
|
|
2118
2046
|
|
package/package.json
CHANGED
|
@@ -1,65 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@liriraid/agentflow-ai",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Multi-agent workspace orchestrator with TUI. Coordinates AI coding agents over your real frontend and backend projects.",
|
|
5
|
-
"author": "LiriRaid",
|
|
6
|
-
"homepage": "https://github.com/LiriRaid/agentflow-ai#readme",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/LiriRaid/agentflow-ai.git"
|
|
10
|
-
},
|
|
11
|
-
"bugs": {
|
|
12
|
-
"url": "https://github.com/LiriRaid/agentflow-ai/issues"
|
|
13
|
-
},
|
|
14
|
-
"publishConfig": {
|
|
15
|
-
"access": "public"
|
|
16
|
-
},
|
|
17
|
-
"main": "orchestrator.js",
|
|
18
|
-
"bin": {
|
|
19
|
-
"agentflow": "bin/agentflow.mjs"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"bin",
|
|
23
|
-
"src",
|
|
24
|
-
"templates",
|
|
25
|
-
"orchestrator.js",
|
|
26
|
-
"LICENSE",
|
|
27
|
-
"README.md"
|
|
28
|
-
],
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@liriraid/agentflow-ai",
|
|
3
|
+
"version": "1.0.28",
|
|
4
|
+
"description": "Multi-agent workspace orchestrator with TUI. Coordinates AI coding agents over your real frontend and backend projects.",
|
|
5
|
+
"author": "LiriRaid",
|
|
6
|
+
"homepage": "https://github.com/LiriRaid/agentflow-ai#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/LiriRaid/agentflow-ai.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/LiriRaid/agentflow-ai/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"main": "orchestrator.js",
|
|
18
|
+
"bin": {
|
|
19
|
+
"agentflow": "bin/agentflow.mjs"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"bin",
|
|
23
|
+
"src",
|
|
24
|
+
"templates",
|
|
25
|
+
"orchestrator.js",
|
|
26
|
+
"LICENSE",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"ai",
|
|
34
|
+
"agents",
|
|
35
|
+
"orchestrator",
|
|
36
|
+
"agentflow-ai",
|
|
37
|
+
"claude",
|
|
38
|
+
"codex",
|
|
39
|
+
"gemini",
|
|
40
|
+
"cursor",
|
|
41
|
+
"opencode",
|
|
42
|
+
"abacus",
|
|
43
|
+
"tui",
|
|
44
|
+
"multi-agent",
|
|
45
|
+
"coding-assistant",
|
|
46
|
+
"openspec",
|
|
47
|
+
"engram",
|
|
48
|
+
"skills",
|
|
49
|
+
"agent-config"
|
|
50
|
+
],
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"blessed": "^0.1.81",
|
|
54
|
+
"ink": "^5.2.1",
|
|
55
|
+
"react": "^18.3.1"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"start": "node orchestrator.js",
|
|
59
|
+
"start:paused": "node orchestrator.js --paused",
|
|
60
|
+
"start:ink": "node src/ink/index.mjs",
|
|
61
|
+
"start:ink:paused": "node src/ink/index.mjs --paused",
|
|
62
|
+
"cli:help": "node bin/agentflow.mjs --help"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -16,7 +16,7 @@ Gather useful context before creating TASKs or OpenSpec artifacts.
|
|
|
16
16
|
|
|
17
17
|
## Critical Rules
|
|
18
18
|
|
|
19
|
-
- Understand the user's exact scope first
|
|
19
|
+
- Understand the user's exact scope first — clarify by asking the user directly, **NOT by reading project files yourself**.
|
|
20
20
|
- Prefer exploration before implementation when context is unclear.
|
|
21
21
|
- Use **ONLY OpenCode** as the exploration agent when deep codebase analysis is needed — its role is **EXCLUSIVELY analysis**, **NEVER implementation**.
|
|
22
22
|
- When delegating exploration to OpenCode, include in the brief exactly what it must report: flows, dependencies, architecture findings, inconsistencies, etc.
|
|
@@ -74,7 +74,7 @@ This directory (`orchestrator-<name>`) exists **only** for work management:
|
|
|
74
74
|
- `logs/` — agent output
|
|
75
75
|
|
|
76
76
|
The real project code lives at the paths defined in `orchestrator.config.json → repos`.
|
|
77
|
-
|
|
77
|
+
**Do NOT read real project code files to understand the project.** If codebase analysis is needed to plan tasks, delegate it to OpenCode via a TASK in `QUEUE.md` — that is what OpenCode is for.
|
|
78
78
|
**Never modify real project files directly** — that is exclusively the workers' job.
|
|
79
79
|
|
|
80
80
|
## Startup Checklist
|
|
@@ -136,14 +136,16 @@ del .away-mode
|
|
|
136
136
|
|
|
137
137
|
## Fallback Policy
|
|
138
138
|
|
|
139
|
-
The TUI handles fallback automatically following
|
|
139
|
+
The TUI handles fallback automatically following these chains:
|
|
140
140
|
|
|
141
|
+
**By failure:**
|
|
141
142
|
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
Codex fails → Frontend (frontend repo) or Backend (backend repo) directly
|
|
143
|
+
OpenCode fails → Codex → Claude-Worker (Frontend/Backend)
|
|
144
|
+
Codex fails → OpenCode → Claude-Worker (Frontend/Backend)
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
+
**By availability (when assigning new tasks):** Claude-Orchestrator should check `STATUS.md` before writing to `QUEUE.md`. If the primary agent for a task is already busy or rate-limited, assign directly to the next available idle agent in the chain rather than queuing behind a busy one.
|
|
148
|
+
|
|
147
149
|
As Orchestrator you do **not** need to manually reassign on failure — the TUI does it. Your role is:
|
|
148
150
|
|
|
149
151
|
1. Check `INBOX.md` or `QUEUE.md` to confirm the fallback ran correctly.
|
|
@@ -17,7 +17,7 @@ Guiar la fase de exploración del orquestador para reunir contexto útil antes d
|
|
|
17
17
|
|
|
18
18
|
## Reglas críticas
|
|
19
19
|
|
|
20
|
-
- Empieza por entender el alcance exacto del pedido del usuario
|
|
20
|
+
- Empieza por entender el alcance exacto del pedido del usuario — acláralo preguntándole directamente, **NO leyendo archivos del proyecto tú mismo**.
|
|
21
21
|
- Si hace falta lectura amplia, prioriza exploración y análisis antes de planear implementación.
|
|
22
22
|
- Usa **SOLO OpenCode** como agente de exploración cuando necesites análisis profundo del codebase — su rol es **EXCLUSIVAMENTE análisis**, **NUNCA implementación**.
|
|
23
23
|
- Al delegar exploración a OpenCode, incluye en el brief exactamente qué debe reportar: flujos, dependencias, hallazgos de arquitectura, inconsistencias, etc.
|
|
@@ -38,7 +38,7 @@ Este directorio (`orchestrator-<nombre>`) existe **únicamente** para gestión d
|
|
|
38
38
|
- `logs/` — salida de los agentes
|
|
39
39
|
|
|
40
40
|
El código real del proyecto vive en las rutas definidas en `orchestrator.config.json → repos`.
|
|
41
|
-
|
|
41
|
+
**NO leas archivos de código del proyecto real para planificar tareas.** Si necesitas análisis del codebase para crear TASKs, delégalo a OpenCode mediante una TASK en `QUEUE.md` — para eso existe OpenCode.
|
|
42
42
|
**Nunca modifiques archivos del proyecto real directamente** — eso es trabajo exclusivo de los agentes workers.
|
|
43
43
|
|
|
44
44
|
## Al iniciar la sesión — OBLIGATORIO
|
|
@@ -132,14 +132,16 @@ del .away-mode
|
|
|
132
132
|
|
|
133
133
|
### Fallback por cuota o indisponibilidad
|
|
134
134
|
|
|
135
|
-
La TUI gestiona el fallback automáticamente siguiendo
|
|
135
|
+
La TUI gestiona el fallback automáticamente siguiendo estas cadenas:
|
|
136
136
|
|
|
137
|
+
**Por fallo:**
|
|
137
138
|
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
Codex falla → Frontend (repo FE) o Backend (repo BE) directamente
|
|
139
|
+
OpenCode falla → Codex → Claude-Worker (Frontend/Backend)
|
|
140
|
+
Codex falla → OpenCode → Claude-Worker (Frontend/Backend)
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
+
**Por disponibilidad (al asignar tareas nuevas):** Claude-Orquestador debe revisar `STATUS.md` antes de escribir en `QUEUE.md`. Si el agente primario para una tarea ya está ocupado o tiene rate limit, asigna directamente al siguiente agente idle en la cadena en lugar de dejar la tarea esperando detrás de uno ocupado.
|
|
144
|
+
|
|
143
145
|
Como Orquestador, **no necesitas reasignar manualmente** cuando hay un fallo — la TUI lo hace sola. Tu rol en este caso es:
|
|
144
146
|
|
|
145
147
|
1. Verificar en `INBOX.md` o `QUEUE.md` que el fallback se ejecutó correctamente.
|
|
@@ -221,7 +223,7 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
|
|
|
221
223
|
6. Al terminar la sesión, escribe un `handoffs/HANDOFF-<fecha>.md` resumiendo qué se hizo y qué sigue.
|
|
222
224
|
7. **Por defecto solo usa Claude, Codex y OpenCode**. No uses Gemini, Cursor ni Abacus salvo instrucción explícita del usuario.
|
|
223
225
|
8. Si el usuario activa **Modo Ausencia**, revisa progreso cada 5 minutos y reasigna nuevas TASKs razonables dentro del alcance actual sin esperar confirmación intermedia.
|
|
224
|
-
9. La TUI gestiona el fallback automáticamente:
|
|
226
|
+
9. La TUI gestiona el fallback automáticamente: OpenCode falla → Codex → Claude-Worker; Codex falla → OpenCode → Claude-Worker. Solo intervén manualmente si la tarea queda marcada `failed`.
|
|
225
227
|
10. Usa Engram para guardar decisiones, hallazgos, bugs y resúmenes de sesión; no dependas solo del contexto corto de la conversación.
|
|
226
228
|
11. **VERIFICACIÓN OBLIGATORIA:** Antes de crear TASKs de implementación, confirma una de estas condiciones:
|
|
227
229
|
- Existe un reporte de OpenCode en `INBOX.md` o `progress/PROGRESS-OpenCode.md` que cubre el área, O
|