@cydm/pie 1.0.22 → 1.0.24

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.
@@ -0,0 +1,95 @@
1
+ import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+
3
+ // src/session-preview-worker-protocol.ts
4
+ var SESSION_PREVIEW_WORKER_PROTOCOL_VERSION = 1;
5
+ var SESSION_PREVIEW_WORKER_INPUT_BYTES = 32 * 1024;
6
+ var SESSION_PREVIEW_WORKER_OUTPUT_BYTES = 4 * 1024;
7
+ var SESSION_PREVIEW_WORKER_TIMEOUT_MS = 6e4;
8
+ var DURABLE_ROLES = /* @__PURE__ */ new Set(["main", "backup", "previous"]);
9
+ function isFiniteNumber(value) {
10
+ return typeof value === "number" && Number.isFinite(value);
11
+ }
12
+ function isSessionPreviewWorkerRequest(value) {
13
+ if (!value || typeof value !== "object") return false;
14
+ const request = value;
15
+ if (request.version !== SESSION_PREVIEW_WORKER_PROTOCOL_VERSION || !Array.isArray(request.files)) return false;
16
+ if (request.files.length < 1 || request.files.length > 3) return false;
17
+ const seenRoles = /* @__PURE__ */ new Set();
18
+ for (const candidate of request.files) {
19
+ if (!candidate || typeof candidate !== "object") return false;
20
+ const file = candidate;
21
+ if (!DURABLE_ROLES.has(file.role) || seenRoles.has(file.role)) return false;
22
+ seenRoles.add(file.role);
23
+ if (typeof file.path !== "string" || file.path.length === 0) return false;
24
+ if (!isFiniteNumber(file.size) || file.size < 0) return false;
25
+ for (const key of ["mtimeMs", "ctimeMs", "dev", "ino"]) {
26
+ if (!isFiniteNumber(file[key])) return false;
27
+ }
28
+ }
29
+ return true;
30
+ }
31
+ function isSessionPreviewWorkerResponse(value) {
32
+ if (!value || typeof value !== "object") return false;
33
+ const response = value;
34
+ return response.version === SESSION_PREVIEW_WORKER_PROTOCOL_VERSION && (response.preview === null || typeof response.preview === "string");
35
+ }
36
+
37
+ // src/session-preview-utils.ts
38
+ var MAX_SESSION_PREVIEW_ENTRIES = 50;
39
+ var MAX_SESSION_PREVIEW_LENGTH = 120;
40
+ function extractTextFromSessionContent(content) {
41
+ if (typeof content === "string") return content;
42
+ if (Array.isArray(content)) {
43
+ const parts = [];
44
+ for (const block of content) {
45
+ if (block && typeof block === "object" && block.type === "text") {
46
+ parts.push(block.text || "");
47
+ }
48
+ }
49
+ return parts.join(" ");
50
+ }
51
+ return "";
52
+ }
53
+ function normalizeSessionPreview(text) {
54
+ let normalized = "";
55
+ let pendingSpace = false;
56
+ for (let index = 0; index < text.length; index += 1) {
57
+ const char = text[index];
58
+ if (/\s/.test(char)) {
59
+ if (normalized) pendingSpace = true;
60
+ continue;
61
+ }
62
+ if (pendingSpace) {
63
+ normalized += " ";
64
+ pendingSpace = false;
65
+ if (normalized.length > MAX_SESSION_PREVIEW_LENGTH) break;
66
+ }
67
+ normalized += char;
68
+ if (normalized.length > MAX_SESSION_PREVIEW_LENGTH) break;
69
+ }
70
+ if (!normalized) return null;
71
+ const preview = normalized.length > MAX_SESSION_PREVIEW_LENGTH ? `${normalized.slice(0, MAX_SESSION_PREVIEW_LENGTH)}...` : normalized;
72
+ return Buffer.from(preview, "utf-8").toString("utf-8");
73
+ }
74
+ function extractPreviewFromSessionData(data) {
75
+ if (!Array.isArray(data.entries)) return null;
76
+ for (const entry of data.entries.slice(0, MAX_SESSION_PREVIEW_ENTRIES)) {
77
+ if (entry?.type !== "message" || entry.message?.role !== "user") continue;
78
+ const preview = normalizeSessionPreview(extractTextFromSessionContent(entry.message.content));
79
+ if (preview) return preview;
80
+ }
81
+ return null;
82
+ }
83
+
84
+ export {
85
+ SESSION_PREVIEW_WORKER_PROTOCOL_VERSION,
86
+ SESSION_PREVIEW_WORKER_INPUT_BYTES,
87
+ SESSION_PREVIEW_WORKER_OUTPUT_BYTES,
88
+ SESSION_PREVIEW_WORKER_TIMEOUT_MS,
89
+ isSessionPreviewWorkerRequest,
90
+ isSessionPreviewWorkerResponse,
91
+ MAX_SESSION_PREVIEW_ENTRIES,
92
+ extractTextFromSessionContent,
93
+ normalizeSessionPreview,
94
+ extractPreviewFromSessionData
95
+ };
@@ -6,12 +6,14 @@ import {
6
6
  createSharedWebFetchTool,
7
7
  createSharedWebResearchTool,
8
8
  createSharedWebSearchTool,
9
- interpretShellExit,
9
+ interpretShellExit
10
+ } from "./chunk-XWNIIJ3X.js";
11
+ import {
10
12
  requestInteraction
11
- } from "./chunk-NHR6EBM2.js";
13
+ } from "./chunk-J4P2LP7K.js";
12
14
  import {
13
15
  Type
14
- } from "./chunk-VESPMEDG.js";
16
+ } from "./chunk-HAAYC2N5.js";
15
17
 
