@cydm/pie 1.0.51 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +32 -15
  2. package/dist/builtin/extensions/ask-user/index.js +4 -3
  3. package/dist/builtin/extensions/ask-user/package.json +8 -7
  4. package/dist/builtin/extensions/changelog/package.json +9 -9
  5. package/dist/builtin/extensions/computer-use/index.js +5466 -0
  6. package/dist/builtin/extensions/computer-use/package.json +11 -0
  7. package/dist/builtin/extensions/computer-use/prebuilt/linux/arm64/linux-bridge +0 -0
  8. package/dist/builtin/extensions/computer-use/prebuilt/linux/x64/linux-bridge +0 -0
  9. package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
  10. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +24 -0
  11. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
  12. package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +115 -0
  13. package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
  14. package/dist/builtin/extensions/computer-use/prebuilt/windows/windows-bridge.exe +0 -0
  15. package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +277 -0
  16. package/dist/builtin/extensions/computer-use/scripts/helper-path.mjs +48 -0
  17. package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +549 -0
  18. package/dist/builtin/extensions/document-attachments/package.json +9 -9
  19. package/dist/builtin/extensions/init/package.json +9 -9
  20. package/dist/builtin/extensions/mcp-adapter/index.js +25250 -0
  21. package/dist/builtin/extensions/mcp-adapter/package.json +11 -0
  22. package/dist/builtin/extensions/plan-mode/index.js +4 -3
  23. package/dist/builtin/extensions/plan-mode/package.json +9 -9
  24. package/dist/builtin/extensions/subagent/index.js +6 -4
  25. package/dist/builtin/extensions/subagent/package.json +16 -12
  26. package/dist/builtin/extensions/todo/index.js +4 -3
  27. package/dist/builtin/extensions/todo/package.json +9 -9
  28. package/dist/builtin/skills/chrome-devtools-axi/CHANGELOG.md +5 -0
  29. package/dist/builtin/skills/chrome-devtools-axi/README.md +17 -0
  30. package/dist/builtin/skills/chrome-devtools-axi/SKILL.md +31 -0
  31. package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +77 -0
  32. package/dist/builtin/skills/chrome-devtools-axi/package.json +12 -0
  33. package/dist/builtin/skills/tui-use/README.md +7 -0
  34. package/dist/builtin/skills/tui-use/SKILL.md +58 -0
  35. package/dist/chunks/chunk-5353DEEC.js +130 -0
  36. package/dist/chunks/{chunk-KDPAGHYY.js → chunk-G2POWIA5.js} +129 -194
  37. package/dist/chunks/{chunk-S2J3SZZX.js → chunk-IM43UYVV.js} +827 -3385
  38. package/dist/chunks/{chunk-A644H2XX.js → chunk-PMPD56N2.js} +159 -72
  39. package/dist/chunks/{chunk-B3SMW2XW.js → chunk-QJH6YN2W.js} +1 -1
  40. package/dist/chunks/chunk-XXGYUYXI.js +2718 -0
  41. package/dist/chunks/{src-UKCIAX6F.js → src-QSP2OPHU.js} +3 -2
  42. package/dist/chunks/{test-stream-NCBFPM2I.js → test-stream-CVGWFLSX.js} +2 -1
  43. package/dist/chunks/webapi-MBCKO7ZV.js +2481 -0
  44. package/dist/cli.js +149 -68
  45. package/package.json +5 -4
  46. package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -5
  47. package/dist/builtin/skills/browser-tools/README.md +0 -17
  48. package/dist/builtin/skills/browser-tools/SKILL.md +0 -43
  49. package/dist/builtin/skills/browser-tools/package.json +0 -12
  50. package/dist/builtin/skills/browser-tools/playwright-cli.js +0 -45
