@tambo-ai/react 0.72.0 → 0.73.1

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 (151) hide show
  1. package/dist/mcp/mcp-hooks.d.ts +4 -0
  2. package/dist/mcp/mcp-hooks.d.ts.map +1 -1
  3. package/dist/mcp/mcp-hooks.js +4 -0
  4. package/dist/mcp/mcp-hooks.js.map +1 -1
  5. package/dist/providers/tambo-provider.d.ts +3 -0
  6. package/dist/providers/tambo-provider.d.ts.map +1 -1
  7. package/dist/providers/tambo-provider.js +3 -0
  8. package/dist/providers/tambo-provider.js.map +1 -1
  9. package/dist/util/resource-content-resolver.d.ts.map +1 -1
  10. package/dist/util/resource-content-resolver.js +2 -0
  11. package/dist/util/resource-content-resolver.js.map +1 -1
  12. package/dist/v1/hooks/use-tambo-v1-messages.test.js +22 -9
  13. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  14. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
  15. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  16. package/dist/v1/hooks/use-tambo-v1-send-message.js +9 -2
  17. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  18. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
  19. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  20. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
  21. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
  22. package/dist/v1/hooks/use-tambo-v1-suggestions.js +152 -0
  23. package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
  24. package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
  25. package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
  26. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +511 -0
  27. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
  28. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
  29. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
  30. package/dist/v1/hooks/use-tambo-v1-thread-input.js +7 -67
  31. package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
  32. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +201 -72
  33. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  34. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
  35. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  36. package/dist/v1/hooks/use-tambo-v1-thread-list.js +2 -2
  37. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  38. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
  39. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  40. package/dist/v1/hooks/use-tambo-v1.test.js +16 -7
  41. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
  42. package/dist/v1/index.d.ts +22 -13
  43. package/dist/v1/index.d.ts.map +1 -1
  44. package/dist/v1/index.js +31 -39
  45. package/dist/v1/index.js.map +1 -1
  46. package/dist/v1/providers/tambo-v1-provider.d.ts +27 -9
  47. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  48. package/dist/v1/providers/tambo-v1-provider.js +22 -11
  49. package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
  50. package/dist/v1/providers/tambo-v1-provider.test.js +27 -10
  51. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
  52. package/dist/v1/providers/tambo-v1-stream-context.d.ts +19 -10
  53. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  54. package/dist/v1/providers/tambo-v1-stream-context.js +43 -53
  55. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
  56. package/dist/v1/providers/tambo-v1-stream-context.test.js +94 -19
  57. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  58. package/dist/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
  59. package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
  60. package/dist/v1/providers/tambo-v1-stub-provider.js +212 -0
  61. package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -0
  62. package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
  63. package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
  64. package/dist/v1/providers/tambo-v1-stub-provider.test.js +162 -0
  65. package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
  66. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
  67. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
  68. package/dist/v1/providers/tambo-v1-thread-input-provider.js +191 -0
  69. package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
  70. package/dist/v1/utils/component-renderer.d.ts +15 -67
  71. package/dist/v1/utils/component-renderer.d.ts.map +1 -1
  72. package/dist/v1/utils/component-renderer.js +3 -149
  73. package/dist/v1/utils/component-renderer.js.map +1 -1
  74. package/dist/v1/utils/component-renderer.test.js +15 -350
  75. package/dist/v1/utils/component-renderer.test.js.map +1 -1
  76. package/esm/mcp/mcp-hooks.d.ts +4 -0
  77. package/esm/mcp/mcp-hooks.d.ts.map +1 -1
  78. package/esm/mcp/mcp-hooks.js +4 -0
  79. package/esm/mcp/mcp-hooks.js.map +1 -1
  80. package/esm/providers/tambo-provider.d.ts +3 -0
  81. package/esm/providers/tambo-provider.d.ts.map +1 -1
  82. package/esm/providers/tambo-provider.js +3 -0
  83. package/esm/providers/tambo-provider.js.map +1 -1
  84. package/esm/util/resource-content-resolver.d.ts.map +1 -1
  85. package/esm/util/resource-content-resolver.js +2 -0
  86. package/esm/util/resource-content-resolver.js.map +1 -1
  87. package/esm/v1/hooks/use-tambo-v1-messages.test.js +22 -9
  88. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  89. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
  90. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  91. package/esm/v1/hooks/use-tambo-v1-send-message.js +9 -2
  92. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  93. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
  94. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  95. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
  96. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
  97. package/esm/v1/hooks/use-tambo-v1-suggestions.js +149 -0
  98. package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
  99. package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
  100. package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
  101. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +506 -0
  102. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
  103. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
  104. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
  105. package/esm/v1/hooks/use-tambo-v1-thread-input.js +5 -66
  106. package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
  107. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +199 -73
  108. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  109. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
  110. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  111. package/esm/v1/hooks/use-tambo-v1-thread-list.js +2 -2
  112. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  113. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
  114. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  115. package/esm/v1/hooks/use-tambo-v1.test.js +16 -7
  116. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
  117. package/esm/v1/index.d.ts +22 -13
  118. package/esm/v1/index.d.ts.map +1 -1
  119. package/esm/v1/index.js +23 -18
  120. package/esm/v1/index.js.map +1 -1
  121. package/esm/v1/providers/tambo-v1-provider.d.ts +27 -9
  122. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  123. package/esm/v1/providers/tambo-v1-provider.js +20 -10
  124. package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
  125. package/esm/v1/providers/tambo-v1-provider.test.js +28 -11
  126. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
  127. package/esm/v1/providers/tambo-v1-stream-context.d.ts +19 -10
  128. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  129. package/esm/v1/providers/tambo-v1-stream-context.js +44 -54
  130. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
  131. package/esm/v1/providers/tambo-v1-stream-context.test.js +95 -20
  132. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  133. package/esm/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
  134. package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
  135. package/esm/v1/providers/tambo-v1-stub-provider.js +176 -0
  136. package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -0
  137. package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
  138. package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
  139. package/esm/v1/providers/tambo-v1-stub-provider.test.js +157 -0
  140. package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
  141. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
  142. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
  143. package/esm/v1/providers/tambo-v1-thread-input-provider.js +153 -0
  144. package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
  145. package/esm/v1/utils/component-renderer.d.ts +15 -67
  146. package/esm/v1/utils/component-renderer.d.ts.map +1 -1
  147. package/esm/v1/utils/component-renderer.js +4 -146
  148. package/esm/v1/utils/component-renderer.js.map +1 -1
  149. package/esm/v1/utils/component-renderer.test.js +16 -351
  150. package/esm/v1/utils/component-renderer.test.js.map +1 -1
  151. package/package.json +2 -2
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useTamboV1Suggestions = useTamboV1Suggestions;
5
+ const react_1 = require("react");
6
+ const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
7
+ const tambo_registry_provider_1 = require("../../providers/tambo-registry-provider");
8
+ const registry_1 = require("../../util/registry");
9
+ const react_query_hooks_1 = require("../../hooks/react-query-hooks");
10
+ const query_utils_1 = require("../../util/query-utils");
11
+ const use_tambo_v1_1 = require("./use-tambo-v1");
12
+ const use_tambo_v1_thread_input_1 = require("./use-tambo-v1-thread-input");
13
+ function normalizeSuggestionGenerateResponse(response) {
14
+ if (response === undefined) {
15
+ return [];
16
+ }
17
+ if (Array.isArray(response)) {
18
+ return response;
19
+ }
20
+ throw new Error("Unexpected suggestions.generate response shape; expected an array");
21
+ }
22
+ /**
23
+ * Hook for managing Tambo AI suggestions in a v1 thread.
24
+ *
25
+ * Automatically generates suggestions when the latest message is from the assistant
26
+ * and the thread is idle (not streaming).
27
+ *
28
+ * Uses the shared thread input context, so accepting a suggestion without submitting
29
+ * will automatically update the input field value for any component using
30
+ * useTamboV1ThreadInput.
31
+ * @param options - Configuration options for suggestion generation
32
+ * @returns Object containing suggestions state and control functions
33
+ * @example
34
+ * ```tsx
35
+ * function SuggestionsPanel() {
36
+ * const { suggestions, accept, isPending } = useTamboV1Suggestions();
37
+ *
38
+ * return (
39
+ * <div>
40
+ * {suggestions.map(suggestion => (
41
+ * <button
42
+ * key={suggestion.id}
43
+ * onClick={() => accept({ suggestion })}
44
+ * disabled={isPending}
45
+ * >
46
+ * {suggestion.suggestion}
47
+ * </button>
48
+ * ))}
49
+ * </div>
50
+ * );
51
+ * }
52
+ *
53
+ * function ChatInput() {
54
+ * // This input will automatically show the accepted suggestion
55
+ * const { value, setValue, submit } = useTamboV1ThreadInput();
56
+ * return <input value={value} onChange={e => setValue(e.target.value)} />;
57
+ * }
58
+ * ```
59
+ */
60
+ function useTamboV1Suggestions(options = {}) {
61
+ const { maxSuggestions = 3 } = options;
62
+ // Use shared thread input context
63
+ const { setValue, submit, threadId } = (0, use_tambo_v1_thread_input_1.useTamboV1ThreadInput)();
64
+ const { messages, isIdle } = (0, use_tambo_v1_1.useTamboV1)(threadId);
65
+ const tamboClient = (0, tambo_client_provider_1.useTamboClient)();
66
+ const { componentList, toolRegistry, componentToolAssociations } = (0, tambo_registry_provider_1.useTamboRegistry)();
67
+ const [selectedSuggestionId, setSelectedSuggestionId] = (0, react_1.useState)(null);
68
+ const latestMessage = messages[messages.length - 1];
69
+ const isLatestFromAssistant = latestMessage?.role === "assistant";
70
+ const latestMessageId = latestMessage?.id;
71
+ // Reset selected suggestion when the message changes
72
+ (0, react_1.useEffect)(() => {
73
+ setSelectedSuggestionId(null);
74
+ }, [latestMessageId]);
75
+ const shouldGenerateSuggestions = latestMessageId && isLatestFromAssistant && isIdle && threadId;
76
+ // Use React Query to fetch suggestions when conditions are met
77
+ const suggestionsResult = (0, react_query_hooks_1.useTamboQuery)({
78
+ queryKey: [
79
+ "v1-suggestions",
80
+ shouldGenerateSuggestions ? latestMessageId : null,
81
+ ],
82
+ queryFn: async () => {
83
+ if (!shouldGenerateSuggestions || !threadId || !latestMessageId) {
84
+ return [];
85
+ }
86
+ // Get registered components from the registry
87
+ const components = (0, registry_1.getAvailableComponents)(componentList, toolRegistry, componentToolAssociations);
88
+ const response = await tamboClient.beta.threads.suggestions.generate(latestMessageId, {
89
+ id: threadId,
90
+ maxSuggestions,
91
+ availableComponents: components,
92
+ });
93
+ return normalizeSuggestionGenerateResponse(response);
94
+ },
95
+ enabled: Boolean(shouldGenerateSuggestions),
96
+ refetchOnWindowFocus: false,
97
+ refetchOnReconnect: false,
98
+ retry: false,
99
+ });
100
+ // Accept suggestion mutation
101
+ const acceptMutationState = (0, react_query_hooks_1.useTamboMutation)({
102
+ mutationFn: async ({ suggestion, shouldSubmit = false }) => {
103
+ const text = suggestion.detailedSuggestion?.trim();
104
+ if (!text) {
105
+ throw new Error("Suggestion has no detailed content");
106
+ }
107
+ if (shouldSubmit) {
108
+ // Set the value first, then submit
109
+ setValue(text);
110
+ await submit();
111
+ }
112
+ else {
113
+ // Just update the shared input value
114
+ setValue(text);
115
+ }
116
+ setSelectedSuggestionId(suggestion.id);
117
+ },
118
+ });
119
+ // Generate suggestions mutation (for manual refresh)
120
+ const generateMutationState = (0, react_query_hooks_1.useTamboMutation)({
121
+ mutationFn: async (abortController) => {
122
+ if (!shouldGenerateSuggestions || !threadId || !latestMessageId) {
123
+ return [];
124
+ }
125
+ const components = (0, registry_1.getAvailableComponents)(componentList, toolRegistry, componentToolAssociations);
126
+ const response = await tamboClient.beta.threads.suggestions.generate(latestMessageId, {
127
+ id: threadId,
128
+ maxSuggestions,
129
+ availableComponents: components,
130
+ }, { signal: abortController.signal });
131
+ return normalizeSuggestionGenerateResponse(response);
132
+ },
133
+ retry: false,
134
+ });
135
+ // Use query data if available, otherwise use mutation data
136
+ const suggestions = isLatestFromAssistant
137
+ ? (suggestionsResult.data ?? generateMutationState.data ?? [])
138
+ : [];
139
+ const accept = (0, react_1.useCallback)(async (acceptOptions) => {
140
+ await acceptMutationState.mutateAsync(acceptOptions);
141
+ }, [acceptMutationState]);
142
+ return {
143
+ suggestions,
144
+ accept,
145
+ selectedSuggestionId,
146
+ acceptResult: acceptMutationState,
147
+ generateResult: generateMutationState,
148
+ suggestionsResult,
149
+ ...(0, query_utils_1.combineMutationResults)(acceptMutationState, generateMutationState),
150
+ };
151
+ }
152
+ //# sourceMappingURL=use-tambo-v1-suggestions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-suggestions.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-suggestions.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1Suggestions - Suggestions Hook for v1 API\n *\n * Provides AI-generated suggestions based on the current thread state.\n * Uses the shared thread input context so accepting a suggestion\n * automatically updates the input field.\n */\n\nimport TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { getAvailableComponents } from \"../../util/registry\";\nimport {\n useTamboMutation,\n useTamboQuery,\n type UseTamboMutationResult,\n type UseTamboQueryResult,\n} from \"../../hooks/react-query-hooks\";\nimport {\n CombinedMutationResult,\n combineMutationResults,\n} from \"../../util/query-utils\";\nimport { useTamboV1 } from \"./use-tambo-v1\";\nimport { useTamboV1ThreadInput } from \"./use-tambo-v1-thread-input\";\n\ntype Suggestion = TamboAI.Beta.Threads.Suggestion;\n\n// The SDK defines this as an alias of `Suggestion[]`.\ntype SuggestionGenerateResponse =\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse;\n\ntype SuggestionsMutationData = void | SuggestionGenerateResponse;\n\nfunction normalizeSuggestionGenerateResponse(\n response: unknown,\n): SuggestionGenerateResponse {\n if (response === undefined) {\n return [];\n }\n\n if (Array.isArray(response)) {\n return response as SuggestionGenerateResponse;\n }\n\n throw new Error(\n \"Unexpected suggestions.generate response shape; expected an array\",\n );\n}\n\n/**\n * Configuration options for the useTamboV1Suggestions hook\n */\nexport interface UseTamboV1SuggestionsOptions {\n /** Maximum number of suggestions to generate (1-10, default 3) */\n maxSuggestions?: number;\n}\n\n/**\n * Return value interface for useTamboV1Suggestions hook\n */\nexport interface UseTamboV1SuggestionsResultInternal {\n /** List of available suggestions */\n suggestions: Suggestion[];\n\n /** ID of the currently selected suggestion */\n selectedSuggestionId: string | null;\n\n /**\n * Accept and apply a suggestion.\n * If shouldSubmit is false, updates the shared input context value.\n * If shouldSubmit is true, submits the suggestion directly.\n * @param suggestion - The suggestion to accept\n * @param shouldSubmit - Whether to automatically submit after accepting (default: false)\n */\n accept: (acceptOptions: {\n suggestion: Suggestion;\n shouldSubmit?: boolean;\n }) => Promise<void>;\n\n /** Result and network state for accepting a suggestion */\n acceptResult: UseTamboMutationResult<\n void,\n Error,\n { suggestion: Suggestion; shouldSubmit?: boolean }\n >;\n\n /** Result and network state for generating suggestions */\n generateResult: UseTamboMutationResult<\n SuggestionGenerateResponse,\n Error,\n AbortController\n >;\n\n /** The full suggestions query object from React Query */\n suggestionsResult: UseTamboQueryResult<SuggestionGenerateResponse>;\n}\n\ntype UseTamboV1SuggestionsResult = CombinedMutationResult<\n SuggestionsMutationData,\n Error\n> &\n UseTamboV1SuggestionsResultInternal;\n\n/**\n * Hook for managing Tambo AI suggestions in a v1 thread.\n *\n * Automatically generates suggestions when the latest message is from the assistant\n * and the thread is idle (not streaming).\n *\n * Uses the shared thread input context, so accepting a suggestion without submitting\n * will automatically update the input field value for any component using\n * useTamboV1ThreadInput.\n * @param options - Configuration options for suggestion generation\n * @returns Object containing suggestions state and control functions\n * @example\n * ```tsx\n * function SuggestionsPanel() {\n * const { suggestions, accept, isPending } = useTamboV1Suggestions();\n *\n * return (\n * <div>\n * {suggestions.map(suggestion => (\n * <button\n * key={suggestion.id}\n * onClick={() => accept({ suggestion })}\n * disabled={isPending}\n * >\n * {suggestion.suggestion}\n * </button>\n * ))}\n * </div>\n * );\n * }\n *\n * function ChatInput() {\n * // This input will automatically show the accepted suggestion\n * const { value, setValue, submit } = useTamboV1ThreadInput();\n * return <input value={value} onChange={e => setValue(e.target.value)} />;\n * }\n * ```\n */\nexport function useTamboV1Suggestions(\n options: UseTamboV1SuggestionsOptions = {},\n): UseTamboV1SuggestionsResult {\n const { maxSuggestions = 3 } = options;\n\n // Use shared thread input context\n const { setValue, submit, threadId } = useTamboV1ThreadInput();\n\n const { messages, isIdle } = useTamboV1(threadId);\n const tamboClient = useTamboClient();\n const { componentList, toolRegistry, componentToolAssociations } =\n useTamboRegistry();\n\n const [selectedSuggestionId, setSelectedSuggestionId] = useState<\n string | null\n >(null);\n\n const latestMessage = messages[messages.length - 1];\n const isLatestFromAssistant = latestMessage?.role === \"assistant\";\n const latestMessageId = latestMessage?.id;\n\n // Reset selected suggestion when the message changes\n useEffect(() => {\n setSelectedSuggestionId(null);\n }, [latestMessageId]);\n\n const shouldGenerateSuggestions =\n latestMessageId && isLatestFromAssistant && isIdle && threadId;\n\n // Use React Query to fetch suggestions when conditions are met\n const suggestionsResult = useTamboQuery<SuggestionGenerateResponse>({\n queryKey: [\n \"v1-suggestions\",\n shouldGenerateSuggestions ? latestMessageId : null,\n ],\n queryFn: async () => {\n if (!shouldGenerateSuggestions || !threadId || !latestMessageId) {\n return [];\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n const response = await tamboClient.beta.threads.suggestions.generate(\n latestMessageId,\n {\n id: threadId,\n maxSuggestions,\n availableComponents: components,\n },\n );\n\n return normalizeSuggestionGenerateResponse(response);\n },\n enabled: Boolean(shouldGenerateSuggestions),\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n });\n\n // Accept suggestion mutation\n const acceptMutationState = useTamboMutation<\n void,\n Error,\n { suggestion: Suggestion; shouldSubmit?: boolean }\n >({\n mutationFn: async ({ suggestion, shouldSubmit = false }) => {\n const text = suggestion.detailedSuggestion?.trim();\n if (!text) {\n throw new Error(\"Suggestion has no detailed content\");\n }\n\n if (shouldSubmit) {\n // Set the value first, then submit\n setValue(text);\n await submit();\n } else {\n // Just update the shared input value\n setValue(text);\n }\n setSelectedSuggestionId(suggestion.id);\n },\n });\n\n // Generate suggestions mutation (for manual refresh)\n const generateMutationState = useTamboMutation<\n SuggestionGenerateResponse,\n Error,\n AbortController\n >({\n mutationFn: async (abortController: AbortController) => {\n if (!shouldGenerateSuggestions || !threadId || !latestMessageId) {\n return [];\n }\n\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n const response = await tamboClient.beta.threads.suggestions.generate(\n latestMessageId,\n {\n id: threadId,\n maxSuggestions,\n availableComponents: components,\n },\n { signal: abortController.signal },\n );\n\n return normalizeSuggestionGenerateResponse(response);\n },\n retry: false,\n });\n\n // Use query data if available, otherwise use mutation data\n const suggestions = isLatestFromAssistant\n ? (suggestionsResult.data ?? generateMutationState.data ?? [])\n : [];\n\n const accept = useCallback(\n async (acceptOptions: {\n suggestion: Suggestion;\n shouldSubmit?: boolean;\n }) => {\n await acceptMutationState.mutateAsync(acceptOptions);\n },\n [acceptMutationState],\n );\n\n return {\n suggestions,\n accept,\n selectedSuggestionId,\n acceptResult: acceptMutationState,\n generateResult: generateMutationState,\n suggestionsResult,\n ...combineMutationResults(acceptMutationState, generateMutationState),\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-tambo-v1-suggestions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-v1-suggestions.test.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-suggestions.test.tsx"],"names":[],"mappings":""}