donobu 5.57.0 → 5.60.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 (47) hide show
  1. package/dist/cli/donobu-cli.d.ts +8 -0
  2. package/dist/cli/donobu-cli.js +27 -0
  3. package/dist/codegen/CodeGenerator.js +83 -38
  4. package/dist/codegen/TargetCodeGenerator.d.ts +54 -0
  5. package/dist/codegen/TargetCodeGenerator.js +21 -0
  6. package/dist/esm/cli/donobu-cli.d.ts +8 -0
  7. package/dist/esm/cli/donobu-cli.js +27 -0
  8. package/dist/esm/codegen/CodeGenerator.js +83 -38
  9. package/dist/esm/codegen/TargetCodeGenerator.d.ts +54 -0
  10. package/dist/esm/codegen/TargetCodeGenerator.js +21 -0
  11. package/dist/esm/lib/ai/cache/assertCache.d.ts +14 -1
  12. package/dist/esm/lib/ai/cache/cache.d.ts +12 -4
  13. package/dist/esm/lib/ai/cache/cache.js +40 -24
  14. package/dist/esm/lib/ai/cache/cacheEntryBuilder.d.ts +3 -3
  15. package/dist/esm/lib/ai/cache/cacheEntryBuilder.js +4 -6
  16. package/dist/esm/lib/page/extendPage.js +2 -0
  17. package/dist/esm/lib/test/testExtension.js +7 -0
  18. package/dist/esm/lib/test/utils/selfHealing.js +14 -0
  19. package/dist/esm/main.d.ts +7 -1
  20. package/dist/esm/main.js +7 -1
  21. package/dist/esm/managers/DonobuFlowsManager.js +17 -4
  22. package/dist/esm/managers/DonobuStack.js +9 -0
  23. package/dist/esm/managers/TestsManager.js +5 -0
  24. package/dist/esm/managers/ToolManager.js +11 -0
  25. package/dist/esm/models/CreateDonobuFlow.js +1 -1
  26. package/dist/esm/models/RunConfig.js +1 -1
  27. package/dist/esm/models/ToolTemplateDataSource.d.ts +5 -0
  28. package/dist/esm/targets/TargetRuntimePlugin.d.ts +13 -0
  29. package/dist/lib/ai/cache/assertCache.d.ts +14 -1
  30. package/dist/lib/ai/cache/cache.d.ts +12 -4
  31. package/dist/lib/ai/cache/cache.js +40 -24
  32. package/dist/lib/ai/cache/cacheEntryBuilder.d.ts +3 -3
  33. package/dist/lib/ai/cache/cacheEntryBuilder.js +4 -6
  34. package/dist/lib/page/extendPage.js +2 -0
  35. package/dist/lib/test/testExtension.js +7 -0
  36. package/dist/lib/test/utils/selfHealing.js +14 -0
  37. package/dist/main.d.ts +7 -1
  38. package/dist/main.js +7 -1
  39. package/dist/managers/DonobuFlowsManager.js +17 -4
  40. package/dist/managers/DonobuStack.js +9 -0
  41. package/dist/managers/TestsManager.js +5 -0
  42. package/dist/managers/ToolManager.js +11 -0
  43. package/dist/models/CreateDonobuFlow.js +1 -1
  44. package/dist/models/RunConfig.js +1 -1
  45. package/dist/models/ToolTemplateDataSource.d.ts +5 -0
  46. package/dist/targets/TargetRuntimePlugin.d.ts +13 -0
  47. package/package.json +1 -1
@@ -42,6 +42,7 @@ const fs = __importStar(require("fs/promises"));
42
42
  const os_1 = require("os");
43
43
  const path = __importStar(require("path"));
44
44
  const CodeGenerator_1 = require("../codegen/CodeGenerator");
45
+ const TargetCodeGenerator_1 = require("../codegen/TargetCodeGenerator");
45
46
  const ActiveFlowNotFoundException_1 = require("../exceptions/ActiveFlowNotFoundException");
46
47
  const BrowserStateNotFoundException_1 = require("../exceptions/BrowserStateNotFoundException");
47
48
  const CannotDeleteRunningFlowException_1 = require("../exceptions/CannotDeleteRunningFlowException");
