Skip to content

Commit db97787

Browse files
Copilothotlong
andcommitted
Fix all PR review comments: hooks rules, ESM import, timer cleanup, docs alignment
Addresses all 11 review comments from copilot-pull-request-reviewer: 1. Fix Rules of Hooks violation: lock mode on first render via useRef instead of conditionally calling different hook implementations. useChat is now always called (with /noop api in local mode). 2. Replace require('@ai-sdk/react') with static ESM import to avoid runtime crashes in browser/ESM builds where require is undefined. 3. Include 'tool' in role union when converting initial messages for useChat, matching the expanded ChatMessage.role type. 4. Fix onSend callback in API mode to include newly appended user message in the messages array (consistent with local mode). 5. Add useEffect cleanup to cancel auto-response timer on unmount, preventing state updates on unmounted components. 6. Fix clear() in local mode to cancel pending auto-response timer by calling stop() before clearing messages. 7. Fix conversationId doc comment to say "x-conversation-id header" matching the actual implementation. 8. Fix tool messages docs to accurately describe rendering behavior (tool role messages render as assistant bubbles in current UI). 9. Fix AIWithToolCalls story comment to not imply UI display of toolInvocations (metadata only, no dedicated rendering). 10. Remove duplicate "### Added" heading in CHANGELOG.md. 11. Remove avatar/avatarFallback from ChatMessage docs (not in types, avatars are configured at Chatbot schema level). Added metadata and timestamp type alignment with actual types. Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/cbd1330e-479e-448d-a9b6-9e34df3edfb5 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 42f6b4a commit db97787

File tree

6 files changed

+179
-187
lines changed

6 files changed

+179
-187
lines changed

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515

1616
- **New Storybook stories for AI chatbot** (`@object-ui/components`): Added `AIStreamingMode`, `AIWithSystemPrompt`, and `AIWithToolCalls` stories demonstrating the new AI SDUI chat modes alongside existing local/demo stories.
1717

18-
### Added
19-
2018
- **Object Manager visual designer** (`@object-ui/plugin-designer`): Enterprise-grade object management interface for creating, editing, deleting, and configuring meta-object definitions. Uses standard ObjectGrid for the list view and ModalForm for create/edit operations. Features include property editing (name, label, plural label, description, icon, group, sort order, enabled toggle), object relationship display, search/filter, system object protection, confirm dialogs for destructive actions, and read-only mode. 18 unit tests.
2119

2220
- **Field Designer visual designer** (`@object-ui/plugin-designer`): Enterprise-grade field configuration wizard supporting 27 field types with full CRUD operations. Uses standard ObjectGrid for the list view with a specialized FieldEditor panel for advanced type-specific properties. Features include uniqueness constraints, default values, picklist/option set management, read-only, hidden, validation rules (min/max/length/pattern/custom), external ID, history tracking, and database indexing. Type-specific editors for lookup references, formula expressions, and select options. Field type filtering, search, system field protection, and read-only mode. 22 unit tests.

content/docs/plugins/plugin-chatbot.mdx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,8 @@ const schema = {
191191
id: string,
192192
role: 'user' | 'assistant' | 'system' | 'tool',
193193
content: string,
194-
timestamp?: string,
195-
avatar?: string,
196-
avatarFallback?: string,
194+
timestamp?: string | Date,
195+
metadata?: any,
197196
streaming?: boolean,
198197
toolInvocations?: ChatToolInvocation[],
199198
}
@@ -302,7 +301,7 @@ System messages appear centered with muted styling:
302301

303302
### Tool Messages (AI Mode)
304303

305-
Tool messages represent results from tool invocations during AI streaming. They are generated automatically by the vercel/ai SDK when the backend performs tool calls (e.g., fetching weather, querying a database). Tool messages are not displayed directly — their results are embedded in the assistant message's `toolInvocations` array:
304+
Tool messages represent results from tool invocations during AI streaming. They are generated automatically by the vercel/ai SDK when the backend performs tool calls (e.g., fetching weather, querying a database). The SDK may emit `role: 'tool'` messages as well as populate the assistant message's `toolInvocations` array. In the current chat UI, any non-`user` role (including `tool`) is rendered as an assistant bubble, so if you do not want raw tool messages to appear you should filter them out before rendering and instead rely on the assistant message's `toolInvocations`:
306305

307306
```tsx
308307
{

packages/components/src/stories-json/chatbot.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ export const AIWithSystemPrompt: Story = {
315315
};
316316

317317
/**
318-
* AI Chat with tool invocations display.
318+
* AI Chat including tool invocation metadata in messages.
319319
*/
320320
export const AIWithToolCalls: Story = {
321321
render: renderStory,

packages/plugin-chatbot/src/__tests__/useObjectChat.test.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@
99
import '@testing-library/jest-dom';
1010
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
1111
import { renderHook, act } from '@testing-library/react';
12+
13+
// Mock @ai-sdk/react so the static import in useObjectChat doesn't break tests
14+
vi.mock('@ai-sdk/react', () => ({
15+
useChat: vi.fn(() => ({
16+
messages: [],
17+
isLoading: false,
18+
error: undefined,
19+
input: '',
20+
setInput: vi.fn(),
21+
handleInputChange: vi.fn(),
22+
append: vi.fn(),
23+
stop: vi.fn(),
24+
reload: vi.fn(),
25+
setMessages: vi.fn(),
26+
})),
27+
}));
28+
1229
import { useObjectChat } from '../useObjectChat';
1330

1431
describe('useObjectChat', () => {
@@ -295,5 +312,36 @@ describe('useObjectChat', () => {
295312
const { result } = renderHook(() => useObjectChat({ api: '' }));
296313
expect(result.current.isApiMode).toBe(false);
297314
});
315+
316+
it('should cancel pending auto-response timer when clear is called', () => {
317+
const { result } = renderHook(() =>
318+
useObjectChat({
319+
autoResponse: true,
320+
autoResponseText: 'Auto reply!',
321+
autoResponseDelay: 1000,
322+
})
323+
);
324+
325+
act(() => {
326+
result.current.sendMessage('Hello');
327+
});
328+
329+
expect(result.current.messages).toHaveLength(1);
330+
expect(result.current.isLoading).toBe(true);
331+
332+
act(() => {
333+
result.current.clear();
334+
});
335+
336+
expect(result.current.messages).toHaveLength(0);
337+
expect(result.current.isLoading).toBe(false);
338+
339+
// Advance time - no auto-response should appear after clear
340+
act(() => {
341+
vi.advanceTimersByTime(2000);
342+
});
343+
344+
expect(result.current.messages).toHaveLength(0);
345+
});
298346
});
299347
});

0 commit comments

Comments
 (0)