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.
Files changed (71) hide show
  1. package/dist/apis/FileUploadsApi.d.ts +18 -0
  2. package/dist/apis/FileUploadsApi.js +25 -0
  3. package/dist/apis/ToolsApi.js +2 -19
  4. package/dist/clients/AnthropicGptClient.js +4 -0
  5. package/dist/clients/OpenAiGptClient.js +4 -0
  6. package/dist/esm/apis/FileUploadsApi.d.ts +18 -0
  7. package/dist/esm/apis/FileUploadsApi.js +25 -0
  8. package/dist/esm/apis/ToolsApi.js +2 -19
  9. package/dist/esm/clients/AnthropicGptClient.js +4 -0
  10. package/dist/esm/clients/OpenAiGptClient.js +4 -0
  11. package/dist/esm/init.d.ts +25 -0
  12. package/dist/esm/init.js +52 -0
  13. package/dist/esm/lib/page/extendPage.js +6 -1
  14. package/dist/esm/lib/test/testExtension.d.ts +15 -1
  15. package/dist/esm/lib/test/testExtension.js +279 -3
  16. package/dist/esm/main.d.ts +1 -0
  17. package/dist/esm/main.js +5 -1
  18. package/dist/esm/managers/AdminApiController.js +3 -0
  19. package/dist/esm/managers/DonobuFlow.d.ts +1 -1
  20. package/dist/esm/models/FlowHandle.d.ts +2 -1
  21. package/dist/esm/models/FlowMetadata.d.ts +1 -1
  22. package/dist/esm/models/FlowMetadata.js +4 -1
  23. package/dist/esm/persistence/DonobuSqliteDb.js +207 -0
  24. package/dist/esm/persistence/TestConfigHash.js +4 -2
  25. package/dist/esm/persistence/files/FileUploadCache.d.ts +123 -0
  26. package/dist/esm/persistence/files/FileUploadCache.js +315 -0
  27. package/dist/esm/persistence/files/FileUploadWorker.d.ts +66 -0
  28. package/dist/esm/persistence/files/FileUploadWorker.js +181 -0
  29. package/dist/esm/persistence/files/fileUploadWorkerRegistry.d.ts +42 -0
  30. package/dist/esm/persistence/files/fileUploadWorkerRegistry.js +73 -0
  31. package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.d.ts +32 -6
  32. package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.js +83 -13
  33. package/dist/esm/persistence/normalizeFlowMetadata.js +35 -0
  34. package/dist/esm/reporter/render.d.ts +0 -1
  35. package/dist/esm/reporter/render.js +2 -5
  36. package/dist/esm/reporter/renderMarkdown.js +2 -2
  37. package/dist/esm/tools/toolConstants.d.ts +2 -0
  38. package/dist/esm/tools/toolConstants.js +22 -0
  39. package/dist/esm/utils/ansi.d.ts +11 -0
  40. package/dist/esm/utils/ansi.js +16 -0
  41. package/dist/init.d.ts +25 -0
  42. package/dist/init.js +52 -0
  43. package/dist/lib/page/extendPage.js +6 -1
  44. package/dist/lib/test/testExtension.d.ts +15 -1
  45. package/dist/lib/test/testExtension.js +279 -3
  46. package/dist/main.d.ts +1 -0
  47. package/dist/main.js +5 -1
  48. package/dist/managers/AdminApiController.js +3 -0
  49. package/dist/managers/DonobuFlow.d.ts +1 -1
  50. package/dist/models/FlowHandle.d.ts +2 -1
  51. package/dist/models/FlowMetadata.d.ts +1 -1
  52. package/dist/models/FlowMetadata.js +4 -1
  53. package/dist/persistence/DonobuSqliteDb.js +207 -0
  54. package/dist/persistence/TestConfigHash.js +4 -2
  55. package/dist/persistence/files/FileUploadCache.d.ts +123 -0
  56. package/dist/persistence/files/FileUploadCache.js +315 -0
  57. package/dist/persistence/files/FileUploadWorker.d.ts +66 -0
  58. package/dist/persistence/files/FileUploadWorker.js +181 -0
  59. package/dist/persistence/files/fileUploadWorkerRegistry.d.ts +42 -0
  60. package/dist/persistence/files/fileUploadWorkerRegistry.js +73 -0
  61. package/dist/persistence/flows/FlowsPersistenceDonobuApi.d.ts +32 -6
  62. package/dist/persistence/flows/FlowsPersistenceDonobuApi.js +83 -13
  63. package/dist/persistence/normalizeFlowMetadata.js +35 -0
  64. package/dist/reporter/render.d.ts +0 -1
  65. package/dist/reporter/render.js +2 -5
  66. package/dist/reporter/renderMarkdown.js +2 -2
  67. package/dist/tools/toolConstants.d.ts +2 -0
  68. package/dist/tools/toolConstants.js +22 -0
  69. package/dist/utils/ansi.d.ts +11 -0
  70. package/dist/utils/ansi.js +16 -0
  71. 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
@@ -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 AcknowledgeUserInstruction_1 = require("../tools/AcknowledgeUserInstruction");
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 AcknowledgeUserInstruction_1 = require("../tools/AcknowledgeUserInstruction");
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',
@@ -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
- forLlm: `Assertion FAILED (cached) for: ${assertion}\nPlaywright Error: ${lastError?.message}`,
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 & import("@playwright/test").PlaywrightWorkerOptions>;
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