iriai-build 0.2.6 → 0.2.7
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/package.json +1 -1
- package/v3/agent-supervisor.js +12 -6
- package/v3/operator.js +4 -5
- package/v3/orchestrator.js +30 -2
package/package.json
CHANGED
package/v3/agent-supervisor.js
CHANGED
|
@@ -192,12 +192,18 @@ export class AgentSupervisor extends EventEmitter {
|
|
|
192
192
|
console.log(`[supervisor] Scheduling retry ${updatedAgent.retry_count}/${agent.max_retries} for ${agent.agent_key} in ${backoffS}s (${isFastExit ? "fast-exit" : "normal"})`);
|
|
193
193
|
|
|
194
194
|
const entry = this._processes[agent.agent_key] || {};
|
|
195
|
-
entry.retryTimer = setTimeout(() => {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
entry.retryTimer = setTimeout(async () => {
|
|
196
|
+
try {
|
|
197
|
+
const result = await promptFn(updatedAgent);
|
|
198
|
+
// promptFn can return null (already handled spawn), a string, or { prompt, continue }
|
|
199
|
+
if (result == null) return;
|
|
200
|
+
const prompt = typeof result === "string" ? result : result.prompt;
|
|
201
|
+
const spawnOpts = typeof result === "string" ? {} : { continue: !!result.continue };
|
|
202
|
+
this.spawn(agentId, prompt, spawnOpts);
|
|
203
|
+
} catch (err) {
|
|
204
|
+
console.error(`[supervisor] Retry callback error for ${agent.agent_key}:`, err.message);
|
|
205
|
+
queries.updateAgentStatus(agentId, "crashed");
|
|
206
|
+
}
|
|
201
207
|
}, backoffS * 1000);
|
|
202
208
|
this._processes[agent.agent_key] = entry;
|
|
203
209
|
|
package/v3/operator.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
* @param {AgentSupervisor} opts.supervisor - Agent supervisor instance
|
|
26
26
|
* @param {number} opts.agentId - Operator agent DB id
|
|
27
27
|
*/
|
|
28
|
-
export async function invokeOperator({ feature, operatorDir, flDir, featureDir, userMessage, supervisor, agentId, planDir, activePlanningRole }) {
|
|
28
|
+
export async function invokeOperator({ feature, operatorDir, flDir, featureDir, userMessage, supervisor, agentId, planDir, activePlanningRole, continue: useContinue }) {
|
|
29
29
|
// 1. Assemble context from SQLite (async — Haiku summarization is non-blocking)
|
|
30
30
|
const history = await assembleHistory(feature.id);
|
|
31
31
|
const activeAgents = assembleActiveAgents(feature.id);
|
|
@@ -49,10 +49,9 @@ export async function invokeOperator({ feature, operatorDir, flDir, featureDir,
|
|
|
49
49
|
directoryMap,
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
// 3. Spawn claude via supervisor
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
supervisor.spawn(agentId, prompt, { continue: true });
|
|
52
|
+
// 3. Spawn claude via supervisor — default to --continue for session context,
|
|
53
|
+
// but allow caller to force a fresh session (e.g. after "Prompt is too long")
|
|
54
|
+
supervisor.spawn(agentId, prompt, { continue: useContinue !== undefined ? useContinue : true });
|
|
56
55
|
|
|
57
56
|
// Record the event
|
|
58
57
|
queries.insertEvent(feature.id, "user-message", "bridge", `Operator invoked for: ${userMessage.slice(0, 100)}`);
|
package/v3/orchestrator.js
CHANGED
|
@@ -2232,6 +2232,11 @@ export class Orchestrator {
|
|
|
2232
2232
|
|
|
2233
2233
|
// Invoke ephemeral operator with planning-phase context
|
|
2234
2234
|
const planDir = tree.plansDir || path.join(tree.featureDir, "plans");
|
|
2235
|
+
|
|
2236
|
+
// Stash context for retry if "Prompt is too long" — readSignal already deleted the file
|
|
2237
|
+
if (!this._lastOperatorContext) this._lastOperatorContext = {};
|
|
2238
|
+
this._lastOperatorContext[feature.slug] = { userMessage, planDir, tree, feature };
|
|
2239
|
+
|
|
2235
2240
|
try {
|
|
2236
2241
|
await invokeOperator({
|
|
2237
2242
|
feature,
|
|
@@ -2263,6 +2268,8 @@ export class Orchestrator {
|
|
|
2263
2268
|
if (exitCode === 0) {
|
|
2264
2269
|
queries.updateAgentStatus(agentId, "idle");
|
|
2265
2270
|
queries.resetAgentRetry(agentId);
|
|
2271
|
+
// Clean up stashed context
|
|
2272
|
+
if (this._lastOperatorContext) delete this._lastOperatorContext[feature.slug];
|
|
2266
2273
|
return;
|
|
2267
2274
|
}
|
|
2268
2275
|
|
|
@@ -2275,8 +2282,29 @@ export class Orchestrator {
|
|
|
2275
2282
|
|
|
2276
2283
|
console.log(`[orchestrator] Operator exited with code ${exitCode} after ${elapsed}ms — scheduling retry`);
|
|
2277
2284
|
|
|
2278
|
-
|
|
2279
|
-
|
|
2285
|
+
// Capture stashed context for the retry closure
|
|
2286
|
+
const stashedCtx = this._lastOperatorContext?.[feature.slug];
|
|
2287
|
+
|
|
2288
|
+
const retried = this.supervisor.scheduleRetry(agentId, async () => {
|
|
2289
|
+
// Retry with continue:false to start a fresh session (old session hit context limit).
|
|
2290
|
+
// Re-invoke the full Operator with the original user message so it doesn't lose context.
|
|
2291
|
+
if (stashedCtx) {
|
|
2292
|
+
console.log(`[orchestrator] Operator retry: re-invoking with original user message (continue:false)`);
|
|
2293
|
+
const freshFeature = queries.getFeatureById(feature.id) || feature;
|
|
2294
|
+
await invokeOperator({
|
|
2295
|
+
feature: freshFeature,
|
|
2296
|
+
operatorDir: tree.operator,
|
|
2297
|
+
flDir: tree.featureLead,
|
|
2298
|
+
featureDir: tree.featureDir,
|
|
2299
|
+
userMessage: stashedCtx.userMessage,
|
|
2300
|
+
supervisor: this.supervisor,
|
|
2301
|
+
agentId,
|
|
2302
|
+
planDir: stashedCtx.planDir,
|
|
2303
|
+
activePlanningRole: freshFeature.active_planning_role,
|
|
2304
|
+
continue: false,
|
|
2305
|
+
});
|
|
2306
|
+
return null; // invokeOperator already called supervisor.spawn
|
|
2307
|
+
}
|
|
2280
2308
|
return { prompt: "Re-read your CLAUDE.md and check for pending relay queue items or user messages. Write a status update to .agent-response if there's nothing to relay.", continue: false };
|
|
2281
2309
|
});
|
|
2282
2310
|
|