@@ -471,10 +472,22 @@ class DonobuFlowsManager {
471
472
  const originalToolCalls = (await this.getToolCalls(flowId)).filter((tc) => tc.outcome?.isSuccessful);
472
473
  const proposedToolCalls = await prepareToolCallsForRerun(originalToolCalls, effectiveOptions, this.toolRegistry);
473
474
  const scriptVariant = effectiveOptions.playwrightScriptVariant === 'classic' ? 'classic' : 'ai';
474
- if (scriptVariant === 'classic') {
475
- return (0, CodeGenerator_1.getFlowAsPlaywrightScript)(flowMetadata, proposedToolCalls, effectiveOptions, this.toolRegistry);
476
- }
477
- return (0, CodeGenerator_1.getFlowAsAiPlaywrightScript)(flowMetadata, proposedToolCalls, effectiveOptions, this.toolRegistry);
475
+ // Dispatch to the target's code generator (web is built in; plugin targets
476
+ // register their own). A target with no generator (e.g. mobile, which owns
477
+ // its codegen entirely in-plugin) has no spec output via this endpoint.
478
+ const generator = (0, TargetCodeGenerator_1.getCodeGenerator)(flowMetadata.target);
479
+ if (!generator) {
480
+ throw new Error(`Code generation is not supported for target "${flowMetadata.target}".`);
481
+ }
482
+ const ctx = {
483
+ flowMetadata,
484
+ toolCalls: proposedToolCalls,
485
+ options: effectiveOptions,
486
+ toolRegistry: this.toolRegistry,
487
+ };
488
+ return scriptVariant === 'classic'
489
+ ? generator.generateClassicScript(ctx)
490
+ : generator.generateAiScript(ctx);
478
491
  }
479
492
  /**
480
493
  * Generates a complete Playwright project structure for multiple flows with dependency management.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupDonobuStack = setupDonobuStack;
4
4
  const GptClientFactory_1 = require("../clients/GptClientFactory");
5
5
  const GptClientPlugin_1 = require("../clients/GptClientPlugin");
6
+ const TargetCodeGenerator_1 = require("../codegen/TargetCodeGenerator");
6
7
  const envVars_1 = require("../envVars");
7
8
  const AgentsPersistenceSqlite_1 = require("../persistence/agents/AgentsPersistenceSqlite");
8
9
  const DonobuSqliteDb_1 = require("../persistence/DonobuSqliteDb");
@@ -78,6 +79,14 @@ async function loadDefaultPlugins() {
78
79
  const pluginLoader = await PluginLoader_1.PluginLoader.create();
79
80
  const plugins = await pluginLoader.loadAllPlugins();
80
81
  plugins.targetRuntimePlugins.unshift(WebTargetRuntime_1.webTargetRuntimePlugin);
82
+ // Register each target's code generator (if any) so the code generator can
83
+ // emit spec files for plugin targets without knowing about them. The web
84
+ // generator is registered by the code generator module itself.
85
+ for (const plugin of plugins.targetRuntimePlugins) {
86
+ if (plugin.codeGenerator) {
87
+ (0, TargetCodeGenerator_1.registerCodeGenerator)(plugin.codeGenerator);
88
+ }
89
+ }
81
90
  return plugins;
82
91
  }
83
92
  //# sourceMappingURL=DonobuStack.js.map
@@ -23,6 +23,10 @@ class TestsManager {
23
23
  targetWebsite: params.web.targetWebsite,
24
24
  }
25
25
  : undefined;
26
+ const targetConfig = {};
27
+ if (params.target && params.target !== 'web' && params.target in params) {
28
+ targetConfig[params.target] = params[params.target];
29
+ }
26
30
  const testMetadata = {
27
31
  id: testId,
28
32
  metadataVersion: MetadataVersion_1.CURRENT_METADATA_VERSION,
@@ -41,6 +45,7 @@ class TestsManager {
41
45
  videoDisabled: params.videoDisabled,
42
46
  tags: [],
43
47
  provenance: (0, buildProvenance_1.buildProvenance)('DONOBU_STUDIO'),
48
+ ...targetConfig,
44
49
  };
45
50
  // If the test is part of a suite, write it to the same persistence layer
46
51
  // as the suite — otherwise the suite_id foreign key fails (in SQLite)
@@ -173,12 +173,14 @@ exports.ToolManager = ToolManager;
173
173
  function buildToolInterpolationDataSource(envData, previousToolCalls) {
174
174
  const dataSource = {
175
175
  env: envData,
176
+ vars: {},
176
177
  calls: [],
177
178
  };
178
179
  const interpolatedPastToolCalls = [];
179
180
  for (const toolCall of previousToolCalls) {
180
181
  const tempDataSource = {
181
182
  env: envData,
183
+ vars: dataSource.vars,
182
184
  calls: [...interpolatedPastToolCalls],
183
185
  };
184
186
  const processedParameters = (0, TemplateInterpolator_1.interpolateObject)(toolCall.parameters, tempDataSource);
@@ -188,6 +190,15 @@ function buildToolInterpolationDataSource(envData, previousToolCalls) {
188
190
  result: toolCall.outcome.forLlm,
189
191
  });
190
192
  dataSource.calls = [...interpolatedPastToolCalls];
193
+ const variables = toolCall.outcome?.metadata?.variables;
194
+ if (variables &&
195
+ typeof variables === 'object' &&
196
+ !Array.isArray(variables)) {
197
+ dataSource.vars = {
198
+ ...dataSource.vars,
199
+ ...variables,
200
+ };
201
+ }
191
202
  }
192
203
  return dataSource;
193
204
  }
@@ -40,7 +40,7 @@ not need this, omit it and let the SDK mint an ID.`),
40
40
  })
41
41
  .optional()
42
42
  .describe('Web target configuration. Required when target is "web".'),
43
- // Plugin-provided target configurations (e.g. mobile) flow through via
43
+ // Plugin-provided target configurations (e.g. mobile, api) flow through via
44
44
  // .passthrough() and are validated by the corresponding TargetRuntimePlugin.
45
45
  // -- Target-invariant fields --
46
46
  name: v4_1.z
@@ -25,7 +25,7 @@ exports.RunConfigSchema = v4_1.z.looseObject({
25
25
  .string()
26
26
  .describe('The target type (e.g. "web", "mobile"). The value names the key containing the target-specific configuration.'),
27
27
  web: WebTargetConfigSchema.optional().describe('Web target configuration. Present when target is "web".'),
28
- // Plugin-provided target configurations (e.g. mobile) flow through via
28
+ // Plugin-provided target configurations (e.g. mobile, api) flow through via
29
29
  // the loose object behavior and are validated by the corresponding
30
30
  // TargetRuntimePlugin.
31
31
  envVars: v4_1.z
@@ -19,6 +19,11 @@ export type ToolTemplateDataSource = {
19
19
  * The environment variables available to the current Donobu flow.
20
20
  */
