@visulima/task-runner 1.0.0-alpha.3 → 1.0.0-alpha.5

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +193 -51
  3. package/dist/affected.d.ts +37 -3
  4. package/dist/cache.d.ts +8 -1
  5. package/dist/command-parser/expand-arguments.d.ts +11 -0
  6. package/dist/command-parser/expand-shortcut.d.ts +15 -0
  7. package/dist/command-parser/expand-wildcard.d.ts +13 -0
  8. package/dist/command-parser/index.d.ts +18 -0
  9. package/dist/command-parser/strip-quotes.d.ts +6 -0
  10. package/dist/concurrent-fallback.d.ts +16 -0
  11. package/dist/concurrent.d.ts +23 -0
  12. package/dist/detect-shell.d.ts +19 -0
  13. package/dist/flow-controllers/index.d.ts +7 -0
  14. package/dist/flow-controllers/input-handler.d.ts +44 -0
  15. package/dist/flow-controllers/log-timings.d.ts +18 -0
  16. package/dist/flow-controllers/restart-process.d.ts +21 -0
  17. package/dist/flow-controllers/teardown.d.ts +22 -0
  18. package/dist/index.d.ts +14 -4
  19. package/dist/index.js +26 -12
  20. package/dist/native-binding.d.ts +44 -2
  21. package/dist/packem_shared/{Cache-IYpTYVUC.js → Cache-iAjRMV2d.js} +5 -5
  22. package/dist/packem_shared/{FingerprintManager-D6Y0erg-.js → FingerprintManager-Cu-ta9ee.js} +0 -1
  23. package/dist/packem_shared/{IncrementalFileHasher-Ds3J6dgb.js → IncrementalFileHasher-Cm_kJY5V.js} +1 -1
  24. package/dist/packem_shared/{TaskOrchestrator-BvYs3ONw.js → TaskOrchestrator-lLn-PH1m.js} +2 -5
  25. package/dist/packem_shared/TerminalBuffer-CnPyFgPB.js +266 -0
  26. package/dist/packem_shared/{filterAffectedTasks-I-18zPg6.js → buildForwardDependencyMap-0BJFMMPv.js} +61 -21
  27. package/dist/packem_shared/{computeTaskHash-BoCnnvIJ.js → computeTaskHash-B2SVZqgp.js} +1 -2
  28. package/dist/packem_shared/createInputHandler-DTfePcTG.js +37 -0
  29. package/dist/packem_shared/{defaultTaskRunner-CrW4v5Ye.js → defaultTaskRunner-BdFTifsh.js} +6 -7
  30. package/dist/packem_shared/detectScriptShell-CR-xXKA4.js +53 -0
  31. package/dist/packem_shared/enforceProjectConstraints-C5Jp_C3u.js +111 -0
  32. package/dist/packem_shared/expandArguments-0AwD2BIA.js +26 -0
  33. package/dist/packem_shared/expandShortcut-BVG05ee4.js +23 -0
  34. package/dist/packem_shared/expandWildcard-B0xN_knq.js +107 -0
  35. package/dist/packem_shared/{findCycle-DF4_BRdO.js → findCycle-DefgNYhg.js} +1 -1
  36. package/dist/packem_shared/formatTimingTable-3qtCM552.js +46 -0
  37. package/dist/packem_shared/isNativeAvailable-BpD28A6Z.js +44 -0
  38. package/dist/packem_shared/parseCommands-D-IgF8Zh.js +26 -0
  39. package/dist/packem_shared/{TaskScheduler-CJilHDta.js → parsePartition-C4-P5RjK.js} +44 -1
  40. package/dist/packem_shared/{projectGraphToDot-VdTjHcVp.js → projectGraphToDot-C8uYeaPo.js} +20 -3
  41. package/dist/packem_shared/runConcurrentFallback-CGHz_f-Q.js +371 -0
  42. package/dist/packem_shared/runConcurrently-qrkWyzXW.js +67 -0
  43. package/dist/packem_shared/runTeardown-BAezH79J.js +49 -0
  44. package/dist/packem_shared/stripQuotes-Cey-zwFf.js +9 -0
  45. package/dist/packem_shared/withRestart-BREjRJa4.js +49 -0
  46. package/dist/project-constraints.d.ts +9 -0
  47. package/dist/task-scheduler.d.ts +23 -0
  48. package/dist/terminal-buffer.d.ts +29 -0
  49. package/dist/types.d.ts +239 -1
  50. package/index.js +769 -0
  51. package/package.json +14 -13
  52. package/binding.js +0 -204
  53. package/dist/packem_shared/isNativeAvailable-BWhnZ4ES.js +0 -19
  54. package/dist/packem_shared/{RemoteCache-BDqrnDEi.js → RemoteCache-BFceSe4a.js} +1 -1
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Log timings flow controller.
3
+ *
4
+ * Prints a summary table of all command durations after completion.
5
+ */
6
+ import type { ConcurrentCloseEvent } from "../types.d.ts";
7
+ /**
8
+ * Generate a timing summary table string from close events.
9
+ * @param closeEvents Close events from the concurrent run (in completion order)
10
+ * @returns Formatted table string
11
+ */
12
+ export declare const formatTimingTable: (closeEvents: ConcurrentCloseEvent[]) => string;
13
+ /**
14
+ * Print timing summary to a writable stream.
15
+ * @param closeEvents Close events from the concurrent run
16
+ * @param output Output stream (default: process.stdout)
17
+ */
18
+ export declare const logTimings: (closeEvents: ConcurrentCloseEvent[], output?: NodeJS.WritableStream) => void;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Restart flow controller.
3
+ *
4
+ * Re-runs failed commands with configurable retry count and delay.
5
+ * Supports fixed delay or exponential backoff.
6
+ */
7
+ import type { ConcurrentCommandConfig, ConcurrentRunnerOptions, ConcurrentRunResult } from "../types.d.ts";
8
+ export interface RestartOptions {
9
+ /** Delay between restarts in milliseconds. "exponential" for 2^attempt * 1000ms. */
10
+ delay: number | "exponential";
11
+ /** Maximum number of restart attempts per command. 0 = no restarts. -1 = infinite. */
12
+ tries: number;
13
+ }
14
+ /**
15
+ * Wraps a runner function to add restart-on-failure behavior.
16
+ * @param runFn The underlying runner function (runConcurrently or runConcurrentFallback)
17
+ * @param commands The original command configs
18
+ * @param options Runner options
19
+ * @param restartOptions Restart-specific options
20
+ */
21
+ export declare const withRestart: (runFunction: (commands: ConcurrentCommandConfig[], options: ConcurrentRunnerOptions) => Promise<ConcurrentRunResult>, commands: ConcurrentCommandConfig[], options: ConcurrentRunnerOptions, restartOptions: RestartOptions) => Promise<ConcurrentRunResult>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Teardown flow controller.
3
+ *
4
+ * Runs cleanup commands sequentially after all concurrent processes complete.
5
+ * Each teardown command inherits stdio (output goes directly to terminal).
6
+ *
7
+ * Commands are sourced from configuration (trusted, not user input).
8
+ * Shell execution is intentional for pipe/redirect support.
9
+ */
10
+ export interface TeardownOptions {
11
+ /** Commands to run in sequence after all processes complete. */
12
+ commands: string[];
13
+ /** Working directory for teardown commands. */
14
+ cwd?: string;
15
+ }
16
+ /**
17
+ * Run teardown commands sequentially.
18
+ * Each command runs in the shell with inherited stdio.
19
+ * If a command fails, subsequent commands are still attempted.
20
+ * @returns Array of exit codes for each teardown command
21
+ */
22
+ export declare const runTeardown: (options: TeardownOptions) => Promise<number[]>;
package/dist/index.d.ts CHANGED
@@ -1,12 +1,19 @@
1
1
  export type { AffectedOptions, AffectedResult } from "./affected.d.ts";
2
- export { filterAffectedTasks, getAffectedProjects, getChangedFiles } from "./affected.d.ts";
2
+ export { buildForwardDependencyMap, buildReverseDependencyMap, expandAffected, filterAffectedTasks, getAffectedProjects, getChangedFiles } from "./affected.d.ts";
3
3
  export type { CachedResult, CacheOptions } from "./cache.d.ts";
4
- export { Cache, formatCacheSize, parseCacheSize } from "./cache.d.ts";
4
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize } from "./cache.d.ts";
5
+ export type { ParseCommandsOptions } from "./command-parser/index.d.ts";
6
+ export { expandArguments, expandShortcut, expandWildcard, parseCommands, stripQuotes } from "./command-parser/index.d.ts";
7
+ export { runConcurrently } from "./concurrent.d.ts";
8
+ export { runConcurrentFallback } from "./concurrent-fallback.d.ts";
5
9
  export { defaultTaskRunner } from "./default-task-runner.d.ts";
10
+ export { detectScriptShell } from "./detect-shell.d.ts";
6
11
  export type { FileAccess, TrackingResult } from "./file-access-tracker.d.ts";
7
12
  export { FileAccessTracker, generatePreloadScript } from "./file-access-tracker.d.ts";
8
13
  export type { CacheMissReason, TaskFingerprint } from "./fingerprint.d.ts";
9
14
  export { FingerprintManager } from "./fingerprint.d.ts";
15
+ export type { InputHandlerOptions, RestartOptions, TeardownOptions } from "./flow-controllers/index.d.ts";
16
+ export { createInputHandler, formatTimingTable, logTimings, runTeardown, withRestart } from "./flow-controllers/index.d.ts";
10
17
  export type { DetectedFramework } from "./framework-inference.d.ts";
