nworks 0.3.1 → 0.3.3

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/index.js CHANGED
@@ -919,6 +919,51 @@ Content-Type: application/octet-stream\r
919
919
  if (!uploadRes.ok) return handleError(uploadRes);
920
920
  return await uploadRes.json();
921
921
  }
922
+ async function uploadBuffer(fileBuffer, fileName, userId = "me", folderId, overwrite = false, profile = "default") {
923
+ const fileSize = fileBuffer.length;
924
+ const base = `${BASE_URL3}/users/${userId}/drive/files`;
925
+ const createUrl = folderId ? `${base}/${folderId}` : base;
926
+ if (process.env["NWORKS_VERBOSE"] === "1") {
927
+ console.error(`[nworks] POST ${createUrl} (create upload URL for buffer)`);
928
+ }
929
+ const createRes = await authedFetch(
930
+ createUrl,
931
+ {
932
+ method: "POST",
933
+ headers: { "Content-Type": "application/json" },
934
+ body: JSON.stringify({ fileName, fileSize, overwrite })
935
+ },
936
+ profile
937
+ );
938
+ if (!createRes.ok) return handleError(createRes);
939
+ const { uploadUrl } = await createRes.json();
940
+ const boundary = `----nworks${Date.now()}`;
941
+ const header = Buffer.from(
942
+ `--${boundary}\r
943
+ Content-Disposition: form-data; name="Filedata"; filename="${fileName}"\r
944
+ Content-Type: application/octet-stream\r
945
+ \r
946
+ `
947
+ );
948
+ const footer = Buffer.from(`\r
949
+ --${boundary}--\r
950
+ `);
951
+ const body = Buffer.concat([header, fileBuffer, footer]);
952
+ if (process.env["NWORKS_VERBOSE"] === "1") {
953
+ console.error(`[nworks] POST ${uploadUrl} (upload buffer, ${fileSize} bytes)`);
954
+ }
955
+ const uploadRes = await authedFetch(
956
+ uploadUrl,
957
+ {
958
+ method: "POST",
959
+ headers: { "Content-Type": `multipart/form-data; boundary=${boundary}` },
960
+ body
961
+ },
962
+ profile
963
+ );
964
+ if (!uploadRes.ok) return handleError(uploadRes);
965
+ return await uploadRes.json();
966
+ }
922
967
  async function downloadFile(fileId, userId = "me", profile = "default") {
923
968
  const url2 = `${BASE_URL3}/users/${userId}/drive/files/${fileId}/download`;
924
969
  if (process.env["NWORKS_VERBOSE"] === "1") {
@@ -14979,28 +15024,54 @@ function registerTools(server) {
14979
15024
  );
14980
15025
  server.tool(
14981
15026
  "nworks_drive_upload",
14982
- "\uB85C\uCEEC \uD30C\uC77C\uC744 \uB4DC\uB77C\uC774\uBE0C\uC5D0 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file scope \uD544\uC694)",
15027
+ "\uD30C\uC77C\uC744 \uB4DC\uB77C\uC774\uBE0C\uC5D0 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file scope \uD544\uC694). content(base64)\uC640 fileName\uC73C\uB85C \uC804\uB2EC\uD558\uAC70\uB098, filePath\uB85C \uB85C\uCEEC \uD30C\uC77C \uACBD\uB85C\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4. MCP \uD074\uB77C\uC774\uC5B8\uD2B8\uC5D0\uC11C\uB294 content+fileName \uBC29\uC2DD\uC744 \uAD8C\uC7A5\uD569\uB2C8\uB2E4.",
14983
15028
  {
14984
- filePath: external_exports.string().describe("\uC5C5\uB85C\uB4DC\uD560 \uB85C\uCEEC \uD30C\uC77C \uACBD\uB85C"),
15029
+ content: external_exports.string().optional().describe("\uC5C5\uB85C\uB4DC\uD560 \uD30C\uC77C \uB0B4\uC6A9 (base64 \uC778\uCF54\uB529). filePath \uB300\uC2E0 \uC0AC\uC6A9"),
15030
+ fileName: external_exports.string().optional().describe("\uD30C\uC77C\uBA85 (content \uC0AC\uC6A9 \uC2DC \uD544\uC218)"),
15031
+ filePath: external_exports.string().optional().describe("\uC5C5\uB85C\uB4DC\uD560 \uB85C\uCEEC \uD30C\uC77C \uACBD\uB85C (content \uB300\uC2E0 \uC0AC\uC6A9, \uB85C\uCEEC \uD658\uACBD\uC5D0\uC11C\uB9CC \uB3D9\uC791)"),
14985
15032
  userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)"),
14986
15033
  folderId: external_exports.string().optional().describe("\uC5C5\uB85C\uB4DC\uD560 \uD3F4\uB354 ID (\uBBF8\uC9C0\uC815 \uC2DC \uB8E8\uD2B8)"),
14987
15034
  overwrite: external_exports.boolean().optional().describe("\uB3D9\uC77C \uD30C\uC77C\uBA85 \uB36E\uC5B4\uC4F0\uAE30 (\uAE30\uBCF8: false)")
14988
15035
  },
14989
- async ({ filePath, userId, folderId, overwrite }) => {
15036
+ async ({ content, fileName, filePath, userId, folderId, overwrite }) => {
14990
15037
  try {
14991
- const result = await uploadFile(
14992
- filePath,
14993
- userId ?? "me",
14994
- folderId,
14995
- overwrite ?? false
14996
- );
15038
+ let result;
15039
+ if (content && fileName) {
15040
+ const buffer = Buffer.from(content, "base64");
15041
+ if (process.env["NWORKS_VERBOSE"] === "1") {
15042
+ console.error(`[nworks] MCP upload: fileName=${fileName}, bufferSize=${buffer.length}`);
15043
+ }
15044
+ result = await uploadBuffer(
15045
+ buffer,
15046
+ fileName,
15047
+ userId ?? "me",
15048
+ folderId,
15049
+ overwrite ?? false
15050
+ );
15051
+ } else if (filePath) {
15052
+ if (process.env["NWORKS_VERBOSE"] === "1") {
15053
+ console.error(`[nworks] MCP upload: filePath=${filePath}`);
15054
+ }
15055
+ result = await uploadFile(
15056
+ filePath,
15057
+ userId ?? "me",
15058
+ folderId,
15059
+ overwrite ?? false
15060
+ );
15061
+ } else {
15062
+ return {
15063
+ content: [{ type: "text", text: "Error: content+fileName \uB610\uB294 filePath \uC911 \uD558\uB098\uB97C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4. MCP \uD074\uB77C\uC774\uC5B8\uD2B8\uC5D0\uC11C\uB294 \uD30C\uC77C \uB0B4\uC6A9\uC744 base64\uB85C \uC778\uCF54\uB529\uD558\uC5EC content \uD30C\uB77C\uBBF8\uD130\uC5D0 \uC804\uB2EC\uD558\uACE0, fileName\uC5D0 \uD30C\uC77C\uBA85\uC744 \uC9C0\uC815\uD558\uC138\uC694." }],
15064
+ isError: true
15065
+ };
15066
+ }
14997
15067
  return {
14998
15068
  content: [{ type: "text", text: JSON.stringify({ success: true, ...result }) }]
14999
15069
  };
15000
15070
  } catch (err) {
15001
15071
  const error48 = err;
15072
+ const detail = process.env["NWORKS_VERBOSE"] === "1" ? ` | stack: ${error48.stack}` : "";
15002
15073
  return {
15003
- content: [{ type: "text", text: `Error: ${error48.message}` }],
15074
+ content: [{ type: "text", text: `Error: ${error48.message}${detail}` }],
15004
15075
  isError: true
15005
15076
  };
15006
15077
  }
@@ -15008,27 +15079,40 @@ function registerTools(server) {
15008
15079
  );
15009
15080
  server.tool(
15010
15081
  "nworks_drive_download",
15011
- "\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694)",
15082
+ "\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694). outputDir\uC744 \uC9C0\uC815\uD558\uBA74 \uB85C\uCEEC\uC5D0 \uD30C\uC77C\uB85C \uC800\uC7A5\uD558\uACE0, \uBBF8\uC9C0\uC815 \uC2DC \uD30C\uC77C \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uBC18\uD658\uD569\uB2C8\uB2E4 (\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC740 text, \uBC14\uC774\uB108\uB9AC\uB294 base64).",
15012
15083
  {
15013
15084
  fileId: external_exports.string().describe("\uB2E4\uC6B4\uB85C\uB4DC\uD560 \uD30C\uC77C ID"),
15014
- outputDir: external_exports.string().optional().describe("\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uBBF8\uC9C0\uC815 \uC2DC \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC)"),
15085
+ outputDir: external_exports.string().optional().describe("\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uC9C0\uC815 \uC2DC \uD30C\uC77C\uB85C \uC800\uC7A5, \uBBF8\uC9C0\uC815 \uC2DC \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uBC18\uD658)"),
15015
15086
  outputName: external_exports.string().optional().describe("\uC800\uC7A5 \uD30C\uC77C\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uC6D0\uBCF8 \uD30C\uC77C\uBA85)"),
15016
15087
  userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
15017
15088
  },
15018
15089
  async ({ fileId, outputDir, outputName, userId }) => {
15019
15090
  try {
15020
- const { writeFile: writeFile3 } = await import("fs/promises");
15021
- const { join: join3 } = await import("path");
15022
15091
  const result = await downloadFile(
15023
15092
  fileId,
15024
15093
  userId ?? "me"
15025
15094
  );
15026
15095
  const fileName = outputName ?? result.fileName ?? fileId;
15027
- const dir = outputDir ?? process.cwd();
15028
- const outPath = join3(dir, fileName);
15029
- await writeFile3(outPath, result.buffer);
15096
+ if (outputDir) {
15097
+ const { writeFile: writeFile3 } = await import("fs/promises");
15098
+ const { join: join3 } = await import("path");
15099
+ const outPath = join3(outputDir, fileName);
15100
+ await writeFile3(outPath, result.buffer);
15101
+ return {
15102
+ content: [{ type: "text", text: JSON.stringify({ success: true, fileName, path: outPath, size: result.buffer.length }) }]
15103
+ };
15104
+ }
15105
+ const textExtensions = /\.(txt|md|csv|json|xml|html|htm|css|js|ts|jsx|tsx|yaml|yml|toml|ini|cfg|conf|log|sh|bash|zsh|py|rb|java|go|rs|c|cpp|h|hpp|sql|graphql|env|gitignore|dockerignore|editorconfig)$/i;
15106
+ const isText = textExtensions.test(fileName);
15107
+ if (isText) {
15108
+ const text = result.buffer.toString("utf-8");
15109
+ return {
15110
+ content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "text", content: text }) }]
15111
+ };
15112
+ }
15113
+ const base643 = result.buffer.toString("base64");
15030
15114
  return {
15031
- content: [{ type: "text", text: JSON.stringify({ success: true, fileName, path: outPath, size: result.buffer.length }) }]
15115
+ content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "base64", content: base643 }) }]
15032
15116
  };
15033
15117
  } catch (err) {
15034
15118
  const error48 = err;