fix(config): respect HOME env var in default_config_dir for Windows#2688
Closed
fix(config): respect HOME env var in default_config_dir for Windows#2688
Conversation
The Anthropic provider had no Image variant in NativeContentOut, so [IMAGE:data:image/jpeg;base64,...] markers produced by the multimodal pipeline were sent to the API as plain text. The API counted every base64 character as a token, reliably exceeding the 200k token limit for any real image (a typical Telegram-compressed photo produced ~130k tokens of base64 text alone). Fix: - Add ImageSource struct and Image variant to NativeContentOut that serializes to the Anthropic Messages API image content block format - Add parse_inline_image() to decode data URI markers into Image blocks - Add build_user_content_blocks() to split user message content into Text and Image blocks using the existing parse_image_markers helper - Update convert_messages() user arm to use build_user_content_blocks() - Handle Image in the apply_cache_to_last_message no-op arm Fixes #1626
format_attachment_content was matching only Photo for [IMAGE:] routing. Documents with image extensions (jpg, png, gif, webp, bmp) were formatted as [Document: name] /path, bypassing the multimodal pipeline entirely. Extend the match arm to cover Document when is_image_extension returns true, so both Photos and image Documents produce [IMAGE:/path] and reach the provider as proper vision input blocks. Adds regression tests covering Document+image extension → [IMAGE:] and Document+non-image extension → [Document:] paths.
…cking
- Base branch target: dev
- Problem: ZeroClaw agents have no structured way to decompose complex tasks into trackable steps, falling behind
every comparable agent runtime
- Why it matters: Without task tracking, multi-step work is fragile (lost on context compression), invisible to users
(no progress signal), and error-prone (agent loses track of what's done vs. pending)
- What changed: Added a session-scoped task_plan tool with create/add/update/list/delete actions, integrated with
SecurityPolicy, registered in the tool factory
- What did not change: No config schema changes, no persistence layer, no CLI subcommand, no changes to agent loop or
any other subsystem
Label Snapshot
- Risk label: risk: low
- Size label: size: S
- Scope labels: tool
- Module labels: tool: task_plan
- Contributor tier label: (auto-managed)
- If any auto-label is incorrect: N/A
Change Metadata
- Change type: feature
- Primary scope: tool
Linked Issue
- Closes #(issue number)
- Related: N/A
- Depends on: N/A
- Supersedes: N/A
Supersede Attribution
N/A — no superseded PRs.
Validation Evidence
cargo fmt --all -- --check # pass (no output)
cargo clippy --all-targets -- -D warnings # task_plan.rs: 0 warnings (pre-existing warnings in other files
unrelated)
cargo test --lib tools::task_plan # 15/15 passed
- Evidence provided: test output (15 passed, 0 failed)
- If any command is intentionally skipped: cargo clippy reports pre-existing warnings in unrelated files
(onboard/wizard.rs etc.); task_plan.rs itself has zero clippy warnings
Security Impact
- New permissions/capabilities? No — uses existing ToolOperation::Act enforcement
- New external network calls? No
- Secrets/tokens handling changed? No
- File system access scope changed? No
Privacy and Data Hygiene
- Data-hygiene status: pass
- Redaction/anonymization notes: No identity data in code or tests. Test fixtures use neutral strings ("step one",
"do thing", "first")
- Neutral wording confirmation: All naming follows ZeroClaw/project-native conventions
Compatibility / Migration
- Backward compatible? Yes
- Config/env changes? No
- Migration needed? No
i18n Follow-Through
- i18n follow-through triggered? No — no docs or user-facing wording changes
Human Verification
- Verified scenarios: Ran ./target/debug/zeroclaw agent -m "调用 task_plan 工具,action=list" — agent correctly
identified and called task_plan, returned "No tasks."
- Edge cases checked: read-only mode blocks mutations, empty task list, invalid action names, missing required
parameters, create replaces existing list, ID auto-increment after add
- What was not verified: Behavior with non-CLI channels (Telegram, Discord); behavior with XML-fallback dispatcher
(non-native-tool providers)
Side Effects / Blast Radius
- Affected subsystems/workflows: src/tools/ only — tool factory gains one additional entry
- Potential unintended effects: Marginally increases tool spec payload size sent to LLM (one more tool definition).
Could theoretically cause tool name confusion with schedule if LLM descriptions are ambiguous — mitigated by distinct
naming (task_plan vs schedule) and different description wording.
- Guardrails/monitoring for early detection: Standard tool dispatch logging. Tool is session-scoped so no persistent
side effects on failure.
Agent Collaboration Notes
- Agent tools used: Claude Code for implementation assistance and review
- Workflow/plan summary: Implement Tool trait → register in factory → validate with tests → manual agent session test
- Verification focus: Security policy enforcement, parameter validation edge cases, all 5 action paths
- Confirmation: naming + architecture boundaries followed (CLAUDE.md §6.3, §6.4, §7.3): Yes
Rollback Plan
- Fast rollback command/path: git revert <commit> — removes 3 lines from mod.rs and deletes task_plan.rs
- Feature flags or config toggles: None needed — tool is stateless and session-scoped
- Observable failure symptoms: Tool not appearing in agent tool list, or tool returning errors on valid input
Risks and Mitigations
- Risk: LLM may occasionally confuse task_plan (action: list) with schedule (action: list) due to similar parameter
structure
- Mitigation: Distinct tool names and descriptions; task_plan description emphasizes "session checklist" while
schedule emphasizes "cron/recurring tasks"
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 6.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v4.6.2...b7c566a) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Automated replay on latest dev.
…ints Add an OpenAI-compatible API surface to the gateway so that standard OpenAI client libraries can interact with ZeroClaw directly. Endpoints: - POST /v1/chat/completions — supports both streaming (SSE) and non-streaming responses, bearer token auth, rate limiting - GET /v1/models — returns the gateway's configured model The chat completions endpoint accepts the standard OpenAI request format (model, messages, temperature, stream) and returns responses in the OpenAI envelope format. Streaming uses SSE with delta chunks and a [DONE] sentinel. A 512KB body limit is applied (vs 64KB default) since chat histories can be large. When the underlying provider doesn't support native streaming, the handler falls back to wrapping the non-streaming response in a single SSE chunk for transparent compatibility. Includes 8 unit tests for request/response serialization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the streaming provider trait methods for Bedrock, enabling
real-time token-by-token responses via the ConverseStream endpoint.
Key implementation details:
- Uses /model/{id}/converse-stream endpoint with SigV4 signing
- Parses AWS binary event-stream format (application/vnd.amazon.eventstream)
with a minimal parser (~60 lines) — no new crate dependencies needed
- Handles contentBlockDelta events for text extraction, plus error and
exception events
- Uses mpsc channel + stream::unfold pattern (matching compatible.rs)
- Clones credentials for async task ownership
The binary event-stream parser extracts frame lengths, header sections
(looking for :event-type), and payload bytes. CRC validation is skipped
since TLS already provides integrity guarantees.
Includes 10 new tests for URL formatting, binary parsing, and
deserialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add underscores to long numeric literals (1234567890 → 1_234_567_890) - Allow cast_possible_truncation for rough token estimates - Replace loop/match with while-let for event stream parsing - Merge identical match arms for event types - Add #[allow(clippy::cast_possible_truncation)] on test helper Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The default trait implementation returned a single error chunk that the SSE mapper silently converted to `data: [DONE]`, producing empty streaming responses from the OpenAI-compatible endpoint. Mirror the non-streaming chat_with_history pattern: extract system + last user message and delegate to stream_chat_with_system, which all providers already implement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add zh-CN translations and locale normalization in i18n\n- type locale context/state and support three-language cycle in header Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 4814e80)
parse_attachment_markers used .find(']') which returns the first ']', so
filenames containing brackets (e.g. yt-dlp output 'Video [G4PvTrTp7Tc].mp4')
were truncated at the inner bracket, producing a wrong path and a send failure.
Replace the naive search with find_matching_close, a depth-tracking scanner
that correctly skips nested '[...]' pairs and returns the index of the
outermost closing bracket.
Adds regression tests for the bracket-in-filename case and for the
unclosed-bracket fallback (no match → message passed through unchanged).
Replace default UTC timer with ChronoLocal::rfc_3339() so daemon and CLI log lines display the operator's local time, making correlation with external events easier. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Automated conflict recovery via changed-file replay on latest dev.
Voice messages were being silently ignored when transcription was disabled or user was unauthorized, making it difficult to diagnose configuration issues. This change adds: - Debug log when voice/audio message received but transcription disabled - Debug log when voice message skipped due to unauthorized user - Info log on successful voice transcription Closes #1469 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add production-ready CSS styling for the embedded web dashboard with electric theme, collapsible sections, and responsive layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
theonlyhennygod
previously approved these changes
Mar 5, 2026
Collaborator
theonlyhennygod
left a comment
There was a problem hiding this comment.
Reviewed: change is scoped and correct for Windows/test environments. Approving for merge.
The test load_or_init_uses_persisted_active_workspace_marker was failing on Windows because default_config_dir() used UserDirs::new() which queries the Windows API for the user profile directory, not the HOME environment variable. Fix: Check HOME environment variable first before falling back to UserDirs::new(). This is useful for testing and Docker scenarios. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
theonlyhennygod
previously approved these changes
Mar 5, 2026
Collaborator
theonlyhennygod
left a comment
There was a problem hiding this comment.
Re-reviewed on dev base: scoped config fix remains correct. Approving.
Collaborator
|
Closing as part of branch cleanup (March 2026). If this work is still needed, please rebase onto |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
load_or_init_uses_persisted_active_workspace_markertest failure on Windowsdefault_config_dir()now respectsHOMEenvironment variable before falling back toUserDirs::new()Problem
The test was failing because on Windows,
UserDirs::new()queries the Windows API for the user profile directory, which doesn't respect theHOMEenvironment variable set in tests.Solution
Check
HOMEenvironment variable first before falling back toUserDirs::new(). This is useful for:HOMEenvironment variableRisk
HOMEis explicitly setHOMEis not setRollback
Revert commit if issues arise.
Test
🤖 Generated with Claude Code
Summary by CodeRabbit