Replace the single _processing_lock (asyncio.Lock) with per-session locks
so that different sessions can process LLM requests concurrently, while
messages within the same session remain serialised.
An optional global concurrency cap is available via the
NANOBOT_MAX_CONCURRENT_REQUESTS env var (default 3, <=0 for unlimited).
Also re-binds tool context before each tool execution round to prevent
concurrent sessions from clobbering each other's routing info.
Tested in production and manually reviewed.
(cherry picked from commit c397bb4229e8c3b7f99acea7ffe4bea15e73e957)