donobu 5.40.0 → 5.41.1

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 (49) hide show
  1. package/dist/cli/donobu-cli.js +142 -163
  2. package/dist/envVars.d.ts +2 -0
  3. package/dist/envVars.js +12 -0
  4. package/dist/esm/cli/donobu-cli.js +142 -163
  5. package/dist/esm/envVars.d.ts +2 -0
  6. package/dist/esm/envVars.js +12 -0
  7. package/dist/esm/lib/test/utils/donobuTestStack.js +1 -1
  8. package/dist/esm/main.d.ts +2 -1
  9. package/dist/esm/main.js +2 -4
  10. package/dist/esm/managers/AdminApiController.d.ts +1 -1
  11. package/dist/esm/managers/DonobuStack.d.ts +2 -0
  12. package/dist/esm/managers/DonobuStack.js +1 -1
  13. package/dist/esm/managers/TestsManager.js +5 -2
  14. package/dist/esm/persistence/DonobuApiClient.js +1 -1
  15. package/dist/esm/persistence/flows/FlowsPersistenceRegistry.d.ts +1 -1
  16. package/dist/esm/persistence/flows/FlowsPersistenceRegistry.js +7 -1
  17. package/dist/esm/persistence/suites/SuitesPersistenceRegistry.d.ts +1 -1
  18. package/dist/esm/persistence/suites/SuitesPersistenceRegistry.js +7 -1
  19. package/dist/esm/persistence/tests/TestsPersistenceDonobuApi.js +3 -0
  20. package/dist/esm/persistence/tests/TestsPersistenceRegistry.d.ts +1 -1
  21. package/dist/esm/persistence/tests/TestsPersistenceRegistry.js +7 -1
  22. package/dist/esm/persistence/tests/TestsPersistenceSqlite.js +4 -1
  23. package/dist/esm/persistence/tests/TestsPersistenceVolatile.js +4 -1
  24. package/dist/lib/test/utils/donobuTestStack.js +1 -1
  25. package/dist/main.d.ts +2 -1
  26. package/dist/main.js +2 -4
  27. package/dist/managers/AdminApiController.d.ts +1 -1
  28. package/dist/managers/DonobuStack.d.ts +2 -0
  29. package/dist/managers/DonobuStack.js +1 -1
  30. package/dist/managers/TestsManager.js +5 -2
  31. package/dist/persistence/DonobuApiClient.js +1 -1
  32. package/dist/persistence/flows/FlowsPersistenceRegistry.d.ts +1 -1
  33. package/dist/persistence/flows/FlowsPersistenceRegistry.js +7 -1
  34. package/dist/persistence/suites/SuitesPersistenceRegistry.d.ts +1 -1
  35. package/dist/persistence/suites/SuitesPersistenceRegistry.js +7 -1
  36. package/dist/persistence/tests/TestsPersistenceDonobuApi.js +3 -0
  37. package/dist/persistence/tests/TestsPersistenceRegistry.d.ts +1 -1
  38. package/dist/persistence/tests/TestsPersistenceRegistry.js +7 -1
  39. package/dist/persistence/tests/TestsPersistenceSqlite.js +4 -1
  40. package/dist/persistence/tests/TestsPersistenceVolatile.js +4 -1
  41. package/package.json +2 -8
  42. package/dist/cli/generate-site-tests.d.ts +0 -2
  43. package/dist/cli/generate-site-tests.js +0 -43
  44. package/dist/codegen/runGenerateSiteTests.d.ts +0 -69
  45. package/dist/codegen/runGenerateSiteTests.js +0 -937
  46. package/dist/esm/cli/generate-site-tests.d.ts +0 -2
  47. package/dist/esm/cli/generate-site-tests.js +0 -43
  48. package/dist/esm/codegen/runGenerateSiteTests.d.ts +0 -69
  49. package/dist/esm/codegen/runGenerateSiteTests.js +0 -937
@@ -46,7 +46,7 @@ export declare class FlowsPersistenceRegistryImpl implements FlowsPersistenceReg
46
46
  * Creates an instance by reading environment variables and eagerly constructing
