@tangle-network/agent-integrations 0.44.0 → 0.45.0
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/catalog.d.ts +2 -2
- package/dist/catalog.js +6 -6
- package/dist/{chunk-YA52626Y.js → chunk-E6BBOBYT.js} +2 -2
- package/dist/{chunk-U4W37I5T.js → chunk-LA76XB7M.js} +2 -2
- package/dist/{chunk-ITA67K5M.js → chunk-S2BUASSV.js} +2 -2
- package/dist/{chunk-BDSGHMY6.js → chunk-UWF33ESC.js} +38 -2
- package/dist/chunk-UWF33ESC.js.map +1 -0
- package/dist/{chunk-HNHR2MKW.js → chunk-VLVSP7SP.js} +2 -2
- package/dist/{chunk-ZBMMGAE2.js → chunk-WTMOFI3U.js} +391 -213
- package/dist/{chunk-ZBMMGAE2.js.map → chunk-WTMOFI3U.js.map} +1 -1
- package/dist/connect/index.d.ts +2 -2
- package/dist/connect/index.js +2 -2
- package/dist/connectors/adapters/index.d.ts +64 -3
- package/dist/connectors/adapters/index.js +12 -2
- package/dist/connectors/index.d.ts +3 -3
- package/dist/connectors/index.js +16 -2
- package/dist/{consumer-rANg4Qhz.d.ts → consumer-CTMB1xcc.d.ts} +1 -1
- package/dist/consumer.d.ts +3 -3
- package/dist/consumer.js +2 -2
- package/dist/{core-types-ZABxT4_F.d.ts → core-types-BZLzY8Oa.d.ts} +1 -1
- package/dist/coverage-catalog.d.ts +2 -2
- package/dist/{importers-CWmyogMo.d.ts → importers-6Beu0SQ9.d.ts} +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +20 -6
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +6 -6
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +2 -2
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +6 -6
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +6 -6
- package/dist/specs.d.ts +2 -2
- package/dist/{tangle-id-DE1QrpAY.d.ts → tangle-id-_uZ3ywCF.d.ts} +1 -1
- package/dist/{types-DzPmyjGl.d.ts → types-rBPdMcpb.d.ts} +52 -5
- package/package.json +1 -1
- package/dist/chunk-BDSGHMY6.js.map +0 -1
- /package/dist/{chunk-YA52626Y.js.map → chunk-E6BBOBYT.js.map} +0 -0
- /package/dist/{chunk-U4W37I5T.js.map → chunk-LA76XB7M.js.map} +0 -0
- /package/dist/{chunk-ITA67K5M.js.map → chunk-S2BUASSV.js.map} +0 -0
- /package/dist/{chunk-HNHR2MKW.js.map → chunk-VLVSP7SP.js.map} +0 -0
|
@@ -6,13 +6,15 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
CredentialsExpired,
|
|
8
8
|
DEFAULT_TANGLE_PLATFORM_URL,
|
|
9
|
+
ProviderConfigError,
|
|
10
|
+
ProviderRateLimited,
|
|
9
11
|
ResourceContention,
|
|
10
12
|
TANGLE_API_KEY_PREFIX,
|
|
11
13
|
TANGLE_SERVICE_TOKEN_PREFIX,
|
|
12
14
|
TangleIdentityUnreachableError,
|
|
13
15
|
createTangleIdentityClient,
|
|
14
16
|
tangleIdentity
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UWF33ESC.js";
|
|
16
18
|
import {
|
|
17
19
|
__export
|
|
18
20
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -112,6 +114,8 @@ __export(adapters_exports, {
|
|
|
112
114
|
chatwootConnector: () => chatwootConnector,
|
|
113
115
|
checkoutConnector: () => checkoutConnector,
|
|
114
116
|
circleConnector: () => circleConnector,
|
|
117
|
+
classifyGoogleError: () => classifyGoogleError,
|
|
118
|
+
classifyGoogleReason: () => classifyGoogleReason,
|
|
115
119
|
clayConnector: () => clayConnector,
|
|
116
120
|
clearoutConnector: () => clearoutConnector,
|
|
117
121
|
clicdataConnector: () => clicdataConnector,
|
|
@@ -215,12 +219,14 @@ __export(adapters_exports, {
|
|
|
215
219
|
gmail: () => gmail,
|
|
216
220
|
gongConnector: () => gongConnector,
|
|
217
221
|
googleAnalyticsConnector: () => googleAnalyticsConnector,
|
|
222
|
+
googleApiError: () => googleApiError,
|
|
218
223
|
googleBigqueryConnector: () => googleBigqueryConnector,
|
|
219
224
|
googleCalendar: () => googleCalendar,
|
|
220
225
|
googleCloudStorageConnector: () => googleCloudStorageConnector,
|
|
221
226
|
googleContactsConnector: () => googleContactsConnector,
|
|
222
227
|
googleDocs: () => googleDocs,
|
|
223
228
|
googleDrive: () => googleDrive,
|
|
229
|
+
googleErrorReason: () => googleErrorReason,
|
|
224
230
|
googleForms: () => googleForms,
|
|
225
231
|
googleGeminiConnector: () => googleGeminiConnector,
|
|
226
232
|
googleMeetConnector: () => googleMeetConnector,
|
|
@@ -230,6 +236,7 @@ __export(adapters_exports, {
|
|
|
230
236
|
googleSheets: () => googleSheets,
|
|
231
237
|
googleSlidesConnector: () => googleSlidesConnector,
|
|
232
238
|
googleTasksConnector: () => googleTasksConnector,
|
|
239
|
+
googleTestFailureReason: () => googleTestFailureReason,
|
|
233
240
|
googleVertexaiConnector: () => googleVertexaiConnector,
|
|
234
241
|
googlechatConnector: () => googlechatConnector,
|
|
235
242
|
gorgiasConnector: () => gorgiasConnector,
|
|
@@ -689,6 +696,117 @@ function _resetPendingFlowsForTests() {
|
|
|
689
696
|
defaultFlowStore.clear?.();
|
|
690
697
|
}
|
|
691
698
|
|
|
699
|
+
// src/connectors/adapters/google-errors.ts
|
|
700
|
+
var AUTH_REASONS = /* @__PURE__ */ new Set([
|
|
701
|
+
"autherror",
|
|
702
|
+
"authenticationerror",
|
|
703
|
+
"invalidcredentials",
|
|
704
|
+
"invalid_grant",
|
|
705
|
+
"invalidgrant",
|
|
706
|
+
"unauthorized",
|
|
707
|
+
"unauthenticated",
|
|
708
|
+
"logindenied"
|
|
709
|
+
]);
|
|
710
|
+
var CONFIG_REASONS = /* @__PURE__ */ new Set([
|
|
711
|
+
"accessnotconfigured",
|
|
712
|
+
"insufficientpermissions",
|
|
713
|
+
"insufficientscopes",
|
|
714
|
+
"forbidden",
|
|
715
|
+
"permissiondenied",
|
|
716
|
+
"permission_denied",
|
|
717
|
+
"ssorequired"
|
|
718
|
+
]);
|
|
719
|
+
var QUOTA_REASONS = /* @__PURE__ */ new Set([
|
|
720
|
+
"ratelimitexceeded",
|
|
721
|
+
"userratelimitexceeded",
|
|
722
|
+
"userratelimitexceededunreg",
|
|
723
|
+
"dailylimitexceeded",
|
|
724
|
+
"quotaexceeded",
|
|
725
|
+
"resourceexhausted",
|
|
726
|
+
"resource_exhausted"
|
|
727
|
+
]);
|
|
728
|
+
function googleErrorReason(body) {
|
|
729
|
+
if (!body || typeof body !== "object") return void 0;
|
|
730
|
+
const error = body.error;
|
|
731
|
+
if (!error || typeof error !== "object") return void 0;
|
|
732
|
+
const fromErrors = error.errors?.find(
|
|
733
|
+
(entry) => typeof entry?.reason === "string" && entry.reason.length > 0
|
|
734
|
+
)?.reason;
|
|
735
|
+
if (fromErrors) return fromErrors;
|
|
736
|
+
if (typeof error.status === "string" && error.status.length > 0) {
|
|
737
|
+
return error.status;
|
|
738
|
+
}
|
|
739
|
+
return void 0;
|
|
740
|
+
}
|
|
741
|
+
function classifyGoogleReason(reason) {
|
|
742
|
+
if (!reason) return void 0;
|
|
743
|
+
const key = reason.toLowerCase();
|
|
744
|
+
if (QUOTA_REASONS.has(key)) return "quota";
|
|
745
|
+
if (AUTH_REASONS.has(key)) return "auth";
|
|
746
|
+
if (CONFIG_REASONS.has(key)) return "config";
|
|
747
|
+
return void 0;
|
|
748
|
+
}
|
|
749
|
+
function stringifyBody(body) {
|
|
750
|
+
const text = typeof body === "string" ? body : JSON.stringify(body ?? {});
|
|
751
|
+
return text.slice(0, 200);
|
|
752
|
+
}
|
|
753
|
+
function classifyGoogleError(status, body, context, dataSourceId) {
|
|
754
|
+
const reason = googleErrorReason(body);
|
|
755
|
+
const cls = classifyGoogleReason(reason);
|
|
756
|
+
const init = { status, reason, body };
|
|
757
|
+
const suffix = reason ? `: ${reason}` : "";
|
|
758
|
+
if (cls === "quota" || status === 429) {
|
|
759
|
+
return new ProviderRateLimited(
|
|
760
|
+
`${context} rate limit (${status})${suffix}`,
|
|
761
|
+
dataSourceId,
|
|
762
|
+
init
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (cls === "auth" || status === 401) {
|
|
766
|
+
return new CredentialsExpired(
|
|
767
|
+
`${context} rejected token (${status})${suffix}`,
|
|
768
|
+
dataSourceId,
|
|
769
|
+
init
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
if (cls === "config" || status === 403) {
|
|
773
|
+
return new ProviderConfigError(
|
|
774
|
+
`${context} permission/config error (${status})${suffix}`,
|
|
775
|
+
dataSourceId,
|
|
776
|
+
init
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
return new Error(`${context} ${status}: ${stringifyBody(body)}`);
|
|
780
|
+
}
|
|
781
|
+
async function googleApiError(res, context, dataSourceId) {
|
|
782
|
+
const body = await readErrorBody(res);
|
|
783
|
+
return classifyGoogleError(res.status, body, context, dataSourceId);
|
|
784
|
+
}
|
|
785
|
+
function googleTestFailureReason(status, body, provider) {
|
|
786
|
+
const reason = googleErrorReason(body);
|
|
787
|
+
const cls = classifyGoogleReason(reason);
|
|
788
|
+
const detail = reason ? `, ${reason}` : "";
|
|
789
|
+
if (cls === "quota" || status === 429) {
|
|
790
|
+
return `${provider} rate limit (${status}${detail}) \u2014 retry later`;
|
|
791
|
+
}
|
|
792
|
+
if (cls === "auth" || status === 401) {
|
|
793
|
+
return `${provider} rejected token (${status}${detail}) \u2014 reconnect required`;
|
|
794
|
+
}
|
|
795
|
+
if (cls === "config" || status === 403) {
|
|
796
|
+
return `${provider} permission/config error (${status}${detail}) \u2014 check the API is enabled and scopes are granted`;
|
|
797
|
+
}
|
|
798
|
+
return `${provider} returned ${status}`;
|
|
799
|
+
}
|
|
800
|
+
async function readErrorBody(res) {
|
|
801
|
+
const text = await res.text().catch(() => "");
|
|
802
|
+
if (!text) return void 0;
|
|
803
|
+
try {
|
|
804
|
+
return JSON.parse(text);
|
|
805
|
+
} catch {
|
|
806
|
+
return text;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
692
810
|
// src/connectors/adapters/google-calendar.ts
|
|
693
811
|
var SCOPE_CALENDAR = "https://www.googleapis.com/auth/calendar";
|
|
694
812
|
var SCOPE_WRITE = "https://www.googleapis.com/auth/calendar.events";
|
|
@@ -871,7 +989,7 @@ function googleCalendar(opts) {
|
|
|
871
989
|
if (inv.capabilityName === "list_availability") {
|
|
872
990
|
const calendarId = readMetaString(inv.source.metadata, "calendarId");
|
|
873
991
|
const { timeMin, timeMax } = inv.args;
|
|
874
|
-
const fb = await freebusyQuery({ accessToken, calendarId, timeMin, timeMax });
|
|
992
|
+
const fb = await freebusyQuery({ accessToken, calendarId, timeMin, timeMax, sourceId: inv.source.id });
|
|
875
993
|
return {
|
|
876
994
|
data: { busy: fb.busy },
|
|
877
995
|
fetchedAt: Date.now()
|
|
@@ -891,7 +1009,7 @@ function googleCalendar(opts) {
|
|
|
891
1009
|
}
|
|
892
1010
|
const calendarId = readMetaString(inv.source.metadata, "calendarId");
|
|
893
1011
|
const { start, end, summary, description, attendees } = inv.args;
|
|
894
|
-
const fb = await freebusyQuery({ accessToken, calendarId, timeMin: start, timeMax: end });
|
|
1012
|
+
const fb = await freebusyQuery({ accessToken, calendarId, timeMin: start, timeMax: end, sourceId: inv.source.id });
|
|
895
1013
|
if (fb.busy.length > 0) {
|
|
896
1014
|
const startMs = Date.parse(start);
|
|
897
1015
|
const endMs = Date.parse(end);
|
|
@@ -901,7 +1019,8 @@ function googleCalendar(opts) {
|
|
|
901
1019
|
calendarId,
|
|
902
1020
|
searchFromMs: endMs,
|
|
903
1021
|
durationMs: durMs,
|
|
904
|
-
wanted: 3
|
|
1022
|
+
wanted: 3,
|
|
1023
|
+
sourceId: inv.source.id
|
|
905
1024
|
});
|
|
906
1025
|
throw new ResourceContention(
|
|
907
1026
|
`requested slot ${start}\u2013${end} is no longer free`,
|
|
@@ -939,12 +1058,8 @@ function googleCalendar(opts) {
|
|
|
939
1058
|
idempotentReplay: true
|
|
940
1059
|
};
|
|
941
1060
|
}
|
|
942
|
-
if (res.status === 401 || res.status === 403) {
|
|
943
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
944
|
-
}
|
|
945
1061
|
if (!res.ok) {
|
|
946
|
-
|
|
947
|
-
throw new Error(`google-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
|
|
1062
|
+
throw await googleApiError(res, "google-calendar book_slot", inv.source.id);
|
|
948
1063
|
}
|
|
949
1064
|
const created = await res.json();
|
|
950
1065
|
return {
|
|
@@ -1001,10 +1116,10 @@ function googleCalendar(opts) {
|
|
|
1001
1116
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1002
1117
|
signal: AbortSignal.timeout(8e3)
|
|
1003
1118
|
});
|
|
1004
|
-
if (res.
|
|
1005
|
-
|
|
1119
|
+
if (!res.ok) {
|
|
1120
|
+
const body = await res.json().catch(() => void 0);
|
|
1121
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Google Calendar") };
|
|
1006
1122
|
}
|
|
1007
|
-
if (!res.ok) return { ok: false, reason: `Google returned ${res.status}` };
|
|
1008
1123
|
return { ok: true };
|
|
1009
1124
|
} catch (err) {
|
|
1010
1125
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -1048,12 +1163,8 @@ async function createEvent(inv, accessToken, timeoutMs) {
|
|
|
1048
1163
|
body: JSON.stringify(event),
|
|
1049
1164
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1050
1165
|
});
|
|
1051
|
-
if (res.status === 401 || res.status === 403) {
|
|
1052
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
1053
|
-
}
|
|
1054
1166
|
if (!res.ok) {
|
|
1055
|
-
|
|
1056
|
-
throw new Error(`google-calendar create_event ${res.status}: ${text.slice(0, 200)}`);
|
|
1167
|
+
throw await googleApiError(res, "google-calendar create_event", inv.source.id);
|
|
1057
1168
|
}
|
|
1058
1169
|
const created = await res.json();
|
|
1059
1170
|
return {
|
|
@@ -1093,12 +1204,8 @@ async function updateEvent(inv, accessToken, timeoutMs) {
|
|
|
1093
1204
|
body: JSON.stringify(patch),
|
|
1094
1205
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1095
1206
|
});
|
|
1096
|
-
if (res.status === 401 || res.status === 403) {
|
|
1097
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
1098
|
-
}
|
|
1099
1207
|
if (!res.ok) {
|
|
1100
|
-
|
|
1101
|
-
throw new Error(`google-calendar update_event ${res.status}: ${text.slice(0, 200)}`);
|
|
1208
|
+
throw await googleApiError(res, "google-calendar update_event", inv.source.id);
|
|
1102
1209
|
}
|
|
1103
1210
|
const updated = await res.json();
|
|
1104
1211
|
return {
|
|
@@ -1124,13 +1231,9 @@ async function deleteEvent(inv, accessToken, timeoutMs) {
|
|
|
1124
1231
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1125
1232
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1126
1233
|
});
|
|
1127
|
-
if (res.status === 401 || res.status === 403) {
|
|
1128
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
1129
|
-
}
|
|
1130
1234
|
const idempotent = res.status === 404 || res.status === 410;
|
|
1131
1235
|
if (!res.ok && !idempotent) {
|
|
1132
|
-
|
|
1133
|
-
throw new Error(`google-calendar delete_event ${res.status}: ${text.slice(0, 200)}`);
|
|
1236
|
+
throw await googleApiError(res, "google-calendar delete_event", inv.source.id);
|
|
1134
1237
|
}
|
|
1135
1238
|
return {
|
|
1136
1239
|
status: "committed",
|
|
@@ -1148,12 +1251,8 @@ async function getEvent(inv, accessToken, timeoutMs) {
|
|
|
1148
1251
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1149
1252
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1150
1253
|
});
|
|
1151
|
-
if (res.status === 401 || res.status === 403) {
|
|
1152
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
1153
|
-
}
|
|
1154
1254
|
if (!res.ok) {
|
|
1155
|
-
|
|
1156
|
-
throw new Error(`google-calendar get_event ${res.status}: ${text.slice(0, 200)}`);
|
|
1255
|
+
throw await googleApiError(res, "google-calendar get_event", inv.source.id);
|
|
1157
1256
|
}
|
|
1158
1257
|
const event = await res.json();
|
|
1159
1258
|
return {
|
|
@@ -1178,12 +1277,8 @@ async function listEvents(inv, accessToken, timeoutMs) {
|
|
|
1178
1277
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1179
1278
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1180
1279
|
});
|
|
1181
|
-
if (res.status === 401 || res.status === 403) {
|
|
1182
|
-
throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id);
|
|
1183
|
-
}
|
|
1184
1280
|
if (!res.ok) {
|
|
1185
|
-
|
|
1186
|
-
throw new Error(`google-calendar list_events ${res.status}: ${text.slice(0, 200)}`);
|
|
1281
|
+
throw await googleApiError(res, "google-calendar list_events", inv.source.id);
|
|
1187
1282
|
}
|
|
1188
1283
|
const json = await res.json();
|
|
1189
1284
|
return {
|
|
@@ -1210,8 +1305,7 @@ async function freebusyQuery(input) {
|
|
|
1210
1305
|
signal: AbortSignal.timeout(1e4)
|
|
1211
1306
|
});
|
|
1212
1307
|
if (!res.ok) {
|
|
1213
|
-
|
|
1214
|
-
throw new Error(`freebusy ${res.status}: ${text.slice(0, 200)}`);
|
|
1308
|
+
throw await googleApiError(res, "google-calendar freebusy", input.sourceId);
|
|
1215
1309
|
}
|
|
1216
1310
|
const json = await res.json();
|
|
1217
1311
|
return { busy: json.calendars?.[input.calendarId]?.busy ?? [] };
|
|
@@ -1226,7 +1320,8 @@ async function findNextFreeSlots(input) {
|
|
|
1226
1320
|
accessToken: input.accessToken,
|
|
1227
1321
|
calendarId: input.calendarId,
|
|
1228
1322
|
timeMin: new Date(cursor).toISOString(),
|
|
1229
|
-
timeMax: new Date(windowEnd).toISOString()
|
|
1323
|
+
timeMax: new Date(windowEnd).toISOString(),
|
|
1324
|
+
sourceId: input.sourceId
|
|
1230
1325
|
});
|
|
1231
1326
|
const busy = fb.busy.map((b) => ({ s: Date.parse(b.start), e: Date.parse(b.end) })).filter((b) => Number.isFinite(b.s) && Number.isFinite(b.e)).sort((a, b) => a.s - b.s);
|
|
1232
1327
|
let pos = cursor;
|
|
@@ -1480,10 +1575,10 @@ function googleDrive(opts) {
|
|
|
1480
1575
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1481
1576
|
signal: AbortSignal.timeout(8e3)
|
|
1482
1577
|
});
|
|
1483
|
-
if (res.
|
|
1484
|
-
|
|
1578
|
+
if (!res.ok) {
|
|
1579
|
+
const body = await res.json().catch(() => void 0);
|
|
1580
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Google Drive") };
|
|
1485
1581
|
}
|
|
1486
|
-
if (!res.ok) return { ok: false, reason: `Google Drive returned ${res.status}` };
|
|
1487
1582
|
return { ok: true };
|
|
1488
1583
|
} catch (err) {
|
|
1489
1584
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -1508,12 +1603,8 @@ async function listFiles(inv, accessToken, timeoutMs) {
|
|
|
1508
1603
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1509
1604
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1510
1605
|
});
|
|
1511
|
-
if (res.status === 401 || res.status === 403) {
|
|
1512
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1513
|
-
}
|
|
1514
1606
|
if (!res.ok) {
|
|
1515
|
-
|
|
1516
|
-
throw new Error(`google-drive list_files ${res.status}: ${text.slice(0, 200)}`);
|
|
1607
|
+
throw await googleApiError(res, "google-drive list_files", inv.source.id);
|
|
1517
1608
|
}
|
|
1518
1609
|
const json = await res.json();
|
|
1519
1610
|
return {
|
|
@@ -1532,15 +1623,11 @@ async function readFile(inv, accessToken, timeoutMs) {
|
|
|
1532
1623
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1533
1624
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1534
1625
|
});
|
|
1535
|
-
if (metaRes.status === 401 || metaRes.status === 403) {
|
|
1536
|
-
throw new CredentialsExpired(`Google Drive rejected token (${metaRes.status})`, inv.source.id);
|
|
1537
|
-
}
|
|
1538
1626
|
if (metaRes.status === 404) {
|
|
1539
1627
|
throw new Error(`google-drive read_file: file ${fileId} not found`);
|
|
1540
1628
|
}
|
|
1541
1629
|
if (!metaRes.ok) {
|
|
1542
|
-
|
|
1543
|
-
throw new Error(`google-drive read_file meta ${metaRes.status}: ${text.slice(0, 200)}`);
|
|
1630
|
+
throw await googleApiError(metaRes, "google-drive read_file meta", inv.source.id);
|
|
1544
1631
|
}
|
|
1545
1632
|
const meta = await metaRes.json();
|
|
1546
1633
|
const isNative = meta.mimeType.startsWith("application/vnd.google-apps.");
|
|
@@ -1552,8 +1639,7 @@ async function readFile(inv, accessToken, timeoutMs) {
|
|
|
1552
1639
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1553
1640
|
});
|
|
1554
1641
|
if (!res2.ok) {
|
|
1555
|
-
|
|
1556
|
-
throw new Error(`google-drive read_file export ${res2.status}: ${text.slice(0, 200)}`);
|
|
1642
|
+
throw await googleApiError(res2, "google-drive read_file export", inv.source.id);
|
|
1557
1643
|
}
|
|
1558
1644
|
const isTextLike2 = /^text\/|application\/(json|xml|csv|javascript)/.test(targetMime);
|
|
1559
1645
|
if (isTextLike2) {
|
|
@@ -1574,8 +1660,7 @@ async function readFile(inv, accessToken, timeoutMs) {
|
|
|
1574
1660
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1575
1661
|
});
|
|
1576
1662
|
if (!res.ok) {
|
|
1577
|
-
|
|
1578
|
-
throw new Error(`google-drive read_file media ${res.status}: ${text.slice(0, 200)}`);
|
|
1663
|
+
throw await googleApiError(res, "google-drive read_file media", inv.source.id);
|
|
1579
1664
|
}
|
|
1580
1665
|
const isTextLike = /^text\/|application\/(json|xml|csv|javascript)/.test(meta.mimeType);
|
|
1581
1666
|
if (isTextLike) {
|
|
@@ -1608,9 +1693,6 @@ async function watchFolder(inv, accessToken, timeoutMs) {
|
|
|
1608
1693
|
body: JSON.stringify(body),
|
|
1609
1694
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1610
1695
|
});
|
|
1611
|
-
if (res.status === 401 || res.status === 403) {
|
|
1612
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1613
|
-
}
|
|
1614
1696
|
if (res.status === 409) {
|
|
1615
1697
|
const cached = inv.source.metadata.watchedChannels?.[channelId];
|
|
1616
1698
|
return {
|
|
@@ -1621,8 +1703,7 @@ async function watchFolder(inv, accessToken, timeoutMs) {
|
|
|
1621
1703
|
};
|
|
1622
1704
|
}
|
|
1623
1705
|
if (!res.ok) {
|
|
1624
|
-
|
|
1625
|
-
throw new Error(`google-drive watch_folder ${res.status}: ${text.slice(0, 200)}`);
|
|
1706
|
+
throw await googleApiError(res, "google-drive watch_folder", inv.source.id);
|
|
1626
1707
|
}
|
|
1627
1708
|
const json = await res.json();
|
|
1628
1709
|
return {
|
|
@@ -1667,12 +1748,8 @@ Content-Type: ${mimeType}\r
|
|
|
1667
1748
|
body,
|
|
1668
1749
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1669
1750
|
});
|
|
1670
|
-
if (res.status === 401 || res.status === 403) {
|
|
1671
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1672
|
-
}
|
|
1673
1751
|
if (!res.ok) {
|
|
1674
|
-
|
|
1675
|
-
throw new Error(`google-drive upload_file ${res.status}: ${text.slice(0, 200)}`);
|
|
1752
|
+
throw await googleApiError(res, "google-drive upload_file", inv.source.id);
|
|
1676
1753
|
}
|
|
1677
1754
|
const json = await res.json();
|
|
1678
1755
|
return {
|
|
@@ -1707,12 +1784,8 @@ async function createFolder(inv, accessToken, timeoutMs) {
|
|
|
1707
1784
|
body: JSON.stringify(body),
|
|
1708
1785
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1709
1786
|
});
|
|
1710
|
-
if (res.status === 401 || res.status === 403) {
|
|
1711
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1712
|
-
}
|
|
1713
1787
|
if (!res.ok) {
|
|
1714
|
-
|
|
1715
|
-
throw new Error(`google-drive create_folder ${res.status}: ${text.slice(0, 200)}`);
|
|
1788
|
+
throw await googleApiError(res, "google-drive create_folder", inv.source.id);
|
|
1716
1789
|
}
|
|
1717
1790
|
const json = await res.json();
|
|
1718
1791
|
return {
|
|
@@ -1736,12 +1809,8 @@ async function deleteFile(inv, accessToken, timeoutMs) {
|
|
|
1736
1809
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
1737
1810
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1738
1811
|
});
|
|
1739
|
-
if (res.status === 401 || res.status === 403) {
|
|
1740
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1741
|
-
}
|
|
1742
1812
|
if (!res.ok && res.status !== 204) {
|
|
1743
|
-
|
|
1744
|
-
throw new Error(`google-drive delete_file ${res.status}: ${text.slice(0, 200)}`);
|
|
1813
|
+
throw await googleApiError(res, "google-drive delete_file", inv.source.id);
|
|
1745
1814
|
}
|
|
1746
1815
|
return {
|
|
1747
1816
|
status: "committed",
|
|
@@ -1771,12 +1840,8 @@ async function moveFile(inv, accessToken, timeoutMs) {
|
|
|
1771
1840
|
body: "{}",
|
|
1772
1841
|
signal: AbortSignal.timeout(timeoutMs)
|
|
1773
1842
|
});
|
|
1774
|
-
if (res.status === 401 || res.status === 403) {
|
|
1775
|
-
throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id);
|
|
1776
|
-
}
|
|
1777
1843
|
if (!res.ok) {
|
|
1778
|
-
|
|
1779
|
-
throw new Error(`google-drive move_file ${res.status}: ${text.slice(0, 200)}`);
|
|
1844
|
+
throw await googleApiError(res, "google-drive move_file", inv.source.id);
|
|
1780
1845
|
}
|
|
1781
1846
|
const json = await res.json();
|
|
1782
1847
|
return {
|
|
@@ -2030,10 +2095,10 @@ function googleSheets(opts) {
|
|
|
2030
2095
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
2031
2096
|
signal: AbortSignal.timeout(8e3)
|
|
2032
2097
|
});
|
|
2033
|
-
if (res.
|
|
2034
|
-
|
|
2098
|
+
if (!res.ok) {
|
|
2099
|
+
const body = await res.json().catch(() => void 0);
|
|
2100
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Google Sheets") };
|
|
2035
2101
|
}
|
|
2036
|
-
if (!res.ok) return { ok: false, reason: `Google returned ${res.status}` };
|
|
2037
2102
|
return { ok: true };
|
|
2038
2103
|
} catch (err) {
|
|
2039
2104
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -2060,12 +2125,8 @@ async function fetchAllRows(accessToken, meta) {
|
|
|
2060
2125
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
2061
2126
|
signal: AbortSignal.timeout(15e3)
|
|
2062
2127
|
});
|
|
2063
|
-
if (res.status === 401 || res.status === 403) {
|
|
2064
|
-
throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, "");
|
|
2065
|
-
}
|
|
2066
2128
|
if (!res.ok) {
|
|
2067
|
-
|
|
2068
|
-
throw new Error(`google-sheets values.get ${res.status}: ${text.slice(0, 200)}`);
|
|
2129
|
+
throw await googleApiError(res, "google-sheets values.get", "");
|
|
2069
2130
|
}
|
|
2070
2131
|
const json = await res.json();
|
|
2071
2132
|
const grid = json.values ?? [];
|
|
@@ -2178,12 +2239,8 @@ async function updateRow(inv, accessToken, timeoutMs) {
|
|
|
2178
2239
|
body: JSON.stringify({ values: [updatedValues] }),
|
|
2179
2240
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2180
2241
|
});
|
|
2181
|
-
if (res.status === 401 || res.status === 403) {
|
|
2182
|
-
throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, inv.source.id);
|
|
2183
|
-
}
|
|
2184
2242
|
if (!res.ok) {
|
|
2185
|
-
|
|
2186
|
-
throw new Error(`google-sheets update_row ${res.status}: ${text.slice(0, 200)}`);
|
|
2243
|
+
throw await googleApiError(res, "google-sheets update_row", inv.source.id);
|
|
2187
2244
|
}
|
|
2188
2245
|
const updatedValuesByHeader = Object.fromEntries(
|
|
2189
2246
|
meta.headers.map((h, i) => [h, updatedValues[i] ?? ""])
|
|
@@ -2218,12 +2275,8 @@ async function appendRow(inv, accessToken, timeoutMs) {
|
|
|
2218
2275
|
body: JSON.stringify({ values: args.values }),
|
|
2219
2276
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2220
2277
|
});
|
|
2221
|
-
if (res.status === 401 || res.status === 403) {
|
|
2222
|
-
throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, inv.source.id);
|
|
2223
|
-
}
|
|
2224
2278
|
if (!res.ok) {
|
|
2225
|
-
|
|
2226
|
-
throw new Error(`google-sheets append_row ${res.status}: ${text.slice(0, 200)}`);
|
|
2279
|
+
throw await googleApiError(res, "google-sheets append_row", inv.source.id);
|
|
2227
2280
|
}
|
|
2228
2281
|
const json = await res.json();
|
|
2229
2282
|
return {
|
|
@@ -2254,12 +2307,8 @@ async function clearRange(inv, accessToken, timeoutMs) {
|
|
|
2254
2307
|
body: "{}",
|
|
2255
2308
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2256
2309
|
});
|
|
2257
|
-
if (res.status === 401 || res.status === 403) {
|
|
2258
|
-
throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, inv.source.id);
|
|
2259
|
-
}
|
|
2260
2310
|
if (!res.ok) {
|
|
2261
|
-
|
|
2262
|
-
throw new Error(`google-sheets clear_range ${res.status}: ${text.slice(0, 200)}`);
|
|
2311
|
+
throw await googleApiError(res, "google-sheets clear_range", inv.source.id);
|
|
2263
2312
|
}
|
|
2264
2313
|
const json = await res.json().catch(() => ({}));
|
|
2265
2314
|
return {
|
|
@@ -2285,12 +2334,8 @@ async function createSheet(inv, accessToken, timeoutMs) {
|
|
|
2285
2334
|
body: JSON.stringify({ properties: { title: args.title } }),
|
|
2286
2335
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2287
2336
|
});
|
|
2288
|
-
if (res.status === 401 || res.status === 403) {
|
|
2289
|
-
throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, inv.source.id);
|
|
2290
|
-
}
|
|
2291
2337
|
if (!res.ok) {
|
|
2292
|
-
|
|
2293
|
-
throw new Error(`google-sheets create_sheet ${res.status}: ${text.slice(0, 200)}`);
|
|
2338
|
+
throw await googleApiError(res, "google-sheets create_sheet", inv.source.id);
|
|
2294
2339
|
}
|
|
2295
2340
|
const json = await res.json();
|
|
2296
2341
|
return {
|
|
@@ -2450,6 +2495,9 @@ async function executeRestRequest(spec, request, inv, requiredArgs) {
|
|
|
2450
2495
|
}
|
|
2451
2496
|
};
|
|
2452
2497
|
}
|
|
2498
|
+
if (request.existenceCheck && (res.status === 204 || res.status === 404)) {
|
|
2499
|
+
return { data: { exists: res.status === 204 } };
|
|
2500
|
+
}
|
|
2453
2501
|
if (!res.ok) {
|
|
2454
2502
|
throw new Error(`${spec.kind} ${request.method} ${url.pathname} HTTP ${res.status}: ${(await safeErrorText(res)).slice(0, 300)}`);
|
|
2455
2503
|
}
|
|
@@ -2882,10 +2930,10 @@ function gmail(opts) {
|
|
|
2882
2930
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
2883
2931
|
signal: AbortSignal.timeout(8e3)
|
|
2884
2932
|
});
|
|
2885
|
-
if (res.
|
|
2886
|
-
|
|
2933
|
+
if (!res.ok) {
|
|
2934
|
+
const body = await res.json().catch(() => void 0);
|
|
2935
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Gmail") };
|
|
2887
2936
|
}
|
|
2888
|
-
if (!res.ok) return { ok: false, reason: `Gmail returned ${res.status}` };
|
|
2889
2937
|
return { ok: true };
|
|
2890
2938
|
} catch (err) {
|
|
2891
2939
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -2906,12 +2954,8 @@ async function listMessages(inv, accessToken, timeoutMs) {
|
|
|
2906
2954
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
2907
2955
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2908
2956
|
});
|
|
2909
|
-
if (listRes.status === 401 || listRes.status === 403) {
|
|
2910
|
-
throw new CredentialsExpired(`Gmail rejected token (${listRes.status})`, inv.source.id);
|
|
2911
|
-
}
|
|
2912
2957
|
if (!listRes.ok) {
|
|
2913
|
-
|
|
2914
|
-
throw new Error(`gmail list_messages ${listRes.status}: ${text.slice(0, 200)}`);
|
|
2958
|
+
throw await googleApiError(listRes, "gmail list_messages", inv.source.id);
|
|
2915
2959
|
}
|
|
2916
2960
|
const listJson = await listRes.json();
|
|
2917
2961
|
const ids = listJson.messages ?? [];
|
|
@@ -2951,15 +2995,11 @@ async function readMessage(inv, accessToken, timeoutMs) {
|
|
|
2951
2995
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
2952
2996
|
signal: AbortSignal.timeout(timeoutMs)
|
|
2953
2997
|
});
|
|
2954
|
-
if (res.status === 401 || res.status === 403) {
|
|
2955
|
-
throw new CredentialsExpired(`Gmail rejected token (${res.status})`, inv.source.id);
|
|
2956
|
-
}
|
|
2957
2998
|
if (res.status === 404) {
|
|
2958
2999
|
throw new Error(`gmail read_message: message ${id} not found`);
|
|
2959
3000
|
}
|
|
2960
3001
|
if (!res.ok) {
|
|
2961
|
-
|
|
2962
|
-
throw new Error(`gmail read_message ${res.status}: ${text.slice(0, 200)}`);
|
|
3002
|
+
throw await googleApiError(res, "gmail read_message", inv.source.id);
|
|
2963
3003
|
}
|
|
2964
3004
|
const full = await res.json();
|
|
2965
3005
|
const headers = new Map((full.payload?.headers ?? []).map((h) => [h.name.toLowerCase(), h.value]));
|
|
@@ -3035,12 +3075,8 @@ ${args.body}`;
|
|
|
3035
3075
|
body: JSON.stringify({ raw: encodeBase64Url(raw) }),
|
|
3036
3076
|
signal: AbortSignal.timeout(timeoutMs)
|
|
3037
3077
|
});
|
|
3038
|
-
if (sendRes.status === 401 || sendRes.status === 403) {
|
|
3039
|
-
throw new CredentialsExpired(`Gmail rejected token (${sendRes.status})`, inv.source.id);
|
|
3040
|
-
}
|
|
3041
3078
|
if (!sendRes.ok) {
|
|
3042
|
-
|
|
3043
|
-
throw new Error(`gmail send ${sendRes.status}: ${text.slice(0, 200)}`);
|
|
3079
|
+
throw await googleApiError(sendRes, "gmail send", inv.source.id);
|
|
3044
3080
|
}
|
|
3045
3081
|
const sent = await sendRes.json();
|
|
3046
3082
|
return {
|
|
@@ -3056,12 +3092,8 @@ async function sendReply(inv, accessToken, timeoutMs) {
|
|
|
3056
3092
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
3057
3093
|
signal: AbortSignal.timeout(timeoutMs)
|
|
3058
3094
|
});
|
|
3059
|
-
if (threadRes.status === 401 || threadRes.status === 403) {
|
|
3060
|
-
throw new CredentialsExpired(`Gmail rejected token (${threadRes.status})`, inv.source.id);
|
|
3061
|
-
}
|
|
3062
3095
|
if (!threadRes.ok) {
|
|
3063
|
-
|
|
3064
|
-
throw new Error(`gmail send_reply thread fetch ${threadRes.status}: ${text.slice(0, 200)}`);
|
|
3096
|
+
throw await googleApiError(threadRes, "gmail send_reply thread fetch", inv.source.id);
|
|
3065
3097
|
}
|
|
3066
3098
|
const thread = await threadRes.json();
|
|
3067
3099
|
const last = thread.messages?.[thread.messages.length - 1];
|
|
@@ -3104,12 +3136,8 @@ ${body}`;
|
|
|
3104
3136
|
body: JSON.stringify(sendBody),
|
|
3105
3137
|
signal: AbortSignal.timeout(timeoutMs)
|
|
3106
3138
|
});
|
|
3107
|
-
if (sendRes.status === 401 || sendRes.status === 403) {
|
|
3108
|
-
throw new CredentialsExpired(`Gmail rejected token (${sendRes.status})`, inv.source.id);
|
|
3109
|
-
}
|
|
3110
3139
|
if (!sendRes.ok) {
|
|
3111
|
-
|
|
3112
|
-
throw new Error(`gmail send_reply ${sendRes.status}: ${text.slice(0, 200)}`);
|
|
3140
|
+
throw await googleApiError(sendRes, "gmail send_reply", inv.source.id);
|
|
3113
3141
|
}
|
|
3114
3142
|
const sent = await sendRes.json();
|
|
3115
3143
|
return {
|
|
@@ -3135,12 +3163,8 @@ async function watchLabel(inv, accessToken, timeoutMs) {
|
|
|
3135
3163
|
body: JSON.stringify(body),
|
|
3136
3164
|
signal: AbortSignal.timeout(timeoutMs)
|
|
3137
3165
|
});
|
|
3138
|
-
if (res.status === 401 || res.status === 403) {
|
|
3139
|
-
throw new CredentialsExpired(`Gmail rejected token (${res.status})`, inv.source.id);
|
|
3140
|
-
}
|
|
3141
3166
|
if (!res.ok) {
|
|
3142
|
-
|
|
3143
|
-
throw new Error(`gmail watch_label ${res.status}: ${text.slice(0, 200)}`);
|
|
3167
|
+
throw await googleApiError(res, "gmail watch_label", inv.source.id);
|
|
3144
3168
|
}
|
|
3145
3169
|
const json = await res.json();
|
|
3146
3170
|
return {
|
|
@@ -7297,6 +7321,83 @@ var githubConnector = declarativeRestConnector({
|
|
|
7297
7321
|
},
|
|
7298
7322
|
request: { method: "GET", path: "/search/issues", query: { q: "{q}", per_page: "{per_page}" } }
|
|
7299
7323
|
},
|
|
7324
|
+
{
|
|
7325
|
+
name: "users.getAuthenticated",
|
|
7326
|
+
class: "read",
|
|
7327
|
+
description: "Resolve the authenticated user (the token owner). Quest verification anchors author:/owner: filters to this login, so it must be resolved first.",
|
|
7328
|
+
parameters: { type: "object", properties: {}, required: [] },
|
|
7329
|
+
request: { method: "GET", path: "/user" }
|
|
7330
|
+
},
|
|
7331
|
+
{
|
|
7332
|
+
name: "activity.checkStarred",
|
|
7333
|
+
class: "read",
|
|
7334
|
+
description: "Check whether the authenticated user has starred a repository. Returns { exists: true } when starred, { exists: false } when not.",
|
|
7335
|
+
parameters: repoParams,
|
|
7336
|
+
request: { method: "GET", path: "/user/starred/{owner}/{repo}", existenceCheck: true }
|
|
7337
|
+
},
|
|
7338
|
+
{
|
|
7339
|
+
name: "users.checkFollowing",
|
|
7340
|
+
class: "read",
|
|
7341
|
+
description: "Check whether the authenticated user follows another user. Returns { exists: true } when following, { exists: false } when not.",
|
|
7342
|
+
parameters: {
|
|
7343
|
+
type: "object",
|
|
7344
|
+
properties: { target: { type: "string", description: "Login of the user to check the follow against." } },
|
|
7345
|
+
required: ["target"]
|
|
7346
|
+
},
|
|
7347
|
+
request: { method: "GET", path: "/user/following/{target}", existenceCheck: true }
|
|
7348
|
+
},
|
|
7349
|
+
{
|
|
7350
|
+
name: "repos.listCommits",
|
|
7351
|
+
class: "read",
|
|
7352
|
+
description: "List commits on a repository, optionally filtered to a single author login/email. Used to verify a user contributed to the repo.",
|
|
7353
|
+
parameters: {
|
|
7354
|
+
type: "object",
|
|
7355
|
+
properties: {
|
|
7356
|
+
owner: { type: "string" },
|
|
7357
|
+
repo: { type: "string" },
|
|
7358
|
+
author: { type: "string", description: "Restrict to commits authored by this GitHub login or email." },
|
|
7359
|
+
per_page: { type: "integer", minimum: 1, maximum: 100 }
|
|
7360
|
+
},
|
|
7361
|
+
required: ["owner", "repo"]
|
|
7362
|
+
},
|
|
7363
|
+
request: {
|
|
7364
|
+
method: "GET",
|
|
7365
|
+
path: "/repos/{owner}/{repo}/commits",
|
|
7366
|
+
query: { author: "{author}", per_page: "{per_page}" }
|
|
7367
|
+
}
|
|
7368
|
+
},
|
|
7369
|
+
{
|
|
7370
|
+
name: "repos.getReadme",
|
|
7371
|
+
class: "read",
|
|
7372
|
+
description: "Read a repository's README (returns base64-encoded content). Used to verify README mentions.",
|
|
7373
|
+
parameters: repoParams,
|
|
7374
|
+
request: { method: "GET", path: "/repos/{owner}/{repo}/readme" }
|
|
7375
|
+
},
|
|
7376
|
+
{
|
|
7377
|
+
name: "search.code",
|
|
7378
|
+
class: "read",
|
|
7379
|
+
description: "Search code across GitHub. Used to verify code usage of a symbol or string.",
|
|
7380
|
+
parameters: {
|
|
7381
|
+
type: "object",
|
|
7382
|
+
properties: { q: { type: "string" }, per_page: { type: "integer", minimum: 1, maximum: 100 } },
|
|
7383
|
+
required: ["q"]
|
|
7384
|
+
},
|
|
7385
|
+
request: { method: "GET", path: "/search/code", query: { q: "{q}", per_page: "{per_page}" } }
|
|
7386
|
+
},
|
|
7387
|
+
{
|
|
7388
|
+
name: "orgs.checkMembership",
|
|
7389
|
+
class: "read",
|
|
7390
|
+
description: "Check whether a user is a member of an organization. Returns { exists: true } when a member, { exists: false } when not.",
|
|
7391
|
+
parameters: {
|
|
7392
|
+
type: "object",
|
|
7393
|
+
properties: {
|
|
7394
|
+
org: { type: "string" },
|
|
7395
|
+
user: { type: "string", description: "Login of the user to check membership for." }
|
|
7396
|
+
},
|
|
7397
|
+
required: ["org", "user"]
|
|
7398
|
+
},
|
|
7399
|
+
request: { method: "GET", path: "/orgs/{org}/members/{user}", existenceCheck: true }
|
|
7400
|
+
},
|
|
7300
7401
|
{
|
|
7301
7402
|
name: "issues.create",
|
|
7302
7403
|
class: "mutation",
|
|
@@ -38378,10 +38479,10 @@ function googleDocs(opts) {
|
|
|
38378
38479
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38379
38480
|
signal: AbortSignal.timeout(8e3)
|
|
38380
38481
|
});
|
|
38381
|
-
if (res.
|
|
38382
|
-
|
|
38482
|
+
if (!res.ok) {
|
|
38483
|
+
const body = await res.json().catch(() => void 0);
|
|
38484
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Google Docs") };
|
|
38383
38485
|
}
|
|
38384
|
-
if (!res.ok) return { ok: false, reason: `Google userinfo returned ${res.status}` };
|
|
38385
38486
|
return { ok: true };
|
|
38386
38487
|
} catch (err) {
|
|
38387
38488
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -38417,15 +38518,11 @@ async function getDocument2(inv, accessToken, timeoutMs) {
|
|
|
38417
38518
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38418
38519
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38419
38520
|
});
|
|
38420
|
-
if (res.status === 401 || res.status === 403) {
|
|
38421
|
-
throw new CredentialsExpired(`Google Docs rejected token (${res.status})`, inv.source.id);
|
|
38422
|
-
}
|
|
38423
38521
|
if (res.status === 404) {
|
|
38424
38522
|
throw new Error(`google-docs get_document: document ${documentId} not found`);
|
|
38425
38523
|
}
|
|
38426
38524
|
if (!res.ok) {
|
|
38427
|
-
|
|
38428
|
-
throw new Error(`google-docs get_document ${res.status}: ${text.slice(0, 200)}`);
|
|
38525
|
+
throw await googleApiError(res, "google-docs get_document", inv.source.id);
|
|
38429
38526
|
}
|
|
38430
38527
|
const doc = await res.json();
|
|
38431
38528
|
return {
|
|
@@ -38456,12 +38553,8 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38456
38553
|
body: JSON.stringify({ title }),
|
|
38457
38554
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38458
38555
|
});
|
|
38459
|
-
if (createRes.status === 401 || createRes.status === 403) {
|
|
38460
|
-
throw new CredentialsExpired(`Google Docs rejected token (${createRes.status})`, inv.source.id);
|
|
38461
|
-
}
|
|
38462
38556
|
if (!createRes.ok) {
|
|
38463
|
-
|
|
38464
|
-
throw new Error(`google-docs create_document ${createRes.status}: ${text.slice(0, 200)}`);
|
|
38557
|
+
throw await googleApiError(createRes, "google-docs create_document", inv.source.id);
|
|
38465
38558
|
}
|
|
38466
38559
|
const created = await createRes.json();
|
|
38467
38560
|
let revisionId = created.revisionId;
|
|
@@ -38487,12 +38580,8 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38487
38580
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38488
38581
|
}
|
|
38489
38582
|
);
|
|
38490
|
-
if (insertRes.status === 401 || insertRes.status === 403) {
|
|
38491
|
-
throw new CredentialsExpired(`Google Docs rejected token (${insertRes.status})`, inv.source.id);
|
|
38492
|
-
}
|
|
38493
38583
|
if (!insertRes.ok) {
|
|
38494
|
-
|
|
38495
|
-
throw new Error(`google-docs create_document insertText ${insertRes.status}: ${text.slice(0, 200)}`);
|
|
38584
|
+
throw await googleApiError(insertRes, "google-docs create_document insertText", inv.source.id);
|
|
38496
38585
|
}
|
|
38497
38586
|
const insertJson = await insertRes.json();
|
|
38498
38587
|
revisionId = insertJson.writeControl?.requiredRevisionId ?? revisionId;
|
|
@@ -38514,15 +38603,11 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38514
38603
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38515
38604
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38516
38605
|
});
|
|
38517
|
-
if (docRes.status === 401 || docRes.status === 403) {
|
|
38518
|
-
throw new CredentialsExpired(`Google Docs rejected token (${docRes.status})`, inv.source.id);
|
|
38519
|
-
}
|
|
38520
38606
|
if (docRes.status === 404) {
|
|
38521
38607
|
throw new Error(`google-docs append_text: document ${documentId} not found`);
|
|
38522
38608
|
}
|
|
38523
38609
|
if (!docRes.ok) {
|
|
38524
|
-
|
|
38525
|
-
throw new Error(`google-docs append_text fetch ${docRes.status}: ${errText.slice(0, 200)}`);
|
|
38610
|
+
throw await googleApiError(docRes, "google-docs append_text fetch", inv.source.id);
|
|
38526
38611
|
}
|
|
38527
38612
|
const doc = await docRes.json();
|
|
38528
38613
|
const insertIndex = findAppendIndex(doc);
|
|
@@ -38551,9 +38636,6 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38551
38636
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38552
38637
|
}
|
|
38553
38638
|
);
|
|
38554
|
-
if (res.status === 401 || res.status === 403) {
|
|
38555
|
-
throw new CredentialsExpired(`Google Docs rejected token (${res.status})`, inv.source.id);
|
|
38556
|
-
}
|
|
38557
38639
|
if (res.status === 400 && requiredRevisionId) {
|
|
38558
38640
|
const errBody = await res.text().catch(() => "");
|
|
38559
38641
|
if (/FAILED_PRECONDITION|requiredRevisionId/i.test(errBody)) {
|
|
@@ -38566,8 +38648,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38566
38648
|
throw new Error(`google-docs append_text ${res.status}: ${errBody.slice(0, 200)}`);
|
|
38567
38649
|
}
|
|
38568
38650
|
if (!res.ok) {
|
|
38569
|
-
|
|
38570
|
-
throw new Error(`google-docs append_text ${res.status}: ${errBody.slice(0, 200)}`);
|
|
38651
|
+
throw await googleApiError(res, "google-docs append_text", inv.source.id);
|
|
38571
38652
|
}
|
|
38572
38653
|
const json = await res.json();
|
|
38573
38654
|
return {
|
|
@@ -38592,15 +38673,11 @@ async function deleteDocument(inv, accessToken, timeoutMs) {
|
|
|
38592
38673
|
body: JSON.stringify({ trashed: true }),
|
|
38593
38674
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38594
38675
|
});
|
|
38595
|
-
if (res.status === 401 || res.status === 403) {
|
|
38596
|
-
throw new CredentialsExpired(`Google Docs rejected token (${res.status})`, inv.source.id);
|
|
38597
|
-
}
|
|
38598
38676
|
if (res.status === 404) {
|
|
38599
38677
|
throw new Error(`google-docs delete_document: document ${documentId} not found`);
|
|
38600
38678
|
}
|
|
38601
38679
|
if (!res.ok) {
|
|
38602
|
-
|
|
38603
|
-
throw new Error(`google-docs delete_document ${res.status}: ${text.slice(0, 200)}`);
|
|
38680
|
+
throw await googleApiError(res, "google-docs delete_document", inv.source.id);
|
|
38604
38681
|
}
|
|
38605
38682
|
const json = await res.json().catch(() => ({}));
|
|
38606
38683
|
return {
|
|
@@ -38626,15 +38703,11 @@ async function exportDocument(inv, accessToken, timeoutMs) {
|
|
|
38626
38703
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38627
38704
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38628
38705
|
});
|
|
38629
|
-
if (res.status === 401 || res.status === 403) {
|
|
38630
|
-
throw new CredentialsExpired(`Google Docs rejected token (${res.status})`, inv.source.id);
|
|
38631
|
-
}
|
|
38632
38706
|
if (res.status === 404) {
|
|
38633
38707
|
throw new Error(`google-docs export_document: document ${documentId} not found`);
|
|
38634
38708
|
}
|
|
38635
38709
|
if (!res.ok) {
|
|
38636
|
-
|
|
38637
|
-
throw new Error(`google-docs export_document ${res.status}: ${text.slice(0, 200)}`);
|
|
38710
|
+
throw await googleApiError(res, "google-docs export_document", inv.source.id);
|
|
38638
38711
|
}
|
|
38639
38712
|
const buf = new Uint8Array(await res.arrayBuffer());
|
|
38640
38713
|
let binary = "";
|
|
@@ -38879,10 +38952,10 @@ function googleForms(opts) {
|
|
|
38879
38952
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38880
38953
|
signal: AbortSignal.timeout(8e3)
|
|
38881
38954
|
});
|
|
38882
|
-
if (res.
|
|
38883
|
-
|
|
38955
|
+
if (!res.ok) {
|
|
38956
|
+
const body = await res.json().catch(() => void 0);
|
|
38957
|
+
return { ok: false, reason: googleTestFailureReason(res.status, body, "Google Forms") };
|
|
38884
38958
|
}
|
|
38885
|
-
if (!res.ok) return { ok: false, reason: `Google userinfo returned ${res.status}` };
|
|
38886
38959
|
return { ok: true };
|
|
38887
38960
|
} catch (err) {
|
|
38888
38961
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -38910,15 +38983,11 @@ async function getForm(inv, accessToken, timeoutMs) {
|
|
|
38910
38983
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38911
38984
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38912
38985
|
});
|
|
38913
|
-
if (res.status === 401 || res.status === 403) {
|
|
38914
|
-
throw new CredentialsExpired(`Google Forms rejected token (${res.status})`, inv.source.id);
|
|
38915
|
-
}
|
|
38916
38986
|
if (res.status === 404) {
|
|
38917
38987
|
throw new Error(`google-forms get_form: form ${formId} not found`);
|
|
38918
38988
|
}
|
|
38919
38989
|
if (!res.ok) {
|
|
38920
|
-
|
|
38921
|
-
throw new Error(`google-forms get_form ${res.status}: ${text.slice(0, 200)}`);
|
|
38990
|
+
throw await googleApiError(res, "google-forms get_form", inv.source.id);
|
|
38922
38991
|
}
|
|
38923
38992
|
const form = await res.json();
|
|
38924
38993
|
return {
|
|
@@ -38946,15 +39015,11 @@ async function listResponses(inv, accessToken, timeoutMs) {
|
|
|
38946
39015
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38947
39016
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38948
39017
|
});
|
|
38949
|
-
if (res.status === 401 || res.status === 403) {
|
|
38950
|
-
throw new CredentialsExpired(`Google Forms rejected token (${res.status})`, inv.source.id);
|
|
38951
|
-
}
|
|
38952
39018
|
if (res.status === 404) {
|
|
38953
39019
|
throw new Error(`google-forms list_responses: form ${formId} not found`);
|
|
38954
39020
|
}
|
|
38955
39021
|
if (!res.ok) {
|
|
38956
|
-
|
|
38957
|
-
throw new Error(`google-forms list_responses ${res.status}: ${text.slice(0, 200)}`);
|
|
39022
|
+
throw await googleApiError(res, "google-forms list_responses", inv.source.id);
|
|
38958
39023
|
}
|
|
38959
39024
|
const envelope = await res.json();
|
|
38960
39025
|
const responses = (envelope.responses ?? []).map((r) => ({
|
|
@@ -38984,15 +39049,11 @@ async function getResponse(inv, accessToken, timeoutMs) {
|
|
|
38984
39049
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38985
39050
|
}
|
|
38986
39051
|
);
|
|
38987
|
-
if (res.status === 401 || res.status === 403) {
|
|
38988
|
-
throw new CredentialsExpired(`Google Forms rejected token (${res.status})`, inv.source.id);
|
|
38989
|
-
}
|
|
38990
39052
|
if (res.status === 404) {
|
|
38991
39053
|
throw new Error(`google-forms get_response: response ${responseId} not found`);
|
|
38992
39054
|
}
|
|
38993
39055
|
if (!res.ok) {
|
|
38994
|
-
|
|
38995
|
-
throw new Error(`google-forms get_response ${res.status}: ${text.slice(0, 200)}`);
|
|
39056
|
+
throw await googleApiError(res, "google-forms get_response", inv.source.id);
|
|
38996
39057
|
}
|
|
38997
39058
|
const r = await res.json();
|
|
38998
39059
|
return {
|
|
@@ -39021,12 +39082,8 @@ async function createForm(inv, accessToken, timeoutMs) {
|
|
|
39021
39082
|
body: JSON.stringify({ info }),
|
|
39022
39083
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39023
39084
|
});
|
|
39024
|
-
if (res.status === 401 || res.status === 403) {
|
|
39025
|
-
throw new CredentialsExpired(`Google Forms rejected token (${res.status})`, inv.source.id);
|
|
39026
|
-
}
|
|
39027
39085
|
if (!res.ok) {
|
|
39028
|
-
|
|
39029
|
-
throw new Error(`google-forms create_form ${res.status}: ${text.slice(0, 200)}`);
|
|
39086
|
+
throw await googleApiError(res, "google-forms create_form", inv.source.id);
|
|
39030
39087
|
}
|
|
39031
39088
|
const form = await res.json();
|
|
39032
39089
|
return {
|
|
@@ -39060,12 +39117,8 @@ async function batchUpdate(inv, accessToken, timeoutMs) {
|
|
|
39060
39117
|
body: JSON.stringify(body),
|
|
39061
39118
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39062
39119
|
});
|
|
39063
|
-
if (res.status === 401 || res.status === 403) {
|
|
39064
|
-
throw new CredentialsExpired(`Google Forms rejected token (${res.status})`, inv.source.id);
|
|
39065
|
-
}
|
|
39066
39120
|
if (!res.ok) {
|
|
39067
|
-
|
|
39068
|
-
throw new Error(`google-forms batch_update ${res.status}: ${text.slice(0, 200)}`);
|
|
39121
|
+
throw await googleApiError(res, "google-forms batch_update", inv.source.id);
|
|
39069
39122
|
}
|
|
39070
39123
|
const json = await res.json();
|
|
39071
39124
|
return {
|
|
@@ -113175,11 +113228,11 @@ var twinLabsConnector = declarativeRestConnector({
|
|
|
113175
113228
|
// src/connectors/adapters/twitter.ts
|
|
113176
113229
|
var AUTH_URL18 = "https://twitter.com/i/oauth2/authorize";
|
|
113177
113230
|
var TOKEN_URL19 = "https://api.twitter.com/2/oauth2/token";
|
|
113178
|
-
var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "like.write", "offline.access"];
|
|
113231
|
+
var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "follows.read", "like.write", "like.read", "offline.access"];
|
|
113179
113232
|
var TWITTER_SPEC = {
|
|
113180
113233
|
kind: "twitter",
|
|
113181
113234
|
displayName: "Twitter",
|
|
113182
|
-
description: "
|
|
113235
|
+
description: "Read and verify Twitter/X engagement (follows, tweets, likes, retweets, mentions) and post or reply to tweets.",
|
|
113183
113236
|
auth: {
|
|
113184
113237
|
kind: "one_of",
|
|
113185
113238
|
preferred: "oauth2",
|
|
@@ -113201,7 +113254,10 @@ var TWITTER_SPEC = {
|
|
|
113201
113254
|
category: "comms",
|
|
113202
113255
|
defaultConsistencyModel: "authoritative",
|
|
113203
113256
|
baseUrl: "https://api.twitter.com/2",
|
|
113204
|
-
|
|
113257
|
+
// `/users/me` is the cheapest read that proves the grant: it needs only
|
|
113258
|
+
// users.read, carries no required query param, and works on the free tier
|
|
113259
|
+
// (unlike `/tweets/search/recent`, which 400s without a `query`).
|
|
113260
|
+
test: { method: "GET", path: "/users/me" },
|
|
113205
113261
|
capabilities: [
|
|
113206
113262
|
{
|
|
113207
113263
|
name: "tweets.create",
|
|
@@ -113299,6 +113355,123 @@ var TWITTER_SPEC = {
|
|
|
113299
113355
|
},
|
|
113300
113356
|
cas: "native-idempotency",
|
|
113301
113357
|
externalEffect: true
|
|
113358
|
+
},
|
|
113359
|
+
// Read capabilities (official X API v2) — power quest verification in
|
|
113360
|
+
// blueprint-agent. `users.me` is the anchor: it resolves the connected
|
|
113361
|
+
// user id every other read needs. Optional `max_results` / `pagination_token`
|
|
113362
|
+
// are dropped from the query when the caller omits them, so the declarative
|
|
113363
|
+
// engine renders the bare endpoint by default. `following`, `liking_users`,
|
|
113364
|
+
// and `retweeted_by` are gated behind a PAID X API tier at runtime — the
|
|
113365
|
+
// capability is always present; availability is the registered app's tier.
|
|
113366
|
+
{
|
|
113367
|
+
name: "users.me",
|
|
113368
|
+
class: "read",
|
|
113369
|
+
description: 'Resolve the connected account (id, name, username) \u2014 anchors every other read. Pass user_fields (e.g. "public_metrics,created_at") to also fetch follower count and account age for anti-bot gating.',
|
|
113370
|
+
parameters: {
|
|
113371
|
+
type: "object",
|
|
113372
|
+
properties: {
|
|
113373
|
+
user_fields: {
|
|
113374
|
+
type: "string",
|
|
113375
|
+
description: 'Optional X `user.fields` selector, e.g. "public_metrics,created_at".'
|
|
113376
|
+
}
|
|
113377
|
+
}
|
|
113378
|
+
},
|
|
113379
|
+
request: { method: "GET", path: "/users/me", query: { "user.fields": "{user_fields}" } }
|
|
113380
|
+
},
|
|
113381
|
+
{
|
|
113382
|
+
name: "users.following",
|
|
113383
|
+
class: "read",
|
|
113384
|
+
description: "List the accounts a user follows, for verifying follows and followed_by. Cursor with pagination_token. Gated behind a paid X API tier.",
|
|
113385
|
+
parameters: {
|
|
113386
|
+
type: "object",
|
|
113387
|
+
properties: {
|
|
113388
|
+
id: { type: "string", description: "User id whose following list to read (from users.me)." },
|
|
113389
|
+
max_results: { type: "integer", description: "Page size (1\u20131000)." },
|
|
113390
|
+
pagination_token: { type: "string", description: "Cursor from a prior page (meta.next_token)." }
|
|
113391
|
+
},
|
|
113392
|
+
required: ["id"]
|
|
113393
|
+
},
|
|
113394
|
+
request: {
|
|
113395
|
+
method: "GET",
|
|
113396
|
+
path: "/users/{id}/following",
|
|
113397
|
+
query: { max_results: "{max_results}", pagination_token: "{pagination_token}" }
|
|
113398
|
+
}
|
|
113399
|
+
},
|
|
113400
|
+
{
|
|
113401
|
+
name: "users.tweets",
|
|
113402
|
+
class: "read",
|
|
113403
|
+
description: "List recent tweets authored by a user, for verifying tweeted. Hashtag filtering is applied by the caller. Cursor with pagination_token.",
|
|
113404
|
+
parameters: {
|
|
113405
|
+
type: "object",
|
|
113406
|
+
properties: {
|
|
113407
|
+
id: { type: "string", description: "Author user id (from users.me)." },
|
|
113408
|
+
max_results: { type: "integer", description: "Page size (5\u2013100)." },
|
|
113409
|
+
pagination_token: { type: "string", description: "Cursor from a prior page (meta.next_token)." }
|
|
113410
|
+
},
|
|
113411
|
+
required: ["id"]
|
|
113412
|
+
},
|
|
113413
|
+
request: {
|
|
113414
|
+
method: "GET",
|
|
113415
|
+
path: "/users/{id}/tweets",
|
|
113416
|
+
query: { max_results: "{max_results}", "tweet.fields": "text,created_at", pagination_token: "{pagination_token}" }
|
|
113417
|
+
}
|
|
113418
|
+
},
|
|
113419
|
+
{
|
|
113420
|
+
name: "tweets.retweetedBy",
|
|
113421
|
+
class: "read",
|
|
113422
|
+
description: "List the accounts that retweeted a tweet, for verifying retweeted. Cursor with pagination_token. Gated behind a paid X API tier.",
|
|
113423
|
+
parameters: {
|
|
113424
|
+
type: "object",
|
|
113425
|
+
properties: {
|
|
113426
|
+
id: { type: "string", description: "Tweet id to inspect." },
|
|
113427
|
+
max_results: { type: "integer", description: "Page size (1\u2013100)." },
|
|
113428
|
+
pagination_token: { type: "string", description: "Cursor from a prior page (meta.next_token)." }
|
|
113429
|
+
},
|
|
113430
|
+
required: ["id"]
|
|
113431
|
+
},
|
|
113432
|
+
request: {
|
|
113433
|
+
method: "GET",
|
|
113434
|
+
path: "/tweets/{id}/retweeted_by",
|
|
113435
|
+
query: { max_results: "{max_results}", pagination_token: "{pagination_token}" }
|
|
113436
|
+
}
|
|
113437
|
+
},
|
|
113438
|
+
{
|
|
113439
|
+
name: "tweets.likingUsers",
|
|
113440
|
+
class: "read",
|
|
113441
|
+
description: "List the accounts that liked a tweet, for verifying liked. Requires the like.read scope and a paid X API tier.",
|
|
113442
|
+
parameters: {
|
|
113443
|
+
type: "object",
|
|
113444
|
+
properties: {
|
|
113445
|
+
id: { type: "string", description: "Tweet id to inspect." },
|
|
113446
|
+
max_results: { type: "integer", description: "Page size (1\u2013100)." },
|
|
113447
|
+
pagination_token: { type: "string", description: "Cursor from a prior page (meta.next_token)." }
|
|
113448
|
+
},
|
|
113449
|
+
required: ["id"]
|
|
113450
|
+
},
|
|
113451
|
+
request: {
|
|
113452
|
+
method: "GET",
|
|
113453
|
+
path: "/tweets/{id}/liking_users",
|
|
113454
|
+
query: { max_results: "{max_results}", pagination_token: "{pagination_token}" }
|
|
113455
|
+
}
|
|
113456
|
+
},
|
|
113457
|
+
{
|
|
113458
|
+
name: "users.mentions",
|
|
113459
|
+
class: "read",
|
|
113460
|
+
description: "List tweets that mention a user, for verifying mentioned. Author filtering is applied by the caller. Cursor with pagination_token.",
|
|
113461
|
+
parameters: {
|
|
113462
|
+
type: "object",
|
|
113463
|
+
properties: {
|
|
113464
|
+
id: { type: "string", description: "Mentioned user id (from users.me)." },
|
|
113465
|
+
max_results: { type: "integer", description: "Page size (5\u2013100)." },
|
|
113466
|
+
pagination_token: { type: "string", description: "Cursor from a prior page (meta.next_token)." }
|
|
113467
|
+
},
|
|
113468
|
+
required: ["id"]
|
|
113469
|
+
},
|
|
113470
|
+
request: {
|
|
113471
|
+
method: "GET",
|
|
113472
|
+
path: "/users/{id}/mentions",
|
|
113473
|
+
query: { max_results: "{max_results}", "tweet.fields": "author_id,text", pagination_token: "{pagination_token}" }
|
|
113474
|
+
}
|
|
113302
113475
|
}
|
|
113303
113476
|
]
|
|
113304
113477
|
};
|
|
@@ -124598,6 +124771,11 @@ export {
|
|
|
124598
124771
|
exchangeAuthorizationCode,
|
|
124599
124772
|
refreshAccessToken,
|
|
124600
124773
|
_resetPendingFlowsForTests,
|
|
124774
|
+
googleErrorReason,
|
|
124775
|
+
classifyGoogleReason,
|
|
124776
|
+
classifyGoogleError,
|
|
124777
|
+
googleApiError,
|
|
124778
|
+
googleTestFailureReason,
|
|
124601
124779
|
googleCalendar,
|
|
124602
124780
|
googleDrive,
|
|
124603
124781
|
googleSheets,
|
|
@@ -125135,4 +125313,4 @@ export {
|
|
|
125135
125313
|
demandbaseConnector,
|
|
125136
125314
|
adapters_exports
|
|
125137
125315
|
};
|
|
125138
|
-
//# sourceMappingURL=chunk-
|
|
125316
|
+
//# sourceMappingURL=chunk-WTMOFI3U.js.map
|