donobu 5.31.0 → 5.33.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 (39) hide show
  1. package/dist/esm/lib/page/extendPage.js +2 -0
  2. package/dist/esm/lib/test/testExtension.js +51 -8
  3. package/dist/esm/main.d.ts +2 -0
  4. package/dist/esm/main.js +2 -0
  5. package/dist/esm/managers/AdminApiController.js +4 -1
  6. package/dist/esm/managers/DonobuFlowsManager.js +2 -0
  7. package/dist/esm/managers/SuitesManager.js +2 -0
  8. package/dist/esm/managers/TestsManager.js +2 -0
  9. package/dist/esm/models/FlowMetadata.d.ts +17 -0
  10. package/dist/esm/models/FlowMetadata.js +3 -0
  11. package/dist/esm/models/Provenance.d.ts +43 -0
  12. package/dist/esm/models/Provenance.js +60 -0
  13. package/dist/esm/models/SuiteMetadata.d.ts +17 -0
  14. package/dist/esm/models/SuiteMetadata.js +3 -0
  15. package/dist/esm/models/TestMetadata.d.ts +85 -0
  16. package/dist/esm/models/TestMetadata.js +3 -0
  17. package/dist/esm/reporter/render.js +76 -27
  18. package/dist/esm/utils/buildProvenance.d.ts +3 -0
  19. package/dist/esm/utils/buildProvenance.js +101 -0
  20. package/dist/lib/page/extendPage.js +2 -0
  21. package/dist/lib/test/testExtension.js +51 -8
  22. package/dist/main.d.ts +2 -0
  23. package/dist/main.js +2 -0
  24. package/dist/managers/AdminApiController.js +4 -1
  25. package/dist/managers/DonobuFlowsManager.js +2 -0
  26. package/dist/managers/SuitesManager.js +2 -0
  27. package/dist/managers/TestsManager.js +2 -0
  28. package/dist/models/FlowMetadata.d.ts +17 -0
  29. package/dist/models/FlowMetadata.js +3 -0
  30. package/dist/models/Provenance.d.ts +43 -0
  31. package/dist/models/Provenance.js +60 -0
  32. package/dist/models/SuiteMetadata.d.ts +17 -0
  33. package/dist/models/SuiteMetadata.js +3 -0
  34. package/dist/models/TestMetadata.d.ts +85 -0
  35. package/dist/models/TestMetadata.js +3 -0
  36. package/dist/reporter/render.js +76 -27
  37. package/dist/utils/buildProvenance.d.ts +3 -0
  38. package/dist/utils/buildProvenance.js +101 -0
  39. package/package.json +1 -1
@@ -23,6 +23,7 @@ const GoToWebpageTool_1 = require("../../tools/GoToWebpageTool");
23
23
  const RunAccessibilityTestTool_1 = require("../../tools/RunAccessibilityTestTool");
24
24
  const ansi_1 = require("../../utils/ansi");
25
25
  const BrowserUtils_1 = require("../../utils/BrowserUtils");
26
+ const buildProvenance_1 = require("../../utils/buildProvenance");
26
27
  const Logger_1 = require("../../utils/Logger");
27
28
  const MiscUtils_1 = require("../../utils/MiscUtils");
28
29
  const PlaywrightUtils_1 = require("../../utils/PlaywrightUtils");
@@ -120,6 +121,7 @@ async function extendPage(page, options) {
120
121
  completedAt: null,
121
122
  state: 'RUNNING_ACTION',
122
123
  nextState: null,
124
+ provenance: (0, buildProvenance_1.buildProvenance)('CODE'),
123
125
  },
124
126
  interactionVisualizer: interactionVisualizer,
125
127
  donobuStack: donobuStack,
@@ -33,6 +33,7 @@ const DonobuFlowsManager_1 = require("../../managers/DonobuFlowsManager");
33
33
  const fileUploadWorkerRegistry_1 = require("../../persistence/files/fileUploadWorkerRegistry");
34
34
  const ansi_1 = require("../../utils/ansi");
35
35
  const BrowserUtils_1 = require("../../utils/BrowserUtils");
36
+ const buildProvenance_1 = require("../../utils/buildProvenance");
36
37
  const FlowLogBuffer_1 = require("../../utils/FlowLogBuffer");
37
38
  const Logger_1 = require("../../utils/Logger");
38
39
  const MiscUtils_1 = require("../../utils/MiscUtils");
