donobu 5.40.0 → 5.41.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 (41) hide show
  1. package/dist/codegen/runGenerateSiteTests.js +1 -1
  2. package/dist/envVars.d.ts +2 -0
  3. package/dist/envVars.js +12 -0
  4. package/dist/esm/codegen/runGenerateSiteTests.js +1 -1
  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 -0
  9. package/dist/esm/main.js +1 -1
  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 -0
  26. package/dist/main.js +1 -1
  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 +1 -1
@@ -769,7 +769,7 @@ async function runGenerateSiteTests(opts, onProgress, shouldCancel) {
769
769
  }
770
770
  const storageState = await loadStorageState(storageStatePath);
771
771
  assertNotCancelled('loading storage state');
772
- const donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(snapshotEnv()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_REGION', 'AWS_S3_BUCKET', 'AWS_S3_REGION', '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', 'GOOGLE_CLOUD_STORAGE_BUCKET', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
772
+ const donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(snapshotEnv()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_REGION', 'AWS_S3_BUCKET', 'AWS_S3_REGION', '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', 'GOOGLE_CLOUD_STORAGE_BUCKET', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
773
773
  await ensureGptAvailability(donobuStack, gptConfigName);
774
774
  assertNotCancelled('ensuring GPT availability');
775
775
  const allowedTools = buildAllowedTools(toolAllowlist, toolDenylist);
package/dist/envVars.d.ts CHANGED
@@ -74,6 +74,7 @@ export declare const env: Env<{
74
74
  AWS_SECRET_ACCESS_KEY: z.ZodOptional<z.ZodString>;
75
75
  EXPERIMENTAL_FEATURES_ENABLED: z.ZodDefault<z.ZodBoolean>;
76
76
  DONOBU_API_KEY: z.ZodOptional<z.ZodString>;
77
+ DONOBU_PERSISTENCE_API_KEY: z.ZodOptional<z.ZodString>;
77
78
  GOOGLE_CLOUD_STORAGE_BUCKET: z.ZodOptional<z.ZodString>;
78
79
  SCREENSHOT_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
79
80
  SELF_HEAL_TESTS_ENABLED: z.ZodOptional<z.ZodString>;
@@ -127,6 +128,7 @@ export declare const env: Env<{
127
128
  AWS_ACCESS_KEY_ID?: string | undefined;
128
129
  AWS_SECRET_ACCESS_KEY?: string | undefined;
129
130
  DONOBU_API_KEY?: string | undefined;
131
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
130
132
  GOOGLE_CLOUD_STORAGE_BUCKET?: string | undefined;
131
133
  SELF_HEAL_TESTS_ENABLED?: string | undefined;
132
134
  PROXY_SERVER?: string | undefined;
package/dist/envVars.js CHANGED
@@ -188,6 +188,18 @@ flows. If specified, AWS credentials must also be present.`),
188
188
  .optional()
189
189
  .describe(`The API key for the Donobu API. Used to create GPT configurations backed
190
190
  by the Donobu API, and to persist flows via the Donobu API when set.`),
191
+ DONOBU_PERSISTENCE_API_KEY: v4_1.z
192
+ .string()
193
+ .optional()
194
+ .describe(`Persistence-only fallback for the Donobu API key. When set, the DONOBU
195
+ persistence layer will instantiate using this key if DONOBU_API_KEY is
196
+ absent — but unlike DONOBU_API_KEY, this value is NOT consulted by
197
+ DonobuFlowsManager.createGptClient's env-var fallback chain.
198
+
199
+ Intended for hosts (e.g. the Donobu Studio desktop app) that drive AI
200
+ inference through an explicit gpt-config / flow-runner agent and want
201
+ to enable Donobu Cloud persistence without their persistence credential
202
+ silently overriding the user's flow-runner pick.`),
191
203
  GOOGLE_CLOUD_STORAGE_BUCKET: v4_1.z.string().optional()
192
204
  .describe(`Directs Donobu flows to be persisted using this Google Cloud Storage
193
205
  bucket.`),
@@ -769,7 +769,7 @@ async function runGenerateSiteTests(opts, onProgress, shouldCancel) {
769
769
  }
770
770
  const storageState = await loadStorageState(storageStatePath);
771
771
  assertNotCancelled('loading storage state');
772
- const donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(snapshotEnv()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_REGION', 'AWS_S3_BUCKET', 'AWS_S3_REGION', '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', 'GOOGLE_CLOUD_STORAGE_BUCKET', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
772
+ const donobuStack = await (0, DonobuStack_1.setupDonobuStack)('LOCAL', ControlPanel_1.NoOpControlPanelFactory, new EnvPersistenceVolatile_1.EnvPersistenceVolatile(snapshotEnv()), envVars_1.env.pick('ANTHROPIC_API_KEY', 'ANTHROPIC_MODEL_NAME', 'AWS_ACCESS_KEY_ID', 'AWS_BEDROCK_MODEL_NAME', 'AWS_REGION', 'AWS_S3_BUCKET', 'AWS_S3_REGION', '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', 'GOOGLE_CLOUD_STORAGE_BUCKET', 'OLLAMA_API_URL', 'OLLAMA_MODEL_NAME', 'OPENAI_API_KEY', 'OPENAI_API_MODEL_NAME', 'PERSISTENCE_PRIORITY'));
773
773
  await ensureGptAvailability(donobuStack, gptConfigName);
774
774
  assertNotCancelled('ensuring GPT availability');
775
775
  const allowedTools = buildAllowedTools(toolAllowlist, toolDenylist);
@@ -74,6 +74,7 @@ export declare const env: Env<{
74
74
  AWS_SECRET_ACCESS_KEY: z.ZodOptional<z.ZodString>;
75
75
  EXPERIMENTAL_FEATURES_ENABLED: z.ZodDefault<z.ZodBoolean>;
76
76
  DONOBU_API_KEY: z.ZodOptional<z.ZodString>;
77
+ DONOBU_PERSISTENCE_API_KEY: z.ZodOptional<z.ZodString>;
77
78
  GOOGLE_CLOUD_STORAGE_BUCKET: z.ZodOptional<z.ZodString>;
78
79
  SCREENSHOT_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
79
80
  SELF_HEAL_TESTS_ENABLED: z.ZodOptional<z.ZodString>;
@@ -127,6 +128,7 @@ export declare const env: Env<{
127
128
  AWS_ACCESS_KEY_ID?: string | undefined;
128
129
  AWS_SECRET_ACCESS_KEY?: string | undefined;
129
130
  DONOBU_API_KEY?: string | undefined;
131
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
130
132
  GOOGLE_CLOUD_STORAGE_BUCKET?: string | undefined;
131
133
  SELF_HEAL_TESTS_ENABLED?: string | undefined;
132
134
  PROXY_SERVER?: string | undefined;
@@ -188,6 +188,18 @@ flows. If specified, AWS credentials must also be present.`),
188
188
  .optional()
189
189
  .describe(`The API key for the Donobu API. Used to create GPT configurations backed
190
190
  by the Donobu API, and to persist flows via the Donobu API when set.`),
191
+ DONOBU_PERSISTENCE_API_KEY: v4_1.z
192
+ .string()
193
+ .optional()
194
+ .describe(`Persistence-only fallback for the Donobu API key. When set, the DONOBU
195
+ persistence layer will instantiate using this key if DONOBU_API_KEY is
196
+ absent — but unlike DONOBU_API_KEY, this value is NOT consulted by
197
+ DonobuFlowsManager.createGptClient's env-var fallback chain.
198
+
199
+ Intended for hosts (e.g. the Donobu Studio desktop app) that drive AI
200
+ inference through an explicit gpt-config / flow-runner agent and want
201
+ to enable Donobu Cloud persistence without their persistence credential
202
+ silently overriding the user's flow-runner pick.`),
191
203
  GOOGLE_CLOUD_STORAGE_BUCKET: v4_1.z.string().optional()
192
204
  .describe(`Directs Donobu flows to be persisted using this Google Cloud Storage
193
205
  bucket.`),
@@ -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 {
@@ -105,6 +105,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
105
105
  AWS_ACCESS_KEY_ID: z.ZodOptional<z.ZodString>;
106
106
  AWS_SECRET_ACCESS_KEY: z.ZodOptional<z.ZodString>;
107
107
  DONOBU_API_KEY: z.ZodOptional<z.ZodString>;
108
+ DONOBU_PERSISTENCE_API_KEY: z.ZodOptional<z.ZodString>;
108
109
  }, {
109
110
  BASE64_GPT_CONFIG?: string | undefined;
110
111
  BROWSERBASE_API_KEY?: string | undefined;
@@ -124,6 +125,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
124
125
  AWS_ACCESS_KEY_ID?: string | undefined;
125
126
  AWS_SECRET_ACCESS_KEY?: string | undefined;
126
127
  DONOBU_API_KEY?: string | undefined;
128
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
127
129
  }> | undefined;
128
130
  }): Promise<void>;
129
131
  //# sourceMappingURL=main.d.ts.map
package/dist/esm/main.js CHANGED
@@ -113,7 +113,7 @@ const DEFAULT_PORT = 31000;
113
113
  * Starts a Donobu API server at the given port. The server assumes that the
114
114
  * Playwright browsers have been installed.
115
115
  */
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'), } = {}) {
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', '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
117
  try {
118
118
  const adminController = await AdminApiController_1.AdminApiController.create(environ.data.DONOBU_DEPLOYMENT_ENVIRONMENT ?? 'LOCAL', controlPanelHost, environ);
119
119
  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;
@@ -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
@@ -105,6 +105,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
105
105
  AWS_ACCESS_KEY_ID: z.ZodOptional<z.ZodString>;
106
106
  AWS_SECRET_ACCESS_KEY: z.ZodOptional<z.ZodString>;
107
107
  DONOBU_API_KEY: z.ZodOptional<z.ZodString>;
108
+ DONOBU_PERSISTENCE_API_KEY: z.ZodOptional<z.ZodString>;
108
109
  }, {
109
110
  BASE64_GPT_CONFIG?: string | undefined;
110
111
  BROWSERBASE_API_KEY?: string | undefined;
@@ -124,6 +125,7 @@ export declare function startDonobuServer({ port, controlPanelHost, environ, }?:
124
125
  AWS_ACCESS_KEY_ID?: string | undefined;
125
126
  AWS_SECRET_ACCESS_KEY?: string | undefined;
126
127
  DONOBU_API_KEY?: string | undefined;
128
+ DONOBU_PERSISTENCE_API_KEY?: string | undefined;
127
129
  }> | undefined;
128
130
  }): Promise<void>;
129
131
  //# sourceMappingURL=main.d.ts.map
package/dist/main.js CHANGED
@@ -113,7 +113,7 @@ const DEFAULT_PORT = 31000;
113
113
  * Starts a Donobu API server at the given port. The server assumes that the
114
114
  * Playwright browsers have been installed.
115
115
  */
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'), } = {}) {
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', '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
117
  try {
118
118
  const adminController = await AdminApiController_1.AdminApiController.create(environ.data.DONOBU_DEPLOYMENT_ENVIRONMENT ?? 'LOCAL', controlPanelHost, environ);
119
119
  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.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",