@@ -1,4 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ getConfigDir
4
+ } from "./chunk-5353DEEC.js";
2
5
  import {
3
6
  classifyShellCommand,
4
7
  createCodeIntelTool,
@@ -8,129 +11,16 @@ import {
8
11
  createSharedWebSearchTool,
9
12
  interpretShellExit,
10
13
  requestInteraction
11
- } from "./chunk-A644H2XX.js";
14
+ } from "./chunk-PMPD56N2.js";
12
15
  import {
13
16
  Type
14
- } from "./chunk-S2J3SZZX.js";
15
-
16
- // src/config.ts
17
- import { existsSync, mkdirSync, readFileSync, renameSync } from "fs";
18
- import { homedir } from "os";
19
- import { dirname, join } from "path";
20
- import { fileURLToPath } from "url";
21
- var __filename = fileURLToPath(import.meta.url);
22
- var __dirname = dirname(__filename);
23
- var isBunRuntime = !!process.versions.bun;
24
- function getPackageDir() {
25
- const envDir = process.env.PIE_PACKAGE_DIR;
26
- if (envDir) {
27
- if (envDir === "~") return homedir();
28
- if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
29
- return envDir;
30
- }
31
- let dir = __dirname;
32
- while (dir !== dirname(dir)) {
33
- if (existsSync(join(dir, "package.json"))) {
34
- return dir;
35
- }
36
- dir = dirname(dir);
37
- }
38
- return __dirname;
39
- }
40
- function getThemesDir() {
41
- const packageDir = getPackageDir();
42
- const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
43
- return join(packageDir, srcOrDist, "theme");
44
- }
45
- function getBuiltinDir() {
46
- const packageDir = getPackageDir();
47
- const distBuiltinDir = join(packageDir, "dist", "builtin");
48
- if (existsSync(distBuiltinDir)) {
49
- return distBuiltinDir;
50
- }
51
- return join(packageDir, "builtin");
52
- }
53
- function getPackageJsonPath() {
54
- return join(getPackageDir(), "package.json");
55
- }
56
- var pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
57
- var CONFIG_DIR_NAME = ".pie";
58
- var VERSION = pkg.version;
59
- var ENV_AGENT_DIR = "PIE_CODING_AGENT_DIR";
60
- function getConfigDir() {
61
- const envDir = process.env[ENV_AGENT_DIR];
62
- if (envDir) {
63
- if (envDir === "~") return homedir();
64
- if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
65
- return envDir;
66
- }
67
- return join(homedir(), CONFIG_DIR_NAME);
68
- }
69
- function getAgentDir() {
70
- return getConfigDir();
71
- }
72
- function getCustomThemesDir() {
73
- return join(getConfigDir(), "themes");
74
- }
75
- function getSettingsPath() {
76
- return join(getConfigDir(), "settings.json");
77
- }
78
- function getProjectSettingsPath(cwd) {
79
- return join(cwd, CONFIG_DIR_NAME, "settings.json");
80
- }
81
- function getSessionsDir() {
82
- return join(getConfigDir(), "sessions");
83
- }
84
- function getLogsDir() {
85
- return join(getConfigDir(), "logs");
86
- }
87
- function getRuntimeLogPath() {
88
- return join(getLogsDir(), "pie-cli.log");
89
- }
90
- function migrateConfigFromAgentDir() {
91
- const oldAgentDir = join(homedir(), CONFIG_DIR_NAME, "agent");
92
- const newConfigDir = getConfigDir();
93
- if (!existsSync(oldAgentDir)) {
94
- return;
95
- }
96
- if (!existsSync(newConfigDir)) {
97
- mkdirSync(newConfigDir, { recursive: true });
98
- }
99
- const filesToMigrate = [
100
- "keybindings.json",
101
- "settings.json",
102
- "pie-debug.log"
103
- ];
104
- for (const file of filesToMigrate) {
105
- const oldPath = join(oldAgentDir, file);
106
- const newPath = file === "pie-debug.log" ? getRuntimeLogPath() : join(newConfigDir, file);
107
- if (existsSync(oldPath) && !existsSync(newPath)) {
108
- try {
109
- if (file === "pie-debug.log") {
110
- mkdirSync(getLogsDir(), { recursive: true });
111
- }
112
- renameSync(oldPath, newPath);
113
- console.log(`[Config] Migrated ${file} to ${newPath}`);
114
- } catch (e) {
115
- }
116
- }
117
- }
118
- const oldThemesDir = join(oldAgentDir, "themes");
119
- const newThemesDir = getCustomThemesDir();
120
- if (existsSync(oldThemesDir) && !existsSync(newThemesDir)) {
121
- try {
122
- renameSync(oldThemesDir, newThemesDir);
123
- console.log(`[Config] Migrated themes to ${newThemesDir}`);
124
- } catch (e) {
125
- }
126
- }
127
- }
17
+ } from "./chunk-XXGYUYXI.js";
128
18
 
