@oh-my-pi/pi-coding-agent 16.1.7 → 16.1.9
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/CHANGELOG.md +71 -0
- package/dist/cli.js +4266 -3446
- package/dist/types/cli/flag-tables.d.ts +17 -0
- package/dist/types/cli/session-picker.d.ts +0 -1
- package/dist/types/cli/tiny-models-cli.d.ts +2 -0
- package/dist/types/cli-commands.d.ts +4 -2
- package/dist/types/collab/protocol.d.ts +20 -1
- package/dist/types/config/settings-schema.d.ts +57 -6
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +5 -1
- package/dist/types/internal-urls/filesystem-resource.d.ts +9 -0
- package/dist/types/mcp/loader.d.ts +3 -2
- package/dist/types/mcp/manager.d.ts +4 -3
- package/dist/types/mcp/startup-events.d.ts +21 -4
- package/dist/types/mnemopi/config.d.ts +1 -0
- package/dist/types/modes/components/agent-hub.d.ts +1 -0
- package/dist/types/modes/components/agent-transcript-viewer.d.ts +1 -0
- package/dist/types/modes/components/assistant-message.d.ts +5 -1
- package/dist/types/modes/components/btw-panel.d.ts +2 -0
- package/dist/types/modes/components/chat-transcript-builder.d.ts +1 -0
- package/dist/types/modes/components/session-selector.d.ts +0 -2
- package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/controllers/streaming-reveal.d.ts +3 -2
- package/dist/types/modes/interactive-mode.d.ts +4 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/session/agent-session.d.ts +18 -3
- package/dist/types/session/session-history-format.d.ts +25 -0
- package/dist/types/session/snapcompact-inline.d.ts +1 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +7 -4
- package/dist/types/slash-commands/types.d.ts +2 -0
- package/dist/types/system-prompt.d.ts +1 -0
- package/dist/types/tiny/models.d.ts +11 -7
- package/dist/types/tools/browser/launch.d.ts +5 -0
- package/dist/types/tools/todo.d.ts +1 -0
- package/dist/types/utils/thinking-display.d.ts +2 -0
- package/package.json +12 -12
- package/src/advisor/__tests__/advisor.test.ts +104 -0
- package/src/advisor/runtime.ts +38 -2
- package/src/cli/args.ts +0 -1
- package/src/cli/flag-tables.ts +42 -0
- package/src/cli/profile-bootstrap.ts +1 -11
- package/src/cli/session-picker.ts +1 -2
- package/src/cli/tiny-models-cli.ts +7 -2
- package/src/cli-commands.ts +48 -3
- package/src/collab/guest.ts +172 -20
- package/src/collab/host.ts +47 -5
- package/src/collab/protocol.ts +16 -1
- package/src/config/model-registry.ts +6 -7
- package/src/config/settings-schema.ts +59 -5
- package/src/edit/renderer.ts +8 -12
- package/src/extensibility/legacy-pi-ai-shim.ts +16 -4
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/internal-urls/filesystem-resource.ts +34 -0
- package/src/internal-urls/local-protocol.ts +7 -1
- package/src/internal-urls/memory-protocol.ts +5 -1
- package/src/internal-urls/skill-protocol.ts +20 -4
- package/src/internal-urls/vault-protocol.ts +5 -2
- package/src/lsp/client.ts +39 -25
- package/src/main.ts +8 -8
- package/src/mcp/loader.ts +4 -3
- package/src/mcp/manager.ts +35 -15
- package/src/mcp/startup-events.ts +106 -11
- package/src/mnemopi/config.ts +2 -0
- package/src/mnemopi/state.ts +3 -1
- package/src/modes/components/agent-hub.ts +4 -0
- package/src/modes/components/agent-transcript-viewer.ts +2 -0
- package/src/modes/components/assistant-message.ts +217 -18
- package/src/modes/components/btw-panel.ts +15 -3
- package/src/modes/components/chat-transcript-builder.ts +8 -2
- package/src/modes/components/model-selector.ts +72 -9
- package/src/modes/components/omfg-panel.ts +1 -1
- package/src/modes/components/session-selector.ts +4 -9
- package/src/modes/components/snapcompact-shape-preview.ts +1 -1
- package/src/modes/components/tool-execution.ts +10 -2
- package/src/modes/controllers/btw-controller.ts +32 -7
- package/src/modes/controllers/command-controller.ts +18 -3
- package/src/modes/controllers/event-controller.ts +24 -4
- package/src/modes/controllers/input-controller.ts +43 -21
- package/src/modes/controllers/mcp-command-controller.ts +40 -12
- package/src/modes/controllers/selector-controller.ts +23 -13
- package/src/modes/controllers/streaming-reveal.ts +78 -20
- package/src/modes/controllers/todo-command-controller.ts +9 -10
- package/src/modes/interactive-mode.ts +84 -9
- package/src/modes/types.ts +4 -1
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/prompts/advisor/system.md +1 -1
- package/src/prompts/system/side-channel-no-tools.md +3 -0
- package/src/sdk.ts +12 -8
- package/src/session/agent-session.ts +385 -85
- package/src/session/history-storage.ts +15 -16
- package/src/session/session-history-format.ts +41 -1
- package/src/session/snapcompact-inline.ts +9 -6
- package/src/slash-commands/builtin-registry.ts +171 -87
- package/src/slash-commands/helpers/todo.ts +12 -6
- package/src/slash-commands/types.ts +2 -0
- package/src/system-prompt.ts +6 -11
- package/src/tiny/models.ts +7 -3
- package/src/tiny/title-client.ts +8 -2
- package/src/tiny/worker.ts +1 -0
- package/src/tools/browser/launch.ts +107 -31
- package/src/tools/puppeteer/00_stealth_tampering.txt +16 -35
- package/src/tools/puppeteer/01_stealth_activity.txt +79 -19
- package/src/tools/puppeteer/02_stealth_hairline.txt +57 -11
- package/src/tools/puppeteer/03_stealth_botd.txt +10 -14
- package/src/tools/puppeteer/04_stealth_iframe.txt +156 -63
- package/src/tools/puppeteer/05_stealth_webgl.txt +222 -64
- package/src/tools/puppeteer/06_stealth_screen.txt +255 -67
- package/src/tools/puppeteer/07_stealth_fonts.txt +17 -15
- package/src/tools/puppeteer/08_stealth_audio.txt +32 -20
- package/src/tools/puppeteer/09_stealth_locale.txt +45 -40
- package/src/tools/puppeteer/10_stealth_plugins.txt +12 -8
- package/src/tools/puppeteer/11_stealth_hardware.txt +57 -6
- package/src/tools/puppeteer/12_stealth_codecs.txt +20 -18
- package/src/tools/puppeteer/13_stealth_worker.txt +206 -45
- package/src/tools/search.ts +10 -1
- package/src/tools/sqlite-reader.ts +59 -3
- package/src/tools/todo.ts +6 -0
- package/src/tools/write.ts +4 -6
- package/src/utils/thinking-display.ts +78 -0
|
@@ -1,72 +1,260 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
;(() => {
|
|
2
|
+
if (typeof Window_Proxy !== "function" || typeof Reflect_apply !== "function") return;
|
|
3
|
+
|
|
4
|
+
const screenObject = window.screen;
|
|
5
|
+
if (!screenObject) return;
|
|
6
|
+
|
|
7
|
+
const isFiniteNumber = (value) =>
|
|
8
|
+
typeof value === "number" &&
|
|
9
|
+
value === value &&
|
|
10
|
+
value !== Infinity &&
|
|
11
|
+
value !== -Infinity;
|
|
12
|
+
|
|
13
|
+
const readValue = (object, prop, fallback) => {
|
|
14
|
+
try {
|
|
15
|
+
const value = object[prop];
|
|
16
|
+
return value === undefined ? fallback : value;
|
|
17
|
+
} catch {
|
|
18
|
+
return fallback;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const finiteNumber = (value, fallback) =>
|
|
23
|
+
isFiniteNumber(value) ? value : fallback;
|
|
24
|
+
|
|
25
|
+
const positiveNumber = (value, fallback) =>
|
|
26
|
+
isFiniteNumber(value) && value > 0 ? value : fallback;
|
|
27
|
+
|
|
28
|
+
const integerNumber = (value, fallback) =>
|
|
29
|
+
isFiniteNumber(value) ? Math_floor(value) : fallback;
|
|
30
|
+
|
|
31
|
+
const positiveInteger = (value, fallback) =>
|
|
32
|
+
isFiniteNumber(value) && value > 0 ? Math_floor(value) : fallback;
|
|
33
|
+
|
|
34
|
+
const findDescriptorOwner = (object, prop) => {
|
|
35
|
+
let owner = object;
|
|
36
|
+
while (owner) {
|
|
37
|
+
let descriptor;
|
|
38
|
+
try {
|
|
39
|
+
descriptor = Object_getOwnPropertyDescriptor(owner, prop);
|
|
40
|
+
} catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
if (descriptor) return [owner, descriptor];
|
|
44
|
+
try {
|
|
45
|
+
owner = Object_getPrototypeOf(owner);
|
|
46
|
+
} catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const patchGetter = (object, prop, getValue) => {
|
|
54
|
+
const found = findDescriptorOwner(object, prop);
|
|
55
|
+
if (!found) return false;
|
|
56
|
+
|
|
57
|
+
const owner = found[0];
|
|
58
|
+
const descriptor = found[1];
|
|
59
|
+
if (descriptor.configurable !== true || typeof descriptor.get !== "function") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const originalGet = descriptor.get;
|
|
64
|
+
const patchedGet = new Window_Proxy(originalGet, {
|
|
65
|
+
apply(target, thisArg, args) {
|
|
66
|
+
const nativeValue = Reflect_apply(target, thisArg, args);
|
|
67
|
+
return getValue(nativeValue, thisArg);
|
|
68
|
+
},
|
|
16
69
|
});
|
|
17
|
-
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// Override screen properties
|
|
21
|
-
for (const [prop, descriptor] of Object_entries({
|
|
22
|
-
width,
|
|
23
|
-
height,
|
|
24
|
-
availWidth,
|
|
25
|
-
availHeight,
|
|
26
|
-
availLeft: 0,
|
|
27
|
-
availTop: 0,
|
|
28
|
-
colorDepth,
|
|
29
|
-
pixelDepth,
|
|
30
|
-
})) {
|
|
31
|
-
defineScreenProp(prop, descriptor);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Ensure outer dimensions match screen for consistency
|
|
35
|
-
const chromeFrameHeight = 85;
|
|
36
|
-
Object_defineProperty(window, "outerWidth", {
|
|
37
|
-
get: () => window.innerWidth,
|
|
38
|
-
configurable: true,
|
|
39
|
-
enumerable: true,
|
|
40
|
-
});
|
|
41
|
-
Object_defineProperty(window, "outerHeight", {
|
|
42
|
-
get: () => window.innerHeight + chromeFrameHeight,
|
|
43
|
-
configurable: true,
|
|
44
|
-
enumerable: true,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
if (window.visualViewport) {
|
|
48
|
-
const defineVvpProp = (prop, value) => {
|
|
70
|
+
patchToString(patchedGet, "get " + prop);
|
|
49
71
|
try {
|
|
50
|
-
Object_defineProperty(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
Object_defineProperty(owner, prop, {
|
|
73
|
+
configurable: descriptor.configurable,
|
|
74
|
+
enumerable: descriptor.enumerable,
|
|
75
|
+
get: patchedGet,
|
|
76
|
+
set: descriptor.set,
|
|
54
77
|
});
|
|
55
|
-
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
56
82
|
};
|
|
57
83
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
const patchStableNumber = (object, prop, value) => {
|
|
85
|
+
const current = readValue(object, prop, undefined);
|
|
86
|
+
if (current === value) return;
|
|
87
|
+
patchGetter(object, prop, () => value);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const initialInnerWidth = positiveInteger(readValue(window, "innerWidth", 0), 0);
|
|
91
|
+
const initialInnerHeight = positiveInteger(readValue(window, "innerHeight", 0), 0);
|
|
92
|
+
const initialOuterWidth = positiveInteger(
|
|
93
|
+
readValue(window, "outerWidth", Math_max(initialInnerWidth, 1)),
|
|
94
|
+
Math_max(initialInnerWidth, 1),
|
|
95
|
+
);
|
|
96
|
+
const initialOuterHeight = positiveInteger(
|
|
97
|
+
readValue(window, "outerHeight", Math_max(initialInnerHeight, 1)),
|
|
98
|
+
Math_max(initialInnerHeight, 1),
|
|
99
|
+
);
|
|
100
|
+
// Real Chrome reserves vertical space for the tab strip + URL bar, so
|
|
101
|
+
// outerHeight is always taller than innerHeight (~88px on a stock window).
|
|
102
|
+
// Headless reports outerHeight === innerHeight, which is a well-known tell, so
|
|
103
|
+
// synthesize a realistic chrome height when the window has no visible chrome.
|
|
104
|
+
const browserChromeHeight = 88;
|
|
105
|
+
const targetOuterHeight =
|
|
106
|
+
initialOuterHeight > initialInnerHeight
|
|
107
|
+
? initialOuterHeight
|
|
108
|
+
: initialInnerHeight + browserChromeHeight;
|
|
109
|
+
const requiredWidth = Math_max(initialInnerWidth, initialOuterWidth, 1);
|
|
110
|
+
const requiredHeight = Math_max(initialInnerHeight, initialOuterHeight, targetOuterHeight, 1);
|
|
111
|
+
|
|
112
|
+
const screenWidth = Math_max(
|
|
113
|
+
positiveInteger(readValue(screenObject, "width", requiredWidth), requiredWidth),
|
|
114
|
+
requiredWidth,
|
|
115
|
+
);
|
|
116
|
+
const screenHeight = Math_max(
|
|
117
|
+
positiveInteger(readValue(screenObject, "height", requiredHeight), requiredHeight),
|
|
118
|
+
requiredHeight,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
let screenAvailWidth = positiveInteger(
|
|
122
|
+
readValue(screenObject, "availWidth", screenWidth),
|
|
123
|
+
screenWidth,
|
|
124
|
+
);
|
|
125
|
+
if (screenAvailWidth < requiredWidth || screenAvailWidth > screenWidth) {
|
|
126
|
+
screenAvailWidth = screenWidth;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let screenAvailHeight = positiveInteger(
|
|
130
|
+
readValue(screenObject, "availHeight", screenHeight),
|
|
131
|
+
screenHeight,
|
|
132
|
+
);
|
|
133
|
+
if (screenAvailHeight < requiredHeight || screenAvailHeight > screenHeight) {
|
|
134
|
+
screenAvailHeight = screenHeight;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const screenAvailLeft = integerNumber(readValue(screenObject, "availLeft", 0), 0);
|
|
138
|
+
const screenAvailTop = integerNumber(readValue(screenObject, "availTop", 0), 0);
|
|
139
|
+
const screenColorDepth = positiveInteger(readValue(screenObject, "colorDepth", 24), 24);
|
|
140
|
+
const screenPixelDepth = positiveInteger(
|
|
141
|
+
readValue(screenObject, "pixelDepth", screenColorDepth),
|
|
142
|
+
screenColorDepth,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
for (const entry of [
|
|
146
|
+
["width", screenWidth],
|
|
147
|
+
["height", screenHeight],
|
|
148
|
+
["availWidth", screenAvailWidth],
|
|
149
|
+
["availHeight", screenAvailHeight],
|
|
150
|
+
["availLeft", screenAvailLeft],
|
|
151
|
+
["availTop", screenAvailTop],
|
|
152
|
+
["colorDepth", screenColorDepth],
|
|
153
|
+
["pixelDepth", screenPixelDepth],
|
|
154
|
+
]) {
|
|
155
|
+
patchStableNumber(screenObject, entry[0], entry[1]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const outerWidthNeedsPatch =
|
|
159
|
+
!isFiniteNumber(readValue(window, "outerWidth", undefined)) ||
|
|
160
|
+
readValue(window, "outerWidth", 0) <= 0 ||
|
|
161
|
+
Math_floor(readValue(window, "outerWidth", 0)) < initialInnerWidth;
|
|
162
|
+
if (outerWidthNeedsPatch) {
|
|
163
|
+
patchGetter(window, "outerWidth", (nativeValue) =>
|
|
164
|
+
Math_max(
|
|
165
|
+
positiveInteger(nativeValue, initialOuterWidth),
|
|
166
|
+
positiveInteger(readValue(window, "innerWidth", requiredWidth), requiredWidth),
|
|
167
|
+
),
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const outerHeightNeedsPatch =
|
|
172
|
+
!isFiniteNumber(readValue(window, "outerHeight", undefined)) ||
|
|
173
|
+
readValue(window, "outerHeight", 0) <= 0 ||
|
|
174
|
+
Math_floor(readValue(window, "outerHeight", 0)) <= initialInnerHeight;
|
|
175
|
+
if (outerHeightNeedsPatch) {
|
|
176
|
+
patchGetter(window, "outerHeight", (nativeValue) =>
|
|
177
|
+
Math_max(
|
|
178
|
+
positiveInteger(nativeValue, initialOuterHeight),
|
|
179
|
+
positiveInteger(readValue(window, "innerHeight", requiredHeight), requiredHeight) +
|
|
180
|
+
browserChromeHeight,
|
|
181
|
+
),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const initialDevicePixelRatio = positiveNumber(
|
|
186
|
+
readValue(window, "devicePixelRatio", 1),
|
|
187
|
+
1,
|
|
188
|
+
);
|
|
189
|
+
if (readValue(window, "devicePixelRatio", undefined) !== initialDevicePixelRatio) {
|
|
190
|
+
patchGetter(window, "devicePixelRatio", () => initialDevicePixelRatio);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const visualViewportObject = readValue(window, "visualViewport", null);
|
|
194
|
+
if (visualViewportObject) {
|
|
195
|
+
const initialScale = positiveNumber(readValue(visualViewportObject, "scale", 1), 1);
|
|
196
|
+
if (readValue(visualViewportObject, "scale", undefined) !== initialScale) {
|
|
197
|
+
patchGetter(visualViewportObject, "scale", (nativeValue) =>
|
|
198
|
+
positiveNumber(nativeValue, initialScale),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const getViewportScale = () =>
|
|
203
|
+
positiveNumber(readValue(visualViewportObject, "scale", initialScale), initialScale);
|
|
204
|
+
|
|
205
|
+
const getViewportWidthFallback = () =>
|
|
206
|
+
positiveNumber(readValue(window, "innerWidth", requiredWidth), requiredWidth) /
|
|
207
|
+
getViewportScale();
|
|
208
|
+
|
|
209
|
+
const getViewportHeightFallback = () =>
|
|
210
|
+
positiveNumber(readValue(window, "innerHeight", requiredHeight), requiredHeight) /
|
|
211
|
+
getViewportScale();
|
|
212
|
+
|
|
213
|
+
if (positiveNumber(readValue(visualViewportObject, "width", 0), 0) <= 0) {
|
|
214
|
+
patchGetter(visualViewportObject, "width", (nativeValue) =>
|
|
215
|
+
positiveNumber(nativeValue, getViewportWidthFallback()),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (positiveNumber(readValue(visualViewportObject, "height", 0), 0) <= 0) {
|
|
220
|
+
patchGetter(visualViewportObject, "height", (nativeValue) =>
|
|
221
|
+
positiveNumber(nativeValue, getViewportHeightFallback()),
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const getViewportOffsetLeft = () =>
|
|
226
|
+
finiteNumber(readValue(visualViewportObject, "offsetLeft", 0), 0);
|
|
227
|
+
const getViewportOffsetTop = () =>
|
|
228
|
+
finiteNumber(readValue(visualViewportObject, "offsetTop", 0), 0);
|
|
229
|
+
|
|
230
|
+
if (!isFiniteNumber(readValue(visualViewportObject, "offsetLeft", undefined))) {
|
|
231
|
+
patchGetter(visualViewportObject, "offsetLeft", (nativeValue) =>
|
|
232
|
+
finiteNumber(nativeValue, 0),
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (!isFiniteNumber(readValue(visualViewportObject, "offsetTop", undefined))) {
|
|
237
|
+
patchGetter(visualViewportObject, "offsetTop", (nativeValue) =>
|
|
238
|
+
finiteNumber(nativeValue, 0),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!isFiniteNumber(readValue(visualViewportObject, "pageLeft", undefined))) {
|
|
243
|
+
patchGetter(visualViewportObject, "pageLeft", (nativeValue) =>
|
|
244
|
+
finiteNumber(
|
|
245
|
+
nativeValue,
|
|
246
|
+
finiteNumber(readValue(window, "scrollX", 0), 0) + getViewportOffsetLeft(),
|
|
247
|
+
),
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (!isFiniteNumber(readValue(visualViewportObject, "pageTop", undefined))) {
|
|
252
|
+
patchGetter(visualViewportObject, "pageTop", (nativeValue) =>
|
|
253
|
+
finiteNumber(
|
|
254
|
+
nativeValue,
|
|
255
|
+
finiteNumber(readValue(window, "scrollY", 0), 0) + getViewportOffsetTop(),
|
|
256
|
+
),
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
@@ -47,7 +47,6 @@ const commonFonts = [
|
|
|
47
47
|
"Wingdings 3",
|
|
48
48
|
"Apple Color Emoji",
|
|
49
49
|
"Apple SD Gothic Neo",
|
|
50
|
-
"Helvetica Neue",
|
|
51
50
|
"Hoefler Text",
|
|
52
51
|
"Menlo",
|
|
53
52
|
"Monaco",
|
|
@@ -56,32 +55,31 @@ const commonFonts = [
|
|
|
56
55
|
"SF Pro Text",
|
|
57
56
|
];
|
|
58
57
|
|
|
59
|
-
// Override queryLocalFonts if present (Local Font Access API)
|
|
60
58
|
if ("queryLocalFonts" in window) {
|
|
59
|
+
const queryLocalFonts = async function queryLocalFonts() {
|
|
60
|
+
return commonFonts.map((family) => ({
|
|
61
|
+
family,
|
|
62
|
+
fullName: family,
|
|
63
|
+
postscriptName: family.replace(/\s+/g, ""),
|
|
64
|
+
style: "Regular",
|
|
65
|
+
blob: () => Promise_resolve(new Window_Blob([])),
|
|
66
|
+
}));
|
|
67
|
+
};
|
|
68
|
+
patchToString(queryLocalFonts, "queryLocalFonts");
|
|
61
69
|
Object_defineProperty(window, "queryLocalFonts", {
|
|
62
|
-
value:
|
|
63
|
-
return commonFonts.map((family) => ({
|
|
64
|
-
family,
|
|
65
|
-
fullName: family,
|
|
66
|
-
postscriptName: family.replace(/\s+/g, ""),
|
|
67
|
-
style: "Regular",
|
|
68
|
-
blob: () => Promise_resolve(new Window_Blob([])),
|
|
69
|
-
}));
|
|
70
|
-
},
|
|
70
|
+
value: queryLocalFonts,
|
|
71
71
|
writable: true,
|
|
72
72
|
configurable: true,
|
|
73
73
|
enumerable: true,
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// Hide fonts-unique tracking via canvas
|
|
78
77
|
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
|
79
|
-
|
|
78
|
+
const patchedGetContext = function getContext(type, options) {
|
|
80
79
|
const ctx = originalGetContext.call(this, type, options);
|
|
81
80
|
if (ctx && type === "2d") {
|
|
82
81
|
const originalFillText = ctx.fillText;
|
|
83
|
-
|
|
84
|
-
// Add tiny imperceptible noise to text rendering
|
|
82
|
+
const patchedFillText = function fillText(text, x, y, maxWidth) {
|
|
85
83
|
const noiseX = (Math_random() - 0.5) * 0.02;
|
|
86
84
|
const noiseY = (Math_random() - 0.5) * 0.02;
|
|
87
85
|
return originalFillText.call(
|
|
@@ -92,6 +90,10 @@ HTMLCanvasElement.prototype.getContext = function (type, options) {
|
|
|
92
90
|
maxWidth,
|
|
93
91
|
);
|
|
94
92
|
};
|
|
93
|
+
patchToString(patchedFillText, "fillText");
|
|
94
|
+
ctx.fillText = patchedFillText;
|
|
95
95
|
}
|
|
96
96
|
return ctx;
|
|
97
97
|
};
|
|
98
|
+
patchToString(patchedGetContext, "getContext");
|
|
99
|
+
HTMLCanvasElement.prototype.getContext = patchedGetContext;
|
|
@@ -1,32 +1,45 @@
|
|
|
1
|
-
// Spoof AudioContext latency values to look like real hardware
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// Spoof AudioContext latency values to look like real hardware.
|
|
2
|
+
const audioLatencyAccessors = {
|
|
3
|
+
get baseLatency() {
|
|
4
|
+
return 0.005;
|
|
5
|
+
},
|
|
6
|
+
get outputLatency() {
|
|
7
|
+
return 0.01;
|
|
8
|
+
},
|
|
9
|
+
get sampleRate() {
|
|
10
|
+
return 48000;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const defineAudioGetter = (proto, name) => {
|
|
15
|
+
const descriptor = Object_getOwnPropertyDescriptor(audioLatencyAccessors, name);
|
|
16
|
+
if (!descriptor || !descriptor.get) return;
|
|
17
|
+
patchToString(descriptor.get, "get " + name);
|
|
18
|
+
Object_defineProperty(proto, name, {
|
|
19
|
+
get: descriptor.get,
|
|
10
20
|
configurable: true,
|
|
11
21
|
enumerable: true,
|
|
12
22
|
});
|
|
13
23
|
};
|
|
14
24
|
|
|
25
|
+
const spoofLatency = (proto) => {
|
|
26
|
+
defineAudioGetter(proto, "baseLatency");
|
|
27
|
+
defineAudioGetter(proto, "outputLatency");
|
|
28
|
+
};
|
|
29
|
+
|
|
15
30
|
if (window.AudioContext) {
|
|
16
31
|
spoofLatency(AudioContext.prototype);
|
|
17
32
|
}
|
|
33
|
+
|
|
18
34
|
if (window.OfflineAudioContext) {
|
|
19
|
-
// For offline context, add subtle randomness to prevent deterministic fingerprints
|
|
20
35
|
const OriginalOfflineAudioContext = window.OfflineAudioContext;
|
|
21
|
-
|
|
36
|
+
const PatchedOfflineAudioContext = class OfflineAudioContext extends OriginalOfflineAudioContext {
|
|
22
37
|
constructor(numberOfChannels, length, sampleRate) {
|
|
23
38
|
super(numberOfChannels, length, sampleRate);
|
|
24
39
|
|
|
25
|
-
// Hook startRendering to add noise
|
|
26
40
|
const originalStartRendering = this.startRendering.bind(this);
|
|
27
|
-
|
|
41
|
+
const patchedStartRendering = async function startRendering() {
|
|
28
42
|
const buffer = await originalStartRendering();
|
|
29
|
-
// Add imperceptible noise to prevent deterministic hash
|
|
30
43
|
for (let c = 0; c < buffer.numberOfChannels; c++) {
|
|
31
44
|
const channel = buffer.getChannelData(c);
|
|
32
45
|
for (let i = 0; i < channel.length; i++) {
|
|
@@ -37,15 +50,14 @@ if (window.OfflineAudioContext) {
|
|
|
37
50
|
}
|
|
38
51
|
return buffer;
|
|
39
52
|
};
|
|
53
|
+
patchToString(patchedStartRendering, "startRendering");
|
|
54
|
+
this.startRendering = patchedStartRendering;
|
|
40
55
|
}
|
|
41
56
|
};
|
|
57
|
+
patchToString(PatchedOfflineAudioContext, "OfflineAudioContext");
|
|
58
|
+
window.OfflineAudioContext = PatchedOfflineAudioContext;
|
|
42
59
|
}
|
|
43
60
|
|
|
44
|
-
// Also spoof sampleRate consistency
|
|
45
61
|
if (window.AudioContext) {
|
|
46
|
-
|
|
47
|
-
get: () => 48000, // Common hardware rate
|
|
48
|
-
configurable: true,
|
|
49
|
-
enumerable: true,
|
|
50
|
-
});
|
|
62
|
+
defineAudioGetter(AudioContext.prototype, "sampleRate");
|
|
51
63
|
}
|
|
@@ -1,46 +1,51 @@
|
|
|
1
|
-
// Define a consistent locale profile
|
|
2
1
|
const locale = "en-US";
|
|
3
|
-
const languages = [
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
configurable: true,
|
|
10
|
-
enumerable: true,
|
|
11
|
-
});
|
|
12
|
-
Object_defineProperty(navigator, "languages", {
|
|
13
|
-
get: () => [...languages],
|
|
14
|
-
configurable: true,
|
|
15
|
-
enumerable: true,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// Override Intl.DateTimeFormat for timezone consistency
|
|
19
|
-
const OriginalDateTimeFormat = Intl_DateTimeFormat;
|
|
20
|
-
Intl.DateTimeFormat = class extends OriginalDateTimeFormat {
|
|
21
|
-
constructor(locales, options) {
|
|
22
|
-
const mergedOptions = { ...options, timeZone: timezone };
|
|
23
|
-
super(locales, mergedOptions);
|
|
24
|
-
}
|
|
25
|
-
resolvedOptions() {
|
|
26
|
-
const options = super.resolvedOptions();
|
|
27
|
-
options.timeZone = timezone;
|
|
28
|
-
return options;
|
|
2
|
+
const languages = [locale, "en"];
|
|
3
|
+
|
|
4
|
+
const sameLanguages = (value) => {
|
|
5
|
+
if (!value || value.length !== languages.length) return false;
|
|
6
|
+
for (let index = 0; index < languages.length; index += 1) {
|
|
7
|
+
if (value[index] !== languages[index]) return false;
|
|
29
8
|
}
|
|
9
|
+
return true;
|
|
30
10
|
};
|
|
31
11
|
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
.replace(/\(.*\)$/, "(Eastern Standard Time)");
|
|
12
|
+
const navigatorProto = Object_getPrototypeOf(navigator);
|
|
13
|
+
const navigatorAccessors = {
|
|
14
|
+
get language() {
|
|
15
|
+
return locale;
|
|
16
|
+
},
|
|
17
|
+
get languages() {
|
|
18
|
+
return [locale, "en"];
|
|
19
|
+
},
|
|
41
20
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
21
|
+
|
|
22
|
+
const defineNavigatorAccessor = (name) => {
|
|
23
|
+
const owner = navigatorProto || navigator;
|
|
24
|
+
const descriptor =
|
|
25
|
+
(navigatorProto && Object_getOwnPropertyDescriptor(navigatorProto, name)) ||
|
|
26
|
+
Object_getOwnPropertyDescriptor(navigator, name);
|
|
27
|
+
if (descriptor && descriptor.configurable === false) return;
|
|
28
|
+
|
|
29
|
+
const accessor = Object_getOwnPropertyDescriptor(navigatorAccessors, name);
|
|
30
|
+
if (!accessor || !accessor.get) return;
|
|
31
|
+
patchToString(accessor.get, "get " + name);
|
|
32
|
+
|
|
33
|
+
Object_defineProperty(owner, name, {
|
|
34
|
+
get: accessor.get,
|
|
35
|
+
configurable: descriptor ? descriptor.configurable : true,
|
|
36
|
+
enumerable: descriptor ? descriptor.enumerable : true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const ownDescriptor = Object_getOwnPropertyDescriptor(navigator, name);
|
|
40
|
+
if (owner !== navigator && ownDescriptor && ownDescriptor.configurable !== false) {
|
|
41
|
+
Reflect_deleteProperty(navigator, name);
|
|
42
|
+
}
|
|
46
43
|
};
|
|
44
|
+
|
|
45
|
+
if (navigator.language !== locale) {
|
|
46
|
+
defineNavigatorAccessor("language");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!sameLanguages(navigator.languages)) {
|
|
50
|
+
defineNavigatorAccessor("languages");
|
|
51
|
+
}
|
|
@@ -54,8 +54,8 @@ const defineProp = (obj, prop, value) =>
|
|
|
54
54
|
configurable: true,
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
const generateFunctionMocks = (proto, itemMainProp, dataArray) =>
|
|
58
|
-
item
|
|
57
|
+
const generateFunctionMocks = (proto, itemMainProp, dataArray) => {
|
|
58
|
+
const item = new Window_Proxy(proto.item, {
|
|
59
59
|
apply(target, ctx, args) {
|
|
60
60
|
if (!args.length) {
|
|
61
61
|
throw new TypeError(
|
|
@@ -65,8 +65,8 @@ const generateFunctionMocks = (proto, itemMainProp, dataArray) => ({
|
|
|
65
65
|
const isInteger = args[0] && Number.isInteger(Number(args[0]));
|
|
66
66
|
return (isInteger ? dataArray[Number(args[0])] : dataArray[0]) || null;
|
|
67
67
|
},
|
|
68
|
-
})
|
|
69
|
-
namedItem
|
|
68
|
+
});
|
|
69
|
+
const namedItem = new Window_Proxy(proto.namedItem, {
|
|
70
70
|
apply(target, ctx, args) {
|
|
71
71
|
if (!args.length) {
|
|
72
72
|
throw new TypeError(
|
|
@@ -75,15 +75,19 @@ const generateFunctionMocks = (proto, itemMainProp, dataArray) => ({
|
|
|
75
75
|
}
|
|
76
76
|
return dataArray.find(item => item[itemMainProp] === args[0]) || null;
|
|
77
77
|
},
|
|
78
|
-
})
|
|
79
|
-
|
|
78
|
+
});
|
|
79
|
+
patchToString(item, "item");
|
|
80
|
+
patchToString(namedItem, "namedItem");
|
|
81
|
+
const refresh = proto.refresh
|
|
80
82
|
? new Window_Proxy(proto.refresh, {
|
|
81
83
|
apply() {
|
|
82
84
|
return undefined;
|
|
83
85
|
},
|
|
84
86
|
})
|
|
85
|
-
: undefined
|
|
86
|
-
|
|
87
|
+
: undefined;
|
|
88
|
+
patchToString(refresh, "refresh");
|
|
89
|
+
return { item, namedItem, refresh };
|
|
90
|
+
};
|
|
87
91
|
|
|
88
92
|
const generateMagicArray = (dataArray, proto, itemProto, itemMainProp) => {
|
|
89
93
|
const makeItem = (data) => {
|
|
@@ -1,8 +1,59 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
const hardwareConcurrencyName = "hardwareConcurrency";
|
|
2
|
+
let hardwareConcurrencyProto = Object_getPrototypeOf(navigator);
|
|
3
|
+
let hardwareConcurrencyOwner;
|
|
4
|
+
let hardwareConcurrencyDescriptor;
|
|
5
|
+
|
|
6
|
+
while (hardwareConcurrencyProto && !hardwareConcurrencyDescriptor) {
|
|
7
|
+
hardwareConcurrencyDescriptor = Object_getOwnPropertyDescriptor(
|
|
8
|
+
hardwareConcurrencyProto,
|
|
9
|
+
hardwareConcurrencyName,
|
|
10
|
+
);
|
|
11
|
+
if (hardwareConcurrencyDescriptor) {
|
|
12
|
+
hardwareConcurrencyOwner = hardwareConcurrencyProto;
|
|
13
|
+
} else {
|
|
14
|
+
hardwareConcurrencyProto = Object_getPrototypeOf(hardwareConcurrencyProto);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const hardwareConcurrencyValue = 8;
|
|
19
|
+
let shouldPatchHardwareConcurrency = false;
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
hardwareConcurrencyOwner &&
|
|
23
|
+
hardwareConcurrencyDescriptor &&
|
|
24
|
+
hardwareConcurrencyDescriptor.configurable &&
|
|
25
|
+
typeof hardwareConcurrencyDescriptor.get === "function"
|
|
26
|
+
) {
|
|
27
|
+
shouldPatchHardwareConcurrency = true;
|
|
28
|
+
try {
|
|
29
|
+
shouldPatchHardwareConcurrency =
|
|
30
|
+
Reflect_apply(hardwareConcurrencyDescriptor.get, navigator, []) !==
|
|
31
|
+
hardwareConcurrencyValue;
|
|
32
|
+
} catch {
|
|
33
|
+
shouldPatchHardwareConcurrency = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (shouldPatchHardwareConcurrency) {
|
|
38
|
+
const hardwareConcurrencyAccessors = {
|
|
39
|
+
get hardwareConcurrency() {
|
|
40
|
+
Reflect_apply(hardwareConcurrencyDescriptor.get, this, []);
|
|
41
|
+
return hardwareConcurrencyValue;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const getHardwareConcurrency = Object_getOwnPropertyDescriptor(
|
|
45
|
+
hardwareConcurrencyAccessors,
|
|
46
|
+
hardwareConcurrencyName,
|
|
47
|
+
).get;
|
|
48
|
+
|
|
49
|
+
if (typeof patchToString === "function") {
|
|
50
|
+
patchToString(getHardwareConcurrency, "get hardwareConcurrency");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Object_defineProperty(hardwareConcurrencyOwner, hardwareConcurrencyName, {
|
|
54
|
+
get: getHardwareConcurrency,
|
|
55
|
+
set: hardwareConcurrencyDescriptor.set,
|
|
56
|
+
enumerable: hardwareConcurrencyDescriptor.enumerable,
|
|
57
|
+
configurable: hardwareConcurrencyDescriptor.configurable,
|
|
7
58
|
});
|
|
8
59
|
}
|