forkit-ai-footprints 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PRIVACY.md +150 -0
- package/README.md +313 -0
- package/STATUS.md +136 -0
- package/dist/agents.d.ts +22 -0
- package/dist/agents.js +281 -0
- package/dist/aggregate.d.ts +28 -0
- package/dist/aggregate.js +151 -0
- package/dist/assets/forkit-icon-dark.png +0 -0
- package/dist/assets/forkit-icon-light.png +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Info.plist +5 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/MacOS/Forkit AI Footprint +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitAIFootprint.icns +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitStatusTemplate.png +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.d.ts +22 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.js +281 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.d.ts +28 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.js +151 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-dark.png +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-light.png +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.d.ts +3 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.js +196 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.d.ts +32 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.js +404 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.d.ts +14 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.js +71 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.d.ts +8 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.js +45 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.d.ts +44 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.js +102 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.d.ts +11 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.js +226 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.d.ts +7 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.js +78 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.d.ts +4 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.js +16 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.d.ts +22 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.js +58 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.d.ts +13 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.js +76 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.d.ts +19 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.js +81 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/locales.json +272 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.d.ts +277 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.js +55 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.d.ts +9 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.js +93 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.d.ts +99 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.js +285 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.d.ts +34 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.js +88 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.d.ts +6 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.js +24 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.d.ts +9 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.js +71 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.d.ts +12 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.js +171 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.d.ts +10 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.js +68 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.d.ts +17 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.js +52 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.d.ts +5 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.js +66 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.d.ts +7 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.js +66 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.d.ts +21 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.js +308 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.d.ts +75 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.js +167 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.d.ts +35 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.js +67 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.d.ts +9 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.js +106 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.d.ts +166 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.js +3 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.d.ts +4 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.js +13 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.d.ts +76 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.js +366 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/license +9 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/package.json +44 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/readme.md +56 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x86.exe +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/package.json +6 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/runtime/node +0 -0
- package/dist/bootstrap/Forkit AI Footprint.app/Contents/_CodeSignature/CodeResources +931 -0
- package/dist/census.d.ts +3 -0
- package/dist/census.js +196 -0
- package/dist/cli.d.ts +32 -0
- package/dist/cli.js +404 -0
- package/dist/doctor.d.ts +14 -0
- package/dist/doctor.js +71 -0
- package/dist/endpoints.d.ts +8 -0
- package/dist/endpoints.js +45 -0
- package/dist/evaluate.d.ts +44 -0
- package/dist/evaluate.js +102 -0
- package/dist/filesystem.d.ts +11 -0
- package/dist/filesystem.js +226 -0
- package/dist/format.d.ts +7 -0
- package/dist/format.js +78 -0
- package/dist/hash.d.ts +4 -0
- package/dist/hash.js +16 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +58 -0
- package/dist/insights.d.ts +13 -0
- package/dist/insights.js +76 -0
- package/dist/local-device.d.ts +19 -0
- package/dist/local-device.js +81 -0
- package/dist/locales.json +272 -0
- package/dist/localization.d.ts +277 -0
- package/dist/localization.js +55 -0
- package/dist/mcp.d.ts +9 -0
- package/dist/mcp.js +93 -0
- package/dist/monitor.d.ts +99 -0
- package/dist/monitor.js +285 -0
- package/dist/providers/base.d.ts +34 -0
- package/dist/providers/base.js +88 -0
- package/dist/providers/index.d.ts +6 -0
- package/dist/providers/index.js +24 -0
- package/dist/providers/lmstudio.d.ts +9 -0
- package/dist/providers/lmstudio.js +71 -0
- package/dist/providers/ollama.d.ts +12 -0
- package/dist/providers/ollama.js +171 -0
- package/dist/providers/openai-compatible.d.ts +10 -0
- package/dist/providers/openai-compatible.js +68 -0
- package/dist/resource-evidence.d.ts +17 -0
- package/dist/resource-evidence.js +52 -0
- package/dist/runtime-activity.d.ts +5 -0
- package/dist/runtime-activity.js +66 -0
- package/dist/runtime-identity.d.ts +7 -0
- package/dist/runtime-identity.js +66 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.js +308 -0
- package/dist/share-page.d.ts +75 -0
- package/dist/share-page.js +167 -0
- package/dist/sharing.d.ts +35 -0
- package/dist/sharing.js +67 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.js +106 -0
- package/dist/types.d.ts +166 -0
- package/dist/types.js +3 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +13 -0
- package/docs/GLOBAL_DISTRIBUTION.md +79 -0
- package/docs/MACOS_ACCURACY_GATE.md +140 -0
- package/docs/MACOS_TESTER_GUIDE.md +88 -0
- package/examples/macos-truth.template.json +10 -0
- package/package.json +75 -0
- package/release/channels.json +41 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type Options = {
|
|
2
|
+
/**
|
|
3
|
+
Include other users' processes as well as your own.
|
|
4
|
+
|
|
5
|
+
On Windows this has no effect and will always be the user's own processes.
|
|
6
|
+
|
|
7
|
+
@default true
|
|
8
|
+
*/
|
|
9
|
+
readonly all?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type ProcessDescriptor = {
|
|
13
|
+
readonly pid: number;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly ppid: number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Full command line with arguments.
|
|
19
|
+
|
|
20
|
+
Not supported on Windows.
|
|
21
|
+
*/
|
|
22
|
+
readonly cmd?: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
CPU usage as a percentage (0-100).
|
|
26
|
+
|
|
27
|
+
Not supported on Windows.
|
|
28
|
+
*/
|
|
29
|
+
readonly cpu?: number;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
Memory usage as a percentage (0-100).
|
|
33
|
+
|
|
34
|
+
Not supported on Windows.
|
|
35
|
+
*/
|
|
36
|
+
readonly memory?: number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
User ID of the process owner.
|
|
40
|
+
|
|
41
|
+
Not supported on Windows.
|
|
42
|
+
*/
|
|
43
|
+
readonly uid?: number;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
Best-effort attempt to get the full executable path.
|
|
47
|
+
- Linux: Reads from `/proc/{pid}/exe` when available
|
|
48
|
+
- macOS: Extracted from command line when possible
|
|
49
|
+
- Falls back to `comm` (which may be truncated)
|
|
50
|
+
|
|
51
|
+
Not supported on Windows.
|
|
52
|
+
*/
|
|
53
|
+
readonly path?: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
The date and time when the process was started.
|
|
57
|
+
|
|
58
|
+
Not supported on Windows. May be `undefined` if the date cannot be parsed.
|
|
59
|
+
*/
|
|
60
|
+
readonly startTime?: Date;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
Get running processes.
|
|
65
|
+
|
|
66
|
+
@returns A list of running processes.
|
|
67
|
+
|
|
68
|
+
@example
|
|
69
|
+
```
|
|
70
|
+
import psList from 'ps-list';
|
|
71
|
+
|
|
72
|
+
console.log(await psList());
|
|
73
|
+
//=> [{pid: 3213, name: 'node', cmd: 'node test.js', ppid: 1, uid: 501, cpu: 0.1, memory: 1.5, path: '/usr/local/bin/node', startTime: 2025-01-15T10:30:00.000Z}, …]
|
|
74
|
+
```
|
|
75
|
+
*/
|
|
76
|
+
export default function psList(options?: Options): Promise<ProcessDescriptor[]>;
|
package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import {promisify} from 'node:util';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {fileURLToPath} from 'node:url';
|
|
6
|
+
import childProcess from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
const DEFAULT_MAX_BUFFER = 64_000_000; // 64 MB
|
|
11
|
+
const MAXIMUM_PATH_COMBINATION_ATTEMPTS = 6; // Limit path parsing attempts for performance
|
|
12
|
+
|
|
13
|
+
const execFile = promisify(childProcess.execFile);
|
|
14
|
+
|
|
15
|
+
// Process list field names (used in ps command output)
|
|
16
|
+
const PROCESS_FIELDS = {
|
|
17
|
+
CPU_PERCENT: '%cpu',
|
|
18
|
+
MEMORY_PERCENT: '%mem',
|
|
19
|
+
PROCESS_ID: 'pid',
|
|
20
|
+
PARENT_PROCESS_ID: 'ppid',
|
|
21
|
+
USER_ID: 'uid',
|
|
22
|
+
START_TIME: 'lstart',
|
|
23
|
+
COMMAND_NAME: 'comm',
|
|
24
|
+
ARGUMENTS: 'args',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Helper to build ps command flags consistently
|
|
28
|
+
const buildProcessCommandFlags = includeAllUsersProcesses => (includeAllUsersProcesses === false ? '' : 'a') + 'wwxo';
|
|
29
|
+
|
|
30
|
+
// Safe Date parsing with validation
|
|
31
|
+
const makeStartTime = startTimeString => {
|
|
32
|
+
if (!startTimeString) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const parsedDate = new Date(startTimeString);
|
|
37
|
+
return Number.isNaN(parsedDate.getTime()) ? undefined : parsedDate;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Extract executable path from command line using filesystem validation only
|
|
41
|
+
const extractExecutablePath = commandLine => {
|
|
42
|
+
if (!commandLine) {
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Skip non-path commands (no filesystem validation possible)
|
|
47
|
+
if (!commandLine.startsWith('/') && !commandLine.startsWith('"')) {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Handle quoted paths first: "/path with spaces/executable"
|
|
52
|
+
if (commandLine.startsWith('"')) {
|
|
53
|
+
const quotedPathMatch = commandLine.match(/^"([^"]+)"/);
|
|
54
|
+
if (quotedPathMatch && fs.existsSync(quotedPathMatch[1])) {
|
|
55
|
+
return quotedPathMatch[1];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// For unquoted absolute paths, try different strategies
|
|
62
|
+
const commandParts = commandLine.split(' ');
|
|
63
|
+
|
|
64
|
+
// Strategy 1: Simple first token (most common case)
|
|
65
|
+
const firstCommandToken = commandParts[0];
|
|
66
|
+
if (fs.existsSync(firstCommandToken)) {
|
|
67
|
+
return firstCommandToken;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Strategy 2: Progressive combination for paths with spaces
|
|
71
|
+
// Limit to reasonable number of attempts for performance
|
|
72
|
+
const maximumCombinationAttempts = Math.min(commandParts.length, MAXIMUM_PATH_COMBINATION_ATTEMPTS);
|
|
73
|
+
for (let tokenCount = 2; tokenCount <= maximumCombinationAttempts; tokenCount++) {
|
|
74
|
+
const candidateExecutablePath = commandParts.slice(0, tokenCount).join(' ');
|
|
75
|
+
if (fs.existsSync(candidateExecutablePath)) {
|
|
76
|
+
return candidateExecutablePath;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return '';
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Resolve executable path - simple approach
|
|
84
|
+
const resolveExecutablePath = (operatingSystemPlatform, processId, commandLine) => {
|
|
85
|
+
// On Linux, try /proc/{pid}/exe first for accurate path
|
|
86
|
+
if (operatingSystemPlatform === 'linux' && processId) {
|
|
87
|
+
try {
|
|
88
|
+
const symbolicLink = fs.readlinkSync(`/proc/${processId}/exe`);
|
|
89
|
+
return symbolicLink.replace(/\s+\(deleted\)$/, '');
|
|
90
|
+
} catch {
|
|
91
|
+
// Continue to other methods
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Extract path from command line
|
|
96
|
+
return extractExecutablePath(commandLine);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Parse and validate numeric field with fallback
|
|
100
|
+
const parseNumericField = (fieldValue, parserFunction = Number.parseInt, defaultValue = 0) => {
|
|
101
|
+
if (!fieldValue) {
|
|
102
|
+
return defaultValue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const parsedValue = parserFunction(fieldValue, 10);
|
|
106
|
+
return Number.isNaN(parsedValue) ? defaultValue : parsedValue;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Parse integer or return undefined - used for uid to avoid conflating unknown with root (0)
|
|
110
|
+
const parseIntegerOrUndefined = fieldValue => {
|
|
111
|
+
if (fieldValue === undefined || fieldValue === '') {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const parsedValue = Number.parseInt(fieldValue, 10);
|
|
116
|
+
return Number.isNaN(parsedValue) ? undefined : parsedValue;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Unified field parser
|
|
120
|
+
const parseProcessFields = ({processId, parentProcessId, userId, cpuUsage, memoryUsage, commandName, startTimeString, command}) => {
|
|
121
|
+
// Parse numeric fields with proper defaults
|
|
122
|
+
const parsedProcessId = parseNumericField(processId);
|
|
123
|
+
const parsedParentProcessId = parseNumericField(parentProcessId);
|
|
124
|
+
const parsedUserId = parseIntegerOrUndefined(userId);
|
|
125
|
+
const parsedCpuUsagePercentage = parseNumericField(cpuUsage, Number.parseFloat);
|
|
126
|
+
const parsedMemoryUsagePercentage = parseNumericField(memoryUsage, Number.parseFloat);
|
|
127
|
+
|
|
128
|
+
// Resolve executable path from command line
|
|
129
|
+
const resolvedExecutablePath = resolveExecutablePath(process.platform, parsedProcessId, command);
|
|
130
|
+
|
|
131
|
+
// Derive process name: prefer basename of path, fallback to command name
|
|
132
|
+
const derivedProcessName = resolvedExecutablePath ? path.basename(resolvedExecutablePath) : (commandName || '');
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
pid: parsedProcessId,
|
|
136
|
+
ppid: parsedParentProcessId,
|
|
137
|
+
uid: parsedUserId, // Undefined when uid can't be parsed (avoid conflating with root)
|
|
138
|
+
cpu: parsedCpuUsagePercentage,
|
|
139
|
+
memory: parsedMemoryUsagePercentage,
|
|
140
|
+
name: derivedProcessName,
|
|
141
|
+
path: resolvedExecutablePath,
|
|
142
|
+
startTime: makeStartTime(startTimeString),
|
|
143
|
+
cmd: command || '',
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const windows = async () => {
|
|
148
|
+
// Source: https://github.com/MarkTiedemann/fastlist
|
|
149
|
+
let binary;
|
|
150
|
+
switch (process.arch) {
|
|
151
|
+
case 'x64': {
|
|
152
|
+
binary = 'fastlist-0.3.0-x64.exe';
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case 'ia32': {
|
|
157
|
+
binary = 'fastlist-0.3.0-x86.exe';
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
case 'arm64': {
|
|
162
|
+
throw new Error('Windows ARM64 is not supported yet.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
default: {
|
|
166
|
+
throw new Error(`Unsupported architecture: ${process.arch}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const binaryPath = path.join(__dirname, 'vendor', binary);
|
|
171
|
+
const {stdout} = await execFile(binaryPath, {
|
|
172
|
+
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
173
|
+
windowsHide: true,
|
|
174
|
+
encoding: 'utf8',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return stdout
|
|
178
|
+
.trim()
|
|
179
|
+
.split(/\r?\n/)
|
|
180
|
+
.map(line => line.split('\t'))
|
|
181
|
+
.map(([processId, parentProcessId, processName]) => ({
|
|
182
|
+
pid: Number.parseInt(processId, 10),
|
|
183
|
+
ppid: Number.parseInt(parentProcessId, 10),
|
|
184
|
+
name: processName,
|
|
185
|
+
}));
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Fallback implementation with multiple ps calls
|
|
189
|
+
const nonWindowsFallbackMultipleCalls = async (options = {}) => {
|
|
190
|
+
const processDataByProcessId = {};
|
|
191
|
+
const processCommandFlags = buildProcessCommandFlags(options.all);
|
|
192
|
+
|
|
193
|
+
const fields = [
|
|
194
|
+
PROCESS_FIELDS.COMMAND_NAME,
|
|
195
|
+
PROCESS_FIELDS.ARGUMENTS,
|
|
196
|
+
PROCESS_FIELDS.PARENT_PROCESS_ID,
|
|
197
|
+
PROCESS_FIELDS.USER_ID,
|
|
198
|
+
PROCESS_FIELDS.CPU_PERCENT,
|
|
199
|
+
PROCESS_FIELDS.MEMORY_PERCENT,
|
|
200
|
+
PROCESS_FIELDS.START_TIME,
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
await Promise.all(fields.map(async fieldName => {
|
|
204
|
+
// Use headerless output with = syntax
|
|
205
|
+
const {stdout} = await execFile('ps', [processCommandFlags, `${PROCESS_FIELDS.PROCESS_ID}=,${fieldName}=`], {
|
|
206
|
+
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
207
|
+
encoding: 'utf8',
|
|
208
|
+
env: {
|
|
209
|
+
...process.env,
|
|
210
|
+
LC_ALL: 'C',
|
|
211
|
+
LANG: 'C',
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
for (const line of stdout.trim().split('\n')) {
|
|
216
|
+
const trimmedLine = line.trim();
|
|
217
|
+
const spaceIndex = trimmedLine.indexOf(' ');
|
|
218
|
+
if (spaceIndex === -1) {
|
|
219
|
+
// No space found - treat entire line as processId with empty field value
|
|
220
|
+
const processId = trimmedLine;
|
|
221
|
+
const fieldValue = '';
|
|
222
|
+
processDataByProcessId[processId] ??= {};
|
|
223
|
+
processDataByProcessId[processId][fieldName] = fieldValue;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const processId = trimmedLine.slice(0, spaceIndex);
|
|
228
|
+
const fieldValue = trimmedLine.slice(spaceIndex + 1).trim();
|
|
229
|
+
|
|
230
|
+
processDataByProcessId[processId] ??= {};
|
|
231
|
+
processDataByProcessId[processId][fieldName] = fieldValue;
|
|
232
|
+
}
|
|
233
|
+
}));
|
|
234
|
+
|
|
235
|
+
// Filter out incomplete entries and convert to process objects
|
|
236
|
+
return Object.entries(processDataByProcessId)
|
|
237
|
+
.filter(([, data]) => data[PROCESS_FIELDS.COMMAND_NAME] && data[PROCESS_FIELDS.PARENT_PROCESS_ID] !== undefined)
|
|
238
|
+
.map(([processId, data]) => parseProcessFields({
|
|
239
|
+
processId,
|
|
240
|
+
parentProcessId: data[PROCESS_FIELDS.PARENT_PROCESS_ID],
|
|
241
|
+
userId: data[PROCESS_FIELDS.USER_ID],
|
|
242
|
+
cpuUsage: data[PROCESS_FIELDS.CPU_PERCENT],
|
|
243
|
+
memoryUsage: data[PROCESS_FIELDS.MEMORY_PERCENT],
|
|
244
|
+
commandName: data[PROCESS_FIELDS.COMMAND_NAME],
|
|
245
|
+
startTimeString: data[PROCESS_FIELDS.START_TIME],
|
|
246
|
+
command: data[PROCESS_FIELDS.ARGUMENTS] ?? '',
|
|
247
|
+
}));
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// Main implementation with headerless output and simpler parsing
|
|
251
|
+
const nonWindowsCall = async (options = {}) => {
|
|
252
|
+
const processCommandFlags = buildProcessCommandFlags(options.all);
|
|
253
|
+
|
|
254
|
+
// Common execFile options to avoid duplication
|
|
255
|
+
const executeFileOptions = {
|
|
256
|
+
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
257
|
+
encoding: 'utf8',
|
|
258
|
+
env: {
|
|
259
|
+
...process.env,
|
|
260
|
+
LC_ALL: 'C',
|
|
261
|
+
LANG: 'C',
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Build field lists for ps commands
|
|
266
|
+
const processFieldCommaSeparatedList = [
|
|
267
|
+
PROCESS_FIELDS.PROCESS_ID,
|
|
268
|
+
PROCESS_FIELDS.PARENT_PROCESS_ID,
|
|
269
|
+
PROCESS_FIELDS.USER_ID,
|
|
270
|
+
PROCESS_FIELDS.CPU_PERCENT,
|
|
271
|
+
PROCESS_FIELDS.MEMORY_PERCENT,
|
|
272
|
+
PROCESS_FIELDS.START_TIME,
|
|
273
|
+
PROCESS_FIELDS.COMMAND_NAME,
|
|
274
|
+
].map(fieldName => `${fieldName}=`).join(',');
|
|
275
|
+
|
|
276
|
+
const commandFieldCommaSeparatedList = [
|
|
277
|
+
PROCESS_FIELDS.PROCESS_ID,
|
|
278
|
+
PROCESS_FIELDS.ARGUMENTS,
|
|
279
|
+
].map(fieldName => `${fieldName}=`).join(',');
|
|
280
|
+
|
|
281
|
+
// Use headerless output with = syntax for consistent parsing
|
|
282
|
+
const processListingPromises = [
|
|
283
|
+
execFile('ps', [processCommandFlags, processFieldCommaSeparatedList], executeFileOptions),
|
|
284
|
+
execFile('ps', [processCommandFlags, commandFieldCommaSeparatedList], executeFileOptions),
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
const [processOutput, commandOutput] = await Promise.all(processListingPromises);
|
|
288
|
+
const processLines = processOutput.stdout.trim().split('\n');
|
|
289
|
+
const commandLines = commandOutput.stdout.trim().split('\n');
|
|
290
|
+
|
|
291
|
+
// Build command lookup map
|
|
292
|
+
const commandLinesByProcessId = {};
|
|
293
|
+
for (const line of commandLines) {
|
|
294
|
+
const trimmedLine = line.trim();
|
|
295
|
+
const spaceIndex = trimmedLine.indexOf(' ');
|
|
296
|
+
if (spaceIndex === -1) {
|
|
297
|
+
// No space found - treat entire line as processId with empty command
|
|
298
|
+
const processId = trimmedLine;
|
|
299
|
+
commandLinesByProcessId[processId] = '';
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const processId = trimmedLine.slice(0, spaceIndex);
|
|
304
|
+
const command = trimmedLine.slice(spaceIndex + 1).trim();
|
|
305
|
+
commandLinesByProcessId[processId] = command;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Parse process lines - format: pid ppid uid cpu mem lstart comm
|
|
309
|
+
const processes = [];
|
|
310
|
+
for (const line of processLines) {
|
|
311
|
+
const trimmedLine = line.trim();
|
|
312
|
+
if (!trimmedLine) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Parse fixed-width fields more carefully
|
|
317
|
+
// Format: "pid ppid uid cpu mem Day Mon DD HH:MM:SS YYYY comm"
|
|
318
|
+
// First 5 fields should be numeric values (pid, ppid, uid are integers; cpu, memory are floats)
|
|
319
|
+
// Regex breakdown: ^(\d+) = pid, \s+(\d+) = ppid, \s+(\d+) = uid, \s+([\d.]+) = cpu%, \s+([\d.]+) = mem%, \s+(.+) = rest
|
|
320
|
+
const processLineRegexMatch = trimmedLine.match(/^(\d+)\s+(\d+)\s+(\d+)\s+([\d.]+)\s+([\d.]+)\s+(.+)/);
|
|
321
|
+
if (!processLineRegexMatch) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const [, processId, parentProcessId, userId, cpuUsage, memoryUsage, dateAndCommandPortion] = processLineRegexMatch;
|
|
326
|
+
|
|
327
|
+
// Parse lstart from dateAndCommandPortion - it's always: "Day Mon DD HH:MM:SS YYYY"
|
|
328
|
+
// This regex handles both single and double digit days
|
|
329
|
+
// Regex breakdown: ((?:\w{3}\s+){2} = "Day Mon ", \d{1,2} = day, \s+(?:\d{2}:){2}\d{2} = "HH:MM:SS", \s+\d{4}) = " YYYY"
|
|
330
|
+
const startTimeRegexMatch = dateAndCommandPortion.match(/^((?:\w{3}\s+){2}\d{1,2}\s+(?:\d{2}:){2}\d{2}\s+\d{4})\s+(.*)$/);
|
|
331
|
+
|
|
332
|
+
let startTimeString = '';
|
|
333
|
+
let processCommandName = dateAndCommandPortion; // Fallback if start time parsing fails
|
|
334
|
+
|
|
335
|
+
if (startTimeRegexMatch) {
|
|
336
|
+
startTimeString = startTimeRegexMatch[1];
|
|
337
|
+
processCommandName = startTimeRegexMatch[2] || '';
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
processes.push(parseProcessFields({
|
|
341
|
+
processId,
|
|
342
|
+
parentProcessId,
|
|
343
|
+
userId,
|
|
344
|
+
cpuUsage,
|
|
345
|
+
memoryUsage,
|
|
346
|
+
commandName: processCommandName,
|
|
347
|
+
startTimeString,
|
|
348
|
+
command: commandLinesByProcessId[processId] ?? '',
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return processes;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const nonWindows = async (options = {}) => {
|
|
356
|
+
try {
|
|
357
|
+
return await nonWindowsCall(options);
|
|
358
|
+
} catch {
|
|
359
|
+
// Fallback to multiple calls if main approach fails
|
|
360
|
+
return nonWindowsFallbackMultipleCalls(options);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const psList = process.platform === 'win32' ? windows : nonWindows;
|
|
365
|
+
|
|
366
|
+
export default psList;
|
package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/license
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ps-list",
|
|
3
|
+
"version": "9.0.0",
|
|
4
|
+
"description": "Get running processes",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": "sindresorhus/ps-list",
|
|
7
|
+
"funding": "https://github.com/sponsors/sindresorhus",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Sindre Sorhus",
|
|
10
|
+
"email": "sindresorhus@gmail.com",
|
|
11
|
+
"url": "https://sindresorhus.com"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"default": "./index.js"
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "xo && ava && tsd"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"index.js",
|
|
27
|
+
"index.d.ts",
|
|
28
|
+
"vendor/*.exe"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"ps",
|
|
32
|
+
"proc",
|
|
33
|
+
"process",
|
|
34
|
+
"processes",
|
|
35
|
+
"list",
|
|
36
|
+
"running",
|
|
37
|
+
"tasklist"
|
|
38
|
+
],
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"ava": "^6.4.1",
|
|
41
|
+
"tsd": "^0.33.0",
|
|
42
|
+
"xo": "^0.59.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/readme.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# ps-list
|
|
2
|
+
|
|
3
|
+
> Get running processes
|
|
4
|
+
|
|
5
|
+
Works on macOS, Linux, and Windows. Windows ARM64 is not supported yet.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install ps-list
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import psList from 'ps-list';
|
|
17
|
+
|
|
18
|
+
console.log(await psList());
|
|
19
|
+
//=> [{pid: 3213, name: 'node', cmd: 'node test.js', ppid: 1, uid: 501, cpu: 0.1, memory: 1.5, path: '/usr/local/bin/node', startTime: 2025-01-15T10:30:00.000Z}, …]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## API
|
|
23
|
+
|
|
24
|
+
### psList(options?)
|
|
25
|
+
|
|
26
|
+
Returns a `Promise<ProcessDescriptor[]>` with the running processes.
|
|
27
|
+
|
|
28
|
+
On macOS and Linux:
|
|
29
|
+
- The `name` property is truncated to 15 characters by the system
|
|
30
|
+
- The `cmd` property contains the full command line with arguments
|
|
31
|
+
- The `cpu` property is the CPU usage percentage (0-100)
|
|
32
|
+
- The `memory` property is the memory usage percentage (0-100)
|
|
33
|
+
- The `path` property is a best-effort attempt to get the full executable path:
|
|
34
|
+
- On Linux: reads from `/proc/{pid}/exe` when available
|
|
35
|
+
- On macOS: extracted from command line when possible
|
|
36
|
+
- Falls back to `comm` (which may be truncated)
|
|
37
|
+
- The `startTime` property contains the process start time as a Date object
|
|
38
|
+
|
|
39
|
+
The `cmd`, `cpu`, `memory`, `uid`, `path`, and `startTime` properties are not available on Windows.
|
|
40
|
+
|
|
41
|
+
#### options
|
|
42
|
+
|
|
43
|
+
Type: `object`
|
|
44
|
+
|
|
45
|
+
##### all
|
|
46
|
+
|
|
47
|
+
Type: `boolean`\
|
|
48
|
+
Default: `true`
|
|
49
|
+
|
|
50
|
+
Include other users' processes as well as your own.
|
|
51
|
+
|
|
52
|
+
On Windows this has no effect and will always be the user's own processes.
|
|
53
|
+
|
|
54
|
+
## Related
|
|
55
|
+
|
|
56
|
+
- [fastlist](https://github.com/MarkTiedemann/fastlist) - The binary used in this module to list the running processes on Windows
|
|
Binary file
|
|
Binary file
|