donobu 5.27.3 → 5.28.0
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/apis/FileUploadsApi.d.ts +18 -0
- package/dist/apis/FileUploadsApi.js +25 -0
- package/dist/apis/ToolsApi.js +2 -19
- package/dist/clients/AnthropicGptClient.js +4 -0
- package/dist/clients/OpenAiGptClient.js +4 -0
- package/dist/esm/apis/FileUploadsApi.d.ts +18 -0
- package/dist/esm/apis/FileUploadsApi.js +25 -0
- package/dist/esm/apis/ToolsApi.js +2 -19
- package/dist/esm/clients/AnthropicGptClient.js +4 -0
- package/dist/esm/clients/OpenAiGptClient.js +4 -0
- package/dist/esm/init.d.ts +25 -0
- package/dist/esm/init.js +52 -0
- package/dist/esm/lib/page/extendPage.js +6 -1
- package/dist/esm/lib/test/testExtension.d.ts +15 -1
- package/dist/esm/lib/test/testExtension.js +279 -3
- package/dist/esm/main.d.ts +1 -0
- package/dist/esm/main.js +5 -1
- package/dist/esm/managers/AdminApiController.js +3 -0
- package/dist/esm/managers/DonobuFlow.d.ts +1 -1
- package/dist/esm/models/FlowHandle.d.ts +2 -1
- package/dist/esm/models/FlowMetadata.d.ts +1 -1
- package/dist/esm/models/FlowMetadata.js +4 -1
- package/dist/esm/persistence/DonobuSqliteDb.js +207 -0
- package/dist/esm/persistence/TestConfigHash.js +4 -2
- package/dist/esm/persistence/files/FileUploadCache.d.ts +123 -0
- package/dist/esm/persistence/files/FileUploadCache.js +315 -0
- package/dist/esm/persistence/files/FileUploadWorker.d.ts +66 -0
- package/dist/esm/persistence/files/FileUploadWorker.js +181 -0
- package/dist/esm/persistence/files/fileUploadWorkerRegistry.d.ts +42 -0
- package/dist/esm/persistence/files/fileUploadWorkerRegistry.js +73 -0
- package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.d.ts +32 -6
- package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.js +83 -13
- package/dist/esm/persistence/normalizeFlowMetadata.js +35 -0
- package/dist/esm/reporter/render.d.ts +0 -1
- package/dist/esm/reporter/render.js +2 -5
- package/dist/esm/reporter/renderMarkdown.js +2 -2
- package/dist/esm/tools/toolConstants.d.ts +2 -0
- package/dist/esm/tools/toolConstants.js +22 -0
- package/dist/esm/utils/ansi.d.ts +11 -0
- package/dist/esm/utils/ansi.js +16 -0
- package/dist/init.d.ts +25 -0
- package/dist/init.js +52 -0
- package/dist/lib/page/extendPage.js +6 -1
- package/dist/lib/test/testExtension.d.ts +15 -1
- package/dist/lib/test/testExtension.js +279 -3
- package/dist/main.d.ts +1 -0
- package/dist/main.js +5 -1
- package/dist/managers/AdminApiController.js +3 -0
- package/dist/managers/DonobuFlow.d.ts +1 -1
- package/dist/models/FlowHandle.d.ts +2 -1
- package/dist/models/FlowMetadata.d.ts +1 -1
- package/dist/models/FlowMetadata.js +4 -1
- package/dist/persistence/DonobuSqliteDb.js +207 -0
- package/dist/persistence/TestConfigHash.js +4 -2
- package/dist/persistence/files/FileUploadCache.d.ts +123 -0
- package/dist/persistence/files/FileUploadCache.js +315 -0
- package/dist/persistence/files/FileUploadWorker.d.ts +66 -0
- package/dist/persistence/files/FileUploadWorker.js +181 -0
- package/dist/persistence/files/fileUploadWorkerRegistry.d.ts +42 -0
- package/dist/persistence/files/fileUploadWorkerRegistry.js +73 -0
- package/dist/persistence/flows/FlowsPersistenceDonobuApi.d.ts +32 -6
- package/dist/persistence/flows/FlowsPersistenceDonobuApi.js +83 -13
- package/dist/persistence/normalizeFlowMetadata.js +35 -0
- package/dist/reporter/render.d.ts +0 -1
- package/dist/reporter/render.js +2 -5
- package/dist/reporter/renderMarkdown.js +2 -2
- package/dist/tools/toolConstants.d.ts +2 -0
- package/dist/tools/toolConstants.js +22 -0
- package/dist/utils/ansi.d.ts +11 -0
- package/dist/utils/ansi.js +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Admin endpoints for observing the local file upload queue. Used by the
|
|
4
|
+
* desktop app's quit flow: query status, surface to the user, let them
|
|
5
|
+
* decide between waiting for drain and quitting anyway.
|
|
6
|
+
*
|
|
7
|
+
* No mutating endpoint is needed — the worker is always trying to drain.
|
|
8
|
+
* Callers wanting a "wait for drain" UX poll this until the active count
|
|
9
|
+
* hits zero, then exit the backend.
|
|
10
|
+
*/
|
|
11
|
+
export declare class FileUploadsApi {
|
|
12
|
+
/**
|
|
13
|
+
* GET /api/uploads/status — returns total + per-platform counts of files
|
|
14
|
+
* pending upload, currently in-flight, or failed.
|
|
15
|
+
*/
|
|
16
|
+
getStatus(_req: Request, res: Response): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=FileUploadsApi.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileUploadsApi = void 0;
|
|
4
|
+
const fileUploadWorkerRegistry_1 = require("../persistence/files/fileUploadWorkerRegistry");
|
|
5
|
+
/**
|
|
6
|
+
* Admin endpoints for observing the local file upload queue. Used by the
|
|
7
|
+
* desktop app's quit flow: query status, surface to the user, let them
|
|
8
|
+
* decide between waiting for drain and quitting anyway.
|
|
9
|
+
*
|
|
10
|
+
* No mutating endpoint is needed — the worker is always trying to drain.
|
|
11
|
+
* Callers wanting a "wait for drain" UX poll this until the active count
|
|
12
|
+
* hits zero, then exit the backend.
|
|
13
|
+
*/
|
|
14
|
+
class FileUploadsApi {
|
|
15
|
+
/**
|
|
16
|
+
* GET /api/uploads/status — returns total + per-platform counts of files
|
|
17
|
+
* pending upload, currently in-flight, or failed.
|
|
18
|
+
*/
|
|
19
|
+
async getStatus(_req, res) {
|
|
20
|
+
const status = await (0, fileUploadWorkerRegistry_1.getFileUploadAggregateStatus)();
|
|
21
|
+
res.json(status);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.FileUploadsApi = FileUploadsApi;
|
|
25
|
+
//# sourceMappingURL=FileUploadsApi.js.map
|
package/dist/apis/ToolsApi.js
CHANGED
|
@@ -2,24 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ToolsApi = void 0;
|
|
4
4
|
const v4_1 = require("zod/v4");
|
|
5
|
-
const
|
|
6
|
-
const AssertPageTextTool_1 = require("../tools/AssertPageTextTool");
|
|
7
|
-
const DetectBrokenLinksTool_1 = require("../tools/DetectBrokenLinksTool");
|
|
8
|
-
const DownloadPdfTool_1 = require("../tools/DownloadPdfTool");
|
|
9
|
-
const HandleBrowserDialogTool_1 = require("../tools/HandleBrowserDialogTool");
|
|
10
|
-
const PauseForUserInteractionTool_1 = require("../tools/PauseForUserInteractionTool");
|
|
11
|
-
const SaveWebpageAsPdfTool_1 = require("../tools/SaveWebpageAsPdfTool");
|
|
12
|
-
const TriggerDonobuFlowTool_1 = require("../tools/TriggerDonobuFlowTool");
|
|
13
|
-
const SUPPRESSED_TOOLS_BY_NAME = new Set([
|
|
14
|
-
AcknowledgeUserInstruction_1.AcknowledgeUserInstructionTool.NAME,
|
|
15
|
-
AssertPageTextTool_1.AssertPageTextTool.NAME,
|
|
16
|
-
DownloadPdfTool_1.DownloadPdfTool.NAME,
|
|
17
|
-
DetectBrokenLinksTool_1.DetectBrokenLinksTool.NAME,
|
|
18
|
-
HandleBrowserDialogTool_1.HandleBrowserDialogTool.NAME,
|
|
19
|
-
PauseForUserInteractionTool_1.PauseForUserInteractionTool.NAME,
|
|
20
|
-
SaveWebpageAsPdfTool_1.SaveWebpageAsPdfTool.NAME,
|
|
21
|
-
TriggerDonobuFlowTool_1.TriggerDonobuFlowTool.NAME,
|
|
22
|
-
]);
|
|
5
|
+
const toolConstants_1 = require("../tools/toolConstants");
|
|
23
6
|
/**
|
|
24
7
|
* This class reports the tools supported by the Donobu runtime.
|
|
25
8
|
*/
|
|
@@ -36,7 +19,7 @@ class ToolsApi {
|
|
|
36
19
|
? this.toolRegistry.toolsForTarget(targetType)
|
|
37
20
|
: this.toolRegistry.allTools();
|
|
38
21
|
const response = tools
|
|
39
|
-
.filter((tool) => !SUPPRESSED_TOOLS_BY_NAME.has(tool.name))
|
|
22
|
+
.filter((tool) => !toolConstants_1.SUPPRESSED_TOOLS_BY_NAME.has(tool.name))
|
|
40
23
|
.map((tool) => ({
|
|
41
24
|
name: tool.name,
|
|
42
25
|
description: tool.description,
|
|
@@ -7,6 +7,7 @@ const GptPlatformAuthenticationFailedException_1 = require("../exceptions/GptPla
|
|
|
7
7
|
const GptPlatformInsufficientQuotaException_1 = require("../exceptions/GptPlatformInsufficientQuotaException");
|
|
8
8
|
const GptPlatformInternalErrorException_1 = require("../exceptions/GptPlatformInternalErrorException");
|
|
9
9
|
const GptPlatformNotReachableException_1 = require("../exceptions/GptPlatformNotReachableException");
|
|
10
|
+
const InvalidParamValueException_1 = require("../exceptions/InvalidParamValueException");
|
|
10
11
|
const JsonUtils_1 = require("../utils/JsonUtils");
|
|
11
12
|
const Logger_1 = require("../utils/Logger");
|
|
12
13
|
const MiscUtils_1 = require("../utils/MiscUtils");
|
|
@@ -19,6 +20,9 @@ class AnthropicGptClient extends GptClient_1.GptClient {
|
|
|
19
20
|
constructor(anthropicConfig) {
|
|
20
21
|
super(anthropicConfig);
|
|
21
22
|
this.anthropicConfig = anthropicConfig;
|
|
23
|
+
if (!/^[\x21-\x7e]{1,128}$/.test(anthropicConfig.apiKey)) {
|
|
24
|
+
throw new InvalidParamValueException_1.InvalidParamValueException('apiKey', 'REDACTED', 'it is malformed');
|
|
25
|
+
}
|
|
22
26
|
this.headers = new Headers({
|
|
23
27
|
[AnthropicGptClient.API_KEY_HEADER_NAME]: anthropicConfig.apiKey,
|
|
24
28
|
[AnthropicGptClient.API_VERSION_HEADER_NAME]: AnthropicGptClient.API_VERSION_HEADER_VALUE,
|
|
@@ -7,6 +7,7 @@ const GptPlatformAuthenticationFailedException_1 = require("../exceptions/GptPla
|
|
|
7
7
|
const GptPlatformInsufficientQuotaException_1 = require("../exceptions/GptPlatformInsufficientQuotaException");
|
|
8
8
|
const GptPlatformInternalErrorException_1 = require("../exceptions/GptPlatformInternalErrorException");
|
|
9
9
|
const GptPlatformNotReachableException_1 = require("../exceptions/GptPlatformNotReachableException");
|
|
10
|
+
const InvalidParamValueException_1 = require("../exceptions/InvalidParamValueException");
|
|
10
11
|
const JsonUtils_1 = require("../utils/JsonUtils");
|
|
11
12
|
const Logger_1 = require("../utils/Logger");
|
|
12
13
|
const MiscUtils_1 = require("../utils/MiscUtils");
|
|
@@ -20,6 +21,9 @@ class OpenAiGptClient extends GptClient_1.GptClient {
|
|
|
20
21
|
super(openAiConfig);
|
|
21
22
|
this.openAiConfig = openAiConfig;
|
|
22
23
|
this.apiUrl = apiUrl;
|
|
24
|
+
if (!/^[\x21-\x7e]{1,128}$/.test(openAiConfig.apiKey)) {
|
|
25
|
+
throw new InvalidParamValueException_1.InvalidParamValueException('apiKey', 'REDACTED', 'it is malformed');
|
|
26
|
+
}
|
|
23
27
|
this.headers = new Headers({
|
|
24
28
|
Authorization: `Bearer ${openAiConfig.apiKey}`,
|
|
25
29
|
'Content-Type': 'application/json',
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Admin endpoints for observing the local file upload queue. Used by the
|
|
4
|
+
* desktop app's quit flow: query status, surface to the user, let them
|
|
5
|
+
* decide between waiting for drain and quitting anyway.
|
|
6
|
+
*
|
|
7
|
+
* No mutating endpoint is needed — the worker is always trying to drain.
|
|
8
|
+
* Callers wanting a "wait for drain" UX poll this until the active count
|
|
9
|
+
* hits zero, then exit the backend.
|
|
10
|
+
*/
|
|
11
|
+
export declare class FileUploadsApi {
|
|
12
|
+
/**
|
|
13
|
+
* GET /api/uploads/status — returns total + per-platform counts of files
|
|
14
|
+
* pending upload, currently in-flight, or failed.
|
|
15
|
+
*/
|
|
16
|
+
getStatus(_req: Request, res: Response): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=FileUploadsApi.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileUploadsApi = void 0;
|
|
4
|
+
const fileUploadWorkerRegistry_1 = require("../persistence/files/fileUploadWorkerRegistry");
|
|
5
|
+
/**
|
|
6
|
+
* Admin endpoints for observing the local file upload queue. Used by the
|
|
7
|
+
* desktop app's quit flow: query status, surface to the user, let them
|
|
8
|
+
* decide between waiting for drain and quitting anyway.
|
|
9
|
+
*
|
|
10
|
+
* No mutating endpoint is needed — the worker is always trying to drain.
|
|
11
|
+
* Callers wanting a "wait for drain" UX poll this until the active count
|
|
12
|
+
* hits zero, then exit the backend.
|
|
13
|
+
*/
|
|
14
|
+
class FileUploadsApi {
|
|
15
|
+
/**
|
|
16
|
+
* GET /api/uploads/status — returns total + per-platform counts of files
|
|
17
|
+
* pending upload, currently in-flight, or failed.
|
|
18
|
+
*/
|
|
19
|
+
async getStatus(_req, res) {
|
|
20
|
+
const status = await (0, fileUploadWorkerRegistry_1.getFileUploadAggregateStatus)();
|
|
21
|
+
res.json(status);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.FileUploadsApi = FileUploadsApi;
|
|
25
|
+
//# sourceMappingURL=FileUploadsApi.js.map
|
|
@@ -2,24 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ToolsApi = void 0;
|
|
4
4
|
const v4_1 = require("zod/v4");
|
|
5
|
-
const
|
|
6
|
-
const AssertPageTextTool_1 = require("../tools/AssertPageTextTool");
|
|
7
|
-
const DetectBrokenLinksTool_1 = require("../tools/DetectBrokenLinksTool");
|
|
8
|
-
const DownloadPdfTool_1 = require("../tools/DownloadPdfTool");
|
|
9
|
-
const HandleBrowserDialogTool_1 = require("../tools/HandleBrowserDialogTool");
|
|
10
|
-
const PauseForUserInteractionTool_1 = require("../tools/PauseForUserInteractionTool");
|
|
11
|
-
const SaveWebpageAsPdfTool_1 = require("../tools/SaveWebpageAsPdfTool");
|
|
12
|
-
const TriggerDonobuFlowTool_1 = require("../tools/TriggerDonobuFlowTool");
|
|
13
|
-
const SUPPRESSED_TOOLS_BY_NAME = new Set([
|
|
14
|
-
AcknowledgeUserInstruction_1.AcknowledgeUserInstructionTool.NAME,
|
|
15
|
-
AssertPageTextTool_1.AssertPageTextTool.NAME,
|
|
16
|
-
DownloadPdfTool_1.DownloadPdfTool.NAME,
|
|
17
|
-
DetectBrokenLinksTool_1.DetectBrokenLinksTool.NAME,
|
|
18
|
-
HandleBrowserDialogTool_1.HandleBrowserDialogTool.NAME,
|
|
19
|
-
PauseForUserInteractionTool_1.PauseForUserInteractionTool.NAME,
|
|
20
|
-
SaveWebpageAsPdfTool_1.SaveWebpageAsPdfTool.NAME,
|
|
21
|
-
TriggerDonobuFlowTool_1.TriggerDonobuFlowTool.NAME,
|
|
22
|
-
]);
|
|
5
|
+
const toolConstants_1 = require("../tools/toolConstants");
|
|
23
6
|
/**
|
|
24
7
|
* This class reports the tools supported by the Donobu runtime.
|
|
25
8
|
*/
|
|
@@ -36,7 +19,7 @@ class ToolsApi {
|
|
|
36
19
|
? this.toolRegistry.toolsForTarget(targetType)
|
|
37
20
|
: this.toolRegistry.allTools();
|
|
38
21
|
const response = tools
|
|
39
|
-
.filter((tool) => !SUPPRESSED_TOOLS_BY_NAME.has(tool.name))
|
|
22
|
+
.filter((tool) => !toolConstants_1.SUPPRESSED_TOOLS_BY_NAME.has(tool.name))
|
|
40
23
|
.map((tool) => ({
|
|
41
24
|
name: tool.name,
|
|
42
25
|
description: tool.description,
|
|
@@ -7,6 +7,7 @@ const GptPlatformAuthenticationFailedException_1 = require("../exceptions/GptPla
|
|
|
7
7
|
const GptPlatformInsufficientQuotaException_1 = require("../exceptions/GptPlatformInsufficientQuotaException");
|
|
8
8
|
const GptPlatformInternalErrorException_1 = require("../exceptions/GptPlatformInternalErrorException");
|
|
9
9
|
const GptPlatformNotReachableException_1 = require("../exceptions/GptPlatformNotReachableException");
|
|
10
|
+
const InvalidParamValueException_1 = require("../exceptions/InvalidParamValueException");
|
|
10
11
|
const JsonUtils_1 = require("../utils/JsonUtils");
|
|
11
12
|
const Logger_1 = require("../utils/Logger");
|
|
12
13
|
const MiscUtils_1 = require("../utils/MiscUtils");
|
|
@@ -19,6 +20,9 @@ class AnthropicGptClient extends GptClient_1.GptClient {
|
|
|
19
20
|
constructor(anthropicConfig) {
|
|
20
21
|
super(anthropicConfig);
|
|
21
22
|
this.anthropicConfig = anthropicConfig;
|
|
23
|
+
if (!/^[\x21-\x7e]{1,128}$/.test(anthropicConfig.apiKey)) {
|
|
24
|
+
throw new InvalidParamValueException_1.InvalidParamValueException('apiKey', 'REDACTED', 'it is malformed');
|
|
25
|
+
}
|
|
22
26
|
this.headers = new Headers({
|
|
23
27
|
[AnthropicGptClient.API_KEY_HEADER_NAME]: anthropicConfig.apiKey,
|
|
24
28
|
[AnthropicGptClient.API_VERSION_HEADER_NAME]: AnthropicGptClient.API_VERSION_HEADER_VALUE,
|
|
@@ -7,6 +7,7 @@ const GptPlatformAuthenticationFailedException_1 = require("../exceptions/GptPla
|
|
|
7
7
|
const GptPlatformInsufficientQuotaException_1 = require("../exceptions/GptPlatformInsufficientQuotaException");
|
|
8
8
|
const GptPlatformInternalErrorException_1 = require("../exceptions/GptPlatformInternalErrorException");
|
|
9
9
|
const GptPlatformNotReachableException_1 = require("../exceptions/GptPlatformNotReachableException");
|
|
10
|
+
const InvalidParamValueException_1 = require("../exceptions/InvalidParamValueException");
|
|
10
11
|
const JsonUtils_1 = require("../utils/JsonUtils");
|
|
11
12
|
const Logger_1 = require("../utils/Logger");
|
|
12
13
|
const MiscUtils_1 = require("../utils/MiscUtils");
|
|
@@ -20,6 +21,9 @@ class OpenAiGptClient extends GptClient_1.GptClient {
|
|
|
20
21
|
super(openAiConfig);
|
|
21
22
|
this.openAiConfig = openAiConfig;
|
|
22
23
|
this.apiUrl = apiUrl;
|
|
24
|
+
if (!/^[\x21-\x7e]{1,128}$/.test(openAiConfig.apiKey)) {
|
|
25
|
+
throw new InvalidParamValueException_1.InvalidParamValueException('apiKey', 'REDACTED', 'it is malformed');
|
|
26
|
+
}
|
|
23
27
|
this.headers = new Headers({
|
|
24
28
|
Authorization: `Bearer ${openAiConfig.apiKey}`,
|
|
25
29
|
'Content-Type': 'application/json',
|
package/dist/esm/init.d.ts
CHANGED
|
@@ -15,4 +15,29 @@
|
|
|
15
15
|
* long-lived processes unexpectedly.
|
|
16
16
|
*/
|
|
17
17
|
export declare function installCrashHandlers(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Installs SIGTERM/SIGINT handlers that drain any in-flight file uploads
|
|
20
|
+
* (bounded by {@link SHUTDOWN_FLUSH_TIMEOUT_MS}) before exiting cleanly.
|
|
21
|
+
*
|
|
22
|
+
* **Intended primarily as a developer / CLI fallback.** In production the
|
|
23
|
+
* desktop app drives shutdown explicitly: it queries
|
|
24
|
+
* `GET /api/uploads/status`, surfaces the count to the user, and either
|
|
25
|
+
* (a) waits for the worker to drain on its own and then terminates the
|
|
26
|
+
* backend, or (b) terminates immediately on user request. In that path
|
|
27
|
+
* these handlers may not fire at all — terminations from the host are
|
|
28
|
+
* what they are.
|
|
29
|
+
*
|
|
30
|
+
* For `node dist/main.js` runs (developers, integration tests), Ctrl+C
|
|
31
|
+
* still benefits from a graceful drain so test artefacts don't pile up
|
|
32
|
+
* as `.uploading.<token>` markers.
|
|
33
|
+
*
|
|
34
|
+
* Same constraint as {@link installCrashHandlers}: only call this when
|
|
35
|
+
* running as a standalone server, never when imported as a library —
|
|
36
|
+
* process-wide signal handlers would hijack the host.
|
|
37
|
+
*
|
|
38
|
+
* Uploads that don't complete within the timeout stay on disk as
|
|
39
|
+
* `.uploading.<token>` markers; another Studio process will reclaim them
|
|
40
|
+
* once the claim goes stale (5 min default).
|
|
41
|
+
*/
|
|
42
|
+
export declare function installShutdownHandlers(): void;
|
|
18
43
|
//# sourceMappingURL=init.d.ts.map
|
package/dist/esm/init.js
CHANGED
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.installCrashHandlers = installCrashHandlers;
|
|
11
|
+
exports.installShutdownHandlers = installShutdownHandlers;
|
|
12
|
+
const fileUploadWorkerRegistry_1 = require("./persistence/files/fileUploadWorkerRegistry");
|
|
11
13
|
const JsonUtils_1 = require("./utils/JsonUtils");
|
|
12
14
|
const Logger_1 = require("./utils/Logger");
|
|
15
|
+
const SHUTDOWN_FLUSH_TIMEOUT_MS = 30_000;
|
|
13
16
|
/**
|
|
14
17
|
* Installs global error handlers that crash the process on unhandled errors.
|
|
15
18
|
*
|
|
@@ -62,4 +65,53 @@ function installCrashHandlers() {
|
|
|
62
65
|
process.exit(1);
|
|
63
66
|
});
|
|
64
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Installs SIGTERM/SIGINT handlers that drain any in-flight file uploads
|
|
70
|
+
* (bounded by {@link SHUTDOWN_FLUSH_TIMEOUT_MS}) before exiting cleanly.
|
|
71
|
+
*
|
|
72
|
+
* **Intended primarily as a developer / CLI fallback.** In production the
|
|
73
|
+
* desktop app drives shutdown explicitly: it queries
|
|
74
|
+
* `GET /api/uploads/status`, surfaces the count to the user, and either
|
|
75
|
+
* (a) waits for the worker to drain on its own and then terminates the
|
|
76
|
+
* backend, or (b) terminates immediately on user request. In that path
|
|
77
|
+
* these handlers may not fire at all — terminations from the host are
|
|
78
|
+
* what they are.
|
|
79
|
+
*
|
|
80
|
+
* For `node dist/main.js` runs (developers, integration tests), Ctrl+C
|
|
81
|
+
* still benefits from a graceful drain so test artefacts don't pile up
|
|
82
|
+
* as `.uploading.<token>` markers.
|
|
83
|
+
*
|
|
84
|
+
* Same constraint as {@link installCrashHandlers}: only call this when
|
|
85
|
+
* running as a standalone server, never when imported as a library —
|
|
86
|
+
* process-wide signal handlers would hijack the host.
|
|
87
|
+
*
|
|
88
|
+
* Uploads that don't complete within the timeout stay on disk as
|
|
89
|
+
* `.uploading.<token>` markers; another Studio process will reclaim them
|
|
90
|
+
* once the claim goes stale (5 min default).
|
|
91
|
+
*/
|
|
92
|
+
function installShutdownHandlers() {
|
|
93
|
+
let shuttingDown = false;
|
|
94
|
+
const handle = (signal) => {
|
|
95
|
+
if (shuttingDown) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
shuttingDown = true;
|
|
99
|
+
void (async () => {
|
|
100
|
+
Logger_1.appLogger.info(`Received ${signal}; draining file upload workers.`);
|
|
101
|
+
try {
|
|
102
|
+
const result = await (0, fileUploadWorkerRegistry_1.shutdownFileUploadWorkers)(SHUTDOWN_FLUSH_TIMEOUT_MS);
|
|
103
|
+
if (!result.drained) {
|
|
104
|
+
Logger_1.appLogger.warn(`File upload queue did not fully drain at shutdown; ` +
|
|
105
|
+
`${result.totalRemaining} upload(s) remain on disk and will resume on next start.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
Logger_1.appLogger.error(`Error draining file upload workers at shutdown: ${err.message}`);
|
|
110
|
+
}
|
|
111
|
+
process.exit(0);
|
|
112
|
+
})();
|
|
113
|
+
};
|
|
114
|
+
process.on('SIGTERM', handle);
|
|
115
|
+
process.on('SIGINT', handle);
|
|
116
|
+
}
|
|
65
117
|
//# sourceMappingURL=init.js.map
|
|
@@ -21,6 +21,7 @@ const ChangeWebBrowserTabTool_1 = require("../../tools/ChangeWebBrowserTabTool")
|
|
|
21
21
|
const CreateBrowserCookieReportTool_1 = require("../../tools/CreateBrowserCookieReportTool");
|
|
22
22
|
const GoToWebpageTool_1 = require("../../tools/GoToWebpageTool");
|
|
23
23
|
const RunAccessibilityTestTool_1 = require("../../tools/RunAccessibilityTestTool");
|
|
24
|
+
const ansi_1 = require("../../utils/ansi");
|
|
24
25
|
const BrowserUtils_1 = require("../../utils/BrowserUtils");
|
|
25
26
|
const Logger_1 = require("../../utils/Logger");
|
|
26
27
|
const MiscUtils_1 = require("../../utils/MiscUtils");
|
|
@@ -241,7 +242,11 @@ Valid options:
|
|
|
241
242
|
// All retry attempts exhausted
|
|
242
243
|
throw new ToolCallFailedException_1.ToolCallFailedException(AssertTool_1.AssertTool.NAME, {
|
|
243
244
|
isSuccessful: false,
|
|
244
|
-
|
|
245
|
+
// Strip ANSI: Playwright matchers style their messages for the
|
|
246
|
+
// terminal, but this string flows into JSON-stringified exception
|
|
247
|
+
// messages, the LLM, and HTML/markdown reports — places where the
|
|
248
|
+
// codes never render and just become visible junk.
|
|
249
|
+
forLlm: `Assertion FAILED (cached) for: ${assertion}\nPlaywright Error: ${(0, ansi_1.stripAnsi)(lastError?.message ?? '')}`,
|
|
245
250
|
metadata: {
|
|
246
251
|
cached: true,
|
|
247
252
|
steps: cached.steps,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PlaywrightWorkerOptions } from '@playwright/test';
|
|
1
2
|
import type { GptClient } from '../../clients/GptClient';
|
|
2
3
|
import type { BrowserStorageState } from '../../models/BrowserStorageState';
|
|
3
4
|
import { FlowLogBuffer } from '../../utils/FlowLogBuffer';
|
|
@@ -11,5 +12,18 @@ export declare const test: import("@playwright/test").TestType<import("@playwrig
|
|
|
11
12
|
storageState?: BrowserStorageState | Promise<BrowserStorageState>;
|
|
12
13
|
gptClient?: GptClient;
|
|
13
14
|
page: DonobuExtendedPage;
|
|
14
|
-
}, import("@playwright/test").PlaywrightWorkerArgs &
|
|
15
|
+
}, import("@playwright/test").PlaywrightWorkerArgs & PlaywrightWorkerOptions & {
|
|
16
|
+
/**
|
|
17
|
+
* Auto worker-scoped fixture that drains pending file uploads to
|
|
18
|
+
* Donobu Cloud at the end of each Playwright worker's lifetime. Without
|
|
19
|
+
* this, the worker process would exit while uploads are still in-flight
|
|
20
|
+
* — fine for local dev (the next process resumes them) but a real
|
|
21
|
+
* data-loss case in ephemeral CI runners.
|
|
22
|
+
*
|
|
23
|
+
* Logs loudly when it has work to do so the user understands why
|
|
24
|
+
* teardown is taking time instead of wondering why the process isn't
|
|
25
|
+
* exiting.
|
|
26
|
+
*/
|
|
27
|
+
donobuFileUploadDrainGuard: void;
|
|
28
|
+
}>;
|
|
15
29
|
//# sourceMappingURL=testExtension.d.ts.map
|