16
18
  // src/config.ts
17
19
  import { existsSync, mkdirSync, readFileSync, renameSync } from "fs";
@@ -75,6 +77,9 @@ function getCustomThemesDir() {
75
77
  function getSettingsPath() {
76
78
  return join(getConfigDir(), "settings.json");
77
79
  }
80
+ function getProjectSettingsPath(cwd) {
81
+ return join(cwd, CONFIG_DIR_NAME, "settings.json");
82
+ }
78
83
  function getSessionsDir() {
79
84
  return join(getConfigDir(), "sessions");
80
85
  }
@@ -126,8 +131,8 @@ function migrateConfigFromAgentDir() {
126
131
  // src/capabilities/bash/index.ts
127
132
  import { spawn } from "child_process";
128
133
  import { createWriteStream, existsSync as existsSync2, statSync, writeFileSync } from "fs";
129
- import { tmpdir } from "os";
130
- import { join as join2 } from "path";
134
+ import { tmpdir, homedir as homedir2 } from "os";
135
+ import { join as join2, resolve as resolve2 } from "path";
131
136
  import { randomBytes } from "crypto";
132
137
 
133
138
  // src/capabilities/bash/truncate.ts
@@ -263,7 +268,7 @@ function buildSpawnCommand(shell, command) {
263
268
  if (shell === "cmd") {
264
269
  return { file: "cmd.exe", args: ["/d", "/s", "/c", command], shell: false };
265
270
  }
266
- return { file: command, args: [], shell: true };
271
+ return { file: process.platform === "win32" ? "bash.exe" : "bash", args: ["-c", command], shell: false };
267
272
  }
268
273
  async function requestHighRiskConfirmation(request) {
269
274
  const response = await requestInteraction({
@@ -296,7 +301,7 @@ function validateWorkingDirectory(cwd) {
296
301
  }
297
302
  function normalizeWorkingDirectory(cwd, defaultCwd) {
298
303
  const requestedCwd = typeof cwd === "string" && cwd.trim().length > 0 ? cwd.trim() : void 0;
299
- return requestedCwd ?? defaultCwd ?? process.cwd();
304
+ return resolve2(requestedCwd ?? defaultCwd ?? process.cwd());
300
305
  }
301
306
  function getTempFilePath() {
302
307
  const id = randomBytes(8).toString("hex");
@@ -304,7 +309,7 @@ function getTempFilePath() {
304
309
  }
305
310
  function finishTempFileStream(stream) {
306
311
  if (!stream) return Promise.resolve();
307
- return new Promise((resolve3, reject) => {
312
+ return new Promise((resolve4, reject) => {
308
313
  const onError = (error) => {
309
314
  stream.off("error", onError);
310
315
  reject(error);
@@ -312,7 +317,7 @@ function finishTempFileStream(stream) {
312
317
  stream.once("error", onError);
313
318
  stream.end(() => {
314
319
  stream.off("error", onError);
315
- resolve3();
320
+ resolve4();
316
321
  });
317
322
  });
318
323
  }
@@ -357,7 +362,35 @@ function createBashTool(defaultCwd, options) {
357
362
  const effectiveCommand = buildEffectiveCommand(command, options);
358
363
  const workingDir = normalizeWorkingDirectory(cwd, defaultCwd);
359
364
  validateWorkingDirectory(workingDir);
360
- const risk = classifyShellCommand(effectiveCommand, resolvedShell);
365
+ const risk = classifyShellCommand(effectiveCommand, resolvedShell, {
366
+ homeDir: homedir2(),
367
+ cwd: workingDir,
368
+ env: process.env,
369
+ pathStyle: process.platform === "win32" ? "windows" : "posix"
370
+ });
371
+ if (risk.destructive && risk.catastrophic) {
372
+ const targetExplanation = risk.catastrophicReason === "indeterminate_target" ? "The agent shell tool cannot statically prove every deletion target is scoped" : "The command targets a filesystem root, home directory, or system directory";
373
+ return {
374
+ content: [{
375
+ type: "text",
376
+ text: `Blocked catastrophic shell command (${risk.commandClass}): ${risk.riskWarnings.join("; ")}. ${targetExplanation} and is never executed, even in YOLO mode, by the agent shell tool. Narrow the target to a statically resolvable subdirectory and retry.`
377
+ }],
378
+ details: {
379
+ exitCode: null,
380
+ signal: null,
381
+ timedOut: false,
382
+ shell: resolvedShell,
383
+ commandClass: risk.commandClass,
384
+ riskWarnings: risk.riskWarnings,
385
+ permissionDecision: {
386
+ allowed: false,
387
+ reason: "catastrophic command blocked by shell policy",
388
+ requiresPermission: true
389
+ }
390
+ },
391
+ isError: true
392
+ };
393
+ }
361
394
  if (risk.destructive && !options?.isYoloMode?.()) {
362
395
  const approved = await (options?.confirm ?? requestHighRiskConfirmation)({
363
396
  command: effectiveCommand,
@@ -389,7 +422,7 @@ function createBashTool(defaultCwd, options) {
389
422
  }
390
423
  }
391
424
  const timeoutMs = (timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1e3;
392
- return new Promise((resolve3, reject) => {
425
+ return new Promise((resolve4, reject) => {
393
426
  if (signal?.aborted) {
394
427
  reject(new Error("Operation aborted"));
395
428
  return;
@@ -402,7 +435,7 @@ function createBashTool(defaultCwd, options) {
402
435
  const maxChunksBytes = DEFAULT_MAX_BYTES * 2;
403
436
  let timedOut = false;
404
437
  const spawnCommand = buildSpawnCommand(resolvedShell, effectiveCommand);
405
- const child = spawn(spawnCommand.file, spawnCommand.args, {
438
+ const child = (options?.spawnProcess ?? spawn)(spawnCommand.file, spawnCommand.args, {
406
439
  shell: spawnCommand.shell,
407
440
  cwd: workingDir,
408
441
  env: process.env,
@@ -556,7 +589,7 @@ function createBashTool(defaultCwd, options) {
556
589
  [Recovery hint: ${recoveryHint}]`;
557
590
  }
558
591
  const content = [{ type: "text", text: outputText }];
559
- resolve3({ content, details, isError: timedOut || semantic.isError });
592
+ resolve4({ content, details, isError: timedOut || semantic.isError });
560
593
  } catch (error) {
561
594
  reject(error);
562
595
  }
@@ -774,7 +807,7 @@ function resolvePlaywrightCli() {
774
807
  return require2.resolve("@playwright/cli/playwright-cli.js");
775
808
  }
776
809
  function runPlaywright(args, timeoutMs = 6e4) {
777
- return new Promise((resolve3, reject) => {
810
+ return new Promise((resolve4, reject) => {
778
811
  const child = spawn2(process.execPath, [resolvePlaywrightCli(), ...args], {
779
812
  stdio: ["ignore", "pipe", "pipe"],
780
813
  shell: false
@@ -799,7 +832,7 @@ function runPlaywright(args, timeoutMs = 6e4) {
799
832
  });
800
833
  child.on("close", (code) => {
801
834
  clearTimeout(timer);
802
- if (code === 0) resolve3(stdout.trim());
835
+ if (code === 0) resolve4(stdout.trim());
803
836
  else reject(new Error((stderr || stdout || `Playwright CLI exited with ${code}`).trim()));
804
837
  });
805
838
  });
@@ -833,12 +866,12 @@ function createCliRenderedPageReader() {
833
866
  try {
834
867
  await runPlaywright([`-s=${session}`, "open", "about:blank"]);
835
868
  await runPlaywright([`-s=${session}`, "goto", url]);
836
- const [snapshot, pageInfoRaw, screenshotOutput, consoleOutput, networkOutput] = await Promise.all([
869
+ const [snapshot, pageInfoRaw, screenshotOutput, consoleOutput, requestsOutput] = await Promise.all([
837
870
  runPlaywright([`-s=${session}`, "snapshot"]),
838
871
  runPlaywright([`-s=${session}`, "--raw", "eval", "() => JSON.stringify({ title: document.title, href: location.href, text: document.body ? document.body.innerText : '' })"]),
839
872
  runPlaywright([`-s=${session}`, "--raw", "screenshot"]).catch((error) => `screenshot_failed: ${error instanceof Error ? error.message : String(error)}`),
840
873
  runPlaywright([`-s=${session}`, "--raw", "console"]).catch((error) => `console_failed: ${error instanceof Error ? error.message : String(error)}`),
841
- runPlaywright([`-s=${session}`, "--raw", "network"]).catch((error) => `network_failed: ${error instanceof Error ? error.message : String(error)}`)
874
+ runPlaywright([`-s=${session}`, "--raw", "requests"]).catch((error) => `requests_failed: ${error instanceof Error ? error.message : String(error)}`)
842
875
  ]);
843
876
  const pageInfo = parsePageInfo(pageInfoRaw);
844
877
  const text = pageInfo.text?.trim() || snapshot.trim();
@@ -853,7 +886,7 @@ function createCliRenderedPageReader() {
853
886
  citationAnchors: [{ url: pageInfo.finalUrl || url, title: pageInfo.title, startOffset: 0, endOffset: Math.min(120, text.length) }],
854
887
  screenshotPath: parseScreenshotPath(screenshotOutput),
855
888
  consoleMessages: linesOf(consoleOutput),
856
- networkRequests: linesOf(networkOutput)
889
+ networkRequests: linesOf(requestsOutput)
857
890
  };
858
891
  } finally {
859
892
  runPlaywright([`-s=${session}`, "close"], 1e4).catch(() => void 0);
@@ -908,7 +941,7 @@ function createCliWebResearchHealthStore(configDir) {
908
941
 
909
942
  // src/capabilities/index.ts
910
943
  function createCliHostCapabilities(cwd, options = {}) {
911
- const bashTool = createBashTool(cwd);
944
+ const bashTool = createBashTool(cwd, { isYoloMode: options.isYoloMode });
912
945
  const healthStore = createCliWebResearchHealthStore(options.configDir ?? getConfigDir());
913
946
  const webSearchTool = createSharedWebSearchTool({
914
947
  getModel: options.getModel ?? (() => void 0),
@@ -983,6 +1016,7 @@ export {
983
1016
  getAgentDir,
984
1017
  getCustomThemesDir,
985
1018
  getSettingsPath,
1019
+ getProjectSettingsPath,
986
1020
  getSessionsDir,
987
1021
  getLogsDir,
988
1022
  getRuntimeLogPath,
@@ -3,7 +3,7 @@ import {
3
3
  EventStream,
4
4
  streamSimple,
5
5
  validateToolArguments
6
- } from "./chunk-VESPMEDG.js";
6
+ } from "./chunk-HAAYC2N5.js";
7
7
 
8
8
  // ../../packages/agent-core/src/agent-loop.ts
9
9
  function createLoopErrorMessage(error, config, signal) {