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

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 +54 -3
  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 +13 -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 +124 -4
  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 +14 -14
  58. package/src/utils/StreamedJson.tsx +11 -2
package/dist/client/ai.js CHANGED
@@ -1,12 +1,10 @@
1
- import { findLast, isArray, isNil, last } from 'lodash';
1
+ import { isArray } from 'lodash';
2
2
  import { getApiAddresses } from '../api-addresses.js';
3
3
  import { addFavoriteV1AiStacksStackIdFavoritePost, addFavoriteV1QuickCommandsSlugFavoritePost, calculateNextStepV1QuickCommandsSlugStepsStepSlugCalculateNextStepPost, callbackV1QuickCommandsCallbackExecutionIdGet, checkQuickCommandExistsV1QuickCommandsSlugExistsGet, conversationHistoryV1ConversationsConversationIdGet, createAnswerForReviewV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdAnswersPost, createExecutionV1QuickCommandsCreateExecutionSlugPost, createQuickCommandV1QuickCommandsPost, createResourceReviewV1ResourcesResourceTypeSlugResourceSlugReviewsPost, currentV1TokensUsageCurrentGet, defaults, deleteConversationV1ConversationsConversationIdDelete, deleteFavoriteV1AiStacksStackIdFavoriteDelete, deleteFavoriteV1QuickCommandsSlugFavoriteDelete, deleteKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdDelete, deleteKnowledgeSourceV1KnowledgeSourcesSlugDelete, deleteQuickCommandV1QuickCommandsSlugDelete, deleteResourceReviewV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdDelete, deleteReviewCommentV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdAnswersAnswerIdDelete, downloadConversationV1ConversationsConversationIdDownloadGet, findKnowledgeObjectByCustomIdV1KnowledgeSourcesSlugObjectsCustomIdGet, findKnowledgeSourceDependenciesV1KnowledgeSourcesSlugDependenciesGet, findKnowledgeSourceV1KnowledgeSourcesSlugGet, forkV1QuickCommandsSlugForkPost, formatFetchStepV1QuickCommandsSlugStepsStepSlugFetchFormatPost, formatResultV1QuickCommandsSlugResultFormatPost, getContentDependenciesV1ContentContentTypeContentIdDependenciesGet, getFlagsV1FlagsGet, getQuickCommandV1QuickCommandsSlugGet, getReviewsByResourceV1ResourcesResourceTypeSlugResourceSlugReviewsGet, getScriptExecutionStatusV1QuickCommandsScriptExecutionsScriptExecutionIdGet, getUploadFormV1FileUploadFormPost, listAiStacksV1AiStacksGet, listAllV1QuickCommandsAllGet, listAllV2QuickCommandsAllGet, listAllV3QuickCommandsGet, listAssociationV1WorkspaceWorkspaceIdGet, listConversationsV1ConversationsGet, listKnowledgeSourcesV1KnowledgeSourcesGet, postEventV1EventsPost, publishV1QuickCommandsSlugPublishPost, quickActionsV1QuickActionsPost, quickCommandsRunV2V2QuickCommandsSlugStepsStepSlugRunPost, resetKnowledgeObjectsV1KnowledgeSourcesSlugObjectsDelete, runFetchStepV1QuickCommandsSlugStepsStepSlugFetchRunPost, searchKnowledgeSourcesV1KnowledgeSourcesSearchPost, startScriptStepV1QuickCommandsSlugStepsStepSlugStartScriptPost, tokensByUserV1AnalyticsTokensByUserGet, tokensDailyUsageV1AnalyticsTokensDailyUsageGet, totalV1TokensUsageTotalGet, updateQuickCommandV1QuickCommandsSlugPatch, updateResourceReviewV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdPatch, updateReviewCommentV1ResourcesResourceTypeSlugResourceSlugReviewsReviewIdAnswersAnswerIdPatch, updateTitleV1ConversationsConversationIdPatch, vectorizeCustomKnowledgeSourceV1KnowledgeSourcesSlugCustomPost, } from '../api/ai.js';
4
4
  import { StackspotAPIError } from '../error/StackspotAPIError.js';
5
5
  import { ReactQueryNetworkClient } from '../network/ReactQueryNetworkClient.js';
