@unityclaw/sdk 1.0.3 → 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/{chunk-WG7OYNEX.js → chunk-SZITFMFH.js} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +50 -21
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +50 -21
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import os from "os";
|
|
|
4
4
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
5
5
|
var CONFIG_DIR = path.join(os.homedir(), ".unityclaw");
|
|
6
6
|
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
7
|
-
var DEFAULT_TASKS_DIR = path.join(
|
|
7
|
+
var DEFAULT_TASKS_DIR = path.join(os.homedir(), "Documents", "tasks");
|
|
8
8
|
function getConfigPath() {
|
|
9
9
|
return CONFIG_FILE;
|
|
10
10
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -29,7 +29,7 @@ var import_os = __toESM(require("os"), 1);
|
|
|
29
29
|
var import_fs = require("fs");
|
|
30
30
|
var CONFIG_DIR = import_path.default.join(import_os.default.homedir(), ".unityclaw");
|
|
31
31
|
var CONFIG_FILE = import_path.default.join(CONFIG_DIR, "config.json");
|
|
32
|
-
var DEFAULT_TASKS_DIR = import_path.default.join(
|
|
32
|
+
var DEFAULT_TASKS_DIR = import_path.default.join(import_os.default.homedir(), "Documents", "tasks");
|
|
33
33
|
function getConfigPath() {
|
|
34
34
|
return CONFIG_FILE;
|
|
35
35
|
}
|
package/dist/cli.js
CHANGED
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
|
@@ -239,7 +254,7 @@ var import_os = __toESM(require("os"), 1);
|
|
|
239
254
|
var import_fs2 = require("fs");
|
|
240
255
|
var CONFIG_DIR = import_path2.default.join(import_os.default.homedir(), ".unityclaw");
|
|
241
256
|
var CONFIG_FILE = import_path2.default.join(CONFIG_DIR, "config.json");
|
|
242
|
-
var DEFAULT_TASKS_DIR = import_path2.default.join(
|
|
257
|
+
var DEFAULT_TASKS_DIR = import_path2.default.join(import_os.default.homedir(), "Documents", "tasks");
|
|
243
258
|
function getConfigPath() {
|
|
244
259
|
return CONFIG_FILE;
|
|
245
260
|
}
|
|
@@ -775,6 +790,16 @@ var MediaAPI = class {
|
|
|
775
790
|
// src/client.ts
|
|
776
791
|
var DEFAULT_BASE_URL = "https://unityclaw.com";
|
|
777
792
|
var DEFAULT_TIMEOUT = 3e5;
|
|
793
|
+
var OLD_DOMAINS = ["fieldshortcut.cn", "fieldshortcut.com"];
|
|
794
|
+
var NEW_DOMAIN = "unityclaw.com";
|
|
795
|
+
function replaceOldDomains(text) {
|
|
796
|
+
if (!text || typeof text !== "string") return text;
|
|
797
|
+
let result = text;
|
|
798
|
+
for (const oldDomain of OLD_DOMAINS) {
|
|
799
|
+
result = result.replace(new RegExp(oldDomain.replace(/\./g, "\\."), "g"), NEW_DOMAIN);
|
|
800
|
+
}
|
|
801
|
+
return result;
|
|
802
|
+
}
|
|
778
803
|
var UnityClawClient = class {
|
|
779
804
|
config;
|
|
780
805
|
httpClient;
|
|
@@ -881,6 +906,9 @@ var UnityClawClient = class {
|
|
|
881
906
|
await this.taskFolderManager.writeRequest(taskCtx, endpoint, params, context);
|
|
882
907
|
await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params });
|
|
883
908
|
const response = await this.httpClient.post(endpoint, requestBody);
|
|
909
|
+
if (response.data.msg) {
|
|
910
|
+
response.data.msg = replaceOldDomains(response.data.msg);
|
|
911
|
+
}
|
|
884
912
|
await this.taskFolderManager.writeResponse(taskCtx, response.data);
|
|
885
913
|
await this.taskFolderManager.log(taskCtx, "info", "Response received", {
|
|
886
914
|
code: response.data.code,
|
|
@@ -908,7 +936,8 @@ var UnityClawClient = class {
|
|
|
908
936
|
response.data.code === 0
|
|
909
937
|
);
|
|
910
938
|
} catch (error) {
|
|
911
|
-
const
|
|
939
|
+
const rawErrorMessage = error instanceof import_axios2.AxiosError ? error.response?.data?.msg || error.message : error instanceof Error ? error.message : String(error);
|
|
940
|
+
const errorMessage = replaceOldDomains(rawErrorMessage);
|
|
912
941
|
await this.taskFolderManager.log(taskCtx, "error", `Request failed: ${errorMessage}`, {
|
|
913
942
|
error: error instanceof import_axios2.AxiosError ? { status: error.response?.status, data: error.response?.data } : error
|
|
914
943
|
});
|
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
|
*/
|
|
@@ -812,7 +813,7 @@ declare class UnityClawClient {
|
|
|
812
813
|
declare const CONFIG_DIR: string;
|
|
813
814
|
/** Config file path */
|
|
814
815
|
declare const CONFIG_FILE: string;
|
|
815
|
-
/** Default tasks directory */
|
|
816
|
+
/** Default tasks directory - in Documents so users can easily find results */
|
|
816
817
|
declare const DEFAULT_TASKS_DIR: string;
|
|
817
818
|
/** UnityClaw configuration */
|
|
818
819
|
interface UnityClawConfig {
|
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
|
*/
|
|
@@ -812,7 +813,7 @@ declare class UnityClawClient {
|
|
|
812
813
|
declare const CONFIG_DIR: string;
|
|
813
814
|
/** Config file path */
|
|
814
815
|
declare const CONFIG_FILE: string;
|
|
815
|
-
/** Default tasks directory */
|
|
816
|
+
/** Default tasks directory - in Documents so users can easily find results */
|
|
816
817
|
declare const DEFAULT_TASKS_DIR: string;
|
|
817
818
|
/** UnityClaw configuration */
|
|
818
819
|
interface UnityClawConfig {
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
loadConfig,
|
|
8
8
|
saveConfig,
|
|
9
9
|
setConfigValue
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SZITFMFH.js";
|
|
11
11
|
|
|
12
12
|
// src/client.ts
|
|
13
13
|
import axios2, { AxiosError } from "axios";
|
|
@@ -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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
@@ -676,6 +691,16 @@ var MediaAPI = class {
|
|
|
676
691
|
// src/client.ts
|
|
677
692
|
var DEFAULT_BASE_URL = "https://unityclaw.com";
|
|
678
693
|
var DEFAULT_TIMEOUT = 3e5;
|
|
694
|
+
var OLD_DOMAINS = ["fieldshortcut.cn", "fieldshortcut.com"];
|
|
695
|
+
var NEW_DOMAIN = "unityclaw.com";
|
|
696
|
+
function replaceOldDomains(text) {
|
|
697
|
+
if (!text || typeof text !== "string") return text;
|
|
698
|
+
let result = text;
|
|
699
|
+
for (const oldDomain of OLD_DOMAINS) {
|
|
700
|
+
result = result.replace(new RegExp(oldDomain.replace(/\./g, "\\."), "g"), NEW_DOMAIN);
|
|
701
|
+
}
|
|
702
|
+
return result;
|
|
703
|
+
}
|
|
679
704
|
var UnityClawClient = class {
|
|
680
705
|
config;
|
|
681
706
|
httpClient;
|
|
@@ -782,6 +807,9 @@ var UnityClawClient = class {
|
|
|
782
807
|
await this.taskFolderManager.writeRequest(taskCtx, endpoint, params, context);
|
|
783
808
|
await this.taskFolderManager.log(taskCtx, "info", "Request prepared", { endpoint, params });
|
|
784
809
|
const response = await this.httpClient.post(endpoint, requestBody);
|
|
810
|
+
if (response.data.msg) {
|
|
811
|
+
response.data.msg = replaceOldDomains(response.data.msg);
|
|
812
|
+
}
|
|
785
813
|
await this.taskFolderManager.writeResponse(taskCtx, response.data);
|
|
786
814
|
await this.taskFolderManager.log(taskCtx, "info", "Response received", {
|
|
787
815
|
code: response.data.code,
|
|
@@ -809,7 +837,8 @@ var UnityClawClient = class {
|
|
|
809
837
|
response.data.code === 0
|
|
810
838
|
);
|
|
811
839
|
} catch (error) {
|
|
812
|
-
const
|
|
840
|
+
const rawErrorMessage = error instanceof AxiosError ? error.response?.data?.msg || error.message : error instanceof Error ? error.message : String(error);
|
|
841
|
+
const errorMessage = replaceOldDomains(rawErrorMessage);
|
|
813
842
|
await this.taskFolderManager.log(taskCtx, "error", `Request failed: ${errorMessage}`, {
|
|
814
843
|
error: error instanceof AxiosError ? { status: error.response?.status, data: error.response?.data } : error
|
|
815
844
|
});
|