1033 Commits

Author SHA1 Message Date
nanobot 59b4abaa14 chore: bump model defaults to Opus 4.7, Sonnet 4.6
Build Nanobot OAuth / build (pull_request) Successful in 7m4s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Build Nanobot OAuth / build (push) Successful in 2m48s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- Default model: anthropic/claude-opus-4-5 → anthropic/claude-opus-4-7
- Quota switcher: claude-opus-4-6 → claude-opus-4-7
- Update all provider defaults and test fixtures
- Update comments/docstrings referencing old model names
- Claude Opus 4.7 released 2026-04-16, same pricing as 4.6
2026-04-17 02:53:08 +02:00
code-server 71e65052d1 fix: use correct build_messages signature after emergency trim
Build Nanobot OAuth / build (push) Successful in 1m33s
Build Nanobot OAuth / cleanup (push) Successful in 0s
Used nonexistent 'system_prompt' variable. Match the keyword-arg call
pattern used at the top of _process_message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:22:06 +01:00
code-server 7b0714c5c5 fix(oauth): re-raise LongContextError past chat() blanket except
Build Nanobot OAuth / cleanup (push) Has been cancelled
Build Nanobot OAuth / build (push) Has been cancelled
chat() had a blanket `except Exception` that swallowed LongContextError,
preventing the agent loop from catching it for auto-consolidation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:17:57 +01:00
code-server 4bdcd0b568 feat: auto-consolidate session on long context 429
Build Nanobot OAuth / build (push) Successful in 5m1s
Build Nanobot OAuth / cleanup (push) Successful in 0s
When Anthropic returns 429 "Extra usage is required for long context
requests", the agent now automatically runs memory consolidation and
trims the session, then retries the LLM call with shorter context.

- Add LongContextError exception in providers/base.py
- Provider detects long-context 429 and raises immediately (no retry)
- Agent loop catches it in both _process_message and _process_system_message
- Consolidates facts, trims session, rebuilds messages, retries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:07:08 +01:00
code-server fdecb76035 fix(mem0): handle dict facts from LLM and fix slice error on dicts
Build Nanobot OAuth / build (push) Successful in 55s
Build Nanobot OAuth / cleanup (push) Successful in 1s
The extraction LLM returns facts as {"fact": "...", "date": "..."} dicts
instead of plain strings. store_facts now normalizes these to strings
before passing to mem0.add(). Also fixes KeyError when slicing dicts
in the error handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:48:31 +01:00
code-server b7d451ec5d fix(mem0): increase max_tokens for fact extraction from 2000 to 16384
Build Nanobot OAuth / cleanup (push) Has been cancelled
Build Nanobot OAuth / build (push) Has been cancelled
2000 tokens is insufficient for large sessions (700+ messages), causing
JSON truncation and parse failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:45:38 +01:00
code-server 86fe3a4749 test: add tests for identity block, fact extraction, and audit log
Build Nanobot OAuth / build (push) Successful in 47s
Build Nanobot OAuth / cleanup (push) Successful in 0s
- test_oauth_identity_block: verify identity block is included in API
  requests even when system=None (covers fix in 3f2684d)
- test_mem0_extract_facts: verify extract_facts passes thinking_budget=0
  to provider.chat() (covers fix in 76d5a73)
- test_session_audit_log: verify save() creates append-only audit log
  with markers and message preservation (covers feat in 2ab6494)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 12:49:23 +01:00
code-server 76d5a73cc7 fix(mem0): disable thinking for fact extraction calls
Build Nanobot OAuth / build (push) Successful in 5m40s
Build Nanobot OAuth / cleanup (push) Successful in 0s
Fact extraction inherited the instance thinking_budget (10000), causing
the model to spend tokens on thinking instead of outputting JSON. The
response content was empty, failing JSON parse every time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 12:36:21 +01:00
code-server 2ab6494ec9 feat(session): add append-only audit log
Build Nanobot OAuth / build (push) Successful in 5m59s
Build Nanobot OAuth / cleanup (push) Successful in 0s
Every SessionManager.save() now also appends the full session state
to a parallel audit file (*.audit.YYYY-MM.jsonl). This survives
session trims and memory consolidation — when something wipes the
session, the audit file retains the complete history.

