@tanstack/ai-svelte 0.19.4 → 0.20.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/chat-ui/create-chat-hook.d.ts +27 -0
- package/dist/chat-ui/create-chat-hook.js +26 -0
- package/dist/chat-ui/create-ui.d.ts +131 -0
- package/dist/chat-ui/create-ui.js +100 -0
- package/dist/chat-ui/selected-part.svelte +45 -0
- package/dist/chat-ui/selected-part.svelte.d.ts +9 -0
- package/dist/chat-ui/ui-chat.svelte +42 -0
- package/dist/chat-ui/ui-chat.svelte.d.ts +9 -0
- package/dist/chat-ui/ui-interrupt.svelte +30 -0
- package/dist/chat-ui/ui-interrupt.svelte.d.ts +9 -0
- package/dist/chat-ui/ui-interrupts.svelte +30 -0
- package/dist/chat-ui/ui-interrupts.svelte.d.ts +9 -0
- package/dist/chat-ui/ui-message.svelte +45 -0
- package/dist/chat-ui/ui-message.svelte.d.ts +12 -0
- package/dist/chat-ui/ui-messages.svelte +31 -0
- package/dist/chat-ui/ui-messages.svelte.d.ts +10 -0
- package/dist/chat-ui/ui-part.svelte +30 -0
- package/dist/chat-ui/ui-part.svelte.d.ts +9 -0
- package/dist/chat-ui/ui-provider.svelte +29 -0
- package/dist/chat-ui/ui-provider.svelte.d.ts +10 -0
- package/dist/chat-ui/ui-queue.svelte +21 -0
- package/dist/chat-ui/ui-queue.svelte.d.ts +7 -0
- package/dist/create-chat-hook.d.ts +35 -0
- package/dist/create-chat-hook.js +31 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/ui.d.ts +11 -0
- package/dist/ui.js +11 -0
- package/package.json +9 -4
- package/src/chat-ui/create-chat-hook.ts +62 -0
- package/src/chat-ui/create-ui.ts +310 -0
- package/src/chat-ui/selected-part.svelte +45 -0
- package/src/chat-ui/ui-chat.svelte +42 -0
- package/src/chat-ui/ui-interrupt.svelte +30 -0
- package/src/chat-ui/ui-interrupts.svelte +30 -0
- package/src/chat-ui/ui-message.svelte +45 -0
- package/src/chat-ui/ui-messages.svelte +31 -0
- package/src/chat-ui/ui-part.svelte +30 -0
- package/src/chat-ui/ui-provider.svelte +29 -0
- package/src/chat-ui/ui-queue.svelte +21 -0
- package/src/create-chat-hook.ts +67 -0
- package/src/index.ts +1 -0
- package/src/ui.ts +25 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { InferredClientContext } from '@tanstack/ai-client';
|
|
2
|
+
import type { ChatUIInterruptsOf, ChatUISchemaOf, ChatUIToolsOf } from '@tanstack/ai-client/ui';
|
|
3
|
+
import type { CreateChatOptions } from '../types';
|
|
4
|
+
import type { ChatUIFactoryConfig, ChatUIHost } from './create-ui';
|
|
5
|
+
type HeadlessOptions<TOptions> = CreateChatOptions<ChatUIToolsOf<TOptions>, ChatUISchemaOf<TOptions>, InferredClientContext<ChatUIToolsOf<TOptions>>, ChatUIInterruptsOf<TOptions>>;
|
|
6
|
+
type ChatInstanceOverrides<TOptions> = {
|
|
7
|
+
threadId?: string;
|
|
8
|
+
live?: boolean;
|
|
9
|
+
forwardedProps?: Record<string, any>;
|
|
10
|
+
body?: Record<string, any>;
|
|
11
|
+
initialMessages?: HeadlessOptions<TOptions>['initialMessages'];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Bind chat options and UI widgets once at module scope.
|
|
15
|
+
*
|
|
16
|
+
* Returns a bound `createAppChat`, the UI descriptor (`ui`), and
|
|
17
|
+
* `useChatContext`. Pass `{ui}` into `UIChat`. Pass instance overrides
|
|
18
|
+
* such as `threadId` into `createAppChat()`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createChatHook<const TOptions>({ options, ...chatComponents }: {
|
|
21
|
+
options: TOptions;
|
|
22
|
+
} & ChatUIFactoryConfig<NoInfer<TOptions>>): {
|
|
23
|
+
createAppChat: (overrides?: ChatInstanceOverrides<TOptions>) => ChatUIHost<TOptions>;
|
|
24
|
+
ui: import("./create-ui").UIDescriptor<TOptions>;
|
|
25
|
+
useChatContext: () => ChatUIHost<TOptions>;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createChat as createUnboundChat } from '../create-chat.svelte';
|
|
2
|
+
import { createChatUI } from './create-ui';
|
|
3
|
+
/**
|
|
4
|
+
* Bind chat options and UI widgets once at module scope.
|
|
5
|
+
*
|
|
6
|
+
* Returns a bound `createAppChat`, the UI descriptor (`ui`), and
|
|
7
|
+
* `useChatContext`. Pass `{ui}` into `UIChat`. Pass instance overrides
|
|
8
|
+
* such as `threadId` into `createAppChat()`.
|
|
9
|
+
*/
|
|
10
|
+
export function createChatHook({ options, ...chatComponents }) {
|
|
11
|
+
const ui = createChatUI(options, chatComponents);
|
|
12
|
+
function createAppChat(overrides) {
|
|
13
|
+
if (!overrides) {
|
|
14
|
+
return createUnboundChat(options);
|
|
15
|
+
}
|
|
16
|
+
return createUnboundChat({
|
|
17
|
+
...options,
|
|
18
|
+
...overrides,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
createAppChat,
|
|
23
|
+
ui,
|
|
24
|
+
useChatContext: ui.useChatContext,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { ChatUIData, ChatUIHasNamedInterrupts, ChatUIHasNamedTools, ChatUIInterrupt, ChatUIInterruptName, ChatUIInterruptOf, ChatUIInterruptsOf, ChatUINamedInterruptId, ChatUIPartKey, ChatUIPartOf, ChatUISchemaOf, ChatUISelectedPart, ChatUIToolApproval, ChatUIToolName, ChatUIToolsOf } from '@tanstack/ai-client/ui';
|
|
2
|
+
import type { QueuedMessage, ToolCallPart, ToolResultPart, UIMessage } from '@tanstack/ai-client';
|
|
3
|
+
import type { CreateChatReturn } from '../types';
|
|
4
|
+
export type ChatUIHost<TOptions = unknown> = CreateChatReturn<ChatUIToolsOf<TOptions>, ChatUISchemaOf<TOptions>, unknown, ChatUIInterruptsOf<TOptions>>;
|
|
5
|
+
type GenericInterruptComponents<TOptions> = ChatUIHasNamedInterrupts<TOptions> extends true ? {
|
|
6
|
+
[K in ChatUINamedInterruptId<TOptions>]: unknown;
|
|
7
|
+
} & {
|
|
8
|
+
fallback?: unknown;
|
|
9
|
+
} : {
|
|
10
|
+
fallback?: unknown;
|
|
11
|
+
};
|
|
12
|
+
type ToolApprovalMap<TOptions> = {
|
|
13
|
+
[K in ChatUIToolName<TOptions>]?: unknown;
|
|
14
|
+
};
|
|
15
|
+
/** The chrome around the message list: `layout`, `message`, and `input`. */
|
|
16
|
+
export type ChatUIChromeComponents = {
|
|
17
|
+
layout: unknown;
|
|
18
|
+
message: unknown;
|
|
19
|
+
input?: unknown;
|
|
20
|
+
queue?: unknown;
|
|
21
|
+
};
|
|
22
|
+
export type ChatUIPartsComponents = {
|
|
23
|
+
[K in ChatUIPartKey]?: unknown;
|
|
24
|
+
} & {
|
|
25
|
+
fallback?: unknown;
|
|
26
|
+
};
|
|
27
|
+
export type ChatUIInterruptsComponents<TOptions> = {
|
|
28
|
+
tools?: ToolApprovalMap<TOptions>;
|
|
29
|
+
generic: GenericInterruptComponents<TOptions>;
|
|
30
|
+
};
|
|
31
|
+
/** The flat shape the runtime reads, assembled from the factory config. */
|
|
32
|
+
export type ChatUIComponents<TOptions> = ChatUIChromeComponents & {
|
|
33
|
+
parts: ChatUIPartsComponents;
|
|
34
|
+
tools?: {
|
|
35
|
+
[K in ChatUIToolName<TOptions>]?: unknown;
|
|
36
|
+
};
|
|
37
|
+
interrupts?: {
|
|
38
|
+
tools?: ToolApprovalMap<TOptions>;
|
|
39
|
+
generic?: GenericInterruptComponents<TOptions>;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type ChatUIFactoryConfig<TOptions> = {
|
|
43
|
+
components: ChatUIChromeComponents;
|
|
44
|
+
partsComponents: ChatUIPartsComponents;
|
|
45
|
+
} & (ChatUIHasNamedTools<TOptions> extends true ? {
|
|
46
|
+
toolsComponents: {
|
|
47
|
+
[K in ChatUIToolName<TOptions>]: unknown;
|
|
48
|
+
};
|
|
49
|
+
} : {
|
|
50
|
+
toolsComponents?: {
|
|
51
|
+
[K in ChatUIToolName<TOptions>]?: unknown;
|
|
52
|
+
};
|
|
53
|
+
}) & (ChatUIHasNamedInterrupts<TOptions> extends true ? {
|
|
54
|
+
interruptsComponents: ChatUIInterruptsComponents<TOptions>;
|
|
55
|
+
} : {
|
|
56
|
+
interruptsComponents?: {
|
|
57
|
+
tools?: ToolApprovalMap<TOptions>;
|
|
58
|
+
generic?: GenericInterruptComponents<TOptions>;
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
export type UIDescriptor<TOptions = unknown> = {
|
|
62
|
+
key: symbol;
|
|
63
|
+
warn: (key: string, message: string) => void;
|
|
64
|
+
components: ChatUIComponents<TOptions>;
|
|
65
|
+
useChatContext: () => ChatUIHost<TOptions>;
|
|
66
|
+
};
|
|
67
|
+
export type UIContextValue<TOptions = unknown> = {
|
|
68
|
+
chat: ChatUIHost<TOptions>;
|
|
69
|
+
components: ChatUIComponents<TOptions>;
|
|
70
|
+
ui: UIDescriptor<TOptions>;
|
|
71
|
+
};
|
|
72
|
+
type ComponentsValue<TOptions = unknown> = {
|
|
73
|
+
components: ChatUIComponents<TOptions>;
|
|
74
|
+
warn: (key: string, message: string) => void;
|
|
75
|
+
inlineToolNames: ReadonlyArray<string>;
|
|
76
|
+
};
|
|
77
|
+
export declare function createChatUI<const TOptions>(options: TOptions, config: ChatUIFactoryConfig<NoInfer<TOptions>>): UIDescriptor<TOptions>;
|
|
78
|
+
export declare function setUIContext<TOptions>(value: UIContextValue<TOptions>): void;
|
|
79
|
+
export declare function getChatContext<TOptions>(ui: UIDescriptor<TOptions>): ChatUIHost<TOptions>;
|
|
80
|
+
export declare function getComponentsContext<TOptions>(ui: UIDescriptor<TOptions>): ComponentsValue<TOptions>;
|
|
81
|
+
export declare function getUIContext<TOptions>(ui: UIDescriptor<TOptions>): {
|
|
82
|
+
ui: UIDescriptor<TOptions>;
|
|
83
|
+
chat: ChatUIHost<TOptions>;
|
|
84
|
+
components: ChatUIComponents<TOptions>;
|
|
85
|
+
};
|
|
86
|
+
export declare function readMessages<TOptions>(chat: ChatUIHost<TOptions>): UIMessage<ChatUIToolsOf<TOptions>, ChatUISchemaOf<TOptions> extends infer T ? T extends ChatUISchemaOf<TOptions> ? T extends import("@tanstack/ai").SchemaInput ? import("@tanstack/ai").InferSchemaType<T> : unknown : never : never>[];
|
|
87
|
+
export declare function readInterrupts<TOptions>(chat: ChatUIHost<TOptions>): import("@tanstack/ai-client").BoundInterrupts<ChatUIToolsOf<TOptions>, ChatUIInterruptsOf<TOptions>>;
|
|
88
|
+
export declare function readQueue<TOptions>(chat: ChatUIHost<TOptions>): {
|
|
89
|
+
cancelQueued: () => void;
|
|
90
|
+
id: string;
|
|
91
|
+
content: string | import("@tanstack/ai-client").MultimodalContent;
|
|
92
|
+
createdAt: number;
|
|
93
|
+
}[];
|
|
94
|
+
export declare function inlineNames<TOptions>(components: ChatUIComponents<TOptions>): string[];
|
|
95
|
+
export declare function messageParts(message: UIMessage, interrupts: ReadonlyArray<ChatUIInterrupt>, inlineToolNames: ReadonlyArray<string>): Array<ChatUISelectedPart>;
|
|
96
|
+
export declare function listInterrupts<TOptions>(chat: ChatUIHost<TOptions>, inlineToolNames: ReadonlyArray<string>): ChatUIInterrupt[];
|
|
97
|
+
export declare function toolComponent<TOptions>(components: ChatUIComponents<TOptions>, name: string): undefined;
|
|
98
|
+
export declare function partComponent<TOptions>(components: ChatUIComponents<TOptions>, key: string): unknown;
|
|
99
|
+
export declare function interruptComponent<TOptions>(components: ChatUIComponents<TOptions>, interrupt: ChatUIInterrupt): unknown;
|
|
100
|
+
export type ChatUIQueueItem = QueuedMessage & {
|
|
101
|
+
cancelQueued: () => void;
|
|
102
|
+
};
|
|
103
|
+
export type LayoutProps<TOptions> = {
|
|
104
|
+
readonly __ui?: TOptions;
|
|
105
|
+
};
|
|
106
|
+
export type MessageProps<TOptions> = {
|
|
107
|
+
message: UIMessage<ChatUIToolsOf<TOptions>, ChatUIData<TOptions>>;
|
|
108
|
+
};
|
|
109
|
+
export type InputProps<TOptions> = {
|
|
110
|
+
readonly __ui?: TOptions;
|
|
111
|
+
};
|
|
112
|
+
export type QueueProps<TOptions> = {
|
|
113
|
+
item: ChatUIQueueItem;
|
|
114
|
+
readonly __ui?: TOptions;
|
|
115
|
+
};
|
|
116
|
+
export type PartProps<TOptions, TKey extends ChatUIPartKey = ChatUIPartKey> = {
|
|
117
|
+
part: ChatUIPartOf<TOptions, TKey>;
|
|
118
|
+
};
|
|
119
|
+
export type ToolProps<TOptions, TName extends ChatUIToolName<TOptions> = ChatUIToolName<TOptions>> = {
|
|
120
|
+
part: Extract<ToolCallPart<ChatUIToolsOf<TOptions>>, {
|
|
121
|
+
name: TName;
|
|
122
|
+
}>;
|
|
123
|
+
result?: ToolResultPart;
|
|
124
|
+
interrupt?: ChatUIToolApproval<TOptions, TName>;
|
|
125
|
+
readonly __ui?: TOptions;
|
|
126
|
+
};
|
|
127
|
+
export type InterruptProps<TOptions, TName extends ChatUIInterruptName<TOptions> = never> = {
|
|
128
|
+
interrupt: ChatUIInterruptOf<TOptions, TName>;
|
|
129
|
+
readonly __ui?: TOptions;
|
|
130
|
+
};
|
|
131
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
import { automaticPartsForMessage, collectInlineToolNames, resolveInterruptComponent, selectChatUI, selectMessageUI, } from '@tanstack/ai-client/ui';
|
|
3
|
+
function createWarnOnce() {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
return (key, message) => {
|
|
6
|
+
if (process.env.NODE_ENV === 'production')
|
|
7
|
+
return;
|
|
8
|
+
if (seen.has(key))
|
|
9
|
+
return;
|
|
10
|
+
seen.add(key);
|
|
11
|
+
console.warn(message);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function createChatUI(options, config) {
|
|
15
|
+
void options;
|
|
16
|
+
const { components: chrome, partsComponents, toolsComponents, interruptsComponents, } = config;
|
|
17
|
+
// The runtime keeps the flat shape the rest of this module reads.
|
|
18
|
+
const components = {
|
|
19
|
+
...chrome,
|
|
20
|
+
parts: partsComponents,
|
|
21
|
+
tools: toolsComponents,
|
|
22
|
+
interrupts: interruptsComponents,
|
|
23
|
+
};
|
|
24
|
+
const ui = {
|
|
25
|
+
key: Symbol('tanstack-ai-ui-chat'),
|
|
26
|
+
componentsKey: Symbol('tanstack-ai-ui-components'),
|
|
27
|
+
warn: createWarnOnce(),
|
|
28
|
+
components,
|
|
29
|
+
useChatContext() {
|
|
30
|
+
return getChatContext(ui);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return ui;
|
|
34
|
+
}
|
|
35
|
+
export function setUIContext(value) {
|
|
36
|
+
setContext(value.ui.key, value.chat);
|
|
37
|
+
setContext(value.ui.componentsKey, {
|
|
38
|
+
components: value.components,
|
|
39
|
+
warn: value.ui.warn,
|
|
40
|
+
inlineToolNames: inlineNames(value.components),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export function getChatContext(ui) {
|
|
44
|
+
const chat = getContext(ui.key);
|
|
45
|
+
if (!chat) {
|
|
46
|
+
throw new Error('Chat UI components must be wrapped in UIProvider or UIChat.');
|
|
47
|
+
}
|
|
48
|
+
return chat;
|
|
49
|
+
}
|
|
50
|
+
export function getComponentsContext(ui) {
|
|
51
|
+
const value = getContext(ui.componentsKey);
|
|
52
|
+
if (!value) {
|
|
53
|
+
throw new Error('Chat UI components must be wrapped in UIProvider or UIChat.');
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
export function getUIContext(ui) {
|
|
58
|
+
return {
|
|
59
|
+
ui,
|
|
60
|
+
chat: getChatContext(ui),
|
|
61
|
+
components: getComponentsContext(ui).components,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export function readMessages(chat) {
|
|
65
|
+
return chat.messages ?? [];
|
|
66
|
+
}
|
|
67
|
+
export function readInterrupts(chat) {
|
|
68
|
+
return chat.interrupts ?? [];
|
|
69
|
+
}
|
|
70
|
+
export function readQueue(chat) {
|
|
71
|
+
const items = chat.queue ?? [];
|
|
72
|
+
return items.map((item) => ({
|
|
73
|
+
...item,
|
|
74
|
+
cancelQueued: () => {
|
|
75
|
+
chat.cancelQueued(item.id);
|
|
76
|
+
},
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
export function inlineNames(components) {
|
|
80
|
+
return collectInlineToolNames(components.interrupts?.tools, Object.keys(components.tools ?? {}));
|
|
81
|
+
}
|
|
82
|
+
export function messageParts(message, interrupts, inlineToolNames) {
|
|
83
|
+
return automaticPartsForMessage(selectMessageUI(message, { interrupts, inlineToolNames }));
|
|
84
|
+
}
|
|
85
|
+
export function listInterrupts(chat, inlineToolNames) {
|
|
86
|
+
return selectChatUI({
|
|
87
|
+
messages: readMessages(chat),
|
|
88
|
+
interrupts: readInterrupts(chat),
|
|
89
|
+
inlineToolNames,
|
|
90
|
+
}).interrupts;
|
|
91
|
+
}
|
|
92
|
+
export function toolComponent(components, name) {
|
|
93
|
+
return components.tools?.[name];
|
|
94
|
+
}
|
|
95
|
+
export function partComponent(components, key) {
|
|
96
|
+
return components.parts[key] ?? components.parts.fallback;
|
|
97
|
+
}
|
|
98
|
+
export function interruptComponent(components, interrupt) {
|
|
99
|
+
return resolveInterruptComponent(interrupt, components.interrupts);
|
|
100
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getComponentsContext,
|
|
4
|
+
partComponent,
|
|
5
|
+
toolComponent,
|
|
6
|
+
type UIDescriptor,
|
|
7
|
+
} from './create-ui'
|
|
8
|
+
import type { ChatUISelectedPart } from '@tanstack/ai-client/ui'
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
ui,
|
|
12
|
+
selected,
|
|
13
|
+
}: {
|
|
14
|
+
ui: UIDescriptor
|
|
15
|
+
selected: ChatUISelectedPart
|
|
16
|
+
} = $props()
|
|
17
|
+
|
|
18
|
+
const comps = $derived(getComponentsContext(ui))
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
{#if selected.key === 'toolCall'}
|
|
22
|
+
{@const Tool = toolComponent(comps.components, selected.part.name) as any}
|
|
23
|
+
{#if Tool}
|
|
24
|
+
<Tool
|
|
25
|
+
part={selected.part}
|
|
26
|
+
result={selected.result}
|
|
27
|
+
interrupt={selected.interrupt}
|
|
28
|
+
/>
|
|
29
|
+
{:else}
|
|
30
|
+
{comps.warn(
|
|
31
|
+
`tool:${selected.part.name}`,
|
|
32
|
+
`[tanstack-ai-ui] Missing tools.${selected.part.name} component`,
|
|
33
|
+
)}
|
|
34
|
+
{/if}
|
|
35
|
+
{:else}
|
|
36
|
+
{@const Part = partComponent(comps.components, selected.key) as any}
|
|
37
|
+
{#if Part}
|
|
38
|
+
<Part part={selected.part} />
|
|
39
|
+
{:else}
|
|
40
|
+
{comps.warn(
|
|
41
|
+
`part:${selected.key}`,
|
|
42
|
+
`[tanstack-ai-ui] Missing parts.${selected.key} component`,
|
|
43
|
+
)}
|
|
44
|
+
{/if}
|
|
45
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { ChatUISelectedPart } from '@tanstack/ai-client/ui';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
ui: UIDescriptor;
|
|
5
|
+
selected: ChatUISelectedPart;
|
|
6
|
+
};
|
|
7
|
+
declare const SelectedPart: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type SelectedPart = ReturnType<typeof SelectedPart>;
|
|
9
|
+
export default SelectedPart;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import UIProvider from './ui-provider.svelte'
|
|
3
|
+
import UIMessages from './ui-messages.svelte'
|
|
4
|
+
import UIInterrupts from './ui-interrupts.svelte'
|
|
5
|
+
import UIQueue from './ui-queue.svelte'
|
|
6
|
+
import type { ChatUIComponents, UIDescriptor } from './create-ui'
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
ui,
|
|
10
|
+
chat,
|
|
11
|
+
components,
|
|
12
|
+
}: {
|
|
13
|
+
ui: UIDescriptor
|
|
14
|
+
// ponytail: Svelte components are not generic, so ChatUIHost<TOptions> cannot
|
|
15
|
+
// accept a typed createChat() host with tool-approval interrupts.
|
|
16
|
+
chat: any
|
|
17
|
+
components?: ChatUIComponents<unknown>
|
|
18
|
+
} = $props()
|
|
19
|
+
|
|
20
|
+
const bound = $derived(components ?? ui.components)
|
|
21
|
+
const Layout = $derived(bound.layout as any)
|
|
22
|
+
const Input = $derived(bound.input as any)
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<UIProvider {ui} {chat} components={bound}>
|
|
26
|
+
<Layout>
|
|
27
|
+
{#snippet messages()}
|
|
28
|
+
<UIMessages {ui} />
|
|
29
|
+
{/snippet}
|
|
30
|
+
{#snippet interrupts()}
|
|
31
|
+
<UIInterrupts {ui} />
|
|
32
|
+
{/snippet}
|
|
33
|
+
{#snippet queue()}
|
|
34
|
+
<UIQueue {ui} />
|
|
35
|
+
{/snippet}
|
|
36
|
+
{#snippet input()}
|
|
37
|
+
{#if Input}
|
|
38
|
+
<Input />
|
|
39
|
+
{/if}
|
|
40
|
+
{/snippet}
|
|
41
|
+
</Layout>
|
|
42
|
+
</UIProvider>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChatUIComponents, UIDescriptor } from './create-ui';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
ui: UIDescriptor;
|
|
4
|
+
chat: any;
|
|
5
|
+
components?: ChatUIComponents<unknown>;
|
|
6
|
+
};
|
|
7
|
+
declare const UiChat: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type UiChat = ReturnType<typeof UiChat>;
|
|
9
|
+
export default UiChat;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getComponentsContext,
|
|
4
|
+
interruptComponent,
|
|
5
|
+
type UIDescriptor,
|
|
6
|
+
} from './create-ui'
|
|
7
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui'
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
ui,
|
|
11
|
+
interrupt,
|
|
12
|
+
}: {
|
|
13
|
+
ui: UIDescriptor
|
|
14
|
+
interrupt: ChatUIInterrupt
|
|
15
|
+
} = $props()
|
|
16
|
+
|
|
17
|
+
const comps = $derived(getComponentsContext(ui))
|
|
18
|
+
const Component = $derived(
|
|
19
|
+
interruptComponent(comps.components, interrupt) as any,
|
|
20
|
+
)
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
{#if Component}
|
|
24
|
+
<Component {interrupt} />
|
|
25
|
+
{:else}
|
|
26
|
+
{comps.warn(
|
|
27
|
+
`interrupt:${interrupt.id}`,
|
|
28
|
+
`[tanstack-ai-ui] Missing interrupt component for ${interrupt.kind}`,
|
|
29
|
+
)}
|
|
30
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
ui: UIDescriptor;
|
|
5
|
+
interrupt: ChatUIInterrupt;
|
|
6
|
+
};
|
|
7
|
+
declare const UiInterrupt: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type UiInterrupt = ReturnType<typeof UiInterrupt>;
|
|
9
|
+
export default UiInterrupt;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getChatContext,
|
|
4
|
+
getComponentsContext,
|
|
5
|
+
listInterrupts,
|
|
6
|
+
type UIDescriptor,
|
|
7
|
+
} from './create-ui'
|
|
8
|
+
import UIInterrupt from './ui-interrupt.svelte'
|
|
9
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui'
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
ui,
|
|
13
|
+
children,
|
|
14
|
+
}: {
|
|
15
|
+
ui: UIDescriptor
|
|
16
|
+
children?: import('svelte').Snippet<[Array<ChatUIInterrupt>]>
|
|
17
|
+
} = $props()
|
|
18
|
+
|
|
19
|
+
const chat = $derived(getChatContext(ui))
|
|
20
|
+
const comps = $derived(getComponentsContext(ui))
|
|
21
|
+
const interrupts = $derived(listInterrupts(chat, comps.inlineToolNames))
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{#if children}
|
|
25
|
+
{@render children(interrupts)}
|
|
26
|
+
{:else}
|
|
27
|
+
{#each interrupts as interrupt (interrupt.id)}
|
|
28
|
+
<UIInterrupt {ui} {interrupt} />
|
|
29
|
+
{/each}
|
|
30
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
ui: UIDescriptor;
|
|
5
|
+
children?: import('svelte').Snippet<[Array<ChatUIInterrupt>]>;
|
|
6
|
+
};
|
|
7
|
+
declare const UiInterrupts: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type UiInterrupts = ReturnType<typeof UiInterrupts>;
|
|
9
|
+
export default UiInterrupts;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getChatContext,
|
|
4
|
+
getComponentsContext,
|
|
5
|
+
messageParts,
|
|
6
|
+
readInterrupts,
|
|
7
|
+
type UIDescriptor,
|
|
8
|
+
} from './create-ui'
|
|
9
|
+
import SelectedPart from './selected-part.svelte'
|
|
10
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui'
|
|
11
|
+
import type { UIMessage } from '@tanstack/ai-client'
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
ui,
|
|
15
|
+
message,
|
|
16
|
+
interrupts,
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
ui: UIDescriptor
|
|
20
|
+
message: UIMessage
|
|
21
|
+
interrupts?: ReadonlyArray<ChatUIInterrupt>
|
|
22
|
+
children?: import('svelte').Snippet<[unknown]>
|
|
23
|
+
} = $props()
|
|
24
|
+
|
|
25
|
+
const comps = $derived(getComponentsContext(ui))
|
|
26
|
+
const resolvedInterrupts = $derived(
|
|
27
|
+
interrupts ?? readInterrupts(getChatContext(ui)),
|
|
28
|
+
)
|
|
29
|
+
const selectedParts = $derived(
|
|
30
|
+
messageParts(message, resolvedInterrupts, comps.inlineToolNames),
|
|
31
|
+
)
|
|
32
|
+
const Message = $derived(comps.components.message as any)
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if children}
|
|
36
|
+
{@render children(selectedParts)}
|
|
37
|
+
{:else}
|
|
38
|
+
<Message {message}>
|
|
39
|
+
{#snippet parts()}
|
|
40
|
+
{#each selectedParts as part, index (`${message.id}-${index}`)}
|
|
41
|
+
<SelectedPart {ui} selected={part} />
|
|
42
|
+
{/each}
|
|
43
|
+
{/snippet}
|
|
44
|
+
</Message>
|
|
45
|
+
{/if}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { ChatUIInterrupt } from '@tanstack/ai-client/ui';
|
|
3
|
+
import type { UIMessage } from '@tanstack/ai-client';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
ui: UIDescriptor;
|
|
6
|
+
message: UIMessage;
|
|
7
|
+
interrupts?: ReadonlyArray<ChatUIInterrupt>;
|
|
8
|
+
children?: import('svelte').Snippet<[unknown]>;
|
|
9
|
+
};
|
|
10
|
+
declare const UiMessage: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type UiMessage = ReturnType<typeof UiMessage>;
|
|
12
|
+
export default UiMessage;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getChatContext,
|
|
4
|
+
readInterrupts,
|
|
5
|
+
readMessages,
|
|
6
|
+
type UIDescriptor,
|
|
7
|
+
} from './create-ui'
|
|
8
|
+
import UIMessage from './ui-message.svelte'
|
|
9
|
+
import type { Snippet } from 'svelte'
|
|
10
|
+
import type { UIMessage as UIMessageModel } from '@tanstack/ai-client'
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
ui,
|
|
14
|
+
children,
|
|
15
|
+
}: {
|
|
16
|
+
ui: UIDescriptor
|
|
17
|
+
children?: Snippet<[ReadonlyArray<UIMessageModel>]>
|
|
18
|
+
} = $props()
|
|
19
|
+
|
|
20
|
+
const chat = $derived(getChatContext(ui))
|
|
21
|
+
const messages = $derived(readMessages(chat))
|
|
22
|
+
const interrupts = $derived(readInterrupts(chat))
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{#if children}
|
|
26
|
+
{@render children(messages)}
|
|
27
|
+
{:else}
|
|
28
|
+
{#each messages as message (message.id)}
|
|
29
|
+
<UIMessage {ui} {message} {interrupts} />
|
|
30
|
+
{/each}
|
|
31
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { UIMessage as UIMessageModel } from '@tanstack/ai-client';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
ui: UIDescriptor;
|
|
6
|
+
children?: Snippet<[ReadonlyArray<UIMessageModel>]>;
|
|
7
|
+
};
|
|
8
|
+
declare const UiMessages: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type UiMessages = ReturnType<typeof UiMessages>;
|
|
10
|
+
export default UiMessages;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
getChatContext,
|
|
4
|
+
readInterrupts,
|
|
5
|
+
type UIDescriptor,
|
|
6
|
+
} from './create-ui'
|
|
7
|
+
import { selectMessageUI } from '@tanstack/ai-client/ui'
|
|
8
|
+
import SelectedPart from './selected-part.svelte'
|
|
9
|
+
import type { MessagePart } from '@tanstack/ai-client'
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
ui,
|
|
13
|
+
part,
|
|
14
|
+
}: {
|
|
15
|
+
ui: UIDescriptor
|
|
16
|
+
part: MessagePart
|
|
17
|
+
} = $props()
|
|
18
|
+
|
|
19
|
+
const chat = $derived(getChatContext(ui))
|
|
20
|
+
const selected = $derived(
|
|
21
|
+
selectMessageUI(
|
|
22
|
+
{ id: 'part', role: 'assistant', parts: [part] },
|
|
23
|
+
{ interrupts: readInterrupts(chat), inlineToolNames: [] },
|
|
24
|
+
).parts[0],
|
|
25
|
+
)
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
{#if selected}
|
|
29
|
+
<SelectedPart {ui} {selected} />
|
|
30
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type UIDescriptor } from './create-ui';
|
|
2
|
+
import type { MessagePart } from '@tanstack/ai-client';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
ui: UIDescriptor;
|
|
5
|
+
part: MessagePart;
|
|
6
|
+
};
|
|
7
|
+
declare const UiPart: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type UiPart = ReturnType<typeof UiPart>;
|
|
9
|
+
export default UiPart;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
setUIContext,
|
|
4
|
+
type ChatUIComponents,
|
|
5
|
+
type UIDescriptor,
|
|
6
|
+
} from './create-ui'
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
ui,
|
|
10
|
+
chat,
|
|
11
|
+
components,
|
|
12
|
+
children,
|
|
13
|
+
}: {
|
|
14
|
+
ui: UIDescriptor
|
|
15
|
+
// ponytail: Svelte components are not generic, so ChatUIHost<TOptions> cannot
|
|
16
|
+
// accept a typed createChat() host with tool-approval interrupts.
|
|
17
|
+
chat: any
|
|
18
|
+
components?: ChatUIComponents<unknown>
|
|
19
|
+
children?: import('svelte').Snippet
|
|
20
|
+
} = $props()
|
|
21
|
+
|
|
22
|
+
setUIContext({
|
|
23
|
+
ui,
|
|
24
|
+
chat,
|
|
25
|
+
components: (components ?? ui.components) as never,
|
|
26
|
+
})
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{@render children?.()}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ChatUIComponents, type UIDescriptor } from './create-ui';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
ui: UIDescriptor;
|
|
4
|
+
chat: any;
|
|
5
|
+
components?: ChatUIComponents<unknown>;
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
};
|
|
8
|
+
declare const UiProvider: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type UiProvider = ReturnType<typeof UiProvider>;
|
|
10
|
+
export default UiProvider;
|