donsetch 3.4.4 → 3.5.1

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 CHANGED
@@ -6,7 +6,7 @@
6
6
  [![CI](https://img.shields.io/github/actions/workflow/status/dondai44423/donsetch/ci.yml?label=CI&style=flat-square)](https://github.com/dondai44423/donsetch/actions/workflows/ci.yml)
7
7
  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-00d4aa?style=flat-square)](https://github.com/dondai44423/donsetch/blob/master/LICENSE)
8
8
 
9
- DonSeTch gives AI agents web research from a single local process fetch any URL, search across 10+ engines, and crawl multi-page docs. Chrome-true TLS fingerprinting, bot-wall bypass, PDF extraction with OCR, semantic reranking. Zero API keys.
9
+ DonSeTch gives AI agents web research from a single local process : fetch any URL, search across 10+ engines, and crawl multi-page docs. Chrome-true TLS fingerprinting, bot-wall bypass, PDF extraction with OCR, semantic reranking. Zero API keys.
10
10
 
11
11
  ## Install
12
12
 
@@ -60,6 +60,6 @@ donsetch update
60
60
 
61
61
  ## License
62
62
 
63
- AGPL-3.0 Copyright (c) 2026 Bishesh Bhandari
63
+ AGPL-3.0 : Copyright (c) 2026 Bishesh Bhandari
64
64
 
65
65
  Full documentation: [github.com/dondai44423/donsetch](https://github.com/dondai44423/donsetch)
package/install.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // donsetch postinstall: download the prebuilt binary for this platform
5
5
  // from GitHub Releases, verify SHA256, and extract to ./binaries/.
6
6
  //
7
- // The binary is NOT bundled in the npm package it's fetched at
7
+ // The binary is NOT bundled in the npm package : it's fetched at
8
8
  // install time from the GitHub release matching this package version.
9
9
  // This keeps the npm registry clean (no 35 MB binary tarballs) and
10
10
  // uses the same release artifacts that manual users download.
@@ -40,8 +40,8 @@ const plat = PLATFORMS[platKey];
40
40
 
41
41
  if (!plat) {
42
42
  const known = {
43
- 'darwin-x64': 'prebuilt binaries exist update donsetch to a version that ships one',
44
- 'win32-arm64': 'no prebuilt binary yet build from source (see below)',
43
+ 'darwin-x64': 'prebuilt binaries exist : update donsetch to a version that ships one',
44
+ 'win32-arm64': 'no prebuilt binary yet : build from source (see below)',
45
45
  }[platKey];
46
46
  console.error(`donsetch: unsupported platform ${platKey}${known ? ` (${known})` : ''}`);
47
47
  console.error('');
@@ -58,7 +58,7 @@ if (!plat) {
58
58
 
59
59
  // ── musl detection (Alpine etc.) ────────────────────────────────
60
60
  // The Linux binaries are glibc-linked. On musl systems they install
61
- // fine but can never exec (missing ld-linux loader) fail HERE with
61
+ // fine but can never exec (missing ld-linux loader) : fail HERE with
62
62
  // the actual cause instead of a cryptic spawn error on first run.
63
63
  //
64
64
  // Checking for /lib/ld-musl-*.so.1 existence is a false positive on
@@ -143,7 +143,7 @@ if (fs.existsSync(binaryPath)) {
143
143
  console.log(`donsetch: binary already present (${plat.binary})`);
144
144
  process.exit(0);
145
145
  }
146
- console.log(`donsetch: leftover ${plat.binary} is ${size} bytes re-downloading`);
146
+ console.log(`donsetch: leftover ${plat.binary} is ${size} bytes : re-downloading`);
147
147
  try { fs.unlinkSync(binaryPath); } catch (_) {}
148
148
  }
149
149
 
@@ -236,7 +236,7 @@ async function main() {
236
236
 
237
237
  // 4. Extract (tar is built into Linux, macOS, and Windows 10+)
238
238
  console.log('donsetch: extracting...');
239
- // execFileSync: no shell, no string interpolation the install
239
+ // execFileSync: no shell, no string interpolation : the install
240
240
  // path (which can contain quotes/spaces) is passed as argv.
241
241
  execFileSync('tar', ['xzf', tarball, '-C', binDir], { stdio: 'inherit' });
242
242
 
@@ -244,7 +244,7 @@ async function main() {
244
244
  try { fs.unlinkSync(tarball); } catch (_) {}
245
245
  try { fs.unlinkSync(checksumFile); } catch (_) {}
246
246
 
247
- // 6. Verify the binary exists after extraction (BEFORE chmod
247
+ // 6. Verify the binary exists after extraction (BEFORE chmod :
248
248
  // chmod on a missing file throws an opaque error).
249
249
  if (!fs.existsSync(binaryPath)) {
250
250
  console.error(`donsetch: expected ${plat.binary} not found after extraction`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donsetch",
3
- "version": "3.4.4",
3
+ "version": "3.5.1",
4
4
  "description": "Web fetch, search and crawl for AI agents. Zero API keys. Chrome-true TLS.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Bishesh Bhandari",
package/pi-extension.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DonSeTch pi extension bridges the donsetch MCP binary into pi.
2
+ * DonSeTch pi extension : bridges the donsetch MCP binary into pi.
3
3
  *
4
4
  * `pi install npm:donsetch` installs this package. At session_start the
5
5
  * extension spawns `donsetch mcp`, performs the MCP handshake, discovers
@@ -8,14 +8,14 @@
8
8
  *
9
9
  * Zero maintenance: tool definitions are fetched dynamically from the
10
10
  * binary. When donsetch adds or changes tools, this extension picks
11
- * them up automatically no code changes needed here.
11
+ * them up automatically : no code changes needed here.
12
12
  *
13
13
  * Auto-download: if the binary is missing (e.g. postinstall was
14
14
  * blocked by npm 10+), the extension runs install.js at session_start
15
15
  * to fetch it from GitHub Releases.
16
16
  *
17
17
  * Custom TUI: each tool has clean renderCall/renderResult showing
18
- * a compact summary card not the full raw output. The LLM still
18
+ * a compact summary card : not the full raw output. The LLM still
19
19
  * receives complete content; the user sees a minimal status line +
20
20
  * one-line preview. Amber theme matching DonSeTch's identity.
21
21
  */
@@ -31,14 +31,20 @@ const INIT_TIMEOUT_MS = 10_000;
31
31
  const CALL_TIMEOUT_MS = 120_000;
32
32
  const SHUTDOWN_GRACE_MS = 2_000;
33
33
 
34
+ // A raw process.stderr.write bypasses pi's TUI paint cycle and
35
+ // corrupts the viewport (worse across parallel agents). Gate it here.
36
+ const DEBUG_MODE =
37
+ (process.env.DONSETCH_DEBUG ?? "").length > 0 ||
38
+ (process.env.DEBUG ?? "").length > 0;
39
+
34
40
  // ── TUI rendering note ──
35
41
  // Pi's TUI wraps tool calls in its own green (success) / red (failure)
36
- // highlight. We output PLAIN TEXT only no ANSI codes at all.
42
+ // highlight. We output PLAIN TEXT only : no ANSI codes at all.
37
43
  // pi-tui's truncateToWidth injects \x1b[0m RESET around the ellipsis,
38
44
  // which breaks pi's overlay mid-line. We use our own truncate()
39
45
  // that adds zero ANSI codes.
40
46
 
41
- /** Plain text truncation no ANSI codes. */
47
+ /** Plain text truncation : no ANSI codes. */
42
48
  function truncate(text: string, maxLen: number): string {
43
49
  if (text.length <= maxLen) return text;
44
50
  if (maxLen <= 3) return text.slice(0, maxLen);
@@ -120,7 +126,7 @@ function startServer(): Promise<void> {
120
126
  try {
121
127
  // --supervised: crash-only daemon. If the MCP server is SIGKILLed
122
128
  // (OOM, crash), the supervisor respawns it and replays in-flight
123
- // requests pi users never see a dead tool until the process
129
+ // requests : pi users never see a dead tool until the process
124
130
  // itself dies.
125
131
  proc = spawn(binaryPath, ["mcp", "--supervised"], {
126
132
  stdio: ["pipe", "pipe", "pipe"],
@@ -158,8 +164,29 @@ function startServer(): Promise<void> {
158
164
  }
159
165
  });
160
166
 
167
+ // The daemon writes diagnostics to stderr (Xvfb warnings,
168
+ // fallback notices, ghost telemetry). Pi's TUI surfaces stderr
169
+ // as user-facing output: raw forwarding used to pop non-fatal
170
+ // warnings up (issue #95). Gate it:
171
+ // - DONSETCH_DEBUG / DEBUG set: forward everything (dev mode)
172
+ // - otherwise only crash/fatal lines survive; the rest is
173
+ // tool-level information the caller already has
174
+ const FATAL_RE = /fatal|panic|crash|SIGSEGV|abort|OOM|out of memory/i;
175
+ let stderrTail = "";
161
176
  proc.stderr?.on("data", (chunk: Buffer) => {
162
- process.stderr.write(chunk);
177
+ if (DEBUG_MODE) {
178
+ process.stderr.write(chunk);
179
+ return;
180
+ }
181
+ stderrTail = (stderrTail + chunk.toString()).slice(-2048);
182
+ const lines = stderrTail.split("\n");
183
+ stderrTail = lines.pop() || "";
184
+ for (const line of lines) {
185
+ const trimmed = line.trim();
186
+ if (trimmed && FATAL_RE.test(trimmed)) {
187
+ process.stderr.write(`[donsetch] ${trimmed}\n`);
188
+ }
189
+ }
163
190
  });
164
191
 
165
192
  proc.on("error", (err) => {
@@ -518,7 +545,7 @@ export default function (pi: ExtensionAPI) {
518
545
  } else if (args?.query) {
519
546
  key = truncate(`"${args.query}"`, 50);
520
547
  }
521
- // Plain text only no ANSI codes. Pi wraps tool calls
548
+ // Plain text only : no ANSI codes. Pi wraps tool calls
522
549
  // in its own green (success) / red (failure) highlight.
523
550
  // Any ANSI we emit breaks pi's overlay mid-line.
524
551
  return new Text(
@@ -567,7 +594,7 @@ export default function (pi: ExtensionAPI) {
567
594
  line2 = d.preview;
568
595
  }
569
596
 
570
- // Plain text only no ANSI. Pi handles all coloring.
597
+ // Plain text only : no ANSI. Pi handles all coloring.
571
598
  const line1 = `${toolName} \u00B7 ${meta}`;
572
599
  const output = line2
573
600
  ? `${line1}\n ${line2}`
@@ -578,7 +605,11 @@ export default function (pi: ExtensionAPI) {
578
605
  });
579
606
  }
580
607
 
581
- process.stderr.write(`[donsetch] ${mcpTools.length} tools registered: ${toolNames.join(", ")}\n`);
608
+ // Fires every session_start (unlike the failure paths above), so
609
+ // this one corrupted the viewport on every normal run.
610
+ if (DEBUG_MODE) {
611
+ process.stderr.write(`[donsetch] ${mcpTools.length} tools registered: ${toolNames.join(", ")}\n`);
612
+ }
582
613
  });
583
614
 
584
615
  pi.on("session_shutdown", () => {