Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions apps/vscode-e2e/src/fixtures/subtasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@ import { toolResultContains } from "./tool-result"

const SUBTASK_PARENT_MARKER = "SUBTASK_PARENT_CANCELLATION_SMOKE"
const SUBTASK_CHILD_MARKER = "SUBTASK_CHILD_CALCULATOR_SMOKE"
const SUBTASK_FAST_PARENT_MARKER = "SUBTASK_PARENT_IMMEDIATE_COMPLETION"
const SUBTASK_FAST_CHILD_MARKER = "SUBTASK_CHILD_IMMEDIATE_COMPLETION"
const SUBTASK_XPROFILE_PARENT_MARKER = "SUBTASK_PARENT_CROSS_PROFILE"
const SUBTASK_XPROFILE_SAME_CHILD_MARKER = "SUBTASK_CHILD_SAME_PROFILE"
const SUBTASK_XPROFILE_DIFFERENT_CHILD_MARKER = "SUBTASK_CHILD_DIFFERENT_PROFILE"

const SUBTASK_CHILD_PROMPT = `${SUBTASK_CHILD_MARKER}: Ask the user exactly this follow-up question: What is the square root of 81? After the user answers, complete with only the answer.`
export const SUBTASK_PARENT_PROMPT = `${SUBTASK_PARENT_MARKER}: Use the new_task tool exactly once. Create an ask-mode subtask with this exact message: "${SUBTASK_CHILD_PROMPT}" Do not answer directly.`
export const SUBTASK_CHILD_FOLLOWUP_ANSWER = "9"
const SUBTASK_FAST_CHILD_PROMPT = `${SUBTASK_FAST_CHILD_MARKER}: Complete immediately with the exact result "Fast child completed".`
export const SUBTASK_FAST_PARENT_PROMPT = `${SUBTASK_FAST_PARENT_MARKER}: Use the new_task tool exactly once. Create an ask-mode subtask with this exact message: "${SUBTASK_FAST_CHILD_PROMPT}" Do not answer directly.`

const SUBTASK_XPROFILE_SAME_CHILD_PROMPT = `${SUBTASK_XPROFILE_SAME_CHILD_MARKER}: Complete immediately with the exact result "Same-profile child completed".`
const SUBTASK_XPROFILE_DIFFERENT_CHILD_PROMPT = `${SUBTASK_XPROFILE_DIFFERENT_CHILD_MARKER}: Complete immediately with the exact result "Different-profile child completed".`
export const SUBTASK_XPROFILE_PARENT_PROMPT = `${SUBTASK_XPROFILE_PARENT_MARKER}: First use new_task to create a code-mode subtask with this exact message: "${SUBTASK_XPROFILE_SAME_CHILD_PROMPT}" After it returns, create an ask-mode subtask with the next instructions you receive.`
export const SUBTASK_XPROFILE_SAME_CHILD_RESULT = "Same-profile child completed"
export const SUBTASK_XPROFILE_DIFFERENT_CHILD_RESULT = "Different-profile child completed"
export const SUBTASK_XPROFILE_PARENT_RESULT = "Sequential cross-profile parent resumed"

const requestContains = (req: ChatCompletionRequest, expected: string[]) => {
const rawRequest = JSON.stringify(req)
Expand Down Expand Up @@ -40,6 +54,55 @@ const completionAfterAnswer = (followupId: string, completionId: string) => ({
})

export function addSubtaskFixtures(mock: InstanceType<typeof LLMock>) {
mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_FAST_PARENT_MARKER),
sequenceIndex: 0,
},
response: {
toolCalls: [
{
name: "new_task",
arguments: JSON.stringify({
mode: "ask",
message: SUBTASK_FAST_CHILD_PROMPT,
}),
id: "call_subtasks_fast_parent_new_task_001",
},
],
},
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.

mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_FAST_CHILD_MARKER),
},
response: {
toolCalls: [
{
name: "attempt_completion",
arguments: JSON.stringify({ result: "Fast child completed" }),
id: "call_subtasks_fast_child_completion_002",
},
],
},
})

mock.addFixture({
match: {
toolCallId: "call_subtasks_fast_parent_new_task_001",
},
response: {
toolCalls: [
{
name: "attempt_completion",
arguments: JSON.stringify({ result: "Fast parent resumed" }),
id: "call_subtasks_fast_parent_completion_003",
},
],
},
})

mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_PARENT_MARKER),
Expand Down Expand Up @@ -92,4 +155,95 @@ export function addSubtaskFixtures(mock: InstanceType<typeof LLMock>) {
],
},
})

// Issue #457 sequence: a same-profile child returns first, then the resumed
// parent delegates to a child whose mode uses a different API profile.
mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_XPROFILE_PARENT_MARKER),
sequenceIndex: 0,
},
response: {
toolCalls: [
{
name: "new_task",
arguments: JSON.stringify({
mode: "code",
message: SUBTASK_XPROFILE_SAME_CHILD_PROMPT,
}),
id: "call_subtasks_xprofile_parent_same_child_001",
},
],
},
})

mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_XPROFILE_SAME_CHILD_MARKER),
},
response: {
toolCalls: [
{
name: "attempt_completion",
arguments: JSON.stringify({ result: SUBTASK_XPROFILE_SAME_CHILD_RESULT }),
id: "call_subtasks_xprofile_same_child_completion_002",
},
],
},
})

mock.addFixture({
match: {
predicate: (req: ChatCompletionRequest) =>
requestContains(req, [SUBTASK_XPROFILE_PARENT_MARKER, SUBTASK_XPROFILE_SAME_CHILD_RESULT]) &&
!requestContains(req, [SUBTASK_XPROFILE_DIFFERENT_CHILD_RESULT]),
},
response: {
toolCalls: [
{
name: "new_task",
arguments: JSON.stringify({
mode: "ask",
message: SUBTASK_XPROFILE_DIFFERENT_CHILD_PROMPT,
}),
id: "call_subtasks_xprofile_parent_different_child_003",
},
],
},
})

mock.addFixture({
match: {
userMessage: new RegExp(SUBTASK_XPROFILE_DIFFERENT_CHILD_MARKER),
},
response: {
toolCalls: [
{
name: "attempt_completion",
arguments: JSON.stringify({ result: SUBTASK_XPROFILE_DIFFERENT_CHILD_RESULT }),
id: "call_subtasks_xprofile_different_child_completion_004",
},
],
},
})

mock.addFixture({
match: {
predicate: (req: ChatCompletionRequest) =>
requestContains(req, [
SUBTASK_XPROFILE_PARENT_MARKER,
SUBTASK_XPROFILE_SAME_CHILD_RESULT,
SUBTASK_XPROFILE_DIFFERENT_CHILD_RESULT,
]),
},
response: {
toolCalls: [
{
name: "attempt_completion",
arguments: JSON.stringify({ result: SUBTASK_XPROFILE_PARENT_RESULT }),
id: "call_subtasks_xprofile_parent_completion_005",
},
],
},
})
}
Loading
Loading