@vitest-agent/engine 0.2.10 → 0.2.11

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 CHANGED
@@ -1370,6 +1370,15 @@ export declare const OutputRendererLive: Layer.Layer<OutputRenderer, never, neve
1370
1370
  * @public
1371
1371
  */
1372
1372
  export declare const APP_NAMESPACE = "vitest-agent";
1373
+ /**
1374
+ * Where the XDG data root lands when `XDG_DATA_HOME` is unset:
1375
+ * `$HOME/.local/share/vitest-agent` — the XDG spec default. `AppDirs` alone
1376
+ * would fall back to `$HOME/.vitest-agent`. Shared by `PathResolutionLive`
1377
+ * (reporter/MCP route) and `resolveHookPaths` (hook/sidecar route) so both
1378
+ * routes land in the same directory.
1379
+ * @public
1380
+ */
1381
+ export declare const DATA_FALLBACK_DIR = ".local/share/vitest-agent";
1373
1382
  /**
1374
1383
  * Composite layer providing every service `resolveDataPath` requires:
1375
1384
  * `AppDirs` (XDG path resolution), `VitestAgentConfigFile` (TOML
package/index.js CHANGED
@@ -22,7 +22,7 @@ import { LoggerLive, resolveLogFile, resolveLogLevel } from "./layers/LoggerLive
22
22
  import { OutputRenderer } from "./services/OutputRenderer.js";
23
23
  import { OutputRendererLive } from "./layers/OutputRendererLive.js";
24
24
  import { OutputPipelineLive } from "./layers/OutputPipelineLive.js";
25
- import { APP_NAMESPACE, PathResolutionLive } from "./layers/PathResolutionLive.js";
25
+ import { APP_NAMESPACE, DATA_FALLBACK_DIR, PathResolutionLive } from "./layers/PathResolutionLive.js";
26
26
  import { PerClientSessionMapReader, PerClientSessionMapWriter } from "./services/PerClientSessionMap.js";
27
27
  import { PerClientSessionMapReaderLive, PerClientSessionMapWriterLive } from "./layers/PerClientSessionMapLive.js";
28
28
  import { ProjectDiscovery } from "./services/ProjectDiscovery.js";
@@ -60,4 +60,4 @@ import { DATABASE_FILENAME, resolveDataPath } from "./utils/resolve-data-path.js
60
60
  import { resolveWorkspaceKey } from "./utils/resolve-workspace-key.js";
61
61
  import { CURRENT_ENGINE_VERSION } from "./version.js";
62
62
 
63
- export { APP_NAMESPACE, AgentContext, CURRENT_ENGINE_VERSION, ConfigLive, DATABASE_FILENAME, DATA_DB_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreLive, DetailResolver, DetailResolverLive, DiscoveryRegistry, DiscoveryRegistryLive, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, IDEMPOTENCY_ROOT_SENTINEL, INLINE_ATTACHMENT_BODY_CAP_BYTES, LoggerLive, NodePlatformLayer, OutputPipelineLive, OutputRenderer, OutputRendererLive, PROJECT_MIGRATIONS, PathResolutionLive, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PlatformLive, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityLive, ProjectIdentityTest, REGISTRY_DB_FILENAME, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, SESSIONS_DB_FILENAME, SidecarPlatformLive, VitestAgentConfigFile, _resetMigrationCacheForTesting, assembleHistoryRecord, assembleManifest, classifyEnvironment, computeFailureSignature, deriveIdempotencyKey, dispatchRecordTddArtifactEffect, endAgentEffect, ensureMigrated, formatTriageEffect, formatWrapupEffect, historyKey, makeSqliteStack, migration as migration0001, migration$1 as migration0002, normalizeAssertionShape, parseAndValidateTurnPayload, parseSessionEnvExports, recordRunWorkspaceChangesEffect, recordSessionEnd, recordSessionStart, recordTddArtifactByTaskIdEffect, recordTddArtifactEffect, recordTurnEffect, recoverSessionContextFromSessionEnv, registerAgentEffect, migration$2 as registryMigration0001, resolveDataPath, resolveHookPaths, resolveLogFile, resolveLogLevel, resolveProjectDir, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveSessionForRecording, resolveSessionMapPath, resolveWorkspaceKey, migration$3 as sessionMapMigration0001 };
63
+ export { APP_NAMESPACE, AgentContext, CURRENT_ENGINE_VERSION, ConfigLive, DATABASE_FILENAME, DATA_DB_FILENAME, DATA_FALLBACK_DIR, DataReader, DataReaderLive, DataStore, DataStoreLive, DetailResolver, DetailResolverLive, DiscoveryRegistry, DiscoveryRegistryLive, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, ExecutorResolver, ExecutorResolverLive, FormatSelector, FormatSelectorLive, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, IDEMPOTENCY_ROOT_SENTINEL, INLINE_ATTACHMENT_BODY_CAP_BYTES, LoggerLive, NodePlatformLayer, OutputPipelineLive, OutputRenderer, OutputRendererLive, PROJECT_MIGRATIONS, PathResolutionLive, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PlatformLive, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityLive, ProjectIdentityTest, REGISTRY_DB_FILENAME, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, SESSIONS_DB_FILENAME, SidecarPlatformLive, VitestAgentConfigFile, _resetMigrationCacheForTesting, assembleHistoryRecord, assembleManifest, classifyEnvironment, computeFailureSignature, deriveIdempotencyKey, dispatchRecordTddArtifactEffect, endAgentEffect, ensureMigrated, formatTriageEffect, formatWrapupEffect, historyKey, makeSqliteStack, migration as migration0001, migration$1 as migration0002, normalizeAssertionShape, parseAndValidateTurnPayload, parseSessionEnvExports, recordRunWorkspaceChangesEffect, recordSessionEnd, recordSessionStart, recordTddArtifactByTaskIdEffect, recordTddArtifactEffect, recordTurnEffect, recoverSessionContextFromSessionEnv, registerAgentEffect, migration$2 as registryMigration0001, resolveDataPath, resolveHookPaths, resolveLogFile, resolveLogLevel, resolveProjectDir, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveSessionForRecording, resolveSessionMapPath, resolveWorkspaceKey, migration$3 as sessionMapMigration0001 };
@@ -606,14 +606,28 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
606
606
  const runs = yield* sql`SELECT id FROM test_runs WHERE project = ${project} ORDER BY timestamp DESC LIMIT 1`;
607
607
  return runs.length === 0 ? null : runs[0].id;
608
608
  });
609
- const attachmentsFor = (column, ownerId) => Effect.gen(function* () {
610
- return (column === "annotation_id" ? yield* sql`SELECT content_type, path, body, body_encoding, byte_size FROM attachments WHERE annotation_id = ${ownerId} ORDER BY id` : yield* sql`SELECT content_type, path, body, body_encoding, byte_size FROM attachments WHERE artifact_id = ${ownerId} ORDER BY id`).map((r) => ({
611
- ...r.content_type !== null && { contentType: r.content_type },
612
- ...r.path !== null && { path: r.path },
613
- ...r.body !== null && { body: r.body },
614
- ...r.body_encoding !== null && { bodyEncoding: r.body_encoding },
615
- byteSize: r.byte_size
616
- }));
609
+ /**
610
+ * Load the attachments of every owner in `ownerIds` with a single query,
611
+ * grouped by owner id. Per-owner order follows `attachments.id`. An empty
612
+ * owner list issues no query.
613
+ */
614
+ const attachmentsForMany = (column, ownerIds) => Effect.gen(function* () {
615
+ const grouped = /* @__PURE__ */ new Map();
616
+ if (ownerIds.length === 0) return grouped;
617
+ const rows = column === "annotation_id" ? yield* sql`SELECT annotation_id AS owner_id, content_type, path, body, body_encoding, byte_size FROM attachments WHERE annotation_id IN ${sql.in(ownerIds)} ORDER BY id` : yield* sql`SELECT artifact_id AS owner_id, content_type, path, body, body_encoding, byte_size FROM attachments WHERE artifact_id IN ${sql.in(ownerIds)} ORDER BY id`;
618
+ for (const r of rows) {
619
+ const attachment = {
620
+ ...r.content_type !== null && { contentType: r.content_type },
621
+ ...r.path !== null && { path: r.path },
622
+ ...r.body !== null && { body: r.body },
623
+ ...r.body_encoding !== null && { bodyEncoding: r.body_encoding },
624
+ byteSize: r.byte_size
625
+ };
626
+ const list = grouped.get(r.owner_id);
627
+ if (list === void 0) grouped.set(r.owner_id, [attachment]);
628
+ else list.push(attachment);
629
+ }
630
+ return grouped;
617
631
  });
