@vitest-agent/sdk 3.1.1 → 4.0.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/README.md +23 -19
- package/dispatch.d.ts +25 -6
- package/formatters/markdown.js +1 -0
- package/formatters/terminal.js +4 -3
- package/index.d.ts +448 -2341
- package/index.js +10 -68
- package/internal-inject-env.js +5 -7
- package/package.json +3 -19
- package/schemas/run-report-file-1.0.0.json +18 -18
- package/sidecar-dispatch.js +7 -5
- package/utils/format-console.js +9 -10
- package/utils/format-terminal.js +7 -7
- package/utils/posix-path.js +52 -0
- package/utils/test-location.js +11 -5
- package/version.js +17 -0
- package/layers/ConfigLive.js +0 -46
- package/layers/DataReaderLive.js +0 -1923
- package/layers/DataStoreLive.js +0 -1287
- package/layers/DetailResolverLive.js +0 -9
- package/layers/DiscoveryRegistryLive.js +0 -70
- package/layers/EnvironmentDetectorLive.js +0 -21
- package/layers/EnvironmentDetectorTest.js +0 -13
- package/layers/ExecutorResolverLive.js +0 -9
- package/layers/FormatSelectorLive.js +0 -20
- package/layers/HistoryTrackerLive.js +0 -49
- package/layers/HistoryTrackerTest.js +0 -25
- package/layers/LoggerLive.js +0 -64
- package/layers/OutputPipelineLive.js +0 -13
- package/layers/OutputRendererLive.js +0 -28
- package/layers/PathResolutionLive.js +0 -40
- package/layers/PerClientSessionMapLive.js +0 -145
- package/layers/ProjectDiscoveryLive.js +0 -68
- package/layers/ProjectDiscoveryTest.js +0 -12
- package/layers/ProjectIdentityLive.js +0 -96
- package/layers/RunContextLive.js +0 -81
- package/lib/format-triage.js +0 -103
- package/lib/format-wrapup.js +0 -67
- package/migrations/0001_initial.js +0 -824
- package/migrations/0002_test_artifacts.js +0 -30
- package/migrations/index.js +0 -26
- package/migrations/registry_0001_initial.js +0 -39
- package/migrations/session_map_0001_initial.js +0 -38
- package/services/Config.js +0 -15
- package/services/DataReader.js +0 -8
- package/services/DataStore.js +0 -15
- package/services/DetailResolver.js +0 -8
- package/services/DiscoveryRegistry.js +0 -8
- package/services/EnvironmentDetector.js +0 -8
- package/services/ExecutorResolver.js +0 -8
- package/services/FormatSelector.js +0 -8
- package/services/HistoryTracker.js +0 -20
- package/services/OutputRenderer.js +0 -8
- package/services/PerClientSessionMap.js +0 -22
- package/services/ProjectDiscovery.js +0 -8
- package/services/ProjectIdentity.js +0 -63
- package/services/RunContext.js +0 -53
- package/services/idempotency.js +0 -58
- package/sql/assemblers.js +0 -69
- package/testing/layers.js +0 -21
- package/testing.d.ts +0 -1862
- package/testing.js +0 -254
- package/utils/ensure-migrated.js +0 -52
- package/utils/failure-signature.js +0 -34
- package/utils/resolve-data-path.js +0 -65
- package/utils/resolve-project-key-from-cwd.js +0 -53
- package/utils/resolve-workspace-key.js +0 -41
package/index.js
CHANGED
|
@@ -16,57 +16,10 @@ import { MarkdownFormatter } from "./formatters/markdown.js";
|
|
|
16
16
|
import { SilentFormatter } from "./formatters/silent.js";
|
|
17
17
|
import { compressLines } from "./utils/compress-lines.js";
|
|
18
18
|
import { osc8 } from "./utils/hyperlink.js";
|
|
19
|
+
import { basenamePosix, joinPosix, relativePosix, toPosix } from "./utils/posix-path.js";
|
|
19
20
|
import { TerminalFormatter } from "./formatters/terminal.js";
|
|
20
|
-
import { VitestAgentConfig } from "./schemas/Config.js";
|
|
21
|
-
import { VitestAgentConfigFile } from "./services/Config.js";
|
|
22
|
-
import { ConfigLive } from "./layers/ConfigLive.js";
|
|
23
|
-
import { DataReader } from "./services/DataReader.js";
|
|
24
|
-
import { HistoryTracker, historyKey } from "./services/HistoryTracker.js";
|
|
25
|
-
import { DataReaderLive } from "./layers/DataReaderLive.js";
|
|
26
21
|
import { ActorType, AgentId, ChatId, ConversationId, HostKind, ProjectKey, TddTaskId } from "./schemas/Identity.js";
|
|
27
22
|
import { Agent, IdempotencyHit } from "./schemas/Agent.js";
|
|
28
|
-
import { DataStore, INLINE_ATTACHMENT_BODY_CAP_BYTES } from "./services/DataStore.js";
|
|
29
|
-
import { coerceErrorField, coerceErrorText } from "./utils/coerce-error-text.js";
|
|
30
|
-
import { DataStoreLive } from "./layers/DataStoreLive.js";
|
|
31
|
-
import { DetailResolver } from "./services/DetailResolver.js";
|
|
32
|
-
import { DetailResolverLive } from "./layers/DetailResolverLive.js";
|
|
33
|
-
import { DiscoveryRegistry } from "./services/DiscoveryRegistry.js";
|
|
34
|
-
import { DiscoveryRegistryLive } from "./layers/DiscoveryRegistryLive.js";
|
|
35
|
-
import { EnvironmentDetector } from "./services/EnvironmentDetector.js";
|
|
36
|
-
import { EnvironmentDetectorLive } from "./layers/EnvironmentDetectorLive.js";
|
|
37
|
-
import { EnvironmentDetectorTest } from "./layers/EnvironmentDetectorTest.js";
|
|
38
|
-
import { ExecutorResolver } from "./services/ExecutorResolver.js";
|
|
39
|
-
import { ExecutorResolverLive } from "./layers/ExecutorResolverLive.js";
|
|
40
|
-
import { FormatSelector } from "./services/FormatSelector.js";
|
|
41
|
-
import { FormatSelectorLive } from "./layers/FormatSelectorLive.js";
|
|
42
|
-
import { classifyTest } from "./utils/classify-test.js";
|
|
43
|
-
import { HistoryTrackerLive } from "./layers/HistoryTrackerLive.js";
|
|
44
|
-
import { HistoryTrackerTest } from "./layers/HistoryTrackerTest.js";
|
|
45
|
-
import { LoggerLive, resolveLogFile, resolveLogLevel } from "./layers/LoggerLive.js";
|
|
46
|
-
import { OutputRenderer } from "./services/OutputRenderer.js";
|
|
47
|
-
import { OutputRendererLive } from "./layers/OutputRendererLive.js";
|
|
48
|
-
import { OutputPipelineLive } from "./layers/OutputPipelineLive.js";
|
|
49
|
-
import { PathResolutionLive } from "./layers/PathResolutionLive.js";
|
|
50
|
-
import { PerClientSessionMapReader, PerClientSessionMapWriter } from "./services/PerClientSessionMap.js";
|
|
51
|
-
import { PerClientSessionMapReaderLive, PerClientSessionMapWriterLive } from "./layers/PerClientSessionMapLive.js";
|
|
52
|
-
import { ProjectDiscovery } from "./services/ProjectDiscovery.js";
|
|
53
|
-
import { BATS_FILE_GLOB_SUFFIX, NON_DISCOVERABLE_DIRS, SRC_DIR, TEST_DIR, TEST_FILE_GLOB_SUFFIX, TEST_HELPER_DIRS, classifyTestPath, findOwningWorkspace, isTestFileName } from "./utils/test-location.js";
|
|
54
|
-
import { ProjectDiscoveryLive } from "./layers/ProjectDiscoveryLive.js";
|
|
55
|
-
import { ProjectDiscoveryTest } from "./layers/ProjectDiscoveryTest.js";
|
|
56
|
-
import { canonicalizeGitUrl, gitUrlToProjectKey } from "./utils/canonicalize-git-url.js";
|
|
57
|
-
import { normalizeWorkspaceKey } from "./utils/normalize-workspace-key.js";
|
|
58
|
-
import { ProjectIdentity, resolveProjectIdentityFromCandidates } from "./services/ProjectIdentity.js";
|
|
59
|
-
import { ProjectIdentityLive, ProjectIdentityTest } from "./layers/ProjectIdentityLive.js";
|
|
60
|
-
import { AgentContext, RunContext, RunContext$, RunContextService } from "./services/RunContext.js";
|
|
61
|
-
import { probeHostMetadataFromEnv } from "./utils/probe-host-metadata.js";
|
|
62
|
-
import { RunContextLive, RunContextTest } from "./layers/RunContextLive.js";
|
|
63
|
-
import { formatTriageEffect } from "./lib/format-triage.js";
|
|
64
|
-
import { formatWrapupEffect } from "./lib/format-wrapup.js";
|
|
65
|
-
import migration from "./migrations/0001_initial.js";
|
|
66
|
-
import migration$1 from "./migrations/0002_test_artifacts.js";
|
|
67
|
-
import { PROJECT_MIGRATIONS } from "./migrations/index.js";
|
|
68
|
-
import migration$2 from "./migrations/registry_0001_initial.js";
|
|
69
|
-
import migration$3 from "./migrations/session_map_0001_initial.js";
|
|
70
23
|
import { AgentConsoleMode, CiConsoleMode, ConsoleMode, ConsoleOutputMode, DetailLevel, Environment, Executor, HumanConsoleMode, OutputFormat, PackageManager, ReportError, TestClassification, TestRunReason, TestState } from "./schemas/Common.js";
|
|
71
24
|
import { ConsoleLeakFile, ConsoleLeaks, ConsoleLeaksFromFailingTests } from "./schemas/ConsoleLeaks.js";
|
|
72
25
|
import { MetricThresholds, PatternMetricThresholds, PatternThresholds, PerFileThresholds, ResolvedThresholds } from "./schemas/Thresholds.js";
|
|
@@ -75,6 +28,7 @@ import { AgentReport, ModuleReport, ReportSummary, TagCountEntry, TestReport } f
|
|
|
75
28
|
import { CoverageBaselines } from "./schemas/Baselines.js";
|
|
76
29
|
import { CacheManifest, CacheManifestEntry } from "./schemas/CacheManifest.js";
|
|
77
30
|
import { BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorsReadyEvent, BlockedEvent, ChannelEvent, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalStartedEvent, GoalsReadyEvent, PhaseTransitionEvent, SessionCompleteEvent, SessionOutcome } from "./schemas/ChannelEvent.js";
|
|
31
|
+
import { VitestAgentConfig } from "./schemas/Config.js";
|
|
78
32
|
import { CoverageLevel, resolveCoverageInput, validateCoverageConfig } from "./schemas/CoverageLevel.js";
|
|
79
33
|
import { CoverageTargets, CoverageTargetsMetrics } from "./schemas/CoverageTargets.js";
|
|
80
34
|
import { HistoryRecord, TestHistory, TestRun } from "./schemas/History.js";
|
|
@@ -94,36 +48,24 @@ import { ToolCallPayload } from "./schemas/turns/ToolCallPayload.js";
|
|
|
94
48
|
import { ToolResultPayload } from "./schemas/turns/ToolResultPayload.js";
|
|
95
49
|
import { UserPromptPayload } from "./schemas/turns/UserPromptPayload.js";
|
|
96
50
|
import { TurnPayload } from "./schemas/turns/index.js";
|
|
97
|
-
import {
|
|
98
|
-
import { assembleHistoryRecord, assembleManifest } from "./sql/assemblers.js";
|
|
51
|
+
import { coerceErrorField, coerceErrorText } from "./utils/coerce-error-text.js";
|
|
99
52
|
import { buildAgentReport, countSuiteFailures } from "./utils/build-report.js";
|
|
53
|
+
import { canonicalizeGitUrl, gitUrlToProjectKey } from "./utils/canonicalize-git-url.js";
|
|
54
|
+
import { classifyTest } from "./utils/classify-test.js";
|
|
100
55
|
import { computeTrend, getRecentDirection, hashTargets } from "./utils/compute-trend.js";
|
|
101
56
|
import { buildConsoleLeaks, collectConsoleLeakEntries } from "./utils/console-leaks.js";
|
|
102
57
|
import { detectNonDefaultDiscoverStrategy } from "./utils/detect-non-default-discover-strategy.js";
|
|
103
58
|
import { detectPackageManager, getRunCommand } from "./utils/detect-pm.js";
|
|
104
59
|
import { isTimeoutError } from "./utils/detect-timeout.js";
|
|
105
|
-
import { _resetMigrationCacheForTesting, ensureMigrated } from "./utils/ensure-migrated.js";
|
|
106
|
-
import { computeFailureSignature, normalizeAssertionShape } from "./utils/failure-signature.js";
|
|
107
60
|
import { formatFatalError } from "./utils/format-fatal-error.js";
|
|
108
61
|
import { findFunctionBoundary } from "./utils/function-boundary.js";
|
|
109
62
|
import { buildEnvPrefix, detectVitestScripts, isVitestInvocation, rewriteBashCommand } from "./utils/match-vitest-command.js";
|
|
110
|
-
import {
|
|
111
|
-
import {
|
|
112
|
-
import { resolveWorkspaceKey } from "./utils/resolve-workspace-key.js";
|
|
63
|
+
import { normalizeWorkspaceKey } from "./utils/normalize-workspace-key.js";
|
|
64
|
+
import { probeHostMetadataFromEnv } from "./utils/probe-host-metadata.js";
|
|
113
65
|
import { safeFilename } from "./utils/safe-filename.js";
|
|
66
|
+
import { BATS_FILE_GLOB_SUFFIX, NON_DISCOVERABLE_DIRS, SRC_DIR, TEST_DIR, TEST_FILE_GLOB_SUFFIX, TEST_HELPER_DIRS, classifyTestPath, findOwningWorkspace, isTestFileName } from "./utils/test-location.js";
|
|
114
67
|
import { validateCoverageTargetsShape } from "./utils/validate-coverage-targets-shape.js";
|
|
115
68
|
import { requiredArtifactForTransition, transitionEnforcesBehaviorMatch, validatePhaseTransition } from "./utils/validate-phase-transition.js";
|
|
69
|
+
import { CURRENT_SDK_VERSION } from "./version.js";
|
|
116
70
|
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* The version of this package. Inlined at build time from
|
|
120
|
-
* package.json#version via rslib-builder's __PACKAGE_VERSION__ substitution.
|
|
121
|
-
* Source-level reads (workspace `exports: "./src/index.ts"` during dev)
|
|
122
|
-
* see the `"0.0.0"` fallback — a clear signal the build pipeline has not
|
|
123
|
-
* substituted yet. Exported for version introspection by downstream tooling.
|
|
124
|
-
* @public
|
|
125
|
-
*/
|
|
126
|
-
const CURRENT_SDK_VERSION = "3.1.1";
|
|
127
|
-
|
|
128
|
-
//#endregion
|
|
129
|
-
export { ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentContext, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, BATS_FILE_GLOB_SUFFIX, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, ChannelEvent, ChatId, CiConsoleMode, ConfigLive, ConsoleLeakFile, ConsoleLeaks, ConsoleLeaksFromFailingTests, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, CoverageGap, CoverageLevel, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTotals, DATABASE_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreError, DataStoreLive, DetailLevel, DetailResolver, DetailResolverLive, DiscoveryError, DiscoveryRegistry, DiscoveryRegistryLive, Environment, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, Executor, ExecutorResolver, ExecutorResolverLive, FailureRecord, FileCoverageReport, FileEditPayload, FormatSelector, FormatSelectorLive, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HumanConsoleMode, HypothesisPayload, IDEMPOTENCY_ROOT_SENTINEL, INLINE_ATTACHMENT_BODY_CAP_BYTES, IdempotencyHit, IllegalStatusTransitionError, JsonFormatter, LoggerLive, MarkdownFormatter, MetricThresholds, ModuleRecord, ModuleReport, NON_DISCOVERABLE_DIRS, NotePayload, OutputFormat, OutputPipelineLive, OutputRenderer, OutputRendererLive, PROJECT_MIGRATIONS, PackageManager, PathResolutionError, PathResolutionLive, PatternMetricThresholds, PatternThresholds, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PerFileThresholds, PhaseTransitionEvent, ProbeMissError, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityLive, ProjectIdentityNotResolvableError, ProjectIdentityTest, ProjectKey, RUN_REPORT_FILE_SCHEMA_URL, RegistrationConflictError, RenderState, RenderTotals, ReportError, ReportOption, ReportSettings, ReportSummary, ResolvedThresholds, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, RunEvent, RunReportFile, SRC_DIR, SessionCompleteEvent, SessionNotFoundError, SessionOutcome, SidecarTimeoutError, SilentFormatter, SuggestedActionRecord, TEST_DIR, TEST_FILE_GLOB_SUFFIX, TEST_HELPER_DIRS, TagCountEntry, TddTaskAlreadyEndedError, TddTaskId, TddTaskNotFoundError, TerminalFormatter, TestAnnotation, TestArtifact, TestArtifactLocation, TestAttachment, TestClassification, TestHistory, TestRecord, TestReport, TestRun, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TurnPayload, UserPromptPayload, VitestAgentConfig, VitestAgentConfigFile, _resetMigrationCacheForTesting, ansi, assembleHistoryRecord, assembleManifest, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, classifyTestPath, coerceErrorField, coerceErrorText, collectConsoleLeakEntries, compressLines, computeFailureSignature, computeTrend, countSuiteFailures, deriveIdempotencyKey, detectNonDefaultDiscoverStrategy, detectPackageManager, detectVitestScripts, determineTier, ensureMigrated, extractSqlReason, findFunctionBoundary, findOwningWorkspace, formatConsoleMarkdown, formatFatalError, formatGfm, formatScopedCoverageNote, formatTriageEffect, formatWrapupEffect, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, historyKey, initialRenderState, isTestFileName, isTimeoutError, isVitestInvocation, migration as migration0001, migration$1 as migration0002, normalizeAssertionShape, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, migration$2 as registryMigration0001, relativePath, requiredArtifactForTransition, resolveCoverageInput, resolveDataPath, resolveLogFile, resolveLogLevel, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveWorkspaceKey, rewriteBashCommand, safeFilename, migration$3 as sessionMapMigration0001, stripAnsi, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
|
71
|
+
export { ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, BATS_FILE_GLOB_SUFFIX, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, ChannelEvent, ChatId, CiConsoleMode, ConsoleLeakFile, ConsoleLeaks, ConsoleLeaksFromFailingTests, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, CoverageGap, CoverageLevel, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTotals, DataStoreError, DetailLevel, DiscoveryError, Environment, Executor, FailureRecord, FileCoverageReport, FileEditPayload, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HumanConsoleMode, HypothesisPayload, IdempotencyHit, IllegalStatusTransitionError, JsonFormatter, MarkdownFormatter, MetricThresholds, ModuleRecord, ModuleReport, NON_DISCOVERABLE_DIRS, NotePayload, OutputFormat, PackageManager, PathResolutionError, PatternMetricThresholds, PatternThresholds, PerFileThresholds, PhaseTransitionEvent, ProbeMissError, ProjectIdentityNotResolvableError, ProjectKey, RUN_REPORT_FILE_SCHEMA_URL, RegistrationConflictError, RenderState, RenderTotals, ReportError, ReportOption, ReportSettings, ReportSummary, ResolvedThresholds, RunEvent, RunReportFile, SRC_DIR, SessionCompleteEvent, SessionNotFoundError, SessionOutcome, SidecarTimeoutError, SilentFormatter, SuggestedActionRecord, TEST_DIR, TEST_FILE_GLOB_SUFFIX, TEST_HELPER_DIRS, TagCountEntry, TddTaskAlreadyEndedError, TddTaskId, TddTaskNotFoundError, TerminalFormatter, TestAnnotation, TestArtifact, TestArtifactLocation, TestAttachment, TestClassification, TestHistory, TestRecord, TestReport, TestRun, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TurnPayload, UserPromptPayload, VitestAgentConfig, ansi, basenamePosix, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, classifyTestPath, coerceErrorField, coerceErrorText, collectConsoleLeakEntries, compressLines, computeTrend, countSuiteFailures, detectNonDefaultDiscoverStrategy, detectPackageManager, detectVitestScripts, determineTier, extractSqlReason, findFunctionBoundary, findOwningWorkspace, formatConsoleMarkdown, formatFatalError, formatGfm, formatScopedCoverageNote, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, initialRenderState, isTestFileName, isTimeoutError, isVitestInvocation, joinPosix, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, relativePath, relativePosix, requiredArtifactForTransition, resolveCoverageInput, rewriteBashCommand, safeFilename, stripAnsi, toPosix, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
package/internal-inject-env.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { detectVitestScripts, rewriteBashCommand } from "./utils/match-vitest-command.js";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
2
|
|
|
5
3
|
//#region src/internal-inject-env.ts
|
|
6
|
-
const readPackageScripts = (cwd) => {
|
|
4
|
+
const readPackageScripts = (cwd, readFile) => {
|
|
7
5
|
try {
|
|
8
|
-
const raw =
|
|
6
|
+
const raw = readFile(`${cwd}/package.json`);
|
|
9
7
|
return JSON.parse(raw).scripts ?? {};
|
|
10
8
|
} catch {
|
|
11
9
|
return {};
|
|
@@ -19,15 +17,15 @@ const readPackageScripts = (cwd) => {
|
|
|
19
17
|
* - `VITEST_AGENT_CONVERSATION_ID` or `VITEST_AGENT_AGENT_ID` is
|
|
20
18
|
* missing from env (no agent context to attribute to)
|
|
21
19
|
*
|
|
22
|
-
* Always synchronous — the package.json read is the only I/O
|
|
23
|
-
* fast enough not to need Effect wrapping.
|
|
20
|
+
* Always synchronous — the package.json read is the only I/O, goes through
|
|
21
|
+
* the injected `readFile`, and is fast enough not to need Effect wrapping.
|
|
24
22
|
* @public
|
|
25
23
|
*/
|
|
26
24
|
const injectEnv = (input) => {
|
|
27
25
|
const conversationId = input.env.VITEST_AGENT_CONVERSATION_ID;
|
|
28
26
|
const agentId = input.env.VITEST_AGENT_AGENT_ID;
|
|
29
27
|
if (conversationId === void 0 || agentId === void 0) return input.command;
|
|
30
|
-
const scripts = readPackageScripts(input.cwd);
|
|
28
|
+
const scripts = readPackageScripts(input.cwd, input.readFile);
|
|
31
29
|
const vitestScripts = detectVitestScripts(scripts);
|
|
32
30
|
const parentAgentId = input.env.VITEST_AGENT_PARENT_AGENT_ID;
|
|
33
31
|
return rewriteBashCommand({
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest-agent/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Platform-free core for the vitest-agent package family: Effect Schema definitions, reporter and dispatcher contracts, errors, formatters, and pure utilities.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"vitest",
|
|
8
8
|
"agent",
|
|
@@ -37,29 +37,13 @@
|
|
|
37
37
|
"import": "./dispatch.js",
|
|
38
38
|
"default": "./dispatch.js"
|
|
39
39
|
},
|
|
40
|
-
"./testing": {
|
|
41
|
-
"types": "./testing.d.ts",
|
|
42
|
-
"import": "./testing.js",
|
|
43
|
-
"default": "./testing.js"
|
|
44
|
-
},
|
|
45
40
|
"./schemas/*.json": "./schemas/*.json",
|
|
46
41
|
"./package.json": "./package.json"
|
|
47
42
|
},
|
|
48
43
|
"dependencies": {
|
|
49
|
-
"@effect/platform-node": "4.0.0-rc.112",
|
|
50
|
-
"@effect/sql-sqlite-node": "4.0.0-rc.112",
|
|
51
|
-
"@effected/config-file": "^0.7.0",
|
|
52
|
-
"@effected/jsonc": "^0.9.0",
|
|
53
|
-
"@effected/toml": "^0.6.0",
|
|
54
|
-
"@effected/walker": "^0.7.0",
|
|
55
|
-
"@effected/workspaces": "^0.20.3",
|
|
56
|
-
"@effected/xdg": "^0.4.1",
|
|
57
|
-
"@effected/yaml": "^0.14.0",
|
|
58
44
|
"acorn": "^8.18.0",
|
|
59
45
|
"acorn-typescript": "^1.4.13",
|
|
60
|
-
"
|
|
61
|
-
"effect": "4.0.0-rc.112",
|
|
62
|
-
"std-env": "^4.2.0"
|
|
46
|
+
"effect": "4.0.0-rc.115"
|
|
63
47
|
},
|
|
64
48
|
"engines": {
|
|
65
49
|
"node": ">=24.11.0"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
"required": ["total", "passed", "failed", "skipped", "duration"],
|
|
93
|
-
"additionalProperties":
|
|
93
|
+
"additionalProperties": true
|
|
94
94
|
},
|
|
95
95
|
"TestState": {
|
|
96
96
|
"type": "string",
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
146
|
"required": ["message"],
|
|
147
|
-
"additionalProperties":
|
|
147
|
+
"additionalProperties": true
|
|
148
148
|
},
|
|
149
149
|
"TestClassification": {
|
|
150
150
|
"type": "string",
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
}
|
|
226
226
|
},
|
|
227
227
|
"required": ["name", "fullName", "state"],
|
|
228
|
-
"additionalProperties":
|
|
228
|
+
"additionalProperties": true
|
|
229
229
|
},
|
|
230
230
|
"ModuleReport": {
|
|
231
231
|
"type": "object",
|
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
}
|
|
276
276
|
},
|
|
277
277
|
"required": ["file", "state", "tests"],
|
|
278
|
-
"additionalProperties":
|
|
278
|
+
"additionalProperties": true
|
|
279
279
|
},
|
|
280
280
|
"CoverageTotals": {
|
|
281
281
|
"type": "object",
|
|
@@ -326,7 +326,7 @@
|
|
|
326
326
|
}
|
|
327
327
|
},
|
|
328
328
|
"required": ["statements", "branches", "functions", "lines"],
|
|
329
|
-
"additionalProperties":
|
|
329
|
+
"additionalProperties": true
|
|
330
330
|
},
|
|
331
331
|
"MetricThresholds": {
|
|
332
332
|
"type": "object",
|
|
@@ -404,7 +404,7 @@
|
|
|
404
404
|
]
|
|
405
405
|
}
|
|
406
406
|
},
|
|
407
|
-
"additionalProperties":
|
|
407
|
+
"additionalProperties": true
|
|
408
408
|
},
|
|
409
409
|
"PerFileThresholds": {
|
|
410
410
|
"anyOf": [
|
|
@@ -495,7 +495,7 @@
|
|
|
495
495
|
"$ref": "#/$defs/PerFileThresholds"
|
|
496
496
|
}
|
|
497
497
|
},
|
|
498
|
-
"additionalProperties":
|
|
498
|
+
"additionalProperties": true
|
|
499
499
|
},
|
|
500
500
|
"PatternThresholds": {
|
|
501
501
|
"type": "array",
|
|
@@ -524,7 +524,7 @@
|
|
|
524
524
|
}
|
|
525
525
|
},
|
|
526
526
|
"required": ["file", "summary", "uncoveredLines"],
|
|
527
|
-
"additionalProperties":
|
|
527
|
+
"additionalProperties": true
|
|
528
528
|
},
|
|
529
529
|
"CoverageReport": {
|
|
530
530
|
"type": "object",
|
|
@@ -546,7 +546,7 @@
|
|
|
546
546
|
}
|
|
547
547
|
},
|
|
548
548
|
"required": ["global"],
|
|
549
|
-
"additionalProperties":
|
|
549
|
+
"additionalProperties": true
|
|
550
550
|
},
|
|
551
551
|
"targets": {
|
|
552
552
|
"anyOf": [
|
|
@@ -564,7 +564,7 @@
|
|
|
564
564
|
}
|
|
565
565
|
},
|
|
566
566
|
"required": ["global"],
|
|
567
|
-
"additionalProperties":
|
|
567
|
+
"additionalProperties": true
|
|
568
568
|
},
|
|
569
569
|
{
|
|
570
570
|
"type": "null"
|
|
@@ -587,7 +587,7 @@
|
|
|
587
587
|
}
|
|
588
588
|
},
|
|
589
589
|
"required": ["global"],
|
|
590
|
-
"additionalProperties":
|
|
590
|
+
"additionalProperties": true
|
|
591
591
|
},
|
|
592
592
|
{
|
|
593
593
|
"type": "null"
|
|
@@ -668,7 +668,7 @@
|
|
|
668
668
|
}
|
|
669
669
|
},
|
|
670
670
|
"required": ["totals", "thresholds", "lowCoverage", "lowCoverageFiles"],
|
|
671
|
-
"additionalProperties":
|
|
671
|
+
"additionalProperties": true
|
|
672
672
|
},
|
|
673
673
|
"TagCountEntry": {
|
|
674
674
|
"type": "object",
|
|
@@ -728,7 +728,7 @@
|
|
|
728
728
|
]
|
|
729
729
|
}
|
|
730
730
|
},
|
|
731
|
-
"additionalProperties":
|
|
731
|
+
"additionalProperties": true
|
|
732
732
|
},
|
|
733
733
|
"ConsoleLeakFile": {
|
|
734
734
|
"type": "object",
|
|
@@ -783,7 +783,7 @@
|
|
|
783
783
|
}
|
|
784
784
|
},
|
|
785
785
|
"required": ["file", "stdout", "stderr"],
|
|
786
|
-
"additionalProperties":
|
|
786
|
+
"additionalProperties": true
|
|
787
787
|
},
|
|
788
788
|
"ConsoleLeaksFromFailingTests": {
|
|
789
789
|
"type": "object",
|
|
@@ -812,7 +812,7 @@
|
|
|
812
812
|
}
|
|
813
813
|
},
|
|
814
814
|
"required": ["total", "files"],
|
|
815
|
-
"additionalProperties":
|
|
815
|
+
"additionalProperties": true
|
|
816
816
|
},
|
|
817
817
|
"ConsoleLeaks": {
|
|
818
818
|
"type": "object",
|
|
@@ -856,7 +856,7 @@
|
|
|
856
856
|
}
|
|
857
857
|
},
|
|
858
858
|
"required": ["total", "byFile"],
|
|
859
|
-
"additionalProperties":
|
|
859
|
+
"additionalProperties": true
|
|
860
860
|
},
|
|
861
861
|
"AgentReport": {
|
|
862
862
|
"type": "object",
|
|
@@ -933,7 +933,7 @@
|
|
|
933
933
|
}
|
|
934
934
|
},
|
|
935
935
|
"required": ["timestamp", "reason", "summary", "failed", "unhandledErrors", "failedFiles"],
|
|
936
|
-
"additionalProperties":
|
|
936
|
+
"additionalProperties": true
|
|
937
937
|
},
|
|
938
938
|
"RunReportFile": {
|
|
939
939
|
"type": "object",
|
|
@@ -956,7 +956,7 @@
|
|
|
956
956
|
}
|
|
957
957
|
},
|
|
958
958
|
"required": ["schemaVersion", "generatedAt", "reports"],
|
|
959
|
-
"additionalProperties":
|
|
959
|
+
"additionalProperties": true,
|
|
960
960
|
"description": "The vitest-agent run report file (.vitest/vitest-agent/run.json): one AgentReport per Vitest project from the most recent run. Read reports[].summary for pass/fail counts and reports[].failed for the failing modules and their tests. schemaVersion is the envelope contract version; generatedAt is when the run finished."
|
|
961
961
|
}
|
|
962
962
|
}
|
package/sidecar-dispatch.js
CHANGED
|
@@ -37,17 +37,18 @@ const messageFromError = (err) => {
|
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
39
|
* Dispatch one argv invocation. `argv` is the post-`node post-bin`
|
|
40
|
-
* slice — i.e. `process.argv.slice(2)
|
|
41
|
-
*
|
|
40
|
+
* slice — i.e. `process.argv.slice(2)` — and `io` carries the process
|
|
41
|
+
* facts (cwd, env, a file reader) the runner owns. Never throws: every
|
|
42
|
+
* failure is folded into the returned {@link DispatchResult}.
|
|
42
43
|
* @public
|
|
43
44
|
*/
|
|
44
|
-
const dispatch = async (argv) => {
|
|
45
|
+
const dispatch = async (argv, io) => {
|
|
45
46
|
const subcommand = argv[0];
|
|
46
47
|
const rest = argv.slice(1);
|
|
47
48
|
if (subcommand === "inject-env") {
|
|
48
49
|
const flags = parseFlags(rest);
|
|
49
50
|
const command = flags.command;
|
|
50
|
-
const cwd = flags.cwd ??
|
|
51
|
+
const cwd = flags.cwd ?? io.cwd;
|
|
51
52
|
if (command === void 0) return {
|
|
52
53
|
stdout: "",
|
|
53
54
|
stderr: `${exitCodeForTag("Defect")} Defect: inject-env requires --command\n`,
|
|
@@ -58,7 +59,8 @@ const dispatch = async (argv) => {
|
|
|
58
59
|
stdout: `${injectEnv({
|
|
59
60
|
command,
|
|
60
61
|
cwd,
|
|
61
|
-
env:
|
|
62
|
+
env: io.env,
|
|
63
|
+
readFile: io.readFile
|
|
62
64
|
})}\n`,
|
|
63
65
|
stderr: "",
|
|
64
66
|
code: 0
|
package/utils/format-console.js
CHANGED
|
@@ -40,15 +40,14 @@ function getWorstMetric(f) {
|
|
|
40
40
|
* project-relative path for display.
|
|
41
41
|
*
|
|
42
42
|
* @param filePath - Absolute or relative file path
|
|
43
|
-
* @param cwd - Working directory to strip
|
|
43
|
+
* @param cwd - Working directory to strip
|
|
44
44
|
* @returns Project-relative path string
|
|
45
45
|
*
|
|
46
46
|
* @internal
|
|
47
47
|
*/
|
|
48
48
|
function relativePath(filePath, cwd) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const rel = filePath.slice(root.length);
|
|
49
|
+
if (filePath.startsWith(cwd)) {
|
|
50
|
+
const rel = filePath.slice(cwd.length);
|
|
52
51
|
return rel.startsWith("/") ? rel.slice(1) : rel;
|
|
53
52
|
}
|
|
54
53
|
return filePath;
|
|
@@ -93,7 +92,7 @@ function determineTier(report) {
|
|
|
93
92
|
* @internal
|
|
94
93
|
*/
|
|
95
94
|
function formatConsoleMarkdown(report, options) {
|
|
96
|
-
const { consoleOutput, coverageConsoleLimit, noColor } = options;
|
|
95
|
+
const { consoleOutput, coverageConsoleLimit, noColor, cwd } = options;
|
|
97
96
|
if (consoleOutput === "silent") return "";
|
|
98
97
|
const ao = { noColor };
|
|
99
98
|
const lines = [];
|
|
@@ -130,7 +129,7 @@ function formatConsoleMarkdown(report, options) {
|
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
if (hasFailures) for (const mod of report.failed) {
|
|
133
|
-
const file = relativePath(mod.file);
|
|
132
|
+
const file = relativePath(mod.file, cwd);
|
|
134
133
|
lines.push(`### ${ansi("✗", "red", ao)} \`${file}\``);
|
|
135
134
|
lines.push("");
|
|
136
135
|
if (mod.errors && mod.errors.length > 0) for (const err of mod.errors) {
|
|
@@ -171,7 +170,7 @@ function formatConsoleMarkdown(report, options) {
|
|
|
171
170
|
lines.push(`### Coverage gaps`);
|
|
172
171
|
lines.push("");
|
|
173
172
|
for (const f of filesToShow) {
|
|
174
|
-
const file = relativePath(f.file);
|
|
173
|
+
const file = relativePath(f.file, cwd);
|
|
175
174
|
const worst = getWorstMetric(f);
|
|
176
175
|
const thresholdValue = globalThresholds[worst.label === "Stmts" ? "statements" : worst.label === "Branch" ? "branches" : worst.label === "Funcs" ? "functions" : "lines"];
|
|
177
176
|
const thresholdSuffix = thresholdValue != null ? ` (threshold: ${thresholdValue}%)` : "";
|
|
@@ -183,7 +182,7 @@ function formatConsoleMarkdown(report, options) {
|
|
|
183
182
|
lines.push(`### Coverage improvements needed`);
|
|
184
183
|
lines.push("");
|
|
185
184
|
for (const f of cov.belowTarget.slice(0, coverageConsoleLimit)) {
|
|
186
|
-
const file = relativePath(f.file);
|
|
185
|
+
const file = relativePath(f.file, cwd);
|
|
187
186
|
const worst = getWorstMetric(f);
|
|
188
187
|
const metricKey = worst.label === "Stmts" ? "statements" : worst.label === "Branch" ? "branches" : worst.label === "Funcs" ? "functions" : "lines";
|
|
189
188
|
const targetValue = cov.targets.global[metricKey];
|
|
@@ -202,12 +201,12 @@ function formatConsoleMarkdown(report, options) {
|
|
|
202
201
|
const persistent = allFailedTests.filter((t) => t.classification === "persistent");
|
|
203
202
|
const flaky = allFailedTests.filter((t) => t.classification === "flaky");
|
|
204
203
|
if (newFailures.length > 0) {
|
|
205
|
-
const files = [...new Set(report.failed.filter((m) => m.tests.some((t) => t.classification === "new-failure")).map((m) => relativePath(m.file)))];
|
|
204
|
+
const files = [...new Set(report.failed.filter((m) => m.tests.some((t) => t.classification === "new-failure")).map((m) => relativePath(m.file, cwd)))];
|
|
206
205
|
lines.push(`- Fix ${newFailures.length} new failure${newFailures.length > 1 ? "s" : ""} in ${files.map((f) => `\`${f}\``).join(", ")} (likely caused by recent changes)`);
|
|
207
206
|
}
|
|
208
207
|
if (persistent.length > 0) lines.push(`- ${persistent.length} persistent failure${persistent.length > 1 ? "s" : ""} (pre-existing, may not be yours)`);
|
|
209
208
|
if (flaky.length > 0) lines.push(`- ${flaky.length} flaky test${flaky.length > 1 ? "s" : ""} (may pass on retry)`);
|
|
210
|
-
for (const file of report.failedFiles) lines.push(`- Re-run: \`vitest run ${relativePath(file)}\``);
|
|
209
|
+
for (const file of report.failedFiles) lines.push(`- Re-run: \`vitest run ${relativePath(file, cwd)}\``);
|
|
211
210
|
if (options.mcp) {
|
|
212
211
|
lines.push("- Use `test_history` for failure trends");
|
|
213
212
|
lines.push("- Use `test_errors` to search errors by type");
|
package/utils/format-terminal.js
CHANGED
|
@@ -209,10 +209,10 @@ const sepRow = (widths) => widths.map((w) => "-".repeat(w + 2)).join("|");
|
|
|
209
209
|
*
|
|
210
210
|
* @internal
|
|
211
211
|
*/
|
|
212
|
-
const renderBelowTargetTable = (files) => {
|
|
212
|
+
const renderBelowTargetTable = (files, cwd) => {
|
|
213
213
|
if (files.length === 0) return [];
|
|
214
214
|
const rows = files.map((f) => ({
|
|
215
|
-
file: relativePath(f.file),
|
|
215
|
+
file: relativePath(f.file, cwd),
|
|
216
216
|
stmts: String(Math.round(f.summary.statements)),
|
|
217
217
|
branches: String(Math.round(f.summary.branches)),
|
|
218
218
|
funcs: String(Math.round(f.summary.functions)),
|
|
@@ -331,7 +331,7 @@ const renderCoverageSection = (reports, options, ao) => {
|
|
|
331
331
|
lines.push("Files below aspirational target:");
|
|
332
332
|
const limit = options.coverageConsoleLimit;
|
|
333
333
|
const shown = agg.belowTargetFiles.slice(0, limit);
|
|
334
|
-
lines.push(...renderBelowTargetTable(shown));
|
|
334
|
+
lines.push(...renderBelowTargetTable(shown, options.cwd));
|
|
335
335
|
if (agg.belowTargetFiles.length > limit) lines.push(`… ${agg.belowTargetFiles.length - limit} more (use the test_coverage MCP tool for the full list)`);
|
|
336
336
|
}
|
|
337
337
|
return lines;
|
|
@@ -342,7 +342,7 @@ const renderCoverageSection = (reports, options, ao) => {
|
|
|
342
342
|
*
|
|
343
343
|
* @internal
|
|
344
344
|
*/
|
|
345
|
-
const renderFailuresSection = (reports, ao) => {
|
|
345
|
+
const renderFailuresSection = (reports, cwd, ao) => {
|
|
346
346
|
const lines = [];
|
|
347
347
|
const reportsWithFailures = reports.filter((r) => r.summary.failed > 0 || r.unhandledErrors.length > 0);
|
|
348
348
|
if (reportsWithFailures.length === 0) return lines;
|
|
@@ -351,7 +351,7 @@ const renderFailuresSection = (reports, ao) => {
|
|
|
351
351
|
const projectName = report.project ?? "default";
|
|
352
352
|
lines.push(` ${projectName}`);
|
|
353
353
|
for (const mod of report.failed) {
|
|
354
|
-
const file = relativePath(mod.file);
|
|
354
|
+
const file = relativePath(mod.file, cwd);
|
|
355
355
|
const failedTests = mod.tests.filter((t) => t.state === "failed");
|
|
356
356
|
for (const test of failedTests) lines.push(...renderFailedTest(file, test, ao));
|
|
357
357
|
if (mod.errors && mod.errors.length > 0) for (const err of mod.errors) {
|
|
@@ -403,7 +403,7 @@ const renderTotal = (reports, ao) => {
|
|
|
403
403
|
const renderNextSteps = (reports, options) => {
|
|
404
404
|
const lines = [];
|
|
405
405
|
const allFailedFiles = /* @__PURE__ */ new Set();
|
|
406
|
-
for (const r of reports) for (const f of r.failedFiles) allFailedFiles.add(relativePath(f));
|
|
406
|
+
for (const r of reports) for (const f of r.failedFiles) allFailedFiles.add(relativePath(f, options.cwd));
|
|
407
407
|
if (allFailedFiles.size === 0) return lines;
|
|
408
408
|
lines.push("Next steps:");
|
|
409
409
|
for (const file of allFailedFiles) lines.push(` Re-run: pnpm vitest run ${file}`);
|
|
@@ -470,7 +470,7 @@ const formatTerminal = (reports, options) => {
|
|
|
470
470
|
out.push("");
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
|
-
const failures = renderFailuresSection(reports, ao);
|
|
473
|
+
const failures = renderFailuresSection(reports, options.cwd, ao);
|
|
474
474
|
if (failures.length > 0) {
|
|
475
475
|
out.push(...failures);
|
|
476
476
|
out.push("");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/utils/posix-path.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pure POSIX path helpers for the platform-free core.
|
|
4
|
+
*
|
|
5
|
+
* `@vitest-agent/sdk` must not import `node:path`, so the handful of path
|
|
6
|
+
* operations the core needs are implemented here over normalized
|
|
7
|
+
* forward-slash strings. Every helper accepts Windows-style input (a
|
|
8
|
+
* backslash separator) and normalizes it via {@link toPosix} at entry, so a
|
|
9
|
+
* caller never has to know which separator the platform used.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes `p` to forward slashes: every backslash becomes `/`.
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
const toPosix = (p) => p.replaceAll("\\", "/");
|
|
16
|
+
/**
|
|
17
|
+
* Last segment of `p` after normalization — `"b.ts"` for `"/a/b.ts"`.
|
|
18
|
+
* Trailing separators are ignored, so `"/a/b/"` yields `"b"`.
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
const basenamePosix = (p) => {
|
|
22
|
+
const normalized = toPosix(p).replace(/\/+$/, "");
|
|
23
|
+
const index = normalized.lastIndexOf("/");
|
|
24
|
+
return index === -1 ? normalized : normalized.slice(index + 1);
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Joins `parts` with a single `/` between each, normalizing every part and
|
|
28
|
+
* collapsing duplicate separators at the seams. Empty parts are skipped.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
const joinPosix = (...parts) => {
|
|
32
|
+
const normalized = parts.map(toPosix).filter((part) => part.length > 0);
|
|
33
|
+
if (normalized.length === 0) return "";
|
|
34
|
+
const [first, ...rest] = normalized;
|
|
35
|
+
return rest.reduce((acc, part) => `${acc.replace(/\/+$/, "")}/${part.replace(/^\/+/, "")}`, first);
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Path of `to` relative to `from`, both normalized. Returns `""` when they
|
|
39
|
+
* are the same path and `to` unchanged when it is not under `from` (no
|
|
40
|
+
* `../` climbing — the core has no notion of a filesystem to climb through).
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
const relativePosix = (from, to) => {
|
|
44
|
+
const base = toPosix(from).replace(/\/+$/, "");
|
|
45
|
+
const target = toPosix(to);
|
|
46
|
+
if (target === base) return "";
|
|
47
|
+
const prefix = `${base}/`;
|
|
48
|
+
return target.startsWith(prefix) ? target.slice(prefix.length) : target;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { basenamePosix, joinPosix, relativePosix, toPosix };
|
package/utils/test-location.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { basenamePosix, joinPosix, relativePosix, toPosix } from "./posix-path.js";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/test-location.ts
|
|
4
4
|
/** Directory holding source files whose tests may be co-located. @public */
|
|
@@ -58,9 +58,15 @@ const TEST_FILE_SUFFIX_RE = /\.(?:test|spec)\.(?:ts|tsx|js|jsx)$/;
|
|
|
58
58
|
function isTestFileName(filePathOrName) {
|
|
59
59
|
return TEST_FILE_SUFFIX_RE.test(filePathOrName);
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* True when `child` is `parent` or sits beneath it on a segment boundary.
|
|
63
|
+
* Both sides are normalized to forward slashes first, so a Windows path
|
|
64
|
+
* compares the same way a POSIX one does.
|
|
65
|
+
*/
|
|
62
66
|
function contains(parent, child) {
|
|
63
|
-
|
|
67
|
+
const parentPosix = toPosix(parent);
|
|
68
|
+
const childPosix = toPosix(child);
|
|
69
|
+
return childPosix === parentPosix || childPosix.startsWith(parentPosix.endsWith("/") ? parentPosix : `${parentPosix}/`);
|
|
64
70
|
}
|
|
65
71
|
/**
|
|
66
72
|
* Returns the deepest supplied workspace containing `filePath`, or `null` when
|
|
@@ -100,7 +106,7 @@ function findOwningWorkspace(workspaces, filePath) {
|
|
|
100
106
|
function classifyTestPath(workspaces, filePath) {
|
|
101
107
|
const owner = findOwningWorkspace(workspaces, filePath);
|
|
102
108
|
if (owner === null) return null;
|
|
103
|
-
const segments =
|
|
109
|
+
const segments = relativePosix(owner.path, filePath).split("/");
|
|
104
110
|
if (segments.some((s) => NON_DISCOVERABLE_DIRS.has(s))) return null;
|
|
105
111
|
const [head] = segments;
|
|
106
112
|
if (head === "src") return {
|
|
@@ -119,7 +125,7 @@ function classifyTestPath(workspaces, filePath) {
|
|
|
119
125
|
return {
|
|
120
126
|
verdict: "invalid",
|
|
121
127
|
workspace: owner.name,
|
|
122
|
-
suggestedPath:
|
|
128
|
+
suggestedPath: joinPosix(owner.path, TEST_DIR, basenamePosix(filePath))
|
|
123
129
|
};
|
|
124
130
|
}
|
|
125
131
|
|
package/version.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/version.ts
|
|
2
|
+
/**
|
|
3
|
+
* The version of this package. Inlined at build time from
|
|
4
|
+
* package.json#version via rslib-builder's __PACKAGE_VERSION__ substitution.
|
|
5
|
+
* Source-level reads (workspace `exports: "./src/index.ts"` during dev)
|
|
6
|
+
* see the `"0.0.0"` fallback — a clear signal the build pipeline has not
|
|
7
|
+
* substituted yet. Exported for version introspection by downstream tooling.
|
|
8
|
+
*
|
|
9
|
+
* This is the one sanctioned `process` read in the platform-free core: the
|
|
10
|
+
* bundler replaces the token at build time, so no runtime `process` access
|
|
11
|
+
* survives into the published artifact.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
const CURRENT_SDK_VERSION = "4.0.0";
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CURRENT_SDK_VERSION };
|