47
47
  * all applicable persistence layers.
48
48
  */
49
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<FlowsPersistenceRegistryImpl>;
49
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<FlowsPersistenceRegistryImpl>;
50
50
  /**
51
51
  * Returns the primary persistence layer.
52
52
  */
@@ -26,7 +26,13 @@ class FlowsPersistenceRegistryImpl {
26
26
  */
27
27
  static async fromEnvironment(environ, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
28
28
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
29
- const donobuApiKey = environ.data.DONOBU_API_KEY;
29
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
30
+ // (which also drives the inference fallback chain in
31
+ // DonobuFlowsManager.createGptClient), then fall back to the
32
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
33
+ // inference through an explicit gpt-config and don't want their
34
+ // persistence credential to short-circuit the agent lookup.
35
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
30
36
  const layers = [];
31
37
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
32
38
  switch (key) {
@@ -26,7 +26,7 @@ export interface SuitesPersistenceRegistry {
26
26
  export declare class SuitesPersistenceRegistryImpl implements SuitesPersistenceRegistry {
27
27
  private readonly layers;
28
28
  constructor(layers: SuitesPersistenceLayer[]);
29
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<SuitesPersistenceRegistryImpl>;
29
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<SuitesPersistenceRegistryImpl>;
30
30
  get(): Promise<SuitesPersistence>;
31
31
  getAll(): Promise<SuitesPersistence[]>;
32
32
  getEntries(): Promise<SuitesPersistenceLayer[]>;
@@ -15,7 +15,13 @@ class SuitesPersistenceRegistryImpl {
15
15
  }
16
16
  static async fromEnvironment(environ, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
17
17
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
18
- const donobuApiKey = environ.data.DONOBU_API_KEY;
18
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
19
+ // (which also drives the inference fallback chain in
20
+ // DonobuFlowsManager.createGptClient), then fall back to the
21
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
22
+ // inference through an explicit gpt-config and don't want their
23
+ // persistence credential to short-circuit the agent lookup.
24
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
19
25
  const layers = [];
20
26
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
21
27
  switch (key) {
@@ -103,6 +103,9 @@ class TestsPersistenceDonobuApi extends DonobuApiClient_1.DonobuApiClient {
103
103
  // DB FK constraint.
104
104
  const response = await this.jsonRequest(`/v1/tests/${encodeURIComponent(testId)}`, 'DELETE');
105
105
  if (!response.ok) {
106
+ if (response.status === 404) {
107
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
108
+ }
106
109
  throw new Error(`Failed to delete test: ${response.status} ${response.statusText}`);
107
110
  }
108
111
  }
@@ -27,7 +27,7 @@ export interface TestsPersistenceRegistry {
27
27
  export declare class TestsPersistenceRegistryImpl implements TestsPersistenceRegistry {
28
28
  private readonly layers;
29
29
  constructor(layers: TestsPersistenceLayer[]);
30
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>,
30
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>,
31
31
  /**
32
32
  * Flows registry — used by the volatile tests layer to compute
33
33
  * flow-derived sort keys (flow_count, latest_flow_created_at).
@@ -22,7 +22,13 @@ class TestsPersistenceRegistryImpl {
22
22
  */
23
23
  flowsRegistry, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
24
24
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
25
- const donobuApiKey = environ.data.DONOBU_API_KEY;
25
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
26
+ // (which also drives the inference fallback chain in
27
+ // DonobuFlowsManager.createGptClient), then fall back to the
28
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
29
+ // inference through an explicit gpt-config and don't want their
30
+ // persistence credential to short-circuit the agent lookup.
31
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
26
32
  const layers = [];
27
33
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
28
34
  switch (key) {
@@ -151,7 +151,10 @@ class TestsPersistenceSqlite {
151
151
  async deleteTest(testId) {
152
152
  // Flows are cascade-deleted by the DB FK constraint.
153
153
  const stmt = this.db.prepare('DELETE FROM test_metadata WHERE id = ?');
154
- stmt.run(testId);
154
+ const { changes } = stmt.run(testId);
155
+ if (changes === 0) {
156
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
157
+ }
155
158
  }
156
159
  }
157
160
  exports.TestsPersistenceSqlite = TestsPersistenceSqlite;
@@ -124,7 +124,10 @@ class TestsPersistenceVolatile {
124
124
  };
125
125
  }
126
126
  async deleteTest(testId) {
127
- this.tests.delete(testId);
127
+ const didExist = this.tests.delete(testId);
128
+ if (!didExist) {
129
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
130
+ }
128
131
  }
129
132
  }
130
133
  exports.TestsPersistenceVolatile = TestsPersistenceVolatile;
@@ -20,7 +20,7 @@ function getEnvSnapshot() {
20
20
  }
21
21
  async function getOrCreateDonobuStack() {
22
22
  if (!donobuStack) {
23
- donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(getEnvSnapshot()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
23
+ donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(getEnvSnapshot()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'DONOBU_PERSISTENCE_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
24
24
  return donobuStack;
25
25
  }
26
26
  else {
package/dist/main.d.ts CHANGED
@@ -6,7 +6,6 @@ export { GptClient } from './clients/GptClient';
6
6
  export { type GptClientPlugin, GptClientPluginRegistry, } from './clients/GptClientPlugin';
7
7
  export { OpenAiGptClient } from './clients/OpenAiGptClient';
8
8
  export { VercelAiGptClient } from './clients/VercelAiGptClient';
9
- export { runGenerateSiteTests } from './codegen/runGenerateSiteTests';
10
9
  export { env } from './envVars';
11
10
  export * from './exceptions/DonobuException';
12
11
  export * from './exceptions/FlowIdCollisionException';
@@ -105,6 +104,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
105
104
  AWS_ACCESS_KEY_ID: z.ZodOptional<z.ZodString>;
106
105
  AWS_SECRET_ACCESS_KEY: z.ZodOptional<z.ZodString>;
107
106
  DONOBU_API_KEY: z.ZodOptional<z.ZodString>;
107
+ DONOBU_PERSISTENCE_API_KEY: z.ZodOptional<z.ZodString>;
108
108
  }, {
109
109
  BASE64_GPT_CONFIG?: string | undefined;
110
110
  BROWSERBASE_API_KEY?: string | undefined;
@@ -124,6 +124,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
124
124
  AWS_ACCESS_KEY_ID?: string | undefined;
125
125
  AWS_SECRET_ACCESS_KEY?: string | undefined;
126
126
  DONOBU_API_KEY?: string | undefined;
127
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
127
128
  }> | undefined;
128
129
  }): Promise<void>;
129
130
  //# sourceMappingURL=main.d.ts.map
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.PluginLoader = exports.InteractionVisualizer = exports.setupDonobuStack = exports.prepareToolCallsForRerun = exports.DonobuFlowsManager = exports.distillAllowedEnvVariableNames = exports.DonobuFlow = exports.AdminApiController = exports.env = exports.runGenerateSiteTests = exports.VercelAiGptClient = exports.OpenAiGptClient = exports.GptClientPluginRegistry = exports.GptClient = exports.GoogleGenerativeAiGptClient = exports.fixAssertFields = exports.DonobuGptClient = exports.AnthropicGptClient = void 0;
17
+ exports.TargetRuntimePluginRegistry = exports.PersistencePluginRegistry = exports.shutdownFileUploadWorkers = exports.getFileUploadAggregateStatus = exports.createDefaultToolRegistry = exports.ToolManager = 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");
@@ -39,8 +39,6 @@ var OpenAiGptClient_1 = require("./clients/OpenAiGptClient");
39
39
  Object.defineProperty(exports, "OpenAiGptClient", { enumerable: true, get: function () { return OpenAiGptClient_1.OpenAiGptClient; } });
40
40
  var VercelAiGptClient_1 = require("./clients/VercelAiGptClient");
41
41
  Object.defineProperty(exports, "VercelAiGptClient", { enumerable: true, get: function () { return VercelAiGptClient_1.VercelAiGptClient; } });
42
- var runGenerateSiteTests_1 = require("./codegen/runGenerateSiteTests");
43
- Object.defineProperty(exports, "runGenerateSiteTests", { enumerable: true, get: function () { return runGenerateSiteTests_1.runGenerateSiteTests; } });
44
42
  var envVars_2 = require("./envVars");
45
43
  Object.defineProperty(exports, "env", { enumerable: true, get: function () { return envVars_2.env; } });
46
44
  __exportStar(require("./exceptions/DonobuException"), exports);
@@ -113,7 +111,7 @@ const DEFAULT_PORT = 31000;
113
111
  * Starts a Donobu API server at the given port. The server assumes that the
114
112
  * Playwright browsers have been installed.
115
113
  */
116
- async function startDonobuServer({ port = DEFAULT_PORT, controlPanelHost = ControlPanel_1.NoOpControlPanelFactory, environ = envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_DEPLOYMENT_ENVIRONMENT', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'), } = {}) {
114
+ async function startDonobuServer({ port = DEFAULT_PORT, controlPanelHost = ControlPanel_1.NoOpControlPanelFactory, environ = envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_DEPLOYMENT_ENVIRONMENT', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'DONOBU_PERSISTENCE_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'), } = {}) {
117
115
  try {
118
116
  const adminController = await AdminApiController_1.AdminApiController.create(environ.data.DONOBU_DEPLOYMENT_ENVIRONMENT ?? 'LOCAL', controlPanelHost, environ);
119
117
  await adminController.start(port);
@@ -59,7 +59,7 @@ export declare class AdminApiController {
59
59
  * - no checking for flow ownership is performed, as all flows are considered owned by the
60
60
  * local environment.
61
61
  */
62
- static create(donobuDeploymentEnvironment: DonobuDeploymentEnvironment, controlPanelFactory: ControlPanelFactory, environ: EnvPick<typeof env, 'ANTHROPIC_API_KEY' | 'ANTHROPIC_MODEL_NAME' | 'AWS_ACCESS_KEY_ID' | 'AWS_BEDROCK_MODEL_NAME' | 'AWS_SECRET_ACCESS_KEY' | 'BASE64_GPT_CONFIG' | 'BROWSERBASE_API_KEY' | 'BROWSERBASE_PROJECT_ID' | 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'GOOGLE_GENERATIVE_AI_API_KEY' | 'GOOGLE_GENERATIVE_AI_MODEL_NAME' | 'OLLAMA_API_URL' | 'OLLAMA_MODEL_NAME' | 'OPENAI_API_KEY' | 'OPENAI_API_MODEL_NAME' | 'PERSISTENCE_PRIORITY'>): Promise<AdminApiController>;
62
+ static create(donobuDeploymentEnvironment: DonobuDeploymentEnvironment, controlPanelFactory: ControlPanelFactory, environ: EnvPick<typeof env, 'ANTHROPIC_API_KEY' | 'ANTHROPIC_MODEL_NAME' | 'AWS_ACCESS_KEY_ID' | 'AWS_BEDROCK_MODEL_NAME' | 'AWS_SECRET_ACCESS_KEY' | 'BASE64_GPT_CONFIG' | 'BROWSERBASE_API_KEY' | 'BROWSERBASE_PROJECT_ID' | 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'GOOGLE_GENERATIVE_AI_API_KEY' | 'GOOGLE_GENERATIVE_AI_MODEL_NAME' | 'OLLAMA_API_URL' | 'OLLAMA_MODEL_NAME' | 'OPENAI_API_KEY' | 'OPENAI_API_MODEL_NAME' | 'PERSISTENCE_PRIORITY'>): Promise<AdminApiController>;
63
63
  private constructor();
64
64
  /**
65
65
  * Binds the API/web-asset server to `port` and resolves once the socket is
@@ -60,6 +60,7 @@ export declare function setupDonobuStack(donobuDeploymentEnvironment: DonobuDepl
60
60
  AWS_ACCESS_KEY_ID: import("zod/v4").ZodOptional<import("zod/v4").ZodString>;
61
61
  AWS_SECRET_ACCESS_KEY: import("zod/v4").ZodOptional<import("zod/v4").ZodString>;
62
62
  DONOBU_API_KEY: import("zod/v4").ZodOptional<import("zod/v4").ZodString>;
63
+ DONOBU_PERSISTENCE_API_KEY: import("zod/v4").ZodOptional<import("zod/v4").ZodString>;
63
64
  }, {
64
65
  BASE64_GPT_CONFIG?: string | undefined;
65
66
  BROWSERBASE_API_KEY?: string | undefined;
@@ -78,5 +79,6 @@ export declare function setupDonobuStack(donobuDeploymentEnvironment: DonobuDepl
78
79
  AWS_ACCESS_KEY_ID?: string | undefined;
79
80
  AWS_SECRET_ACCESS_KEY?: string | undefined;
80
81
  DONOBU_API_KEY?: string | undefined;
82
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
81
83
  }>): Promise<DonobuStack>;
82
84
  //# sourceMappingURL=DonobuStack.d.ts.map
@@ -33,7 +33,7 @@ const ToolRegistry_1 = require("./ToolRegistry");
33
33
  * then having this snapshot is relevant so that tests can use normal
34
34
  * environment variables.
35
35
  */
36
- async function setupDonobuStack(donobuDeploymentEnvironment, controlPanelFactory, envPersistenceVolatile, environ = envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY')) {
36
+ async function setupDonobuStack(donobuDeploymentEnvironment, controlPanelFactory, envPersistenceVolatile, environ = envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_SECRET_ACCESS_KEY', 'BASE64_GPT_CONFIG', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID', 'DONOBU_API_BASE_URL', 'DONOBU_API_KEY', 'DONOBU_PERSISTENCE_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_GENERATIVE_AI_MODEL_NAME', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY')) {
37
37
  const loadedPlugins = await loadDefaultPlugins();
38
38
  const resolvedToolRegistry = await (0, ToolRegistry_1.createDefaultToolRegistry)(loadedPlugins.tools);
39
39
  const persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry(loadedPlugins.persistencePlugins);
@@ -174,8 +174,11 @@ class TestsManager {
174
174
  try {
175
175
  await persistence.deleteTest(testId);
176
176
  }
177
- catch {
178
- // Ignore errors from layers that don't have this test.
177
+ catch (e) {
178
+ // Ignore TestNotFoundException errors from layers that don't have this test.
179
+ if (!(e instanceof TestNotFoundException_1.TestNotFoundException)) {
180
+ throw e;
181
+ }
179
182
  }
180
183
  }
181
184
  // Cascade-delete flows belonging to this test. Paginate through all flows
@@ -24,7 +24,7 @@ class DonobuApiClient {
24
24
  async jsonRequest(path, method, body) {
25
25
  return this.request(path, {
26
26
  method,
27
- headers: { 'Content-Type': 'application/json' },
27
+ headers: body !== undefined ? { 'Content-Type': 'application/json' } : {},
28
28
  body: body !== undefined ? JSON.stringify(body) : undefined,
29
29
  });
30
30
  }
@@ -46,7 +46,7 @@ export declare class FlowsPersistenceRegistryImpl implements FlowsPersistenceReg
46
46
  * Creates an instance by reading environment variables and eagerly constructing
47
47
  * all applicable persistence layers.
48
48
  */
49
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<FlowsPersistenceRegistryImpl>;
49
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<FlowsPersistenceRegistryImpl>;
50
50
  /**
51
51
  * Returns the primary persistence layer.
52
52
  */
@@ -26,7 +26,13 @@ class FlowsPersistenceRegistryImpl {
26
26
  */
27
27
  static async fromEnvironment(environ, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
28
28
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
29
- const donobuApiKey = environ.data.DONOBU_API_KEY;
29
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
30
+ // (which also drives the inference fallback chain in
31
+ // DonobuFlowsManager.createGptClient), then fall back to the
32
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
33
+ // inference through an explicit gpt-config and don't want their
34
+ // persistence credential to short-circuit the agent lookup.
35
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
30
36
  const layers = [];
31
37
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
32
38
  switch (key) {
@@ -26,7 +26,7 @@ export interface SuitesPersistenceRegistry {
26
26
  export declare class SuitesPersistenceRegistryImpl implements SuitesPersistenceRegistry {
27
27
  private readonly layers;
28
28
  constructor(layers: SuitesPersistenceLayer[]);
29
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<SuitesPersistenceRegistryImpl>;
29
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>, persistencePlugins?: PersistencePluginRegistry): Promise<SuitesPersistenceRegistryImpl>;
30
30
  get(): Promise<SuitesPersistence>;
31
31
  getAll(): Promise<SuitesPersistence[]>;
32
32
  getEntries(): Promise<SuitesPersistenceLayer[]>;
@@ -15,7 +15,13 @@ class SuitesPersistenceRegistryImpl {
15
15
  }
16
16
  static async fromEnvironment(environ, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
17
17
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
18
- const donobuApiKey = environ.data.DONOBU_API_KEY;
18
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
19
+ // (which also drives the inference fallback chain in
20
+ // DonobuFlowsManager.createGptClient), then fall back to the
21
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
22
+ // inference through an explicit gpt-config and don't want their
23
+ // persistence credential to short-circuit the agent lookup.
24
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
19
25
  const layers = [];
20
26
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
21
27
  switch (key) {
@@ -103,6 +103,9 @@ class TestsPersistenceDonobuApi extends DonobuApiClient_1.DonobuApiClient {
103
103
  // DB FK constraint.
104
104
  const response = await this.jsonRequest(`/v1/tests/${encodeURIComponent(testId)}`, 'DELETE');
105
105
  if (!response.ok) {
106
+ if (response.status === 404) {
107
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
108
+ }
106
109
  throw new Error(`Failed to delete test: ${response.status} ${response.statusText}`);
107
110
  }
108
111
  }
@@ -27,7 +27,7 @@ export interface TestsPersistenceRegistry {
27
27
  export declare class TestsPersistenceRegistryImpl implements TestsPersistenceRegistry {
28
28
  private readonly layers;
29
29
  constructor(layers: TestsPersistenceLayer[]);
30
- static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'PERSISTENCE_PRIORITY'>,
30
+ static fromEnvironment(environ: EnvPick<typeof env, 'DONOBU_API_BASE_URL' | 'DONOBU_API_KEY' | 'DONOBU_PERSISTENCE_API_KEY' | 'PERSISTENCE_PRIORITY'>,
31
31
  /**
32
32
  * Flows registry — used by the volatile tests layer to compute
33
33
  * flow-derived sort keys (flow_count, latest_flow_created_at).
@@ -22,7 +22,13 @@ class TestsPersistenceRegistryImpl {
22
22
  */
23
23
  flowsRegistry, persistencePlugins = new PersistencePlugin_1.PersistencePluginRegistry()) {
24
24
  const donobuApiBaseUrl = environ.data.DONOBU_API_BASE_URL;
25
- const donobuApiKey = environ.data.DONOBU_API_KEY;
25
+ // Persistence credential resolution: prefer the primary DONOBU_API_KEY
26
+ // (which also drives the inference fallback chain in
27
+ // DonobuFlowsManager.createGptClient), then fall back to the
28
+ // persistence-only DONOBU_PERSISTENCE_API_KEY for hosts that route
29
+ // inference through an explicit gpt-config and don't want their
30
+ // persistence credential to short-circuit the agent lookup.
31
+ const donobuApiKey = environ.data.DONOBU_API_KEY ?? environ.data.DONOBU_PERSISTENCE_API_KEY;
26
32
  const layers = [];
27
33
  for (const key of environ.data.PERSISTENCE_PRIORITY) {
28
34
  switch (key) {
@@ -151,7 +151,10 @@ class TestsPersistenceSqlite {
151
151
  async deleteTest(testId) {
152
152
  // Flows are cascade-deleted by the DB FK constraint.
153
153
  const stmt = this.db.prepare('DELETE FROM test_metadata WHERE id = ?');
154
- stmt.run(testId);
154
+ const { changes } = stmt.run(testId);
155
+ if (changes === 0) {
156
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
157
+ }
155
158
  }
156
159
  }
157
160
  exports.TestsPersistenceSqlite = TestsPersistenceSqlite;
@@ -124,7 +124,10 @@ class TestsPersistenceVolatile {
124
124
  };
125
125
  }
126
126
  async deleteTest(testId) {
127
- this.tests.delete(testId);
127
+ const didExist = this.tests.delete(testId);
128
+ if (!didExist) {
129
+ throw TestNotFoundException_1.TestNotFoundException.forId(testId);
130
+ }
128
131
  }
129
132
  }
130
133
  exports.TestsPersistenceVolatile = TestsPersistenceVolatile;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donobu",
3
- "version": "5.40.0",
3
+ "version": "5.41.1",
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",
@@ -29,8 +29,7 @@
29
29
  },
30
30
  "bin": {
31
31
  "donobu": "./dist/cli/donobu-cli.js",
32
- "install-donobu-plugin": "./dist/cli/install-donobu-plugin.js",
33
- "generate-site-tests": "./dist/cli/generate-site-tests.js"
32
+ "install-donobu-plugin": "./dist/cli/install-donobu-plugin.js"
34
33
  },
35
34
  "keywords": [
36
35
  "playwright",
@@ -50,19 +49,15 @@
50
49
  "@playwright/test": "^1.57.0",
51
50
  "@types/better-sqlite3": "^7.6.13",
52
51
  "@types/express": "^5.0.6",
53
- "@types/glob": "^8.1.0",
54
- "@types/js-yaml": "^4.0.9",
55
52
  "@types/node": "^22.10.5",
56
53
  "@types/proper-lockfile": "^4.1.4",
57
54
  "@typescript-eslint/eslint-plugin": "^8.56.1",
58
55
  "@typescript-eslint/parser": "^8.56.1",
59
56
  "@vitest/coverage-v8": "^4.0.17",
60
57
  "axe-core": "^4.11.2",
61
- "csv-stringify": "^6.6.0",
62
58
  "eslint": "^10.0.2",
63
59
  "eslint-plugin-simple-import-sort": "^12.1.1",
64
60
  "globals": "^16.0.0",
65
- "js-yaml": "^4.1.0",
66
61
  "playwright": "^1.57.0",
67
62
  "playwright-core": "^1.57.0",
68
63
  "typescript-eslint": "^8.47.0",
@@ -84,7 +79,6 @@
84
79
  "fast-json-stable-stringify": "^2.1.0",
85
80
  "prettier": "^3.8.0",
86
81
  "proper-lockfile": "^4.1.2",
87
- "slugify": "^1.6.6",
88
82
  "typescript": "^5.8.3",
89
83
  "winston": "^3.19.0",
90
84
  "winston-daily-rotate-file": "^5.0.0",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=generate-site-tests.d.ts.map
@@ -1,43 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- /**
4
- * Thin CLI wrapper for Donobu Site Test Generator.
5
- */
6
- const commander_1 = require("commander");
7
- const runGenerateSiteTests_1 = require("../codegen/runGenerateSiteTests");
8
- async function main() {
9
- const program = new commander_1.Command();
10
- program
11
- .requiredOption('--url <url>', 'Target website URL')
12
- .option('--storage-state <path>', 'Path to Playwright storageState JSON')
13
- .option('--out <dir>', 'Output directory for the generated project', undefined)
14
- .option('--max-tests <n>', 'Maximum number of tests to generate', String(12))
15
- .option('--max-discovery-steps <n>', 'Max Donobu tool calls when profiling the site', String(32))
16
- .option('--max-test-steps <n>', 'Max Donobu tool calls when executing each test flow', String(28))
17
- .option('--gpt-config-name <name>', 'Name of the GPT config to use')
18
- .option('--playwright-variant <variant>', 'Use "ai" (page.ai) or "classic" scripts in the generated project', 'ai')
19
- .option('--headed', 'Generate headed Playwright config (xvfb-friendly)', false)
20
- .option('--slowmo <ms>', 'Slow motion delay in ms for headed runs', (value) => Number(value))
21
- .option('--disable-self-heal', 'Disable Donobu self-healing in generated AI-mode tests', false);
22
- const cli = program.parse(process.argv).opts();
23
- await (0, runGenerateSiteTests_1.runGenerateSiteTests)({
24
- url: cli.url,
25
- outDir: cli.outDir,
26
- storageStatePath: cli.storageStatePath,
27
- maxTests: cli.maxTests ? Number(cli.maxTests) : undefined,
28
- maxDiscoverySteps: cli.maxDiscoverySteps
29
- ? Number(cli.maxDiscoverySteps)
30
- : undefined,
31
- maxTestSteps: cli.maxTestSteps ? Number(cli.maxTestSteps) : undefined,
32
- gptConfigName: cli.gptConfigName,
33
- playwrightVariant: cli.playwrightVariant,
34
- headed: cli.headed,
35
- slowMo: cli.slowMo,
36
- disableSelfHeal: cli.disableSelfHeal,
37
- });
38
- }
39
- void main().catch((error) => {
40
- console.error(error.message);
41
- process.exit(1);
42
- });
43
- //# sourceMappingURL=generate-site-tests.js.map
@@ -1,69 +0,0 @@
1
- /**
2
- * Library entrypoint for Donobu Site Test Generator (coverage-aware).
3
- *
4
- * Use `runGenerateSiteTests(options, onProgress?, shouldCancel?)` to invoke programmatically.
5
- */
6
- type DiscoveryTestCase = {
7
- title: string;
8
- objective: string;
9
- assertions: string[];
10
- category?: string;
11
- startUrl?: string;
12
- dependsOnAuth?: boolean;
13
- dataNeeds?: string[];
14
- priority?: 'P0' | 'P1' | 'P2';
15
- };
16
- type DiscoveryResult = {
17
- siteProfile: {
18
- siteType: string;
19
- primaryAudiences: string[];
20
- requiresAuth: boolean;
21
- authNotes?: string;
22
- keyJourneys: string[];
23
- riskAreas: string[];
24
- };
25
- testCases: DiscoveryTestCase[];
26
- };
27
- export type GenerateSiteTestsOptions = {
28
- url: string;
29
- outDir?: string;
30
- storageStatePath?: string;
31
- maxTests?: number;
32
- maxDiscoverySteps?: number;
33
- maxTestSteps?: number;
34
- gptConfigName?: string;
35
- playwrightVariant?: 'ai' | 'classic';
36
- headed?: boolean;
37
- slowMo?: number;
38
- disableSelfHeal?: boolean;
39
- /** Explicit tool allowlist for discovery and test flows. If provided, only these tools are enabled. */
40
- toolAllowlist?: string[];
41
- /** Tool denylist to disable specific tools. Applied after allowlist. */
42
- toolDenylist?: string[];
43
- };
44
- export type ProgressEvent = {
45
- type: 'log';
46
- level?: 'info' | 'warn' | 'error';
47
- message: string;
48
- } | {
49
- type: 'flow';
50
- stage: 'start' | 'end';
51
- flowId: string;
52
- name?: string;
53
- } | {
54
- type: 'stdout';
55
- data: string;
56
- } | {
57
- type: 'summary';
58
- data: {
59
- projectDir: string;
60
- newlyGeneratedTests: number;
61
- totalPlannedTests: number;
62
- requiresAuth: boolean;
63
- usedStorageState: boolean;
64
- siteProfile?: DiscoveryResult['siteProfile'];
65
- };
66
- };
67
- export declare function runGenerateSiteTests(opts: GenerateSiteTestsOptions, onProgress?: (event: ProgressEvent) => void, shouldCancel?: () => boolean): Promise<void>;
68
- export {};
69
- //# sourceMappingURL=runGenerateSiteTests.d.ts.map