SessionManager._load() migrates sessions from the legacy directory
(~/.nanobot/sessions/) to the workspace path, but delete_session only
checked the workspace path. A user deleting a session could therefore
see its history come back the next time the session was loaded.
- delete_session now attempts to unlink both paths
- returns True if at least one file was removed
- added regression tests: legacy-only, both-paths, and no-revival
When the primary model (e.g. DeepSeek during peak hours) returns an empty
choices response with HTTP 200, the error carries no status code or
structured error metadata. The existing _FALLBACK_ERROR_TOKENS had no
matching token, so _should_fallback() returned False and fallback models
were never tried.
Changes:
- Add 'empty' token to _FALLBACK_ERROR_TOKENS so 'Error: API returned
empty choices.' text matches the fallback path
- Set error_kind='empty' in openai_compat_provider when returning
the empty-choices error, making the classification explicit
- Add test coverage for both text-only and error_kind matching paths
Fixes: glebov reported primary never falls back when DeepSeek returns
empty responses
Maintainer edit: keep capability-specific allowed_dir boundaries active even when the outer workspace scope is full access, and cover Dream plus ordinary full-access filesystem behavior.
maintainer edit: Dream write tools used file paths as directory roots, so a missing canonical memory file could be treated as a parent directory. Add exact-file allowlist support and keep skills/ as the only Dream write directory.
Treat the current live user message as the replay boundary for normal user turns, while keeping user-turn extension for history and consolidation paths that need it. Add regression coverage for the user-triggered long tool-turn case.
Maintainer edit: make token truncation include the suffix within the budget and route the consolidator through the shared helper so recent-history and archive truncation keep the same semantics.
Maintainer edit: subagents rebuilt their scoped ToolsConfig without carrying tools.file, which re-enabled built-in file tools after the parent agent disabled them. Preserve the file config and add loader/subagent coverage for the disabled path.
Idle compaction summarized only the dropped prefix, excluding the recent
suffix it retains. On a finished conversation a late user correction or
final result lands in that kept suffix, so it never reached the persisted
summary and history kept the stale pre-correction conclusion — which, for
idle sessions that are rarely resumed, is never fixed.
Summarize over the full unconsolidated tail instead, while still removing
(and raw-dumping on LLM failure) only the dropped messages. Adds an opt-in
summary_context argument to Consolidator.archive so the summarization
window and the archived set can differ without affecting other callers.
maintainer edit: streamed timeout recovery was returning the retried response internally while the channel still treated the final outbound as already streamed. End the current stream segment before retry/fallback recovery so subsequent deltas are delivered in a new segment.
When a stream stalls mid-response, both the retry layer and
FallbackProvider blocked recovery because content had already been
emitted via on_content_delta. This left users with truncated replies
and no automatic recovery.
For error_kind="timeout" specifically:
- _run_with_retry now suppresses delta callbacks and retries the same
model instead of returning immediately
- FallbackProvider now allows failover to a different model with
delta callbacks suppressed
Non-timeout errors retain the original "skip retry/failover after
streamed content" behavior to avoid duplicate output.
Adds ProviderConfig.extra_query, threaded into AsyncOpenAI(default_query)
so that Azure-style gateways requiring query params like api-version can
be configured without URL hacks.
Also updates provider_signature to track extra_query changes so per-turn
refresh rebuilds the provider when the value changes.
Addresses the extra_query portion of #4204. The max_completion_tokens
model-awareness enhancement is intentionally left separate.
maintainer edit: keep cancellation out of on_error so shutdown paths do not look like run failures, and let the SDK capture hook use the authoritative after_run snapshot.
maintainer edit: handle prompt sessions that report Connection closed outside McpError, and match reconnect registration prefixes with the same sanitization used by MCP wrapper names.