@rizal_ncc/agent-client
v1.4.6
Published
UI wrapper and helpers for BAWANA AI agent integrations
Readme
Agen Client
A component (for now support react and vanilla) and headless core for AI agent chat interfaces, designed for seamless integration with a compatible backend API. Provides built-in transport logic, flexible layouts, and tool result handling, while allowing full customization through props and custom transport functions.
Table of Contents
- Install
- Quick Start (React)
- Layouts
- AiAgentChat Props
- Built-in Transport Contract
- Headless Core Usage
- Tool Result Helpers
- Theme and Styling
- Architecture
- Testing
- Development
- Playground (Local Source Mode)
- Release and Publish
- File Map
- Known Tradeoffs
Install
npm install @rizal_ncc/agent-clientQuick Start (React)
import { AiAgentChat } from "@rizal_ncc/agent-client/react";
import "@rizal_ncc/agent-client/style.css";
export function App() {
return (
<AiAgentChat
baseURL="https://example.com/api"
accessToken="your-access-token"
agent="home-assistant"
primaryColor="#0f766e"
primaryForeground="#ffffff"
suggestedMessages={[
"recommend leadership course",
"recommend data analysis course",
]}
/>
);
}Layouts
The component supports three layouts:
inline: always open in page flow.floating: fixed toggle button + popover panel.dropdown: inline toggle bar + expandable panel.
Examples:
<AiAgentChat layout="inline" />
<AiAgentChat layout="floating" defaultOpen={false} />
<AiAgentChat layout="dropdown" defaultOpen={false} panelHeight="560px" />Open state control:
- Controlled: pass
open+onOpenChange. - Uncontrolled: pass
defaultOpen.
AiAgentChat Props
Core
baseURL?: stringbackend base URL (required for built-in transport)accessToken?: string | () => string | undefined | Promise<string | undefined>bearer token provider (required for built-in transport)agent?: stringdefaulthome-assistantmetadata?: { course_id?: number }requestHeaders?: HeadersInitrespondPath?: stringendpoint overridegenerateResponse?: (request) => Promise<{ content: string }>custom transport override
UI
headerTitle?: stringheaderDescription?: stringsuggestedMessages?: string[]assistantAvatar?: ReactNodeassistantAvatarUrl?: stringdefault bundled package avatar (override as needed)assistantInitials?: stringdefaultAIuserInitials?: stringdefaultYOUinitials?: booleandefaulttrueplaceholder?: stringdefaultAsk the assistant...sendLabel?: stringdefaultSendstopLabel?: stringdefaultStopclassName?: string
Theme
primaryColor?: stringdefault#1168bbprimaryForeground?: stringdefault#ffffffpanelHeight?: stringoptional CSS height override (uses CSS variable fallback if omitted)zIndex?: numberdefault60
Layout control
layout?: "inline" | "floating" | "dropdown"defaultinlineopen?: booleandefaultOpen?: booleanonOpenChange?: (open: boolean) => voidfloatingPosition?: "bottom-right" | "bottom-left"defaultbottom-rightopenLabel?: stringdefaultOpen chatcloseLabel?: stringdefaultClose chat
Events
onMessage?: (message, messages) => voidonError?: (error, messages) => void
Built-in Transport Contract
If generateResponse is not provided, AiAgentChat performs backend requests.
Path resolution:
- if
baseURLends with/api->POST /v2/ai-agent/respond/ - otherwise ->
POST /api/v2/ai-agent/respond/
Request body:
agentmessage(latest user message)metadata
Expected response shape (minimum):
message: stringtool_results?: ToolResult[]
Recommendation behavior:
- Renders
get_course_recommendationresults as horizontal cards. - Uses
nextfor pagination when available. Load moreappends validated incoming items.- Duplicate items are currently allowed by design.
Headless Core Usage
import { ChatbotCore } from "@rizal_ncc/agent-client";
const bot = new ChatbotCore({
generateResponse: async () => ({ content: "Hello" }),
});
await bot.sendMessage("Hi");
console.log(bot.getState().messages);ChatbotCore notes:
- Ignores empty messages.
- Aborts previous in-flight request on new send.
- Throws if
generateResponsereturns emptycontent. - Exposes
stop()for manual cancellation.
Tool Result Helpers
Helpers exported from core entry:
getToolResultsByName(response, toolName)getToolErrors(response)extractCourseDetail(response)extractRecommendationOutput(response)extractRecommendationItems(response)
Known backend tool names:
get_course_recommendationget_course_detail
Theme and Styling
Import styles once:
import "@rizal_ncc/agent-client/style.css";Runtime CSS variables used by component shell:
--chat-primary--chat-primary-rgb--chat-primary-foreground--chat-panel-height--chat-shell-z-index
Important:
- Do not redeclare
--chat-primary*inside.ai-agent-chatif you want prop colors to apply.
Architecture
Primary layers:
ChatbotCorestate engine (src/core/chatbot.ts)- React adapter + transport + layout shell (
src/adapters/react.tsx) - Tool parsing and pagination helpers (
src/lib/tool-results.ts,src/lib/recommendation-pagination.ts) - UI styles and layout animations (
src/style.css)
Message lifecycle:
- User input -> user message append (
isLoading = true) - Transport call (custom or built-in)
- Assistant message normalize + append
- Optional recommendation pagination update
isLoading = false
Testing
Stack:
- Vitest
- React Testing Library
- jsdom
Current coverage includes:
- core behavior/error flow
- tool helper parsing
- recommendation merge behavior
- dropdown/floating open state
- typing/stop/error UI states
- load-more append flow
Run tests:
npm testDevelopment
npm install
npm run dev
npm test
npm run buildnpm run dev starts Vite playground (index.html + demo/*).
Demo env (.env):
VITE_API_BASE_URL=http://example.com/
VITE_AI_AGENT_TOKEN=<access_token>
VITE_AI_AGENT_AGENT=home-assistantPlayground (Local Source Mode)
playground/ is configured to consume library source files from ../src/* via Vite/TypeScript aliases, so you can test changes without publishing to npm.
Run:
cd playground
pnpm devNotes:
- Local aliases are defined in
playground/vite.config.tsandplayground/tsconfig.app.json. - To test the published npm package behavior, remove those aliases/paths and reinstall dependencies in
playground/.
Release and Publish
Pre-release validation:
npm run release:checkManual publish:
npm publish --access publicAutomated publish (GitHub Actions):
- Workflow:
.github/workflows/npm-publish.yml - Trigger: push tag matching
v*.*.* - Required secret:
NPM_TOKEN(npm automation token)
Tag-based release flow:
npm version patch
git push --follow-tagsUse minor or major instead of patch when needed.
File Map
- Core
src/core/chatbot.tssrc/core/types.tssrc/core/errors.ts
- React
src/adapters/react.tsxsrc/react.ts
- Helpers
src/lib/tool-results.tssrc/lib/recommendation-pagination.ts
- Styles
src/style.css
- Tests
tests/chatbot-core.test.tstests/tool-results.test.tstests/recommendation-pagination.test.tstests/ai-agent-chat-ui.test.tsx
Known Tradeoffs
- Recommendation dedupe is intentionally disabled.
- Built-in transport assumes JSON response (
response.json()). - Some layout behavior depends on CSS class contracts.
- Token refresh strategy is caller-managed when using function token provider.