@@ -450,15 +451,25 @@ exports.test = test_1.test.extend({
450
451
  * 3. `_steps` is fully populated by the time `finalizeTest()` runs (the
451
452
  * test body has already completed).
452
453
  */
453
- function collectNativeSteps(rawSteps) {
454
+ function collectNativeSteps(rawSteps, startTimes) {
454
455
  const result = [];
455
456
  for (const step of rawSteps) {
456
457
  const cat = step.category ?? '';
458
+ const childRaw = Array.isArray(step.steps) ? step.steps : [];
459
+ const collectedChildren = collectNativeSteps(childRaw, startTimes);
457
460
  if (cat === 'expect' || cat === 'test.step') {
461
+ // Start time comes from the onStepBegin payload (captured by the
462
+ // pwApiStepLogger fixture into startTimes). If unavailable, fall
463
+ // back to the step's endWallTime so the window is zero-width and
464
+ // sibling steps don't get falsely nested inside.
465
+ const endWallTime = step.endWallTime ?? Date.now();
466
+ const startWallTime = (typeof step.stepId === 'string' && startTimes.get(step.stepId)) ||
467
+ endWallTime;
458
468
  result.push({
459
469
  title: step.title ?? '',
460
470
  category: cat,
461
- endWallTime: step.endWallTime ?? Date.now(),
471
+ startWallTime,
472
+ endWallTime,
462
473
  passed: !step.error,
463
474
  error: step.error
464
475
  ? { message: step.error.message, stack: step.error.stack }
@@ -470,15 +481,16 @@ function collectNativeSteps(rawSteps) {
470
481
  column: step.location.column ?? 0,
471
482
  }
472
483
  : undefined,
484
+ children: collectedChildren,
473
485
  });
474
486
  }
475
- // Recurse into child steps regardless of parent category so nested
476
- // expect() calls inside test.step() blocks are captured.
477
- if (Array.isArray(step.steps) && step.steps.length > 0) {
478
- result.push(...collectNativeSteps(step.steps));
487
+ else {
488
+ // Parent is not a kept category (e.g. pw:api) promote any qualifying
489
+ // descendants so a nested expect() still appears in the report.
490
+ result.push(...collectedChildren);
479
491
  }
480
492
  }
481
- result.sort((a, b) => a.endWallTime - b.endWallTime);
493
+ result.sort((a, b) => a.startWallTime - b.startWallTime);
482
494
  return result;
483
495
  }
484
496
  // ---------------------------------------------------------------------------
@@ -688,9 +700,20 @@ function installPlaywrightStepLogger(testInfo) {
688
700
  const originalOnStepEnd = callbacks && typeof callbacks.onStepEnd === 'function'
689
701
  ? callbacks.onStepEnd
690
702
  : null;
703
+ const originalOnStepBegin = callbacks && typeof callbacks.onStepBegin === 'function'
704
+ ? callbacks.onStepBegin
705
+ : null;
691
706
  if (!callbacks || !originalOnStepEnd || !stepMap) {
692
707
  return () => { };
693
708
  }
709
+ // Stash a stepId -> wallTime map on testInfo so collectNativeSteps can
710
+ // look up start times when building the report hierarchy. Playwright
711
+ // doesn't store wallTime on the step object itself — it's only emitted
712
+ // via the onStepBegin payload — so we capture it here. Without this,
713
+ // `test.step` blocks have no recoverable start time and any preceding
714
+ // tool-call step gets falsely nested inside them.
715
+ const startTimes = new Map();
716
+ ti.__donobuStepStartTimes = startTimes;
694
717
  let installed = false;
695
718
  try {
696
719
  callbacks.onStepEnd = function patchedOnStepEnd(payload) {
@@ -709,6 +732,21 @@ function installPlaywrightStepLogger(testInfo) {
709
732
  }
710
733
  return ret;
711
734
  };
735
+ callbacks.onStepBegin = function patchedOnStepBegin(payload) {
736
+ const ret = originalOnStepBegin
737
+ ? originalOnStepBegin.call(this, payload)
738
+ : undefined;
739
+ try {
740
+ if (typeof payload?.stepId === 'string' &&
741
+ typeof payload?.wallTime === 'number') {
742
+ startTimes.set(payload.stepId, payload.wallTime);
743
+ }
744
+ }
745
+ catch (err) {
746
+ Logger_1.appLogger.debug('Failed to record Playwright step start time', err);
747
+ }
748
+ return ret;
749
+ };
712
750
  installed = true;
713
751
  }
714
752
  catch (err) {
@@ -717,6 +755,9 @@ function installPlaywrightStepLogger(testInfo) {
717
755
  return () => {
718
756
  if (installed) {
719
757
  callbacks.onStepEnd = originalOnStepEnd;
758
+ if (originalOnStepBegin) {
759
+ callbacks.onStepBegin = originalOnStepBegin;
760
+ }
720
761
  }
721
762
  };
722
763
  }
@@ -824,7 +865,8 @@ async function finalizeTest(page, testInfo, logBuffer, videoOption) {
824
865
  // Attach native Playwright steps (expect assertions, test.step blocks)
825
866
  // so the HTML report can show a unified timeline alongside AI tool calls.
826
867
  try {
827
- const nativeSteps = collectNativeSteps(testInfo._steps ?? []);
868
+ const startTimes = testInfo.__donobuStepStartTimes ?? new Map();
869
+ const nativeSteps = collectNativeSteps(testInfo._steps ?? [], startTimes);
828
870
  if (nativeSteps.length > 0) {
829
871
  await testInfo.attach('donobu-native-steps', {
830
872
  body: JSON.stringify(nativeSteps),
@@ -945,6 +987,7 @@ function flowMetadataToTestMetadata(testId, flowMeta) {
945
987
  maxToolCalls: flowMeta.maxToolCalls,
946
988
  suiteId: null,
947
989
  nextRunMode: 'DETERMINISTIC',
990
+ provenance: (0, buildProvenance_1.buildProvenance)('CODE'),
948
991
  };
949
992
  }
950
993
  //# sourceMappingURL=testExtension.js.map
@@ -44,6 +44,7 @@ export type * from './models/GptMessage';
44
44
  export * from './models/InteractableElement';
45
45
  export type { PaginatedResult } from './models/PaginatedResult';
46
46
  export * from './models/ProposedToolCall';
47
+ export * from './models/Provenance';
47
48
  export * from './models/RunConfig';
48
49
  export * from './models/SuiteMetadata';
49
50
  export * from './models/TargetConfig';
@@ -63,6 +64,7 @@ export type { TargetRuntime } from './targets/TargetRuntime';
63
64
  export { type TargetRuntimeParams, type TargetRuntimePlugin, TargetRuntimePluginRegistry, } from './targets/TargetRuntimePlugin';
64
65
  export * from './tools/ReplayableInteraction';
65
66
  export * from './tools/Tool';
67
+ export * from './utils/buildProvenance';
66
68
  export * from './utils/createTool';
67
69
  export * from './utils/FlowLogBuffer';
68
70
  export * from './utils/JsonSchemaUtils';
package/dist/esm/main.js CHANGED
@@ -82,6 +82,7 @@ __exportStar(require("./models/CreateDonobuFlow"), exports);
82
82
  __exportStar(require("./models/FlowMetadata"), exports);
83
83
  __exportStar(require("./models/InteractableElement"), exports);
84
84
  __exportStar(require("./models/ProposedToolCall"), exports);
85
+ __exportStar(require("./models/Provenance"), exports);
85
86
  __exportStar(require("./models/RunConfig"), exports);
86
87
  __exportStar(require("./models/SuiteMetadata"), exports);
87
88
  __exportStar(require("./models/TargetConfig"), exports);
@@ -97,6 +98,7 @@ var TargetRuntimePlugin_1 = require("./targets/TargetRuntimePlugin");
97
98
  Object.defineProperty(exports, "TargetRuntimePluginRegistry", { enumerable: true, get: function () { return TargetRuntimePlugin_1.TargetRuntimePluginRegistry; } });
98
99
  __exportStar(require("./tools/ReplayableInteraction"), exports);
99
100
  __exportStar(require("./tools/Tool"), exports);
101
+ __exportStar(require("./utils/buildProvenance"), exports);
100
102
  __exportStar(require("./utils/createTool"), exports);
101
103
  __exportStar(require("./utils/FlowLogBuffer"), exports);
102
104
  __exportStar(require("./utils/JsonSchemaUtils"), exports);
@@ -185,7 +185,10 @@ class AdminApiController {
185
185
  const start = performance.now();
186
186
  res.on('finish', () => {
187
187
  const duration = Math.round(performance.now() - start);
188
- const logLevel = req.path === '/api/ping' ? 'debug' : 'info';
188
+ // Turn down the log noise for the endpoints polled by the frontend.
189
+ const logLevel = req.path === '/api/ping' || req.path === '/api/uploads/status'
190
+ ? 'debug'
191
+ : 'info';
189
192
  Logger_1.accessLogger[logLevel](`${req.method} | ${req.path} | ${res.statusCode} | ${duration}ms`);
190
193
  });
191
194
  next();
@@ -52,6 +52,7 @@ const UnknownToolException_1 = require("../exceptions/UnknownToolException");
52
52
  const GptConfig_1 = require("../models/GptConfig");
53
53
  const resolveTargetRuntime_1 = require("../targets/resolveTargetRuntime");
54
54
  const CustomToolRunnerTool_1 = require("../tools/CustomToolRunnerTool");
55
+ const buildProvenance_1 = require("../utils/buildProvenance");
55
56
  const displayName_1 = require("../utils/displayName");
56
57
  const FlowLogBuffer_1 = require("../utils/FlowLogBuffer");
57
58
  const Logger_1 = require("../utils/Logger");
@@ -176,6 +177,7 @@ class DonobuFlowsManager {
176
177
  testId: flowParams.testId ?? null,
177
178
  // Target-specific fields (browser, targetWebsite, isControlPanelEnabled, etc.)
178
179
  ...targetRuntime.getMetadataFields(),
180
+ provenance: (0, buildProvenance_1.buildProvenance)('DONOBU_STUDIO'),
179
181
  };
180
182
  const flowsPersistence = await this.flowsPersistenceRegistry.get();
181
183
  const envData = await this.envDataManager.getByNames(flowMetadata.envVars ?? []);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SuitesManager = void 0;
4
4
  const crypto_1 = require("crypto");
5
5
  const SuiteNotFoundException_1 = require("../exceptions/SuiteNotFoundException");
6
+ const buildProvenance_1 = require("../utils/buildProvenance");
6
7
  const FederatedPagination_1 = require("./FederatedPagination");
7
8
  class SuitesManager {
8
9
  constructor(suitesPersistenceRegistry, testsPersistenceRegistry) {
@@ -30,6 +31,7 @@ class SuitesManager {
30
31
  resultJsonSchema: params.resultJsonSchema ?? null,
31
32
  maxToolCalls: params.maxToolCalls ?? null,
32
33
  videoDisabled: params.videoDisabled,
34
+ provenance: (0, buildProvenance_1.buildProvenance)('DONOBU_STUDIO'),
33
35
  };
34
36
  // Create in the primary persistence layer only.
35
37
  const primary = await this.suitesPersistenceRegistry.get();
@@ -4,6 +4,7 @@ exports.TestsManager = void 0;
4
4
  const crypto_1 = require("crypto");
5
5
  const CannotDeleteRunningFlowException_1 = require("../exceptions/CannotDeleteRunningFlowException");
6
6
  const TestNotFoundException_1 = require("../exceptions/TestNotFoundException");
7
+ const buildProvenance_1 = require("../utils/buildProvenance");
7
8
  const displayName_1 = require("../utils/displayName");
8
9
  const FederatedPagination_1 = require("./FederatedPagination");
9
10
  class TestsManager {
@@ -35,6 +36,7 @@ class TestsManager {
35
36
  resultJsonSchema: params.resultJsonSchema ?? null,
36
37
  maxToolCalls: params.maxToolCalls ?? null,
37
38
  videoDisabled: params.videoDisabled,
39
+ provenance: (0, buildProvenance_1.buildProvenance)('DONOBU_STUDIO'),
38
40
  };
39
41
  // Create in the primary persistence layer only.
40
42
  const primary = await this.testsPersistenceRegistry.get();
@@ -181,6 +181,23 @@ export declare const FlowMetadataSchema: z.ZodObject<{
181
181
  FAILED: "FAILED";
182
182
  SUCCESS: "SUCCESS";
183
183
  }>>;
184
+ provenance: z.ZodOptional<z.ZodObject<{
185
+ source: z.ZodEnum<{
186
+ DONOBU_STUDIO: "DONOBU_STUDIO";
187
+ CODE: "CODE";
188
+ }>;
189
+ user: z.ZodOptional<z.ZodString>;
190
+ os: z.ZodOptional<z.ZodString>;
191
+ hostname: z.ZodOptional<z.ZodString>;
192
+ ci: z.ZodOptional<z.ZodObject<{
193
+ provider: z.ZodOptional<z.ZodString>;
194
+ }, z.core.$loose>>;
195
+ git: z.ZodOptional<z.ZodObject<{
196
+ sha: z.ZodOptional<z.ZodString>;
197
+ branch: z.ZodOptional<z.ZodString>;
198
+ dirty: z.ZodOptional<z.ZodBoolean>;
199
+ }, z.core.$loose>>;
200
+ }, z.core.$loose>>;
184
201
  }, z.core.$loose>;
185
202
  export type FlowMetadata = z.infer<typeof FlowMetadataSchema>;
186
203
  /**
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isComplete = exports.FlowsQuerySchema = exports.FlowMetadataSchema = exports.StateSchema = void 0;
4
4
  const v4_1 = require("zod/v4");
5
+ const Provenance_1 = require("./Provenance");
5
6
  const RunConfig_1 = require("./RunConfig");
6
7
  const RunMode_1 = require("./RunMode");
7
8
  const SortOrder_1 = require("./SortOrder");
@@ -87,6 +88,8 @@ depends on how the flow completes:
87
88
  .describe('The Unix epoch millisecond timestamp of when the flow completed.'),
88
89
  state: exports.StateSchema.describe('The current state of the flow.'),
89
90
  nextState: exports.StateSchema.nullable().describe('The planned next state of the flow.'),
91
+ provenance: Provenance_1.ProvenanceSchema.optional().describe('Records how this flow came into existence (Studio vs. code-first). ' +
92
+ 'Absent on rows written before provenance tracking was introduced.'),
90
93
  });
91
94
  const FlowSortBySchema = v4_1.z.enum(['created_at', 'name', 'run_mode', 'state']);
92
95
  /**
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod/v4';
2
+ export declare const ProvenanceSourceSchema: z.ZodEnum<{
3
+ DONOBU_STUDIO: "DONOBU_STUDIO";
4
+ CODE: "CODE";
5
+ }>;
6
+ export type ProvenanceSource = z.infer<typeof ProvenanceSourceSchema>;
7
+ export declare const GitProvenanceSchema: z.ZodObject<{
8
+ sha: z.ZodOptional<z.ZodString>;
9
+ branch: z.ZodOptional<z.ZodString>;
10
+ dirty: z.ZodOptional<z.ZodBoolean>;
11
+ }, z.core.$loose>;
12
+ export type GitProvenance = z.infer<typeof GitProvenanceSchema>;
13
+ export declare const CiProvenanceSchema: z.ZodObject<{
14
+ provider: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$loose>;
16
+ export type CiProvenance = z.infer<typeof CiProvenanceSchema>;
17
+ /**
18
+ * Provenance — records *how* a Suite/Test/Flow came into existence so downstream
19
+ * code can render origin badges and gate operations that aren't safe across run
20
+ * modes (e.g. running a CODE-created test from Studio).
21
+ *
22
+ * `.loose()` so newer SDKs can write extra provenance fields without breaking
23
+ * older readers that round-trip the metadata blob.
24
+ */
25
+ export declare const ProvenanceSchema: z.ZodObject<{
26
+ source: z.ZodEnum<{
27
+ DONOBU_STUDIO: "DONOBU_STUDIO";
28
+ CODE: "CODE";
29
+ }>;
30
+ user: z.ZodOptional<z.ZodString>;
31
+ os: z.ZodOptional<z.ZodString>;
32
+ hostname: z.ZodOptional<z.ZodString>;
33
+ ci: z.ZodOptional<z.ZodObject<{
34
+ provider: z.ZodOptional<z.ZodString>;
35
+ }, z.core.$loose>>;
36
+ git: z.ZodOptional<z.ZodObject<{
37
+ sha: z.ZodOptional<z.ZodString>;
38
+ branch: z.ZodOptional<z.ZodString>;
39
+ dirty: z.ZodOptional<z.ZodBoolean>;
40
+ }, z.core.$loose>>;
41
+ }, z.core.$loose>;
42
+ export type Provenance = z.infer<typeof ProvenanceSchema>;
43
+ //# sourceMappingURL=Provenance.d.ts.map
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProvenanceSchema = exports.CiProvenanceSchema = exports.GitProvenanceSchema = exports.ProvenanceSourceSchema = void 0;
4
+ const v4_1 = require("zod/v4");
5
+ exports.ProvenanceSourceSchema = v4_1.z.enum(['DONOBU_STUDIO', 'CODE']);
6
+ exports.GitProvenanceSchema = v4_1.z
7
+ .object({
8
+ sha: v4_1.z.string().optional().describe('The git commit SHA at HEAD.'),
9
+ branch: v4_1.z
10
+ .string()
11
+ .optional()
12
+ .describe('The git branch at HEAD; absent in detached-HEAD state.'),
13
+ dirty: v4_1.z
14
+ .boolean()
15
+ .optional()
16
+ .describe('True if the working tree had uncommitted changes.'),
17
+ })
18
+ .loose();
19
+ exports.CiProvenanceSchema = v4_1.z
20
+ .object({
21
+ provider: v4_1.z
22
+ .string()
23
+ .optional()
24
+ .describe('The CI provider name when identified (e.g. "github", "gitlab", "circle"); ' +
25
+ 'absent when only a generic CI=true marker was present.'),
26
+ })
27
+ .loose();
28
+ /**
29
+ * Provenance — records *how* a Suite/Test/Flow came into existence so downstream
30
+ * code can render origin badges and gate operations that aren't safe across run
31
+ * modes (e.g. running a CODE-created test from Studio).
32
+ *
33
+ * `.loose()` so newer SDKs can write extra provenance fields without breaking
34
+ * older readers that round-trip the metadata blob.
35
+ */
36
+ exports.ProvenanceSchema = v4_1.z
37
+ .object({
38
+ source: exports.ProvenanceSourceSchema.describe('The run mode that created this entity. ' +
39
+ 'DONOBU_STUDIO = created via the Studio desktop app (HTTP API → managers); ' +
40
+ "CODE = created via a code-first SDK fixture (e.g. `donobu`'s `test` " +
41
+ "or `donobu-mobile`'s `mobileTest`)."),
42
+ user: v4_1.z
43
+ .string()
44
+ .optional()
45
+ .describe('The OS username under which the entity was created.'),
46
+ os: v4_1.z
47
+ .string()
48
+ .optional()
49
+ .describe('The OS platform (e.g. "darwin", "linux", "win32").'),
50
+ hostname: v4_1.z
51
+ .string()
52
+ .optional()
53
+ .describe('The hostname of the machine that created this entity.'),
54
+ ci: exports.CiProvenanceSchema.optional().describe('CI context when creation happened in a CI environment. Absent when ' +
55
+ 'no CI markers were detected.'),
56
+ git: exports.GitProvenanceSchema.optional().describe('Git working-tree context at creation time. Absent when the CWD is ' +
57
+ 'not a git repo or `git` is unavailable.'),
58
+ })
59
+ .loose();
60
+ //# sourceMappingURL=Provenance.js.map
@@ -140,6 +140,23 @@ export declare const SuiteMetadataSchema: z.ZodObject<{
140
140
  metadataVersion: z.ZodOptional<z.ZodNumber>;
141
141
  name: z.ZodString;
142
142
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
143
+ provenance: z.ZodOptional<z.ZodObject<{
144
+ source: z.ZodEnum<{
145
+ DONOBU_STUDIO: "DONOBU_STUDIO";
146
+ CODE: "CODE";
147
+ }>;
148
+ user: z.ZodOptional<z.ZodString>;
149
+ os: z.ZodOptional<z.ZodString>;
150
+ hostname: z.ZodOptional<z.ZodString>;
151
+ ci: z.ZodOptional<z.ZodObject<{
152
+ provider: z.ZodOptional<z.ZodString>;
153
+ }, z.core.$loose>>;
154
+ git: z.ZodOptional<z.ZodObject<{
155
+ sha: z.ZodOptional<z.ZodString>;
156
+ branch: z.ZodOptional<z.ZodString>;
157
+ dirty: z.ZodOptional<z.ZodBoolean>;
158
+ }, z.core.$loose>>;
159
+ }, z.core.$loose>>;
143
160
  }, z.core.$loose>;
144
161
  export type SuiteMetadata = z.infer<typeof SuiteMetadataSchema>;
145
162
  /**
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SuitesQuerySchema = exports.SuiteMetadataSchema = void 0;
4
4
  const v4_1 = require("zod/v4");
5
+ const Provenance_1 = require("./Provenance");
5
6
  const RunConfig_1 = require("./RunConfig");
6
7
  const SortOrder_1 = require("./SortOrder");
7
8
  /**
@@ -24,6 +25,8 @@ exports.SuiteMetadataSchema = RunConfig_1.RunConfigSchema.partial().extend({
24
25
  .nullable()
25
26
  .optional()
26
27
  .describe('An optional description of the suite.'),
28
+ provenance: Provenance_1.ProvenanceSchema.optional().describe('Records how this suite came into existence (Studio vs. code-first). ' +
29
+ 'Absent on rows written before provenance tracking was introduced.'),
27
30
  });
28
31
  const SuiteSortBySchema = v4_1.z.enum(['created_at', 'name']);
29
32
  /**
@@ -143,6 +143,23 @@ export declare const TestMetadataSchema: z.ZodObject<{
143
143
  INSTRUCT: "INSTRUCT";
144
144
  DETERMINISTIC: "DETERMINISTIC";
145
145
  }>;
146
+ provenance: z.ZodOptional<z.ZodObject<{
147
+ source: z.ZodEnum<{
148
+ DONOBU_STUDIO: "DONOBU_STUDIO";
149
+ CODE: "CODE";
150
+ }>;
151
+ user: z.ZodOptional<z.ZodString>;
152
+ os: z.ZodOptional<z.ZodString>;
153
+ hostname: z.ZodOptional<z.ZodString>;
154
+ ci: z.ZodOptional<z.ZodObject<{
155
+ provider: z.ZodOptional<z.ZodString>;
156
+ }, z.core.$loose>>;
157
+ git: z.ZodOptional<z.ZodObject<{
158
+ sha: z.ZodOptional<z.ZodString>;
159
+ branch: z.ZodOptional<z.ZodString>;
160
+ dirty: z.ZodOptional<z.ZodBoolean>;
161
+ }, z.core.$loose>>;
162
+ }, z.core.$loose>>;
146
163
  }, z.core.$loose>;
147
164
  export type TestMetadata = z.infer<typeof TestMetadataSchema>;
148
165
  /**
@@ -307,6 +324,23 @@ export declare const TestListItemSchema: z.ZodObject<{
307
324
  INSTRUCT: "INSTRUCT";
308
325
  DETERMINISTIC: "DETERMINISTIC";
309
326
  }>;
327
+ provenance: z.ZodOptional<z.ZodObject<{
328
+ source: z.ZodEnum<{
329
+ DONOBU_STUDIO: "DONOBU_STUDIO";
330
+ CODE: "CODE";
331
+ }>;
332
+ user: z.ZodOptional<z.ZodString>;
333
+ os: z.ZodOptional<z.ZodString>;
334
+ hostname: z.ZodOptional<z.ZodString>;
335
+ ci: z.ZodOptional<z.ZodObject<{
336
+ provider: z.ZodOptional<z.ZodString>;
337
+ }, z.core.$loose>>;
338
+ git: z.ZodOptional<z.ZodObject<{
339
+ sha: z.ZodOptional<z.ZodString>;
340
+ branch: z.ZodOptional<z.ZodString>;
341
+ dirty: z.ZodOptional<z.ZodBoolean>;
342
+ }, z.core.$loose>>;
343
+ }, z.core.$loose>>;
310
344
  flowCount: z.ZodNumber;
311
345
  latestFlow: z.ZodNullable<z.ZodObject<{
312
346
  target: z.ZodString;
@@ -478,6 +512,23 @@ export declare const TestListItemSchema: z.ZodObject<{
478
512
  FAILED: "FAILED";
479
513
  SUCCESS: "SUCCESS";
480
514
  }>>;
515
+ provenance: z.ZodOptional<z.ZodObject<{
516
+ source: z.ZodEnum<{
517
+ DONOBU_STUDIO: "DONOBU_STUDIO";
518
+ CODE: "CODE";
519
+ }>;
520
+ user: z.ZodOptional<z.ZodString>;
521
+ os: z.ZodOptional<z.ZodString>;
522
+ hostname: z.ZodOptional<z.ZodString>;
523
+ ci: z.ZodOptional<z.ZodObject<{
524
+ provider: z.ZodOptional<z.ZodString>;
525
+ }, z.core.$loose>>;
526
+ git: z.ZodOptional<z.ZodObject<{
527
+ sha: z.ZodOptional<z.ZodString>;
528
+ branch: z.ZodOptional<z.ZodString>;
529
+ dirty: z.ZodOptional<z.ZodBoolean>;
530
+ }, z.core.$loose>>;
531
+ }, z.core.$loose>>;
481
532
  }, z.core.$loose>>;
482
533
  }, z.core.$loose>;
483
534
  export type TestListItem = z.infer<typeof TestListItemSchema>;
@@ -621,6 +672,23 @@ export declare const TestListItemPaginatedResultSchema: z.ZodObject<{
621
672
  INSTRUCT: "INSTRUCT";
622
673
  DETERMINISTIC: "DETERMINISTIC";
623
674
  }>;
675
+ provenance: z.ZodOptional<z.ZodObject<{
676
+ source: z.ZodEnum<{
677
+ DONOBU_STUDIO: "DONOBU_STUDIO";
678
+ CODE: "CODE";
679
+ }>;
680
+ user: z.ZodOptional<z.ZodString>;
681
+ os: z.ZodOptional<z.ZodString>;
682
+ hostname: z.ZodOptional<z.ZodString>;
683
+ ci: z.ZodOptional<z.ZodObject<{
684
+ provider: z.ZodOptional<z.ZodString>;
685
+ }, z.core.$loose>>;
686
+ git: z.ZodOptional<z.ZodObject<{
687
+ sha: z.ZodOptional<z.ZodString>;
688
+ branch: z.ZodOptional<z.ZodString>;
689
+ dirty: z.ZodOptional<z.ZodBoolean>;
690
+ }, z.core.$loose>>;
691
+ }, z.core.$loose>>;
624
692
  flowCount: z.ZodNumber;
625
693
  latestFlow: z.ZodNullable<z.ZodObject<{
626
694
  target: z.ZodString;
@@ -792,6 +860,23 @@ export declare const TestListItemPaginatedResultSchema: z.ZodObject<{
792
860
  FAILED: "FAILED";
793
861
  SUCCESS: "SUCCESS";
794
862
  }>>;
863
+ provenance: z.ZodOptional<z.ZodObject<{
864
+ source: z.ZodEnum<{
865
+ DONOBU_STUDIO: "DONOBU_STUDIO";
866
+ CODE: "CODE";
867
+ }>;
868
+ user: z.ZodOptional<z.ZodString>;
869
+ os: z.ZodOptional<z.ZodString>;
870
+ hostname: z.ZodOptional<z.ZodString>;
871
+ ci: z.ZodOptional<z.ZodObject<{
872
+ provider: z.ZodOptional<z.ZodString>;
873
+ }, z.core.$loose>>;
874
+ git: z.ZodOptional<z.ZodObject<{
875
+ sha: z.ZodOptional<z.ZodString>;
876
+ branch: z.ZodOptional<z.ZodString>;
877
+ dirty: z.ZodOptional<z.ZodBoolean>;
878
+ }, z.core.$loose>>;
879
+ }, z.core.$loose>>;
795
880
  }, z.core.$loose>>;
796
881
  }, z.core.$loose>>;
797
882
  nextPageToken: z.ZodOptional<z.ZodString>;
@@ -4,6 +4,7 @@ exports.TestListItemPaginatedResultSchema = exports.TestListItemSchema = exports
4
4
  const v4_1 = require("zod/v4");
5
5
  const FlowMetadata_1 = require("./FlowMetadata");
6
6
  const PaginatedResult_1 = require("./PaginatedResult");
7
+ const Provenance_1 = require("./Provenance");
7
8
  const RunConfig_1 = require("./RunConfig");
8
9
  const RunMode_1 = require("./RunMode");
9
10
  const SortOrder_1 = require("./SortOrder");
@@ -28,6 +29,8 @@ exports.TestMetadataSchema = RunConfig_1.RunConfigSchema.extend({
28
29
  .nullable()
29
30
  .describe('The ID of the suite this test belongs to, or null if the test has not been added to a test suite (or was orphaned when the suite was deleted).'),
30
31
  nextRunMode: RunMode_1.RunModeSchema.describe('The run mode to use when creating the next flow from this test.'),
32
+ provenance: Provenance_1.ProvenanceSchema.optional().describe('Records how this test came into existence (Studio vs. code-first). ' +
33
+ 'Absent on rows written before provenance tracking was introduced.'),
31
34
  });
32
35
  const TestSortBySchema = v4_1.z.enum([
33
36
  'created_at',