respond without assetstool restuls

This commit is contained in:
dal 2025-08-15 14:58:46 -06:00
parent cdb7e4f17e
commit 37aa14c43b
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
7 changed files with 123 additions and 86 deletions

View File

@ -7,7 +7,7 @@ export function createRespondWithoutAssetCreationResponseMessage(
toolCallId?: string toolCallId?: string
): ChatMessageResponseMessage_Text | null { ): ChatMessageResponseMessage_Text | null {
// Use entry_id from state or fallback to provided toolCallId // Use entry_id from state or fallback to provided toolCallId
const id = state.entry_id || toolCallId; const id = state.toolCallId || toolCallId;
if (!id) { if (!id) {
return null; return null;
@ -25,7 +25,7 @@ export function createRespondWithoutAssetCreationRawLlmMessageEntry(
state: RespondWithoutAssetCreationState, state: RespondWithoutAssetCreationState,
toolCallId?: string toolCallId?: string
): ModelMessage | null { ): ModelMessage | null {
const id = state.entry_id || toolCallId; const id = state.toolCallId || toolCallId;
if (!id) { if (!id) {
return null; return null;

View File

@ -19,8 +19,8 @@ const FINAL_RESPONSE_KEY =
'final_response' as const satisfies keyof RespondWithoutAssetCreationInput; 'final_response' as const satisfies keyof RespondWithoutAssetCreationInput;
export function createRespondWithoutAssetCreationDelta( export function createRespondWithoutAssetCreationDelta(
state: RespondWithoutAssetCreationState, context: RespondWithoutAssetCreationContext,
context: RespondWithoutAssetCreationContext state: RespondWithoutAssetCreationState
) { ) {
return async function respondWithoutAssetCreationDelta( return async function respondWithoutAssetCreationDelta(
options: { inputTextDelta: string } & ToolCallOptions options: { inputTextDelta: string } & ToolCallOptions

View File

@ -1,20 +1,53 @@
import { updateMessageEntries } from '@buster/database';
import { wrapTraced } from 'braintrust'; import { wrapTraced } from 'braintrust';
import type { import { createRawToolResultEntry } from '../../shared/create-raw-llm-tool-result-entry';
RespondWithoutAssetCreationContext, import {
RespondWithoutAssetCreationInput, RESPOND_WITHOUT_ASSET_CREATION_TOOL_NAME,
RespondWithoutAssetCreationOutput, type RespondWithoutAssetCreationContext,
type RespondWithoutAssetCreationInput,
type RespondWithoutAssetCreationOutput,
type RespondWithoutAssetCreationState,
} from './respond-without-asset-creation-tool'; } from './respond-without-asset-creation-tool';
async function processRespondWithoutAssetCreation(): Promise<RespondWithoutAssetCreationOutput> { async function processRespondWithoutAssetCreation(
return {}; toolCallId: string,
messageId: string
): Promise<RespondWithoutAssetCreationOutput> {
const output: RespondWithoutAssetCreationOutput = {
success: true,
};
const rawToolResultEntry = createRawToolResultEntry(
toolCallId,
RESPOND_WITHOUT_ASSET_CREATION_TOOL_NAME,
output
);
try {
await updateMessageEntries({
messageId,
rawLlmMessages: [rawToolResultEntry],
});
} catch (error) {
console.error('[respond-without-asset-creation] Error updating message entries:', error);
}
return output;
} }
export function createRespondWithoutAssetCreationExecute() { export function createRespondWithoutAssetCreationExecute(
context: RespondWithoutAssetCreationContext,
state: RespondWithoutAssetCreationState
) {
return wrapTraced( return wrapTraced(
async ( async (
_input: RespondWithoutAssetCreationInput _input: RespondWithoutAssetCreationInput
): Promise<RespondWithoutAssetCreationOutput> => { ): Promise<RespondWithoutAssetCreationOutput> => {
return await processRespondWithoutAssetCreation(); if (!state.toolCallId) {
throw new Error('Tool call ID is required');
}
return await processRespondWithoutAssetCreation(state.toolCallId, context.messageId);
}, },
{ name: 'Respond Without Asset Creation' } { name: 'Respond Without Asset Creation' }
); );

View File

@ -10,13 +10,14 @@ import type {
RespondWithoutAssetCreationState, RespondWithoutAssetCreationState,
} from './respond-without-asset-creation-tool'; } from './respond-without-asset-creation-tool';
export function createRespondWithoutAssetCreationFinish< export function createRespondWithoutAssetCreationFinish(
TAgentContext extends RespondWithoutAssetCreationContext, context: RespondWithoutAssetCreationContext,
>(state: RespondWithoutAssetCreationState, context: TAgentContext) { state: RespondWithoutAssetCreationState
) {
return async function respondWithoutAssetCreationFinish( return async function respondWithoutAssetCreationFinish(
options: { input: RespondWithoutAssetCreationInput } & ToolCallOptions options: { input: RespondWithoutAssetCreationInput } & ToolCallOptions
): Promise<void> { ): Promise<void> {
state.entry_id = options.toolCallId; state.toolCallId = options.toolCallId;
state.final_response = options.input.final_response; state.final_response = options.input.final_response;
const responseEntry = createRespondWithoutAssetCreationResponseMessage( const responseEntry = createRespondWithoutAssetCreationResponseMessage(

View File

@ -10,13 +10,14 @@ import type {
} from './respond-without-asset-creation-tool'; } from './respond-without-asset-creation-tool';
// Factory function that creates a type-safe callback for the specific agent context // Factory function that creates a type-safe callback for the specific agent context
export function createRespondWithoutAssetCreationStart< export function createRespondWithoutAssetCreationStart(
TAgentContext extends RespondWithoutAssetCreationContext, context: RespondWithoutAssetCreationContext,
>(state: RespondWithoutAssetCreationState, context: TAgentContext) { state: RespondWithoutAssetCreationState
) {
return async function respondWithoutAssetCreationStart( return async function respondWithoutAssetCreationStart(
options: Pick<ToolCallOptions, 'toolCallId'> options: Pick<ToolCallOptions, 'toolCallId'>
): Promise<void> { ): Promise<void> {
state.entry_id = options.toolCallId; state.toolCallId = options.toolCallId;
const responseEntry = createRespondWithoutAssetCreationResponseMessage( const responseEntry = createRespondWithoutAssetCreationResponseMessage(
state, state,

View File

@ -22,12 +22,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
describe('createRespondWithoutAssetCreationStart', () => { describe('createRespondWithoutAssetCreationStart', () => {
test('should initialize state with entry_id on start', async () => { test('should initialize state with entry_id on start', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const startHandler = createRespondWithoutAssetCreationStart(state, mockContext); const startHandler = createRespondWithoutAssetCreationStart(mockContext, state);
const options: ToolCallOptions = { const options: ToolCallOptions = {
toolCallId: 'tool-call-123', toolCallId: 'tool-call-123',
messages: [], messages: [],
@ -35,7 +35,7 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
await startHandler(options); await startHandler(options);
expect(state.entry_id).toBe('tool-call-123'); expect(state.toolCallId).toBe('tool-call-123');
}); });
test('should handle start without messageId in context', async () => { test('should handle start without messageId in context', async () => {
@ -44,19 +44,19 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
workflowStartTime: Date.now(), workflowStartTime: Date.now(),
}; };
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const startHandler = createRespondWithoutAssetCreationStart(state, contextWithoutMessageId); const startHandler = createRespondWithoutAssetCreationStart(contextWithoutMessageId, state);
const options: ToolCallOptions = { const options: ToolCallOptions = {
toolCallId: 'tool-call-456', toolCallId: 'tool-call-456',
messages: [], messages: [],
}; };
await expect(startHandler(options)).resolves.not.toThrow(); await expect(startHandler(options)).resolves.not.toThrow();
expect(state.entry_id).toBe('tool-call-456'); expect(state.toolCallId).toBe('tool-call-456');
}); });
test('should handle empty messageId gracefully', async () => { test('should handle empty messageId gracefully', async () => {
@ -65,31 +65,31 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
workflowStartTime: Date.now(), workflowStartTime: Date.now(),
}; };
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const startHandler = createRespondWithoutAssetCreationStart(state, contextWithEmptyMessageId); const startHandler = createRespondWithoutAssetCreationStart(contextWithEmptyMessageId, state);
const options: ToolCallOptions = { const options: ToolCallOptions = {
toolCallId: 'tool-call-789', toolCallId: 'tool-call-789',
messages: [], messages: [],
}; };
await expect(startHandler(options)).resolves.not.toThrow(); await expect(startHandler(options)).resolves.not.toThrow();
expect(state.entry_id).toBe('tool-call-789'); expect(state.toolCallId).toBe('tool-call-789');
}); });
}); });
describe('createRespondWithoutAssetCreationDelta', () => { describe('createRespondWithoutAssetCreationDelta', () => {
test('should accumulate text deltas to args', async () => { test('should accumulate text deltas to args', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_', inputTextDelta: '{"final_',
@ -110,12 +110,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should extract partial final_response from incomplete JSON', async () => { test('should extract partial final_response from incomplete JSON', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_response": "This is a partial response that is still being', inputTextDelta: '{"final_response": "This is a partial response that is still being',
@ -129,12 +129,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should handle complete JSON in delta', async () => { test('should handle complete JSON in delta', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_response": "Complete response message"}', inputTextDelta: '{"final_response": "Complete response message"}',
@ -148,12 +148,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should handle markdown content in final_response', async () => { test('should handle markdown content in final_response', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
const markdownContent = `## Summary const markdownContent = `## Summary
@ -173,12 +173,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should handle escaped characters in JSON', async () => { test('should handle escaped characters in JSON', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_response": "Line 1\\nLine 2\\n\\"Quoted text\\""}', inputTextDelta: '{"final_response": "Line 1\\nLine 2\\n\\"Quoted text\\""}',
@ -191,12 +191,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should not update state when no final_response is extracted', async () => { test('should not update state when no final_response is extracted', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"other_field": "value"}', inputTextDelta: '{"other_field": "value"}',
@ -210,12 +210,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
test('should handle empty final_response gracefully', async () => { test('should handle empty final_response gracefully', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_response": ""}', inputTextDelta: '{"final_response": ""}',
@ -233,12 +233,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
workflowStartTime: Date.now(), workflowStartTime: Date.now(),
}; };
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, contextWithoutMessageId); const deltaHandler = createRespondWithoutAssetCreationDelta(contextWithoutMessageId, state);
await expect( await expect(
deltaHandler({ deltaHandler({
@ -255,12 +255,12 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
describe('createRespondWithoutAssetCreationFinish', () => { describe('createRespondWithoutAssetCreationFinish', () => {
test('should update state with final input on finish', async () => { test('should update state with final input on finish', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: '{"final_response": "Final message"}', args: '{"final_response": "Final message"}',
final_response: 'Final message', final_response: 'Final message',
}; };
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
const input: RespondWithoutAssetCreationInput = { const input: RespondWithoutAssetCreationInput = {
final_response: 'This is the final response message', final_response: 'This is the final response message',
@ -272,18 +272,18 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
messages: [], messages: [],
}); });
expect(state.entry_id).toBe('tool-call-123'); expect(state.toolCallId).toBe('tool-call-123');
expect(state.final_response).toBe('This is the final response message'); expect(state.final_response).toBe('This is the final response message');
}); });
test('should handle finish without prior entry_id', async () => { test('should handle finish without prior entry_id', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
const input: RespondWithoutAssetCreationInput = { const input: RespondWithoutAssetCreationInput = {
final_response: 'Response without prior start', final_response: 'Response without prior start',
@ -295,18 +295,18 @@ describe('Respond Without Asset Creation Tool Streaming Tests', () => {
messages: [], messages: [],
}); });
expect(state.entry_id).toBe('tool-call-456'); expect(state.toolCallId).toBe('tool-call-456');
expect(state.final_response).toBe('Response without prior start'); expect(state.final_response).toBe('Response without prior start');
}); });
test('should handle markdown formatted final response', async () => { test('should handle markdown formatted final response', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
const markdownResponse = ` const markdownResponse = `
## Analysis Complete ## Analysis Complete
@ -332,7 +332,7 @@ The following items were processed:
messages: [], messages: [],
}); });
expect(state.entry_id).toBe('tool-call-789'); expect(state.toolCallId).toBe('tool-call-789');
expect(state.final_response).toBe(markdownResponse); expect(state.final_response).toBe(markdownResponse);
}); });
@ -342,12 +342,12 @@ The following items were processed:
workflowStartTime: Date.now(), workflowStartTime: Date.now(),
}; };
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const finishHandler = createRespondWithoutAssetCreationFinish(state, contextWithoutMessageId); const finishHandler = createRespondWithoutAssetCreationFinish(contextWithoutMessageId, state);
const input: RespondWithoutAssetCreationInput = { const input: RespondWithoutAssetCreationInput = {
final_response: 'Test response without messageId', final_response: 'Test response without messageId',
@ -379,13 +379,13 @@ The following items were processed:
}; };
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const handler1 = createRespondWithoutAssetCreationStart(state, validContext); const handler1 = createRespondWithoutAssetCreationStart(validContext, state);
const handler2 = createRespondWithoutAssetCreationStart(state, extendedContext); const handler2 = createRespondWithoutAssetCreationStart(extendedContext, state);
expect(handler1).toBeDefined(); expect(handler1).toBeDefined();
expect(handler2).toBeDefined(); expect(handler2).toBeDefined();
@ -393,17 +393,17 @@ The following items were processed:
test('should maintain state type consistency through streaming lifecycle', async () => { test('should maintain state type consistency through streaming lifecycle', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const startHandler = createRespondWithoutAssetCreationStart(state, mockContext); const startHandler = createRespondWithoutAssetCreationStart(mockContext, state);
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
await startHandler({ toolCallId: 'test-123' }); await startHandler({ toolCallId: 'test-123' });
expect(state.entry_id).toBeTypeOf('string'); expect(state.toolCallId).toBeTypeOf('string');
await deltaHandler({ await deltaHandler({
inputTextDelta: '{"final_response": "Testing"}', inputTextDelta: '{"final_response": "Testing"}',
@ -417,7 +417,7 @@ The following items were processed:
final_response: 'Final test', final_response: 'Final test',
}; };
await finishHandler({ input, toolCallId: 'test-123', messages: [] }); await finishHandler({ input, toolCallId: 'test-123', messages: [] });
expect(state.entry_id).toBeTypeOf('string'); expect(state.toolCallId).toBeTypeOf('string');
expect(state.final_response).toBeTypeOf('string'); expect(state.final_response).toBeTypeOf('string');
}); });
}); });
@ -425,19 +425,19 @@ The following items were processed:
describe('Streaming Flow Integration', () => { describe('Streaming Flow Integration', () => {
test('should handle complete streaming flow from start to finish', async () => { test('should handle complete streaming flow from start to finish', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const startHandler = createRespondWithoutAssetCreationStart(state, mockContext); const startHandler = createRespondWithoutAssetCreationStart(mockContext, state);
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
const toolCallId = 'streaming-test-123'; const toolCallId = 'streaming-test-123';
await startHandler({ toolCallId }); await startHandler({ toolCallId });
expect(state.entry_id).toBe(toolCallId); expect(state.toolCallId).toBe(toolCallId);
const chunks = [ const chunks = [
'{"final_', '{"final_',
@ -468,7 +468,7 @@ The following items were processed:
}; };
await finishHandler({ input, toolCallId, messages: [] }); await finishHandler({ input, toolCallId, messages: [] });
expect(state.entry_id).toBe(toolCallId); expect(state.toolCallId).toBe(toolCallId);
expect(state.final_response).toBe( expect(state.final_response).toBe(
'This is a streaming response that comes in multiple chunks' 'This is a streaming response that comes in multiple chunks'
); );
@ -476,12 +476,12 @@ The following items were processed:
test('should handle streaming with special characters and formatting', async () => { test('should handle streaming with special characters and formatting', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
const chunks = [ const chunks = [
'{"final_response": "', '{"final_response": "',
@ -509,12 +509,12 @@ The following items were processed:
test('should handle streaming with very long responses', async () => { test('should handle streaming with very long responses', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
const longText = 'A'.repeat(1000); const longText = 'A'.repeat(1000);
const jsonWithLongText = JSON.stringify({ final_response: longText }); const jsonWithLongText = JSON.stringify({ final_response: longText });
@ -533,12 +533,12 @@ The following items were processed:
describe('Error Handling', () => { describe('Error Handling', () => {
test('should handle malformed JSON gracefully', async () => { test('should handle malformed JSON gracefully', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: 'test-entry', toolCallId: 'test-entry',
args: '', args: '',
final_response: undefined, final_response: undefined,
}; };
const deltaHandler = createRespondWithoutAssetCreationDelta(state, mockContext); const deltaHandler = createRespondWithoutAssetCreationDelta(mockContext, state);
await expect( await expect(
deltaHandler({ deltaHandler({
@ -554,12 +554,12 @@ The following items were processed:
test('should handle null or undefined values', async () => { test('should handle null or undefined values', async () => {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const finishHandler = createRespondWithoutAssetCreationFinish(state, mockContext); const finishHandler = createRespondWithoutAssetCreationFinish(mockContext, state);
const input: RespondWithoutAssetCreationInput = { const input: RespondWithoutAssetCreationInput = {
final_response: '', final_response: '',

View File

@ -16,7 +16,9 @@ export const RespondWithoutAssetCreationInputSchema = z.object({
), ),
}); });
export const RespondWithoutAssetCreationOutputSchema = z.object({}); export const RespondWithoutAssetCreationOutputSchema = z.object({
success: z.boolean().describe('Whether the operation was successful'),
});
const RespondWithoutAssetCreationContextSchema = z.object({ const RespondWithoutAssetCreationContextSchema = z.object({
messageId: z messageId: z
@ -28,7 +30,7 @@ const RespondWithoutAssetCreationContextSchema = z.object({
}); });
const RespondWithoutAssetCreationStateSchema = z.object({ const RespondWithoutAssetCreationStateSchema = z.object({
entry_id: z toolCallId: z
.string() .string()
.optional() .optional()
.describe( .describe(
@ -58,15 +60,15 @@ export type RespondWithoutAssetCreationState = z.infer<
export function createRespondWithoutAssetCreationTool(context: RespondWithoutAssetCreationContext) { export function createRespondWithoutAssetCreationTool(context: RespondWithoutAssetCreationContext) {
const state: RespondWithoutAssetCreationState = { const state: RespondWithoutAssetCreationState = {
entry_id: undefined, toolCallId: undefined,
args: undefined, args: undefined,
final_response: undefined, final_response: undefined,
}; };
const execute = createRespondWithoutAssetCreationExecute(); const execute = createRespondWithoutAssetCreationExecute(context, state);
const onInputStart = createRespondWithoutAssetCreationStart(state, context); const onInputStart = createRespondWithoutAssetCreationStart(context, state);
const onInputDelta = createRespondWithoutAssetCreationDelta(state, context); const onInputDelta = createRespondWithoutAssetCreationDelta(context, state);
const onInputAvailable = createRespondWithoutAssetCreationFinish(state, context); const onInputAvailable = createRespondWithoutAssetCreationFinish(context, state);
return tool({ return tool({
description: description: