nx 22.1.0-canary.20251030-b283663 → 22.1.0-canary.20251106-e9146c7

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 (62) hide show
  1. package/executors.json +16 -16
  2. package/generators.json +13 -13
  3. package/migrations.json +143 -137
  4. package/package.json +11 -14
  5. package/presets/npm.json +4 -4
  6. package/schemas/nx-schema.json +1286 -1286
  7. package/schemas/project-schema.json +359 -359
  8. package/schemas/workspace-schema.json +165 -165
  9. package/src/ai/set-up-ai-agents/schema.json +31 -31
  10. package/src/command-line/init/implementation/dot-nx/add-nx-scripts.d.ts +2 -0
  11. package/src/command-line/init/implementation/dot-nx/add-nx-scripts.d.ts.map +1 -1
  12. package/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +11 -1
  13. package/src/core/graph/main.js +1 -1
  14. package/src/daemon/client/client.d.ts +1 -0
  15. package/src/daemon/client/client.d.ts.map +1 -1
  16. package/src/daemon/client/client.js +18 -1
  17. package/src/devkit-internals.d.ts +1 -1
  18. package/src/devkit-internals.d.ts.map +1 -1
  19. package/src/devkit-internals.js +2 -1
  20. package/src/executors/noop/schema.json +8 -8
  21. package/src/executors/run-commands/run-commands.impl.d.ts +1 -1
  22. package/src/executors/run-commands/run-commands.impl.d.ts.map +1 -1
  23. package/src/executors/run-commands/run-commands.impl.js +7 -4
  24. package/src/executors/run-commands/running-tasks.d.ts +4 -3
  25. package/src/executors/run-commands/running-tasks.d.ts.map +1 -1
  26. package/src/executors/run-commands/running-tasks.js +30 -9
  27. package/src/executors/run-commands/schema.json +187 -187
  28. package/src/executors/run-script/schema.json +25 -25
  29. package/src/generators/internal-utils/format-changed-files-with-prettier-if-available.d.ts.map +1 -1
  30. package/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +5 -1
  31. package/src/hasher/hash-task.d.ts +1 -0
  32. package/src/hasher/hash-task.d.ts.map +1 -1
  33. package/src/hasher/hash-task.js +57 -0
  34. package/src/migrations/update-22-1-0/update-nx-wrapper.d.ts +3 -0
  35. package/src/migrations/update-22-1-0/update-nx-wrapper.d.ts.map +1 -0
  36. package/src/migrations/update-22-1-0/update-nx-wrapper.js +7 -0
  37. package/src/native/index.d.ts +90 -0
  38. package/src/native/native-bindings.js +1 -0
  39. package/src/native/nx.wasm32-wasi.wasm +0 -0
  40. package/src/nx-cloud/generators/connect-to-nx-cloud/schema.json +38 -38
  41. package/src/project-graph/plugins/isolation/plugin-pool.d.ts.map +1 -1
  42. package/src/project-graph/plugins/isolation/plugin-pool.js +17 -1
  43. package/src/tasks-runner/create-task-graph.d.ts.map +1 -1
  44. package/src/tasks-runner/create-task-graph.js +4 -11
  45. package/src/tasks-runner/forked-process-task-runner.d.ts.map +1 -1
  46. package/src/tasks-runner/forked-process-task-runner.js +36 -4
  47. package/src/tasks-runner/is-tui-enabled.d.ts.map +1 -1
  48. package/src/tasks-runner/is-tui-enabled.js +0 -4
  49. package/src/tasks-runner/process-metrics-service.d.ts +54 -0
  50. package/src/tasks-runner/process-metrics-service.d.ts.map +1 -0
  51. package/src/tasks-runner/process-metrics-service.js +161 -0
  52. package/src/tasks-runner/pseudo-terminal.d.ts +1 -0
  53. package/src/tasks-runner/pseudo-terminal.d.ts.map +1 -1
  54. package/src/tasks-runner/pseudo-terminal.js +3 -0
  55. package/src/tasks-runner/running-tasks/node-child-process.d.ts.map +1 -1
  56. package/src/tasks-runner/task-orchestrator.d.ts.map +1 -1
  57. package/src/tasks-runner/task-orchestrator.js +3 -7
  58. package/src/tasks-runner/utils.d.ts +1 -0
  59. package/src/tasks-runner/utils.d.ts.map +1 -1
  60. package/src/tasks-runner/utils.js +8 -0
  61. package/src/utils/update-nxw.d.ts.map +1 -1
  62. package/src/utils/update-nxw.js +11 -0
