@stack-spot/portal-network 1.0.0-dev.1769537511491 → 1.0.0-dev.1769783915267

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 (58) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/api/accountAssetManager.d.ts +1 -0
  3. package/dist/api/accountAssetManager.d.ts.map +1 -1
  4. package/dist/api/accountAssetManager.js.map +1 -1
  5. package/dist/api/cloudPlatform.d.ts +79 -33
  6. package/dist/api/cloudPlatform.d.ts.map +1 -1
  7. package/dist/api/cloudPlatform.js +86 -76
  8. package/dist/api/cloudPlatform.js.map +1 -1
  9. package/dist/api/codeShift.d.ts +7 -3
  10. package/dist/api/codeShift.d.ts.map +1 -1
  11. package/dist/api/codeShift.js +3 -2
  12. package/dist/api/codeShift.js.map +1 -1
  13. package/dist/api/genAiInference.d.ts +49 -2
  14. package/dist/api/genAiInference.d.ts.map +1 -1
  15. package/dist/api/genAiInference.js +55 -2
  16. package/dist/api/genAiInference.js.map +1 -1
  17. package/dist/apis.json +3 -3
  18. package/dist/client/account.d.ts +16 -0
  19. package/dist/client/account.d.ts.map +1 -1
  20. package/dist/client/account.js +9 -0
  21. package/dist/client/account.js.map +1 -1
  22. package/dist/client/ai.d.ts +5 -28
  23. package/dist/client/ai.d.ts.map +1 -1
  24. package/dist/client/ai.js +1 -560
  25. package/dist/client/ai.js.map +1 -1
  26. package/dist/client/cloud-platform.d.ts +4 -12
  27. package/dist/client/cloud-platform.d.ts.map +1 -1
  28. package/dist/client/cloud-platform.js +5 -14
  29. package/dist/client/cloud-platform.js.map +1 -1
  30. package/dist/client/code-shift.d.ts +2 -1
  31. package/dist/client/code-shift.d.ts.map +1 -1
  32. package/dist/client/discover.d.ts +11 -4
  33. package/dist/client/discover.d.ts.map +1 -1
  34. package/dist/client/discover.js +140 -136
  35. package/dist/client/discover.js.map +1 -1
  36. package/dist/client/gen-ai-inference.d.ts +4 -0
  37. package/dist/client/gen-ai-inference.d.ts.map +1 -1
  38. package/dist/client/gen-ai-inference.js +267 -0
  39. package/dist/client/gen-ai-inference.js.map +1 -1
  40. package/dist/client/types.d.ts +12 -14
  41. package/dist/client/types.d.ts.map +1 -1
  42. package/dist/utils/StreamedJson.d.ts +7 -1
  43. package/dist/utils/StreamedJson.d.ts.map +1 -1
  44. package/dist/utils/StreamedJson.js +10 -2
  45. package/dist/utils/StreamedJson.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/api/accountAssetManager.ts +1 -0
  48. package/src/api/cloudPlatform.ts +170 -111
  49. package/src/api/codeShift.ts +9 -4
  50. package/src/api/genAiInference.ts +119 -3
  51. package/src/apis.json +8 -8
  52. package/src/client/account.ts +4 -0
  53. package/src/client/ai.ts +1 -626
  54. package/src/client/cloud-platform.ts +4 -9
  55. package/src/client/discover.ts +151 -137
  56. package/src/client/gen-ai-inference.ts +281 -0
  57. package/src/client/types.ts +13 -14
  58. package/src/utils/StreamedJson.tsx +11 -2
package/src/client/ai.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HttpError } from '@oazapfts/runtime'
2
- import { findLast, isArray, isNil, last } from 'lodash'
2
+ import { isArray } from 'lodash'
3
3
  import { getApiAddresses } from '../api-addresses'
