Skip to content

Commit a14ffcb

Browse files
authored
Missions tab overhaul and fixes
Ship the missions tab overhaul and review fixes from the ADE lane.
1 parent a00fb19 commit a14ffcb

136 files changed

Lines changed: 25331 additions & 2240 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/ade-cli/src/adeRpcServer.test.ts

Lines changed: 172 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,7 @@ function createRuntime() {
937937
})),
938938
finalizeRun: vi.fn(() => ({ finalized: true, blockers: [], finalStatus: "succeeded" })),
939939
cancelRunGracefully: vi.fn(async ({ runId }: any) => ({ cancelled: true, runId })),
940+
resumeRun: vi.fn(async ({ runId }: any) => ({ id: runId, status: "running" })),
940941
steerMission: vi.fn(({ missionId }: any) => ({ acknowledged: true, appliedAt: new Date().toISOString() })),
941942
getWorkerStates: vi.fn(({ runId }: any) => [
942943
{ attemptId: "a-1", stepId: "s-1", runId, state: "running" }
@@ -1242,6 +1243,7 @@ describe("adeRpcServer", () => {
12421243
"report_validation",
12431244
"delegate_to_subagent",
12441245
"delegate_parallel",
1246+
"message_worker",
12451247
"get_worker_output",
12461248
"list_workers",
12471249
"read_mission_status",
@@ -1257,7 +1259,6 @@ describe("adeRpcServer", () => {
12571259
"revise_plan",
12581260
"request_specialist",
12591261
"set_current_phase",
1260-
"message_worker",
12611262
"update_tool_profiles",
12621263
])
12631264
);
@@ -2704,6 +2705,127 @@ describe("adeRpcServer", () => {
27042705
});
27052706
});
27062707

2708+
it("queues message_worker handoffs for get_pending_messages when live delivery is unavailable", async () => {
2709+
await withEnv({ ADE_RUN_ID: "run-1" }, async () => {
2710+
const fixture = createRuntime();
2711+
fixture.runtime.orchestratorService.getRunGraph = vi.fn(() => ({
2712+
run: { id: "run-1", missionId: "mission-1", status: "running", metadata: {} },
2713+
steps: [
2714+
{
2715+
id: "step-a",
2716+
runId: "run-1",
2717+
missionStepId: null,
2718+
stepKey: "worker-a",
2719+
stepIndex: 0,
2720+
title: "Worker A",
2721+
laneId: "lane-1",
2722+
status: "running",
2723+
joinPolicy: "all_success",
2724+
quorumCount: null,
2725+
dependencyStepIds: [],
2726+
retryLimit: 1,
2727+
retryCount: 0,
2728+
lastAttemptId: "attempt-a",
2729+
createdAt: new Date().toISOString(),
2730+
updatedAt: new Date().toISOString(),
2731+
startedAt: new Date().toISOString(),
2732+
completedAt: null,
2733+
metadata: {}
2734+
},
2735+
{
2736+
id: "step-b",
2737+
runId: "run-1",
2738+
missionStepId: null,
2739+
stepKey: "worker-b",
2740+
stepIndex: 1,
2741+
title: "Worker B",
2742+
laneId: "lane-1",
2743+
status: "running",
2744+
joinPolicy: "all_success",
2745+
quorumCount: null,
2746+
dependencyStepIds: [],
2747+
retryLimit: 1,
2748+
retryCount: 0,
2749+
lastAttemptId: "attempt-b",
2750+
createdAt: new Date().toISOString(),
2751+
updatedAt: new Date().toISOString(),
2752+
startedAt: new Date().toISOString(),
2753+
completedAt: null,
2754+
metadata: {}
2755+
}
2756+
],
2757+
attempts: [
2758+
{ id: "attempt-a", stepId: "step-a", status: "running", createdAt: new Date().toISOString(), executorSessionId: "session-a" },
2759+
{ id: "attempt-b", stepId: "step-b", status: "running", createdAt: new Date().toISOString(), executorSessionId: "session-b" }
2760+
],
2761+
claims: [],
2762+
contextSnapshots: [],
2763+
handoffs: [],
2764+
timeline: [],
2765+
runtimeEvents: [],
2766+
completionEvaluation: null
2767+
}));
2768+
2769+
const senderHandler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
2770+
await initialize(senderHandler, {
2771+
callerId: "attempt-a",
2772+
role: "agent",
2773+
missionId: "mission-1",
2774+
runId: "run-1",
2775+
stepId: "step-a",
2776+
attemptId: "attempt-a"
2777+
});
2778+
const sent = await callTool(senderHandler, "message_worker", {
2779+
toWorkerId: "worker-b",
2780+
content: "contract is ready",
2781+
});
2782+
2783+
expect(sent?.isError).toBeUndefined();
2784+
expect(sent.structuredContent.ok).toBe(true);
2785+
expect(sent.structuredContent.delivered).toBe(false);
2786+
expect(sent.structuredContent.reason).toBe("queued_for_polling");
2787+
expect(fixture.runtime.aiOrchestratorService.sendAgentMessage).toHaveBeenCalledWith(
2788+
expect.objectContaining({
2789+
missionId: "mission-1",
2790+
fromAttemptId: "attempt-a",
2791+
toAttemptId: "attempt-b",
2792+
content: "contract is ready",
2793+
metadata: expect.objectContaining({
2794+
source: "message_worker",
2795+
fromWorkerId: "worker-a",
2796+
toWorkerId: "worker-b",
2797+
queuedForPolling: true
2798+
})
2799+
})
2800+
);
2801+
2802+
const recipientHandler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
2803+
await initialize(recipientHandler, {
2804+
callerId: "attempt-b",
2805+
role: "agent",
2806+
missionId: "mission-1",
2807+
runId: "run-1",
2808+
stepId: "step-b",
2809+
attemptId: "attempt-b"
2810+
});
2811+
const pending = await callTool(recipientHandler, "get_pending_messages", {});
2812+
2813+
expect(pending?.isError).toBeUndefined();
2814+
expect(pending.structuredContent.messages).toEqual(
2815+
expect.arrayContaining([
2816+
expect.objectContaining({
2817+
role: "agent",
2818+
content: "contract is ready",
2819+
metadata: expect.objectContaining({
2820+
source: "message_worker",
2821+
interAgentDelivery: true
2822+
})
2823+
})
2824+
])
2825+
);
2826+
});
2827+
});
2828+
27072829
it("surfaces native terminal rollups through get_pending_messages after report_result", async () => {
27082830
await withEnv({ ADE_RUN_ID: "run-1" }, async () => {
27092831
const fixture = createRuntime();
@@ -3625,6 +3747,28 @@ describe("adeRpcServer", () => {
36253747
expect(layoutGet.structuredContent.result).toEqual({ left: 100, right: 0 });
36263748
});
36273749

3750+
it("binds service method context when invoking dynamic ADE actions", async () => {
3751+
const fixture = createRuntime();
3752+
const missionService = fixture.runtime.missionService as any;
3753+
missionService.create = vi.fn(function (this: { get: (missionId: string) => unknown }, args: { prompt: string }) {
3754+
expect(args.prompt).toBe("smoke mission");
3755+
return this.get("mission-new");
3756+
});
3757+
const handler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
3758+
await initialize(handler, { callerId: "agent-1", role: "agent" });
3759+
3760+
const response = await callTool(handler, "run_ade_action", {
3761+
domain: "mission",
3762+
action: "create",
3763+
args: { prompt: "smoke mission" },
3764+
});
3765+
3766+
expect(response?.isError).toBeUndefined();
3767+
expect(missionService.create).toHaveBeenCalledWith({ prompt: "smoke mission" });
3768+
expect(response.structuredContent.result).toMatchObject({ id: "mission-new", status: "running" });
3769+
expect(response.structuredContent.statusHints.missionId).toBe("mission-new");
3770+
});
3771+
36283772
it("does not expose unlisted service methods through dynamic ADE actions", async () => {
36293773
const fixture = createRuntime();
36303774
const handler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
@@ -4245,7 +4389,7 @@ describe("adeRpcServer", () => {
42454389
);
42464390
});
42474391

4248-
it("routes resume_mission to orchestratorService.resumeRun", async () => {
4392+
it("routes resume_mission through aiOrchestratorService.resumeRun so coordinator runtime restarts", async () => {
42494393
const fixture = createRuntime();
42504394
const handler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
42514395

@@ -4255,7 +4399,7 @@ describe("adeRpcServer", () => {
42554399
expect(response?.isError).toBeUndefined();
42564400
expect(response.structuredContent.run.id).toBe("run-1");
42574401
expect(response.structuredContent.run.status).toBe("running");
4258-
expect(fixture.runtime.orchestratorService.resumeRun).toHaveBeenCalledWith({ runId: "run-1" });
4402+
expect(fixture.runtime.aiOrchestratorService.resumeRun).toHaveBeenCalledWith({ runId: "run-1" });
42594403
});
42604404

42614405
it("routes cancel_mission to aiOrchestratorService.cancelRunGracefully", async () => {
@@ -4411,6 +4555,23 @@ describe("adeRpcServer", () => {
44114555
it("routes get_worker_states to aiOrchestratorService.getWorkerStates", async () => {
44124556
const fixture = createRuntime();
44134557
const handler = createAdeRpcRequestHandler({ runtime: fixture.runtime, serverVersion: "test" });
4558+
fixture.runtime.orchestratorService.getRunGraph.mockReturnValueOnce({
4559+
run: { id: "run-1", missionId: "mission-1", status: "running" },
4560+
steps: [
4561+
{ id: "step-1", stepKey: "step-a", laneId: "lane-1", title: "Worker", status: "completed", retryCount: 0, metadata: {} },
4562+
{ id: "task-1", stepKey: "task-a", laneId: null, title: "Display task", status: "pending", retryCount: 0, metadata: { isTask: true } },
4563+
{ id: "system-1", stepKey: "system-a", laneId: null, title: "System", status: "pending", retryCount: 0, metadata: { systemManaged: true } },
4564+
{ id: "tracker-1", stepKey: "tracker-a", laneId: null, title: "Tracker", status: "pending", retryCount: 0, metadata: { plannerLaunchTracker: true } },
4565+
{ id: "planner-1", stepKey: "__planner__", laneId: null, title: "Planner", status: "succeeded", retryCount: 0, metadata: {} },
4566+
],
4567+
attempts: [{ id: "attempt-1", stepId: "step-1", status: "completed" }],
4568+
claims: [],
4569+
contextSnapshots: [],
4570+
handoffs: [],
4571+
timeline: [],
4572+
runtimeEvents: [],
4573+
completionEvaluation: null,
4574+
});
44144575

44154576
await initialize(handler, { role: "external" });
44164577
const response = await callTool(handler, "get_worker_states", { runId: "run-1" });
@@ -4419,7 +4580,15 @@ describe("adeRpcServer", () => {
44194580
expect(response.structuredContent.runId).toBe("run-1");
44204581
expect(response.structuredContent.workers).toHaveLength(1);
44214582
expect(response.structuredContent.workers[0].state).toBe("running");
4583+
expect(response.structuredContent.runWorkers).toHaveLength(1);
4584+
expect(response.structuredContent.runWorkers[0]).toMatchObject({
4585+
workerId: "step-a",
4586+
status: "completed",
4587+
});
44224588
expect(fixture.runtime.aiOrchestratorService.getWorkerStates).toHaveBeenCalledWith({ runId: "run-1" });
4589+
expect(fixture.runtime.orchestratorService.getRunGraph).toHaveBeenCalledWith(
4590+
expect.objectContaining({ runId: "run-1", timelineLimit: 0 })
4591+
);
44234592
});
44244593

44254594
it("routes get_timeline to orchestratorService.listTimeline", async () => {

0 commit comments

Comments
 (0)