11
18
  export { detectFrameworks, getFrameworkEnvVariables, inferFrameworkEnvPatterns } from "./framework-inference.d.ts";
12
19
  export type { GraphFormat, GraphJson, GraphVisualizerOptions } from "./graph-visualizer.d.ts";
@@ -17,6 +24,7 @@ export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle } from "./life-cyc
17
24
  export type { PackageLockfileHash, ResolvedDependency } from "./lockfile-hasher.d.ts";
18
25
  export { extractPackageName, LockfileHasher, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile } from "./lockfile-hasher.d.ts";
19
26
  export { isNativeAvailable, loadNativeBindings } from "./native-binding.d.ts";
27
+ export { enforceProjectConstraints } from "./project-constraints.d.ts";
20
28
  export type { RemoteCacheOptions } from "./remote-cache.d.ts";
21
29
  export { RemoteCache } from "./remote-cache.d.ts";
22
30
  export type { RunSummary, TaskSummary } from "./run-summary.d.ts";
@@ -27,8 +35,10 @@ export type { TaskHasher, TaskHasherOptions } from "./task-hasher.d.ts";
27
35
  export { computeTaskHash, InProcessTaskHasher } from "./task-hasher.d.ts";
28
36
  export type { TaskOrchestratorOptions } from "./task-orchestrator.d.ts";
29
37
  export { TaskOrchestrator } from "./task-orchestrator.d.ts";
30
- export { TaskScheduler } from "./task-scheduler.d.ts";
38
+ export type { PartitionOptions } from "./task-scheduler.d.ts";
39
+ export { parsePartition, TaskScheduler } from "./task-scheduler.d.ts";
40
+ export { TerminalBuffer } from "./terminal-buffer.d.ts";
31
41
  export type { TrackedExecutionResult } from "./tracked-executor.d.ts";
32
42
  export { TrackedTaskExecutor } from "./tracked-executor.d.ts";
33
- export type { EnvironmentInput, ExternalDependencyInput, FileSetInput, InputDefinition, LifeCycleInterface, NamedInputs, ProjectConfiguration, ProjectGraph, ProjectGraphDependency, ProjectGraphProjectNode, RuntimeInput, TargetConfiguration, TargetDependencyConfig, Task, TaskExecutionOptions, TaskExecutor, TaskGraph, TaskHashDetails, TaskResult, TaskResults, TaskRunnerContext, TaskRunnerOptions, TasksRunner, TaskStatus, TaskTarget, WorkspaceConfiguration, } from "./types.d.ts";
43
+ export type { AffectedScope, ConcurrentCloseEvent, ConcurrentCommandConfig, ConcurrentCommandInput, ConcurrentRunnerOptions, ConcurrentRunResult, ConstraintsConfig, ConstraintViolation, DependencyKindRules, DependencyType, EnvironmentInput, ExternalDependencyInput, FileSetInput, InputDefinition, LifeCycleInterface, NamedInputs, ProcessEvent, ProjectConfiguration, ProjectGraph, ProjectGraphDependency, ProjectGraphProjectNode, RuntimeInput, TagRelationships, TargetConfiguration, TargetDependencyConfig, Task, TaskExecutionOptions, TaskExecutor, TaskGraph, TaskHashDetails, TaskResult, TaskResults, TaskRunnerContext, TaskRunnerOptions, TasksRunner, TaskStatus, TaskTarget, TypeBoundaries, WorkspaceConfiguration, } from "./types.d.ts";
34
44
  export { collectFiles, createFailureResult, hashFile, hashStrings, readPackageDeps, resolveTaskCwd, sortObjectKeys, uniqueId } from "./utils.d.ts";
package/dist/index.js CHANGED
@@ -1,20 +1,34 @@
1
- export { filterAffectedTasks, getAffectedProjects, getChangedFiles } from './packem_shared/filterAffectedTasks-I-18zPg6.js';
2
- export { Cache, formatCacheSize, parseCacheSize } from './packem_shared/Cache-IYpTYVUC.js';
3
- export { defaultTaskRunner } from './packem_shared/defaultTaskRunner-CrW4v5Ye.js';
1
+ export { buildForwardDependencyMap, buildReverseDependencyMap, expandAffected, filterAffectedTasks, getAffectedProjects, getChangedFiles } from './packem_shared/buildForwardDependencyMap-0BJFMMPv.js';
2
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize } from './packem_shared/Cache-iAjRMV2d.js';
3
+ export { parseCommands } from './packem_shared/parseCommands-D-IgF8Zh.js';
4
+ export { runConcurrently } from './packem_shared/runConcurrently-qrkWyzXW.js';
5
+ export { runConcurrentFallback } from './packem_shared/runConcurrentFallback-CGHz_f-Q.js';
6
+ export { defaultTaskRunner } from './packem_shared/defaultTaskRunner-BdFTifsh.js';
7
+ export { detectScriptShell } from './packem_shared/detectScriptShell-CR-xXKA4.js';
4
8
  export { FileAccessTracker, generatePreloadScript } from './packem_shared/FileAccessTracker-CrtBAt5D.js';
