nworks 0.5.0 → 0.6.2
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/README.md +33 -6
- package/dist/index.js +383 -67
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +298 -61
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -736,6 +736,9 @@ var directoryCommand = new Command5("directory").description("Directory (organiz
|
|
|
736
736
|
// src/commands/calendar.ts
|
|
737
737
|
import { Command as Command6 } from "commander";
|
|
738
738
|
|
|
739
|
+
// src/api/calendar.ts
|
|
740
|
+
import { randomUUID } from "crypto";
|
|
741
|
+
|
|
739
742
|
// src/auth/token-user.ts
|
|
740
743
|
async function getValidUserToken(profile = "default") {
|
|
741
744
|
const cached2 = await loadUserToken(profile);
|
|
@@ -754,37 +757,164 @@ async function getValidUserToken(profile = "default") {
|
|
|
754
757
|
|
|
755
758
|
// src/api/calendar.ts
|
|
756
759
|
var BASE_URL2 = "https://www.worksapis.com/v1.0";
|
|
757
|
-
async function
|
|
760
|
+
async function authedFetch(url2, init, profile) {
|
|
758
761
|
const token = await getValidUserToken(profile);
|
|
762
|
+
const headers = new Headers(init.headers);
|
|
763
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
764
|
+
return fetch(url2, { ...init, headers });
|
|
765
|
+
}
|
|
766
|
+
async function handleError(res) {
|
|
767
|
+
if (res.status === 401) {
|
|
768
|
+
throw new AuthError("User token expired. Run `nworks login --user --scope calendar` again.");
|
|
769
|
+
}
|
|
770
|
+
let code = "UNKNOWN";
|
|
771
|
+
let description = `HTTP ${res.status}`;
|
|
772
|
+
try {
|
|
773
|
+
const body = await res.json();
|
|
774
|
+
code = body.code ?? code;
|
|
775
|
+
description = body.description ?? description;
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
throw new ApiError(code, description, res.status);
|
|
779
|
+
}
|
|
780
|
+
function generateEventId() {
|
|
781
|
+
return `event-${randomUUID()}`;
|
|
782
|
+
}
|
|
783
|
+
function normalizeDateTime(dt) {
|
|
784
|
+
const match = dt.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2})([+-]\d{2}:\d{2}|Z)?$/);
|
|
785
|
+
if (match) {
|
|
786
|
+
return `${match[1]}:00${match[2] ?? ""}`;
|
|
787
|
+
}
|
|
788
|
+
return dt;
|
|
789
|
+
}
|
|
790
|
+
async function listEvents(fromDateTime, untilDateTime, userId = "me", profile = "default") {
|
|
759
791
|
const from = encodeURIComponent(fromDateTime);
|
|
760
792
|
const until = encodeURIComponent(untilDateTime);
|
|
761
793
|
const url2 = `${BASE_URL2}/users/${userId}/calendar/events?fromDateTime=${from}&untilDateTime=${until}`;
|
|
762
794
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
763
795
|
console.error(`[nworks] GET ${url2}`);
|
|
764
796
|
}
|
|
765
|
-
const res = await
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
797
|
+
const res = await authedFetch(url2, { method: "GET" }, profile);
|
|
798
|
+
if (!res.ok) return handleError(res);
|
|
799
|
+
const data = await res.json();
|
|
800
|
+
return { events: data.events ?? [] };
|
|
801
|
+
}
|
|
802
|
+
async function createEvent(opts) {
|
|
803
|
+
const userId = opts.userId ?? "me";
|
|
804
|
+
const profile = opts.profile ?? "default";
|
|
805
|
+
const timeZone = opts.timeZone ?? "Asia/Seoul";
|
|
806
|
+
const eventId = generateEventId();
|
|
807
|
+
const eventComponent = {
|
|
808
|
+
eventId,
|
|
809
|
+
summary: opts.summary,
|
|
810
|
+
start: { dateTime: normalizeDateTime(opts.start), timeZone },
|
|
811
|
+
end: { dateTime: normalizeDateTime(opts.end), timeZone }
|
|
812
|
+
};
|
|
813
|
+
if (opts.description) eventComponent.description = opts.description;
|
|
814
|
+
if (opts.location) eventComponent.location = opts.location;
|
|
815
|
+
if (opts.transparency) eventComponent.transparency = opts.transparency;
|
|
816
|
+
if (opts.visibility) eventComponent.visibility = opts.visibility;
|
|
817
|
+
if (opts.attendees) {
|
|
818
|
+
eventComponent.attendees = opts.attendees.map((a) => ({
|
|
819
|
+
email: a.email,
|
|
820
|
+
displayName: a.displayName ?? "",
|
|
821
|
+
partstat: "NEEDS-ACTION",
|
|
822
|
+
isOptional: false,
|
|
823
|
+
isResource: false
|
|
824
|
+
}));
|
|
774
825
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
}
|
|
784
|
-
throw new ApiError(code, description, res.status);
|
|
826
|
+
const body = {
|
|
827
|
+
eventComponents: [eventComponent],
|
|
828
|
+
sendNotification: opts.sendNotification ?? false
|
|
829
|
+
};
|
|
830
|
+
const url2 = `${BASE_URL2}/users/${userId}/calendar/events`;
|
|
831
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
832
|
+
console.error(`[nworks] POST ${url2}`);
|
|
833
|
+
console.error(`[nworks] Body: ${JSON.stringify(body, null, 2)}`);
|
|
785
834
|
}
|
|
835
|
+
const res = await authedFetch(
|
|
836
|
+
url2,
|
|
837
|
+
{
|
|
838
|
+
method: "POST",
|
|
839
|
+
headers: { "Content-Type": "application/json" },
|
|
840
|
+
body: JSON.stringify(body)
|
|
841
|
+
},
|
|
842
|
+
profile
|
|
843
|
+
);
|
|
844
|
+
if (res.status === 201) {
|
|
845
|
+
return await res.json();
|
|
846
|
+
}
|
|
847
|
+
if (!res.ok) return handleError(res);
|
|
848
|
+
return await res.json();
|
|
849
|
+
}
|
|
850
|
+
async function getEvent(eventId, userId = "me", profile = "default") {
|
|
851
|
+
const url2 = `${BASE_URL2}/users/${userId}/calendar/events/${eventId}`;
|
|
852
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
853
|
+
console.error(`[nworks] GET ${url2}`);
|
|
854
|
+
}
|
|
855
|
+
const res = await authedFetch(url2, { method: "GET" }, profile);
|
|
856
|
+
if (!res.ok) return handleError(res);
|
|
786
857
|
const data = await res.json();
|
|
787
|
-
return
|
|
858
|
+
return data.eventComponents[0];
|
|
859
|
+
}
|
|
860
|
+
async function updateEvent(opts) {
|
|
861
|
+
const userId = opts.userId ?? "me";
|
|
862
|
+
const profile = opts.profile ?? "default";
|
|
863
|
+
const timeZone = opts.timeZone ?? "Asia/Seoul";
|
|
864
|
+
const existing = await getEvent(opts.eventId, userId, profile);
|
|
865
|
+
const eventComponent = {
|
|
866
|
+
eventId: opts.eventId,
|
|
867
|
+
summary: opts.summary ?? existing.summary,
|
|
868
|
+
start: opts.start ? { dateTime: normalizeDateTime(opts.start), timeZone } : existing.start,
|
|
869
|
+
end: opts.end ? { dateTime: normalizeDateTime(opts.end), timeZone } : existing.end
|
|
870
|
+
};
|
|
871
|
+
if (opts.description !== void 0) eventComponent.description = opts.description;
|
|
872
|
+
else if (existing.description) eventComponent.description = existing.description;
|
|
873
|
+
if (opts.location !== void 0) eventComponent.location = opts.location;
|
|
874
|
+
else if (existing.location) eventComponent.location = existing.location;
|
|
875
|
+
if (opts.transparency !== void 0) eventComponent.transparency = opts.transparency;
|
|
876
|
+
if (opts.visibility !== void 0) eventComponent.visibility = opts.visibility;
|
|
877
|
+
if (opts.attendees !== void 0) {
|
|
878
|
+
eventComponent.attendees = opts.attendees.map((a) => ({
|
|
879
|
+
email: a.email,
|
|
880
|
+
displayName: a.displayName ?? "",
|
|
881
|
+
partstat: "NEEDS-ACTION",
|
|
882
|
+
isOptional: false,
|
|
883
|
+
isResource: false
|
|
884
|
+
}));
|
|
885
|
+
} else if (existing.attendees) {
|
|
886
|
+
eventComponent.attendees = existing.attendees;
|
|
887
|
+
}
|
|
888
|
+
const body = {
|
|
889
|
+
eventComponents: [eventComponent],
|
|
890
|
+
sendNotification: opts.sendNotification ?? false
|
|
891
|
+
};
|
|
892
|
+
const url2 = `${BASE_URL2}/users/${userId}/calendar/events/${opts.eventId}`;
|
|
893
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
894
|
+
console.error(`[nworks] PUT ${url2}`);
|
|
895
|
+
console.error(`[nworks] Body: ${JSON.stringify(body, null, 2)}`);
|
|
896
|
+
}
|
|
897
|
+
const res = await authedFetch(
|
|
898
|
+
url2,
|
|
899
|
+
{
|
|
900
|
+
method: "PUT",
|
|
901
|
+
headers: { "Content-Type": "application/json" },
|
|
902
|
+
body: JSON.stringify(body)
|
|
903
|
+
},
|
|
904
|
+
profile
|
|
905
|
+
);
|
|
906
|
+
if (!res.ok) return handleError(res);
|
|
907
|
+
}
|
|
908
|
+
async function deleteEvent(eventId, userId = "me", sendNotification = false, profile = "default") {
|
|
909
|
+
const params = new URLSearchParams();
|
|
910
|
+
params.set("sendNotification", String(sendNotification));
|
|
911
|
+
const url2 = `${BASE_URL2}/users/${userId}/calendar/events/${eventId}?${params.toString()}`;
|
|
912
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
913
|
+
console.error(`[nworks] DELETE ${url2}`);
|
|
914
|
+
}
|
|
915
|
+
const res = await authedFetch(url2, { method: "DELETE" }, profile);
|
|
916
|
+
if (res.status === 204) return;
|
|
917
|
+
if (!res.ok) return handleError(res);
|
|
788
918
|
}
|
|
789
919
|
|
|
790
920
|
// src/commands/calendar.ts
|
|
@@ -798,7 +928,7 @@ function todayRange() {
|
|
|
798
928
|
until: `${yyyy}-${mm}-${dd}T23:59:59+09:00`
|
|
799
929
|
};
|
|
800
930
|
}
|
|
801
|
-
var listCommand = new Command6("list").description("List calendar events (requires User OAuth with calendar.read scope)").option("--user <userId>", "Target user ID (default: me)").option("--from <dateTime>", "Start (YYYY-MM-DDThh:mm:ss+09:00, default: today 00:00)").option("--until <dateTime>", "End (YYYY-MM-DDThh:mm:ss+09:00, default: today 23:59)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
931
|
+
var listCommand = new Command6("list").description("List calendar events (requires User OAuth with calendar.read or calendar scope)").option("--user <userId>", "Target user ID (default: me)").option("--from <dateTime>", "Start (YYYY-MM-DDThh:mm:ss+09:00, default: today 00:00)").option("--until <dateTime>", "End (YYYY-MM-DDThh:mm:ss+09:00, default: today 23:59)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
802
932
|
try {
|
|
803
933
|
const defaults = todayRange();
|
|
804
934
|
const from = opts.from ?? defaults.from;
|
|
@@ -812,6 +942,7 @@ var listCommand = new Command6("list").description("List calendar events (requir
|
|
|
812
942
|
);
|
|
813
943
|
const events = result.events.flatMap(
|
|
814
944
|
(e) => e.eventComponents.map((c) => ({
|
|
945
|
+
eventId: c.eventId,
|
|
815
946
|
summary: c.summary,
|
|
816
947
|
start: c.start.dateTime ? `${c.start.dateTime} (${c.start.timeZone ?? ""})` : c.start.date ?? "",
|
|
817
948
|
end: c.end.dateTime ? `${c.end.dateTime} (${c.end.timeZone ?? ""})` : c.end.date ?? "",
|
|
@@ -825,7 +956,85 @@ var listCommand = new Command6("list").description("List calendar events (requir
|
|
|
825
956
|
process.exitCode = 1;
|
|
826
957
|
}
|
|
827
958
|
});
|
|
828
|
-
var
|
|
959
|
+
var createCommand = new Command6("create").description("Create a calendar event (requires User OAuth with calendar scope)").requiredOption("--title <title>", "Event title (summary)").requiredOption("--start <dateTime>", "Start (YYYY-MM-DDThh:mm:ss)").requiredOption("--end <dateTime>", "End (YYYY-MM-DDThh:mm:ss)").option("--tz <timeZone>", "Time zone (default: Asia/Seoul)", "Asia/Seoul").option("--description <text>", "Event description").option("--location <place>", "Event location").option("--attendees <emails>", "Attendee emails (comma-separated)").option("--notify", "Send notification to attendees").option("--user <userId>", "Target user ID (default: me)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
960
|
+
try {
|
|
961
|
+
const attendees = opts.attendees ? opts.attendees.split(",").map((e) => ({ email: e.trim() })) : void 0;
|
|
962
|
+
const result = await createEvent({
|
|
963
|
+
summary: opts.title,
|
|
964
|
+
start: opts.start,
|
|
965
|
+
end: opts.end,
|
|
966
|
+
timeZone: opts.tz,
|
|
967
|
+
description: opts.description,
|
|
968
|
+
location: opts.location,
|
|
969
|
+
attendees,
|
|
970
|
+
sendNotification: opts.notify ?? false,
|
|
971
|
+
userId: opts.user ?? "me",
|
|
972
|
+
profile: opts.profile
|
|
973
|
+
});
|
|
974
|
+
const event = result.eventComponents?.[0];
|
|
975
|
+
const fmt = (t) => t?.dateTime ? `${t.dateTime} (${t.timeZone ?? ""})` : "";
|
|
976
|
+
output(
|
|
977
|
+
{
|
|
978
|
+
success: true,
|
|
979
|
+
eventId: event?.eventId,
|
|
980
|
+
summary: event?.summary,
|
|
981
|
+
start: fmt(event?.start),
|
|
982
|
+
end: fmt(event?.end)
|
|
983
|
+
},
|
|
984
|
+
opts
|
|
985
|
+
);
|
|
986
|
+
} catch (err) {
|
|
987
|
+
const error48 = err;
|
|
988
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
989
|
+
process.exitCode = 1;
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
var updateCommand = new Command6("update").description("Update a calendar event (requires User OAuth with calendar scope)").requiredOption("--id <eventId>", "Event ID").option("--title <title>", "New title (summary)").option("--start <dateTime>", "New start (YYYY-MM-DDThh:mm:ss)").option("--end <dateTime>", "New end (YYYY-MM-DDThh:mm:ss)").option("--tz <timeZone>", "Time zone (default: Asia/Seoul)", "Asia/Seoul").option("--description <text>", "New description").option("--location <place>", "New location").option("--attendees <emails>", "Attendee emails (comma-separated)").option("--notify", "Send notification to attendees").option("--user <userId>", "Target user ID (default: me)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
993
|
+
try {
|
|
994
|
+
const hasUpdate = opts.title || opts.start || opts.end || opts.description || opts.location || opts.attendees;
|
|
995
|
+
if (!hasUpdate) {
|
|
996
|
+
throw new Error("Specify at least one of: --title, --start, --end, --description, --location, --attendees");
|
|
997
|
+
}
|
|
998
|
+
const attendees = opts.attendees ? opts.attendees.split(",").map((e) => ({ email: e.trim() })) : void 0;
|
|
999
|
+
await updateEvent({
|
|
1000
|
+
eventId: opts.id,
|
|
1001
|
+
summary: opts.title,
|
|
1002
|
+
start: opts.start,
|
|
1003
|
+
end: opts.end,
|
|
1004
|
+
timeZone: opts.tz,
|
|
1005
|
+
description: opts.description,
|
|
1006
|
+
location: opts.location,
|
|
1007
|
+
attendees,
|
|
1008
|
+
sendNotification: opts.notify ?? false,
|
|
1009
|
+
userId: opts.user ?? "me",
|
|
1010
|
+
profile: opts.profile
|
|
1011
|
+
});
|
|
1012
|
+
output(
|
|
1013
|
+
{ success: true, eventId: opts.id, message: "Event updated" },
|
|
1014
|
+
opts
|
|
1015
|
+
);
|
|
1016
|
+
} catch (err) {
|
|
1017
|
+
const error48 = err;
|
|
1018
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
1019
|
+
process.exitCode = 1;
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
var deleteCommand = new Command6("delete").description("Delete a calendar event (requires User OAuth with calendar scope)").requiredOption("--id <eventId>", "Event ID").option("--notify", "Send notification to attendees").option("--user <userId>", "Target user ID (default: me)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
1023
|
+
try {
|
|
1024
|
+
await deleteEvent(
|
|
1025
|
+
opts.id,
|
|
1026
|
+
opts.user ?? "me",
|
|
1027
|
+
opts.notify ?? false,
|
|
1028
|
+
opts.profile
|
|
1029
|
+
);
|
|
1030
|
+
output({ success: true, eventId: opts.id, message: "Event deleted" }, opts);
|
|
1031
|
+
} catch (err) {
|
|
1032
|
+
const error48 = err;
|
|
1033
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
1034
|
+
process.exitCode = 1;
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
var calendarCommand = new Command6("calendar").description("Calendar operations (requires User OAuth)").addCommand(listCommand).addCommand(createCommand).addCommand(updateCommand).addCommand(deleteCommand);
|
|
829
1038
|
|
|
830
1039
|
// src/commands/drive.ts
|
|
831
1040
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
@@ -836,13 +1045,13 @@ import { Command as Command7 } from "commander";
|
|
|
836
1045
|
import { readFile as readFile4, stat } from "fs/promises";
|
|
837
1046
|
import { basename } from "path";
|
|
838
1047
|
var BASE_URL3 = "https://www.worksapis.com/v1.0";
|
|
839
|
-
async function
|
|
1048
|
+
async function authedFetch2(url2, init, profile) {
|
|
840
1049
|
const token = await getValidUserToken(profile);
|
|
841
1050
|
const headers = new Headers(init.headers);
|
|
842
1051
|
headers.set("Authorization", `Bearer ${token}`);
|
|
843
1052
|
return fetch(url2, { ...init, headers });
|
|
844
1053
|
}
|
|
845
|
-
async function
|
|
1054
|
+
async function handleError2(res) {
|
|
846
1055
|
if (res.status === 401) {
|
|
847
1056
|
throw new AuthError("User token expired. Run `nworks login --user --scope file` again.");
|
|
848
1057
|
}
|
|
@@ -866,8 +1075,8 @@ async function listFiles(userId = "me", folderId, count = 20, cursor, profile =
|
|
|
866
1075
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
867
1076
|
console.error(`[nworks] GET ${url2}`);
|
|
868
1077
|
}
|
|
869
|
-
const res = await
|
|
870
|
-
if (!res.ok) return
|
|
1078
|
+
const res = await authedFetch2(url2, { method: "GET" }, profile);
|
|
1079
|
+
if (!res.ok) return handleError2(res);
|
|
871
1080
|
const data = await res.json();
|
|
872
1081
|
return { files: data.files ?? [], responseMetaData: data.responseMetaData };
|
|
873
1082
|
}
|
|
@@ -880,7 +1089,7 @@ async function uploadFile(localPath, userId = "me", folderId, overwrite = false,
|
|
|
880
1089
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
881
1090
|
console.error(`[nworks] POST ${createUrl} (create upload URL)`);
|
|
882
1091
|
}
|
|
883
|
-
const createRes = await
|
|
1092
|
+
const createRes = await authedFetch2(
|
|
884
1093
|
createUrl,
|
|
885
1094
|
{
|
|
886
1095
|
method: "POST",
|
|
@@ -889,7 +1098,7 @@ async function uploadFile(localPath, userId = "me", folderId, overwrite = false,
|
|
|
889
1098
|
},
|
|
890
1099
|
profile
|
|
891
1100
|
);
|
|
892
|
-
if (!createRes.ok) return
|
|
1101
|
+
if (!createRes.ok) return handleError2(createRes);
|
|
893
1102
|
const { uploadUrl } = await createRes.json();
|
|
894
1103
|
const fileBuffer = await readFile4(localPath);
|
|
895
1104
|
const boundary = `----nworks${Date.now()}`;
|
|
@@ -907,7 +1116,7 @@ Content-Type: application/octet-stream\r
|
|
|
907
1116
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
908
1117
|
console.error(`[nworks] POST ${uploadUrl} (upload content, ${fileSize} bytes)`);
|
|
909
1118
|
}
|
|
910
|
-
const uploadRes = await
|
|
1119
|
+
const uploadRes = await authedFetch2(
|
|
911
1120
|
uploadUrl,
|
|
912
1121
|
{
|
|
913
1122
|
method: "POST",
|
|
@@ -916,7 +1125,7 @@ Content-Type: application/octet-stream\r
|
|
|
916
1125
|
},
|
|
917
1126
|
profile
|
|
918
1127
|
);
|
|
919
|
-
if (!uploadRes.ok) return
|
|
1128
|
+
if (!uploadRes.ok) return handleError2(uploadRes);
|
|
920
1129
|
return await uploadRes.json();
|
|
921
1130
|
}
|
|
922
1131
|
async function uploadBuffer(fileBuffer, fileName, userId = "me", folderId, overwrite = false, profile = "default") {
|
|
@@ -926,7 +1135,7 @@ async function uploadBuffer(fileBuffer, fileName, userId = "me", folderId, overw
|
|
|
926
1135
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
927
1136
|
console.error(`[nworks] POST ${createUrl} (create upload URL for buffer)`);
|
|
928
1137
|
}
|
|
929
|
-
const createRes = await
|
|
1138
|
+
const createRes = await authedFetch2(
|
|
930
1139
|
createUrl,
|
|
931
1140
|
{
|
|
932
1141
|
method: "POST",
|
|
@@ -935,7 +1144,7 @@ async function uploadBuffer(fileBuffer, fileName, userId = "me", folderId, overw
|
|
|
935
1144
|
},
|
|
936
1145
|
profile
|
|
937
1146
|
);
|
|
938
|
-
if (!createRes.ok) return
|
|
1147
|
+
if (!createRes.ok) return handleError2(createRes);
|
|
939
1148
|
const { uploadUrl } = await createRes.json();
|
|
940
1149
|
const boundary = `----nworks${Date.now()}`;
|
|
941
1150
|
const header = Buffer.from(
|
|
@@ -952,7 +1161,7 @@ Content-Type: application/octet-stream\r
|
|
|
952
1161
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
953
1162
|
console.error(`[nworks] POST ${uploadUrl} (upload buffer, ${fileSize} bytes)`);
|
|
954
1163
|
}
|
|
955
|
-
const uploadRes = await
|
|
1164
|
+
const uploadRes = await authedFetch2(
|
|
956
1165
|
uploadUrl,
|
|
957
1166
|
{
|
|
958
1167
|
method: "POST",
|
|
@@ -961,7 +1170,7 @@ Content-Type: application/octet-stream\r
|
|
|
961
1170
|
},
|
|
962
1171
|
profile
|
|
963
1172
|
);
|
|
964
|
-
if (!uploadRes.ok) return
|
|
1173
|
+
if (!uploadRes.ok) return handleError2(uploadRes);
|
|
965
1174
|
return await uploadRes.json();
|
|
966
1175
|
}
|
|
967
1176
|
async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
@@ -969,7 +1178,7 @@ async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
|
969
1178
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
970
1179
|
console.error(`[nworks] GET ${url2} (get download URL)`);
|
|
971
1180
|
}
|
|
972
|
-
const redirectRes = await
|
|
1181
|
+
const redirectRes = await authedFetch2(
|
|
973
1182
|
url2,
|
|
974
1183
|
{ method: "GET", redirect: "manual" },
|
|
975
1184
|
profile
|
|
@@ -979,14 +1188,14 @@ async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
|
979
1188
|
}
|
|
980
1189
|
const location = redirectRes.headers.get("location");
|
|
981
1190
|
if (!location) {
|
|
982
|
-
if (!redirectRes.ok) return
|
|
1191
|
+
if (!redirectRes.ok) return handleError2(redirectRes);
|
|
983
1192
|
throw new ApiError("NO_REDIRECT", "No download URL returned", redirectRes.status);
|
|
984
1193
|
}
|
|
985
1194
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
986
1195
|
console.error(`[nworks] GET ${location} (download content)`);
|
|
987
1196
|
}
|
|
988
|
-
const downloadRes = await
|
|
989
|
-
if (!downloadRes.ok) return
|
|
1197
|
+
const downloadRes = await authedFetch2(location, { method: "GET" }, profile);
|
|
1198
|
+
if (!downloadRes.ok) return handleError2(downloadRes);
|
|
990
1199
|
const arrayBuffer = await downloadRes.arrayBuffer();
|
|
991
1200
|
const buffer = Buffer.from(arrayBuffer);
|
|
992
1201
|
const disposition = downloadRes.headers.get("content-disposition");
|
|
@@ -1105,13 +1314,13 @@ import { Command as Command8 } from "commander";
|
|
|
1105
1314
|
|
|
1106
1315
|
// src/api/mail.ts
|
|
1107
1316
|
var BASE_URL4 = "https://www.worksapis.com/v1.0";
|
|
1108
|
-
async function
|
|
1317
|
+
async function authedFetch3(url2, init, profile) {
|
|
1109
1318
|
const token = await getValidUserToken(profile);
|
|
1110
1319
|
const headers = new Headers(init.headers);
|
|
1111
1320
|
headers.set("Authorization", `Bearer ${token}`);
|
|
1112
1321
|
return fetch(url2, { ...init, headers });
|
|
1113
1322
|
}
|
|
1114
|
-
async function
|
|
1323
|
+
async function handleError3(res) {
|
|
1115
1324
|
if (res.status === 401) {
|
|
1116
1325
|
throw new AuthError("User token expired. Run `nworks login --user --scope mail` again.");
|
|
1117
1326
|
}
|
|
@@ -1140,7 +1349,7 @@ async function sendMail(opts) {
|
|
|
1140
1349
|
if (opts.cc) body.cc = opts.cc;
|
|
1141
1350
|
if (opts.bcc) body.bcc = opts.bcc;
|
|
1142
1351
|
if (opts.contentType) body.contentType = opts.contentType;
|
|
1143
|
-
const res = await
|
|
1352
|
+
const res = await authedFetch3(
|
|
1144
1353
|
url2,
|
|
1145
1354
|
{
|
|
1146
1355
|
method: "POST",
|
|
@@ -1150,7 +1359,7 @@ async function sendMail(opts) {
|
|
|
1150
1359
|
profile
|
|
1151
1360
|
);
|
|
1152
1361
|
if (res.status === 202) return;
|
|
1153
|
-
if (!res.ok) return
|
|
1362
|
+
if (!res.ok) return handleError3(res);
|
|
1154
1363
|
}
|
|
1155
1364
|
async function listMails(folderId = 0, userId = "me", count = 30, cursor, isUnread, profile = "default") {
|
|
1156
1365
|
const params = new URLSearchParams();
|
|
@@ -1161,8 +1370,8 @@ async function listMails(folderId = 0, userId = "me", count = 30, cursor, isUnre
|
|
|
1161
1370
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1162
1371
|
console.error(`[nworks] GET ${url2}`);
|
|
1163
1372
|
}
|
|
1164
|
-
const res = await
|
|
1165
|
-
if (!res.ok) return
|
|
1373
|
+
const res = await authedFetch3(url2, { method: "GET" }, profile);
|
|
1374
|
+
if (!res.ok) return handleError3(res);
|
|
1166
1375
|
const data = await res.json();
|
|
1167
1376
|
return {
|
|
1168
1377
|
mails: data.mails ?? [],
|
|
@@ -1177,8 +1386,8 @@ async function readMail(mailId, userId = "me", profile = "default") {
|
|
|
1177
1386
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1178
1387
|
console.error(`[nworks] GET ${url2}`);
|
|
1179
1388
|
}
|
|
1180
|
-
const res = await
|
|
1181
|
-
if (!res.ok) return
|
|
1389
|
+
const res = await authedFetch3(url2, { method: "GET" }, profile);
|
|
1390
|
+
if (!res.ok) return handleError3(res);
|
|
1182
1391
|
return await res.json();
|
|
1183
1392
|
}
|
|
1184
1393
|
|
|
@@ -1281,13 +1490,13 @@ import { Command as Command9 } from "commander";
|
|
|
1281
1490
|
|
|
1282
1491
|
// src/api/task.ts
|
|
1283
1492
|
var BASE_URL5 = "https://www.worksapis.com/v1.0";
|
|
1284
|
-
async function
|
|
1493
|
+
async function authedFetch4(url2, init, profile) {
|
|
1285
1494
|
const token = await getValidUserToken(profile);
|
|
1286
1495
|
const headers = new Headers(init.headers);
|
|
1287
1496
|
headers.set("Authorization", `Bearer ${token}`);
|
|
1288
1497
|
return fetch(url2, { ...init, headers });
|
|
1289
1498
|
}
|
|
1290
|
-
async function
|
|
1499
|
+
async function handleError4(res) {
|
|
1291
1500
|
if (res.status === 401) {
|
|
1292
1501
|
throw new AuthError("User token expired. Run `nworks login --user --scope task` again.");
|
|
1293
1502
|
}
|
|
@@ -1304,8 +1513,8 @@ async function handleError3(res) {
|
|
|
1304
1513
|
async function resolveUserId(userId, profile) {
|
|
1305
1514
|
if (userId !== "me") return userId;
|
|
1306
1515
|
const url2 = `${BASE_URL5}/users/me`;
|
|
1307
|
-
const res = await
|
|
1308
|
-
if (!res.ok) return
|
|
1516
|
+
const res = await authedFetch4(url2, { method: "GET" }, profile);
|
|
1517
|
+
if (!res.ok) return handleError4(res);
|
|
1309
1518
|
const data = await res.json();
|
|
1310
1519
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1311
1520
|
console.error(`[nworks] Resolved "me" \u2192 ${data.userId}`);
|
|
@@ -1322,8 +1531,8 @@ async function listTasks(categoryId = "default", userId = "me", count = 50, curs
|
|
|
1322
1531
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1323
1532
|
console.error(`[nworks] GET ${url2}`);
|
|
1324
1533
|
}
|
|
1325
|
-
const res = await
|
|
1326
|
-
if (!res.ok) return
|
|
1534
|
+
const res = await authedFetch4(url2, { method: "GET" }, profile);
|
|
1535
|
+
if (!res.ok) return handleError4(res);
|
|
1327
1536
|
const data = await res.json();
|
|
1328
1537
|
return { tasks: data.tasks ?? [], responseMetaData: data.responseMetaData };
|
|
1329
1538
|
}
|
|
@@ -1347,7 +1556,7 @@ async function createTask(opts) {
|
|
|
1347
1556
|
console.error(`[nworks] POST ${url2}`);
|
|
1348
1557
|
console.error(`[nworks] Body: ${JSON.stringify(body, null, 2)}`);
|
|
1349
1558
|
}
|
|
1350
|
-
const res = await
|
|
1559
|
+
const res = await authedFetch4(
|
|
1351
1560
|
url2,
|
|
1352
1561
|
{
|
|
1353
1562
|
method: "POST",
|
|
@@ -1359,7 +1568,7 @@ async function createTask(opts) {
|
|
|
1359
1568
|
if (res.status === 201) {
|
|
1360
1569
|
return await res.json();
|
|
1361
1570
|
}
|
|
1362
|
-
if (!res.ok) return
|
|
1571
|
+
if (!res.ok) return handleError4(res);
|
|
1363
1572
|
return await res.json();
|
|
1364
1573
|
}
|
|
1365
1574
|
async function updateTask(opts) {
|
|
@@ -1372,7 +1581,7 @@ async function updateTask(opts) {
|
|
|
1372
1581
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1373
1582
|
console.error(`[nworks] PATCH ${url2}`);
|
|
1374
1583
|
}
|
|
1375
|
-
const res = await
|
|
1584
|
+
const res = await authedFetch4(
|
|
1376
1585
|
url2,
|
|
1377
1586
|
{
|
|
1378
1587
|
method: "PATCH",
|
|
@@ -1381,7 +1590,7 @@ async function updateTask(opts) {
|
|
|
1381
1590
|
},
|
|
1382
1591
|
profile
|
|
1383
1592
|
);
|
|
1384
|
-
if (!res.ok) return
|
|
1593
|
+
if (!res.ok) return handleError4(res);
|
|
1385
1594
|
return await res.json();
|
|
1386
1595
|
}
|
|
1387
1596
|
async function completeTask(taskId, profile = "default") {
|
|
@@ -1389,39 +1598,39 @@ async function completeTask(taskId, profile = "default") {
|
|
|
1389
1598
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1390
1599
|
console.error(`[nworks] POST ${url2}`);
|
|
1391
1600
|
}
|
|
1392
|
-
const res = await
|
|
1601
|
+
const res = await authedFetch4(
|
|
1393
1602
|
url2,
|
|
1394
1603
|
{ method: "POST" },
|
|
1395
1604
|
profile
|
|
1396
1605
|
);
|
|
1397
1606
|
if (res.status === 204) return;
|
|
1398
|
-
if (!res.ok) return
|
|
1607
|
+
if (!res.ok) return handleError4(res);
|
|
1399
1608
|
}
|
|
1400
1609
|
async function incompleteTask(taskId, profile = "default") {
|
|
1401
1610
|
const url2 = `${BASE_URL5}/tasks/${taskId}/incomplete`;
|
|
1402
1611
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1403
1612
|
console.error(`[nworks] POST ${url2}`);
|
|
1404
1613
|
}
|
|
1405
|
-
const res = await
|
|
1614
|
+
const res = await authedFetch4(
|
|
1406
1615
|
url2,
|
|
1407
1616
|
{ method: "POST" },
|
|
1408
1617
|
profile
|
|
1409
1618
|
);
|
|
1410
1619
|
if (res.status === 204) return;
|
|
1411
|
-
if (!res.ok) return
|
|
1620
|
+
if (!res.ok) return handleError4(res);
|
|
1412
1621
|
}
|
|
1413
1622
|
async function deleteTask(taskId, profile = "default") {
|
|
1414
1623
|
const url2 = `${BASE_URL5}/tasks/${taskId}`;
|
|
1415
1624
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1416
1625
|
console.error(`[nworks] DELETE ${url2}`);
|
|
1417
1626
|
}
|
|
1418
|
-
const res = await
|
|
1627
|
+
const res = await authedFetch4(
|
|
1419
1628
|
url2,
|
|
1420
1629
|
{ method: "DELETE" },
|
|
1421
1630
|
profile
|
|
1422
1631
|
);
|
|
1423
1632
|
if (res.status === 204) return;
|
|
1424
|
-
if (!res.ok) return
|
|
1633
|
+
if (!res.ok) return handleError4(res);
|
|
1425
1634
|
}
|
|
1426
1635
|
|
|
1427
1636
|
// src/commands/task.ts
|
|
@@ -1457,7 +1666,7 @@ var listCommand4 = new Command9("list").description("List tasks (requires User O
|
|
|
1457
1666
|
process.exitCode = 1;
|
|
1458
1667
|
}
|
|
1459
1668
|
});
|
|
1460
|
-
var
|
|
1669
|
+
var createCommand2 = new Command9("create").description("Create a task (requires User OAuth with task scope)").requiredOption("--title <title>", "Task title").option("--body <content>", "Task content/description").option("--due <date>", "Due date (YYYY-MM-DD)").option("--category <categoryId>", "Category ID").option("--assignee <userIds>", "Assignee user IDs (comma-separated)").option("--user <userId>", "Creator user ID (default: me)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
1461
1670
|
try {
|
|
1462
1671
|
const assigneeIds = opts.assignee ? opts.assignee.split(",").map((s) => s.trim()) : void 0;
|
|
1463
1672
|
const result = await createTask({
|
|
@@ -1485,7 +1694,7 @@ var createCommand = new Command9("create").description("Create a task (requires
|
|
|
1485
1694
|
process.exitCode = 1;
|
|
1486
1695
|
}
|
|
1487
1696
|
});
|
|
1488
|
-
var
|
|
1697
|
+
var updateCommand2 = new Command9("update").description("Update a task (requires User OAuth with task scope)").requiredOption("--id <taskId>", "Task ID").option("--title <title>", "New title").option("--body <content>", "New content").option("--due <date>", "New due date (YYYY-MM-DD)").option("--status <status>", "Set status: done or todo").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
1489
1698
|
try {
|
|
1490
1699
|
const profile = opts.profile;
|
|
1491
1700
|
const taskId = opts.id;
|
|
@@ -1532,7 +1741,7 @@ var updateCommand = new Command9("update").description("Update a task (requires
|
|
|
1532
1741
|
process.exitCode = 1;
|
|
1533
1742
|
}
|
|
1534
1743
|
});
|
|
1535
|
-
var
|
|
1744
|
+
var deleteCommand2 = new Command9("delete").description("Delete a task (requires User OAuth with task scope)").requiredOption("--id <taskId>", "Task ID").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
1536
1745
|
try {
|
|
1537
1746
|
await deleteTask(
|
|
1538
1747
|
opts.id,
|
|
@@ -1545,7 +1754,7 @@ var deleteCommand = new Command9("delete").description("Delete a task (requires
|
|
|
1545
1754
|
process.exitCode = 1;
|
|
1546
1755
|
}
|
|
1547
1756
|
});
|
|
1548
|
-
var taskCommand = new Command9("task").description("Task operations (requires User OAuth with task scope)").addCommand(listCommand4).addCommand(
|
|
1757
|
+
var taskCommand = new Command9("task").description("Task operations (requires User OAuth with task scope)").addCommand(listCommand4).addCommand(createCommand2).addCommand(updateCommand2).addCommand(deleteCommand2);
|
|
1549
1758
|
|
|
1550
1759
|
// src/commands/mcp-cmd.ts
|
|
1551
1760
|
import { Command as Command10 } from "commander";
|
|
@@ -15414,6 +15623,7 @@ function registerTools(server) {
|
|
|
15414
15623
|
);
|
|
15415
15624
|
const events = result.events.flatMap(
|
|
15416
15625
|
(e) => e.eventComponents.map((c) => ({
|
|
15626
|
+
eventId: c.eventId,
|
|
15417
15627
|
summary: c.summary,
|
|
15418
15628
|
start: c.start.dateTime ?? c.start.date ?? "",
|
|
15419
15629
|
end: c.end.dateTime ?? c.end.date ?? "",
|
|
@@ -15432,6 +15642,112 @@ function registerTools(server) {
|
|
|
15432
15642
|
}
|
|
15433
15643
|
}
|
|
15434
15644
|
);
|
|
15645
|
+
server.tool(
|
|
15646
|
+
"nworks_calendar_create",
|
|
15647
|
+
"\uCE98\uB9B0\uB354 \uC77C\uC815\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4 (User OAuth calendar scope \uD544\uC694)",
|
|
15648
|
+
{
|
|
15649
|
+
summary: external_exports.string().describe("\uC77C\uC815 \uC81C\uBAA9"),
|
|
15650
|
+
start: external_exports.string().describe("\uC2DC\uC791 \uC77C\uC2DC (YYYY-MM-DDThh:mm:ss)"),
|
|
15651
|
+
end: external_exports.string().describe("\uC885\uB8CC \uC77C\uC2DC (YYYY-MM-DDThh:mm:ss)"),
|
|
15652
|
+
timeZone: external_exports.string().optional().describe("\uD0C0\uC784\uC874 (\uAE30\uBCF8: Asia/Seoul)"),
|
|
15653
|
+
description: external_exports.string().optional().describe("\uC77C\uC815 \uC124\uBA85"),
|
|
15654
|
+
location: external_exports.string().optional().describe("\uC7A5\uC18C"),
|
|
15655
|
+
attendees: external_exports.array(external_exports.object({ email: external_exports.string(), displayName: external_exports.string().optional() })).optional().describe("\uCC38\uC11D\uC790 \uBAA9\uB85D"),
|
|
15656
|
+
sendNotification: external_exports.boolean().optional().describe("\uCC38\uC11D\uC790\uC5D0\uAC8C \uC54C\uB9BC \uBC1C\uC1A1 (\uAE30\uBCF8: false)"),
|
|
15657
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
15658
|
+
},
|
|
15659
|
+
async ({ summary, start, end, timeZone, description, location, attendees, sendNotification, userId }) => {
|
|
15660
|
+
try {
|
|
15661
|
+
const result = await createEvent({
|
|
15662
|
+
summary,
|
|
15663
|
+
start,
|
|
15664
|
+
end,
|
|
15665
|
+
timeZone,
|
|
15666
|
+
description,
|
|
15667
|
+
location,
|
|
15668
|
+
attendees,
|
|
15669
|
+
sendNotification,
|
|
15670
|
+
userId: userId ?? "me"
|
|
15671
|
+
});
|
|
15672
|
+
const event = result.eventComponents?.[0];
|
|
15673
|
+
return {
|
|
15674
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, eventId: event?.eventId, summary: event?.summary, start: event?.start, end: event?.end }) }]
|
|
15675
|
+
};
|
|
15676
|
+
} catch (err) {
|
|
15677
|
+
const error48 = err;
|
|
15678
|
+
return {
|
|
15679
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
15680
|
+
isError: true
|
|
15681
|
+
};
|
|
15682
|
+
}
|
|
15683
|
+
}
|
|
15684
|
+
);
|
|
15685
|
+
server.tool(
|
|
15686
|
+
"nworks_calendar_update",
|
|
15687
|
+
"\uCE98\uB9B0\uB354 \uC77C\uC815\uC744 \uC218\uC815\uD569\uB2C8\uB2E4 (User OAuth calendar scope \uD544\uC694)",
|
|
15688
|
+
{
|
|
15689
|
+
eventId: external_exports.string().describe("\uC77C\uC815 ID"),
|
|
15690
|
+
summary: external_exports.string().optional().describe("\uC0C8 \uC81C\uBAA9"),
|
|
15691
|
+
start: external_exports.string().optional().describe("\uC0C8 \uC2DC\uC791 \uC77C\uC2DC (YYYY-MM-DDThh:mm:ss)"),
|
|
15692
|
+
end: external_exports.string().optional().describe("\uC0C8 \uC885\uB8CC \uC77C\uC2DC (YYYY-MM-DDThh:mm:ss)"),
|
|
15693
|
+
timeZone: external_exports.string().optional().describe("\uD0C0\uC784\uC874 (\uAE30\uBCF8: Asia/Seoul)"),
|
|
15694
|
+
description: external_exports.string().optional().describe("\uC0C8 \uC124\uBA85"),
|
|
15695
|
+
location: external_exports.string().optional().describe("\uC0C8 \uC7A5\uC18C"),
|
|
15696
|
+
sendNotification: external_exports.boolean().optional().describe("\uCC38\uC11D\uC790\uC5D0\uAC8C \uC54C\uB9BC \uBC1C\uC1A1 (\uAE30\uBCF8: false)"),
|
|
15697
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
15698
|
+
},
|
|
15699
|
+
async ({ eventId, summary, start, end, timeZone, description, location, sendNotification, userId }) => {
|
|
15700
|
+
try {
|
|
15701
|
+
await updateEvent({
|
|
15702
|
+
eventId,
|
|
15703
|
+
summary,
|
|
15704
|
+
start,
|
|
15705
|
+
end,
|
|
15706
|
+
timeZone,
|
|
15707
|
+
description,
|
|
15708
|
+
location,
|
|
15709
|
+
sendNotification,
|
|
15710
|
+
userId: userId ?? "me"
|
|
15711
|
+
});
|
|
15712
|
+
return {
|
|
15713
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, eventId, message: "Event updated" }) }]
|
|
15714
|
+
};
|
|
15715
|
+
} catch (err) {
|
|
15716
|
+
const error48 = err;
|
|
15717
|
+
return {
|
|
15718
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
15719
|
+
isError: true
|
|
15720
|
+
};
|
|
15721
|
+
}
|
|
15722
|
+
}
|
|
15723
|
+
);
|
|
15724
|
+
server.tool(
|
|
15725
|
+
"nworks_calendar_delete",
|
|
15726
|
+
"\uCE98\uB9B0\uB354 \uC77C\uC815\uC744 \uC0AD\uC81C\uD569\uB2C8\uB2E4 (User OAuth calendar scope \uD544\uC694)",
|
|
15727
|
+
{
|
|
15728
|
+
eventId: external_exports.string().describe("\uC0AD\uC81C\uD560 \uC77C\uC815 ID"),
|
|
15729
|
+
sendNotification: external_exports.boolean().optional().describe("\uCC38\uC11D\uC790\uC5D0\uAC8C \uC54C\uB9BC \uBC1C\uC1A1 (\uAE30\uBCF8: false)"),
|
|
15730
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
15731
|
+
},
|
|
15732
|
+
async ({ eventId, sendNotification, userId }) => {
|
|
15733
|
+
try {
|
|
15734
|
+
await deleteEvent(
|
|
15735
|
+
eventId,
|
|
15736
|
+
userId ?? "me",
|
|
15737
|
+
sendNotification ?? false
|
|
15738
|
+
);
|
|
15739
|
+
return {
|
|
15740
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, eventId, message: "Event deleted" }) }]
|
|
15741
|
+
};
|
|
15742
|
+
} catch (err) {
|
|
15743
|
+
const error48 = err;
|
|
15744
|
+
return {
|
|
15745
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
15746
|
+
isError: true
|
|
15747
|
+
};
|
|
15748
|
+
}
|
|
15749
|
+
}
|
|
15750
|
+
);
|
|
15435
15751
|
server.tool(
|
|
15436
15752
|
"nworks_drive_list",
|
|
15437
15753
|
"\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694)",
|