wave-agent-sdk 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/agent.js +7 -4
  2. package/dist/managers/aiManager.d.ts.map +1 -1
  3. package/dist/managers/aiManager.js +10 -9
  4. package/dist/managers/hookManager.d.ts +4 -12
  5. package/dist/managers/hookManager.d.ts.map +1 -1
  6. package/dist/managers/hookManager.js +19 -14
  7. package/dist/managers/messageManager.d.ts +3 -11
  8. package/dist/managers/messageManager.d.ts.map +1 -1
  9. package/dist/managers/messageManager.js +6 -20
  10. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  11. package/dist/managers/slashCommandManager.js +5 -2
  12. package/dist/managers/subagentManager.js +1 -1
  13. package/dist/tools/todoWriteTool.d.ts.map +1 -1
  14. package/dist/tools/todoWriteTool.js +3 -10
  15. package/dist/types/messaging.d.ts +7 -7
  16. package/dist/types/messaging.d.ts.map +1 -1
  17. package/dist/types/messaging.js +5 -1
  18. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  19. package/dist/utils/convertMessagesForAPI.js +1 -8
  20. package/dist/utils/hookMatcher.d.ts +1 -6
  21. package/dist/utils/hookMatcher.d.ts.map +1 -1
  22. package/dist/utils/messageOperations.d.ts +9 -21
  23. package/dist/utils/messageOperations.d.ts.map +1 -1
  24. package/dist/utils/messageOperations.js +21 -20
  25. package/package.json +1 -1
  26. package/src/agent.ts +3 -3
  27. package/src/managers/aiManager.ts +8 -9
  28. package/src/managers/hookManager.ts +23 -44
  29. package/src/managers/messageManager.ts +8 -38
  30. package/src/managers/slashCommandManager.ts +5 -6
  31. package/src/managers/subagentManager.ts +1 -1
  32. package/src/tools/todoWriteTool.ts +3 -11
  33. package/src/types/messaging.ts +7 -8
  34. package/src/utils/convertMessagesForAPI.ts +1 -9
  35. package/src/utils/hookMatcher.ts +1 -12
  36. package/src/utils/messageOperations.ts +37 -42
  37. package/src/types/index.ts.backup +0 -357
@@ -57,15 +57,16 @@ export const convertImageToBase64 = (imagePath) => {
57
57
  }
58
58
  };
59
59
  // Add user message
