@salesforce/sfdx-agent-harness-mastra 0.16.0 → 0.18.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 +16 -0
- package/README.md +5 -7
- package/dist/mastra-approval-coordinator.d.ts +4 -5
- package/dist/mastra-approval-coordinator.js +48 -63
- package/dist/mastra-harness.d.ts +4 -12
- package/dist/mastra-harness.js +5 -61
- package/package.json +15 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
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.18.0] - 2026-06-11
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- **harness-mastra**: drive one resume per pending approval for parallel batches ([#587](https://github.com/forcedotcom/agentic-dx/pull/587))
|
|
10
|
+
|
|
11
|
+
## [0.17.0] - 2026-06-09
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
- **harness-mastra**: drop inline WAL-pragma workaround now that LibSQLStore.close() ships stable ([#576](https://github.com/forcedotcom/agentic-dx/pull/576))
|
|
15
|
+
|
|
16
|
+
### Chores
|
|
17
|
+
- **deps**: bump dependencies across packages @W-22695116@ ([#577](https://github.com/forcedotcom/agentic-dx/pull/577))
|
|
18
|
+
- **deps**: bump the mastra group across 1 directory with 5 updates ([#569](https://github.com/forcedotcom/agentic-dx/pull/569))
|
|
19
|
+
- **deps**: bump @libsql/client from 0.15.15 to 0.17.3 ([#570](https://github.com/forcedotcom/agentic-dx/pull/570))
|
|
20
|
+
- **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))
|
|
21
|
+
|
|
6
22
|
## [0.16.0] - 2026-06-09
|
|
7
23
|
|
|
8
24
|
### 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
|
|
30
|
-
on Windows is asynchronous at the OS level. After
|
|
31
|
-
|
|
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.
|
|
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
|
|
|
@@ -143,12 +143,11 @@ export declare class MastraApprovalCoordinator {
|
|
|
143
143
|
*/
|
|
144
144
|
private currentRunId;
|
|
145
145
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* closes to decide whether to drive a resume.
|
|
146
|
+
* ToolCallIds Mastra is currently suspended on. Mastra retains a separate
|
|
147
|
+
* workflow snapshot step per id, so the pump must drive one resume per
|
|
148
|
+
* pending id with `{ toolCallId }` to disambiguate (#586).
|
|
150
149
|
*/
|
|
151
|
-
private
|
|
150
|
+
private readonly pendingSuspendIds;
|
|
152
151
|
/** Consumer-tool: bound parkers, keyed by `toolCallId`. `submitToolResult` resolves these. */
|
|
153
152
|
private readonly pendingByToolCallId;
|
|
154
153
|
/**
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
import { AgentSDKError, AgentSDKErrorType, } from '@salesforce/sfdx-agent-sdk';
|
|
6
6
|
import { GenSink } from '@salesforce/sfdx-agent-sdk/harness';
|
|
7
7
|
import { MastraEventAdapter } from './mastra-event-adapter.js';
|
|
8
|
+
function pickIdWithDecision(pendingIds, decisions) {
|
|
9
|
+
for (const id of pendingIds) {
|
|
10
|
+
if (decisions.has(id))
|
|
11
|
+
return id;
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
8
15
|
/**
|
|
9
16
|
* Per-`(agentId, threadId)` coordinator that subsumes the pre-#529
|
|
10
17
|
* `MastraStreamBroker` + `activeRuns` pair into one object owning a single
|
|
@@ -72,12 +79,11 @@ export class MastraApprovalCoordinator {
|
|
|
72
79
|
*/
|
|
73
80
|
currentRunId = '';
|
|
74
81
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* closes to decide whether to drive a resume.
|
|
82
|
+
* ToolCallIds Mastra is currently suspended on. Mastra retains a separate
|
|
83
|
+
* workflow snapshot step per id, so the pump must drive one resume per
|
|
84
|
+
* pending id with `{ toolCallId }` to disambiguate (#586).
|
|
79
85
|
*/
|
|
80
|
-
|
|
86
|
+
pendingSuspendIds = new Set();
|
|
81
87
|
/** Consumer-tool: bound parkers, keyed by `toolCallId`. `submitToolResult` resolves these. */
|
|
82
88
|
pendingByToolCallId = new Map();
|
|
83
89
|
/**
|
|
@@ -210,7 +216,7 @@ export class MastraApprovalCoordinator {
|
|
|
210
216
|
this.initial.push({ type: 'finish', finishReason: 'error' });
|
|
211
217
|
this.initial.end();
|
|
212
218
|
}
|
|
213
|
-
this.
|
|
219
|
+
this.pendingSuspendIds.clear();
|
|
214
220
|
this.runTeardownCallbacks();
|
|
215
221
|
}
|
|
216
222
|
// ───────────────────────── settle methods ───────────────────────────────
|
|
@@ -233,14 +239,9 @@ export class MastraApprovalCoordinator {
|
|
|
233
239
|
this.consumerSettled.add(toolCallId);
|
|
234
240
|
this.cancelTimer(toolCallId);
|
|
235
241
|
this.decisions.set(toolCallId, decision);
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
// when it sees the matching suspension and drives the resume. If
|
|
240
|
-
// the pump is currently parked on `awaitContinuation` (saw the
|
|
241
|
-
// suspension first, decision arrived second), wake it so it
|
|
242
|
-
// re-checks `decisions`.
|
|
243
|
-
if (this.continuationResolver && this.currentSuspendId === toolCallId) {
|
|
242
|
+
// Wake the pump if it's parked on `awaitContinuation` waiting for
|
|
243
|
+
// a decision on a pending id.
|
|
244
|
+
if (this.continuationResolver && this.pendingSuspendIds.has(toolCallId)) {
|
|
244
245
|
const resolve = this.continuationResolver;
|
|
245
246
|
this.continuationResolver = undefined;
|
|
246
247
|
resolve('continued');
|
|
@@ -330,33 +331,29 @@ export class MastraApprovalCoordinator {
|
|
|
330
331
|
}
|
|
331
332
|
if (this.aborted || this.disposed || this.timedOut)
|
|
332
333
|
return;
|
|
333
|
-
// outcome === 'suspended':
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
|
|
338
|
-
const suspendId = this.currentSuspendId;
|
|
339
|
-
if (suspendId === null) {
|
|
340
|
-
// Defensive: stream ended without a suspension. Treat
|
|
341
|
-
// as terminal.
|
|
334
|
+
// outcome === 'suspended': drive one resume per outer
|
|
335
|
+
// iteration. For parallel batches, all but the last resume
|
|
336
|
+
// returns a stream that closes silently while still
|
|
337
|
+
// suspended — the pump re-enters here to drive the next id.
|
|
338
|
+
if (this.pendingSuspendIds.size === 0) {
|
|
342
339
|
if (!this.initial.isEnded())
|
|
343
340
|
this.initial.end();
|
|
344
341
|
return;
|
|
345
342
|
}
|
|
346
|
-
let
|
|
347
|
-
if (
|
|
348
|
-
// Park for a decision (or teardown).
|
|
343
|
+
let nextId = pickIdWithDecision(this.pendingSuspendIds, this.decisions);
|
|
344
|
+
if (nextId === undefined) {
|
|
349
345
|
const cont = await this.awaitContinuation();
|
|
350
346
|
if (cont === 'done')
|
|
351
347
|
return;
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
buffered = this.decisions.get(suspendId);
|
|
355
|
-
if (buffered === undefined)
|
|
348
|
+
nextId = pickIdWithDecision(this.pendingSuspendIds, this.decisions);
|
|
349
|
+
if (nextId === undefined)
|
|
356
350
|
return;
|
|
357
351
|
}
|
|
358
|
-
|
|
359
|
-
|
|
352
|
+
const decision = this.decisions.get(nextId);
|
|
353
|
+
if (decision === undefined)
|
|
354
|
+
return;
|
|
355
|
+
this.pendingSuspendIds.delete(nextId);
|
|
356
|
+
const next = await this.driveResumeReturning(nextId, decision);
|
|
360
357
|
if (next === 'done')
|
|
361
358
|
return;
|
|
362
359
|
currentStream = next;
|
|
@@ -434,22 +431,21 @@ export class MastraApprovalCoordinator {
|
|
|
434
431
|
continue;
|
|
435
432
|
}
|
|
436
433
|
if (event.type === 'tool-approval-request') {
|
|
437
|
-
//
|
|
438
|
-
//
|
|
439
|
-
//
|
|
440
|
-
// auto-approve silently.
|
|
434
|
+
// Parallel batches emit one chunk per suspension before
|
|
435
|
+
// the stream closes; accumulate every id and let the
|
|
436
|
+
// read loop continue to the natural close.
|
|
441
437
|
const tc = event.toolCall;
|
|
442
438
|
this.toolCallArgs.set(tc.toolCallId, tc.args);
|
|
443
|
-
this.
|
|
439
|
+
this.pendingSuspendIds.add(tc.toolCallId);
|
|
444
440
|
sawSuspension = true;
|
|
445
441
|
if (this.consumerToolNames.has(tc.toolName)) {
|
|
446
442
|
// Consumer tools bypass the gate per the
|
|
447
443
|
// StreamOptions.requireToolApproval JSDoc. Auto-
|
|
448
444
|
// approve silently — no ChatEvent surfaces, and the
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
445
|
+
// pump loop drives `agent.approveToolCall` when it
|
|
446
|
+
// picks up the buffered decision. After Mastra
|
|
447
|
+
// resumes, the bridge `execute` parker runs and
|
|
448
|
+
// `submitToolResult` settles it — same shape as
|
|
453
449
|
// non-approval-mode consumer-tool flow.
|
|
454
450
|
this.settledByCoordinator.add(tc.toolCallId);
|
|
455
451
|
this.decisions.set(tc.toolCallId, { kind: 'approve' });
|
|
@@ -459,14 +455,7 @@ export class MastraApprovalCoordinator {
|
|
|
459
455
|
// pre-emit in tool-call routing).
|
|
460
456
|
this.emitApprovalRequest(tc.toolCallId, tc.toolName, tc.args);
|
|
461
457
|
}
|
|
462
|
-
|
|
463
|
-
// snapshot persists before we attempt a resume.
|
|
464
|
-
while (true) {
|
|
465
|
-
const { done: d } = await reader.read();
|
|
466
|
-
if (d)
|
|
467
|
-
break;
|
|
468
|
-
}
|
|
469
|
-
return 'suspended';
|
|
458
|
+
continue;
|
|
470
459
|
}
|
|
471
460
|
this.routeEnriched(event);
|
|
472
461
|
}
|
|
@@ -490,17 +479,13 @@ export class MastraApprovalCoordinator {
|
|
|
490
479
|
/* best-effort: lock may already be released after a thrown read */
|
|
491
480
|
}
|
|
492
481
|
}
|
|
493
|
-
// Stream closed
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
// have arrived in the loop above. So (b) shouldn't reach here.
|
|
501
|
-
// Treat as terminal: sink is either ended already (teardown) or
|
|
502
|
-
// we must end it now.
|
|
503
|
-
if (!sawTerminal && !sawSuspension && !this.initial.isEnded()) {
|
|
482
|
+
// Stream closed without `finish`/`error`. If any suspension is
|
|
483
|
+
// pending (just observed, or carried over from a prior non-final
|
|
484
|
+
// resume that closed silently), defer to the pump loop's drive.
|
|
485
|
+
if (sawSuspension || this.pendingSuspendIds.size > 0) {
|
|
486
|
+
return 'suspended';
|
|
487
|
+
}
|
|
488
|
+
if (!sawTerminal && !this.initial.isEnded()) {
|
|
504
489
|
this.initial.end();
|
|
505
490
|
}
|
|
506
491
|
return 'terminal';
|
|
@@ -540,10 +525,10 @@ export class MastraApprovalCoordinator {
|
|
|
540
525
|
return output.fullStream;
|
|
541
526
|
}
|
|
542
527
|
catch (err) {
|
|
528
|
+
// Route through teardown so siblings in `pendingSuspendIds`
|
|
529
|
+
// settle as auto-resolved rather than silently orphaning.
|
|
543
530
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
544
|
-
this.
|
|
545
|
-
this.initial.push({ type: 'finish', finishReason: 'error' });
|
|
546
|
-
this.initial.end();
|
|
531
|
+
this.teardown('pump-error', error, 'pump-error');
|
|
547
532
|
return 'done';
|
|
548
533
|
}
|
|
549
534
|
}
|
package/dist/mastra-harness.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
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;
|
package/dist/mastra-harness.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
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.
|
|
3
|
+
"version": "0.18.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
|
-
"@
|
|
33
|
-
"@mastra/
|
|
34
|
-
"@mastra/
|
|
35
|
-
"@mastra/
|
|
36
|
-
"@mastra/
|
|
37
|
-
"@
|
|
38
|
-
"@salesforce/
|
|
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.
|
|
41
|
+
"@salesforce/sfdx-agent-sdk": "0.19.0"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
44
|
"@eslint/js": "^10.0.1",
|
|
46
|
-
"@salesforce/sfdx-agent-sdk": "0.
|
|
47
|
-
"@types/node": "^22.19.
|
|
45
|
+
"@salesforce/sfdx-agent-sdk": "0.19.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
|
|
53
|
+
"eslint-plugin-n": "^18.1.0",
|
|
55
54
|
"globals": "^17.6.0",
|
|
56
55
|
"lint-staged": "^17.0.7",
|
|
57
|
-
"prettier": "^3.8.
|
|
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.
|
|
62
|
-
"vitest": "^4.1.
|
|
60
|
+
"typescript-eslint": "^8.61.0",
|
|
61
|
+
"vitest": "^4.1.8"
|
|
63
62
|
},
|
|
64
63
|
"engines": {
|
|
65
64
|
"node": ">=22.19.0"
|