mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* fix(shell-ready): honor ZDOTDIR without breaking zsh scoping Fixes #1866 This reimplements PR #1737 (reverted in #1864) with a safer approach that preserves normal zsh startup semantics. **Core fix**: Discover ZDOTDIR by sourcing user ~/.zshenv in a subshell instead of inside a wrapper function. This preserves top-level zsh scoping for common patterns like `typeset -U path` that broke in the original implementation. **Shell safety improvements**: - Use `printf '%s\n'` instead of `echo` for capturing ZDOTDIR (handles special characters in paths safely) - Subshell isolates early returns and side effects from wrapper **Code quality**: - Extract duplicated zsh wrapper template to `src/main/shell-templates.ts` - Both local-pty and daemon paths now share identical wrapper logic **Test coverage**: - Add live zsh subprocess tests that spawn real zsh to verify: - XDG ZDOTDIR discovery works - `typeset -U path` in .zshrc preserves top-level scoping - Early returns in .zshenv don't crash the wrapper - Vanilla (non-XDG) configs fall back to HOME correctly - Template structure tests validate subshell discovery logic Before (broken): ```zsh __orca_source_user_zshenv() { source "$HOME/.zshenv" # typeset becomes function-scoped } ``` After (fixed): ```zsh _orca_discovered_zdotdir=$( unset ZDOTDIR [[ -f "$HOME/.zshenv" ]] && source "$HOME/.zshenv" 2>/dev/null printf '%s\n' "${ZDOTDIR}" ) export ORCA_ORIG_ZDOTDIR="${_orca_discovered_zdotdir:-${_orca_spawn_orig_zdotdir:-$HOME}}" ``` The subshell sources .zshenv at top-level (preserving normal scoping), captures only the ZDOTDIR value, then exits. User rcfiles (.zshrc, etc.) are still sourced at the wrapper's top level, so all scoping works normally. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Add shell-script-literal test framework and improvements Adds a new declarative test framework for shell-ready tests that uses literal shell scripts (copy-pastable into terminals) with inline snapshots. Framework features: - Shell scripts as string literals with # Run: marker to split setup/test - Direct script execution (no brittle parsing) via temp files - Path normalization for reproducible snapshots (<HOME>, <WRAPPER_DIR>) - Auto-detects shell from command, supports bash/zsh/sh - Inline snapshot testing with vitest toMatchInlineSnapshot() Code quality improvements: - Extract escapeRegex to shared string-utils.ts (deduplicates 2 copies) - Refactor shell-templates.ts for readability (condense comments, add structure) - Pre-compile regex patterns to avoid hot-path allocation - Fix path normalization to sort by length (prevent nested path corruption) - Fix actualUserHome handling to skip empty values All tests passing (64/64 shell-ready tests, 55/55 affected tests). Files added: - src/main/providers/__tests__/shell-ready-framework/shell-script-test.ts - src/main/providers/__tests__/shell-ready-framework/README.md - src/main/providers/__tests__/shell-ready-framework-example.test.ts - src/shared/string-utils.ts Files modified: - src/main/shell-templates.ts (readability cleanup) - src/main/codex/config-toml-trust.ts (use shared escapeRegex) - src/main/daemon/shell-ready.test.ts (updated for new framework) - src/main/providers/local-pty-shell-ready.test.ts (updated for new framework) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(shell-ready): preserve zshenv semantics --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
13 lines
441 B
TypeScript
13 lines
441 B
TypeScript
/**
|
|
* Escape special regex characters in a string for use in RegExp constructor.
|
|
*
|
|
* Why: When building a regex from user input or file paths, special regex
|
|
* characters (. * + ? ^ $ { } ( ) | [ ] \) must be escaped to match literally.
|
|
*
|
|
* @param str - String to escape
|
|
* @returns Escaped string safe for use in new RegExp()
|
|
*/
|
|
export function escapeRegex(str: string): string {
|
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
}
|