lsh-framework 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +70 -4
  2. package/dist/cli.js +104 -486
  3. package/dist/commands/doctor.js +427 -0
  4. package/dist/commands/init.js +371 -0
  5. package/dist/constants/api.js +94 -0
  6. package/dist/constants/commands.js +64 -0
  7. package/dist/constants/config.js +56 -0
  8. package/dist/constants/database.js +21 -0
  9. package/dist/constants/errors.js +79 -0
  10. package/dist/constants/index.js +28 -0
  11. package/dist/constants/paths.js +28 -0
  12. package/dist/constants/ui.js +73 -0
  13. package/dist/constants/validation.js +124 -0
  14. package/dist/daemon/lshd.js +11 -32
  15. package/dist/lib/daemon-client-helper.js +7 -4
  16. package/dist/lib/daemon-client.js +9 -2
  17. package/dist/lib/format-utils.js +163 -0
  18. package/dist/lib/job-manager.js +2 -1
  19. package/dist/lib/platform-utils.js +211 -0
  20. package/dist/lib/secrets-manager.js +11 -1
  21. package/dist/lib/string-utils.js +128 -0
  22. package/dist/services/daemon/daemon-registrar.js +3 -2
  23. package/dist/services/secrets/secrets.js +154 -30
  24. package/package.json +10 -74
  25. package/dist/app.js +0 -33
  26. package/dist/cicd/analytics.js +0 -261
  27. package/dist/cicd/auth.js +0 -269
  28. package/dist/cicd/cache-manager.js +0 -172
  29. package/dist/cicd/data-retention.js +0 -305
  30. package/dist/cicd/performance-monitor.js +0 -224
  31. package/dist/cicd/webhook-receiver.js +0 -640
  32. package/dist/commands/api.js +0 -346
  33. package/dist/commands/theme.js +0 -261
  34. package/dist/commands/zsh-import.js +0 -240
  35. package/dist/components/App.js +0 -1
  36. package/dist/components/Divider.js +0 -29
  37. package/dist/components/REPL.js +0 -43
  38. package/dist/components/Terminal.js +0 -232
  39. package/dist/components/UserInput.js +0 -30
  40. package/dist/daemon/api-server.js +0 -316
  41. package/dist/daemon/monitoring-api.js +0 -220
  42. package/dist/lib/api-error-handler.js +0 -185
  43. package/dist/lib/associative-arrays.js +0 -285
  44. package/dist/lib/base-api-server.js +0 -290
  45. package/dist/lib/brace-expansion.js +0 -160
  46. package/dist/lib/builtin-commands.js +0 -439
  47. package/dist/lib/executors/builtin-executor.js +0 -52
  48. package/dist/lib/extended-globbing.js +0 -411
  49. package/dist/lib/extended-parameter-expansion.js +0 -227
  50. package/dist/lib/interactive-shell.js +0 -460
  51. package/dist/lib/job-builtins.js +0 -582
  52. package/dist/lib/pathname-expansion.js +0 -216
  53. package/dist/lib/script-runner.js +0 -226
  54. package/dist/lib/shell-executor.js +0 -2504
  55. package/dist/lib/shell-parser.js +0 -958
  56. package/dist/lib/shell-types.js +0 -6
  57. package/dist/lib/shell.lib.js +0 -40
  58. package/dist/lib/theme-manager.js +0 -476
  59. package/dist/lib/variable-expansion.js +0 -385
  60. package/dist/lib/zsh-compatibility.js +0 -659
  61. package/dist/lib/zsh-import-manager.js +0 -707
  62. package/dist/lib/zsh-options.js +0 -328
  63. package/dist/pipeline/job-tracker.js +0 -491
  64. package/dist/pipeline/mcli-bridge.js +0 -309
  65. package/dist/pipeline/pipeline-service.js +0 -1119
  66. package/dist/pipeline/workflow-engine.js +0 -870
  67. package/dist/services/api/api.js +0 -58
  68. package/dist/services/api/auth.js +0 -35
  69. package/dist/services/api/config.js +0 -7
  70. package/dist/services/api/file.js +0 -22
  71. package/dist/services/shell/shell.js +0 -28
  72. package/dist/services/zapier.js +0 -16
  73. package/dist/simple-api-server.js +0 -148
