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,285 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActivityMonitor = void 0;
4
+ const agents_1 = require("./agents");
5
+ const DEFAULT_INTERVAL_MS = 1000;
6
+ const DEFAULT_HISTORY_LIMIT = 900;
7
+ function rounded(value, digits = 1) {
8
+ const factor = 10 ** digits;
9
+ return Math.round(value * factor) / factor;
10
+ }
11
+ function sum(values) {
12
+ const measured = values.filter((value) => value !== null);
13
+ return measured.length === 0 ? null : rounded(measured.reduce((total, value) => total + value, 0));
14
+ }
15
+ function percentile(values, fraction) {
16
+ if (values.length === 0)
17
+ return null;
18
+ const sorted = [...values].sort((left, right) => left - right);
19
+ const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * fraction) - 1));
20
+ return rounded(sorted[index]);
21
+ }
22
+ function localContextFromEnvironment() {
23
+ const chat = process.env.FORKIT_AI_FOOTPRINTS_CONTEXT_CHAT?.trim() || null;
24
+ const workspace = process.env.FORKIT_AI_FOOTPRINTS_CONTEXT_WORKSPACE?.trim() || null;
25
+ return {
26
+ chat,
27
+ workspace,
28
+ source: chat || workspace ? 'cooperating-app-metadata' : null,
29
+ };
30
+ }
31
+ function groupProcesses(processes) {
32
+ const result = new Map();
33
+ for (const entry of processes)
34
+ result.set(entry.signature, [...(result.get(entry.signature) ?? []), entry]);
35
+ return result;
36
+ }
37
+ function historyByteSize(snapshot) {
38
+ return Buffer.byteLength(JSON.stringify({
39
+ started_at: snapshot.started_at,
40
+ observed_seconds: snapshot.observed_seconds,
41
+ active_seconds: snapshot.active_seconds,
42
+ products: snapshot.products,
43
+ timeline: snapshot.timeline,
44
+ }));
45
+ }
46
+ class ActivityMonitor {
47
+ sampleProcesses;
48
+ now;
49
+ intervalMs;
50
+ historyLimit;
51
+ excludedRootPid;
52
+ context;
53
+ classifyProcesses;
54
+ lifecycle = 'stopped';
55
+ startedAt = null;
56
+ stoppedAt = null;
57
+ previousAt = null;
58
+ observationId = 0;
59
+ previousCpuTimes = new Map();
60
+ observedMs = 0;
61
+ activeMs = 0;
62
+ products = new Map();
63
+ timeline = [];
64
+ timer = null;
65
+ sampling = false;
66
+ nodeCpuUsage = null;
67
+ nodeCpuAt = null;
68
+ overheadCpuSamples = [];
69
+ overheadMemorySamples = [];
70
+ constructor(options = {}) {
71
+ this.sampleProcesses = options.sampleProcesses ?? agents_1.listSystemProcesses;
72
+ this.now = options.now ?? Date.now;
73
+ this.intervalMs = Math.max(500, options.intervalMs ?? DEFAULT_INTERVAL_MS);
74
+ this.historyLimit = Math.max(10, options.historyLimit ?? DEFAULT_HISTORY_LIMIT);
75
+ this.excludedRootPid = options.excludedRootPid === undefined ? process.pid : options.excludedRootPid;
76
+ this.context = options.context ?? localContextFromEnvironment;
77
+ this.classifyProcesses = options.classifyProcesses ?? ((entries) => (0, agents_1.classifyAgentProcessTrees)(entries, this.excludedRootPid));
78
+ }
79
+ async start(options = {}) {
80
+ if (this.lifecycle === 'monitoring')
81
+ return this.snapshot();
82
+ const now = this.now();
83
+ this.lifecycle = 'monitoring';
84
+ this.observationId += 1;
85
+ this.startedAt = now;
86
+ this.stoppedAt = null;
87
+ this.previousAt = null;
88
+ this.previousCpuTimes.clear();
89
+ this.nodeCpuUsage = process.cpuUsage();
90
+ this.nodeCpuAt = now;
91
+ await this.sampleNow();
92
+ if (options.schedule !== false) {
93
+ this.timer = setInterval(() => { void this.sampleNow(); }, this.intervalMs);
94
+ this.timer.unref();
95
+ }
96
+ return this.snapshot();
97
+ }
98
+ async sampleNow() {
99
+ if (this.lifecycle !== 'monitoring' || this.sampling)
100
+ return this.snapshot();
101
+ this.sampling = true;
102
+ try {
103
+ const entries = await this.sampleProcesses();
104
+ const now = this.now();
105
+ const elapsed = this.previousAt === null ? 0 : Math.max(0, now - this.previousAt);
106
+ const validElapsed = elapsed > 0 && elapsed <= this.intervalMs * 3 ? elapsed : 0;
107
+ const grouped = groupProcesses(await this.classifyProcesses(entries));
108
+ const signatures = new Set([...this.products.keys(), ...grouped.keys()]);
109
+ for (const signature of signatures) {
110
+ const current = grouped.get(signature) ?? [];
111
+ const previous = this.products.get(signature);
112
+ let cpuDeltaMs = 0;
113
+ let deltaCount = 0;
114
+ for (const entry of current) {
115
+ const currentTime = entry.cpu_time_ms;
116
+ const previousTime = this.previousCpuTimes.get(entry.pid);
117
+ if (currentTime === null || previousTime === undefined || currentTime < previousTime)
118
+ continue;
119
+ cpuDeltaMs += currentTime - previousTime;
120
+ deltaCount += 1;
121
+ }
122
+ const measuredDelta = deltaCount > 0 ? cpuDeltaMs : null;
123
+ const strongSignal = current.length > 0
124
+ && validElapsed > 0
125
+ && measuredDelta !== null
126
+ && measuredDelta >= Math.max(20, validElapsed * 0.02);
127
+ const signals = [...(previous?.signals ?? []), strongSignal].slice(-3);
128
+ let state;
129
+ if (current.length === 0)
130
+ state = 'not-running';
131
+ else if (previous?.state === 'working-now')
132
+ state = signals.every((value) => !value) ? 'open-idle' : 'working-now';
133
+ else
134
+ state = signals.slice(-2).length === 2 && signals.slice(-2).every(Boolean) ? 'working-now' : 'open-idle';
135
+ const activeMs = (previous?.activeMs ?? 0) + (validElapsed > 0 && state === 'working-now' ? validElapsed : 0);
136
+ const first = current[0];
137
+ this.products.set(signature, {
138
+ signature,
139
+ name: first?.name ?? previous?.name ?? signature,
140
+ kind: first?.kind ?? previous?.kind ?? 'unknown',
141
+ state,
142
+ signals,
143
+ activeMs,
144
+ processCount: current.length,
145
+ cpuPercent: sum(current.map((entry) => entry.cpu_percent)),
146
+ memoryPercent: sum(current.map((entry) => entry.memory_percent)),
147
+ cpuDeltaMs: measuredDelta,
148
+ });
149
+ }
150
+ if (validElapsed > 0) {
151
+ this.observedMs += validElapsed;
152
+ if ([...this.products.values()].some((product) => product.state === 'working-now'))
153
+ this.activeMs += validElapsed;
154
+ }
155
+ this.updateTimeline(now);
156
+ this.previousCpuTimes = new Map(entries.flatMap((entry) => Number.isFinite(entry.cpu_time_ms)
157
+ ? [[entry.pid, Number(entry.cpu_time_ms)]]
158
+ : []));
159
+ this.previousAt = now;
160
+ this.sampleOverhead(now, entries);
161
+ return this.snapshot();
162
+ }
163
+ finally {
164
+ this.sampling = false;
165
+ }
166
+ }
167
+ stop() {
168
+ if (this.timer)
169
+ clearInterval(this.timer);
170
+ this.timer = null;
171
+ if (this.lifecycle === 'monitoring')
172
+ this.stoppedAt = this.now();
173
+ this.lifecycle = 'stopped';
174
+ return this.snapshot();
175
+ }
176
+ clearHistory() {
177
+ const now = this.now();
178
+ this.startedAt = this.lifecycle === 'monitoring' ? now : null;
179
+ this.stoppedAt = null;
180
+ this.previousAt = null;
181
+ this.previousCpuTimes.clear();
182
+ this.observedMs = 0;
183
+ this.activeMs = 0;
184
+ this.products.clear();
185
+ this.timeline = [];
186
+ this.overheadCpuSamples = [];
187
+ this.overheadMemorySamples = [];
188
+ this.nodeCpuUsage = process.cpuUsage();
189
+ this.nodeCpuAt = now;
190
+ return this.snapshot();
191
+ }
192
+ updateTimeline(now) {
193
+ const working = [...this.products.values()].filter((product) => product.state === 'working-now');
194
+ const running = [...this.products.values()].filter((product) => product.state !== 'not-running');
195
+ const state = working.length > 0
196
+ ? 'working-now'
197
+ : running.length > 0 ? 'open-idle' : 'not-running';
198
+ const signatures = (working.length > 0 ? working : running).map((product) => product.signature).sort();
199
+ const at = new Date(now).toISOString();
200
+ const latest = this.timeline.at(-1);
201
+ if (latest && latest.observation_id === this.observationId && latest.state === state && latest.product_signatures.join('|') === signatures.join('|'))
202
+ latest.ended_at = at;
203
+ else
204
+ this.timeline.push({ started_at: at, ended_at: at, state, product_signatures: signatures, observation_id: this.observationId });
205
+ if (this.timeline.length > this.historyLimit)
206
+ this.timeline.splice(0, this.timeline.length - this.historyLimit);
207
+ }
208
+ sampleOverhead(now, entries) {
209
+ const included = new Set([process.pid]);
210
+ if (process.env.FORKIT_AI_FOOTPRINTS_APP_BUNDLE === '1' && process.ppid > 1)
211
+ included.add(process.ppid);
212
+ let changed = true;
213
+ while (changed) {
214
+ changed = false;
215
+ for (const entry of entries) {
216
+ if (included.has(entry.pid) || entry.ppid === undefined || !included.has(entry.ppid))
217
+ continue;
218
+ included.add(entry.pid);
219
+ changed = true;
220
+ }
221
+ }
222
+ const ownEntries = entries.filter((entry) => included.has(entry.pid));
223
+ const measuredMemory = ownEntries.reduce((total, entry) => total + (Number.isFinite(entry.rss_bytes) ? Number(entry.rss_bytes) : 0), 0);
224
+ const memory = measuredMemory > 0 ? measuredMemory : process.memoryUsage().rss;
225
+ this.overheadMemorySamples.push(memory);
226
+ if (this.overheadMemorySamples.length > this.historyLimit)
227
+ this.overheadMemorySamples.shift();
228
+ if (this.nodeCpuUsage && this.nodeCpuAt !== null && now - this.nodeCpuAt >= this.intervalMs * 0.5) {
229
+ const usage = process.cpuUsage(this.nodeCpuUsage);
230
+ const nodeCpu = ((usage.user + usage.system) / ((now - this.nodeCpuAt) * 1000)) * 100;
231
+ const measuredTreeCpu = ownEntries.reduce((total, entry) => total + (Number.isFinite(entry.cpu_percent) ? Number(entry.cpu_percent) : 0), 0);
232
+ const cpu = process.env.FORKIT_AI_FOOTPRINTS_APP_BUNDLE === '1' && measuredTreeCpu > 0 ? measuredTreeCpu : nodeCpu;
233
+ this.overheadCpuSamples.push(rounded(Math.max(0, cpu)));
234
+ if (this.overheadCpuSamples.length > this.historyLimit)
235
+ this.overheadCpuSamples.shift();
236
+ }
237
+ this.nodeCpuUsage = process.cpuUsage();
238
+ this.nodeCpuAt = now;
239
+ }
240
+ snapshot() {
241
+ const products = [...this.products.values()].map((product) => ({
242
+ signature: product.signature,
243
+ name: product.name,
244
+ kind: product.kind,
245
+ state: product.state,
246
+ process_count: product.processCount,
247
+ cpu_percent: product.cpuPercent,
248
+ memory_percent: product.memoryPercent,
249
+ recent_cpu_time_delta_ms: product.cpuDeltaMs,
250
+ active_seconds: rounded(product.activeMs / 1000),
251
+ context: this.context(),
252
+ })).sort((left, right) => left.name.localeCompare(right.name));
253
+ const base = {
254
+ schema_version: '1.0',
255
+ lifecycle: this.lifecycle,
256
+ started_at: this.startedAt === null ? null : new Date(this.startedAt).toISOString(),
257
+ stopped_at: this.stoppedAt === null ? null : new Date(this.stoppedAt).toISOString(),
258
+ observed_seconds: rounded(this.observedMs / 1000),
259
+ active_seconds: rounded(this.activeMs / 1000),
260
+ activity_ratio: this.observedMs > 0 ? rounded(this.activeMs / this.observedMs, 3) : null,
261
+ products,
262
+ timeline: this.timeline.map((segment) => ({ ...segment, product_signatures: [...segment.product_signatures] })),
263
+ sample_interval_ms: this.intervalMs,
264
+ history_limit: this.historyLimit,
265
+ evidence: 'repeated-process-tree-cpu-time-deltas',
266
+ limitation: 'Working now means sustained recent work in a supported app process tree; it is not prompt, task, token, energy, or cost attribution.',
267
+ };
268
+ const memory = this.overheadMemorySamples.at(-1) ?? process.memoryUsage().rss;
269
+ return {
270
+ ...base,
271
+ overhead: {
272
+ current_cpu_percent: this.overheadCpuSamples.at(-1) ?? null,
273
+ current_memory_bytes: memory,
274
+ history_bytes: historyByteSize(base),
275
+ sample_count: this.overheadCpuSamples.length,
276
+ median_cpu_percent: percentile(this.overheadCpuSamples, 0.5),
277
+ p95_cpu_percent: percentile(this.overheadCpuSamples, 0.95),
278
+ max_memory_bytes: Math.max(memory, ...this.overheadMemorySamples),
279
+ measurement: 'forkit-process-tree',
280
+ },
281
+ };
282
+ }
283
+ }
284
+ exports.ActivityMonitor = ActivityMonitor;
285
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1,34 @@
1
+ import type { CensusModel, CensusRuntime, Confidence, RuntimeKind, RuntimeStatus } from '../types';
2
+ export declare function fetchJson(url: string, init: RequestInit, fetchImpl: typeof fetch, timeoutMs?: number): Promise<{
3
+ ok: boolean;
4
+ status: number;
5
+ body: unknown;
6
+ error: string | null;
7
+ }>;
8
+ export declare function createRuntime(input: {
9
+ name: RuntimeKind;
10
+ endpoint: string | null;
11
+ status: RuntimeStatus;
12
+ modelCount: number;
13
+ observedAt: string;
14
+ errorCode?: string | null;
15
+ }): CensusRuntime;
16
+ export declare function createModel(input: {
17
+ name: string;
18
+ runtime: RuntimeKind;
19
+ identityKind: CensusModel['identity_kind'];
20
+ identity: string;
21
+ source: CensusModel['source'];
22
+ confidence: Confidence;
23
+ sizeBytes?: number | null;
24
+ modifiedAt?: string | null;
25
+ quantization?: string | null;
26
+ architecture?: string | null;
27
+ parameterSize?: string | null;
28
+ locationHint?: string | null;
29
+ }): CensusModel;
30
+ export declare function readRecord(value: unknown): Record<string, unknown> | null;
31
+ export declare function readArray(value: unknown): unknown[];
32
+ export declare function readString(value: unknown): string | null;
33
+ export declare function readNumber(value: unknown): number | null;
34
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchJson = fetchJson;
4
+ exports.createRuntime = createRuntime;
5
+ exports.createModel = createModel;
6
+ exports.readRecord = readRecord;
7
+ exports.readArray = readArray;
8
+ exports.readString = readString;
9
+ exports.readNumber = readNumber;
10
+ const hash_1 = require("../hash");
11
+ async function fetchJson(url, init, fetchImpl, timeoutMs = 3000) {
12
+ const controller = new AbortController();
13
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
14
+ try {
15
+ const response = await fetchImpl(url, { ...init, signal: controller.signal });
16
+ let body = null;
17
+ try {
18
+ body = await response.json();
19
+ }
20
+ catch {
21
+ body = null;
22
+ }
23
+ return {
24
+ ok: response.ok,
25
+ status: response.status,
26
+ body,
27
+ error: response.ok ? null : `http_${response.status}`,
28
+ };
29
+ }
30
+ catch (error) {
31
+ const code = error instanceof Error && error.name === 'AbortError'
32
+ ? 'timeout'
33
+ : 'connection_unavailable';
34
+ return { ok: false, status: 0, body: null, error: code };
35
+ }
36
+ finally {
37
+ clearTimeout(timer);
38
+ }
39
+ }
40
+ function createRuntime(input) {
41
+ return {
42
+ runtime_id: (0, hash_1.stableId)('runtime', `${input.name}:${input.endpoint ?? 'local-inventory'}`),
43
+ name: input.name,
44
+ status: input.status,
45
+ endpoint: input.endpoint,
46
+ model_count: input.modelCount,
47
+ observed_at: input.observedAt,
48
+ error_code: input.errorCode ?? null,
49
+ evidence_status: input.status === 'available'
50
+ ? 'online'
51
+ : input.status === 'inventory-only'
52
+ ? 'configured'
53
+ : 'unavailable',
54
+ };
55
+ }
56
+ function createModel(input) {
57
+ return {
58
+ model_id: (0, hash_1.stableId)('model', `${input.runtime}:${input.name}:${input.identity}`),
59
+ name: input.name,
60
+ runtime: input.runtime,
61
+ identity_kind: input.identityKind,
62
+ identity: input.identity,
63
+ size_bytes: input.sizeBytes ?? null,
64
+ modified_at: input.modifiedAt ?? null,
65
+ quantization: input.quantization ?? null,
66
+ architecture: input.architecture ?? null,
67
+ parameter_size: input.parameterSize ?? null,
68
+ source: input.source,
69
+ location_hint: input.locationHint ?? null,
70
+ confidence: input.confidence,
71
+ evidence_status: 'discovered',
72
+ };
73
+ }
74
+ function readRecord(value) {
75
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
76
+ ? value
77
+ : null;
78
+ }
79
+ function readArray(value) {
80
+ return Array.isArray(value) ? value : [];
81
+ }
82
+ function readString(value) {
83
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
84
+ }
85
+ function readNumber(value) {
86
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
87
+ }
88
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1,6 @@
1
+ import type { RuntimeProvider } from '../types';
2
+ export { LMStudioProvider } from './lmstudio';
3
+ export { OllamaProvider } from './ollama';
4
+ export { OpenAICompatibleProvider, configuredOpenAICompatibleProviders } from './openai-compatible';
5
+ export declare function createDefaultProviders(fetchImpl?: typeof fetch): RuntimeProvider[];
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configuredOpenAICompatibleProviders = exports.OpenAICompatibleProvider = exports.OllamaProvider = exports.LMStudioProvider = void 0;
4
+ exports.createDefaultProviders = createDefaultProviders;
5
+ const lmstudio_1 = require("./lmstudio");
6
+ const ollama_1 = require("./ollama");
7
+ const openai_compatible_1 = require("./openai-compatible");
8
+ var lmstudio_2 = require("./lmstudio");
9
+ Object.defineProperty(exports, "LMStudioProvider", { enumerable: true, get: function () { return lmstudio_2.LMStudioProvider; } });
10
+ var ollama_2 = require("./ollama");
11
+ Object.defineProperty(exports, "OllamaProvider", { enumerable: true, get: function () { return ollama_2.OllamaProvider; } });
12
+ var openai_compatible_2 = require("./openai-compatible");
13
+ Object.defineProperty(exports, "OpenAICompatibleProvider", { enumerable: true, get: function () { return openai_compatible_2.OpenAICompatibleProvider; } });
14
+ Object.defineProperty(exports, "configuredOpenAICompatibleProviders", { enumerable: true, get: function () { return openai_compatible_2.configuredOpenAICompatibleProviders; } });
15
+ function createDefaultProviders(fetchImpl = fetch) {
16
+ if (process.env.FORKIT_CENSUS_DISABLE_DEFAULT_RUNTIMES === '1')
17
+ return [];
18
+ return [
19
+ new ollama_1.OllamaProvider('http://localhost:11434', fetchImpl),
20
+ new lmstudio_1.LMStudioProvider('http://localhost:1234', fetchImpl),
21
+ ...(0, openai_compatible_1.configuredOpenAICompatibleProviders)(process.env.FORKIT_CENSUS_OPENAI_ENDPOINTS ?? 'http://localhost:8000', fetchImpl),
22
+ ];
23
+ }
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ import type { RuntimeProvider, RuntimeScanResult } from '../types';
2
+ export declare class LMStudioProvider implements RuntimeProvider {
3
+ private readonly fetchImpl;
4
+ readonly name: "lmstudio";
5
+ private readonly endpoint;
6
+ constructor(endpoint?: string, fetchImpl?: typeof fetch);
7
+ scan(observedAt: string): Promise<RuntimeScanResult>;
8
+ }
9
+ //# sourceMappingURL=lmstudio.d.ts.map
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LMStudioProvider = void 0;
4
+ const endpoints_1 = require("../endpoints");
5
+ const hash_1 = require("../hash");
6
+ const base_1 = require("./base");
7
+ class LMStudioProvider {
8
+ fetchImpl;
9
+ name = 'lmstudio';
10
+ endpoint;
11
+ constructor(endpoint = 'http://localhost:1234', fetchImpl = fetch) {
12
+ this.fetchImpl = fetchImpl;
13
+ const safeEndpoint = (0, endpoints_1.parseLoopbackEndpoint)(endpoint);
14
+ if (!safeEndpoint)
15
+ throw new Error('LM Studio endpoint must be loopback HTTP(S).');
16
+ this.endpoint = safeEndpoint;
17
+ }
18
+ async scan(observedAt) {
19
+ const v0 = await (0, base_1.fetchJson)(`${this.endpoint.url}/api/v0/models`, { method: 'GET' }, this.fetchImpl);
20
+ const result = v0.ok
21
+ ? v0
22
+ : await (0, base_1.fetchJson)(`${this.endpoint.url}/v1/models`, { method: 'GET' }, this.fetchImpl);
23
+ if (!result.ok) {
24
+ return {
25
+ runtime: (0, base_1.createRuntime)({
26
+ name: this.name,
27
+ endpoint: this.endpoint.display,
28
+ status: 'unavailable',
29
+ modelCount: 0,
30
+ observedAt,
31
+ errorCode: result.error,
32
+ }),
33
+ models: [],
34
+ warnings: [],
35
+ };
36
+ }
37
+ const body = (0, base_1.readRecord)(result.body);
38
+ const models = (0, base_1.readArray)(body?.data).flatMap((value) => {
39
+ const entry = (0, base_1.readRecord)(value);
40
+ const name = (0, base_1.readString)(entry?.id);
41
+ if (!name)
42
+ return [];
43
+ return [(0, base_1.createModel)({
44
+ name,
45
+ runtime: this.name,
46
+ identityKind: 'provider-id',
47
+ identity: (0, hash_1.sha256)(`lmstudio:${name}`),
48
+ source: 'runtime-api',
49
+ confidence: 'medium',
50
+ quantization: (0, base_1.readString)(entry?.quantization),
51
+ architecture: (0, base_1.readString)(entry?.arch),
52
+ parameterSize: (0, base_1.readNumber)(entry?.parameter_size) === null
53
+ ? (0, base_1.readString)(entry?.parameter_size)
54
+ : String((0, base_1.readNumber)(entry?.parameter_size)),
55
+ })];
56
+ });
57
+ return {
58
+ runtime: (0, base_1.createRuntime)({
59
+ name: this.name,
60
+ endpoint: this.endpoint.display,
61
+ status: 'available',
62
+ modelCount: models.length,
63
+ observedAt,
64
+ }),
65
+ models,
66
+ warnings: [],
67
+ };
68
+ }
69
+ }
70
+ exports.LMStudioProvider = LMStudioProvider;
71
+ //# sourceMappingURL=lmstudio.js.map
@@ -0,0 +1,12 @@
1
+ import { type RuntimeIdentityVerifier } from '../runtime-identity';
2
+ import type { RuntimeProvider, RuntimeScanResult } from '../types';
3
+ export declare class OllamaProvider implements RuntimeProvider {
4
+ private readonly fetchImpl;
5
+ private readonly verifyIdentity;
6
+ readonly name: "ollama";
7
+ private readonly endpoint;
8
+ private readonly detailsCache;
9
+ constructor(endpoint?: string, fetchImpl?: typeof fetch, verifyIdentity?: RuntimeIdentityVerifier);
10
+ scan(observedAt: string): Promise<RuntimeScanResult>;
11
+ }
12
+ //# sourceMappingURL=ollama.d.ts.map