@elizaos/plugin-agent-orchestrator 0.3.4 → 0.3.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/dist/actions/coding-task-handlers.d.ts +46 -0
- package/dist/actions/coding-task-handlers.d.ts.map +1 -0
- package/dist/actions/coding-task-helpers.d.ts +27 -0
- package/dist/actions/coding-task-helpers.d.ts.map +1 -0
- package/dist/actions/finalize-workspace.d.ts +11 -0
- package/dist/actions/finalize-workspace.d.ts.map +1 -0
- package/dist/actions/list-agents.d.ts +11 -0
- package/dist/actions/list-agents.d.ts.map +1 -0
- package/dist/actions/manage-issues.d.ts +11 -0
- package/dist/actions/manage-issues.d.ts.map +1 -0
- package/dist/actions/provision-workspace.d.ts +11 -0
- package/dist/actions/provision-workspace.d.ts.map +1 -0
- package/dist/actions/send-to-agent.d.ts +11 -0
- package/dist/actions/send-to-agent.d.ts.map +1 -0
- package/dist/actions/spawn-agent.d.ts +11 -0
- package/dist/actions/spawn-agent.d.ts.map +1 -0
- package/dist/actions/start-coding-task.d.ts +17 -0
- package/dist/actions/start-coding-task.d.ts.map +1 -0
- package/dist/actions/stop-agent.d.ts +11 -0
- package/dist/actions/stop-agent.d.ts.map +1 -0
- package/dist/api/agent-routes.d.ts +18 -0
- package/dist/api/agent-routes.d.ts.map +1 -0
- package/dist/api/coordinator-routes.d.ts +22 -0
- package/dist/api/coordinator-routes.d.ts.map +1 -0
- package/dist/api/issue-routes.d.ts +17 -0
- package/dist/api/issue-routes.d.ts.map +1 -0
- package/dist/api/routes.d.ts +36 -0
- package/dist/api/routes.d.ts.map +1 -0
- package/dist/api/workspace-routes.d.ts +17 -0
- package/dist/api/workspace-routes.d.ts.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -3
- package/dist/index.js.map +8 -8
- package/dist/providers/action-examples.d.ts +13 -0
- package/dist/providers/action-examples.d.ts.map +1 -0
- package/dist/providers/active-workspace-context.d.ts +13 -0
- package/dist/providers/active-workspace-context.d.ts.map +1 -0
- package/dist/services/agent-metrics.d.ts +28 -0
- package/dist/services/agent-metrics.d.ts.map +1 -0
- package/dist/services/agent-selection.d.ts +53 -0
- package/dist/services/agent-selection.d.ts.map +1 -0
- package/dist/services/ansi-utils.d.ts +48 -0
- package/dist/services/ansi-utils.d.ts.map +1 -0
- package/dist/services/pty-auto-response.d.ts +30 -0
- package/dist/services/pty-auto-response.d.ts.map +1 -0
- package/dist/services/pty-init.d.ts +47 -0
- package/dist/services/pty-init.d.ts.map +1 -0
- package/dist/services/pty-service.d.ts +92 -0
- package/dist/services/pty-service.d.ts.map +1 -0
- package/dist/services/pty-session-io.d.ts +49 -0
- package/dist/services/pty-session-io.d.ts.map +1 -0
- package/dist/services/pty-spawn.d.ts +50 -0
- package/dist/services/pty-types.d.ts +80 -0
- package/dist/services/pty-types.d.ts.map +1 -0
- package/dist/services/stall-classifier.d.ts +67 -0
- package/dist/services/stall-classifier.d.ts.map +1 -1
- package/dist/services/swarm-coordinator-prompts.d.ts +75 -0
- package/dist/services/swarm-coordinator-prompts.d.ts.map +1 -0
- package/dist/services/swarm-coordinator.d.ts +200 -0
- package/dist/services/swarm-coordinator.d.ts.map +1 -0
- package/dist/services/swarm-decision-loop.d.ts +44 -0
- package/dist/services/swarm-decision-loop.d.ts.map +1 -0
- package/dist/services/swarm-event-triage.d.ts +49 -0
- package/dist/services/swarm-event-triage.d.ts.map +1 -0
- package/dist/services/swarm-idle-watchdog.d.ts +22 -0
- package/dist/services/swarm-idle-watchdog.d.ts.map +1 -0
- package/dist/services/workspace-git-ops.d.ts +28 -0
- package/dist/services/workspace-git-ops.d.ts.map +1 -0
- package/dist/services/workspace-github.d.ts +58 -0
- package/dist/services/workspace-github.d.ts.map +1 -0
- package/dist/services/workspace-lifecycle.d.ts +18 -0
- package/dist/services/workspace-lifecycle.d.ts.map +1 -0
- package/dist/services/workspace-service.d.ts +84 -0
- package/dist/services/workspace-service.d.ts.map +1 -0
- package/dist/services/workspace-types.d.ts +81 -0
- package/dist/services/workspace-types.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -490,6 +490,17 @@ function toDecisionHistory(taskCtx) {
|
|
|
490
490
|
reasoning: d.reasoning
|
|
491
491
|
}));
|
|
492
492
|
}
|
|
493
|
+
async function drainPendingTurnComplete(ctx, sessionId) {
|
|
494
|
+
if (!ctx.pendingTurnComplete.has(sessionId))
|
|
495
|
+
return;
|
|
496
|
+
const pendingData = ctx.pendingTurnComplete.get(sessionId);
|
|
497
|
+
ctx.pendingTurnComplete.delete(sessionId);
|
|
498
|
+
const taskCtx = ctx.tasks.get(sessionId);
|
|
499
|
+
if (!taskCtx || taskCtx.status !== "active")
|
|
500
|
+
return;
|
|
501
|
+
ctx.log(`Draining buffered turn-complete for "${taskCtx.label}"`);
|
|
502
|
+
await handleTurnComplete(ctx, sessionId, taskCtx, pendingData);
|
|
503
|
+
}
|
|
493
504
|
function formatDecisionResponse(decision) {
|
|
494
505
|
if (decision.action !== "respond")
|
|
495
506
|
return;
|
|
@@ -721,7 +732,8 @@ async function handleBlocked(ctx, sessionId, taskCtx, data) {
|
|
|
721
732
|
}
|
|
722
733
|
async function handleTurnComplete(ctx, sessionId, taskCtx, data) {
|
|
723
734
|
if (ctx.inFlightDecisions.has(sessionId)) {
|
|
724
|
-
ctx.log(`
|
|
735
|
+
ctx.log(`Buffering turn-complete for ${sessionId} (in-flight decision running)`);
|
|
736
|
+
ctx.pendingTurnComplete.set(sessionId, data);
|
|
725
737
|
return;
|
|
726
738
|
}
|
|
727
739
|
ctx.inFlightDecisions.add(sessionId);
|
|
@@ -813,6 +825,7 @@ async function handleTurnComplete(ctx, sessionId, taskCtx, data) {
|
|
|
813
825
|
await executeDecision(ctx, sessionId, decision);
|
|
814
826
|
} finally {
|
|
815
827
|
ctx.inFlightDecisions.delete(sessionId);
|
|
828
|
+
await drainPendingTurnComplete(ctx, sessionId);
|
|
816
829
|
}
|
|
817
830
|
}
|
|
818
831
|
async function handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
@@ -914,6 +927,7 @@ async function handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, rec
|
|
|
914
927
|
await executeDecision(ctx, sessionId, decision);
|
|
915
928
|
} finally {
|
|
916
929
|
ctx.inFlightDecisions.delete(sessionId);
|
|
930
|
+
await drainPendingTurnComplete(ctx, sessionId);
|
|
917
931
|
}
|
|
918
932
|
}
|
|
919
933
|
async function handleConfirmDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
@@ -989,6 +1003,7 @@ async function handleConfirmDecision(ctx, sessionId, taskCtx, promptText, recent
|
|
|
989
1003
|
});
|
|
990
1004
|
} finally {
|
|
991
1005
|
ctx.inFlightDecisions.delete(sessionId);
|
|
1006
|
+
await drainPendingTurnComplete(ctx, sessionId);
|
|
992
1007
|
}
|
|
993
1008
|
}
|
|
994
1009
|
var MAX_AUTO_RESPONSES = 10;
|
|
@@ -2754,6 +2769,130 @@ async function classifyStallOutput(ctx) {
|
|
|
2754
2769
|
return null;
|
|
2755
2770
|
}
|
|
2756
2771
|
}
|
|
2772
|
+
function buildCombinedClassifyDecidePrompt(agentType, sessionId, output, taskContext, decisionHistory) {
|
|
2773
|
+
const historySection = decisionHistory.length > 0 ? `
|
|
2774
|
+
Previous decisions for this session:
|
|
2775
|
+
${decisionHistory.slice(-5).map((d, i) => ` ${i + 1}. [${d.event}] prompt="${d.promptText}" → ${d.action}${d.response ? ` ("${d.response}")` : ""} — ${d.reasoning}`).join(`
|
|
2776
|
+
`)}
|
|
2777
|
+
` : "";
|
|
2778
|
+
return `You are Milady, an AI orchestrator managing coding agent sessions. A ${agentType} coding agent (session: ${sessionId}) appears to have stalled — ` + `it has stopped producing output while in a busy state.
|
|
2779
|
+
|
|
2780
|
+
Original task: "${taskContext.originalTask}"
|
|
2781
|
+
Working directory: ${taskContext.workdir}
|
|
2782
|
+
Repository: ${taskContext.repo ?? "none (scratch directory)"}
|
|
2783
|
+
` + historySection + `
|
|
2784
|
+
Here is the recent terminal output:
|
|
2785
|
+
---
|
|
2786
|
+
${output.slice(-1500)}
|
|
2787
|
+
---
|
|
2788
|
+
|
|
2789
|
+
Classify what's happening AND decide how to respond. Read the output carefully.
|
|
2790
|
+
|
|
2791
|
+
Classification states:
|
|
2792
|
+
|
|
2793
|
+
` + `1. "task_complete" — The agent FINISHED its task and returned to its idle prompt. ` + `Strong indicators: a summary of completed work, timing info, ` + `or the agent's main prompt symbol (❯) appearing AFTER completion output.
|
|
2794
|
+
|
|
2795
|
+
` + `2. "waiting_for_input" — The agent is MID-TASK and blocked on a specific question or permission prompt. ` + `Examples: Y/n confirmation, file permission dialogs, tool approval prompts, interactive menus.
|
|
2796
|
+
|
|
2797
|
+
` + `3. "still_working" — The agent is actively processing (API call, compilation, thinking). ` + `No prompt or completion summary visible.
|
|
2798
|
+
|
|
2799
|
+
` + `4. "error" — The agent hit an error state (crash, unrecoverable error, stack trace).
|
|
2800
|
+
|
|
2801
|
+
` + `5. "tool_running" — The agent is using an external tool (browser automation, MCP tool, etc.).
|
|
2802
|
+
|
|
2803
|
+
` + `If "waiting_for_input", you must also decide how to respond. Guidelines:
|
|
2804
|
+
- IMPORTANT: If the prompt asks to approve access to files or directories OUTSIDE the working directory (${taskContext.workdir}), DECLINE the request. Respond with "n" and tell the agent: "That path is outside your workspace. Use ${taskContext.workdir} instead."
|
|
2805
|
+
- For tool approval prompts (file writes, shell commands), respond "y" or use "keys:enter".
|
|
2806
|
+
- For Y/n confirmations that align with the original task, respond "y".
|
|
2807
|
+
- For TUI menus, use "keys:enter" for default or "keys:down,enter" for non-default.
|
|
2808
|
+
- If the prompt asks for information NOT in the original task, set suggestedResponse to null (this will escalate to the human).
|
|
2809
|
+
- If a PR was just created, respond to review & verify test plan items before completing.
|
|
2810
|
+
|
|
2811
|
+
Respond with ONLY a JSON object:
|
|
2812
|
+
{"state": "...", "prompt": "...", "suggestedResponse": "..."}`;
|
|
2813
|
+
}
|
|
2814
|
+
async function classifyAndDecideForCoordinator(ctx) {
|
|
2815
|
+
const {
|
|
2816
|
+
sessionId,
|
|
2817
|
+
recentOutput,
|
|
2818
|
+
agentType,
|
|
2819
|
+
buffers,
|
|
2820
|
+
traceEntries,
|
|
2821
|
+
runtime,
|
|
2822
|
+
manager,
|
|
2823
|
+
metricsTracker,
|
|
2824
|
+
taskContext,
|
|
2825
|
+
decisionHistory = [],
|
|
2826
|
+
log
|
|
2827
|
+
} = ctx;
|
|
2828
|
+
metricsTracker.incrementStalls(agentType);
|
|
2829
|
+
let effectiveOutput = recentOutput;
|
|
2830
|
+
if (!recentOutput || recentOutput.trim().length < 200) {
|
|
2831
|
+
const ourBuffer = buffers.get(sessionId);
|
|
2832
|
+
if (ourBuffer && ourBuffer.length > 0) {
|
|
2833
|
+
const rawTail = ourBuffer.slice(-100).join(`
|
|
2834
|
+
`);
|
|
2835
|
+
const stripped = stripAnsi(rawTail);
|
|
2836
|
+
if (stripped.length > effectiveOutput.length) {
|
|
2837
|
+
effectiveOutput = stripped;
|
|
2838
|
+
log(`Using own buffer for combined classify+decide (${effectiveOutput.length} chars after stripping, pty-manager had ${recentOutput.length})`);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
const systemPrompt = buildCombinedClassifyDecidePrompt(agentType, sessionId, effectiveOutput, taskContext, decisionHistory);
|
|
2843
|
+
if (ctx.debugSnapshots) {
|
|
2844
|
+
await writeStallSnapshot(sessionId, agentType, recentOutput, effectiveOutput, buffers, traceEntries, log);
|
|
2845
|
+
}
|
|
2846
|
+
try {
|
|
2847
|
+
log(`Stall detected for coordinator-managed ${sessionId}, combined classify+decide...`);
|
|
2848
|
+
const result = await runtime.useModel(ModelType.TEXT_SMALL, {
|
|
2849
|
+
prompt: systemPrompt
|
|
2850
|
+
});
|
|
2851
|
+
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
2852
|
+
if (!jsonMatch) {
|
|
2853
|
+
log(`Combined classify+decide: no JSON in LLM response`);
|
|
2854
|
+
return null;
|
|
2855
|
+
}
|
|
2856
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
2857
|
+
const validStates = [
|
|
2858
|
+
"waiting_for_input",
|
|
2859
|
+
"still_working",
|
|
2860
|
+
"task_complete",
|
|
2861
|
+
"error",
|
|
2862
|
+
"tool_running"
|
|
2863
|
+
];
|
|
2864
|
+
if (!validStates.includes(parsed.state)) {
|
|
2865
|
+
log(`Combined classify+decide: invalid state "${parsed.state}"`);
|
|
2866
|
+
return null;
|
|
2867
|
+
}
|
|
2868
|
+
const mappedState = parsed.state === "tool_running" ? "still_working" : parsed.state;
|
|
2869
|
+
if (mappedState === "waiting_for_input" && parsed.suggestedResponse) {
|
|
2870
|
+
const promptText = typeof parsed.prompt === "string" ? parsed.prompt : "";
|
|
2871
|
+
const responseText = parsed.suggestedResponse.trim().toLowerCase();
|
|
2872
|
+
const approving = ["y", "yes", "keys:enter", "keys:down,enter"].includes(responseText);
|
|
2873
|
+
const hasAbsPath = /(?:^|[\s"'`])\/[^\s"'`]+/.test(promptText);
|
|
2874
|
+
if (approving && hasAbsPath && !promptText.includes(taskContext.workdir)) {
|
|
2875
|
+
log(`Combined classify+decide: overriding out-of-scope approval for ${sessionId}`);
|
|
2876
|
+
parsed.suggestedResponse = `n — That path is outside your workspace. Use ${taskContext.workdir} instead.`;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
const classification = {
|
|
2880
|
+
state: mappedState,
|
|
2881
|
+
prompt: parsed.prompt,
|
|
2882
|
+
suggestedResponse: parsed.suggestedResponse
|
|
2883
|
+
};
|
|
2884
|
+
log(`Combined classify+decide for ${sessionId}: ${classification.state}${classification.suggestedResponse ? ` → "${classification.suggestedResponse}"` : ""}`);
|
|
2885
|
+
if (classification.state === "task_complete") {
|
|
2886
|
+
const session = manager?.get(sessionId);
|
|
2887
|
+
const durationMs = session?.startedAt ? Date.now() - new Date(session.startedAt).getTime() : 0;
|
|
2888
|
+
metricsTracker.recordCompletion(agentType, "classifier", durationMs);
|
|
2889
|
+
}
|
|
2890
|
+
return classification;
|
|
2891
|
+
} catch (err) {
|
|
2892
|
+
log(`Combined classify+decide failed: ${err}`);
|
|
2893
|
+
return null;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2757
2896
|
|
|
2758
2897
|
// src/services/swarm-coordinator.ts
|
|
2759
2898
|
init_ansi_utils();
|
|
@@ -2947,6 +3086,7 @@ class SwarmCoordinator {
|
|
|
2947
3086
|
supervisionLevel = "autonomous";
|
|
2948
3087
|
pendingDecisions = new Map;
|
|
2949
3088
|
inFlightDecisions = new Set;
|
|
3089
|
+
pendingTurnComplete = new Map;
|
|
2950
3090
|
chatCallback = null;
|
|
2951
3091
|
wsBroadcast = null;
|
|
2952
3092
|
agentDecisionCb = null;
|
|
@@ -3014,6 +3154,7 @@ class SwarmCoordinator {
|
|
|
3014
3154
|
this.tasks.clear();
|
|
3015
3155
|
this.pendingDecisions.clear();
|
|
3016
3156
|
this.inFlightDecisions.clear();
|
|
3157
|
+
this.pendingTurnComplete.clear();
|
|
3017
3158
|
this.unregisteredBuffer.clear();
|
|
3018
3159
|
this.lastSeenOutput.clear();
|
|
3019
3160
|
this.lastToolNotification.clear();
|
|
@@ -3708,6 +3849,38 @@ class PTYService {
|
|
|
3708
3849
|
async classifyStall(sessionId, recentOutput) {
|
|
3709
3850
|
const meta = this.sessionMetadata.get(sessionId);
|
|
3710
3851
|
const agentType = meta?.agentType ?? "unknown";
|
|
3852
|
+
if (meta?.coordinatorManaged && this.coordinator?.getSupervisionLevel() === "autonomous") {
|
|
3853
|
+
const taskCtx = this.coordinator.getTaskContext(sessionId);
|
|
3854
|
+
if (taskCtx) {
|
|
3855
|
+
return classifyAndDecideForCoordinator({
|
|
3856
|
+
sessionId,
|
|
3857
|
+
recentOutput,
|
|
3858
|
+
agentType,
|
|
3859
|
+
buffers: this.sessionOutputBuffers,
|
|
3860
|
+
traceEntries: this.traceEntries,
|
|
3861
|
+
runtime: this.runtime,
|
|
3862
|
+
manager: this.manager,
|
|
3863
|
+
metricsTracker: this.metricsTracker,
|
|
3864
|
+
debugSnapshots: this.serviceConfig.debug === true,
|
|
3865
|
+
log: (msg) => this.log(msg),
|
|
3866
|
+
taskContext: {
|
|
3867
|
+
sessionId: taskCtx.sessionId,
|
|
3868
|
+
agentType: taskCtx.agentType,
|
|
3869
|
+
label: taskCtx.label,
|
|
3870
|
+
originalTask: taskCtx.originalTask,
|
|
3871
|
+
workdir: taskCtx.workdir,
|
|
3872
|
+
repo: taskCtx.repo
|
|
3873
|
+
},
|
|
3874
|
+
decisionHistory: taskCtx.decisions.filter((d) => d.decision !== "auto_resolved").slice(-5).map((d) => ({
|
|
3875
|
+
event: d.event,
|
|
3876
|
+
promptText: d.promptText,
|
|
3877
|
+
action: d.decision,
|
|
3878
|
+
response: d.response,
|
|
3879
|
+
reasoning: d.reasoning
|
|
3880
|
+
}))
|
|
3881
|
+
});
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3711
3884
|
const classification = await classifyStallOutput({
|
|
3712
3885
|
sessionId,
|
|
3713
3886
|
recentOutput,
|
|
@@ -4184,7 +4357,7 @@ async function handleMultiAgent(ctx, agentsParam) {
|
|
|
4184
4357
|
let specRequestedType = rawAgentType;
|
|
4185
4358
|
let specTask = spec;
|
|
4186
4359
|
const colonIdx = spec.indexOf(":");
|
|
4187
|
-
if (colonIdx > 0 && colonIdx < 20) {
|
|
4360
|
+
if (ctx.agentSelectionStrategy !== "fixed" && colonIdx > 0 && colonIdx < 20) {
|
|
4188
4361
|
const prefix = spec.slice(0, colonIdx).trim().toLowerCase();
|
|
4189
4362
|
const knownTypes = [
|
|
4190
4363
|
"claude",
|
|
@@ -4209,6 +4382,28 @@ async function handleMultiAgent(ctx, agentsParam) {
|
|
|
4209
4382
|
specAgentType = normalizeAgentType(prefix);
|
|
4210
4383
|
specTask = spec.slice(colonIdx + 1).trim();
|
|
4211
4384
|
}
|
|
4385
|
+
} else if (ctx.agentSelectionStrategy === "fixed" && colonIdx > 0 && colonIdx < 20) {
|
|
4386
|
+
const prefix = spec.slice(0, colonIdx).trim().toLowerCase();
|
|
4387
|
+
const knownTypes = [
|
|
4388
|
+
"claude",
|
|
4389
|
+
"claude-code",
|
|
4390
|
+
"claudecode",
|
|
4391
|
+
"codex",
|
|
4392
|
+
"openai",
|
|
4393
|
+
"gemini",
|
|
4394
|
+
"google",
|
|
4395
|
+
"aider",
|
|
4396
|
+
"pi",
|
|
4397
|
+
"pi-ai",
|
|
4398
|
+
"piai",
|
|
4399
|
+
"pi-coding-agent",
|
|
4400
|
+
"picodingagent",
|
|
4401
|
+
"shell",
|
|
4402
|
+
"bash"
|
|
4403
|
+
];
|
|
4404
|
+
if (knownTypes.includes(prefix)) {
|
|
4405
|
+
specTask = spec.slice(colonIdx + 1).trim();
|
|
4406
|
+
}
|
|
4212
4407
|
}
|
|
4213
4408
|
const specLabel = explicitLabel ? `${explicitLabel}-${i + 1}` : generateLabel(repo, specTask);
|
|
4214
4409
|
try {
|
|
@@ -4583,6 +4778,7 @@ var startCodingTaskAction = {
|
|
|
4583
4778
|
repo,
|
|
4584
4779
|
defaultAgentType,
|
|
4585
4780
|
rawAgentType,
|
|
4781
|
+
agentSelectionStrategy: ptyService.agentSelectionStrategy,
|
|
4586
4782
|
memoryContent,
|
|
4587
4783
|
approvalPreset,
|
|
4588
4784
|
explicitLabel
|
|
@@ -6360,5 +6556,5 @@ export {
|
|
|
6360
6556
|
CodingWorkspaceService
|
|
6361
6557
|
};
|
|
6362
6558
|
|
|
6363
|
-
//# debugId=
|
|
6559
|
+
//# debugId=D5A4E2FBAF42C88664756E2164756E21
|
|
6364
6560
|
//# sourceMappingURL=index.js.map
|