mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(codex): stop phantom parent subagents (#2214)
This commit is contained in:
@@ -3144,6 +3144,115 @@ describe("Codex app-server provider", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test("does not import a parent interaction from child history as another sub-agent", async () => {
|
||||
const appServer = createFakeCodexAppServer({
|
||||
"thread/read": (params) => {
|
||||
const threadId = (params as { threadId?: string }).threadId;
|
||||
if (threadId === "test-thread") {
|
||||
return {
|
||||
thread: {
|
||||
turns: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
type: "subAgentActivity",
|
||||
id: "child-started",
|
||||
kind: "started",
|
||||
agentThreadId: "child-thread",
|
||||
agentPath: "/root/child",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
thread: {
|
||||
turns: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
type: "subAgentActivity",
|
||||
id: "parent-interacted",
|
||||
kind: "interacted",
|
||||
agentThreadId: "test-thread",
|
||||
agentPath: "/root",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
const session = new CodexAppServerAgentSession(
|
||||
createConfig({ cwd: "/workspace/project" }),
|
||||
{ sessionId: "test-thread" },
|
||||
createTestLogger(),
|
||||
async () => appServer.child,
|
||||
);
|
||||
|
||||
try {
|
||||
await session.connect();
|
||||
|
||||
const providerSubagentIds = new Set<string>();
|
||||
for await (const event of session.streamHistory()) {
|
||||
if (event.type === "provider_subagent" && event.event.type === "upsert") {
|
||||
providerSubagentIds.add(event.event.id);
|
||||
}
|
||||
}
|
||||
|
||||
expect(providerSubagentIds).toEqual(new Set(["child-thread"]));
|
||||
appServer.assertNoErrors();
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("does not register a parent interaction on a child thread as another sub-agent", async () => {
|
||||
const appServer = createFakeCodexAppServer();
|
||||
const session = new CodexAppServerAgentSession(
|
||||
createConfig({ cwd: "/workspace/project" }),
|
||||
null,
|
||||
createTestLogger(),
|
||||
async () => appServer.child,
|
||||
);
|
||||
const providerSubagentIds = new Set<string>();
|
||||
session.subscribe((event) => {
|
||||
if (event.type === "provider_subagent" && event.event.type === "upsert") {
|
||||
providerSubagentIds.add(event.event.id);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const resultPromise = session.run("Delegate the investigation.");
|
||||
await appServer.waitForTurnStart();
|
||||
|
||||
const child = waitForProviderSubagent(session, "child-thread");
|
||||
appServer.startsSubAgent({
|
||||
callId: "child-started",
|
||||
threadId: "child-thread",
|
||||
agentPath: "/root/child",
|
||||
});
|
||||
await child;
|
||||
appServer.beginsSubAgentActivity({
|
||||
callId: "parent-interacted",
|
||||
threadId: "thread-1",
|
||||
parentThreadId: "child-thread",
|
||||
kind: "interacted",
|
||||
agentPath: "/root",
|
||||
});
|
||||
appServer.completeTurn();
|
||||
await resultPromise;
|
||||
|
||||
expect(providerSubagentIds).toEqual(new Set(["child-thread"]));
|
||||
appServer.assertNoErrors();
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("uses Codex turn timestamps for timestamp-less persisted history items", async () => {
|
||||
const session = createSession();
|
||||
session.client = {
|
||||
|
||||
@@ -3503,7 +3503,7 @@ export class CodexAppServerAgentSession implements AgentSession {
|
||||
rootRoutes: readonly PersistedSubAgentRoute[],
|
||||
): Promise<void> {
|
||||
const queue = rootRoutes.map((route) => ({ route, parentCallId: null as string | null }));
|
||||
const visitedThreadIds = new Set<string>();
|
||||
const visitedThreadIds = new Set(this.currentThreadId ? [this.currentThreadId] : []);
|
||||
while (queue.length > 0 && visitedThreadIds.size < 100) {
|
||||
const next = queue.shift();
|
||||
if (!next || visitedThreadIds.has(next.route.childThreadId)) {
|
||||
@@ -4831,7 +4831,7 @@ export class CodexAppServerAgentSession implements AgentSession {
|
||||
: null;
|
||||
const childThreadIds = Array.from(
|
||||
new Set(agentThreadId ? [...receiverThreadIds, agentThreadId] : receiverThreadIds),
|
||||
);
|
||||
).filter((threadId) => threadId !== this.currentThreadId);
|
||||
for (const receiverThreadId of childThreadIds) {
|
||||
this.subAgentCallIdByChildThreadId.set(receiverThreadId, timelineItem.callId);
|
||||
state.childThreadIds.add(receiverThreadId);
|
||||
|
||||
Reference in New Issue
Block a user