60
- export const addUserMessageToMessages = ({ messages, content, images, customCommandBlock, }) => {
60
+ export const addUserMessageToMessages = ({ messages, content, images, customCommandContent, source, }) => {
61
61
  const blocks = [];
62
- // If there's a custom command block, use it instead of text content
63
- if (customCommandBlock) {
64
- blocks.push(customCommandBlock);
65
- }
66
- else {
67
- blocks.push({ type: "text", content });
68
- }
62
+ // Create text block with optional customCommandContent and source
63
+ const textBlock = {
64
+ type: "text",
65
+ content,
66
+ ...(customCommandContent && { customCommandContent }),
67
+ ...(source && { source }),
68
+ };
69
+ blocks.push(textBlock);
69
70
  // If there are images, add image block
70
71
  if (images && images.length > 0) {
71
72
  const imageUrls = images.map((img) => img.path);
@@ -174,23 +175,23 @@ export const updateToolBlockInMessage = ({ messages, id, parameters, result, suc
174
175
  // Add Error Block to the last assistant message
175
176
  export const addErrorBlockToMessage = ({ messages, error, }) => {
176
177
  const newMessages = [...messages];
177
- // Find the last assistant message
178
- let assistantMessageFound = false;
179
- for (let i = newMessages.length - 1; i >= 0; i--) {
180
- if (newMessages[i].role === "assistant") {
181
- newMessages[i].blocks = [
182
- ...newMessages[i].blocks,
178
+ // Check if the last message is an assistant message
179
+ const lastMessage = newMessages[newMessages.length - 1];
180
+ if (lastMessage && lastMessage.role === "assistant") {
181
+ // Create a new message object with the error block added
182
+ newMessages[newMessages.length - 1] = {
183
+ ...lastMessage,
184
+ blocks: [
185
+ ...lastMessage.blocks,
183
186
  {
184
187
  type: "error",
185
188
  content: error,
186
189
  },
187
- ];
188
- assistantMessageFound = true;
189
- break;
190
- }
190
+ ],
191
+ };
191
192
  }
192
- // If no assistant message found, create a new assistant message with only error block
193
- if (!assistantMessageFound) {
193
+ else {
194
+ // If the last message is not an assistant message, create a new assistant message
194
195
  newMessages.push({
195
196
  role: "assistant",
196
197
  blocks: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
package/src/agent.ts CHANGED
@@ -487,13 +487,13 @@ export class Agent {
487
487
  this.addToInputHistory(content);
488
488
 
489
489
  // Add user message first, will automatically sync to UI
490
- this.messageManager.addUserMessage(
490
+ this.messageManager.addUserMessage({
491
491
  content,
492
- images?.map((img) => ({
492
+ images: images?.map((img) => ({
493
493
  path: img.path,
494
494
  mimeType: img.mimeType,
495
495
  })),
496
- );
496
+ });
497
497
 
498
498
  // Execute UserPromptSubmit hooks after adding the user message
499
499
  if (this.hookManager) {
@@ -282,6 +282,7 @@ export class AIManager {
282
282
 
283
283
  if (result.tool_calls) {
284
284
  for (const toolCall of result.tool_calls) {
285
+ this.logger?.debug("ToolCall", toolCall);
285
286
  if (toolCall.type === "function") {
286
287
  toolCalls.push(toolCall);
287
288
  }
@@ -351,8 +352,8 @@ export class AIManager {
351
352
  );
352
353
 
353
354
  this.messageManager.updateToolBlock({
354
- toolId,
355
- args: JSON.stringify(toolArgs, null, 2),
355
+ id: toolId,
356
+ parameters: JSON.stringify(toolArgs, null, 2),
356
357
  isRunning: true, // isRunning: true
357
358
  name: toolName,
358
359
  compactParams,
@@ -390,8 +391,8 @@ export class AIManager {
390
391
 
391
392
  // Update message state - tool execution completed
392
393
  this.messageManager.updateToolBlock({
393
- toolId,
394
- args: JSON.stringify(toolArgs, null, 2),
394
+ id: toolId,
395
+ parameters: JSON.stringify(toolArgs, null, 2),
395
396
  result:
396
397
  toolResult.content ||
397
398
  (toolResult.error ? `Error: ${toolResult.error}` : ""),
@@ -429,8 +430,8 @@ export class AIManager {
429
430
  : String(toolError);
430
431
 
431
432
  this.messageManager.updateToolBlock({
432
- toolId,
433
- args: JSON.stringify(toolArgs, null, 2),
433
+ id: toolId,
434
+ parameters: JSON.stringify(toolArgs, null, 2),
434
435
  result: `Tool execution failed: ${errorMessage}`,
435
436
  success: false,
436
437
  error: errorMessage,
@@ -614,6 +615,7 @@ export class AIManager {
614
615
  results,
615
616
  this.messageManager,
616
617
  toolId, // Pass toolId for proper PreToolUse blocking error handling
618
+ JSON.stringify(toolInput || {}, null, 2), // Pass serialized tool parameters
617
619
  );
618
620
  shouldContinue = !processResult.shouldBlock;
619
621
  }
@@ -671,14 +673,11 @@ export class AIManager {
671
673
 
672
674
  // Process hook results to handle exit codes and update tool results
673
675
  if (results.length > 0) {
674
- const originalToolResult = toolResponse?.content || "";
675
-
676
676
  this.hookManager.processHookResults(
677
677
  "PostToolUse",
678
678
  results,
679
679
  this.messageManager,
680
680
  toolId,
681
- originalToolResult,
682
681
  );
683
682
  }
684
683
 
@@ -18,50 +18,25 @@ import {
18
18
  isValidHookEvent,
19
19
  isValidHookEventConfig,
20
20
  } from "../types/hooks.js";
21
- import { type IHookMatcher, HookMatcher } from "../utils/hookMatcher.js";
21
+ import { HookMatcher } from "../utils/hookMatcher.js";
22
22
  import {
23
23
  executeCommand,
24
24
  isCommandSafe,
25
25
  loadMergedHooksConfig,
26
26
  } from "../services/hook.js";
27
27
  import type { Logger } from "../types/index.js";
28
+ import { MessageSource } from "../types/index.js";
28
29
  import type { MessageManager } from "./messageManager.js";
29
30
 
30
- export interface IHookManager {
31
- // Load configuration from settings
32
- loadConfiguration(
33
- userHooks?: PartialHookConfiguration,
34
- projectHooks?: PartialHookConfiguration,
35
- ): void;
36
-
37
- // Load configuration from filesystem settings
38
- loadConfigurationFromSettings(): void;
39
-
40
- // Execute hooks for specific event
41
- executeHooks(
42
- event: HookEvent,
43
- context: HookExecutionContext | ExtendedHookExecutionContext,
44
- ): Promise<HookExecutionResult[]>;
45
-
46
- // Check if hooks are configured for event
47
- hasHooks(event: HookEvent, toolName?: string): boolean;
48
-
49
- // Validate hook configuration
50
- validateConfiguration(config: HookConfiguration): ValidationResult;
51
-
52
- // Get current configuration
53
- getConfiguration(): PartialHookConfiguration | undefined;
54
- }
55
-
56
- export class HookManager implements IHookManager {
31
+ export class HookManager {
57
32
  private configuration: PartialHookConfiguration | undefined;
58
- private readonly matcher: IHookMatcher;
33
+ private readonly matcher: HookMatcher;
59
34
  private readonly logger?: Logger;
60
35
  private readonly workdir: string;
61
36
 
62
37
  constructor(
63
38
  workdir: string,
64
- matcher: IHookMatcher = new HookMatcher(),
39
+ matcher: HookMatcher = new HookMatcher(),
65
40
  logger?: Logger,
66
41
  ) {
67
42
  this.workdir = workdir;
@@ -274,7 +249,7 @@ export class HookManager implements IHookManager {
274
249
  results: HookExecutionResult[],
275
250
  messageManager?: MessageManager,
276
251
  toolId?: string,
277
- originalToolResult?: string,
252
+ toolParameters?: string,
278
253
  ): {
279
254
  shouldBlock: boolean;
280
255
  errorMessage?: string;
@@ -293,7 +268,7 @@ export class HookManager implements IHookManager {
293
268
  result,
294
269
  messageManager,
295
270
  toolId,
296
- originalToolResult,
271
+ toolParameters,
297
272
  );
298
273
  }
299
274
  }
@@ -327,7 +302,10 @@ export class HookManager implements IHookManager {
327
302
  ): void {
328
303
  if (event === "UserPromptSubmit" && result.stdout?.trim()) {
329
304
  // Inject stdout as user message context for UserPromptSubmit
330
- messageManager.addUserMessage(result.stdout.trim());
305
+ messageManager.addUserMessage({
306
+ content: result.stdout.trim(),
307
+ source: MessageSource.HOOK,
308
+ });
331
309
  }
332
310
  // For other hook types (PreToolUse, PostToolUse, Stop), ignore stdout
333
311
  }
@@ -340,7 +318,7 @@ export class HookManager implements IHookManager {
340
318
  result: HookExecutionResult,
341
319
  messageManager: MessageManager,
342
320
  toolId?: string,
343
- originalToolResult?: string,
321
+ toolParameters?: string,
344
322
  ): {
345
323
  shouldBlock: boolean;
346
324
  errorMessage?: string;
@@ -361,7 +339,8 @@ export class HookManager implements IHookManager {
361
339
  // Block tool execution and show error to Wave Agent via tool block
362
340
  if (toolId) {
363
341
  messageManager.updateToolBlock({
364
- toolId,
342
+ id: toolId,
343
+ parameters: toolParameters || "",
365
344
  result: errorMessage,
366
345
  success: false,
367
346
  error: "Hook blocked tool execution",
@@ -370,19 +349,19 @@ export class HookManager implements IHookManager {
370
349
  return { shouldBlock: true };
371
350
 
372
351
  case "PostToolUse":
373
- // Show error to Wave Agent via tool block, execution continues
374
- if (toolId && originalToolResult !== undefined) {
375
- messageManager.updateToolBlock({
376
- toolId,
377
- result: `${originalToolResult}\n\nHook feedback: ${errorMessage}`,
378
- success: false,
379
- });
380
- }
352
+ // Show error to Wave Agent via user message and allow AI to continue
353
+ messageManager.addUserMessage({
354
+ content: errorMessage,
355
+ source: MessageSource.HOOK,
356
+ });
381
357
  return { shouldBlock: false };
382
358
 
383
359
  case "Stop":
384
360
  // Show error to Wave Agent via user message and block stopping to continue conversation
385
- messageManager.addUserMessage(errorMessage);
361
+ messageManager.addUserMessage({
362
+ content: errorMessage,
363
+ source: MessageSource.HOOK,
364
+ });
386
365
  return { shouldBlock: true, errorMessage };
387
366
 
388
367
  default:
@@ -13,6 +13,7 @@ import {
13
13
  addSubagentBlockToMessage,
14
14
  updateSubagentBlockInMessage,
15
15
  removeLastUserMessage,
16
+ UserMessageParams,
16
17
  type AddSubagentBlockParams,
17
18
  type UpdateSubagentBlockParams,
18
19
  type AgentToolBlockUpdateParams,
@@ -35,10 +36,7 @@ export interface MessageManagerCallbacks {
35
36
  onUserInputHistoryChange?: (history: string[]) => void;
36
37
  onUsagesChange?: (usages: Usage[]) => void;
37
38
  // Incremental callback
38
- onUserMessageAdded?: (
39
- content: string,
40
- images?: Array<{ path: string; mimeType: string }>,
41
- ) => void;
39
+ onUserMessageAdded?: (params: UserMessageParams) => void;
42
40
  onAssistantMessageAdded?: (
43
41
  content?: string,
44
42
  toolCalls?: ChatCompletionMessageFunctionToolCall[],
@@ -54,12 +52,6 @@ export interface MessageManagerCallbacks {
54
52
  type: "project" | "user",
55
53
  storagePath: string,
56
54
  ) => void;
57
- // Custom command callback
58
- onCustomCommandAdded?: (
59
- commandName: string,
60
- content: string,
61
- originalInput?: string,
62
- ) => void;
63
55
  // Bash command callback
64
56
  onAddCommandOutputMessage?: (command: string) => void;
65
57
  onUpdateCommandOutputMessage?: (command: string, output: string) => void;
@@ -281,36 +273,13 @@ export class MessageManager {
281
273
  }
282
274
 
283
275
  // Encapsulated message operation functions
284
- public addUserMessage(
285
- content: string,
286
- images?: Array<{ path: string; mimeType: string }>,
287
- ): void {
288
- const newMessages = addUserMessageToMessages({
289
- messages: this.messages,
290
- content,
291
- images,
292
- });
293
- this.setMessages(newMessages);
294
- this.callbacks.onUserMessageAdded?.(content, images);
295
- }
296
-
297
- public addCustomCommandMessage(
298
- commandName: string,
299
- content: string,
300
- originalInput?: string,
301
- ): void {
276
+ public addUserMessage(params: UserMessageParams): void {
302
277
  const newMessages = addUserMessageToMessages({
303
278
  messages: this.messages,
304
- content: "", // Empty content, as we will use CustomCommandBlock
305
- customCommandBlock: {
306
- type: "custom_command",
307
- commandName,
308
- content,
309
- originalInput,
310
- },
279
+ ...params,
311
280
  });
312
281
  this.setMessages(newMessages);
313
- this.callbacks.onCustomCommandAdded?.(commandName, content, originalInput);
282
+ this.callbacks.onUserMessageAdded?.(params);
314
283
  }
315
284
 
316
285
  public addAssistantMessage(
@@ -331,14 +300,15 @@ export class MessageManager {
331
300
  public updateToolBlock(params: AgentToolBlockUpdateParams): void {
332
301
  const newMessages = updateToolBlockInMessage({
333
302
  messages: this.messages,
334
- id: params.toolId,
335
- parameters: params.args || "",
303
+ id: params.id,
304
+ parameters: params.parameters,
336
305
  result: params.result,
337
306
  success: params.success,
338
307
  error: params.error,
339
308
  isRunning: params.isRunning,
340
309
  name: params.name,
341
310
  shortResult: params.shortResult,
311
+ images: params.images,
342
312
  compactParams: params.compactParams,
343
313
  });
344
314
  this.setMessages(newMessages);
@@ -257,15 +257,14 @@ export class SlashCommandManager {
257
257
  ? replaceBashCommandsWithOutput(processedContent, bashResults)
258
258
  : processedContent;
259
259
 
260
- // Add custom command block to show the command being executed
260
+ // Add custom command message to show the command being executed
261
261
  const originalInput = args
262
262
  ? `/${commandName} ${args}`
263
263
  : `/${commandName}`;
264
- this.messageManager.addCustomCommandMessage(
265
- commandName,
266
- finalContent,
267
- originalInput,
268
- );
264
+ this.messageManager.addUserMessage({
265
+ content: originalInput,
266
+ customCommandContent: finalContent,
267
+ });
269
268
 
270
269
  // Execute the AI conversation with custom configuration
271
270
  await this.aiManager.sendAIMessage({
@@ -232,7 +232,7 @@ export class SubagentManager {
232
232
  }
233
233
 
234
234
  // Add the user's prompt as a message
235
- instance.messageManager.addUserMessage(prompt);
235
+ instance.messageManager.addUserMessage({ content: prompt });
236
236
 
237
237
  // Create allowed tools list - always exclude Task tool to prevent subagent recursion
238
238
  let allowedTools = instance.configuration.tools;
@@ -200,18 +200,10 @@ When in doubt, use this tool. Being proactive with task management demonstrates
200
200
  in_progress: "[>]",
201
201
  completed: "[x]",
202
202
  };
203
- const inProgress = todos.filter((t) => t.status === "in_progress");
204
- const pending = todos.filter((t) => t.status === "pending");
205
203
 
206
- if (inProgress.length > 0) {
207
- shortResult += `\n${symbols.in_progress} ${inProgress[0].content}`;
208
- }
209
-
210
- if (pending.length > 0) {
211
- shortResult += `\n${symbols.pending} ${pending[0].content}`;
212
- if (pending.length > 1) {
213
- shortResult += ` +${pending.length - 1}`;
214
- }
204
+ // Show all todos in the shortResult
205
+ for (const todo of todos) {
206
+ shortResult += `\n${symbols[todo.status]} ${todo.content}`;
215
207
  }
216
208
  }
217
209
 
@@ -5,6 +5,11 @@
5
5
 
6
6
  import type { Usage } from "./core.js";
7
7
 
8
+ export enum MessageSource {
9
+ USER = "user",
10
+ HOOK = "hook",
11
+ }
12
+
8
13
  export interface Message {
9
14
  role: "user" | "assistant";
10
15
  blocks: MessageBlock[];
@@ -20,12 +25,13 @@ export type MessageBlock =
20
25
  | CommandOutputBlock
21
26
  | CompressBlock
22
27
  | MemoryBlock
23
- | CustomCommandBlock
24
28
  | SubagentBlock;
25
29
 
26
30
  export interface TextBlock {
27
31
  type: "text";
28
32
  content: string;
33
+ customCommandContent?: string;
34
+ source?: MessageSource;
29
35
  }
30
36
 
31
37
  export interface ErrorBlock {
@@ -87,13 +93,6 @@ export interface MemoryBlock {
87
93
  storagePath?: string; // Storage path text
88
94
  }
89
95
 
90
- export interface CustomCommandBlock {
91
- type: "custom_command";
92
- commandName: string;
93
- content: string; // Complete command content, used when passing to AI
94
- originalInput?: string; // Original user input, used for UI display (e.g., "/fix-issue 123 high")
95
- }
96
-
97
96
  export interface SubagentBlock {
98
97
  type: "subagent";
99
98
  subagentId: string;
@@ -176,15 +176,7 @@ export function convertMessagesForAPI(
176
176
  if (block.type === "text" && block.content) {
177
177
  contentParts.push({
178
178
  type: "text",
179
- text: block.content,
180
- });
181
- }
182
-
183
- // Handle custom command blocks - pass full content as text to AI
184
- if (block.type === "custom_command" && block.content) {
185
- contentParts.push({
186
- type: "text",
187
- text: block.content,
179
+ text: block.customCommandContent || block.content,
188
180
  });
189
181
  }
190
182
 
@@ -7,18 +7,7 @@
7
7
 
8
8
  import { minimatch } from "minimatch";
9
9
 
10
- export interface IHookMatcher {
11
- // Test if pattern matches tool name
12
- matches(pattern: string, toolName: string): boolean;
13
-
14
- // Validate pattern syntax
15
- isValidPattern(pattern: string): boolean;
16
-
17
- // Get pattern type for optimization
18
- getPatternType(pattern: string): "exact" | "glob" | "regex" | "alternatives";
19
- }
20
-
21
- export class HookMatcher implements IHookMatcher {
10
+ export class HookMatcher {
22
11
  /**
23
12
  * Test if pattern matches tool name
24
13
  * Supports multiple matching strategies:
@@ -1,19 +1,19 @@
1
- import type { Message, Usage } from "../types/index.js";
1
+ import type { Message, Usage, MessageSource } from "../types/index.js";
2
2
  import { readFileSync } from "fs";
3
3
  import { extname } from "path";
4
4
  import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
5
5
 
6
- // Parameter interfaces for message operations
7
- export interface AddUserMessageParams {
8
- messages: Message[];
6
+ // Base user message parameters interface
7
+ export interface UserMessageParams {
9
8
  content: string;
10
9
  images?: Array<{ path: string; mimeType: string }>;
11
- customCommandBlock?: {
12
- type: "custom_command";
13
- commandName: string;
14
- content: string;
15
- originalInput?: string;
16
- };
10
+ customCommandContent?: string;
11
+ source?: MessageSource;
12
+ }
13
+
14
+ // Parameter interfaces for message operations
15
+ export interface AddUserMessageParams extends UserMessageParams {
16
+ messages: Message[];
17
17
  }
18
18
 
19
19
  export interface UpdateToolBlockParams {
@@ -31,17 +31,10 @@ export interface UpdateToolBlockParams {
31
31
  }
32
32
 
33
33
  // Agent specific interfaces (without messages parameter)
34
- export interface AgentToolBlockUpdateParams {
35
- toolId: string;
36
- args?: string;
37
- result?: string;
38
- success?: boolean;
39
- error?: string;
40
- isRunning?: boolean;
41
- name?: string;
42
- shortResult?: string;
43
- compactParams?: string;
44
- }
34
+ export type AgentToolBlockUpdateParams = Omit<
35
+ UpdateToolBlockParams,
36
+ "messages"
37
+ >;
45
38
 
46
39
  export interface AddDiffBlockParams {
47
40
  messages: Message[];
@@ -145,16 +138,19 @@ export const addUserMessageToMessages = ({
145
138
  messages,
146
139
  content,
147
140
  images,
148
- customCommandBlock,
141
+ customCommandContent,
142
+ source,
149
143
  }: AddUserMessageParams): Message[] => {
150
144
  const blocks: Message["blocks"] = [];
151
145
 
152
- // If there's a custom command block, use it instead of text content
153
- if (customCommandBlock) {
154
- blocks.push(customCommandBlock);
155
- } else {
156
- blocks.push({ type: "text", content });
157
- }
146
+ // Create text block with optional customCommandContent and source
147
+ const textBlock = {
148
+ type: "text" as const,
149
+ content,
150
+ ...(customCommandContent && { customCommandContent }),
151
+ ...(source && { source }),
152
+ };
153
+ blocks.push(textBlock);
158
154
 
159
155
  // If there are images, add image block
160
156
  if (images && images.length > 0) {
@@ -294,24 +290,23 @@ export const addErrorBlockToMessage = ({
294
290
  error,
295
291
  }: AddErrorBlockParams): Message[] => {
296
292
  const newMessages = [...messages];
297
- // Find the last assistant message
298
- let assistantMessageFound = false;
299
- for (let i = newMessages.length - 1; i >= 0; i--) {
300
- if (newMessages[i].role === "assistant") {
301
- newMessages[i].blocks = [
302
- ...newMessages[i].blocks,
293
+
294
+ // Check if the last message is an assistant message
295
+ const lastMessage = newMessages[newMessages.length - 1];
296
+ if (lastMessage && lastMessage.role === "assistant") {
297
+ // Create a new message object with the error block added
298
+ newMessages[newMessages.length - 1] = {
299
+ ...lastMessage,
300
+ blocks: [
301
+ ...lastMessage.blocks,
303
302
  {
304
303
  type: "error",
305
304
  content: error,
306
305
  },
307
- ];
308
- assistantMessageFound = true;
309
- break;
310
- }
311
- }
312
-
313
- // If no assistant message found, create a new assistant message with only error block
314
- if (!assistantMessageFound) {
306
+ ],
307
+ };
308
+ } else {
309
+ // If the last message is not an assistant message, create a new assistant message
315
310
  newMessages.push({
316
311
  role: "assistant",
317
312
  blocks: [