mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Add cli types (#11781)
This commit is contained in:
parent
50c8101754
commit
b55409c0b0
6 changed files with 291 additions and 62 deletions
|
|
@ -156,7 +156,7 @@ export class JsonEventEmitter {
|
|||
emitControl(event: {
|
||||
subtype: "ack" | "done" | "error"
|
||||
requestId?: string
|
||||
command?: string
|
||||
command?: JsonEvent["command"]
|
||||
taskId?: string
|
||||
content?: string
|
||||
success?: boolean
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { createInterface } from "readline"
|
||||
import { randomUUID } from "crypto"
|
||||
|
||||
import type { RooCodeSettings } from "@roo-code/types"
|
||||
import {
|
||||
rooCliCommandNames,
|
||||
type RooCliCommandName,
|
||||
type RooCliInputCommand,
|
||||
type RooCliStartCommand,
|
||||
} from "@roo-code/types"
|
||||
|
||||
import { isRecord } from "@/lib/utils/guards.js"
|
||||
|
||||
|
|
@ -12,20 +17,15 @@ import type { JsonEventEmitter } from "@/agent/json-event-emitter.js"
|
|||
// Types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type StdinStreamCommandName = "start" | "message" | "cancel" | "ping" | "shutdown"
|
||||
export type StdinStreamCommandName = RooCliCommandName
|
||||
|
||||
export type StdinStreamCommand =
|
||||
| { command: "start"; requestId: string; prompt: string; configuration?: RooCodeSettings }
|
||||
| { command: "message"; requestId: string; prompt: string }
|
||||
| { command: "cancel"; requestId: string }
|
||||
| { command: "ping"; requestId: string }
|
||||
| { command: "shutdown"; requestId: string }
|
||||
export type StdinStreamCommand = RooCliInputCommand
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const VALID_STDIN_COMMANDS = new Set<StdinStreamCommandName>(["start", "message", "cancel", "ping", "shutdown"])
|
||||
export const VALID_STDIN_COMMANDS = new Set<StdinStreamCommandName>(rooCliCommandNames)
|
||||
|
||||
export function parseStdinStreamCommand(line: string, lineNumber: number): StdinStreamCommand {
|
||||
let parsed: unknown
|
||||
|
|
@ -67,7 +67,12 @@ export function parseStdinStreamCommand(line: string, lineNumber: number): Stdin
|
|||
}
|
||||
|
||||
if (command === "start" && isRecord(parsed.configuration)) {
|
||||
return { command, requestId, prompt: promptRaw, configuration: parsed.configuration as RooCodeSettings }
|
||||
return {
|
||||
command,
|
||||
requestId,
|
||||
prompt: promptRaw,
|
||||
configuration: parsed.configuration as RooCliStartCommand["configuration"],
|
||||
}
|
||||
}
|
||||
|
||||
return { command, requestId, prompt: promptRaw }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
import {
|
||||
rooCliOutputFormats,
|
||||
type RooCliCost,
|
||||
type RooCliEventType,
|
||||
type RooCliFinalOutput,
|
||||
type RooCliOutputFormat,
|
||||
type RooCliQueueItem,
|
||||
type RooCliStreamEvent,
|
||||
type RooCliToolResult,
|
||||
type RooCliToolUse,
|
||||
} from "@roo-code/types"
|
||||
|
||||
/**
|
||||
* JSON Event Types for Structured CLI Output
|
||||
*
|
||||
|
|
@ -14,9 +26,9 @@
|
|||
/**
|
||||
* Output format options for the CLI.
|
||||
*/
|
||||
export const OUTPUT_FORMATS = ["text", "json", "stream-json"] as const
|
||||
export const OUTPUT_FORMATS = rooCliOutputFormats
|
||||
|
||||
export type OutputFormat = (typeof OUTPUT_FORMATS)[number]
|
||||
export type OutputFormat = RooCliOutputFormat
|
||||
|
||||
export function isValidOutputFormat(format: string): format is OutputFormat {
|
||||
return (OUTPUT_FORMATS as readonly string[]).includes(format)
|
||||
|
|
@ -25,66 +37,24 @@ export function isValidOutputFormat(format: string): format is OutputFormat {
|
|||
/**
|
||||
* Event type discriminators for JSON output.
|
||||
*/
|
||||
export type JsonEventType =
|
||||
| "system" // System messages (init, ready, shutdown)
|
||||
| "control" // Transport/control protocol events
|
||||
| "queue" // Message queue telemetry from extension state
|
||||
| "assistant" // Assistant text messages
|
||||
| "user" // User messages (echoed input)
|
||||
| "tool_use" // Tool invocations (file ops, commands, browser, MCP)
|
||||
| "tool_result" // Results from tool execution
|
||||
| "thinking" // Reasoning/thinking content
|
||||
| "error" // Errors
|
||||
| "result" // Final task result
|
||||
export type JsonEventType = RooCliEventType
|
||||
|
||||
export interface JsonEventQueueItem {
|
||||
/** Queue item id generated by MessageQueueService */
|
||||
id: string
|
||||
/** Queued text prompt preview */
|
||||
text?: string
|
||||
/** Number of attached images in the queued message */
|
||||
imageCount?: number
|
||||
/** Queue insertion/update timestamp (ms epoch) */
|
||||
timestamp?: number
|
||||
}
|
||||
export type JsonEventQueueItem = RooCliQueueItem
|
||||
|
||||
/**
|
||||
* Tool use information for tool_use events.
|
||||
*/
|
||||
export interface JsonEventToolUse {
|
||||
/** Tool name (e.g., "read_file", "write_to_file", "execute_command") */
|
||||
name: string
|
||||
/** Tool input parameters */
|
||||
input?: Record<string, unknown>
|
||||
}
|
||||
export type JsonEventToolUse = RooCliToolUse
|
||||
|
||||
/**
|
||||
* Tool result information for tool_result events.
|
||||
*/
|
||||
export interface JsonEventToolResult {
|
||||
/** Tool name that produced this result */
|
||||
name: string
|
||||
/** Tool output (for successful execution) */
|
||||
output?: string
|
||||
/** Error message (for failed execution) */
|
||||
error?: string
|
||||
}
|
||||
export type JsonEventToolResult = RooCliToolResult
|
||||
|
||||
/**
|
||||
* Cost and token usage information.
|
||||
*/
|
||||
export interface JsonEventCost {
|
||||
/** Total cost in USD */
|
||||
totalCost?: number
|
||||
/** Input tokens used */
|
||||
inputTokens?: number
|
||||
/** Output tokens generated */
|
||||
outputTokens?: number
|
||||
/** Cache write tokens */
|
||||
cacheWrites?: number
|
||||
/** Cache read tokens */
|
||||
cacheReads?: number
|
||||
}
|
||||
export type JsonEventCost = RooCliCost
|
||||
|
||||
/**
|
||||
* Base JSON event structure.
|
||||
|
|
@ -94,7 +64,7 @@ export interface JsonEventCost {
|
|||
* - Each delta includes `id` for easy correlation
|
||||
* - Final message has `done: true`
|
||||
*/
|
||||
export interface JsonEvent {
|
||||
export type JsonEvent = RooCliStreamEvent & {
|
||||
/** Event type discriminator */
|
||||
type: JsonEventType
|
||||
/** Protocol schema version (included on system.init) */
|
||||
|
|
@ -137,7 +107,7 @@ export interface JsonEvent {
|
|||
* Final JSON output for "json" mode (single object at end).
|
||||
* Contains the result and accumulated messages.
|
||||
*/
|
||||
export interface JsonFinalOutput {
|
||||
export type JsonFinalOutput = RooCliFinalOutput & {
|
||||
/** Final result type */
|
||||
type: "result"
|
||||
/** Whether the task succeeded */
|
||||
|
|
|
|||
80
packages/types/src/__tests__/cli.test.ts
Normal file
80
packages/types/src/__tests__/cli.test.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import {
|
||||
rooCliControlEventSchema,
|
||||
rooCliFinalOutputSchema,
|
||||
rooCliInputCommandSchema,
|
||||
rooCliStreamEventSchema,
|
||||
} from "../cli.js"
|
||||
|
||||
describe("CLI types", () => {
|
||||
describe("rooCliInputCommandSchema", () => {
|
||||
it("validates a start command", () => {
|
||||
const result = rooCliInputCommandSchema.safeParse({
|
||||
command: "start",
|
||||
requestId: "req-1",
|
||||
prompt: "hello",
|
||||
configuration: {},
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects a message command without prompt", () => {
|
||||
const result = rooCliInputCommandSchema.safeParse({
|
||||
command: "message",
|
||||
requestId: "req-2",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("rooCliControlEventSchema", () => {
|
||||
it("validates a control done event", () => {
|
||||
const result = rooCliControlEventSchema.safeParse({
|
||||
type: "control",
|
||||
subtype: "done",
|
||||
requestId: "req-3",
|
||||
command: "start",
|
||||
success: true,
|
||||
code: "task_completed",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
it("rejects control event without requestId", () => {
|
||||
const result = rooCliControlEventSchema.safeParse({
|
||||
type: "control",
|
||||
subtype: "ack",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("rooCliStreamEventSchema", () => {
|
||||
it("accepts passthrough fields for forward compatibility", () => {
|
||||
const result = rooCliStreamEventSchema.safeParse({
|
||||
type: "assistant",
|
||||
id: 42,
|
||||
content: "partial",
|
||||
customField: "future",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("rooCliFinalOutputSchema", () => {
|
||||
it("validates final json output shape", () => {
|
||||
const result = rooCliFinalOutputSchema.safeParse({
|
||||
type: "result",
|
||||
success: true,
|
||||
content: "done",
|
||||
events: [],
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
173
packages/types/src/cli.ts
Normal file
173
packages/types/src/cli.ts
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
import { z } from "zod"
|
||||
|
||||
import { rooCodeSettingsSchema } from "./global-settings.js"
|
||||
|
||||
/**
|
||||
* Roo CLI stdin commands
|
||||
*/
|
||||
|
||||
export const rooCliCommandNames = ["start", "message", "cancel", "ping", "shutdown"] as const
|
||||
|
||||
export const rooCliCommandNameSchema = z.enum(rooCliCommandNames)
|
||||
|
||||
export type RooCliCommandName = z.infer<typeof rooCliCommandNameSchema>
|
||||
|
||||
export const rooCliCommandBaseSchema = z.object({
|
||||
command: rooCliCommandNameSchema,
|
||||
requestId: z.string().min(1),
|
||||
})
|
||||
|
||||
export type RooCliCommandBase = z.infer<typeof rooCliCommandBaseSchema>
|
||||
|
||||
export const rooCliStartCommandSchema = rooCliCommandBaseSchema.extend({
|
||||
command: z.literal("start"),
|
||||
prompt: z.string(),
|
||||
configuration: rooCodeSettingsSchema.optional(),
|
||||
})
|
||||
|
||||
export type RooCliStartCommand = z.infer<typeof rooCliStartCommandSchema>
|
||||
|
||||
export const rooCliMessageCommandSchema = rooCliCommandBaseSchema.extend({
|
||||
command: z.literal("message"),
|
||||
prompt: z.string(),
|
||||
})
|
||||
|
||||
export type RooCliMessageCommand = z.infer<typeof rooCliMessageCommandSchema>
|
||||
|
||||
export const rooCliCancelCommandSchema = rooCliCommandBaseSchema.extend({
|
||||
command: z.literal("cancel"),
|
||||
})
|
||||
|
||||
export type RooCliCancelCommand = z.infer<typeof rooCliCancelCommandSchema>
|
||||
|
||||
export const rooCliPingCommandSchema = rooCliCommandBaseSchema.extend({
|
||||
command: z.literal("ping"),
|
||||
})
|
||||
|
||||
export type RooCliPingCommand = z.infer<typeof rooCliPingCommandSchema>
|
||||
|
||||
export const rooCliShutdownCommandSchema = rooCliCommandBaseSchema.extend({
|
||||
command: z.literal("shutdown"),
|
||||
})
|
||||
|
||||
export type RooCliShutdownCommand = z.infer<typeof rooCliShutdownCommandSchema>
|
||||
|
||||
export const rooCliInputCommandSchema = z.discriminatedUnion("command", [
|
||||
rooCliStartCommandSchema,
|
||||
rooCliMessageCommandSchema,
|
||||
rooCliCancelCommandSchema,
|
||||
rooCliPingCommandSchema,
|
||||
rooCliShutdownCommandSchema,
|
||||
])
|
||||
|
||||
export type RooCliInputCommand = z.infer<typeof rooCliInputCommandSchema>
|
||||
|
||||
/**
|
||||
* Roo CLI stream-json output
|
||||
*/
|
||||
|
||||
export const rooCliOutputFormats = ["text", "json", "stream-json"] as const
|
||||
|
||||
export const rooCliOutputFormatSchema = z.enum(rooCliOutputFormats)
|
||||
|
||||
export type RooCliOutputFormat = z.infer<typeof rooCliOutputFormatSchema>
|
||||
|
||||
export const rooCliEventTypes = [
|
||||
"system",
|
||||
"control",
|
||||
"queue",
|
||||
"assistant",
|
||||
"user",
|
||||
"tool_use",
|
||||
"tool_result",
|
||||
"thinking",
|
||||
"error",
|
||||
"result",
|
||||
] as const
|
||||
|
||||
export const rooCliEventTypeSchema = z.enum(rooCliEventTypes)
|
||||
|
||||
export type RooCliEventType = z.infer<typeof rooCliEventTypeSchema>
|
||||
|
||||
export const rooCliControlSubtypes = ["ack", "done", "error"] as const
|
||||
|
||||
export const rooCliControlSubtypeSchema = z.enum(rooCliControlSubtypes)
|
||||
|
||||
export type RooCliControlSubtype = z.infer<typeof rooCliControlSubtypeSchema>
|
||||
|
||||
export const rooCliQueueItemSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
text: z.string().optional(),
|
||||
imageCount: z.number().optional(),
|
||||
timestamp: z.number().optional(),
|
||||
})
|
||||
|
||||
export type RooCliQueueItem = z.infer<typeof rooCliQueueItemSchema>
|
||||
|
||||
export const rooCliToolUseSchema = z.object({
|
||||
name: z.string(),
|
||||
input: z.record(z.unknown()).optional(),
|
||||
})
|
||||
|
||||
export type RooCliToolUse = z.infer<typeof rooCliToolUseSchema>
|
||||
|
||||
export const rooCliToolResultSchema = z.object({
|
||||
name: z.string(),
|
||||
output: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export type RooCliToolResult = z.infer<typeof rooCliToolResultSchema>
|
||||
|
||||
export const rooCliCostSchema = z.object({
|
||||
totalCost: z.number().optional(),
|
||||
inputTokens: z.number().optional(),
|
||||
outputTokens: z.number().optional(),
|
||||
cacheWrites: z.number().optional(),
|
||||
cacheReads: z.number().optional(),
|
||||
})
|
||||
|
||||
export type RooCliCost = z.infer<typeof rooCliCostSchema>
|
||||
|
||||
export const rooCliStreamEventSchema = z
|
||||
.object({
|
||||
type: rooCliEventTypeSchema.optional(),
|
||||
subtype: z.string().optional(),
|
||||
requestId: z.string().optional(),
|
||||
command: rooCliCommandNameSchema.optional(),
|
||||
taskId: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
content: z.string().optional(),
|
||||
success: z.boolean().optional(),
|
||||
id: z.number().optional(),
|
||||
done: z.boolean().optional(),
|
||||
queueDepth: z.number().optional(),
|
||||
queue: z.array(rooCliQueueItemSchema).optional(),
|
||||
schemaVersion: z.number().optional(),
|
||||
protocol: z.string().optional(),
|
||||
capabilities: z.array(z.string()).optional(),
|
||||
tool_use: rooCliToolUseSchema.optional(),
|
||||
tool_result: rooCliToolResultSchema.optional(),
|
||||
cost: rooCliCostSchema.optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
export type RooCliStreamEvent = z.infer<typeof rooCliStreamEventSchema>
|
||||
|
||||
export const rooCliControlEventSchema = rooCliStreamEventSchema.extend({
|
||||
type: z.literal("control"),
|
||||
subtype: rooCliControlSubtypeSchema,
|
||||
requestId: z.string().min(1),
|
||||
})
|
||||
|
||||
export type RooCliControlEvent = z.infer<typeof rooCliControlEventSchema>
|
||||
|
||||
export const rooCliFinalOutputSchema = z.object({
|
||||
type: z.literal("result"),
|
||||
success: z.boolean(),
|
||||
content: z.string().optional(),
|
||||
cost: rooCliCostSchema.optional(),
|
||||
events: z.array(rooCliStreamEventSchema),
|
||||
})
|
||||
|
||||
export type RooCliFinalOutput = z.infer<typeof rooCliFinalOutputSchema>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
export * from "./api.js"
|
||||
export * from "./cli.js"
|
||||
export * from "./cloud.js"
|
||||
export * from "./codebase-index.js"
|
||||
export * from "./context-management.js"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue