@unityclaw/sdk 1.0.4 → 1.0.5

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.cjs CHANGED
@@ -103,30 +103,45 @@ var TaskFolderManager = class {
103
103
  /**
104
104
  * Download an attachment from URL to local folder
105
105
  * Important: Downloads attachments to avoid tmp_url expiration
106
+ * Includes retry logic for transient failures
106
107
  */
107
- async downloadAttachment(ctx, attachment) {
108
+ async downloadAttachment(ctx, attachment, maxRetries = 3, retryDelayMs = 1e3) {
108
109
  if (!this.options.downloadAttachments || !attachment.tmp_url) {
109
110
  return attachment.tmp_url;
110
111
  }
111
- try {
112
- const url = attachment.tmp_url;
113
- const urlPath = url.split("?")[0];
114
- const baseName = urlPath ? (0, import_path.basename)(urlPath) : "";
115
- const filename = attachment.name || baseName || `file_${Date.now()}`;
116
- const localPath = (0, import_path.join)(ctx.attachmentsPath, filename);
117
- const response = await import_axios.default.get(url, {
118
- responseType: "arraybuffer",
119
- timeout: 6e4
120
- });
121
- await (0, import_promises.writeFile)(localPath, Buffer.from(response.data));
122
- ctx.downloadedFiles.push(localPath);
123
- return localPath;
124
- } catch (error) {
125
- await this.log(ctx, "warn", `Failed to download attachment: ${attachment.name}`, {
126
- error: error instanceof Error ? error.message : error
127
- });
128
- return attachment.tmp_url;
112
+ const url = attachment.tmp_url;
113
+ const urlPath = url.split("?")[0];
114
+ const baseName = urlPath ? (0, import_path.basename)(urlPath) : "";
115
+ const filename = attachment.name || baseName || `file_${Date.now()}`;
116
+ const localPath = (0, import_path.join)(ctx.attachmentsPath, filename);
117
+ let lastError;
118
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
119
+ try {
120
+ const response = await import_axios.default.get(url, {
121
+ responseType: "arraybuffer",
122
+ timeout: 6e4
123
+ });
124
+ await (0, import_promises.writeFile)(localPath, Buffer.from(response.data));
125
+ ctx.downloadedFiles.push(localPath);
126
+ if (attempt > 1) {
127
+ await this.log(ctx, "info", `Download succeeded on attempt ${attempt}: ${filename}`);
128
+ }
129
+ return localPath;
130
+ } catch (error) {
131
+ lastError = error instanceof Error ? error : new Error(String(error));
132
+ if (attempt < maxRetries) {
133
+ await this.log(ctx, "warn", `Download attempt ${attempt}/${maxRetries} failed for ${filename}, retrying...`, {
134
+ error: lastError.message
135
+ });
136
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs * attempt));
137
+ }
138
+ }
129
139
  }
140
+ await this.log(ctx, "warn", `Failed to download attachment after ${maxRetries} attempts: ${filename}`, {
141
+ error: lastError?.message,
142
+ url: url.substring(0, 100) + "..."
143
+ });
144
+ return attachment.tmp_url;
130
145
  }
131
146
  /**
132
147
  * Download multiple attachments
package/dist/index.d.cts CHANGED
@@ -272,8 +272,9 @@ declare class TaskFolderManager {
272
272
  /**
273
273
  * Download an attachment from URL to local folder
274
274
  * Important: Downloads attachments to avoid tmp_url expiration
275
+ * Includes retry logic for transient failures
275
276
  */
276
- downloadAttachment(ctx: TaskFolderContext, attachment: AttachmentFieldItem): Promise<string | undefined>;
277
+ downloadAttachment(ctx: TaskFolderContext, attachment: AttachmentFieldItem, maxRetries?: number, retryDelayMs?: number): Promise<string | undefined>;
277
278
  /**
278
279
  * Download multiple attachments
279
280
  */
package/dist/index.d.ts CHANGED
@@ -272,8 +272,9 @@ declare class TaskFolderManager {
272
272
  /**
273
273
  * Download an attachment from URL to local folder
274
274
  * Important: Downloads attachments to avoid tmp_url expiration
275
+ * Includes retry logic for transient failures
275
276
  */
276
- downloadAttachment(ctx: TaskFolderContext, attachment: AttachmentFieldItem): Promise<string | undefined>;
277
+ downloadAttachment(ctx: TaskFolderContext, attachment: AttachmentFieldItem, maxRetries?: number, retryDelayMs?: number): Promise<string | undefined>;
277
278
  /**
278
279
  * Download multiple attachments
279
280
  */
package/dist/index.js CHANGED
@@ -65,30 +65,45 @@ var TaskFolderManager = class {
65
65
  /**
66
66
  * Download an attachment from URL to local folder
67
67
  * Important: Downloads attachments to avoid tmp_url expiration
68
+ * Includes retry logic for transient failures
68
69
  */
69
- async downloadAttachment(ctx, attachment) {
70
+ async downloadAttachment(ctx, attachment, maxRetries = 3, retryDelayMs = 1e3) {
70
71
  if (!this.options.downloadAttachments || !attachment.tmp_url) {
71
72
  return attachment.tmp_url;
72
73
  }
73
- try {
74
- const url = attachment.tmp_url;
75
- const urlPath = url.split("?")[0];
76
- const baseName = urlPath ? basename(urlPath) : "";
77
- const filename = attachment.name || baseName || `file_${Date.now()}`;
78
- const localPath = join(ctx.attachmentsPath, filename);
79
- const response = await axios.get(url, {
80
- responseType: "arraybuffer",
81
- timeout: 6e4
82
- });
83
- await writeFile(localPath, Buffer.from(response.data));
84
- ctx.downloadedFiles.push(localPath);
85
- return localPath;
86
- } catch (error) {
87
- await this.log(ctx, "warn", `Failed to download attachment: ${attachment.name}`, {
88
- error: error instanceof Error ? error.message : error
89
- });
90
- return attachment.tmp_url;
74
+ const url = attachment.tmp_url;
75
+ const urlPath = url.split("?")[0];
76
+ const baseName = urlPath ? basename(urlPath) : "";
77
+ const filename = attachment.name || baseName || `file_${Date.now()}`;
78
+ const localPath = join(ctx.attachmentsPath, filename);
79
+ let lastError;
80
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
81
+ try {
82
+ const response = await axios.get(url, {
83
+ responseType: "arraybuffer",
84
+ timeout: 6e4
85
+ });
86
+ await writeFile(localPath, Buffer.from(response.data));
87
+ ctx.downloadedFiles.push(localPath);
88
+ if (attempt > 1) {
89
+ await this.log(ctx, "info", `Download succeeded on attempt ${attempt}: ${filename}`);
90
+ }
91
+ return localPath;
92
+ } catch (error) {
93
+ lastError = error instanceof Error ? error : new Error(String(error));
94
+ if (attempt < maxRetries) {
95
+ await this.log(ctx, "warn", `Download attempt ${attempt}/${maxRetries} failed for ${filename}, retrying...`, {
96
+ error: lastError.message
97
+ });
98
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs * attempt));
99
+ }
100
+ }
91
101
  }
102
+ await this.log(ctx, "warn", `Failed to download attachment after ${maxRetries} attempts: ${filename}`, {
103
+ error: lastError?.message,
104
+ url: url.substring(0, 100) + "..."
105
+ });
106
+ return attachment.tmp_url;
92
107
  }
93
108
  /**
94
109
  * Download multiple attachments
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unityclaw/sdk",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Node.js SDK for UnityClaw API - AI-powered image/video generation, media analysis, and more",
5
5
  "type": "module",
6
6
  "bin": {