forkit-ai-footprints 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PRIVACY.md +12 -8
- package/README.md +17 -18
- package/STATUS.md +10 -9
- package/dist/activity-page.js +9 -4
- package/dist/bootstrap/Forkit AI Footprint.app.zip +0 -0
- package/dist/cli.js +5 -5
- package/dist/global-preview.d.ts +1 -0
- package/dist/global-preview.js +5 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/locales.json +25 -25
- package/dist/localization.js +37 -1
- package/dist/server.js +1 -1
- package/dist/sharing.d.ts +5 -2
- package/dist/sharing.js +7 -4
- package/docs/GLOBAL_DISTRIBUTION.md +3 -3
- package/docs/MACOS_TESTER_GUIDE.md +3 -3
- package/package.json +1 -1
package/PRIVACY.md
CHANGED
|
@@ -61,7 +61,7 @@ AI Footprints may call HTTP(S) endpoints only when the hostname is one of:
|
|
|
61
61
|
- `::1`
|
|
62
62
|
- `www.forkit.dev`, limited to `/api/v1/ai-footprints/challenges` and
|
|
63
63
|
`/api/v1/ai-footprints/contributions` after explicit Preview consent and the
|
|
64
|
-
|
|
64
|
+
ten-minute eligibility gate.
|
|
65
65
|
|
|
66
66
|
Other remote endpoints and endpoints containing embedded credentials are rejected.
|
|
67
67
|
AI Footprints contains no Forkit.dev login, registry-write, passport-publish,
|
|
@@ -98,11 +98,13 @@ generate one App Attest key and store only its opaque key identifier in the
|
|
|
98
98
|
device-only Keychain. The current UI and CLI do not invoke enrollment,
|
|
99
99
|
attestation, assertion generation, or upload.
|
|
100
100
|
|
|
101
|
-
On first launch of the
|
|
102
|
-
anonymous aggregate will be sent after
|
|
103
|
-
when internet is available. The answer and consent version
|
|
104
|
-
in macOS user defaults. A user who chose “Not now” can reopen
|
|
105
|
-
permission from the comparison view. No request is made before
|
|
101
|
+
On first launch of the v3 Preview consent, the native app states that an
|
|
102
|
+
anonymous aggregate will be sent after ten valid observed minutes and refreshed
|
|
103
|
+
at most once per hour when internet is available. The answer and consent version
|
|
104
|
+
are stored locally in macOS user defaults. A user who chose “Not now” can reopen
|
|
105
|
+
the same permission from the comparison view. No request is made before
|
|
106
|
+
permission. Existing v2 consent retains its original one-hour threshold until
|
|
107
|
+
the person upgrades and accepts the v3 notice.
|
|
106
108
|
|
|
107
109
|
## Filesystem identity
|
|
108
110
|
|
|
@@ -144,14 +146,16 @@ used as automatic evidence of ownership, safety, provenance, or passport status.
|
|
|
144
146
|
## Anonymous contribution boundary
|
|
145
147
|
|
|
146
148
|
The local app can create and send an allowlisted schema `2.0` Preview only after
|
|
147
|
-
at least
|
|
149
|
+
at least 600 valid observed seconds and explicit v3 native permission. The Preview
|
|
148
150
|
contains valid seconds, AI-active seconds, activity ratio, supported app count
|
|
149
151
|
and categories, model/loaded/runtime counts, recognized model-file bytes,
|
|
150
152
|
macOS major, architecture, and scanner/runtime schema versions. It excludes
|
|
151
153
|
names, process counts, CPU/RAM values, guess, device identity, local scan ID,
|
|
152
154
|
timestamps, and all item-level records. The native app generates one owner-only
|
|
153
155
|
local Ed25519 key, signs the exact aggregate against a one-time server challenge,
|
|
154
|
-
and stores a small local sync receipt. The
|
|
156
|
+
and stores a small local sync receipt. The first eligible payload may be sent
|
|
157
|
+
immediately; later refreshes are limited to no more than once per hour. The
|
|
158
|
+
server persists only a keyed hash of
|
|
155
159
|
the public contribution identity and one latest aggregate. Community Preview
|
|
156
160
|
signatures prevent undetected payload changes and simple replay; they do not
|
|
157
161
|
prove unique hardware or truthful measurement. Public Preview copy must say
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ git clone https://github.com/arpitasarker01/forkit-ai-footprints.git
|
|
|
67
67
|
cd forkit-ai-footprints
|
|
68
68
|
npm ci
|
|
69
69
|
npm pack
|
|
70
|
-
npm install -g ./forkit-ai-footprints-0.2.
|
|
70
|
+
npm install -g ./forkit-ai-footprints-0.2.6.tgz
|
|
71
71
|
forkit-ai-footprints serve
|
|
72
72
|
```
|
|
73
73
|
|
|
@@ -194,20 +194,19 @@ forkit-ai-footprints scan --no-mcp
|
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
CLI flags cannot bypass the required monitoring session. The local UI enables
|
|
197
|
-
an exact schema `2.0` aggregate preview
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
aggregate after the
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
identifiers.
|
|
197
|
+
an exact schema `2.0` aggregate preview after 600 valid observed seconds; the
|
|
198
|
+
installed app asks with versioned consent whether the anonymous aggregate may
|
|
199
|
+
join the Global AI Preview. When allowed, the app sends one latest signed
|
|
200
|
+
aggregate after the ten-minute eligibility gate and refreshes that same row at
|
|
201
|
+
most once per hour. The server does not count refreshes as new installations.
|
|
202
|
+
The payload excludes app/model names, process counts, CPU/RAM, chat, workspace,
|
|
203
|
+
repository, device, guess, local scan, and account identifiers.
|
|
205
204
|
|
|
206
205
|
### How the community Preview is calculated
|
|
207
206
|
|
|
208
|
-
-
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
- An **active contributor** is an opted-in local installation that has reached
|
|
208
|
+
at least 600 valid observed seconds and successfully submitted a signed
|
|
209
|
+
aggregate. Installing or downloading the package alone does not count.
|
|
211
210
|
- Repeated syncs use the same private local contribution key and replace that
|
|
212
211
|
installation's previous aggregate. They do not increase the participant
|
|
213
212
|
total.
|
|
@@ -217,13 +216,13 @@ identifiers.
|
|
|
217
216
|
than a short observation.
|
|
218
217
|
- npm downloads are reported separately as registry download events. They are
|
|
219
218
|
not unique people, devices, installations, or consenting participants.
|
|
220
|
-
- Percentile placement stays unavailable until at least 30
|
|
221
|
-
|
|
222
|
-
met.
|
|
219
|
+
- Percentile placement stays unavailable until at least 30 contributors with
|
|
220
|
+
one valid observed hour. Regional output stays hidden until its privacy
|
|
221
|
+
threshold is met.
|
|
223
222
|
|
|
224
|
-
The service evaluates Preview eligibility once a minute.
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
The service evaluates Preview eligibility once a minute. The first eligible
|
|
224
|
+
aggregate syncs when internet is available; subsequent submissions are locally
|
|
225
|
+
throttled to no more than one per hour. See [the privacy boundary](./PRIVACY.md)
|
|
227
226
|
for the exact allowlist and exclusions.
|
|
228
227
|
|
|
229
228
|
## Shared core API
|
package/STATUS.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Last updated: 2026-08-29
|
|
4
4
|
|
|
5
|
-
Version: `0.2.
|
|
5
|
+
Version: `0.2.6`
|
|
6
6
|
|
|
7
7
|
Production classification: `current` for Apple Silicon macOS
|
|
8
8
|
|
|
9
|
-
Release state: v0.2.
|
|
9
|
+
Release state: v0.2.6 npm-first community Preview is public. The npm
|
|
10
10
|
bootstrap installs a persistent unsigned local app; Developer ID signing and
|
|
11
11
|
notarization remain future work.
|
|
12
12
|
|
|
@@ -91,9 +91,10 @@ notarization remain future work.
|
|
|
91
91
|
- A schema `2.0` Global AI Preview aggregate based on valid observed seconds and
|
|
92
92
|
AI-active seconds. It excludes names, process counts, paths, commands, chat,
|
|
93
93
|
workspace, device identity, guess, and local scan ID. Review and consent are
|
|
94
|
-
separate. After explicit
|
|
94
|
+
separate. After explicit v3 native permission and ten valid observed minutes,
|
|
95
95
|
the app signs and syncs the allowlisted aggregate to Forkit.dev, keeping one
|
|
96
|
-
latest community-reported Preview row per stable local contribution key
|
|
96
|
+
latest community-reported Preview row per stable local contribution key and
|
|
97
|
+
refreshing it no more than once per hour.
|
|
97
98
|
- A 1080×1080 local share card with Share, Save PNG, Copy Image, and Copy
|
|
98
99
|
Caption controls. It contains only measured totals and supported tool names.
|
|
99
100
|
- A single Forkit.dev `/ai-footprint` page with an honest benchmark-forming
|
|
@@ -124,10 +125,10 @@ notarization remain future work.
|
|
|
124
125
|
valid time and **62.1 seconds** AI-active (ratio **0.981**). The deterministic
|
|
125
126
|
evidence reports the supported app activity share, longest continuous signal,
|
|
126
127
|
and stored local model records without attributing prompts or tasks.
|
|
127
|
-
- A separate earlier real session crossed the
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
- A separate earlier real session crossed the **600 valid-second** active
|
|
129
|
+
contributor gate at **598 AI-active seconds**. Personal percentile ranking
|
|
130
|
+
still requires **3,600 valid seconds** when the community population is large
|
|
131
|
+
enough; contribution itself does not.
|
|
131
132
|
|
|
132
133
|
## Validation completed locally
|
|
133
134
|
|
|
@@ -187,5 +188,5 @@ claim that a cloud model is running locally.
|
|
|
187
188
|
|
|
188
189
|
Future expansion requires representative multi-device field accuracy, Intel Mac
|
|
189
190
|
validation, and Apple signing/notarization. Community Preview contribution is
|
|
190
|
-
open under the
|
|
191
|
+
open under the v3 consent/integrity boundary; verified global ranking remains
|
|
191
192
|
closed until its separate hardware-verification and abuse-control gate passes.
|
package/dist/activity-page.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderActivityApplicationPage = renderActivityApplicationPage;
|
|
4
4
|
const localization_1 = require("./localization");
|
|
5
|
+
const sharing_1 = require("./sharing");
|
|
5
6
|
function escapeHtml(value) {
|
|
6
7
|
return String(value).replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", ''');
|
|
7
8
|
}
|
|
@@ -11,6 +12,10 @@ function renderActivityApplicationPage(input) {
|
|
|
11
12
|
const t = (key, values = {}) => escapeHtml((0, localization_1.uiText)(locale, key, values));
|
|
12
13
|
const config = rescan ?? null;
|
|
13
14
|
const globalUrl = rescan ? 'https://www.forkit.dev/ai-footprint#global-vision' : null;
|
|
15
|
+
const clientCopy = Object.fromEntries(Object.keys(localization_1.UI_COPY).map((copyLocale) => [
|
|
16
|
+
copyLocale,
|
|
17
|
+
Object.fromEntries(Object.keys(localization_1.UI_COPY[copyLocale]).map((key) => [key, (0, localization_1.uiText)(copyLocale, key)])),
|
|
18
|
+
]));
|
|
14
19
|
return `<!doctype html>
|
|
15
20
|
<html lang="${locale}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="light dark"><title>Forkit AI Footprint</title>
|
|
16
21
|
<style>
|
|
@@ -45,13 +50,13 @@ body{font-size:var(--ui-md);line-height:1.45}.brand-copy strong,.inspector-head
|
|
|
45
50
|
<section class="surface metric-rail" aria-label="${t('scorecard')}"><div class="headline"><span class="metric-label">${t('activityRatio')}</span><strong class="metric-value" id="metric-ratio">—</strong><span class="metric-sub" id="metric-active">0s</span></div><div class="headline"><span class="metric-label">${t('activeAiTools')}</span><strong class="metric-value" id="metric-systems">0</strong><span class="metric-sub" id="ratio-label">${t('earlyObservation')}</span></div><div class="headline"><span class="metric-label">${t('localAi')}</span><strong class="metric-value" id="metric-local">${snapshot.model_record_count} · ${snapshot.model_storage_decimal_display}</strong><span class="metric-sub" id="metric-local-running">${snapshot.confirmed_running_model_count} ${t('runningShort')}</span></div></section>
|
|
46
51
|
<section class="workspace"><article class="surface explorer"><div class="panel-head"><div><p class="eyebrow" id="explorer-eyebrow">${t('currentSession')}</p><h1 id="explorer-title">${t('activityExplorer')}</h1><p class="panel-copy" id="explorer-copy">${t('activityExplorerCopy')}</p></div><div class="chart-controls"><div class="resource-modes" aria-label="${t('resourcePulse')}"><button class="active" data-resource-mode="both" type="button">${t('both')}</button><button data-resource-mode="cpu" type="button">${t('cpu')}</button><button data-resource-mode="memory" type="button">${t('memory')}</button></div><button class="icon-button" id="zoom-out" type="button" title="${t('zoomOut')}" aria-label="${t('zoomOut')}">−</button><button class="icon-button" id="zoom-in" type="button" title="${t('zoomIn')}" aria-label="${t('zoomIn')}">+</button><button class="icon-button" id="reset-view" type="button">${t('resetView')}</button></div></div><div class="temporal"><div class="temporal-main"><details class="date-picker" id="date-picker"><summary><span>${t('dateHistory')}</span> <strong id="observation-date">—</strong></summary><div class="date-popover" id="date-options"></div></details><span id="observation-span"></span></div><span id="resource-history-state">${t('resourceCollecting')}</span></div><section class="focus-summary" id="focus-summary" aria-live="polite"><div class="focus-copy"><strong id="focus-title">${t('pulseDetailTitle')}</strong><span id="focus-copy">${t('pulseDetailCopy')}</span></div><div class="focus-stats" id="focus-stats"></div></section><div class="chart-wrap"><div class="system-timeline" id="system-timeline" aria-label="${t('mainChartDescription')}"><div class="timeline-empty">${t('earlyObservationCopy')}</div></div><canvas class="chart-canvas legacy-timeline" id="activity-explorer" tabindex="0" role="img" aria-label="${t('mainChartDescription')}"></canvas><canvas class="navigator" id="activity-navigator" aria-hidden="true"></canvas><div class="chart-tooltip" id="chart-tooltip" hidden></div></div><div class="chart-help"><div class="legend"><span><i class="active"></i>${t('working')}</span><span><i></i>${t('idleTimeLabel')}</span><span><i class="excluded"></i>${t('excluded')}</span></div><span>${t('timelineHelp')}</span></div><section class="below-timeline"><article class="below-card observation-metrics" data-center-view="pulse"><h2>${t('observationMetrics')}</h2><div class="below-metrics"><div class="below-stat"><span>${t('observed')}</span><strong id="below-observed">0s</strong></div><div class="below-stat"><span>${t('aiActive')}</span><strong id="below-active">0s</strong></div><div class="below-stat"><span>${t('activityRatio')}</span><strong id="below-ratio">—</strong></div><div class="below-stat"><span>${t('activityPeriods')}</span><strong id="below-periods">0</strong></div><div class="below-stat"><span>${t('longestActive')}</span><strong id="below-longest">0s</strong></div><div class="below-stat"><span>${t('systems')}</span><strong id="below-systems">0</strong></div></div></article><article class="below-card" data-center-view="runtime"><h2>${t('runtimeFootprint')}</h2><div class="runtime-footprint-list" id="runtime-footprint-list"></div></article><article class="below-card" data-center-view="resources"><h2>${t('liveResourceFootprint')}</h2><div class="resource-summary"><div class="below-stat"><span>${t('cpu')}</span><strong id="below-cpu">—</strong></div><div class="below-stat"><span>${t('memory')}</span><strong id="below-memory">—</strong></div><div class="below-stat"><span>${t('gpu')}</span><strong>${t('notMeasured')}</strong></div><div class="below-stat"><span>${t('resourcePulse')}</span><strong id="resource-history-label">${t('resourceCollecting')}</strong></div></div><h3 class="resource-history-title">${t('resourceHistory')}</h3><div class="resource-history-list" id="center-resource-history"></div><p class="truth-note" id="resource-history-note">${t('resourceCollecting')}</p></article><article class="below-card" data-center-view="apps"><h2>${t('appsDetailTitle')}</h2><div class="center-app-list" id="center-apps-list"></div></article><article class="below-card" data-center-view="pulse"><h2>${t('localAiFootprint')}</h2><div class="local-summary"><div class="below-stat"><span>${t('localRuntimes')}</span><strong id="below-runtimes">0</strong></div><div class="below-stat"><span>${t('modelRecordsShort')}</span><strong id="below-models">${snapshot.model_record_count}</strong></div><div class="below-stat"><span>${t('hostedModelsRunning')}</span><strong id="below-running">${snapshot.confirmed_running_model_count}</strong></div><div class="below-stat"><span>${t('recognizedModelSpace')}</span><strong id="below-space">${snapshot.model_storage_decimal_display}</strong></div></div><p class="statement" id="below-local-insight">${t('localAiNone')}</p></article></section></article>
|
|
47
52
|
<aside class="surface insight-rail"><div class="device-identity"><div><p class="eyebrow">${t('deviceIdentity')}</p><strong>${escapeHtml(device)}</strong></div><span class="observation-number" id="observation-identity">${t('observationIdentity', { number: '—' })}</span></div><nav class="observation-tools" aria-label="${t('observationTools')}"><button class="feature-tool" data-explorer-mode="pulse" data-tip="${t('inspectPulseHint')}" title="${t('inspectPulseHint')}" type="button" aria-pressed="true"><span class="feature-icon" aria-hidden="true">⌁</span><span>${t('pulseView')}</span></button><button class="feature-tool" data-explorer-mode="runtime" data-tip="${t('inspectRuntimeHint')}" title="${t('inspectRuntimeHint')}" type="button" aria-pressed="false"><span class="feature-icon" aria-hidden="true">◷</span><span>${t('runtimeView')}</span></button><button class="feature-tool" data-explorer-mode="resources" data-tip="${t('inspectResourcesHint')}" title="${t('inspectResourcesHint')}" type="button" aria-pressed="false"><span class="feature-icon" aria-hidden="true">◉</span><span>${t('resourcesView')}</span></button><button class="feature-tool" data-explorer-mode="apps" data-tip="${t('inspectAppsHint')}" title="${t('inspectAppsHint')}" type="button" aria-pressed="false"><span class="feature-icon" aria-hidden="true">▦</span><span>${t('appsView')}</span></button></nav><section class="rail-section" data-view="pulse"><div id="inspector-headline"><h2>${t('observationShows')}</h2><p class="insight-copy">${t('selectTimelineBlock')}</p></div><div class="selected-evidence" id="selected-evidence" aria-live="polite">${t('noSelection')}</div><div class="insight-list" id="insight-list"></div></section><section class="rail-section" data-view="runtime"><div class="rail-heading"><strong>${t('observationOverview')}</strong><span>${t('measuredCurrentOnly')}</span></div><div class="observation-grid"><div class="rail-stat"><span>${t('observed')}</span><strong id="rail-observed">0s</strong></div><div class="rail-stat"><span>${t('aiActive')}</span><strong id="rail-active">0s</strong></div><div class="rail-stat"><span>${t('activityRatio')}</span><strong id="rail-ratio">—</strong></div><div class="rail-stat"><span>${t('longestActive')}</span><strong id="rail-longest">0s</strong></div></div></section><section class="rail-section" data-view="resources"><div class="rail-heading"><strong>${t('resourcesNow')}</strong><span>${t('resourceLiveOnly')}</span></div><div class="resource-grid"><div class="rail-stat"><span>${t('cpu')}</span><strong id="rail-cpu">—</strong></div><div class="rail-stat"><span>${t('memory')}</span><strong id="rail-memory">—</strong></div><div class="rail-stat"><span>${t('gpu')}</span><strong>${t('notMeasured')}</strong></div><div class="rail-stat"><span>${t('recognizedModelSpace')}</span><strong id="rail-space">${snapshot.model_storage_decimal_display}</strong></div></div></section><section class="rail-section" data-view="runtime"><div class="rail-heading"><strong>${t('localRuntimes')}</strong><span>${t('localOnly')}</span></div><div class="rail-list" id="rail-runtimes"></div></section><section class="rail-section" data-view="apps"><div class="rail-heading"><strong>${t('appsView')}</strong><span>${t('measuredCurrentOnly')}</span></div><div class="inspector-app-list" id="inspector-apps-list"></div></section><section class="system-mix rail-section"><div class="rail-heading"><strong>${t('aiAppsOnDevice')}</strong></div><p class="insight-copy">${t('focusSystemHelp')}</p><div class="mix-bar" id="mix-bar"></div><div class="mix-list" id="mix-list"></div><div class="system-actions"><button class="button all-apps" id="all-apps" type="button">${t('allApps')}</button><button class="button" id="focus-system" type="button" disabled>${t('focusSystem')}</button></div><div class="app-inspector" id="app-inspector" hidden></div></section></aside></section>
|
|
48
|
-
<section class="surface footprint-strip global-contribution" aria-labelledby="global-status-title"><div class="global-contribution-copy"><p class="eyebrow">${t('globalContribution')} · ${t('notAvailableYet')}</p><strong id="global-status-title">${t('globalNotJoined')}</strong><span id="global-status-copy">${t('globalNotJoinedCopy')}</span><div class="eligibility-meter" role="progressbar" aria-valuemin="0" aria-valuemax="
|
|
53
|
+
<section class="surface footprint-strip global-contribution" aria-labelledby="global-status-title"><div class="global-contribution-copy"><p class="eyebrow">${t('globalContribution')} · ${t('notAvailableYet')}</p><strong id="global-status-title">${t('globalNotJoined')}</strong><span id="global-status-copy">${t('globalNotJoinedCopy')}</span><div class="eligibility-meter" role="progressbar" aria-valuemin="0" aria-valuemax="${sharing_1.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS}" aria-valuenow="0" id="global-progress"><i id="global-progress-fill"></i></div><div class="global-meta"><span id="global-valid-progress">${t('globalValidProgress', { current: '0s', required: '${Math.floor(MINIMUM_GLOBAL_CONTRIBUTION_SECONDS / 60)}m' })}</span><span id="global-last-sync">${t('globalNeverSynced')}</span><span>${t('globalDownloadsNote')}</span></div><span class="scan-status" id="compare-progress"></span><span class="scan-status" id="global-result"></span></div><div class="global-action">${rescan ? `<button class="button" id="global-permission-button" type="button">${t('reviewPermission')}</button><button class="button primary" id="review-payload" type="button">${t('openGlobal')}</button>` : ''}</div><div class="local-strip" hidden><span id="models-found">${snapshot.model_record_count}</span><span id="device-storage">${snapshot.model_storage_decimal_display}</span><span id="models-running">${snapshot.confirmed_running_model_count}</span><span id="hosted-insight">${t('localAiNone')}</span></div></section>
|
|
49
54
|
<div class="monitor-line"><span>${t('monitorOverhead')} · <span id="overhead">${t('warmingUp')}</span> · <span id="overhead-note"></span></span><span>${t('validObservation')} <b id="metric-observed">0s</b> · ${t('longestActive')} <b id="metric-longest">0s</b></span></div>
|
|
50
55
|
<details class="surface advanced"><summary>${t('technical')}</summary><div class="details-grid"><article class="detail-box"><h3>${t('engines')}</h3><ul class="detail-list" id="runtime-list"></ul></article><article class="detail-box"><h3>${t('modelsDevice')}</h3><ul class="detail-list" id="model-list"></ul></article><article class="detail-box"><h3>${t('appsTools')}</h3><ul class="detail-list" id="app-list"></ul></article><article class="detail-box"><h3>${t('measurementBoundary')}</h3><ul class="detail-list"><li><strong>${t('activityMeasurement')}</strong>${t('workingBoundary')}</li><li><strong>${t('loadedModel')}</strong>${t('loadedBoundary')}</li><li><strong>${t('storage')}</strong>${t('storageBoundary')}</li><li><strong>${t('resourcePulse')}</strong>${t('resourceLiveOnly')}</li><li><strong>${t('systems')}</strong><span id="raw-system-count">0</span></li></ul></article></div></details>
|
|
51
56
|
<footer class="footer"><span>${t('localDevice')} · ${t('nothingUploaded')}</span><span>${t('noPrivateFooter')} · v${snapshot.product_version}</span></footer></main>
|
|
52
57
|
<dialog id="share-dialog"><div class="share-layout"><div class="share-preview"><canvas id="share-canvas" width="1080" height="1080"></canvas></div><div class="share-side"><p class="eyebrow">${t('shareTitle')}</p><h2 id="share-heading">${t('shareHeading')}</h2><p>${t('shareFormat')}</p><div class="share-actions"><button class="button primary" id="native-share" type="button">${t('share')}</button><button class="button" id="download-share" type="button">${t('savePng')}</button><button class="button" id="copy-image" type="button">${t('copyImage')}</button><button class="button" id="copy-share" type="button">${t('copyCaption')}</button><button class="button" id="close-share" type="button">${t('close')}</button></div><p class="share-status" id="share-status">${t('sharePrivacy')}</p></div></div></dialog>
|
|
53
58
|
<script>
|
|
54
|
-
const copy=${safeScriptJson(
|
|
59
|
+
const copy=${safeScriptJson(clientCopy)},locale=${safeScriptJson(locale)},config=${safeScriptJson(config)},globalUrl=${safeScriptJson(globalUrl)},shareLogo=${safeScriptJson(shareLogo)},globalContributionMinimumSeconds=${sharing_1.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS};
|
|
55
60
|
let footprint=${safeScriptJson(view ?? snapshot)},monitor={lifecycle:'stopped',observed_seconds:0,active_seconds:0,activity_ratio:null,products:[],timeline:[],resource_history:[],insights:[],presence:{state:'active',observation_eligible:true},overhead:{current_cpu_percent:null,current_memory_bytes:0,history_bytes:0},activity_view:{segments:[],contributions:[],insights:[],systems:[],extent:null,active_block_count:0,longest_active_seconds:0,longest_active_range:null,idle_seconds:0,excluded_seconds:0,simultaneous_systems_max:0,active_tool_count:0,observation_ids:[],continuity_ids:[],available_date_keys:[],current_resources:{cpu_percent:null,memory_bytes:null,process_count:0},resource_history:{buckets:[],systems:[]},resource_history_state:'not-retained'},last_observation:null};
|
|
56
61
|
const $=id=>document.getElementById(id),format=new Intl.NumberFormat(locale),clock=new Intl.DateTimeFormat(locale,{day:'2-digit',month:'short',hour:'2-digit',minute:'2-digit',second:'2-digit'}),fullMoment=new Intl.DateTimeFormat(locale,{dateStyle:'medium',timeStyle:'medium'}),dateLabel=new Intl.DateTimeFormat(locale,{weekday:'short',day:'numeric',month:'short',year:'numeric'}),shareDateLabel=new Intl.DateTimeFormat(locale,{day:'numeric',month:'short',year:'numeric'}),systemPalette=['#00888d','#d98a25','#7758c7','#2e8f68','#c85578','#487bc4','#9b6b37','#637b2f'],colorsKey='forkit-footprints-colors-v1',lastSummaryKey='forkit-footprints-last-summary-v1';
|
|
57
62
|
function text(key,values={}){let value=copy[locale][key]||key;for(const [name,replacement] of Object.entries(values))value=value.split('{'+name+'}').join(String(replacement));return value}
|
|
@@ -83,8 +88,8 @@ function renderMix(){const bar=$('mix-bar'),listNode=$('mix-list'),view=viewForD
|
|
|
83
88
|
function renderHostedLocal(){const products=monitor.products||[],workingLocal=products.filter(product=>product.kind==='local-model-runtime'&&product.state==='working-now'),running=footprint.confirmed_running_model_count||0;$('models-found').textContent=format.format(footprint.model_record_count||0);$('models-running').textContent=format.format(running);$('device-storage').textContent=bytes(footprint.model_storage_bytes||0);$('metric-local').textContent=format.format(footprint.model_record_count||0)+' · '+bytes(footprint.model_storage_bytes||0);$('metric-local-running').textContent=format.format(running)+' '+text('runningShort');$('hosted-insight').textContent=running>0||workingLocal.length?text('hostedModelsRunningInsight'):text('localAiNone')}
|
|
84
89
|
function renderRuntimes(){const container=$('rail-runtimes');container.replaceChildren();for(const runtime of footprint.local_details?.runtimes||[]){const row=document.createElement('button'),name=document.createElement('strong'),status=document.createElement('span');row.type='button';row.className='runtime-item';row.title=text('inspectRuntimeHint');name.textContent=runtime.name;status.textContent=runtime.loaded_model_count?text('modelsLoaded',{count:runtime.loaded_model_count,models:runtime.loaded_model_count===1?text('model'):text('models')}):text('verifiedAvailable');row.append(name,status);row.addEventListener('click',()=>setExplorerMode('runtime'));container.append(row)}if(!container.children.length){const note=document.createElement('div');note.className='early';note.textContent='—';container.append(note)}}function renderDetails(){if(!footprint.local_details)return;const details=footprint.local_details,runtimeList=$('runtime-list'),modelList=$('model-list'),appList=$('app-list');for(const node of [runtimeList,modelList,appList])node.replaceChildren();for(const runtime of details.runtimes)add(runtimeList,runtime.name,runtime.loaded_model_count?text('modelsLoaded',{count:runtime.loaded_model_count,models:runtime.loaded_model_count===1?text('model'):text('models')}):text('verifiedAvailable'));for(const model of details.models.filter(item=>item.loaded))add(modelList,model.name,text('loaded',{count:''}).trim());for(const product of monitor.products||[]){const note=[text(product.state==='working-now'?'working':'openIdleLegend'),format.format(product.process_count)+' '+text(product.process_count===1?'measuredProcess':'measuredProcesses'),product.memory_bytes?bytes(product.memory_bytes):''].filter(Boolean).join(' · ');add(appList,product.name,note)}if(!appList.children.length)for(const agent of details.agents)add(appList,agent.name,text('processActivity'));if($('raw-system-count'))$('raw-system-count').textContent=format.format((monitor.products||[]).length);renderRuntimes()}
|
|
85
90
|
function saveLastSummary(){if(!monitor.observed_seconds)return;const dominant=dominantProduct();try{localStorage.setItem(lastSummaryKey,JSON.stringify({activity_ratio:monitor.activity_ratio,active_tool:dominant?.name||null,local_models_found:footprint.model_record_count||0,local_models_running:footprint.confirmed_running_model_count||0}))}catch{}}
|
|
86
|
-
function renderMonitor(){const products=monitor.products||[],working=userFacingProducts().filter(product=>product.state==='working-now'),presence=monitor.presence||{state:'active',observation_eligible:true},status=$('monitor-status');status.className='status';let statusText;if(monitor.lifecycle==='stopped'){status.classList.add('stopped');statusText=text('stopped')}else if(!presence.observation_eligible){status.classList.add('paused');statusText=text('paused')}else if(working.length)statusText=text('menuWorking',{count:working.length});else statusText=text('menuMonitoring');$('monitor-status-text').textContent=statusText;if($('monitor-button'))$('monitor-button').textContent=monitor.lifecycle==='monitoring'?text('stopMonitoring'):monitor.observed_seconds?text('startMonitoringAgain'):text('startMonitoring');appendResourceSample();renderDates();const view=currentView()||{segments:[],contributions:[],systems:[],insights:[],longest_active_seconds:0},totals=selectedDateKey||focusedSystemSignature?viewTotals(view):{active:monitor.active_seconds,observed:monitor.observed_seconds,ratio:monitor.activity_ratio},resources=aggregateResources(products),historical=selectedDateKey&&selectedDateKey!==localDateKey(monitor.activity_view?.extent?.end_ms||Date.now()),live=!historical&&monitor.lifecycle==='monitoring',dominant=dominantProduct();if(dominant)document.documentElement.style.setProperty('--accent-system',systemColor(dominant));$('metric-ratio').textContent=pct(totals.ratio);$('ratio-label').textContent=totals.observed<60?text('earlyObservation'):totals.ratio>=.7?text('mostlyActive'):totals.ratio<=.3?text('mostlyIdle'):text('mixedActivity');$('metric-active').textContent=seconds(totals.active);$('metric-observed').textContent=seconds(totals.observed);$('metric-systems').textContent=format.format((view.systems||[]).filter(system=>system.active_seconds>0||system.state==='working-now').length);$('metric-longest').textContent=seconds(view.longest_active_seconds||0);$('observation-identity').textContent=text('observationIdentity',{number:monitor.observation_id??'—'});$('rail-observed').textContent=seconds(totals.observed);$('rail-active').textContent=seconds(totals.active);$('rail-ratio').textContent=pct(totals.ratio);$('rail-longest').textContent=seconds(view.longest_active_seconds||0);$('rail-cpu').textContent=live&&Number.isFinite(resources.cpu)?format.format(Number(resources.cpu.toFixed(1)))+'%':'—';$('rail-memory').textContent=live&&Number.isFinite(resources.memory)?bytes(resources.memory):'—';$('rail-space').textContent=bytes(footprint.model_storage_bytes||0);explorer.setData(view);renderInsights();renderMix();renderHostedLocal();renderDetails();renderInspector();renderFocusSummary();renderSystemTimeline();renderInspectorApps();renderBelowSummary();if($('overhead')){$('overhead').textContent=monitor.overhead?.current_cpu_percent===null?text('warmingUp'):format.format(Number(monitor.overhead.current_cpu_percent.toFixed(1)))+'% CPU';$('overhead-note').textContent=bytes(monitor.overhead?.current_memory_bytes||0)+' RAM'}if($('review-payload')){const eligible=monitor.observed_seconds>=
|
|
87
|
-
function renderGlobalContribution(){if(!$('global-status-title'))return;const observed=Math.max(0,Number(monitor.observed_seconds)||0),eligible=observed>=
|
|
91
|
+
function renderMonitor(){const products=monitor.products||[],working=userFacingProducts().filter(product=>product.state==='working-now'),presence=monitor.presence||{state:'active',observation_eligible:true},status=$('monitor-status');status.className='status';let statusText;if(monitor.lifecycle==='stopped'){status.classList.add('stopped');statusText=text('stopped')}else if(!presence.observation_eligible){status.classList.add('paused');statusText=text('paused')}else if(working.length)statusText=text('menuWorking',{count:working.length});else statusText=text('menuMonitoring');$('monitor-status-text').textContent=statusText;if($('monitor-button'))$('monitor-button').textContent=monitor.lifecycle==='monitoring'?text('stopMonitoring'):monitor.observed_seconds?text('startMonitoringAgain'):text('startMonitoring');appendResourceSample();renderDates();const view=currentView()||{segments:[],contributions:[],systems:[],insights:[],longest_active_seconds:0},totals=selectedDateKey||focusedSystemSignature?viewTotals(view):{active:monitor.active_seconds,observed:monitor.observed_seconds,ratio:monitor.activity_ratio},resources=aggregateResources(products),historical=selectedDateKey&&selectedDateKey!==localDateKey(monitor.activity_view?.extent?.end_ms||Date.now()),live=!historical&&monitor.lifecycle==='monitoring',dominant=dominantProduct();if(dominant)document.documentElement.style.setProperty('--accent-system',systemColor(dominant));$('metric-ratio').textContent=pct(totals.ratio);$('ratio-label').textContent=totals.observed<60?text('earlyObservation'):totals.ratio>=.7?text('mostlyActive'):totals.ratio<=.3?text('mostlyIdle'):text('mixedActivity');$('metric-active').textContent=seconds(totals.active);$('metric-observed').textContent=seconds(totals.observed);$('metric-systems').textContent=format.format((view.systems||[]).filter(system=>system.active_seconds>0||system.state==='working-now').length);$('metric-longest').textContent=seconds(view.longest_active_seconds||0);$('observation-identity').textContent=text('observationIdentity',{number:monitor.observation_id??'—'});$('rail-observed').textContent=seconds(totals.observed);$('rail-active').textContent=seconds(totals.active);$('rail-ratio').textContent=pct(totals.ratio);$('rail-longest').textContent=seconds(view.longest_active_seconds||0);$('rail-cpu').textContent=live&&Number.isFinite(resources.cpu)?format.format(Number(resources.cpu.toFixed(1)))+'%':'—';$('rail-memory').textContent=live&&Number.isFinite(resources.memory)?bytes(resources.memory):'—';$('rail-space').textContent=bytes(footprint.model_storage_bytes||0);explorer.setData(view);renderInsights();renderMix();renderHostedLocal();renderDetails();renderInspector();renderFocusSummary();renderSystemTimeline();renderInspectorApps();renderBelowSummary();if($('overhead')){$('overhead').textContent=monitor.overhead?.current_cpu_percent===null?text('warmingUp'):format.format(Number(monitor.overhead.current_cpu_percent.toFixed(1)))+'% CPU';$('overhead-note').textContent=bytes(monitor.overhead?.current_memory_bytes||0)+' RAM'}if($('review-payload')){const eligible=monitor.observed_seconds>=globalContributionMinimumSeconds;$('review-payload').disabled=!eligible;$('compare-progress').textContent=eligible?'':text('globalProgress',{remaining:seconds(Math.max(0,globalContributionMinimumSeconds-monitor.observed_seconds))});const preview=monitor.global_preview;$('global-result').textContent=preview?.state==='contributed'?text('previewContributed'):preview?.state==='unavailable'?text('previewUnavailable'):monitor.global_permission==='granted'?text('previewWaiting'):text('permissionNeeded')}saveLastSummary()}
|
|
92
|
+
function renderGlobalContribution(){if(!$('global-status-title'))return;const observed=Math.max(0,Number(monitor.observed_seconds)||0),eligible=observed>=globalContributionMinimumSeconds,permission=monitor.global_permission==='granted',preview=monitor.global_preview||{},progress=Math.min(100,(observed/globalContributionMinimumSeconds)*100),lastSuccess=preview.last_success_at?new Date(preview.last_success_at):null;let title,copyText;if(!permission){title=text('globalNotJoined');copyText=text('globalNotJoinedCopy')}else if(preview.state==='contributed'){title=text('globalQualified');copyText=text('globalQualifiedCopy')}else if(preview.state==='unavailable'){title=eligible?text('globalRetry'):text('globalBuilding');copyText=eligible?text('globalRetryCopy'):text('globalBuildingCopy')}else if(eligible){title=text('globalSyncing');copyText=text('globalSyncingCopy')}else{title=text('globalBuilding');copyText=text('globalBuildingCopy')}$('global-status-title').textContent=title;$('global-status-copy').textContent=copyText;$('global-progress').setAttribute('aria-valuenow',String(Math.min(globalContributionMinimumSeconds,Math.round(observed))));$('global-progress-fill').style.width=progress+'%';$('global-valid-progress').textContent=text('globalValidProgress',{current:seconds(Math.min(observed,globalContributionMinimumSeconds)),required:seconds(globalContributionMinimumSeconds)});$('global-last-sync').textContent=lastSuccess&&!Number.isNaN(lastSuccess.getTime())?text('globalLastSync',{time:shareDateLabel.format(lastSuccess)+' '+clock.format(lastSuccess)}):text('globalNeverSynced');$('compare-progress').textContent=permission&&!eligible?text('globalProgress',{remaining:seconds(Math.max(0,globalContributionMinimumSeconds-observed))}):'';$('global-result').textContent=preview.state==='contributed'?text('previewContributed'):preview.state==='unavailable'?text('previewUnavailable'):permission?text('previewWaiting'):text('permissionNeeded')}
|
|
88
93
|
const renderMonitorContributionBase=renderMonitor;renderMonitor=function(){renderMonitorContributionBase();renderGlobalContribution()}
|
|
89
94
|
const renderGlobalContributionAccessBase=renderGlobalContribution;renderGlobalContribution=function(){renderGlobalContributionAccessBase();if($('review-payload'))$('review-payload').disabled=false;const last=monitor.global_preview?.last_success_at?new Date(monitor.global_preview.last_success_at):null;if(last&&!Number.isNaN(last.getTime()))$('global-last-sync').textContent=text('globalLastSync',{time:fullMoment.format(last)})}
|
|
90
95
|
function shareObservationWindow(){const extent=monitor.activity_view?.extent;if(!extent)return text('shareMeasuredLocally');const start=new Date(extent.start_ms),end=new Date(Math.max(extent.start_ms,extent.end_ms-1));return shareDateLabel.format(start)+' '+clock.format(start)+' – '+shareDateLabel.format(end)+' '+clock.format(end)}
|
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ Options:
|
|
|
40
40
|
--verbose Show detector and identity details
|
|
41
41
|
--guess <count> Compare your estimate with discovered models
|
|
42
42
|
--copy Copy the rendered local result to the clipboard
|
|
43
|
-
--anonymous-payload Reserved for a completed
|
|
43
|
+
--anonymous-payload Reserved for a completed ten-minute monitor session
|
|
44
44
|
--consent-share Prepare an aggregate payload; native-app consent controls Preview sync
|
|
45
45
|
--output <file> Save the selected human or JSON report
|
|
46
46
|
--model-dir <path> Inspect an explicit model directory; repeatable
|
|
@@ -58,7 +58,7 @@ Privacy:
|
|
|
58
58
|
AI Footprints reads metadata only. It does not read model bytes or retain raw
|
|
59
59
|
process commands or MCP configuration values. It does not write to any passport,
|
|
60
60
|
registry, or Runtime_C2 service. The installed app may sync only the allowlisted anonymous
|
|
61
|
-
Global AI Preview aggregate after explicit
|
|
61
|
+
Global AI Preview aggregate after explicit v3 consent and ten valid minutes.
|
|
62
62
|
`;
|
|
63
63
|
function parseArgs(args) {
|
|
64
64
|
let command = 'install';
|
|
@@ -355,7 +355,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
355
355
|
}
|
|
356
356
|
if (options.command === 'install') {
|
|
357
357
|
const destination = await installPersistentMacApp();
|
|
358
|
-
process.stdout.write(`Forkit AI Footprint is installed at ${destination}\nOpen it later from Applications or Spotlight; Terminal is no longer required.\nOn first launch, Forkit asks whether an aggregate-only measurement may be contributed to the Global AI Preview after
|
|
358
|
+
process.stdout.write(`Forkit AI Footprint is installed at ${destination}\nOpen it later from Applications or Spotlight; Terminal is no longer required.\nOn first launch, Forkit asks whether an aggregate-only measurement may be contributed to the Global AI Preview after ten valid observed minutes. Nothing is sent unless the person explicitly agrees.\n`);
|
|
359
359
|
return 0;
|
|
360
360
|
}
|
|
361
361
|
if (options.command === 'serve') {
|
|
@@ -387,7 +387,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
387
387
|
: `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`;
|
|
388
388
|
await emit(rendered, options.output);
|
|
389
389
|
if (options.anonymousPayload) {
|
|
390
|
-
process.stderr.write('Anonymous preview requires a completed
|
|
390
|
+
process.stderr.write('Anonymous preview requires a completed ten-minute GUI session with the exact payload reviewed first. Nothing was uploaded.\n');
|
|
391
391
|
return 2;
|
|
392
392
|
}
|
|
393
393
|
return 0;
|
|
@@ -464,7 +464,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
464
464
|
}
|
|
465
465
|
if (options.anonymousPayload) {
|
|
466
466
|
process.stderr.write(options.shareConsent
|
|
467
|
-
? 'Anonymous contribution was not prepared: a valid
|
|
467
|
+
? 'Anonymous contribution was not prepared: a valid ten-minute monitor session and exact payload review are required. Nothing was uploaded.\n'
|
|
468
468
|
: 'Anonymous contribution was not prepared: separate --consent-share is required. Nothing was uploaded.\n');
|
|
469
469
|
return 2;
|
|
470
470
|
}
|
package/dist/global-preview.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AnonymousAiFootprintContribution } from './sharing';
|
|
2
2
|
export declare const GLOBAL_PREVIEW_ENDPOINT = "https://www.forkit.dev/api/v1/ai-footprints";
|
|
3
|
+
/** The first eligible aggregate syncs immediately; later refreshes are hourly. */
|
|
3
4
|
export declare const GLOBAL_PREVIEW_SYNC_INTERVAL_MS: number;
|
|
4
5
|
export interface GlobalPreviewStatus {
|
|
5
6
|
state: 'disabled' | 'waiting' | 'syncing' | 'contributed' | 'unavailable';
|
package/dist/global-preview.js
CHANGED
|
@@ -9,7 +9,8 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const local_device_1 = require("./local-device");
|
|
11
11
|
exports.GLOBAL_PREVIEW_ENDPOINT = 'https://www.forkit.dev/api/v1/ai-footprints';
|
|
12
|
-
|
|
12
|
+
/** The first eligible aggregate syncs immediately; later refreshes are hourly. */
|
|
13
|
+
exports.GLOBAL_PREVIEW_SYNC_INTERVAL_MS = 60 * 60 * 1000;
|
|
13
14
|
function base64url(value) {
|
|
14
15
|
return value.toString('base64url');
|
|
15
16
|
}
|
|
@@ -144,7 +145,9 @@ class GlobalPreviewContributor {
|
|
|
144
145
|
const now = this.now();
|
|
145
146
|
const lastAttempt = this.currentStatus.last_attempt_at ? Date.parse(this.currentStatus.last_attempt_at) : 0;
|
|
146
147
|
const observedSeconds = contribution.observation.valid_seconds;
|
|
147
|
-
|
|
148
|
+
// A new contributor is sent immediately. Once an attempt has been made,
|
|
149
|
+
// persist the hourly cadence across reconnects and browser restarts.
|
|
150
|
+
if (lastAttempt && now.getTime() - lastAttempt < this.minimumSyncIntervalMs) {
|
|
148
151
|
return { ...this.currentStatus };
|
|
149
152
|
}
|
|
150
153
|
this.currentStatus = { ...this.currentStatus, state: 'syncing', last_attempt_at: now.toISOString(), last_error: null };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { detectAgentProducts, listSystemProcesses } from './agents';
|
|
2
2
|
export { aggregateMacosFieldEvaluationDirectory, aggregateMacosFieldEvaluations } from './aggregate';
|
|
3
3
|
export { runCensus } from './census';
|
|
4
|
-
export { authorizeAnonymousAiFootprintContribution, buildAnonymousAiFootprintPreview, MINIMUM_COMPARISON_SECONDS } from './sharing';
|
|
4
|
+
export { authorizeAnonymousAiFootprintContribution, buildAnonymousAiFootprintPreview, MINIMUM_COMPARISON_SECONDS, MINIMUM_GLOBAL_CONTRIBUTION_SECONDS } from './sharing';
|
|
5
5
|
export { GlobalPreviewContributor, GLOBAL_PREVIEW_ENDPOINT, GLOBAL_PREVIEW_SYNC_INTERVAL_MS } from './global-preview';
|
|
6
6
|
export type { GlobalPreviewContributorOptions, GlobalPreviewStatus } from './global-preview';
|
|
7
7
|
export { ActivityMonitor } from './monitor';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.evaluateMacosFieldTruthFile = exports.evaluateMacosFieldTruth = exports.detectMacosMajorVersion = exports.formatDoctorReport = exports.formatCensusReport = exports.scanFilesystemModels = exports.parseLoopbackEndpointList = exports.parseLoopbackEndpoint = exports.runDoctor = exports.detectMcpConfigs = exports.detectAiTools = exports.startAiFootprintsServer = exports.buildLocalInsights = exports.renderCensusSharePage = exports.buildCensusShareSnapshot = exports.ActivityMonitor = exports.GLOBAL_PREVIEW_SYNC_INTERVAL_MS = exports.GLOBAL_PREVIEW_ENDPOINT = exports.GlobalPreviewContributor = exports.MINIMUM_COMPARISON_SECONDS = exports.buildAnonymousAiFootprintPreview = exports.authorizeAnonymousAiFootprintContribution = exports.runCensus = exports.aggregateMacosFieldEvaluations = exports.aggregateMacosFieldEvaluationDirectory = exports.listSystemProcesses = exports.detectAgentProducts = void 0;
|
|
17
|
+
exports.evaluateMacosFieldTruthFile = exports.evaluateMacosFieldTruth = exports.detectMacosMajorVersion = exports.formatDoctorReport = exports.formatCensusReport = exports.scanFilesystemModels = exports.parseLoopbackEndpointList = exports.parseLoopbackEndpoint = exports.runDoctor = exports.detectMcpConfigs = exports.detectAiTools = exports.startAiFootprintsServer = exports.buildLocalInsights = exports.renderCensusSharePage = exports.buildCensusShareSnapshot = exports.ActivityMonitor = exports.GLOBAL_PREVIEW_SYNC_INTERVAL_MS = exports.GLOBAL_PREVIEW_ENDPOINT = exports.GlobalPreviewContributor = exports.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS = exports.MINIMUM_COMPARISON_SECONDS = exports.buildAnonymousAiFootprintPreview = exports.authorizeAnonymousAiFootprintContribution = exports.runCensus = exports.aggregateMacosFieldEvaluations = exports.aggregateMacosFieldEvaluationDirectory = exports.listSystemProcesses = exports.detectAgentProducts = void 0;
|
|
18
18
|
var agents_1 = require("./agents");
|
|
19
19
|
Object.defineProperty(exports, "detectAgentProducts", { enumerable: true, get: function () { return agents_1.detectAgentProducts; } });
|
|
20
20
|
Object.defineProperty(exports, "listSystemProcesses", { enumerable: true, get: function () { return agents_1.listSystemProcesses; } });
|
|
@@ -27,6 +27,7 @@ var sharing_1 = require("./sharing");
|
|
|
27
27
|
Object.defineProperty(exports, "authorizeAnonymousAiFootprintContribution", { enumerable: true, get: function () { return sharing_1.authorizeAnonymousAiFootprintContribution; } });
|
|
28
28
|
Object.defineProperty(exports, "buildAnonymousAiFootprintPreview", { enumerable: true, get: function () { return sharing_1.buildAnonymousAiFootprintPreview; } });
|
|
29
29
|
Object.defineProperty(exports, "MINIMUM_COMPARISON_SECONDS", { enumerable: true, get: function () { return sharing_1.MINIMUM_COMPARISON_SECONDS; } });
|
|
30
|
+
Object.defineProperty(exports, "MINIMUM_GLOBAL_CONTRIBUTION_SECONDS", { enumerable: true, get: function () { return sharing_1.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS; } });
|
|
30
31
|
var global_preview_1 = require("./global-preview");
|
|
31
32
|
Object.defineProperty(exports, "GlobalPreviewContributor", { enumerable: true, get: function () { return global_preview_1.GlobalPreviewContributor; } });
|
|
32
33
|
Object.defineProperty(exports, "GLOBAL_PREVIEW_ENDPOINT", { enumerable: true, get: function () { return global_preview_1.GLOBAL_PREVIEW_ENDPOINT; } });
|
package/dist/locales.json
CHANGED
|
@@ -231,36 +231,36 @@
|
|
|
231
231
|
"optionalComparison": "Compare globally",
|
|
232
232
|
"comparisonQuestion": "Is this unusually high?",
|
|
233
233
|
"comparisonCopy": "Compare this device observation with qualified, consented Forkit observations.",
|
|
234
|
-
"globalProgress": "{remaining} of valid observed time until this device
|
|
234
|
+
"globalProgress": "{remaining} of valid observed time until this device joins the community.",
|
|
235
235
|
"seeGlobal": "See global position",
|
|
236
236
|
"reviewSharing": "Review sharing choice",
|
|
237
237
|
"payloadIntro": "This is the complete aggregate eligible for the Global AI Preview:",
|
|
238
238
|
"allowGlobal": "Allow Preview contribution",
|
|
239
239
|
"benchmarkForming": "Global AI Preview is forming from consented anonymous aggregates.",
|
|
240
240
|
"permissionNeeded": "Global contribution is off. The local Footprint still works and nothing is uploaded.",
|
|
241
|
-
"permissionGranted": "Global contribution is on. After
|
|
241
|
+
"permissionGranted": "Global contribution is on. After 10 valid minutes, the anonymous aggregate syncs when internet is available, then refreshes at most once an hour.",
|
|
242
242
|
"permissionDeclined": "Global contribution stays off. The local Footprint still works.",
|
|
243
243
|
"syncObservation": "Local signal",
|
|
244
244
|
"syncPermission": "Permission",
|
|
245
245
|
"syncVerified": "Preview sync",
|
|
246
|
-
"previewWaiting": "Building
|
|
246
|
+
"previewWaiting": "Building the first 10 valid minutes",
|
|
247
247
|
"previewContributed": "Counted in the Global AI Preview",
|
|
248
248
|
"previewUnavailable": "Sync will retry when internet is available",
|
|
249
249
|
"globalContribution": "Global contribution",
|
|
250
250
|
"globalNotJoined": "Not contributing",
|
|
251
251
|
"globalNotJoinedCopy": "Join only if you want this device’s anonymous totals included.",
|
|
252
|
-
"globalBuilding": "
|
|
253
|
-
"globalBuildingCopy": "This device needs
|
|
254
|
-
"globalSyncing": "
|
|
252
|
+
"globalBuilding": "Preparing this device’s contribution",
|
|
253
|
+
"globalBuildingCopy": "This device needs 10 valid observed minutes before its first anonymous sync.",
|
|
254
|
+
"globalSyncing": "Active contributor · sync pending",
|
|
255
255
|
"globalSyncingCopy": "The aggregate is ready and will sync when internet is available.",
|
|
256
|
-
"globalQualified": "
|
|
257
|
-
"globalQualifiedCopy": "This installation is counted as one
|
|
258
|
-
"globalRetry": "
|
|
259
|
-
"globalRetryCopy": "The saved aggregate
|
|
256
|
+
"globalQualified": "Active in the Preview",
|
|
257
|
+
"globalQualifiedCopy": "This installation is counted as one active contributor and refreshes at most once an hour.",
|
|
258
|
+
"globalRetry": "Active contributor · connection retrying",
|
|
259
|
+
"globalRetryCopy": "The saved aggregate retries at the next hourly refresh when internet is available.",
|
|
260
260
|
"globalValidProgress": "{current} of {required} valid time",
|
|
261
261
|
"globalLastSync": "Last synced {time}",
|
|
262
262
|
"globalNeverSynced": "Not synced yet",
|
|
263
|
-
"globalDownloadsNote": "
|
|
263
|
+
"globalDownloadsNote": "NPM download events show reach; they are not active contributors.",
|
|
264
264
|
"reviewPermission": "Sharing choice",
|
|
265
265
|
"permissionNativeOnly": "Open the installed Forkit app to change global contribution permission.",
|
|
266
266
|
"technical": "Advanced details",
|
|
@@ -361,7 +361,7 @@
|
|
|
361
361
|
"fatalStopped": "The local service stopped unexpectedly. No monitoring remains active.",
|
|
362
362
|
"quit": "Quit",
|
|
363
363
|
"globalPermissionTitle": "Join the Global AI Preview?",
|
|
364
|
-
"globalPermissionBody": "After
|
|
364
|
+
"globalPermissionBody": "After 10 valid observed minutes, Forkit sends one anonymous aggregate and refreshes it at most once per hour when internet is available. It includes observed and AI-active time, supported app categories, local model counts and storage, and system/version fields. A random local contribution key prevents duplicate counting. It excludes chat titles, projects, paths, prompts, commands, account details, and the local device name. Community Preview data is not hardware-verified.",
|
|
365
365
|
"globalPermissionAllow": "Join Preview",
|
|
366
366
|
"globalPermissionNotNow": "Not now",
|
|
367
367
|
"personalPattern": "Device pattern",
|
|
@@ -611,36 +611,36 @@
|
|
|
611
611
|
"optionalComparison": "Global vergleichen",
|
|
612
612
|
"comparisonQuestion": "Ist das ungewöhnlich hoch?",
|
|
613
613
|
"comparisonCopy": "Vergleichen Sie diese Gerätebeobachtung mit qualifizierten, freigegebenen Forkit-Beobachtungen.",
|
|
614
|
-
"globalProgress": "Noch {remaining} gültige Beobachtungszeit bis zur
|
|
614
|
+
"globalProgress": "Noch {remaining} gültige Beobachtungszeit, bis dieses Gerät zur Community beiträgt.",
|
|
615
615
|
"seeGlobal": "Globale Position ansehen",
|
|
616
616
|
"reviewSharing": "Freigabe prüfen",
|
|
617
617
|
"payloadIntro": "Dies ist das vollständige Aggregat für die Global AI Preview:",
|
|
618
618
|
"allowGlobal": "Preview-Beitrag erlauben",
|
|
619
619
|
"benchmarkForming": "Die Global AI Preview entsteht aus freigegebenen anonymen Aggregaten.",
|
|
620
620
|
"permissionNeeded": "Der globale Beitrag ist aus. Der lokale Footprint funktioniert weiter und nichts wird hochgeladen.",
|
|
621
|
-
"permissionGranted": "Der globale Beitrag ist an. Nach
|
|
621
|
+
"permissionGranted": "Der globale Beitrag ist an. Nach 10 gültigen Minuten wird das anonyme Aggregat bei verfügbarer Internetverbindung synchronisiert und danach höchstens stündlich aktualisiert.",
|
|
622
622
|
"permissionDeclined": "Der globale Beitrag bleibt aus. Der lokale Footprint funktioniert weiter.",
|
|
623
623
|
"syncObservation": "Lokales Signal",
|
|
624
624
|
"syncPermission": "Erlaubnis",
|
|
625
625
|
"syncVerified": "Preview-Sync",
|
|
626
|
-
"previewWaiting": "
|
|
626
|
+
"previewWaiting": "Die ersten 10 gültigen Minuten werden aufgebaut",
|
|
627
627
|
"previewContributed": "In der Global AI Preview gezählt",
|
|
628
628
|
"previewUnavailable": "Sync wird bei verfügbarer Verbindung wiederholt",
|
|
629
629
|
"globalContribution": "Globaler Beitrag",
|
|
630
630
|
"globalNotJoined": "Kein Beitrag aktiv",
|
|
631
631
|
"globalNotJoinedCopy": "Nur beitreten, wenn die anonymen Summen dieses Geräts einfließen sollen.",
|
|
632
|
-
"globalBuilding": "
|
|
633
|
-
"globalBuildingCopy": "Dieses Gerät benötigt
|
|
634
|
-
"globalSyncing": "
|
|
635
|
-
"globalSyncingCopy": "Das Aggregat ist bereit und wird bei verfügbarer
|
|
636
|
-
"globalQualified": "
|
|
637
|
-
"globalQualifiedCopy": "Diese Installation
|
|
638
|
-
"globalRetry": "
|
|
639
|
-
"globalRetryCopy": "Das gespeicherte Aggregat versucht den Sync
|
|
632
|
+
"globalBuilding": "Beitrag dieses Geräts wird vorbereitet",
|
|
633
|
+
"globalBuildingCopy": "Dieses Gerät benötigt 10 gültige Beobachtungsminuten vor dem ersten anonymen Sync.",
|
|
634
|
+
"globalSyncing": "Aktiver Beitrag · Sync ausstehend",
|
|
635
|
+
"globalSyncingCopy": "Das Aggregat ist bereit und wird bei verfügbarer Internetverbindung synchronisiert.",
|
|
636
|
+
"globalQualified": "In der Preview aktiv",
|
|
637
|
+
"globalQualifiedCopy": "Diese Installation zählt als ein aktiver Beitrag und wird höchstens stündlich aktualisiert.",
|
|
638
|
+
"globalRetry": "Aktiver Beitrag · Verbindung wird wiederholt",
|
|
639
|
+
"globalRetryCopy": "Das gespeicherte Aggregat versucht den Sync bei der nächsten stündlichen Aktualisierung erneut.",
|
|
640
640
|
"globalValidProgress": "{current} von {required} gültiger Zeit",
|
|
641
641
|
"globalLastSync": "Zuletzt synchronisiert: {time}",
|
|
642
642
|
"globalNeverSynced": "Noch nicht synchronisiert",
|
|
643
|
-
"globalDownloadsNote": "
|
|
643
|
+
"globalDownloadsNote": "NPM-Downloadereignisse zeigen Reichweite, keine aktiven Beiträge.",
|
|
644
644
|
"reviewPermission": "Freigabe wählen",
|
|
645
645
|
"permissionNativeOnly": "Öffnen Sie die installierte Forkit-App, um die globale Freigabe zu ändern.",
|
|
646
646
|
"technical": "Erweiterte Details",
|
|
@@ -741,7 +741,7 @@
|
|
|
741
741
|
"fatalStopped": "Der lokale Dienst wurde unerwartet beendet. Es ist kein Monitoring mehr aktiv.",
|
|
742
742
|
"quit": "Beenden",
|
|
743
743
|
"globalPermissionTitle": "An der Global AI Preview teilnehmen?",
|
|
744
|
-
"globalPermissionBody": "Nach
|
|
744
|
+
"globalPermissionBody": "Nach 10 gültigen Beobachtungsminuten sendet Forkit ein anonymes Aggregat und aktualisiert es bei verfügbarer Internetverbindung höchstens einmal pro Stunde. Enthalten sind Beobachtungszeit, KI-aktive Zeit, unterstützte App-Kategorien, lokale Modellanzahl und -speicher sowie System-/Versionsfelder. Ein zufälliger lokaler Beitragsschlüssel verhindert Doppelzählung. Ausgeschlossen sind Chat-Titel, Projekte, Pfade, Prompts, Befehle, Kontodaten und der lokale Gerätename. Community-Preview-Daten sind nicht hardwareverifiziert.",
|
|
745
745
|
"globalPermissionAllow": "Preview beitreten",
|
|
746
746
|
"globalPermissionNotNow": "Nicht jetzt",
|
|
747
747
|
"personalPattern": "Gerätemuster",
|
package/dist/localization.js
CHANGED
|
@@ -55,9 +55,45 @@ exports.UI_COPY = {
|
|
|
55
55
|
personalPattern: 'Gerätemuster', patternFocused: 'Fokussierter KI-Workflow: Alle beobachtete Aktivität kam von {product}.', patternInterrupted: 'Unterbrochener Rhythmus: Aktivität erschien in vielen kurzen Blöcken.', patternDeepWork: 'Deep-Work-Block: Die längste aktive Phase dauerte {duration}.', patternLocalInactive: 'Lokale Modelle verfügbar, aber keines lief.', insightMostlyIdle: 'Meist bereite Beobachtung: Unterstützte KI war bereit, aber nicht aktiv am Arbeiten.', insightActivityProduct: '{product}-App-Aktivität wurde während {percent} % der Gerätebeobachtung erkannt.', insightActivityGeneric: 'Unterstützte KI-App-Aktivität wurde während {percent} % der Gerätebeobachtung erkannt.', insightLongest: 'Das längste durchgehende KI-App-Aktivitätssignal dauerte {duration}.', insightDeepWork: 'Deep-Work-Block: Die längste aktive Phase dauerte {duration}.', insightMulti: 'Lokale KI-App-Aktivität wurde in {count} unterstützten Tools beobachtet.', insightModelsUnused: 'Lokale KI-Reserve: {count} lokale Modelle sind verfügbar, 0 laufen.', insightHostedFirst: 'Hosted-first-Workflow: {product} war aktiv, während lokale Modelle inaktiv blieben.', insightFocused: 'Fokussierter KI-Workflow: Alle beobachtete Aktivität kam von {product}.',
|
|
56
56
|
},
|
|
57
57
|
};
|
|
58
|
+
// v3 lowered the explicitly-consented community entry threshold. Keeping this
|
|
59
|
+
// override separate from the historical copy preserves the existing locale
|
|
60
|
+
// catalogue while ensuring the native prompt, local status, and generated app
|
|
61
|
+
// page always describe the currently shipped privacy terms.
|
|
62
|
+
const GLOBAL_CONTRIBUTION_V3_COPY = {
|
|
63
|
+
en: {
|
|
64
|
+
globalProgress: '{remaining} of valid observed time until this device joins the community.',
|
|
65
|
+
permissionGranted: 'Global contribution is on. After 10 valid minutes, the anonymous aggregate syncs when internet is available, then refreshes at most once an hour.',
|
|
66
|
+
previewWaiting: 'Building the first 10 valid minutes',
|
|
67
|
+
globalBuilding: 'Preparing this device’s contribution',
|
|
68
|
+
globalBuildingCopy: 'This device needs 10 valid observed minutes before its first anonymous sync.',
|
|
69
|
+
globalSyncing: 'Active contributor · sync pending',
|
|
70
|
+
globalSyncingCopy: 'The aggregate is ready and will sync when internet is available.',
|
|
71
|
+
globalQualified: 'Active in the Preview',
|
|
72
|
+
globalQualifiedCopy: 'This installation is counted as one active contributor and refreshes at most once an hour.',
|
|
73
|
+
globalRetry: 'Active contributor · connection retrying',
|
|
74
|
+
globalRetryCopy: 'The saved aggregate retries at the next hourly refresh when internet is available.',
|
|
75
|
+
globalDownloadsNote: 'NPM download events show reach; they are not active contributors.',
|
|
76
|
+
globalPermissionBody: 'After 10 valid observed minutes, Forkit sends one anonymous aggregate and refreshes it at most once per hour when internet is available. It includes observed and AI-active time, supported app categories, local model counts and storage, and system/version fields. A random local contribution key prevents duplicate counting. It excludes chat titles, projects, paths, prompts, commands, account details, and the local device name. Community Preview data is not hardware-verified.',
|
|
77
|
+
},
|
|
78
|
+
de: {
|
|
79
|
+
globalProgress: 'Noch {remaining} gültige Beobachtungszeit, bis dieses Gerät zur Community beiträgt.',
|
|
80
|
+
permissionGranted: 'Der globale Beitrag ist an. Nach 10 gültigen Minuten wird das anonyme Aggregat bei verfügbarer Internetverbindung synchronisiert und danach höchstens stündlich aktualisiert.',
|
|
81
|
+
previewWaiting: 'Die ersten 10 gültigen Minuten werden aufgebaut',
|
|
82
|
+
globalBuilding: 'Beitrag dieses Geräts wird vorbereitet',
|
|
83
|
+
globalBuildingCopy: 'Dieses Gerät benötigt 10 gültige Beobachtungsminuten vor dem ersten anonymen Sync.',
|
|
84
|
+
globalSyncing: 'Aktiver Beitrag · Sync ausstehend',
|
|
85
|
+
globalSyncingCopy: 'Das Aggregat ist bereit und wird bei verfügbarer Internetverbindung synchronisiert.',
|
|
86
|
+
globalQualified: 'In der Preview aktiv',
|
|
87
|
+
globalQualifiedCopy: 'Diese Installation zählt als ein aktiver Beitrag und wird höchstens stündlich aktualisiert.',
|
|
88
|
+
globalRetry: 'Aktiver Beitrag · Verbindung wird wiederholt',
|
|
89
|
+
globalRetryCopy: 'Das gespeicherte Aggregat versucht den Sync bei der nächsten stündlichen Aktualisierung erneut.',
|
|
90
|
+
globalDownloadsNote: 'NPM-Downloadereignisse zeigen Reichweite, keine aktiven Beiträge.',
|
|
91
|
+
globalPermissionBody: 'Nach 10 gültigen Beobachtungsminuten sendet Forkit ein anonymes Aggregat und aktualisiert es bei verfügbarer Internetverbindung höchstens einmal pro Stunde. Enthalten sind Beobachtungszeit, KI-aktive Zeit, unterstützte App-Kategorien, lokale Modellanzahl und -speicher sowie System-/Versionsfelder. Ein zufälliger lokaler Beitragsschlüssel verhindert Doppelzählung. Ausgeschlossen sind Chat-Titel, Projekte, Pfade, Prompts, Befehle, Kontodaten und der lokale Gerätename. Community-Preview-Daten sind nicht hardwareverifiziert.',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
58
94
|
function normalizeLocale(value) { return String(value || '').toLowerCase().startsWith('de') ? 'de' : 'en'; }
|
|
59
95
|
function uiText(locale, key, values = {}) {
|
|
60
|
-
let text = exports.UI_COPY[locale][key];
|
|
96
|
+
let text = GLOBAL_CONTRIBUTION_V3_COPY[locale][key] ?? exports.UI_COPY[locale][key];
|
|
61
97
|
for (const [name, value] of Object.entries(values))
|
|
62
98
|
text = text.replaceAll(`{${name}}`, String(value));
|
|
63
99
|
return text;
|
package/dist/server.js
CHANGED
|
@@ -104,7 +104,7 @@ async function startAiFootprintsServer(options = {}) {
|
|
|
104
104
|
let previewTimer = null;
|
|
105
105
|
let persistenceQueue = Promise.resolve();
|
|
106
106
|
async function syncGlobalPreview(snapshot = monitor.snapshot()) {
|
|
107
|
-
if (globalPermission !== 'granted' || !currentReport || snapshot.observed_seconds <
|
|
107
|
+
if (globalPermission !== 'granted' || !currentReport || snapshot.observed_seconds < sharing_1.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS) {
|
|
108
108
|
return globalPreviewContributor.status(globalPermission);
|
|
109
109
|
}
|
|
110
110
|
try {
|
package/dist/sharing.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { MonitorSnapshot } from './monitor';
|
|
2
2
|
import type { CensusReport } from './types';
|
|
3
|
-
|
|
3
|
+
/** A consented installation joins the community Preview after ten valid minutes. */
|
|
4
|
+
export declare const MINIMUM_GLOBAL_CONTRIBUTION_SECONDS: number;
|
|
5
|
+
/** @deprecated Use MINIMUM_GLOBAL_CONTRIBUTION_SECONDS for Preview eligibility. */
|
|
6
|
+
export declare const MINIMUM_COMPARISON_SECONDS: number;
|
|
4
7
|
export interface AnonymousAiFootprintContribution {
|
|
5
8
|
schema_version: '2.0';
|
|
6
9
|
observation: {
|
|
@@ -21,7 +24,7 @@ export interface AnonymousAiFootprintContribution {
|
|
|
21
24
|
local_active_seconds: number;
|
|
22
25
|
system_active_seconds: Record<string, number>;
|
|
23
26
|
privacy: {
|
|
24
|
-
consent_version: 'ai-footprints-global-preview-
|
|
27
|
+
consent_version: 'ai-footprints-global-preview-v3';
|
|
25
28
|
location_mode: 'none';
|
|
26
29
|
country_code: null;
|
|
27
30
|
region_code: null;
|
package/dist/sharing.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MINIMUM_COMPARISON_SECONDS = void 0;
|
|
3
|
+
exports.MINIMUM_COMPARISON_SECONDS = exports.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS = void 0;
|
|
4
4
|
exports.buildAnonymousAiFootprintPreview = buildAnonymousAiFootprintPreview;
|
|
5
5
|
exports.authorizeAnonymousAiFootprintContribution = authorizeAnonymousAiFootprintContribution;
|
|
6
6
|
const node_child_process_1 = require("node:child_process");
|
|
7
|
-
|
|
7
|
+
/** A consented installation joins the community Preview after ten valid minutes. */
|
|
8
|
+
exports.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS = 10 * 60;
|
|
9
|
+
/** @deprecated Use MINIMUM_GLOBAL_CONTRIBUTION_SECONDS for Preview eligibility. */
|
|
10
|
+
exports.MINIMUM_COMPARISON_SECONDS = exports.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS;
|
|
8
11
|
function macosMajorVersion() {
|
|
9
12
|
try {
|
|
10
13
|
const productVersion = (0, node_child_process_1.execFileSync)('/usr/bin/sw_vers', ['-productVersion'], {
|
|
@@ -62,7 +65,7 @@ function buildAnonymousAiFootprintPreview(report, monitor, options = {}) {
|
|
|
62
65
|
throw new Error('ANONYMOUS_FOOTPRINT_MACOS_REQUIRED');
|
|
63
66
|
if (!report.summary.storage_complete)
|
|
64
67
|
throw new Error('ANONYMOUS_FOOTPRINT_STORAGE_INCOMPLETE');
|
|
65
|
-
if (monitor.observed_seconds < exports.
|
|
68
|
+
if (monitor.observed_seconds < exports.MINIMUM_GLOBAL_CONTRIBUTION_SECONDS)
|
|
66
69
|
throw new Error('ANONYMOUS_FOOTPRINT_MINIMUM_OBSERVATION_REQUIRED');
|
|
67
70
|
if (monitor.active_seconds < 0 || monitor.active_seconds > monitor.observed_seconds)
|
|
68
71
|
throw new Error('ANONYMOUS_FOOTPRINT_INVALID_ACTIVITY_DURATION');
|
|
@@ -98,7 +101,7 @@ function buildAnonymousAiFootprintPreview(report, monitor, options = {}) {
|
|
|
98
101
|
local_active_seconds: Math.min(activeSeconds, localActiveSeconds),
|
|
99
102
|
system_active_seconds: systemActiveSeconds,
|
|
100
103
|
privacy: {
|
|
101
|
-
consent_version: 'ai-footprints-global-preview-
|
|
104
|
+
consent_version: 'ai-footprints-global-preview-v3',
|
|
102
105
|
location_mode: 'none',
|
|
103
106
|
country_code: null,
|
|
104
107
|
region_code: null,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Forkit AI Footprints global distribution
|
|
2
2
|
|
|
3
|
-
Status: v0.2.
|
|
3
|
+
Status: v0.2.6 npm-first Apple Silicon macOS community Preview is public.
|
|
4
4
|
|
|
5
5
|
## Goal
|
|
6
6
|
|
|
@@ -23,8 +23,8 @@ does not publish anything.
|
|
|
23
23
|
|
|
24
24
|
| Channel | Audience | Cost to users | Current state |
|
|
25
25
|
|---|---|---:|---|
|
|
26
|
-
| GitHub Release | canonical immutable source/release identity | Free | v0.2.
|
|
27
|
-
| npm public registry | primary Apple Silicon bootstrap; installs a persistent app in `~/Applications` | Free | v0.2.
|
|
26
|
+
| GitHub Release | canonical immutable source/release identity | Free | v0.2.6 public |
|
|
27
|
+
| npm public registry | primary Apple Silicon bootstrap; installs a persistent app in `~/Applications` | Free | v0.2.6 public |
|
|
28
28
|
| Homebrew tap | optional future package-manager channel | Free | Tap not created |
|
|
29
29
|
| Signed `.pkg` | future click installation | Free to users | Blocked on paid Apple identity and notarization |
|
|
30
30
|
|
|
@@ -16,14 +16,14 @@ commands, emit full paths or MCP values, authenticate, or contact Forkit.dev.
|
|
|
16
16
|
|
|
17
17
|
- a Mac you are authorized to inspect;
|
|
18
18
|
- Node.js 20, 22, or 24 and npm;
|
|
19
|
-
- the provided `forkit-ai-footprints-0.2.
|
|
19
|
+
- the provided `forkit-ai-footprints-0.2.6.tgz` test artifact;
|
|
20
20
|
- its SHA-256 checksum from the test coordinator.
|
|
21
21
|
|
|
22
22
|
Verify and install the artifact:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
shasum -a 256 ./forkit-ai-footprints-0.2.
|
|
26
|
-
npm install -g ./forkit-ai-footprints-0.2.
|
|
25
|
+
shasum -a 256 ./forkit-ai-footprints-0.2.6.tgz
|
|
26
|
+
npm install -g ./forkit-ai-footprints-0.2.6.tgz
|
|
27
27
|
forkit-ai-footprints doctor
|
|
28
28
|
```
|
|
29
29
|
|