Skip to content

v1.0.45

Choose a tag to compare

@andrelncampos andrelncampos released this 21 Jun 15:19
· 19 commits to master since this release

⚡ V40: Performance-First Execution — 4 specs, zero regressions

Surgical I/O, CPU, and memory optimization across 4 fronts. Result: faster sessions, lighter startup, leaner history.

Session I/O (spec 420)

  • Incremental writes: appendFileSync replaces rewriting the entire messages file
  • Sessions index cache: _cachedSessionsIndex in memory — loadSessionsIndex() was called 6× per turn reading from disk
  • Directory guard: _projectDirEnsured avoids unnecessary mkdirSync
  • String buffers: push + join in streaming loops instead of += (reallocation on every chunk)

Startup (spec 430)

  • Parallel skills: Promise.all + fs/promises — simultaneous loading, zero sequential readFileSync
  • Cached templates: Prompt templates (templates/tools/*.md, templates/skills/*.md) in immutable cache — no longer re-read from disk each turn

Compaction & memory (spec 440)

  • Incremental hash: findStablePrefixEndIndex() uses a single incremental SHA-256 instance — O(N) instead of O(N²)
  • Parallel turns: readRecentTurns() decompresses files in parallel with Promise.all
  • Async backup: backupSpecFile() uses fs/promises.copyFile — zero blocking

Hardening (spec 450)

  • Bounded concurrency: readRecentTurns processes in batches of 8 with early bailout — no wasted I/O
  • mtime-based invalidation: Sessions index cache checks mtimeMs — safe for multi-terminal use
  • ENOENT recovery: ensureProjectDir resets the flag if .dscode/ is deleted mid-session
  • ESLint no-floating-promises: Rule active — 5 violations fixed with void

🐛 PDF: Context Budget Fix (spec 460)

  • PDFs with compressed ObjStm: countPdfPages returns null (not 0) when the regex heuristic fails. Large PDFs are no longer embedded as base64 in context — preventing 1M token window overflow.
  • PDF read handler uses followUpMessages: Output is a short descriptive string instead of inline base64. Content goes through contentParams as image_url, matching the image handler pattern. Prevents context pollution.
  • Functional pages parameter: pages now extracts only the requested page range (via pdf-lib) instead of encoding the entire file. Falls back to full file with clear error metadata on extraction failure.
  • 5 new tests: Covers descriptive output, followUpMessages, page extraction, fallback on corruption, and single-page extraction.

🚀 Optimizations with native Node.js 24 APIs

  • Grep handler: native fs.globSync, async parallel reads, streaming — -143 lines, -1 dependency
  • Glob handler: custom walker replaced by fs.globSync-51 lines

🔧 Fixes

  • cacheMode in Zod schema: Settings with cacheMode are no longer rejected as invalid
  • /spec-pipe: Auto-creates session when none is active
  • FD leaks: File descriptors closed in grep binary detection catch and MCP client disconnect
  • Unused variable: Regex unusedInBinaryDetection removed from grep handler

📋 Documentation & infra

  • 5 steering rules in AGENTS.md: authorization, cross-check, verify, consequence, output
  • V39 and V40 documented in vision.md
  • Node 26 notice on welcome screen: "Starting October 2026, DsCode will require Node.js 26."
  • Release notes now use RELEASE_NOTES.md (not --generate-notes)

🚀 Node.js 24 — All-in

Full migration to Node 24 as baseline. Zero backward compatibility.

Native APIs replacing dependencies

  • Native fs.globSync replaces npm glob package — -4 dependencies
  • Native node:zstd replaces Brotli fallback from node:zlib — 4× smaller compressor
  • Error.isError()getErrorMessage() cross-realm safe in 21 files
  • Native structuredClone — 8-line deep clone becomes 1
  • esbuild target node24 — no polyfills for Node 22
  • CI on Node 24 — build and test on the real runtime

🍎 macOS Apple Silicon in automatic releases

  • macOS ARM64 (macos-latest) now builds automatically on every tag push
  • macOS Intel (macos-13) removed — deprecated runner by GitHub, no queue wait
  • Dry-run covers Windows, Linux, and macOS ARM64
  • Checksum download fixed (cause of 400 Bad Content-Length error in v1.0.41)

🔄 Robust auto-update

  • Asset naming 100% aligned between CI and update-check.ts
  • Portable packages (fallback when SEA fails) now copy all companion files: dscode.mjs, node, templates/, node_modules/
  • File extraction and atomic binary replacement across all platforms

🖼️ Local OCR with Tesseract.js

  • Offline OCR via tesseract.js for models without image support (e.g., DeepSeek V4)
  • Dynamic importtesseract.js only loads when OCR is actually used, zero startup impact
  • All 12 transitive dependencies packaged in the portable bundle
  • Extracted text truncated at 2000 characters (word boundary)
  • /image-paste and /image-upload with automatic OCR fallback
  • Drag-and-drop files via paste in terminal

🐛 Fixes (from previous versions)

  • v1.0.41: 400 Bad Content-Length error on publish — checksums were not downloaded
  • v1.0.42/43: macOS Intel blocked releases due to missing runner — removed from pipeline
  • Auto-update: Portable packages broke on update — now copies companion files
  • Bundle: Silent build failure — now exit(1) and CI detects it
  • OCR startup: regenerator-runtime not found at startup — tesseract.js loaded on demand
  • ErrorBanner in Ink, context window overflow, spec suffixes

📐 Specifications and build

  • Specs 370-410: build validation, operational resilience, traceability, auto-update
  • validate-binary.mjs uses tag version (not package.json)
  • release-dry-run.yml covers 3 platforms
  • README URL validation in CI