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.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/PRIVACY.md +150 -0
  3. package/README.md +313 -0
  4. package/STATUS.md +136 -0
  5. package/dist/agents.d.ts +22 -0
  6. package/dist/agents.js +281 -0
  7. package/dist/aggregate.d.ts +28 -0
  8. package/dist/aggregate.js +151 -0
  9. package/dist/assets/forkit-icon-dark.png +0 -0
  10. package/dist/assets/forkit-icon-light.png +0 -0
  11. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Info.plist +5 -0
  12. package/dist/bootstrap/Forkit AI Footprint.app/Contents/MacOS/Forkit AI Footprint +0 -0
  13. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitAIFootprint.icns +0 -0
  14. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/ForkitStatusTemplate.png +0 -0
  15. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.d.ts +22 -0
  16. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/agents.js +281 -0
  17. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.d.ts +28 -0
  18. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/aggregate.js +151 -0
  19. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-dark.png +0 -0
  20. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/assets/forkit-icon-light.png +0 -0
  21. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.d.ts +3 -0
  22. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/census.js +196 -0
  23. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.d.ts +32 -0
  24. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/cli.js +404 -0
  25. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.d.ts +14 -0
  26. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/doctor.js +71 -0
  27. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.d.ts +8 -0
  28. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/endpoints.js +45 -0
  29. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.d.ts +44 -0
  30. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/evaluate.js +102 -0
  31. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.d.ts +11 -0
  32. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/filesystem.js +226 -0
  33. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.d.ts +7 -0
  34. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/format.js +78 -0
  35. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.d.ts +4 -0
  36. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/hash.js +16 -0
  37. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.d.ts +22 -0
  38. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/index.js +58 -0
  39. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.d.ts +13 -0
  40. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/insights.js +76 -0
  41. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.d.ts +19 -0
  42. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/local-device.js +81 -0
  43. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/locales.json +272 -0
  44. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.d.ts +277 -0
  45. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/localization.js +55 -0
  46. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.d.ts +9 -0
  47. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/mcp.js +93 -0
  48. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.d.ts +99 -0
  49. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/monitor.js +285 -0
  50. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.d.ts +34 -0
  51. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/base.js +88 -0
  52. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.d.ts +6 -0
  53. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/index.js +24 -0
  54. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.d.ts +9 -0
  55. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/lmstudio.js +71 -0
  56. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.d.ts +12 -0
  57. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/ollama.js +171 -0
  58. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.d.ts +10 -0
  59. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/providers/openai-compatible.js +68 -0
  60. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.d.ts +17 -0
  61. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/resource-evidence.js +52 -0
  62. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.d.ts +5 -0
  63. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-activity.js +66 -0
  64. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.d.ts +7 -0
  65. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/runtime-identity.js +66 -0
  66. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.d.ts +21 -0
  67. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/server.js +308 -0
  68. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.d.ts +75 -0
  69. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/share-page.js +167 -0
  70. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.d.ts +35 -0
  71. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/sharing.js +67 -0
  72. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.d.ts +9 -0
  73. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/tools.js +106 -0
  74. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.d.ts +166 -0
  75. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/types.js +3 -0
  76. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.d.ts +4 -0
  77. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/dist/version.js +13 -0
  78. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.d.ts +76 -0
  79. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/index.js +366 -0
  80. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/license +9 -0
  81. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/package.json +44 -0
  82. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/readme.md +56 -0
  83. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe +0 -0
  84. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/node_modules/ps-list/vendor/fastlist-0.3.0-x86.exe +0 -0
  85. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/app/package.json +6 -0
  86. package/dist/bootstrap/Forkit AI Footprint.app/Contents/Resources/runtime/node +0 -0
  87. package/dist/bootstrap/Forkit AI Footprint.app/Contents/_CodeSignature/CodeResources +931 -0
  88. package/dist/census.d.ts +3 -0
  89. package/dist/census.js +196 -0
  90. package/dist/cli.d.ts +32 -0
  91. package/dist/cli.js +404 -0
  92. package/dist/doctor.d.ts +14 -0
  93. package/dist/doctor.js +71 -0
  94. package/dist/endpoints.d.ts +8 -0
  95. package/dist/endpoints.js +45 -0
  96. package/dist/evaluate.d.ts +44 -0
  97. package/dist/evaluate.js +102 -0
  98. package/dist/filesystem.d.ts +11 -0
  99. package/dist/filesystem.js +226 -0
  100. package/dist/format.d.ts +7 -0
  101. package/dist/format.js +78 -0
  102. package/dist/hash.d.ts +4 -0
  103. package/dist/hash.js +16 -0
  104. package/dist/index.d.ts +22 -0
  105. package/dist/index.js +58 -0
  106. package/dist/insights.d.ts +13 -0
  107. package/dist/insights.js +76 -0
  108. package/dist/local-device.d.ts +19 -0
  109. package/dist/local-device.js +81 -0
  110. package/dist/locales.json +272 -0
  111. package/dist/localization.d.ts +277 -0
  112. package/dist/localization.js +55 -0
  113. package/dist/mcp.d.ts +9 -0
  114. package/dist/mcp.js +93 -0
  115. package/dist/monitor.d.ts +99 -0
  116. package/dist/monitor.js +285 -0
  117. package/dist/providers/base.d.ts +34 -0
  118. package/dist/providers/base.js +88 -0
  119. package/dist/providers/index.d.ts +6 -0
  120. package/dist/providers/index.js +24 -0
  121. package/dist/providers/lmstudio.d.ts +9 -0
  122. package/dist/providers/lmstudio.js +71 -0
  123. package/dist/providers/ollama.d.ts +12 -0
  124. package/dist/providers/ollama.js +171 -0
  125. package/dist/providers/openai-compatible.d.ts +10 -0
  126. package/dist/providers/openai-compatible.js +68 -0
  127. package/dist/resource-evidence.d.ts +17 -0
  128. package/dist/resource-evidence.js +52 -0
  129. package/dist/runtime-activity.d.ts +5 -0
  130. package/dist/runtime-activity.js +66 -0
  131. package/dist/runtime-identity.d.ts +7 -0
  132. package/dist/runtime-identity.js +66 -0
  133. package/dist/server.d.ts +21 -0
  134. package/dist/server.js +308 -0
  135. package/dist/share-page.d.ts +75 -0
  136. package/dist/share-page.js +167 -0
  137. package/dist/sharing.d.ts +35 -0
  138. package/dist/sharing.js +67 -0
  139. package/dist/tools.d.ts +9 -0
  140. package/dist/tools.js +106 -0
  141. package/dist/types.d.ts +166 -0
  142. package/dist/types.js +3 -0
  143. package/dist/version.d.ts +4 -0
  144. package/dist/version.js +13 -0
  145. package/docs/GLOBAL_DISTRIBUTION.md +79 -0
  146. package/docs/MACOS_ACCURACY_GATE.md +140 -0
  147. package/docs/MACOS_TESTER_GUIDE.md +88 -0
  148. package/examples/macos-truth.template.json +10 -0
  149. package/package.json +75 -0
  150. package/release/channels.json +41 -0
