@stack-spot/portal-network 0.184.0 → 0.185.0-beta.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 (142) hide show
  1. package/CHANGELOG.md +2444 -2412
  2. package/dist/api/account.js +1 -1
  3. package/dist/api/agent-tools.js +1 -1
  4. package/dist/api/agent.js +1 -1
  5. package/dist/api/ai.js +1 -1
  6. package/dist/api/apiManagement.js +1 -1
  7. package/dist/api/apiRuntime.js +1 -1
  8. package/dist/api/cloudAccount.js +1 -1
  9. package/dist/api/cloudPlatform.js +1 -1
  10. package/dist/api/cloudPlatformHorizon.js +1 -1
  11. package/dist/api/cloudRuntimes.js +1 -1
  12. package/dist/api/cloudServices.js +1 -1
  13. package/dist/api/codeShift.d.ts +63 -4
  14. package/dist/api/codeShift.d.ts.map +1 -1
  15. package/dist/api/codeShift.js +14 -1
  16. package/dist/api/codeShift.js.map +1 -1
  17. package/dist/api/content.js +1 -1
  18. package/dist/api/dataIntegration.js +1 -1
  19. package/dist/api/discover.js +1 -1
  20. package/dist/api/genAiInference.js +1 -1
  21. package/dist/api/insights.js +1 -1
  22. package/dist/api/notification.js +1 -1
  23. package/dist/api/secrets.js +1 -1
  24. package/dist/api/serviceCatalog.js +1 -1
  25. package/dist/api/workspace-ai.js +1 -1
  26. package/dist/api/workspace.js +1 -1
  27. package/dist/api/workspaceManager.js +1 -1
  28. package/dist/api/workspaceSearchEngine.js +1 -1
  29. package/dist/client/ai.d.ts.map +1 -1
  30. package/dist/client/ai.js +84 -14
  31. package/dist/client/ai.js.map +1 -1
  32. package/dist/client/code-shift.d.ts +30 -0
  33. package/dist/client/code-shift.d.ts.map +1 -1
  34. package/dist/client/code-shift.js +37 -1
  35. package/dist/client/code-shift.js.map +1 -1
  36. package/dist/client/types.d.ts +26 -6
  37. package/dist/client/types.d.ts.map +1 -1
  38. package/package.json +7 -7
  39. package/readme.md +1 -1
  40. package/scripts/generate-apis.ts +134 -134
  41. package/src/api/account.ts +8368 -8367
  42. package/src/api/agent-tools.ts +2172 -2169
  43. package/src/api/agent.ts +1085 -1083
  44. package/src/api/ai.ts +3388 -3388
  45. package/src/api/apiManagement.ts +570 -570
  46. package/src/api/apiRuntime.ts +2103 -2103
  47. package/src/api/cloudAccount.ts +1239 -1239
  48. package/src/api/cloudPlatform.ts +927 -927
  49. package/src/api/cloudPlatformHorizon.ts +2655 -2655
  50. package/src/api/cloudRuntimes.ts +2043 -2043
  51. package/src/api/cloudServices.ts +1445 -1445
  52. package/src/api/codeShift.ts +3567 -3481
  53. package/src/api/content.ts +9785 -9785
  54. package/src/api/dataIntegration.ts +1657 -1657
  55. package/src/api/discover.ts +435 -435
  56. package/src/api/eventBus.ts +171 -171
  57. package/src/api/genAiInference.ts +603 -603
  58. package/src/api/insights.ts +310 -310
  59. package/src/api/notification.ts +336 -334
  60. package/src/api/secrets.ts +342 -342
  61. package/src/api/serviceCatalog.ts +2908 -2908
  62. package/src/api/workflows.ts +1669 -1669
  63. package/src/api/workspace-ai.ts +677 -677
  64. package/src/api/workspace.ts +5889 -5889
  65. package/src/api/workspaceManager.ts +2951 -2951
  66. package/src/api/workspaceSearchEngine.ts +153 -153
  67. package/src/api-addresses.ts +120 -120
  68. package/src/apis-itau.json +225 -225
  69. package/src/apis.json +225 -225
  70. package/src/client/account.ts +902 -902
  71. package/src/client/agent-tools.ts +210 -210
  72. package/src/client/agent.ts +81 -81
  73. package/src/client/ai.ts +469 -395
  74. package/src/client/api-management.ts +40 -40
  75. package/src/client/cloud-account.ts +70 -70
  76. package/src/client/cloud-platform-horizon.ts +113 -113
  77. package/src/client/cloud-platform.ts +163 -163
  78. package/src/client/cloud-runtimes.ts +129 -129
  79. package/src/client/cloud-services.ts +94 -94
  80. package/src/client/code-shift.ts +371 -349
  81. package/src/client/content.ts +538 -538
  82. package/src/client/data-integration.ts +191 -191
  83. package/src/client/discover.ts +89 -89
  84. package/src/client/event-bus.ts +84 -84
  85. package/src/client/gen-ai-inference.ts +65 -65
  86. package/src/client/insights.ts +28 -28
  87. package/src/client/notification.ts +32 -32
  88. package/src/client/runtime-manager.ts +76 -76
  89. package/src/client/secrets.ts +60 -60
  90. package/src/client/types.ts +398 -377
  91. package/src/client/workflow.ts +83 -83
  92. package/src/client/workspace-ai.ts +191 -191
  93. package/src/client/workspace-manager.ts +564 -564
  94. package/src/client/workspace-search.ts +39 -39
  95. package/src/client/workspace.ts +480 -480
  96. package/src/error/DefaultAPIError.ts +151 -151
  97. package/src/error/FileUploadError.ts +18 -18
  98. package/src/error/IgnoredErrorCodes.ts +3 -3
  99. package/src/error/StackspotAPIError.ts +101 -101
  100. package/src/error/StreamCanceledError.ts +10 -10
  101. package/src/error/StreamError.ts +7 -7
  102. package/src/error/StreamJsonError.ts +10 -10
  103. package/src/error/dictionary/account.ts +58 -58
  104. package/src/error/dictionary/action-details.ts +20 -20
  105. package/src/error/dictionary/action.ts +211 -211
  106. package/src/error/dictionary/agent-tools.ts +75 -75
  107. package/src/error/dictionary/ai-inference.ts +28 -28
  108. package/src/error/dictionary/base.ts +22 -22
  109. package/src/error/dictionary/cloud-platform.ts +82 -82
  110. package/src/error/dictionary/cnt-fields.ts +14 -14
  111. package/src/error/dictionary/cnt.ts +103 -103
  112. package/src/error/dictionary/code-shift.ts +12 -12
  113. package/src/error/dictionary/rte.ts +24 -24
  114. package/src/error/dictionary/rtm.ts +10 -10
  115. package/src/error/dictionary/secrets.ts +14 -14
  116. package/src/error/dictionary/workspace-ai.ts +10 -10
  117. package/src/error/dictionary/workspace-details.ts +15 -15
  118. package/src/error/dictionary/workspace-fields.ts +10 -10
  119. package/src/error/dictionary/workspace.ts +209 -209
  120. package/src/error/types.ts +21 -21
  121. package/src/index.ts +43 -43
  122. package/src/network/AutoInfiniteQuery.ts +115 -115
  123. package/src/network/AutoMutation.ts +27 -27
  124. package/src/network/AutoOperation.ts +73 -73
  125. package/src/network/AutoQuery.ts +75 -75
  126. package/src/network/ManualInfiniteQuery.ts +95 -95
  127. package/src/network/ManualMutation.ts +40 -40
  128. package/src/network/ManualOperation.ts +52 -52
  129. package/src/network/ManualQuery.ts +82 -82
  130. package/src/network/NetworkClient.ts +167 -167
  131. package/src/network/ReactQueryNetworkClient.ts +312 -312
  132. package/src/network/react-query-client.ts +14 -14
  133. package/src/network/types.ts +294 -294
  134. package/src/types.ts +1 -1
  135. package/src/utils/StreamedArray.tsx +146 -146
  136. package/src/utils/StreamedJson.tsx +166 -166
  137. package/src/utils/remove-authorization-param.ts +6 -6
  138. package/src/utils/string.ts +19 -19
  139. package/src/utils/use-extended-list.ts +80 -80
  140. package/src/utils/use-streamed-array.ts +17 -17
  141. package/tsconfig.build.json +4 -4
  142. package/tsconfig.json +10 -10
