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,66 @@
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.verifyMacosLoopbackRuntimeIdentity = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_child_process_1 = require("node:child_process");
9
+ const node_util_1 = require("node:util");
10
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
11
+ function exactBasename(value) {
12
+ return node_path_1.default.basename(value.trim()).toLowerCase();
13
+ }
14
+ /**
15
+ * Correlates a loopback listener with an exact executable name. Only the
16
+ * boolean result leaves this adapter; PID and executable path stay ephemeral.
17
+ */
18
+ const verifyMacosLoopbackRuntimeIdentity = async (endpoint, expectedExecutable) => {
19
+ if (process.platform !== 'darwin')
20
+ return false;
21
+ let parsed;
22
+ try {
23
+ parsed = new URL(endpoint);
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ const port = Number(parsed.port || (parsed.protocol === 'https:' ? 443 : 80));
29
+ if (!Number.isSafeInteger(port) || port < 1 || port > 65535)
30
+ return false;
31
+ try {
32
+ const { stdout } = await execFileAsync('lsof', [
33
+ '-nP', `-iTCP:${port}`, '-sTCP:LISTEN', '-Fpc',
34
+ ], {
35
+ encoding: 'utf8',
36
+ maxBuffer: 1_000_000,
37
+ env: { ...process.env, LC_ALL: 'C', LANG: 'C' },
38
+ });
39
+ let currentPid = null;
40
+ const candidates = [];
41
+ for (const line of stdout.split('\n')) {
42
+ if (line.startsWith('p'))
43
+ currentPid = Number(line.slice(1));
44
+ else if (line.startsWith('c') && currentPid !== null
45
+ && exactBasename(line.slice(1)) === expectedExecutable.toLowerCase())
46
+ candidates.push(currentPid);
47
+ }
48
+ for (const pid of candidates) {
49
+ if (!Number.isSafeInteger(pid) || pid < 1)
50
+ continue;
51
+ const { stdout: command } = await execFileAsync('ps', ['-p', String(pid), '-o', 'comm='], {
52
+ encoding: 'utf8',
53
+ maxBuffer: 64_000,
54
+ env: { ...process.env, LC_ALL: 'C', LANG: 'C' },
55
+ });
56
+ if (exactBasename(command) === expectedExecutable.toLowerCase())
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ };
65
+ exports.verifyMacosLoopbackRuntimeIdentity = verifyMacosLoopbackRuntimeIdentity;
66
+ //# sourceMappingURL=runtime-identity.js.map
@@ -0,0 +1,21 @@
1
+ import http from 'node:http';
2
+ import { type LocalDeviceJournal } from './local-device';
3
+ import { ActivityMonitor } from './monitor';
4
+ import type { CensusReport } from './types';
5
+ export interface AiFootprintsServerOptions {
6
+ hostname?: '127.0.0.1';
7
+ port?: number;
8
+ scan?: () => Promise<CensusReport>;
9
+ recordScan?: (generatedAt: string) => Promise<LocalDeviceJournal>;
10
+ monitor?: ActivityMonitor;
11
+ nativeToken?: string | null;
12
+ }
13
+ export interface AiFootprintsServer {
14
+ server: http.Server;
15
+ url: string;
16
+ sessionToken: string;
17
+ monitor: ActivityMonitor;
18
+ close: () => Promise<void>;
19
+ }
20
+ export declare function startAiFootprintsServer(options?: AiFootprintsServerOptions): Promise<AiFootprintsServer>;
21
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1,308 @@
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.startAiFootprintsServer = startAiFootprintsServer;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const node_http_1 = __importDefault(require("node:http"));
9
+ const census_1 = require("./census");
10
+ const agents_1 = require("./agents");
11
+ const share_page_1 = require("./share-page");
12
+ const local_device_1 = require("./local-device");
13
+ const monitor_1 = require("./monitor");
14
+ const providers_1 = require("./providers");
15
+ const runtime_activity_1 = require("./runtime-activity");
16
+ const sharing_1 = require("./sharing");
17
+ const insights_1 = require("./insights");
18
+ const localization_1 = require("./localization");
19
+ function securityHeaders(contentType) {
20
+ return {
21
+ 'cache-control': 'no-store',
22
+ 'content-security-policy': "default-src 'none'; img-src data:; style-src 'unsafe-inline'; script-src 'unsafe-inline'; connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'self'",
23
+ 'content-type': contentType,
24
+ 'referrer-policy': 'no-referrer',
25
+ 'x-content-type-options': 'nosniff',
26
+ 'x-frame-options': 'SAMEORIGIN',
27
+ };
28
+ }
29
+ function sendText(response, status, contentType, body) {
30
+ response.writeHead(status, securityHeaders(contentType));
31
+ response.end(body);
32
+ }
33
+ function sendJson(response, status, value) {
34
+ sendText(response, status, 'application/json; charset=utf-8', JSON.stringify(value));
35
+ }
36
+ async function startAiFootprintsServer(options = {}) {
37
+ const hostname = options.hostname ?? '127.0.0.1';
38
+ const requestedPort = options.port ?? 47811;
39
+ const scan = options.scan ?? (() => (0, census_1.runCensus)());
40
+ const recordScan = options.recordScan ?? ((generatedAt) => (0, local_device_1.recordLocalScan)({ now: () => new Date(generatedAt) }));
41
+ const sessionToken = node_crypto_1.default.randomBytes(24).toString('hex');
42
+ const nativeToken = options.nativeToken ?? process.env.FORKIT_AI_FOOTPRINTS_NATIVE_TOKEN ?? null;
43
+ const runtimeProviders = (0, providers_1.createDefaultProviders)();
44
+ let loadedRuntimeCache = new Set();
45
+ let loadedRuntimeCacheAt = 0;
46
+ const monitor = options.monitor ?? new monitor_1.ActivityMonitor({
47
+ classifyProcesses: async (entries) => {
48
+ const now = Date.now();
49
+ if (now - loadedRuntimeCacheAt >= 3000) {
50
+ loadedRuntimeCache = await (0, runtime_activity_1.loadedRuntimeSignatures)(runtimeProviders, new Date(now).toISOString());
51
+ loadedRuntimeCacheAt = now;
52
+ }
53
+ return [
54
+ ...(0, agents_1.classifyAgentProcessTrees)(entries, process.pid),
55
+ ...(0, runtime_activity_1.classifyLoadedRuntimeProcesses)(entries, loadedRuntimeCache, process.pid),
56
+ ];
57
+ },
58
+ });
59
+ let currentReport = await scan();
60
+ let localDevice = await recordScan(currentReport.generated_at);
61
+ currentReport.privacy.local_state_written = true;
62
+ currentReport.privacy.local_state_scope = 'device-journal-only';
63
+ let scanning = false;
64
+ const streams = new Set();
65
+ let origin = '';
66
+ let closing = null;
67
+ let currentLocale = 'en';
68
+ function browserAuthorized(request) {
69
+ return request.headers.origin === origin
70
+ && request.headers['x-forkit-footprints-session'] === sessionToken;
71
+ }
72
+ function nativeAuthorized(request) {
73
+ return typeof nativeToken === 'string' && nativeToken.length >= 32
74
+ && request.headers['x-forkit-footprints-native'] === nativeToken;
75
+ }
76
+ function stopStreams() {
77
+ for (const stream of streams) {
78
+ clearInterval(stream.timer);
79
+ stream.response.end();
80
+ }
81
+ streams.clear();
82
+ }
83
+ function browserSnapshot(snapshot = monitor.snapshot()) {
84
+ return {
85
+ ...snapshot,
86
+ insights: (0, insights_1.buildLocalInsights)(snapshot, {
87
+ model_record_count: currentReport.summary.model_count,
88
+ confirmed_running_model_count: currentReport.summary.confirmed_running_model_count,
89
+ }, 60, currentLocale).map((insight) => insight.text),
90
+ };
91
+ }
92
+ const server = node_http_1.default.createServer(async (request, response) => {
93
+ const host = request.headers.host ?? '';
94
+ if (!origin || host !== new URL(origin).host) {
95
+ sendText(response, 421, 'text/plain; charset=utf-8', 'Invalid local host.');
96
+ return;
97
+ }
98
+ const requestUrl = new URL(request.url ?? '/', origin);
99
+ const pathname = requestUrl.pathname;
100
+ if (request.method === 'GET' && (pathname === '/' || pathname === '/index.html')) {
101
+ const requestedLocale = requestUrl.searchParams.get('lang');
102
+ currentLocale = requestedLocale === 'en' || requestedLocale === 'de'
103
+ ? requestedLocale
104
+ : (0, localization_1.normalizeLocale)(request.headers['accept-language']);
105
+ sendText(response, 200, 'text/html; charset=utf-8', (0, share_page_1.renderCensusSharePage)(currentReport, {
106
+ localDeviceLabel: localDevice.device_label,
107
+ locale: currentLocale,
108
+ rescan: {
109
+ endpoint: '/api/scan',
110
+ monitor_start_endpoint: '/api/monitor/start',
111
+ monitor_stop_endpoint: '/api/monitor/stop',
112
+ monitor_stream_endpoint: '/api/monitor/stream',
113
+ monitor_clear_endpoint: '/api/monitor/clear',
114
+ contribution_preview_endpoint: '/api/contribution/preview',
115
+ locale_endpoint: '/api/ui/locale',
116
+ session_token: sessionToken,
117
+ },
118
+ }));
119
+ return;
120
+ }
121
+ const browserControl = pathname.startsWith('/api/') && browserAuthorized(request);
122
+ const nativeControl = pathname.startsWith('/api/native/') && nativeAuthorized(request);
123
+ if (request.method === 'POST' && pathname === '/api/monitor/stream') {
124
+ if (!browserControl) {
125
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
126
+ return;
127
+ }
128
+ response.writeHead(200, {
129
+ ...securityHeaders('application/x-ndjson; charset=utf-8'),
130
+ 'content-security-policy': "default-src 'none'",
131
+ });
132
+ const send = () => response.write(`${JSON.stringify(browserSnapshot())}\n`);
133
+ send();
134
+ const timer = setInterval(send, 750);
135
+ timer.unref();
136
+ const stream = { timer, response };
137
+ streams.add(stream);
138
+ request.on('close', () => {
139
+ clearInterval(timer);
140
+ streams.delete(stream);
141
+ });
142
+ return;
143
+ }
144
+ if (request.method === 'POST' && pathname === '/api/scan') {
145
+ if (!browserControl) {
146
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
147
+ return;
148
+ }
149
+ if (scanning) {
150
+ sendJson(response, 409, { error: 'SCAN_IN_PROGRESS' });
151
+ return;
152
+ }
153
+ scanning = true;
154
+ try {
155
+ currentReport = await scan();
156
+ localDevice = await recordScan(currentReport.generated_at);
157
+ currentReport.privacy.local_state_written = true;
158
+ currentReport.privacy.local_state_scope = 'device-journal-only';
159
+ sendJson(response, 200, (0, share_page_1.buildLocalScanView)(currentReport));
160
+ }
161
+ catch {
162
+ sendJson(response, 500, { error: 'LOCAL_SCAN_FAILED' });
163
+ }
164
+ finally {
165
+ scanning = false;
166
+ }
167
+ return;
168
+ }
169
+ const startPath = pathname === '/api/monitor/start' || pathname === '/api/native/start';
170
+ if (request.method === 'POST' && startPath) {
171
+ if (!(browserControl || nativeControl)) {
172
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
173
+ return;
174
+ }
175
+ try {
176
+ const snapshot = await monitor.start();
177
+ sendJson(response, 200, nativeControl ? snapshot : browserSnapshot(snapshot));
178
+ }
179
+ catch {
180
+ sendJson(response, 500, { error: 'MONITOR_START_FAILED' });
181
+ }
182
+ return;
183
+ }
184
+ const stopPath = pathname === '/api/monitor/stop' || pathname === '/api/native/stop';
185
+ if (request.method === 'POST' && stopPath) {
186
+ if (!(browserControl || nativeControl)) {
187
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
188
+ return;
189
+ }
190
+ const snapshot = monitor.stop();
191
+ sendJson(response, 200, nativeControl ? snapshot : browserSnapshot(snapshot));
192
+ return;
193
+ }
194
+ if (request.method === 'POST' && pathname === '/api/monitor/clear') {
195
+ if (!browserControl) {
196
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
197
+ return;
198
+ }
199
+ sendJson(response, 200, browserSnapshot(monitor.clearHistory()));
200
+ return;
201
+ }
202
+ if (request.method === 'POST' && pathname === '/api/ui/locale') {
203
+ if (!browserControl) {
204
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
205
+ return;
206
+ }
207
+ let raw = '';
208
+ for await (const chunk of request) {
209
+ raw += String(chunk);
210
+ if (raw.length > 128) {
211
+ sendJson(response, 413, { error: 'INVALID_LOCALE' });
212
+ return;
213
+ }
214
+ }
215
+ try {
216
+ const value = JSON.parse(raw);
217
+ if (value.locale !== 'en' && value.locale !== 'de')
218
+ throw new Error('INVALID_LOCALE');
219
+ currentLocale = value.locale;
220
+ sendJson(response, 200, { locale: currentLocale });
221
+ }
222
+ catch {
223
+ sendJson(response, 400, { error: 'INVALID_LOCALE' });
224
+ }
225
+ return;
226
+ }
227
+ if (request.method === 'POST' && pathname === '/api/contribution/preview') {
228
+ if (!browserControl) {
229
+ sendJson(response, 403, { error: 'LOCAL_SESSION_REQUIRED' });
230
+ return;
231
+ }
232
+ try {
233
+ sendJson(response, 200, (0, sharing_1.buildAnonymousAiFootprintPreview)(currentReport, monitor.snapshot()));
234
+ }
235
+ catch (error) {
236
+ sendJson(response, 409, { error: error instanceof Error ? error.message : 'CONTRIBUTION_PREVIEW_UNAVAILABLE' });
237
+ }
238
+ return;
239
+ }
240
+ if (request.method === 'POST' && pathname === '/api/native/status') {
241
+ if (!nativeControl) {
242
+ sendJson(response, 403, { error: 'NATIVE_CONTROL_REQUIRED' });
243
+ return;
244
+ }
245
+ sendJson(response, 200, { ...monitor.snapshot(), ui_locale: currentLocale });
246
+ return;
247
+ }
248
+ if (request.method === 'POST' && pathname === '/api/native/quit') {
249
+ if (!nativeControl) {
250
+ sendJson(response, 403, { error: 'NATIVE_CONTROL_REQUIRED' });
251
+ return;
252
+ }
253
+ const summary = monitor.stop();
254
+ sendJson(response, 200, summary);
255
+ setImmediate(() => { void closeService(); });
256
+ return;
257
+ }
258
+ sendText(response, 404, 'text/plain; charset=utf-8', 'Not found.');
259
+ });
260
+ async function listen(port) {
261
+ await new Promise((resolve, reject) => {
262
+ const onError = (error) => {
263
+ server.off('listening', onListening);
264
+ reject(error);
265
+ };
266
+ const onListening = () => {
267
+ server.off('error', onError);
268
+ resolve();
269
+ };
270
+ server.once('error', onError);
271
+ server.once('listening', onListening);
272
+ server.listen(port, hostname);
273
+ });
274
+ }
275
+ try {
276
+ await listen(requestedPort);
277
+ }
278
+ catch (error) {
279
+ if (error.code !== 'EADDRINUSE' || requestedPort === 0)
280
+ throw error;
281
+ await listen(0);
282
+ }
283
+ const address = server.address();
284
+ origin = `http://${hostname}:${address.port}`;
285
+ function closeService() {
286
+ if (closing)
287
+ return closing;
288
+ closing = new Promise((resolve, reject) => {
289
+ monitor.stop();
290
+ stopStreams();
291
+ if (!server.listening) {
292
+ resolve();
293
+ return;
294
+ }
295
+ server.close((error) => error ? reject(error) : resolve());
296
+ server.closeIdleConnections();
297
+ });
298
+ return closing;
299
+ }
300
+ return {
301
+ server,
302
+ url: `${origin}/`,
303
+ sessionToken,
304
+ monitor,
305
+ close: closeService,
306
+ };
307
+ }
308
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1,75 @@
1
+ import type { CensusReport } from './types';
2
+ import { type UiLocale } from './localization';
3
+ export interface CensusShareSnapshot {
4
+ generated_date: string;
5
+ architecture_label: string;
6
+ model_record_count: number;
7
+ verified_runtime_count: number;
8
+ detected_agent_product_count: number;
9
+ detected_agent_process_count: number;
10
+ confirmed_running_model_count: number;
11
+ model_storage_bytes: number;
12
+ model_storage_decimal_display: string;
13
+ model_storage_binary_display: string;
14
+ model_storage_display: string;
15
+ model_storage_file_count: number;
16
+ model_storage_complete: boolean;
17
+ model_storage_measurement: 'recognized-logical-file-bytes';
18
+ external_request_count: 0;
19
+ product_version: string;
20
+ node_major: number;
21
+ }
22
+ export interface CensusLocalDetails {
23
+ agents: Array<{
24
+ name: string;
25
+ kind: string;
26
+ process_count: number;
27
+ }>;
28
+ runtimes: Array<{
29
+ name: string;
30
+ model_count: number;
31
+ loaded_model_count: number;
32
+ }>;
33
+ models: Array<{
34
+ name: string;
35
+ source: string;
36
+ loaded: boolean;
37
+ }>;
38
+ tools: Array<{
39
+ name: string;
40
+ status: 'configured' | 'online';
41
+ }>;
42
+ technical: {
43
+ runtime_probes: Array<{
44
+ name: string;
45
+ state: string;
46
+ error_code: string | null;
47
+ }>;
48
+ warnings: Array<{
49
+ code: string;
50
+ message: string;
51
+ }>;
52
+ };
53
+ }
54
+ export interface LocalScanView extends CensusShareSnapshot {
55
+ local_details: CensusLocalDetails;
56
+ }
57
+ export interface LocalRescanOptions {
58
+ endpoint: string;
59
+ monitor_start_endpoint: string;
60
+ monitor_stop_endpoint: string;
61
+ monitor_stream_endpoint: string;
62
+ monitor_clear_endpoint: string;
63
+ contribution_preview_endpoint: string;
64
+ locale_endpoint: string;
65
+ session_token: string;
66
+ }
67
+ export interface AiFootprintPageOptions {
68
+ rescan?: LocalRescanOptions;
69
+ localDeviceLabel?: string;
70
+ locale?: UiLocale;
71
+ }
72
+ export declare function buildCensusShareSnapshot(report: CensusReport): CensusShareSnapshot;
73
+ export declare function buildLocalScanView(report: CensusReport): LocalScanView;
74
+ export declare function renderCensusSharePage(report: CensusReport, options?: AiFootprintPageOptions): string;
75
+ //# sourceMappingURL=share-page.d.ts.map