Rotated monthly by filename. Never truncated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 06:31:53 +01:00
code-server 3f2684dcfe fix(oauth): include identity block in all API calls
Build Nanobot OAuth / build (push) Successful in 48s
Build Nanobot OAuth / cleanup (push) Successful in 0s
Anthropic requires the identity prefix for OAuth tokens on every
request, but it was only included when a system prompt was present.
Calls without a system prompt (e.g. fact extraction during memory
consolidation) got 400 invalid_request_error every time, silently
breaking memory consolidation while the session trim still ran.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 17:03:01 +01:00
code-server 266458528e fix(oauth): restore identity block required by Anthropic API
Build Nanobot OAuth / build (push) Successful in 23m54s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Anthropic now requires OAuth requests to include an approved identity
string as a separate first content block in the system prompt array.
Without it, Sonnet/Opus models return 400 invalid_request_error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 16:14:32 +01:00
code-server 35eb35cdc2 Merge pull request 'Sign intermediate messages for model visibility' (#31) from feat/message-visibility-signing into main
Build Nanobot OAuth / build (push) Successful in 1m1s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-09 18:08:37 +01:00
code-server 8cb5d93005 docs: add PR testing workflow guide
Build Nanobot OAuth / cleanup (push) Has been cancelled
Build Nanobot OAuth / build (push) Has been cancelled
Comprehensive guide for using the staging environment:
- Quick start with test-pr.sh script
- Manual testing methods
- Cache verification procedures
- Session management
- Troubleshooting tips

Includes examples for multi-turn testing and cache validation.
2026-03-09 18:07:57 +01:00
code-server 5569c99b8e feat: sign intermediate messages so model knows what user didn't see
Build Nanobot OAuth / build (pull_request) Successful in 6m14s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Intermediate assistant messages (with tool_calls) and tool result messages
are never sent to the user but remain in the model's context. This causes
the model to refer to content the user never saw.

Add _hidden_sig field at message creation time (context.py), then apply
[HIDDEN:sig] prefix at read time (session get_history) so the model sees
which messages were hidden. Storing the signature separately from content
preserves Anthropic prompt caching — the same prefixed string is produced
every turn.

Changes:
- visibility.py: add compute_signature(), refactor sign_content/verify to
  use it, fix Tuple -> tuple (PEP 585)
- context.py: add_assistant_message() and add_tool_result() store _hidden_sig
- session/manager.py: get_history() applies [HIDDEN:sig] prefix at read time
- tests/test_message_visibility.py: 14 tests covering compute_signature,
  _hidden_sig creation, get_history prefix, JSONL round-trip, idempotency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 15:23:46 +01:00
code-server d90c3b4a24 feat: sign intermediate messages so model knows what user didn't see
Build Nanobot OAuth / build (pull_request) Failing after 7m24s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Intermediate assistant messages (with tool_calls) and tool result messages
are never sent to the user but remain in the model's context. This causes
the model to refer to content the user never saw.

Add _hidden_sig field at message creation time (context.py), then apply
[HIDDEN:sig] prefix at read time (session get_history) so the model sees
which messages were hidden. Storing the signature separately from content
preserves Anthropic prompt caching — the same prefixed string is produced
every turn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 15:17:28 +01:00
code-server ee0b25e29a Merge pull request #32 'Add local staging environment for PR testing' from staging-setup into main
Build Nanobot OAuth / build (push) Failing after 8m39s
Build Nanobot OAuth / cleanup (push) Has been skipped
2026-03-09 15:16:32 +01:00
code-server a3fe901886 test: add coverage for NANOBOT_CONFIG and migration logic
Build Nanobot OAuth / build (pull_request) Failing after 7m0s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Tests for:
- get_config_path() with/without NANOBOT_CONFIG env var
- _migrate_config() with various oauthCredentials scenarios
- Edge cases: empty tokens, already-migrated configs, field preservation

All 7 tests passing.

Addresses review feedback from PR #32.
2026-03-09 12:21:48 +01:00
code-server 153b08f872 fix: clean up oauthCredentials after migration
Build Nanobot OAuth / build (pull_request) Failing after 7m49s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
- Remove oauthCredentials dict after extracting api_key to avoid duplication
- Use _ for unused provider_name variable per convention

Addresses review feedback from PR #32.
2026-03-09 12:20:27 +01:00
code-server 1b920d7299 fix: prevent branch collision in test-pr.sh
Use + refspec to force update pr-N branch on re-run. Prevents
'already exists' error when testing the same PR multiple times.

Addresses review feedback from PR #32.
2026-03-09 12:20:25 +01:00
code-server 4b3c42ad5c Add PR testing helper script
Build Nanobot OAuth / build (pull_request) Successful in 6m37s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Creates test-pr.sh to streamline PR testing workflow:
- Fetches PR from wylab remote
- Checks out PR branch
- Installs in editable mode with uv
- Runs test with staging config
- Uses NANOBOT_CONFIG to isolate from production

Usage: ./test-pr.sh <pr-number> [test-message]

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-09 10:44:02 +01:00
code-server 0de186071b Fix: Extract api_key from oauthCredentials in config migration
Added logic to _migrate_config() to automatically populate the api_key field
from oauthCredentials.access_token when present. This allows configs that
store OAuth tokens in the oauthCredentials structure to work correctly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-09 10:21:57 +01:00
code-server 7bcd6c5349 Add support for NANOBOT_CONFIG environment variable
Modify get_config_path() to check NANOBOT_CONFIG env var first before
falling back to ~/.nanobot/config.json. This allows staging/custom
setups to use a different config file without modifying code.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-09 10:17:59 +01:00
code-server 08b399a450 Merge pull request 'Fix test suite warnings (RuntimeWarning, DeprecationWarning)' (#28) from fix/test-warnings into main
Build Nanobot OAuth / build (push) Successful in 24m22s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-06 06:36:12 +01:00
code-server 97d5bd3c4d fix: resolve test suite warnings (RuntimeWarning, DeprecationWarning)
Build Nanobot OAuth / build (pull_request) Successful in 45s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Fixes all critical warnings from test suite:

1. **DeprecationWarning: datetime.utcnow()** (anthropic_oauth.py:458)
   - Replace `datetime.utcnow()` with `datetime.now(datetime.UTC)`
   - Python 3.12+ deprecation, will be removed in future versions
   - Affects API header debug logging

2. **RuntimeWarning: unawaited coroutine** (test_agent_loop_tool_result.py:31)
   - Change `session_mgr.save = AsyncMock()` to `MagicMock()`
   - Mock was async but production code is synchronous
   - Affected 4 tests (tool result handling tests)

**Test Results:**
```
======================= 277 passed in 7.61s =======================
```

All RuntimeWarning and DeprecationWarning eliminated from nanobot tests.

Note: PytestCacheWarning persists due to root-owned .pytest_cache directory
(cosmetic only, run with `-p no:cacheprovider` for clean output).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-06 05:20:46 +00:00
code-server a8f408b3b0 Merge pull request 'Fix remaining test failures (9 tests)' (#27) from fix/remaining-test-failures into main
Build Nanobot OAuth / build (push) Successful in 47s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-06 06:15:10 +01:00
code-server 0bdb762832 fix(tests): restore removed functionality and fix test failures
Build Nanobot OAuth / build (pull_request) Successful in 43s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
This commit fixes 9 test failures by addressing:

1. Computer tool VNC mocking (3 tests)
   - Fixed mock path from VNCDoToolClient to vnc_api.connect
   - Fixed captureScreen to write file instead of returning bytes
   - Fixed key press to expect lowercase keys

2. Onboard command fixture (4 tests)
   - Added workspace_dir.mkdir() in test fixture
   - Updated exit code expectations to match actual behavior
   - Fixed assertion messages

3. System prompt identity test (1 test)
   - Removed outdated test - feature moved to agent loop

4. Cron timezone validation (1 test)
   - Restored --tz flag (removed in f959185 as collateral damage)
   - Restored CLI-level validation
   - Restored try/except wrapper for service errors

All 277 tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-06 04:41:44 +00:00
wylab d49e009b12 revert 7dc400c05c
Build Nanobot OAuth / build (push) Successful in 23m15s
Build Nanobot OAuth / cleanup (push) Successful in 1s
revert Revert "Merge pull request #25: Add matrix optional dependencies and fix tests"

This reverts commit 65aca4d260, reversing
changes made to 53e09b924c.
2026-03-05 20:22:50 +01:00
code-server 7dc400c05c Revert "Merge pull request #25: Add matrix optional dependencies and fix tests"
Build Nanobot OAuth / build (push) Failing after 51s
Build Nanobot OAuth / cleanup (push) Has been skipped
This reverts commit 65aca4d260, reversing
changes made to 53e09b924c.
2026-03-05 17:35:05 +00:00
code-server 65aca4d260 Merge pull request #25: Add matrix optional dependencies and fix tests
Build Nanobot OAuth / build (push) Failing after 55s
Build Nanobot OAuth / cleanup (push) Has been skipped
2026-03-05 17:32:15 +00:00
code-server 34584c3a2e add matrix optional dependencies and fix tests
Build Nanobot OAuth / build (pull_request) Failing after 53s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
- Add [matrix] optional dependencies section to pyproject.toml
  (matrix-nio, mistune, nh3) to match error message guidance
- Fix test mock function signature to accept positional args
  instead of keyword-only args (removed *,)
- Fix test assertions to handle optional metadata keys
  using .get("attachments", []) instead of ["attachments"]

All 45 matrix channel tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 17:28:40 +00:00
code-server 53e09b924c remove obsolete task cancellation tests
Build Nanobot OAuth / build (push) Failing after 53s
Build Nanobot OAuth / cleanup (push) Has been skipped
These tests were for /stop command functionality that was removed
during the quota-based model switching refactor (commit 19a81e1).

Tests were checking for methods that no longer exist:
- _handle_stop()
- _dispatch()
- _active_tasks
- _session_tasks
- cancel_by_session()

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 16:23:10 +00:00
code-server 1b302ab4bf Merge pull request 'fix: update runtime context test for system prompt inclusion' (#24) from fix/runtime-context-test into main
Build Nanobot OAuth / build (push) Failing after 54s
Build Nanobot OAuth / cleanup (push) Has been skipped
2026-03-05 17:16:48 +01:00
code-server 3c681f1639 Merge pull request 'fix: update beta flags tests to expect combined hardcoded + tool flags' (#23) from fix/beta-flags-tests into main
Build Nanobot OAuth / build (push) Successful in 21m26s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-05 14:04:04 +01:00
code-server 1ff3356d1b Merge pull request 'fix: update EditTool name in tests to match implementation' (#22) from fix/edit-tool-name-tests into main
Build Nanobot OAuth / cleanup (push) Has been cancelled
Build Nanobot OAuth / build (push) Has been cancelled
2026-03-05 14:02:29 +01:00
code-server 5193e34803 fix: update runtime context test for system prompt inclusion
Build Nanobot OAuth / build (pull_request) Successful in 21m52s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The runtime context (channel/chat_id) is now included in the system
prompt instead of being a separate user message. This is a deliberate
design change to simplify the message structure.

Changes:
-  Updated test to expect runtime context in system prompt
-  Updated test description to reflect new behavior
-  Removed assertions for separate user message

Test now passes with the current implementation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 12:48:51 +00:00
code-server 8f8fc81135 fix: update beta flags tests to expect combined hardcoded + tool flags
Build Nanobot OAuth / build (pull_request) Successful in 6m13s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The AnthropicOAuthProvider always includes hardcoded beta flags:
- claude-code-20250219
- oauth-2025-04-20
- context-management-2025-06-27

Tool-specific beta flags are then merged with these and sorted
alphabetically. Tests were only checking for tool flags, not the
combined result.

Changes:
-  Updated test_oauth_utils.py to expect all hardcoded flags
-  Updated test_beta_flags_collected_from_tools to expect combined flags
-  Updated test_multiple_beta_flags_joined to expect combined flags

All 3 beta flags tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 09:44:17 +00:00
code-server d4abb3d06f fix: update EditTool name in tests to match implementation
Build Nanobot OAuth / build (pull_request) Successful in 6m11s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The EditTool20250728 uses the name "str_replace_based_edit_tool" but
tests were checking for the old name "str_replace_editor". This commit
updates all test expectations to use the correct tool name.

Changes:
-  Updated test_edit_tool.py to expect "str_replace_based_edit_tool"
-  Updated test_native_tools_registration.py for correct tool name
-  Updated test_registry_native_execution.py to execute with correct name
-  Removed computer tool assertion (intentionally disabled by default)

All 3 EditTool naming tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 09:34:25 +00:00
code-server b2570f1a62 Merge pull request 'fix: update SubagentManager spawn() to match test expectations' (#21) from fix/subagent-manager-tests into main
Build Nanobot OAuth / build (push) Successful in 48s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-05 10:31:54 +01:00
code-server f19b5f5929 fix: update SubagentManager spawn() to match test expectations
Build Nanobot OAuth / build (pull_request) Successful in 6m13s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The SubagentManager.spawn() method was returning a human-readable status
message, but tests (and wait_for()) expected it to return the task ID
directly. This commit fixes both the implementation and the tests:

Implementation changes:
- spawn() now returns the task_id (string) instead of a status message
- Updated docstring to reflect the correct return value
- Status message is still logged for debugging

Test changes:
- Updated spawn() calls to use new parameter structure:
  * Changed from: origin={"channel": "x", "chat_id": "y"}
  * Changed to: origin_channel="x", origin_chat_id="y"

This makes spawn() more useful programmatically - callers can use the
returned task_id with wait_for() without parsing a message.

All 3 SubagentManager tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 08:05:54 +00:00
code-server 8e829396b2 Merge pull request 'fix: update HeartbeatService tests for new constructor API' (#20) from fix/heartbeat-service-tests into main
Build Nanobot OAuth / build (push) Successful in 44s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-03-05 08:44:05 +01:00
code-server e8e8ca6700 fix: update HeartbeatService tests for new constructor API
Build Nanobot OAuth / build (pull_request) Successful in 7m4s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The HeartbeatService constructor was refactored to use an on_heartbeat
callback instead of accepting provider/model parameters directly. This
commit updates the tests to match the new API:

- Removed DummyProvider class (no longer needed)
- Updated test_start_is_idempotent to use new constructor
- Removed test_decide_returns_skip_when_no_tool_call (_decide method no longer exists)
- Updated test_trigger_now_executes_when_decision_is_run to use on_heartbeat callback
- Updated test_trigger_now_returns_none_when_no_callback to test new behavior

Also fixed a bug where start() was not idempotent - it now checks if a
task is already running before creating a new one.

All 3 HeartbeatService tests now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 07:04:37 +00:00
code-server f1cbd4d730 Merge pull request 'fix: restore message tool suppression to prevent duplicate messages' (#19) from fix/message-tool-suppression into main
Build Nanobot OAuth / build (push) Successful in 6m10s
Build Nanobot OAuth / cleanup (push) Successful in 2s
2026-03-05 07:40:50 +01:00
code-server f7cebfe7f3 fix: restore message tool suppression to prevent duplicate messages
Build Nanobot OAuth / build (pull_request) Successful in 7m14s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
When the agent uses the message tool to reply to the same channel/chat_id
as the incoming message, the final automatic reply is now suppressed to
prevent duplicate messages to the user.

Changes:
- MessageTool: add _sent_in_turn flag and start_turn() method
- MessageTool.execute(): set flag when sending to same target as context
- AgentLoop._process_message(): call start_turn() at beginning
- AgentLoop._process_message(): return None if message tool already sent

This restores functionality that was accidentally removed during refactoring
(originally implemented in commits fafd8d4, 29e6709).

Fixes 3 failing tests in test_message_tool_suppress.py

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 04:30:48 +00:00
code-server b854d9a888 test: remove obsolete last_consolidated tests
Build Nanobot OAuth / build (pull_request) Successful in 5m59s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The test_consolidate_offset.py file contained ~100 tests for the
last_consolidated field which no longer exists. Since the field and its
incremental consolidation behavior have been removed, these tests are
obsolete.

Also removed redundant empty check in memory.py consolidation (if
len <= keep_count, then slice will be empty).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-04 18:39:26 +00:00
code-server 83d2acf07f fix: remove dead last_consolidated field from Session
Build Nanobot OAuth / build (pull_request) Successful in 5m51s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
The `last_consolidated` marker was designed for incremental consolidation
assuming append-only messages. However, deferred trim removes messages from
the session, which broke the incremental assumption and caused consolidation
to fail silently (early exit when end_idx <= stale last_consolidated).

After trim, the session only contains NEW unconsolidated messages, making
the marker unnecessary. Consolidation now always starts from index 0,
processing all messages in the session (which are by definition not yet
consolidated due to trim).

Fixes the bug where extraction completely stopped working after trim
(zero facts extracted despite multiple consolidation attempts).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-04 17:23:21 +00:00
code-server eee9c38953 Merge pull request 'Fix consolidation checkpoint-based trim to preserve history' (#17) from fix/consolidation-checkpoint-trim into main
Build Nanobot OAuth / build (push) Successful in 23m51s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Fix consolidation checkpoint-based trim (#17)
2026-03-04 16:32:55 +01:00
code-server e782318338 fix: add deferred trim to system message handler
Build Nanobot OAuth / build (pull_request) Successful in 6m58s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
System messages (including subagents) can trigger memory_consolidate,
which sets _trim_checkpoint. The system handler must also check and
apply deferred trims to prevent unbounded session growth.

Addresses review feedback from PR #17.
2026-03-04 15:15:53 +00:00
code-server dc94aa76cc fix(consolidation): use checkpoint-based trim instead of relative count
Build Nanobot OAuth / build (pull_request) Successful in 6m50s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
**Problem:**
When memory_consolidate is called mid-turn, deferred trim was using a
relative count (_pending_trim) that gets applied after the turn completes.
This caused the trim to recalculate the cut point based on the FINAL session
size (after messages were added), and _trim_to_clean_boundary would walk
backward to find a user message, often landing at the START of the current
turn and wiping all prior history.

Example: Session with 426 messages, consolidate sets pending_trim=10, turn
grows to 440 messages, trim calculates cut=430, finds no user messages in
430-439 (all tool chain), walks back to position 426 (current turn start),
wipes messages 0-425.

**Solution:**
Replace relative count with absolute checkpoint position:
- At consolidation time: calculate checkpoint = len(session) - keep_count
- Find clean boundary at or before checkpoint (not after turn completes)
- Store absolute position in session._trim_checkpoint
- At trim time: simply slice session.messages[checkpoint:]

This preserves the intended trim point regardless of messages added during
the remainder of the turn.

**Testing:**
Hot-patched and verified:
- Before: consolidation wiped all history, kept only current turn (16 msgs)
- After: consolidation preserved history correctly (23 msgs from before consolidation)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-04 15:05:02 +00:00
code-server 5cf019c21e Merge pull request 'feat: extract facts with main agent LLM, bypass mem0 GPT-nano' (#15) from feat/mem0-extract-llm into main
Build Nanobot OAuth / build (push) Successful in 56s
Build Nanobot OAuth / cleanup (push) Successful in 0s
2026-03-04 14:16:45 +01:00
nanobot 790bdd6b8a fix: remove dead code, fix JSON parsing, add facts validation
Build Nanobot OAuth / build (pull_request) Successful in 6m30s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
2026-03-04 14:06:44 +01:00