package/src/client/ai.ts CHANGED
@@ -1,395 +1,469 @@
1
- import { HttpError } from '@oazapfts/runtime'
2
- import { findLast, isArray, last } from 'lodash'
3
- import { getApiAddresses } from '../api-addresses'
4
- import {
5
- addFavoriteV1AiStacksStackIdFavoritePost,
6
- addFavoriteV1QuickCommandsSlugFavoritePost,
7
- calculateNextStepV1QuickCommandsSlugStepsStepSlugCalculateNextStepPost,
8
- callbackV1QuickCommandsCallbackExecutionIdGet,
9
- conversationHistoryV1ConversationsConversationIdGet,
10
- createExecutionV1QuickCommandsCreateExecutionSlugPost,
11
- currentV1TokensUsageCurrentGet,
12
- currentV1TokensUsageTotalGet,
13
- defaults,
14
- deleteConversationV1ConversationsConversationIdDelete,
15
- deleteFavoriteV1AiStacksStackIdFavoriteDelete,
16
- deleteFavoriteV1QuickCommandsSlugFavoriteDelete,
17
- deleteKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdDelete,
18
- downloadConversationV1ConversationsConversationIdDownloadGet,
19
- findKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdGet,
20
- findKnowledgeSourceV1KnowledgeSourcesSlugGet,
21
- formatFetchStepV1QuickCommandsSlugStepsStepSlugFetchFormatPost,
22
- formatResultV1QuickCommandsSlugResultFormatPost,
23
- getContentDependenciesV1ContentContentTypeContentIdDependenciesGet,
24
- getQuickCommandV1QuickCommandsSlugGet,
25
- getUploadFormV1FileUploadFormPost,
26
- HttpValidationError,
27
- listAiStacksV1AiStacksGet,
28
- listAllV1QuickCommandsAllGet,
29
- listAllV2QuickCommandsAllGet,
30
- listAssociationV1WorkspaceWorkspaceIdGet,
31
- listConversationsV1ConversationsGet,
32
- listKnowledgeSourcesV1KnowledgeSourcesGet,
33
- postEventV1EventsPost,
34
- quickActionsV1QuickActionsPost,
35
- QuickCommandPromptResponse2,
36
- QuickCommandsExecutionRequest,
37
- quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost,
38
- resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete,
39
- runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost,
40
- searchKnowledgeSourcesV1KnowledgeSourcesSearchPost,
41
- updateQuickCommandV1QuickCommandsSlugPatch,
42
- updateTitleV1ConversationsConversationIdPatch,
43
- vectorizeCustomKnowledgeSourceV1KnowledgeSourcesSlugCustomPost,
44
- } from '../api/ai'
45
- import { StackspotAPIError } from '../error/StackspotAPIError'
46
- import { ReactQueryNetworkClient } from '../network/ReactQueryNetworkClient'
47
- import { removeAuthorizationParam } from '../utils/remove-authorization-param'
48
- import { StreamedJson } from '../utils/StreamedJson'
49
- import { formatJson } from '../utils/string'
50
- import { agentToolsClient } from './agent-tools'
51
- import {
52
- ChatAgentTool,
53
- ChatResponseWithSteps,
54
- FixedChatRequest,
55
- FixedChatResponse,
56
- FixedConversationResponse,
57
- FixedDependencyResponse,
58
- ReplaceResult,
59
- StepChatStep,
60
- } from './types'
61
-
62
- class AIClient extends ReactQueryNetworkClient {
63
- constructor() {
64
- super(getApiAddresses().ai.url, defaults)
65
- }
66
-
67
- protected buildStackSpotError(error: HttpError): StackspotAPIError {
68
- // @ts-ignore API documentation is wrong
69
- const details = (error.data as HttpValidationError | undefined)?.details
70
- return new StackspotAPIError({
71
- status: error.status,
72
- headers: error.headers,
73
- stack: error.stack,
74
- message: isArray(details) ? details?.map(d => d.msg)?.join('\n') : details,
75
- })
76
- }
77
-
78
- /**
79
- * Chat: runs a quick action.
80
- */
81
- runQuickAction = this.mutation(removeAuthorizationParam(quickActionsV1QuickActionsPost))
82
- /**
83
- * Deletes a KO from a KS
84
- */
85
- deleteKnowledgeObjectFromKs = this.mutation(
86
- removeAuthorizationParam(deleteKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdDelete))
87
- /**
88
- * Deletes a KO by standalone (reset Knowledge Objects)
89
- */
90
- deleteKnowledgeObjectsByStandalone = this.mutation(
91
- removeAuthorizationParam(resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete))
92
- /**
93
- * Uploads a KO file
94
- */
95
- fileUploadFormKnowledgeObject = this.mutation(
96
- removeAuthorizationParam(getUploadFormV1FileUploadFormPost))
97
- /**
98
- * Creates a custom KO (Vectorize)
99
- */
100
- vectorizeCustomKS = this.mutation(
101
- removeAuthorizationParam(vectorizeCustomKnowledgeSourceV1KnowledgeSourcesSlugCustomPost))
102
- /**
103
- * Lists the AI Stacks according to their visibilities.
104
- */
105
- aiStacks = this.query(removeAuthorizationParam(listAiStacksV1AiStacksGet))
106
- /**
107
- * Gets total tokens usage
108
- */
109
- totalTokensUsage = this.query(removeAuthorizationParam(currentV1TokensUsageTotalGet))
110
- /**
111
- * Gets current tokens usage
112
- */
113
- currentTokensUsage = this.query(removeAuthorizationParam(currentV1TokensUsageCurrentGet))
114
- /**
115
- * Gets a workspace by its id.
116
- */
117
- workspace = this.query(removeAuthorizationParam(listAssociationV1WorkspaceWorkspaceIdGet))
118
- /**
119
- * @deprecated
120
- * Lists the quick commands according to filters passed as parameter (QC with secrets will not be returned).
121
- */
122
- quickCommands = this.query(removeAuthorizationParam(listAllV1QuickCommandsAllGet))
123
- /**
124
- * Lists all the quick commands according to filters passed as parameter (including QC with secrets).
125
- */
126
- allQuickCommands = this.query(removeAuthorizationParam(listAllV2QuickCommandsAllGet))
127
- /**
128
- * Gets a quick command by its slug.
129
- */
130
- quickCommand = this.query(removeAuthorizationParam(getQuickCommandV1QuickCommandsSlugGet))
131
- /**
132
- * Creates a new execution for a quick command by its slug.
133
- */
134
- quickCommandCreateExecution = this.mutation(removeAuthorizationParam(createExecutionV1QuickCommandsCreateExecutionSlugPost))
135
- /**
136
- * Gets the execution status and result of a quick command by its execution ID.
137
- */
138
- quickCommandCallbackExecutionId = this.query(removeAuthorizationParam(callbackV1QuickCommandsCallbackExecutionIdGet))
139
- /**
140
- * Lists the knowledge sources according to filters passed as parameter.
141
- */
142
- knowledgeSources = this.query(removeAuthorizationParam(listKnowledgeSourcesV1KnowledgeSourcesGet))
143
- /**
144
- * Gets a knowledge source by its slug.
145
- */
146
- knowledgeSource = this.query(removeAuthorizationParam(findKnowledgeSourceV1KnowledgeSourcesSlugGet))
147
- /**
148
- * Gets a knowledge source document by the slug of the parent knowledge source and the document id.
149
- */
150
- knowledgeSourceDocument = this.query(removeAuthorizationParam(findKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdGet))
151
- /**
152
- * Lists knowledge sources matching the provided IDs.
153
- */
154
- searchKnowledgeSources = this.query(removeAuthorizationParam(searchKnowledgeSourcesV1KnowledgeSourcesSearchPost))
155
- /**
156
- * Gets the chat history. This is a paginated resource.
157
- */
158
- chats = this.infiniteQuery(removeAuthorizationParam(listConversationsV1ConversationsGet))
159
- /**
160
- * Gets a specific chat from the history according to its id.
161
- */
162
- chat = this.query(removeAuthorizationParam(
163
- conversationHistoryV1ConversationsConversationIdGet as ReplaceResult<
164
- typeof conversationHistoryV1ConversationsConversationIdGet,
165
- FixedConversationResponse
166
- >,
167
- ))
168
- /**
169
- * Deletes a chat from the chat history.
170
- */
171
- deleteChat = this.mutation(removeAuthorizationParam(deleteConversationV1ConversationsConversationIdDelete))
172
- /**
173
- * Gets a plain text version of the chat with id passed as parameter.
174
- */
175
- downloadChat = this.mutation(removeAuthorizationParam(downloadConversationV1ConversationsConversationIdDownloadGet))
176
- /**
177
- * Renames a chat.
178
- */
179
- renameChat = this.mutation(removeAuthorizationParam(updateTitleV1ConversationsConversationIdPatch))
180
- /**
181
- * Creates an event so it can be used as metric by the product designers (analytics).
182
- */
183
- createEvent = this.mutation(removeAuthorizationParam(postEventV1EventsPost))
184
- /**
185
- * Runs a step of type "fetch" of a quick command.
186
- */
187
- fetchStepOfQuickCommand = this.mutation(removeAuthorizationParam(formatFetchStepV1QuickCommandsSlugStepsStepSlugFetchFormatPost))
188
- /**
189
- * Remotely runs a step of type "fetch" of a quick command remotely (used when secrets are present).
190
- */
191
- fetchStepOfQuickCommandRemotely = this.mutation({
192
- name: 'fetchStepOfQuickCommandRemotely',
193
- request: (
194
- signal,
195
- variables: Omit<Parameters<typeof runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost>[0], 'authorization'> &
196
- { headers?: Record<string, any> },
197
- ) => {
198
- const { headers, ...props } = variables
199
- return runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost({ ...props, authorization: '' }, { signal, headers })
200
- },
201
- permission: this.createPermissionFunctionFor(runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost),
202
- })
203
-
204
- /**
205
- * @deprecated This method does not use stream, only json. The json support has been removed
206
- * So this method might not work as expected.
207
- * Runs a step of type "llm" of a quick command.
208
- */
209
- llmStepOfQuickCommand = this.mutation(removeAuthorizationParam(quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost))
210
- /**
211
- * Calculates QC router next step.
212
- */
213
- calculateNextStep = this.mutation(removeAuthorizationParam(calculateNextStepV1QuickCommandsSlugStepsStepSlugCalculateNextStepPost))
214
- /**
215
- * Runs a stream of a step of type "llm" of a quick command.
216
- */
217
- streamLlmStepOfQuickCommand(slug: string, stepSlug: string, quickCommandsExecutionRequest: QuickCommandsExecutionRequest,
218
- minChangeIntervalMS?: number):
219
- StreamedJson<QuickCommandPromptResponse2> {
220
- const abortController = new AbortController()
221
- const headers = {
222
- 'Content-Type': 'application/json',
223
- 'Accept': 'text/event-stream',
224
- }
225
- const events = this.stream(
226
- this.resolveURL(`/v2/quick-commands/${slug}/steps/${stepSlug}/run`),
227
- { method: 'post', body: JSON.stringify(quickCommandsExecutionRequest), headers, signal: abortController.signal },
228
- )
229
-
230
- return new StreamedJson({
231
- eventsPromise: events,
232
- abortController,
233
- minChangeIntervalMS,
234
- })
235
- }
236
- /**
237
- * Formats the result of a quick command into a human-readable text (markdown).
238
- */
239
- formatResultOfQuickCommand = this.mutation(removeAuthorizationParam(formatResultV1QuickCommandsSlugResultFormatPost))
240
- /**
241
- * Adds the resource of type Stack AI to the list of favorites.
242
- */
243
- addFavoriteStackAi = this.mutation(removeAuthorizationParam(addFavoriteV1AiStacksStackIdFavoritePost))
244
- /**
245
- * Removes the resource of type Stack AI from the list of favorites.
246
- */
247
- removeFavoriteStackAi = this.mutation(removeAuthorizationParam(deleteFavoriteV1AiStacksStackIdFavoriteDelete))
248
- /**
249
- * Updates a Quick Command
250
- */
251
- updateQuickCommand = this.mutation(removeAuthorizationParam(updateQuickCommandV1QuickCommandsSlugPatch))
252
- /**
253
- * Adds the resource of type Quick Command to the list of favorites.
254
- */
255
- addFavoriteQuickCommand = this.mutation(removeAuthorizationParam(addFavoriteV1QuickCommandsSlugFavoritePost))
256
- /**
257
- * Removes the resource of type Quick Command from the list of favorites.
258
- */
259
- removeFavoriteQuickCommand = this.mutation(removeAuthorizationParam(deleteFavoriteV1QuickCommandsSlugFavoriteDelete))
260
-
261
- private static async toolsOfAgent(agentId?: string) {
262
- try {
263
- const agent = agentId ? await agentToolsClient.agent.query({ agentId }) : undefined
264
- if (!agent) return []
265
- const tools: (Omit<ChatAgentTool, 'duration' | 'prompt' | 'output'>)[] = []
266
- agent.toolkits?.builtin_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
267
- if (id) tools.push({ image: kit.image_url, id, name: name || id, description })
268
- }))
269
- return tools
270
- } catch {
271
- return []
272
- }
273
- }
274
-
275
- sendChatMessage(request: FixedChatRequest, minChangeIntervalMS?: number): StreamedJson<ChatResponseWithSteps> {
276
- const abortController = new AbortController()
277
- const headers = {
278
- 'Content-Type': 'application/json',
279
- 'Accept': 'text/event-stream',
280
- }
281
- const events = this.stream(
282
- this.resolveURL('v3/chat'),
283
- { method: 'post', body: JSON.stringify(request), headers, signal: abortController.signal },
284
- )
285
-
286
- /**
287
- * This function treats events in the streaming that deals with the execution of tools. Since these events are not concatenated like
288
- * normal streamings of data, we need this separate function to deal with them. It transforms the internal data model of the
289
- * StreamedJson object whenever an event is triggered.
290
- */
291
- async function transform(event: Partial<FixedChatResponse>, data: Partial<ChatResponseWithSteps>) {
292
- const info = event.agent_info
293
- if (!info) return
294
- const tools = await AIClient.toolsOfAgent(request.context?.agent_id)
295
- data.steps = data.steps ? [...data.steps] : []
296
-
297
- if (info.type === 'planning' && info.action === 'end') {
298
- data.steps.push({
299
- id: 'planning',
300
- type: 'planning',
301
- status: 'success',
302
- duration: info.duration || 0,
303
- steps: info.data?.steps?.map(s => s.goal) ?? [],
304
- goal: info.data?.plan_goal ?? '',
305
- })
306
- info.data?.steps.forEach(s => data.steps?.push({
307
- id: s.id,
308
- type: 'step',
309
- status: 'pending',
310
- input: s.goal,
311
- attempts: [{
312
- tools: s.tools?.map(t => ({
313
- ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
314
- executionId: t.tool_execution_id,
315
- })),
316
- }],
317
- }))
318
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
319
- }
320
-
321
- if (info.type === 'step' && info.action === 'start') {
322
- const step = data.steps.find(s => s.id === info.id)
323
- if (step) step.status = 'running'
324
- }
325
-
326
- if (info.type === 'step' && info.action === 'end') {
327
- const step = data.steps.find(s => s.id === info.id) as StepChatStep
328
- if (step) {
329
- step.status = 'success'
330
- step.duration = info.duration
331
- const lastToolId = last(step.attempts[0].tools)?.id
332
- const lastAttemptOfLastTool = findLast(step.attempts.map(a => a.tools).flat(), t => t?.id === lastToolId)
333
- step.output = lastAttemptOfLastTool?.output
334
- }
335
- }
336
-
337
- if (info.type === 'tool' && info.action === 'start') {
338
- const currentStep = data.steps.find(s => s.status === 'running') as StepChatStep
339
- if (!currentStep || !info.data || !currentStep.attempts[0].tools) return
340
- const toolInFirstAttempt = currentStep.attempts[0].tools.find(t => t.executionId === info.id)
341
- if (!toolInFirstAttempt) return
342
- const input = formatJson(info.data.input)
343
- if (info.data.attempt === 0) {
344
- toolInFirstAttempt.input = input
345
- } else {
346
- currentStep.attempts[info.data.attempt] ??= { tools: [] }
347
- currentStep.attempts[info.data.attempt].tools?.push({
348
- ...toolInFirstAttempt,
349
- input,
350
- })
351
- }
352
- }
353
-
354
- if (info.type === 'tool' && info.action === 'end') {
355
- const currentStep = data.steps.find(s => s.status === 'running') as StepChatStep
356
- if (!currentStep || !info.data) return
357
- const tool = currentStep.attempts[info.data.attempt]?.tools?.find(t => t.executionId === info.id)
358
- if (tool) {
359
- tool.output = formatJson(info.data.output)
360
- tool.duration = info.duration
361
- }
362
- }
363
-
364
- if (info.type === 'final_answer' && info.action === 'start') {
365
- const answerStep = last(data.steps)
366
- if (answerStep) answerStep.status = 'running'
367
- }
368
-
369
- if (info.type === 'final_answer' && info.action === 'end') {
370
- const answerStep = last(data.steps)
371
- if (answerStep) {
372
- answerStep.status = 'success'
373
- answerStep.duration = info.duration
374
- }
375
- }
376
- }
377
-
378
- return new StreamedJson({
379
- eventsPromise: events,
380
- abortController,
381
- minChangeIntervalMS,
382
- ignoreKeys: ['agent_info'],
383
- transform,
384
- })
385
- }
386
-
387
- contentDependencies = this.query(removeAuthorizationParam(
388
- getContentDependenciesV1ContentContentTypeContentIdDependenciesGet as ReplaceResult<
389
- typeof getContentDependenciesV1ContentContentTypeContentIdDependenciesGet,
390
- FixedDependencyResponse
391
- >,
392
- ))
393
- }
394
-
395
- export const aiClient = new AIClient()
1
+ import { HttpError } from '@oazapfts/runtime'
2
+ import { findLast, isArray, last } from 'lodash'
3
+ import { getApiAddresses } from '../api-addresses'
4
+ import {
5
+ addFavoriteV1AiStacksStackIdFavoritePost,
6
+ addFavoriteV1QuickCommandsSlugFavoritePost,
7
+ calculateNextStepV1QuickCommandsSlugStepsStepSlugCalculateNextStepPost,
8
+ callbackV1QuickCommandsCallbackExecutionIdGet,
9
+ conversationHistoryV1ConversationsConversationIdGet,
10
+ createExecutionV1QuickCommandsCreateExecutionSlugPost,
11
+ currentV1TokensUsageCurrentGet,
12
+ currentV1TokensUsageTotalGet,
13
+ defaults,
14
+ deleteConversationV1ConversationsConversationIdDelete,
15
+ deleteFavoriteV1AiStacksStackIdFavoriteDelete,
16
+ deleteFavoriteV1QuickCommandsSlugFavoriteDelete,
17
+ deleteKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdDelete,
18
+ downloadConversationV1ConversationsConversationIdDownloadGet,
19
+ findKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdGet,
20
+ findKnowledgeSourceV1KnowledgeSourcesSlugGet,
21
+ formatFetchStepV1QuickCommandsSlugStepsStepSlugFetchFormatPost,
22
+ formatResultV1QuickCommandsSlugResultFormatPost,
23
+ getContentDependenciesV1ContentContentTypeContentIdDependenciesGet,
24
+ getQuickCommandV1QuickCommandsSlugGet,
25
+ getUploadFormV1FileUploadFormPost,
26
+ HttpValidationError,
27
+ listAiStacksV1AiStacksGet,
28
+ listAllV1QuickCommandsAllGet,
29
+ listAllV2QuickCommandsAllGet,
30
+ listAssociationV1WorkspaceWorkspaceIdGet,
31
+ listConversationsV1ConversationsGet,
32
+ listKnowledgeSourcesV1KnowledgeSourcesGet,
33
+ postEventV1EventsPost,
34
+ quickActionsV1QuickActionsPost,
35
+ QuickCommandPromptResponse2,
36
+ QuickCommandsExecutionRequest,
37
+ quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost,
38
+ resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete,
39
+ runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost,
40
+ searchKnowledgeSourcesV1KnowledgeSourcesSearchPost,
41
+ updateQuickCommandV1QuickCommandsSlugPatch,
42
+ updateTitleV1ConversationsConversationIdPatch,
43
+ vectorizeCustomKnowledgeSourceV1KnowledgeSourcesSlugCustomPost,
44
+ } from '../api/ai'
45
+ import { StackspotAPIError } from '../error/StackspotAPIError'
46
+ import { ReactQueryNetworkClient } from '../network/ReactQueryNetworkClient'
47
+ import { removeAuthorizationParam } from '../utils/remove-authorization-param'
48
+ import { StreamedJson } from '../utils/StreamedJson'
49
+ import { formatJson } from '../utils/string'
50
+ import { agentToolsClient } from './agent-tools'
51
+ import {
52
+ ChatAgentTool,
53
+ ChatResponseWithSteps,
54
+ FixedChatRequest,
55
+ FixedChatResponse,
56
+ FixedConversationResponse,
57
+ FixedDependencyResponse,
58
+ ReplaceResult,
59
+ StepChatStep,
60
+ } from './types'
61
+
62
+ class AIClient extends ReactQueryNetworkClient {
63
+ constructor() {
64
+ super(getApiAddresses().ai.url, defaults)
65
+ }
66
+
67
+ protected buildStackSpotError(error: HttpError): StackspotAPIError {
68
+ // @ts-ignore API documentation is wrong
69
+ const details = (error.data as HttpValidationError | undefined)?.details
70
+ return new StackspotAPIError({
71
+ status: error.status,
72
+ headers: error.headers,
73
+ stack: error.stack,
74
+ message: isArray(details) ? details?.map(d => d.msg)?.join('\n') : details,
75
+ })
76
+ }
77
+
78
+ /**
79
+ * Chat: runs a quick action.
80
+ */
81
+ runQuickAction = this.mutation(removeAuthorizationParam(quickActionsV1QuickActionsPost))
82
+ /**
83
+ * Deletes a KO from a KS
84
+ */
85
+ deleteKnowledgeObjectFromKs = this.mutation(
86
+ removeAuthorizationParam(deleteKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdDelete))
87
+ /**
88
+ * Deletes a KO by standalone (reset Knowledge Objects)
89
+ */
90
+ deleteKnowledgeObjectsByStandalone = this.mutation(
91
+ removeAuthorizationParam(resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete))
92
+ /**
93
+ * Uploads a KO file
94
+ */
95
+ fileUploadFormKnowledgeObject = this.mutation(
96
+ removeAuthorizationParam(getUploadFormV1FileUploadFormPost))
97
+ /**
98
+ * Creates a custom KO (Vectorize)
99
+ */
100
+ vectorizeCustomKS = this.mutation(
101
+ removeAuthorizationParam(vectorizeCustomKnowledgeSourceV1KnowledgeSourcesSlugCustomPost))
102
+ /**
103
+ * Lists the AI Stacks according to their visibilities.
104
+ */
105
+ aiStacks = this.query(removeAuthorizationParam(listAiStacksV1AiStacksGet))
106
+ /**
107
+ * Gets total tokens usage
108
+ */
109
+ totalTokensUsage = this.query(removeAuthorizationParam(currentV1TokensUsageTotalGet))
110
+ /**
111
+ * Gets current tokens usage
112
+ */
113
+ currentTokensUsage = this.query(removeAuthorizationParam(currentV1TokensUsageCurrentGet))
114
+ /**
115
+ * Gets a workspace by its id.
116
+ */
117
+ workspace = this.query(removeAuthorizationParam(listAssociationV1WorkspaceWorkspaceIdGet))
118
+ /**
119
+ * @deprecated
120
+ * Lists the quick commands according to filters passed as parameter (QC with secrets will not be returned).
121
+ */
122
+ quickCommands = this.query(removeAuthorizationParam(listAllV1QuickCommandsAllGet))
123
+ /**
124
+ * Lists all the quick commands according to filters passed as parameter (including QC with secrets).
125
+ */
126
+ allQuickCommands = this.query(removeAuthorizationParam(listAllV2QuickCommandsAllGet))
127
+ /**
128
+ * Gets a quick command by its slug.
129
+ */
130
+ quickCommand = this.query(removeAuthorizationParam(getQuickCommandV1QuickCommandsSlugGet))
131
+ /**
132
+ * Creates a new execution for a quick command by its slug.
133
+ */
134
+ quickCommandCreateExecution = this.mutation(removeAuthorizationParam(createExecutionV1QuickCommandsCreateExecutionSlugPost))
135
+ /**
136
+ * Gets the execution status and result of a quick command by its execution ID.
137
+ */
138
+ quickCommandCallbackExecutionId = this.query(removeAuthorizationParam(callbackV1QuickCommandsCallbackExecutionIdGet))
139
+ /**
140
+ * Lists the knowledge sources according to filters passed as parameter.
141
+ */
142
+ knowledgeSources = this.query(removeAuthorizationParam(listKnowledgeSourcesV1KnowledgeSourcesGet))
143
+ /**
144
+ * Gets a knowledge source by its slug.
145
+ */
146
+ knowledgeSource = this.query(removeAuthorizationParam(findKnowledgeSourceV1KnowledgeSourcesSlugGet))
147
+ /**
148
+ * Gets a knowledge source document by the slug of the parent knowledge source and the document id.
149
+ */
150
+ knowledgeSourceDocument = this.query(removeAuthorizationParam(findKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdGet))
151
+ /**
152
+ * Lists knowledge sources matching the provided IDs.
153
+ */
154
+ searchKnowledgeSources = this.query(removeAuthorizationParam(searchKnowledgeSourcesV1KnowledgeSourcesSearchPost))
155
+ /**
156
+ * Gets the chat history. This is a paginated resource.
157
+ */
158
+ chats = this.infiniteQuery(removeAuthorizationParam(listConversationsV1ConversationsGet))
159
+ /**
160
+ * Gets a specific chat from the history according to its id.
161
+ */
162
+ chat = this.query(removeAuthorizationParam(
163
+ conversationHistoryV1ConversationsConversationIdGet as ReplaceResult<
164
+ typeof conversationHistoryV1ConversationsConversationIdGet,
165
+ FixedConversationResponse
166
+ >,
167
+ ))
168
+ /**
169
+ * Deletes a chat from the chat history.
170
+ */
171
+ deleteChat = this.mutation(removeAuthorizationParam(deleteConversationV1ConversationsConversationIdDelete))
172
+ /**
173
+ * Gets a plain text version of the chat with id passed as parameter.
174
+ */
175
+ downloadChat = this.mutation(removeAuthorizationParam(downloadConversationV1ConversationsConversationIdDownloadGet))
176
+ /**
177
+ * Renames a chat.
178
+ */
179
+ renameChat = this.mutation(removeAuthorizationParam(updateTitleV1ConversationsConversationIdPatch))
180
+ /**
181
+ * Creates an event so it can be used as metric by the product designers (analytics).
182
+ */
183
+ createEvent = this.mutation(removeAuthorizationParam(postEventV1EventsPost))
184
+ /**
185
+ * Runs a step of type "fetch" of a quick command.
186
+ */
187
+ fetchStepOfQuickCommand = this.mutation(removeAuthorizationParam(formatFetchStepV1QuickCommandsSlugStepsStepSlugFetchFormatPost))
188
+ /**
189
+ * Remotely runs a step of type "fetch" of a quick command remotely (used when secrets are present).
190
+ */
191
+ fetchStepOfQuickCommandRemotely = this.mutation({
192
+ name: 'fetchStepOfQuickCommandRemotely',
193
+ request: (
194
+ signal,
195
+ variables: Omit<Parameters<typeof runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost>[0], 'authorization'> &
196
+ { headers?: Record<string, any> },
197
+ ) => {
198
+ const { headers, ...props } = variables
199
+ return runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost({ ...props, authorization: '' }, { signal, headers })
200
+ },
201
+ permission: this.createPermissionFunctionFor(runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost),
202
+ })
203
+
204
+ /**
205
+ * @deprecated This method does not use stream, only json. The json support has been removed
206
+ * So this method might not work as expected.
207
+ * Runs a step of type "llm" of a quick command.
208
+ */
209
+ llmStepOfQuickCommand = this.mutation(removeAuthorizationParam(quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost))
210
+ /**
211
+ * Calculates QC router next step.
212
+ */
213
+ calculateNextStep = this.mutation(removeAuthorizationParam(calculateNextStepV1QuickCommandsSlugStepsStepSlugCalculateNextStepPost))
214
+ /**
215
+ * Runs a stream of a step of type "llm" of a quick command.
216
+ */
217
+ streamLlmStepOfQuickCommand(slug: string, stepSlug: string, quickCommandsExecutionRequest: QuickCommandsExecutionRequest,
218
+ minChangeIntervalMS?: number):
219
+ StreamedJson<QuickCommandPromptResponse2> {
220
+ const abortController = new AbortController()
221
+ const headers = {
222
+ 'Content-Type': 'application/json',
223
+ 'Accept': 'text/event-stream',
224
+ }
225
+ const events = this.stream(
226
+ this.resolveURL(`/v2/quick-commands/${slug}/steps/${stepSlug}/run`),
227
+ { method: 'post', body: JSON.stringify(quickCommandsExecutionRequest), headers, signal: abortController.signal },
228
+ )
229
+
230
+ return new StreamedJson({
231
+ eventsPromise: events,
232
+ abortController,
233
+ minChangeIntervalMS,
234
+ })
235
+ }
236
+ /**
237
+ * Formats the result of a quick command into a human-readable text (markdown).
238
+ */
239
+ formatResultOfQuickCommand = this.mutation(removeAuthorizationParam(formatResultV1QuickCommandsSlugResultFormatPost))
240
+ /**
241
+ * Adds the resource of type Stack AI to the list of favorites.
242
+ */
243
+ addFavoriteStackAi = this.mutation(removeAuthorizationParam(addFavoriteV1AiStacksStackIdFavoritePost))
244
+ /**
245
+ * Removes the resource of type Stack AI from the list of favorites.
246
+ */
247
+ removeFavoriteStackAi = this.mutation(removeAuthorizationParam(deleteFavoriteV1AiStacksStackIdFavoriteDelete))
248
+ /**
249
+ * Updates a Quick Command
250
+ */
251
+ updateQuickCommand = this.mutation(removeAuthorizationParam(updateQuickCommandV1QuickCommandsSlugPatch))
252
+ /**
253
+ * Adds the resource of type Quick Command to the list of favorites.
254
+ */
255
+ addFavoriteQuickCommand = this.mutation(removeAuthorizationParam(addFavoriteV1QuickCommandsSlugFavoritePost))
256
+ /**
257
+ * Removes the resource of type Quick Command from the list of favorites.
258
+ */
259
+ removeFavoriteQuickCommand = this.mutation(removeAuthorizationParam(deleteFavoriteV1QuickCommandsSlugFavoriteDelete))
260
+
261
+ private static async toolsOfAgent(agentId?: string) {
262
+ try {
263
+ const agent = agentId ? await agentToolsClient.agent.query({ agentId }) : undefined
264
+ if (!agent) return []
265
+ const tools: (Omit<ChatAgentTool, 'duration' | 'prompt' | 'output'>)[] = []
266
+ agent.toolkits?.builtin_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
267
+ if (id) tools.push({ image: kit.image_url, id, name: name || id, description, goal: '' })
268
+ }))
269
+ agent.toolkits?.custom_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
270
+ if (id) tools.push({ image: kit.avatar ?? undefined, id, name: name || id, description, goal: '' })
271
+ }))
272
+ return tools
273
+ } catch {
274
+ return []
275
+ }
276
+ }
277
+
278
+ sendChatMessage(request: FixedChatRequest, minChangeIntervalMS?: number): StreamedJson<ChatResponseWithSteps> {
279
+ const abortController = new AbortController()
280
+ const headers = {
281
+ 'Content-Type': 'application/json',
282
+ 'Accept': 'text/event-stream',
283
+ }
284
+ const events = this.stream(
285
+ this.resolveURL('v3/chat'),
286
+ { method: 'post', body: JSON.stringify(request), headers, signal: abortController.signal },
287
+ )
288
+
289
+ /**
290
+ * This function treats events in the streaming that deals with the execution of tools. Since these events are not concatenated like
291
+ * normal streamings of data, we need this separate function to deal with them. It transforms the internal data model of the
292
+ * StreamedJson object whenever an event is triggered.
293
+ */
294
+ async function transform(event: Partial<FixedChatResponse>, data: Partial<ChatResponseWithSteps>) {
295
+ const info = event.agent_info
296
+ if (!info) return
297
+ const tools = await AIClient.toolsOfAgent(request.context?.agent_id)
298
+ data.steps = data.steps ? [...data.steps] : []
299
+
300
+ if (info.type === 'planning' && info.action === 'end') {
301
+ data.steps.push({
302
+ id: 'planning',
303
+ type: 'planning',
304
+ status: 'success',
305
+ duration: info.duration || 0,
306
+ steps: info.data?.steps?.map(s => s.goal) ?? [],
307
+ goal: info.data?.plan_goal ?? '',
308
+ })
309
+
310
+ info.data?.steps.forEach(s => data.steps?.push({
311
+ id: s.id,
312
+ type: 'step',
313
+ status: 'pending',
314
+ input: s.goal,
315
+ attempts: [{
316
+ tools: s.tools?.map(t => ({
317
+ ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
318
+ executionId: t.tool_execution_id,
319
+ goal: t.goal,
320
+ })),
321
+ }],
322
+ }))
323
+ data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
324
+ }
325
+
326
+ if (info.type === 'planning' && info.action === 'awaiting_approval') {
327
+ data.steps.push({
328
+ id: 'planning',
329
+ type: 'planning',
330
+ status: 'awaiting_approval',
331
+ user_question: info.data?.user_question,
332
+ duration: info.duration || 0,
333
+ steps: info.data?.steps?.map(s => s.goal) ?? [],
334
+ goal: info.data?.plan_goal ?? '',
335
+ })
336
+ info.data?.steps.forEach(s => data.steps?.push({
337
+ id: s.id,
338
+ type: 'step',
339
+ status: 'pending',
340
+ input: s.goal,
341
+ attempts: [{
342
+ tools: s.tools?.map(t => ({
343
+ ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
344
+ executionId: t.tool_execution_id,
345
+ goal: t.goal,
346
+ })),
347
+ }],
348
+ }))
349
+ data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
350
+ }
351
+
352
+ if (info.type === 'step' && info.action === 'start') {
353
+ const step = data.steps.find(s => s.id === info.id)
354
+ if (step) step.status = 'running'
355
+ }
356
+
357
+ if (info.type === 'step' && info.action === 'end') {
358
+ const step = data.steps.find(s => s.id === info.id) as StepChatStep
359
+ if (step) {
360
+ step.status = 'success'
361
+ step.duration = info.duration
362
+ const lastToolId = last(step.attempts[0].tools)?.id
363
+ const lastAttemptOfLastTool = findLast(step.attempts.map(a => a.tools).flat(), t => t?.id === lastToolId)
364
+ step.output = lastAttemptOfLastTool?.output
365
+ }
366
+ }
367
+
368
+ if (info.type === 'tool' && info.action === 'awaiting_approval') {
369
+ const tool = tools.find(({ id }) => id === info.data?.tool_id)
370
+ data.steps.push({
371
+ id: info.id,
372
+ type: 'tool',
373
+ status: 'awaiting_approval',
374
+ duration: info.duration || 0,
375
+ input: info.data?.input,
376
+ user_question: info.data?.user_question,
377
+ attempts: [{
378
+ tools: [{
379
+ executionId: info.id,
380
+ id: info.data?.tool_id ?? '',
381
+ name: tool?.name ?? '',
382
+ goal: tool?.goal ?? '',
383
+ ...tool,
384
+ }],
385
+ }],
386
+ })
387
+ data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
388
+ }
389
+
390
+ if (info.type === 'tool' && info.action === 'start') {
391
+ const currentStep = data.steps.find(s => s.status === 'running') as StepChatStep
392
+ if (!info.data) return
393
+
394
+ //There might be a tool with status awaiting_approval, so we want to inform tool has already started
395
+ if (!currentStep || !currentStep.attempts[0].tools) {
396
+ const input = formatJson(info.data.input)
397
+ const tool = tools.find(({ id }) => id === info.data?.tool_id) ?? { id: info.data?.tool_id, name: info.data?.tool_id }
398
+ data.steps.push({
399
+ id: info.id,
400
+ type: 'tool',
401
+ status: 'running',
402
+ duration: info.duration || 0,
403
+ input: info.data?.input,
404
+ user_question: info.data?.user_question,
405
+ attempts: [{
406
+ tools:[{ ...tool, executionId: info.id, input }],
407
+ }],
408
+ })
409
+ } else {
410
+ const toolInFirstAttempt = currentStep.attempts[0].tools.find(t => t.executionId === info.id)
411
+ if (!toolInFirstAttempt) return
412
+ const input = formatJson(info.data.input)
413
+ if (info.data.attempt === 1) {
414
+ toolInFirstAttempt.input = input
415
+ } else {
416
+ const tool = tools.find(({ id }) => id === info.data?.tool_id) ?? { id: info.data?.tool_id, name: info.data?.tool_id }
417
+ currentStep.attempts[info.data.attempt-1] ??= { tools: [] }
418
+ currentStep.attempts[info.data.attempt-1].tools?.push({
419
+ ...tool,
420
+ input,
421
+ })
422
+ }
423
+
424
+ }
425
+ }
426
+
427
+ if (info.type === 'tool' && info.action === 'end') {
428
+ const currentStep = data.steps.find(s => s.status === 'running') as StepChatStep
429
+ if (!currentStep || !info.data) return
430
+ const tool = currentStep.attempts[info.data.attempt-1]?.tools?.find(t => t.executionId === info.id)
431
+ if (tool) {
432
+ tool.output = formatJson(info.data.output)
433
+ tool.duration = info.duration
434
+ }
435
+ }
436
+
437
+ if (info.type === 'final_answer' && info.action === 'start') {
438
+ const answerStep = last(data.steps)
439
+ if (answerStep) answerStep.status = 'running'
440
+ }
441
+
442
+ if (info.type === 'final_answer' && info.action === 'end') {
443
+ const answerStep = last(data.steps)
444
+ if (answerStep) {
445
+ answerStep.status = 'success'
446
+ answerStep.duration = info.duration
447
+ }
448
+ }
449
+ }
450
+
451
+ return new StreamedJson({
452
+ eventsPromise: events,
453
+ abortController,
454
+ minChangeIntervalMS,
455
+ ignoreKeys: ['agent_info'],
456
+ transform,
457
+ })
458
+ }
459
+
460
+ contentDependencies = this.query(removeAuthorizationParam(
461
+ getContentDependenciesV1ContentContentTypeContentIdDependenciesGet as ReplaceResult<
462
+ typeof getContentDependenciesV1ContentContentTypeContentIdDependenciesGet,
463
+ FixedDependencyResponse
464
+ >,
465
+ ))
466
+ }
467
+
468
+ export const aiClient = new AIClient()
469
+