@@ -27,6 +27,7 @@ export declare class AppLifeCycle {
27
27
 
28
28
  export declare class ChildProcess {
29
29
  getParserAndWriter(): ExternalObject<[ParserArc, WriterArc]>
30
+ getPid(): number
30
31
  kill(signal?: NodeJS.Signals): void
31
32
  onExit(callback: (message: string) => void): void
32
33
  onOutput(callback: (message: string) => void): void
@@ -92,6 +93,45 @@ export declare class NxTaskHistory {
92
93
  getEstimatedTaskTimings(targets: Array<TaskTarget>): Record<string, number>
93
94
  }
94
95
 
96
+ /**
97
+ * High-performance metrics collector for Nx tasks
98
+ * Thread-safe and designed for minimal overhead
99
+ */
100
+ export declare class ProcessMetricsCollector {
101
+ /** Create a new ProcessMetricsCollector with default configuration */
102
+ constructor()
103
+ /**
104
+ * Start metrics collection
105
+ * Idempotent - safe to call multiple times
106
+ */
107
+ startCollection(): void
108
+ /**
109
+ * Stop metrics collection
110
+ * Returns true if collection was stopped, false if not running
111
+ */
112
+ stopCollection(): boolean
113
+ /**
114
+ * Get system information (CPU cores and total memory)
115
+ * This is separate from the collection interval and meant to be called imperatively
116
+ */
117
+ getSystemInfo(): SystemInfo
118
+ /** Register the main CLI process for metrics collection */
119
+ registerMainCliProcess(pid: number): void
120
+ /** Register the daemon process for metrics collection */
121
+ registerDaemonProcess(pid: number): void
122
+ /**
123
+ * Register a process for a specific task
124
+ * Automatically creates the task if it doesn't exist
125
+ */
126
+ registerTaskProcess(taskId: string, pid: number): void
127
+ /** Register a batch with multiple tasks sharing a worker */
128
+ registerBatch(batchId: string, taskIds: Array<string>, pid: number): void
129
+ /** Register a subprocess of the main CLI for metrics collection */
130
+ registerMainCliSubprocess(pid: number): void
131
+ /** Subscribe to push-based metrics notifications from TypeScript */
132
+ subscribe(callback: (err: Error | null, event: MetricsUpdate) => void): void
133
+ }
134
+
95
135
  export declare class RunningTasksService {
96
136
  constructor(db: ExternalObject<NxDbConnection>)
97
137
  getRunningTasks(ids: Array<string>): Array<string>
@@ -153,6 +193,13 @@ export declare class WorkspaceContext {
153
193
  getFilesInDirectory(directory: string): Array<string>
154
194
  }
155
195
 
196
+ /** Batch metrics snapshot */
197
+ export interface BatchMetricsSnapshot {
198
+ batchId: string
199
+ taskIds: Array<string>
200
+ processes: Array<ProcessMetrics>
201
+ }
202
+
156
203
  export interface CachedResult {
157
204
  code: number
158
205
  terminalOutput?: string
@@ -264,6 +311,12 @@ export declare export declare function isEditorInstalled(editor: SupportedEditor
264
311
 
265
312
  export declare export declare function logDebug(message: string): void
266
313
 
314
+ /** Metrics update sent every collection cycle */
315
+ export interface MetricsUpdate {
316
+ metrics: ProcessMetricsSnapshot
317
+ metadata?: Record<string, ProcessMetadata>
318
+ }
319
+
267
320
  /** Stripped version of the NxJson interface for use in rust */
268
321
  export interface NxJson {
269
322
  namedInputs?: Record<string, Array<JsInputs>>
@@ -283,6 +336,37 @@ export interface NxWorkspaceFilesExternals {
283
336
 
284
337
  export declare export declare function parseTaskStatus(stringStatus: string): TaskStatus
285
338
 
339
+ /** Process metadata (static, doesn't change during process lifetime) */
340
+ export interface ProcessMetadata {
341
+ ppid: number
342
+ name: string
343
+ command: string
344
+ exePath: string
345
+ cwd: string
346
+ }
347
+
348
+ /** Process metrics (dynamic, changes every collection) */
349
+ export interface ProcessMetrics {
350
+ pid: number
351
+ cpu: number
352
+ memory: number
353
+ }
354
+
355
+ /** Organized collection of process metrics with timestamp */
356
+ export interface ProcessMetricsSnapshot {
357
+ timestamp: number
358
+ mainCli?: ProcessTreeMetrics
359
+ daemon?: ProcessTreeMetrics
360
+ tasks: Record<string, Array<ProcessMetrics>>
361
+ batches: Record<string, BatchMetricsSnapshot>
362
+ }
363
+
364
+ /** Metrics for a process and its subprocesses (used for both CLI and daemon) */
365
+ export interface ProcessTreeMetrics {
366
+ main: ProcessMetrics
367
+ subprocesses: Array<ProcessMetrics>
368
+ }
369
+
286
370
  export interface Project {
287
371
  root: string
288
372
  namedInputs?: Record<string, Array<JsInputs>>
@@ -318,6 +402,12 @@ export declare const enum SupportedEditor {
318
402
  Unknown = 5
319
403
  }
320
404
 
405
+ /** System information (static system-level data) */
406
+ export interface SystemInfo {
407
+ cpuCores: number
408
+ totalMemory: number
409
+ }
410
+
321
411
  export interface Target {
322
412
  executor?: string
323
413
  inputs?: Array<JsInputs>
@@ -371,6 +371,7 @@ module.exports.ImportResult = nativeBinding.ImportResult
371
371
  module.exports.NxCache = nativeBinding.NxCache
372
372
  module.exports.NxConsolePreferences = nativeBinding.NxConsolePreferences
373
373
  module.exports.NxTaskHistory = nativeBinding.NxTaskHistory
374
+ module.exports.ProcessMetricsCollector = nativeBinding.ProcessMetricsCollector
374
375
  module.exports.RunningTasksService = nativeBinding.RunningTasksService
375
376
  module.exports.RustPseudoTerminal = nativeBinding.RustPseudoTerminal
376
377
  module.exports.TaskDetails = nativeBinding.TaskDetails
Binary file
@@ -1,41 +1,41 @@
1
1
  {
2
- "$schema": "https://json-schema.org/schema",
3
- "id": "NxCloudInit",
4
- "title": "Add Nx Cloud Configuration to the workspace",
5
- "description": "Connect a workspace to Nx Cloud.",
6
- "type": "object",
7
- "cli": "nx",
8
- "properties": {
9
- "analytics": {
10
- "type": "boolean",
11
- "description": "Anonymously store hashed machine ID for task runs",
12
- "default": false
2
+ "$schema": "https://json-schema.org/schema",
3
+ "id": "NxCloudInit",
4
+ "title": "Add Nx Cloud Configuration to the workspace",
5
+ "description": "Connect a workspace to Nx Cloud.",
6
+ "type": "object",
7
+ "cli": "nx",
8
+ "properties": {
9
+ "analytics": {
10
+ "type": "boolean",
11
+ "description": "Anonymously store hashed machine ID for task runs",
12
+ "default": false
13
+ },
14
+ "installationSource": {
15
+ "type": "string",
16
+ "description": "Name of Nx Cloud installation invoker (ex. user, add-nx-to-monorepo, create-nx-workspace, nx-upgrade",
17
+ "default": "user"
18
+ },
19
+ "hideFormatLogs": {
20
+ "type": "boolean",
21
+ "description": "Hide formatting logs",
22
+ "x-priority": "internal"
23
+ },
24
+ "generateToken": {
25
+ "type": "boolean",
26
+ "description": "Explicitly asks for a token to be created, do not override existing tokens from Nx Cloud"
27
+ },
28
+ "github": {
29
+ "type": "boolean",
30
+ "description": "If the user will be using GitHub as their git hosting provider",
31
+ "default": false
32
+ },
33
+ "directory": {
34
+ "type": "string",
35
+ "description": "The directory where the workspace is located",
36
+ "x-priority": "internal"
37
+ }
13
38
  },
14
- "installationSource": {
15
- "type": "string",
16
- "description": "Name of Nx Cloud installation invoker (ex. user, add-nx-to-monorepo, create-nx-workspace, nx-upgrade",
17
- "default": "user"
18
- },
19
- "hideFormatLogs": {
20
- "type": "boolean",
21
- "description": "Hide formatting logs",
22
- "x-priority": "internal"
23
- },
24
- "generateToken": {
25
- "type": "boolean",
26
- "description": "Explicitly asks for a token to be created, do not override existing tokens from Nx Cloud"
27
- },
28
- "github": {
29
- "type": "boolean",
30
- "description": "If the user will be using GitHub as their git hosting provider",
31
- "default": false
32
- },
33
- "directory": {
34
- "type": "string",
35
- "description": "The directory where the workspace is located",
36
- "x-priority": "internal"
37
- }
38
- },
39
- "additionalProperties": false,
40
- "required": []
39
+ "additionalProperties": false,
40
+ "required": []
41
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-pool.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAK9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA8C1D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CA6DhD"}
1
+ {"version":3,"file":"plugin-pool.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAK9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA8C1D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAgFhD"}
@@ -33,6 +33,22 @@ async function loadRemoteNxPlugin(plugin, root) {
33
33
  const moduleName = typeof plugin === 'string' ? plugin : plugin.plugin;
34
34
  const { name, pluginPath, shouldRegisterTSTranspiler } = await (0, resolve_plugin_1.resolveNxPlugin)(moduleName, root, (0, installation_directory_1.getNxRequirePaths)(root));
35
35
  const { worker, socket } = await startPluginWorker();
36
+ // Register plugin worker as a subprocess of the main CLI
37
+ // This allows metrics collection when the daemon is not used
38
+ if (worker.pid) {
39
+ try {
40
+ const { isDaemonEnabled } = await Promise.resolve().then(() => require('../../../daemon/client/client'));
41
+ // Only register if daemon is not enabled - when daemon is enabled,
42
+ // plugin workers are spawned as children of the daemon and tracked automatically
43
+ if (!isDaemonEnabled()) {
44
+ const { getProcessMetricsService } = await Promise.resolve().then(() => require('../../../tasks-runner/process-metrics-service'));
45
+ getProcessMetricsService().registerMainCliSubprocess(worker.pid);
46
+ }
47
+ }
48
+ catch {
49
+ // Silently ignore - metrics collection is optional
50
+ }
51
+ }
36
52
  const pendingPromises = new Map();
37
53
  const exitHandler = createWorkerExitHandler(worker, pendingPromises);
38
54
  const cleanupFunction = () => {
@@ -271,7 +287,7 @@ async function startPluginWorker() {
271
287
  }
272
288
  : {}),
273
289
  };
274
- const ipcPath = (0, socket_utils_1.getPluginOsSocketPath)([process.pid, global.nxPluginWorkerCount++].join('-'));
290
+ const ipcPath = (0, socket_utils_1.getPluginOsSocketPath)([process.pid, global.nxPluginWorkerCount++, performance.now()].join('-'));
275
291
  const worker = (0, child_process_1.spawn)(process.execPath, [
276
292
  ...(isWorkerTypescript ? ['--require', 'ts-node/register'] : []),
277
293
  workerPath,
@@ -1 +1 @@
1
- {"version":3,"file":"create-task-graph.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/create-task-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAMhF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAOvE,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAR/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,QAAQ,CAAC,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IAC5C,QAAQ,CAAC,YAAY,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAM;IACtD,QAAQ,CAAC,sBAAsB,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAM;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;gBAGvB,uBAAuB,EAAE,kBAAkB,EAC3C,YAAY,EAAE,YAAY;IAY7C,YAAY,CACV,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,uBAAuB,EAAE,OAAO,GAC/B,MAAM,EAAE;IAoFX,WAAW,CACT,IAAI,EAAE,IAAI,EACV,+BAA+B,EAAE,MAAM,EACvC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB,IAAI;IAkDP,OAAO,CAAC,+BAA+B;IA2BvC,OAAO,CAAC,4BAA4B;IAmDpC,OAAO,CAAC,2BAA2B;IAyFnC,OAAO,CAAC,eAAe;IAOvB,UAAU,CACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,EACd,qBAAqB,EAAE,MAAM,GAAG,SAAS,EACzC,SAAS,EAAE,MAAM,GAChB,IAAI;IAyCP,oBAAoB,CAClB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GAAG,SAAS;CASpC;AAED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,YAAY,EAC1B,uBAAuB,EAAE,kBAAkB,EAC3C,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,EAAE,MAAM,EACjB,uBAAuB,GAAE,OAAe,GACvC,SAAS,CAgBX;AAED,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,cAAc,GAAG,SAAS,GACnC,kBAAkB,CAOpB;AAsBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,QAoBvE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,EACvC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EACpB,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAC5B,MAAM,EAAE,CAkBV"}
1
+ {"version":3,"file":"create-task-graph.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/create-task-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAWhF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAOvE,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAR/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,QAAQ,CAAC,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IAC5C,QAAQ,CAAC,YAAY,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAM;IACtD,QAAQ,CAAC,sBAAsB,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAM;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;gBAGvB,uBAAuB,EAAE,kBAAkB,EAC3C,YAAY,EAAE,YAAY;IAY7C,YAAY,CACV,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,uBAAuB,EAAE,OAAO,GAC/B,MAAM,EAAE;IAoFX,WAAW,CACT,IAAI,EAAE,IAAI,EACV,+BAA+B,EAAE,MAAM,EACvC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB,IAAI;IAkDP,OAAO,CAAC,+BAA+B;IA2BvC,OAAO,CAAC,4BAA4B;IAmDpC,OAAO,CAAC,2BAA2B;IAyFnC,OAAO,CAAC,eAAe;IAOvB,UAAU,CACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,EACd,qBAAqB,EAAE,MAAM,GAAG,SAAS,EACzC,SAAS,EAAE,MAAM,GAChB,IAAI;IAyCP,oBAAoB,CAClB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GAAG,SAAS;CASpC;AAED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,YAAY,EAC1B,uBAAuB,EAAE,kBAAkB,EAC3C,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,EAAE,MAAM,EACjB,uBAAuB,GAAE,OAAe,GACvC,SAAS,CAgBX;AAED,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,cAAc,GAAG,SAAS,GACnC,kBAAkB,CAOpB;AAsBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,QAoBvE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,EACvC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EACpB,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAC5B,MAAM,EAAE,CAkBV"}
@@ -33,7 +33,7 @@ class ProcessTasks {
33
33
  const project = this.projectGraph.nodes[projectName];
34
34
  if (targets.length === 1 || project.data.targets[target]) {
35
35
  const resolvedConfiguration = this.resolveConfiguration(project, target, configuration);
36
- const id = createTaskId(projectName, target, resolvedConfiguration);
36
+ const id = (0, utils_1.createTaskId)(projectName, target, resolvedConfiguration);
37
37
  const task = this.createTask(id, project, target, resolvedConfiguration, overrides);
38
38
  this.tasks[task.id] = task;
39
39
  this.dependencies[task.id] = [];
@@ -118,7 +118,7 @@ class ProcessTasks {
118
118
  const selfProject = this.projectGraph.nodes[projectName];
119
119
  if ((0, project_graph_utils_1.projectHasTarget)(selfProject, dependencyConfig.target)) {
120
120
  const resolvedConfiguration = this.resolveConfiguration(selfProject, dependencyConfig.target, configuration);
121
- const selfTaskId = createTaskId(selfProject.name, dependencyConfig.target, resolvedConfiguration);
121
+ const selfTaskId = (0, utils_1.createTaskId)(selfProject.name, dependencyConfig.target, resolvedConfiguration);
122
122
  if (!this.tasks[selfTaskId]) {
123
123
  const newTask = this.createTask(selfTaskId, selfProject, dependencyConfig.target, resolvedConfiguration, taskOverrides);
124
124
  this.tasks[selfTaskId] = newTask;
@@ -147,7 +147,7 @@ class ProcessTasks {
147
147
  continue;
148
148
  if ((0, project_graph_utils_1.projectHasTarget)(depProject, dependencyConfig.target)) {
149
149
  const resolvedConfiguration = this.resolveConfiguration(depProject, dependencyConfig.target, configuration);
150
- const depTargetId = createTaskId(depProject.name, dependencyConfig.target, resolvedConfiguration);
150
+ const depTargetId = (0, utils_1.createTaskId)(depProject.name, dependencyConfig.target, resolvedConfiguration);
151
151
  const depTargetConfiguration = this.projectGraph.nodes[depProject.name].data.targets[dependencyConfig.target];
152
152
  if (task.id !== depTargetId) {
153
153
  if (depTargetConfiguration.continuous) {
@@ -167,7 +167,7 @@ class ProcessTasks {
167
167
  }
168
168
  else {
169
169
  // Create a dummy task for task.target.project... which simulates if depProject had dependencyConfig.target
170
- const dummyId = createTaskId(depProject.name, task.target.project +
170
+ const dummyId = (0, utils_1.createTaskId)(depProject.name, task.target.project +
171
171
  task.target.target +
172
172
  '__' +
173
173
  dependencyConfig.target +
@@ -307,10 +307,3 @@ function createTaskOverrides(dependencyConfig, cliOverrides, sourceTask, project
307
307
  ? { ...optionsToForward, ...cliOverrides }
308
308
  : { ...optionsToForward, __overrides_unparsed__: [] };
309
309
  }
310
- function createTaskId(project, target, configuration) {
311
- let id = `${project}:${target}`;
312
- if (configuration) {
313
- id += `:${configuration}`;
314
- }
315
- return id;
316
- }
@@ -1 +1 @@
1
- {"version":3,"file":"forked-process-task-runner.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/forked-process-task-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAIzC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAkB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAKvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAO3D,qBAAa,uBAAuB;IAShC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAT7B,OAAO,SAAgB;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6C;IACrE,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,eAAe,CAA6B;gBAGjC,OAAO,EAAE,yBAAyB,EAClC,UAAU,EAAE,OAAO;IAGhC,IAAI;IAKG,mBAAmB,CAC9B,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,KAAK,EAClD,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,SAAS,EACxB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,YAAY,CAAC;IAsCjB,qBAAqB;IASf,iBAAiB,CAC5B,IAAI,EAAE,IAAI,EACV,EACE,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,GAAG,GACJ,EAAE;QACD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,YAAY,EAAE,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,SAAS,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,GACA,OAAO,CAAC,WAAW,CAAC;IAgBV,WAAW,CACtB,IAAI,EAAE,IAAI,EACV,EACE,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACT,GAAG,EACH,qBAAqB,GACtB,EAAE;QACD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,YAAY,EAAE,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,SAAS,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;QACvB,qBAAqB,EAAE,OAAO,CAAC;KAChC,GACA,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC;YAiC5B,oBAAoB;YAYpB,6BAA6B;IAyD3C,OAAO,CAAC,8BAA8B;IA2DtC,OAAO,CAAC,8BAA8B;IAkEtC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO;IAO/B,OAAO,CAAC,0BAA0B;CAwCnC"}
1
+ {"version":3,"file":"forked-process-task-runner.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/forked-process-task-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAIzC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAkB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAKvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAQ3D,qBAAa,uBAAuB;IAShC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAT7B,OAAO,SAAgB;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6C;IACrE,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,eAAe,CAA6B;gBAGjC,OAAO,EAAE,yBAAyB,EAClC,UAAU,EAAE,OAAO;IAGhC,IAAI;IAKG,mBAAmB,CAC9B,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,KAAK,EAClD,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,SAAS,EACxB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,YAAY,CAAC;IAiDjB,qBAAqB;IASf,iBAAiB,CAC5B,IAAI,EAAE,IAAI,EACV,EACE,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,GAAG,GACJ,EAAE;QACD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,YAAY,EAAE,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,SAAS,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,GACA,OAAO,CAAC,WAAW,CAAC;IAgBV,WAAW,CACtB,IAAI,EAAE,IAAI,EACV,EACE,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACT,GAAG,EACH,qBAAqB,GACtB,EAAE;QACD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,YAAY,EAAE,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,SAAS,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;QACvB,qBAAqB,EAAE,OAAO,CAAC;KAChC,GACA,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC;YAiC5B,oBAAoB;YAYpB,6BAA6B;IAkE3C,OAAO,CAAC,8BAA8B;IAmEtC,OAAO,CAAC,8BAA8B;IA2EtC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO;IAO/B,OAAO,CAAC,0BAA0B;CAwCnC"}
@@ -13,6 +13,7 @@ const exit_codes_1 = require("../utils/exit-codes");
13
13
  const node_child_process_1 = require("./running-tasks/node-child-process");
14
14
  const batch_process_1 = require("./running-tasks/batch-process");
15
15
  const native_1 = require("../native");
16
+ const process_metrics_service_1 = require("./process-metrics-service");
16
17
  const forkScript = (0, path_1.join)(__dirname, './fork.js');
17
18
  const workerPath = (0, path_1.join)(__dirname, './batch/run-batch.js');
18
19
  class ForkedProcessTaskRunner {
@@ -40,8 +41,17 @@ class ForkedProcessTaskRunner {
40
41
  }
41
42
  const p = (0, child_process_1.fork)(workerPath, {
42
43
  stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
43
- env,
44
+ env: {
45
+ ...env,
46
+ NX_FORKED_TASK_EXECUTOR: 'true',
47
+ },
44
48
  });
49
+ // Register batch worker process with all tasks
50
+ if (p.pid) {
51
+ const batchId = `${executorName}-${p.pid}`;
52
+ const taskIds = Object.keys(batchTaskGraph.tasks);
53
+ (0, process_metrics_service_1.getProcessMetricsService)().registerBatch(batchId, taskIds, p.pid);
54
+ }
45
55
  const cp = new batch_process_1.BatchProcess(p, executorName);
46
56
  this.processes.add(cp);
47
57
  cp.onExit(() => {
@@ -124,10 +134,18 @@ class ForkedProcessTaskRunner {
124
134
  const p = await pseudoTerminal.fork(childId, forkScript, {
125
135
  cwd: process.cwd(),
126
136
  execArgv: process.execArgv,
127
- jsEnv: env,
137
+ jsEnv: {
138
+ ...env,
139
+ NX_FORKED_TASK_EXECUTOR: 'true',
140
+ },
128
141
  quiet: !streamOutput,
129
142
  commandLabel: `nx run ${task.id}`,
130
143
  });
144
+ // Register forked process for metrics collection
145
+ const pid = p.getPid();
146
+ if (pid) {
147
+ (0, process_metrics_service_1.getProcessMetricsService)().registerTaskProcess(task.id, pid);
148
+ }
131
149
  p.send({
132
150
  targetDescription: task.target,
133
151
  overrides: task.overrides,
@@ -160,8 +178,15 @@ class ForkedProcessTaskRunner {
160
178
  }
161
179
  const p = (0, child_process_1.fork)(this.cliPath, {
162
180
  stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
163
- env,
181
+ env: {
182
+ ...env,
183
+ NX_FORKED_TASK_EXECUTOR: 'true',
184
+ },
164
185
  });
186
+ // Register forked process for metrics collection
187
+ if (p.pid) {
188
+ (0, process_metrics_service_1.getProcessMetricsService)().registerTaskProcess(task.id, p.pid);
189
+ }
165
190
  // Send message to run the executor
166
191
  p.send({
167
192
  targetDescription: task.target,
@@ -196,8 +221,15 @@ class ForkedProcessTaskRunner {
196
221
  }
197
222
  const p = (0, child_process_1.fork)(this.cliPath, {
198
223
  stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
199
- env,
224
+ env: {
225
+ ...env,
226
+ NX_FORKED_TASK_EXECUTOR: 'true',
227
+ },
200
228
  });
229
+ // Register forked process for metrics collection
230
+ if (p.pid) {
231
+ (0, process_metrics_service_1.getProcessMetricsService)().registerTaskProcess(task.id, p.pid);
232
+ }
201
233
  const cp = new node_child_process_1.NodeChildProcessWithDirectOutput(p, temporaryOutputPath);
202
234
  this.processes.add(cp);
203
235
  // Send message to run the executor
@@ -1 +1 @@
1
- {"version":3,"file":"is-tui-enabled.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/is-tui-enabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAIrD;;GAEG;AACH,wBAAgB,YAAY,YAE3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,MAAM,EACd,mBAAmB,UAAsD,WAkE1E"}
1
+ {"version":3,"file":"is-tui-enabled.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/is-tui-enabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAIrD;;GAEG;AACH,wBAAgB,YAAY,YAE3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,MAAM,EACd,mBAAmB,UAAsD,WA8D1E"}
@@ -23,7 +23,6 @@ function isTuiEnabled() {
23
23
  */
24
24
  function shouldUseTui(nxJson, nxArgs, skipCapabilityCheck = process.env.NX_TUI_SKIP_CAPABILITY_CHECK === 'true') {
25
25
  // If the current terminal/environment is not capable of displaying the TUI, we don't run it
26
- const isWindows = process.platform === 'win32';
27
26
  const isCapable = skipCapabilityCheck || (process.stderr.isTTY && isUnicodeSupported());
28
27
  if (typeof nxArgs.tui === 'boolean') {
29
28
  if (nxArgs.tui && !isCapable) {
@@ -57,9 +56,6 @@ function shouldUseTui(nxJson, nxArgs, skipCapabilityCheck = process.env.NX_TUI_S
57
56
  (0, is_ci_1.isCI)() ||
58
57
  // Interactive TUI doesn't make sense in an AI agent context
59
58
  (0, native_1.isAiAgent)() ||
60
- // TODO(@JamesHenry): Remove this check once Windows issues are fixed.
61
- // Windows is not working well right now, temporarily disable it on Windows even if it has been specified as enabled
62
- isWindows ||
63
59
  // WASM needs further testing
64
60
  native_1.IS_WASM) {
65
61
  return false;
@@ -0,0 +1,54 @@
1
+ import { ProcessMetadata, ProcessMetrics, ProcessTreeMetrics, ProcessMetricsSnapshot, BatchMetricsSnapshot, MetricsUpdate, SystemInfo } from '../native';
2
+ export type { ProcessMetadata, ProcessMetrics, ProcessTreeMetrics, ProcessMetricsSnapshot, BatchMetricsSnapshot, MetricsUpdate, SystemInfo, };
3
+ export type MetricsCallback = (event: MetricsUpdate) => void;
4
+ /**
5
+ * Simplified service providing subscription-based access to Rust metrics collector
6
+ * Manages singleton access pattern for metrics collection during execution of tasks and CLI commands
7
+ * All methods handle errors internally to ensure metrics collection never breaks task execution
8
+ */
9
+ declare class ProcessMetricsService {
10
+ private collector;
11
+ private cleanupRegistered;
12
+ constructor();
13
+ /**
14
+ * Register signal handlers for graceful shutdown
15
+ * Ensures collection thread is stopped cleanly on Ctrl+C or process termination
16
+ */
17
+ private registerCleanupHandlers;
18
+ /**
19
+ * Subscribe to push-based metrics notifications
20
+ * Collection starts automatically on first subscription (lazy start)
21
+ */
22
+ subscribe(callback: MetricsCallback): void;
23
+ /**
24
+ * Register a process for a task - creates anchor for discovery
25
+ * This is the core integration point - called from RunningTask constructors
26
+ */
27
+ registerTaskProcess(taskId: string, pid: number): void;
28
+ /**
29
+ * Register a batch with multiple tasks sharing a worker
30
+ */
31
+ registerBatch(batchId: string, taskIds: string[], pid: number): void;
32
+ /**
33
+ * Register the daemon process
34
+ */
35
+ registerDaemonProcess(pid: number): void;
36
+ /**
37
+ * Register a subprocess of the main CLI (e.g., plugin worker)
38
+ */
39
+ registerMainCliSubprocess(pid: number): void;
40
+ /**
41
+ * Get system information (CPU cores and total memory)
42
+ */
43
+ getSystemInfo(): SystemInfo | null;
44
+ /**
45
+ * Stop collection and cleanup
46
+ */
47
+ shutdown(): void;
48
+ }
49
+ /**
50
+ * Get or create the singleton ProcessMetricsService instance
51
+ * Lazy initialization - service only starts when first accessed
52
+ */
53
+ export declare function getProcessMetricsService(): ProcessMetricsService;
54
+ //# sourceMappingURL=process-metrics-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-metrics-service.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/tasks-runner/process-metrics-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,aAAa,EACb,UAAU,EACX,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,aAAa,EACb,UAAU,GACX,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE7D;;;;GAIG;AACH,cAAM,qBAAqB;IACzB,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,iBAAiB,CAAS;;IAmBlC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAe/B;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IA+B1C;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAQtD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAQpE;;OAEG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQxC;;OAEG;IACH,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQ5C;;OAEG;IACH,aAAa,IAAI,UAAU,GAAG,IAAI;IASlC;;OAEG;IACH,QAAQ,IAAI,IAAI;CAOjB;AAOD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,qBAAqB,CAKhE"}
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getProcessMetricsService = getProcessMetricsService;
4
+ const native_1 = require("../native");
5
+ const cache_1 = require("../daemon/cache");
6
+ /**
7
+ * Simplified service providing subscription-based access to Rust metrics collector
8
+ * Manages singleton access pattern for metrics collection during execution of tasks and CLI commands
9
+ * All methods handle errors internally to ensure metrics collection never breaks task execution
10
+ */
11
+ class ProcessMetricsService {
12
+ constructor() {
13
+ this.collector = null;
14
+ this.cleanupRegistered = false;
15
+ try {
16
+ this.collector = new native_1.ProcessMetricsCollector();
17
+ // Register main nx process as CLI
18
+ this.collector.registerMainCliProcess(process.pid);
19
+ // Register daemon process if available
20
+ const daemonPid = (0, cache_1.getDaemonProcessIdSync)();
21
+ if (daemonPid) {
22
+ this.collector.registerDaemonProcess(daemonPid);
23
+ }
24
+ }
25
+ catch {
26
+ // Silent failure - metrics collection is optional and should never break task execution
27
+ }
28
+ }
29
+ /**
30
+ * Register signal handlers for graceful shutdown
31
+ * Ensures collection thread is stopped cleanly on Ctrl+C or process termination
32
+ */
33
+ registerCleanupHandlers() {
34
+ const cleanup = () => {
35
+ try {
36
+ this.shutdown();
37
+ }
38
+ catch {
39
+ // Silent failure during cleanup
40
+ }
41
+ };
42
+ // Handle various exit scenarios
43
+ process.on('SIGINT', cleanup);
44
+ process.on('SIGTERM', cleanup);
45
+ process.on('exit', cleanup);
46
+ }
47
+ /**
48
+ * Subscribe to push-based metrics notifications
49
+ * Collection starts automatically on first subscription (lazy start)
50
+ */
51
+ subscribe(callback) {
52
+ if (!this.collector) {
53
+ return;
54
+ }
55
+ try {
56
+ // Start collection on first subscription (idempotent - safe to call multiple times)
57
+ this.collector.startCollection();
58
+ // Register cleanup handlers on first successful start
59
+ // If startCollection() threw, we never reach this line
60
+ if (!this.cleanupRegistered) {
61
+ this.registerCleanupHandlers();
62
+ this.cleanupRegistered = true;
63
+ }
64
+ // Wrap the user's callback to adapt from error-first pattern (err, data) => void
65
+ // to the simple pattern (event) => void that users expect
66
+ // The Rust side uses CalleeHandled which sends (null, data) on success
67
+ this.collector.subscribe((err, event) => {
68
+ if (err) {
69
+ // Silently ignore errors - metrics collection is optional
70
+ return;
71
+ }
72
+ callback(event);
73
+ });
74
+ }
75
+ catch {
76
+ // Silent failure - metrics collection is optional
77
+ }
78
+ }
79
+ /**
80
+ * Register a process for a task - creates anchor for discovery
81
+ * This is the core integration point - called from RunningTask constructors
82
+ */
83
+ registerTaskProcess(taskId, pid) {
84
+ try {
85
+ this.collector?.registerTaskProcess(taskId, pid);
86
+ }
87
+ catch {
88
+ // Silent failure - metrics collection is optional
89
+ }
90
+ }
91
+ /**
92
+ * Register a batch with multiple tasks sharing a worker
93
+ */
94
+ registerBatch(batchId, taskIds, pid) {
95
+ try {
96
+ this.collector?.registerBatch(batchId, taskIds, pid);
97
+ }
98
+ catch {
99
+ // Silent failure - metrics collection is optional
100
+ }
101
+ }
102
+ /**
103
+ * Register the daemon process
104
+ */
105
+ registerDaemonProcess(pid) {
106
+ try {
107
+ this.collector?.registerDaemonProcess(pid);
108
+ }
109
+ catch {
110
+ // Silent failure - metrics collection is optional
111
+ }
112
+ }
113
+ /**
114
+ * Register a subprocess of the main CLI (e.g., plugin worker)
115
+ */
116
+ registerMainCliSubprocess(pid) {
117
+ try {
118
+ this.collector?.registerMainCliSubprocess(pid);
119
+ }
120
+ catch {
121
+ // Silent failure - metrics collection is optional
122
+ }
123
+ }
124
+ /**
125
+ * Get system information (CPU cores and total memory)
126
+ */
127
+ getSystemInfo() {
128
+ try {
129
+ return this.collector?.getSystemInfo();
130
+ }
131
+ catch {
132
+ // Silent failure - metrics collection is optional
133
+ return null;
134
+ }
135
+ }
136
+ /**
137
+ * Stop collection and cleanup
138
+ */
139
+ shutdown() {
140
+ try {
141
+ this.collector?.stopCollection();
142
+ }
143
+ catch {
144
+ // Silent failure during cleanup
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Singleton instance (lazily initialized)
150
+ */
151
+ let instance = null;
152
+ /**
153
+ * Get or create the singleton ProcessMetricsService instance
154
+ * Lazy initialization - service only starts when first accessed
155
+ */
156
+ function getProcessMetricsService() {
157
+ if (!instance) {
158
+ instance = new ProcessMetricsService();
159
+ }
160
+ return instance;
161
+ }
@@ -44,6 +44,7 @@ export declare class PseudoTtyProcess implements RunningTask {
44
44
  }>;
45
45
  onExit(callback: (code: number) => void): void;
46
46
  onOutput(callback: (message: string) => void): void;
47
+ getPid(): number | undefined;
47
48
  kill(s?: NodeJS.Signals): void;
48
49
  getParserAndWriter(): import("../native").ExternalObject<[ParserArc, WriterArc]>;
49
50
  }