@djangocfg/ui-tools 2.1.381 → 2.1.383

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.
Files changed (178) hide show
  1. package/README.md +132 -899
  2. package/dist/ChatRoot-6IZFM5HM.mjs +5 -0
  3. package/dist/{ChatRoot-EJC5Y2YM.cjs.map → ChatRoot-6IZFM5HM.mjs.map} +1 -1
  4. package/dist/ChatRoot-LW4XNIKP.cjs +14 -0
  5. package/dist/{ChatRoot-QOSKJPM6.mjs.map → ChatRoot-LW4XNIKP.cjs.map} +1 -1
  6. package/dist/DictationField-U25MEYAL.mjs +4 -0
  7. package/dist/DictationField-U25MEYAL.mjs.map +1 -0
  8. package/dist/DictationField-XWR5VOID.cjs +13 -0
  9. package/dist/DictationField-XWR5VOID.cjs.map +1 -0
  10. package/dist/{DocsLayout-2YKPXZYO.mjs → DocsLayout-2P3ONDWJ.mjs} +3 -3
  11. package/dist/{DocsLayout-2YKPXZYO.mjs.map → DocsLayout-2P3ONDWJ.mjs.map} +1 -1
  12. package/dist/{DocsLayout-Q4KS3QWW.cjs → DocsLayout-2YZNS5VK.cjs} +8 -8
  13. package/dist/{DocsLayout-Q4KS3QWW.cjs.map → DocsLayout-2YZNS5VK.cjs.map} +1 -1
  14. package/dist/chunk-4PFW7MIJ.cjs +837 -0
  15. package/dist/chunk-4PFW7MIJ.cjs.map +1 -0
  16. package/dist/chunk-C2YN6WEO.mjs +833 -0
  17. package/dist/chunk-C2YN6WEO.mjs.map +1 -0
  18. package/dist/{chunk-XACCHZH2.cjs → chunk-FIRK5CEH.cjs} +42 -4
  19. package/dist/chunk-FIRK5CEH.cjs.map +1 -0
  20. package/dist/{chunk-NWUT327A.mjs → chunk-HIK6BPL7.mjs} +38 -5
  21. package/dist/chunk-HIK6BPL7.mjs.map +1 -0
  22. package/dist/chunk-OZAU3QWD.cjs +2493 -0
  23. package/dist/chunk-OZAU3QWD.cjs.map +1 -0
  24. package/dist/chunk-UWVP6LCW.mjs +2447 -0
  25. package/dist/chunk-UWVP6LCW.mjs.map +1 -0
  26. package/dist/index.cjs +1668 -99
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +1215 -107
  29. package/dist/index.d.ts +1215 -107
  30. package/dist/index.mjs +1555 -50
  31. package/dist/index.mjs.map +1 -1
  32. package/package.json +16 -15
  33. package/src/audio-assets.d.ts +8 -0
  34. package/src/components/markdown/MarkdownMessage/CollapseToggle.tsx +3 -1
  35. package/src/components/markdown/MarkdownMessage/components.tsx +2 -5
  36. package/src/tools/Chat/README.md +347 -530
  37. package/src/tools/Chat/components/Attachments.tsx +6 -1
  38. package/src/tools/Chat/components/ChatRoot.tsx +30 -2
  39. package/src/tools/Chat/components/Composer.tsx +20 -3
  40. package/src/tools/Chat/components/ErrorBanner.tsx +7 -3
  41. package/src/tools/Chat/components/MessageActions.tsx +3 -1
  42. package/src/tools/Chat/components/MessageBubble.tsx +6 -5
  43. package/src/tools/Chat/components/MessageList.tsx +87 -1
  44. package/src/tools/Chat/components/ToolCalls.tsx +21 -3
  45. package/src/tools/Chat/context/ChatProvider.tsx +21 -3
  46. package/src/tools/Chat/core/audio/audioBus.ts +10 -163
  47. package/src/tools/Chat/core/audio/defaults.ts +43 -0
  48. package/src/tools/Chat/core/audio/index.ts +1 -0
  49. package/src/tools/Chat/core/audio/preferences.ts +5 -59
  50. package/src/tools/Chat/core/audio/sounds/error.mp3 +0 -0
  51. package/src/tools/Chat/core/audio/sounds/mention.mp3 +0 -0
  52. package/src/tools/Chat/core/audio/sounds/notification.mp3 +0 -0
  53. package/src/tools/Chat/core/audio/sounds/received.mp3 +0 -0
  54. package/src/tools/Chat/core/audio/sounds/sent.mp3 +0 -0
  55. package/src/tools/Chat/core/audio/sounds/start.mp3 +0 -0
  56. package/src/tools/Chat/core/audio/types.ts +28 -0
  57. package/src/tools/Chat/core/reducer.ts +33 -0
  58. package/src/tools/Chat/core/transport/index.ts +13 -0
  59. package/src/tools/Chat/core/transport/mappers/index.ts +6 -0
  60. package/src/tools/Chat/core/transport/mappers/pydantic-ai.ts +142 -0
  61. package/src/tools/Chat/core/transport/pydantic-ai-transport.ts +208 -0
  62. package/src/tools/Chat/core/transport/sse.ts +18 -5
  63. package/src/tools/Chat/hooks/index.ts +25 -0
  64. package/src/tools/Chat/hooks/useAutoFocusOnStreamEnd.ts +5 -3
  65. package/src/tools/Chat/hooks/useChat.ts +28 -0
  66. package/src/tools/Chat/hooks/useChatAudio.ts +59 -180
  67. package/src/tools/Chat/hooks/useChatDockPrefs.ts +74 -0
  68. package/src/tools/Chat/hooks/useChatReset.ts +70 -0
  69. package/src/tools/Chat/hooks/useChatUnread.ts +87 -0
  70. package/src/tools/Chat/hooks/useFocusOnEmptyClick.ts +111 -0
  71. package/src/tools/Chat/hooks/useVisitorFingerprint.ts +48 -0
  72. package/src/tools/Chat/index.ts +84 -1
  73. package/src/tools/Chat/launcher/ChatDock.tsx +263 -0
  74. package/src/tools/Chat/launcher/ChatFAB.tsx +349 -0
  75. package/src/tools/Chat/launcher/ChatGreeting.tsx +200 -0
  76. package/src/tools/Chat/launcher/ChatHeader.tsx +76 -0
  77. package/src/tools/Chat/launcher/ChatHeaderActionButton.tsx +87 -0
  78. package/src/tools/Chat/launcher/ChatHeaderAudioToggle.tsx +47 -0
  79. package/src/tools/Chat/launcher/ChatHeaderLanguageButton.tsx +179 -0
  80. package/src/tools/Chat/launcher/ChatHeaderModeToggle.tsx +57 -0
  81. package/src/tools/Chat/launcher/ChatHeaderResetButton.tsx +93 -0
  82. package/src/tools/Chat/launcher/ChatLauncher.tsx +321 -0
  83. package/src/tools/Chat/launcher/ChatUnreadPreview.tsx +197 -0
  84. package/src/tools/Chat/launcher/index.ts +46 -0
  85. package/src/tools/Chat/launcher/useChatPresence.ts +44 -0
  86. package/src/tools/Chat/styles/bubbleTokens.ts +71 -0
  87. package/src/tools/Chat/styles/index.ts +16 -0
  88. package/src/tools/Chat/styles/useChatStyles.ts +101 -0
  89. package/src/tools/Chat/types/attachment.ts +25 -0
  90. package/src/tools/Chat/types/config.ts +48 -0
  91. package/src/tools/Chat/types/events.ts +35 -0
  92. package/src/tools/Chat/types/index.ts +34 -0
  93. package/src/tools/Chat/types/labels.ts +38 -0
  94. package/src/tools/Chat/types/message.ts +32 -0
  95. package/src/tools/Chat/types/persona.ts +31 -0
  96. package/src/tools/Chat/types/session.ts +43 -0
  97. package/src/tools/Chat/types/tool-call.ts +17 -0
  98. package/src/tools/Chat/types/transport.ts +28 -0
  99. package/src/tools/Chat/types.ts +5 -240
  100. package/src/tools/MarkdownEditor/MarkdownEditor.tsx +50 -14
  101. package/src/tools/MarkdownEditor/index.ts +1 -1
  102. package/src/tools/SpeechRecognition/README.md +336 -0
  103. package/src/tools/SpeechRecognition/__tests__/ids.test.ts +15 -0
  104. package/src/tools/SpeechRecognition/__tests__/language.test.ts +59 -0
  105. package/src/tools/SpeechRecognition/__tests__/reducer.test.ts +71 -0
  106. package/src/tools/SpeechRecognition/__tests__/transcript.test.ts +52 -0
  107. package/src/tools/SpeechRecognition/components/DevicePicker.tsx +49 -0
  108. package/src/tools/SpeechRecognition/components/DictationButton.tsx +93 -0
  109. package/src/tools/SpeechRecognition/components/EngineBadge.tsx +30 -0
  110. package/src/tools/SpeechRecognition/components/ErrorBanner.tsx +52 -0
  111. package/src/tools/SpeechRecognition/components/LanguagePicker.tsx +63 -0
  112. package/src/tools/SpeechRecognition/components/MicMeter.tsx +63 -0
  113. package/src/tools/SpeechRecognition/components/PushToTalkHint.tsx +51 -0
  114. package/src/tools/SpeechRecognition/components/TranscriptView.tsx +55 -0
  115. package/src/tools/SpeechRecognition/components/index.ts +16 -0
  116. package/src/tools/SpeechRecognition/context/SpeechRecognitionProvider.tsx +47 -0
  117. package/src/tools/SpeechRecognition/context/index.ts +6 -0
  118. package/src/tools/SpeechRecognition/core/audio/defaults.ts +24 -0
  119. package/src/tools/SpeechRecognition/core/engine/external.ts +222 -0
  120. package/src/tools/SpeechRecognition/core/engine/http.ts +147 -0
  121. package/src/tools/SpeechRecognition/core/engine/index.ts +52 -0
  122. package/src/tools/SpeechRecognition/core/engine/mediarecorder.ts +105 -0
  123. package/src/tools/SpeechRecognition/core/engine/websocket.ts +211 -0
  124. package/src/tools/SpeechRecognition/core/engine/webspeech.ts +188 -0
  125. package/src/tools/SpeechRecognition/core/ids.ts +11 -0
  126. package/src/tools/SpeechRecognition/core/index.ts +14 -0
  127. package/src/tools/SpeechRecognition/core/language.ts +78 -0
  128. package/src/tools/SpeechRecognition/core/languages-catalog.ts +229 -0
  129. package/src/tools/SpeechRecognition/core/logger.ts +3 -0
  130. package/src/tools/SpeechRecognition/core/reducer.ts +105 -0
  131. package/src/tools/SpeechRecognition/core/transcript.ts +36 -0
  132. package/src/tools/SpeechRecognition/hooks/index.ts +14 -0
  133. package/src/tools/SpeechRecognition/hooks/useDictation.ts +59 -0
  134. package/src/tools/SpeechRecognition/hooks/useEnginePrefs.ts +15 -0
  135. package/src/tools/SpeechRecognition/hooks/useMicDevices.ts +57 -0
  136. package/src/tools/SpeechRecognition/hooks/useMicLevel.ts +52 -0
  137. package/src/tools/SpeechRecognition/hooks/usePushToTalk.ts +85 -0
  138. package/src/tools/SpeechRecognition/hooks/useResolvedLanguage.ts +28 -0
  139. package/src/tools/SpeechRecognition/hooks/useSpeechLanguageInfo.ts +108 -0
  140. package/src/tools/SpeechRecognition/hooks/useSpeechRecognition.ts +188 -0
  141. package/src/tools/SpeechRecognition/hooks/useVoiceSupport.ts +78 -0
  142. package/src/tools/SpeechRecognition/index.ts +82 -0
  143. package/src/tools/SpeechRecognition/lazy.tsx +19 -0
  144. package/src/tools/SpeechRecognition/store/index.ts +2 -0
  145. package/src/tools/SpeechRecognition/store/prefsStore.ts +54 -0
  146. package/src/tools/SpeechRecognition/types.ts +133 -0
  147. package/src/tools/SpeechRecognition/widgets/DictationField.tsx +105 -0
  148. package/src/tools/SpeechRecognition/widgets/VoiceComposerSlot.tsx +305 -0
  149. package/src/tools/SpeechRecognition/widgets/VoiceMessageRecorder.tsx +88 -0
  150. package/src/tools/SpeechRecognition/widgets/index.ts +6 -0
  151. package/dist/ChatRoot-EJC5Y2YM.cjs +0 -14
  152. package/dist/ChatRoot-QOSKJPM6.mjs +0 -5
  153. package/dist/chunk-NWUT327A.mjs.map +0 -1
  154. package/dist/chunk-QLMKCSR6.mjs +0 -2420
  155. package/dist/chunk-QLMKCSR6.mjs.map +0 -1
  156. package/dist/chunk-SI5RD2GD.cjs +0 -2460
  157. package/dist/chunk-SI5RD2GD.cjs.map +0 -1
  158. package/dist/chunk-XACCHZH2.cjs.map +0 -1
  159. package/src/components/markdown/MarkdownMessage/MarkdownMessage.story.tsx +0 -771
  160. package/src/stories/index.ts +0 -33
  161. package/src/tools/AudioPlayer/AudioPlayer.story.tsx +0 -481
  162. package/src/tools/Chat/Chat.story.tsx +0 -1457
  163. package/src/tools/CodeEditor/CodeEditor.story.tsx +0 -202
  164. package/src/tools/CronScheduler/CronScheduler.story.tsx +0 -300
  165. package/src/tools/Gallery/Gallery.story.tsx +0 -237
  166. package/src/tools/ImageViewer/ImageViewer.story.tsx +0 -85
  167. package/src/tools/JsonForm/JsonForm.story.tsx +0 -350
  168. package/src/tools/JsonTree/JsonTree.story.tsx +0 -141
  169. package/src/tools/LottiePlayer/LottiePlayer.story.tsx +0 -95
  170. package/src/tools/Map/Map.story.tsx +0 -458
  171. package/src/tools/MarkdownEditor/MarkdownEditor.story.tsx +0 -225
  172. package/src/tools/Mermaid/Mermaid.story.tsx +0 -251
  173. package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +0 -230
  174. package/src/tools/PrettyCode/PrettyCode.story.tsx +0 -304
  175. package/src/tools/Tour/Tour.story.tsx +0 -279
  176. package/src/tools/Tree/Tree.story.tsx +0 -620
  177. package/src/tools/Uploader/Uploader.story.tsx +0 -415
  178. package/src/tools/VideoPlayer/VideoPlayer.story.tsx +0 -87
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Role-aware style hooks for chat surfaces.
3
+ *
4
+ * Pure utility hooks — no React state, no side effects, just memoized
5
+ * className strings derived from `bubbleTokens`. They exist so:
6
+ * - components don't import token constants directly (single facade)
7
+ * - "the user-bubble link color" can be changed in one file
8
+ * - tests can mock the hook to assert intent without parsing classNames
9
+ */
10
+
11
+ import { useMemo } from 'react';
12
+
13
+ import {
14
+ ANCHOR,
15
+ BUBBLE_SURFACE,
16
+ DESTRUCTIVE_SURFACE,
17
+ TOGGLE,
18
+ TOOL_CALL,
19
+ type ChatBubbleSurface,
20
+ } from './bubbleTokens';
21
+
22
+ export interface ChatBubbleStyles {
23
+ /** className for the bubble container (background + text + border). */
24
+ surface: string;
25
+ /** className for an inline anchor inside markdown. */
26
+ anchor: string;
27
+ /** className for a secondary inline action (e.g. show more). */
28
+ toggle: string;
29
+ }
30
+
31
+ /**
32
+ * Resolve bubble + content styles for a single message.
33
+ *
34
+ * @param role 'user' | 'assistant' | 'system' (system defaults to assistant styling)
35
+ * @param isError marks the bubble as a failed turn (overrides surface)
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * const { surface, anchor } = useChatBubbleStyles(message.role, !!message.isError);
40
+ * <div className={cn('rounded-2xl px-3.5 py-2', surface)}>…</div>
41
+ * ```
42
+ */
43
+ export function useChatBubbleStyles(
44
+ role: 'user' | 'assistant' | 'system',
45
+ isError: boolean,
46
+ ): ChatBubbleStyles {
47
+ return useMemo(() => {
48
+ const isUser = role === 'user';
49
+ const variant: ChatBubbleSurface = isUser ? 'user' : isError ? 'error' : 'assistant';
50
+ return {
51
+ surface: BUBBLE_SURFACE[variant],
52
+ anchor: isUser ? ANCHOR.user : ANCHOR.assistant,
53
+ toggle: isUser ? TOGGLE.user : TOGGLE.assistant,
54
+ };
55
+ }, [role, isError]);
56
+ }
57
+
58
+ export interface ChatRoleStyles {
59
+ anchor: string;
60
+ toggle: string;
61
+ }
62
+
63
+ /**
64
+ * Lightweight variant when only role matters (no error state, no surface).
65
+ * Use in shared markdown renderers that don't know about bubble background.
66
+ */
67
+ export function useChatRoleStyles(isUser: boolean): ChatRoleStyles {
68
+ return useMemo(
69
+ () => ({
70
+ anchor: isUser ? ANCHOR.user : ANCHOR.assistant,
71
+ toggle: isUser ? TOGGLE.user : TOGGLE.assistant,
72
+ }),
73
+ [isUser],
74
+ );
75
+ }
76
+
77
+ export interface ChatDestructiveStyles {
78
+ banner: string;
79
+ hover: string;
80
+ hoverStrong: string;
81
+ text: string;
82
+ menuItem: string;
83
+ toolErrorText: string;
84
+ }
85
+
86
+ /**
87
+ * Destructive (delete / error) class facade. Hook form keeps the API
88
+ * symmetric with the others; under the hood it returns a frozen object.
89
+ */
90
+ export function useChatDestructiveStyles(): ChatDestructiveStyles {
91
+ return DESTRUCTIVE_STYLES;
92
+ }
93
+
94
+ const DESTRUCTIVE_STYLES: ChatDestructiveStyles = {
95
+ banner: DESTRUCTIVE_SURFACE.banner,
96
+ hover: DESTRUCTIVE_SURFACE.hover,
97
+ hoverStrong: DESTRUCTIVE_SURFACE.hoverStrong,
98
+ text: DESTRUCTIVE_SURFACE.text,
99
+ menuItem: DESTRUCTIVE_SURFACE.menuItem,
100
+ toolErrorText: TOOL_CALL.errorText,
101
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Attachments + sources attached to a chat message.
3
+ */
4
+
5
+ export interface ChatAttachment {
6
+ id: string;
7
+ type: 'image' | 'file' | 'audio' | 'video';
8
+ url: string;
9
+ thumbnailUrl?: string;
10
+ name?: string;
11
+ mimeType?: string;
12
+ sizeBytes?: number;
13
+ status?: 'uploading' | 'ready' | 'error';
14
+ /** 0..1 while uploading. */
15
+ progress?: number;
16
+ /** Extracted text from images (OCR). */
17
+ ocrText?: string;
18
+ }
19
+
20
+ export interface ChatSource {
21
+ title: string;
22
+ url: string;
23
+ snippet?: string;
24
+ chunkIndex?: number;
25
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Top-level chat configuration — placeholder, suggestions, identities, prefs.
3
+ */
4
+
5
+ import type { ChatAssistantContext, ChatUserContext } from './persona';
6
+ import type { ChatLabels } from './labels';
7
+
8
+ export type ChatDisplayMode = 'closed' | 'embedded' | 'floating' | 'sidebar' | 'fullscreen';
9
+
10
+ export interface ChatPrefs {
11
+ /** Submit hotkey for the composer. */
12
+ submitOn?: 'enter' | 'cmd+enter';
13
+ /** UI density. */
14
+ density?: 'comfortable' | 'compact';
15
+ /** Locale forwarded to transport metadata. */
16
+ locale?: string;
17
+ /** Show timestamps on each bubble. */
18
+ showTimestamps?: boolean;
19
+ }
20
+
21
+ export interface ChatConfig {
22
+ /** Window title / aria-label. */
23
+ title?: string;
24
+ /** Composer placeholder. */
25
+ placeholder?: string;
26
+ /** Empty-state greeting. */
27
+ greeting?: string;
28
+ /** Empty-state description. */
29
+ description?: string;
30
+ /** Suggested prompts shown on empty conversation. */
31
+ suggestions?: Array<{ label: string; prompt: string }>;
32
+ /** Locale forwarded to the transport via stream metadata. */
33
+ locale?: string;
34
+ /** Project / chat slug forwarded to the transport. */
35
+ slug?: string;
36
+ /** UI density. Use `prefs.density` for the same effect; this stays for
37
+ * backwards compatibility. */
38
+ density?: 'comfortable' | 'compact';
39
+ /** Identity of the human author. Renders avatar / name on user bubbles
40
+ * and gets stamped on outgoing messages as `message.sender`. */
41
+ user?: ChatUserContext;
42
+ /** Identity of the assistant. Renders avatar / name on assistant bubbles. */
43
+ assistant?: ChatAssistantContext;
44
+ /** UI preferences. */
45
+ prefs?: ChatPrefs;
46
+ /** Visual labels (i18n is the host's job). */
47
+ labels?: Partial<ChatLabels>;
48
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * SSE stream events — the canonical wire shape consumed by the reducer.
3
+ *
4
+ * Backend-specific shapes (e.g. pydantic-AI's `text_delta`) get normalized
5
+ * into this union by `mapPydanticAIEvent` and friends.
6
+ */
7
+
8
+ import type { ChatSource } from './attachment';
9
+
10
+ export type ChatStreamEvent =
11
+ | { type: 'message_start'; messageId: string; sessionId: string }
12
+ | { type: 'resume_start' }
13
+ | { type: 'chunk'; delta: string }
14
+ | { type: 'tool_activity'; tool: string; status: string }
15
+ | {
16
+ type: 'tool_call_start';
17
+ toolId: string;
18
+ name: string;
19
+ input: unknown;
20
+ sourceHostname?: string;
21
+ }
22
+ | { type: 'tool_call_delta'; toolId: string; delta: string }
23
+ | {
24
+ type: 'tool_call_end';
25
+ toolId: string;
26
+ output: unknown;
27
+ status: 'success' | 'error';
28
+ }
29
+ | {
30
+ type: 'message_end';
31
+ tokensIn?: number;
32
+ tokensOut?: number;
33
+ sources?: ChatSource[];
34
+ }
35
+ | { type: 'error'; code: string; message: string };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Public types for the Chat tool — single source of truth.
3
+ *
4
+ * Shapes here are the contract between transport adapters, the reducer,
5
+ * the hooks layer and the components. Keep serializable (no Date, no Map).
6
+ *
7
+ * Organized by domain:
8
+ * persona — identity (role, ChatPersona, user/assistant contexts)
9
+ * tool-call — ChatToolCall
10
+ * attachment — ChatAttachment, ChatSource
11
+ * message — ChatMessage (composes the above)
12
+ * labels — UI strings + DEFAULT_LABELS
13
+ * config — ChatConfig + ChatPrefs + display mode
14
+ * events — ChatStreamEvent SSE union
15
+ * session — Session/history/stream/send option shapes
16
+ * transport — ChatTransport interface
17
+ */
18
+
19
+ export type { ChatRole, ChatPersona, ChatUserContext, ChatAssistantContext } from './persona';
20
+ export type { ChatToolCall } from './tool-call';
21
+ export type { ChatAttachment, ChatSource } from './attachment';
22
+ export type { ChatMessage } from './message';
23
+ export { DEFAULT_LABELS } from './labels';
24
+ export type { ChatLabels } from './labels';
25
+ export type { ChatConfig, ChatPrefs, ChatDisplayMode } from './config';
26
+ export type { ChatStreamEvent } from './events';
27
+ export type {
28
+ CreateSessionOptions,
29
+ SessionInfo,
30
+ HistoryPage,
31
+ StreamOptions,
32
+ SendOptions,
33
+ } from './session';
34
+ export type { ChatTransport } from './transport';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * UI label strings — i18n is the host's job. Pass overrides via
3
+ * `ChatConfig.labels` and merge with `DEFAULT_LABELS`.
4
+ */
5
+
6
+ export interface ChatLabels {
7
+ send: string;
8
+ cancel: string;
9
+ copy: string;
10
+ regenerate: string;
11
+ edit: string;
12
+ delete: string;
13
+ retry: string;
14
+ newChat: string;
15
+ loadMore: string;
16
+ jumpToLatest: string;
17
+ attach: string;
18
+ voice: string;
19
+ errorGeneric: string;
20
+ cancelledSuffix: string;
21
+ }
22
+
23
+ export const DEFAULT_LABELS: ChatLabels = {
24
+ send: 'Send',
25
+ cancel: 'Stop',
26
+ copy: 'Copy',
27
+ regenerate: 'Regenerate',
28
+ edit: 'Edit',
29
+ delete: 'Delete',
30
+ retry: 'Retry',
31
+ newChat: 'New chat',
32
+ loadMore: 'Load more',
33
+ jumpToLatest: 'Jump to latest',
34
+ attach: 'Attach files',
35
+ voice: 'Voice input',
36
+ errorGeneric: 'Something went wrong',
37
+ cancelledSuffix: '[cancelled]',
38
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The atomic unit — a single message in a chat session.
3
+ *
4
+ * Composed of role + content + optional rich-data slots (attachments,
5
+ * sources, tool calls). Serializable: no Date, no Map.
6
+ */
7
+
8
+ import type { ChatAttachment, ChatSource } from './attachment';
9
+ import type { ChatPersona, ChatRole } from './persona';
10
+ import type { ChatToolCall } from './tool-call';
11
+
12
+ export interface ChatMessage {
13
+ id: string;
14
+ role: ChatRole;
15
+ content: string;
16
+ /** epoch ms — serializable. */
17
+ createdAt: number;
18
+ isStreaming?: boolean;
19
+ isError?: boolean;
20
+ /** Bumps on edit so memo keys invalidate. */
21
+ version?: number;
22
+ /** Per-message persona override (multi-user / multi-bot). Falls back to
23
+ * `ChatConfig.user` / `ChatConfig.assistant` when absent. */
24
+ sender?: ChatPersona;
25
+ /** Simple status indicator above message ("Searching knowledge base..."). */
26
+ toolActivity?: string;
27
+ toolCalls?: ChatToolCall[];
28
+ attachments?: ChatAttachment[];
29
+ sources?: ChatSource[];
30
+ tokensIn?: number;
31
+ tokensOut?: number;
32
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Persona — display identity attached to messages and config.
3
+ *
4
+ * Used by `ChatMessage.sender`, `ChatConfig.user`, `ChatConfig.assistant`.
5
+ */
6
+
7
+ export type ChatRole = 'user' | 'assistant' | 'system';
8
+
9
+ export interface ChatPersona {
10
+ /** Display name. */
11
+ name?: string;
12
+ /** Avatar image URL. */
13
+ avatarUrl?: string;
14
+ /** Initials fallback when no avatar. Auto-derived from `name` if absent. */
15
+ initials?: string;
16
+ /** Tooltip / aria description. */
17
+ description?: string;
18
+ }
19
+
20
+ export interface ChatUserContext extends ChatPersona {
21
+ email?: string;
22
+ language?: string;
23
+ role?: string;
24
+ /** Free-form custom data forwarded to transport metadata. */
25
+ custom?: Record<string, unknown>;
26
+ }
27
+
28
+ export interface ChatAssistantContext extends ChatPersona {
29
+ /** Model identifier (gpt-4o, claude-opus, …). */
30
+ model?: string;
31
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Session info + history page shapes returned by transports.
3
+ */
4
+
5
+ import type { ChatAttachment } from './attachment';
6
+ import type { ChatMessage } from './message';
7
+
8
+ export interface CreateSessionOptions {
9
+ metadata?: Record<string, unknown>;
10
+ }
11
+
12
+ export interface SessionInfo {
13
+ sessionId: string;
14
+ /** If the server resumed an existing session, it may return prior messages. */
15
+ messages?: ChatMessage[];
16
+ hasMore?: boolean;
17
+ cursor?: string | null;
18
+ resumed?: boolean;
19
+ /**
20
+ * Optional human-readable title (typically derived from the first
21
+ * user message). Hosts that render a session-list sidebar can read
22
+ * this directly instead of crawling messages. Plan64.
23
+ */
24
+ title?: string;
25
+ }
26
+
27
+ export interface HistoryPage {
28
+ messages: ChatMessage[];
29
+ hasMore: boolean;
30
+ nextCursor: string | null;
31
+ }
32
+
33
+ export interface StreamOptions {
34
+ signal: AbortSignal;
35
+ attachments?: ChatAttachment[];
36
+ metadata?: Record<string, unknown>;
37
+ }
38
+
39
+ export interface SendOptions {
40
+ signal?: AbortSignal;
41
+ attachments?: ChatAttachment[];
42
+ metadata?: Record<string, unknown>;
43
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tool calls — assistant-initiated function/tool invocations during a turn.
3
+ */
4
+
5
+ export interface ChatToolCall {
6
+ id: string;
7
+ name: string;
8
+ input: unknown;
9
+ output?: unknown;
10
+ /** Live buffer accumulated during streaming. Replaced by `output` on completion. */
11
+ streamingText?: string;
12
+ status: 'running' | 'success' | 'error' | 'cancelled';
13
+ startedAt: number;
14
+ endedAt?: number;
15
+ /** Optional grouping label for parallel/fan-out execution. */
16
+ sourceHostname?: string;
17
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Transport interface — what every chat backend adapter implements.
3
+ *
4
+ * Default web implementation lives in `core/transport/http.ts`.
5
+ * Pydantic-AI adapter lives in `core/transport/pydantic-ai-transport.ts`.
6
+ */
7
+
8
+ import type { ChatMessage } from './message';
9
+ import type { ChatStreamEvent } from './events';
10
+ import type {
11
+ CreateSessionOptions,
12
+ HistoryPage,
13
+ SendOptions,
14
+ SessionInfo,
15
+ StreamOptions,
16
+ } from './session';
17
+
18
+ export interface ChatTransport {
19
+ createSession(opts?: CreateSessionOptions): Promise<SessionInfo>;
20
+ loadHistory(sessionId: string, cursor?: string | null, limit?: number): Promise<HistoryPage>;
21
+ stream(
22
+ sessionId: string,
23
+ content: string,
24
+ options: StreamOptions,
25
+ ): AsyncGenerator<ChatStreamEvent, void, void>;
26
+ send(sessionId: string, content: string, options?: SendOptions): Promise<ChatMessage>;
27
+ closeSession(sessionId: string): Promise<void>;
28
+ }
@@ -1,244 +1,9 @@
1
1
  /**
2
- * Public types for the Chat tool.
2
+ * Backwards-compatibility re-export.
3
3
  *
4
- * Shapes here are the contract between transport adapters, the reducer,
5
- * the hooks layer and the components. Keep serializable (no Date, no Map).
4
+ * Types live in `./types/` (one file per domain). Import directly from
5
+ * `@djangocfg/ui-tools/Chat` in new code; this barrel exists so old
6
+ * `import … from '.../types'` paths keep working.
6
7
  */
7
8
 
8
- export type ChatRole = 'user' | 'assistant' | 'system';
9
-
10
- export interface ChatToolCall {
11
- id: string;
12
- name: string;
13
- input: unknown;
14
- output?: unknown;
15
- /** Live buffer accumulated during streaming. Replaced by `output` on completion. */
16
- streamingText?: string;
17
- status: 'running' | 'success' | 'error' | 'cancelled';
18
- startedAt: number;
19
- endedAt?: number;
20
- /** Optional grouping label for parallel/fan-out execution. */
21
- sourceHostname?: string;
22
- }
23
-
24
- export interface ChatAttachment {
25
- id: string;
26
- type: 'image' | 'file' | 'audio' | 'video';
27
- url: string;
28
- thumbnailUrl?: string;
29
- name?: string;
30
- mimeType?: string;
31
- sizeBytes?: number;
32
- status?: 'uploading' | 'ready' | 'error';
33
- /** 0..1 while uploading. */
34
- progress?: number;
35
- /** Extracted text from images (OCR). */
36
- ocrText?: string;
37
- }
38
-
39
- export interface ChatSource {
40
- title: string;
41
- url: string;
42
- snippet?: string;
43
- chunkIndex?: number;
44
- }
45
-
46
- export interface ChatPersona {
47
- /** Display name. */
48
- name?: string;
49
- /** Avatar image URL. */
50
- avatarUrl?: string;
51
- /** Initials fallback when no avatar. Auto-derived from `name` if absent. */
52
- initials?: string;
53
- /** Tooltip / aria description. */
54
- description?: string;
55
- }
56
-
57
- export interface ChatMessage {
58
- id: string;
59
- role: ChatRole;
60
- content: string;
61
- /** epoch ms — serializable. */
62
- createdAt: number;
63
- isStreaming?: boolean;
64
- isError?: boolean;
65
- /** Bumps on edit so memo keys invalidate. */
66
- version?: number;
67
- /** Per-message persona override (multi-user / multi-bot). Falls back to
68
- * `ChatConfig.user` / `ChatConfig.assistant` when absent. */
69
- sender?: ChatPersona;
70
- /** Simple status indicator above message ("Searching knowledge base..."). */
71
- toolActivity?: string;
72
- toolCalls?: ChatToolCall[];
73
- attachments?: ChatAttachment[];
74
- sources?: ChatSource[];
75
- tokensIn?: number;
76
- tokensOut?: number;
77
- }
78
-
79
- export type ChatDisplayMode = 'closed' | 'embedded' | 'floating' | 'sidebar' | 'fullscreen';
80
-
81
- export interface ChatUserContext extends ChatPersona {
82
- email?: string;
83
- language?: string;
84
- role?: string;
85
- /** Free-form custom data forwarded to transport metadata. */
86
- custom?: Record<string, unknown>;
87
- }
88
-
89
- export interface ChatAssistantContext extends ChatPersona {
90
- /** Model identifier (gpt-4o, claude-opus, …). */
91
- model?: string;
92
- }
93
-
94
- export interface ChatPrefs {
95
- /** Submit hotkey for the composer. */
96
- submitOn?: 'enter' | 'cmd+enter';
97
- /** UI density. */
98
- density?: 'comfortable' | 'compact';
99
- /** Locale forwarded to transport metadata. */
100
- locale?: string;
101
- /** Show timestamps on each bubble. */
102
- showTimestamps?: boolean;
103
- }
104
-
105
- export interface ChatConfig {
106
- /** Window title / aria-label. */
107
- title?: string;
108
- /** Composer placeholder. */
109
- placeholder?: string;
110
- /** Empty-state greeting. */
111
- greeting?: string;
112
- /** Empty-state description. */
113
- description?: string;
114
- /** Suggested prompts shown on empty conversation. */
115
- suggestions?: Array<{ label: string; prompt: string }>;
116
- /** Locale forwarded to the transport via stream metadata. */
117
- locale?: string;
118
- /** Project / chat slug forwarded to the transport. */
119
- slug?: string;
120
- /** UI density. Use `prefs.density` for the same effect; this stays for
121
- * backwards compatibility. */
122
- density?: 'comfortable' | 'compact';
123
- /** Identity of the human author. Renders avatar / name on user bubbles
124
- * and gets stamped on outgoing messages as `message.sender`. */
125
- user?: ChatUserContext;
126
- /** Identity of the assistant. Renders avatar / name on assistant bubbles. */
127
- assistant?: ChatAssistantContext;
128
- /** UI preferences. */
129
- prefs?: ChatPrefs;
130
- /** Visual labels (i18n is the host's job). */
131
- labels?: Partial<ChatLabels>;
132
- }
133
-
134
- export interface ChatLabels {
135
- send: string;
136
- cancel: string;
137
- copy: string;
138
- regenerate: string;
139
- edit: string;
140
- delete: string;
141
- retry: string;
142
- newChat: string;
143
- loadMore: string;
144
- jumpToLatest: string;
145
- attach: string;
146
- voice: string;
147
- errorGeneric: string;
148
- cancelledSuffix: string;
149
- }
150
-
151
- export const DEFAULT_LABELS: ChatLabels = {
152
- send: 'Send',
153
- cancel: 'Stop',
154
- copy: 'Copy',
155
- regenerate: 'Regenerate',
156
- edit: 'Edit',
157
- delete: 'Delete',
158
- retry: 'Retry',
159
- newChat: 'New chat',
160
- loadMore: 'Load more',
161
- jumpToLatest: 'Jump to latest',
162
- attach: 'Attach files',
163
- voice: 'Voice input',
164
- errorGeneric: 'Something went wrong',
165
- cancelledSuffix: '[cancelled]',
166
- };
167
-
168
- // ---- Transport ------------------------------------------------------------
169
-
170
- export interface CreateSessionOptions {
171
- metadata?: Record<string, unknown>;
172
- }
173
-
174
- export interface SessionInfo {
175
- sessionId: string;
176
- /** If the server resumed an existing session, it may return prior messages. */
177
- messages?: ChatMessage[];
178
- hasMore?: boolean;
179
- cursor?: string | null;
180
- resumed?: boolean;
181
- /**
182
- * Optional human-readable title (typically derived from the first
183
- * user message). Hosts that render a session-list sidebar can read
184
- * this directly instead of crawling messages. Plan64.
185
- */
186
- title?: string;
187
- }
188
-
189
- export interface HistoryPage {
190
- messages: ChatMessage[];
191
- hasMore: boolean;
192
- nextCursor: string | null;
193
- }
194
-
195
- export interface StreamOptions {
196
- signal: AbortSignal;
197
- attachments?: ChatAttachment[];
198
- metadata?: Record<string, unknown>;
199
- }
200
-
201
- export interface SendOptions {
202
- signal?: AbortSignal;
203
- attachments?: ChatAttachment[];
204
- metadata?: Record<string, unknown>;
205
- }
206
-
207
- export type ChatStreamEvent =
208
- | { type: 'message_start'; messageId: string; sessionId: string }
209
- | { type: 'resume_start' }
210
- | { type: 'chunk'; delta: string }
211
- | { type: 'tool_activity'; tool: string; status: string }
212
- | {
213
- type: 'tool_call_start';
214
- toolId: string;
215
- name: string;
216
- input: unknown;
217
- sourceHostname?: string;
218
- }
219
- | { type: 'tool_call_delta'; toolId: string; delta: string }
220
- | {
221
- type: 'tool_call_end';
222
- toolId: string;
223
- output: unknown;
224
- status: 'success' | 'error';
225
- }
226
- | {
227
- type: 'message_end';
228
- tokensIn?: number;
229
- tokensOut?: number;
230
- sources?: ChatSource[];
231
- }
232
- | { type: 'error'; code: string; message: string };
233
-
234
- export interface ChatTransport {
235
- createSession(opts?: CreateSessionOptions): Promise<SessionInfo>;
236
- loadHistory(sessionId: string, cursor?: string | null, limit?: number): Promise<HistoryPage>;
237
- stream(
238
- sessionId: string,
239
- content: string,
240
- options: StreamOptions,
241
- ): AsyncGenerator<ChatStreamEvent, void, void>;
242
- send(sessionId: string, content: string, options?: SendOptions): Promise<ChatMessage>;
243
- closeSession(sessionId: string): Promise<void>;
244
- }
9
+ export * from './types/index';