@ynhcj/xiaoyi-channel 0.0.195-next → 0.0.196-next
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.
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import https from 'https';
|
|
5
5
|
import { URL } from 'url';
|
|
6
6
|
import { getConfig } from './config.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
7
8
|
import { DEFAULT_HTTPS_PORT, DEFAULT_HTTP_PORT, HTTP_STATUS_BAD_REQUEST } from './constants.js';
|
|
8
9
|
function buildHeadersForCelia(config, sessionId) {
|
|
9
10
|
if (!config.uid || !config.apiKey || !config.skillId || !config.requestFrom) {
|
|
@@ -69,6 +70,7 @@ function handleResponse(res, resolve, reject) {
|
|
|
69
70
|
data += chunk;
|
|
70
71
|
});
|
|
71
72
|
res.on('end', () => {
|
|
73
|
+
logger.log(`[SENTINEL HOOK] callApi response body: ${data}`);
|
|
72
74
|
try {
|
|
73
75
|
const result = parseResponseData(data);
|
|
74
76
|
resolve(result);
|
|
@@ -84,6 +86,8 @@ export async function callApi(payload, api, sessionId) {
|
|
|
84
86
|
// 确保 uid 存在于消息体中(从 config 注入)
|
|
85
87
|
const payloadWithUid = { ...payload, uid: config.uid };
|
|
86
88
|
const httpBody = JSON.stringify(payloadWithUid);
|
|
89
|
+
logger.log(`[SENTINEL HOOK] callApi request URL: ${config.api.url}`);
|
|
90
|
+
logger.log(`[SENTINEL HOOK] callApi request body: ${httpBody}`);
|
|
87
91
|
return new Promise((resolve, reject) => {
|
|
88
92
|
const options = buildRequestOptions(config.api.url, headersForCelia, config.api.timeout);
|
|
89
93
|
const req = https.request(options, (res) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReportPayload, LogReporterEnv } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Send a log report to the sync API.
|
|
3
|
+
* Send a log report to the sync API with retry on failure.
|
|
4
|
+
* Retries up to 3 times with delays of 10s, 20s, 30s.
|
|
4
5
|
*/
|
|
5
6
|
export declare function sendReport(payload: ReportPayload, env: LogReporterEnv): Promise<void>;
|
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
import fetch from "node-fetch";
|
|
3
3
|
import { calculateSHA256String } from "../utils/crypto.js";
|
|
4
4
|
import { logger } from "../utils/logger.js";
|
|
5
|
+
/** Retry delays in milliseconds: 10s, 20s, 30s */
|
|
6
|
+
const RETRY_DELAYS_MS = [10000, 20000, 30000];
|
|
7
|
+
const MAX_RETRIES = RETRY_DELAYS_MS.length;
|
|
8
|
+
/** Sleep for a given duration in milliseconds */
|
|
9
|
+
function sleep(ms) {
|
|
10
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
+
}
|
|
5
12
|
/**
|
|
6
|
-
* Send a log report to the sync API.
|
|
13
|
+
* Send a log report to the sync API with retry on failure.
|
|
14
|
+
* Retries up to 3 times with delays of 10s, 20s, 30s.
|
|
7
15
|
*/
|
|
8
16
|
export async function sendReport(payload, env) {
|
|
9
17
|
if (payload.logFiles.length === 0) {
|
|
@@ -19,14 +27,30 @@ export async function sendReport(payload, env) {
|
|
|
19
27
|
"x-request-from": "openclaw",
|
|
20
28
|
};
|
|
21
29
|
logger.log(`[log-reporter] Sending report to ${url}, ${payload.logFiles.length} log file(s)`);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
let lastError;
|
|
31
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
const resp = await fetch(url, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers,
|
|
36
|
+
body: JSON.stringify(payload),
|
|
37
|
+
});
|
|
38
|
+
if (!resp.ok) {
|
|
39
|
+
const body = await resp.text().catch(() => "");
|
|
40
|
+
throw new Error(`Report API returned HTTP ${resp.status}: ${body}`);
|
|
41
|
+
}
|
|
42
|
+
logger.log(`[log-reporter] Report sent successfully, status: ${resp.status}`);
|
|
43
|
+
return; // success, exit
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
47
|
+
if (attempt < MAX_RETRIES) {
|
|
48
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
49
|
+
logger.warn(`[log-reporter] Report failed (attempt ${attempt + 1}/${MAX_RETRIES + 1}): ${lastError.message}. Retrying in ${delay / 1000}s...`);
|
|
50
|
+
await sleep(delay);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
30
53
|
}
|
|
31
|
-
|
|
54
|
+
// All retries exhausted
|
|
55
|
+
throw lastError;
|
|
32
56
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { UploadService } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Write content to a .bak file, upload, and return the URL.
|
|
4
|
+
* Retries upload up to 3 times with delays of 10s, 20s, 30s.
|
|
4
5
|
* Cleans up .bak file regardless of success/failure.
|
|
5
6
|
*/
|
|
6
7
|
export declare function uploadContent(content: string, name: string, bakDir: string, uploadService: UploadService): Promise<string>;
|
|
@@ -2,8 +2,17 @@
|
|
|
2
2
|
import { writeFileSync, unlinkSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { mkdirSync } from "fs";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
/** Retry delays in milliseconds: 10s, 20s, 30s */
|
|
7
|
+
const RETRY_DELAYS_MS = [10000, 20000, 30000];
|
|
8
|
+
const MAX_RETRIES = RETRY_DELAYS_MS.length;
|
|
9
|
+
/** Sleep for a given duration in milliseconds */
|
|
10
|
+
function sleep(ms) {
|
|
11
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
14
|
* Write content to a .bak file, upload, and return the URL.
|
|
15
|
+
* Retries upload up to 3 times with delays of 10s, 20s, 30s.
|
|
7
16
|
* Cleans up .bak file regardless of success/failure.
|
|
8
17
|
*/
|
|
9
18
|
export async function uploadContent(content, name, bakDir, uploadService) {
|
|
@@ -15,12 +24,26 @@ export async function uploadContent(content, name, bakDir, uploadService) {
|
|
|
15
24
|
mkdirSync(bakDir, { recursive: true });
|
|
16
25
|
}
|
|
17
26
|
catch { }
|
|
27
|
+
// Write incremental content to .bak file (only once)
|
|
28
|
+
writeFileSync(bakPath, content, "utf-8");
|
|
29
|
+
let lastError;
|
|
18
30
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
const url = await uploadService.uploadFileAndGetUrl(bakPath);
|
|
34
|
+
return url; // success
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
38
|
+
if (attempt < MAX_RETRIES) {
|
|
39
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
40
|
+
logger.warn(`[log-reporter] Upload failed for "${name}" (attempt ${attempt + 1}/${MAX_RETRIES + 1}): ${lastError.message}. Retrying in ${delay / 1000}s...`);
|
|
41
|
+
await sleep(delay);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// All retries exhausted
|
|
46
|
+
throw lastError;
|
|
24
47
|
}
|
|
25
48
|
finally {
|
|
26
49
|
// Always clean up the .bak file
|