@oh-my-pi/pi-coding-agent 16.1.8 → 16.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/cli.js +4775 -3942
  3. package/dist/types/cli/flag-tables.d.ts +17 -0
  4. package/dist/types/cli-commands.d.ts +4 -2
  5. package/dist/types/config/settings-schema.d.ts +10 -0
  6. package/dist/types/edit/streaming.d.ts +5 -5
  7. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  8. package/dist/types/modes/controllers/selector-controller.d.ts +0 -1
  9. package/dist/types/modes/interactive-mode.d.ts +1 -1
  10. package/dist/types/modes/types.d.ts +1 -1
  11. package/dist/types/sdk.d.ts +1 -0
  12. package/dist/types/session/agent-session.d.ts +13 -0
  13. package/dist/types/system-prompt.d.ts +2 -0
  14. package/dist/types/tools/browser/aria/aria-snapshot.d.ts +39 -0
  15. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +3 -0
  16. package/dist/types/tools/browser/launch.d.ts +5 -0
  17. package/dist/types/tools/browser.d.ts +1 -0
  18. package/dist/types/tools/find.d.ts +1 -2
  19. package/dist/types/tools/write.d.ts +1 -2
  20. package/package.json +12 -12
  21. package/scripts/generate-aria-snapshot.ts +134 -0
  22. package/src/cli/args.ts +0 -1
  23. package/src/cli/flag-tables.ts +42 -0
  24. package/src/cli/profile-bootstrap.ts +1 -11
  25. package/src/cli-commands.ts +48 -3
  26. package/src/config/model-registry.ts +6 -7
  27. package/src/config/settings-schema.ts +12 -0
  28. package/src/edit/streaming.ts +5 -5
  29. package/src/internal-urls/docs-index.generated.txt +1 -1
  30. package/src/lsp/client.ts +39 -25
  31. package/src/modes/controllers/command-controller.ts +18 -3
  32. package/src/modes/controllers/event-controller.ts +20 -0
  33. package/src/modes/controllers/mcp-command-controller.ts +40 -12
  34. package/src/modes/controllers/selector-controller.ts +3 -5
  35. package/src/modes/interactive-mode.ts +1 -1
  36. package/src/modes/types.ts +1 -1
  37. package/src/prompts/system/project-prompt.md +2 -0
  38. package/src/prompts/system/system-prompt.md +0 -1
  39. package/src/prompts/tools/browser.md +2 -0
  40. package/src/sdk.ts +8 -1
  41. package/src/session/agent-session.ts +36 -1
  42. package/src/slash-commands/builtin-registry.ts +24 -66
  43. package/src/system-prompt.ts +15 -3
  44. package/src/tools/bash.ts +3 -3
  45. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  46. package/src/tools/browser/aria/aria-snapshot.ts +103 -0
  47. package/src/tools/browser/cmux/cmux-tab.ts +36 -1
  48. package/src/tools/browser/launch.ts +107 -31
  49. package/src/tools/browser/tab-worker.ts +89 -17
  50. package/src/tools/browser.ts +5 -0
  51. package/src/tools/find.ts +1 -2
  52. package/src/tools/index.ts +1 -1
  53. package/src/tools/puppeteer/00_stealth_tampering.txt +16 -35
  54. package/src/tools/puppeteer/01_stealth_activity.txt +79 -19
  55. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -11
  56. package/src/tools/puppeteer/03_stealth_botd.txt +10 -14
  57. package/src/tools/puppeteer/04_stealth_iframe.txt +156 -63
  58. package/src/tools/puppeteer/05_stealth_webgl.txt +222 -64
  59. package/src/tools/puppeteer/06_stealth_screen.txt +255 -67
  60. package/src/tools/puppeteer/07_stealth_fonts.txt +17 -15
  61. package/src/tools/puppeteer/08_stealth_audio.txt +32 -20
  62. package/src/tools/puppeteer/09_stealth_locale.txt +45 -40
  63. package/src/tools/puppeteer/10_stealth_plugins.txt +12 -8
  64. package/src/tools/puppeteer/11_stealth_hardware.txt +57 -6
  65. package/src/tools/puppeteer/12_stealth_codecs.txt +20 -18
  66. package/src/tools/puppeteer/13_stealth_worker.txt +206 -45
  67. package/src/tools/write.ts +1 -2
  68. package/src/utils/git.ts +3 -2