4
4
  import {
5
5
  addFavoriteV1AiStacksStackIdFavoritePost,
@@ -46,13 +46,9 @@ import {
46
46
  postEventV1EventsPost,
47
47
  publishV1QuickCommandsSlugPublishPost,
48
48
  quickActionsV1QuickActionsPost,
49
- QuickCommandPromptResponse,
50
49
  QuickCommandPromptResponse2,
51
- QuickCommandScriptExecutionResponse,
52
50
  QuickCommandsExecutionRequest,
53
51
  quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost,
54
- QuickCommandStepFetchResponse,
55
- QuickCommandStepLlmResponse,
56
52
  resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete,
57
53
  runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost,
58
54
  searchKnowledgeSourcesV1KnowledgeSourcesSearchPost,
@@ -71,21 +67,10 @@ import { StackspotAPIError } from '../error/StackspotAPIError'
71
67
  import { ReactQueryNetworkClient } from '../network/ReactQueryNetworkClient'
72
68
  import { removeAuthorizationParam } from '../utils/remove-authorization-param'
73
69
  import { StreamedJson } from '../utils/StreamedJson'
74
- import { formatJson, getSizeOfString } from '../utils/string'
75
- import { agentToolsClient } from './agent-tools'
76
70
  import {
77
- AgentInfo,
78
- ChatAgentTool,
79
- ChatResponseWithSteps,
80
- FixedChatRequest,
81
- FixedChatResponse,
82
71
  FixedConversationResponse,
83
72
  FixedDependencyResponse,
84
- QCContext,
85
- QCContextExecution,
86
- QCProgressProps,
87
73
  ReplaceResult,
88
- StepChatStep,
89
74
  } from './types'
90
75
 
91
76
  const listQAV3WithoutAuthorization = removeAuthorizationParam(listAllV3QuickCommandsGet)
@@ -381,616 +366,6 @@ class AIClient extends ReactQueryNetworkClient {
381
366
  deleteReviewComment = this.mutation(
382
367
  removeAuthorizationParam(deleteReviewCommentV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdAnswersAnswerIdDelete))
383
368
 
384
- private static async toolsOfAgent(agentId?: string, agent_version_number?: number) {
385
- try {
386
- const agent = agentId ? await agentToolsClient.agentV2.query({
387
- agentCoreId: agentId, versionNumber: agent_version_number }) : undefined
388
- if (!agent) return []
389
- const tools: (Omit<ChatAgentTool, 'duration' | 'prompt' | 'output'>)[] = []
390
- agent.version?.toolkits?.builtin_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
391
- if (id) tools.push({ image: kit.image_url, id, name: name || id, description })
392
- }))
393
- agent.version?.toolkits?.custom_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
394
- if (id) tools.push({ image: kit.avatar ?? undefined, id, name: name || id, description })
395
- }))
396
- return tools
397
- } catch {
398
- return []
399
- }
400
- }
401
-
402
- /**
403
- * Runs an Router step of a quick command.
404
- */
405
- async runRouterStep(
406
- ctx: QCContextExecution,
407
- stepIndex: number, iteration: Record<string, number>,
408
- progress?:QCProgressProps,
409
- ) {
410
- const { qc: { slug, steps }, code, resultMap, customInputs } = ctx
411
- const step = steps![stepIndex]
412
- const inputData = Object.keys(customInputs).length > 0 && code ? { ...customInputs, [code]: code } : code ?? customInputs
413
- try {
414
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'START' } })
415
- if (step.slug in iteration) {
416
- iteration[step.slug] = iteration[step.slug] + 1
417
- } else {
418
- iteration[step.slug] = 1
419
- }
420
-
421
- const { next_step_slug } = await aiClient.calculateNextStep.mutate({
422
- stepSlug: step.slug,
423
- slug: slug,
424
- quickCommandEvaluateStepRouterRequest: {
425
- executions_count: iteration[step.slug],
426
- input_data: inputData,
427
- slugs_executions: resultMap,
428
- },
429
- })
430
-
431
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'END' } })
432
-
433
- if (next_step_slug === step.slug) {
434
- return aiClient.runStepsRecursively(stepIndex, ctx, iteration, progress)
435
- }
436
- const nextStepIndex = steps?.findIndex((step) => step.slug === next_step_slug)
437
-
438
- if (isNil(nextStepIndex) || nextStepIndex === -1) return
439
-
440
- return aiClient.runStepsRecursively(nextStepIndex, ctx, iteration, progress)
441
- }
442
- catch (error: any) {
443
- progress?.onStepChange?.({
444
- step: step.slug, error: error, answer: JSON.stringify(error.message), statusResult: 'ERROR', ...resultMap,
445
- })
446
- // eslint-disable-next-line no-console
447
- console.error('Error executing QC step', error)
448
- }
449
- }
450
-
451
- async getScriptStepStatus(
452
- scriptExecutionId: string,
453
- interval = 5000,
454
- maxAttempts = 500,
455
- currentAttempt = 0,
456
- ): Promise<QuickCommandScriptExecutionResponse> {
457
- if (currentAttempt >= maxAttempts) {
458
- throw new Error('Max attempts reached in verify script status')
459
- }
460
- await aiClient.getStatusScriptStep.invalidate({ scriptExecutionId })
461
- const response = await aiClient.getStatusScriptStep.query({ scriptExecutionId })
462
-
463
- if (response.status === 'success') {
464
- return response
465
- }
466
-
467
- if (response.status === 'failure') {
468
- throw response
469
- }
470
-
471
- await new Promise(resolve => {setTimeout(resolve, interval)})
472
-
473
- return aiClient.getScriptStepStatus(scriptExecutionId, interval, maxAttempts, currentAttempt + 1)
474
- }
475
- /**
476
- * Runs a fetch step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
477
- */
478
- async runFetchStep(ctx: QCContextExecution, stepIndex: number, progress?: QCProgressProps) {
479
- const { qc: { slug, steps }, code, context, resultMap, customInputs, executionId, signal } = ctx
480
- const step = steps![stepIndex] as QuickCommandStepFetchResponse
481
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: undefined, statusResult: 'START' })
482
-
483
- //If is_remote we call backend to execute for us and we only have the response
484
- if (step.is_remote) {
485
- ctx.isRemote = true
486
- try {
487
- const { data } = await aiClient.fetchStepOfQuickCommandRemotely.mutate({
488
- slug, stepSlug: step.slug,
489
- quickCommandsExecutionRequest: {
490
- code_selection: code, context, qc_execution_id: executionId,
491
- slugs_executions: { ...resultMap, ...customInputs },
492
- },
493
- }, signal)
494
-
495
- //data is the return of the request in the QC so we do not have full control over the response
496
- //We handle the usual format with body, status_code and headers, but we might also handle other formats
497
- const responseData = data as any
498
- progress?.onStepChange?.({
499
- step: step.slug, ...resultMap, answer: JSON.stringify(responseData.body) ?? JSON.stringify(responseData), statusResult: 'END' })
500
- resultMap[step.slug] = {
501
- status: responseData.status_code || 200,
502
- data: JSON.stringify(responseData.body) ?? JSON.stringify(responseData),
503
- headers: responseData.headers ?? {},
504
- }
505
- return
506
- } catch (error) {
507
- const errorMessage = `${error}, Failed to execute step "${step.slug}" of quick command "${slug}".`
508
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorMessage, error: errorMessage, statusResult: 'ERROR' })
509
- throw new Error(errorMessage)
510
- }
511
- }
512
-
513
- const { headers, data, method, url } = await aiClient.fetchStepOfQuickCommand.mutate({
514
- slug,
515
- stepSlug: step.slug,
516
- quickCommandsExecutionRequest: {
517
- input_data: code, context, qc_execution_id: executionId,
518
- slugs_executions: { ...resultMap, ...customInputs },
519
- },
520
- }, signal)
521
- const body = ['get', 'head'].includes(method.toLowerCase()) ? undefined : data
522
-
523
- try {
524
- //Local execution
525
- const response = await fetch(url, { headers: headers || undefined, body, method, signal })
526
- const responseData = await response.text()
527
- if (!response.ok) throw new Error(`Failed to execute step "${step.slug}" of quick command "${slug}". Status ${response.status}.`)
528
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: responseData, statusResult: 'END' })
529
-
530
- resultMap[step.slug] = {
531
- status: response.status,
532
- data: responseData,
533
- headers: Object.fromEntries(response.headers.entries()),
534
- }
535
- }
536
- catch (error) {
537
- const errorMessage = `${error}, Failed to execute step "${step.slug}" of quick command "${slug}".`
538
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorMessage, error: errorMessage, statusResult: 'ERROR' })
539
- throw new Error(errorMessage)
540
- }
541
- }
542
-
543
- /**
544
- * Runs an LLM step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
545
- */
546
- async runLLMStep(
547
- { qc: { slug, steps }, code, customInputs, context, executionId, resultMap, signal }: QCContextExecution,
548
- stepIndex: number,
549
- progress?: QCProgressProps,
550
- ) {
551
- const step = steps![stepIndex] as QuickCommandStepLlmResponse
552
- let stepContext = context
553
- if (!step.use_uploaded_files) {
554
- const { upload_ids: _upload_ids, ...contextDataProps } = context
555
- stepContext = { ...contextDataProps }
556
- }
557
- // eslint-disable-next-line no-async-promise-executor
558
- return new Promise(async (resolve) => {
559
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: undefined, statusResult: 'START' })
560
-
561
- const stream = aiClient.streamLlmStepOfQuickCommand(
562
- slug,
563
- step.slug,
564
- {
565
- input_data: code,
566
- context: stepContext,
567
- qc_execution_id: executionId,
568
- slugs_executions: { ...resultMap, ...customInputs },
569
- },
570
- )
571
-
572
- signal.addEventListener('abort', () => stream.cancel())
573
-
574
- stream.onChange(item => {
575
- if (item?.sources?.length) {
576
- progress?.onStepChange?.({ step: step.slug, ...resultMap, sources: JSON.stringify(item.sources) })
577
- } else {
578
- item.answer !== undefined && progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: item.answer })
579
- }
580
- })
581
-
582
- try {
583
- const finalValue = await stream.getValue()
584
- resultMap[step.slug] = finalValue
585
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: finalValue.answer,
586
- sources: finalValue.sources ? JSON.stringify(finalValue.sources) : '', statusResult: 'END' })
587
- resolve(finalValue)
588
- } catch (error: any) {
589
- // eslint-disable-next-line no-console
590
- console.error('Error executing QC step', error)
591
- const errorStep = `Failed to execute step "${step.slug}" of quick command "${slug}". Reason: ${error.message}`
592
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorStep, error: errorStep, statusResult: 'ERROR' })
593
- throw error
594
- }
595
- })
596
- }
597
-
598
- async runScriptStep(
599
- { qc: { slug, steps }, code, context, resultMap, customInputs, signal }: QCContextExecution,
600
- stepIndex: number,
601
- progress?: QCProgressProps,
602
- ) {
603
- const step = steps![stepIndex] as QuickCommandStepLlmResponse
604
- let stepContext = context
605
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'START' } })
606
-
607
- if (!step.use_uploaded_files) {
608
- const { upload_ids: _upload_ids, ...contextDataProps } = context
609
- stepContext = { ...contextDataProps }
610
- }
611
-
612
- try {
613
- const { script_execution_id } = await aiClient.startScriptStep.mutate({
614
- stepSlug: step.slug,
615
- slug: slug,
616
- quickCommandStartScriptRequest: {
617
- input_data: code,
618
- custom_inputs: customInputs,
619
- context: stepContext,
620
- slugs_executions: resultMap,
621
- },
622
- }, signal)
623
- const scriptResult = await aiClient.getScriptStepStatus(script_execution_id)
624
- progress?.onStepChange?.({ step: step.slug, ...scriptResult, ...{ statusResult: 'END' } })
625
- resultMap[step.slug] = scriptResult
626
- }
627
- catch (error: any) {
628
- progress?.onStepChange?.({ step: step.slug, ...error, statusResult: 'ERROR', ...resultMap })
629
- let message = error.result?.error ?? error.message ?? `${error}`
630
- if (error instanceof StackspotAPIError) message = error.translate()
631
- throw new Error(`Failed to execute step "${step.slug}" of quick command "${slug}". Error ${message}.`)
632
- }
633
- }
634
-
635
- async runStepsRecursively(currentIndex: number, ctx: QCContextExecution, iteration: Record<string, number>,
636
- progress?: QCProgressProps) {
637
- const { qc, resultMap } = ctx
638
-
639
- if (!qc.steps || currentIndex >= qc.steps?.length) return
640
- progress?.update?.(currentIndex)
641
-
642
- const currentStep = qc.steps[currentIndex]
643
-
644
- if (currentStep.type === 'ROUTER') {
645
- await aiClient.runRouterStep(ctx, currentIndex, iteration, progress)
646
- return
647
- }
648
-
649
- const parsedStep = currentStep as QuickCommandStepFetchResponse | QuickCommandStepLlmResponse
650
- let nextIndex = currentIndex + 1
651
- let nextStepSlug = parsedStep.next_step_slug
652
-
653
- if (currentStep.type === 'SCRIPT') {
654
- await aiClient.runScriptStep(ctx, currentIndex, progress)
655
- } else if (currentStep.type === 'FETCH') {
656
- await aiClient.runFetchStep(ctx, currentIndex, progress)
657
- } else {
658
- try {
659
- await aiClient.runLLMStep(ctx, currentIndex, progress)
660
- } catch (error: any) {
661
- progress?.onStepChange?.({ step: currentStep.slug,
662
- error: error, answer: JSON.stringify(error), statusResult: 'ERROR', ...resultMap })
663
- }
664
- const stepResult = resultMap[currentStep.slug] as QuickCommandPromptResponse
665
-
666
- //When we have an error but there is an error path defined
667
- if (typeof stepResult !== 'string' && stepResult.answer_status?.next_step_slug) {
668
- nextStepSlug = stepResult?.answer_status?.next_step_slug
669
- } else if (!stepResult?.answer_status?.success) { //When we have an error but no error path defined we should fail the execution
670
- progress?.onStepChange?.({
671
- step: currentStep.slug, error: stepResult?.answer_status,
672
- answer: JSON.stringify(stepResult?.answer_status?.failure_message), statusResult: 'ERROR', ...resultMap })
673
- throw new Error()
674
- }
675
- }
676
-
677
- const stepResult = ctx.resultMap[currentStep.slug]
678
- if (stepResult && typeof stepResult !== 'string' && 'answer_status' in stepResult && !!stepResult.answer_status?.next_step_slug) {
679
- nextStepSlug = stepResult.answer_status.next_step_slug
680
- }
681
-
682
- if (nextStepSlug) {
683
- nextIndex = nextStepSlug === 'end' ?
684
- qc.steps.length : qc.steps?.findIndex((step) => step.slug === nextStepSlug)
685
- }
686
- await aiClient.runStepsRecursively(nextIndex, ctx, iteration, progress)
687
- }
688
-
689
- async formatResult({ qc, code, executionId, context, resultMap, customInputs, signal }: QCContextExecution) {
690
- const formatted = await aiClient.formatResultOfQuickCommand.mutate({
691
- slug: qc.slug,
692
- quickCommandsExecutionRequest: {
693
- input_data: code,
694
- context,
695
- qc_execution_id: executionId,
696
- slugs_executions: { ...resultMap, ...customInputs },
697
- },
698
-
699
- }, signal)
700
- return formatted.result
701
- }
702
-
703
- /**
704
- * This registers a quick command event in the backend (analytics).
705
- */
706
- private async registerQCAnalyticsEvent({
707
- qc, isRemote, executionId, code = '', context }: QCContextExecution, status: string, start: number) {
708
- const now = new Date().getTime()
709
- try {
710
- await aiClient.createEvent.mutate({
711
- body: [{
712
- type: 'custom_quick_command_execution',
713
- quick_command_event: {
714
- type: qc.type || '',
715
- duration_execution: now - start,
716
- status_execution: status,
717
- slug: qc.slug,
718
- qc_execution_id: executionId,
719
- id: qc.id,
720
- is_remote: isRemote,
721
- },
722
- code,
723
- context,
724
- knowledge_sources: [],
725
- size: getSizeOfString(code),
726
- generated_at: now,
727
- }],
728
- })
729
- } catch (error) {
730
- // eslint-disable-next-line no-console
731
- console.warn('Failed to register event: quick command.')
732
- }
733
- }
734
-
735
- async runQuickCommand(ctx: QCContext, progress?: QCProgressProps) {
736
- const start = new Date().getTime()
737
-
738
- const { slug } = ctx
739
- const qc = await aiClient.quickCommand.query({ slug })
740
- const ctxExecution: QCContextExecution = { ...ctx, qc }
741
- try {
742
- await aiClient.runStepsRecursively(0, ctxExecution, {}, progress)
743
- progress?.remove?.()
744
- const result = await aiClient.formatResult(ctxExecution)
745
- await aiClient.registerQCAnalyticsEvent(ctxExecution, '200', start)
746
- return result
747
- } catch (error: any) {
748
- let message = error.message || `${error}`
749
- if (error instanceof StackspotAPIError) message = error.translate()
750
- await aiClient.registerQCAnalyticsEvent(ctxExecution, message, start)
751
- throw error
752
- }
753
- }
754
-
755
- sendChatMessage(request: FixedChatRequest, minChangeIntervalMS?: number): StreamedJson<ChatResponseWithSteps> {
756
- const abortController = new AbortController()
757
- const headers = {
758
- 'Content-Type': 'application/json',
759
- 'Accept': 'text/event-stream',
760
- }
761
- const events = this.stream(
762
- this.resolveURL('v3/chat'),
763
- { method: 'post', body: JSON.stringify(request), headers, signal: abortController.signal },
764
- )
765
-
766
- const DYNAMIC_TOOL_ID = 'dynamic'
767
- function isDynamicTool(info: AgentInfo) {
768
- return info.type === 'tool' && info.id === DYNAMIC_TOOL_ID
769
- }
770
- /**
771
- * This function treats events in the streaming that deals with the execution of tools. Since these events are not concatenated like
772
- * normal streamings of data, we need this separate function to deal with them. It transforms the internal data model of the
773
- * StreamedJson object whenever an event is triggered.
774
- */
775
- async function transform(event: Partial<FixedChatResponse>, data: Partial<ChatResponseWithSteps>) {
776
- const info = event.agent_info
777
- if (!info) return
778
- const tools = await AIClient.toolsOfAgent(request.context?.agent_id, request.agent_version_number ?? undefined)
779
- data.steps = data.steps ? [...data.steps] : []
780
-
781
- if (info.type === 'planning' && info.action === 'end') {
782
- data.steps.push({
783
- id: 'planning',
784
- type: 'planning',
785
- status: 'success',
786
- duration: info.duration || 0,
787
- steps: info.data?.steps?.map(s => s.goal) ?? [],
788
- goal: info.data?.plan_goal ?? '',
789
- })
790
-
791
- info.data?.steps.forEach(s => data.steps?.push({
792
- id: s.id,
793
- type: 'step',
794
- status: 'pending',
795
- input: s.goal,
796
- attempts: [{
797
- tools: s.tools?.map(t => ({
798
- ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
799
- executionId: t.tool_execution_id,
800
- goal: t.goal,
801
- })),
802
- }],
803
- }))
804
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
805
- }
806
-
807
- if (info.type === 'planning' && info.action === 'awaiting_approval') {
808
- data.steps.push({
809
- id: 'planning',
810
- type: 'planning',
811
- status: 'awaiting_approval',
812
- user_question: info.data?.user_question,
813
- duration: info.duration || 0,
814
- steps: info.data?.steps?.map(s => s.goal) ?? [],
815
- goal: info.data?.plan_goal ?? '',
816
- })
817
- info.data?.steps.forEach(s => data.steps?.push({
818
- id: s.id,
819
- type: 'step',
820
- status: 'pending',
821
- input: s.goal,
822
- attempts: [{
823
- tools: s.tools?.map(t => ({
824
- ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
825
- executionId: t.tool_execution_id,
826
- goal: t.goal,
827
- })),
828
- }],
829
- }))
830
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
831
- }
832
-
833
- if (info.type === 'step' && info.action === 'start') {
834
- const step = data.steps.find(s => s.id === info.id)
835
- if (step) step.status = 'running'
836
- }
837
-
838
- if (info.type === 'step' && info.action === 'end') {
839
- const step = data.steps.find(s => s.id === info.id) as StepChatStep
840
- if (step) {
841
- step.status = 'success'
842
- step.duration = info.duration
843
- const lastToolId = last(step.attempts[0].tools)?.id
844
- const lastAttemptOfLastTool = findLast(step.attempts.map(a => a.tools).flat(), t => t?.id === lastToolId)
845
- step.output = lastAttemptOfLastTool?.output
846
- }
847
- }
848
-
849
- if (info.type === 'tool_calls' && info.action === 'start') {
850
- const hasPlanning = data.steps.find(s => s.type === 'planning')
851
- // On the first tool_calls:start, create the synthetic planning ("dynamic") step.
852
- if (!hasPlanning) {
853
- const userPrompt = request.user_prompt === 'string' ? request.user_prompt : JSON.stringify(request.user_prompt)
854
- data.steps.push({
855
- id: 'dynamic',
856
- type: 'planning',
857
- status: 'success',
858
- steps: [],
859
- goal: userPrompt,
860
- user_question: userPrompt,
861
- })
862
- }
863
- const toolsStepId = data.steps.filter(s => s.id === 'tools' || s.id.startsWith('tools-')).length + 1
864
- data.steps.push({
865
- id: `tools-${toolsStepId.toString()}`,
866
- type: 'step',
867
- status: 'running',
868
- attempts: [{ tools: [] }],
869
- } as StepChatStep)
870
- }
871
-
872
- if (info.type === 'tool_calls' && info.action === 'end') {
873
- const lastStep = findLast(data.steps, s => s.id === 'tools' || s.id.startsWith('tools-')) as StepChatStep
874
- if (lastStep) {
875
- lastStep.status = 'success'
876
- lastStep.duration = info.duration
877
- const lastAttemptOfLastTool = last(lastStep.attempts.map(a => a.tools).flat())
878
- lastStep.output = lastAttemptOfLastTool?.output
879
- }
880
- }
881
-
882
- if (info.type === 'tool' && info.action === 'awaiting_approval') {
883
- const tool = tools.find(({ id }) => id === info.data?.tool_id)
884
- data.steps.push({
885
- id: info.id,
886
- type: 'tool',
887
- status: 'awaiting_approval',
888
- duration: info.duration || 0,
889
- input: info.data?.input,
890
- user_question: info.data?.user_question,
891
- attempts: [{
892
- tools: [{
893
- executionId: info.id,
894
- id: info.data?.tool_id ?? '',
895
- name: tool?.name ?? '',
896
- goal: tool?.goal,
897
- ...tool,
898
- }],
899
- }],
900
- })
901
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' })
902
- }
903
-
904
- if (info.type === 'tool' && info.action === 'start') {
905
- if (!info.data) return
906
- const input = formatJson(info.data.input)
907
- const tool = findLast(tools, ({ id }) => id === info.data?.tool_id) ?? { id: info.data?.tool_id, name: info.data?.tool_id }
908
-
909
- const currentStep = findLast(data.steps, s => s.status === 'running') as StepChatStep
910
-
911
- //There might be a tool with status awaiting_approval, so we want to inform tool has already started
912
- if (!currentStep || !currentStep?.attempts?.[0]?.tools) {
913
- data.steps.push({
914
- id: info.id,
915
- type: 'tool',
916
- status: 'running',
917
- duration: info.duration || 0,
918
- input: info.data?.input,
919
- user_question: info.data?.user_question,
920
- attempts: [{
921
- tools: [{ ...tool, executionId: info.id, input }],
922
- }],
923
- })
924
- } else {
925
- const toolInFirstAttempt = findLast(currentStep?.attempts?.[0]?.tools, t => t.executionId === info.id)
926
- //One step might have multiple tools. When in an approval mode, we might not have all the tools in the array yet.
927
- //For dynamic tools (id === 'dynamic'), we always push a new tool, since dynamic executions can trigger
928
- //multiple tool runs in the same step and do not follow the planned tool structure.
929
- //So we make sure to add any tools that are not in there, or always add for dynamic tools.
930
- if (!toolInFirstAttempt || isDynamicTool(info)) {
931
- currentStep.attempts?.[0].tools?.push({
932
- ...tool,
933
- executionId: info.id,
934
- input,
935
- status: 'running',
936
- })
937
- } else {
938
- const input = formatJson(info.data.input)
939
- if (info.data.attempt === 1) {
940
- toolInFirstAttempt.input = input
941
- } else {
942
- currentStep.attempts[info.data.attempt - 1] ??= { tools: [] }
943
- currentStep.attempts[info.data.attempt - 1].tools?.push({
944
- ...tool,
945
- executionId: info.id,
946
- input,
947
- })
948
- }
949
- }
950
- }
951
- }
952
-
953
- if (info.type === 'tool' && info.action === 'end') {
954
- const currentStep = data.steps.find(s => s.status === 'running') as StepChatStep
955
- if (!currentStep || !info.data) return
956
-
957
- // attempt index for tool execution starts at 0 for dynamically executed tools,while for planned tools it starts at 1
958
- const attempt = isDynamicTool(info) ? info.data.attempt : info.data.attempt - 1
959
- const tool = last(currentStep?.attempts?.[attempt]?.tools)
960
- if (tool) {
961
- tool.output = formatJson(info.data.output)
962
- tool.duration = info.duration
963
- tool.status = 'success'
964
- }
965
- }
966
-
967
- if (info.type === 'final_answer' && info.action === 'start') {
968
- const answerStep = last(data.steps)
969
- if (answerStep) answerStep.status = 'running'
970
- }
971
-
972
-
973
- if (info.type === 'chat' && info.action === 'end') {
974
- const lastStep = last(data.steps)
975
- if (lastStep?.type === 'answer') {
976
- lastStep.status = 'success'
977
- lastStep.duration = info.duration
978
- } else {
979
- data.steps.push({ id: 'answer', type: 'answer', status: 'success' })
980
- }
981
- }
982
- }
983
-
984
- return new StreamedJson({
985
- eventsPromise: events,
986
- abortController,
987
- minChangeIntervalMS,
988
- ignoreKeys: ['agent_info'],
989
- transform,
990
- textFromErrorEvent: data => data.answer ?? 'Unknown error',
991
- })
992
- }
993
-
994
369
  contentDependencies = this.query(removeAuthorizationParam(
995
370
  getContentDependenciesV1ContentContentTypeContentIdDependenciesGet as ReplaceResult<
996
371
  typeof getContentDependenciesV1ContentContentTypeContentIdDependenciesGet,
@@ -36,7 +36,6 @@ import {
36
36
  listRuntime,
37
37
  listTenant,
38
38
  listVpns,
39
- providers,
40
39
  putCertificateTags,
41
40
  putCidrTags,
42
41
  putDnsZoneTags,
@@ -72,10 +71,6 @@ class CloudPlatformClient extends ReactQueryNetworkClient {
72
71
  * Get list of foundations folders or folder by id
73
72
  */
74
73
  getFolder = this.query(removeAuthorizationParam(getFolder))
75
- /**
76
- * Get list of providers for a foundation
77
- */
78
- listProviders = this.query(removeAuthorizationParam(providers))
79
74
  /**
80
75
  * Create a foundation
81
76
  */
@@ -225,12 +220,12 @@ class CloudPlatformClient extends ReactQueryNetworkClient {
225
220
  */
226
221
  deleteDnsRecord = this.mutation(removeAuthorizationParam(deleteDnsRecord))
227
222
  /**
228
- * Delete a VPN
229
- */
223
+ * Delete a VPN
224
+ */
230
225
  deleteVPN = this.mutation(removeAuthorizationParam(deleteVpn))
231
226
  /**
232
- * Delete a CIDR
233
- */
227
+ * Delete a CIDR
228
+ */
234
229
  deleteCidr = this.mutation(removeAuthorizationParam(deleteCidr))
235
230
  }
236
231