@vitest-agent/engine 1.0.6 → 1.1.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.
- package/index.d.ts +27 -116
- package/index.js +2 -1
- package/layers/ConfigLive.js +1 -2
- package/layers/DataReaderLive.js +1 -2
- package/layers/DataStoreLive.js +21 -6
- package/layers/DetailResolverLive.js +1 -2
- package/layers/DiscoveryRegistryLive.js +1 -2
- package/layers/EnvironmentDetectorLive.js +1 -2
- package/layers/EnvironmentDetectorTest.js +1 -2
- package/layers/ExecutorResolverLive.js +1 -2
- package/layers/HistoryTrackerLive.js +1 -2
- package/layers/HistoryTrackerTest.js +1 -2
- package/layers/LoggerLive.js +1 -2
- package/layers/OutputPipelineLive.js +1 -2
- package/layers/PathResolutionLive.js +1 -2
- package/layers/PerClientSessionMapLive.js +1 -2
- package/layers/ProjectDiscoveryLive.js +1 -2
- package/layers/ProjectDiscoveryTest.js +1 -2
- package/layers/ProjectIdentityLive.js +1 -2
- package/layers/RunContextLive.js +1 -2
- package/lib/format-triage.js +1 -2
- package/lib/format-wrapup.js +1 -2
- package/migrations/0001_initial.js +1 -2
- package/migrations/0002_test_artifacts.js +1 -2
- package/migrations/index.js +1 -2
- package/migrations/registry_0001_initial.js +1 -2
- package/migrations/session_map_0001_initial.js +1 -2
- package/package.json +18 -18
- package/platform.js +4 -4
- package/programs/end-agent.js +1 -2
- package/programs/hook-paths.js +1 -2
- package/programs/platform-sidecar.js +1 -2
- package/programs/record-session.js +1 -2
- package/programs/record-tdd-artifact.js +1 -2
- package/programs/record-turn.js +1 -2
- package/programs/record-workspace-changes.js +1 -2
- package/programs/register-agent.js +1 -2
- package/programs/resolve-session-for-recording.js +1 -2
- package/programs/session-env.js +1 -2
- package/project-dir.js +1 -2
- package/services/Config.js +1 -2
- package/services/DataReader.js +1 -2
- package/services/DataStore.js +1 -2
- package/services/DetailResolver.js +1 -2
- package/services/DiscoveryRegistry.js +1 -2
- package/services/EnvironmentDetector.js +1 -2
- package/services/ExecutorResolver.js +1 -2
- package/services/HistoryTracker.js +1 -2
- package/services/PerClientSessionMap.js +1 -2
- package/services/ProjectDiscovery.js +1 -2
- package/services/ProjectIdentity.js +1 -2
- package/services/RunContext.js +1 -2
- package/services/idempotency.js +1 -2
- package/sql/assemblers.js +1 -2
- package/stores.js +1 -2
- package/testing/layers.js +1 -2
- package/testing.d.ts +0 -12
- package/testing.js +1 -2
- package/utils/ensure-migrated.js +1 -2
- package/utils/failure-signature.js +1 -2
- package/utils/persist-transaction.js +84 -0
- package/utils/resolve-data-path.js +1 -2
- package/utils/resolve-project-key-from-cwd.js +1 -2
- package/utils/resolve-workspace-key.js +1 -2
- package/version.js +2 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/services/PerClientSessionMap.ts
|
|
4
4
|
/**
|
|
5
5
|
* Read-only side of the session map.
|
|
6
6
|
*
|
|
@@ -18,5 +18,4 @@ var PerClientSessionMapReader = class extends Context.Service()("vitest-agent/Pe
|
|
|
18
18
|
*/
|
|
19
19
|
var PerClientSessionMapWriter = class extends Context.Service()("vitest-agent/PerClientSessionMapWriter") {};
|
|
20
20
|
|
|
21
|
-
//#endregion
|
|
22
21
|
export { PerClientSessionMapReader, PerClientSessionMapWriter };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Context } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/services/ProjectDiscovery.ts
|
|
4
4
|
/** @public */
|
|
5
5
|
var ProjectDiscovery = class extends Context.Service()("vitest-agent/ProjectDiscovery") {};
|
|
6
6
|
|
|
7
|
-
//#endregion
|
|
8
7
|
export { ProjectDiscovery };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { canonicalizeGitUrl, gitUrlToProjectKey, normalizeWorkspaceKey } from "@vitest-agent/sdk";
|
|
2
2
|
import { Context } from "effect";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/services/ProjectIdentity.ts
|
|
5
5
|
const isUseful = (value) => value !== void 0 && value.trim().length > 0;
|
|
6
6
|
/**
|
|
7
7
|
* Pure priority resolver. Returns `null` when no candidate produces a
|
|
@@ -58,5 +58,4 @@ const resolveProjectIdentityFromCandidates = (candidates) => {
|
|
|
58
58
|
*/
|
|
59
59
|
var ProjectIdentity = class extends Context.Service()("vitest-agent/ProjectIdentity") {};
|
|
60
60
|
|
|
61
|
-
//#endregion
|
|
62
61
|
export { ProjectIdentity, resolveProjectIdentityFromCandidates };
|
package/services/RunContext.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/services/RunContext.ts
|
|
4
4
|
/**
|
|
5
5
|
* Per-run snapshot of the workspace's git state and host context.
|
|
6
6
|
* Every field is nullable: a non-git workspace has all-NULL git
|
|
@@ -49,5 +49,4 @@ var RunContext$ = class extends Context.Service()("vitest-agent/RunContextServic
|
|
|
49
49
|
*/
|
|
50
50
|
const RunContextService = RunContext$;
|
|
51
51
|
|
|
52
|
-
//#endregion
|
|
53
52
|
export { AgentContext, RunContext, RunContext$, RunContextService };
|
package/services/idempotency.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/services/idempotency.ts
|
|
4
4
|
/**
|
|
5
5
|
* Sentinel substituted for `parentAgentId` when the value is `null`.
|
|
6
6
|
* Avoids ambiguity around hashing the literal string "null" or empty
|
|
@@ -54,5 +54,4 @@ const base32Encode = (bytes) => {
|
|
|
54
54
|
return output;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
//#endregion
|
|
58
57
|
export { IDEMPOTENCY_ROOT_SENTINEL, deriveIdempotencyKey };
|
package/sql/assemblers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { historyKey } from "../services/HistoryTracker.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/sql/assemblers.ts
|
|
4
4
|
/**
|
|
5
5
|
* Builds a `CacheManifest` from an array of test_runs aggregation rows.
|
|
6
6
|
*
|
|
@@ -65,5 +65,4 @@ function assembleHistoryRecord(rows) {
|
|
|
65
65
|
return record;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
//#endregion
|
|
69
68
|
export { assembleHistoryRecord, assembleManifest };
|
package/stores.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context, Effect } from "effect";
|
|
2
2
|
import { SqlClient } from "effect/sql/SqlClient";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/stores.ts
|
|
5
5
|
/**
|
|
6
6
|
* The ledger options every store opens with: adopt a 2.x effect/sql ledger
|
|
7
7
|
* once, on the first open.
|
|
@@ -39,5 +39,4 @@ var RegistryStore = class extends Context.Service()("vitest-agent/RegistryStore"
|
|
|
39
39
|
*/
|
|
40
40
|
var SessionMapStore = class extends Context.Service()("vitest-agent/SessionMapStore") {};
|
|
41
41
|
|
|
42
|
-
//#endregion
|
|
43
42
|
export { LEDGER_OPTIONS, RegistryStore, SessionMapStore, toStoreMigrations };
|
package/testing/layers.js
CHANGED
|
@@ -3,7 +3,7 @@ import { DataStoreLive } from "../layers/DataStoreLive.js";
|
|
|
3
3
|
import { NodePlatformLayer, makeSqliteStack } from "../platform.js";
|
|
4
4
|
import { Layer } from "effect";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/testing/layers.ts
|
|
7
7
|
/** @public */
|
|
8
8
|
function makeTestLayer(filename) {
|
|
9
9
|
const { SqliteLayer, MigratorLayer } = makeSqliteStack(filename);
|
|
@@ -12,5 +12,4 @@ function makeTestLayer(filename) {
|
|
|
12
12
|
/** @public */
|
|
13
13
|
const DataStoreTestLayer = makeTestLayer(":memory:");
|
|
14
14
|
|
|
15
|
-
//#endregion
|
|
16
15
|
export { DataStoreTestLayer, makeTestLayer };
|
package/testing.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ import "@effect/sql-sqlite-node/SqliteClient";
|
|
|
5
5
|
import { StoreError, StoreMigrationError } from "@effected/store";
|
|
6
6
|
import "effect/sql/SqlClient";
|
|
7
7
|
import { SqlError } from "effect/sql/SqlError";
|
|
8
|
-
//#region src/services/DataStore.d.ts
|
|
9
8
|
/** @public */
|
|
10
9
|
interface CreateGoalInput {
|
|
11
10
|
readonly tddTaskId: number;
|
|
@@ -530,8 +529,6 @@ declare const DataStore_base: Context.ServiceClass<DataStore, "vitest-agent/Data
|
|
|
530
529
|
}>;
|
|
531
530
|
/** @public */
|
|
532
531
|
export declare class DataStore extends DataStore_base {}
|
|
533
|
-
//#endregion
|
|
534
|
-
//#region src/services/DataReader.d.ts
|
|
535
532
|
/** @public */
|
|
536
533
|
interface ProjectRunSummary {
|
|
537
534
|
readonly project: string;
|
|
@@ -1061,8 +1058,6 @@ declare const DataReader_base: Context.ServiceClass<DataReader, "vitest-agent/Da
|
|
|
1061
1058
|
}>;
|
|
1062
1059
|
/** @public */
|
|
1063
1060
|
export declare class DataReader extends DataReader_base {}
|
|
1064
|
-
//#endregion
|
|
1065
|
-
//#region src/platform.d.ts
|
|
1066
1061
|
/**
|
|
1067
1062
|
* What building a SQLite stack, and so `PlatformLive`, can fail with:
|
|
1068
1063
|
* opening the database (`SqlError`), `@effected/store`'s setup /
|
|
@@ -1070,8 +1065,6 @@ export declare class DataReader extends DataReader_base {}
|
|
|
1070
1065
|
* @public
|
|
1071
1066
|
*/
|
|
1072
1067
|
type PlatformLiveError = SqlError | StoreError | StoreMigrationError;
|
|
1073
|
-
//#endregion
|
|
1074
|
-
//#region src/migrations/index.d.ts
|
|
1075
1068
|
/**
|
|
1076
1069
|
* Every migration that must run against a per-project `data.db`, keyed by
|
|
1077
1070
|
* migration id in application order.
|
|
@@ -1093,14 +1086,10 @@ export declare const PROJECT_MIGRATIONS: {
|
|
|
1093
1086
|
readonly "0001_initial": import("effect/Effect").Effect<void, import("effect/sql/SqlError").SqlError, import("effect/sql/SqlClient").SqlClient>;
|
|
1094
1087
|
readonly "0002_test_artifacts": import("effect/Effect").Effect<void, import("effect/sql/SqlError").SqlError, import("effect/sql/SqlClient").SqlClient>;
|
|
1095
1088
|
};
|
|
1096
|
-
//#endregion
|
|
1097
|
-
//#region src/testing/layers.d.ts
|
|
1098
1089
|
/** @public */
|
|
1099
1090
|
export declare function makeTestLayer(filename: string): Layer.Layer<DataReader | DataStore | import("effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | import("@effect/platform-node/NodeServices").NodeServices, PlatformLiveError, never>;
|
|
1100
1091
|
/** @public */
|
|
1101
1092
|
export declare const DataStoreTestLayer: Layer.Layer<DataReader | DataStore | import("effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | import("@effect/platform-node/NodeServices").NodeServices, PlatformLiveError, never>;
|
|
1102
|
-
//#endregion
|
|
1103
|
-
//#region src/testing/index.d.ts
|
|
1104
1093
|
/** @public */
|
|
1105
1094
|
export declare function empty(filename: string): Layer.Layer<DataReader | DataStore | import("effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | import("@effect/platform-node/NodeServices").NodeServices, PlatformLiveError, never>;
|
|
1106
1095
|
/** @public */
|
|
@@ -1111,6 +1100,5 @@ export declare function withFailures(filename: string): Layer.Layer<DataReader |
|
|
|
1111
1100
|
export declare function flaky(filename: string): Layer.Layer<DataReader | DataStore | import("effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | import("@effect/platform-node/NodeServices").NodeServices, import("@vitest-agent/sdk").DataStoreError | PlatformLiveError, never>;
|
|
1112
1101
|
/** @public */
|
|
1113
1102
|
export declare function withTddTask(filename: string): Layer.Layer<DataReader | DataStore | import("effect/sql/SqlClient").SqlClient | import("@effect/sql-sqlite-node/SqliteClient").SqliteClient | import("@effect/platform-node/NodeServices").NodeServices, import("@vitest-agent/sdk").BehaviorNotFoundError | import("@vitest-agent/sdk").DataStoreError | import("@vitest-agent/sdk").GoalNotFoundError | import("@vitest-agent/sdk").IllegalStatusTransitionError | import("@vitest-agent/sdk").TddTaskAlreadyEndedError | import("@vitest-agent/sdk").TddTaskNotFoundError | PlatformLiveError, never>;
|
|
1114
|
-
//#endregion
|
|
1115
1103
|
export { type AcceptanceMetrics, Agent, AgentId, AgentNotFoundError, AgentReport, type ArtifactKind, type ArtifactSuite, type AssociateRunSessionInput, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorStatus, CacheManifest, type ChangeKind, ChatId, type CitedArtifact, type CitedArtifactRow, type ClassificationQueryOptions, type CommitChangesEntry, CoverageBaselines, CoverageReport, type CreateBehaviorInput, type CreateGoalInput, type CurrentTddPhase, DataStoreError, type EndTddTaskInput, type FailureSignatureDetail, type FailureSignatureWriteInput, type FileCoverageInput, FileCoverageReport, type FlakyTest, GoalDetail, GoalNotFoundError, GoalRow, GoalStatus, type HistoryQueryOptions, HistoryRecord, type HypothesisDetail, type HypothesisInput, IdempotencyHit, type IdempotentResponseInput, type IllegalStatusTransitionEntity, IllegalStatusTransitionError, type ModuleInput, type ModuleListEntry, type NoteInput, type NoteRow, type PersistedAttachment, type PersistentFailure, type Phase, type PlatformLiveError, type ProjectRunSummary, type RegisterAgentInput, RegistrationConflictError, type ResolvedThresholds, type RunChangedFile, type RunInvocationMethod, type SessionDetail, type SessionInput, type SettingsInput, type SettingsListEntry, type SettingsRow, type StackFrameInput, type SuiteInput, type SuiteListEntry, type TagInventoryRow, type TddArtifactDetail, type TddArtifactRow, type TddPhaseDetail, TddTaskAlreadyEndedError, type TddTaskDetail, type TddTaskEndOutcome, type TddTaskInput, TddTaskNotFoundError, type TddTaskSummary, type TestAnnotationInput, type TestAnnotationRow, type TestArtifactInput, type TestArtifactQueryOptions, type TestArtifactRow, type TestAttachmentInput, type TestCaseInput, type TestError, type TestErrorInput, type TestListEntry, type TestLookupOptions, type TestRunInput, TrendEntry, TrendRecord, type TurnInput, type TurnSearchOptions, type TurnSummary, type UpdateBehaviorInput, type UpdateGoalInput, type ValidateHypothesisInput, type WriteCommitInput, type WriteRunChangedFilesInput, type WriteTddArtifactInput, type WriteTddPhaseInput, type WriteTddPhaseOutput };
|
|
1116
1104
|
//# sourceMappingURL=testing.d.ts.map
|
package/testing.js
CHANGED
|
@@ -5,7 +5,7 @@ import { DataStoreTestLayer, makeTestLayer } from "./testing/layers.js";
|
|
|
5
5
|
import { Agent, AgentId, AgentNotFoundError, AgentReport, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorStatus, CacheManifest, ChatId, CoverageBaselines, CoverageReport, DataStoreError, FileCoverageReport, GoalDetail, GoalNotFoundError, GoalRow, GoalStatus, HistoryRecord, IdempotencyHit, IllegalStatusTransitionError, RegistrationConflictError, TddTaskAlreadyEndedError, TddTaskNotFoundError, TrendEntry, TrendRecord } from "@vitest-agent/sdk";
|
|
6
6
|
import { Effect, Layer } from "effect";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// src/testing/index.ts
|
|
9
9
|
/** @public */
|
|
10
10
|
function empty(filename) {
|
|
11
11
|
return makeTestLayer(filename);
|
|
@@ -239,5 +239,4 @@ function withTddTask(filename) {
|
|
|
239
239
|
return Layer.effectDiscard(seed).pipe(Layer.provideMerge(base));
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
//#endregion
|
|
243
242
|
export { Agent, AgentId, AgentNotFoundError, AgentReport, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorStatus, CacheManifest, ChatId, CoverageBaselines, CoverageReport, DataReader, DataStore, DataStoreError, DataStoreTestLayer, FileCoverageReport, GoalDetail, GoalNotFoundError, GoalRow, GoalStatus, HistoryRecord, IdempotencyHit, IllegalStatusTransitionError, PROJECT_MIGRATIONS, RegistrationConflictError, TddTaskAlreadyEndedError, TddTaskNotFoundError, TrendEntry, TrendRecord, empty, flaky, makeTestLayer, singlePassingRun, withFailures, withTddTask };
|
package/utils/ensure-migrated.js
CHANGED
|
@@ -3,7 +3,7 @@ import { NodePlatformLayer, makeSqliteStack } from "../platform.js";
|
|
|
3
3
|
import { Effect, Layer } from "effect";
|
|
4
4
|
import { SqlClient } from "effect/sql/SqlClient";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/utils/ensure-migrated.ts
|
|
7
7
|
const GLOBAL_KEY = Symbol.for("vitest-agent/migration-promises");
|
|
8
8
|
const getCache = () => {
|
|
9
9
|
const g = globalThis;
|
|
@@ -49,5 +49,4 @@ function _resetMigrationCacheForTesting() {
|
|
|
49
49
|
getCache().clear();
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
//#endregion
|
|
53
52
|
export { _resetMigrationCacheForTesting, ensureMigrated };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/utils/failure-signature.ts
|
|
4
4
|
const ASSERTION_REGEX = /(toBe|toEqual|toContain|toMatch|toThrow|toBeNull|toBeUndefined|toBeTruthy|toBeFalsy|toBeGreaterThan|toBeLessThan|toBeInstanceOf|toBeCloseTo|toHaveBeenCalled|toHaveBeenCalledWith|toHaveProperty|toHaveLength)\s*\(([^)]*)\)/;
|
|
5
5
|
const typeTagOf = (literal) => {
|
|
6
6
|
const trimmed = literal.trim();
|
|
@@ -30,5 +30,4 @@ const computeFailureSignature = (input) => {
|
|
|
30
30
|
return createHash("sha256").update(key).digest("hex").substring(0, 16);
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
//#endregion
|
|
34
33
|
export { computeFailureSignature, normalizeAssertionShape };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DataStoreError, extractSqlReason } from "@vitest-agent/sdk";
|
|
2
|
+
import { Context, Effect, References } from "effect";
|
|
3
|
+
import { SqlClient } from "effect/sql/SqlClient";
|
|
4
|
+
import { isSqlError } from "effect/sql/SqlError";
|
|
5
|
+
|
|
6
|
+
// src/utils/persist-transaction.ts
|
|
7
|
+
/**
|
|
8
|
+
* The open persist batch, or `undefined` outside {@link withPersistTransaction}.
|
|
9
|
+
* Read by `DataStoreLive`; not part of the public surface.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
const PersistBatch = Context.Reference("@vitest-agent/engine/PersistBatch", { defaultValue: () => void 0 });
|
|
14
|
+
/** Matches the per-write window `DataStoreLive.writeHistory` keeps outside a batch. */
|
|
15
|
+
const HISTORY_WINDOW = 10;
|
|
16
|
+
/**
|
|
17
|
+
* Keep the newest {@link HISTORY_WINDOW} rows of every
|
|
18
|
+
* `(project, module_path, full_name)` series that has a row from `runId`,
|
|
19
|
+
* in one statement. The same rows the per-write prune deletes: a series is
|
|
20
|
+
* unique on `(project, module_path, full_name, timestamp)`, so there are no
|
|
21
|
+
* timestamp ties for `ROW_NUMBER` to break arbitrarily, and every series
|
|
22
|
+
* this run wrote carries `run_id = runId` (the upsert overwrites it).
|
|
23
|
+
*/
|
|
24
|
+
const pruneHistoryForRun = (sql, runId) => sql`DELETE FROM test_history WHERE id IN (
|
|
25
|
+
SELECT id FROM (
|
|
26
|
+
SELECT h.id, ROW_NUMBER() OVER (
|
|
27
|
+
PARTITION BY h.project, h.module_path, h.full_name
|
|
28
|
+
ORDER BY h.timestamp DESC
|
|
29
|
+
) AS rn
|
|
30
|
+
FROM test_history h
|
|
31
|
+
JOIN (
|
|
32
|
+
SELECT DISTINCT project, module_path, full_name FROM test_history WHERE run_id = ${runId}
|
|
33
|
+
) a ON a.project = h.project AND a.module_path = h.module_path AND a.full_name = h.full_name
|
|
34
|
+
) WHERE rn > ${HISTORY_WINDOW}
|
|
35
|
+
)`;
|
|
36
|
+
/**
|
|
37
|
+
* Run `effect` as one SQLite write transaction on the `data.db` connection:
|
|
38
|
+
* every `DataStore` write inside it commits together or not at all, and a
|
|
39
|
+
* failure rolls the whole block back before the error propagates.
|
|
40
|
+
*
|
|
41
|
+
* Built for the reporter's run-end persist phase, where per-statement
|
|
42
|
+
* autocommits (one fsync each) dominated wall time. Inside the block
|
|
43
|
+
* `DataStoreLive` caches tag and file ids and defers `writeHistory`'s
|
|
44
|
+
* keep-10 prune to one statement per run, executed before commit; the
|
|
45
|
+
* persisted rows are the same as without the block.
|
|
46
|
+
*
|
|
47
|
+
* The fiber does not yield to the scheduler while the block runs. node:sqlite
|
|
48
|
+
* is synchronous, so the whole transaction executes in one turn of the event
|
|
49
|
+
* loop: a second connection in the same process (another project's reporter,
|
|
50
|
+
* or the MCP server's own connection while it runs Vitest in-process) can
|
|
51
|
+
* neither interleave a write nor block the thread in SQLite's busy handler
|
|
52
|
+
* while this connection holds the write lock. Keep `effect` free of
|
|
53
|
+
* genuinely asynchronous work for that reason; CPU-heavy work that needs no
|
|
54
|
+
* database belongs before the block.
|
|
55
|
+
*
|
|
56
|
+
* Nested `withTransaction` calls inside `effect` become savepoints. A
|
|
57
|
+
* `DataReader` query inside it runs on the transaction's connection.
|
|
58
|
+
*
|
|
59
|
+
* @param effect - the writes (and the reads they depend on) to run atomically
|
|
60
|
+
* @public
|
|
61
|
+
*/
|
|
62
|
+
const withPersistTransaction = (effect) => Effect.gen(function* () {
|
|
63
|
+
const sql = yield* SqlClient;
|
|
64
|
+
const batch = {
|
|
65
|
+
historyRunIds: /* @__PURE__ */ new Set(),
|
|
66
|
+
tagIds: /* @__PURE__ */ new Map(),
|
|
67
|
+
fileIds: /* @__PURE__ */ new Map()
|
|
68
|
+
};
|
|
69
|
+
return yield* sql.withTransaction(Effect.gen(function* () {
|
|
70
|
+
const result = yield* effect.pipe(Effect.provideService(PersistBatch, batch));
|
|
71
|
+
for (const runId of batch.historyRunIds) yield* pruneHistoryForRun(sql, runId).pipe(Effect.mapError((e) => new DataStoreError({
|
|
72
|
+
operation: "write",
|
|
73
|
+
table: "test_history",
|
|
74
|
+
reason: extractSqlReason(e)
|
|
75
|
+
})));
|
|
76
|
+
return result;
|
|
77
|
+
}));
|
|
78
|
+
}).pipe(Effect.provideService(References.PreventSchedulerYield, true), Effect.catchIf(isSqlError, (e) => Effect.fail(new DataStoreError({
|
|
79
|
+
operation: "write",
|
|
80
|
+
table: "transaction",
|
|
81
|
+
reason: extractSqlReason(e)
|
|
82
|
+
}))));
|
|
83
|
+
|
|
84
|
+
export { PersistBatch, withPersistTransaction };
|
|
@@ -5,7 +5,7 @@ import { Effect, FileSystem } from "effect";
|
|
|
5
5
|
import { AppDirs } from "@effected/xdg";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// src/utils/resolve-data-path.ts
|
|
9
9
|
/**
|
|
10
10
|
* Filename of the SQLite database that stores all reporter data.
|
|
11
11
|
* @public
|
|
@@ -60,5 +60,4 @@ const resolveDataPath = (projectDir, options = {}) => Effect.gen(function* () {
|
|
|
60
60
|
return join(dir, DATABASE_FILENAME);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
//#endregion
|
|
64
63
|
export { DATABASE_FILENAME, resolveDataPath };
|
|
@@ -3,7 +3,7 @@ import { Effect, FileSystem } from "effect";
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/utils/resolve-project-key-from-cwd.ts
|
|
7
7
|
const PACKAGE_JSON = "package.json";
|
|
8
8
|
const findNearestPackageJson = (startDir) => {
|
|
9
9
|
let dir = startDir;
|
|
@@ -98,5 +98,4 @@ const resolveProjectKeyFromCwdEffect = (cwd) => Effect.gen(function* () {
|
|
|
98
98
|
}
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
//#endregion
|
|
102
101
|
export { resolveProjectKeyFromCwd, resolveProjectKeyFromCwdEffect };
|
|
@@ -2,7 +2,7 @@ import { normalizeWorkspaceKey } from "@vitest-agent/sdk";
|
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { WorkspaceDiscovery, WorkspaceRootNotFoundError } from "@effected/workspaces";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// src/utils/resolve-workspace-key.ts
|
|
6
6
|
/**
|
|
7
7
|
* Resolve the normalized workspace key for the workspace containing
|
|
8
8
|
* `projectDir`.
|
|
@@ -37,5 +37,4 @@ const resolveWorkspaceKey = (projectDir) => Effect.gen(function* () {
|
|
|
37
37
|
return normalizeWorkspaceKey(root.name);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
//#endregion
|
|
41
40
|
export { resolveWorkspaceKey };
|
package/version.js
CHANGED