Skip to main content

TurnResult

The TurnResult class encapsulates all data from a single AI interaction, including the final response, tool calls, messages, and execution metadata.

Import

import { TurnResult } from '@activade/droid-sdk';

// TurnResult is returned from Thread.run() and Droid.exec()
const result = await thread.run('Generate code');

Properties

finalResponse

readonly finalResponse: string

The final text response from the AI. For structured output, this contains JSON that can be parsed using parse() or tryParse().

items

readonly items: AnyTurnItem[]

All items from this execution turn (messages, tool calls, tool results) in chronological order.

sessionId

readonly sessionId: string

The unique session identifier. Use with Droid.resumeThread() to continue the conversation.

durationMs

readonly durationMs: number

Total execution time in milliseconds.

numTurns

readonly numTurns: number

Number of conversation turns in this execution.

isError

readonly isError: boolean

Whether the execution resulted in an error.

Methods

parse()

parse<T>(schema: { parse: (data: unknown) => T }): T

Parses the final response as JSON and validates against a schema.

ParameterTypeRequiredDescription
schema{ parse: (data: unknown) => T }YesSchema with parse method (e.g., Zod)

Returns: The parsed and validated data.

Throws:

  • ParseError - If the response is not valid JSON
  • Schema error - If validation fails
import { z } from 'zod';

const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email()
});

const result = await thread.run('Generate a user object as JSON');
const user = result.parse(UserSchema);
// TypeScript knows: user.id is number, user.name is string, etc.

tryParse()

tryParse<T>(schema: { safeParse: (data: unknown) => { success: boolean; data?: T } }): T | null

Attempts to parse the final response, returning null on failure.

const config = result.tryParse(ConfigSchema);

if (config) {
console.log('Config:', config);
} else {
console.log('No valid config in response');
}

toolCalls

get toolCalls(): ToolCallItem[]

All tool calls made during this execution.

for (const call of result.toolCalls) {
console.log(`Tool: ${call.toolName}`);
console.log(`Params: ${JSON.stringify(call.parameters)}`);
}

toolResults

get toolResults(): ToolResultItem[]

All tool results from this execution.

for (const toolResult of result.toolResults) {
if (toolResult.isError) {
console.error(`${toolResult.toolName} failed: ${toolResult.value}`);
} else {
console.log(`${toolResult.toolName} succeeded`);
}
}

messages

get messages(): MessageItem[]

All messages (user and assistant) from this execution.

assistantMessages

get assistantMessages(): MessageItem[]

Assistant messages only, excluding user prompts.

for (const msg of result.assistantMessages) {
console.log(`[${new Date(msg.timestamp).toISOString()}] ${msg.text}`);
}

toJSON()

toJSON(): TurnResultData

Converts the result to a plain JSON-serializable object.

// Save to file
fs.writeFileSync('result.json', JSON.stringify(result.toJSON(), null, 2));

Item Types

MessageItem

interface MessageItem {
type: 'message';
role: 'user' | 'assistant';
id: string;
text: string;
timestamp: number;
}

ToolCallItem

interface ToolCallItem {
type: 'tool_call';
id: string;
messageId: string;
toolId: string;
toolName: string;
parameters: Record<string, unknown>;
timestamp: number;
}

ToolResultItem

interface ToolResultItem {
type: 'tool_result';
id: string;
messageId: string;
toolId: string;
toolName: string;
isError: boolean;
value: string;
timestamp: number;
}

Full Example

import { Droid } from '@activade/droid-sdk';
import { z } from 'zod';

const droid = new Droid();
const thread = droid.startThread();

const result = await thread.run('Create a config file and return the config as JSON');

// Access metadata
console.log(`Session: ${result.sessionId}`);
console.log(`Duration: ${result.durationMs}ms`);
console.log(`Turns: ${result.numTurns}`);
console.log(`Error: ${result.isError}`);

// Access tool activity
console.log(`Tool calls: ${result.toolCalls.length}`);
for (const call of result.toolCalls) {
const resultItem = result.toolResults.find(r => r.toolId === call.toolId);
console.log(` ${call.toolName}: ${resultItem?.isError ? 'FAILED' : 'OK'}`);
}

// Parse structured output
const ConfigSchema = z.object({
port: z.number(),
host: z.string(),
debug: z.boolean().optional()
});

const config = result.tryParse(ConfigSchema);
if (config) {
console.log(`Server: ${config.host}:${config.port}`);
}