129
19
  // src/capabilities/bash/index.ts
130
20
  import { spawn } from "child_process";
131
- import { closeSync, createWriteStream, existsSync as existsSync2, openSync, statSync, unlinkSync, writeFileSync } from "fs";
21
+ import { closeSync, createWriteStream, existsSync, openSync, statSync, unlinkSync, writeFileSync } from "fs";
132
22
  import { tmpdir } from "os";
133
- import { join as join2, resolve as resolve2 } from "path";
23
+ import { join, resolve } from "path";
134
24
  import { createHash, randomBytes } from "crypto";
135
25
 
136
26
  // src/capabilities/bash/truncate.ts
@@ -341,7 +231,7 @@ async function requestHighRiskConfirmation(request) {
341
231
  return response.type === "confirm" && response.confirmed === true;
342
232
  }
343
233
  function validateWorkingDirectory(cwd) {
344
- if (!existsSync2(cwd)) {
234
+ if (!existsSync(cwd)) {
345
235
  throw new Error(`Invalid bash cwd: ${cwd} does not exist. Use the current workspace path or pass an existing directory in cwd.`);
346
236
  }
347
237
  let stat;
@@ -356,11 +246,11 @@ function validateWorkingDirectory(cwd) {
356
246
  }
357
247
  function normalizeWorkingDirectory(cwd, defaultCwd) {
358
248
  const requestedCwd = typeof cwd === "string" && cwd.trim().length > 0 ? cwd.trim() : void 0;
359
- return resolve2(requestedCwd ?? defaultCwd ?? process.cwd());
249
+ return resolve(requestedCwd ?? defaultCwd ?? process.cwd());
360
250
  }
361
251
  function getTempFilePath() {
362
252
  const id = randomBytes(8).toString("hex");
363
- return join2(tmpdir(), `pie-bash-${id}.log`);
253
+ return join(tmpdir(), `pie-bash-${id}.log`);
364
254
  }
365
255
  var retainedOutputArtifacts = /* @__PURE__ */ new Set();
366
256
  function getErrorCode(error) {
@@ -370,15 +260,15 @@ function getErrorCode(error) {
370
260
  }
371
261
  function createPrivateOutputArtifact() {
372
262
  for (let attempt = 0; attempt < 10; attempt++) {
373
- const path3 = getTempFilePath();
263
+ const path4 = getTempFilePath();
374
264
  try {
375
- const fd = openSync(path3, "wx", 384);
376
- retainedOutputArtifacts.add(path3);
265
+ const fd = openSync(path4, "wx", 384);
266
+ retainedOutputArtifacts.add(path4);
377
267
  try {
378
- return { path: path3, stream: createWriteStream(path3, { fd, autoClose: true }) };
268
+ return { path: path4, stream: createWriteStream(path4, { fd, autoClose: true }) };
379
269
  } catch (error) {
380
270
  closeSync(fd);
381
- removeOutputArtifact(path3);
271
+ removeOutputArtifact(path4);
382
272
  throw error;
383
273
  }
384
274
  } catch (error) {
@@ -387,34 +277,34 @@ function createPrivateOutputArtifact() {
387
277
  }
388
278
  throw new Error("Unable to allocate a private bash output artifact.");
389
279
  }
390
- function removeOutputArtifact(path3) {
391
- if (!path3) return;
280
+ function removeOutputArtifact(path4) {
281
+ if (!path4) return;
392
282
  try {
393
- unlinkSync(path3);
283
+ unlinkSync(path4);
394
284
  } catch (error) {
395
285
  if (getErrorCode(error) !== "ENOENT") throw error;
396
286
  }
397
- retainedOutputArtifacts.delete(path3);
287
+ retainedOutputArtifacts.delete(path4);
398
288
  }
399
- function discardOutputArtifact(path3, stream) {
289
+ function discardOutputArtifact(path4, stream) {
400
290
  if (stream && !stream.closed) {
401
291
  stream.once("close", () => {
402
292
  try {
403
- removeOutputArtifact(path3);
293
+ removeOutputArtifact(path4);
404
294
  } catch {
405
295
  }
406
296
  });
407
297
  stream.destroy();
408
298
  }
409
299
  try {
410
- removeOutputArtifact(path3);
300
+ removeOutputArtifact(path4);
411
301
  } catch {
412
302
  }
413
303
  }
414
304
  function cleanupBashOutputArtifacts() {
415
- for (const path3 of [...retainedOutputArtifacts]) {
305
+ for (const path4 of [...retainedOutputArtifacts]) {
416
306
  try {
417
- removeOutputArtifact(path3);
307
+ removeOutputArtifact(path4);
418
308
  } catch {
419
309
  }
420
310
  }
@@ -422,7 +312,7 @@ function cleanupBashOutputArtifacts() {
422
312
  process.once("exit", cleanupBashOutputArtifacts);
423
313
  function finishTempFileStream(stream) {
424
314
  if (!stream || stream.closed) return Promise.resolve();
425
- return new Promise((resolve3, reject) => {
315
+ return new Promise((resolve2, reject) => {
426
316
  let done = false;
427
317
  const cleanup = () => {
428
318
  stream.off("close", onClose);
@@ -432,7 +322,7 @@ function finishTempFileStream(stream) {
432
322
  if (done) return;
433
323
  done = true;
434
324
  cleanup();
435
- resolve3();
325
+ resolve2();
436
326
  };
437
327
  const onError = (error) => {
438
328
  if (done) return;
@@ -581,7 +471,7 @@ function createBashTool(defaultCwd, options) {
581
471
  }
582
472
  const timeoutPolicy = resolveTimeoutPolicy(timeout, risk.commandClass);
583
473
  const timeoutMs = timeoutPolicy.effectiveSeconds * 1e3;
584
- return new Promise((resolve3, reject) => {
474
+ return new Promise((resolve2, reject) => {
585
475
  if (signal?.aborted) {
586
476
  reject(new Error("Operation aborted"));
587
477
  return;
@@ -736,10 +626,10 @@ ${fullOutput}`;
736
626
  }
737
627
  let outputText = truncation.content || "(no output)";
738
628
  if (truncation.truncated && !tempFilePath) {
739
- const path3 = getTempFilePath();
740
- const fd = openSync(path3, "wx", 384);
741
- tempFilePath = path3;
742
- retainedOutputArtifacts.add(path3);
629
+ const path4 = getTempFilePath();
630
+ const fd = openSync(path4, "wx", 384);
631
+ tempFilePath = path4;
632
+ retainedOutputArtifacts.add(path4);
743
633
  try {
744
634
  writeFileSync(fd, fullOutput, "utf-8");
745
635
  } finally {
@@ -827,7 +717,7 @@ ${commandNonzeroHint}`;
827
717
  }
828
718
  const content = [{ type: "text", text: outputText }];
829
719
  settled = true;
830
- resolve3({ content, details, isError: outcome.toolFailure });
720
+ resolve2({ content, details, isError: outcome.toolFailure });
831
721
  } catch (error) {
832
722
  discardOutputArtifact(tempFilePath, tempFileStream);
833
723
  settled = true;
@@ -845,7 +735,7 @@ ${commandNonzeroHint}`;
845
735
  // src/capabilities/code-intel.ts
846
736
  import * as fs from "node:fs";
847
737
  import * as path from "node:path";
848
- import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
738
+ import { fileURLToPath, pathToFileURL } from "node:url";
849
739
  import { Worker } from "node:worker_threads";
850
740
  var WORKER_TIMEOUT_MS = 3e4;
851
741
  var MAX_ACTIVE_CODE_INTEL_WORKERS = 1;
@@ -873,8 +763,8 @@ function acquireWorkerSlot(deadline, signal) {
873
763
  if (codeIntelWorkerWaiters.length >= MAX_QUEUED_CODE_INTEL_WORKERS) {
874
764
  return Promise.reject(new Error("TypeScript code intelligence queue is full"));
875
765
  }
876
- return new Promise((resolve3, reject) => {
877
- const waiter = { resolve: () => resolve3(releaseWorkerSlot), reject, signal };
766
+ return new Promise((resolve2, reject) => {
767
+ const waiter = { resolve: () => resolve2(releaseWorkerSlot), reject, signal };
878
768
  waiter.onAbort = () => {
879
769
  const index = codeIntelWorkerWaiters.indexOf(waiter);
880
770
  if (index >= 0) codeIntelWorkerWaiters.splice(index, 1);
@@ -893,7 +783,7 @@ function acquireWorkerSlot(deadline, signal) {
893
783
  });
894
784
  }
895
785
  function resolveWorkerPath() {
896
- const moduleDirectory = path.dirname(fileURLToPath2(import.meta.url));
786
+ const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));
897
787
  const candidates = [
898
788
  path.join(moduleDirectory, "code-intel-worker.cjs"),
899
789
  path.join(moduleDirectory, "..", "code-intel-worker.cjs"),
@@ -904,7 +794,7 @@ function resolveWorkerPath() {
904
794
  return workerPath;
905
795
  }
906
796
  function runWorker(request, timeoutMs, signal) {
907
- return new Promise((resolve3, reject) => {
797
+ return new Promise((resolve2, reject) => {
908
798
  if (signal?.aborted) {
909
799
  reject(new Error("Operation aborted"));
910
800
  return;
@@ -929,7 +819,7 @@ function runWorker(request, timeoutMs, signal) {
929
819
  }
930
820
  }
931
821
  if (error) reject(error);
932
- else resolve3(result);
822
+ else resolve2(result);
933
823
  })();
934
824
  };
935
825
  const onAbort = () => finish(new Error("Operation aborted"));
@@ -1017,21 +907,32 @@ function createCodeIntelTool2(options) {
1017
907
  // src/capabilities/rendered-page-reader.ts
1018
908
  import { spawn as spawn2 } from "node:child_process";
1019
909
  import { createRequire } from "node:module";
910
+ import * as fs2 from "node:fs";
911
+ import * as os from "node:os";
912
+ import * as path2 from "node:path";
1020
913
  var require2 = createRequire(import.meta.url);
1021
- function resolvePlaywrightCli() {
1022
- return require2.resolve("@playwright/cli/playwright-cli.js");
914
+ function resolveAxiCli() {
915
+ const packageJson = require2.resolve("chrome-devtools-axi/package.json");
916
+ return path2.join(path2.dirname(packageJson), "dist", "bin", "chrome-devtools-axi.js");
917
+ }
918
+ function resolveMcpScript() {
919
+ const packageJson = require2.resolve("chrome-devtools-mcp/package.json");
920
+ return path2.join(path2.dirname(packageJson), "build", "src", "bin", "chrome-devtools-mcp.js");
1023
921
  }
1024
- function runPlaywright(args, timeoutMs = 6e4) {
1025
- return new Promise((resolve3, reject) => {
1026
- const child = spawn2(process.execPath, [resolvePlaywrightCli(), ...args], {
922
+ function runAxi(args, options = {}) {
923
+ const timeoutMs = options.timeoutMs ?? 6e4;
924
+ return new Promise((resolve2, reject) => {
925
+ const child = spawn2(process.execPath, [resolveAxiCli(), ...args], {
1027
926
  stdio: ["ignore", "pipe", "pipe"],
1028
- shell: false
927
+ shell: false,
928
+ env: options.env,
929
+ cwd: options.cwd
1029
930
  });
1030
931
  let stdout = "";
1031
932
  let stderr = "";
1032
933
  const timer = setTimeout(() => {
1033
934
  child.kill("SIGTERM");
1034
- reject(new Error(`Playwright CLI timed out after ${Math.ceil(timeoutMs / 1e3)} seconds`));
935
+ reject(new Error(`chrome-devtools-axi timed out after ${Math.ceil(timeoutMs / 1e3)} seconds`));
1035
936
  }, timeoutMs);
1036
937
  child.stdout.setEncoding("utf8");
1037
938
  child.stderr.setEncoding("utf8");
@@ -1047,24 +948,40 @@ function runPlaywright(args, timeoutMs = 6e4) {
1047
948
  });
1048
949
  child.on("close", (code) => {
1049
950
  clearTimeout(timer);
1050
- if (code === 0) resolve3(stdout.trim());
1051
- else reject(new Error((stderr || stdout || `Playwright CLI exited with ${code}`).trim()));
951
+ if (code === 0) resolve2(stdout.trim());
952
+ else reject(new Error((stderr || stdout || `chrome-devtools-axi exited with ${code}`).trim()));
1052
953
  });
1053
954
  });
1054
955
  }
1055
956
  function linesOf(output, max = 50) {
1056
- return output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).slice(0, max);
957
+ if (/^(console|network)_failed:/i.test(output.trim())) return [];
958
+ return output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).filter((line) => !/^(console:|network:|##\s|Showing \d|\(\d+ args\)$|<no .+ found>$|no \w+ found\.$)/i.test(line)).slice(0, max);
1057
959
  }
1058
960
  function parseScreenshotPath(output) {
1059
- const match = output.match(/\(([^)]+\.png)\)/i) || output.match(/([^\s]+\.png)/i);
961
+ if (output.startsWith("screenshot_failed:")) return void 0;
962
+ const match = output.match(/(?:^|\n)screenshot:\s*(\S+)/i) || output.match(/([^\s]+\.(?:png|jpe?g|webp))/i);
1060
963
  return match?.[1];
1061
964
  }
965
+ function unwrapJsonValue(payload) {
966
+ let value = payload;
967
+ for (let depth = 0; depth < 4; depth += 1) {
968
+ if (typeof value !== "string") break;
969
+ const text = value.trim();
970
+ if (!text.startsWith('"') && !text.startsWith("{") && !text.startsWith("[")) break;
971
+ try {
972
+ value = JSON.parse(text);
973
+ } catch {
974
+ break;
975
+ }
976
+ }
977
+ return value;
978
+ }
1062
979
  function parsePageInfo(raw) {
1063
980
  const trimmed = raw.trim();
1064
981
  if (!trimmed) return {};
982
+ const payload = trimmed.replace(/^result:\s*/i, "");
1065
983
  try {
1066
- const decoded = trimmed.startsWith('"') ? JSON.parse(trimmed) : trimmed;
1067
- const parsed = typeof decoded === "string" ? JSON.parse(decoded) : decoded;
984
+ const parsed = unwrapJsonValue(payload);
1068
985
  if (!parsed || typeof parsed !== "object") return {};
1069
986
  return {
1070
987
  finalUrl: typeof parsed.href === "string" ? parsed.href : void 0,
@@ -1075,23 +992,53 @@ function parsePageInfo(raw) {
1075
992
  return {};
1076
993
  }
1077
994
  }
995
+ function stripHelpHints(output) {
996
+ return output.replace(/(?:^|\n)help\[\d+\]:[\s\S]*$/i, "").trim();
997
+ }
998
+ function parseSnapshot(output) {
999
+ const match = output.match(/(?:^|\n)snapshot:\n([\s\S]*)$/i);
1000
+ return stripHelpHints(match ? match[1] : output);
1001
+ }
1002
+ function cleanStaleScreenshotDirs(retentionMs = 60 * 60 * 1e3) {
1003
+ try {
1004
+ const tmp = os.tmpdir();
1005
+ const cutoff = Date.now() - retentionMs;
1006
+ for (const entry of fs2.readdirSync(tmp)) {
1007
+ if (!entry.startsWith("pie-axi-shot-")) continue;
1008
+ const dir = path2.join(tmp, entry);
1009
+ try {
1010
+ if (fs2.statSync(dir).mtimeMs < cutoff) fs2.rmSync(dir, { recursive: true, force: true });
1011
+ } catch {
1012
+ }
1013
+ }
1014
+ } catch {
1015
+ }
1016
+ }
1078
1017
  function createCliRenderedPageReader() {
1079
1018
  return async ({ url }) => {
1080
1019
  const session = `pie-web-research-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1020
+ const env = { ...process.env, CHROME_DEVTOOLS_AXI_SESSION: session };
1021
+ delete env.CHROME_DEVTOOLS_AXI_PORT;
1022
+ if (!env.CHROME_DEVTOOLS_AXI_MCP_PATH?.trim()) env.CHROME_DEVTOOLS_AXI_MCP_PATH = resolveMcpScript();
1023
+ if (!env.CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS) env.CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS = "1";
1024
+ cleanStaleScreenshotDirs();
1025
+ const screenshotDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "pie-axi-shot-"));
1081
1026
  try {
1082
- await runPlaywright([`-s=${session}`, "open", "about:blank"]);
1083
- await runPlaywright([`-s=${session}`, "goto", url]);
1084
- const [snapshot, pageInfoRaw, screenshotOutput, consoleOutput, requestsOutput] = await Promise.all([
1085
- runPlaywright([`-s=${session}`, "snapshot"]),
1086
- runPlaywright([`-s=${session}`, "--raw", "eval", "() => JSON.stringify({ title: document.title, href: location.href, text: document.body ? document.body.innerText : '' })"]),
1087
- runPlaywright([`-s=${session}`, "--raw", "screenshot"]).catch((error) => `screenshot_failed: ${error instanceof Error ? error.message : String(error)}`),
1088
- runPlaywright([`-s=${session}`, "--raw", "console"]).catch((error) => `console_failed: ${error instanceof Error ? error.message : String(error)}`),
1089
- runPlaywright([`-s=${session}`, "--raw", "requests"]).catch((error) => `requests_failed: ${error instanceof Error ? error.message : String(error)}`)
1027
+ await runAxi(["open", `data:text/html,<title>pie-warm-${session}</title>`], { env });
1028
+ await runAxi(["open", url], { env });
1029
+ const [snapshotOutput, pageInfoRaw, screenshotOutput, consoleOutput, networkOutput] = await Promise.all([
1030
+ runAxi(["snapshot"], { env }),
1031
+ // --full: eval output is truncated at ~8KB by default, which would
1032
+ // break JSON parsing and drop title/finalUrl/text on real pages.
1033
+ runAxi(["eval", "() => JSON.stringify({ title: document.title, href: location.href, text: document.body ? document.body.innerText : '' })", "--full"], { env }),
1034
+ runAxi(["screenshot", path2.join(screenshotDir, "page.png")], { env }).catch((error) => `screenshot_failed: ${error instanceof Error ? error.message : String(error)}`),
1035
+ runAxi(["console"], { env }).catch((error) => `console_failed: ${error instanceof Error ? error.message : String(error)}`),
1036
+ runAxi(["network"], { env }).catch((error) => `network_failed: ${error instanceof Error ? error.message : String(error)}`)
1090
1037
  ]);
1091
- const pageInfo = parsePageInfo(pageInfoRaw);
1092
- const text = pageInfo.text?.trim() || snapshot.trim();
1038
+ const pageInfo = parsePageInfo(stripHelpHints(pageInfoRaw));
1039
+ const text = pageInfo.text?.trim() || parseSnapshot(snapshotOutput);
1093
1040
  if (!text) {
1094
- throw new Error("Playwright snapshot returned no text.");
1041
+ throw new Error("chrome-devtools-axi snapshot returned no text.");
1095
1042
  }
1096
1043
  return {
1097
1044
  url,
@@ -1100,18 +1047,18 @@ function createCliRenderedPageReader() {
1100
1047
  text,
1101
1048
  citationAnchors: [{ url: pageInfo.finalUrl || url, title: pageInfo.title, startOffset: 0, endOffset: Math.min(120, text.length) }],
1102
1049
  screenshotPath: parseScreenshotPath(screenshotOutput),
1103
- consoleMessages: linesOf(consoleOutput),
1104
- networkRequests: linesOf(requestsOutput)
1050
+ consoleMessages: linesOf(stripHelpHints(consoleOutput)),
1051
+ networkRequests: linesOf(stripHelpHints(networkOutput))
1105
1052
  };
1106
1053
  } finally {
1107
- runPlaywright([`-s=${session}`, "close"], 1e4).catch(() => void 0);
1054
+ runAxi(["stop"], { env, timeoutMs: 1e4 }).catch(() => void 0);
1108
1055
  }
1109
1056
  };
1110
1057
  }
1111
1058
 
1112
1059
  // src/capabilities/web-research-health.ts
1113
- import fs2 from "node:fs";
1114
- import path2 from "node:path";
1060
+ import fs3 from "node:fs";
1061
+ import path3 from "node:path";
1115
1062
  function isRecord(value) {
1116
1063
  return !!value && typeof value === "object" && !Array.isArray(value);
1117
1064
  }
@@ -1133,11 +1080,11 @@ function parseHealthEntry(value) {
1133
1080
  };
1134
1081
  }
1135
1082
  function createCliWebResearchHealthStore(configDir) {
1136
- const filePath = path2.join(configDir, "web-research-health.json");
1083
+ const filePath = path3.join(configDir, "web-research-health.json");
1137
1084
  return {
1138
1085
  loadProviderHealth: () => {
1139
1086
  try {
1140
- const parsed = JSON.parse(fs2.readFileSync(filePath, "utf8"));
1087
+ const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8"));
1141
1088
  if (!Array.isArray(parsed)) return [];
1142
1089
  return parsed.map(parseHealthEntry).filter((entry) => !!entry);
1143
1090
  } catch {
@@ -1146,8 +1093,8 @@ function createCliWebResearchHealthStore(configDir) {
1146
1093
  },
1147
1094
  saveProviderHealth: (entries) => {
1148
1095
  try {
1149
- fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
1150
- fs2.writeFileSync(filePath, JSON.stringify(entries, null, 2));
1096
+ fs3.mkdirSync(path3.dirname(filePath), { recursive: true });
1097
+ fs3.writeFileSync(filePath, JSON.stringify(entries, null, 2));
1151
1098
  } catch {
1152
1099
  }
1153
1100
  }
@@ -1213,22 +1160,10 @@ function createCliHostCapabilities(cwd, options = {}) {
1213
1160
  }
1214
1161
 
1215
1162
  export {
1216
- getPackageDir,
1217
- getThemesDir,
1218
- getBuiltinDir,
1219
- VERSION,
1220
- getConfigDir,
1221
- getAgentDir,
1222
- getCustomThemesDir,
1223
- getSettingsPath,
1224
- getProjectSettingsPath,
1225
- getSessionsDir,
1226
- getLogsDir,
1227
- getRuntimeLogPath,
1228
- migrateConfigFromAgentDir,
1229
1163
  createCliWebResearchHealthStore,
1230
1164
  truncateHeadTail,
1231
1165
  formatSize,
1232
1166
  cleanupBashOutputArtifacts,
1167
+ createBashTool,
1233
1168
  createCliHostCapabilities
1234
1169
  };