@salesforce/sfdx-agent-harness-mastra 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to `@salesforce/sfdx-agent-harness-mastra` are documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.17.0] - 2026-06-09
7
+
8
+ ### Fixes
9
+ - **harness-mastra**: drop inline WAL-pragma workaround now that LibSQLStore.close() ships stable ([#576](https://github.com/forcedotcom/agentic-dx/pull/576))
10
+
11
+ ### Chores
12
+ - **deps**: bump dependencies across packages @W-22695116@ ([#577](https://github.com/forcedotcom/agentic-dx/pull/577))
13
+ - **deps**: bump the mastra group across 1 directory with 5 updates ([#569](https://github.com/forcedotcom/agentic-dx/pull/569))
14
+ - **deps**: bump @libsql/client from 0.15.15 to 0.17.3 ([#570](https://github.com/forcedotcom/agentic-dx/pull/570))
15
+ - **deps-dev**: bump @types/node from 22.19.19 to 22.19.20 in the dev-dependencies group ([#568](https://github.com/forcedotcom/agentic-dx/pull/568))
16
+
6
17
  ## [0.16.0] - 2026-06-09
7
18
 
8
19
  ### Features
package/README.md CHANGED
@@ -26,10 +26,10 @@ internal architecture, see [ARCHITECTURE.md](ARCHITECTURE.md).
26
26
 
27
27
  ### Removing the storage directory on Windows
28
28
 
29
- `manager.shutdown()` closes the libsql client (forcedotcom/agentic-dx#429), but the underlying SQLite/WAL handle release
30
- on Windows is asynchronous at the OS level. After `shutdown()` returns, Windows can take anywhere from ~60 ms to several
31
- seconds to actually release the file lock — so a naïve `fs.rm(storageRoot)` immediately afterward will fail with
32
- `EBUSY`. Pass `maxRetries` and `retryDelay` so Node retries until the OS lets go:
29
+ `manager.shutdown()` checkpoints the WAL and closes the libsql client (forcedotcom/agentic-dx#429,
30
+ mastra-ai/mastra#17285), but the underlying SQLite handle release on Windows is asynchronous at the OS level. After
31
+ `shutdown()` returns, Windows can briefly hold the file lock — so a naïve `fs.rm(storageRoot)` immediately afterward can
32
+ fail with `EBUSY`. Pass `maxRetries` and `retryDelay` so Node retries until the OS lets go:
33
33
 
34
34
  ```ts
35
35
  import { rm } from 'node:fs/promises';
@@ -38,9 +38,7 @@ await manager.shutdown();
38
38
  await rm(storageRoot, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
39
39
  ```
40
40
 
41
- Linux and macOS release the handle eagerly; the retry options are no-ops on those platforms. Tracking upstream at
42
- [mastra-ai/mastra#17285](https://github.com/mastra-ai/mastra/issues/17285) — when `LibSQLStore` exposes a public
43
- `close()` that includes a WAL checkpoint, this delay should shrink or disappear.
41
+ Linux and macOS release the handle eagerly; the retry options are no-ops on those platforms.
44
42
 
45
43
  ## Public API
46
44
 
@@ -207,18 +207,10 @@ export declare class MastraHarness implements MastraAgentHarness {
207
207
  * would mix process state.
208
208
  */
209
209
  protected readonly activeAgents: Map<string, MastraAgentState>;
210
- private readonly libsqlClient;
211
210
  private readonly storage;
212
211
  private readonly memory;
213
212
  private readonly mastra;
214
213
  private readonly buses;
215
- /**
216
- * Tracks the in-flight storage init so {@link shutdown} can settle it
217
- * before closing the libsql client. Without this, Mastra's lazy storage
218
- * init can fire after `client.close()` and surface as an unhandled
219
- * `CLIENT_CLOSED` rejection (#429 follow-up).
220
- */
221
- private readonly storageReady;
222
214
  /**
223
215
  * Mastra-specific extension surface, typed off `MastraAgentHarness`. The
224
216
  * SDK never reads this; consumers reach through `manager.extensions.mastra`.
@@ -233,10 +225,10 @@ export declare class MastraHarness implements MastraAgentHarness {
233
225
  * @requirements
234
226
  * - MUST disconnect the mcpClient for every active agent before clearing state.
235
227
  * - MUST clear the `activeAgents` map.
236
- * - MUST shut down the global `this.mastra` orchestrator.
237
- * - MUST close the libsql client so the underlying SQLite handle is released
238
- * (Windows blocks fs.rm of the storage dir while the WAL/shm files are open;
239
- * see forcedotcom/agentic-dx#429).
228
+ * - MUST shut down the global `this.mastra` orchestrator. Mastra.shutdown() awaits
229
+ * `storage.close()`, which checkpoints the WAL and unlinks the -wal/-shm sidecars
230
+ * so a subsequent `fs.rm` of the storage dir succeeds on Windows
231
+ * (forcedotcom/agentic-dx#429, mastra-ai/mastra#17285).
240
232
  */
241
233
  shutdown(): Promise<void>;
242
234
  onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
@@ -10,7 +10,6 @@ import { Memory } from '@mastra/memory';
10
10
  import { SkillSearchProcessor, ToolSearchProcessor } from '@mastra/core/processors';
11
11
  import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from '@mastra/core/request-context';
12
12
  import { LibSQLStore } from '@mastra/libsql';
13
- import { createClient } from '@libsql/client';
14
13
  import { MCPClient } from '@mastra/mcp';
15
14
  import { AgentSDKError, AgentSDKErrorType, DEFAULT_MAX_STEPS, McpServerStatus, resolveToolApprovalMode, } from '@salesforce/sfdx-agent-sdk';
16
15
  import { HarnessBusOwner, lowerStreamInput, mcpServerConfigEqual, } from '@salesforce/sfdx-agent-sdk/harness';
@@ -340,18 +339,10 @@ export class MastraHarness {
340
339
  * would mix process state.
341
340
  */
342
341
  activeAgents = new Map();
343
- libsqlClient;
344
342
  storage;
345
343
  memory;
346
344
  mastra;
347
345
  buses = new HarnessBusOwner();
348
- /**
349
- * Tracks the in-flight storage init so {@link shutdown} can settle it
350
- * before closing the libsql client. Without this, Mastra's lazy storage
351
- * init can fire after `client.close()` and surface as an unhandled
352
- * `CLIENT_CLOSED` rejection (#429 follow-up).
353
- */
354
- storageReady;
355
346
  /**
356
347
  * Mastra-specific extension surface, typed off `MastraAgentHarness`. The
357
348
  * SDK never reads this; consumers reach through `manager.extensions.mastra`.
@@ -381,24 +372,9 @@ export class MastraHarness {
381
372
  this.clock = opts.clock ?? new RealClock();
382
373
  this.idGenerator = opts.idGenerator ?? new UUIDGenerator();
383
374
  this.toolApprovalTimeoutMs = opts.toolApprovalTimeoutMs ?? 600_000;
384
- // Construct the libsql Client ourselves and inject it into LibSQLStore
385
- // via the `{ client }` constructor form. We keep our own reference so
386
- // shutdown() can call client.close() — Mastra's shutdown() does not
387
- // close the storage, and LibSQLStore declares `client` as private, so
388
- // we cannot reach in. Without an explicit close, the SQLite WAL/shm
389
- // handles stay open on Windows and block fs.rm of the storage dir
390
- // (forcedotcom/agentic-dx#429).
391
- //
392
- // Upstream tracking: https://github.com/mastra-ai/mastra/issues/17285
393
- // — when LibSQLStore exposes a public close(), revert to the simpler
394
- // `new LibSQLStore({ id, url })` form and call store.close() in
395
- // shutdown().
396
- this.libsqlClient = createClient({
397
- url: `file:${this.storageRootFolder}/mastra.db`,
398
- });
399
375
  this.storage = new LibSQLStore({
400
376
  id: 'mastra-storage',
401
- client: this.libsqlClient,
377
+ url: `file:${this.storageRootFolder}/mastra.db`,
402
378
  });
403
379
  this.memory = new Memory({
404
380
  storage: this.storage,
@@ -415,24 +391,15 @@ export class MastraHarness {
415
391
  storage: this.storage,
416
392
  memory: { shared: this.memory },
417
393
  });
418
- // Eagerly run storage init so Mastra's augment-with-init proxy caches
419
- // the result. Without this, any lazy storage call deferred until after
420
- // shutdown() (e.g. background tool/agent registration paths in Mastra)
421
- // races our libsqlClient.close() and surfaces as an unhandled
422
- // CLIENT_CLOSED rejection. We retain the promise so shutdown() can
423
- // settle it before closing the client (a swallowed rejection here is
424
- // fine — Mastra retains its own init proxy and surfaces real init
425
- // errors at the next storage call site).
426
- this.storageReady = this.storage.init().catch(() => undefined);
427
394
  }
428
395
  /**
429
396
  * @requirements
430
397
  * - MUST disconnect the mcpClient for every active agent before clearing state.
431
398
  * - MUST clear the `activeAgents` map.
432
- * - MUST shut down the global `this.mastra` orchestrator.
433
- * - MUST close the libsql client so the underlying SQLite handle is released
434
- * (Windows blocks fs.rm of the storage dir while the WAL/shm files are open;
435
- * see forcedotcom/agentic-dx#429).
399
+ * - MUST shut down the global `this.mastra` orchestrator. Mastra.shutdown() awaits
400
+ * `storage.close()`, which checkpoints the WAL and unlinks the -wal/-shm sidecars
401
+ * so a subsequent `fs.rm` of the storage dir succeeds on Windows
402
+ * (forcedotcom/agentic-dx#429, mastra-ai/mastra#17285).
436
403
  */
437
404
  async shutdown() {
438
405
  await Promise.all([...this.activeAgents.values()].map(async (state) => {
@@ -448,29 +415,6 @@ export class MastraHarness {
448
415
  }));
449
416
  this.activeAgents.clear();
450
417
  await this.mastra?.shutdown();
451
- // Settle the constructor's eager init before closing — see the
452
- // `storageReady` field comment for the why.
453
- await this.storageReady;
454
- // Fold the WAL into the main DB and switch journal_mode=DELETE
455
- // so SQLite unlinks the -wal/-shm sidecars on close. Without this,
456
- // Windows holds the sidecars open well past `client.close()` and
457
- // racing `fs.rm` calls (e.g. vitest's per-test cleanup) crash the
458
- // worker. Mirrors the fix Mastra shipped on `LibSQLStore.close()`
459
- // in `@mastra/libsql@1.12.0-alpha.0`. Replace this block with a
460
- // call to `storage.close()` once that release ships stable — see
461
- // https://github.com/forcedotcom/agentic-dx/issues/475.
462
- try {
463
- await this.libsqlClient.execute('PRAGMA wal_checkpoint(TRUNCATE);');
464
- await this.libsqlClient.execute('PRAGMA journal_mode=DELETE;');
465
- }
466
- catch (err) {
467
- // Best-effort: still close even if checkpoint fails (e.g. the
468
- // client was already closed by a prior shutdown path).
469
- this.buses.getLogBus()?.warn('libsql WAL checkpoint failed before close', {
470
- error: getErrorMessage(err),
471
- });
472
- }
473
- this.libsqlClient.close();
474
418
  this.buses.dispose();
475
419
  }
476
420
  onTelemetry(callback) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/sfdx-agent-harness-mastra",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Mastra-backed AgentHarness implementation for @salesforce/sfdx-agent-sdk",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,37 +29,36 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "@ai-sdk/provider": "^3.0.10",
32
- "@libsql/client": "^0.15.15",
33
- "@mastra/core": "^1.37.1",
34
- "@mastra/libsql": "^1.11.1",
35
- "@mastra/mcp": "^1.8.1",
36
- "@mastra/memory": "^1.20.0",
37
- "@mastra/schema-compat": "^1.2.10",
38
- "@salesforce/agentic-common": "0.9.0",
39
- "@salesforce/llm-gateway-sdk": "0.13.0"
32
+ "@mastra/core": "^1.41.0",
33
+ "@mastra/libsql": "^1.12.1",
34
+ "@mastra/mcp": "^1.9.1",
35
+ "@mastra/memory": "^1.20.2",
36
+ "@mastra/schema-compat": "^1.2.11",
37
+ "@salesforce/agentic-common": "0.10.0",
38
+ "@salesforce/llm-gateway-sdk": "0.14.0"
40
39
  },
41
40
  "peerDependencies": {
42
- "@salesforce/sfdx-agent-sdk": "0.17.0"
41
+ "@salesforce/sfdx-agent-sdk": "0.18.0"
43
42
  },
44
43
  "devDependencies": {
45
44
  "@eslint/js": "^10.0.1",
46
- "@salesforce/sfdx-agent-sdk": "0.17.0",
47
- "@types/node": "^22.19.19",
45
+ "@salesforce/sfdx-agent-sdk": "0.18.0",
46
+ "@types/node": "^22.19.20",
48
47
  "@vitest/coverage-istanbul": "^4.1.8",
49
48
  "@vitest/eslint-plugin": "^1.6.19",
50
49
  "eslint": "^10.4.1",
51
50
  "eslint-config-prettier": "^10.1.8",
52
51
  "eslint-import-resolver-typescript": "^4.4.5",
53
52
  "eslint-plugin-import": "^2.32.0",
54
- "eslint-plugin-n": "^18.0.1",
53
+ "eslint-plugin-n": "^18.1.0",
55
54
  "globals": "^17.6.0",
56
55
  "lint-staged": "^17.0.7",
57
- "prettier": "^3.8.3",
56
+ "prettier": "^3.8.4",
58
57
  "rimraf": "^6.1.3",
59
58
  "tsx": "^4.22.4",
60
59
  "typescript": "^6.0.3",
61
- "typescript-eslint": "^8.60.1",
62
- "vitest": "^4.1.7"
60
+ "typescript-eslint": "^8.61.0",
61
+ "vitest": "^4.1.8"
63
62
  },
64
63
  "engines": {
65
64
  "node": ">=22.19.0"