114 Commits

Author SHA1 Message Date
yu-xin-c
a7a6c26eab fix(heartbeat): route unified sessions to last channel 2026-07-27 00:12:44 +08:00
santhreal
7c94ba9643 fix(session): coerce null session metadata to empty dict 2026-07-26 17:47:16 +08:00
Xubin Ren
9a7debcb48 chore: defer compatibility cleanup to v0.3.1 2026-07-25 21:07:33 +08:00
KDB
274613f064 fix(session): tolerate files removed during listing 2026-07-23 23:53:56 +08:00
chengyongru
96eb965aae
feat(webui): show the actual fallback model (#5017) 2026-07-23 15:57:13 +08:00
chengyongru
089216f9c7 chore(session): schedule legacy fallback removal for v0.2.4 2026-07-23 14:53:00 +08:00
axelray-dev
464f71b488 fix(session): fall back to legacy paths in metadata reads
Fixes #4940
2026-07-23 14:53:00 +08:00
chengyongru
c22efb5f7a
feat(agent): make model presets session-scoped (#4866) 2026-07-23 00:38:49 +08:00
chengyongru
66690fdb0c
fix(webui): deliver late subagent results as new turns (#4992) 2026-07-22 23:04:36 +08:00
KDB
7cf3c71e3a fix(session): cap messages at persistence boundary
Bind SessionManager saves to the existing raw archive path so SDK imports and other bypass saves cannot persist more than the file cap without archiving unconsolidated overflow.

Add an SDK regression test that exercises the real ingest path.

Refs #4787
2026-07-21 13:47:18 +08:00
chengyongru
dfc3919b52 fix: stop masking runtime failures 2026-07-21 11:44:52 +08:00
chengyongru
afc65c086e refactor(session): simplify directory fsync handling 2026-07-21 10:11:53 +08:00
sunpengcheng05
4a79cbb6e7 fix(session): tolerate unsupported directory fsync 2026-07-21 10:11:53 +08:00
KDB
d35f99abfc fix(session): bound the in-memory session cache
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
2026-07-18 17:37:07 +08:00
Xubin Ren
01e4f3762a fix(agent): keep runtime context within its lifecycle 2026-07-12 00:35:17 +08:00
chengyongru
54b250430d fix(session): stop synthesizing MCP preset prompt context 2026-07-12 00:35:17 +08:00
chengyongru
2eb7398f34 fix(agent): close runtime context persistence gaps 2026-07-12 00:35:17 +08:00
chengyongru
f75d3519db feat(agent): add persistent runtime context providers 2026-07-12 00:35:17 +08:00
chengyongru
7f8c3453e1 refactor(agent): gate sustained goals behind explicit /goal
Replace the legacy long-goal skill contract with command-scoped goal tools and runtime guidance. Keep goal state durable across continuations while restricting create and replace mutations to explicit user /goal turns.
2026-07-12 00:35:17 +08:00
chengyongru
34535b4e7c fix(webui): hide subagent backfill payloads 2026-07-02 14:36:23 +08:00
chengyongru
2ebf5c4972 refactor(trigger): name CLI trigger source as local
maintainer edit: cron is also a trigger source, so keep the new CLI-delivered source explicitly named as local trigger across backend, WebUI, docs, and tests.
2026-07-02 13:32:46 +08:00
chengyongru
55b550ee01 fix(trigger): hide external trigger inputs 2026-07-02 13:32:46 +08:00
chengyongru
5f4cfbcb16 refactor(bus): type outbound runtime events 2026-07-01 20:17:00 +08:00
axelray-dev
8fa9eed6a8 refactor(session): trim RetentionResult to only fields callers read
Remove retained and new_last_consolidated from RetentionResult.
Both were populated but never read by any caller. The authoritative
state remains self.messages and self.last_consolidated, which the
method mutates in place. Update docstring accordingly.
2026-06-29 14:24:00 +08:00
axelray-dev
5692f7a68a refactor(session): return RetentionResult instead of bare tuple
Replace the tuple(list[dict], int) return of
Session.retain_recent_legal_suffix with a named RetentionResult
dataclass that exposes retained, dropped,
already_consolidated_count, and new_last_consolidated fields.

The tuple return was easy to misuse because the second value only
made sense relative to the first and the old last_consolidated
cursor. The named fields make the archive-skip semantics explicit
at every call site.

No behavior change. All existing tests pass unchanged in semantics.

Refs #4136

Signed-off-by: axelray-dev <110029405+axelray-dev@users.noreply.github.com>
2026-06-29 14:24:00 +08:00
chengyongru
57f0c859fc refactor(context): trim replay cap plumbing 2026-06-29 14:23:55 +08:00
chengyongru
40282e3b74 fix(context): scale replay cap with context window 2026-06-29 14:23:55 +08:00
chengyongru
dacc699293 fix(config): retire max messages setting 2026-06-29 14:23:55 +08:00
chengyongru
c8638dee46 fix(context): raise max messages fallback cap
Treat max_messages as a last-resort replay guard now that consolidation and idle auto-compact own normal history reduction. Raising the default avoids frequent sliding-window prefix churn in moderate conversations without adding a new cache-policy knob.
2026-06-29 14:23:55 +08:00
axelray-dev
89dc34df88 fix(session): repair corrupt legacy-stem files in list_sessions
list_sessions() silently dropped corrupt session files whose filename
stem was a legacy non-base64 name (e.g. telegram_12345.jsonl from the
old lossy path scheme). The repair path called _repair(fallback_key),
but _repair re-encodes the key via _storage_key(), producing a
different base64 filename that never matches the actual file on disk.

Add an optional path parameter to _repair so callers can pass the
actual file path directly, bypassing the key-to-filename round trip.

Signed-off-by: axelray-dev <110029405+axelray-dev@users.noreply.github.com>
2026-06-28 19:46:55 +08:00
Xubin Ren
c90e433057 fix(session): guard lossy migration by stored key 2026-06-27 16:52:54 +08:00
axelray-dev
3ce77633c0 fix(session): add _decode_storage_key for corrupt-file repair in list_sessions 2026-06-27 16:52:54 +08:00
axelray-dev
00a907c493 fix(session): split safe_key and _storage_key to fix WebUI coupling (#4533) 2026-06-27 16:52:54 +08:00
axelray-dev
cf2f589615 fix(session): prevent save from writing to legacy lossy path, add collision tests (#4533) 2026-06-27 16:52:54 +08:00
axelray-dev
463f536750 fix: prevent session key collision on disk (#4057)
safe_key() replaces ':' with '_', causing collisions between distinct
keys (e.g. telegram:a_b vs telegram🅰️b both become telegram_a_b).

Use base64url (no padding) for collision-resistant encoding while
maintaining backward compatibility: _get_session_path and
_get_legacy_session_path check the new path first, then fall back
to the old lossy encoding for existing session files.
2026-06-27 16:52:54 +08:00
chengyongru
9b45fc1172 fix(session): remove message time replay prefixes 2026-06-27 11:04:36 +08:00
Xubin Ren
c915e98c15 test: cover archived heartbeat target selection 2026-06-24 15:45:49 +08:00
Heng Wei Bin
de4009efbd fix: exclude archived keys in heartbeat & fallback missing session timestamps 2026-06-24 15:45:49 +08:00
yorkhellen
33638417be fix(session): delete_session also removes legacy path files to prevent history revival
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
2026-06-19 21:07:47 +08:00
Xubin Ren
09962895fb fix(session): preserve user turns in replay history 2026-06-18 00:03:22 +08:00
Xubin Ren
7bec0f6e01 fix(api): honor skip-user persist through save boundary 2026-06-16 21:31:26 +08:00
04cb
d75f80437c fix(api): don't re-persist user turn on empty-response retry (#4079)
The non-streaming retry called process_direct again with the same
content, persisting a duplicate user turn. Pass persist_user_message=False
so the retry recovers a response without re-recording the user message.
2026-06-16 21:31:26 +08:00
chengyongru
3ce0cd972e fix(session): keep auto compact suffix on user turn 2026-06-15 19:03:37 +08:00
chengyongru
af0e3441d7 Fix WebUI startup blocking on slow gateway routes 2026-06-13 21:59:36 +08:00
Xubin Ren
dac4e39bcf
Merge PR #4299: feat(cron): bind scheduled automations to sessions
feat(cron): bind scheduled automations to sessions
2026-06-13 00:07:55 +08:00
chengyongru
d72d0102d9 style: trim orphan toolcall comments
maintainer edit: keep the invariant comments in production code but remove repeated issue background from tests.
2026-06-13 00:05:03 +08:00
tangtaizhong666
ac5e84d453 fix(session): anchor save boundary to prompt prefix size (#4006)
build_messages merges the current message into a same-role history tail,
shrinking the prompt prefix to 1 + history_count. The save boundary
assumed a standalone current message and skipped one message too many,
cutting the first new-turn assistant message (with its tool_calls) from
persistence while keeping its tool results - producing orphaned tool
results in session history.
2026-06-13 00:05:03 +08:00
chengyongru
32d8a1dd7b fix: hide internal cron prompts from webui 2026-06-12 18:17:28 +08:00
chengyongru
80524e9e88 refactor: bind cron jobs to origin sessions 2026-06-12 14:00:53 +08:00
chengyongru
271b3651d7 refactor: use cron turn naming internally 2026-06-12 11:57:35 +08:00