618
632
  const getAnnotationsForTest = (project, fullName, options) => Effect.gen(function* () {
619
633
  yield* Effect.logDebug("getAnnotationsForTest").pipe(Effect.annotateLogs({
@@ -631,9 +645,10 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
631
645
  WHERE tm.run_id = ${runId} AND tc.full_name = ${fullName}
632
646
  AND (${modulePath} IS NULL OR tm.relative_module_id = ${modulePath})
633
647
  ORDER BY ta.id`;
648
+ const attachmentsByOwner = yield* attachmentsForMany("annotation_id", rows.map((r) => r.id));
634
649
  const out = [];
635
650
  for (const r of rows) {
636
- const attachments = yield* attachmentsFor("annotation_id", r.id);
651
+ const attachments = attachmentsByOwner.get(r.id) ?? [];
637
652
  out.push({
638
653
  id: r.id,
639
654
  type: r.type,
@@ -668,9 +683,10 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
668
683
  WHERE tm.run_id = ${runId} AND tc.full_name = ${fullName}
669
684
  AND (${modulePath} IS NULL OR tm.relative_module_id = ${modulePath})
670
685
  ORDER BY ta.id`;
686
+ const attachmentsByOwner = yield* attachmentsForMany("artifact_id", rows.map((r) => r.id));
671
687
  const out = [];
672
688
  for (const r of rows) {
673
- const attachments = yield* attachmentsFor("artifact_id", r.id);
689
+ const attachments = attachmentsByOwner.get(r.id) ?? [];
674
690
  out.push({
675
691
  id: r.id,
676
692
  type: r.type,
@@ -11,12 +11,24 @@ import { AppDirs, Xdg } from "@effected/xdg";
11
11
  */
12
12
  const APP_NAMESPACE = "vitest-agent";
13
13
  /**
14
+ * Where the XDG data root lands when `XDG_DATA_HOME` is unset:
15
+ * `$HOME/.local/share/vitest-agent` — the XDG spec default. `AppDirs` alone
16
+ * would fall back to `$HOME/.vitest-agent`. Shared by `PathResolutionLive`
17
+ * (reporter/MCP route) and `resolveHookPaths` (hook/sidecar route) so both
18
+ * routes land in the same directory.
19
+ * @public
20
+ */
21
+ const DATA_FALLBACK_DIR = `.local/share/${APP_NAMESPACE}`;
22
+ /**
14
23
  * `AppDirs` over the ambient `Xdg` environment, bound to a `const` so the
15
24
  * layer memoizes by reference (calling `AppDirs.layer(...)` inline at two
16
25
  * provide sites would resolve two independent services). Requires
17
26
  * `FileSystem` + `Path` at the edge.
18
27
  */
19
- const AppDirsLive = AppDirs.layer({ namespace: APP_NAMESPACE }).pipe(Layer.provide(Xdg.layer));
28
+ const AppDirsLive = AppDirs.layer({
29
+ namespace: APP_NAMESPACE,
30
+ fallbackDir: DATA_FALLBACK_DIR
31
+ }).pipe(Layer.provide(Xdg.layer));
20
32
  /**
21
33
  * Composite layer providing every service `resolveDataPath` requires:
22
34
  * `AppDirs` (XDG path resolution), `VitestAgentConfigFile` (TOML
@@ -43,4 +55,4 @@ const PathResolutionLive = (projectDir) => {
43
55
  };
44
56
 
45
57
  //#endregion
46
- export { APP_NAMESPACE, PathResolutionLive };
58
+ export { APP_NAMESPACE, DATA_FALLBACK_DIR, PathResolutionLive };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/engine",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "private": false,
5
5
  "description": "Shared services, layers, SQLite data layer, migrations and platform resolution for the vitest-agent CLI and MCP server.",
6
6
  "keywords": [
@@ -42,14 +42,14 @@
42
42
  "dependencies": {
43
43
  "@effect/platform-node": "4.0.0-rc.118",
44
44
  "@effect/sql-sqlite-node": "4.0.0-rc.118",
45
- "@effected/config-file": "^0.13.0",
45
+ "@effected/config-file": "^0.13.1",
46
46
  "@effected/engine": "^0.2.0",
47
47
  "@effected/glob": "^0.9.0",
48
48
  "@effected/jsonc": "^0.14.0",
49
49
  "@effected/toml": "^0.10.0",
50
- "@effected/walker": "^0.13.0",
51
- "@effected/workspaces": "^0.30.1",
52
- "@effected/xdg": "^0.8.0",
50
+ "@effected/walker": "^0.14.0",
51
+ "@effected/workspaces": "^0.30.2",
52
+ "@effected/xdg": "^0.8.1",
53
53
  "@effected/yaml": "^0.18.0",
54
54
  "@vitest-agent/sdk": "5.1.3",
55
55
  "effect": "4.0.0-rc.118",
@@ -1,4 +1,4 @@
1
- import { APP_NAMESPACE } from "../layers/PathResolutionLive.js";
1
+ import { APP_NAMESPACE, DATA_FALLBACK_DIR } from "../layers/PathResolutionLive.js";
2
2
  import { ProjectIdentityNotResolvableError } from "@vitest-agent/sdk";
3
3
  import { ConfigProvider, Effect, FileSystem, Layer, Path } from "effect";
4
4
  import { AppDirs, Xdg } from "@effected/xdg";
@@ -22,12 +22,6 @@ const SESSIONS_DB_FILENAME = "sessions.db";
22
22
  * @public
23
23
  */
24
24
  const REGISTRY_DB_FILENAME = "registry.db";
25
- /**
26
- * Where the XDG data root lands when `XDG_DATA_HOME` is unset:
27
- * `$HOME/.local/share/vitest-agent` — the XDG spec default the sidecar has
28
- * always used. (`AppDirs` alone would fall back to `$HOME/.vitest-agent`.)
29
- */
30
- const HOOK_DATA_FALLBACK_DIR = `.local/share/${APP_NAMESPACE}`;
31
25
  /** Directory under the home dir that holds the per-client `sessions.db` fallback. */
32
26
  const SESSION_MAP_HOME_DIR = `.${APP_NAMESPACE}`;
33
27
  const nonEmpty = (value) => value !== void 0 && value.length > 0 ? value : void 0;
@@ -48,7 +42,7 @@ const hookAppDirs = (env) => {
48
42
  const XdgLive = Xdg.layer.pipe(Layer.provide(ConfigProvider.layer(provider)));
49
43
  return AppDirs.layer({
50
44
  namespace: APP_NAMESPACE,
51
- fallbackDir: HOOK_DATA_FALLBACK_DIR
45
+ fallbackDir: DATA_FALLBACK_DIR
52
46
  }).pipe(Layer.provide(XdgLive));
53
47
  };
54
48
  /**
package/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/version.ts
2
2
  /** Build-time injected package version (see architecture.md D36). @public */
3
- const CURRENT_ENGINE_VERSION = "0.2.10";
3
+ const CURRENT_ENGINE_VERSION = "0.2.11";
4
4
 
5
5
  //#endregion
6
6
  export { CURRENT_ENGINE_VERSION };