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
78 changes: 76 additions & 2 deletions src/core/Cline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ export class Cline {

let newUserContent: UserContent = [...modifiedOldUserContent]

const agoText = (() => {
const agoText = ((): string => {
const timestamp = lastClineMessage?.ts ?? Date.now()
const now = Date.now()
const diff = now - timestamp
Expand Down Expand Up @@ -996,7 +996,7 @@ export class Cline {
break
}
case "tool_use":
const toolDescription = () => {
const toolDescription = (): string => {
switch (block.name) {
case "execute_command":
return `[${block.name} for '${block.params.command}']`
Expand Down Expand Up @@ -1030,6 +1030,12 @@ export class Cline {
return `[${block.name}]`
case "switch_mode":
return `[${block.name} to '${block.params.mode_slug}'${block.params.reason ? ` because: ${block.params.reason}` : ""}]`
case "new_task": {
const mode = block.params.mode ?? defaultModeSlug
const message = block.params.message ?? "(no message)"
const modeName = getModeBySlug(mode, customModes)?.name ?? mode
return `[${block.name} in ${modeName} mode: '${message}']`
}
}
}

Expand Down Expand Up @@ -2402,6 +2408,74 @@ export class Cline {
}
}

case "new_task": {
const mode: string | undefined = block.params.mode
const message: string | undefined = block.params.message
try {
if (block.partial) {
const partialMessage = JSON.stringify({
tool: "newTask",
mode: removeClosingTag("mode", mode),
message: removeClosingTag("message", message),
})
await this.ask("tool", partialMessage, block.partial).catch(() => {})
break
} else {
if (!mode) {
this.consecutiveMistakeCount++
pushToolResult(await this.sayAndCreateMissingParamError("new_task", "mode"))
break
}
if (!message) {
this.consecutiveMistakeCount++
pushToolResult(await this.sayAndCreateMissingParamError("new_task", "message"))
break
}
this.consecutiveMistakeCount = 0

// Verify the mode exists
const targetMode = getModeBySlug(
mode,
(await this.providerRef.deref()?.getState())?.customModes,
)
if (!targetMode) {
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode}`))
break
}

// Show what we're about to do
const toolMessage = JSON.stringify({
tool: "newTask",
mode: targetMode.name,
content: message,
})

const didApprove = await askApproval("tool", toolMessage)
if (!didApprove) {
break
}

// Switch mode first, then create new task instance
const provider = this.providerRef.deref()
if (provider) {
await provider.handleModeSwitch(mode)
await provider.initClineWithTask(message)
pushToolResult(
`Successfully created new task in ${targetMode.name} mode with message: ${message}`,
)
} else {
pushToolResult(
formatResponse.toolError("Failed to create new task: provider not available"),
)
}
break
}
} catch (error) {
await handleError("creating new task", error)
break
}
}

case "attempt_completion": {
/*
this.consecutiveMistakeCount = 0
Expand Down
8 changes: 8 additions & 0 deletions src/core/assistant-message/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const toolUseNames = [
"ask_followup_question",
"attempt_completion",
"switch_mode",
"new_task",
] as const

// Converts array of tool call names into a union type ("execute_command" | "read_file" | ...)
Expand Down Expand Up @@ -53,6 +54,8 @@ export const toolParamNames = [
"mode_slug",
"reason",
"operations",
"mode",
"message",
] as const

export type ToolParamName = (typeof toolParamNames)[number]
Expand Down Expand Up @@ -130,3 +133,8 @@ export interface SwitchModeToolUse extends ToolUse {
name: "switch_mode"
params: Partial<Pick<Record<ToolParamName, string>, "mode_slug" | "reason">>
}

export interface NewTaskToolUse extends ToolUse {
name: "new_task"
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
}
Loading
Loading