@jungjaehoon/mama-os 0.9.2 → 0.9.3
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 +41 -7
- package/dist/api/graph-api.js +1 -1
- package/dist/api/graph-api.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +60 -15
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/config/types.d.ts +16 -4
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js.map +1 -1
- package/dist/gateways/slack.d.ts.map +1 -1
- package/dist/gateways/slack.js +0 -10
- package/dist/gateways/slack.js.map +1 -1
- package/dist/multi-agent/agent-process-manager.d.ts +3 -1
- package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
- package/dist/multi-agent/agent-process-manager.js +21 -12
- package/dist/multi-agent/agent-process-manager.js.map +1 -1
- package/dist/multi-agent/background-task-manager.d.ts +2 -2
- package/dist/multi-agent/background-task-manager.js +2 -2
- package/dist/multi-agent/council-engine.d.ts +60 -0
- package/dist/multi-agent/council-engine.d.ts.map +1 -0
- package/dist/multi-agent/council-engine.js +284 -0
- package/dist/multi-agent/council-engine.js.map +1 -0
- package/dist/multi-agent/multi-agent-base.d.ts +17 -9
- package/dist/multi-agent/multi-agent-base.d.ts.map +1 -1
- package/dist/multi-agent/multi-agent-base.js +109 -30
- package/dist/multi-agent/multi-agent-base.js.map +1 -1
- package/dist/multi-agent/multi-agent-discord.d.ts +3 -35
- package/dist/multi-agent/multi-agent-discord.d.ts.map +1 -1
- package/dist/multi-agent/multi-agent-discord.js +57 -300
- package/dist/multi-agent/multi-agent-discord.js.map +1 -1
- package/dist/multi-agent/multi-agent-slack.d.ts +0 -25
- package/dist/multi-agent/multi-agent-slack.d.ts.map +1 -1
- package/dist/multi-agent/multi-agent-slack.js +95 -234
- package/dist/multi-agent/multi-agent-slack.js.map +1 -1
- package/dist/multi-agent/shared-context.d.ts.map +1 -1
- package/dist/multi-agent/shared-context.js +4 -4
- package/dist/multi-agent/shared-context.js.map +1 -1
- package/dist/multi-agent/system-reminder.d.ts +1 -1
- package/dist/multi-agent/system-reminder.js +1 -1
- package/dist/multi-agent/types.d.ts +11 -15
- package/dist/multi-agent/types.d.ts.map +1 -1
- package/dist/multi-agent/types.js +1 -3
- package/dist/multi-agent/types.js.map +1 -1
- package/dist/multi-agent/ultrawork-state.d.ts +57 -0
- package/dist/multi-agent/ultrawork-state.d.ts.map +1 -0
- package/dist/multi-agent/ultrawork-state.js +191 -0
- package/dist/multi-agent/ultrawork-state.js.map +1 -0
- package/dist/multi-agent/ultrawork.d.ts +37 -19
- package/dist/multi-agent/ultrawork.d.ts.map +1 -1
- package/dist/multi-agent/ultrawork.js +587 -41
- package/dist/multi-agent/ultrawork.js.map +1 -1
- package/dist/multi-agent/workflow-engine.d.ts.map +1 -1
- package/dist/multi-agent/workflow-engine.js +39 -14
- package/dist/multi-agent/workflow-engine.js.map +1 -1
- package/dist/multi-agent/workflow-types.d.ts +69 -0
- package/dist/multi-agent/workflow-types.d.ts.map +1 -1
- package/dist/onboarding/complete-autonomous-prompt.d.ts +1 -1
- package/dist/onboarding/complete-autonomous-prompt.d.ts.map +1 -1
- package/dist/onboarding/complete-autonomous-prompt.js +27 -10
- package/dist/onboarding/complete-autonomous-prompt.js.map +1 -1
- package/dist/onboarding/phase-7-integrations.d.ts.map +1 -1
- package/dist/onboarding/phase-7-integrations.js +23 -3
- package/dist/onboarding/phase-7-integrations.js.map +1 -1
- package/dist/onboarding/phase-9-finalization.d.ts.map +1 -1
- package/dist/onboarding/phase-9-finalization.js +33 -0
- package/dist/onboarding/phase-9-finalization.js.map +1 -1
- package/package.json +1 -1
- package/templates/personas/architect.md +70 -0
- package/templates/personas/conductor.md +302 -0
- package/templates/personas/developer.md +20 -7
- package/templates/personas/pm.md +49 -33
- package/templates/personas/reviewer.md +18 -5
- package/dist/multi-agent/pr-review-poller.d.ts +0 -197
- package/dist/multi-agent/pr-review-poller.d.ts.map +0 -1
- package/dist/multi-agent/pr-review-poller.js +0 -972
- package/dist/multi-agent/pr-review-poller.js.map +0 -1
- package/templates/personas/sisyphus-builtin-en.md +0 -161
- package/templates/personas/sisyphus.md +0 -218
|
@@ -5,22 +5,65 @@
|
|
|
5
5
|
* Manages autonomous multi-step work sessions that combine
|
|
6
6
|
* delegation and task continuation for extended workflows.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Supports two modes:
|
|
9
|
+
* 1. **Phased Loop** (Ralph Loop, default): Plan -> Build -> Retrospective
|
|
10
|
+
* - File-based state persist for crash recovery
|
|
11
|
+
* - Council integration at plan and retrospective phases
|
|
12
|
+
* - Structured task execution from plan
|
|
13
|
+
* 2. **Freeform Loop** (legacy): Lead agent freely delegates and continues
|
|
11
14
|
*
|
|
12
15
|
* Constraints:
|
|
13
16
|
* - max_duration (default 30 min)
|
|
14
17
|
* - max_steps (default 20)
|
|
15
18
|
* - Lead agent must be Tier 1 with can_delegate
|
|
16
19
|
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
17
53
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
54
|
exports.UltraWorkManager = void 0;
|
|
19
55
|
const tool_permission_manager_js_1 = require("./tool-permission-manager.js");
|
|
20
56
|
const delegation_manager_js_1 = require("./delegation-manager.js");
|
|
21
57
|
const task_continuation_js_1 = require("./task-continuation.js");
|
|
58
|
+
const ultrawork_state_js_1 = require("./ultrawork-state.js");
|
|
59
|
+
const os = __importStar(require("os"));
|
|
60
|
+
const path = __importStar(require("path"));
|
|
22
61
|
/** Default timeout for executeCallback (5 minutes) */
|
|
23
62
|
const DEFAULT_EXECUTE_TIMEOUT = 300000;
|
|
63
|
+
/** Default stall threshold — if response is too short, likely stalled */
|
|
64
|
+
const STALL_MIN_LENGTH = 20;
|
|
65
|
+
/** Max consecutive stalls before forcing a re-prompt */
|
|
66
|
+
const MAX_CONSECUTIVE_STALLS = 2;
|
|
24
67
|
/**
|
|
25
68
|
* Default trigger keywords for UltraWork
|
|
26
69
|
*/
|
|
@@ -37,6 +80,7 @@ const DEFAULT_TRIGGER_KEYWORDS = [
|
|
|
37
80
|
class UltraWorkManager {
|
|
38
81
|
config;
|
|
39
82
|
permissionManager;
|
|
83
|
+
stateManager = null;
|
|
40
84
|
/** Active sessions per channel */
|
|
41
85
|
sessions = new Map();
|
|
42
86
|
/** Session counter for unique IDs */
|
|
@@ -44,6 +88,9 @@ class UltraWorkManager {
|
|
|
44
88
|
constructor(config, permissionManager) {
|
|
45
89
|
this.config = config;
|
|
46
90
|
this.permissionManager = permissionManager ?? new tool_permission_manager_js_1.ToolPermissionManager();
|
|
91
|
+
if (config.persist_state !== false) {
|
|
92
|
+
this.stateManager = new ultrawork_state_js_1.UltraWorkStateManager(path.join(os.homedir(), '.mama', 'workspace', 'ultrawork'));
|
|
93
|
+
}
|
|
47
94
|
}
|
|
48
95
|
/**
|
|
49
96
|
* Check if a message contains UltraWork trigger keywords.
|
|
@@ -58,7 +105,7 @@ class UltraWorkManager {
|
|
|
58
105
|
/**
|
|
59
106
|
* Start a new UltraWork session.
|
|
60
107
|
*/
|
|
61
|
-
async startSession(channelId, leadAgentId, task, agents, executeCallback, notifyCallback) {
|
|
108
|
+
async startSession(channelId, leadAgentId, task, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
62
109
|
// Validate lead agent
|
|
63
110
|
const leadAgent = agents.find((a) => a.id === leadAgentId);
|
|
64
111
|
if (!leadAgent) {
|
|
@@ -84,13 +131,18 @@ class UltraWorkManager {
|
|
|
84
131
|
steps: [],
|
|
85
132
|
};
|
|
86
133
|
this.sessions.set(channelId, session);
|
|
134
|
+
// Persist session state
|
|
135
|
+
if (this.stateManager) {
|
|
136
|
+
await this.stateManager.createSession(session.id, task, agents.filter((a) => a.enabled !== false).map((a) => a.id));
|
|
137
|
+
}
|
|
138
|
+
const modeLabel = this.config.phased_loop !== false ? 'Phased (Plan->Build->Retro)' : 'Freeform';
|
|
87
139
|
await notifyCallback(`**UltraWork Session Started** (${session.id})\n` +
|
|
88
140
|
`Lead: **${leadAgent.display_name}**\n` +
|
|
141
|
+
`Mode: ${modeLabel}\n` +
|
|
89
142
|
`Task: ${task.substring(0, 200)}${task.length > 200 ? '...' : ''}\n` +
|
|
90
143
|
`Limits: ${session.maxSteps} steps, ${Math.round(session.maxDuration / 60000)} min`);
|
|
91
144
|
// Run the autonomous loop in detached context (non-blocking)
|
|
92
|
-
|
|
93
|
-
this.runSessionLoop(session, agents, executeCallback, notifyCallback).catch((err) => {
|
|
145
|
+
this.runSessionLoop(session, agents, executeCallback, notifyCallback, responseInterceptor).catch((err) => {
|
|
94
146
|
console.error(`[UltraWork] Session ${session.id} loop error:`, err);
|
|
95
147
|
session.active = false;
|
|
96
148
|
this.sessions.delete(session.channelId);
|
|
@@ -145,15 +197,20 @@ class UltraWorkManager {
|
|
|
145
197
|
updateConfig(config) {
|
|
146
198
|
this.config = config;
|
|
147
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Get the state manager (for testing).
|
|
202
|
+
*/
|
|
203
|
+
getStateManager() {
|
|
204
|
+
return this.stateManager;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Override state manager (for testing with temp dirs).
|
|
208
|
+
*/
|
|
209
|
+
setStateManager(sm) {
|
|
210
|
+
this.stateManager = sm;
|
|
211
|
+
}
|
|
148
212
|
/**
|
|
149
213
|
* Execute callback with timeout protection.
|
|
150
|
-
* Prevents long-running agent responses from blocking indefinitely.
|
|
151
|
-
*
|
|
152
|
-
* @param executeCallback - The callback to execute
|
|
153
|
-
* @param agentId - Agent ID for error messages
|
|
154
|
-
* @param prompt - Prompt to send to agent
|
|
155
|
-
* @param timeoutMs - Timeout in milliseconds (default: 5 minutes)
|
|
156
|
-
* @returns Promise that rejects on timeout
|
|
157
214
|
*/
|
|
158
215
|
async executeWithTimeout(executeCallback, agentId, prompt, timeoutMs = DEFAULT_EXECUTE_TIMEOUT) {
|
|
159
216
|
let timeoutHandle;
|
|
@@ -167,29 +224,424 @@ class UltraWorkManager {
|
|
|
167
224
|
return result;
|
|
168
225
|
}
|
|
169
226
|
/**
|
|
170
|
-
* Run the autonomous session loop.
|
|
171
|
-
* Lead agent works on the task, delegating and continuing as needed.
|
|
227
|
+
* Run the autonomous session loop — dispatches to phased or freeform mode.
|
|
172
228
|
*/
|
|
173
|
-
async runSessionLoop(session, agents, executeCallback, notifyCallback) {
|
|
229
|
+
async runSessionLoop(session, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
230
|
+
if (this.config.phased_loop !== false) {
|
|
231
|
+
await this.runPhasedLoop(session, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
await this.runFreeformLoop(session, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// ============================================================================
|
|
238
|
+
// Phase 1: Planning
|
|
239
|
+
// ============================================================================
|
|
240
|
+
async runPlanningPhase(session, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
241
|
+
await notifyCallback(`**Phase 1: Planning** - Creating implementation plan...`);
|
|
242
|
+
session.currentStep++;
|
|
243
|
+
const planPrompt = this.buildPlanningPrompt(session.task, agents);
|
|
244
|
+
const planResult = await this.executeWithTimeout(executeCallback, session.leadAgentId, planPrompt);
|
|
245
|
+
session.steps.push({
|
|
246
|
+
stepNumber: session.currentStep,
|
|
247
|
+
agentId: session.leadAgentId,
|
|
248
|
+
action: 'planning',
|
|
249
|
+
responseSummary: planResult.response.substring(0, 200),
|
|
250
|
+
isDelegation: false,
|
|
251
|
+
duration: planResult.duration ?? 0,
|
|
252
|
+
timestamp: Date.now(),
|
|
253
|
+
});
|
|
254
|
+
// Council check — if Conductor outputs council_plan, interceptor will handle it
|
|
255
|
+
let councilResult = null;
|
|
256
|
+
if (responseInterceptor) {
|
|
257
|
+
const intercepted = await responseInterceptor(planResult.response, session.channelId);
|
|
258
|
+
if (intercepted?.type === 'council') {
|
|
259
|
+
councilResult = intercepted.result;
|
|
260
|
+
await notifyCallback(councilResult);
|
|
261
|
+
session.currentStep++;
|
|
262
|
+
session.steps.push({
|
|
263
|
+
stepNumber: session.currentStep,
|
|
264
|
+
agentId: session.leadAgentId,
|
|
265
|
+
action: 'council_execution',
|
|
266
|
+
responseSummary: councilResult.substring(0, 200),
|
|
267
|
+
isDelegation: false,
|
|
268
|
+
duration: 0,
|
|
269
|
+
timestamp: Date.now(),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Synthesize final plan (with council input if available)
|
|
274
|
+
let finalPlan;
|
|
275
|
+
if (councilResult) {
|
|
276
|
+
session.currentStep++;
|
|
277
|
+
const synthesisPrompt = `Based on the council discussion:\n---\n${councilResult}\n---\n\n` +
|
|
278
|
+
`Create the final IMPLEMENTATION_PLAN. Format:\n## Tasks\n1. [task description] - assigned to: [agent_id]\n2. ...\n\n` +
|
|
279
|
+
`Include acceptance criteria for each task. End with "PLAN_COMPLETE".`;
|
|
280
|
+
const synthesis = await this.executeWithTimeout(executeCallback, session.leadAgentId, synthesisPrompt);
|
|
281
|
+
finalPlan = synthesis.response;
|
|
282
|
+
session.steps.push({
|
|
283
|
+
stepNumber: session.currentStep,
|
|
284
|
+
agentId: session.leadAgentId,
|
|
285
|
+
action: 'plan_synthesis',
|
|
286
|
+
responseSummary: finalPlan.substring(0, 200),
|
|
287
|
+
isDelegation: false,
|
|
288
|
+
duration: synthesis.duration ?? 0,
|
|
289
|
+
timestamp: Date.now(),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
finalPlan = planResult.response;
|
|
294
|
+
}
|
|
295
|
+
// Persist plan
|
|
296
|
+
if (this.stateManager) {
|
|
297
|
+
await this.stateManager.savePlan(session.id, finalPlan);
|
|
298
|
+
}
|
|
299
|
+
return finalPlan;
|
|
300
|
+
}
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Phase 2: Building
|
|
303
|
+
// ============================================================================
|
|
304
|
+
async runBuildingPhase(session, plan, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
305
|
+
await notifyCallback(`**Phase 2: Building** - Executing plan...`);
|
|
306
|
+
const delegationManager = new delegation_manager_js_1.DelegationManager(agents, this.permissionManager);
|
|
307
|
+
const continuationEnforcer = new task_continuation_js_1.TaskContinuationEnforcer({
|
|
308
|
+
enabled: true,
|
|
309
|
+
max_retries: 3,
|
|
310
|
+
});
|
|
311
|
+
let consecutiveStalls = 0;
|
|
312
|
+
let currentPrompt = this.buildBuildingPrompt(plan, agents);
|
|
313
|
+
let currentAgentId = session.leadAgentId;
|
|
314
|
+
while (this.shouldContinue(session)) {
|
|
315
|
+
session.currentStep++;
|
|
316
|
+
const stepStart = Date.now();
|
|
317
|
+
try {
|
|
318
|
+
const result = await this.executeWithTimeout(executeCallback, currentAgentId, currentPrompt);
|
|
319
|
+
const stepDuration = Date.now() - stepStart;
|
|
320
|
+
// Stall detection
|
|
321
|
+
if (result.response.trim().length < STALL_MIN_LENGTH) {
|
|
322
|
+
consecutiveStalls++;
|
|
323
|
+
if (consecutiveStalls >= MAX_CONSECUTIVE_STALLS) {
|
|
324
|
+
consecutiveStalls = 0;
|
|
325
|
+
await notifyCallback(`Agent ${currentAgentId} appears stalled (${MAX_CONSECUTIVE_STALLS} short responses). Re-prompting...`);
|
|
326
|
+
currentPrompt =
|
|
327
|
+
`Your previous responses were too brief. The task is NOT complete yet.\n\n` +
|
|
328
|
+
`Original plan:\n${plan.substring(0, 1000)}\n\n` +
|
|
329
|
+
`Please continue executing the plan. When ALL tasks are done, respond with "BUILD_COMPLETE".`;
|
|
330
|
+
currentAgentId = session.leadAgentId;
|
|
331
|
+
session.steps.push({
|
|
332
|
+
stepNumber: session.currentStep,
|
|
333
|
+
agentId: currentAgentId,
|
|
334
|
+
action: 'stall_detected',
|
|
335
|
+
responseSummary: `Stalled: "${result.response.trim().substring(0, 100)}"`,
|
|
336
|
+
isDelegation: false,
|
|
337
|
+
duration: stepDuration,
|
|
338
|
+
timestamp: Date.now(),
|
|
339
|
+
});
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
consecutiveStalls = 0;
|
|
345
|
+
}
|
|
346
|
+
// Council/workflow interceptor
|
|
347
|
+
if (responseInterceptor) {
|
|
348
|
+
const intercepted = await responseInterceptor(result.response, session.channelId);
|
|
349
|
+
if (intercepted) {
|
|
350
|
+
session.steps.push({
|
|
351
|
+
stepNumber: session.currentStep,
|
|
352
|
+
agentId: currentAgentId,
|
|
353
|
+
action: intercepted.type === 'council' ? 'council_execution' : 'workflow_execution',
|
|
354
|
+
responseSummary: intercepted.result.substring(0, 200),
|
|
355
|
+
isDelegation: false,
|
|
356
|
+
duration: Date.now() - stepStart,
|
|
357
|
+
timestamp: Date.now(),
|
|
358
|
+
});
|
|
359
|
+
await notifyCallback(intercepted.result);
|
|
360
|
+
currentPrompt =
|
|
361
|
+
`The ${intercepted.type} plan completed. Results:\n---\n${intercepted.result.substring(0, 1000)}\n---\n` +
|
|
362
|
+
`Continue executing the plan. When ALL tasks are done, respond with "BUILD_COMPLETE".`;
|
|
363
|
+
currentAgentId = session.leadAgentId;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// Delegation check
|
|
368
|
+
const delegationRequest = delegationManager.parseDelegation(currentAgentId, result.response);
|
|
369
|
+
if (delegationRequest) {
|
|
370
|
+
session.steps.push({
|
|
371
|
+
stepNumber: session.currentStep,
|
|
372
|
+
agentId: currentAgentId,
|
|
373
|
+
action: 'delegation',
|
|
374
|
+
responseSummary: delegationRequest.originalContent.substring(0, 200),
|
|
375
|
+
isDelegation: true,
|
|
376
|
+
duration: stepDuration,
|
|
377
|
+
timestamp: Date.now(),
|
|
378
|
+
});
|
|
379
|
+
const delegationResult = await delegationManager.executeDelegation(delegationRequest, executeCallback, notifyCallback);
|
|
380
|
+
if (delegationResult.success && delegationResult.response) {
|
|
381
|
+
session.currentStep++;
|
|
382
|
+
session.steps.push({
|
|
383
|
+
stepNumber: session.currentStep,
|
|
384
|
+
agentId: delegationRequest.toAgentId,
|
|
385
|
+
action: 'delegated_task',
|
|
386
|
+
responseSummary: delegationResult.response.substring(0, 200),
|
|
387
|
+
isDelegation: false,
|
|
388
|
+
duration: delegationResult.duration ?? 0,
|
|
389
|
+
timestamp: Date.now(),
|
|
390
|
+
});
|
|
391
|
+
// Persist step
|
|
392
|
+
if (this.stateManager) {
|
|
393
|
+
await this.stateManager.recordStep(session.id, {
|
|
394
|
+
stepNumber: session.currentStep,
|
|
395
|
+
agentId: delegationRequest.toAgentId,
|
|
396
|
+
action: 'delegated_task',
|
|
397
|
+
responseSummary: delegationResult.response.substring(0, 200),
|
|
398
|
+
isDelegation: false,
|
|
399
|
+
duration: delegationResult.duration ?? 0,
|
|
400
|
+
timestamp: Date.now(),
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
currentPrompt = this.buildContinuationAfterDelegation(delegationRequest.toAgentId, delegationResult.response);
|
|
404
|
+
currentAgentId = session.leadAgentId;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
currentPrompt = `Delegation to ${delegationRequest.toAgentId} failed: ${delegationResult.error}. Please continue the task yourself.`;
|
|
408
|
+
currentAgentId = session.leadAgentId;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
// No delegation — record step, check build completion
|
|
413
|
+
session.steps.push({
|
|
414
|
+
stepNumber: session.currentStep,
|
|
415
|
+
agentId: currentAgentId,
|
|
416
|
+
action: 'direct_work',
|
|
417
|
+
responseSummary: result.response.substring(0, 200),
|
|
418
|
+
isDelegation: false,
|
|
419
|
+
duration: stepDuration,
|
|
420
|
+
timestamp: Date.now(),
|
|
421
|
+
});
|
|
422
|
+
// Persist step
|
|
423
|
+
if (this.stateManager) {
|
|
424
|
+
await this.stateManager.recordStep(session.id, {
|
|
425
|
+
stepNumber: session.currentStep,
|
|
426
|
+
agentId: currentAgentId,
|
|
427
|
+
action: 'direct_work',
|
|
428
|
+
responseSummary: result.response.substring(0, 200),
|
|
429
|
+
isDelegation: false,
|
|
430
|
+
duration: stepDuration,
|
|
431
|
+
timestamp: Date.now(),
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
// Build-phase completion check
|
|
435
|
+
if (this.isBuildComplete(result.response)) {
|
|
436
|
+
return; // Move to retrospective
|
|
437
|
+
}
|
|
438
|
+
// Fallback: use continuation enforcer for "DONE" compat
|
|
439
|
+
const continuation = continuationEnforcer.analyzeResponse(currentAgentId, session.channelId, result.response);
|
|
440
|
+
if (continuation.isComplete) {
|
|
441
|
+
return; // Move to retrospective
|
|
442
|
+
}
|
|
443
|
+
if (continuation.maxRetriesReached) {
|
|
444
|
+
return; // Move to retrospective anyway
|
|
445
|
+
}
|
|
446
|
+
currentPrompt = continuationEnforcer.buildContinuationPrompt(result.response);
|
|
447
|
+
currentAgentId = session.leadAgentId;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
452
|
+
session.steps.push({
|
|
453
|
+
stepNumber: session.currentStep,
|
|
454
|
+
agentId: currentAgentId,
|
|
455
|
+
action: 'error',
|
|
456
|
+
responseSummary: errorMessage.substring(0, 200),
|
|
457
|
+
isDelegation: false,
|
|
458
|
+
duration: Date.now() - stepStart,
|
|
459
|
+
timestamp: Date.now(),
|
|
460
|
+
});
|
|
461
|
+
currentPrompt = `An error occurred: ${errorMessage}. Please assess the situation and decide how to continue.`;
|
|
462
|
+
currentAgentId = session.leadAgentId;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
// ============================================================================
|
|
467
|
+
// Phase 3: Retrospective
|
|
468
|
+
// ============================================================================
|
|
469
|
+
async runRetrospectivePhase(session, planFromPhase1, _agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
470
|
+
await notifyCallback(`**Phase 3: Retrospective** - Reviewing results...`);
|
|
471
|
+
const steps = this.stateManager
|
|
472
|
+
? await this.stateManager.loadProgress(session.id)
|
|
473
|
+
: session.steps;
|
|
474
|
+
const plan = this.stateManager
|
|
475
|
+
? ((await this.stateManager.loadPlan(session.id)) ?? planFromPhase1)
|
|
476
|
+
: planFromPhase1;
|
|
477
|
+
session.currentStep++;
|
|
478
|
+
const retroPrompt = this.buildRetrospectivePrompt(plan, steps);
|
|
479
|
+
const retroResult = await this.executeWithTimeout(executeCallback, session.leadAgentId, retroPrompt);
|
|
480
|
+
session.steps.push({
|
|
481
|
+
stepNumber: session.currentStep,
|
|
482
|
+
agentId: session.leadAgentId,
|
|
483
|
+
action: 'retrospective',
|
|
484
|
+
responseSummary: retroResult.response.substring(0, 200),
|
|
485
|
+
isDelegation: false,
|
|
486
|
+
duration: retroResult.duration ?? 0,
|
|
487
|
+
timestamp: Date.now(),
|
|
488
|
+
});
|
|
489
|
+
// Council check
|
|
490
|
+
if (responseInterceptor) {
|
|
491
|
+
const intercepted = await responseInterceptor(retroResult.response, session.channelId);
|
|
492
|
+
if (intercepted?.type === 'council') {
|
|
493
|
+
await notifyCallback(intercepted.result);
|
|
494
|
+
session.currentStep++;
|
|
495
|
+
session.steps.push({
|
|
496
|
+
stepNumber: session.currentStep,
|
|
497
|
+
agentId: session.leadAgentId,
|
|
498
|
+
action: 'council_execution',
|
|
499
|
+
responseSummary: intercepted.result.substring(0, 200),
|
|
500
|
+
isDelegation: false,
|
|
501
|
+
duration: 0,
|
|
502
|
+
timestamp: Date.now(),
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const isComplete = this.isRetroComplete(retroResult.response);
|
|
507
|
+
// Persist retrospective
|
|
508
|
+
if (this.stateManager) {
|
|
509
|
+
await this.stateManager.saveRetrospective(session.id, retroResult.response);
|
|
510
|
+
}
|
|
511
|
+
return { complete: isComplete, retro: retroResult.response };
|
|
512
|
+
}
|
|
513
|
+
// ============================================================================
|
|
514
|
+
// Phased Loop (Ralph Loop): Plan -> Build -> Retrospective
|
|
515
|
+
// ============================================================================
|
|
516
|
+
async runPhasedLoop(session, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
517
|
+
// Phase 1: Planning + Council
|
|
518
|
+
if (this.stateManager) {
|
|
519
|
+
await this.stateManager.updatePhase(session.id, 'planning');
|
|
520
|
+
}
|
|
521
|
+
const plan = await this.runPlanningPhase(session, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
522
|
+
if (!this.shouldContinue(session)) {
|
|
523
|
+
this.endSession(session, notifyCallback);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
// Phase 2: Building
|
|
527
|
+
if (this.stateManager) {
|
|
528
|
+
await this.stateManager.updatePhase(session.id, 'building');
|
|
529
|
+
}
|
|
530
|
+
await this.runBuildingPhase(session, plan, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
531
|
+
if (!this.shouldContinue(session)) {
|
|
532
|
+
this.endSession(session, notifyCallback);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// Phase 3: Retrospective + Council
|
|
536
|
+
if (this.stateManager) {
|
|
537
|
+
await this.stateManager.updatePhase(session.id, 'retrospective');
|
|
538
|
+
}
|
|
539
|
+
const { complete } = await this.runRetrospectivePhase(session, plan, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
540
|
+
if (!complete && this.shouldContinue(session)) {
|
|
541
|
+
// Incomplete → re-enter Build phase (max 1 retry)
|
|
542
|
+
await notifyCallback(`Retrospective found incomplete items. Re-entering Build phase...`);
|
|
543
|
+
if (this.stateManager) {
|
|
544
|
+
await this.stateManager.updatePhase(session.id, 'building');
|
|
545
|
+
}
|
|
546
|
+
await this.runBuildingPhase(session, plan, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
547
|
+
// Re-run retrospective after retry Build phase
|
|
548
|
+
if (!this.shouldContinue(session)) {
|
|
549
|
+
// Session cancelled or limits exceeded
|
|
550
|
+
session.active = false;
|
|
551
|
+
this.sessions.delete(session.channelId);
|
|
552
|
+
await notifyCallback(`**UltraWork Session Ended** — limits exceeded or cancelled`);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (this.stateManager) {
|
|
556
|
+
await this.stateManager.updatePhase(session.id, 'retrospective');
|
|
557
|
+
}
|
|
558
|
+
const retryRetro = await this.runRetrospectivePhase(session, plan, agents, executeCallback, notifyCallback, responseInterceptor);
|
|
559
|
+
if (!retryRetro.complete) {
|
|
560
|
+
// Still incomplete after retry — end session with warning
|
|
561
|
+
if (this.stateManager) {
|
|
562
|
+
await this.stateManager.updatePhase(session.id, 'completed');
|
|
563
|
+
}
|
|
564
|
+
session.active = false;
|
|
565
|
+
this.sessions.delete(session.channelId);
|
|
566
|
+
await notifyCallback(`**UltraWork Session Complete** (${session.id}) — with incomplete items\n` +
|
|
567
|
+
`Phases: Plan -> Build -> Retro -> Build (retry) -> Retro\n` +
|
|
568
|
+
`Steps: ${session.currentStep} | Duration: ${Math.round((Date.now() - session.startTime) / 1000)}s`);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// Complete
|
|
573
|
+
if (this.stateManager) {
|
|
574
|
+
await this.stateManager.updatePhase(session.id, 'completed');
|
|
575
|
+
}
|
|
576
|
+
session.active = false;
|
|
577
|
+
this.sessions.delete(session.channelId);
|
|
578
|
+
await notifyCallback(`**UltraWork Session Complete** (${session.id})\n` +
|
|
579
|
+
`Phases: Plan -> Build -> Retrospective\n` +
|
|
580
|
+
`Steps: ${session.currentStep} | Duration: ${Math.round((Date.now() - session.startTime) / 1000)}s`);
|
|
581
|
+
}
|
|
582
|
+
// ============================================================================
|
|
583
|
+
// Freeform Loop (Legacy)
|
|
584
|
+
// ============================================================================
|
|
585
|
+
async runFreeformLoop(session, agents, executeCallback, notifyCallback, responseInterceptor) {
|
|
174
586
|
const delegationManager = new delegation_manager_js_1.DelegationManager(agents, this.permissionManager);
|
|
175
587
|
const continuationEnforcer = new task_continuation_js_1.TaskContinuationEnforcer({
|
|
176
588
|
enabled: true,
|
|
177
589
|
max_retries: 3,
|
|
178
590
|
});
|
|
179
|
-
|
|
591
|
+
let consecutiveStalls = 0;
|
|
180
592
|
let currentPrompt = this.buildInitialPrompt(session.task, agents);
|
|
181
593
|
let currentAgentId = session.leadAgentId;
|
|
182
594
|
while (this.shouldContinue(session)) {
|
|
183
595
|
session.currentStep++;
|
|
184
596
|
const stepStart = Date.now();
|
|
185
597
|
try {
|
|
186
|
-
// Execute current agent's task with timeout protection
|
|
187
598
|
const result = await this.executeWithTimeout(executeCallback, currentAgentId, currentPrompt);
|
|
188
599
|
const stepDuration = Date.now() - stepStart;
|
|
189
|
-
//
|
|
600
|
+
// Stall detection
|
|
601
|
+
if (result.response.trim().length < STALL_MIN_LENGTH) {
|
|
602
|
+
consecutiveStalls++;
|
|
603
|
+
if (consecutiveStalls >= MAX_CONSECUTIVE_STALLS) {
|
|
604
|
+
consecutiveStalls = 0;
|
|
605
|
+
await notifyCallback(`Agent ${currentAgentId} appears stalled (${MAX_CONSECUTIVE_STALLS} short responses). Re-prompting...`);
|
|
606
|
+
currentPrompt = `Your previous responses were too brief. The task is NOT complete yet.\n\nOriginal task: ${session.task}\n\nPlease take concrete action now. When fully done, respond with "DONE".`;
|
|
607
|
+
currentAgentId = session.leadAgentId;
|
|
608
|
+
session.steps.push({
|
|
609
|
+
stepNumber: session.currentStep,
|
|
610
|
+
agentId: currentAgentId,
|
|
611
|
+
action: 'stall_detected',
|
|
612
|
+
responseSummary: `Stalled: "${result.response.trim().substring(0, 100)}"`,
|
|
613
|
+
isDelegation: false,
|
|
614
|
+
duration: stepDuration,
|
|
615
|
+
timestamp: Date.now(),
|
|
616
|
+
});
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
consecutiveStalls = 0;
|
|
622
|
+
}
|
|
623
|
+
// Council/workflow interceptor
|
|
624
|
+
if (responseInterceptor) {
|
|
625
|
+
const intercepted = await responseInterceptor(result.response, session.channelId);
|
|
626
|
+
if (intercepted) {
|
|
627
|
+
session.steps.push({
|
|
628
|
+
stepNumber: session.currentStep,
|
|
629
|
+
agentId: currentAgentId,
|
|
630
|
+
action: intercepted.type === 'council' ? 'council_execution' : 'workflow_execution',
|
|
631
|
+
responseSummary: intercepted.result.substring(0, 200),
|
|
632
|
+
isDelegation: false,
|
|
633
|
+
duration: Date.now() - stepStart,
|
|
634
|
+
timestamp: Date.now(),
|
|
635
|
+
});
|
|
636
|
+
await notifyCallback(intercepted.result);
|
|
637
|
+
currentPrompt = `The ${intercepted.type} plan completed. Results:\n---\n${intercepted.result.substring(0, 1000)}\n---\nContinue with the next step. When done, respond with "DONE".`;
|
|
638
|
+
currentAgentId = session.leadAgentId;
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
// Delegation check
|
|
190
643
|
const delegationRequest = delegationManager.parseDelegation(currentAgentId, result.response);
|
|
191
644
|
if (delegationRequest) {
|
|
192
|
-
// Record lead agent's step
|
|
193
645
|
session.steps.push({
|
|
194
646
|
stepNumber: session.currentStep,
|
|
195
647
|
agentId: currentAgentId,
|
|
@@ -199,10 +651,8 @@ class UltraWorkManager {
|
|
|
199
651
|
duration: stepDuration,
|
|
200
652
|
timestamp: Date.now(),
|
|
201
653
|
});
|
|
202
|
-
// Execute delegation
|
|
203
654
|
const delegationResult = await delegationManager.executeDelegation(delegationRequest, executeCallback, notifyCallback);
|
|
204
655
|
if (delegationResult.success && delegationResult.response) {
|
|
205
|
-
// Increment again: delegation response counts as a separate step from the lead's request
|
|
206
656
|
session.currentStep++;
|
|
207
657
|
session.steps.push({
|
|
208
658
|
stepNumber: session.currentStep,
|
|
@@ -213,18 +663,15 @@ class UltraWorkManager {
|
|
|
213
663
|
duration: delegationResult.duration ?? 0,
|
|
214
664
|
timestamp: Date.now(),
|
|
215
665
|
});
|
|
216
|
-
// Continue with lead agent, incorporating delegation result
|
|
217
666
|
currentPrompt = this.buildContinuationAfterDelegation(delegationRequest.toAgentId, delegationResult.response);
|
|
218
667
|
currentAgentId = session.leadAgentId;
|
|
219
668
|
}
|
|
220
669
|
else {
|
|
221
|
-
// Delegation failed, let lead agent continue
|
|
222
670
|
currentPrompt = `Delegation to ${delegationRequest.toAgentId} failed: ${delegationResult.error}. Please continue the task yourself.`;
|
|
223
671
|
currentAgentId = session.leadAgentId;
|
|
224
672
|
}
|
|
225
673
|
}
|
|
226
674
|
else {
|
|
227
|
-
// No delegation - record step and check continuation
|
|
228
675
|
session.steps.push({
|
|
229
676
|
stepNumber: session.currentStep,
|
|
230
677
|
agentId: currentAgentId,
|
|
@@ -234,10 +681,8 @@ class UltraWorkManager {
|
|
|
234
681
|
duration: stepDuration,
|
|
235
682
|
timestamp: Date.now(),
|
|
236
683
|
});
|
|
237
|
-
// Check if response is complete
|
|
238
684
|
const continuation = continuationEnforcer.analyzeResponse(currentAgentId, session.channelId, result.response);
|
|
239
685
|
if (continuation.isComplete) {
|
|
240
|
-
// Task is done
|
|
241
686
|
session.active = false;
|
|
242
687
|
this.sessions.delete(session.channelId);
|
|
243
688
|
await notifyCallback(`**UltraWork Session Complete** (${session.id})\n` +
|
|
@@ -245,14 +690,12 @@ class UltraWorkManager {
|
|
|
245
690
|
break;
|
|
246
691
|
}
|
|
247
692
|
if (continuation.maxRetriesReached) {
|
|
248
|
-
// Can't continue further
|
|
249
693
|
session.active = false;
|
|
250
694
|
this.sessions.delete(session.channelId);
|
|
251
695
|
await notifyCallback(`**UltraWork Session Stopped** (${session.id}): Max continuation retries reached.\n` +
|
|
252
696
|
`Steps: ${session.currentStep}`);
|
|
253
697
|
break;
|
|
254
698
|
}
|
|
255
|
-
// Build continuation prompt
|
|
256
699
|
currentPrompt = continuationEnforcer.buildContinuationPrompt(result.response);
|
|
257
700
|
currentAgentId = session.leadAgentId;
|
|
258
701
|
}
|
|
@@ -268,23 +711,101 @@ class UltraWorkManager {
|
|
|
268
711
|
duration: Date.now() - stepStart,
|
|
269
712
|
timestamp: Date.now(),
|
|
270
713
|
});
|
|
271
|
-
// Try to recover by sending error context to lead
|
|
272
714
|
currentPrompt = `An error occurred: ${errorMessage}. Please assess the situation and decide how to continue.`;
|
|
273
715
|
currentAgentId = session.leadAgentId;
|
|
274
716
|
}
|
|
275
717
|
}
|
|
276
718
|
// Session limits reached
|
|
277
719
|
if (session.active) {
|
|
278
|
-
|
|
279
|
-
session.active = false;
|
|
280
|
-
this.sessions.delete(session.channelId);
|
|
281
|
-
await notifyCallback(`**UltraWork Session Ended** (${session.id}): ${reason}.\n` +
|
|
282
|
-
`Steps: ${session.currentStep} | Duration: ${Math.round((Date.now() - session.startTime) / 1000)}s`);
|
|
720
|
+
this.endSession(session, notifyCallback);
|
|
283
721
|
}
|
|
284
722
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
723
|
+
// ============================================================================
|
|
724
|
+
// Prompt builders
|
|
725
|
+
// ============================================================================
|
|
726
|
+
buildPlanningPrompt(task, agents) {
|
|
727
|
+
const agentList = agents
|
|
728
|
+
.filter((a) => a.enabled !== false)
|
|
729
|
+
.map((a) => `- **${a.display_name}** (ID: ${a.id}, Tier ${a.tier ?? 1})`)
|
|
730
|
+
.join('\n');
|
|
731
|
+
return `**UltraWork — Phase 1: Planning**
|
|
732
|
+
|
|
733
|
+
You are leading an autonomous work session. Before implementing, create a detailed plan.
|
|
734
|
+
|
|
735
|
+
**Task:** ${task}
|
|
736
|
+
|
|
737
|
+
**Available agents:**
|
|
738
|
+
${agentList}
|
|
739
|
+
|
|
740
|
+
**Instructions:**
|
|
741
|
+
1. Analyze the task requirements
|
|
742
|
+
2. If multiple perspectives would help, start a council discussion:
|
|
743
|
+
\`\`\`council_plan
|
|
744
|
+
{"name":"plan_review","topic":"Review implementation approach for: ${task.substring(0, 100)}","agents":["developer","reviewer"],"rounds":1}
|
|
745
|
+
\`\`\`
|
|
746
|
+
3. After gathering input, create a structured plan:
|
|
747
|
+
|
|
748
|
+
## Implementation Plan
|
|
749
|
+
### Task 1: [description]
|
|
750
|
+
- Assigned to: [agent_id]
|
|
751
|
+
- Acceptance criteria: [what defines "done"]
|
|
752
|
+
### Task 2: ...
|
|
753
|
+
|
|
754
|
+
4. End with "PLAN_COMPLETE" when the plan is ready.`;
|
|
755
|
+
}
|
|
756
|
+
buildBuildingPrompt(plan, agents) {
|
|
757
|
+
const agentList = agents
|
|
758
|
+
.filter((a) => a.enabled !== false)
|
|
759
|
+
.map((a) => `- ${a.display_name} (ID: ${a.id})`)
|
|
760
|
+
.join('\n');
|
|
761
|
+
return `**UltraWork — Phase 2: Building**
|
|
762
|
+
|
|
763
|
+
Execute the following plan. Delegate tasks to specialists.
|
|
764
|
+
|
|
765
|
+
**Plan:**
|
|
766
|
+
---
|
|
767
|
+
${plan.substring(0, 3000)}
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
**Available agents:**
|
|
771
|
+
${agentList}
|
|
772
|
+
|
|
773
|
+
**Instructions:**
|
|
774
|
+
- Execute tasks in order from the plan
|
|
775
|
+
- Delegate using: DELEGATE::{agent_id}::{task description with acceptance criteria}
|
|
776
|
+
- If a task fails or needs discussion, use council_plan for team input
|
|
777
|
+
- After ALL tasks are done, respond with "BUILD_COMPLETE"
|
|
778
|
+
- Do NOT skip any tasks from the plan`;
|
|
779
|
+
}
|
|
780
|
+
buildRetrospectivePrompt(plan, steps) {
|
|
781
|
+
const stepSummary = steps
|
|
782
|
+
.map((s) => `- Step ${s.stepNumber} [${s.action}] by ${s.agentId}: ${s.responseSummary.substring(0, 100)}`)
|
|
783
|
+
.join('\n');
|
|
784
|
+
return `**UltraWork — Phase 3: Retrospective**
|
|
785
|
+
|
|
786
|
+
Review the completed work against the original plan.
|
|
787
|
+
|
|
788
|
+
**Original Plan:**
|
|
789
|
+
---
|
|
790
|
+
${plan.substring(0, 2000)}
|
|
791
|
+
---
|
|
792
|
+
|
|
793
|
+
**Completed Steps:**
|
|
794
|
+
${stepSummary || '(no steps recorded)'}
|
|
795
|
+
|
|
796
|
+
**Instructions:**
|
|
797
|
+
1. Compare completed work against the plan
|
|
798
|
+
2. If team review would help, start a council discussion:
|
|
799
|
+
\`\`\`council_plan
|
|
800
|
+
{"name":"retrospective","topic":"Review completed work quality and identify gaps","agents":["developer","reviewer"],"rounds":1}
|
|
801
|
+
\`\`\`
|
|
802
|
+
3. After council input, provide final assessment:
|
|
803
|
+
- What was completed successfully
|
|
804
|
+
- What needs additional work (if any)
|
|
805
|
+
- Lessons learned
|
|
806
|
+
4. If ALL tasks are done satisfactorily: respond with "RETRO_COMPLETE"
|
|
807
|
+
5. If tasks remain: respond with "RETRO_INCOMPLETE" and list remaining items`;
|
|
808
|
+
}
|
|
288
809
|
buildInitialPrompt(task, agents) {
|
|
289
810
|
const agentList = agents
|
|
290
811
|
.filter((a) => a.enabled !== false)
|
|
@@ -307,9 +828,6 @@ ${agentList}
|
|
|
307
828
|
- End your response with "DONE" when the overall task is complete
|
|
308
829
|
- Stay focused on the task and be efficient`;
|
|
309
830
|
}
|
|
310
|
-
/**
|
|
311
|
-
* Build continuation prompt after a delegation completes.
|
|
312
|
-
*/
|
|
313
831
|
buildContinuationAfterDelegation(delegatedAgentId, response) {
|
|
314
832
|
const summary = response.length > 500 ? response.substring(0, 500) + '...' : response;
|
|
315
833
|
return `Agent ${delegatedAgentId} completed the delegated task. Their response:
|
|
@@ -318,6 +836,34 @@ ${summary}
|
|
|
318
836
|
---
|
|
319
837
|
Continue with the next step of the overall task. When everything is done, respond with "DONE".`;
|
|
320
838
|
}
|
|
839
|
+
// ============================================================================
|
|
840
|
+
// Completion markers
|
|
841
|
+
// ============================================================================
|
|
842
|
+
isBuildComplete(response) {
|
|
843
|
+
return /\bBUILD_COMPLETE\b/i.test(response);
|
|
844
|
+
}
|
|
845
|
+
isRetroComplete(response) {
|
|
846
|
+
return /\bRETRO_COMPLETE\b/i.test(response);
|
|
847
|
+
}
|
|
848
|
+
// ============================================================================
|
|
849
|
+
// Helpers
|
|
850
|
+
// ============================================================================
|
|
851
|
+
async endSession(session, notifyCallback) {
|
|
852
|
+
let reason;
|
|
853
|
+
if (!session.active) {
|
|
854
|
+
reason = 'cancelled';
|
|
855
|
+
}
|
|
856
|
+
else if (session.currentStep >= session.maxSteps) {
|
|
857
|
+
reason = 'max steps reached';
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
reason = 'max duration reached';
|
|
861
|
+
}
|
|
862
|
+
session.active = false;
|
|
863
|
+
this.sessions.delete(session.channelId);
|
|
864
|
+
await notifyCallback(`**UltraWork Session Ended** (${session.id}): ${reason}.\n` +
|
|
865
|
+
`Steps: ${session.currentStep} | Duration: ${Math.round((Date.now() - session.startTime) / 1000)}s`);
|
|
866
|
+
}
|
|
321
867
|
}
|
|
322
868
|
exports.UltraWorkManager = UltraWorkManager;
|
|
323
869
|
//# sourceMappingURL=ultrawork.js.map
|