@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.
- package/README.md +32 -15
- package/dist/builtin/extensions/ask-user/index.js +4 -3
- package/dist/builtin/extensions/ask-user/package.json +8 -7
- package/dist/builtin/extensions/changelog/package.json +9 -9
- package/dist/builtin/extensions/computer-use/index.js +5466 -0
- package/dist/builtin/extensions/computer-use/package.json +11 -0
- package/dist/builtin/extensions/computer-use/prebuilt/linux/arm64/linux-bridge +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/linux/x64/linux-bridge +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +24 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +115 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/windows/windows-bridge.exe +0 -0
- package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +277 -0
- package/dist/builtin/extensions/computer-use/scripts/helper-path.mjs +48 -0
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +549 -0
- package/dist/builtin/extensions/document-attachments/package.json +9 -9
- package/dist/builtin/extensions/init/package.json +9 -9
- package/dist/builtin/extensions/mcp-adapter/index.js +25250 -0
- package/dist/builtin/extensions/mcp-adapter/package.json +11 -0
- package/dist/builtin/extensions/plan-mode/index.js +4 -3
- package/dist/builtin/extensions/plan-mode/package.json +9 -9
- package/dist/builtin/extensions/subagent/index.js +6 -4
- package/dist/builtin/extensions/subagent/package.json +16 -12
- package/dist/builtin/extensions/todo/index.js +4 -3
- package/dist/builtin/extensions/todo/package.json +9 -9
- package/dist/builtin/skills/chrome-devtools-axi/CHANGELOG.md +5 -0
- package/dist/builtin/skills/chrome-devtools-axi/README.md +17 -0
- package/dist/builtin/skills/chrome-devtools-axi/SKILL.md +31 -0
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +77 -0
- package/dist/builtin/skills/chrome-devtools-axi/package.json +12 -0
- package/dist/builtin/skills/tui-use/README.md +7 -0
- package/dist/builtin/skills/tui-use/SKILL.md +58 -0
- package/dist/chunks/chunk-5353DEEC.js +130 -0
- package/dist/chunks/{chunk-KDPAGHYY.js → chunk-G2POWIA5.js} +129 -194
- package/dist/chunks/{chunk-S2J3SZZX.js → chunk-IM43UYVV.js} +827 -3385
- package/dist/chunks/{chunk-A644H2XX.js → chunk-PMPD56N2.js} +159 -72
- package/dist/chunks/{chunk-B3SMW2XW.js → chunk-QJH6YN2W.js} +1 -1
- package/dist/chunks/chunk-XXGYUYXI.js +2718 -0
- package/dist/chunks/{src-UKCIAX6F.js → src-QSP2OPHU.js} +3 -2
- package/dist/chunks/{test-stream-NCBFPM2I.js → test-stream-CVGWFLSX.js} +2 -1
- package/dist/chunks/webapi-MBCKO7ZV.js +2481 -0
- package/dist/cli.js +149 -68
- package/package.json +5 -4
- package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -5
- package/dist/builtin/skills/browser-tools/README.md +0 -17
- package/dist/builtin/skills/browser-tools/SKILL.md +0 -43
- package/dist/builtin/skills/browser-tools/package.json +0 -12
- 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-
|
|
14
|
+
} from "./chunk-PMPD56N2.js";
|
|
12
15
|
import {
|
|
13
16
|
Type
|
|
14
|
-
} from "./chunk-
|
|
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
|
|
21
|
+
import { closeSync, createWriteStream, existsSync, openSync, statSync, unlinkSync, writeFileSync } from "fs";
|
|
132
22
|
import { tmpdir } from "os";
|
|
133
|
-
import { join
|
|
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 (!
|
|
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
|
|
249
|
+
return resolve(requestedCwd ?? defaultCwd ?? process.cwd());
|
|
360
250
|
}
|
|
361
251
|
function getTempFilePath() {
|
|
362
252
|
const id = randomBytes(8).toString("hex");
|
|
363
|
-
return
|
|
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
|
|
263
|
+
const path4 = getTempFilePath();
|
|
374
264
|
try {
|
|
375
|
-
const fd = openSync(
|
|
376
|
-
retainedOutputArtifacts.add(
|
|
265
|
+
const fd = openSync(path4, "wx", 384);
|
|
266
|
+
retainedOutputArtifacts.add(path4);
|
|
377
267
|
try {
|
|
378
|
-
return { path:
|
|
268
|
+
return { path: path4, stream: createWriteStream(path4, { fd, autoClose: true }) };
|
|
379
269
|
} catch (error) {
|
|
380
270
|
closeSync(fd);
|
|
381
|
-
removeOutputArtifact(
|
|
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(
|
|
391
|
-
if (!
|
|
280
|
+
function removeOutputArtifact(path4) {
|
|
281
|
+
if (!path4) return;
|
|
392
282
|
try {
|
|
393
|
-
unlinkSync(
|
|
283
|
+
unlinkSync(path4);
|
|
394
284
|
} catch (error) {
|
|
395
285
|
if (getErrorCode(error) !== "ENOENT") throw error;
|
|
396
286
|
}
|
|
397
|
-
retainedOutputArtifacts.delete(
|
|
287
|
+
retainedOutputArtifacts.delete(path4);
|
|
398
288
|
}
|
|
399
|
-
function discardOutputArtifact(
|
|
289
|
+
function discardOutputArtifact(path4, stream) {
|
|
400
290
|
if (stream && !stream.closed) {
|
|
401
291
|
stream.once("close", () => {
|
|
402
292
|
try {
|
|
403
|
-
removeOutputArtifact(
|
|
293
|
+
removeOutputArtifact(path4);
|
|
404
294
|
} catch {
|
|
405
295
|
}
|
|
406
296
|
});
|
|
407
297
|
stream.destroy();
|
|
408
298
|
}
|
|
409
299
|
try {
|
|
410
|
-
removeOutputArtifact(
|
|
300
|
+
removeOutputArtifact(path4);
|
|
411
301
|
} catch {
|
|
412
302
|
}
|
|
413
303
|
}
|
|
414
304
|
function cleanupBashOutputArtifacts() {
|
|
415
|
-
for (const
|
|
305
|
+
for (const path4 of [...retainedOutputArtifacts]) {
|
|
416
306
|
try {
|
|
417
|
-
removeOutputArtifact(
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
|
740
|
-
const fd = openSync(
|
|
741
|
-
tempFilePath =
|
|
742
|
-
retainedOutputArtifacts.add(
|
|
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
|
-
|
|
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
|
|
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((
|
|
877
|
-
const waiter = { resolve: () =>
|
|
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(
|
|
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((
|
|
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
|
|
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
|
|
1022
|
-
|
|
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
|
|
1025
|
-
|
|
1026
|
-
|
|
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(`
|
|
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)
|
|
1051
|
-
else reject(new Error((stderr || stdout || `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
1083
|
-
await
|
|
1084
|
-
const [
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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() ||
|
|
1038
|
+
const pageInfo = parsePageInfo(stripHelpHints(pageInfoRaw));
|
|
1039
|
+
const text = pageInfo.text?.trim() || parseSnapshot(snapshotOutput);
|
|
1093
1040
|
if (!text) {
|
|
1094
|
-
throw new Error("
|
|
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(
|
|
1050
|
+
consoleMessages: linesOf(stripHelpHints(consoleOutput)),
|
|
1051
|
+
networkRequests: linesOf(stripHelpHints(networkOutput))
|
|
1105
1052
|
};
|
|
1106
1053
|
} finally {
|
|
1107
|
-
|
|
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
|
|
1114
|
-
import
|
|
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 =
|
|
1083
|
+
const filePath = path3.join(configDir, "web-research-health.json");
|
|
1137
1084
|
return {
|
|
1138
1085
|
loadProviderHealth: () => {
|
|
1139
1086
|
try {
|
|
1140
|
-
const parsed = JSON.parse(
|
|
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
|
-
|
|
1150
|
-
|
|
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
|
};
|