The previous version (1.1.0) has a native-level bug on macOS where each
PTY spawn leaks one /dev/ptmx file descriptor that is never closed. Over
a long session with hundreds of shell commands, this exhausts the
system-wide PTY pool (kern.tty.ptmx_max = 511), breaking other programs
like tmux and new terminal windows.
Root cause: microsoft/node-pty#882
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Previously, only shell scripts (.sh) had .claude -> .qwen path replacement.
Markdown files (.md) like cancel-ralph.md and help.md were missing this
conversion, causing incorrect paths like .claude/ralph-loop.local.md.
Now performVariableReplacement also replaces .claude directory references
in markdown files using the same regex pattern as shell scripts.
Root cause: PR #1835 accidentally overwrote PR #1912's correct telemetry
isolation during a merge conflict resolution. This restores the original
guard logic so subagent GeminiChat instances (which don't receive a
telemetryService param) no longer write to the global uiTelemetryService.
- Remove unused uiTelemetryService import from geminiChat.ts
- Guard telemetry calls with this.telemetryService checks
- Add test verifying subagent isolation
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
When the WASM files cannot be found (e.g. symlinked CLI whose vendor path
probe still fails, or any other I/O error), isShellCommandReadOnlyAST and
initParser previously left the agent in a permanently broken state:
- initParser() returned a rejected promise stored in initPromise, so every
subsequent call returned the same rejection immediately
- isShellCommandReadOnlyAST() propagated the error to its caller, which
caused the shell tool to throw and left the agent 'thinking forever'
Changes:
- Import isShellCommandReadOnly from shellReadOnlyChecker.js
- Track parserInitFailed: boolean flag on the parser singleton
- initParser(): on any init error, set parserInitFailed=true and reset
initPromise=null (preventing permanent hang on the rejected promise)
- isShellCommandReadOnlyAST(): check parserInitFailed before attempting
AST parse; wrap the AST path in try/catch so any unexpected runtime
error also falls through to the regex checker
- _resetParser(): also resets parserInitFailed so tests can re-initialise
- Export _setParserFailedForTesting() to allow unit tests to exercise the
fallback path without breaking actual WASM loading
Tests added:
- Fallback suite: verifies that when the parser is marked as failed, all
isShellCommandReadOnlyAST calls delegate to isShellCommandReadOnly and
that _resetParser() restores normal AST operation
- Consistency suite: 40+ commands from shellReadOnlyChecker.test.ts run
through BOTH implementations; every case must agree. Known intentional
divergences (pure assignment, process substitution, control flow,
function definitions) are documented explicitly - all happen to agree
on the same boolean result, confirming the two implementations are
behaviourally consistent across the tested corpus
Fixes#2758
The previous fix used fs.realpathSync(fileURLToPath(import.meta.url)) to
resolve symlinks before computing the WASM path. This works in the common
case (/usr/bin/qwen → /usr/lib/node_modules/.../cli.js), but silently falls
back to the unresolved symlink path when:
- realpathSync throws (ENOENT, EACCES, ELOOP, or other OS-level errors)
- Node.js has already resolved import.meta.url to the real path on some
platforms (making realpathSync a no-op and the first candidate correct),
but the vendor files are still not found at that location
The new approach for the bundle case (inSrcUtils = false) collects up to four
candidate directories:
1. path.dirname(fileURLToPath(import.meta.url)) — already resolved on
Node.js 18+ on most platforms
2. path.dirname(realpathSync(import.meta.url)) — symlink-resolved fallback
3. path.dirname(process.argv[1]) — entry point as invoked
4. path.dirname(realpathSync(process.argv[1])) — resolved entry point
It then calls fs.existsSync on each candidate path for the requested .wasm
file and returns the first one that actually exists, rather than trusting
that a single path computation is correct. If none exist we fall back to
the first candidate so the caller still gets a deterministic ENOENT (instead
of silently using a wrong path).
Fixes#2758
- Scan a window of minutes around current time to find matching cron minutes
- Track matched cron minute in lastFiredAt instead of wall-clock time
- Add tests for positive jitter (recurring) and negative jitter (one-shot)
This ensures jittered jobs fire correctly when their delayed or advanced
fire time falls outside the original matching minute.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add queue-based cron processing in nonInteractiveCli for sequential execution
- Block cron processing while user prompt is active in Session
- Drain cron queue after prompt completion to process queued jobs
- Reduce recurring task auto-expiry from 7 days to 3 days
This fixes race conditions where cron jobs could fire during active prompts
and ensures cron prompts are processed sequentially.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Strip auth token when following redirects to a different host
- Strip auth token when downloading tarballs from a different host
- Fix package name encoding to replace all slashes, not just the first
This prevents credentials from being sent to unintended hosts when
private registries redirect to CDNs or other external domains.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Model IDs can legitimately contain colons (e.g., `gpt-4o:online`).
Previously, any string with a colon was parsed as `authType:modelId`,
which caused valid model IDs with colons to be rejected.
Now, if the prefix before a colon isn't a known AuthType, the entire
string is treated as a bare model ID.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Strip trailing orphaned funcCall (force=true) before split point calculation,
so normal compression logic runs cleanly on the remaining history instead of
requiring ad-hoc special-casing
- Remove redundant lastToolCompletionSplitPoint machinery: after fixing the
i+2 index bug, lastSplitPoint already subsumes it, making Math.max redundant
- Add MIN_COMPRESSION_FRACTION constant (0.05) to guard against futile API
calls when historyToCompress is too small relative to total history
- Add tests for orphaned funcCall handling (force=true compresses, force=false NOOP)
- Add test for MIN_COMPRESSION_FRACTION guard
Fixes#2647
Add comprehensive tests for buildAgentContentGeneratorConfig and
resolveCredentialField, covering same-provider overrides, cross-provider
credential clearing, registry-resolved models, and edge cases.
This ensures correct model selection behavior for subagent configurations.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Handle bare model IDs by inheriting parent's authType
- Create dedicated ContentGenerator for any explicit model selection
- Add tests for model override scenarios
Previously, only cross-provider prefixed models (e.g., "openai:gpt-4o")
triggered ContentGenerator creation. Bare IDs like "qwen-coder" were
ignored, causing subagents to always use the parent's model.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Introduce SendMessageType.Cron to differentiate cron-triggered prompts
from user queries
- Skip UserPromptSubmit hook for cron messages
- Add getExitSummary() to display active loops when session ends
- Add tests for exit summary functionality
This improves cron loop handling by treating scheduled prompts
differently from user-initiated queries and provides better UX
when sessions end with active loops running.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Extract buildAgentContentGeneratorConfig to shared module for reuse
- Create per-agent ContentGenerator when subagent uses different provider
- Remove validation restriction on cross-provider model selectors
- Update tests to accept cross-provider selectors
This allows subagents to use models from different providers (e.g.,
"openai:gpt-4" when parent uses Qwen) by creating dedicated
ContentGenerators with proper auth credentials.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>