import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { getTaskFlowById } from "../../tasks/task-flow-registry.js"; import { getTaskById } from "../../tasks/task-registry.js"; import { installRuntimeTaskDeliveryMock, resetRuntimeTaskTestState, } from "./runtime-task-test-harness.js"; import { createRuntimeTaskFlow } from "./runtime-taskflow.js"; afterEach(() => { resetRuntimeTaskTestState({ persist: false }); }); describe("runtime TaskFlow", () => { beforeEach(() => { installRuntimeTaskDeliveryMock(); }); it("binds managed TaskFlow operations to a session key", () => { const runtime = createRuntimeTaskFlow(); const taskFlow = runtime.bindSession({ sessionKey: "agent:main:main", requesterOrigin: { channel: "telegram", to: "telegram:123", }, }); const created = taskFlow.createManaged({ controllerId: "tests/runtime-taskflow", goal: "Triage inbox", currentStep: "classify", stateJson: { lane: "inbox" }, }); expect(created).toMatchObject({ syncMode: "managed", ownerKey: "agent:main:main", controllerId: "tests/runtime-taskflow", requesterOrigin: { channel: "telegram", to: "telegram:123", }, goal: "Triage inbox", }); expect(taskFlow.get(created.flowId)?.flowId).toBe(created.flowId); expect(taskFlow.findLatest()?.flowId).toBe(created.flowId); expect(taskFlow.resolve("agent:main:main")?.flowId).toBe(created.flowId); }); it("binds TaskFlows from trusted tool context", () => { const runtime = createRuntimeTaskFlow(); const taskFlow = runtime.fromToolContext({ sessionKey: "agent:main:main", deliveryContext: { channel: "discord", to: "channel:123", threadId: "thread:456", }, }); const created = taskFlow.createManaged({ controllerId: "tests/runtime-taskflow", goal: "Review queue", }); expect(created.requesterOrigin).toMatchObject({ channel: "discord", to: "channel:123", threadId: "thread:456", }); }); it("rejects tool contexts without a bound session key", () => { const runtime = createRuntimeTaskFlow(); expect(() => runtime.fromToolContext({ sessionKey: undefined, deliveryContext: undefined, }), ).toThrow("TaskFlow runtime requires tool context with a sessionKey."); }); it("keeps TaskFlow reads owner-scoped and runs child tasks under the bound TaskFlow", () => { const runtime = createRuntimeTaskFlow(); const ownerTaskFlow = runtime.bindSession({ sessionKey: "agent:main:main", }); const otherTaskFlow = runtime.bindSession({ sessionKey: "agent:main:other", }); const created = ownerTaskFlow.createManaged({ controllerId: "tests/runtime-taskflow", goal: "Inspect PR batch", }); expect(otherTaskFlow.get(created.flowId)).toBeUndefined(); expect(otherTaskFlow.list()).toEqual([]); const child = ownerTaskFlow.runTask({ flowId: created.flowId, runtime: "acp", childSessionKey: "agent:main:subagent:child", runId: "runtime-taskflow-child", task: "Inspect PR 1", status: "running", startedAt: 10, lastEventAt: 10, }); expect(child).toMatchObject({ created: true, flow: expect.objectContaining({ flowId: created.flowId, }), task: expect.objectContaining({ parentFlowId: created.flowId, ownerKey: "agent:main:main", runId: "runtime-taskflow-child", }), }); if (!child.created) { throw new Error("expected child task creation to succeed"); } expect(getTaskById(child.task.taskId)).toMatchObject({ parentFlowId: created.flowId, ownerKey: "agent:main:main", }); expect(getTaskFlowById(created.flowId)).toMatchObject({ flowId: created.flowId, }); expect(ownerTaskFlow.getTaskSummary(created.flowId)).toMatchObject({ total: 1, active: 1, }); }); });