donsetch 3.4.3 → 3.5.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 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.3",
3
+ "version": "3.5.0",
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
  */
@@ -33,12 +33,12 @@ const SHUTDOWN_GRACE_MS = 2_000;
33
33
 
34
34
  // ── TUI rendering note ──
35
35
  // 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.
36
+ // highlight. We output PLAIN TEXT only : no ANSI codes at all.
37
37
  // pi-tui's truncateToWidth injects \x1b[0m RESET around the ellipsis,
38
38
  // which breaks pi's overlay mid-line. We use our own truncate()
39
39
  // that adds zero ANSI codes.
40
40
 
41
- /** Plain text truncation no ANSI codes. */
41
+ /** Plain text truncation : no ANSI codes. */
42
42
  function truncate(text: string, maxLen: number): string {
43
43
  if (text.length <= maxLen) return text;
44
44
  if (maxLen <= 3) return text.slice(0, maxLen);
@@ -120,7 +120,7 @@ function startServer(): Promise<void> {
120
120
  try {
121
121
  // --supervised: crash-only daemon. If the MCP server is SIGKILLed
122
122
  // (OOM, crash), the supervisor respawns it and replays in-flight
123
- // requests pi users never see a dead tool until the process
123
+ // requests : pi users never see a dead tool until the process
124
124
  // itself dies.
125
125
  proc = spawn(binaryPath, ["mcp", "--supervised"], {
126
126
  stdio: ["pipe", "pipe", "pipe"],
@@ -158,8 +158,32 @@ function startServer(): Promise<void> {
158
158
  }
159
159
  });
160
160
 
161
+ // The daemon writes diagnostics to stderr (Xvfb warnings,
162
+ // fallback notices, ghost telemetry). Pi's TUI surfaces stderr
163
+ // as user-facing output: raw forwarding used to pop non-fatal
164
+ // warnings up (issue #95). Gate it:
165
+ // - DONSETCH_DEBUG / DEBUG set: forward everything (dev mode)
166
+ // - otherwise only crash/fatal lines survive; the rest is
167
+ // tool-level information the caller already has
168
+ const debugMode =
169
+ (process.env.DONSETCH_DEBUG ?? "").length > 0 ||
170
+ (process.env.DEBUG ?? "").length > 0;
171
+ const FATAL_RE = /fatal|panic|crash|SIGSEGV|abort|OOM|out of memory/i;
172
+ let stderrTail = "";
161
173
  proc.stderr?.on("data", (chunk: Buffer) => {
162
- process.stderr.write(chunk);
174
+ if (debugMode) {
175
+ process.stderr.write(chunk);
176
+ return;
177
+ }
178
+ stderrTail = (stderrTail + chunk.toString()).slice(-2048);
179
+ const lines = stderrTail.split("\n");
180
+ stderrTail = lines.pop() || "";
181
+ for (const line of lines) {
182
+ const trimmed = line.trim();
183
+ if (trimmed && FATAL_RE.test(trimmed)) {
184
+ process.stderr.write(`[donsetch] ${trimmed}\n`);
185
+ }
186
+ }
163
187
  });
164
188
 
165
189
  proc.on("error", (err) => {
@@ -518,7 +542,7 @@ export default function (pi: ExtensionAPI) {
518
542
  } else if (args?.query) {
519
543
  key = truncate(`"${args.query}"`, 50);
520
544
  }
521
- // Plain text only no ANSI codes. Pi wraps tool calls
545
+ // Plain text only : no ANSI codes. Pi wraps tool calls
522
546
  // in its own green (success) / red (failure) highlight.
523
547
  // Any ANSI we emit breaks pi's overlay mid-line.
524
548
  return new Text(
@@ -567,7 +591,7 @@ export default function (pi: ExtensionAPI) {
567
591
  line2 = d.preview;
568
592
  }
569
593
 
570
- // Plain text only no ANSI. Pi handles all coloring.
594
+ // Plain text only : no ANSI. Pi handles all coloring.
571
595
  const line1 = `${toolName} \u00B7 ${meta}`;
572
596
  const output = line2
573
597
  ? `${line1}\n ${line2}`