refactor: rename respondWithoutAnalysis to respondWithoutAssetCreation

- Updated references across multiple files to reflect the new tool name.
- Adjusted unit tests and schemas to ensure compatibility with the renamed tool.
- Removed the old respondWithoutAnalysis tool implementation and its associated tests.
- Ensured backward compatibility for existing functionality using the old tool name.
This commit is contained in:
dal 2025-07-23 08:12:23 -06:00
parent 7ddc683104
commit 24cfab962d
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
17 changed files with 75 additions and 53 deletions

View File

@ -80,7 +80,7 @@ steps/
tools/
├── communication-tools/ # Agent-to-agent communication
│ ├── done-tool.ts
│ ├── respond-without-analysis.ts
│ ├── respond-without-asset-creation.ts
│ └── submit-thoughts-tool.ts
├── database-tools/ # Data access
│ └── find-required-text-values.ts

View File

@ -95,8 +95,8 @@ describe('Format Output Step Unit Tests', () => {
],
finished: true,
metadata: {
toolsUsed: ['respondWithoutAnalysis'],
finalTool: 'respondWithoutAnalysis',
toolsUsed: ['respondWithoutAssetCreation'],
finalTool: 'respondWithoutAssetCreation',
},
};

View File

@ -137,11 +137,11 @@ describe('onStepFinish message conversion', () => {
});
});
it('should convert respondWithoutAnalysis to response text messages', async () => {
it('should convert respondWithoutAssetCreation to response text messages', async () => {
const toolCalls = [
{
toolCallId: 'respond-1',
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
args: {
message: 'Here is a quick answer without analysis',
},
@ -155,7 +155,7 @@ describe('onStepFinish message conversion', () => {
{
type: 'tool-call',
toolCallId: 'respond-1',
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
args: {
message: 'Here is a quick answer without analysis',
},
@ -168,7 +168,7 @@ describe('onStepFinish message conversion', () => {
{
type: 'tool-result',
toolCallId: 'respond-1',
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
result: {
message: 'Here is a quick answer without analysis',
},
@ -180,13 +180,13 @@ describe('onStepFinish message conversion', () => {
const step = createMockStepResult(toolCalls, responseMessages);
const toolNames = step.toolCalls.map((call) => call.toolName);
// Check that respondWithoutAnalysis is a finishing tool
// Check that respondWithoutAssetCreation is a finishing tool
const hasFinishingTools = toolNames.some((toolName: string) =>
['submitThoughts', 'respondWithoutAnalysis'].includes(toolName)
['submitThoughts', 'respondWithoutAssetCreation'].includes(toolName)
);
expect(hasFinishingTools).toBe(true);
expect(toolNames.includes('respondWithoutAnalysis')).toBe(true);
expect(toolNames.includes('respondWithoutAssetCreation')).toBe(true);
});
});

View File

@ -90,7 +90,7 @@ const createStepResult = (
toolsUsed: getAllToolsUsed(conversationHistory),
finalTool: getLastToolUsed(conversationHistory) as
| 'submitThoughts'
| 'respondWithoutAnalysis'
| 'respondWithoutAssetCreation'
| 'messageUserClarifyingQuestion'
| undefined,
text: undefined,

View File

@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest';
import { validateArrayAccess } from '../../utils/validation-helpers';
import { parseStreamingArgs } from './respond-without-analysis';
import { parseStreamingArgs } from './respond-without-asset-creation';
describe('Respond Without Analysis Tool Streaming Parser', () => {
test('should return null for empty or invalid input', () => {

View File

@ -3,7 +3,7 @@ import { wrapTraced } from 'braintrust';
import { z } from 'zod';
// Input/Output schemas
const respondWithoutAnalysisInputSchema = z.object({
const respondWithoutAssetCreationInputSchema = z.object({
final_response: z
.string()
.min(1, 'Final response is required')
@ -13,12 +13,12 @@ const respondWithoutAnalysisInputSchema = z.object({
});
/**
* Optimistic parsing function for streaming respond-without-analysis tool arguments
* Optimistic parsing function for streaming respond-without-asset-creation tool arguments
* Extracts the final_response field as it's being built incrementally
*/
export function parseStreamingArgs(
accumulatedText: string
): Partial<z.infer<typeof respondWithoutAnalysisInputSchema>> | null {
): Partial<z.infer<typeof respondWithoutAssetCreationInputSchema>> | null {
// Validate input type
if (typeof accumulatedText !== 'string') {
throw new Error(`parseStreamingArgs expects string input, got ${typeof accumulatedText}`);
@ -63,11 +63,11 @@ export function parseStreamingArgs(
}
}
const respondWithoutAnalysisOutputSchema = z.object({});
const respondWithoutAssetCreationOutputSchema = z.object({});
// Process respond without analysis tool execution
async function processRespondWithoutAnalysis(): Promise<
z.infer<typeof respondWithoutAnalysisOutputSchema>
async function processRespondWithoutAssetCreation(): Promise<
z.infer<typeof respondWithoutAssetCreationOutputSchema>
> {
// This tool signals the end of the workflow and provides the final response.
// The actual agent termination logic resides elsewhere.
@ -75,21 +75,21 @@ async function processRespondWithoutAnalysis(): Promise<
}
// Main respond without analysis function with tracing
const executeRespondWithoutAnalysis = wrapTraced(
async (): Promise<z.infer<typeof respondWithoutAnalysisOutputSchema>> => {
return await processRespondWithoutAnalysis();
const executeRespondWithoutAssetCreation = wrapTraced(
async (): Promise<z.infer<typeof respondWithoutAssetCreationOutputSchema>> => {
return await processRespondWithoutAssetCreation();
},
{ name: 'respond-without-asset-creation' }
);
// Export the tool
export const respondWithoutAssetCreation = createTool({
id: 'respond-without-analysis',
id: 'respond-without-asset-creation',
description:
"Marks all remaining unfinished tasks as complete, sends a final response to the user, and ends the workflow. Use this when the workflow is finished. This must be in markdown format and not use the '•' bullet character.",
inputSchema: respondWithoutAnalysisInputSchema,
outputSchema: respondWithoutAnalysisOutputSchema,
execute: executeRespondWithoutAnalysis,
inputSchema: respondWithoutAssetCreationInputSchema,
outputSchema: respondWithoutAssetCreationOutputSchema,
execute: executeRespondWithoutAssetCreation,
});
export default respondWithoutAssetCreation;

View File

@ -1,6 +1,6 @@
export { doneTool } from './communication-tools/done-tool';
export { idleTool } from './communication-tools/idle-tool';
export { respondWithoutAssetCreation } from './communication-tools/respond-without-analysis';
export { respondWithoutAssetCreation } from './communication-tools/respond-without-asset-creation';
export { submitThoughts } from './communication-tools/submit-thoughts-tool';
export { messageUserClarifyingQuestion } from './communication-tools/message-user-clarifying-question';
export { sequentialThinking } from './planning-thinking-tools/sequential-thinking-tool';

View File

@ -48,7 +48,7 @@ describe('ChunkProcessor', () => {
});
it('should extract response messages with correct field names', async () => {
const availableTools = new Set(['doneTool', 'respondWithoutAnalysis']);
const availableTools = new Set(['doneTool', 'respondWithoutAssetCreation']);
const processor = new ChunkProcessor(mockMessageId, [], [], [], undefined, availableTools);
// Process doneTool with final_response
@ -61,11 +61,11 @@ describe('ChunkProcessor', () => {
},
} as TextStreamPart<ToolSet>);
// Process respondWithoutAnalysis with final_response
// Process respondWithoutAssetCreation with final_response
await processor.processChunk({
type: 'tool-call',
toolCallId: 'respond-1',
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
args: {
final_response: 'I cannot analyze this type of data.',
},

View File

@ -1691,7 +1691,7 @@ export class ChunkProcessor<T extends ToolSet = GenericToolSet> {
}
/**
* Check if a tool is a response tool (doneTool, respondWithoutAnalysis)
* Check if a tool is a response tool (doneTool, respondWithoutAssetCreation)
*/
private isResponseTool(toolName: string): boolean {
const responseTools = [

View File

@ -186,6 +186,8 @@ function formatMessageAsReasoningEntry(
case 'doneTool':
case 'done-tool':
case 'respondWithoutAssetCreation':
case 'respond-without-asset-creation':
case 'respondWithoutAnalysis':
case 'respond-without-analysis':
// These are response messages, not reasoning messages
@ -246,7 +248,7 @@ function formatMessageAsReasoningEntry(
return reasoningMessages;
}
if (toolCalls.length > 0) {
// We had tool calls but no reasoning messages (e.g., doneTool, respondWithoutAnalysis)
// We had tool calls but no reasoning messages (e.g., doneTool, respondWithoutAssetCreation)
// Return null to skip this message
return null;
}
@ -407,7 +409,7 @@ export function appendToReasoning(
/**
* Extract response messages from CoreMessages
* Specifically looks for doneTool and respondWithoutAnalysis tool calls
* Specifically looks for doneTool and respondWithoutAssetCreation tool calls
*/
export function extractResponseMessages(messages: CoreMessage[]): ChatMessageResponseMessage[] {
if (!Array.isArray(messages)) {
@ -439,8 +441,11 @@ export function extractResponseMessages(messages: CoreMessage[]): ChatMessageRes
console.error('Invalid response message:', error, responseMessage);
}
} else if (
// Backwards compatible with respond without anlysis since that was an old tool we used before.
toolCall.toolName === 'respondWithoutAnalysis' ||
toolCall.toolName === 'respond-without-analysis'
toolCall.toolName === 'respond-without-analysis' ||
toolCall.toolName === 'respondWithoutAssetCreation' ||
toolCall.toolName === 'respond-without-asset-creation'
) {
const responseMessage: ResponseTextMessage = {
id: toolCall.toolCallId,

View File

@ -93,9 +93,9 @@ describe('ChunkProcessor - Response Message Streaming', () => {
});
});
describe('respondWithoutAnalysis streaming', () => {
describe('respondWithoutAssetCreation streaming', () => {
it('should create and update response message as response streams', async () => {
const availableTools = new Set(['respondWithoutAnalysis']);
const availableTools = new Set(['respondWithoutAssetCreation']);
const processor = new ChunkProcessor(null, [], [], [], undefined, availableTools);
const toolCallId = 'respond-tool-1';
@ -103,14 +103,14 @@ describe('ChunkProcessor - Response Message Streaming', () => {
await processor.processChunk({
type: 'tool-call-streaming-start',
toolCallId,
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
} as TextStreamPart<never>);
// Stream partial response
await processor.processChunk({
type: 'tool-call-delta',
toolCallId,
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
argsTextDelta: '{"final_response": "Based on',
} as TextStreamPart<never>);
@ -127,7 +127,7 @@ describe('ChunkProcessor - Response Message Streaming', () => {
await processor.processChunk({
type: 'tool-call-delta',
toolCallId,
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
argsTextDelta: ' the analysis"}',
} as TextStreamPart<never>);
@ -156,15 +156,15 @@ describe('ChunkProcessor - Response Message Streaming', () => {
expect(processor.getReasoningHistory()).toHaveLength(0);
});
it('should not create reasoning entries for respondWithoutAnalysis', async () => {
const availableTools = new Set(['respondWithoutAnalysis']);
it('should not create reasoning entries for respondWithoutAssetCreation', async () => {
const availableTools = new Set(['respondWithoutAssetCreation']);
const processor = new ChunkProcessor(null, [], [], [], undefined, availableTools);
const toolCallId = 'respond-tool-2';
await processor.processChunk({
type: 'tool-call',
toolCallId,
toolName: 'respondWithoutAnalysis',
toolName: 'respondWithoutAssetCreation',
args: {
final_response: 'Quick response',
},

View File

@ -53,8 +53,8 @@ describe('message-converters', () => {
});
describe('Respond Without Analysis tool', () => {
it('should convert respondWithoutAnalysis to response text message', () => {
const toolCall = createToolCall('test-id-3', 'respondWithoutAnalysis', {
it('should convert respondWithoutAssetCreation to response text message', () => {
const toolCall = createToolCall('test-id-3', 'respondWithoutAssetCreation', {
message: 'Quick response',
});
const toolResult = { message: 'Quick response' };

View File

@ -14,7 +14,7 @@ const DoneToolResultSchema = z.object({
message: z.string(),
});
const RespondWithoutAnalysisResultSchema = z.object({
const RespondWithoutAssetCreationResultSchema = z.object({
message: z.string(),
});
@ -85,7 +85,7 @@ const ExecuteSqlResultSchema = z.object({
// Type for parsed tool results
type ParsedToolResult =
| z.infer<typeof DoneToolResultSchema>
| z.infer<typeof RespondWithoutAnalysisResultSchema>
| z.infer<typeof RespondWithoutAssetCreationResultSchema>
| z.infer<typeof SequentialThinkingResultSchema>
| z.infer<typeof CreateMetricsFileResultSchema>
| z.infer<typeof CreateDashboardFileResultSchema>
@ -133,11 +133,28 @@ export function convertToolCallToMessage(
}
}
case 'respondWithoutAssetCreation':
case 'respond-without-asset-creation': {
// Respond Without Analysis generates a response message
try {
const parsed = RespondWithoutAssetCreationResultSchema.parse(toolResult);
const responseMessage: Extract<ChatMessageResponseMessage, { type: 'text' }> = {
id: toolId,
type: 'text',
message: parsed.message,
};
return { type: 'response', message: responseMessage };
} catch (_error) {
return null;
}
}
// Deprecated: Here for backwards compatibility
case 'respondWithoutAnalysis':
case 'respond-without-analysis': {
// Respond Without Analysis generates a response message
try {
const parsed = RespondWithoutAnalysisResultSchema.parse(toolResult);
const parsed = RespondWithoutAssetCreationResultSchema.parse(toolResult);
const responseMessage: Extract<ChatMessageResponseMessage, { type: 'text' }> = {
id: toolId,
type: 'text',

View File

@ -239,7 +239,7 @@ export const ThinkAndPrepOutputSchema = z.object({
.object({
toolsUsed: z.array(z.string()),
finalTool: z
.enum(['submitThoughts', 'respondWithoutAnalysis', 'messageUserClarifyingQuestion'])
.enum(['submitThoughts', 'respondWithoutAssetCreation', 'messageUserClarifyingQuestion'])
.optional(),
text: z.string().optional(),
reasoning: z.string().optional(),

View File

@ -36,7 +36,7 @@ Please use one of these tools to continue with your task. Make sure to use the e
const pipelineContext = `
This workflow has two steps:
1. think-and-prep mode: Available tools are sequentialThinking, executeSql, respondWithoutAnalysis, submitThoughts, messageUserClarifyingQuestion
1. think-and-prep mode: Available tools are sequentialThinking, executeSql, respondWithoutAssetCreation, submitThoughts, messageUserClarifyingQuestion
2. analyst mode: Available tools are createMetrics, modifyMetrics, createDashboards, modifyDashboards, doneTool
You are currently in ${currentStep} mode. Please use one of the tools available in your current mode.

View File

@ -54,7 +54,7 @@ interface AnalystInputData {
conversationHistory: CoreMessage[];
metadata: {
toolsUsed: string[];
finalTool?: 'submitThoughts' | 'respondWithoutAnalysis' | undefined;
finalTool?: 'submitThoughts' | 'respondWithoutAssetCreation' | undefined;
};
}

View File

@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest';
import { parseStreamingArgs as parseDoneArgs } from '../../tools/communication-tools/done-tool';
import { parseStreamingArgs as parseRespondWithoutAnalysisArgs } from '../../tools/communication-tools/respond-without-analysis';
import { parseStreamingArgs as parseRespondWithoutAssetCreationArgs } from '../../tools/communication-tools/respond-without-asset-creation';
import { parseStreamingArgs as parseExecuteSqlArgs } from '../../tools/database-tools/execute-sql';
import { parseStreamingArgs as parseSequentialArgs } from '../../tools/planning-thinking-tools/sequential-thinking-tool';
import { parseStreamingArgs as parseCreateMetricsArgs } from '../../tools/visualization-tools/create-metrics-file-tool';
@ -8,7 +8,7 @@ import { parseStreamingArgs as parseCreateMetricsArgs } from '../../tools/visual
describe('Streaming Parser Error Handling', () => {
const parsers = [
{ name: 'done-tool', parser: parseDoneArgs },
{ name: 'respond-without-analysis', parser: parseRespondWithoutAnalysisArgs },
{ name: 'respond-without-asset-creation', parser: parseRespondWithoutAssetCreationArgs },
{ name: 'sequential-thinking', parser: parseSequentialArgs },
{ name: 'execute-sql', parser: parseExecuteSqlArgs },
{ name: 'create-metrics-file', parser: parseCreateMetricsArgs },
@ -82,9 +82,9 @@ describe('Streaming Parser Error Handling', () => {
expect(result).toEqual({ final_response: 'Test response' });
});
test('respond-without-analysis should parse valid complete JSON', () => {
test('respond-without-asset-creation should parse valid complete JSON', () => {
const validJson = '{"final_response": "Test response"}';
const result = parseRespondWithoutAnalysisArgs(validJson);
const result = parseRespondWithoutAssetCreationArgs(validJson);
expect(result).toEqual({ final_response: 'Test response' });
});