Keep only 128 recently used sessions strongly cached while retaining weak references to evicted sessions still owned by active callers. This bounds idle memory growth without allowing duplicate live Session objects or skipping shutdown flushes.
Add LRU, lifecycle, SDK, and flush regression coverage.
Refs #4786
When max_len is 0 or negative the cut pointer never advances, so the loop hangs. Return the content unsplit, matching truncate_text_to_tokens for non-positive budgets.
fe0717b3 ("feat(webui): add guided setup flows") added qrcode and
@types/qrcode to webui/package.json without regenerating the lockfile,
so `npm ci` fails in the Docker build with EUSAGE (Missing: qrcode,
@types/qrcode, dijkstrajs, pngjs, yargs, ...).
Regenerate the lockfile so it matches package.json again.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When an MCP server (e.g. stdio browser-agent subprocess) does not
terminate within the AsyncExitStack.aclose() timeout, asyncio raises
CancelledError. The existing exception handler only caught RuntimeError
and BaseExceptionGroup, so CancelledError escaped the except block and
crashed nanobot with exit code 1 on every shutdown.
Add asyncio.CancelledError to the caught exception tuple so the error
is logged at debug level and shutdown completes cleanly.
Stack trace from the crash:
Traceback (most recent call last):
File ".../nanobot/agent/loop.py", line 1194, in close_mcp
await stack.aclose()
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".../asyncio/__main__.py", line ?, in <module>
File ".../nanobot/agent/loop.py", line ?, in close_mcp
...
RuntimeError: ... (or BaseExceptionGroup) not caught
SystemExit: 1
Send the overflow tail message with HTML parse_mode, but persist the
unrendered markdown chunk in buf.text so later deltas and stream_end
re-render correctly via _split_telegram_markdown_html().
Translate the WebUI common.json to pt-BR, register the locale in
config.ts (with normalizeLocale rules for "pt", "pt-BR", "pt-PT", ...)
and index.ts resources, and add a Brazilian Portuguese overview
assertion in i18n.test.tsx.
Notes:
- Generic "pt" and any "pt-*" variant resolve to pt-BR. A future
pt-PT locale can be added without affecting existing users.
- Universally borrowed technical terms (nanobot, BYOK, MCP, JSON,
URL, Web, Apps when used as a product name, Skills) are kept in
English, matching the pattern used by es/fr/ja/ko/vi/id.
- Empty-thread greetings, quick-action prompts, and slash command
descriptions are translated; quick-action prompts are intentionally
phrased so the agent still receives a clear task spec.
Verified with bun run test (536 passing), bun run lint (clean), and
bun run build (7.18s).