@icanbwell/baileyai-chat-ui 0.2.1-pre.0

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.
@@ -0,0 +1,366 @@
1
+ import { Components } from 'react-markdown';
2
+ import { JSX } from 'react';
3
+ import { ReactNode } from 'react';
4
+
5
+ export declare const BAILEY_CHART_PROMPT_FRAGMENT: string;
6
+
7
+ export declare const BAILEY_TABLE_GRID_ROW_THRESHOLD = 5;
8
+
9
+ export declare const BAILEYAI_CHAT_UI_VERSION: string;
10
+
11
+ export declare interface BaileyChartDataset {
12
+ label: string;
13
+ data: number[] | Array<{
14
+ x: number;
15
+ y: number;
16
+ }>;
17
+ }
18
+
19
+ export declare interface BaileyChartSpec {
20
+ type: BaileyChartType;
21
+ title?: string;
22
+ data: {
23
+ labels?: string[];
24
+ datasets: BaileyChartDataset[];
25
+ };
26
+ }
27
+
28
+ export declare type BaileyChartType = 'bar' | 'line' | 'pie' | 'doughnut' | 'scatter';
29
+
30
+ export declare interface BaileyChatInputMessage {
31
+ role: 'user' | 'assistant';
32
+ content: string;
33
+ }
34
+
35
+ export declare function BaileyChatPanel({ chat, placeholder, className, renderMessageActions, renderTable, renderChart, }: BaileyChatPanelProps): JSX.Element;
36
+
37
+ export declare interface BaileyChatPanelProps extends BaileyMarkdownRenderers {
38
+ chat: UseBaileyChatResult;
39
+ placeholder?: string;
40
+ className?: string;
41
+ /** Renders next to the built-in copy button for a completed assistant message — a static,
42
+ * per-message extension point for a host action (e.g. "regenerate", feedback buttons).
43
+ * Content-derived actions (e.g. baileyai-skills-service's save-as-skill artifact UI) are a
44
+ * host-side composition around useBaileyChat, not this prop — see the Phase 4 plan. */
45
+ renderMessageActions?: (message: BaileyMessage) => ReactNode;
46
+ }
47
+
48
+ export declare interface BaileyChatTransport {
49
+ streamChat(params: {
50
+ model: string;
51
+ instructions: string;
52
+ input: BaileyChatInputMessage[];
53
+ tools: BaileyMcpToolConfig[];
54
+ toolChoice?: BaileyToolChoice;
55
+ signal: AbortSignal;
56
+ onChunk: (text: string) => void;
57
+ onRequestId?: (requestId: string) => void;
58
+ }): Promise<{
59
+ status?: number;
60
+ text: string;
61
+ errorMessage?: string;
62
+ }>;
63
+ }
64
+
65
+ export declare interface BaileyLastRequest {
66
+ model: string;
67
+ systemPrompt: string;
68
+ messages: BaileyChatInputMessage[];
69
+ tools: BaileyMcpToolConfig[];
70
+ toolChoice?: BaileyToolChoice;
71
+ stream: true;
72
+ sentAt: number;
73
+ streamStats: BaileyStreamStats;
74
+ requestId?: string;
75
+ response?: {
76
+ content: string;
77
+ };
78
+ }
79
+
80
+ export declare interface BaileyMarkdownRenderers {
81
+ /** Renders a table once it exceeds BAILEY_TABLE_GRID_ROW_THRESHOLD rows. Omit to always
82
+ * render the plain GFM <table> regardless of size. */
83
+ renderTable?: (data: {
84
+ headers: string[];
85
+ rows: BaileyTableCell[][];
86
+ }) => ReactNode;
87
+ /** Renders a validated ```chartjs code block. Omit to fall through to a plain <pre>. */
88
+ renderChart?: (spec: BaileyChartSpec) => ReactNode;
89
+ }
90
+
91
+ export declare interface BaileyMcpToolConfig {
92
+ type: 'mcp';
93
+ server_url: string;
94
+ server_label: string;
95
+ }
96
+
97
+ export declare interface BaileyMessage {
98
+ id: string;
99
+ role: 'user' | 'assistant';
100
+ content: string;
101
+ streaming?: boolean;
102
+ }
103
+
104
+ export declare interface BaileyOutputItem {
105
+ type: string;
106
+ name?: string;
107
+ arguments?: string;
108
+ output?: string;
109
+ is_error?: boolean;
110
+ runtime_seconds?: number;
111
+ }
112
+
113
+ export declare type BaileyStreamEvent = {
114
+ type: 'response.output_text.delta';
115
+ delta: string;
116
+ } | {
117
+ type: 'response.output_text.done';
118
+ } | {
119
+ type: 'response.output_item.added';
120
+ item: BaileyOutputItem;
121
+ } | {
122
+ type: 'response.output_item.done';
123
+ item: BaileyOutputItem;
124
+ } | {
125
+ type: 'task.progress';
126
+ status: string;
127
+ message?: string;
128
+ } | {
129
+ type: 'response.created';
130
+ } | {
131
+ type: 'response.completed';
132
+ } | {
133
+ type: 'error';
134
+ message: string;
135
+ } | {
136
+ type: 'info';
137
+ message: string;
138
+ };
139
+
140
+ export declare interface BaileyStreamStats {
141
+ chunkCount: number;
142
+ firstChunkAt: number | null;
143
+ lastChunkAt: number | null;
144
+ }
145
+
146
+ export declare interface BaileyTableCell {
147
+ text: string;
148
+ href?: string;
149
+ }
150
+
151
+ export declare type BaileyToolChoice = 'none' | 'auto' | 'required';
152
+
153
+ export declare type BaileyTraceEvent = {
154
+ kind: 'tool_start';
155
+ name: string;
156
+ args?: string;
157
+ at: number;
158
+ turnSentAt: number;
159
+ } | {
160
+ kind: 'tool_end';
161
+ name: string;
162
+ args?: string;
163
+ at: number;
164
+ turnSentAt: number;
165
+ output?: string;
166
+ isError?: boolean;
167
+ runtimeSeconds?: number;
168
+ } | {
169
+ kind: 'pseudo_tool_call';
170
+ name: string;
171
+ args?: string;
172
+ at: number;
173
+ turnSentAt: number;
174
+ } | {
175
+ kind: 'progress';
176
+ status: string;
177
+ message?: string;
178
+ at: number;
179
+ turnSentAt: number;
180
+ } | {
181
+ kind: 'info';
182
+ message: string;
183
+ at: number;
184
+ turnSentAt: number;
185
+ } | {
186
+ kind: 'error';
187
+ message: string;
188
+ at: number;
189
+ turnSentAt: number;
190
+ httpStatus?: number;
191
+ rawBody?: string;
192
+ source?: 'client-timeout';
193
+ } | {
194
+ kind: 'raw';
195
+ eventType: string;
196
+ raw: string;
197
+ at: number;
198
+ turnSentAt: number;
199
+ };
200
+
201
+ export declare function BaileyTracePanel({ events, lastRequest, onClear }: BaileyTracePanelProps): JSX.Element | null;
202
+
203
+ export declare interface BaileyTracePanelProps {
204
+ events: BaileyTraceEvent[];
205
+ lastRequest: BaileyLastRequest | null;
206
+ onClear: () => void;
207
+ }
208
+
209
+ export declare function CopyMarkdownButton({ markdown, className }: CopyMarkdownButtonProps): JSX.Element;
210
+
211
+ export declare interface CopyMarkdownButtonProps {
212
+ markdown: string;
213
+ className?: string;
214
+ }
215
+
216
+ export declare function createBaileyMarkdownComponents({ renderTable, renderChart }?: BaileyMarkdownRenderers): Components;
217
+
218
+ export declare function extractPseudoToolCalls(text: string): ExtractPseudoToolCallsResult;
219
+
220
+ declare interface ExtractPseudoToolCallsResult {
221
+ /** `text` with every matched block removed. */
222
+ cleanedText: string;
223
+ /** Matches in document order. */
224
+ matches: PseudoToolCallMatch[];
225
+ }
226
+
227
+ export declare const extractTableData: (node: HastNode) => {
228
+ headers: string[];
229
+ rows: BaileyTableCell[][];
230
+ } | null;
231
+
232
+ export declare function formatTraceGap(ms: number): string;
233
+
234
+ export declare function formatTraceTime(at: number): string;
235
+
236
+ export declare interface HastNode {
237
+ type: string;
238
+ tagName?: string;
239
+ value?: string;
240
+ properties?: {
241
+ href?: string;
242
+ };
243
+ children?: HastNode[];
244
+ }
245
+
246
+ export declare function hasTraceFailure(events: BaileyTraceEvent[]): boolean;
247
+
248
+ export declare const isSafeMarkdownUrl: (href: string) => boolean;
249
+
250
+ export declare function joinInstructions(...parts: Array<string | undefined | null | false>): string;
251
+
252
+ export declare const parseBaileyChartSpec: (raw: string) => BaileyChartSpec | null;
253
+
254
+ export declare interface ParsedSseFrames {
255
+ events: BaileyStreamEvent[];
256
+ remainder: string;
257
+ done: boolean;
258
+ }
259
+
260
+ export declare function parseSseFrames(buffer: string): ParsedSseFrames;
261
+
262
+ export declare interface PseudoToolCallMatch {
263
+ /** The tool name the model claimed to call, or 'search_tools' for a bare exploration block. */
264
+ name: string;
265
+ /** Raw argument text found inside the block, if any. */
266
+ args?: string;
267
+ }
268
+
269
+ export declare interface ResolvedToolCall {
270
+ /** The real tool name, unwrapped from the call_tool meta-tool if needed. */
271
+ name: string;
272
+ /** The real tool's arguments, or null if they couldn't be parsed. */
273
+ args: Record<string, unknown> | null;
274
+ /** True when this call was made indirectly via the call_tool meta-tool. */
275
+ viaCallTool: boolean;
276
+ }
277
+
278
+ export declare function resolveToolCall(name: string, argsJson: string | undefined): ResolvedToolCall;
279
+
280
+ export declare const shouldUseGrid: (rows: BaileyTableCell[][]) => boolean;
281
+
282
+ export declare function toTraceRows(events: BaileyTraceEvent[]): TraceRow[];
283
+
284
+ export declare function toTraceSegments(rows: TraceRow[]): TraceSegment[];
285
+
286
+ export declare const TRACE_KIND_LABEL: Record<BaileyTraceEvent['kind'], string>;
287
+
288
+ export declare function traceEventArgsDetail(event: BaileyTraceEvent, resolved?: ResolvedToolCall | null): string | null;
289
+
290
+ export declare function traceEventHint(event: BaileyTraceEvent): string;
291
+
292
+ export declare function traceEventOutputDetail(event: BaileyTraceEvent): string | null;
293
+
294
+ export declare function traceEventRawDetail(event: BaileyTraceEvent): string | null;
295
+
296
+ export declare function traceEventSummary(event: BaileyTraceEvent, resolved?: ResolvedToolCall | null): string;
297
+
298
+ export declare function traceEventToolName(event: BaileyTraceEvent, resolved?: ResolvedToolCall | null): string | null;
299
+
300
+ export declare interface TraceRow {
301
+ key: string;
302
+ kind: BaileyTraceEvent['kind'];
303
+ toolName: string | null;
304
+ isToolStart: boolean;
305
+ failed: boolean;
306
+ time: string;
307
+ gapMs: number;
308
+ label: string;
309
+ summary: string;
310
+ argsDetail: string | null;
311
+ outputDetail: string | null;
312
+ rawDetail: string | null;
313
+ }
314
+
315
+ export declare type TraceSegment = {
316
+ type: 'group';
317
+ toolName: string;
318
+ rows: TraceRow[];
319
+ } | {
320
+ type: 'single';
321
+ row: TraceRow;
322
+ };
323
+
324
+ export declare function traceSummaryLine(events: BaileyTraceEvent[]): string;
325
+
326
+ export declare const useBaileyChat: ({ transport, model, instructions, tools, toolChoice, firstUserMessagePrefix, onAssistantMessageComplete, idleTimeoutMs, }: UseBaileyChatConfig) => UseBaileyChatResult;
327
+
328
+ export declare interface UseBaileyChatConfig {
329
+ transport: BaileyChatTransport;
330
+ model: string;
331
+ instructions: string;
332
+ /** Passed verbatim to transport.streamChat on every turn. Memoize this array (e.g. via
333
+ * useMemo) to avoid recreating send/stop/retryLast on every render. */
334
+ tools?: BaileyMcpToolConfig[];
335
+ toolChoice?: BaileyToolChoice;
336
+ /** Prepended to only the very first user message of the conversation (not the system
337
+ * prompt) — e.g. a slash-command-style skill/context marker a host wants visible in the
338
+ * transcript itself. Never applied to any later turn. */
339
+ firstUserMessagePrefix?: string;
340
+ /** Fires once a turn's assistant message finishes successfully, with its final content and
341
+ * the trace events produced during that turn. Lets a host post-process a response — e.g.
342
+ * parsing `propose_skill` tool calls / fenced artifact blocks out of it to drive a
343
+ * save-as-skill UI — without useBaileyChat needing to know anything about what a host does
344
+ * with it. Not called for a turn that errors or is stopped. */
345
+ onAssistantMessageComplete?: (message: BaileyMessage, turnTraceEvents: BaileyTraceEvent[]) => void | Promise<void>;
346
+ /** Aborts a turn that goes this long without a chunk arriving, so a stuck backend doesn't
347
+ * hang the UI forever. Resets on every chunk. Defaults to 150s, matching Bailey's own
348
+ * upstream idle timeout so a well-behaved backend error has a chance to arrive first. */
349
+ idleTimeoutMs?: number;
350
+ }
351
+
352
+ export declare interface UseBaileyChatResult {
353
+ messages: BaileyMessage[];
354
+ traceEvents: BaileyTraceEvent[];
355
+ lastRequest: BaileyLastRequest | null;
356
+ status: 'idle' | 'streaming' | 'error';
357
+ error: string | null;
358
+ send: (text: string) => void;
359
+ stop: () => void;
360
+ retryLast: () => void;
361
+ clearTrace: () => void;
362
+ /** Dismisses the current error without resending — distinct from retryLast, which resends. */
363
+ clearError: () => void;
364
+ }
365
+
366
+ export { }
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@icanbwell/baileyai-chat-ui",
3
+ "version": "0.2.1-pre.0",
4
+ "description": "Shared React chat UI and streaming logic for Bailey, the icanbwell AI assistant",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/icanbwell/baileyai-chat-ui.git"
9
+ },
10
+ "homepage": "https://github.com/icanbwell/baileyai-chat-ui#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/icanbwell/baileyai-chat-ui/issues"
13
+ },
14
+ "type": "module",
15
+ "main": "./dist/baileyai-chat-ui.cjs",
16
+ "module": "./dist/baileyai-chat-ui.js",
17
+ "types": "./dist/index.d.ts",
18
+ "sideEffects": [
19
+ "*.css"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/baileyai-chat-ui.js",
25
+ "require": "./dist/baileyai-chat-ui.cjs"
26
+ },
27
+ "./styles.css": "./dist/baileyai-chat-ui.css"
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "publishConfig": {
33
+ "registry": "https://registry.npmjs.org",
34
+ "access": "public"
35
+ },
36
+ "packageManager": "yarn@4.14.1",
37
+ "scripts": {
38
+ "build": "vite build",
39
+ "dev": "vite dev/ --config vite.config.ts",
40
+ "test": "vitest run",
41
+ "test:watch": "vitest",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p dev/tsconfig.json --noEmit",
43
+ "lint": "eslint \"src/**/*.{ts,tsx}\" \"dev/**/*.{ts,tsx}\" \"vite.config.ts\" \"*.js\""
44
+ },
45
+ "peerDependencies": {
46
+ "react": "^19.0.0",
47
+ "react-dom": "^19.0.0"
48
+ },
49
+ "dependencies": {
50
+ "@radix-ui/react-tooltip": "^1.1.8",
51
+ "react-markdown": "^10.1.0",
52
+ "remark-gfm": "^4.0.1"
53
+ },
54
+ "devDependencies": {
55
+ "@eslint/js": "^9",
56
+ "@tailwindcss/postcss": "^4.3.3",
57
+ "@testing-library/dom": "^10.0.0",
58
+ "@testing-library/jest-dom": "^7.0.1",
59
+ "@testing-library/react": "^16.3.2",
60
+ "@types/node": "^24.0.0",
61
+ "@types/react": "^19.2.17",
62
+ "@types/react-dom": "^19.2.3",
63
+ "@vitejs/plugin-react": "^4.3.4",
64
+ "autoprefixer": "^10.5.0",
65
+ "eslint": "^9.39.1",
66
+ "eslint-plugin-react-hooks": "^7.1.1",
67
+ "eslint-plugin-react-refresh": "^0.5.4",
68
+ "jsdom": "^29.1.1",
69
+ "postcss": "^8.5.23",
70
+ "react": "^19.2.7",
71
+ "react-dom": "^19.2.7",
72
+ "tailwindcss": "^4.3.1",
73
+ "typescript": "^6.0.3",
74
+ "typescript-eslint": "^8.67.0",
75
+ "vite": "^8.0.16",
76
+ "vite-plugin-dts": "^4.5.4",
77
+ "vitest": "^4.1.10"
78
+ }
79
+ }