5
- export { FingerprintManager } from './packem_shared/FingerprintManager-D6Y0erg-.js';
9
+ export { FingerprintManager } from './packem_shared/FingerprintManager-Cu-ta9ee.js';
6
10
  export { detectFrameworks, getFrameworkEnvVariables, inferFrameworkEnvPatterns } from './packem_shared/detectFrameworks-CeFzKE6J.js';
7
- export { projectGraphToDot, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot } from './packem_shared/projectGraphToDot-VdTjHcVp.js';
8
- export { IncrementalFileHasher } from './packem_shared/IncrementalFileHasher-Ds3J6dgb.js';
11
+ export { projectGraphToDot, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot } from './packem_shared/projectGraphToDot-C8uYeaPo.js';
12
+ export { IncrementalFileHasher } from './packem_shared/IncrementalFileHasher-Cm_kJY5V.js';
9
13
  export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle } from './packem_shared/CompositeLifeCycle-7AtYw1dv.js';
10
14
  export { LockfileHasher, extractPackageName, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile } from './packem_shared/extractPackageName-CbVNW-dr.js';
11
- export { isNativeAvailable, loadNativeBindings } from './packem_shared/isNativeAvailable-BWhnZ4ES.js';
12
- export { RemoteCache } from './packem_shared/RemoteCache-BDqrnDEi.js';
15
+ export { isNativeAvailable, loadNativeBindings } from './packem_shared/isNativeAvailable-BpD28A6Z.js';
16
+ export { enforceProjectConstraints } from './packem_shared/enforceProjectConstraints-C5Jp_C3u.js';
17
+ export { RemoteCache } from './packem_shared/RemoteCache-BFceSe4a.js';
13
18
  export { generateRunSummary, writeRunSummary } from './packem_shared/generateRunSummary-qn-_jKwt.js';
14
19
  export { createTaskGraph, getTaskId, parseTaskId } from './packem_shared/createTaskGraph-CcsFaSrz.js';
15
- export { findCycle, findCycles, getDependentTasks, getLeafTasks, getTransitiveDependencies, makeAcyclic, reverseTaskGraph, walkTaskGraph } from './packem_shared/findCycle-DF4_BRdO.js';
16
- export { InProcessTaskHasher, computeTaskHash } from './packem_shared/computeTaskHash-BoCnnvIJ.js';
17
- export { TaskOrchestrator } from './packem_shared/TaskOrchestrator-BvYs3ONw.js';
18
- export { TaskScheduler } from './packem_shared/TaskScheduler-CJilHDta.js';
20
+ export { findCycle, findCycles, getDependentTasks, getLeafTasks, getTransitiveDependencies, makeAcyclic, reverseTaskGraph, walkTaskGraph } from './packem_shared/findCycle-DefgNYhg.js';
21
+ export { InProcessTaskHasher, computeTaskHash } from './packem_shared/computeTaskHash-B2SVZqgp.js';
22
+ export { TaskOrchestrator } from './packem_shared/TaskOrchestrator-lLn-PH1m.js';
23
+ export { TaskScheduler, parsePartition } from './packem_shared/parsePartition-C4-P5RjK.js';
24
+ export { TerminalBuffer } from './packem_shared/TerminalBuffer-CnPyFgPB.js';
19
25
  export { TrackedTaskExecutor } from './packem_shared/TrackedTaskExecutor-BGUKFE-7.js';
20
26
  export { c as collectFiles, a as createFailureResult, h as hashFile, b as hashStrings, r as readPackageDeps, d as resolveTaskCwd, s as sortObjectKeys, u as uniqueId } from './packem_shared/utils-zO0ZRgtf.js';
27
+ export { createInputHandler } from './packem_shared/createInputHandler-DTfePcTG.js';
28
+ export { expandArguments } from './packem_shared/expandArguments-0AwD2BIA.js';
29
+ export { expandShortcut } from './packem_shared/expandShortcut-BVG05ee4.js';
30
+ export { expandWildcard } from './packem_shared/expandWildcard-B0xN_knq.js';
31
+ export { formatTimingTable, logTimings } from './packem_shared/formatTimingTable-3qtCM552.js';
32
+ export { runTeardown } from './packem_shared/runTeardown-BAezH79J.js';
33
+ export { stripQuotes } from './packem_shared/stripQuotes-Cey-zwFf.js';
34
+ export { withRestart } from './packem_shared/withRestart-BREjRJa4.js';
@@ -30,6 +30,44 @@ interface NativeCycleResult {
30
30
  cycle: string[];
31
31
  has_cycle: boolean;
32
32
  }