@@ -15,25 +15,27 @@ const parseInput = (arg) => {
15
15
  };
16
16
 
17
17
  const originalCanPlayType = HTMLMediaElement.prototype.canPlayType;
18
+ const proxiedCanPlayType = new Window_Proxy(originalCanPlayType, {
19
+ apply(target, ctx, args) {
20
+ if (!args || !args.length) {
21
+ return Reflect_apply(target, ctx, args);
22
+ }
23
+ const { mime, codecs } = parseInput(args[0]);
24
+ if (mime === "video/mp4" && codecs.includes("avc1.42E01E")) {
25
+ return "probably";
26
+ }
27
+ if (mime === "audio/x-m4a" && !codecs.length) {
28
+ return "maybe";
29
+ }
30
+ if (mime === "audio/aac" && !codecs.length) {
31
+ return "probably";
32
+ }
33
+ return Reflect_apply(target, ctx, args);
34
+ },
35
+ });
36
+ patchToString(proxiedCanPlayType, "canPlayType");
18
37
  Object_defineProperty(HTMLMediaElement.prototype, "canPlayType", {
19
- value: new Window_Proxy(originalCanPlayType, {
20
- apply(target, ctx, args) {
21
- if (!args || !args.length) {
22
- return Reflect_apply(target, ctx, args);
23
- }
24
- const { mime, codecs } = parseInput(args[0]);
25
- if (mime === "video/mp4" && codecs.includes("avc1.42E01E")) {
26
- return "probably";
27
- }
28
- if (mime === "audio/x-m4a" && !codecs.length) {
29
- return "maybe";
30
- }
31
- if (mime === "audio/aac" && !codecs.length) {
32
- return "probably";
33
- }
34
- return Reflect_apply(target, ctx, args);
35
- },
36
- }),
38
+ value: proxiedCanPlayType,
37
39
  writable: true,
38
40
  configurable: true,
39
41
  enumerable: true,
@@ -1,52 +1,214 @@
1
1
  const patchWorkerConstructor = (name, OriginalWorker) => {
2
2
  if (typeof OriginalWorker !== "function") return;
3
3
 
4
- const buildWrappedUrl = (scriptURL, options) => {
5
- const ua = navigator.userAgent;
6
- const platform = navigator.platform;
7
- const uaData = navigator.userAgentData && typeof navigator.userAgentData.toJSON === "function"
8
- ? navigator.userAgentData.toJSON()
9
- : navigator.userAgentData;
10
-
11
- const preludeLines = [
12
- "try {",
13
- `const ua = ${JSON.stringify(ua)};`,
14
- `const platform = ${JSON.stringify(platform)};`,
15
- "Object_defineProperty(self.navigator, 'userAgent', { get: () => ua, configurable: true });",
16
- "Object_defineProperty(self.navigator, 'platform', { get: () => platform, configurable: true });",
17
- ];
18
-
19
- if (uaData) {
20
- preludeLines.push(`const uaData = ${JSON.stringify(uaData)};`);
21
- preludeLines.push(
22
- "Object_defineProperty(self.navigator, 'userAgentData', { get: () => uaData, configurable: true });",
23
- );
4
+ const windowDescriptor = Object_getOwnPropertyDescriptor(window, name);
5
+ if (windowDescriptor && windowDescriptor.configurable === false) return;
6
+
7
+ const NativeURL = window.URL;
8
+ const URL_createObjectURL = NativeURL && NativeURL.createObjectURL;
9
+ const URL_revokeObjectURL = NativeURL && NativeURL.revokeObjectURL;
10
+ if (
11
+ typeof NativeURL !== "function" ||
12
+ typeof URL_createObjectURL !== "function" ||
13
+ typeof URL_revokeObjectURL !== "function"
14
+ ) {
15
+ return;
16
+ }
17
+
18
+ const sharedWorkerUrls = name === "SharedWorker" ? new Map() : undefined;
19
+
20
+ const revokeUrl = (url) => {
21
+ try {
22
+ Reflect_apply(URL_revokeObjectURL, NativeURL, [url]);
23
+ } catch {}
24
+ };
25
+
26
+ const scheduleWorkerUrlRevoke = (worker, url) => {
27
+ let revoked = false;
28
+ const revokeOnce = () => {
29
+ if (revoked) return;
30
+ revoked = true;
31
+ revokeUrl(url);
32
+ };
33
+ try {
34
+ if (typeof worker.addEventListener === "function") {
35
+ Reflect_apply(worker.addEventListener, worker, ["error", revokeOnce, { once: true }]);
36
+ }
37
+ } catch {}
38
+ Window_setTimeout(revokeOnce, 1000);
39
+ };
40
+
41
+ if (sharedWorkerUrls) {
42
+ try {
43
+ window.addEventListener("pagehide", (event) => {
44
+ if (event && event.persisted) return;
45
+ for (const url of sharedWorkerUrls.values()) {
46
+ revokeUrl(url);
47
+ }
48
+ sharedWorkerUrls.clear();
49
+ });
50
+ } catch {}
51
+ }
52
+
53
+ const canWrapArguments = (args) => {
54
+ if (!args || args.length !== 1) {
55
+ return name === "SharedWorker" && args && args.length === 2 && typeof args[1] === "string";
56
+ }
57
+ return true;
58
+ };
59
+
60
+ const resolveWorkerUrl = (scriptURL) => {
61
+ const baseUrl = document.baseURI || window.location.href;
62
+ const scriptUrlString =
63
+ typeof scriptURL === "string"
64
+ ? scriptURL
65
+ : scriptURL instanceof NativeURL
66
+ ? scriptURL.href
67
+ : undefined;
68
+ if (scriptUrlString === undefined) return undefined;
69
+ let absoluteUrl;
70
+ try {
71
+ absoluteUrl = new NativeURL(scriptUrlString, baseUrl);
72
+ } catch {
73
+ return undefined;
74
+ }
75
+ if (absoluteUrl.origin !== window.location.origin) return undefined;
76
+ if (absoluteUrl.protocol !== "http:" && absoluteUrl.protocol !== "https:") return undefined;
77
+ if (absoluteUrl.username || absoluteUrl.password) return undefined;
78
+ return absoluteUrl.href;
79
+ };
80
+
81
+ const buildWorkerPrelude = () => {
82
+ const values = [];
83
+ const addNavigatorString = (prop) => {
84
+ try {
85
+ const value = navigator[prop];
86
+ if (typeof value === "string") values.push([prop, value]);
87
+ } catch {}
88
+ };
89
+ addNavigatorString("userAgent");
90
+ addNavigatorString("platform");
91
+ if (!values.length) return "";
92
+
93
+ return `(() => {
94
+ try {
95
+ const values = ${JSON.stringify(values)};
96
+ const nav = self.navigator;
97
+ if (!nav) return;
98
+ const defineProperty = Object.defineProperty;
99
+ const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
100
+ const getPrototypeOf = Object.getPrototypeOf;
101
+ const Reflect_apply = Reflect.apply;
102
+ const nativeFunctionToString = Function.prototype.toString;
103
+ const nativeSources = new WeakMap();
104
+ const WeakMap_get = WeakMap.prototype.get;
105
+ const WeakMap_has = WeakMap.prototype.has;
106
+ const WeakMap_set = WeakMap.prototype.set;
107
+ const rememberNative = (fn, source) => {
108
+ if (typeof fn === "function") Reflect_apply(WeakMap_set, nativeSources, [fn, source]);
109
+ return fn;
110
+ };
111
+ const findDescriptor = (prop) => {
112
+ let owner = nav;
113
+ while (owner) {
114
+ const descriptor = getOwnPropertyDescriptor(owner, prop);
115
+ if (descriptor) return [owner, descriptor];
116
+ owner = getPrototypeOf(owner);
117
+ }
118
+ return [getPrototypeOf(nav) || nav, undefined];
119
+ };
120
+ let patched = false;
121
+ for (let i = 0; i < values.length; i += 1) {
122
+ const prop = values[i][0];
123
+ const value = values[i][1];
124
+ try {
125
+ if (nav[prop] === value) continue;
126
+ } catch (_) {}
127
+ const found = findDescriptor(prop);
128
+ const owner = found[0];
129
+ const descriptor = found[1];
130
+ if (!owner || (descriptor && descriptor.configurable === false)) continue;
131
+ const getterDescriptor = getOwnPropertyDescriptor({ get [prop]() { return value; } }, prop);
132
+ const getter = getterDescriptor && getterDescriptor.get;
133
+ if (typeof getter !== "function") continue;
134
+ rememberNative(getter, "function get " + prop + "() { [native code] }");
135
+ defineProperty(owner, prop, {
136
+ get: getter,
137
+ enumerable: descriptor ? descriptor.enumerable : true,
138
+ configurable: true,
139
+ });
140
+ patched = true;
24
141
  }
142
+ if (!patched) return;
143
+ const toStringDescriptor = getOwnPropertyDescriptor(Function.prototype, "toString");
144
+ if (toStringDescriptor && toStringDescriptor.configurable === false) return;
145
+ const functionToString = new Proxy(nativeFunctionToString, {
146
+ apply(target, thisArg, args) {
147
+ if (Reflect_apply(WeakMap_has, nativeSources, [thisArg])) return Reflect_apply(WeakMap_get, nativeSources, [thisArg]);
148
+ return Reflect_apply(target, thisArg, args);
149
+ },
150
+ });
151
+ rememberNative(functionToString, "function toString() { [native code] }");
152
+ defineProperty(Function.prototype, "toString", {
153
+ value: functionToString,
154
+ writable: toStringDescriptor ? toStringDescriptor.writable : true,
155
+ configurable: toStringDescriptor ? toStringDescriptor.configurable : true,
156
+ enumerable: toStringDescriptor ? toStringDescriptor.enumerable : false,
157
+ });
158
+ } catch (_) {}
159
+ })();`;
160
+ };
25
161
 
26
- preludeLines.push("} catch (e) {};");
27
- const prelude = preludeLines.join("\n");
28
- const importLine = options?.type === "module"
29
- ? `import ${JSON.stringify(String(scriptURL))};`
30
- : `importScripts(${JSON.stringify(String(scriptURL))});`;
31
- const blob = new Window_Blob([prelude, "\n", importLine], { type: "application/javascript" });
32
- const url = URL.createObjectURL(blob);
33
- return url;
162
+ const buildWrappedUrl = (scriptURL) => {
163
+ const originalUrl = resolveWorkerUrl(scriptURL);
164
+ if (!originalUrl) return undefined;
165
+ if (sharedWorkerUrls) {
166
+ const cachedUrl = sharedWorkerUrls.get(originalUrl);
167
+ if (cachedUrl) return { url: cachedUrl, cacheKey: originalUrl };
168
+ }
169
+
170
+ const prelude = buildWorkerPrelude();
171
+ if (!prelude) return undefined;
172
+
173
+ try {
174
+ const blob = new Window_Blob(
175
+ [prelude, "\n", `importScripts(${JSON.stringify(originalUrl)});`],
176
+ { type: "application/javascript" },
177
+ );
178
+ const url = Reflect_apply(URL_createObjectURL, NativeURL, [blob]);
179
+ if (sharedWorkerUrls) sharedWorkerUrls.set(originalUrl, url);
180
+ return { url, cacheKey: sharedWorkerUrls ? originalUrl : undefined };
181
+ } catch {
182
+ return undefined;
183
+ }
34
184
  };
35
185
 
36
186
  const handler = {
37
- construct(target, args) {
187
+ construct(target, args, newTarget) {
188
+ if (!canWrapArguments(args)) {
189
+ return Reflect_construct(target, args || [], newTarget);
190
+ }
191
+
192
+ const wrapped = buildWrappedUrl(args[0]);
193
+ if (!wrapped) {
194
+ return Reflect_construct(target, args || [], newTarget);
195
+ }
196
+
197
+ const wrappedArgs = [wrapped.url];
198
+ for (let i = 1; i < args.length; i += 1) {
199
+ wrappedArgs[i] = args[i];
200
+ }
201
+
38
202
  try {
39
- const scriptURL = args?.[0];
40
- const options = args?.[1];
41
- if (!scriptURL) {
42
- return new target(...(args || []));
203
+ const worker = Reflect_construct(target, wrappedArgs, newTarget);
204
+ if (!sharedWorkerUrls) {
205
+ scheduleWorkerUrlRevoke(worker, wrapped.url);
43
206
  }
44
- const wrappedUrl = buildWrappedUrl(scriptURL, options);
45
- const worker = new target(wrappedUrl, options);
46
- URL.revokeObjectURL(wrappedUrl);
47
207
  return worker;
48
208
  } catch {
49
- return new target(...(args || []));
209
+ if (wrapped.cacheKey && sharedWorkerUrls) sharedWorkerUrls.delete(wrapped.cacheKey);
210
+ revokeUrl(wrapped.url);
211
+ return Reflect_construct(target, args || [], newTarget);
50
212
  }
51
213
  },
52
214
  apply(target, thisArg, args) {
@@ -55,16 +217,15 @@ const patchWorkerConstructor = (name, OriginalWorker) => {
55
217
  };
56
218
 
57
219
  const proxied = new Window_Proxy(OriginalWorker, handler);
220
+ patchToString(proxied, name);
58
221
  Object_defineProperty(window, name, {
59
222
  value: proxied,
60
- writable: true,
61
- configurable: true,
62
- });
63
- Object_defineProperty(window[name], "toString", {
64
- value: Function_toString.bind(OriginalWorker),
65
- writable: false,
66
- configurable: true,
67
- enumerable: false,
223
+ writable:
224
+ windowDescriptor && "writable" in windowDescriptor
225
+ ? windowDescriptor.writable
226
+ : true,
227
+ configurable: windowDescriptor ? windowDescriptor.configurable : true,
228
+ enumerable: windowDescriptor ? windowDescriptor.enumerable : false,
68
229
  });
69
230
  };
70
231
 
@@ -293,8 +293,7 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
293
293
  readonly parameters = writeSchema;
294
294
  readonly strict = true;
295
295
  readonly concurrency = "exclusive";
296
- readonly loadMode = "discoverable";
297
- readonly summary = "Write content to a file (creates or overwrites)";
296
+ readonly loadMode = "essential";
298
297
 
299
298
  /** Stream matchers should see the real file content, not its JSON-escaped argument encoding. */
300
299
  matcherDigest(args: unknown): string | undefined {
package/src/utils/git.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import { $which, hasFsCode, isEnoent, Snowflake } from "@oh-my-pi/pi-utils";
4
+ import { $which, hasFsCode, isEisdir, isEnoent, isEnotdir, Snowflake } from "@oh-my-pi/pi-utils";
5
5
  import {
6
6
  parseDiffHunks as parseCommitDiffHunks,
7
7
  parseFileDiffs,
@@ -376,7 +376,8 @@ async function writeTempPatch(content: string): Promise<string> {
376
376
  type EntryType = "directory" | "file";
377
377
 
378
378
  function shouldRetry(err: unknown, n: number) {
379
- if (isEnoent(err) || hasFsCode(err, "ENFILE") || hasFsCode(err, "EMFILE")) return false;
379
+ if (isEnoent(err) || isEisdir(err) || isEnotdir(err) || hasFsCode(err, "ENFILE") || hasFsCode(err, "EMFILE"))
380
+ return false;
380
381
  if (hasFsCode(err, "EINTR")) return n < EINTR_MAX_RETRIES;
381
382
  if (n > EINTR_MAX_RETRIES) throw err;
382
383
  throw err;