Skip to content

Commit 2a974e8

Browse files
Emit event when a task ask requires interaction (#7128)
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent f3864ff commit 2a974e8

File tree

8 files changed

+213
-55
lines changed

8 files changed

+213
-55
lines changed

packages/types/npm/package.metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@roo-code/types",
3-
"version": "1.51.0",
3+
"version": "1.52.0",
44
"description": "TypeScript type definitions for Roo Code.",
55
"publishConfig": {
66
"access": "public",

packages/types/src/events.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export enum RooCodeEventName {
1818
TaskFocused = "taskFocused",
1919
TaskUnfocused = "taskUnfocused",
2020
TaskActive = "taskActive",
21+
TaskInteractive = "taskInteractive",
22+
TaskResumable = "taskResumable",
2123
TaskIdle = "taskIdle",
2224

2325
// Subtask Lifecycle
@@ -59,6 +61,8 @@ export const rooCodeEventsSchema = z.object({
5961
[RooCodeEventName.TaskFocused]: z.tuple([z.string()]),
6062
[RooCodeEventName.TaskUnfocused]: z.tuple([z.string()]),
6163
[RooCodeEventName.TaskActive]: z.tuple([z.string()]),
64+
[RooCodeEventName.TaskInteractive]: z.tuple([z.string()]),
65+
[RooCodeEventName.TaskResumable]: z.tuple([z.string()]),
6266
[RooCodeEventName.TaskIdle]: z.tuple([z.string()]),
6367

6468
[RooCodeEventName.TaskPaused]: z.tuple([z.string()]),
@@ -124,6 +128,16 @@ export const taskEventSchema = z.discriminatedUnion("eventName", [
124128
payload: rooCodeEventsSchema.shape[RooCodeEventName.TaskActive],
125129
taskId: z.number().optional(),
126130
}),
131+
z.object({
132+
eventName: z.literal(RooCodeEventName.TaskInteractive),
133+
payload: rooCodeEventsSchema.shape[RooCodeEventName.TaskInteractive],
134+
taskId: z.number().optional(),
135+
}),
136+
z.object({
137+
eventName: z.literal(RooCodeEventName.TaskResumable),
138+
payload: rooCodeEventsSchema.shape[RooCodeEventName.TaskResumable],
139+
taskId: z.number().optional(),
140+
}),
127141
z.object({
128142
eventName: z.literal(RooCodeEventName.TaskIdle),
129143
payload: rooCodeEventsSchema.shape[RooCodeEventName.TaskIdle],

packages/types/src/message.ts

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,61 @@ export const clineAskSchema = z.enum(clineAsks)
4444

4545
export type ClineAsk = z.infer<typeof clineAskSchema>
4646

47+
// Needs classification:
48+
// - `followup`
49+
// - `command_output
50+
4751
/**
48-
* BlockingAsk
52+
* IdleAsk
53+
*
54+
* Asks that put the task into an "idle" state.
4955
*/
5056

51-
export const blockingAsks: ClineAsk[] = [
52-
"api_req_failed",
53-
"mistake_limit_reached",
57+
export const idleAsks = [
5458
"completion_result",
55-
"resume_task",
59+
"api_req_failed",
5660
"resume_completed_task",
57-
"command_output",
61+
"mistake_limit_reached",
5862
"auto_approval_max_req_reached",
59-
] as const
63+
] as const satisfies readonly ClineAsk[]
64+
65+
export type IdleAsk = (typeof idleAsks)[number]
66+
67+
export function isIdleAsk(ask: ClineAsk): ask is IdleAsk {
68+
return (idleAsks as readonly ClineAsk[]).includes(ask)
69+
}
70+
71+
/**
72+
* ResumableAsk
73+
*
74+
* Asks that put the task into an "resumable" state.
75+
*/
76+
77+
export const resumableAsks = ["resume_task"] as const satisfies readonly ClineAsk[]
78+
79+
export type ResumableAsk = (typeof resumableAsks)[number]
80+
81+
export function isResumableAsk(ask: ClineAsk): ask is ResumableAsk {
82+
return (resumableAsks as readonly ClineAsk[]).includes(ask)
83+
}
84+
85+
/**
86+
* InteractiveAsk
87+
*
88+
* Asks that put the task into an "user interaction required" state.
89+
*/
90+
91+
export const interactiveAsks = [
92+
"command",
93+
"tool",
94+
"browser_action_launch",
95+
"use_mcp_server",
96+
] as const satisfies readonly ClineAsk[]
6097

61-
export type BlockingAsk = (typeof blockingAsks)[number]
98+
export type InteractiveAsk = (typeof interactiveAsks)[number]
6299

63-
export function isBlockingAsk(ask: ClineAsk): ask is BlockingAsk {
64-
return blockingAsks.includes(ask)
100+
export function isInteractiveAsk(ask: ClineAsk): ask is InteractiveAsk {
101+
return (interactiveAsks as readonly ClineAsk[]).includes(ask)
65102
}
66103

67104
/**

packages/types/src/task.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from "zod"
22

33
import { RooCodeEventName } from "./events.js"
4-
import { type ClineMessage, type BlockingAsk, type TokenUsage } from "./message.js"
4+
import { type ClineMessage, type TokenUsage } from "./message.js"
55
import { type ToolUsage, type ToolName } from "./tool.js"
66
import type { StaticAppProperties, GitProperties, TelemetryProperties } from "./telemetry.js"
77

@@ -54,15 +54,24 @@ export type TaskProviderEvents = {
5454
[RooCodeEventName.TaskFocused]: [taskId: string]
5555
[RooCodeEventName.TaskUnfocused]: [taskId: string]
5656
[RooCodeEventName.TaskActive]: [taskId: string]
57+
[RooCodeEventName.TaskInteractive]: [taskId: string]
58+
[RooCodeEventName.TaskResumable]: [taskId: string]
5759
[RooCodeEventName.TaskIdle]: [taskId: string]
5860
}
5961

6062
/**
6163
* TaskLike
6264
*/
6365

66+
export enum TaskStatus {
67+
Running = "running",
68+
Interactive = "interactive",
69+
Resumable = "resumable",
70+
Idle = "idle",
71+
None = "none",
72+
}
73+
6474
export const taskMetadataSchema = z.object({
65-
taskId: z.string(),
6675
task: z.string().optional(),
6776
images: z.array(z.string()).optional(),
6877
})
@@ -71,14 +80,17 @@ export type TaskMetadata = z.infer<typeof taskMetadataSchema>
7180

7281
export interface TaskLike {
7382
readonly taskId: string
74-
readonly rootTask?: TaskLike
75-
readonly blockingAsk?: BlockingAsk
83+
readonly taskStatus: TaskStatus
84+
readonly taskAsk: ClineMessage | undefined
7685
readonly metadata: TaskMetadata
7786

87+
readonly rootTask?: TaskLike
88+
7889
on<K extends keyof TaskEvents>(event: K, listener: (...args: TaskEvents[K]) => void | Promise<void>): this
7990
off<K extends keyof TaskEvents>(event: K, listener: (...args: TaskEvents[K]) => void | Promise<void>): this
8091

81-
setMessageResponse(text: string, images?: string[]): void
92+
approveAsk(options?: { text?: string; images?: string[] }): void
93+
denyAsk(options?: { text?: string; images?: string[] }): void
8294
submitUserMessage(text: string, images?: string[]): void
8395
}
8496

@@ -90,6 +102,8 @@ export type TaskEvents = {
90102
[RooCodeEventName.TaskFocused]: []
91103
[RooCodeEventName.TaskUnfocused]: []
92104
[RooCodeEventName.TaskActive]: [taskId: string]
105+
[RooCodeEventName.TaskInteractive]: [taskId: string]
106+
[RooCodeEventName.TaskResumable]: [taskId: string]
93107
[RooCodeEventName.TaskIdle]: [taskId: string]
94108

95109
// Subtask Lifecycle

pnpm-lock.yaml

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)