6
6
  import { removeAuthorizationParam } from '../utils/remove-authorization-param.js';
7
7
  import { StreamedJson } from '../utils/StreamedJson.js';
8
- import { formatJson, getSizeOfString } from '../utils/string.js';
9
- import { agentToolsClient } from './agent-tools.js';
10
8
  const listQAV3WithoutAuthorization = removeAuthorizationParam(listAllV3QuickCommandsGet);
11
9
  class AIClient extends ReactQueryNetworkClient {
12
10
  constructor() {
@@ -540,563 +538,6 @@ class AIClient extends ReactQueryNetworkClient {
540
538
  minChangeIntervalMS,
541
539
  });
542
540
  }
543
- static async toolsOfAgent(agentId, agent_version_number) {
544
- try {
545
- const agent = agentId ? await agentToolsClient.agentV2.query({
546
- agentCoreId: agentId, versionNumber: agent_version_number
547
- }) : undefined;
548
- if (!agent)
549
- return [];
550
- const tools = [];
551
- agent.version?.toolkits?.builtin_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
552
- if (id)
553
- tools.push({ image: kit.image_url, id, name: name || id, description });
554
- }));
555
- agent.version?.toolkits?.custom_toolkits?.forEach(kit => kit.tools?.forEach(({ id, name, description }) => {
556
- if (id)
557
- tools.push({ image: kit.avatar ?? undefined, id, name: name || id, description });
558
- }));
559
- return tools;
560
- }
561
- catch {
562
- return [];
563
- }
564
- }
565
- /**
566
- * Runs an Router step of a quick command.
567
- */
568
- async runRouterStep(ctx, stepIndex, iteration, progress) {
569
- const { qc: { slug, steps }, code, resultMap, customInputs } = ctx;
570
- const step = steps[stepIndex];
571
- const inputData = Object.keys(customInputs).length > 0 && code ? { ...customInputs, [code]: code } : code ?? customInputs;
572
- try {
573
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'START' } });
574
- if (step.slug in iteration) {
575
- iteration[step.slug] = iteration[step.slug] + 1;
576
- }
577
- else {
578
- iteration[step.slug] = 1;
579
- }
580
- const { next_step_slug } = await aiClient.calculateNextStep.mutate({
581
- stepSlug: step.slug,
582
- slug: slug,
583
- quickCommandEvaluateStepRouterRequest: {
584
- executions_count: iteration[step.slug],
585
- input_data: inputData,
586
- slugs_executions: resultMap,
587
- },
588
- });
589
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'END' } });
590
- if (next_step_slug === step.slug) {
591
- return aiClient.runStepsRecursively(stepIndex, ctx, iteration, progress);
592
- }
593
- const nextStepIndex = steps?.findIndex((step) => step.slug === next_step_slug);
594
- if (isNil(nextStepIndex) || nextStepIndex === -1)
595
- return;
596
- return aiClient.runStepsRecursively(nextStepIndex, ctx, iteration, progress);
597
- }
598
- catch (error) {
599
- progress?.onStepChange?.({
600
- step: step.slug, error: error, answer: JSON.stringify(error.message), statusResult: 'ERROR', ...resultMap,
601
- });
602
- // eslint-disable-next-line no-console
603
- console.error('Error executing QC step', error);
604
- }
605
- }
606
- async getScriptStepStatus(scriptExecutionId, interval = 5000, maxAttempts = 500, currentAttempt = 0) {
607
- if (currentAttempt >= maxAttempts) {
608
- throw new Error('Max attempts reached in verify script status');
609
- }
610
- await aiClient.getStatusScriptStep.invalidate({ scriptExecutionId });
611
- const response = await aiClient.getStatusScriptStep.query({ scriptExecutionId });
612
- if (response.status === 'success') {
613
- return response;
614
- }
615
- if (response.status === 'failure') {
616
- throw response;
617
- }
618
- await new Promise(resolve => { setTimeout(resolve, interval); });
619
- return aiClient.getScriptStepStatus(scriptExecutionId, interval, maxAttempts, currentAttempt + 1);
620
- }
621
- /**
622
- * Runs a fetch step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
623
- */
624
- async runFetchStep(ctx, stepIndex, progress) {
625
- const { qc: { slug, steps }, code, context, resultMap, customInputs, executionId, signal } = ctx;
626
- const step = steps[stepIndex];
627
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: undefined, statusResult: 'START' });
628
- //If is_remote we call backend to execute for us and we only have the response
629
- if (step.is_remote) {
630
- ctx.isRemote = true;
631
- try {
632
- const { data } = await aiClient.fetchStepOfQuickCommandRemotely.mutate({
633
- slug, stepSlug: step.slug,
634
- quickCommandsExecutionRequest: {
635
- code_selection: code, context, qc_execution_id: executionId,
636
- slugs_executions: { ...resultMap, ...customInputs },
637
- },
638
- }, signal);
639
- //data is the return of the request in the QC so we do not have full control over the response
640
- //We handle the usual format with body, status_code and headers, but we might also handle other formats
641
- const responseData = data;
642
- progress?.onStepChange?.({
643
- step: step.slug, ...resultMap, answer: JSON.stringify(responseData.body) ?? JSON.stringify(responseData), statusResult: 'END'
644
- });
645
- resultMap[step.slug] = {
646
- status: responseData.status_code || 200,
647
- data: JSON.stringify(responseData.body) ?? JSON.stringify(responseData),
648
- headers: responseData.headers ?? {},
649
- };
650
- return;
651
- }
652
- catch (error) {
653
- const errorMessage = `${error}, Failed to execute step "${step.slug}" of quick command "${slug}".`;
654
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorMessage, error: errorMessage, statusResult: 'ERROR' });
655
- throw new Error(errorMessage);
656
- }
657
- }
658
- const { headers, data, method, url } = await aiClient.fetchStepOfQuickCommand.mutate({
659
- slug,
660
- stepSlug: step.slug,
661
- quickCommandsExecutionRequest: {
662
- input_data: code, context, qc_execution_id: executionId,
663
- slugs_executions: { ...resultMap, ...customInputs },
664
- },
665
- }, signal);
666
- const body = ['get', 'head'].includes(method.toLowerCase()) ? undefined : data;
667
- try {
668
- //Local execution
669
- const response = await fetch(url, { headers: headers || undefined, body, method, signal });
670
- const responseData = await response.text();
671
- if (!response.ok)
672
- throw new Error(`Failed to execute step "${step.slug}" of quick command "${slug}". Status ${response.status}.`);
673
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: responseData, statusResult: 'END' });
674
- resultMap[step.slug] = {
675
- status: response.status,
676
- data: responseData,
677
- headers: Object.fromEntries(response.headers.entries()),
678
- };
679
- }
680
- catch (error) {
681
- const errorMessage = `${error}, Failed to execute step "${step.slug}" of quick command "${slug}".`;
682
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorMessage, error: errorMessage, statusResult: 'ERROR' });
683
- throw new Error(errorMessage);
684
- }
685
- }
686
- /**
687
- * Runs an LLM step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
688
- */
689
- async runLLMStep({ qc: { slug, steps }, code, customInputs, context, executionId, resultMap, signal }, stepIndex, progress) {
690
- const step = steps[stepIndex];
691
- let stepContext = context;
692
- if (!step.use_uploaded_files) {
693
- const { upload_ids: _upload_ids, ...contextDataProps } = context;
694
- stepContext = { ...contextDataProps };
695
- }
696
- // eslint-disable-next-line no-async-promise-executor
697
- return new Promise(async (resolve) => {
698
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: undefined, statusResult: 'START' });
699
- const stream = aiClient.streamLlmStepOfQuickCommand(slug, step.slug, {
700
- input_data: code,
701
- context: stepContext,
702
- qc_execution_id: executionId,
703
- slugs_executions: { ...resultMap, ...customInputs },
704
- });
705
- signal.addEventListener('abort', () => stream.cancel());
706
- stream.onChange(item => {
707
- if (item?.sources?.length) {
708
- progress?.onStepChange?.({ step: step.slug, ...resultMap, sources: JSON.stringify(item.sources) });
709
- }
710
- else {
711
- item.answer !== undefined && progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: item.answer });
712
- }
713
- });
714
- try {
715
- const finalValue = await stream.getValue();
716
- resultMap[step.slug] = finalValue;
717
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: finalValue.answer,
718
- sources: finalValue.sources ? JSON.stringify(finalValue.sources) : '', statusResult: 'END' });
719
- resolve(finalValue);
720
- }
721
- catch (error) {
722
- // eslint-disable-next-line no-console
723
- console.error('Error executing QC step', error);
724
- const errorStep = `Failed to execute step "${step.slug}" of quick command "${slug}". Reason: ${error.message}`;
725
- progress?.onStepChange?.({ step: step.slug, ...resultMap, answer: errorStep, error: errorStep, statusResult: 'ERROR' });
726
- throw error;
727
- }
728
- });
729
- }
730
- async runScriptStep({ qc: { slug, steps }, code, context, resultMap, customInputs, signal }, stepIndex, progress) {
731
- const step = steps[stepIndex];
732
- let stepContext = context;
733
- progress?.onStepChange?.({ step: step.slug, ...resultMap, ...{ statusResult: 'START' } });
734
- if (!step.use_uploaded_files) {
735
- const { upload_ids: _upload_ids, ...contextDataProps } = context;
736
- stepContext = { ...contextDataProps };
737
- }
738
- try {
739
- const { script_execution_id } = await aiClient.startScriptStep.mutate({
740
- stepSlug: step.slug,
741
- slug: slug,
742
- quickCommandStartScriptRequest: {
743
- input_data: code,
744
- custom_inputs: customInputs,
745
- context: stepContext,
746
- slugs_executions: resultMap,
747
- },
748
- }, signal);
749
- const scriptResult = await aiClient.getScriptStepStatus(script_execution_id);
750
- progress?.onStepChange?.({ step: step.slug, ...scriptResult, ...{ statusResult: 'END' } });
751
- resultMap[step.slug] = scriptResult;
752
- }
753
- catch (error) {
754
- progress?.onStepChange?.({ step: step.slug, ...error, statusResult: 'ERROR', ...resultMap });
755
- let message = error.result?.error ?? error.message ?? `${error}`;
756
- if (error instanceof StackspotAPIError)
757
- message = error.translate();
758
- throw new Error(`Failed to execute step "${step.slug}" of quick command "${slug}". Error ${message}.`);
759
- }
760
- }
761
- async runStepsRecursively(currentIndex, ctx, iteration, progress) {
762
- const { qc, resultMap } = ctx;
763
- if (!qc.steps || currentIndex >= qc.steps?.length)
764
- return;
765
- progress?.update?.(currentIndex);
766
- const currentStep = qc.steps[currentIndex];
767
- if (currentStep.type === 'ROUTER') {
768
- await aiClient.runRouterStep(ctx, currentIndex, iteration, progress);
769
- return;
770
- }
771
- const parsedStep = currentStep;
772
- let nextIndex = currentIndex + 1;
773
- let nextStepSlug = parsedStep.next_step_slug;
774
- if (currentStep.type === 'SCRIPT') {
775
- await aiClient.runScriptStep(ctx, currentIndex, progress);
776
- }
777
- else if (currentStep.type === 'FETCH') {
778
- await aiClient.runFetchStep(ctx, currentIndex, progress);
779
- }
780
- else {
781
- try {
782
- await aiClient.runLLMStep(ctx, currentIndex, progress);
783
- }
784
- catch (error) {
785
- progress?.onStepChange?.({ step: currentStep.slug,
786
- error: error, answer: JSON.stringify(error), statusResult: 'ERROR', ...resultMap });
787
- }
788
- const stepResult = resultMap[currentStep.slug];
789
- //When we have an error but there is an error path defined
790
- if (typeof stepResult !== 'string' && stepResult.answer_status?.next_step_slug) {
791
- nextStepSlug = stepResult?.answer_status?.next_step_slug;
792
- }
793
- else if (!stepResult?.answer_status?.success) { //When we have an error but no error path defined we should fail the execution
794
- progress?.onStepChange?.({
795
- step: currentStep.slug, error: stepResult?.answer_status,
796
- answer: JSON.stringify(stepResult?.answer_status?.failure_message), statusResult: 'ERROR', ...resultMap
797
- });
798
- throw new Error();
799
- }
800
- }
801
- const stepResult = ctx.resultMap[currentStep.slug];
802
- if (stepResult && typeof stepResult !== 'string' && 'answer_status' in stepResult && !!stepResult.answer_status?.next_step_slug) {
803
- nextStepSlug = stepResult.answer_status.next_step_slug;
804
- }
805
- if (nextStepSlug) {
806
- nextIndex = nextStepSlug === 'end' ?
807
- qc.steps.length : qc.steps?.findIndex((step) => step.slug === nextStepSlug);
808
- }
809
- await aiClient.runStepsRecursively(nextIndex, ctx, iteration, progress);
810
- }
811
- async formatResult({ qc, code, executionId, context, resultMap, customInputs, signal }) {
812
- const formatted = await aiClient.formatResultOfQuickCommand.mutate({
813
- slug: qc.slug,
814
- quickCommandsExecutionRequest: {
815
- input_data: code,
816
- context,
817
- qc_execution_id: executionId,
818
- slugs_executions: { ...resultMap, ...customInputs },
819
- },
820
- }, signal);
821
- return formatted.result;
822
- }
823
- /**
824
- * This registers a quick command event in the backend (analytics).
825
- */
826
- async registerQCAnalyticsEvent({ qc, isRemote, executionId, code = '', context }, status, start) {
827
- const now = new Date().getTime();
828
- try {
829
- await aiClient.createEvent.mutate({
830
- body: [{
831
- type: 'custom_quick_command_execution',
832
- quick_command_event: {
833
- type: qc.type || '',
834
- duration_execution: now - start,
835
- status_execution: status,
836
- slug: qc.slug,
837
- qc_execution_id: executionId,
838
- id: qc.id,
839
- is_remote: isRemote,
840
- },
841
- code,
842
- context,
843
- knowledge_sources: [],
844
- size: getSizeOfString(code),
845
- generated_at: now,
846
- }],
847
- });
848
- }
849
- catch (error) {
850
- // eslint-disable-next-line no-console
851
- console.warn('Failed to register event: quick command.');
852
- }
853
- }
854
- async runQuickCommand(ctx, progress) {
855
- const start = new Date().getTime();
856
- const { slug } = ctx;
857
- const qc = await aiClient.quickCommand.query({ slug });
858
- const ctxExecution = { ...ctx, qc };
859
- try {
860
- await aiClient.runStepsRecursively(0, ctxExecution, {}, progress);
861
- progress?.remove?.();
862
- const result = await aiClient.formatResult(ctxExecution);
863
- await aiClient.registerQCAnalyticsEvent(ctxExecution, '200', start);
864
- return result;
865
- }
866
- catch (error) {
867
- let message = error.message || `${error}`;
868
- if (error instanceof StackspotAPIError)
869
- message = error.translate();
870
- await aiClient.registerQCAnalyticsEvent(ctxExecution, message, start);
871
- throw error;
872
- }
873
- }
874
- sendChatMessage(request, minChangeIntervalMS) {
875
- const abortController = new AbortController();
876
- const headers = {
877
- 'Content-Type': 'application/json',
878
- 'Accept': 'text/event-stream',
879
- };
880
- const events = this.stream(this.resolveURL('v3/chat'), { method: 'post', body: JSON.stringify(request), headers, signal: abortController.signal });
881
- const DYNAMIC_TOOL_ID = 'dynamic';
882
- function isDynamicTool(info) {
883
- return info.type === 'tool' && info.id === DYNAMIC_TOOL_ID;
884
- }
885
- /**
886
- * This function treats events in the streaming that deals with the execution of tools. Since these events are not concatenated like
887
- * normal streamings of data, we need this separate function to deal with them. It transforms the internal data model of the
888
- * StreamedJson object whenever an event is triggered.
889
- */
890
- async function transform(event, data) {
891
- const info = event.agent_info;
892
- if (!info)
893
- return;
894
- const tools = await AIClient.toolsOfAgent(request.context?.agent_id, request.agent_version_number ?? undefined);
895
- data.steps = data.steps ? [...data.steps] : [];
896
- if (info.type === 'planning' && info.action === 'end') {
897
- data.steps.push({
898
- id: 'planning',
899
- type: 'planning',
900
- status: 'success',
901
- duration: info.duration || 0,
902
- steps: info.data?.steps?.map(s => s.goal) ?? [],
903
- goal: info.data?.plan_goal ?? '',
904
- });
905
- info.data?.steps.forEach(s => data.steps?.push({
906
- id: s.id,
907
- type: 'step',
908
- status: 'pending',
909
- input: s.goal,
910
- attempts: [{
911
- tools: s.tools?.map(t => ({
912
- ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
913
- executionId: t.tool_execution_id,
914
- goal: t.goal,
915
- })),
916
- }],
917
- }));
918
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' });
919
- }
920
- if (info.type === 'planning' && info.action === 'awaiting_approval') {
921
- data.steps.push({
922
- id: 'planning',
923
- type: 'planning',
924
- status: 'awaiting_approval',
925
- user_question: info.data?.user_question,
926
- duration: info.duration || 0,
927
- steps: info.data?.steps?.map(s => s.goal) ?? [],
928
- goal: info.data?.plan_goal ?? '',
929
- });
930
- info.data?.steps.forEach(s => data.steps?.push({
931
- id: s.id,
932
- type: 'step',
933
- status: 'pending',
934
- input: s.goal,
935
- attempts: [{
936
- tools: s.tools?.map(t => ({
937
- ...(tools.find(({ id }) => id === t.tool_id) ?? { id: t.tool_id, name: t.tool_id }),
938
- executionId: t.tool_execution_id,
939
- goal: t.goal,
940
- })),
941
- }],
942
- }));
943
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' });
944
- }
945
- if (info.type === 'step' && info.action === 'start') {
946
- const step = data.steps.find(s => s.id === info.id);
947
- if (step)
948
- step.status = 'running';
949
- }
950
- if (info.type === 'step' && info.action === 'end') {
951
- const step = data.steps.find(s => s.id === info.id);
952
- if (step) {
953
- step.status = 'success';
954
- step.duration = info.duration;
955
- const lastToolId = last(step.attempts[0].tools)?.id;
956
- const lastAttemptOfLastTool = findLast(step.attempts.map(a => a.tools).flat(), t => t?.id === lastToolId);
957
- step.output = lastAttemptOfLastTool?.output;
958
- }
959
- }
960
- if (info.type === 'tool_calls' && info.action === 'start') {
961
- const hasPlanning = data.steps.find(s => s.type === 'planning');
962
- // On the first tool_calls:start, create the synthetic planning ("dynamic") step.
963
- if (!hasPlanning) {
964
- const userPrompt = request.user_prompt === 'string' ? request.user_prompt : JSON.stringify(request.user_prompt);
965
- data.steps.push({
966
- id: 'dynamic',
967
- type: 'planning',
968
- status: 'success',
969
- steps: [],
970
- goal: userPrompt,
971
- user_question: userPrompt,
972
- });
973
- }
974
- const toolsStepId = data.steps.filter(s => s.id === 'tools' || s.id.startsWith('tools-')).length + 1;
975
- data.steps.push({
976
- id: `tools-${toolsStepId.toString()}`,
977
- type: 'step',
978
- status: 'running',
979
- attempts: [{ tools: [] }],
980
- });
981
- }
982
- if (info.type === 'tool_calls' && info.action === 'end') {
983
- const lastStep = findLast(data.steps, s => s.id === 'tools' || s.id.startsWith('tools-'));
984
- if (lastStep) {
985
- lastStep.status = 'success';
986
- lastStep.duration = info.duration;
987
- const lastAttemptOfLastTool = last(lastStep.attempts.map(a => a.tools).flat());
988
- lastStep.output = lastAttemptOfLastTool?.output;
989
- }
990
- }
991
- if (info.type === 'tool' && info.action === 'awaiting_approval') {
992
- const tool = tools.find(({ id }) => id === info.data?.tool_id);
993
- data.steps.push({
994
- id: info.id,
995
- type: 'tool',
996
- status: 'awaiting_approval',
997
- duration: info.duration || 0,
998
- input: info.data?.input,
999
- user_question: info.data?.user_question,
1000
- attempts: [{
1001
- tools: [{
1002
- executionId: info.id,
1003
- id: info.data?.tool_id ?? '',
1004
- name: tool?.name ?? '',
1005
- goal: tool?.goal,
1006
- ...tool,
1007
- }],
1008
- }],
1009
- });
1010
- data.steps.push({ id: 'answer', type: 'answer', status: 'pending' });
1011
- }
1012
- if (info.type === 'tool' && info.action === 'start') {
1013
- if (!info.data)
1014
- return;
1015
- const input = formatJson(info.data.input);
1016
- const tool = findLast(tools, ({ id }) => id === info.data?.tool_id) ?? { id: info.data?.tool_id, name: info.data?.tool_id };
1017
- const currentStep = findLast(data.steps, s => s.status === 'running');
1018
- //There might be a tool with status awaiting_approval, so we want to inform tool has already started
1019
- if (!currentStep || !currentStep?.attempts?.[0]?.tools) {
1020
- data.steps.push({
1021
- id: info.id,
1022
- type: 'tool',
1023
- status: 'running',
1024
- duration: info.duration || 0,
1025
- input: info.data?.input,
1026
- user_question: info.data?.user_question,
1027
- attempts: [{
1028
- tools: [{ ...tool, executionId: info.id, input }],
1029
- }],
1030
- });
1031
- }
1032
- else {
1033
- const toolInFirstAttempt = findLast(currentStep?.attempts?.[0]?.tools, t => t.executionId === info.id);
1034
- //One step might have multiple tools. When in an approval mode, we might not have all the tools in the array yet.
1035
- //For dynamic tools (id === 'dynamic'), we always push a new tool, since dynamic executions can trigger
1036
- //multiple tool runs in the same step and do not follow the planned tool structure.
1037
- //So we make sure to add any tools that are not in there, or always add for dynamic tools.
1038
- if (!toolInFirstAttempt || isDynamicTool(info)) {
1039
- currentStep.attempts?.[0].tools?.push({
1040
- ...tool,
1041
- executionId: info.id,
1042
- input,
1043
- status: 'running',
1044
- });
1045
- }
1046
- else {
1047
- const input = formatJson(info.data.input);
1048
- if (info.data.attempt === 1) {
1049
- toolInFirstAttempt.input = input;
1050
- }
1051
- else {
1052
- currentStep.attempts[info.data.attempt - 1] ??= { tools: [] };
1053
- currentStep.attempts[info.data.attempt - 1].tools?.push({
1054
- ...tool,
1055
- executionId: info.id,
1056
- input,
1057
- });
1058
- }
1059
- }
1060
- }
1061
- }
1062
- if (info.type === 'tool' && info.action === 'end') {
1063
- const currentStep = data.steps.find(s => s.status === 'running');
1064
- if (!currentStep || !info.data)
1065
- return;
1066
- // attempt index for tool execution starts at 0 for dynamically executed tools,while for planned tools it starts at 1
1067
- const attempt = isDynamicTool(info) ? info.data.attempt : info.data.attempt - 1;
1068
- const tool = last(currentStep?.attempts?.[attempt]?.tools);
1069
- if (tool) {
1070
- tool.output = formatJson(info.data.output);
1071
- tool.duration = info.duration;
1072
- tool.status = 'success';
1073
- }
1074
- }
1075
- if (info.type === 'final_answer' && info.action === 'start') {
1076
- const answerStep = last(data.steps);
1077
- if (answerStep)
1078
- answerStep.status = 'running';
1079
- }
1080
- if (info.type === 'chat' && info.action === 'end') {
1081
- const lastStep = last(data.steps);
1082
- if (lastStep?.type === 'answer') {
1083
- lastStep.status = 'success';
1084
- lastStep.duration = info.duration;
1085
- }
1086
- else {
1087
- data.steps.push({ id: 'answer', type: 'answer', status: 'success' });
1088
- }
1089
- }
1090
- }
1091
- return new StreamedJson({
1092
- eventsPromise: events,
1093
- abortController,
1094
- minChangeIntervalMS,
1095
- ignoreKeys: ['agent_info'],
1096
- transform,
1097
- textFromErrorEvent: data => data.answer ?? 'Unknown error',
1098
- });
1099
- }
1100
541
  }
1101
542
  export const aiClient = new AIClient();
1102
543
  //# sourceMappingURL=ai.js.map