orchid-ai 1.3.0 → 1.3.6

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/README.md CHANGED
@@ -119,6 +119,14 @@ npx orchid-generate-schemas init --verbose
119
119
 
120
120
  See [Schema Generation Guide](docs/SCHEMA_GENERATION.md) for detailed usage.
121
121
 
122
+ ## Publishing & `orchid-ai/headless`
123
+
124
+ `npm publish` and `npm pack` run **`prepack`**, which executes **`npm run build`** and **`npm run verify-dist`**. That guarantees the registry tarball includes **`dist/headless.*`**, **`dist/server/*`**, and the main bundle — required for **`import … from 'orchid-ai/headless'`** and **`orchid-ai/server`**.
125
+
126
+ If you link this repo with **`file:../…`**, run **`npm run build`** in the package after changes so `dist/` is present.
127
+
128
+ See [Headless usage](docs/HEADLESS.md) for MUI / hooks-only integration.
129
+
122
130
  ## Documentation
123
131
 
124
132
  - [**Schema Generation**](docs/SCHEMA_GENERATION.md)
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { type IconName } from './Icon';
3
- import { CommandTheme, ChatMessage, ModelInfo, ChatTheme, ServerConfig } from '../types/types';
3
+ import { CommandTheme, CommandSuggestion, ChatMessage, ModelInfo, ChatTheme, ServerConfig } from '../types/types';
4
4
  interface ChatPanelProps {
5
5
  isOpen: boolean;
6
6
  setIsOpen?: (isOpen: boolean) => void;
@@ -53,6 +53,13 @@ interface ChatPanelProps {
53
53
  headerIcon?: IconName | React.ReactElement;
54
54
  headerTitle?: string;
55
55
  headerSubtitle?: string;
56
+ /** When set, replaces default behavior (setFormState + onNavigate + onClose) for command suggestions. */
57
+ onSuggestionSelect?: (s: CommandSuggestion) => void;
58
+ /**
59
+ * Applied to the full-screen modal root so the chat stacks above app chrome that uses high z-index
60
+ * (e.g. MUI AppBar ~1100, custom sidebars ~999). Default Tailwind z-50 is too low for many shells.
61
+ */
62
+ overlayZIndex?: number;
56
63
  }
57
64
  /**
58
65
  * ChatPanel component
@@ -91,7 +98,7 @@ showHistory, // Default to hidden
91
98
  showProfileBubbles, // Default to hidden
92
99
  modalPosition, // Default to left position
93
100
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features, showFloatingButton, floatingButtonIcon, floatingButtonPosition, floatingButtonSize, floatingButtonClassName, chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon, // Default to bot icon
94
- headerTitle, headerSubtitle, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
101
+ headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
95
102
  /**
96
103
  * ChatInput component
97
104
  * @param query - The current query
@@ -118,6 +125,7 @@ type FloatingChatButtonProps = {
118
125
  className?: string;
119
126
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
120
127
  size?: 'sm' | 'md' | 'lg';
128
+ zIndex?: number;
121
129
  };
122
130
  /**
123
131
  * FloatingChatButton component
@@ -128,5 +136,5 @@ type FloatingChatButtonProps = {
128
136
  * @param position - Position of the floating button
129
137
  * @param size - Size of the floating button
130
138
  */
131
- export declare function FloatingChatButton({ onClick, theme, icon, className, position, size, }: FloatingChatButtonProps): import("react/jsx-runtime").JSX.Element;
139
+ export declare function FloatingChatButton({ onClick, theme, icon, className, position, size, zIndex: floatingZIndex, }: FloatingChatButtonProps): import("react/jsx-runtime").JSX.Element;
132
140
  export {};
@@ -72,5 +72,5 @@ interface ConversationProps {
72
72
  * @param autoScroll - Whether to auto-scroll to bottom on new messages
73
73
  * @param maxHeight - Maximum height of the conversation container
74
74
  */
75
- export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, setFormState, onNavigate, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
75
+ export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
76
76
  export {};
@@ -11,6 +11,6 @@ export declare class ErrorBoundary extends Component<Props, State> {
11
11
  constructor(props: Props);
12
12
  static getDerivedStateFromError(error: Error): State;
13
13
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
14
- render(): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | null | undefined;
14
+ render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
15
15
  }
16
16
  export {};
@@ -10,6 +10,7 @@ const commandTrainingRules = {
10
10
  components: {
11
11
  patterns: {
12
12
  // React component patterns
13
+ // Has /g for matchAll in training.ts; do not use String.match(componentName) (groups break).
13
14
  componentName: /(?:export\s+)?(?:function|const)\s+(\w+)(?:\s*<[^>]*>)?\s*[=(]/g,
14
15
  props: /interface\s+(\w+)Props\s*{([^}]*)}/g,
15
16
  state: /useState<([^>]*)>/g,
@@ -34,7 +35,8 @@ const commandTrainingRules = {
34
35
  schemas: {
35
36
  patterns: {
36
37
  // Monastery schema patterns - updated for actual file format
37
- modelName: /\/\/\s*(\w+)\s+model\s+for\s+monastery/g,
38
+ // No /g: training.ts uses String.match(); with g, capture groups are omitted and modelName is always lost.
39
+ modelName: /\/\/\s*(\w+)\s+model\s+for\s+monastery/,
38
40
  fields: /fields:\s*{([^}]*)}/g,
39
41
  fieldDefinitions: /(\w+):\s*{\s*(?:required:\s*(true|false),?\s*)?type:\s*['"]([^'"]+)['"](?:,\s*required:\s*(true|false))?(?:,\s*default:\s*[^,}]+)?/g,
40
42
  indexes: /indexes:\s*\[([^\]]*)\]/g,
@@ -557,6 +559,7 @@ class CommandTrainingCollector {
557
559
  if (content.formFields?.length > 0) {
558
560
  const form = {
559
561
  name: content.componentName || 'Unknown Form',
562
+ sourceFile: path.relative(this.rootDir, component.filePath),
560
563
  purpose: `Form component for data entry`,
561
564
  fields: content.formFields.map((fieldName) => ({
562
565
  name: fieldName,
@@ -685,12 +688,15 @@ class CommandTrainingCollector {
685
688
  guessEntityFromComponent(componentName) {
686
689
  if (!componentName)
687
690
  return 'Unknown';
688
- // Simple heuristic: remove common suffixes
691
+ // Strip common create/edit wrappers, then UI suffixes (order matters)
689
692
  const cleaned = componentName
693
+ .replace(/^(?:Create|Edit|View|New|Batch)/i, '')
690
694
  .replace(/Form$/, '')
695
+ .replace(/Modal$/, '')
696
+ .replace(/Drawer$/, '')
697
+ .replace(/Dialog$/, '')
691
698
  .replace(/Page$/, '')
692
- .replace(/Component$/, '')
693
- .replace(/Modal$/, '');
699
+ .replace(/Component$/, '');
694
700
  return cleaned || 'Unknown';
695
701
  }
696
702
  guessEntitiesFromComponent(content) {
@@ -804,7 +810,7 @@ class CommandTrainingCollector {
804
810
  this.log(`❌ Error expanding pattern "${pattern}":`, err.message);
805
811
  }
806
812
  }
807
- return expandedPaths;
813
+ return [...new Set(expandedPaths)];
808
814
  }
809
815
  extractFileInfo(fieldName, content) {
810
816
  switch (fieldName) {
@@ -848,11 +854,22 @@ class CommandTrainingCollector {
848
854
  hooks: [],
849
855
  eventHandlers: [],
850
856
  };
851
- // Extract component name
852
- const componentMatch = content.match(patterns.componentName);
853
- if (componentMatch) {
854
- result.componentName = componentMatch[1];
855
- }
857
+ // Do not use String.match() on patterns.componentName — it has /g, so match[1] is the *second*
858
+ // full match, not capture group 1 (yields strings like `const CustomerForm =`).
859
+ const declRe = /(?:export\s+)?(?:function|const)\s+(\w+)(?:\s*<[^>]*>)?\s*[=(]/g;
860
+ const declNames = [];
861
+ for (const m of content.matchAll(declRe)) {
862
+ declNames.push(m[1]);
863
+ }
864
+ const isLikelyComponentSymbol = (n) => /^[A-Z]/.test(n) &&
865
+ !/^use[A-Z]/.test(n) &&
866
+ !/^Styled/i.test(n);
867
+ const preferred = [...declNames].reverse().find((n) => isLikelyComponentSymbol(n) &&
868
+ (/(?:Form|Modal|Drawer|Dialog)$/.test(n) ||
869
+ /^FormStep/i.test(n) ||
870
+ (n.includes('Form') && n.length > 4)));
871
+ const fallback = [...declNames].reverse().find(isLikelyComponentSymbol);
872
+ result.componentName = preferred ?? fallback ?? null;
856
873
  // Extract props interfaces
857
874
  const propsMatches = content.matchAll(patterns.props);
858
875
  for (const match of propsMatches) {
@@ -887,6 +904,7 @@ class CommandTrainingCollector {
887
904
  for (const match of fieldMatches) {
888
905
  result.formFields.push(match[1]);
889
906
  }
907
+ result.formFields = [...new Set(result.formFields)];
890
908
  // Extract imports
891
909
  const importMatches = content.matchAll(patterns.imports);
892
910
  for (const match of importMatches) {
@@ -1635,6 +1653,7 @@ class SchemaGenerator extends CommandTrainingCollector {
1635
1653
  };
1636
1654
  this.log(` ✅ Generated schema with ${Object.keys(properties).length} properties`);
1637
1655
  }
1656
+ this.mergeFormUiFieldsIntoEntitySchemas(trainingData, schemas);
1638
1657
  // If no entities found, try to extract from components
1639
1658
  if (Object.keys(schemas).length === 0) {
1640
1659
  this.log(' ⚠️ No entities found in training data, extracting from components...');
@@ -1642,6 +1661,87 @@ class SchemaGenerator extends CommandTrainingCollector {
1642
1661
  }
1643
1662
  return schemas;
1644
1663
  }
1664
+ /**
1665
+ * Merge `name="..."` fields collected from UI forms/modals into existing entity schemas
1666
+ * (server models stay canonical; this adds frontend surface hints).
1667
+ * Optional `customTrainingData.options.formEntityHints`: map form component name -> schema entity key.
1668
+ * Optional `formEntityPathPatterns`: `{ includes, entity }` — first match on `form.sourceFile` wins
1669
+ * (disambiguates reused names like `FormStepDetails` in different feature folders).
1670
+ */
1671
+ mergeFormUiFieldsIntoEntitySchemas(trainingData, schemas) {
1672
+ const forms = trainingData.customTrainingData?.structuredData?.components?.forms || [];
1673
+ if (!forms.length || !Object.keys(schemas).length)
1674
+ return;
1675
+ const hints = (trainingData.customTrainingData?.options?.formEntityHints || {});
1676
+ const pathPatterns = (trainingData.customTrainingData?.options?.formEntityPathPatterns ||
1677
+ []);
1678
+ /** Short UI stems that don't match lowered model names */
1679
+ const STEM_ALIASES = {
1680
+ hs: 'hsreport',
1681
+ incident: 'incidentreport',
1682
+ };
1683
+ const schemaKeys = new Set(Object.keys(schemas));
1684
+ const resolveKey = (form) => {
1685
+ if (form.sourceFile) {
1686
+ for (const p of pathPatterns) {
1687
+ if (!p?.includes || !p?.entity)
1688
+ continue;
1689
+ if (form.sourceFile.includes(p.includes)) {
1690
+ const k = p.entity.toLowerCase();
1691
+ if (schemaKeys.has(k))
1692
+ return k;
1693
+ }
1694
+ }
1695
+ }
1696
+ const tryKey = (raw) => {
1697
+ if (!raw)
1698
+ return undefined;
1699
+ const mapped = hints[raw];
1700
+ const stem = raw
1701
+ .replace(/^(?:Create|Edit|View|New|Batch)/i, '')
1702
+ .replace(/(?:Form|Modal|Drawer|Dialog)$/i, '');
1703
+ const stemLc = stem.toLowerCase();
1704
+ const alias = STEM_ALIASES[stemLc];
1705
+ if (alias && schemaKeys.has(alias))
1706
+ return alias;
1707
+ const candidates = [
1708
+ (mapped || raw).toLowerCase(),
1709
+ stemLc,
1710
+ ];
1711
+ for (const c of candidates) {
1712
+ if (c && schemaKeys.has(c))
1713
+ return c;
1714
+ }
1715
+ return undefined;
1716
+ };
1717
+ return tryKey(form.name) || tryKey(form.relatedEntity) || undefined;
1718
+ };
1719
+ let mergedForms = 0;
1720
+ let mergedFields = 0;
1721
+ for (const form of forms) {
1722
+ const entityKey = resolveKey(form);
1723
+ if (!entityKey)
1724
+ continue;
1725
+ const gen = schemas[entityKey];
1726
+ if (!gen?.schema?.properties)
1727
+ continue;
1728
+ const props = gen.schema.properties;
1729
+ for (const f of form.fields || []) {
1730
+ const n = f?.name;
1731
+ if (!n || typeof n !== 'string' || props[n])
1732
+ continue;
1733
+ props[n] = {
1734
+ type: 'string',
1735
+ description: `UI form field (from ${form.name}). Cross-check server model; may overlap sharing/base shapes.`,
1736
+ };
1737
+ mergedFields += 1;
1738
+ }
1739
+ mergedForms += 1;
1740
+ }
1741
+ if (mergedForms > 0) {
1742
+ this.log(`\n📎 Merged UI form fields into ${mergedForms} entity schema(s) (+${mergedFields} properties)`);
1743
+ }
1744
+ }
1645
1745
  /**
1646
1746
  * Extract schemas from component analysis if no explicit entities found
1647
1747
  */
@@ -1955,6 +2055,9 @@ class SchemaGenerator extends CommandTrainingCollector {
1955
2055
  * Map training data field types to JSON Schema types
1956
2056
  */
1957
2057
  mapFieldType(type) {
2058
+ if (type == null || typeof type !== 'string') {
2059
+ return 'string';
2060
+ }
1958
2061
  const typeMap = {
1959
2062
  string: 'string',
1960
2063
  number: 'number',
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Headless API — streaming hooks, model switching, and shared types/constants
3
+ * without Tailwind-based components. Build your UI with MUI, plain CSS, etc.
4
+ *
5
+ * @example
6
+ * import { useStreamingAI, useModelSwitcher } from 'orchid-ai/headless';
7
+ */
8
+ export { useStreamingAI } from './hooks/useStreamingAI';
9
+ export type { StreamingModelSelection } from './hooks/useStreamingAI';
10
+ export { useSuggestions, useDebouncedSuggestions, } from './hooks/useSuggestions';
11
+ export { useResolvedDefaultModel } from './hooks/useResolvedDefaultModel';
12
+ export { useModelSwitcher } from './hooks/useModelSwitcher';
13
+ export { mergeWithAi } from './utils';
14
+ export { useAiMerge } from './hooks/useAiMerge';
15
+ export { ErrorBoundary } from './components/ErrorBoundary';
16
+ export { DEFAULT_CONFIG, DEFAULT_MODELS } from './constants';
17
+ export { defaultTheme as defaultCommandTheme } from './constants';
18
+ export { defaultDarkTheme, defaultLightTheme } from './constants';
19
+ export type { CommandConfig, TrainingData, AIProvider, CommandTheme, CommandSuggestion, CommandPopupProps, ChatMessage, ChatTheme, AIStatus, Action, ModelInfo, ServerConfig, ClientConfig, SchemaDefinition, SchemaProperty, ContextualServiceConfig, ContextualRequest, ModelCapabilities, MessageContent, TextContent, SuggestionsContent, LoadingSuggestionsContent, } from './types/types';
@@ -1,5 +1,5 @@
1
1
  import { ChatMessage, ModelCapabilities, ServerConfig } from '../types/types';
2
- interface ModelSelection {
2
+ export interface StreamingModelSelection {
3
3
  provider: string;
4
4
  model?: string;
5
5
  tier?: 'fast' | 'balanced' | 'powerful';
@@ -13,7 +13,7 @@ export declare function useStreamingAI({ userId, serverConfig, formData, chats:
13
13
  setChats?: React.Dispatch<React.SetStateAction<Record<string, ChatMessage[]>>>;
14
14
  currentChatId?: string;
15
15
  setCurrentChatId?: React.Dispatch<React.SetStateAction<string>>;
16
- modelSelection?: ModelSelection;
16
+ modelSelection?: StreamingModelSelection;
17
17
  onUsageTracked?: (tokens: number, computeUnits: number) => void;
18
18
  chatLevel?: 'full' | 'basic' | 'none';
19
19
  additionalContext?: string | Record<string, unknown>;
@@ -27,4 +27,3 @@ export declare function useStreamingAI({ userId, serverConfig, formData, chats:
27
27
  newChat: () => void;
28
28
  switchChat: (chatId: string) => void;
29
29
  };
30
- export {};
@@ -1,4 +1,6 @@
1
+ import './orchid-chat.css';
1
2
  export { useStreamingAI } from './hooks/useStreamingAI';
3
+ export type { StreamingModelSelection } from './hooks/useStreamingAI';
2
4
  export { useSuggestions, useDebouncedSuggestions, } from './hooks/useSuggestions';
3
5
  export { useResolvedDefaultModel } from './hooks/useResolvedDefaultModel';
4
6
  export { ChatPanel } from './components/ChatPanel';
@@ -55,6 +55,14 @@ export declare class SchemaGenerator extends CommandTrainingCollector {
55
55
  * Generate schemas from collected training data
56
56
  */
57
57
  private generateSchemas;
58
+ /**
59
+ * Merge `name="..."` fields collected from UI forms/modals into existing entity schemas
60
+ * (server models stay canonical; this adds frontend surface hints).
61
+ * Optional `customTrainingData.options.formEntityHints`: map form component name -> schema entity key.
62
+ * Optional `formEntityPathPatterns`: `{ includes, entity }` — first match on `form.sourceFile` wins
63
+ * (disambiguates reused names like `FormStepDetails` in different feature folders).
64
+ */
65
+ private mergeFormUiFieldsIntoEntitySchemas;
58
66
  /**
59
67
  * Extract schemas from component analysis if no explicit entities found
60
68
  */
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { type IconName } from './Icon';
3
- import { CommandTheme, ChatMessage, ModelInfo, ChatTheme, ServerConfig } from '../types/types';
3
+ import { CommandTheme, CommandSuggestion, ChatMessage, ModelInfo, ChatTheme, ServerConfig } from '../types/types';
4
4
  interface ChatPanelProps {
5
5
  isOpen: boolean;
6
6
  setIsOpen?: (isOpen: boolean) => void;
@@ -53,6 +53,13 @@ interface ChatPanelProps {
53
53
  headerIcon?: IconName | React.ReactElement;
54
54
  headerTitle?: string;
55
55
  headerSubtitle?: string;
56
+ /** When set, replaces default behavior (setFormState + onNavigate + onClose) for command suggestions. */
57
+ onSuggestionSelect?: (s: CommandSuggestion) => void;
58
+ /**
59
+ * Applied to the full-screen modal root so the chat stacks above app chrome that uses high z-index
60
+ * (e.g. MUI AppBar ~1100, custom sidebars ~999). Default Tailwind z-50 is too low for many shells.
61
+ */
62
+ overlayZIndex?: number;
56
63
  }
57
64
  /**
58
65
  * ChatPanel component
@@ -91,7 +98,7 @@ showHistory, // Default to hidden
91
98
  showProfileBubbles, // Default to hidden
92
99
  modalPosition, // Default to left position
93
100
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features, showFloatingButton, floatingButtonIcon, floatingButtonPosition, floatingButtonSize, floatingButtonClassName, chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon, // Default to bot icon
94
- headerTitle, headerSubtitle, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
101
+ headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
95
102
  /**
96
103
  * ChatInput component
97
104
  * @param query - The current query
@@ -118,6 +125,7 @@ type FloatingChatButtonProps = {
118
125
  className?: string;
119
126
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
120
127
  size?: 'sm' | 'md' | 'lg';
128
+ zIndex?: number;
121
129
  };
122
130
  /**
123
131
  * FloatingChatButton component
@@ -128,5 +136,5 @@ type FloatingChatButtonProps = {
128
136
  * @param position - Position of the floating button
129
137
  * @param size - Size of the floating button
130
138
  */
131
- export declare function FloatingChatButton({ onClick, theme, icon, className, position, size, }: FloatingChatButtonProps): import("react/jsx-runtime").JSX.Element;
139
+ export declare function FloatingChatButton({ onClick, theme, icon, className, position, size, zIndex: floatingZIndex, }: FloatingChatButtonProps): import("react/jsx-runtime").JSX.Element;
132
140
  export {};
@@ -72,5 +72,5 @@ interface ConversationProps {
72
72
  * @param autoScroll - Whether to auto-scroll to bottom on new messages
73
73
  * @param maxHeight - Maximum height of the conversation container
74
74
  */
75
- export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, setFormState, onNavigate, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
75
+ export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
76
76
  export {};
@@ -11,6 +11,6 @@ export declare class ErrorBoundary extends Component<Props, State> {
11
11
  constructor(props: Props);
12
12
  static getDerivedStateFromError(error: Error): State;
13
13
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
14
- render(): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | null | undefined;
14
+ render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
15
15
  }
16
16
  export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Headless API — streaming hooks, model switching, and shared types/constants
3
+ * without Tailwind-based components. Build your UI with MUI, plain CSS, etc.
4
+ *
5
+ * @example
6
+ * import { useStreamingAI, useModelSwitcher } from 'orchid-ai/headless';
7
+ */
8
+ export { useStreamingAI } from './hooks/useStreamingAI';
9
+ export type { StreamingModelSelection } from './hooks/useStreamingAI';
10
+ export { useSuggestions, useDebouncedSuggestions, } from './hooks/useSuggestions';
11
+ export { useResolvedDefaultModel } from './hooks/useResolvedDefaultModel';
12
+ export { useModelSwitcher } from './hooks/useModelSwitcher';
13
+ export { mergeWithAi } from './utils';
14
+ export { useAiMerge } from './hooks/useAiMerge';
15
+ export { ErrorBoundary } from './components/ErrorBoundary';
16
+ export { DEFAULT_CONFIG, DEFAULT_MODELS } from './constants';
17
+ export { defaultTheme as defaultCommandTheme } from './constants';
18
+ export { defaultDarkTheme, defaultLightTheme } from './constants';
19
+ export type { CommandConfig, TrainingData, AIProvider, CommandTheme, CommandSuggestion, CommandPopupProps, ChatMessage, ChatTheme, AIStatus, Action, ModelInfo, ServerConfig, ClientConfig, SchemaDefinition, SchemaProperty, ContextualServiceConfig, ContextualRequest, ModelCapabilities, MessageContent, TextContent, SuggestionsContent, LoadingSuggestionsContent, } from './types/types';