33
+ interface NativeConcurrentCommandConfig {
34
+ command: string;
35
+ cwd?: string;
36
+ env?: Record<string, string>;
37
+ name?: string;
38
+ shell?: boolean;
39
+ stdin?: string;
40
+ }
41
+ interface NativeConcurrentRunnerOptions {
42
+ killOthers?: string[];
43
+ killSignal?: string;
44
+ killTimeout?: number;
45
+ maxProcesses?: number;
46
+ shellPath?: string;
47
+ successCondition?: string;
48
+ }
49
+ interface NativeProcessEvent {
50
+ commandName?: string;
51
+ durationMs?: number;
52
+ exitCode?: number;
53
+ index: number;
54
+ killed?: boolean;
55
+ kind: string;
56
+ message?: string;
57
+ text?: string;
58
+ }
59
+ interface NativeConcurrentCloseEvent {
60
+ command: string;
61
+ durationMs: number;
62
+ exitCode: number;
63
+ index: number;
64
+ killed: boolean;
65
+ name?: string;
66
+ }
67
+ interface NativeConcurrentRunResult {
68
+ closeEvents: NativeConcurrentCloseEvent[];
69
+ success: boolean;
70
+ }
33
71
  interface NativeBindings {
34
72
  collectFiles: (directory: string) => string[];
35
73
  computeTaskHash: (details: NativeTaskHashDetails) => string;
@@ -45,6 +83,8 @@ interface NativeBindings {
45
83
  hashFilesInDirectory: (directory: string, workspaceRoot: string) => NativeFileHash[];
46
84
  hashString: (input: string) => string;
47
85
  hashStrings: (inputs: string[]) => string;
86
+ runConcurrent: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions, onEvent: (event: NativeProcessEvent) => void) => Promise<NativeConcurrentRunResult>;
87
+ runConcurrentBatch: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions) => Promise<NativeConcurrentRunResult>;
48
88
  topologicalSort: (graph: NativeTaskGraph) => string[];
49
89
  }
50
90
  /**
@@ -52,13 +92,15 @@ interface NativeBindings {
52
92
  * The result is cached after the first attempt.
53
93
  *
54
94
  * napi v3 outputs the .node file to the package root as
55
- * `task-runner-native.&lt;platform>.node`. The napi-generated binding.js
95
+ * `task-runner-native.&lt;platform>.node`. The napi-generated index.js
56
96
  * handles platform detection automatically.
97
+ *
98
+ * Uses createRequire because the napi-generated index.js is CJS.
57
99
  */
58
100
  declare const loadNativeBindings: () => NativeBindings | undefined;
59
101
  /**
60
102
  * Returns true if the native addon is loaded and available.
61
103
  */
62
104
  declare const isNativeAvailable: () => boolean;
63
- export type { NativeBindings, NativeCycleResult, NativeFileHash, NativeTaskGraph, NativeTaskHashDetails };
105
+ export type { NativeBindings, NativeConcurrentCloseEvent, NativeConcurrentCommandConfig, NativeConcurrentRunnerOptions, NativeConcurrentRunResult, NativeCycleResult, NativeFileHash, NativeProcessEvent, NativeTaskGraph, NativeTaskHashDetails, };
64
106
  export { isNativeAvailable, loadNativeBindings };
@@ -27,11 +27,12 @@ const {
27
27
  cp,
28
28
  readdir
29
29
  } = __cjs_getBuiltinModule("node:fs/promises");
30
- import { join, resolve, dirname } from '@visulima/path';
31
30
  import { formatBytes, parseBytes } from '@visulima/humanizer';
31
+ import { join, resolve, dirname } from '@visulima/path';
32
32
  import { u as uniqueId } from './utils-zO0ZRgtf.js';
33
33
 
34
34
  const DEFAULT_MAX_CACHE_AGE = 7 * 24 * 60 * 60 * 1e3;
