@pikku/assistant-ui 0.12.3 → 0.12.5
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.
- package/CHANGELOG.md +34 -1
- package/dist/cjs/pikku-agent-chat.d.ts +16 -0
- package/dist/cjs/pikku-agent-chat.js +162 -70
- package/dist/cjs/use-pikku-agent-runtime.js +70 -19
- package/dist/esm/pikku-agent-chat.d.ts +16 -0
- package/dist/esm/pikku-agent-chat.js +175 -76
- package/dist/esm/use-pikku-agent-runtime.js +70 -19
- package/package.json +1 -1
- package/src/pikku-agent-chat.tsx +379 -154
- package/src/use-pikku-agent-runtime.ts +103 -15
package/src/pikku-agent-chat.tsx
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
useMemo,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
type ComponentType,
|
|
9
|
+
type FunctionComponent,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from 'react'
|
|
2
12
|
import Markdown from 'react-markdown'
|
|
3
13
|
import {
|
|
4
14
|
AssistantRuntimeProvider,
|
|
5
15
|
ThreadPrimitive,
|
|
6
16
|
MessagePrimitive,
|
|
7
17
|
ComposerPrimitive,
|
|
18
|
+
useComposerRuntime,
|
|
19
|
+
type ToolCallMessagePartComponent,
|
|
8
20
|
} from '@assistant-ui/react'
|
|
9
21
|
import {
|
|
10
22
|
usePikkuAgentRuntime,
|
|
@@ -16,6 +28,7 @@ import {
|
|
|
16
28
|
} from './use-pikku-agent-runtime.js'
|
|
17
29
|
|
|
18
30
|
export interface PikkuAgentChatProps extends PikkuAgentRuntimeOptions {
|
|
31
|
+
initialPrompt?: string
|
|
19
32
|
emptyMessage?: string
|
|
20
33
|
/** Hide tool calls from the chat display.
|
|
21
34
|
* - `true`: hide all non-approval tool calls
|
|
@@ -25,6 +38,19 @@ export interface PikkuAgentChatProps extends PikkuAgentRuntimeOptions {
|
|
|
25
38
|
dark?: boolean
|
|
26
39
|
/** Max width of the chat content area. Defaults to 768. Set to 'none' for full width. */
|
|
27
40
|
maxWidth?: number | 'none'
|
|
41
|
+
/**
|
|
42
|
+
* Per-tool renderers. Map `toolName` → React component to replace the
|
|
43
|
+
* default expandable tool-call box for that tool. Enables generative-UI
|
|
44
|
+
* patterns: e.g. register a `renderWidget` tool on the agent and mount
|
|
45
|
+
* real UI (charts, diffs, cards) inline in the assistant bubble from the
|
|
46
|
+
* persisted tool-call args.
|
|
47
|
+
*
|
|
48
|
+
* Any tool without an entry here falls through to the default renderer
|
|
49
|
+
* (which still respects `hideToolCalls` and the approval-request UI).
|
|
50
|
+
*/
|
|
51
|
+
toolComponents?: Record<string, ToolCallMessagePartComponent>
|
|
52
|
+
renderAssistantText?: (text: string) => ReactNode
|
|
53
|
+
generativeUIComponents?: Record<string, ComponentType<any>>
|
|
28
54
|
}
|
|
29
55
|
|
|
30
56
|
interface ChatColors {
|
|
@@ -91,7 +117,18 @@ const darkColors: ChatColors = {
|
|
|
91
117
|
}
|
|
92
118
|
|
|
93
119
|
const ColorsContext = createContext<ChatColors>(lightColors)
|
|
94
|
-
const HideToolCallsContext = createContext<boolean | string[] | undefined>(
|
|
120
|
+
const HideToolCallsContext = createContext<boolean | string[] | undefined>(
|
|
121
|
+
undefined
|
|
122
|
+
)
|
|
123
|
+
const ToolComponentsContext = createContext<
|
|
124
|
+
Record<string, ToolCallMessagePartComponent> | undefined
|
|
125
|
+
>(undefined)
|
|
126
|
+
const GenerativeUIComponentsContext = createContext<
|
|
127
|
+
Record<string, ComponentType<any>> | undefined
|
|
128
|
+
>(undefined)
|
|
129
|
+
const RenderAssistantTextContext = createContext<
|
|
130
|
+
((text: string) => ReactNode) | undefined
|
|
131
|
+
>(undefined)
|
|
95
132
|
|
|
96
133
|
function shouldHideToolCall(
|
|
97
134
|
hideToolCalls: boolean | string[] | undefined,
|
|
@@ -118,9 +155,7 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
118
155
|
const approvalReason = (args as any)?.__approvalReason
|
|
119
156
|
const displayArgs = { ...args }
|
|
120
157
|
delete (displayArgs as any).__approvalReason
|
|
121
|
-
const [responded, setResponded] = useState<'approved' | 'denied' | null>(
|
|
122
|
-
null
|
|
123
|
-
)
|
|
158
|
+
const [responded, setResponded] = useState<'approved' | 'denied' | null>(null)
|
|
124
159
|
|
|
125
160
|
// Hide responded approval tool calls
|
|
126
161
|
if (isApproval && responded && shouldHideToolCall(hideToolCalls, toolName)) {
|
|
@@ -157,7 +192,9 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
157
192
|
Approval required
|
|
158
193
|
</div>
|
|
159
194
|
{approvalReason && (
|
|
160
|
-
<div style={{ fontSize: 13, marginBottom: 4, color: colors.text }}>
|
|
195
|
+
<div style={{ fontSize: 13, marginBottom: 4, color: colors.text }}>
|
|
196
|
+
{approvalReason}
|
|
197
|
+
</div>
|
|
161
198
|
)}
|
|
162
199
|
<div style={{ fontSize: 12, color: colors.textMuted, marginBottom: 4 }}>
|
|
163
200
|
The agent wants to call <code>{toolName}</code>
|
|
@@ -238,8 +275,12 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
238
275
|
fontSize: 11,
|
|
239
276
|
padding: '2px 6px',
|
|
240
277
|
borderRadius: 3,
|
|
241
|
-
background:
|
|
242
|
-
|
|
278
|
+
background:
|
|
279
|
+
responded === 'approved' ? colors.successBg : colors.errorBg,
|
|
280
|
+
color:
|
|
281
|
+
responded === 'approved'
|
|
282
|
+
? colors.successColor
|
|
283
|
+
: colors.errorColor,
|
|
243
284
|
}}
|
|
244
285
|
>
|
|
245
286
|
{responded}
|
|
@@ -277,7 +318,9 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
277
318
|
{toolName}
|
|
278
319
|
</span>
|
|
279
320
|
{status.type === 'running' && (
|
|
280
|
-
<span style={{ fontSize: 11, color: colors.textMuted }}>
|
|
321
|
+
<span style={{ fontSize: 11, color: colors.textMuted }}>
|
|
322
|
+
running...
|
|
323
|
+
</span>
|
|
281
324
|
)}
|
|
282
325
|
{status.type === 'error' && (
|
|
283
326
|
<span
|
|
@@ -334,7 +377,9 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
334
377
|
</button>
|
|
335
378
|
{expanded && (
|
|
336
379
|
<div style={{ marginTop: 8 }}>
|
|
337
|
-
<div
|
|
380
|
+
<div
|
|
381
|
+
style={{ fontSize: 12, color: colors.textMuted, marginBottom: 2 }}
|
|
382
|
+
>
|
|
338
383
|
Arguments:
|
|
339
384
|
</div>
|
|
340
385
|
<pre
|
|
@@ -352,7 +397,12 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
352
397
|
{result !== undefined && (
|
|
353
398
|
<>
|
|
354
399
|
<div
|
|
355
|
-
style={{
|
|
400
|
+
style={{
|
|
401
|
+
fontSize: 12,
|
|
402
|
+
color: colors.textMuted,
|
|
403
|
+
marginTop: 8,
|
|
404
|
+
marginBottom: 2,
|
|
405
|
+
}}
|
|
356
406
|
>
|
|
357
407
|
Result:
|
|
358
408
|
</div>
|
|
@@ -378,49 +428,141 @@ const ToolCallDisplay: FunctionComponent<{
|
|
|
378
428
|
)
|
|
379
429
|
}
|
|
380
430
|
|
|
381
|
-
const MarkdownText: FunctionComponent<{ text: string; colors: ChatColors }> = ({
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
431
|
+
const MarkdownText: FunctionComponent<{ text: string; colors: ChatColors }> = ({
|
|
432
|
+
text,
|
|
433
|
+
colors,
|
|
434
|
+
}) => {
|
|
435
|
+
const components = useMemo(
|
|
436
|
+
() => ({
|
|
437
|
+
p: ({ children }: any) => (
|
|
438
|
+
<p
|
|
439
|
+
style={{
|
|
440
|
+
margin: '0 0 8px',
|
|
441
|
+
fontSize: 14,
|
|
442
|
+
lineHeight: 1.6,
|
|
443
|
+
color: colors.text,
|
|
444
|
+
}}
|
|
445
|
+
>
|
|
446
|
+
{children}
|
|
447
|
+
</p>
|
|
448
|
+
),
|
|
449
|
+
strong: ({ children }: any) => (
|
|
450
|
+
<strong style={{ fontWeight: 600, color: colors.text }}>
|
|
451
|
+
{children}
|
|
452
|
+
</strong>
|
|
453
|
+
),
|
|
454
|
+
em: ({ children }: any) => (
|
|
455
|
+
<em style={{ color: colors.text }}>{children}</em>
|
|
456
|
+
),
|
|
457
|
+
ul: ({ children }: any) => (
|
|
458
|
+
<ul
|
|
459
|
+
style={{
|
|
460
|
+
margin: '4px 0 8px',
|
|
461
|
+
paddingLeft: 20,
|
|
462
|
+
fontSize: 14,
|
|
463
|
+
color: colors.text,
|
|
464
|
+
}}
|
|
465
|
+
>
|
|
466
|
+
{children}
|
|
467
|
+
</ul>
|
|
468
|
+
),
|
|
469
|
+
ol: ({ children }: any) => (
|
|
470
|
+
<ol
|
|
471
|
+
style={{
|
|
472
|
+
margin: '4px 0 8px',
|
|
473
|
+
paddingLeft: 20,
|
|
474
|
+
fontSize: 14,
|
|
475
|
+
color: colors.text,
|
|
476
|
+
}}
|
|
477
|
+
>
|
|
478
|
+
{children}
|
|
479
|
+
</ol>
|
|
480
|
+
),
|
|
481
|
+
li: ({ children }: any) => (
|
|
482
|
+
<li style={{ marginBottom: 2, lineHeight: 1.6 }}>{children}</li>
|
|
483
|
+
),
|
|
484
|
+
code: ({ children, className }: any) => {
|
|
485
|
+
const isBlock = className?.startsWith('language-')
|
|
486
|
+
if (isBlock) {
|
|
487
|
+
return (
|
|
488
|
+
<pre
|
|
489
|
+
style={{
|
|
490
|
+
background: colors.codeBg,
|
|
491
|
+
padding: 10,
|
|
492
|
+
borderRadius: 4,
|
|
493
|
+
overflow: 'auto',
|
|
494
|
+
margin: '4px 0 8px',
|
|
495
|
+
fontSize: 12,
|
|
496
|
+
}}
|
|
497
|
+
>
|
|
498
|
+
<code style={{ color: colors.text }}>{children}</code>
|
|
499
|
+
</pre>
|
|
500
|
+
)
|
|
501
|
+
}
|
|
404
502
|
return (
|
|
405
|
-
<
|
|
406
|
-
|
|
407
|
-
|
|
503
|
+
<code
|
|
504
|
+
style={{
|
|
505
|
+
background: colors.codeBg,
|
|
506
|
+
padding: '1px 4px',
|
|
507
|
+
borderRadius: 3,
|
|
508
|
+
fontSize: 13,
|
|
509
|
+
color: colors.text,
|
|
510
|
+
}}
|
|
511
|
+
>
|
|
512
|
+
{children}
|
|
513
|
+
</code>
|
|
408
514
|
)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
515
|
+
},
|
|
516
|
+
pre: ({ children }: any) => <>{children}</>,
|
|
517
|
+
h1: ({ children }: any) => (
|
|
518
|
+
<h3
|
|
519
|
+
style={{
|
|
520
|
+
margin: '8px 0 4px',
|
|
521
|
+
fontSize: 16,
|
|
522
|
+
fontWeight: 600,
|
|
523
|
+
color: colors.text,
|
|
524
|
+
}}
|
|
525
|
+
>
|
|
526
|
+
{children}
|
|
527
|
+
</h3>
|
|
528
|
+
),
|
|
529
|
+
h2: ({ children }: any) => (
|
|
530
|
+
<h4
|
|
531
|
+
style={{
|
|
532
|
+
margin: '8px 0 4px',
|
|
533
|
+
fontSize: 15,
|
|
534
|
+
fontWeight: 600,
|
|
535
|
+
color: colors.text,
|
|
536
|
+
}}
|
|
537
|
+
>
|
|
538
|
+
{children}
|
|
539
|
+
</h4>
|
|
540
|
+
),
|
|
541
|
+
h3: ({ children }: any) => (
|
|
542
|
+
<h5
|
|
543
|
+
style={{
|
|
544
|
+
margin: '8px 0 4px',
|
|
545
|
+
fontSize: 14,
|
|
546
|
+
fontWeight: 600,
|
|
547
|
+
color: colors.text,
|
|
548
|
+
}}
|
|
549
|
+
>
|
|
412
550
|
{children}
|
|
413
|
-
</
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
551
|
+
</h5>
|
|
552
|
+
),
|
|
553
|
+
a: ({ href, children }: any) => (
|
|
554
|
+
<a
|
|
555
|
+
href={href}
|
|
556
|
+
target="_blank"
|
|
557
|
+
rel="noopener noreferrer"
|
|
558
|
+
style={{ color: colors.textMuted, textDecoration: 'underline' }}
|
|
559
|
+
>
|
|
560
|
+
{children}
|
|
561
|
+
</a>
|
|
562
|
+
),
|
|
563
|
+
}),
|
|
564
|
+
[colors]
|
|
565
|
+
)
|
|
424
566
|
|
|
425
567
|
return <Markdown components={components}>{text}</Markdown>
|
|
426
568
|
}
|
|
@@ -456,7 +598,13 @@ const UserMessage: FunctionComponent = () => {
|
|
|
456
598
|
<MessagePrimitive.Content
|
|
457
599
|
components={{
|
|
458
600
|
Text: ({ text }) => (
|
|
459
|
-
<span
|
|
601
|
+
<span
|
|
602
|
+
style={{
|
|
603
|
+
fontSize: 14,
|
|
604
|
+
whiteSpace: 'pre-wrap',
|
|
605
|
+
color: colors.text,
|
|
606
|
+
}}
|
|
607
|
+
>
|
|
460
608
|
{text}
|
|
461
609
|
</span>
|
|
462
610
|
),
|
|
@@ -470,6 +618,9 @@ const UserMessage: FunctionComponent = () => {
|
|
|
470
618
|
|
|
471
619
|
const AssistantMessage: FunctionComponent = () => {
|
|
472
620
|
const colors = useContext(ColorsContext)
|
|
621
|
+
const toolComponents = useContext(ToolComponentsContext)
|
|
622
|
+
const generativeUIComponents = useContext(GenerativeUIComponentsContext)
|
|
623
|
+
const renderAssistantText = useContext(RenderAssistantTextContext)
|
|
473
624
|
return (
|
|
474
625
|
<div
|
|
475
626
|
style={{
|
|
@@ -491,10 +642,14 @@ const AssistantMessage: FunctionComponent = () => {
|
|
|
491
642
|
>
|
|
492
643
|
<MessagePrimitive.Content
|
|
493
644
|
components={{
|
|
494
|
-
Text: ({ text }) =>
|
|
495
|
-
|
|
496
|
-
|
|
645
|
+
Text: ({ text }) =>
|
|
646
|
+
renderAssistantText ? (
|
|
647
|
+
<>{renderAssistantText(text)}</>
|
|
648
|
+
) : (
|
|
649
|
+
<MarkdownText text={text} colors={colors} />
|
|
650
|
+
),
|
|
497
651
|
tools: {
|
|
652
|
+
by_name: toolComponents,
|
|
498
653
|
Fallback: (props) => (
|
|
499
654
|
<ToolCallDisplay
|
|
500
655
|
toolCallId={props.toolCallId}
|
|
@@ -506,6 +661,13 @@ const AssistantMessage: FunctionComponent = () => {
|
|
|
506
661
|
/>
|
|
507
662
|
),
|
|
508
663
|
},
|
|
664
|
+
...(generativeUIComponents
|
|
665
|
+
? {
|
|
666
|
+
generativeUI: {
|
|
667
|
+
components: generativeUIComponents,
|
|
668
|
+
},
|
|
669
|
+
}
|
|
670
|
+
: {}),
|
|
509
671
|
}}
|
|
510
672
|
/>
|
|
511
673
|
<MessagePrimitive.If last>
|
|
@@ -530,61 +692,95 @@ const AssistantMessage: FunctionComponent = () => {
|
|
|
530
692
|
)
|
|
531
693
|
}
|
|
532
694
|
|
|
695
|
+
const ComposerPrefill: FunctionComponent<{ text?: string }> = ({ text }) => {
|
|
696
|
+
const composer = useComposerRuntime()
|
|
697
|
+
const filled = useRef(false)
|
|
698
|
+
useEffect(() => {
|
|
699
|
+
if (filled.current || !text) return
|
|
700
|
+
filled.current = true
|
|
701
|
+
if (composer.getState().text === '') composer.setText(text)
|
|
702
|
+
}, [text, composer])
|
|
703
|
+
return null
|
|
704
|
+
}
|
|
705
|
+
|
|
533
706
|
const PikkuComposer: FunctionComponent<{ disabled?: boolean }> = ({
|
|
534
707
|
disabled,
|
|
535
708
|
}) => {
|
|
536
709
|
const colors = useContext(ColorsContext)
|
|
710
|
+
|
|
537
711
|
return (
|
|
538
712
|
<div style={{ padding: '8px 0 16px' }}>
|
|
539
713
|
<ComposerPrimitive.Root>
|
|
540
714
|
<div
|
|
541
715
|
style={{
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
overflow: 'hidden',
|
|
716
|
+
position: 'relative',
|
|
717
|
+
zIndex: 2,
|
|
545
718
|
display: 'flex',
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
719
|
+
flexDirection: 'column',
|
|
720
|
+
gap: 10,
|
|
721
|
+
backgroundColor: colors.assistantBubble,
|
|
722
|
+
border: `1px solid ${colors.border}`,
|
|
723
|
+
borderRadius: 24,
|
|
724
|
+
padding: '14px 12px 10px',
|
|
725
|
+
boxShadow:
|
|
726
|
+
darkColors.text === colors.text
|
|
727
|
+
? '0 14px 30px rgba(0,0,0,0.24)'
|
|
728
|
+
: '0 14px 30px rgba(0,0,0,0.08)',
|
|
729
|
+
...(disabled
|
|
730
|
+
? { opacity: 0.5, pointerEvents: 'none' as const }
|
|
731
|
+
: {}),
|
|
550
732
|
}}
|
|
551
733
|
>
|
|
552
734
|
<ComposerPrimitive.Input
|
|
553
|
-
placeholder={
|
|
554
|
-
|
|
555
|
-
|
|
735
|
+
placeholder={
|
|
736
|
+
disabled ? 'Respond to approval request above...' : 'Message...'
|
|
737
|
+
}
|
|
738
|
+
rows={1}
|
|
739
|
+
disabled={disabled ?? false}
|
|
556
740
|
style={{
|
|
557
|
-
|
|
741
|
+
width: '100%',
|
|
742
|
+
background: 'transparent',
|
|
558
743
|
border: 'none',
|
|
559
744
|
outline: 'none',
|
|
560
|
-
|
|
745
|
+
color: colors.text,
|
|
561
746
|
fontSize: 14,
|
|
562
747
|
fontFamily: 'inherit',
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
748
|
+
resize: 'none',
|
|
749
|
+
lineHeight: 1.5,
|
|
750
|
+
overflowY: 'auto',
|
|
566
751
|
}}
|
|
567
752
|
/>
|
|
568
|
-
<
|
|
569
|
-
disabled={disabled}
|
|
753
|
+
<div
|
|
570
754
|
style={{
|
|
571
|
-
width:
|
|
572
|
-
height: 28,
|
|
573
|
-
borderRadius: '50%',
|
|
574
|
-
border: 'none',
|
|
575
|
-
background: disabled ? colors.textMuted : colors.sendBg,
|
|
576
|
-
color: colors.sendColor,
|
|
577
|
-
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
755
|
+
width: '100%',
|
|
578
756
|
display: 'flex',
|
|
579
757
|
alignItems: 'center',
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
fontSize: 14,
|
|
758
|
+
gap: 6,
|
|
759
|
+
minWidth: 0,
|
|
760
|
+
justifyContent: 'flex-end',
|
|
584
761
|
}}
|
|
585
762
|
>
|
|
586
|
-
|
|
587
|
-
|
|
763
|
+
<ComposerPrimitive.Send
|
|
764
|
+
disabled={disabled ?? false}
|
|
765
|
+
style={{
|
|
766
|
+
width: 30,
|
|
767
|
+
height: 30,
|
|
768
|
+
borderRadius: 999,
|
|
769
|
+
border: `1px solid ${colors.border}`,
|
|
770
|
+
background: '#e8e8e8',
|
|
771
|
+
color: '#111111',
|
|
772
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
773
|
+
display: 'flex',
|
|
774
|
+
alignItems: 'center',
|
|
775
|
+
justifyContent: 'center',
|
|
776
|
+
flexShrink: 0,
|
|
777
|
+
transition:
|
|
778
|
+
'background-color 150ms ease, color 150ms ease, border-color 150ms ease',
|
|
779
|
+
}}
|
|
780
|
+
>
|
|
781
|
+
↑
|
|
782
|
+
</ComposerPrimitive.Send>
|
|
783
|
+
</div>
|
|
588
784
|
</div>
|
|
589
785
|
</ComposerPrimitive.Root>
|
|
590
786
|
</div>
|
|
@@ -592,7 +788,17 @@ const PikkuComposer: FunctionComponent<{ disabled?: boolean }> = ({
|
|
|
592
788
|
}
|
|
593
789
|
|
|
594
790
|
export function PikkuAgentChat(props: PikkuAgentChatProps) {
|
|
595
|
-
const {
|
|
791
|
+
const {
|
|
792
|
+
emptyMessage,
|
|
793
|
+
hideToolCalls,
|
|
794
|
+
dark,
|
|
795
|
+
maxWidth = 768,
|
|
796
|
+
toolComponents,
|
|
797
|
+
renderAssistantText,
|
|
798
|
+
generativeUIComponents,
|
|
799
|
+
initialPrompt,
|
|
800
|
+
...runtimeOptions
|
|
801
|
+
} = props
|
|
596
802
|
const { runtime, isAwaitingApproval, pendingApprovals, handleApproval } =
|
|
597
803
|
usePikkuAgentRuntime(runtimeOptions)
|
|
598
804
|
|
|
@@ -600,76 +806,95 @@ export function PikkuAgentChat(props: PikkuAgentChatProps) {
|
|
|
600
806
|
|
|
601
807
|
return (
|
|
602
808
|
<ColorsContext.Provider value={colors}>
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
<AssistantRuntimeProvider runtime={runtime}>
|
|
606
|
-
<div
|
|
607
|
-
style={{
|
|
608
|
-
height: '100%',
|
|
609
|
-
display: 'flex',
|
|
610
|
-
flexDirection: 'column',
|
|
611
|
-
background: colors.bg,
|
|
612
|
-
}}
|
|
809
|
+
<PikkuApprovalContext.Provider
|
|
810
|
+
value={{ pendingApprovals, handleApproval }}
|
|
613
811
|
>
|
|
614
|
-
<
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
flex: 1,
|
|
619
|
-
minHeight: 0,
|
|
620
|
-
}}
|
|
621
|
-
>
|
|
622
|
-
<ThreadPrimitive.Viewport
|
|
623
|
-
style={{
|
|
624
|
-
flex: 1,
|
|
625
|
-
minHeight: 0,
|
|
626
|
-
overflowY: 'auto',
|
|
627
|
-
}}
|
|
628
|
-
>
|
|
629
|
-
<div
|
|
630
|
-
style={{
|
|
631
|
-
maxWidth: maxWidth === 'none' ? undefined : maxWidth,
|
|
632
|
-
margin: '0 auto',
|
|
633
|
-
padding: 16,
|
|
634
|
-
display: 'flex',
|
|
635
|
-
flexDirection: 'column',
|
|
636
|
-
gap: 16,
|
|
637
|
-
}}
|
|
812
|
+
<HideToolCallsContext.Provider value={hideToolCalls}>
|
|
813
|
+
<ToolComponentsContext.Provider value={toolComponents}>
|
|
814
|
+
<GenerativeUIComponentsContext.Provider
|
|
815
|
+
value={generativeUIComponents}
|
|
638
816
|
>
|
|
639
|
-
<
|
|
640
|
-
<
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
817
|
+
<RenderAssistantTextContext.Provider value={renderAssistantText}>
|
|
818
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
819
|
+
<ComposerPrefill text={initialPrompt} />
|
|
820
|
+
<div
|
|
821
|
+
style={{
|
|
822
|
+
height: '100%',
|
|
823
|
+
display: 'flex',
|
|
824
|
+
flexDirection: 'column',
|
|
825
|
+
background: colors.bg,
|
|
826
|
+
}}
|
|
827
|
+
>
|
|
828
|
+
<ThreadPrimitive.Root
|
|
829
|
+
style={{
|
|
830
|
+
display: 'flex',
|
|
831
|
+
flexDirection: 'column',
|
|
832
|
+
flex: 1,
|
|
833
|
+
minHeight: 0,
|
|
834
|
+
}}
|
|
835
|
+
>
|
|
836
|
+
<ThreadPrimitive.Viewport
|
|
837
|
+
style={{
|
|
838
|
+
flex: 1,
|
|
839
|
+
minHeight: 0,
|
|
840
|
+
overflowY: 'auto',
|
|
841
|
+
}}
|
|
842
|
+
>
|
|
843
|
+
<div
|
|
844
|
+
style={{
|
|
845
|
+
maxWidth:
|
|
846
|
+
maxWidth === 'none' ? undefined : maxWidth,
|
|
847
|
+
margin: '0 auto',
|
|
848
|
+
padding: 16,
|
|
849
|
+
display: 'flex',
|
|
850
|
+
flexDirection: 'column',
|
|
851
|
+
gap: 16,
|
|
852
|
+
}}
|
|
853
|
+
>
|
|
854
|
+
<ThreadPrimitive.Empty>
|
|
855
|
+
<div
|
|
856
|
+
style={{
|
|
857
|
+
display: 'flex',
|
|
858
|
+
alignItems: 'center',
|
|
859
|
+
justifyContent: 'center',
|
|
860
|
+
minHeight: 300,
|
|
861
|
+
color: colors.textMuted,
|
|
862
|
+
textAlign: 'center',
|
|
863
|
+
fontSize: 14,
|
|
864
|
+
}}
|
|
865
|
+
>
|
|
866
|
+
{emptyMessage ??
|
|
867
|
+
(props.threadId
|
|
868
|
+
? 'Send a message to start the conversation.'
|
|
869
|
+
: 'Start a new conversation.')}
|
|
870
|
+
</div>
|
|
871
|
+
</ThreadPrimitive.Empty>
|
|
872
|
+
<ThreadPrimitive.Messages
|
|
873
|
+
components={{
|
|
874
|
+
UserMessage,
|
|
875
|
+
AssistantMessage,
|
|
876
|
+
}}
|
|
877
|
+
/>
|
|
878
|
+
</div>
|
|
879
|
+
</ThreadPrimitive.Viewport>
|
|
880
|
+
<div
|
|
881
|
+
style={{
|
|
882
|
+
maxWidth: maxWidth === 'none' ? undefined : maxWidth,
|
|
883
|
+
margin: '0 auto',
|
|
884
|
+
width: '100%',
|
|
885
|
+
padding: '0 16px',
|
|
886
|
+
}}
|
|
887
|
+
>
|
|
888
|
+
<PikkuComposer disabled={isAwaitingApproval} />
|
|
889
|
+
</div>
|
|
890
|
+
</ThreadPrimitive.Root>
|
|
891
|
+
</div>
|
|
892
|
+
</AssistantRuntimeProvider>
|
|
893
|
+
</RenderAssistantTextContext.Provider>
|
|
894
|
+
</GenerativeUIComponentsContext.Provider>
|
|
895
|
+
</ToolComponentsContext.Provider>
|
|
896
|
+
</HideToolCallsContext.Provider>
|
|
897
|
+
</PikkuApprovalContext.Provider>
|
|
673
898
|
</ColorsContext.Provider>
|
|
674
899
|
)
|
|
675
900
|
}
|