@@ -0,0 +1,3 @@
1
+ import type { CensusOptions, CensusReport } from './types';
2
+ export declare function runCensus(options?: CensusOptions): Promise<CensusReport>;
3
+ //# sourceMappingURL=census.d.ts.map
package/dist/census.js ADDED
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runCensus = runCensus;
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const agents_1 = require("./agents");
10
+ const filesystem_1 = require("./filesystem");
11
+ const hash_1 = require("./hash");
12
+ const providers_1 = require("./providers");
13
+ const version_1 = require("./version");
14
+ const tools_1 = require("./tools");
15
+ const mcp_1 = require("./mcp");
16
+ function uniqueBy(items, key) {
17
+ const seen = new Map();
18
+ for (const item of items)
19
+ seen.set(key(item), item);
20
+ return [...seen.values()];
21
+ }
22
+ function safeProviderFailure(name, observedAt) {
23
+ return {
24
+ runtime: {
25
+ runtime_id: (0, hash_1.stableId)('runtime', `provider-failure:${name}`),
26
+ name: name === 'ollama' || name === 'lmstudio' || name === 'filesystem'
27
+ ? name
28
+ : 'openai-compatible',
29
+ status: 'unavailable',
30
+ endpoint: null,
31
+ model_count: 0,
32
+ observed_at: observedAt,
33
+ error_code: 'provider_scan_failed',
34
+ evidence_status: 'unavailable',
35
+ },
36
+ models: [],
37
+ warnings: [{
38
+ code: 'provider_scan_failed',
39
+ message: `${name} could not be inspected. No raw provider error was retained.`,
40
+ scope: 'runtime',
41
+ }],
42
+ };
43
+ }
44
+ function sortRuntimes(runtimes) {
45
+ return [...runtimes].sort((left, right) => {
46
+ const name = left.name.localeCompare(right.name);
47
+ return name !== 0 ? name : String(left.endpoint).localeCompare(String(right.endpoint));
48
+ });
49
+ }
50
+ function sortModels(models) {
51
+ return [...models].sort((left, right) => {
52
+ const runtime = left.runtime.localeCompare(right.runtime);
53
+ return runtime !== 0 ? runtime : left.name.localeCompare(right.name);
54
+ });
55
+ }
56
+ function buildCensusId(generatedAt, runtimes, models, agents) {
57
+ const evidence = [
58
+ generatedAt,
59
+ ...runtimes.map((runtime) => runtime.runtime_id),
60
+ ...models.map((model) => model.model_id),
61
+ ...agents.map((agent) => agent.agent_id),
62
+ ].join('|');
63
+ return (0, hash_1.stableId)('census', evidence);
64
+ }
65
+ async function runCensus(options = {}) {
66
+ const generatedAt = (options.now ?? (() => new Date()))().toISOString();
67
+ const includeRuntimes = options.includeRuntimes !== false;
68
+ const includeFilesystem = options.includeFilesystem !== false;
69
+ const includeAgents = options.includeAgents !== false;
70
+ const includeTools = options.includeTools !== false;
71
+ const includeMcp = options.includeMcp !== false;
72
+ const homeDir = options.homeDir ?? node_os_1.default.homedir();
73
+ const cwd = options.cwd ?? process.cwd();
74
+ const env = options.env ?? process.env;
75
+ const platform = options.platform ?? process.platform;
76
+ const providers = options.providers ?? (0, providers_1.createDefaultProviders)();
77
+ const providerResults = includeRuntimes
78
+ ? await Promise.all(providers.map(async (provider) => {
79
+ try {
80
+ return await provider.scan(generatedAt);
81
+ }
82
+ catch {
83
+ return safeProviderFailure(provider.name, generatedAt);
84
+ }
85
+ }))
86
+ : [];
87
+ const filesystemResult = includeFilesystem
88
+ ? await (0, filesystem_1.scanFilesystemModels)(generatedAt, options.filesystemRoots
89
+ ? { roots: options.filesystemRoots }
90
+ : {})
91
+ : null;
92
+ const warnings = [
93
+ ...providerResults.flatMap((result) => result.warnings),
94
+ ...(filesystemResult?.warnings ?? []),
95
+ ];
96
+ let agents = [];
97
+ if (includeAgents) {
98
+ try {
99
+ const processes = options.processEntries ?? await (0, agents_1.listSystemProcesses)();
100
+ agents = (0, agents_1.detectAgentProducts)(processes);
101
+ }
102
+ catch {
103
+ warnings.push({
104
+ code: 'process_inventory_unavailable',
105
+ message: 'Local process inventory was unavailable. No raw process error was retained.',
106
+ scope: 'agent',
107
+ });
108
+ }
109
+ }
110
+ const runtimes = sortRuntimes(uniqueBy([
111
+ ...providerResults.map((result) => result.runtime),
112
+ ...(filesystemResult ? [filesystemResult.runtime] : []),
113
+ ], (runtime) => runtime.runtime_id));
114
+ const models = sortModels(uniqueBy([
115
+ ...providerResults.flatMap((result) => result.models),
116
+ ...(filesystemResult?.models ?? []),
117
+ ], (model) => model.model_id));
118
+ const processCount = agents.reduce((total, agent) => total + agent.instance_count, 0);
119
+ const agentCpuMeasurements = agents.flatMap((agent) => agent.resource_snapshot.cpu_percent === null
120
+ ? []
121
+ : [agent.resource_snapshot.cpu_percent]);
122
+ const agentMemoryMeasurements = agents.flatMap((agent) => agent.resource_snapshot.memory_percent === null
123
+ ? []
124
+ : [agent.resource_snapshot.memory_percent]);
125
+ const [tools, mcpConfigs] = await Promise.all([
126
+ includeTools ? (0, tools_1.detectAiTools)({ homeDir, env, platform, agents }) : Promise.resolve([]),
127
+ includeMcp ? (0, mcp_1.detectMcpConfigs)({ homeDir, cwd: node_path_1.default.resolve(cwd), env, platform }) : Promise.resolve([]),
128
+ ]);
129
+ const storage = filesystemResult?.storage ?? {
130
+ logical_bytes: 0,
131
+ recognized_file_count: 0,
132
+ complete: true,
133
+ measurement: 'recognized-logical-file-bytes',
134
+ };
135
+ const guessed = options.guess === undefined || options.guess === null
136
+ ? null
137
+ : Math.max(0, Math.floor(options.guess));
138
+ return {
139
+ schema_version: version_1.SCHEMA_VERSION,
140
+ product: version_1.PRODUCT_NAME,
141
+ product_version: version_1.PRODUCT_VERSION,
142
+ census_id: buildCensusId(generatedAt, runtimes, models, agents),
143
+ generated_at: generatedAt,
144
+ system: {
145
+ platform,
146
+ architecture: options.architecture ?? node_os_1.default.arch(),
147
+ node_major: Number(process.versions.node.split('.')[0] ?? 0),
148
+ },
149
+ privacy: {
150
+ mode: 'metadata-only',
151
+ raw_commands_retained: false,
152
+ model_file_contents_read: false,
153
+ config_values_emitted: false,
154
+ sensitive_content_retained: false,
155
+ remote_endpoints_allowed: false,
156
+ external_requests_made: 0,
157
+ backend_contacted: false,
158
+ account_read: false,
159
+ local_state_written: false,
160
+ local_state_scope: 'none',
161
+ },
162
+ summary: {
163
+ runtime_count: runtimes.length,
164
+ available_runtime_count: runtimes.filter((runtime) => runtime.status === 'available').length,
165
+ model_count: models.length,
166
+ agent_product_count: agents.length,
167
+ agent_process_count: processCount,
168
+ agent_cpu_percent: agentCpuMeasurements.length === 0
169
+ ? null
170
+ : Math.round(agentCpuMeasurements.reduce((total, value) => total + value, 0) * 10) / 10,
171
+ agent_memory_percent: agentMemoryMeasurements.length === 0
172
+ ? null
173
+ : Math.round(agentMemoryMeasurements.reduce((total, value) => total + value, 0) * 10) / 10,
174
+ tool_count: tools.length,
175
+ mcp_config_count: mcpConfigs.length,
176
+ confirmed_running_model_count: models.filter((model) => model.evidence_status === 'confirmed-running').length,
177
+ storage_bytes: storage.logical_bytes,
178
+ storage_file_count: storage.recognized_file_count,
179
+ storage_complete: storage.complete,
180
+ storage_measurement: storage.measurement,
181
+ warning_count: warnings.length,
182
+ },
183
+ runtimes,
184
+ models,
185
+ agents,
186
+ tools,
187
+ mcp_configs: mcpConfigs,
188
+ guess: {
189
+ provided: guessed,
190
+ discovered: models.length,
191
+ difference: guessed === null ? null : models.length - guessed,
192
+ },
193
+ warnings,
194
+ };
195
+ }
196
+ //# sourceMappingURL=census.js.map
package/dist/cli.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedOptions {
3
+ command: 'install' | 'help' | 'version' | 'scan' | 'monitor' | 'doctor' | 'evaluate' | 'aggregate' | 'share-page' | 'serve';
4
+ json: boolean;
5
+ output: string | null;
6
+ includeRuntimes: boolean;
7
+ includeFilesystem: boolean;
8
+ includeAgents: boolean;
9
+ includeTools: boolean;
10
+ includeMcp: boolean;
11
+ modelDirs: string[];
12
+ verbose: boolean;
13
+ copy: boolean;
14
+ guess: number | null;
15
+ anonymousPayload: boolean;
16
+ shareConsent: boolean;
17
+ truth: string | null;
18
+ results: string | null;
19
+ port: number;
20
+ }
21
+ export declare function parseArgs(args: string[]): ParsedOptions;
22
+ export declare function installPersistentMacApp(options?: {
23
+ applicationsDirectory?: string;
24
+ open?: boolean;
25
+ }): Promise<string>;
26
+ export declare function clipboardCommands(platform: NodeJS.Platform): Array<{
27
+ command: string;
28
+ args: string[];
29
+ }>;
30
+ export declare function main(args?: string[]): Promise<number>;
31
+ export {};
32
+ //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js ADDED
@@ -0,0 +1,404 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseArgs = parseArgs;
8
+ exports.installPersistentMacApp = installPersistentMacApp;
9
+ exports.clipboardCommands = clipboardCommands;
10
+ exports.main = main;
11
+ const promises_1 = __importDefault(require("node:fs/promises"));
12
+ const node_path_1 = __importDefault(require("node:path"));
13
+ const node_os_1 = __importDefault(require("node:os"));
14
+ const node_child_process_1 = require("node:child_process");
15
+ const census_1 = require("./census");
16
+ const doctor_1 = require("./doctor");
17
+ const format_1 = require("./format");
18
+ const version_1 = require("./version");
19
+ const monitor_1 = require("./monitor");
20
+ const evaluate_1 = require("./evaluate");
21
+ const aggregate_1 = require("./aggregate");
22
+ const share_page_1 = require("./share-page");
23
+ const server_1 = require("./server");
24
+ const local_device_1 = require("./local-device");
25
+ const HELP = `Forkit AI Footprints
26
+ Private, metadata-only local AI inventory.
27
+ Apple Silicon macOS local release.
28
+
29
+ Usage:
30
+ forkit-ai-footprints
31
+ forkit-ai-footprints serve [--port 47811]
32
+ forkit-ai-footprints monitor [--json]
33
+ forkit-ai-footprints scan [options]
34
+ forkit-ai-footprints doctor [--json]
35
+ forkit-ai-footprints share-page --output /path/to/local-ai-footprint.html
36
+ forkit-ai-footprints --version
37
+
38
+ Options:
39
+ --json Print a machine-readable AI Footprint report
40
+ --verbose Show detector and identity details
41
+ --guess <count> Compare your estimate with discovered models
42
+ --copy Copy the rendered local result to the clipboard
43
+ --anonymous-payload Reserved for a completed 10-minute monitor session
44
+ --consent-share Separate consent; never enables upload in this build
45
+ --output <file> Save the selected human or JSON report
46
+ --model-dir <path> Inspect an explicit model directory; repeatable
47
+ --truth <file> Evaluate locally against manually labelled macOS truth
48
+ --results <directory> Aggregate local macOS evaluation JSON files
49
+ --port <number> Local-only serve port (default: 47811)
50
+ --no-runtimes Skip local runtime API discovery
51
+ --no-model-files Skip filesystem model metadata discovery
52
+ --no-agents Skip local process metadata discovery
53
+ --no-tools Skip passive AI-tool detection
54
+ --no-mcp Skip known MCP configuration counts
55
+ -h, --help Show this help
56
+
57
+ Privacy:
58
+ AI Footprints reads metadata only. It does not read model bytes, retain raw process
59
+ commands or MCP configuration values, authenticate to Forkit.dev, or write to
60
+ any passport, registry, Runtime_C2, or production service.
61
+ `;
62
+ function parseArgs(args) {
63
+ let command = 'install';
64
+ let json = false;
65
+ let output = null;
66
+ let includeRuntimes = true;
67
+ let includeFilesystem = true;
68
+ let includeAgents = true;
69
+ let includeTools = true;
70
+ let includeMcp = true;
71
+ let verbose = false;
72
+ let copy = false;
73
+ let guess = null;
74
+ let anonymousPayload = false;
75
+ let shareConsent = false;
76
+ let truth = null;
77
+ let results = null;
78
+ let port = 47811;
79
+ const modelDirs = [];
80
+ for (let index = 0; index < args.length; index += 1) {
81
+ const arg = args[index];
82
+ if (arg === 'install' || arg === 'install-app')
83
+ command = 'install';
84
+ else if (arg === 'scan' || arg === 'report')
85
+ command = 'scan';
86
+ else if (arg === 'monitor')
87
+ command = 'monitor';
88
+ else if (arg === 'doctor')
89
+ command = 'doctor';
90
+ else if (arg === 'evaluate')
91
+ command = 'evaluate';
92
+ else if (arg === 'aggregate')
93
+ command = 'aggregate';
94
+ else if (arg === 'share-page')
95
+ command = 'share-page';
96
+ else if (arg === 'serve')
97
+ command = 'serve';
98
+ else if (arg === '--version' || arg === '-V' || arg === 'version')
99
+ command = 'version';
100
+ else if (arg === '--help' || arg === '-h' || arg === 'help')
101
+ command = 'help';
102
+ else if (arg === '--json')
103
+ json = true;
104
+ else if (arg === '--verbose')
105
+ verbose = true;
106
+ else if (arg === '--copy')
107
+ copy = true;
108
+ else if (arg === '--anonymous-payload')
109
+ anonymousPayload = true;
110
+ else if (arg === '--consent-share')
111
+ shareConsent = true;
112
+ else if (arg === '--no-runtimes')
113
+ includeRuntimes = false;
114
+ else if (arg === '--no-model-files')
115
+ includeFilesystem = false;
116
+ else if (arg === '--no-agents')
117
+ includeAgents = false;
118
+ else if (arg === '--no-tools')
119
+ includeTools = false;
120
+ else if (arg === '--no-mcp')
121
+ includeMcp = false;
122
+ else if (arg === '--guess') {
123
+ const rawGuess = args[index + 1];
124
+ const parsedGuess = Number(rawGuess);
125
+ if (!rawGuess || !Number.isFinite(parsedGuess) || parsedGuess < 0) {
126
+ throw new Error('--guess requires a non-negative number.');
127
+ }
128
+ guess = Math.floor(parsedGuess);
129
+ index += 1;
130
+ }
131
+ else if (arg === '--port') {
132
+ const rawPort = args[index + 1];
133
+ const parsedPort = Number(rawPort);
134
+ if (!rawPort || !Number.isSafeInteger(parsedPort) || parsedPort < 1024 || parsedPort > 65535) {
135
+ throw new Error('--port requires an integer from 1024 to 65535.');
136
+ }
137
+ port = parsedPort;
138
+ index += 1;
139
+ }
140
+ else if (arg === '--output') {
141
+ output = args[index + 1] ?? null;
142
+ if (!output)
143
+ throw new Error('--output requires a file path.');
144
+ index += 1;
145
+ }
146
+ else if (arg === '--truth') {
147
+ truth = args[index + 1] ?? null;
148
+ if (!truth)
149
+ throw new Error('--truth requires a file path.');
150
+ index += 1;
151
+ }
152
+ else if (arg === '--results') {
153
+ results = args[index + 1] ?? null;
154
+ if (!results)
155
+ throw new Error('--results requires a directory path.');
156
+ index += 1;
157
+ }
158
+ else if (arg === '--model-dir') {
159
+ const directory = args[index + 1];
160
+ if (!directory)
161
+ throw new Error('--model-dir requires a directory path.');
162
+ modelDirs.push(directory);
163
+ index += 1;
164
+ }
165
+ else {
166
+ throw new Error(`Unknown argument: ${arg}`);
167
+ }
168
+ }
169
+ return {
170
+ command,
171
+ json,
172
+ output,
173
+ includeRuntimes,
174
+ includeFilesystem,
175
+ includeAgents,
176
+ includeTools,
177
+ includeMcp,
178
+ modelDirs,
179
+ verbose,
180
+ copy,
181
+ guess,
182
+ anonymousPayload,
183
+ shareConsent,
184
+ truth,
185
+ results,
186
+ port,
187
+ };
188
+ }
189
+ async function installPersistentMacApp(options = {}) {
190
+ if (process.platform !== 'darwin' || process.arch !== 'arm64')
191
+ throw new Error('The persistent GUI currently supports Apple Silicon macOS only.');
192
+ const source = node_path_1.default.join(__dirname, 'bootstrap', 'Forkit AI Footprint.app');
193
+ try {
194
+ await promises_1.default.access(node_path_1.default.join(source, 'Contents', 'Info.plist'));
195
+ }
196
+ catch {
197
+ throw new Error('This package does not contain the macOS GUI bootstrap. Install from the packed release candidate.');
198
+ }
199
+ const applicationsDirectory = options.applicationsDirectory
200
+ ?? process.env.FORKIT_AI_FOOTPRINTS_APPLICATIONS_DIR
201
+ ?? node_path_1.default.join(node_os_1.default.homedir(), 'Applications');
202
+ const destination = node_path_1.default.join(applicationsDirectory, 'Forkit AI Footprint.app');
203
+ const staging = node_path_1.default.join(applicationsDirectory, `.Forkit AI Footprint.installing-${process.pid}.app`);
204
+ const previous = node_path_1.default.join(applicationsDirectory, `.Forkit AI Footprint.previous-${process.pid}.app`);
205
+ await promises_1.default.mkdir(applicationsDirectory, { recursive: true, mode: 0o700 });
206
+ await promises_1.default.rm(staging, { recursive: true, force: true });
207
+ await promises_1.default.cp(source, staging, { recursive: true, preserveTimestamps: true });
208
+ let hadPrevious = false;
209
+ try {
210
+ const existingInfo = await promises_1.default.readFile(node_path_1.default.join(destination, 'Contents', 'Info.plist'), 'utf8').catch(() => '');
211
+ if (existingInfo && !existingInfo.includes('dev.forkit.ai-footprints'))
212
+ throw new Error('The destination contains a different application.');
213
+ if (existingInfo) {
214
+ await promises_1.default.rename(destination, previous);
215
+ hadPrevious = true;
216
+ }
217
+ await promises_1.default.rename(staging, destination);
218
+ if (hadPrevious)
219
+ await promises_1.default.rm(previous, { recursive: true, force: true });
220
+ }
221
+ catch (error) {
222
+ await promises_1.default.rm(staging, { recursive: true, force: true });
223
+ if (hadPrevious)
224
+ await promises_1.default.rename(previous, destination).catch(() => undefined);
225
+ throw error;
226
+ }
227
+ if (options.open !== false && process.env.FORKIT_AI_FOOTPRINTS_NO_OPEN !== '1') {
228
+ const launched = (0, node_child_process_1.spawnSync)('/usr/bin/open', [destination], { stdio: 'ignore', shell: false });
229
+ if (launched.status !== 0)
230
+ throw new Error('Forkit was installed, but macOS could not open it.');
231
+ }
232
+ return destination;
233
+ }
234
+ async function emit(output, filePath) {
235
+ process.stdout.write(output);
236
+ if (filePath)
237
+ await promises_1.default.writeFile(filePath, output, { encoding: 'utf8', flag: 'w' });
238
+ }
239
+ function clipboardCommands(platform) {
240
+ if (platform === 'darwin')
241
+ return [{ command: 'pbcopy', args: [] }];
242
+ if (platform === 'win32')
243
+ return [{ command: 'clip', args: [] }];
244
+ return [
245
+ { command: 'wl-copy', args: [] },
246
+ { command: 'xclip', args: ['-selection', 'clipboard'] },
247
+ ];
248
+ }
249
+ function copyToClipboard(value) {
250
+ for (const invocation of clipboardCommands(process.platform)) {
251
+ const result = (0, node_child_process_1.spawnSync)(invocation.command, invocation.args, {
252
+ input: value,
253
+ encoding: 'utf8',
254
+ stdio: ['pipe', 'ignore', 'ignore'],
255
+ shell: false,
256
+ });
257
+ if (result.status === 0)
258
+ return true;
259
+ }
260
+ return false;
261
+ }
262
+ async function main(args = process.argv.slice(2)) {
263
+ let options;
264
+ try {
265
+ options = parseArgs(args);
266
+ }
267
+ catch (error) {
268
+ process.stderr.write(`${error instanceof Error ? error.message : 'Invalid arguments'}\n\n${HELP}`);
269
+ return 2;
270
+ }
271
+ if (options.command === 'help') {
272
+ process.stdout.write(HELP);
273
+ return 0;
274
+ }
275
+ if (options.command === 'version') {
276
+ process.stdout.write(`${version_1.PRODUCT_VERSION}\n`);
277
+ return 0;
278
+ }
279
+ if (options.command === 'install') {
280
+ const destination = await installPersistentMacApp();
281
+ process.stdout.write(`Forkit AI Footprint is installed at ${destination}\nOpen it later from Applications or Spotlight; Terminal is no longer required.\nYour AI activity stays on this device by default. After seeing your results, you can optionally review aggregate measurements for global comparison.\n`);
282
+ return 0;
283
+ }
284
+ if (options.command === 'serve') {
285
+ const service = await (0, server_1.startAiFootprintsServer)({ port: options.port });
286
+ process.stdout.write(`Forkit AI Footprints is ready at ${service.url}\nMetadata stays on this device. Press Ctrl+C to stop.\n`);
287
+ if (process.platform === 'darwin' && process.env.FORKIT_AI_FOOTPRINTS_NO_OPEN !== '1'
288
+ && process.env.FORKIT_AI_FOOTPRINTS_APP_BUNDLE !== '1') {
289
+ (0, node_child_process_1.spawnSync)('open', [service.url], { stdio: 'ignore', shell: false });
290
+ }
291
+ await new Promise((resolve) => {
292
+ const stop = () => { void service.close().finally(resolve); };
293
+ process.once('SIGINT', stop);
294
+ process.once('SIGTERM', stop);
295
+ });
296
+ return 0;
297
+ }
298
+ if (options.command === 'monitor') {
299
+ const monitor = new monitor_1.ActivityMonitor();
300
+ await monitor.start();
301
+ process.stderr.write('Monitoring locally until Ctrl+C. Process IDs and commands are not emitted.\n');
302
+ await new Promise((resolve) => {
303
+ const stop = () => resolve();
304
+ process.once('SIGINT', stop);
305
+ process.once('SIGTERM', stop);
306
+ });
307
+ const summary = monitor.stop();
308
+ const rendered = options.json
309
+ ? `${JSON.stringify(summary, null, 2)}\n`
310
+ : `Observed ${summary.observed_seconds.toFixed(1)}s · AI active ${summary.active_seconds.toFixed(1)}s · ratio ${summary.activity_ratio === null ? 'unavailable' : `${Math.round(summary.activity_ratio * 100)}%`}\n`;
311
+ await emit(rendered, options.output);
312
+ if (options.anonymousPayload) {
313
+ process.stderr.write('Anonymous preview requires a completed 10-minute GUI session with the exact payload reviewed first. Nothing was uploaded.\n');
314
+ return 2;
315
+ }
316
+ return 0;
317
+ }
318
+ if (options.command === 'doctor') {
319
+ const report = await (0, doctor_1.runDoctor)();
320
+ const rendered = options.json
321
+ ? `${JSON.stringify(report, null, 2)}\n`
322
+ : (0, format_1.formatDoctorReport)(report);
323
+ await emit(rendered, options.output);
324
+ return report.ok ? 0 : 1;
325
+ }
326
+ if (options.command === 'evaluate') {
327
+ if (!options.truth) {
328
+ process.stderr.write('evaluate requires --truth with a local labelled macOS truth file.\n');
329
+ return 2;
330
+ }
331
+ const evaluation = await (0, evaluate_1.evaluateMacosFieldTruthFile)(options.truth);
332
+ await emit(`${JSON.stringify(evaluation, null, 2)}\n`, options.output);
333
+ return 0;
334
+ }
335
+ if (options.command === 'aggregate') {
336
+ if (!options.results) {
337
+ process.stderr.write('aggregate requires --results with a directory of local evaluation JSON files.\n');
338
+ return 2;
339
+ }
340
+ const aggregate = await (0, aggregate_1.aggregateMacosFieldEvaluationDirectory)(options.results);
341
+ await emit(`${JSON.stringify(aggregate, null, 2)}\n`, options.output);
342
+ return 0;
343
+ }
344
+ if (options.command === 'share-page') {
345
+ if (!options.output) {
346
+ process.stderr.write('share-page requires --output with a local HTML file path.\n');
347
+ return 2;
348
+ }
349
+ const report = await (0, census_1.runCensus)({
350
+ includeRuntimes: options.includeRuntimes,
351
+ includeFilesystem: options.includeFilesystem,
352
+ includeAgents: options.includeAgents,
353
+ includeTools: options.includeTools,
354
+ includeMcp: options.includeMcp,
355
+ guess: options.guess,
356
+ ...(options.modelDirs.length > 0 ? { filesystemRoots: options.modelDirs } : {}),
357
+ });
358
+ if (process.env.FORKIT_AI_FOOTPRINTS_DISABLE_JOURNAL !== '1') {
359
+ await (0, local_device_1.recordLocalScan)({ now: () => new Date(report.generated_at) });
360
+ report.privacy.local_state_written = true;
361
+ report.privacy.local_state_scope = 'device-journal-only';
362
+ }
363
+ await promises_1.default.writeFile(options.output, (0, share_page_1.renderCensusSharePage)(report), { encoding: 'utf8', flag: 'w' });
364
+ process.stdout.write('Local aggregate share page written. No data was uploaded.\n');
365
+ return 0;
366
+ }
367
+ const report = await (0, census_1.runCensus)({
368
+ includeRuntimes: options.includeRuntimes,
369
+ includeFilesystem: options.includeFilesystem,
370
+ includeAgents: options.includeAgents,
371
+ includeTools: options.includeTools,
372
+ includeMcp: options.includeMcp,
373
+ guess: options.guess,
374
+ ...(options.modelDirs.length > 0 ? { filesystemRoots: options.modelDirs } : {}),
375
+ });
376
+ if (process.env.FORKIT_AI_FOOTPRINTS_DISABLE_JOURNAL !== '1') {
377
+ await (0, local_device_1.recordLocalScan)({ now: () => new Date(report.generated_at) });
378
+ report.privacy.local_state_written = true;
379
+ report.privacy.local_state_scope = 'device-journal-only';
380
+ }
381
+ const rendered = options.json
382
+ ? `${JSON.stringify(report, null, 2)}\n`
383
+ : (0, format_1.formatCensusReport)(report, { verbose: options.verbose });
384
+ await emit(rendered, options.output);
385
+ if (options.copy && !copyToClipboard(rendered)) {
386
+ process.stderr.write('Clipboard command unavailable; the result remains printable and can be copied from the terminal.\n');
387
+ }
388
+ if (options.anonymousPayload) {
389
+ process.stderr.write(options.shareConsent
390
+ ? 'Anonymous contribution was not prepared: a valid 10-minute monitor session and exact payload review are required. Nothing was uploaded.\n'
391
+ : 'Anonymous contribution was not prepared: separate --consent-share is required. Nothing was uploaded.\n');
392
+ return 2;
393
+ }
394
+ return 0;
395
+ }
396
+ if (require.main === module) {
397
+ void main().then((code) => {
398
+ process.exitCode = code;
399
+ }).catch(() => {
400
+ process.stderr.write('Forkit AI Footprints failed safely. No raw error details were printed.\n');
401
+ process.exitCode = 1;
402
+ });
403
+ }
404
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,14 @@
1
+ import { PRODUCT_NAME } from './version';
2
+ export interface DoctorCheck {
3
+ name: string;
4
+ ok: boolean;
5
+ detail: string;
6
+ }
7
+ export interface DoctorReport {
8
+ product: typeof PRODUCT_NAME;
9
+ version: string;
10
+ ok: boolean;
11
+ checks: DoctorCheck[];
12
+ }
13
+ export declare function runDoctor(): Promise<DoctorReport>;
14
+ //# sourceMappingURL=doctor.d.ts.map