Commit Graph

271 Commits

Author SHA1 Message Date
Xi Zhang aa3dd00409 feat: add support for session resumption with --resume flag and enhan… (#170)
* feat: add support for session resumption with --resume flag and enhance thread ID resolution

* refactor(tests): streamline help output testing for --resume flag

* feat: enhance session resume functionality with improved thread ID resolution and SQL wildcard handling

* feat: improve error handling for resume hint retrieval in interactive modes

* refactor: streamline logging for print_resume_hint failure in interactive mode

* feat: implement deferred scrolling for Markdown-heavy content in interactive mode
2026-04-21 21:26:40 +01:00
dinos 05f54334ba fix(mcp): stdio env passthrough + durable package installs (#169)
* fix(mcp): forward proxy and CA bundle env vars to stdio subprocesses

The MCP SDK's stdio transport inherits only a minimal allowlist (HOME,
PATH, USER, …) from the parent, stripping http_proxy/https_proxy and
SSL_CERT_FILE/REQUESTS_CA_BUNDLE/etc. Behind a proxy or with a custom CA
bundle, stdio MCP servers silently hang on outbound requests while the
same server over HTTP transport works. Auto-forward the proxy and cert
vars when present; user-configured env still takes precedence.

* fix(mcp): use `uv tool install` so MCP packages survive uv sync

Source installs previously used `uv pip install --python $VENV <pkg>`,
which lands in the evosci venv but is not recorded in pyproject.toml or
uv.lock. A subsequent `uv sync` (typical after `git pull`) reconciles
the venv to the lockfile and removes the MCP package, forcing users to
re-run onboard.

Prefer `uv tool install <pkg>` for the non-uv-tool install path: the
binary symlink in ~/.local/bin survives uv sync and evosci upgrades,
and the MCP server gets its own isolated env (no dep conflicts).
Verify the expected CLI entry point resolves afterward; if not (package
has no console-script), fall through to the old uv-pip path so
command-less packages still work.

The uv-tool-env path (`uv tool install evoscientist --with <pkg>`) is
unchanged — it was already durable via uv's receipt.

* fix(mcp): gate standalone uv tool install on verify_command

Previously `install_pip_package` would route every install through
`uv tool install <pkg>` when `verify_command` was None, returning
success as long as the uv subprocess exited 0. Library callers
(`evoscientist[oauth]`, `lark-oapi`, etc.) expect the package to land
in the active venv so they can import it — a standalone uv tool env
is not importable, so the import fails at the next line.

Gate the `uv tool install <pkg>` branch on `verify_command` being
set: that signals the caller wants a durable CLI binary, which is
what `uv tool install` produces. Library callers omit it and go
straight to the pip-install-into-venv path.

Also: log info messages on every fall-through so stale-binary and
entry-point-missing failure modes are debuggable, and document the
--with → standalone recovery path.

* fix(mcp): resolve MCP binaries to `uv tool dir --bin`, not `.venv/bin`

Under `uv run`, the project venv's `bin/` comes first on PATH, so
`shutil.which("arxiv-mcp-server")` returns a stale `.venv/bin/` copy
left over from an earlier install instead of the fresh symlink that
`uv tool install` just placed in `~/.local/bin`. The venv copy gets
written to mcp.yaml and is then wiped by the next `uv sync` — exactly
the failure mode the durability fix was meant to prevent.

Query `uv tool dir --bin` directly and prefer binaries found there
over `shutil.which`. Same change to the post-install verify in
`install_pip_package` so a venv shadow can't falsely short-circuit
the fallback.

* refactor(mcp): split install_pip_package into install_library + install_cli_tool

`verify_command` was doing double duty: naming the CLI binary to check
*and* signaling "this is a CLI install, use the standalone `uv tool
install` path." Callers routed library installs through the CLI branch
any time they forgot to pass it, and the resulting standalone uv tool
env wasn't importable from the active venv.

Separate the two use cases into distinct functions, each with one
install strategy per environment shape. Shared logic lives in private
`_install_with_uv_tool_env` / `_install_via_pip` helpers.

- install_library(pkg): uv-tool-env --with → pip. Never uses standalone
  `uv tool install <pkg>` (not importable from active venv).
- install_cli_tool(pkg, *, verify_command): uv-tool-env --with →
  standalone `uv tool install` → pip. `verify_command` is now required.

Callers pick the right function at the call site: registry.py picks
based on whether `entry.command` is set; onboard.py call sites all
install libraries.
2026-04-21 16:59:06 +01:00
Xi Zhang 06822f236c feat: enhance tool result handling with tool_call_id for concurrent execution 2026-04-19 23:15:20 +01:00
Ziheng Zhang bd501cce34 fix(channel/qq): deliver HITL approval prompts reliably (#166)
* fix(channel/qq): deliver HITL approval prompts reliably

QQ approval prompts were silently dropped when the markdown send hit
a QQ server-side error (e.g. template not configured, content audit)
because the fallback path only matched TypeError / specific string
patterns, and the plain-text retry reused the already-consumed
msg_seq which QQ then rejects as duplicate.

- Consume a fresh msg_seq for the plain-text fallback send
- Recognize QQ server error codes (304014/304023/304003/40034059)
  and CN fragments ("模版"/"审核") as markdown-fallback triggers
- Promote send failure logs from debug to warning/error with
  chat_id/msg_id/seq so real-world errors can be diagnosed
- Extend test_qq_channel with a server-error-code fallback case

* style(channel/qq): apply ruff formatter to approval-delivery fix

* Fix
2026-04-19 11:14:23 +01:00
Xi Zhang 58435dba52 Release/v0.0.8 (#167)
* chore(release): update version to v0.0.8 and dependencies in project files

* feat(models): add new model entries for Claude Opus 4-7 and update version handling

* Refactor code structure for improved readability and maintainability
2026-04-18 16:49:31 +01:00
Xi Zhang f4a3617646 refactor(paths): unify global data directory to ~/.evoscientist and u… (#164)
* refactor(paths): unify global data directory to ~/.evoscientist and update related paths

* refactor(paths): update legacy session migration to respect XDG_CONFIG_HOME

* refactor(tests): clear XDG_CONFIG_HOME in legacy session migration tests for deterministic behavior
2026-04-18 15:01:22 +01:00
Xi Zhang 210e8864f6 feat(memory): migrate MEMORY.md to global path & enhance ask-user prompts (#161)
* feat(prompt): enhance user interaction with multiple-choice and free-text questions

* refactor(paths): rename MEMORY_DIR to MEMORIES_DIR for consistency

* style(tests): format code for better readability in test cases

* feat(prompt): add validation for 'other' option in user prompt

* feat(prompt): refactor validation logic for user prompts and add skip option

* feat(style): refactor to use shared _PICKER_STYLE from interactive module
2026-04-16 15:33:45 +01:00
Xi Zhang 0b7c162d1b fix(skill-manager): update skill source filtering to include workspace and global tiers (#159) 2026-04-15 15:29:11 +01:00
Ziheng Zhang a2d2ddc5a2 fix(channel): avoid replaying thinking after resume (#154)
* fix(channel): avoid replaying thinking after resume

* fix(channel): relay fresh thinking after resume

* Fix

* Fix

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-04-15 14:05:47 +01:00
dinos 2961e5ee88 fix(minimax): correct API endpoint and add region selection (#158) 2026-04-15 14:30:26 +02:00
Xi Zhang c4237fecb8 feat(backends): rename MergedReadOnlyBackend to MergedSkillsBackend a… (#157)
* feat(backends): rename MergedReadOnlyBackend to MergedSkillsBackend and update documentation for clarity

refactor(paths): simplify ensure_dirs function to create only memory directory eagerly

fix(prompts): update skills availability description for accuracy

test(paths): adjust test to reflect skills directory creation on demand

* refactor(tests): format assertion for skills directory existence in ensure_dirs test
2026-04-15 01:52:31 +01:00
Xi Zhang 65db3a4fcd Add status bar and compact summary widgets with context window resolu… (#152)
* Add status bar and compact summary widgets with context window resolution

- Implemented a shared status bar for CLI and TUI frontends, including helpers for managing session metrics and context windows.
- Created a `CompactSummaryWidget` for displaying manual summaries in a collapsible format.
- Introduced a `CompactingWidget` to indicate ongoing compacting processes.
- Added a base class `TimedStatusWidget` for widgets that require a timer.
- Developed context window resolution helpers to retrieve context window sizes from various model attributes.
- Enhanced tests for context window resolution and status bar functionalities, ensuring accurate behavior across different scenarios.
- Updated existing tests to cover new features and maintain code quality.

* refactor(Channel): simplify lambda function in _send_with_retry method

* feat: enhance context editing logic and improve error handling in StreamState

* refactor(Channel): streamline lambda function in _send_with_retry method

* feat: rename auto-approve option to auto-mode for unattended execution; update checkpoint queries to filter by agent name; improve compatibility validation logic

* feat: rename auto-approve option to auto-mode; update related logic and tests for improved unattended execution

* fix: correct formatting of console message for MCP server configuration status

* feat: add check for None summary_message in _apply_summarization_event to prevent errors

* feat: enhance _load_checkpoint_messages to validate message format and apply summarization event
2026-04-12 17:47:37 +01:00
Xi Zhang ff15f515cc Release/v0.0.7 (#151)
* chore(assets): update wechat_group image file

* Refactor code structure for improved readability and maintainability

* feat(backends): enhance MergedReadOnlyBackend with improved ls, grep, and glob methods

* fix(docs): update WeChat QR code image link in README files

* feat(skills): enhance skill management to support global and workspace tiers

* style: apply ruff format to skills_cmd and commands/implementation/skills

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(skills): improve uninstall_skill to prevent removal of built-in skills

* fix(docs): update skill installation documentation for clarity on global and user directories

* fix(skills): enhance uninstall_skill to validate skill directory before removal

* fix(skills): improve error handling in install_skill and uninstall_skill for directory creation and validation

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 20:04:05 +01:00
Xi Zhang d5b982c980 fix(ccproxy): update Responses API handling and patch system role con… (#149)
* fix(ccproxy): update Responses API handling and patch system role conversion

* fix(ccproxy): streamline _agenerate method in system to developer patch

* fix(ccproxy): improve handling of None output in Codex compatibility patch
2026-04-09 12:51:05 +02:00
Ziheng Zhang 3e493233cf feat(channels): simplify debug tracing and add serve debug mode (#143)
* feat(channels): simplify debug tracing and add serve debug mode

* Fix

* fix(channels): remove serve loop patch
2026-04-09 12:47:48 +02:00
Xi Zhang 4f11de23a2 fix(llm): patch _stream/_astream for OpenAI-compatible content flattening (#147)
* fix(llm): patch _stream/_astream for OpenAI-compatible content flattening

_patch_openai_compat_content() only patched _generate/_agenerate but
EvoSci CLI uses streaming paths. This extends the content flattening
to _stream/_astream so strict OpenAI-compatible relays receive plain
string content during streaming calls.

Closes #142

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): use asyncio.run() instead of pytest-asyncio for CI compat

CI does not have pytest-asyncio installed, so async tests must use
asyncio.run() wrapper instead of @pytest.mark.asyncio decorator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): use @pytest.mark.anyio for async tests (CI compat)

CI does not have pytest-asyncio. Use @pytest.mark.anyio consistent
with existing async tests in the project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:24:13 +01:00
Peidong Yang 066f36fa13 feat: add Moonshot and Kimi Coding Plan as LLM providers (#128)
* feat: add Moonshot and Kimi Coding Plan as LLM providers

Add two new providers for Moonshot AI:
- `moonshot`: OpenAI-compatible direct API (api.moonshot.cn/v1) with
  kimi-k2.5, kimi-k2-thinking, moonshot-v1-auto/128k/32k/8k models
- `kimi-coding`: Anthropic-compatible Kimi Coding Plan endpoint
  (api.kimi.com/coding/) with User-Agent header for compatibility

Both providers disable thinking to avoid multi-turn tool calling
errors caused by LangChain dropping reasoning_content from history.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update Moonshot thinking comment and add provider assertions

- Add clarifying comment for disabling thinking on all Moonshot models
- Add moonshot and kimi-coding assertions to test_entries_has_all_providers

* fix: exclude Moonshot and Kimi Coding from content patch

Tested and verified both APIs support standard list content format:
- Moonshot (OpenAI-compatible): supports list content, no patch needed
- Kimi Coding (Anthropic-compatible): supports list content, no patch needed

Only apply _patch_openai_compat_content to strict providers like DeepSeek.

* fix: set _original_provider in routed provider branches

Ensure _original_provider is set before provider is reassigned to
'openai' or 'anthropic', so the no-patch exclusion for Moonshot
and Kimi Coding works correctly.

* style: translate Moonshot comments to English

* style: translate comment to English to fix ruff lint error

* merge: resolve conflicts

* chore: revert uv.lock and translate Chinese comments to English

Revert unrelated uv.lock dependency changes and replace Chinese code
comments with English for codebase consistency per review feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: fix ruff format for models.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: ypd <ypd@ypddeMac-mini.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
Co-authored-by: Xiaohui Yan <xhcloud@gmail.com>
Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
2026-04-08 19:53:49 +01:00
JackyFan 632159261c Fix: Support XDG_CONFIG_HOME for sessions.db on Windows with non-ASCII usernames (#102)
* fix: support XDG_CONFIG_HOME for sessions.db on Windows

Fixes SQLite database opening failure on Windows systems with non-ASCII
usernames (e.g., Chinese characters). The get_db_path() function now
supports the XDG_CONFIG_HOME environment variable, consistent with
get_config_dir() in settings.py.

Closes #101

* fix: auto-resolve Windows Unicode path for sqlite3 via 8.3 short path

Refactor get_db_path() to reuse get_config_dir() (XDG_CONFIG_HOME
support) and add _to_short_path() helper that converts the config
directory to its Windows 8.3 short form via GetShortPathNameW. This
automatically resolves sqlite3 failures on Windows systems with
non-ASCII usernames (e.g., Chinese characters) without requiring
manual environment variable configuration.

The short-path conversion is best-effort: it targets the directory
(which exists after mkdir) rather than the db file, and falls back
gracefully on non-Windows, non-NTFS, or when 8.3 naming is disabled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 18:50:42 +01:00
Ziheng Zhang 3647ff1afa fix: preserve QQ markdown formatting and newline rendering (#144)
* fix: preserve QQ markdown formatting

* fix: remove stale qq trace fallback hook

* fix: narrow qq markdown fallback handling

* style: format qq channel with ruff
2026-04-08 13:52:45 +01:00
Xiaohui Yan e89b71aa60 feat(cli): add --debug flag for verbose logging in serve mode (#141)
* feat(cli): add --debug flag for verbose logging in serve mode

* feat(cli): add log_level config field with priority over env var

Replace dead `debug` parameter in `main()` with a proper `log_level`
config field in EvoScientistConfig. Enables `EvoSci config set log_level
debug` with priority: config file > EVOSCIENTIST_LOG_LEVEL env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 13:23:10 +08:00
Ziheng Zhang 729cab11be Fix late channel response delivery after timeout (#140)
* Fix late channel response delivery after timeout

* Fix
2026-04-07 15:48:12 +01:00
X-iZhang 080a5c06f3 feat: enhance OpenRouter support with additional reasoning handling and model entries 2026-04-03 17:14:19 +01:00
Allen d08ca535c6 fix:Telegram channel start failed #133 (#134)
* fix:Telegram channel start failed #133

* refactor: simplify bus thread and add nest_asyncio warning

- Remove unnecessary _run_as_task() wrapper; run_until_complete()
  already creates a Task internally via ensure_future()
- Add comment noting nest_asyncio.apply() is global and irreversible

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Xi Zhang <zacharyzhang2022@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-04-03 14:47:15 +01:00
Yinhan Lu 5aa8353613 feat(llm): upgrade OpenAI reasoning effort from high to xhigh (#136)
* feat(llm): upgrade OpenAI reasoning effort from high to xhigh

The OpenAI Responses API supports "xhigh" as a reasoning effort level,
which provides deeper reasoning than "high". This is already used by
other CLI tools (e.g., OpenClaw) for OpenAI models.

Only affects the direct API key path; the ccproxy/OAuth path is
unchanged (reasoning is still skipped there).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(llm): limit xhigh reasoning to gpt-5.4+ and codex models

Only gpt-5.4 series and codex models support xhigh reasoning effort.
Older models (gpt-5, gpt-5.1, gpt-5.2, gpt-5.3) fall back to high.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Xi Zhang <zacharyzhang2022@gmail.com>
Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-04-03 14:35:14 +01:00
Xiaohui Yan 91de173c78 feat: Add GLM-5.1 support for Zhipu providers (#137)
* feat: Add GLM-5.1 support for Zhipu providers

Add GLM-5.1 model entries to both zhipu-code (coding endpoint) and
zhipu (general endpoint) providers, following the existing pattern
for GLM models.

* feat: add glm-5v-turbo support for Zhipu providers

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
Co-authored-by: Xi Zhang <zacharyzhang2022@gmail.com>
2026-04-03 14:00:21 +01:00
Xi Zhang 68f3ab2962 feat: enable reasoning for OpenRouter via extra_body to prevent multi… (#124)
* feat: enable reasoning for OpenRouter via extra_body to prevent multi-turn errors

* feat: implement OpenRouter native reasoning support and patch langchain-openrouter bug

* feat: add OpenRouter reasoning effort configuration and update related tests

* feat: add langchain-openrouter dependency for enhanced reasoning support

* fix: correct spacing in reasoning effort choice label

* feat: implement patch for OpenRouter reasoning details to prevent Pydantic errors

* feat: add patches for OpenRouter reasoning and content handling utilities

* feat: prevent multiple patches of OpenRouter reasoning details by using a global flag

* feat: update OpenRouter reasoning patch to ensure single application with global flag

* feat: refine OpenAI responses API handling to apply only for OpenAI provider

* feat: Enhance TUI interaction by updating todo widget positioning and skipping empty tool call chunks

* feat: Update tool selector threshold and adjust logging level for selector failures

* feat: Temporarily disable timestamp toast in tool call widget for UX review

* feat: Re-enable timestamp toast in tool call widget on click
2026-04-03 11:04:34 +01:00
Xi Zhang 897b444d27 Feat/context management middleware (#127)
* feat: Add context management middleware for improved error handling and context editing

* feat: Implement LLMToolSelectorMiddleware for enhanced tool selection and tracking

* feat(tests): update test functions to include mock timestamp parameter

* refactor: simplify tool selection state storage and update comments in middleware

* feat: Enhance tool selection handling and suppress structured output for improved event streaming

* refactor: simplify patching in test_create_tool_selector functions

* feat: add model parameter to create_tool_selector_middleware for enhanced flexibility

* feat: enhance tool selection suppression with JSON buffering for improved accuracy
2026-04-02 22:39:20 +02:00
Xi Zhang d8720a0b35 feat: Upgrade ccproxy to version 0.2.7 and remove deprecated thinking… (#130)
* feat: Upgrade ccproxy to version 0.2.7 and remove deprecated thinking tag handling

* feat: Enhance ccproxy compatibility and strip legacy thinking tags
2026-04-02 15:09:20 +01:00
dinos b9e809aeb6 fix: use uv tool install --with for durable MCP server installs (#125)
* fix: use `uv tool install --with` for durable MCP server installs (#121)

When EvoScientist is installed via `uv tool install`, MCP server packages
added during onboarding were installed with `uv pip install`, which is
not tracked by uv. Running `uv tool upgrade evoscientist` would recreate
the venv from scratch and silently wipe the MCP server binaries.

Now `install_pip_package()` detects uv tool environments and uses
`uv tool install <tool> --with <package>`, which records the dependency
in uv-receipt.toml so it survives upgrades. Existing --with packages
are read from the receipt and preserved.

Falls back to the old `uv pip install` path if the durable method fails.

* style: fmt

* fix: preserve requirement specs and normalize dedup in uv tool installs

Address review feedback: _uv_tool_existing_requirements() now returns
a dict mapping bare names to full PEP 508 specs (preserving extras and
version constraints from uv-receipt.toml). Dedup check uses
_bare_package_name() to normalize the incoming package argument before
comparing against receipt entries.
2026-04-02 10:51:54 +02:00
Xi Zhang 6e5844a68f Fix/tui file mention display (#123)
* fix: enhance user message display in run_textual_interactive function

* fix: add binary file detection in file mention resolution
2026-03-31 16:52:46 +08:00
Yuyue Zhao 4505300c8d feat: Add **More Effort** code generation mode (#118)
* feat: Add **More Effort** code generation mode

* feat: Enhance code generation mode selection and update documentation

---------

Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
2026-03-28 18:17:47 +00:00
Xi Zhang 6e23e98cca fix: inject thread_id into LangGraph context for compact conversation (#112) 2026-03-27 20:46:12 +00:00
Xi Zhang d3284ee881 v0.0.5 (#110)
* fix: update OpenRouter API key validation to use /auth/key endpoint and httpx

* Refactor code structure for improved readability and maintainability

* feat: enhance welcome banner to include file commands indication

* feat: update LaTeX setup prompt to use selection UI for better user experience

* feat: update version to v0.0.5 in badges and project configuration
2026-03-27 20:03:36 +01:00
dinos 6dc8a25579 feat: add use_responses_api config to force Chat Completions for OpenAI relays (#105)
* feat(config): use_responses_api (#98)

langchain-openai auto-switches to the Responses API when reasoning
params are set, which breaks OpenAI-compatible relays that only support
Chat Completions. This adds a user-facing config option to override
that behavior:

  evosci config set use_responses_api false
  # or EVOSCIENTIST_USE_RESPONSES_API=false

* fix: propagate use_responses_api from config file and add normalization tests

Address PR #105 review comments:
- apply_config_to_env() now sets EVOSCIENTIST_USE_RESPONSES_API so
  config file values take effect (not just the env var directly)
- Add parametrized tests for case/whitespace normalization

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-03-27 16:15:48 +00:00
MuXinCG a813f8afd9 fix(feishu): isolate SDK event loop to prevent cross-thread RuntimeError on Linux
lark_oapi.ws.client captures the main thread's event loop in a
module-level variable at import time. When the WebSocket SDK thread
calls loop.run_until_complete() on that shared loop, nest_asyncio's
global patches cause task-tracking conflicts on Linux/Python 3.12:
    - RuntimeError: Leaving task … does not match the current task
    - AttributeError: 'NoneType' object has no attribute 'select'

Replace the previous Handle._run monkey-patch (which only suppressed
symptoms) with a proper fix: create a fresh event loop in the SDK
thread and swap the module-level loop variable so the SDK operates
on a fully isolated loop with no cross-thread interaction.

Closes #97
2026-03-27 22:23:08 +08:00
Jan Piotrowski 5bc33adeb0 fix(tui): simplify behaviour of pasting clipboard to textbox
Closes #107
2026-03-27 14:39:34 +01:00
Xi Zhang fe6a2c4b83 fix: resolve #93 review comments and close #95 (#92 regression fix included) (#96)
* feat: enhance file mention parsing with deduplication and warning handling

* feat: optimize ancestor grouping by improving path comparison efficiency

* fix: update middleware injection to use extend for better readability

* Refactor code structure for improved readability and maintainability

* feat: update README files to include AstaBench ranking and adjust award image layout

* update

* fix: deduplicate file mentions and improve warning message formatting
2026-03-25 17:01:46 +00:00
Jan Piotrowski 259842243d feat: add context retry middleware when API returns 4xx errors cause by context exceeding limits (#92) 2026-03-25 15:41:06 +00:00
Xi Zhang fab5f85eee v0.0.4 (#93)
* feat(tui): enhance conversation history rendering and implement two-level thread hierarchy in picker

* feat(tui): improve conversation history display and enhance thread selection UI

* feat(file_mentions): implement @file mention parsing and completion for CLI and TUI

* feat(uv-tool): add compatibility checks and installation helpers for uv tool environments

* feat(dependencies): update package versions in uv.lock for compatibility and improvements

* feat(badges): update PyPI version to v0.0.4 in SVG assets and README files

* feat(tests): format code in TestUvToolCompat for improved readability
2026-03-24 18:13:42 +00:00
Xi Zhang cc266dd6b1 Feat/latex onboard setup and tui completion fix (#88)
* feat(onboard): add LaTeX setup steps and TinyTeX installation helpers

* fix(onboard): improve LaTeX status output to a single-line summary

* fix(assets): update wechat_group image
2026-03-23 10:51:42 +00:00
Ziheng Zhang 65cec64445 feat(feishu): add WebSocket long connection subscription mode (#87)
* feat(feishu): add WebSocket long connection subscription mode

Add WebSocket (长连接) mode as an alternative to webhook for Feishu
event subscription. This allows running without a public IP, port
forwarding, or tunnel — ideal for local dev and NAT/firewall setups.

- New `feishu_subscription_mode` config: "webhook" (default) or "websocket"
- WebSocket mode uses official `lark-oapi` SDK with thread-safe queue bridge
- Onboard wizard: mode selection, SDK install prompt for websocket
- CLI: `--mode webhook|websocket` for standalone serve
- `pip install evoscientist[feishu]` optional dependency
- 5 new tests covering config, SDK missing error, message bridge, cleanup
- Docs: subscription mode comparison table, prerequisites per mode

* Fix: Ruff

* Fix: small fix
2026-03-22 14:45:28 +00:00
Xi Zhang 3503142af6 feat(tui): UX polish — multi-line input, timestamps, update check & v0.0.3 (#85)
* feat: implement background update check and startup notifications

* feat: enhance user experience with timestamp notifications and UI polish

* feat: implement multi-line chat input with Enter-to-submit and modifier+Enter newline

* update

* update

* v0.0.3

* feat: improve code readability with consistent formatting in TUI and test files

* feat: update PyPI badge version to v0.0.3 in README files

* feat: add docstrings for test classes in test_update_check.py
2026-03-20 19:57:35 +00:00
Ziheng Zhang a7d3ef8087 fix: subagent summerize (#83)
* fix: subagent summerize

* fix: group subagent text by agent name for parallel fallback

The flat subagent_text_buffer list would interleave text from parallel
sub-agents into incoherent output. Replace with a dict grouped by
agent name so each sub-agent's text stays coherent, with [name]:
attribution when multiple agents contribute.

Add comprehensive tests for the new behavior (24 tests).

* fix: group subagent text by agent name for parallel fallback

The flat subagent_text_buffer list would interleave text from parallel
sub-agents into incoherent output. Replace with a dict grouped by
agent name so each sub-agent's text stays coherent, with [name]:
attribution when multiple agents contribute.

Add comprehensive tests for the new behavior (24 tests).

* fix: group subagent text by agent name for parallel fallback

The flat subagent_text_buffer list would interleave text from parallel
sub-agents into incoherent output. Replace with a dict grouped by
agent name so each sub-agent's text stays coherent, with [name]:
attribution when multiple agents contribute.

Add comprehensive tests for the new behavior (24 tests).

* chore: fix multiple agent

* test: add test

* fix linter

* remove redundant
2026-03-20 17:13:27 +00:00
Xi Zhang 372a6272b7 fix(onboard): Windows npx detection & rename /install-skills to /evoskills (#79)
* fix: improve npx detection on Windows using shutil.which

* fix: rename /install-skills command to /evoskills for consistency
2026-03-20 10:42:56 +00:00
Jiao Huifeng fdafebd47f feat: add STT voice transcription for all messaging channels (#28)
* feat: add STT voice transcription for all channels

Automatically transcribes audio/voice messages (Telegram, WeChat, Slack,
etc.) into text before the agent sees them. Enabled via config, off by default.

Changes:
- EvoScientist/stt.py: new STT engine using faster-whisper with lazy
  model loading and per-language model selection (zh/en/auto)
- EvoScientist/channels/base.py: hook in _enqueue_raw() to transcribe
  audio files and prepend transcript to message text; removes the raw
  [voice: ...] annotation after successful transcription so the agent
  does not attempt further audio processing
- EvoScientist/config/settings.py: stt_enabled (default False),
  stt_language (default "auto")
- pyproject.toml: optional [stt] dependency group (faster-whisper>=1.0)
- tests/test_stt.py: unit tests covering all backends and channel integration

Usage:
  pip install 'EvoScientist[stt]'
  EvoSci config set stt_enabled true
  EvoSci config set stt_language zh   # zh / en / auto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused imports (ruff F401)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address PR #28 reviewer feedback

Changes per SemiGlassFace review (CHANGES_REQUESTED):

1. Cache config at channel __init__ — no longer calls load_config() on
   every incoming message; STT settings stored as instance attributes
   (_stt_enabled, _stt_language, _stt_model, _stt_device,
   _stt_compute_type) set once during Channel.__init__().

2. Replace deprecated asyncio.get_event_loop() with get_running_loop()
   to avoid DeprecationWarning on Python 3.12+.

3. Annotation removal now uses exact path matching instead of substring
   search — checks fp == a or a.endswith(f": {fp}]") so only the
   correct annotation is removed after transcription.

4. Expose stt_model, stt_device, stt_compute_type as config fields so
   users can override the HuggingFace model id, inference device, and
   quantisation without touching code. transcribe_file() forwards all
   three to the engine.

Also: _engines dict replaced with single _engine + _engine_key tuple
(model_id, device, compute_type) — reuses cached model unless settings
change, simpler than a dict.

Tests: 19 STT-specific tests all pass; total 1105 tests green, ruff clean.

* fix: resolve ruff lint errors (UP037, I001, PT006)

* style: apply ruff format

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 10:59:30 +01:00
Xi Zhang 210d71c590 feat(tui): double Ctrl+C quit confirmation & docs Examples/Recipes section (#78)
* feat: enhance quit handling with double Ctrl+C confirmation and cleanup logic

* feat: enhance TUI cancellation handling and improve user interruption messages

* feat: add Examples & Recipes section to documentation

* docs: remove guideline to follow the structure of existing recipes
2026-03-20 00:25:31 +00:00
Icy Fish 649f2ca121 fix: resolve TAB cursor disappearance and up/down double-handling (#58)
- Add priority binding for TAB to intercept before Textual's focus_next
- Remove duplicate up/down handling in on_key (now handled by priority
  bindings from PR #76)
- Update tests to use cmd_manager.list_commands() instead of removed
  _TUI_SLASH_COMMANDS

Closes #57

Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 23:28:34 +00:00
Ziheng Zhang c627aadd39 Fix/deepseek sequence content error (#77)
* feat: add DeepSeek as a recognized third-party provider

Register DeepSeek API (https://api.deepseek.com) with DEEPSEEK_API_KEY
env var and add model short names: deepseek-r1 → deepseek-reasoner,
deepseek-v3 → deepseek-chat.

* feat: add _flatten_message_content utility for list-to-string conversion

Extract text from content block lists while skipping thinking/reasoning
blocks. This handles the case where LangChain stores assistant messages
with content as a list of content blocks instead of a plain string.

* fix: flatten list content to strings for OpenAI-compatible providers

Add _patch_openai_compat_content() that wraps _generate/_agenerate to
sanitize message content before API calls. Apply it for all third-party
OpenAI-compat providers and native OpenAI proxies.

This fixes "invalid type: sequence, expected a string" errors from
strict APIs like DeepSeek that reject list-format content in assistant
messages during multi-turn conversations.

* feat: add DeepSeek API key validation and integrate into onboarding process
test: implement unit tests for content flattening utility in OpenAI-compatible providers

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
2026-03-19 19:28:48 +00:00
X-iZhang ac7fdcecf2 refactor: improve readability of command validation and path extraction logic 2026-03-19 18:38:57 +00:00
X-iZhang edd3823881 feat: implement absolute system path detection in command validation 2026-03-19 18:28:54 +00:00