fix(gateway): accept music generation internal events

This commit is contained in:
Peter Steinberger
2026-04-06 02:18:04 +01:00
parent eba8fed94b
commit dd8525cacd
4 changed files with 68 additions and 8 deletions

View File

@@ -0,0 +1,14 @@
export const AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION = "task_completion" as const;
export const AGENT_INTERNAL_EVENT_SOURCES = [
"subagent",
"cron",
"video_generation",
"music_generation",
] as const;
export const AGENT_INTERNAL_EVENT_STATUSES = ["ok", "timeout", "error", "unknown"] as const;
export type AgentInternalEventType = typeof AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION;
export type AgentInternalEventSource = (typeof AGENT_INTERNAL_EVENT_SOURCES)[number];
export type AgentInternalEventStatus = (typeof AGENT_INTERNAL_EVENT_STATUSES)[number];

View File

@@ -1,19 +1,22 @@
import {
AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION,
type AgentInternalEventSource,
type AgentInternalEventStatus,
} from "./internal-event-contract.js";
import {
escapeInternalRuntimeContextDelimiters,
INTERNAL_RUNTIME_CONTEXT_BEGIN,
INTERNAL_RUNTIME_CONTEXT_END,
} from "./internal-runtime-context.js";
export type AgentInternalEventType = "task_completion";
export type AgentTaskCompletionInternalEvent = {
type: "task_completion";
source: "subagent" | "cron" | "video_generation" | "music_generation";
type: typeof AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION;
source: AgentInternalEventSource;
childSessionKey: string;
childSessionId?: string;
announceType: string;
taskLabel: string;
status: "ok" | "timeout" | "error" | "unknown";
status: AgentInternalEventStatus;
statusLabel: string;
result: string;
statsLine?: string;

View File

@@ -1,15 +1,20 @@
import { Type } from "@sinclair/typebox";
import {
AGENT_INTERNAL_EVENT_SOURCES,
AGENT_INTERNAL_EVENT_STATUSES,
AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION,
} from "../../../agents/internal-event-contract.js";
import { InputProvenanceSchema, NonEmptyString, SessionLabelString } from "./primitives.js";
export const AgentInternalEventSchema = Type.Object(
{
type: Type.Literal("task_completion"),
source: Type.String({ enum: ["subagent", "cron", "video_generation"] }),
type: Type.Literal(AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION),
source: Type.String({ enum: [...AGENT_INTERNAL_EVENT_SOURCES] }),
childSessionKey: Type.String(),
childSessionId: Type.Optional(Type.String()),
announceType: Type.String(),
taskLabel: Type.String(),
status: Type.String({ enum: ["ok", "timeout", "error", "unknown"] }),
status: Type.String({ enum: [...AGENT_INTERNAL_EVENT_STATUSES] }),
statusLabel: Type.String(),
result: Type.String(),
statsLine: Type.Optional(Type.String()),

View File

@@ -759,6 +759,44 @@ describe("gateway agent handler", () => {
);
});
it("accepts music generation internal events", async () => {
primeMainAgentRun();
mocks.agentCommand.mockClear();
const respond = vi.fn();
await invokeAgent(
{
message: "music generation finished",
sessionKey: "agent:main:main",
internalEvents: [
{
type: "task_completion",
source: "music_generation",
childSessionKey: "music:task-123",
childSessionId: "task-123",
announceType: "music generation task",
taskLabel: "compose a loop",
status: "ok",
statusLabel: "completed successfully",
result: "MEDIA: https://example.test/song.mp3",
replyInstruction: "Reply in your normal assistant voice now.",
},
],
idempotencyKey: "music-generation-event",
},
{ reqId: "music-generation-event-1", respond },
);
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
expect(respond).not.toHaveBeenCalledWith(
false,
undefined,
expect.objectContaining({
message: expect.stringContaining("invalid agent params"),
}),
);
});
it("only forwards workspaceDir for spawned sessions with stored workspace inheritance", async () => {
primeMainAgentRun();
mockMainSessionEntry({