35
+ const DEFAULT_CACHE_DIRECTORY_NAME = ".task-runner-cache";
35
36
  const removeEntry = async (entryPath) => {
36
37
  try {
37
38
  await rm(entryPath, { force: true, recursive: true });
@@ -58,7 +59,7 @@ const getDirectorySize = async (directoryPath) => {
58
59
  const parseCacheSize = (sizeString) => {
59
60
  const result = parseBytes(sizeString.trim());
60
61
  if (Number.isNaN(result)) {
61
- throw new Error(`Invalid cache size format: "${sizeString}". Expected format like "500MB" or "1GB".`);
62
+ throw new TypeError(`Invalid cache size format: "${sizeString}". Expected format like "500MB" or "1GB".`);
62
63
  }
63
64
  return result;
64
65
  };
@@ -72,7 +73,7 @@ class Cache {
72
73
  #indexWriteQueue = Promise.resolve();
73
74
  constructor(options) {
74
75
  this.#workspaceRoot = options.workspaceRoot;
75
- this.#cacheDirectory = options.cacheDirectory ?? join(options.workspaceRoot, ".task-runner-cache");
76
+ this.#cacheDirectory = options.cacheDirectory ?? join(options.workspaceRoot, DEFAULT_CACHE_DIRECTORY_NAME);
76
77
  this.#maxCacheAge = options.maxCacheAge ?? DEFAULT_MAX_CACHE_AGE;
77
78
  this.#maxCacheSize = options.maxCacheSize ? parseCacheSize(options.maxCacheSize) : void 0;
78
79
  }
@@ -222,7 +223,6 @@ class Cache {
222
223
  * Removes old cache entries that exceed the maximum age,
223
224
  * and enforces the maximum cache size by evicting oldest entries.
224
225
  */
225
- // eslint-disable-next-line sonarjs/cognitive-complexity
226
226
  async removeOldEntries() {
227
227
  try {
228
228
  const entries = await readdir(this.#cacheDirectory);
@@ -295,4 +295,4 @@ class Cache {
295
295
  }
296
296
  }
297
297
 
298
- export { Cache, formatCacheSize, parseCacheSize };
298
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize };
@@ -30,7 +30,6 @@ class FingerprintManager {
30
30
  constructor(workspaceRoot) {
31
31
  this.#workspaceRoot = resolve(workspaceRoot);
32
32
  }
33
- // eslint-disable-next-line sonarjs/cognitive-complexity
34
33
  async createFingerprint(accesses, command, args, envVariables, envPatterns = [], untrackedEnvVariables = []) {
35
34
  const fileHashes = {};
36
35
  const missingPaths = /* @__PURE__ */ new Set();
@@ -118,7 +118,7 @@ class IncrementalFileHasher {
118
118
  return void 0;
119
119
  }
120
120
  const cached = this.#snapshot.get(filePath);
121
- if (cached && cached.mtimeMs === fileStat.mtimeMs && cached.size === fileStat.size) {
121
+ if (cached?.mtimeMs === fileStat.mtimeMs && cached.size === fileStat.size) {
122
122
  return cached.hash;
123
123
  }
124
124
  const content = await readFile(filePath);
@@ -1,8 +1,8 @@
1
1
  import { d as resolveTaskCwd, a as createFailureResult, e as createXxh3Hasher } from './utils-zO0ZRgtf.js';
2
2
  import { join } from '@visulima/path';
3
- import { FingerprintManager } from './FingerprintManager-D6Y0erg-.js';
3
+ import { FingerprintManager } from './FingerprintManager-Cu-ta9ee.js';
4
4
  import { generateRunSummary, writeRunSummary } from './generateRunSummary-qn-_jKwt.js';
5
- import { computeTaskHash } from './computeTaskHash-BoCnnvIJ.js';
5
+ import { computeTaskHash } from './computeTaskHash-B2SVZqgp.js';
6
6
  import { TrackedTaskExecutor } from './TrackedTaskExecutor-BGUKFE-7.js';
7
7
 
8
8
  const hashFingerprint = (fingerprint) => {
@@ -107,7 +107,6 @@ class TaskOrchestrator {
107
107
  }
108
108
  return this.#results;
109
109
  }
110
- // eslint-disable-next-line sonarjs/cognitive-complexity
111
110
  async #executionLoop() {
112
111
  while (!this.#scheduler.isComplete() && !this.#aborted) {
113
112
  const batch = this.#scheduler.getNextBatch();
@@ -153,7 +152,6 @@ class TaskOrchestrator {
153
152
  await Promise.all(this.#inFlightTasks.values());
154
153
  }
155
154
  }
156
- // eslint-disable-next-line sonarjs/cognitive-complexity
157
155
  async #processTask(task) {
158
156
  const startTime = Date.now();
159
157
  const hashDetails = await this.#taskHasher.hashTask(task);
@@ -186,7 +184,6 @@ class TaskOrchestrator {
186
184
  }
187
185
  return result;
188
186
  }
189
- // eslint-disable-next-line sonarjs/cognitive-complexity
190
187
  async #processTaskWithFingerprint(task) {
191
188
  const startTime = Date.now();
192
189
  if (!this.#skipCache && task.cache !== false) {
@@ -0,0 +1,266 @@
1
+ class TerminalBuffer {
2
+ #lines = [""];
3
+ #row = 0;
4
+ #col = 0;
5
+ #maxBytes;
6
+ constructor(maxBytes = 256 * 1024) {
7
+ this.#maxBytes = maxBytes;
8
+ }
9
+ /**
10
+ * Process raw PTY output data.
11
+ */
12
+ write(data) {
13
+ let i = 0;
14
+ while (i < data.length) {
15
+ const ch = data[i];
16
+ if (ch === "\x1B") {
17
+ if (i + 1 >= data.length) {
18
+ i++;
19
+ continue;
20
+ }
21
+ if (data[i + 1] === "[") {
22
+ const consumed = this.#processCsi(data, i + 2);
23
+ i = consumed;
24
+ continue;
25
+ }
26
+ i += data[i + 1] === "(" || data[i + 1] === ")" ? 3 : 2;
27
+ continue;
28
+ }
29
+ if (ch === "\r") {
30
+ this.#col = 0;
31
+ i++;
32
+ continue;
33
+ }
34
+ if (ch === "\n") {
35
+ this.#row++;
36
+ this.#col = 0;
37
+ this.#ensureRow(this.#row);
38
+ i++;
39
+ continue;
40
+ }
41
+ this.#ensureRow(this.#row);
42
+ this.#putChar(ch);
43
+ this.#col++;
44
+ i++;
45
+ }
46
+ this.#trimToMaxBytes();
47
+ }
48
+ /** Get the current buffer content as a string. */
49
+ toString() {
50
+ return this.#lines.join("\n");
51
+ }
52
+ /**
53
+ * Process a CSI sequence starting after "ESC [".
54
+ * Returns the index to continue parsing from.
55
+ */
56
+ #processCsi(data, start) {
57
+ let j = start;
58
+ let params = "";
59
+ while (j < data.length && (data[j] >= "0" && data[j] <= "9" || data[j] === ";")) {
60
+ params += data[j];
61
+ j++;
62
+ }
63
+ if (j >= data.length) {
64
+ return j;
65
+ }
66
+ const cmd = data[j];
67
+ const n = Number.parseInt(params, 10) || 1;
68
+ switch (cmd) {
69
+ case "A": {
70
+ this.#row = Math.max(0, this.#row - n);
71
+ break;
72
+ }
73
+ case "B": {
74
+ this.#row = Math.min(this.#lines.length - 1, this.#row + n);
75
+ break;
76
+ }
77
+ case "C": {
78
+ this.#col += n;
79
+ break;
80
+ }
81
+ case "D": {
82
+ this.#col = Math.max(0, this.#col - n);
83
+ break;
84
+ }
85
+ case "f":
86
+ case "H": {
87
+ const parts = params.split(";");
88
+ this.#row = Math.max(0, (Number.parseInt(parts[0] ?? "1", 10) || 1) - 1);
89
+ this.#col = Math.max(0, (Number.parseInt(parts[1] ?? "1", 10) || 1) - 1);
90
+ this.#ensureRow(this.#row);
91
+ break;
92
+ }
93
+ case "G": {
94
+ this.#col = Math.max(0, n - 1);
95
+ break;
96
+ }
97
+ case "J": {
98
+ this.#eraseDisplay(Number.parseInt(params, 10) || 0);
99
+ break;
100
+ }
101
+ case "K": {
102
+ this.#eraseLine(Number.parseInt(params, 10) || 0);
103
+ break;
104
+ }
105
+ case "m": {
106
+ const seq = `\x1B[${params}m`;
107
+ this.#ensureRow(this.#row);
108
+ this.#appendAtCursor(seq);
109
+ break;
110
+ }
111
+ }
112
+ return j + 1;
113
+ }
114
+ /** Write a visible character at the cursor position (overwrites). */
115
+ #putChar(ch) {
116
+ const line = this.#lines[this.#row] ?? "";
117
+ const visCol = this.#col;
118
+ let strIndex = 0;
119
+ let vis = 0;
120
+ while (strIndex < line.length && vis < visCol) {
121
+ if (line[strIndex] === "\x1B" && line[strIndex + 1] === "[") {
122
+ strIndex += 2;
123
+ while (strIndex < line.length && !(line[strIndex] >= "A" && line[strIndex] <= "Z" || line[strIndex] >= "a" && line[strIndex] <= "z")) {
124
+ strIndex++;
125
+ }
126
+ if (strIndex < line.length) {
127
+ strIndex++;
128
+ }
129
+ } else {
130
+ strIndex++;
131
+ vis++;
132
+ }
133
+ }
134
+ if (vis < visCol) {
135
+ this.#lines[this.#row] = line + " ".repeat(visCol - vis) + ch;
136
+ } else {
137
+ let endIndex = strIndex;
138
+ if (endIndex < line.length && line[endIndex] !== "\x1B") {
139
+ endIndex++;
140
+ }
141
+ this.#lines[this.#row] = line.slice(0, strIndex) + ch + line.slice(endIndex);
142
+ }
143
+ }
144
+ /** Append a zero-width sequence (SGR) at the current cursor position. */
145
+ #appendAtCursor(seq) {
146
+ const line = this.#lines[this.#row] ?? "";
147
+ let strIndex = 0;
148
+ let vis = 0;
149
+ while (strIndex < line.length && vis < this.#col) {
150
+ if (line[strIndex] === "\x1B" && line[strIndex + 1] === "[") {
151
+ strIndex += 2;
152
+ while (strIndex < line.length && !(line[strIndex] >= "A" && line[strIndex] <= "Z" || line[strIndex] >= "a" && line[strIndex] <= "z")) {
153
+ strIndex++;
154
+ }
155
+ if (strIndex < line.length) {
156
+ strIndex++;
157
+ }
158
+ } else {
159
+ strIndex++;
160
+ vis++;
161
+ }
162
+ }
163
+ this.#lines[this.#row] = line.slice(0, strIndex) + seq + line.slice(strIndex);
164
+ }
165
+ #eraseDisplay(mode) {
166
+ switch (mode) {
167
+ case 0: {
168
+ this.#ensureRow(this.#row);
169
+ this.#truncateLineAtCol(this.#row, this.#col);
170
+ this.#lines.length = this.#row + 1;
171
+ break;
172
+ }
173
+ case 1: {
174
+ for (let r = 0; r < this.#row; r++) {
175
+ this.#lines[r] = "";
176
+ }
177
+ this.#ensureRow(this.#row);
178
+ this.#fillLineToCol(this.#row, this.#col);
179
+ break;
180
+ }
181
+ case 2: {
182
+ this.#lines = [""];
183
+ this.#row = 0;
184
+ this.#col = 0;
185
+ break;
186
+ }
187
+ }
188
+ }
189
+ #eraseLine(mode) {
190
+ this.#ensureRow(this.#row);
191
+ switch (mode) {
192
+ case 0: {
193
+ this.#truncateLineAtCol(this.#row, this.#col);
194
+ break;
195
+ }
196
+ case 1: {
197
+ this.#fillLineToCol(this.#row, this.#col);
198
+ break;
199
+ }
200
+ case 2: {
201
+ this.#lines[this.#row] = "";
202
+ break;
203
+ }
204
+ }
205
+ }
206
+ /** Truncate a line at the given visual column. */
207
+ #truncateLineAtCol(row, col) {
208
+ const line = this.#lines[row] ?? "";
209
+ let strIndex = 0;
210
+ let vis = 0;
211
+ while (strIndex < line.length && vis < col) {
212
+ if (line[strIndex] === "\x1B" && line[strIndex + 1] === "[") {
213
+ strIndex += 2;
214
+ while (strIndex < line.length && !(line[strIndex] >= "A" && line[strIndex] <= "Z" || line[strIndex] >= "a" && line[strIndex] <= "z")) {
215
+ strIndex++;
216
+ }
217
+ if (strIndex < line.length) {
218
+ strIndex++;
219
+ }
220
+ } else {
221
+ strIndex++;
222
+ vis++;
223
+ }
224
+ }
225
+ this.#lines[row] = line.slice(0, strIndex);
226
+ }
227
+ /** Fill a line with spaces from start to the given visual column. */
228
+ #fillLineToCol(row, col) {
229
+ const line = this.#lines[row] ?? "";
230
+ let strIndex = 0;
231
+ let vis = 0;
232
+ while (strIndex < line.length && vis < col) {
233
+ if (line[strIndex] === "\x1B" && line[strIndex + 1] === "[") {
234
+ strIndex += 2;
235
+ while (strIndex < line.length && !(line[strIndex] >= "A" && line[strIndex] <= "Z" || line[strIndex] >= "a" && line[strIndex] <= "z")) {
236
+ strIndex++;
237
+ }
238
+ if (strIndex < line.length) {
239
+ strIndex++;
240
+ }
241
+ } else {
242
+ strIndex++;
243
+ vis++;
244
+ }
245
+ }
246
+ this.#lines[row] = " ".repeat(col) + line.slice(strIndex);
247
+ }
248
+ #ensureRow(row) {
249
+ while (this.#lines.length <= row) {
250
+ this.#lines.push("");
251
+ }
252
+ }
253
+ #trimToMaxBytes() {
254
+ let totalSize = 0;
255
+ for (const line of this.#lines) {
256
+ totalSize += line.length + 1;
257
+ }
258
+ while (totalSize > this.#maxBytes && this.#lines.length > 1) {
259
+ const removed = this.#lines.shift();
260
+ totalSize -= removed.length + 1;
261
+ this.#row = Math.max(0, this.#row - 1);
262
+ }
263
+ }
264
+ }
265
+
266
+ export { TerminalBuffer };