@credal/actions 0.2.147 → 0.2.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/actionMapper.js +1 -0
- package/dist/actions/autogen/templates.d.ts +11 -0
- package/dist/actions/autogen/templates.js +775 -47
- package/dist/actions/autogen/types.d.ts +726 -12
- package/dist/actions/autogen/types.js +213 -4
- package/dist/actions/invoke.js +1 -1
- package/dist/actions/providers/google-oauth/getDriveFileContentById.js +24 -27
- package/dist/actions/providers/googlemail/searchGmailMessages.d.ts +14 -0
- package/dist/actions/providers/googlemail/searchGmailMessages.js +42 -24
- package/dist/actions/providers/jira/assignJiraTicket.js +16 -12
- package/dist/actions/providers/jira/commentJiraTicket.js +10 -22
- package/dist/actions/providers/jira/createJiraTicket.js +39 -49
- package/dist/actions/providers/jira/getJiraIssuesByQuery.js +37 -36
- package/dist/actions/providers/jira/getJiraTicketDetails.js +7 -5
- package/dist/actions/providers/jira/getJiraTicketHistory.js +10 -8
- package/dist/actions/providers/jira/updateJiraTicketDetails.js +16 -37
- package/dist/actions/providers/jira/updateJiraTicketStatus.js +8 -6
- package/dist/actions/providers/jira/utils.d.ts +55 -2
- package/dist/actions/providers/jira/utils.js +129 -9
- package/dist/actions/providers/slackUser/searchSlack.js +59 -32
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ export var ProviderName;
|
|
|
10
10
|
ProviderName["CONFLUENCE"] = "confluence";
|
|
11
11
|
ProviderName["JIRA"] = "jira";
|
|
12
12
|
ProviderName["JIRAORG"] = "jiraOrg";
|
|
13
|
+
ProviderName["JIRADATACENTER"] = "jiraDataCenter";
|
|
13
14
|
ProviderName["KANDJI"] = "kandji";
|
|
14
15
|
ProviderName["GOOGLEMAPS"] = "googlemaps";
|
|
15
16
|
ProviderName["BING"] = "bing";
|
|
@@ -414,7 +415,12 @@ export const jiraCreateJiraTicketParamsSchema = z.object({
|
|
|
414
415
|
.optional(),
|
|
415
416
|
});
|
|
416
417
|
export const jiraCreateJiraTicketOutputSchema = z.object({
|
|
417
|
-
|
|
418
|
+
success: z.boolean().describe("Whether the ticket was successfully created"),
|
|
419
|
+
ticketUrl: z.string().describe("The url to the created Jira Ticket (only present if success is true)").optional(),
|
|
420
|
+
error: z
|
|
421
|
+
.string()
|
|
422
|
+
.describe("Error message if the ticket creation failed (only present if success is false)")
|
|
423
|
+
.optional(),
|
|
418
424
|
});
|
|
419
425
|
export const jiraGetServiceDesksParamsSchema = z.object({});
|
|
420
426
|
export const jiraGetServiceDesksOutputSchema = z.object({
|
|
@@ -503,7 +509,9 @@ export const jiraUpdateJiraTicketDetailsParamsSchema = z.object({
|
|
|
503
509
|
.optional(),
|
|
504
510
|
});
|
|
505
511
|
export const jiraUpdateJiraTicketDetailsOutputSchema = z.object({
|
|
506
|
-
|
|
512
|
+
success: z.boolean().describe("Whether the ticket was successfully updated"),
|
|
513
|
+
ticketUrl: z.string().describe("The url to the Jira ticket (only present if success is true)").optional(),
|
|
514
|
+
error: z.string().describe("Error message if the ticket update failed (only present if success is false)").optional(),
|
|
507
515
|
});
|
|
508
516
|
export const jiraUpdateJiraTicketStatusParamsSchema = z.object({
|
|
509
517
|
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
@@ -600,7 +608,12 @@ export const jiraOrgCreateJiraTicketParamsSchema = z.object({
|
|
|
600
608
|
.optional(),
|
|
601
609
|
});
|
|
602
610
|
export const jiraOrgCreateJiraTicketOutputSchema = z.object({
|
|
603
|
-
|
|
611
|
+
success: z.boolean().describe("Whether the ticket was successfully created"),
|
|
612
|
+
ticketUrl: z.string().describe("The url to the created Jira Ticket (only present if success is true)").optional(),
|
|
613
|
+
error: z
|
|
614
|
+
.string()
|
|
615
|
+
.describe("Error message if the ticket creation failed (only present if success is false)")
|
|
616
|
+
.optional(),
|
|
604
617
|
});
|
|
605
618
|
export const jiraOrgGetServiceDesksParamsSchema = z.object({});
|
|
606
619
|
export const jiraOrgGetServiceDesksOutputSchema = z.object({
|
|
@@ -689,7 +702,9 @@ export const jiraOrgUpdateJiraTicketDetailsParamsSchema = z.object({
|
|
|
689
702
|
.optional(),
|
|
690
703
|
});
|
|
691
704
|
export const jiraOrgUpdateJiraTicketDetailsOutputSchema = z.object({
|
|
692
|
-
|
|
705
|
+
success: z.boolean().describe("Whether the ticket was successfully updated"),
|
|
706
|
+
ticketUrl: z.string().describe("The url to the Jira ticket (only present if success is true)").optional(),
|
|
707
|
+
error: z.string().describe("Error message if the ticket update failed (only present if success is false)").optional(),
|
|
693
708
|
});
|
|
694
709
|
export const jiraOrgUpdateJiraTicketStatusParamsSchema = z.object({
|
|
695
710
|
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
@@ -739,6 +754,199 @@ export const jiraOrgGetJiraIssuesByQueryOutputSchema = z.object({
|
|
|
739
754
|
.optional(),
|
|
740
755
|
error: z.string().describe("The error that occurred if the records were not successfully retrieved").optional(),
|
|
741
756
|
});
|
|
757
|
+
export const jiraDataCenterAssignJiraTicketParamsSchema = z.object({
|
|
758
|
+
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
759
|
+
assignee: z.string().describe("The assignee for the ticket, userID or email"),
|
|
760
|
+
issueId: z.string().describe("The issue ID associated with the ticket to be assigned/re-assigned"),
|
|
761
|
+
});
|
|
762
|
+
export const jiraDataCenterAssignJiraTicketOutputSchema = z.object({
|
|
763
|
+
success: z.boolean().describe("Whether the ticket was successfully assigned/reassigned"),
|
|
764
|
+
error: z
|
|
765
|
+
.string()
|
|
766
|
+
.describe("The error that occurred if the ticket was not successfully assigned/reassigned")
|
|
767
|
+
.optional(),
|
|
768
|
+
ticketUrl: z.string().describe("The url to the newly assigned/reassigned Jira ticket").optional(),
|
|
769
|
+
});
|
|
770
|
+
export const jiraDataCenterPublicCommentOnServiceDeskRequestParamsSchema = z.object({
|
|
771
|
+
issueId: z.string().describe("The issue ID associated with the ticket to be commented on"),
|
|
772
|
+
comment: z.string().describe("The text to be commented on the ticket"),
|
|
773
|
+
});
|
|
774
|
+
export const jiraDataCenterPublicCommentOnServiceDeskRequestOutputSchema = z.object({
|
|
775
|
+
success: z.boolean().describe("Whether the comment was sent successfully"),
|
|
776
|
+
error: z.string().describe("The error that occurred if the comment was not sent successfully").optional(),
|
|
777
|
+
commentUrl: z.string().describe("The url to the created Jira comment").optional(),
|
|
778
|
+
});
|
|
779
|
+
export const jiraDataCenterCommentJiraTicketParamsSchema = z.object({
|
|
780
|
+
projectKey: z.string().describe("The key for the project"),
|
|
781
|
+
issueId: z.string().describe("The issue ID associated with the ticket to be commented on"),
|
|
782
|
+
comment: z.string().describe("The text to be commented on the ticket"),
|
|
783
|
+
});
|
|
784
|
+
export const jiraDataCenterCommentJiraTicketOutputSchema = z.object({
|
|
785
|
+
success: z.boolean().describe("Whether the comment was sent successfully"),
|
|
786
|
+
error: z.string().describe("The error that occurred if the comment was not sent successfully").optional(),
|
|
787
|
+
commentUrl: z.string().describe("The url to the created Jira comment").optional(),
|
|
788
|
+
});
|
|
789
|
+
export const jiraDataCenterCreateJiraTicketParamsSchema = z.object({
|
|
790
|
+
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
791
|
+
summary: z.string().describe("The summary of the new ticket"),
|
|
792
|
+
description: z.string().describe("The description for the new ticket"),
|
|
793
|
+
issueType: z.string().describe("The issue type of the new ticket. Should be Epic, Story, Task, Bug, Sub-task, etc."),
|
|
794
|
+
reporter: z.string().describe("The reporter for the new ticket creation").optional(),
|
|
795
|
+
assignee: z.string().describe("The assignee for the new ticket creation").optional(),
|
|
796
|
+
requestTypeId: z.string().describe("The request type ID for Jira Service Management tickets").optional(),
|
|
797
|
+
customFields: z
|
|
798
|
+
.object({})
|
|
799
|
+
.catchall(z.any())
|
|
800
|
+
.describe("Custom fields to be set on the create ticket request")
|
|
801
|
+
.optional(),
|
|
802
|
+
});
|
|
803
|
+
export const jiraDataCenterCreateJiraTicketOutputSchema = z.object({
|
|
804
|
+
success: z.boolean().describe("Whether the ticket was successfully created"),
|
|
805
|
+
ticketUrl: z.string().describe("The url to the created Jira Ticket (only present if success is true)").optional(),
|
|
806
|
+
error: z
|
|
807
|
+
.string()
|
|
808
|
+
.describe("Error message if the ticket creation failed (only present if success is false)")
|
|
809
|
+
.optional(),
|
|
810
|
+
});
|
|
811
|
+
export const jiraDataCenterGetServiceDesksParamsSchema = z.object({});
|
|
812
|
+
export const jiraDataCenterGetServiceDesksOutputSchema = z.object({
|
|
813
|
+
success: z.boolean().describe("Whether the service desks were retrieved successfully"),
|
|
814
|
+
error: z.string().describe("The error that occurred if the service desks were not retrieved successfully").optional(),
|
|
815
|
+
serviceDesks: z
|
|
816
|
+
.array(z
|
|
817
|
+
.object({
|
|
818
|
+
id: z.string().describe("The ID of the service desk").optional(),
|
|
819
|
+
projectId: z.string().describe("The ID of the project").optional(),
|
|
820
|
+
projectKey: z.string().describe("The key of the project").optional(),
|
|
821
|
+
projectName: z.string().describe("The name of the service desk").optional(),
|
|
822
|
+
requestTypes: z
|
|
823
|
+
.array(z
|
|
824
|
+
.object({
|
|
825
|
+
id: z.string().describe("The ID of the request type").optional(),
|
|
826
|
+
name: z.string().describe("The name of the request type").optional(),
|
|
827
|
+
description: z.string().describe("The description of the request type").optional(),
|
|
828
|
+
issueTypeId: z.string().describe("The ID of the issue type").optional(),
|
|
829
|
+
portalId: z.string().describe("The ID of the customer portal").optional(),
|
|
830
|
+
helpText: z.string().describe("The help text for the request type").optional(),
|
|
831
|
+
serviceDeskId: z.string().describe("The ID of the service desk").optional(),
|
|
832
|
+
canCreateRequest: z.boolean().describe("Whether the request type can be created").optional(),
|
|
833
|
+
})
|
|
834
|
+
.describe("A request type"))
|
|
835
|
+
.describe("The list of request types")
|
|
836
|
+
.optional(),
|
|
837
|
+
})
|
|
838
|
+
.describe("A service desk"))
|
|
839
|
+
.describe("The list of service desks")
|
|
840
|
+
.optional(),
|
|
841
|
+
});
|
|
842
|
+
export const jiraDataCenterCreateServiceDeskRequestParamsSchema = z.object({
|
|
843
|
+
serviceDeskId: z.string().describe("The ID of the service desk to create the request in"),
|
|
844
|
+
requestTypeId: z.string().describe("The ID of the request type to use for the new request"),
|
|
845
|
+
summary: z.string().describe("The summary of the new service desk request"),
|
|
846
|
+
description: z.string().describe("The description for the new service desk request"),
|
|
847
|
+
reporter: z
|
|
848
|
+
.string()
|
|
849
|
+
.describe("The email address of the person reporting the issue (for raising on behalf of)")
|
|
850
|
+
.optional(),
|
|
851
|
+
});
|
|
852
|
+
export const jiraDataCenterCreateServiceDeskRequestOutputSchema = z.object({
|
|
853
|
+
success: z.boolean().describe("Whether the request was created successfully"),
|
|
854
|
+
error: z.string().describe("The error that occurred if the request was not created successfully").optional(),
|
|
855
|
+
issueKey: z.string().describe("The Jira issue key of the created request").optional(),
|
|
856
|
+
webLink: z.string().describe("The link to the customer portal request, if available").optional(),
|
|
857
|
+
currentStatus: z.string().describe("The current status of the created request").optional(),
|
|
858
|
+
});
|
|
859
|
+
export const jiraDataCenterGetJiraTicketDetailsParamsSchema = z.object({
|
|
860
|
+
projectKey: z.string().describe("The key for the project"),
|
|
861
|
+
issueId: z.string().describe("The ID of the ticket"),
|
|
862
|
+
});
|
|
863
|
+
export const jiraDataCenterGetJiraTicketDetailsOutputSchema = z.object({
|
|
864
|
+
success: z.boolean().describe("Whether the status was updated successfully"),
|
|
865
|
+
error: z.string().describe("The error that occurred if the retrieval was unsuccessful").optional(),
|
|
866
|
+
results: z
|
|
867
|
+
.array(z.object({
|
|
868
|
+
name: z.string().describe("The name of the result"),
|
|
869
|
+
url: z.string().describe("The URL of the result"),
|
|
870
|
+
contents: z.object({}).catchall(z.any()).describe("The data of the Jira ticket"),
|
|
871
|
+
}))
|
|
872
|
+
.describe("The results of the Jira ticket")
|
|
873
|
+
.optional(),
|
|
874
|
+
});
|
|
875
|
+
export const jiraDataCenterGetJiraTicketHistoryParamsSchema = z.object({
|
|
876
|
+
projectKey: z.string().describe("The key for the project"),
|
|
877
|
+
issueId: z.string().describe("The ID of the ticket"),
|
|
878
|
+
});
|
|
879
|
+
export const jiraDataCenterGetJiraTicketHistoryOutputSchema = z.object({
|
|
880
|
+
success: z.boolean().describe("Whether the status was updated successfully"),
|
|
881
|
+
error: z.string().describe("The error that occurred if the retrieval was unsuccessful").optional(),
|
|
882
|
+
history: z.array(z.any()).describe("The history data of the Jira ticket").optional(),
|
|
883
|
+
});
|
|
884
|
+
export const jiraDataCenterUpdateJiraTicketDetailsParamsSchema = z.object({
|
|
885
|
+
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
886
|
+
issueId: z.string().describe("The issue ID associated with the ticket to be updated"),
|
|
887
|
+
summary: z.string().describe("The updated summary").optional(),
|
|
888
|
+
description: z.string().describe("The updated description").optional(),
|
|
889
|
+
issueType: z.string().describe("The updated issue type").optional(),
|
|
890
|
+
requestTypeId: z.string().describe("The request type ID for Jira Service Management tickets").optional(),
|
|
891
|
+
customFields: z
|
|
892
|
+
.object({})
|
|
893
|
+
.catchall(z.any())
|
|
894
|
+
.describe("Custom fields to be set on the update ticket request")
|
|
895
|
+
.optional(),
|
|
896
|
+
});
|
|
897
|
+
export const jiraDataCenterUpdateJiraTicketDetailsOutputSchema = z.object({
|
|
898
|
+
success: z.boolean().describe("Whether the ticket was successfully updated"),
|
|
899
|
+
ticketUrl: z.string().describe("The url to the Jira ticket (only present if success is true)").optional(),
|
|
900
|
+
error: z.string().describe("Error message if the ticket update failed (only present if success is false)").optional(),
|
|
901
|
+
});
|
|
902
|
+
export const jiraDataCenterUpdateJiraTicketStatusParamsSchema = z.object({
|
|
903
|
+
projectKey: z.string().describe("The key for the project you want to add it to"),
|
|
904
|
+
issueId: z.string().describe("The issue ID associated with the ticket"),
|
|
905
|
+
status: z.string().describe('The status the ticket should be changed to (eg "In Progress", "Closed")'),
|
|
906
|
+
});
|
|
907
|
+
export const jiraDataCenterUpdateJiraTicketStatusOutputSchema = z.object({
|
|
908
|
+
success: z.boolean().describe("Whether the status was updated successfully"),
|
|
909
|
+
error: z.string().describe("The error that occurred if the status was not updated successfully").optional(),
|
|
910
|
+
ticketUrl: z.string().describe("The url to the Jira ticket").optional(),
|
|
911
|
+
});
|
|
912
|
+
export const jiraDataCenterGetJiraIssuesByQueryParamsSchema = z.object({
|
|
913
|
+
query: z.string().describe("The JQL query to execute"),
|
|
914
|
+
limit: z.number().describe("The maximum number of records to retrieve").optional(),
|
|
915
|
+
});
|
|
916
|
+
export const jiraDataCenterGetJiraIssuesByQueryOutputSchema = z.object({
|
|
917
|
+
success: z.boolean().describe("Whether the records were successfully retrieved"),
|
|
918
|
+
results: z
|
|
919
|
+
.array(z.object({
|
|
920
|
+
name: z.string().describe("The name of the result"),
|
|
921
|
+
url: z.string().describe("The URL of the result"),
|
|
922
|
+
contents: z
|
|
923
|
+
.object({
|
|
924
|
+
id: z.string().describe("Internal Jira issue ID"),
|
|
925
|
+
key: z.string().describe("Human-readable issue key (e.g. SSPR-123)"),
|
|
926
|
+
summary: z.string().describe("Summary of the issue"),
|
|
927
|
+
description: z.string().describe("Plain text description"),
|
|
928
|
+
url: z.string().describe("The web url of the Jira ticket"),
|
|
929
|
+
project: z.object({ id: z.string().optional(), key: z.string().optional(), name: z.string().optional() }),
|
|
930
|
+
issueType: z.object({ id: z.string().optional(), name: z.string().optional() }),
|
|
931
|
+
status: z.object({
|
|
932
|
+
id: z.string().optional(),
|
|
933
|
+
name: z.string().optional(),
|
|
934
|
+
category: z.string().optional(),
|
|
935
|
+
}),
|
|
936
|
+
assignee: z.string().nullable().describe("Email of the assignee, if any").optional(),
|
|
937
|
+
reporter: z.string().nullable().describe("Email of the reporter, if any").optional(),
|
|
938
|
+
creator: z.string().nullable().describe("Email of the creator, if any").optional(),
|
|
939
|
+
created: z.string().datetime({ offset: true }),
|
|
940
|
+
updated: z.string().datetime({ offset: true }),
|
|
941
|
+
resolution: z.string().nullable().optional(),
|
|
942
|
+
dueDate: z.string().date().nullable().optional(),
|
|
943
|
+
})
|
|
944
|
+
.describe("The result object containing issues"),
|
|
945
|
+
}))
|
|
946
|
+
.describe("The results of the Jira issues")
|
|
947
|
+
.optional(),
|
|
948
|
+
error: z.string().describe("The error that occurred if the records were not successfully retrieved").optional(),
|
|
949
|
+
});
|
|
742
950
|
export const kandjiGetFVRecoveryKeyForDeviceParamsSchema = z.object({
|
|
743
951
|
userEmail: z.string().describe("The email of the user requesting the recovery key"),
|
|
744
952
|
subdomain: z.string().describe("The subdomain of the Kandji account"),
|
|
@@ -2943,6 +3151,7 @@ export const googleOauthQueryGoogleBigQueryOutputSchema = z.object({
|
|
|
2943
3151
|
export const googlemailSearchGmailMessagesParamsSchema = z.object({
|
|
2944
3152
|
query: z.string().describe('Gmail search query (e.g. "from:alice subject:urgent")'),
|
|
2945
3153
|
maxResults: z.number().describe("Maximum number of messages to return (optional)").optional(),
|
|
3154
|
+
timeout: z.number().describe("Timeout for the query in seconds (optional)").optional(),
|
|
2946
3155
|
});
|
|
2947
3156
|
export const googlemailSearchGmailMessagesOutputSchema = z.object({
|
|
2948
3157
|
success: z.boolean(),
|
package/dist/actions/invoke.js
CHANGED
|
@@ -20,7 +20,7 @@ export function invokeAction(input) {
|
|
|
20
20
|
if (!safeParseParams.success) {
|
|
21
21
|
throw new Error(`Invalid parameters for action '${name}': ${safeParseParams.error}`);
|
|
22
22
|
}
|
|
23
|
-
return providerFunction({ params: parameters, authParams });
|
|
23
|
+
return providerFunction({ params: parameters, authParams: Object.assign(Object.assign({}, authParams), { provider }) });
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
function isProviderName(value) {
|
|
@@ -16,6 +16,8 @@ import { read, utils } from "xlsx";
|
|
|
16
16
|
import officeParser from "officeparser";
|
|
17
17
|
const BASE_WEB_URL = "https://drive.google.com/file/d/";
|
|
18
18
|
const BASE_API_URL = "https://www.googleapis.com/drive/v3/files/";
|
|
19
|
+
const NEWLINE_REGEX = /\r?\n+/g;
|
|
20
|
+
const WHITESPACE_REGEX = / +/g;
|
|
19
21
|
const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
20
22
|
var _b, _c, _d, _e;
|
|
21
23
|
if (!authParams.authToken) {
|
|
@@ -31,7 +33,10 @@ const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function
|
|
|
31
33
|
`?fields=name,mimeType,size,driveId,parents,` +
|
|
32
34
|
`shortcutDetails(targetId,targetMimeType)` +
|
|
33
35
|
`&supportsAllDrives=true`;
|
|
34
|
-
const res = yield axiosClient.get(metaUrl, {
|
|
36
|
+
const res = yield axiosClient.get(metaUrl, {
|
|
37
|
+
headers,
|
|
38
|
+
timeout: timeoutLimit,
|
|
39
|
+
});
|
|
35
40
|
return res.data;
|
|
36
41
|
});
|
|
37
42
|
try {
|
|
@@ -97,15 +102,8 @@ const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function
|
|
|
97
102
|
};
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
|
-
else if (mimeType === "text/plain" || mimeType === "text/html" || mimeType === "application/rtf") {
|
|
101
|
-
const downloadUrl = `${BASE_API_URL}${encodeURIComponent(params.fileId)}?alt=media${sharedDriveParam}`;
|
|
102
|
-
const downloadRes = yield axiosClient.get(downloadUrl, {
|
|
103
|
-
headers,
|
|
104
|
-
responseType: "text",
|
|
105
|
-
});
|
|
106
|
-
content = downloadRes.data;
|
|
107
|
-
}
|
|
108
105
|
else if (mimeType === "text/plain" ||
|
|
106
|
+
mimeType === "text/html" ||
|
|
109
107
|
mimeType === "text/csv" ||
|
|
110
108
|
mimeType === "text/tab-separated-values" ||
|
|
111
109
|
mimeType === "application/rtf" ||
|
|
@@ -113,11 +111,9 @@ const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function
|
|
|
113
111
|
const downloadUrl = `${BASE_API_URL}${encodeURIComponent(params.fileId)}?alt=media${sharedDriveParam}`;
|
|
114
112
|
const downloadRes = yield axiosClient.get(downloadUrl, {
|
|
115
113
|
headers,
|
|
116
|
-
responseType: "
|
|
114
|
+
responseType: "text",
|
|
117
115
|
});
|
|
118
|
-
|
|
119
|
-
const rawContentBuffer = Buffer.from(bufferResults); // Convert rawContent ArrayBuffer to Buffer
|
|
120
|
-
content = rawContentBuffer.toString("utf-8");
|
|
116
|
+
content = downloadRes.data;
|
|
121
117
|
}
|
|
122
118
|
else if (mimeType === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
|
|
123
119
|
mimeType === "application/vnd.ms-excel") {
|
|
@@ -127,16 +123,21 @@ const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function
|
|
|
127
123
|
responseType: "arraybuffer",
|
|
128
124
|
});
|
|
129
125
|
// 1. Read the buffer into a workbook
|
|
130
|
-
const workbook = read(downloadRes.data, { type: "buffer" });
|
|
126
|
+
const workbook = read(downloadRes.data, { type: "buffer", sheetStubs: false });
|
|
127
|
+
// Convert sheets to CSV with early termination if charLimit is set
|
|
128
|
+
const sheetTexts = [];
|
|
129
|
+
let totalLength = 0;
|
|
130
|
+
const effectiveLimit = charLimit ? charLimit * 1.5 : 100000; // Process 1.5x limit for safety
|
|
131
131
|
// 2. Convert all sheets to plain text (CSV-style)
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
for (const sheetName of workbook.SheetNames) {
|
|
133
|
+
if (totalLength >= effectiveLimit)
|
|
134
|
+
break; // Early termination
|
|
134
135
|
const sheet = workbook.Sheets[sheetName];
|
|
135
|
-
const csv = utils.sheet_to_csv(sheet);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
content =
|
|
136
|
+
const csv = utils.sheet_to_csv(sheet);
|
|
137
|
+
sheetTexts.push(`--- Sheet: ${sheetName} ---\n${csv}`);
|
|
138
|
+
totalLength += csv.length;
|
|
139
|
+
}
|
|
140
|
+
content = sheetTexts.join("\n").trim();
|
|
140
141
|
}
|
|
141
142
|
else if (mimeType === "application/vnd.openxmlformats-officedocument.presentationml.presentation") {
|
|
142
143
|
// Handle modern PowerPoint files (.pptx only)
|
|
@@ -160,14 +161,10 @@ const getDriveFileContentById = (_a) => __awaiter(void 0, [_a], void 0, function
|
|
|
160
161
|
else {
|
|
161
162
|
return { success: false, error: `Unsupported file type: ${mimeType}` };
|
|
162
163
|
}
|
|
163
|
-
// 5)
|
|
164
|
-
content = (content !== null && content !== void 0 ? content : "")
|
|
165
|
-
.trim()
|
|
166
|
-
.replace(/\r?\n+/g, " ")
|
|
167
|
-
.replace(/ +/g, " ");
|
|
164
|
+
// 5) Apply content limit early, then normalize whitespace
|
|
168
165
|
const originalLength = content.length;
|
|
166
|
+
content = content.trim().replace(NEWLINE_REGEX, " ").replace(WHITESPACE_REGEX, " ");
|
|
169
167
|
if (charLimit && content.length > charLimit) {
|
|
170
|
-
// TODO in the future do this around the most valuable snippet of the doc?
|
|
171
168
|
content = content.slice(0, charLimit);
|
|
172
169
|
}
|
|
173
170
|
return {
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export interface GmailMessageResult {
|
|
2
|
+
id: string;
|
|
3
|
+
threadId: string;
|
|
4
|
+
snippet: string;
|
|
5
|
+
labelIds?: string[];
|
|
6
|
+
internalDate: string;
|
|
7
|
+
emailBody: string;
|
|
8
|
+
from?: string;
|
|
9
|
+
to?: string;
|
|
10
|
+
subject?: string;
|
|
11
|
+
cc?: string;
|
|
12
|
+
bcc?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
1
15
|
import type { googlemailSearchGmailMessagesFunction } from "../../autogen/types.js";
|
|
2
16
|
declare const searchGmailMessages: googlemailSearchGmailMessagesFunction;
|
|
3
17
|
export default searchGmailMessages;
|
|
@@ -15,12 +15,16 @@ const MAX_EMAIL_CONTENTS_FETCHED = 50;
|
|
|
15
15
|
const DEFAULT_EMAIL_CONTENTS_FETCHED = 25;
|
|
16
16
|
const MAX_RESULTS_PER_REQUEST = 100;
|
|
17
17
|
const MAX_EMAILS_FETCHED_CONCURRENTLY = 5;
|
|
18
|
+
const DEFAULT_EMAIL_FETCH_TIMEOUT = 5000; // 5 second timeout per email
|
|
18
19
|
const limiter = new RateLimiter({ tokensPerInterval: MAX_EMAILS_FETCHED_CONCURRENTLY, interval: "second" });
|
|
20
|
+
const QUOTED_REPLY_REGEX = /^>.*$/gm;
|
|
21
|
+
const NEWLINE_NORMALIZE_REGEX = /\r\n|\r/g;
|
|
22
|
+
const MULTIPLE_NEWLINES_REGEX = /\n{3,}/g;
|
|
19
23
|
function cleanAndTruncateEmail(text, maxLength = 2000) {
|
|
20
24
|
if (!text)
|
|
21
25
|
return "";
|
|
22
|
-
// Remove quoted replies
|
|
23
|
-
text = text.replace(
|
|
26
|
+
// Remove quoted replies
|
|
27
|
+
text = text.replace(QUOTED_REPLY_REGEX, "");
|
|
24
28
|
// Remove signatures
|
|
25
29
|
const signatureMarkers = ["\nBest", "\nRegards", "\nThanks", "\nSincerely"];
|
|
26
30
|
for (const marker of signatureMarkers) {
|
|
@@ -31,17 +35,14 @@ function cleanAndTruncateEmail(text, maxLength = 2000) {
|
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
// Normalize whitespace
|
|
34
|
-
text = text
|
|
35
|
-
.replace(/\r\n|\r/g, "\n")
|
|
36
|
-
.replace(/\n{3,}/g, "\n\n")
|
|
37
|
-
.trim();
|
|
38
|
+
text = text.replace(NEWLINE_NORMALIZE_REGEX, "\n").replace(MULTIPLE_NEWLINES_REGEX, "\n\n").trim();
|
|
38
39
|
return text.slice(0, maxLength).trim();
|
|
39
40
|
}
|
|
40
41
|
const searchGmailMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
41
42
|
if (!authParams.authToken) {
|
|
42
43
|
return { success: false, error: MISSING_AUTH_TOKEN, messages: [] };
|
|
43
44
|
}
|
|
44
|
-
const { query, maxResults } = params;
|
|
45
|
+
const { query, maxResults, timeout } = params;
|
|
45
46
|
const max = Math.min(maxResults !== null && maxResults !== void 0 ? maxResults : DEFAULT_EMAIL_CONTENTS_FETCHED, MAX_EMAIL_CONTENTS_FETCHED);
|
|
46
47
|
const allMessages = [];
|
|
47
48
|
const errorMessages = [];
|
|
@@ -49,9 +50,11 @@ const searchGmailMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({
|
|
|
49
50
|
let fetched = 0;
|
|
50
51
|
try {
|
|
51
52
|
while (fetched < max) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
// Calculate the optimal batch size for this request
|
|
54
|
+
const batchSize = Math.min(MAX_RESULTS_PER_REQUEST, // API maximum
|
|
55
|
+
max - fetched, // Only fetch what we still need
|
|
56
|
+
MAX_EMAILS_FETCHED_CONCURRENTLY);
|
|
57
|
+
const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages?q=${encodeURIComponent(query)}&maxResults=${batchSize}${pageToken ? `&pageToken=${encodeURIComponent(pageToken)}` : ""}`;
|
|
55
58
|
const listRes = yield axiosClient.get(url, {
|
|
56
59
|
headers: { Authorization: `Bearer ${authParams.authToken}` },
|
|
57
60
|
});
|
|
@@ -59,35 +62,42 @@ const searchGmailMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({
|
|
|
59
62
|
if (!Array.isArray(messageList) || messageList.length === 0)
|
|
60
63
|
break;
|
|
61
64
|
const batch = messageList.slice(0, max - allMessages.length);
|
|
62
|
-
const results = yield Promise.
|
|
65
|
+
const results = yield Promise.allSettled(batch.map((msg) => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
66
|
try {
|
|
64
67
|
yield limiter.removeTokens(1);
|
|
65
68
|
const msgRes = yield axiosClient.get(`https://gmail.googleapis.com/gmail/v1/users/me/messages/${msg.id}?format=full`, {
|
|
66
69
|
headers: { Authorization: `Bearer ${authParams.authToken}` },
|
|
70
|
+
timeout: timeout ? timeout * 1000 : DEFAULT_EMAIL_FETCH_TIMEOUT,
|
|
67
71
|
validateStatus: () => true,
|
|
68
72
|
});
|
|
69
73
|
const { id, threadId, snippet, labelIds, internalDate, payload } = msgRes.data;
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
const headers = {};
|
|
75
|
+
for (const header of payload.headers) {
|
|
76
|
+
const lowerName = header.name.toLowerCase();
|
|
77
|
+
if (lowerName === "from" ||
|
|
78
|
+
lowerName === "to" ||
|
|
79
|
+
lowerName === "subject" ||
|
|
80
|
+
lowerName === "cc" ||
|
|
81
|
+
lowerName === "bcc") {
|
|
82
|
+
headers[lowerName] = header.value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
76
85
|
const rawBody = getEmailContent(msgRes.data) || "";
|
|
77
86
|
const emailBody = cleanAndTruncateEmail(rawBody);
|
|
78
|
-
|
|
87
|
+
const message = {
|
|
79
88
|
id,
|
|
80
89
|
threadId,
|
|
81
90
|
snippet,
|
|
82
91
|
labelIds,
|
|
83
92
|
internalDate,
|
|
84
93
|
emailBody,
|
|
85
|
-
from:
|
|
86
|
-
to:
|
|
87
|
-
subject:
|
|
88
|
-
cc:
|
|
89
|
-
bcc:
|
|
94
|
+
from: headers.from,
|
|
95
|
+
to: headers.to,
|
|
96
|
+
subject: headers.subject,
|
|
97
|
+
cc: headers.cc,
|
|
98
|
+
bcc: headers.bcc,
|
|
90
99
|
};
|
|
100
|
+
return message;
|
|
91
101
|
}
|
|
92
102
|
catch (err) {
|
|
93
103
|
const errorMessage = err instanceof Error ? err.message : "Failed to fetch message details";
|
|
@@ -108,7 +118,15 @@ const searchGmailMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({
|
|
|
108
118
|
};
|
|
109
119
|
}
|
|
110
120
|
})));
|
|
111
|
-
|
|
121
|
+
const successfulResults = results
|
|
122
|
+
.filter((r) => r.status === "fulfilled")
|
|
123
|
+
.map(r => r.value);
|
|
124
|
+
const failedResults = results.filter((r) => r.status === "rejected");
|
|
125
|
+
failedResults.forEach(r => {
|
|
126
|
+
const errorMessage = r.reason instanceof Error ? r.reason.message : "Failed to fetch message details";
|
|
127
|
+
errorMessages.push(errorMessage);
|
|
128
|
+
});
|
|
129
|
+
allMessages.push(...successfulResults);
|
|
112
130
|
fetched = allMessages.length;
|
|
113
131
|
if (!nextPageToken || fetched >= max)
|
|
114
132
|
break;
|
|
@@ -8,22 +8,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import axios from "axios";
|
|
11
|
-
import { getUserAccountIdFromEmail } from "./utils.js";
|
|
11
|
+
import { getUserAccountIdFromEmail, getJiraApiConfig, getErrorMessage } from "./utils.js";
|
|
12
12
|
const assignJiraTicket = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
13
|
-
const { authToken
|
|
14
|
-
const apiUrl =
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const { authToken } = authParams;
|
|
14
|
+
const { apiUrl, browseUrl, strategy } = getJiraApiConfig(authParams);
|
|
15
|
+
const { issueId, assignee } = params;
|
|
16
|
+
if (!authToken) {
|
|
17
|
+
throw new Error("Auth token is required");
|
|
17
18
|
}
|
|
18
19
|
try {
|
|
19
|
-
let assigneeId =
|
|
20
|
+
let assigneeId = assignee;
|
|
20
21
|
if (assigneeId && assigneeId.includes("@")) {
|
|
21
|
-
assigneeId = yield getUserAccountIdFromEmail(assigneeId, apiUrl, authToken);
|
|
22
|
+
assigneeId = yield getUserAccountIdFromEmail(assigneeId, apiUrl, authToken, strategy);
|
|
22
23
|
}
|
|
23
24
|
if (!assigneeId) {
|
|
24
25
|
throw new Error("Unable to get valid assignee account ID.");
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
const assigneePayload = strategy.formatUser(assigneeId);
|
|
28
|
+
if (!assigneePayload) {
|
|
29
|
+
throw new Error("Unable to create assignee payload.");
|
|
30
|
+
}
|
|
31
|
+
yield axios.put(`${apiUrl}/issue/${issueId}/assignee`, assigneePayload, {
|
|
27
32
|
headers: {
|
|
28
33
|
Authorization: `Bearer ${authToken}`,
|
|
29
34
|
Accept: "application/json",
|
|
@@ -32,15 +37,14 @@ const assignJiraTicket = (_a) => __awaiter(void 0, [_a], void 0, function* ({ pa
|
|
|
32
37
|
});
|
|
33
38
|
return {
|
|
34
39
|
success: true,
|
|
35
|
-
ticketUrl: `${
|
|
40
|
+
ticketUrl: `${browseUrl}/browse/${issueId}`,
|
|
36
41
|
};
|
|
37
42
|
}
|
|
38
43
|
catch (error) {
|
|
39
|
-
|
|
40
|
-
console.error("Error assigning issue:", axiosError);
|
|
44
|
+
console.error("Error assigning issue:", error);
|
|
41
45
|
return {
|
|
42
46
|
success: false,
|
|
43
|
-
error:
|
|
47
|
+
error: getErrorMessage(error),
|
|
44
48
|
};
|
|
45
49
|
}
|
|
46
50
|
});
|
|
@@ -8,29 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { axiosClient } from "../../util/axiosClient.js";
|
|
11
|
+
import { getJiraApiConfig, getErrorMessage } from "./utils.js";
|
|
11
12
|
const commentJiraTicket = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
12
|
-
const { authToken
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const { authToken } = authParams;
|
|
14
|
+
const { apiUrl, browseUrl, strategy } = getJiraApiConfig(authParams);
|
|
15
|
+
const { issueId, comment } = params;
|
|
16
|
+
if (!authToken) {
|
|
17
|
+
throw new Error("Auth token is required");
|
|
15
18
|
}
|
|
16
|
-
const apiUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${params.issueId}/comment`;
|
|
17
19
|
try {
|
|
18
|
-
const response = yield axiosClient.post(apiUrl
|
|
19
|
-
body:
|
|
20
|
-
type: "doc",
|
|
21
|
-
version: 1,
|
|
22
|
-
content: [
|
|
23
|
-
{
|
|
24
|
-
type: "paragraph",
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: "text",
|
|
28
|
-
text: params.comment,
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
},
|
|
20
|
+
const response = yield axiosClient.post(`${apiUrl}/issue/${issueId}/comment`, {
|
|
21
|
+
body: strategy.formatText(comment),
|
|
34
22
|
}, {
|
|
35
23
|
headers: {
|
|
36
24
|
Authorization: `Bearer ${authToken}`,
|
|
@@ -40,14 +28,14 @@ const commentJiraTicket = (_a) => __awaiter(void 0, [_a], void 0, function* ({ p
|
|
|
40
28
|
});
|
|
41
29
|
return {
|
|
42
30
|
success: true,
|
|
43
|
-
commentUrl: `${
|
|
31
|
+
commentUrl: `${browseUrl}/browse/${issueId}?focusedCommentId=${response.data.id}`,
|
|
44
32
|
};
|
|
45
33
|
}
|
|
46
34
|
catch (error) {
|
|
47
35
|
console.error("Error commenting on Jira ticket: ", error);
|
|
48
36
|
return {
|
|
49
37
|
success: false,
|
|
50
|
-
error: error
|
|
38
|
+
error: getErrorMessage(error),
|
|
51
39
|
};
|
|
52
40
|
}
|
|
53
41
|
});
|