@@ -1,582 +0,0 @@
1
- /**
2
- * Built-in commands for comprehensive job management
3
- */
4
- export class JobBuiltins {
5
- jobManager;
6
- constructor(jobManager) {
7
- this.jobManager = jobManager;
8
- }
9
- /**
10
- * job-create - Create a new job
11
- * Usage: job-create [OPTIONS] COMMAND
12
- */
13
- async jobCreate(args) {
14
- try {
15
- const options = this.parseCreateOptions(args);
16
- const command = args.slice(args.findIndex(arg => !arg.startsWith('-'))).join(' ');
17
- if (!command) {
18
- return {
19
- stdout: '',
20
- stderr: 'Usage: job-create [OPTIONS] COMMAND\n' +
21
- 'Options:\n' +
22
- ' -n, --name NAME Job name\n' +
23
- ' -t, --type TYPE Job type (shell|system|scheduled)\n' +
24
- ' -p, --priority N Priority (-20 to 19)\n' +
25
- ' -d, --description D Description\n' +
26
- ' --timeout N Timeout in seconds\n' +
27
- ' --cwd PATH Working directory\n' +
28
- ' --log PATH Log file path\n' +
29
- ' --tag TAG Add tag (can be used multiple times)\n' +
30
- ' --schedule CRON Schedule with cron expression\n' +
31
- ' --interval N Run every N seconds\n' +
32
- ' --start Start immediately after creation',
33
- exitCode: 1
34
- };
35
- }
36
- const jobSpec = {
37
- ...options,
38
- command
39
- };
40
- const job = await this.jobManager.createJob(jobSpec);
41
- const extendedJob = job; // Cast to access extended properties
42
- let output = `Job created: ${job.id}\n`;
43
- output += ` Name: ${job.name}\n`;
44
- output += ` Command: ${job.command}\n`;
45
- output += ` Type: ${extendedJob.type || 'standard'}\n`;
46
- output += ` Status: ${job.status}\n`;
47
- if (options.start) {
48
- await this.jobManager.startJob(job.id);
49
- output += ` Started with PID: ${job.pid}\n`;
50
- }
51
- return { stdout: output, stderr: '', exitCode: 0 };
52
- }
53
- catch (error) {
54
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
55
- }
56
- }
57
- /**
58
- * job-list - List jobs with filtering
59
- * Usage: job-list [OPTIONS]
60
- */
61
- async jobList(args) {
62
- try {
63
- const filter = this.parseListOptions(args);
64
- const jobs = await this.jobManager.listJobs(filter);
65
- if (jobs.length === 0) {
66
- return { stdout: 'No jobs found.\n', stderr: '', exitCode: 0 };
67
- }
68
- let output = '';
69
- const detailed = args.includes('-l') || args.includes('--long');
70
- const showAll = args.includes('-a') || args.includes('--all');
71
- if (detailed) {
72
- for (const job of jobs) {
73
- output += this.formatJobDetailed(job) + '\n';
74
- }
75
- }
76
- else {
77
- output += 'ID NAME STATUS PID STARTED COMMAND\n';
78
- output += '============================================================================\n';
79
- for (const job of jobs) {
80
- if (!showAll && job.status === 'completed' &&
81
- job.completedAt &&
82
- Date.now() - job.completedAt.getTime() > 24 * 60 * 60 * 1000) {
83
- continue; // Skip old completed jobs unless --all
84
- }
85
- output += this.formatJobSummary(job) + '\n';
86
- }
87
- }
88
- return { stdout: output, stderr: '', exitCode: 0 };
89
- }
90
- catch (error) {
91
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
92
- }
93
- }
94
- /**
95
- * job-show - Show detailed information about a job
96
- * Usage: job-show JOB_ID
97
- */
98
- async jobShow(args) {
99
- if (args.length === 0) {
100
- return {
101
- stdout: '',
102
- stderr: 'Usage: job-show JOB_ID\n',
103
- exitCode: 1
104
- };
105
- }
106
- const jobId = args[0];
107
- const job = await this.jobManager.getJob(jobId);
108
- if (!job) {
109
- return { stdout: '', stderr: `Job ${jobId} not found.\n`, exitCode: 1 };
110
- }
111
- const output = this.formatJobDetailed(job);
112
- return { stdout: output, stderr: '', exitCode: 0 };
113
- }
114
- /**
115
- * job-start - Start a created job
116
- * Usage: job-start JOB_ID
117
- */
118
- async jobStart(args) {
119
- if (args.length === 0) {
120
- return { stdout: '', stderr: 'Usage: job-start JOB_ID\n', exitCode: 1 };
121
- }
122
- try {
123
- const jobId = args[0];
124
- const job = await this.jobManager.startJob(jobId);
125
- return {
126
- stdout: `Job ${jobId} started with PID ${job.pid}\n`,
127
- stderr: '',
128
- exitCode: 0
129
- };
130
- }
131
- catch (error) {
132
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
133
- }
134
- }
135
- /**
136
- * job-stop - Stop/kill a running job
137
- * Usage: job-stop [OPTIONS] JOB_ID
138
- */
139
- async jobStop(args) {
140
- if (args.length === 0) {
141
- return {
142
- stdout: '',
143
- stderr: 'Usage: job-stop [OPTIONS] JOB_ID\n' +
144
- 'Options:\n' +
145
- ' -9, --kill Send SIGKILL instead of SIGTERM\n' +
146
- ' -s SIGNAL Send specific signal',
147
- exitCode: 1
148
- };
149
- }
150
- try {
151
- let signal = 'SIGTERM';
152
- const jobId = args[args.length - 1];
153
- for (let i = 0; i < args.length - 1; i++) {
154
- if (args[i] === '-9' || args[i] === '--kill') {
155
- signal = 'SIGKILL';
156
- }
157
- else if (args[i] === '-s' && i + 1 < args.length - 1) {
158
- signal = args[i + 1];
159
- i++;
160
- }
161
- }
162
- const _job = await this.jobManager.killJob(jobId, signal);
163
- return {
164
- stdout: `Job ${jobId} stopped with signal ${signal}\n`,
165
- stderr: '',
166
- exitCode: 0
167
- };
168
- }
169
- catch (error) {
170
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
171
- }
172
- }
173
- /**
174
- * job-pause - Pause a running job
175
- * Usage: job-pause JOB_ID
176
- */
177
- async jobPause(args) {
178
- if (args.length === 0) {
179
- return { stdout: '', stderr: 'Usage: job-pause JOB_ID\n', exitCode: 1 };
180
- }
181
- try {
182
- const jobId = args[0];
183
- await this.jobManager.pauseJob(jobId);
184
- return { stdout: `Job ${jobId} paused\n`, stderr: '', exitCode: 0 };
185
- }
186
- catch (error) {
187
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
188
- }
189
- }
190
- /**
191
- * job-resume - Resume a paused job
192
- * Usage: job-resume JOB_ID
193
- */
194
- async jobResume(args) {
195
- if (args.length === 0) {
196
- return { stdout: '', stderr: 'Usage: job-resume JOB_ID\n', exitCode: 1 };
197
- }
198
- try {
199
- const jobId = args[0];
200
- await this.jobManager.resumeJob(jobId);
201
- return { stdout: `Job ${jobId} resumed\n`, stderr: '', exitCode: 0 };
202
- }
203
- catch (error) {
204
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
205
- }
206
- }
207
- /**
208
- * job-remove - Remove a job
209
- * Usage: job-remove [OPTIONS] JOB_ID
210
- */
211
- async jobRemove(args) {
212
- if (args.length === 0) {
213
- return {
214
- stdout: '',
215
- stderr: 'Usage: job-remove [OPTIONS] JOB_ID\n' +
216
- 'Options:\n' +
217
- ' -f, --force Force removal of running jobs',
218
- exitCode: 1
219
- };
220
- }
221
- try {
222
- let force = false;
223
- const jobId = args[args.length - 1];
224
- for (const arg of args.slice(0, -1)) {
225
- if (arg === '-f' || arg === '--force') {
226
- force = true;
227
- }
228
- }
229
- const removed = await this.jobManager.removeJob(jobId, force);
230
- if (removed) {
231
- return { stdout: `Job ${jobId} removed\n`, stderr: '', exitCode: 0 };
232
- }
233
- else {
234
- return { stdout: '', stderr: `Job ${jobId} not found\n`, exitCode: 1 };
235
- }
236
- }
237
- catch (error) {
238
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
239
- }
240
- }
241
- /**
242
- * job-update - Update job properties
243
- * Usage: job-update [OPTIONS] JOB_ID
244
- */
245
- async jobUpdate(args) {
246
- if (args.length < 2) {
247
- return {
248
- stdout: '',
249
- stderr: 'Usage: job-update [OPTIONS] JOB_ID\n' +
250
- 'Options:\n' +
251
- ' -n, --name NAME Change job name\n' +
252
- ' -p, --priority N Change priority (-20 to 19)\n' +
253
- ' -d, --description D Change description\n' +
254
- ' --timeout N Change timeout in seconds\n' +
255
- ' --add-tag TAG Add tag\n' +
256
- ' --remove-tag TAG Remove tag',
257
- exitCode: 1
258
- };
259
- }
260
- try {
261
- const jobId = args[args.length - 1];
262
- const updates = this.parseUpdateOptions(args.slice(0, -1));
263
- const _job = await this.jobManager.updateJob(jobId, updates);
264
- return { stdout: `Job ${jobId} updated successfully\n`, stderr: '', exitCode: 0 };
265
- }
266
- catch (error) {
267
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
268
- }
269
- }
270
- /**
271
- * job-run - Create and immediately start a job
272
- * Usage: job-run [OPTIONS] COMMAND
273
- */
274
- async jobRun(args) {
275
- try {
276
- const options = this.parseCreateOptions(args);
277
- const command = args.slice(args.findIndex(arg => !arg.startsWith('-'))).join(' ');
278
- if (!command) {
279
- return { stdout: '', stderr: 'Usage: job-run [OPTIONS] COMMAND\n', exitCode: 1 };
280
- }
281
- const job = await this.jobManager.runJob({ ...options, command });
282
- return {
283
- stdout: `Job ${job.id} (${job.name}) started with PID ${job.pid}\n`,
284
- stderr: '',
285
- exitCode: 0
286
- };
287
- }
288
- catch (error) {
289
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
290
- }
291
- }
292
- /**
293
- * job-monitor - Monitor job resource usage
294
- * Usage: job-monitor JOB_ID
295
- */
296
- async jobMonitor(args) {
297
- if (args.length === 0) {
298
- return { stdout: '', stderr: 'Usage: job-monitor JOB_ID\n', exitCode: 1 };
299
- }
300
- try {
301
- const jobId = args[0];
302
- const monitoring = await this.jobManager.monitorJob(jobId);
303
- if (!monitoring) {
304
- return { stdout: '', stderr: `Job ${jobId} is not running\n`, exitCode: 1 };
305
- }
306
- let output = `Job ${jobId} Resource Usage:\n`;
307
- output += ` PID: ${monitoring.pid}\n`;
308
- output += ` CPU: ${monitoring.cpu}%\n`;
309
- output += ` Memory: ${monitoring.memory}%\n`;
310
- output += ` Elapsed: ${monitoring.elapsed}\n`;
311
- output += ` State: ${monitoring.state}\n`;
312
- output += ` Timestamp: ${monitoring.timestamp.toISOString()}\n`;
313
- return { stdout: output, stderr: '', exitCode: 0 };
314
- }
315
- catch (error) {
316
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
317
- }
318
- }
319
- /**
320
- * job-stats - Show job statistics
321
- * Usage: job-stats
322
- */
323
- async jobStats(_args) {
324
- try {
325
- const stats = this.jobManager.getJobStats();
326
- let output = 'Job Statistics:\n';
327
- output += ` Total Jobs: ${stats.total}\n`;
328
- output += ` Running: ${stats.running}\n`;
329
- output += ` Completed: ${stats.completed}\n`;
330
- output += ` Failed: ${stats.failed}\n\n`;
331
- output += 'By Status:\n';
332
- for (const [status, count] of Object.entries(stats.byStatus)) {
333
- output += ` ${status}: ${count}\n`;
334
- }
335
- output += '\nBy Type:\n';
336
- for (const [type, count] of Object.entries(stats.byType)) {
337
- output += ` ${type}: ${count}\n`;
338
- }
339
- return { stdout: output, stderr: '', exitCode: 0 };
340
- }
341
- catch (error) {
342
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
343
- }
344
- }
345
- /**
346
- * job-cleanup - Clean up old completed jobs
347
- * Usage: job-cleanup [HOURS]
348
- */
349
- async jobCleanup(args) {
350
- try {
351
- const hours = args.length > 0 ? parseInt(args[0]) : 24;
352
- const removed = await this.jobManager.cleanupJobs(hours);
353
- return {
354
- stdout: `Cleaned up ${removed} old jobs (older than ${hours} hours)\n`,
355
- stderr: '',
356
- exitCode: 0
357
- };
358
- }
359
- catch (error) {
360
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
361
- }
362
- }
363
- /**
364
- * ps-list - List system processes
365
- * Usage: ps-list [OPTIONS]
366
- */
367
- async psList(args) {
368
- try {
369
- const processes = await this.jobManager.getSystemProcesses();
370
- if (processes.length === 0) {
371
- return { stdout: 'No processes found.\n', stderr: '', exitCode: 0 };
372
- }
373
- let output = 'PID PPID USER CPU% MEM% STARTED COMMAND\n';
374
- output += '================================================================================\n';
375
- const filtered = args.includes('--user')
376
- ? processes.filter(p => p.user === process.env.USER)
377
- : processes;
378
- const sorted = filtered.sort((a, b) => {
379
- if (args.includes('--cpu'))
380
- return b.cpu - a.cpu;
381
- if (args.includes('--memory'))
382
- return b.memory - a.memory;
383
- return a.pid - b.pid;
384
- });
385
- const limit = args.includes('--top') ? 20 : sorted.length;
386
- for (const proc of sorted.slice(0, limit)) {
387
- output += `${proc.pid.toString().padEnd(8)} `;
388
- output += `${proc.ppid.toString().padEnd(8)} `;
389
- output += `${proc.user.padEnd(14)} `;
390
- output += `${proc.cpu.toFixed(1).padStart(5)} `;
391
- output += `${proc.memory.toFixed(1).padStart(5)} `;
392
- output += `${proc.startTime.toLocaleString().padEnd(19)} `;
393
- output += `${proc.command.slice(0, 50)}\n`;
394
- }
395
- return { stdout: output, stderr: '', exitCode: 0 };
396
- }
397
- catch (error) {
398
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
399
- }
400
- }
401
- /**
402
- * ps-kill - Kill a system process
403
- * Usage: ps-kill [OPTIONS] PID
404
- */
405
- async psKill(args) {
406
- if (args.length === 0) {
407
- return {
408
- stdout: '',
409
- stderr: 'Usage: ps-kill [OPTIONS] PID\n' +
410
- 'Options:\n' +
411
- ' -9, --kill Send SIGKILL instead of SIGTERM\n' +
412
- ' -s SIGNAL Send specific signal',
413
- exitCode: 1
414
- };
415
- }
416
- try {
417
- let _signal = 'SIGTERM';
418
- const pidStr = args[args.length - 1];
419
- const pid = parseInt(pidStr);
420
- if (isNaN(pid)) {
421
- return { stdout: '', stderr: 'Invalid PID\n', exitCode: 1 };
422
- }
423
- for (let i = 0; i < args.length - 1; i++) {
424
- if (args[i] === '-9' || args[i] === '--kill') {
425
- _signal = 'SIGKILL';
426
- }
427
- else if (args[i] === '-s' && i + 1 < args.length - 1) {
428
- _signal = args[i + 1];
429
- i++;
430
- }
431
- }
432
- // TODO: Implement system process killing
433
- // This functionality was removed during refactoring
434
- return { stdout: '', stderr: `System process killing not yet implemented in refactored job manager\n`, exitCode: 1 };
435
- }
436
- catch (error) {
437
- return { stdout: '', stderr: `Error: ${error.message}\n`, exitCode: 1 };
438
- }
439
- }
440
- // Helper methods for parsing options and formatting output
441
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
442
- parseCreateOptions(args) {
443
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
444
- const options = { tags: [] };
445
- for (let i = 0; i < args.length; i++) {
446
- const arg = args[i];
447
- if (arg === '-n' || arg === '--name') {
448
- options.name = args[++i];
449
- }
450
- else if (arg === '-t' || arg === '--type') {
451
- options.type = args[++i];
452
- }
453
- else if (arg === '-p' || arg === '--priority') {
454
- options.priority = parseInt(args[++i]);
455
- }
456
- else if (arg === '-d' || arg === '--description') {
457
- options.description = args[++i];
458
- }
459
- else if (arg === '--timeout') {
460
- options.timeout = parseInt(args[++i]) * 1000;
461
- }
462
- else if (arg === '--cwd') {
463
- options.cwd = args[++i];
464
- }
465
- else if (arg === '--log') {
466
- options.logFile = args[++i];
467
- }
468
- else if (arg === '--tag') {
469
- options.tags.push(args[++i]);
470
- }
471
- else if (arg === '--schedule') {
472
- options.type = 'scheduled';
473
- options.schedule = { cron: args[++i] };
474
- }
475
- else if (arg === '--interval') {
476
- options.type = 'scheduled';
477
- options.schedule = { interval: parseInt(args[++i]) * 1000 };
478
- }
479
- else if (arg === '--start') {
480
- options.start = true;
481
- }
482
- }
483
- return options;
484
- }
485
- parseListOptions(args) {
486
- const filter = {};
487
- for (let i = 0; i < args.length; i++) {
488
- const arg = args[i];
489
- if (arg === '--status') {
490
- filter.status = args[++i].split(',');
491
- }
492
- else if (arg === '--type') {
493
- filter.type = args[++i].split(',');
494
- }
495
- else if (arg === '--user') {
496
- filter.user = args[++i];
497
- }
498
- else if (arg === '--tag') {
499
- filter.tags = args[++i].split(',');
500
- }
501
- else if (arg === '--name') {
502
- filter.namePattern = new RegExp(args[++i], 'i');
503
- }
504
- }
505
- return filter;
506
- }
507
- parseUpdateOptions(args) {
508
- const updates = {};
509
- for (let i = 0; i < args.length; i++) {
510
- const arg = args[i];
511
- if (arg === '-n' || arg === '--name') {
512
- updates.name = args[++i];
513
- }
514
- else if (arg === '-p' || arg === '--priority') {
515
- updates.priority = parseInt(args[++i]);
516
- }
517
- else if (arg === '-d' || arg === '--description') {
518
- updates.description = args[++i];
519
- }
520
- else if (arg === '--timeout') {
521
- updates.timeout = parseInt(args[++i]) * 1000;
522
- }
523
- else if (arg === '--add-tag') {
524
- if (!updates.tags)
525
- updates.tags = [];
526
- updates.tags.push(args[++i]);
527
- }
528
- }
529
- return updates;
530
- }
531
- formatJobSummary(job) {
532
- const id = job.id.padEnd(13);
533
- const name = job.name.padEnd(20).slice(0, 20);
534
- const status = job.status.padEnd(11);
535
- const pid = (job.pid?.toString() || '-').padEnd(8);
536
- const started = job.startedAt?.toLocaleString().slice(0, 19) || 'Not started';
537
- const command = job.command.slice(0, 30);
538
- return `${id} ${name} ${status} ${pid} ${started} ${command}`;
539
- }
540
- formatJobDetailed(job) {
541
- const jobExt = job; // Cast to access extended properties
542
- let output = `Job: ${job.id}\n`;
543
- output += ` Name: ${job.name}\n`;
544
- output += ` Command: ${job.command}\n`;
545
- output += ` Type: ${jobExt.type || 'standard'}\n`;
546
- output += ` Status: ${job.status}\n`;
547
- output += ` Priority: ${job.priority}\n`;
548
- output += ` Created: ${job.createdAt.toISOString()}\n`;
549
- if (job.startedAt) {
550
- output += ` Started: ${job.startedAt.toISOString()}\n`;
551
- }
552
- if (job.completedAt) {
553
- output += ` Completed: ${job.completedAt.toISOString()}\n`;
554
- }
555
- if (job.pid) {
556
- output += ` PID: ${job.pid}\n`;
557
- }
558
- if (jobExt.cpuUsage !== undefined) {
559
- output += ` CPU Usage: ${jobExt.cpuUsage}%\n`;
560
- }
561
- if (jobExt.memoryUsage !== undefined) {
562
- output += ` Memory Usage: ${jobExt.memoryUsage}%\n`;
563
- }
564
- if (job.cwd) {
565
- output += ` Working Dir: ${job.cwd}\n`;
566
- }
567
- if (job.logFile) {
568
- output += ` Log File: ${job.logFile}\n`;
569
- }
570
- if (job.tags && job.tags.length > 0) {
571
- output += ` Tags: ${job.tags.join(', ')}\n`;
572
- }
573
- if (job.description) {
574
- output += ` Description: ${job.description}\n`;
575
- }
576
- if (job.schedule) {
577
- output += ` Schedule: ${JSON.stringify(job.schedule)}\n`;
578
- }
579
- return output;
580
- }
581
- }
582
- export default JobBuiltins;