21
21
  env: Record<string, string>;
22
+ /**
23
+ * Values published by prior tool calls (via `outcome.metadata.variables`)
24
+ * for reuse in later tool params.
25
+ */
26
+ vars: Record<string, unknown>;
22
27
  /**
23
28
  * The historical tool calls for the current Donobu flow.
24
29
  */
@@ -1,5 +1,6 @@
1
1
  import type { EnvPick } from 'env-struct';
2
2
  import type { BrowserContext } from 'playwright';
3
+ import type { TargetCodeGenerator } from '../codegen/TargetCodeGenerator';
3
4
  import type { env } from '../envVars';
4
5
  import type { InteractionVisualizer } from '../managers/InteractionVisualizer';
5
6
  import type { BrowserStateReference } from '../models/BrowserStateFlowReference';
@@ -77,6 +78,18 @@ export interface TargetRuntimePlugin {
77
78
  * the flow completes or errors.
78
79
  */
79
80
  createRuntime(params: TargetRuntimeParams): Promise<TargetRuntime>;
81
+ /**
82
+ * Optional code generator for this target, registered with the code
83
+ * generator registry at startup. Owns this target's full spec/cache output
84
+ * and is what the unified "flow as code" path dispatches to.
85
+ *
86
+ * Omit when a target doesn't plug into core's codegen — either it produces no
87
+ * replay artifacts, or it owns codegen entirely in-plugin via its own path
88
+ * (e.g. mobile today builds `device.run(...)` cache entries through its own
89
+ * builder and never routes through core). Flows of a target with no
90
+ * registered generator have no output via the unified endpoint.
91
+ */
92
+ readonly codeGenerator?: TargetCodeGenerator;
80
93
  }
81
94
  /**
82
95
  * An immutable registry of target runtime plugins, keyed by target type.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donobu",
3
- "version": "5.57.0",
3
+ "version": "5.60.0",
4
4
  "description": "Create browser automations with an LLM agent and replay them as Playwright scripts.",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/esm/main.js",