donobu 5.61.3 → 5.62.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/cli/donobu-cli.js +2 -1
- package/dist/esm/cli/donobu-cli.js +2 -1
- package/dist/esm/lib/test/testExtension.js +4 -3
- package/dist/esm/lib/test/utils/triageTestFailure.d.ts +0 -7
- package/dist/esm/lib/test/utils/triageTestFailure.js +2 -13
- package/dist/esm/main.d.ts +1 -1
- package/dist/esm/main.js +3 -1
- package/dist/esm/managers/DonobuFlowsManager.d.ts +1 -1
- package/dist/esm/managers/DonobuFlowsManager.js +4 -3
- package/dist/esm/persistence/flows/FlowsPersistence.d.ts +33 -0
- package/dist/esm/persistence/flows/FlowsPersistence.js +34 -0
- package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.d.ts +1 -1
- package/dist/esm/persistence/flows/FlowsPersistenceDonobuApi.js +3 -3
- package/dist/esm/persistence/flows/FlowsPersistenceSqlite.d.ts +1 -3
- package/dist/esm/persistence/flows/FlowsPersistenceSqlite.js +6 -7
- package/dist/lib/test/testExtension.js +4 -3
- package/dist/lib/test/utils/triageTestFailure.d.ts +0 -7
- package/dist/lib/test/utils/triageTestFailure.js +2 -13
- package/dist/main.d.ts +1 -1
- package/dist/main.js +3 -1
- package/dist/managers/DonobuFlowsManager.d.ts +1 -1
- package/dist/managers/DonobuFlowsManager.js +4 -3
- package/dist/persistence/flows/FlowsPersistence.d.ts +33 -0
- package/dist/persistence/flows/FlowsPersistence.js +34 -0
- package/dist/persistence/flows/FlowsPersistenceDonobuApi.d.ts +1 -1
- package/dist/persistence/flows/FlowsPersistenceDonobuApi.js +3 -3
- package/dist/persistence/flows/FlowsPersistenceSqlite.d.ts +1 -3
- package/dist/persistence/flows/FlowsPersistenceSqlite.js +6 -7
- package/package.json +1 -1
package/dist/cli/donobu-cli.js
CHANGED
|
@@ -66,6 +66,7 @@ const healRerunGate_1 = require("../lib/test/healRerunGate");
|
|
|
66
66
|
const donobuTestStack_1 = require("../lib/test/utils/donobuTestStack");
|
|
67
67
|
const triageTestFailure_1 = require("../lib/test/utils/triageTestFailure");
|
|
68
68
|
const fileUploadWorkerRegistry_1 = require("../persistence/files/fileUploadWorkerRegistry");
|
|
69
|
+
const FlowsPersistence_1 = require("../persistence/flows/FlowsPersistence");
|
|
69
70
|
const FlowsPersistenceDonobuApi_1 = require("../persistence/flows/FlowsPersistenceDonobuApi");
|
|
70
71
|
const FlowsPersistenceRegistry_1 = require("../persistence/flows/FlowsPersistenceRegistry");
|
|
71
72
|
const merge_1 = require("../reporter/merge");
|
|
@@ -1292,7 +1293,7 @@ async function postProcessTriageRun(context, originalPlaywrightArgs, reportPath)
|
|
|
1292
1293
|
const donobu = await (0, donobuTestStack_1.getOrCreateDonobuStack)();
|
|
1293
1294
|
const persistence = await donobu.flowsPersistenceRegistry.get();
|
|
1294
1295
|
const planBuffer = Buffer.from(persistedJson, 'utf8');
|
|
1295
|
-
const fileId =
|
|
1296
|
+
const fileId = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.treatmentPlan;
|
|
1296
1297
|
await persistence.setFlowFile(flowId, fileId, planBuffer);
|
|
1297
1298
|
Logger_1.appLogger.info(`Persisted treatment plan for "${testLabel}" as "${fileId}" to Donobu stack (flow: ${flowId}).`);
|
|
1298
1299
|
}
|
|
@@ -66,6 +66,7 @@ const healRerunGate_1 = require("../lib/test/healRerunGate");
|
|
|
66
66
|
const donobuTestStack_1 = require("../lib/test/utils/donobuTestStack");
|
|
67
67
|
const triageTestFailure_1 = require("../lib/test/utils/triageTestFailure");
|
|
68
68
|
const fileUploadWorkerRegistry_1 = require("../persistence/files/fileUploadWorkerRegistry");
|
|
69
|
+
const FlowsPersistence_1 = require("../persistence/flows/FlowsPersistence");
|
|
69
70
|
const FlowsPersistenceDonobuApi_1 = require("../persistence/flows/FlowsPersistenceDonobuApi");
|
|
70
71
|
const FlowsPersistenceRegistry_1 = require("../persistence/flows/FlowsPersistenceRegistry");
|
|
71
72
|
const merge_1 = require("../reporter/merge");
|
|
@@ -1292,7 +1293,7 @@ async function postProcessTriageRun(context, originalPlaywrightArgs, reportPath)
|
|
|
1292
1293
|
const donobu = await (0, donobuTestStack_1.getOrCreateDonobuStack)();
|
|
1293
1294
|
const persistence = await donobu.flowsPersistenceRegistry.get();
|
|
1294
1295
|
const planBuffer = Buffer.from(persistedJson, 'utf8');
|
|
1295
|
-
const fileId =
|
|
1296
|
+
const fileId = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.treatmentPlan;
|
|
1296
1297
|
await persistence.setFlowFile(flowId, fileId, planBuffer);
|
|
1297
1298
|
Logger_1.appLogger.info(`Persisted treatment plan for "${testLabel}" as "${fileId}" to Donobu stack (flow: ${flowId}).`);
|
|
1298
1299
|
}
|
|
@@ -31,6 +31,7 @@ const v4_1 = require("zod/v4");
|
|
|
31
31
|
const envVars_1 = require("../../envVars");
|
|
32
32
|
const DonobuFlowsManager_1 = require("../../managers/DonobuFlowsManager");
|
|
33
33
|
const fileUploadWorkerRegistry_1 = require("../../persistence/files/fileUploadWorkerRegistry");
|
|
34
|
+
const FlowsPersistence_1 = require("../../persistence/flows/FlowsPersistence");
|
|
34
35
|
const ansi_1 = require("../../utils/ansi");
|
|
35
36
|
const BrowserUtils_1 = require("../../utils/BrowserUtils");
|
|
36
37
|
const buildProvenance_1 = require("../../utils/buildProvenance");
|
|
@@ -958,7 +959,7 @@ async function captureAndPersistFinalState(page, testInfo) {
|
|
|
958
959
|
try {
|
|
959
960
|
const screenshot = await (0, triageTestFailure_1.captureLivePageScreenshot)(page);
|
|
960
961
|
if (screenshot) {
|
|
961
|
-
await persistence.setFlowFile(flowId,
|
|
962
|
+
await persistence.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.triage.finalStateScreenshot, screenshot);
|
|
962
963
|
}
|
|
963
964
|
}
|
|
964
965
|
catch (error) {
|
|
@@ -991,11 +992,11 @@ async function finalizeTest(page, testInfo, logBuffer, videoOption) {
|
|
|
991
992
|
// assertion errors with snippets/diffs) so the website can render the
|
|
992
993
|
// report's summary row + error section. Playwright's TestInfoError already
|
|
993
994
|
// carries the code `snippet`, so no source-file access is needed.
|
|
994
|
-
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id,
|
|
995
|
+
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.donobuTestResult, buildDonobuTestResult(testInfo));
|
|
995
996
|
// Persist captured flow logs so they are available in the Donobu UI,
|
|
996
997
|
// mirroring what DonobuFlowsManager does for Studio-launched flows.
|
|
997
998
|
if (logBuffer) {
|
|
998
|
-
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id,
|
|
999
|
+
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs, logBuffer.snapshot());
|
|
999
1000
|
}
|
|
1000
1001
|
// Attach step-level screenshots from the flow's tool call history.
|
|
1001
1002
|
// These enable the HTML report to show a visual timeline of what the
|
|
@@ -409,13 +409,6 @@ declare const TRIAGE_PERSISTENCE_FILE_IDS: {
|
|
|
409
409
|
readonly evidence: "triage-evidence.json";
|
|
410
410
|
readonly failureScreenshot: "triage-failure-screenshot.png";
|
|
411
411
|
readonly baselineScreenshot: "triage-baseline-screenshot.png";
|
|
412
|
-
/**
|
|
413
|
-
* Live screenshot of a flow's final visual state, captured at teardown while
|
|
414
|
-
* the page is still open. Persisted on successful runs so that a *later*
|
|
415
|
-
* failing run can use it as a true final-state baseline — symmetric with the
|
|
416
|
-
* failure screenshot, which is also a live end-of-test capture. Keyed per
|
|
417
|
-
* flow, like browser state.
|
|
418
|
-
*/
|
|
419
412
|
readonly finalStateScreenshot: "triage-final-state-screenshot.png";
|
|
420
413
|
};
|
|
421
414
|
/**
|
|
@@ -49,6 +49,7 @@ const fs = __importStar(require("fs/promises"));
|
|
|
49
49
|
const path = __importStar(require("path"));
|
|
50
50
|
const typescript_1 = __importDefault(require("typescript"));
|
|
51
51
|
const v4_1 = require("zod/v4");
|
|
52
|
+
const FlowsPersistence_1 = require("../../../persistence/flows/FlowsPersistence");
|
|
52
53
|
const AnalyzePageTextTool_1 = require("../../../tools/AnalyzePageTextTool");
|
|
53
54
|
const MarkObjectiveCompleteTool_1 = require("../../../tools/MarkObjectiveCompleteTool");
|
|
54
55
|
const MarkObjectiveNotCompletableTool_1 = require("../../../tools/MarkObjectiveNotCompletableTool");
|
|
@@ -329,19 +330,7 @@ const MAX_SERIALIZED_STRING_LENGTH = 10000;
|
|
|
329
330
|
const MAX_TOOL_CALL_PARAMETERS_LENGTH = 500;
|
|
330
331
|
const MAX_TOOL_CALLS_TO_INCLUDE = 12;
|
|
331
332
|
const TRIAGE_EVIDENCE_SCHEMA_VERSION = 2;
|
|
332
|
-
const TRIAGE_PERSISTENCE_FILE_IDS =
|
|
333
|
-
evidence: 'triage-evidence.json',
|
|
334
|
-
failureScreenshot: 'triage-failure-screenshot.png',
|
|
335
|
-
baselineScreenshot: 'triage-baseline-screenshot.png',
|
|
336
|
-
/**
|
|
337
|
-
* Live screenshot of a flow's final visual state, captured at teardown while
|
|
338
|
-
* the page is still open. Persisted on successful runs so that a *later*
|
|
339
|
-
* failing run can use it as a true final-state baseline — symmetric with the
|
|
340
|
-
* failure screenshot, which is also a live end-of-test capture. Keyed per
|
|
341
|
-
* flow, like browser state.
|
|
342
|
-
*/
|
|
343
|
-
finalStateScreenshot: 'triage-final-state-screenshot.png',
|
|
344
|
-
};
|
|
333
|
+
const TRIAGE_PERSISTENCE_FILE_IDS = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.triage;
|
|
345
334
|
exports.TRIAGE_PERSISTENCE_FILE_IDS = TRIAGE_PERSISTENCE_FILE_IDS;
|
|
346
335
|
/**
|
|
347
336
|
* Ensures text blobs captured from tool calls or error messages fit within storage
|
package/dist/esm/main.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export type * from './models/ToolTemplateDataSource';
|
|
|
61
61
|
export type { VideoSegment } from './models/VideoSegment';
|
|
62
62
|
export type { EnvPersistence } from './persistence/env/EnvPersistence';
|
|
63
63
|
export { type FileUploadAggregateStatus, type FileUploadPlatformStatus, getFileUploadAggregateStatus, shutdownFileUploadWorkers, } from './persistence/files/fileUploadWorkerRegistry';
|
|
64
|
-
export type
|
|
64
|
+
export { type FlowsPersistence, WELL_KNOWN_FILE_IDS, } from './persistence/flows/FlowsPersistence';
|
|
65
65
|
export { type PersistencePlugin, PersistencePluginRegistry, } from './persistence/PersistencePlugin';
|
|
66
66
|
export type { SuitesPersistence } from './persistence/suites/SuitesPersistence';
|
|
67
67
|
export type { TestsPersistence } from './persistence/tests/TestsPersistence';
|
package/dist/esm/main.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.TargetRuntimePluginRegistry = exports.PersistencePluginRegistry = exports.shutdownFileUploadWorkers = exports.getFileUploadAggregateStatus = exports.createDefaultToolRegistry = exports.ToolManager = exports.buildToolInterpolationDataSource = exports.PluginLoader = exports.InteractionVisualizer = exports.setupDonobuStack = exports.prepareToolCallsForRerun = exports.DonobuFlowsManager = exports.distillAllowedEnvVariableNames = exports.DonobuFlow = exports.AdminApiController = exports.env = exports.VercelAiGptClient = exports.OpenAiGptClient = exports.GptClientPluginRegistry = exports.GptClient = exports.GoogleGenerativeAiGptClient = exports.fixAssertFields = exports.DonobuGptClient = exports.AnthropicGptClient = void 0;
|
|
17
|
+
exports.TargetRuntimePluginRegistry = exports.PersistencePluginRegistry = exports.WELL_KNOWN_FILE_IDS = exports.shutdownFileUploadWorkers = exports.getFileUploadAggregateStatus = exports.createDefaultToolRegistry = exports.ToolManager = exports.buildToolInterpolationDataSource = exports.PluginLoader = exports.InteractionVisualizer = exports.setupDonobuStack = exports.prepareToolCallsForRerun = exports.DonobuFlowsManager = exports.distillAllowedEnvVariableNames = exports.DonobuFlow = exports.AdminApiController = exports.env = exports.VercelAiGptClient = exports.OpenAiGptClient = exports.GptClientPluginRegistry = exports.GptClient = exports.GoogleGenerativeAiGptClient = exports.fixAssertFields = exports.DonobuGptClient = exports.AnthropicGptClient = void 0;
|
|
18
18
|
exports.startDonobuServer = startDonobuServer;
|
|
19
19
|
const commander_1 = require("commander");
|
|
20
20
|
const v4_1 = require("zod/v4");
|
|
@@ -94,6 +94,8 @@ __exportStar(require("./models/ToolSchema"), exports);
|
|
|
94
94
|
var fileUploadWorkerRegistry_1 = require("./persistence/files/fileUploadWorkerRegistry");
|
|
95
95
|
Object.defineProperty(exports, "getFileUploadAggregateStatus", { enumerable: true, get: function () { return fileUploadWorkerRegistry_1.getFileUploadAggregateStatus; } });
|
|
96
96
|
Object.defineProperty(exports, "shutdownFileUploadWorkers", { enumerable: true, get: function () { return fileUploadWorkerRegistry_1.shutdownFileUploadWorkers; } });
|
|
97
|
+
var FlowsPersistence_1 = require("./persistence/flows/FlowsPersistence");
|
|
98
|
+
Object.defineProperty(exports, "WELL_KNOWN_FILE_IDS", { enumerable: true, get: function () { return FlowsPersistence_1.WELL_KNOWN_FILE_IDS; } });
|
|
97
99
|
var PersistencePlugin_1 = require("./persistence/PersistencePlugin");
|
|
98
100
|
Object.defineProperty(exports, "PersistencePluginRegistry", { enumerable: true, get: function () { return PersistencePlugin_1.PersistencePluginRegistry; } });
|
|
99
101
|
var TargetRuntimePlugin_1 = require("./targets/TargetRuntimePlugin");
|
|
@@ -49,7 +49,7 @@ export declare class DonobuFlowsManager {
|
|
|
49
49
|
private readonly testsPersistenceRegistry;
|
|
50
50
|
static readonly DEFAULT_MESSAGE_DURATION = 2247;
|
|
51
51
|
static readonly DEFAULT_MAX_TOOL_CALLS = 50;
|
|
52
|
-
static readonly DEFAULT_BROWSER_STATE_FILENAME
|
|
52
|
+
static readonly DEFAULT_BROWSER_STATE_FILENAME: "browserstate.json";
|
|
53
53
|
static readonly FLOW_NAME_MAX_LENGTH = 1024;
|
|
54
54
|
private readonly flowRuntime;
|
|
55
55
|
private readonly flowCatalog;
|
|
@@ -55,6 +55,7 @@ const UnknownToolException_1 = require("../exceptions/UnknownToolException");
|
|
|
55
55
|
const CreateDonobuFlow_1 = require("../models/CreateDonobuFlow");
|
|
56
56
|
const GptConfig_1 = require("../models/GptConfig");
|
|
57
57
|
const MetadataVersion_1 = require("../models/MetadataVersion");
|
|
58
|
+
const FlowsPersistence_1 = require("../persistence/flows/FlowsPersistence");
|
|
58
59
|
const resolveTargetRuntime_1 = require("../targets/resolveTargetRuntime");
|
|
59
60
|
const CustomToolRunnerTool_1 = require("../tools/CustomToolRunnerTool");
|
|
60
61
|
const buildProvenance_1 = require("../utils/buildProvenance");
|
|
@@ -218,7 +219,7 @@ class DonobuFlowsManager {
|
|
|
218
219
|
}
|
|
219
220
|
try {
|
|
220
221
|
const snapshot = logBuffer.snapshot();
|
|
221
|
-
await flowsPersistence.setFlowFile(donobuFlow.metadata.id,
|
|
222
|
+
await flowsPersistence.setFlowFile(donobuFlow.metadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs, Buffer.from(JSON.stringify(snapshot)));
|
|
222
223
|
}
|
|
223
224
|
catch (error) {
|
|
224
225
|
Logger_1.appLogger.error('Failed to persist flow logs:', error);
|
|
@@ -254,7 +255,7 @@ class DonobuFlowsManager {
|
|
|
254
255
|
}
|
|
255
256
|
// Otherwise, read the persisted snapshot.
|
|
256
257
|
const persistence = await this.flowsPersistenceRegistry.get();
|
|
257
|
-
const file = await persistence.getFlowFile(flowId,
|
|
258
|
+
const file = await persistence.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs);
|
|
258
259
|
if (file) {
|
|
259
260
|
return JSON.parse(file.toString('utf8'));
|
|
260
261
|
}
|
|
@@ -757,7 +758,7 @@ DonobuFlowsManager.DEFAULT_MESSAGE_DURATION = 2247;
|
|
|
757
758
|
// If you change this value, also consider changing the frontend default
|
|
758
759
|
// value in createFlowDefaults in flow-types.ts.
|
|
759
760
|
DonobuFlowsManager.DEFAULT_MAX_TOOL_CALLS = 50;
|
|
760
|
-
DonobuFlowsManager.DEFAULT_BROWSER_STATE_FILENAME =
|
|
761
|
+
DonobuFlowsManager.DEFAULT_BROWSER_STATE_FILENAME = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState;
|
|
761
762
|
// Re-exported from models/CreateDonobuFlow so existing callers can keep using
|
|
762
763
|
// DonobuFlowsManager.FLOW_NAME_MAX_LENGTH. The source of truth (and the
|
|
763
764
|
// rationale for keeping it in sync with the donobu-api gateway) lives there.
|
|
@@ -4,6 +4,39 @@ import type { FlowMetadata, FlowsQuery } from '../../models/FlowMetadata';
|
|
|
4
4
|
import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
5
5
|
import type { ToolCall } from '../../models/ToolCall';
|
|
6
6
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
7
|
+
/**
|
|
8
|
+
* Well-known per-flow persistence filenames reserved by Donobu.
|
|
9
|
+
*
|
|
10
|
+
* These names are storage contracts. Avoid reusing them for ad hoc tool
|
|
11
|
+
* artifacts.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WELL_KNOWN_FILE_IDS: {
|
|
14
|
+
/** Full flow video backing {@link FlowsPersistence.setVideo}. */
|
|
15
|
+
readonly video: "video.webm";
|
|
16
|
+
/** Browser storage state backing {@link FlowsPersistence.setBrowserState}. */
|
|
17
|
+
readonly browserState: "browserstate.json";
|
|
18
|
+
/** Structured flow log snapshot consumed by the Studio flow log view. */
|
|
19
|
+
readonly logs: "logs.json";
|
|
20
|
+
/** Playwright test result summary consumed by the Donobu HTML report. */
|
|
21
|
+
readonly donobuTestResult: "donobu-test-result.json";
|
|
22
|
+
/** Generated remediation plan consumed by Studio and admin tooling. */
|
|
23
|
+
readonly treatmentPlan: "treatment-plan.json";
|
|
24
|
+
/** Failure-triage artifacts persisted alongside a test flow. */
|
|
25
|
+
readonly triage: {
|
|
26
|
+
/** Serialized GPT triage evidence and heuristic assessment. */
|
|
27
|
+
readonly evidence: "triage-evidence.json";
|
|
28
|
+
/** Screenshot from the failed run's final page state. */
|
|
29
|
+
readonly failureScreenshot: "triage-failure-screenshot.png";
|
|
30
|
+
/** Screenshot from the latest successful baseline run. */
|
|
31
|
+
readonly baselineScreenshot: "triage-baseline-screenshot.png";
|
|
32
|
+
/**
|
|
33
|
+
* Live final-state screenshot captured at test teardown. Successful runs
|
|
34
|
+
* provide the baseline for later failures; failed runs provide the current
|
|
35
|
+
* failure screenshot.
|
|
36
|
+
*/
|
|
37
|
+
readonly finalStateScreenshot: "triage-final-state-screenshot.png";
|
|
38
|
+
};
|
|
39
|
+
};
|
|
7
40
|
/**
|
|
8
41
|
* Interface for persisting data relating to DonobuFlow runs.
|
|
9
42
|
*/
|
|
@@ -1,3 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WELL_KNOWN_FILE_IDS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Well-known per-flow persistence filenames reserved by Donobu.
|
|
6
|
+
*
|
|
7
|
+
* These names are storage contracts. Avoid reusing them for ad hoc tool
|
|
8
|
+
* artifacts.
|
|
9
|
+
*/
|
|
10
|
+
exports.WELL_KNOWN_FILE_IDS = {
|
|
11
|
+
/** Full flow video backing {@link FlowsPersistence.setVideo}. */
|
|
12
|
+
video: 'video.webm',
|
|
13
|
+
/** Browser storage state backing {@link FlowsPersistence.setBrowserState}. */
|
|
14
|
+
browserState: 'browserstate.json',
|
|
15
|
+
/** Structured flow log snapshot consumed by the Studio flow log view. */
|
|
16
|
+
logs: 'logs.json',
|
|
17
|
+
/** Playwright test result summary consumed by the Donobu HTML report. */
|
|
18
|
+
donobuTestResult: 'donobu-test-result.json',
|
|
19
|
+
/** Generated remediation plan consumed by Studio and admin tooling. */
|
|
20
|
+
treatmentPlan: 'treatment-plan.json',
|
|
21
|
+
/** Failure-triage artifacts persisted alongside a test flow. */
|
|
22
|
+
triage: {
|
|
23
|
+
/** Serialized GPT triage evidence and heuristic assessment. */
|
|
24
|
+
evidence: 'triage-evidence.json',
|
|
25
|
+
/** Screenshot from the failed run's final page state. */
|
|
26
|
+
failureScreenshot: 'triage-failure-screenshot.png',
|
|
27
|
+
/** Screenshot from the latest successful baseline run. */
|
|
28
|
+
baselineScreenshot: 'triage-baseline-screenshot.png',
|
|
29
|
+
/**
|
|
30
|
+
* Live final-state screenshot captured at test teardown. Successful runs
|
|
31
|
+
* provide the baseline for later failures; failed runs provide the current
|
|
32
|
+
* failure screenshot.
|
|
33
|
+
*/
|
|
34
|
+
finalStateScreenshot: 'triage-final-state-screenshot.png',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
3
37
|
//# sourceMappingURL=FlowsPersistence.js.map
|
|
@@ -5,7 +5,7 @@ import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
|
5
5
|
import type { ToolCall } from '../../models/ToolCall';
|
|
6
6
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
7
7
|
import { FileUploadCache } from '../files/FileUploadCache';
|
|
8
|
-
import type
|
|
8
|
+
import { type FlowsPersistence } from './FlowsPersistence';
|
|
9
9
|
/**
|
|
10
10
|
* A {@link FlowsPersistence} implementation that persists flow data via the
|
|
11
11
|
* Donobu API. The API stores the SDK's data models as opaque JSON blobs,
|
|
@@ -14,8 +14,8 @@ const MiscUtils_1 = require("../../utils/MiscUtils");
|
|
|
14
14
|
const FileUploadCache_1 = require("../files/FileUploadCache");
|
|
15
15
|
const FileUploadWorker_1 = require("../files/FileUploadWorker");
|
|
16
16
|
const fileUploadWorkerRegistry_1 = require("../files/fileUploadWorkerRegistry");
|
|
17
|
+
const FlowsPersistence_1 = require("./FlowsPersistence");
|
|
17
18
|
const PLATFORM_LABEL = 'donobu';
|
|
18
|
-
const VIDEO_FILE_ID = 'video.webm';
|
|
19
19
|
/**
|
|
20
20
|
* A {@link FlowsPersistence} implementation that persists flow data via the
|
|
21
21
|
* Donobu API. The API stores the SDK's data models as opaque JSON blobs,
|
|
@@ -205,10 +205,10 @@ class FlowsPersistenceDonobuApi {
|
|
|
205
205
|
}
|
|
206
206
|
// -- Screenshots ---------------------------------------------------
|
|
207
207
|
async setVideo(flowId, bytes) {
|
|
208
|
-
await this.setFlowFile(flowId,
|
|
208
|
+
await this.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video, bytes);
|
|
209
209
|
}
|
|
210
210
|
async getVideoSegment(flowId, startOffset, length) {
|
|
211
|
-
const videoBuffer = await this.getFlowFile(flowId,
|
|
211
|
+
const videoBuffer = await this.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video);
|
|
212
212
|
if (!videoBuffer) {
|
|
213
213
|
return null;
|
|
214
214
|
}
|
|
@@ -5,15 +5,13 @@ import type { FlowMetadata, FlowsQuery } from '../../models/FlowMetadata';
|
|
|
5
5
|
import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
6
6
|
import type { ToolCall } from '../../models/ToolCall';
|
|
7
7
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
8
|
-
import type
|
|
8
|
+
import { type FlowsPersistence } from './FlowsPersistence';
|
|
9
9
|
/**
|
|
10
10
|
* A persistence implementation that uses SQLite for all data storage, including binary files.
|
|
11
11
|
*/
|
|
12
12
|
export declare class FlowsPersistenceSqlite implements FlowsPersistence {
|
|
13
13
|
private readonly db;
|
|
14
14
|
private static readonly VIDEO_MIME_TYPE;
|
|
15
|
-
private static readonly BROWSER_STATE_FILE_ID;
|
|
16
|
-
private static readonly VIDEO_FILE_ID;
|
|
17
15
|
private constructor();
|
|
18
16
|
static create(db: Database.Database): Promise<FlowsPersistenceSqlite>;
|
|
19
17
|
setEnvironmentDatum(key: string, value: string): Promise<void>;
|
|
@@ -7,6 +7,7 @@ const AiQuery_1 = require("../../models/AiQuery");
|
|
|
7
7
|
const BrowserStorageState_1 = require("../../models/BrowserStorageState");
|
|
8
8
|
const MiscUtils_1 = require("../../utils/MiscUtils");
|
|
9
9
|
const normalizeFlowMetadata_1 = require("../normalizeFlowMetadata");
|
|
10
|
+
const FlowsPersistence_1 = require("./FlowsPersistence");
|
|
10
11
|
/**
|
|
11
12
|
* A persistence implementation that uses SQLite for all data storage, including binary files.
|
|
12
13
|
*/
|
|
@@ -221,13 +222,13 @@ class FlowsPersistenceSqlite {
|
|
|
221
222
|
async setVideo(flowId, bytes) {
|
|
222
223
|
// Ensure flow exists.
|
|
223
224
|
await this.getFlowMetadataById(flowId);
|
|
224
|
-
const binaryId = `${flowId}-${
|
|
225
|
+
const binaryId = `${flowId}-${FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video}`;
|
|
225
226
|
const stmt = this.db.prepare('INSERT OR REPLACE INTO binary_files (id, flow_id, file_id, mime_type, content) VALUES (?, ?, ?, ?, ?)');
|
|
226
|
-
stmt.run(binaryId, flowId,
|
|
227
|
+
stmt.run(binaryId, flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video, FlowsPersistenceSqlite.VIDEO_MIME_TYPE, bytes);
|
|
227
228
|
}
|
|
228
229
|
async getVideoSegment(flowId, startOffset, length) {
|
|
229
230
|
const stmt = this.db.prepare('SELECT content FROM binary_files WHERE flow_id = ? AND file_id = ?');
|
|
230
|
-
const row = stmt.get(flowId,
|
|
231
|
+
const row = stmt.get(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video);
|
|
231
232
|
if (!row) {
|
|
232
233
|
return null;
|
|
233
234
|
}
|
|
@@ -261,10 +262,10 @@ class FlowsPersistenceSqlite {
|
|
|
261
262
|
}
|
|
262
263
|
async setBrowserState(flowId, browserState) {
|
|
263
264
|
const serializedBrowserState = Buffer.from(JSON.stringify(browserState), 'utf-8');
|
|
264
|
-
await this.setFlowFile(flowId,
|
|
265
|
+
await this.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState, serializedBrowserState);
|
|
265
266
|
}
|
|
266
267
|
async getBrowserState(flowId) {
|
|
267
|
-
const browserStateRaw = await this.getFlowFile(flowId,
|
|
268
|
+
const browserStateRaw = await this.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState);
|
|
268
269
|
if (browserStateRaw) {
|
|
269
270
|
return BrowserStorageState_1.BrowserStorageStateSchema.parse(JSON.parse(browserStateRaw.toString('utf-8')));
|
|
270
271
|
}
|
|
@@ -284,6 +285,4 @@ class FlowsPersistenceSqlite {
|
|
|
284
285
|
}
|
|
285
286
|
exports.FlowsPersistenceSqlite = FlowsPersistenceSqlite;
|
|
286
287
|
FlowsPersistenceSqlite.VIDEO_MIME_TYPE = 'video/webm';
|
|
287
|
-
FlowsPersistenceSqlite.BROWSER_STATE_FILE_ID = 'browserstate.json';
|
|
288
|
-
FlowsPersistenceSqlite.VIDEO_FILE_ID = 'video.webm';
|
|
289
288
|
//# sourceMappingURL=FlowsPersistenceSqlite.js.map
|
|
@@ -31,6 +31,7 @@ const v4_1 = require("zod/v4");
|
|
|
31
31
|
const envVars_1 = require("../../envVars");
|
|
32
32
|
const DonobuFlowsManager_1 = require("../../managers/DonobuFlowsManager");
|
|
33
33
|
const fileUploadWorkerRegistry_1 = require("../../persistence/files/fileUploadWorkerRegistry");
|
|
34
|
+
const FlowsPersistence_1 = require("../../persistence/flows/FlowsPersistence");
|
|
34
35
|
const ansi_1 = require("../../utils/ansi");
|
|
35
36
|
const BrowserUtils_1 = require("../../utils/BrowserUtils");
|
|
36
37
|
const buildProvenance_1 = require("../../utils/buildProvenance");
|
|
@@ -958,7 +959,7 @@ async function captureAndPersistFinalState(page, testInfo) {
|
|
|
958
959
|
try {
|
|
959
960
|
const screenshot = await (0, triageTestFailure_1.captureLivePageScreenshot)(page);
|
|
960
961
|
if (screenshot) {
|
|
961
|
-
await persistence.setFlowFile(flowId,
|
|
962
|
+
await persistence.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.triage.finalStateScreenshot, screenshot);
|
|
962
963
|
}
|
|
963
964
|
}
|
|
964
965
|
catch (error) {
|
|
@@ -991,11 +992,11 @@ async function finalizeTest(page, testInfo, logBuffer, videoOption) {
|
|
|
991
992
|
// assertion errors with snippets/diffs) so the website can render the
|
|
992
993
|
// report's summary row + error section. Playwright's TestInfoError already
|
|
993
994
|
// carries the code `snippet`, so no source-file access is needed.
|
|
994
|
-
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id,
|
|
995
|
+
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.donobuTestResult, buildDonobuTestResult(testInfo));
|
|
995
996
|
// Persist captured flow logs so they are available in the Donobu UI,
|
|
996
997
|
// mirroring what DonobuFlowsManager does for Studio-launched flows.
|
|
997
998
|
if (logBuffer) {
|
|
998
|
-
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id,
|
|
999
|
+
await persistFlowJson(sharedState.persistence, sharedState.donobuFlowMetadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs, logBuffer.snapshot());
|
|
999
1000
|
}
|
|
1000
1001
|
// Attach step-level screenshots from the flow's tool call history.
|
|
1001
1002
|
// These enable the HTML report to show a visual timeline of what the
|
|
@@ -409,13 +409,6 @@ declare const TRIAGE_PERSISTENCE_FILE_IDS: {
|
|
|
409
409
|
readonly evidence: "triage-evidence.json";
|
|
410
410
|
readonly failureScreenshot: "triage-failure-screenshot.png";
|
|
411
411
|
readonly baselineScreenshot: "triage-baseline-screenshot.png";
|
|
412
|
-
/**
|
|
413
|
-
* Live screenshot of a flow's final visual state, captured at teardown while
|
|
414
|
-
* the page is still open. Persisted on successful runs so that a *later*
|
|
415
|
-
* failing run can use it as a true final-state baseline — symmetric with the
|
|
416
|
-
* failure screenshot, which is also a live end-of-test capture. Keyed per
|
|
417
|
-
* flow, like browser state.
|
|
418
|
-
*/
|
|
419
412
|
readonly finalStateScreenshot: "triage-final-state-screenshot.png";
|
|
420
413
|
};
|
|
421
414
|
/**
|
|
@@ -49,6 +49,7 @@ const fs = __importStar(require("fs/promises"));
|
|
|
49
49
|
const path = __importStar(require("path"));
|
|
50
50
|
const typescript_1 = __importDefault(require("typescript"));
|
|
51
51
|
const v4_1 = require("zod/v4");
|
|
52
|
+
const FlowsPersistence_1 = require("../../../persistence/flows/FlowsPersistence");
|
|
52
53
|
const AnalyzePageTextTool_1 = require("../../../tools/AnalyzePageTextTool");
|
|
53
54
|
const MarkObjectiveCompleteTool_1 = require("../../../tools/MarkObjectiveCompleteTool");
|
|
54
55
|
const MarkObjectiveNotCompletableTool_1 = require("../../../tools/MarkObjectiveNotCompletableTool");
|
|
@@ -329,19 +330,7 @@ const MAX_SERIALIZED_STRING_LENGTH = 10000;
|
|
|
329
330
|
const MAX_TOOL_CALL_PARAMETERS_LENGTH = 500;
|
|
330
331
|
const MAX_TOOL_CALLS_TO_INCLUDE = 12;
|
|
331
332
|
const TRIAGE_EVIDENCE_SCHEMA_VERSION = 2;
|
|
332
|
-
const TRIAGE_PERSISTENCE_FILE_IDS =
|
|
333
|
-
evidence: 'triage-evidence.json',
|
|
334
|
-
failureScreenshot: 'triage-failure-screenshot.png',
|
|
335
|
-
baselineScreenshot: 'triage-baseline-screenshot.png',
|
|
336
|
-
/**
|
|
337
|
-
* Live screenshot of a flow's final visual state, captured at teardown while
|
|
338
|
-
* the page is still open. Persisted on successful runs so that a *later*
|
|
339
|
-
* failing run can use it as a true final-state baseline — symmetric with the
|
|
340
|
-
* failure screenshot, which is also a live end-of-test capture. Keyed per
|
|
341
|
-
* flow, like browser state.
|
|
342
|
-
*/
|
|
343
|
-
finalStateScreenshot: 'triage-final-state-screenshot.png',
|
|
344
|
-
};
|
|
333
|
+
const TRIAGE_PERSISTENCE_FILE_IDS = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.triage;
|
|
345
334
|
exports.TRIAGE_PERSISTENCE_FILE_IDS = TRIAGE_PERSISTENCE_FILE_IDS;
|
|
346
335
|
/**
|
|
347
336
|
* Ensures text blobs captured from tool calls or error messages fit within storage
|
package/dist/main.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export type * from './models/ToolTemplateDataSource';
|
|
|
61
61
|
export type { VideoSegment } from './models/VideoSegment';
|
|
62
62
|
export type { EnvPersistence } from './persistence/env/EnvPersistence';
|
|
63
63
|
export { type FileUploadAggregateStatus, type FileUploadPlatformStatus, getFileUploadAggregateStatus, shutdownFileUploadWorkers, } from './persistence/files/fileUploadWorkerRegistry';
|
|
64
|
-
export type
|
|
64
|
+
export { type FlowsPersistence, WELL_KNOWN_FILE_IDS, } from './persistence/flows/FlowsPersistence';
|
|
65
65
|
export { type PersistencePlugin, PersistencePluginRegistry, } from './persistence/PersistencePlugin';
|
|
66
66
|
export type { SuitesPersistence } from './persistence/suites/SuitesPersistence';
|
|
67
67
|
export type { TestsPersistence } from './persistence/tests/TestsPersistence';
|
package/dist/main.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.TargetRuntimePluginRegistry = exports.PersistencePluginRegistry = exports.shutdownFileUploadWorkers = exports.getFileUploadAggregateStatus = exports.createDefaultToolRegistry = exports.ToolManager = exports.buildToolInterpolationDataSource = exports.PluginLoader = exports.InteractionVisualizer = exports.setupDonobuStack = exports.prepareToolCallsForRerun = exports.DonobuFlowsManager = exports.distillAllowedEnvVariableNames = exports.DonobuFlow = exports.AdminApiController = exports.env = exports.VercelAiGptClient = exports.OpenAiGptClient = exports.GptClientPluginRegistry = exports.GptClient = exports.GoogleGenerativeAiGptClient = exports.fixAssertFields = exports.DonobuGptClient = exports.AnthropicGptClient = void 0;
|
|
17
|
+
exports.TargetRuntimePluginRegistry = exports.PersistencePluginRegistry = exports.WELL_KNOWN_FILE_IDS = exports.shutdownFileUploadWorkers = exports.getFileUploadAggregateStatus = exports.createDefaultToolRegistry = exports.ToolManager = exports.buildToolInterpolationDataSource = exports.PluginLoader = exports.InteractionVisualizer = exports.setupDonobuStack = exports.prepareToolCallsForRerun = exports.DonobuFlowsManager = exports.distillAllowedEnvVariableNames = exports.DonobuFlow = exports.AdminApiController = exports.env = exports.VercelAiGptClient = exports.OpenAiGptClient = exports.GptClientPluginRegistry = exports.GptClient = exports.GoogleGenerativeAiGptClient = exports.fixAssertFields = exports.DonobuGptClient = exports.AnthropicGptClient = void 0;
|
|
18
18
|
exports.startDonobuServer = startDonobuServer;
|
|
19
19
|
const commander_1 = require("commander");
|
|
20
20
|
const v4_1 = require("zod/v4");
|
|
@@ -94,6 +94,8 @@ __exportStar(require("./models/ToolSchema"), exports);
|
|
|
94
94
|
var fileUploadWorkerRegistry_1 = require("./persistence/files/fileUploadWorkerRegistry");
|
|
95
95
|
Object.defineProperty(exports, "getFileUploadAggregateStatus", { enumerable: true, get: function () { return fileUploadWorkerRegistry_1.getFileUploadAggregateStatus; } });
|
|
96
96
|
Object.defineProperty(exports, "shutdownFileUploadWorkers", { enumerable: true, get: function () { return fileUploadWorkerRegistry_1.shutdownFileUploadWorkers; } });
|
|
97
|
+
var FlowsPersistence_1 = require("./persistence/flows/FlowsPersistence");
|
|
98
|
+
Object.defineProperty(exports, "WELL_KNOWN_FILE_IDS", { enumerable: true, get: function () { return FlowsPersistence_1.WELL_KNOWN_FILE_IDS; } });
|
|
97
99
|
var PersistencePlugin_1 = require("./persistence/PersistencePlugin");
|
|
98
100
|
Object.defineProperty(exports, "PersistencePluginRegistry", { enumerable: true, get: function () { return PersistencePlugin_1.PersistencePluginRegistry; } });
|
|
99
101
|
var TargetRuntimePlugin_1 = require("./targets/TargetRuntimePlugin");
|
|
@@ -49,7 +49,7 @@ export declare class DonobuFlowsManager {
|
|
|
49
49
|
private readonly testsPersistenceRegistry;
|
|
50
50
|
static readonly DEFAULT_MESSAGE_DURATION = 2247;
|
|
51
51
|
static readonly DEFAULT_MAX_TOOL_CALLS = 50;
|
|
52
|
-
static readonly DEFAULT_BROWSER_STATE_FILENAME
|
|
52
|
+
static readonly DEFAULT_BROWSER_STATE_FILENAME: "browserstate.json";
|
|
53
53
|
static readonly FLOW_NAME_MAX_LENGTH = 1024;
|
|
54
54
|
private readonly flowRuntime;
|
|
55
55
|
private readonly flowCatalog;
|
|
@@ -55,6 +55,7 @@ const UnknownToolException_1 = require("../exceptions/UnknownToolException");
|
|
|
55
55
|
const CreateDonobuFlow_1 = require("../models/CreateDonobuFlow");
|
|
56
56
|
const GptConfig_1 = require("../models/GptConfig");
|
|
57
57
|
const MetadataVersion_1 = require("../models/MetadataVersion");
|
|
58
|
+
const FlowsPersistence_1 = require("../persistence/flows/FlowsPersistence");
|
|
58
59
|
const resolveTargetRuntime_1 = require("../targets/resolveTargetRuntime");
|
|
59
60
|
const CustomToolRunnerTool_1 = require("../tools/CustomToolRunnerTool");
|
|
60
61
|
const buildProvenance_1 = require("../utils/buildProvenance");
|
|
@@ -218,7 +219,7 @@ class DonobuFlowsManager {
|
|
|
218
219
|
}
|
|
219
220
|
try {
|
|
220
221
|
const snapshot = logBuffer.snapshot();
|
|
221
|
-
await flowsPersistence.setFlowFile(donobuFlow.metadata.id,
|
|
222
|
+
await flowsPersistence.setFlowFile(donobuFlow.metadata.id, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs, Buffer.from(JSON.stringify(snapshot)));
|
|
222
223
|
}
|
|
223
224
|
catch (error) {
|
|
224
225
|
Logger_1.appLogger.error('Failed to persist flow logs:', error);
|
|
@@ -254,7 +255,7 @@ class DonobuFlowsManager {
|
|
|
254
255
|
}
|
|
255
256
|
// Otherwise, read the persisted snapshot.
|
|
256
257
|
const persistence = await this.flowsPersistenceRegistry.get();
|
|
257
|
-
const file = await persistence.getFlowFile(flowId,
|
|
258
|
+
const file = await persistence.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.logs);
|
|
258
259
|
if (file) {
|
|
259
260
|
return JSON.parse(file.toString('utf8'));
|
|
260
261
|
}
|
|
@@ -757,7 +758,7 @@ DonobuFlowsManager.DEFAULT_MESSAGE_DURATION = 2247;
|
|
|
757
758
|
// If you change this value, also consider changing the frontend default
|
|
758
759
|
// value in createFlowDefaults in flow-types.ts.
|
|
759
760
|
DonobuFlowsManager.DEFAULT_MAX_TOOL_CALLS = 50;
|
|
760
|
-
DonobuFlowsManager.DEFAULT_BROWSER_STATE_FILENAME =
|
|
761
|
+
DonobuFlowsManager.DEFAULT_BROWSER_STATE_FILENAME = FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState;
|
|
761
762
|
// Re-exported from models/CreateDonobuFlow so existing callers can keep using
|
|
762
763
|
// DonobuFlowsManager.FLOW_NAME_MAX_LENGTH. The source of truth (and the
|
|
763
764
|
// rationale for keeping it in sync with the donobu-api gateway) lives there.
|
|
@@ -4,6 +4,39 @@ import type { FlowMetadata, FlowsQuery } from '../../models/FlowMetadata';
|
|
|
4
4
|
import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
5
5
|
import type { ToolCall } from '../../models/ToolCall';
|
|
6
6
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
7
|
+
/**
|
|
8
|
+
* Well-known per-flow persistence filenames reserved by Donobu.
|
|
9
|
+
*
|
|
10
|
+
* These names are storage contracts. Avoid reusing them for ad hoc tool
|
|
11
|
+
* artifacts.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WELL_KNOWN_FILE_IDS: {
|
|
14
|
+
/** Full flow video backing {@link FlowsPersistence.setVideo}. */
|
|
15
|
+
readonly video: "video.webm";
|
|
16
|
+
/** Browser storage state backing {@link FlowsPersistence.setBrowserState}. */
|
|
17
|
+
readonly browserState: "browserstate.json";
|
|
18
|
+
/** Structured flow log snapshot consumed by the Studio flow log view. */
|
|
19
|
+
readonly logs: "logs.json";
|
|
20
|
+
/** Playwright test result summary consumed by the Donobu HTML report. */
|
|
21
|
+
readonly donobuTestResult: "donobu-test-result.json";
|
|
22
|
+
/** Generated remediation plan consumed by Studio and admin tooling. */
|
|
23
|
+
readonly treatmentPlan: "treatment-plan.json";
|
|
24
|
+
/** Failure-triage artifacts persisted alongside a test flow. */
|
|
25
|
+
readonly triage: {
|
|
26
|
+
/** Serialized GPT triage evidence and heuristic assessment. */
|
|
27
|
+
readonly evidence: "triage-evidence.json";
|
|
28
|
+
/** Screenshot from the failed run's final page state. */
|
|
29
|
+
readonly failureScreenshot: "triage-failure-screenshot.png";
|
|
30
|
+
/** Screenshot from the latest successful baseline run. */
|
|
31
|
+
readonly baselineScreenshot: "triage-baseline-screenshot.png";
|
|
32
|
+
/**
|
|
33
|
+
* Live final-state screenshot captured at test teardown. Successful runs
|
|
34
|
+
* provide the baseline for later failures; failed runs provide the current
|
|
35
|
+
* failure screenshot.
|
|
36
|
+
*/
|
|
37
|
+
readonly finalStateScreenshot: "triage-final-state-screenshot.png";
|
|
38
|
+
};
|
|
39
|
+
};
|
|
7
40
|
/**
|
|
8
41
|
* Interface for persisting data relating to DonobuFlow runs.
|
|
9
42
|
*/
|
|
@@ -1,3 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WELL_KNOWN_FILE_IDS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Well-known per-flow persistence filenames reserved by Donobu.
|
|
6
|
+
*
|
|
7
|
+
* These names are storage contracts. Avoid reusing them for ad hoc tool
|
|
8
|
+
* artifacts.
|
|
9
|
+
*/
|
|
10
|
+
exports.WELL_KNOWN_FILE_IDS = {
|
|
11
|
+
/** Full flow video backing {@link FlowsPersistence.setVideo}. */
|
|
12
|
+
video: 'video.webm',
|
|
13
|
+
/** Browser storage state backing {@link FlowsPersistence.setBrowserState}. */
|
|
14
|
+
browserState: 'browserstate.json',
|
|
15
|
+
/** Structured flow log snapshot consumed by the Studio flow log view. */
|
|
16
|
+
logs: 'logs.json',
|
|
17
|
+
/** Playwright test result summary consumed by the Donobu HTML report. */
|
|
18
|
+
donobuTestResult: 'donobu-test-result.json',
|
|
19
|
+
/** Generated remediation plan consumed by Studio and admin tooling. */
|
|
20
|
+
treatmentPlan: 'treatment-plan.json',
|
|
21
|
+
/** Failure-triage artifacts persisted alongside a test flow. */
|
|
22
|
+
triage: {
|
|
23
|
+
/** Serialized GPT triage evidence and heuristic assessment. */
|
|
24
|
+
evidence: 'triage-evidence.json',
|
|
25
|
+
/** Screenshot from the failed run's final page state. */
|
|
26
|
+
failureScreenshot: 'triage-failure-screenshot.png',
|
|
27
|
+
/** Screenshot from the latest successful baseline run. */
|
|
28
|
+
baselineScreenshot: 'triage-baseline-screenshot.png',
|
|
29
|
+
/**
|
|
30
|
+
* Live final-state screenshot captured at test teardown. Successful runs
|
|
31
|
+
* provide the baseline for later failures; failed runs provide the current
|
|
32
|
+
* failure screenshot.
|
|
33
|
+
*/
|
|
34
|
+
finalStateScreenshot: 'triage-final-state-screenshot.png',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
3
37
|
//# sourceMappingURL=FlowsPersistence.js.map
|
|
@@ -5,7 +5,7 @@ import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
|
5
5
|
import type { ToolCall } from '../../models/ToolCall';
|
|
6
6
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
7
7
|
import { FileUploadCache } from '../files/FileUploadCache';
|
|
8
|
-
import type
|
|
8
|
+
import { type FlowsPersistence } from './FlowsPersistence';
|
|
9
9
|
/**
|
|
10
10
|
* A {@link FlowsPersistence} implementation that persists flow data via the
|
|
11
11
|
* Donobu API. The API stores the SDK's data models as opaque JSON blobs,
|
|
@@ -14,8 +14,8 @@ const MiscUtils_1 = require("../../utils/MiscUtils");
|
|
|
14
14
|
const FileUploadCache_1 = require("../files/FileUploadCache");
|
|
15
15
|
const FileUploadWorker_1 = require("../files/FileUploadWorker");
|
|
16
16
|
const fileUploadWorkerRegistry_1 = require("../files/fileUploadWorkerRegistry");
|
|
17
|
+
const FlowsPersistence_1 = require("./FlowsPersistence");
|
|
17
18
|
const PLATFORM_LABEL = 'donobu';
|
|
18
|
-
const VIDEO_FILE_ID = 'video.webm';
|
|
19
19
|
/**
|
|
20
20
|
* A {@link FlowsPersistence} implementation that persists flow data via the
|
|
21
21
|
* Donobu API. The API stores the SDK's data models as opaque JSON blobs,
|
|
@@ -205,10 +205,10 @@ class FlowsPersistenceDonobuApi {
|
|
|
205
205
|
}
|
|
206
206
|
// -- Screenshots ---------------------------------------------------
|
|
207
207
|
async setVideo(flowId, bytes) {
|
|
208
|
-
await this.setFlowFile(flowId,
|
|
208
|
+
await this.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video, bytes);
|
|
209
209
|
}
|
|
210
210
|
async getVideoSegment(flowId, startOffset, length) {
|
|
211
|
-
const videoBuffer = await this.getFlowFile(flowId,
|
|
211
|
+
const videoBuffer = await this.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video);
|
|
212
212
|
if (!videoBuffer) {
|
|
213
213
|
return null;
|
|
214
214
|
}
|
|
@@ -5,15 +5,13 @@ import type { FlowMetadata, FlowsQuery } from '../../models/FlowMetadata';
|
|
|
5
5
|
import type { PaginatedResult } from '../../models/PaginatedResult';
|
|
6
6
|
import type { ToolCall } from '../../models/ToolCall';
|
|
7
7
|
import type { VideoSegment } from '../../models/VideoSegment';
|
|
8
|
-
import type
|
|
8
|
+
import { type FlowsPersistence } from './FlowsPersistence';
|
|
9
9
|
/**
|
|
10
10
|
* A persistence implementation that uses SQLite for all data storage, including binary files.
|
|
11
11
|
*/
|
|
12
12
|
export declare class FlowsPersistenceSqlite implements FlowsPersistence {
|
|
13
13
|
private readonly db;
|
|
14
14
|
private static readonly VIDEO_MIME_TYPE;
|
|
15
|
-
private static readonly BROWSER_STATE_FILE_ID;
|
|
16
|
-
private static readonly VIDEO_FILE_ID;
|
|
17
15
|
private constructor();
|
|
18
16
|
static create(db: Database.Database): Promise<FlowsPersistenceSqlite>;
|
|
19
17
|
setEnvironmentDatum(key: string, value: string): Promise<void>;
|
|
@@ -7,6 +7,7 @@ const AiQuery_1 = require("../../models/AiQuery");
|
|
|
7
7
|
const BrowserStorageState_1 = require("../../models/BrowserStorageState");
|
|
8
8
|
const MiscUtils_1 = require("../../utils/MiscUtils");
|
|
9
9
|
const normalizeFlowMetadata_1 = require("../normalizeFlowMetadata");
|
|
10
|
+
const FlowsPersistence_1 = require("./FlowsPersistence");
|
|
10
11
|
/**
|
|
11
12
|
* A persistence implementation that uses SQLite for all data storage, including binary files.
|
|
12
13
|
*/
|
|
@@ -221,13 +222,13 @@ class FlowsPersistenceSqlite {
|
|
|
221
222
|
async setVideo(flowId, bytes) {
|
|
222
223
|
// Ensure flow exists.
|
|
223
224
|
await this.getFlowMetadataById(flowId);
|
|
224
|
-
const binaryId = `${flowId}-${
|
|
225
|
+
const binaryId = `${flowId}-${FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video}`;
|
|
225
226
|
const stmt = this.db.prepare('INSERT OR REPLACE INTO binary_files (id, flow_id, file_id, mime_type, content) VALUES (?, ?, ?, ?, ?)');
|
|
226
|
-
stmt.run(binaryId, flowId,
|
|
227
|
+
stmt.run(binaryId, flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video, FlowsPersistenceSqlite.VIDEO_MIME_TYPE, bytes);
|
|
227
228
|
}
|
|
228
229
|
async getVideoSegment(flowId, startOffset, length) {
|
|
229
230
|
const stmt = this.db.prepare('SELECT content FROM binary_files WHERE flow_id = ? AND file_id = ?');
|
|
230
|
-
const row = stmt.get(flowId,
|
|
231
|
+
const row = stmt.get(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.video);
|
|
231
232
|
if (!row) {
|
|
232
233
|
return null;
|
|
233
234
|
}
|
|
@@ -261,10 +262,10 @@ class FlowsPersistenceSqlite {
|
|
|
261
262
|
}
|
|
262
263
|
async setBrowserState(flowId, browserState) {
|
|
263
264
|
const serializedBrowserState = Buffer.from(JSON.stringify(browserState), 'utf-8');
|
|
264
|
-
await this.setFlowFile(flowId,
|
|
265
|
+
await this.setFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState, serializedBrowserState);
|
|
265
266
|
}
|
|
266
267
|
async getBrowserState(flowId) {
|
|
267
|
-
const browserStateRaw = await this.getFlowFile(flowId,
|
|
268
|
+
const browserStateRaw = await this.getFlowFile(flowId, FlowsPersistence_1.WELL_KNOWN_FILE_IDS.browserState);
|
|
268
269
|
if (browserStateRaw) {
|
|
269
270
|
return BrowserStorageState_1.BrowserStorageStateSchema.parse(JSON.parse(browserStateRaw.toString('utf-8')));
|
|
270
271
|
}
|
|
@@ -284,6 +285,4 @@ class FlowsPersistenceSqlite {
|
|
|
284
285
|
}
|
|
285
286
|
exports.FlowsPersistenceSqlite = FlowsPersistenceSqlite;
|
|
286
287
|
FlowsPersistenceSqlite.VIDEO_MIME_TYPE = 'video/webm';
|
|
287
|
-
FlowsPersistenceSqlite.BROWSER_STATE_FILE_ID = 'browserstate.json';
|
|
288
|
-
FlowsPersistenceSqlite.VIDEO_FILE_ID = 'video.webm';
|
|
289
288
|
//# sourceMappingURL=FlowsPersistenceSqlite.js.map
|