@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.
- package/dist/mcp/mcp-hooks.d.ts +4 -0
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +4 -0
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +3 -0
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +3 -0
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/util/resource-content-resolver.d.ts.map +1 -1
- package/dist/util/resource-content-resolver.js +2 -0
- package/dist/util/resource-content-resolver.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +22 -9
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +9 -2
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.js +152 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +511 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.js +7 -67
- package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +201 -72
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +2 -2
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +16 -7
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +22 -13
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +31 -39
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +27 -9
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +22 -11
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +27 -10
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +19 -10
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +43 -53
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +94 -19
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-stub-provider.js +212 -0
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -0
- package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
- package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-stub-provider.test.js +162 -0
- package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +191 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
- package/dist/v1/utils/component-renderer.d.ts +15 -67
- package/dist/v1/utils/component-renderer.d.ts.map +1 -1
- package/dist/v1/utils/component-renderer.js +3 -149
- package/dist/v1/utils/component-renderer.js.map +1 -1
- package/dist/v1/utils/component-renderer.test.js +15 -350
- package/dist/v1/utils/component-renderer.test.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +4 -0
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +4 -0
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +3 -0
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +3 -0
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/util/resource-content-resolver.d.ts.map +1 -1
- package/esm/util/resource-content-resolver.js +2 -0
- package/esm/util/resource-content-resolver.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +22 -9
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +9 -2
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.js +149 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +506 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.js +5 -66
- package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +199 -73
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +2 -2
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +16 -7
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +22 -13
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +23 -18
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +27 -9
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +20 -10
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +28 -11
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +19 -10
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +44 -54
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +95 -20
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-stub-provider.js +176 -0
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -0
- package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
- package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-stub-provider.test.js +157 -0
- package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +153 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
- package/esm/v1/utils/component-renderer.d.ts +15 -67
- package/esm/v1/utils/component-renderer.d.ts.map +1 -1
- package/esm/v1/utils/component-renderer.js +4 -146
- package/esm/v1/utils/component-renderer.js.map +1 -1
- package/esm/v1/utils/component-renderer.test.js +16 -351
- package/esm/v1/utils/component-renderer.test.js.map +1 -1
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-suggestions.test.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-suggestions.test.tsx"],"names":[],"mappings":""}
|