@urbicon-ui/blocks 6.35.0 → 6.36.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.
- package/dist/components/Chat/Chat/Chat.svelte +53 -0
- package/dist/components/Chat/Chat/Chat.svelte.d.ts +4 -0
- package/dist/components/Chat/Chat/chat.variants.d.ts +20 -0
- package/dist/components/Chat/Chat/chat.variants.js +15 -0
- package/dist/components/Chat/Chat/index.d.ts +47 -0
- package/dist/components/Chat/Chat/index.js +2 -0
- package/dist/components/Chat/ChatMessage/ChatMessage.svelte +342 -0
- package/dist/components/Chat/ChatMessage/ChatMessage.svelte.d.ts +4 -0
- package/dist/components/Chat/ChatMessage/chat-message.variants.d.ts +138 -0
- package/dist/components/Chat/ChatMessage/chat-message.variants.js +118 -0
- package/dist/components/Chat/ChatMessage/index.d.ts +102 -0
- package/dist/components/Chat/ChatMessage/index.js +2 -0
- package/dist/components/Chat/ChatMessageList/ChatMessageList.svelte +301 -0
- package/dist/components/Chat/ChatMessageList/ChatMessageList.svelte.d.ts +6 -0
- package/dist/components/Chat/ChatMessageList/chat-message-list.variants.d.ts +23 -0
- package/dist/components/Chat/ChatMessageList/chat-message-list.variants.js +32 -0
- package/dist/components/Chat/ChatMessageList/chat-scroll.d.ts +45 -0
- package/dist/components/Chat/ChatMessageList/chat-scroll.js +52 -0
- package/dist/components/Chat/ChatMessageList/index.d.ts +93 -0
- package/dist/components/Chat/ChatMessageList/index.js +3 -0
- package/dist/components/Chat/CitationChip/CitationChip.svelte +107 -0
- package/dist/components/Chat/CitationChip/CitationChip.svelte.d.ts +4 -0
- package/dist/components/Chat/CitationChip/citation-chip.variants.d.ts +40 -0
- package/dist/components/Chat/CitationChip/citation-chip.variants.js +42 -0
- package/dist/components/Chat/CitationChip/index.d.ts +69 -0
- package/dist/components/Chat/CitationChip/index.js +2 -0
- package/dist/components/Chat/CodeBlock/CodeBlock.svelte +120 -0
- package/dist/components/Chat/CodeBlock/CodeBlock.svelte.d.ts +4 -0
- package/dist/components/Chat/CodeBlock/code-block.variants.d.ts +40 -0
- package/dist/components/Chat/CodeBlock/code-block.variants.js +51 -0
- package/dist/components/Chat/CodeBlock/index.d.ts +55 -0
- package/dist/components/Chat/CodeBlock/index.js +2 -0
- package/dist/components/Chat/PromptInput/PromptInput.svelte +432 -0
- package/dist/components/Chat/PromptInput/PromptInput.svelte.d.ts +4 -0
- package/dist/components/Chat/PromptInput/index.d.ts +165 -0
- package/dist/components/Chat/PromptInput/index.js +2 -0
- package/dist/components/Chat/PromptInput/prompt-input.variants.d.ts +90 -0
- package/dist/components/Chat/PromptInput/prompt-input.variants.js +102 -0
- package/dist/components/Chat/ReasoningDisclosure/ReasoningDisclosure.svelte +107 -0
- package/dist/components/Chat/ReasoningDisclosure/ReasoningDisclosure.svelte.d.ts +4 -0
- package/dist/components/Chat/ReasoningDisclosure/index.d.ts +85 -0
- package/dist/components/Chat/ReasoningDisclosure/index.js +2 -0
- package/dist/components/Chat/ReasoningDisclosure/reasoning-disclosure.variants.d.ts +20 -0
- package/dist/components/Chat/ReasoningDisclosure/reasoning-disclosure.variants.js +31 -0
- package/dist/components/Chat/StreamingMarkdown/MdBlock.svelte +99 -0
- package/dist/components/Chat/StreamingMarkdown/MdBlock.svelte.d.ts +9 -0
- package/dist/components/Chat/StreamingMarkdown/MdInline.svelte +82 -0
- package/dist/components/Chat/StreamingMarkdown/MdInline.svelte.d.ts +9 -0
- package/dist/components/Chat/StreamingMarkdown/StreamingMarkdown.svelte +118 -0
- package/dist/components/Chat/StreamingMarkdown/StreamingMarkdown.svelte.d.ts +4 -0
- package/dist/components/Chat/StreamingMarkdown/index.d.ts +86 -0
- package/dist/components/Chat/StreamingMarkdown/index.js +2 -0
- package/dist/components/Chat/StreamingMarkdown/md-context.d.ts +58 -0
- package/dist/components/Chat/StreamingMarkdown/md-context.js +1 -0
- package/dist/components/Chat/StreamingMarkdown/streaming-markdown.variants.d.ts +145 -0
- package/dist/components/Chat/StreamingMarkdown/streaming-markdown.variants.js +73 -0
- package/dist/components/Chat/ToolCallCard/ToolCallCard.svelte +174 -0
- package/dist/components/Chat/ToolCallCard/ToolCallCard.svelte.d.ts +4 -0
- package/dist/components/Chat/ToolCallCard/index.d.ts +84 -0
- package/dist/components/Chat/ToolCallCard/index.js +2 -0
- package/dist/components/Chat/ToolCallCard/tool-call-card.variants.d.ts +38 -0
- package/dist/components/Chat/ToolCallCard/tool-call-card.variants.js +38 -0
- package/dist/components/Chat/chat.types.d.ts +82 -0
- package/dist/components/Chat/chat.types.js +7 -0
- package/dist/components/Chat/index.d.ts +22 -0
- package/dist/components/Chat/index.js +14 -0
- package/dist/components/Chat/markdown/blocks.d.ts +54 -0
- package/dist/components/Chat/markdown/blocks.js +462 -0
- package/dist/components/Chat/markdown/inline.d.ts +31 -0
- package/dist/components/Chat/markdown/inline.js +446 -0
- package/dist/components/Chat/markdown/repair.d.ts +23 -0
- package/dist/components/Chat/markdown/repair.js +337 -0
- package/dist/components/Chat/markdown/streaming-harness.d.ts +23 -0
- package/dist/components/Chat/markdown/streaming-harness.js +62 -0
- package/dist/components/Chat/markdown/types.d.ts +139 -0
- package/dist/components/Chat/markdown/types.js +13 -0
- package/dist/components/Chat/markdown/url-policy.d.ts +33 -0
- package/dist/components/Chat/markdown/url-policy.js +109 -0
- package/dist/components/FileUpload/FileUpload.svelte +35 -123
- package/dist/components/FileUpload/FileUpload.svelte.d.ts +1 -1
- package/dist/components/FileUpload/index.d.ts +2 -28
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/primitives/Collapsible/Collapsible.svelte +5 -0
- package/dist/primitives/SplitPane/SplitPane.svelte +293 -0
- package/dist/primitives/SplitPane/SplitPane.svelte.d.ts +4 -0
- package/dist/primitives/SplitPane/index.d.ts +88 -0
- package/dist/primitives/SplitPane/index.js +2 -0
- package/dist/primitives/SplitPane/split-pane.utils.d.ts +73 -0
- package/dist/primitives/SplitPane/split-pane.utils.js +94 -0
- package/dist/primitives/SplitPane/split-pane.variants.d.ts +40 -0
- package/dist/primitives/SplitPane/split-pane.variants.js +56 -0
- package/dist/primitives/index.d.ts +2 -0
- package/dist/primitives/index.js +1 -0
- package/dist/utils/file-intake.d.ts +78 -0
- package/dist/utils/file-intake.js +144 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { untrack } from 'svelte';
|
|
3
|
+
import { Badge, Collapsible } from '../../../primitives';
|
|
4
|
+
import { getBlocksConfig, resolveSlotClasses } from '../../../provider';
|
|
5
|
+
import { resolveIcon } from '../../../icons';
|
|
6
|
+
import ChevronDownIconDefault from '../../../icons/ChevronDownIcon.svelte';
|
|
7
|
+
import CoreSpinner from '../../../internal/core/CoreSpinner.svelte';
|
|
8
|
+
import CodeBlock from '../CodeBlock/CodeBlock.svelte';
|
|
9
|
+
import { toolCallCardVariants } from './tool-call-card.variants';
|
|
10
|
+
import type { ToolCallCardProps } from './index';
|
|
11
|
+
|
|
12
|
+
const ChevronDownIcon = resolveIcon('chevronDown', ChevronDownIconDefault);
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
toolCall,
|
|
16
|
+
open = $bindable(),
|
|
17
|
+
defaultOpen,
|
|
18
|
+
onOpenChange,
|
|
19
|
+
children,
|
|
20
|
+
pendingLabel = 'Pending',
|
|
21
|
+
runningLabel = 'Running',
|
|
22
|
+
completeLabel = 'Done',
|
|
23
|
+
errorLabel = 'Failed',
|
|
24
|
+
inputLabel = 'Input',
|
|
25
|
+
outputLabel = 'Output',
|
|
26
|
+
class: className,
|
|
27
|
+
unstyled: unstyledProp = false,
|
|
28
|
+
slotClasses: slotClassesProp = {},
|
|
29
|
+
preset,
|
|
30
|
+
...restProps
|
|
31
|
+
}: ToolCallCardProps = $props();
|
|
32
|
+
|
|
33
|
+
const blocksConfig = getBlocksConfig();
|
|
34
|
+
const unstyled = $derived(unstyledProp || blocksConfig?.unstyled || false);
|
|
35
|
+
|
|
36
|
+
// Forward arbitrary root attributes onto the underlying Collapsible without
|
|
37
|
+
// re-deriving its (very wide) props union: spreading the typed `HTMLDivElement`
|
|
38
|
+
// rest here makes svelte-check try to reconcile HTMLAttributes' nullable
|
|
39
|
+
// `title` against Collapsible's narrowed one and blows the union-complexity
|
|
40
|
+
// budget. A plain record spread carries the attributes through cleanly.
|
|
41
|
+
const rootProps = $derived(restProps as Record<string, unknown>);
|
|
42
|
+
|
|
43
|
+
const styles = toolCallCardVariants();
|
|
44
|
+
const slotClasses = $derived(
|
|
45
|
+
resolveSlotClasses(blocksConfig, 'ToolCallCard', preset, {}, slotClassesProp)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
function cls(name: keyof typeof slotClasses, extra?: string | (string | undefined)[]) {
|
|
49
|
+
const extras = Array.isArray(extra) ? extra : [extra];
|
|
50
|
+
if (unstyled) {
|
|
51
|
+
return [slotClasses?.[name], ...extras].filter(Boolean).join(' ');
|
|
52
|
+
}
|
|
53
|
+
const slotFns = styles as Record<string, (args: { class?: unknown }) => string>;
|
|
54
|
+
return slotFns[name]({ class: [slotClasses?.[name], ...extras] });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Uncontrolled seed: expanded by default only for an already-failed call.
|
|
58
|
+
// svelte-ignore state_referenced_locally
|
|
59
|
+
let internalOpen = $state(defaultOpen ?? toolCall.state === 'error');
|
|
60
|
+
const isOpen = $derived(open !== undefined ? open : internalOpen);
|
|
61
|
+
|
|
62
|
+
// Tracks whether the user has toggled the card. Once they have, auto-open is
|
|
63
|
+
// disabled — a manual choice always wins.
|
|
64
|
+
let userToggled = $state(false);
|
|
65
|
+
|
|
66
|
+
function toggle() {
|
|
67
|
+
userToggled = true;
|
|
68
|
+
const next = !isOpen;
|
|
69
|
+
if (open !== undefined) {
|
|
70
|
+
open = next;
|
|
71
|
+
} else {
|
|
72
|
+
internalOpen = next;
|
|
73
|
+
}
|
|
74
|
+
onOpenChange?.(next);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Auto-open on a GENUINE transition to `error` while mounted — unless the
|
|
78
|
+
// user has toggled. A call that is already failed at mount is covered by the
|
|
79
|
+
// seed above (so an explicit defaultOpen={false} wins there), and the open
|
|
80
|
+
// runs through the same notification path as a manual toggle so a
|
|
81
|
+
// controlled-without-bind consumer can mirror it (review findings, P3 wave).
|
|
82
|
+
// svelte-ignore state_referenced_locally
|
|
83
|
+
let prevState = toolCall.state;
|
|
84
|
+
$effect(() => {
|
|
85
|
+
const state = toolCall.state;
|
|
86
|
+
const wasError = prevState === 'error';
|
|
87
|
+
prevState = state;
|
|
88
|
+
if (state !== 'error' || wasError) return;
|
|
89
|
+
untrack(() => {
|
|
90
|
+
if (userToggled || isOpen) return;
|
|
91
|
+
if (open !== undefined) open = true;
|
|
92
|
+
else internalOpen = true;
|
|
93
|
+
onOpenChange?.(true);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const statusLabel = $derived(
|
|
98
|
+
{
|
|
99
|
+
pending: pendingLabel,
|
|
100
|
+
running: runningLabel,
|
|
101
|
+
complete: completeLabel,
|
|
102
|
+
error: errorLabel
|
|
103
|
+
}[toolCall.state]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const badgeIntent = $derived(
|
|
107
|
+
toolCall.state === 'complete' ? 'success' : toolCall.state === 'error' ? 'danger' : 'neutral'
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const isBusy = $derived(toolCall.state === 'pending' || toolCall.state === 'running');
|
|
111
|
+
|
|
112
|
+
// JSON.stringify can throw on circular structures, or return `undefined` for
|
|
113
|
+
// a non-serializable value (function, symbol) — fall back to String() so the
|
|
114
|
+
// CodeBlock always receives a string.
|
|
115
|
+
function stringify(value: unknown): string {
|
|
116
|
+
try {
|
|
117
|
+
const json = JSON.stringify(value, null, 2);
|
|
118
|
+
return json ?? String(value);
|
|
119
|
+
} catch {
|
|
120
|
+
return String(value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<Collapsible variant="card" size="sm" open={isOpen} class={className} {...rootProps}>
|
|
126
|
+
{#snippet trigger({ triggerId, contentId })}
|
|
127
|
+
<button
|
|
128
|
+
id={triggerId}
|
|
129
|
+
type="button"
|
|
130
|
+
class={cls('trigger')}
|
|
131
|
+
aria-expanded={isOpen}
|
|
132
|
+
aria-controls={contentId}
|
|
133
|
+
onclick={toggle}
|
|
134
|
+
>
|
|
135
|
+
<span class={cls('triggerLeft')}>
|
|
136
|
+
{#if isBusy}
|
|
137
|
+
<span aria-hidden="true" class="inline-flex">
|
|
138
|
+
<CoreSpinner size="xs" class={cls('spinner')} />
|
|
139
|
+
</span>
|
|
140
|
+
{/if}
|
|
141
|
+
<!-- CoreSpinner and Badge carry no ARIA (the badge is aria-hidden chrome),
|
|
142
|
+
so this sr-only line is the single textual status for assistive tech. -->
|
|
143
|
+
<span class="sr-only">{statusLabel}</span>
|
|
144
|
+
<span class={cls('toolName')}>{toolCall.name}</span>
|
|
145
|
+
</span>
|
|
146
|
+
<span class={cls('triggerRight')}>
|
|
147
|
+
<Badge intent={badgeIntent} variant="soft" aria-hidden="true">{statusLabel}</Badge>
|
|
148
|
+
<ChevronDownIcon class={cls('chevron', isOpen ? 'rotate-180' : undefined)} />
|
|
149
|
+
</span>
|
|
150
|
+
</button>
|
|
151
|
+
{/snippet}
|
|
152
|
+
|
|
153
|
+
{#if children}
|
|
154
|
+
{@render children(toolCall)}
|
|
155
|
+
{:else}
|
|
156
|
+
<div class={cls('body')}>
|
|
157
|
+
{#if toolCall.errorMessage}
|
|
158
|
+
<p class={cls('errorMessage')}>{toolCall.errorMessage}</p>
|
|
159
|
+
{/if}
|
|
160
|
+
{#if toolCall.input !== undefined}
|
|
161
|
+
<div class={cls('section')}>
|
|
162
|
+
<span class={cls('sectionLabel')}>{inputLabel}</span>
|
|
163
|
+
<CodeBlock lang="json" code={stringify(toolCall.input)} />
|
|
164
|
+
</div>
|
|
165
|
+
{/if}
|
|
166
|
+
{#if toolCall.output !== undefined}
|
|
167
|
+
<div class={cls('section')}>
|
|
168
|
+
<span class={cls('sectionLabel')}>{outputLabel}</span>
|
|
169
|
+
<CodeBlock lang="json" code={stringify(toolCall.output)} />
|
|
170
|
+
</div>
|
|
171
|
+
{/if}
|
|
172
|
+
</div>
|
|
173
|
+
{/if}
|
|
174
|
+
</Collapsible>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ChatToolCallPart } from '../chat.types.js';
|
|
4
|
+
import type { ToolCallCardSlots } from './tool-call-card.variants.js';
|
|
5
|
+
/**
|
|
6
|
+
* @description Collapsible card that renders one agent tool-call part (`type: 'tool-call'`)
|
|
7
|
+
* — a status indicator + monospaced tool name in the header, and the JSON input/output (or an
|
|
8
|
+
* error message) in the expandable body. It is the default renderer ChatMessage reaches for on
|
|
9
|
+
* `tool-call` parts (wire it in via `partRenderers`). Opens itself when a call fails so the error
|
|
10
|
+
* is visible without a click; a manual toggle always wins afterwards. Pass a `children` snippet to
|
|
11
|
+
* replace the default JSON body with a domain-specific view of the same part.
|
|
12
|
+
* @tag ai
|
|
13
|
+
* @related ChatMessage
|
|
14
|
+
* @related ReasoningDisclosure
|
|
15
|
+
* @related CodeBlock
|
|
16
|
+
* @stability experimental
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <ToolCallCard toolCall={part} />
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example Domain-specific body via the children snippet
|
|
24
|
+
* ```svelte
|
|
25
|
+
* <ToolCallCard {toolCall}>
|
|
26
|
+
* {#snippet children(call)}
|
|
27
|
+
* <WeatherResult data={call.output} />
|
|
28
|
+
* {/snippet}
|
|
29
|
+
* </ToolCallCard>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export interface ToolCallCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'class' | 'children'> {
|
|
33
|
+
/** The tool-call part to render. Required. */
|
|
34
|
+
toolCall: ChatToolCallPart;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the card is expanded. Supports `bind:open`. Left uncontrolled, the
|
|
37
|
+
* card starts collapsed for `pending` / `running` / `complete` and expanded
|
|
38
|
+
* for `error`.
|
|
39
|
+
*/
|
|
40
|
+
open?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Initial expanded state for uncontrolled usage. Defaults to `true` when the
|
|
43
|
+
* call is already in the `error` state, `false` otherwise.
|
|
44
|
+
*/
|
|
45
|
+
defaultOpen?: boolean;
|
|
46
|
+
/** Fired once per toggle, after the new open state is applied. */
|
|
47
|
+
onOpenChange?: (open: boolean) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Replace the default JSON input/output body with a custom rendering of the
|
|
50
|
+
* tool-call part. Receives the same `toolCall`. When provided, the built-in
|
|
51
|
+
* error line + input/output sections are not rendered.
|
|
52
|
+
*/
|
|
53
|
+
children?: Snippet<[ChatToolCallPart]>;
|
|
54
|
+
/** Header badge label for the `pending` state. @default 'Pending' */
|
|
55
|
+
pendingLabel?: string;
|
|
56
|
+
/** Header badge label for the `running` state. @default 'Running' */
|
|
57
|
+
runningLabel?: string;
|
|
58
|
+
/** Header badge label for the `complete` state. @default 'Done' */
|
|
59
|
+
completeLabel?: string;
|
|
60
|
+
/** Header badge label for the `error` state. @default 'Failed' */
|
|
61
|
+
errorLabel?: string;
|
|
62
|
+
/** Heading above the input code block. @default 'Input' */
|
|
63
|
+
inputLabel?: string;
|
|
64
|
+
/** Heading above the output code block. @default 'Output' */
|
|
65
|
+
outputLabel?: string;
|
|
66
|
+
/** Extra classes merged onto the root card element. */
|
|
67
|
+
class?: string;
|
|
68
|
+
/** Strip the component's default tv() classes (the underlying Collapsible card chrome is kept). */
|
|
69
|
+
unstyled?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Per-slot class overrides. Slots: `trigger` (header button), `triggerLeft`,
|
|
72
|
+
* `triggerRight`, `spinner`, `toolName`, `chevron`, `body`, `section`,
|
|
73
|
+
* `sectionLabel`, `errorMessage`.
|
|
74
|
+
*/
|
|
75
|
+
slotClasses?: Partial<Record<ToolCallCardSlots, string>>;
|
|
76
|
+
/**
|
|
77
|
+
* Apply a named preset registered via `<BlocksProvider presets={{ ToolCallCard: {...} }}>`.
|
|
78
|
+
* Prefer this over `class` overrides when the requested look falls outside the
|
|
79
|
+
* semantic intent palette.
|
|
80
|
+
*/
|
|
81
|
+
preset?: string;
|
|
82
|
+
}
|
|
83
|
+
export { default as ToolCallCard } from './ToolCallCard.svelte';
|
|
84
|
+
export { type ToolCallCardSlots, type ToolCallCardVariants, toolCallCardVariants } from './tool-call-card.variants.js';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type SlotNames, type VariantProps } from '../../../utils/variants.js';
|
|
2
|
+
export declare const toolCallCardVariants: ((props?: {} | undefined) => {
|
|
3
|
+
trigger: (props?: ({} & {
|
|
4
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
5
|
+
}) | undefined) => string;
|
|
6
|
+
triggerLeft: (props?: ({} & {
|
|
7
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
8
|
+
}) | undefined) => string;
|
|
9
|
+
triggerRight: (props?: ({} & {
|
|
10
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
11
|
+
}) | undefined) => string;
|
|
12
|
+
spinner: (props?: ({} & {
|
|
13
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
14
|
+
}) | undefined) => string;
|
|
15
|
+
toolName: (props?: ({} & {
|
|
16
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
17
|
+
}) | undefined) => string;
|
|
18
|
+
chevron: (props?: ({} & {
|
|
19
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
20
|
+
}) | undefined) => string;
|
|
21
|
+
body: (props?: ({} & {
|
|
22
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
23
|
+
}) | undefined) => string;
|
|
24
|
+
section: (props?: ({} & {
|
|
25
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
26
|
+
}) | undefined) => string;
|
|
27
|
+
sectionLabel: (props?: ({} & {
|
|
28
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
29
|
+
}) | undefined) => string;
|
|
30
|
+
errorMessage: (props?: ({} & {
|
|
31
|
+
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
32
|
+
}) | undefined) => string;
|
|
33
|
+
}) & {
|
|
34
|
+
readonly config: import("../../../utils/variants.js").TVConfig;
|
|
35
|
+
};
|
|
36
|
+
export type ToolCallCardVariants = VariantProps<typeof toolCallCardVariants>;
|
|
37
|
+
/** Slot names derived from the tv() config — single source of truth for slotClasses. */
|
|
38
|
+
export type ToolCallCardSlots = SlotNames<typeof toolCallCardVariants>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { tv } from '../../../utils/variants.js';
|
|
2
|
+
export const toolCallCardVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
// The whole card header IS the collapsible trigger button. Collapsible's
|
|
5
|
+
// card variant only styles the DEFAULT trigger; a custom trigger snippet
|
|
6
|
+
// replaces it, so the horizontal padding / focus ring live here.
|
|
7
|
+
trigger: [
|
|
8
|
+
'flex w-full items-center justify-between gap-2 px-4 py-2 text-left cursor-pointer',
|
|
9
|
+
'text-text-primary',
|
|
10
|
+
'transition-colors duration-[var(--blocks-duration-fast)] ease-out',
|
|
11
|
+
'hover:bg-surface-hover',
|
|
12
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:rounded-sm',
|
|
13
|
+
'disabled:opacity-50 disabled:cursor-not-allowed'
|
|
14
|
+
],
|
|
15
|
+
// Status indicator + tool name; min-w-0 lets the mono name truncate.
|
|
16
|
+
triggerLeft: 'flex items-center gap-2 min-w-0',
|
|
17
|
+
// Status badge + chevron; never shrinks so the name gives way first.
|
|
18
|
+
triggerRight: 'flex items-center gap-2 shrink-0',
|
|
19
|
+
// Inline busy indicator (CoreSpinner wrapper) — tertiary tint via text-current.
|
|
20
|
+
spinner: 'text-text-tertiary shrink-0',
|
|
21
|
+
// The invoked tool's identifier, monospaced.
|
|
22
|
+
toolName: 'font-mono text-sm text-text-secondary truncate',
|
|
23
|
+
// Chevron mirrors Collapsible's own spin timing so both animate in sync.
|
|
24
|
+
chevron: [
|
|
25
|
+
'shrink-0 w-4 h-4 text-text-tertiary',
|
|
26
|
+
'transition-transform duration-[var(--blocks-collapse-duration)] ease-[var(--blocks-collapse-easing)]',
|
|
27
|
+
'motion-reduce:duration-[1ms]'
|
|
28
|
+
],
|
|
29
|
+
// Default body wrapper (input/output sections + error line).
|
|
30
|
+
body: 'flex flex-col gap-3',
|
|
31
|
+
// One labelled block (heading + CodeBlock).
|
|
32
|
+
section: 'flex flex-col gap-1',
|
|
33
|
+
// Small tertiary heading above each code block.
|
|
34
|
+
sectionLabel: 'text-xs font-medium text-text-tertiary',
|
|
35
|
+
// Error message line shown above the sections.
|
|
36
|
+
errorMessage: 'text-sm text-danger'
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { CitationSource } from './CitationChip/index.js';
|
|
2
|
+
/** Author of a chat message. */
|
|
3
|
+
export type ChatRole = 'user' | 'assistant' | 'system';
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle of a message. `streaming` drives the live-rendering affordances
|
|
6
|
+
* (markdown tail repair, cursor, deferred screen-reader announcement);
|
|
7
|
+
* `error` / `aborted` switch the message to its failure presentation.
|
|
8
|
+
* A message without a status counts as `complete`.
|
|
9
|
+
*/
|
|
10
|
+
export type ChatMessageStatus = 'streaming' | 'complete' | 'error' | 'aborted';
|
|
11
|
+
/**
|
|
12
|
+
* One renderable segment of a message. Mirrors the shape of modern
|
|
13
|
+
* model/tool transcripts: interleaved text, reasoning, tool calls, sources
|
|
14
|
+
* and attachments — rendered in order by the ChatMessage component.
|
|
15
|
+
*/
|
|
16
|
+
export type ChatMessagePart =
|
|
17
|
+
/** Markdown text, rendered through StreamingMarkdown. */
|
|
18
|
+
{
|
|
19
|
+
type: 'text';
|
|
20
|
+
text: string;
|
|
21
|
+
}
|
|
22
|
+
/** Model reasoning. Collapsed, tertiary presentation; `durationMs` feeds the "Thought for Xs" label. */
|
|
23
|
+
| {
|
|
24
|
+
type: 'reasoning';
|
|
25
|
+
text: string;
|
|
26
|
+
durationMs?: number;
|
|
27
|
+
}
|
|
28
|
+
/** A tool invocation with its lifecycle state. Rendered as a ToolCallCard by default; override via `partRenderers`. */
|
|
29
|
+
| {
|
|
30
|
+
type: 'tool-call';
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
state: 'pending' | 'running' | 'complete' | 'error';
|
|
34
|
+
input?: unknown;
|
|
35
|
+
output?: unknown;
|
|
36
|
+
errorMessage?: string;
|
|
37
|
+
}
|
|
38
|
+
/** A cited source. Same shape as CitationSource — also feeds StreamingMarkdown's `sources` for `[id]` markers. */
|
|
39
|
+
| ({
|
|
40
|
+
type: 'source';
|
|
41
|
+
} & CitationSource)
|
|
42
|
+
/**
|
|
43
|
+
* A file attached to the message. `url` is only ever rendered as a
|
|
44
|
+
* policy-checked download link (never as an inline image/iframe) — LLM- or
|
|
45
|
+
* server-supplied URLs are untrusted input.
|
|
46
|
+
*/
|
|
47
|
+
| {
|
|
48
|
+
type: 'attachment';
|
|
49
|
+
name: string;
|
|
50
|
+
mimeType: string;
|
|
51
|
+
size?: number;
|
|
52
|
+
url?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Declarative A2UI payload (P4). Validated fail-loud by A2UIView; ignored by default renderers until then. */
|
|
55
|
+
| {
|
|
56
|
+
type: 'a2ui';
|
|
57
|
+
payload: unknown;
|
|
58
|
+
};
|
|
59
|
+
/** The `tool-call` member of {@link ChatMessagePart} — the prop shape of ToolCallCard. */
|
|
60
|
+
export type ChatToolCallPart = Extract<ChatMessagePart, {
|
|
61
|
+
type: 'tool-call';
|
|
62
|
+
}>;
|
|
63
|
+
/** The `reasoning` member of {@link ChatMessagePart} — the prop shape of ReasoningDisclosure. */
|
|
64
|
+
export type ChatReasoningPart = Extract<ChatMessagePart, {
|
|
65
|
+
type: 'reasoning';
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* One message in a conversation. Named `ChatMessageData` because the value
|
|
69
|
+
* export `ChatMessage` is the component that renders it.
|
|
70
|
+
*/
|
|
71
|
+
export interface ChatMessageData {
|
|
72
|
+
/** Stable unique id — keyed `{#each}` identity, never an array index. */
|
|
73
|
+
id: string;
|
|
74
|
+
role: ChatRole;
|
|
75
|
+
/** Ordered renderable segments. A plain text answer is `[{ type: 'text', text }]`. */
|
|
76
|
+
parts: ChatMessagePart[];
|
|
77
|
+
createdAt?: Date;
|
|
78
|
+
/** Omitted counts as `complete`. */
|
|
79
|
+
status?: ChatMessageStatus;
|
|
80
|
+
/** Consumer-defined extras (model name, token counts, …). Not rendered by defaults. */
|
|
81
|
+
metadata?: Record<string, unknown>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Chat conversation data model — the contract between a consumer's transport
|
|
2
|
+
// layer (SSE/fetch/websocket) and the Chat family's rendering components.
|
|
3
|
+
//
|
|
4
|
+
// Deliberately NOT a store: the consumer owns `ChatMessageData[]` (typically
|
|
5
|
+
// `$state` + appends from a stream) and passes it down. Components never
|
|
6
|
+
// mutate messages.
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type { ChatProps } from './Chat/index.js';
|
|
2
|
+
export * from './Chat/index.js';
|
|
3
|
+
export type { ChatMessageProps, ChatPartRenderers } from './ChatMessage/index.js';
|
|
4
|
+
export * from './ChatMessage/index.js';
|
|
5
|
+
export type { ChatMessageListItemContext, ChatMessageListProps } from './ChatMessageList/index.js';
|
|
6
|
+
export * from './ChatMessageList/index.js';
|
|
7
|
+
export type { CitationChipProps, CitationSource } from './CitationChip/index.js';
|
|
8
|
+
export * from './CitationChip/index.js';
|
|
9
|
+
export type { CodeBlockProps } from './CodeBlock/index.js';
|
|
10
|
+
export * from './CodeBlock/index.js';
|
|
11
|
+
export type { ChatMessageData, ChatMessagePart, ChatMessageStatus, ChatReasoningPart, ChatRole, ChatToolCallPart } from './chat.types.js';
|
|
12
|
+
export { createIncrementalParser, parseMarkdown } from './markdown/blocks.js';
|
|
13
|
+
export { repairMarkdownTail } from './markdown/repair.js';
|
|
14
|
+
export type { BlockNode, IncrementalMarkdownParser, InlineNode, MarkdownBlock, MarkdownDocument, MarkdownParseOptions, MarkdownUrlPolicy } from './markdown/types.js';
|
|
15
|
+
export type { PromptInputProps } from './PromptInput/index.js';
|
|
16
|
+
export * from './PromptInput/index.js';
|
|
17
|
+
export type { ReasoningDisclosureProps } from './ReasoningDisclosure/index.js';
|
|
18
|
+
export * from './ReasoningDisclosure/index.js';
|
|
19
|
+
export type { MarkdownRenderers, StreamingMarkdownProps } from './StreamingMarkdown/index.js';
|
|
20
|
+
export * from './StreamingMarkdown/index.js';
|
|
21
|
+
export type { ToolCallCardProps } from './ToolCallCard/index.js';
|
|
22
|
+
export * from './ToolCallCard/index.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Chat family barrel — AI-kit surfaces (conversation, composer, streaming
|
|
2
|
+
// markdown, code display, citations) plus the public pieces of the markdown
|
|
3
|
+
// engine underneath them.
|
|
4
|
+
export * from './Chat/index.js';
|
|
5
|
+
export * from './ChatMessage/index.js';
|
|
6
|
+
export * from './ChatMessageList/index.js';
|
|
7
|
+
export * from './CitationChip/index.js';
|
|
8
|
+
export * from './CodeBlock/index.js';
|
|
9
|
+
export { createIncrementalParser, parseMarkdown } from './markdown/blocks.js';
|
|
10
|
+
export { repairMarkdownTail } from './markdown/repair.js';
|
|
11
|
+
export * from './PromptInput/index.js';
|
|
12
|
+
export * from './ReasoningDisclosure/index.js';
|
|
13
|
+
export * from './StreamingMarkdown/index.js';
|
|
14
|
+
export * from './ToolCallCard/index.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { IncrementalMarkdownParser, MarkdownDocument, MarkdownParseOptions } from './types.js';
|
|
2
|
+
type RawBlock = {
|
|
3
|
+
type: 'paragraph';
|
|
4
|
+
start: number;
|
|
5
|
+
lines: string[];
|
|
6
|
+
} | {
|
|
7
|
+
type: 'heading';
|
|
8
|
+
start: number;
|
|
9
|
+
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
10
|
+
text: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'fence';
|
|
13
|
+
start: number;
|
|
14
|
+
lang?: string;
|
|
15
|
+
code: string[];
|
|
16
|
+
open: boolean;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'list';
|
|
19
|
+
start: number;
|
|
20
|
+
ordered: boolean;
|
|
21
|
+
startNumber?: number;
|
|
22
|
+
lines: string[];
|
|
23
|
+
} | {
|
|
24
|
+
type: 'quote';
|
|
25
|
+
start: number;
|
|
26
|
+
lines: string[];
|
|
27
|
+
} | {
|
|
28
|
+
type: 'table';
|
|
29
|
+
start: number;
|
|
30
|
+
header: string;
|
|
31
|
+
delimiter: string;
|
|
32
|
+
rows: string[];
|
|
33
|
+
} | {
|
|
34
|
+
type: 'hr';
|
|
35
|
+
start: number;
|
|
36
|
+
};
|
|
37
|
+
interface ScanResult {
|
|
38
|
+
blocks: RawBlock[];
|
|
39
|
+
refs: Map<string, {
|
|
40
|
+
href: string;
|
|
41
|
+
title?: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Label of a reference definition sitting on the final, not-yet-terminated
|
|
45
|
+
* line — its URL may still be streaming in. Such a definition is used for
|
|
46
|
+
* display (one-shot parity if the stream really ends here) but never for
|
|
47
|
+
* settling, and it does not count as "arrived" for invalidation purposes.
|
|
48
|
+
*/
|
|
49
|
+
unstableRefLabel?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function scanBlocks(text: string): ScanResult;
|
|
52
|
+
export declare function parseMarkdown(text: string, options?: MarkdownParseOptions): MarkdownDocument;
|
|
53
|
+
export declare function createIncrementalParser(options?: MarkdownParseOptions): IncrementalMarkdownParser;
|
|
54
|
+
export {};
|