- Replaced time-based sleeps and polling loops with event-driven promise resolvers and fake timers across agent and tool tests.
- Migrated test suites to share in-memory auth storage and fixtures using lifecycle hooks.
- Updated catalog model definitions, metadata, and configurations.
- Displace overwritten destination into a temporary sibling directory during workspace renames.
- Restore the displaced file and clean up the temp directory if the main rename operation fails.
- applyWorkspaceEdit takes an onExecuted callback fired after each
filesystem mutation, so callers hold the executed prefix even when a
later op throws.
- applyWorkspaceEditWithLsp reconciles overlays/watchers for that prefix
best-effort before rethrowing the original apply error.
- applyWorkspaceEdit now returns { applied, executed }; ops skipped via
ignoreIfExists/ignoreIfNotExists are excluded from executed.
- applyWorkspaceEditWithLsp derives didClose/refresh/watched-file
notifications from executed ops, so a skipped rename no longer closes
the old URI overlay or emits phantom Deleted/Created events.
Kept closing sessions attached to their server until orphan document closes and pending request cancellations are queued.
Added coverage that reopens the last orphan URI after reuse and verifies the replacement overlay remains active.
Fixes#8371
Skipped destination removal when an overwrite rename resolves both paths to the same inode (case-only rename on case-insensitive filesystems), so the source is no longer deleted before fs.rename runs.
Fixes#8373
Reject snippet-formatted or overlapping rename edits across all accepted URIs before applying any, so a later snippet edit cannot leave earlier files half-applied.
Fixes#8376
The willRenameFiles loop caught every non-abort, non-method-not-found
error into serverNotes and fell through to fs.rename, so a genuine
failure from a server that supports the request moved the path without
its semantic edits, leaving references dangling. Split client acquisition
from the request, track hard failures, and abort before any mutation when
a supporting server errors. Servers replying method-not-found are still
skipped without blocking.
Fixes#8380
The direct diagnostics loop caught non-abort server errors without recording them, so a file whose every applicable server failed produced an empty aggregate rendered as OK with success: true — a false-negative hiding a total diagnostics failure.
Track per-file and global success/failure counts: zero successful server responses now yields success: false with an explicit failure line, while partial success still surfaces diagnostics and names the servers that failed.
Fixes#8377
rename_file wrote server-provided reference edits before creating the
destination parent and moving the source, with no rollback. A failed
mkdir/rename (e.g. EXDEV across mounts, EACCES) left the reference files
rewritten while the source stayed put, violating the atomic "moves file
AND rewrites all imports/references" contract.
Extract applyEditsThenRename in lsp/edits.ts: snapshot each edited file,
apply edits, then mkdir+rename; on failure restore every snapshot before
rethrowing. Rewire the rename_file handler to build the summary and hand
the edits to the helper.
Fixes#8379
Propagated CreateFile, RenameFile, and DeleteFile options through workspace edit planning and enforced their overwrite, ignore, and recursive semantics during execution.
Fixes#8373
Assigned concurrent mux links separate language-server processes while retaining idle processes for later reuse.
Added regression coverage for session-specific open-document content and updated mux lifecycle expectations.
Fixes#8371
Advertised abort semantics because multi-file text edits are applied sequentially and cannot satisfy textOnlyTransactional.
Added initialization capability coverage and documented the fix.
Fixes#8375
Address review feedback on #8186:
- add ty.toml to ty rootMarkers so ty.toml-only projects pass the
loadConfig marker gate (Codex P2, roboomp should-fix)
- add ty.toml to PYTHON_ROOT_MARKERS so project-local .venv/bin/ty
resolution runs for ty.toml-only projects (roboomp should-fix)
- add a ty.toml-only regression test covering both the detection
gate and the local venv bin resolution path
- move the changelog entry from the released [16.3.11] section into
[Unreleased] (roboomp should-fix)
Add ty (ty server) to defaults.json behind pyright/basedpyright/pylsp
in primary selection order and ahead of ruff (linter). ty uses the
generic LSP client path with no adapter code; settings.ty pass-through
works via the existing settings field.
- defaults.json: insert ty entry between pylsp and ruff
- lsp-regressions.test.ts: 4 tests (selection order for .py/.pyi,
auto-detect via $which + pyproject.toml, coexistence with ruff)
- CHANGELOG.md: Added entry under [Unreleased] referencing #4617Closes#4617
Why:
Local timeout cleanup removes pending state but leaves the language server
working on an abandoned request.
Changes:
- Send $/cancelRequest after an issued request reaches its client timeout.
- Preserve the existing timeout error and pending-request cleanup.
Evidence:
- The workspace-readiness regression observes cancellation for the dropped
status request before polling succeeds.
Refs #8116
Why:
The module-level idle interval remains referenced after every client shuts
down and keeps short-lived hosts alive.
Changes:
- Stop the idle checker before draining active and pending clients.
- Preserve explicit reconfiguration through setIdleTimeout().
Evidence:
- A child-process regression probe exits after shutdown with the checker
configured.
Refs #8115
- src/lsp/index.ts is the explicit ./lsp package entry, yet held 2821 lines of
warmup, config caching, diagnostics, external build-command workspace
diagnostics, the writethrough batching subsystem and the LspTool class.
- Those are now servers, diagnostics, workspace-diagnostics, writethrough and
tool modules; index.ts is 22 lines and re-exports the same public surface.
- configCache and writethroughBatches remain single instances and every tuned
diagnostics timing constant moved verbatim.
Canonicalized file URI keys at the diagnostics map boundary so server and client spellings match across percent encoding and Windows casing.
Added regression coverage for equivalent percent-encoded URIs and the marksman Windows drive-letter form.
Fixes#7662
- Introduce `@oh-my-pi/omptype` as a new ArkType-compatible schema validation package featuring a lazy JIT runtime, JSON Schema emission, and compatibility adapters.
- Replace `arktype` across workspace packages and test utilities with `@oh-my-pi/omptype`.
- Add benchmark suites, tests, and documentation for the new validation engine and adapters.
- Update workspace build, test runner, and release configurations to include the new package.
- Added an LSP multiplexer server, protocol definitions, and daemon lifecycle management to route traffic across sessions.
- Introduced `lsp.shared` settings configuration and SDK session creation support for shared language servers.
- Migrated shared daemon ensure helpers into a central launch module with updated import references.
- Added comprehensive unit tests and fake LSP server fixtures covering muxing, sharing, caching, and restarts.
Waited briefly for process exit publication after clean stdout EOF so the process handler preserves the real exit code and stderr, while genuine reader errors still tear down immediately.
Cleared only the matching initialization failure for explicit reloads and added regressions for quick exits, reader errors, ordinary backoff, and immediate reload retries.
Fixes#7041
(cherry picked from commit a76522b759f14421202d4cc437ec611b78be20d1)
Added an optional per-server languageId override and used it for both disk-backed and in-memory didOpen notifications.
Covered config loading and both document-open paths with a fake custom GDScript server.
Fixes#6800
Codex P2 on #6403: sendRequest rejected with only the server's error
message; a server answering rust-analyzer/reloadWorkspace with code
-32601 but nonstandard text (e.g. "Unknown request") would fail
isMethodNotFoundError and turn lsp reload into a hard error instead of
falling back to the generic reload. Include the code in the rejection
message so the existing -32601 substring check matches. Adds a
regression test with a -32601/"Unknown request" response.
reloadServer caught every error from both fallback mechanisms in bare
catch blocks, so a caller cancel or tool timeout was swallowed and fell
through to `proc.kill(); return "Restarted"` -- reporting a successful
restart while killing the server with no replacement.
- Propagate ToolAbortError/timeout from both the rust-analyzer request
and the didChangeConfiguration notification fallback.
- Gate the fallback on genuine method-not-found via isMethodNotFoundError
instead of any error.
- Replace the blind proc.kill with shutdownClientInstance: remove the
client from the registry by identity and await confirmed process exit,
surfacing a truthful teardown error when the process outlives the kill.
Fixes#6369
clampTimeout resolved the per-tool default (bash 300s) whenever the agent
omitted `timeout` and only enforced the tool's own min/max, so the
tools.maxTimeout global ceiling — applied solely in sdk.ts on explicitly
numeric args — was bypassed on the common default-fallback path.
Thread maxTimeout into clampTimeout so the resolved effective timeout,
including the default path, is capped before the per-tool floor/ceiling
apply. Explicit values below the cap still win; maxTimeout <= 0 stays
no-cap. Applied at every call site (bash, eval, browser, debug, lsp,
fetch, and the session-level bash executor), and the bash clamp notice
now names the global ceiling when it is the binding limit.
Fixes#6294