Commit Graph
90 Commits
Author SHA1 Message Date
code-serverandClaude Sonnet 4.5 730f42a542 Snapshot: All native Anthropic tools implemented
Complete implementation of all three native Anthropic tools:
- bash_20250124: Shell command execution
- text_editor_20250124: File editing operations
- computer_20251124: VNC desktop control (all 17 actions)

Includes provider updates, test improvements, and registry changes.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-28 02:37:57 +00:00
code-serverandClaude Sonnet 4.5 6845d02456 Add all 17 native computer_20251124 actions to VNC tool
Implemented missing actions reported by nanobot:
- scroll (with direction, amount, modifier support)
- zoom (region cropping)
- triple_click, double_click, middle_click
- left_mouse_down, left_mouse_up, left_click_drag
- hold_key (with duration)
- paste (VNC clipboard)
- wait (with duration)

All actions tested and working via VNC at 172.17.0.1::5900.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-28 02:35:32 +00:00
code-serverandClaude Sonnet 4.5 4dfb40d99d fix(tools): add duck typing to registry execute() method
Registry now supports executing both native Anthropic tools (via __call__)
and function tools (via execute). Native tools return ToolResult/CLIResult
objects instead of strings.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 23:59:39 +00:00
code-serverandClaude Sonnet 4.5 7d3c805905 test(agent): verify native tools registration
Add test confirming BashTool20250124, EditTool20250728, and
ComputerTool20251124 are registered in AgentLoop on initialization.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 23:41:18 +00:00
code-serverandClaude Sonnet 4.5 d65af9e0e8 test(agent): add test for media tracking
Verify that screenshots from computer tool are tracked in
media_paths_for_turn and included in OutboundMessage.media.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 23:18:04 +00:00
code-serverandClaude Sonnet 4.5 34c23aac4b fix(agent): handle ToolResult in system message handler
Apply same result type handling logic to _process_system_message
to support native tools in subagent/system contexts.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 23:00:14 +00:00
code-serverandClaude Sonnet 4.5 19a0b33501 feat(tools): remove ExecTool and EditFileTool
Replaced by BashTool20250124 and EditTool20250728 which provide
better functionality via model-trained behaviors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:59:35 +00:00
code-serverandClaude Sonnet 4.5 d775fa6b24 feat(agent): register native tools in agent loop
BashTool20250124, EditTool20250728, and ComputerTool20251124 are now
automatically registered alongside existing function tools.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:58:41 +00:00
code-serverandClaude Sonnet 4.5 b98c7a1e4d feat(agent): add media tracking for screenshots
Screenshots from computer tool are saved to disk and included in
OutboundMessage.media for channel delivery to users.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:57:31 +00:00
code-serverandClaude Sonnet 4.5 c87a4c50a4 test(agent): add tests for ToolResult handling in agent loop
Comprehensive tests for:
- ToolResult with output field
- ToolResult with error field
- ToolResult with base64_image field
- CLIResult handling
- Legacy string results (backward compatibility)
- Combined output and error fields

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:56:33 +00:00
code-serverandClaude Sonnet 4.5 2f37deeac0 feat(agent): add ToolResult handling to agent loop
Agent loop now processes ToolResult and CLIResult from native tools,
while maintaining backward compatibility with string results.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:56:02 +00:00
code-serverandClaude Sonnet 4.5 c0ea0929ef fix(tests): update CLIResult test for new signature
CLIResult now requires exit_code, output, and error fields after
EditTool implementation. Update test to match new signature.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:49:27 +00:00
code-serverandClaude Sonnet 4.5 568377725d chore: add vncdotool dependency for ComputerTool20251124
Add vncdotool>=1.0.0 to dependencies for VNC-based computer
control. Tool implementation gracefully handles missing dependency
with ImportError check.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:48:13 +00:00
code-serverandClaude Sonnet 4.5 5a440b1c6b feat(tools): implement ComputerTool20251124
Add computer_20251124 for VNC desktop control. Supports keyboard,
mouse, and screenshots via vncdotool.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:47:54 +00:00
code-serverandClaude Sonnet 4.5 88f3bc1b3c test(tools): add missing tests for EditTool20250728
Add test_edit_tool_requires_absolute_path and test_edit_tool_to_params
to complete test coverage per specification.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:45:53 +00:00
code-serverandClaude Sonnet 4.5 c727ba0083 feat: implement EditTool20250728 with view/create/str_replace/insert
- Add text_editor_20250728 native tool
- Support 4 commands: view, create, str_replace, insert
- Require absolute paths for all operations
- Enforce str_replace uniqueness (count == 1)
- Format view output with line numbers
- Return CLIResult with exit_code/output/error
- All 5 tests passing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:41:59 +00:00
code-serverandClaude Sonnet 4.5 0c1bae0391 feat(tools): implement BashTool20250124 with persistent session
Add Anthropic's native bash_20250124 tool with:
- Persistent bash subprocess (_BashSession)
- Sentinel-based output reading (<<BASH_COMMAND_DONE>>)
- 120s timeout per command
- Session restart capability
- Full test coverage (4 tests)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 22:20:03 +00:00
code-serverandClaude Sonnet 4.5 cda3987c30 test(provider): improve beta flag test assertion
Make test more specific by expecting exact sorted order
instead of checking both permutations.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 21:05:12 +00:00
code-serverandClaude Sonnet 4.5 1611daa0be feat(provider): add beta flag collection for native tools
Extract beta_flag from tool objects before conversion and add
to API request headers. Supports multiple flags via comma-join.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:59:24 +00:00
code-serverandClaude Sonnet 4.5 be934767ee feat(provider): support native tools in API conversion
_convert_tools_to_anthropic now passes through native tool format
(bash_20250124, etc.) while still converting function tools.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:29:34 +00:00
code-serverandClaude Sonnet 4.5 a480d972ec feat(tools): add duck typing support to ToolRegistry
Registry now supports both function tools (to_schema) and native
tools (to_params) via hasattr checks. Enables mixed tool types.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:19:31 +00:00
code-serverandClaude Sonnet 4.5 c840be67fb test(tools): add complete coverage for base classes
Add tests for CLIResult and ToolError.
Expand ToolResult test to cover system field.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:16:42 +00:00
code-serverandClaude Sonnet 4.5 9dba6a3a50 feat(tools): add Anthropic native tool base classes
Add BaseAnthropicTool, ToolResult, CLIResult, and ToolError.
These support native tools with version-coupled behaviors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:11:57 +00:00
code-serverandClaude Sonnet 4.5 bf0e3b0197 Add .worktrees/ to .gitignore
Preparing for isolated feature development using git worktrees.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 20:04:02 +00:00
code-serverandClaude Sonnet 4.5 5b0a08d042 Add design: Native Anthropic tools integration
Design for integrating bash_20250124, text_editor_20250728, and
computer_20251124 native tools into nanobot. These tools leverage
model-trained behaviors instead of instruction-following.

Key approach: Duck-typed registry supporting both function tools
and native tools, with beta flag management and ToolResult handling.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 07:51:10 +00:00
code-serverandClaude Sonnet 4.5 6784784211 fix: preserve filenames for documents and audio in Telegram
Build Nanobot OAuth / build (push) Successful in 5m59s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Root cause: send_document and send_audio were receiving raw bytes
without filename metadata, causing Telegram to use generic
"application.octet-stream" name.

Solution: Extract filename from path and pass via filename parameter
to send_document/send_audio and their InputMedia counterparts.

Images/videos unaffected as Telegram infers names from content type.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 07:22:23 +00:00
code-serverandClaude Sonnet 4.5 1c40ac7cfe fix: add missing Path import to telegram.py
Build Nanobot OAuth / build (push) Successful in 6m1s
Build Nanobot OAuth / cleanup (push) Successful in 1s
The _send_with_media method uses Path but the import was missing from the top-level imports, causing "name 'Path' is not defined" error.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 06:59:53 +00:00
code-serverandClaude Sonnet 4.5 3b7890c3d8 feat: complete media implementation with agent tools layer
Build Nanobot OAuth / build (push) Successful in 5m53s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Add missing media parameter to message tool, enabling agents to send media attachments via the message() tool.

Changes:
- message.py: Add media parameter to tool schema and execute() method
- telegram.py: Restore _send_with_media() method with album support

This completes the three-layer media architecture:
- Agent Loop: message tool now accepts media parameter
- Provider Layer: OutboundMessage carries media list
- Telegram Channel: _send_with_media processes and sends media

Fixes the root cause where agents had no way to specify media attachments, resulting in invented [file: ...] syntax in message content.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 06:49:47 +00:00
code-server 69d2bb02e9 Remove accidentally committed system files
Build Nanobot OAuth / build (push) Successful in 6m8s
Build Nanobot OAuth / cleanup (push) Successful in 1s
2026-02-27 05:34:04 +00:00
code-server d87687184a Revert broken media implementation - incomplete, missing agent tools layer
Build Nanobot OAuth / cleanup (push) Has been cancelled
Build Nanobot OAuth / build (push) Has been cancelled
2026-02-27 05:33:18 +00:00
code-serverandClaude Sonnet 4.5 b533c55a53 fix: address resource leaks and caption logic in media sending
Build Nanobot OAuth / build (push) Successful in 5m57s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- Add context manager to PIL Image.open() to prevent file handle leaks
- Fix caption logic for separate media (track first non-album item)
- Improve exception handling with size checks and specific types
- Add constants for magic numbers (REMOTE_MEDIA_SIZE_LIMIT)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 05:06:23 +00:00
code-serverandClaude Sonnet 4.5 f6075999f6 feat: integrate media sending with album support
Processes local files and remote URLs
Optimizes images automatically
Groups 2+ images/videos into albums
Handles caption overflow (>1024 chars)
Routes to correct Telegram API methods

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 04:42:46 +00:00
code-serverandClaude Sonnet 4.5 e131f452da feat: add album grouping logic
Groups 2+ images or 2+ videos into albums
Mixed types or single items sent separately

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 04:12:11 +00:00
code-serverandClaude Sonnet 4.5 b952b7a68a feat: add remote media fetch with httpx
Downloads from URLs with 10s timeout
Detects MIME from response headers or content
Enforces size limit

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 04:07:12 +00:00
code-serverandClaude Sonnet 4.5 cc4a718b56 fix: remove fake async and improve image optimization
- Remove async keyword from synchronous image processing
- Always copy images to avoid mutation issues
- Fix PNG fallback to handle LA (grayscale+alpha) mode
- Use pytest tmp_path fixture for cleaner tests
- Add TELEGRAM_PHOTO_SIZE_LIMIT constant

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 04:02:23 +00:00
code-serverandClaude Sonnet 4.5 944ae445d0 feat: add image optimization with quality ladder
HEIC → JPEG conversion via pillow-heif
PNG with alpha preserved, compressed [6-9]
JPEG optimized via size [2048-800] × quality [80-40] grid

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 03:56:45 +00:00
code-serverandClaude Sonnet 4.5 c28fdd114b feat: add HEIC format detection
Checks for .heic and .heif extensions
Foundation for HEIC to JPEG conversion

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 02:35:14 +00:00
code-serverandClaude Sonnet 4.5 5fab8aeb62 feat: add media kind classification
Classifies MIME types into IMAGE/VIDEO/AUDIO/DOCUMENT
Used for routing to correct Telegram API methods

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 02:01:43 +00:00
code-serverandClaude Sonnet 4.5 c0cc18fb7b fix: clean up imports and improve error handling in telegram_media
- Remove unused imports (Path, pytest)
- Add logging for magic detection failures
- Improve test coverage for edge cases

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 01:57:42 +00:00
code-serverandClaude Sonnet 4.5 89f7829f26 feat: add MIME detection with python-magic and extension fallback
Priority: magic sniff > extension > fallback
Handles JPEG, PNG, video, and unknown files

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 01:52:56 +00:00
code-serverandClaude Sonnet 4.5 edc2501ef1 feat: add pillow-heif and python-magic dependencies
Required for media handling:
- pillow-heif: HEIC to JPEG conversion
- python-magic: MIME type detection

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 01:47:20 +00:00
code-serverandClaude Sonnet 4.5 1303fa4435 fix: reduce heartbeat idle threshold to 20m to avoid hour-long gaps
Build Nanobot OAuth / build (push) Successful in 24m57s
Build Nanobot OAuth / cleanup (push) Successful in 3s
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-24 01:31:48 +00:00
code-serverandClaude Sonnet 4.5 9513bb5731 feat: auto-start moltbook polling loop on gateway startup
Build Nanobot OAuth / build (push) Successful in 5m39s
Build Nanobot OAuth / cleanup (push) Successful in 0s
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-24 00:51:08 +00:00
code-serverandClaude Sonnet 4.5 f4e664914a fix: clarify subagent message tool sends to main agent, not user
Build Nanobot OAuth / build (push) Successful in 5m45s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Updated descriptions to make it clear the message tool sends to the
main agent (who processes and decides how to respond), not directly
to the user.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 22:09:39 +00:00
code-serverandClaude Sonnet 4.5 6004cfa9bf feat: add message tool for subagents with metadata preservation
Subagents can now send messages to users via the message tool.
Messages are routed through the main agent via the bus and preserve
metadata (e.g. suppress_output) from the originating message.

Changes:
1. Created SubagentMessageTool that creates InboundMessages
2. Publishes to bus with preserved metadata
3. Registered in subagent tool registry
4. Updated subagent system prompt to mention message capability

This allows subagents to communicate findings during execution while
respecting suppression flags (e.g. heartbeat subagents won't spam Telegram).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 22:07:37 +00:00
code-serverandClaude Sonnet 4.5 0cfc803301 fix: propagate suppress_output metadata to subagent announcements
When a subagent completes and announces its result, it now inherits the
metadata (including suppress_output) from the original message that spawned it.

Changes:
1. SpawnTool.set_context() now accepts metadata parameter
2. SubagentManager.spawn() now accepts origin_metadata parameter
3. Origin dict now includes 'metadata' field
4. _announce_result() includes metadata when creating InboundMessage
5. All set_context() calls pass msg.metadata

This fixes the bug where heartbeat suppression was lost when subagents
announced their results - the subagent announcement would be visible on
Telegram even though the heartbeat itself was suppressed.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 22:04:25 +00:00
code-serverandClaude Sonnet 4.5 7f331b784e fix: wait_for_subagents now works for top-level subagents
Store results in _task_results for ALL subagents, regardless of origin.
Then only announce to bus if it's a top-level subagent (not a child).

This fixes the bug where wait_for_subagents would return 'No result found'
for subagents spawned from the main telegram session, because their results
went to the bus instead of _task_results.

Now:
- All subagents store results in _task_results (so wait_for can find them)
- Child subagents (origin[channel] == 'subagent') return early (no announcement)
- Top-level subagents continue and announce via bus (so main agent gets notified)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 21:53:06 +00:00
code-server efa3819f13 merge: combine visibility markers + heartbeat idle detection 2026-02-23 21:45:52 +00:00
code-serverandClaude Sonnet 4.5 84383db21f fix: heartbeat idle detection now correctly identifies real user messages
The heartbeat service was incorrectly counting ALL messages with role="user"
as user activity, including system-generated messages (heartbeat prompts,
subagent announcements). This caused the idle detection to never trigger
because heartbeat's own messages were counted as user activity.

Changes:
1. Store sender_id in session messages (loop.py)
   - Added sender_id=msg.sender_id to session.add_message() call
   - Allows distinguishing real user messages from system-generated ones

2. Filter by sender_id in heartbeat idle detection (service.py)
   - Real Telegram messages have sender_id like "239824268|username"
   - System messages via process_direct have sender_id="user" (hardcoded)
   - Heartbeat now skips messages with sender_id="user"
   - Backwards compatible: messages without sender_id are treated as real

This is a robust, source-based solution that checks how messages are
CREATED rather than pattern-matching their content.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 21:08:32 +00:00
code-serverandClaude Sonnet 4.5 6023a1a078 fix: update tests to handle signed visibility markers
Updated existing tests to work with cryptographic visibility markers:

1. test_agent_loop_metadata.py:
   - Updated test_suppress_mode_adds_hidden_prefix to verify [HIDDEN:signature] format
   - Added validation for 8-character hex signature
   - Updated test_normal_mode_no_hidden_prefix to check for [HIDDEN: prefix

2. test_idle_heartbeat_integration.py:
   - Updated test_idle_heartbeat_end_to_end to search for [HIDDEN: prefix
   - Added signature format validation (8-char hex)
   - Updated docstring to reflect signed markers

All 86 tests now pass (excluding OAuth tests as specified).
The changes maintain backwards compatibility while enforcing
the new cryptographic signing requirement.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:41:32 +00:00
code-serverandClaude Sonnet 4.5 71fb1f35ba feat: apply signed markers to system message handler
Extends signed marker support to _process_system_message() for subagent
announcements. Ensures consistency across all suppress mode paths.

- Add forgery detection in system message loop
- Sign content before saving to session when suppressed
- Return unsuppressed content with suppressed metadata
- Add comprehensive tests for system message signing and forgery rejection

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:38:45 +00:00
code-serverandClaude Sonnet 4.5 6b31dba38d feat: add forgery detection and rejection in agent loop
Detects forged [HIDDEN:*] markers in model output and triggers rejection
with retry. Includes correction message to model and fallback stripping
if model persists. Prevents accumulation from model forgery attempts.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:34:53 +00:00
code-serverandClaude Sonnet 4.5 0f5c8ab879 feat: use signed markers in suppress mode (_process_message)
Replaces simple [HIDDEN] prefix with cryptographically signed markers
in _process_message(). Strips any forged markers from model output
before signing with system key.

Includes comprehensive accumulation test that verifies:
- Markers are properly signed when suppress_output=True
- Model seeing markers in context doesn't copy them
- No accumulation of markers across multiple messages
- Each hidden message gets exactly one signed marker

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:25:01 +00:00
code-serverandClaude Sonnet 4.5 d7509fbb88 test: add system prompt visibility docs test
Verifies that system prompt includes documentation about cryptographically
signed visibility markers.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:21:18 +00:00
code-serverandClaude Sonnet 4.5 0d3fb75327 docs: add visibility markers explanation to system prompt
Documents the purpose of [HIDDEN:{sig}] markers and explicitly forbids
model from generating them. Sets clear expectations for rejection behavior.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 20:21:14 +00:00
code-serverandClaude Sonnet 4.5 886ecabe70 fix: use constant-time comparison and flexible whitespace in visibility markers
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 18:10:26 +00:00
code-serverandClaude Sonnet 4.5 131be70dc8 feat: add signature verification and marker stripping
Implements verify_signature() to check HMAC validity, has_forged_marker()
to detect forgery attempts, and strip_all_hidden_markers() for cleanup.
Comprehensive test coverage for all verification scenarios.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 18:05:40 +00:00
code-serverandClaude Sonnet 4.5 7c9dfb6ce6 feat: add HMAC signature generation for visibility markers
Implements sign_content() to cryptographically sign message content
with HMAC-SHA256 (8-char truncated). This prevents models from forging
visibility markers as they cannot generate valid signatures.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 18:00:45 +00:00
code-serverandClaude Sonnet 4.5 9a440d004f fix: ensure integration test uses isolated session storage
Override SessionManager.sessions_dir to use tmp_path, preventing
session accumulation across test runs.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 03:31:30 +00:00
code-serverandClaude Sonnet 4.5 f971e8532f fix: improve integration test cleanup and assertions
- Use tmp_path fixture for automatic cleanup
- Assert exactly 1 heartbeat message (not > 0)
- Use test-specific session key instead of production key

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 03:19:00 +00:00
code-serverandClaude Sonnet 4.5 cfa8bde71d fix: apply [HIDDEN] prefix before saving to session
Bug discovered during integration test: suppress mode was
prefixing content AFTER saving to session, so session stored
unprefixed content while only the outbound message was prefixed.

Fix: Move suppress check before session save and use prefixed
content when adding to session messages.

test: add end-to-end integration test for idle heartbeat

Verifies complete flow:
- Idle detection triggers heartbeat
- Heartbeat runs in main session
- Output is suppressed with [HIDDEN] prefix
- Session contains full context

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 03:14:36 +00:00
code-serverandClaude Sonnet 4.5 bdaff015b5 fix: linting in gateway command
Auto-fix import sorting and whitespace issues.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:51:58 +00:00
code-serverandClaude Sonnet 4.5 e89c199235 feat: wire up idle heartbeat in gateway command
- Update callback to pass metadata and use telegram session
- Pass session manager to HeartbeatService
- Configure 30min idle threshold

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:37:43 +00:00
code-serverandClaude Sonnet 4.5 b6c21b2356 fix: address linting issues in heartbeat idle detection
- Add future annotations import for type hints
- Add TYPE_CHECKING import for SessionManager forward reference
- Remove unused response variable in _tick method
- Fix whitespace in docstring

Tests directory changes (removed unused imports) remain in working tree
but are not committed due to .gitignore.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:24:46 +00:00
code-serverandClaude Sonnet 4.5 26cbade249 feat: add idle detection to heartbeat service
Heartbeat now:
- Checks last user message timestamp in target session
- Only triggers if >30min elapsed since last user message
- Passes suppress_output metadata to callback
- Removes HEARTBEAT_OK check (unnecessary with suppress mode)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:19:12 +00:00
code-serverandClaude Sonnet 4.5 be9e3004cb fix: stop typing indicator before checking suppression
Fixes bug where suppressed messages would leave typing indicator
running forever. Now _stop_typing() is called before early return.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:15:37 +00:00
code-serverandClaude Sonnet 4.5 d3aa685339 feat: add suppression support to Telegram channel
Messages with metadata['suppressed']=True are logged but not sent
to Telegram API, enabling heartbeat to run without spamming user.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:12:11 +00:00
code-serverandClaude Sonnet 4.5 2ed2ac840f feat: implement suppress mode in agent loop
When metadata['suppress_output']=True:
- Adds [HIDDEN] prefix to content saved in session
- Sets metadata['suppressed']=True for channel handler
- Allows explicit message() tool calls to bypass suppression

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 02:04:48 +00:00
code-serverandClaude Sonnet 4.5 0a2dab9af5 feat: add metadata parameter to AgentLoop.process_direct()
Allows passing metadata through process_direct() for features like
suppress mode in heartbeat.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 01:29:58 +00:00
code-serverandClaude Sonnet 4.5 825010f4d1 Refactor hooks config to remove redundancies
Build Nanobot OAuth / build (push) Successful in 50s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- Remove singular `token` field, keep only `tokens` dict
- Simplify `resolve_token()` and `has_tokens` logic
- Use finally block for correlation cleanup in server
- Simplify `_resolve_auth()` to eliminate duplicate pattern
- Remove redundant `has_tokens` check from CLI (server checks internally)
- Update tests to remove backward-compat test cases

Lines removed: ~30
Tests passing: 14/14

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 08:02:30 +00:00
code-serverandClaude Sonnet 4.5 98ca0babf2 test: end-to-end hooks integration tests
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:42:00 +00:00
code-serverandClaude Sonnet 4.5 445e316f9b feat: wire hooks server + hook channel into CLI startup
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:40:54 +00:00
code-serverandClaude Sonnet 4.5 59e1734944 feat(hooks): rewrite server to use bus + correlation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:38:37 +00:00
code-serverandClaude Sonnet 4.5 3af0703b7c feat(channels): add hook channel
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:36:22 +00:00
code-serverandClaude Sonnet 4.5 9b3782adf8 feat(config): named tokens for hooks
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:34:05 +00:00
code-serverandClaude Sonnet 4.5 25a686b100 feat(agent): carry metadata through all OutboundMessage paths, add hook prefix
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:24:48 +00:00
code-serverandClaude Sonnet 4.5 aa055518e0 feat(manager): resolve correlation in outbound dispatch
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:22:42 +00:00
code-serverandClaude Sonnet 4.5 e5bad4eba0 feat(bus): add correlation store for request-response
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-22 07:16:40 +00:00
code-serverandClaude Sonnet 4.5 38e7201a3d MessageTool writes to session; remove max_messages limit
Build Nanobot OAuth / build (push) Successful in 53s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- MessageTool now writes sent messages to session history via SessionManager
- Agent loop wires SessionManager into MessageTool constructor
- Session.get_history() returns full history (removed max_messages limit)
  Server-side context editing API handles trimming, so we send full history

This ensures messages sent via the message() tool (e.g., from heartbeat forks)
are visible in the main conversational agent's context.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-21 23:23:51 +00:00
code-serverandClaude Sonnet 4.5 6d66d0eafd session: remove max_messages slicing from get_history()
Build Nanobot OAuth / build (push) Successful in 50s
Build Nanobot OAuth / cleanup (push) Successful in 2s
Sending a slice of history can cut in the middle of a tool chain, causing
'unexpected tool_use_id' 400 errors when the API receives an orphaned
tool_result without its preceding assistant tool_use block.

The server-side context editing API (clear_tool_uses_20250919) handles
trimming safely at token thresholds while respecting tool chain boundaries.
Let the server manage context length; send the full history from the client.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 12:33:02 +00:00
code-serverandClaude Sonnet 4.5 24babc1654 Store full tool chain in session; replace manual consolidation with server-side context editing
Build Nanobot OAuth / build (push) Successful in 5m33s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- session/manager.py: add add_raw_message() to persist tool chain messages;
  get_history() now passes all API-relevant fields (tool_calls, tool_call_id,
  name, reasoning_content) instead of stripping to role+content only

- loop.py: after each turn, save the complete message sequence (tool_use,
  tool_results, thinking blocks, final reply) instead of just the final text;
  remove automatic consolidation trigger — server-side context editing handles
  the token window now; _consolidate_memory (runs on /new) updated to handle
  list content, tool messages, and new message formats

- anthropic_oauth.py: add context_management parameter to chat() and
  _make_request(); log context edits applied by Anthropic; log context_mgmt
  strategies in request log line

- oauth_utils.py: add context-management-2025-06-27 beta header

- base.py, litellm_provider.py: propagate context_management parameter

CONTEXT_MANAGEMENT config on every agent call:
  - clear_thinking_20251015 keep="all" → preserve all thinking blocks for cache
  - clear_tool_uses_20250919 trigger=80k tokens, keep=5 recent tool uses

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 12:02:56 +00:00
code-serverandClaude Sonnet 4.5 23f2c1a773 fix(subagent): don't inherit Opus from main loop — use Sonnet default
Build Nanobot OAuth / build (push) Successful in 5m25s
Build Nanobot OAuth / cleanup (push) Successful in 1s
SubagentManager was receiving model=self.model (Opus) from the main
agent loop, overriding the intended "claude-sonnet-4-6" fallback in
SubagentManager.__init__. Subagents should default to Sonnet unless
explicitly overridden via the spawn tool call.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 03:33:54 +00:00
code-serverandClaude Sonnet 4.5 9bf0833137 fix(subagent): restore f-string, add exec date first-action rule
Build Nanobot OAuth / build (push) Successful in 5m25s
Build Nanobot OAuth / cleanup (push) Successful in 1s
- Restore f-string prefix so {self.workspace} interpolates correctly
- Add task parameter back to _build_subagent_prompt signature
- Instruct subagents to run exec date as first action (avoids
  injecting dynamic timestamp into system prompt that busts cache)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 03:19:18 +00:00
code-serverandClaude Sonnet 4.5 821673aff6 feat: load KNOWLEDGE.md instead of MEMORY.md into system prompt
Build Nanobot OAuth / build (push) Successful in 5m56s
Build Nanobot OAuth / cleanup (push) Successful in 1s
MEMORY.md is updated by the Haiku consolidator after every session,
changing the system prompt and busting the 1h cache. Replace it with
KNOWLEDGE.md — a static, manually-curated file that stays stable.
MEMORY.md remains accessible to the agent via read/grep tools.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 02:55:15 +00:00
code-serverandClaude Sonnet 4.5 2d7eb2c14d fix: store current_message in session to preserve time prefix for cache hits
Build Nanobot OAuth / build (push) Successful in 5m17s
Build Nanobot OAuth / cleanup (push) Successful in 2s
session.add_message was storing raw msg.content without the [Current time: ...]
prefix, causing cache key mismatches on subsequent turns since the API received
the prefixed version but history replayed the raw version.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 02:44:40 +00:00
code-serverandClaude Sonnet 4.5 9cee8c9f20 fix: move current time from system prompt to user message to enable cache hits
Build Nanobot OAuth / build (push) Successful in 5m19s
Build Nanobot OAuth / cleanup (push) Successful in 1s
The system prompt included a minute-resolution timestamp that changed every
call, busting the 1h cache on every request. Move current time to a [Current
time: ...] prefix on each user message instead, keeping the system prompt
static for cache hits. Also clarify the time-gap notice text.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 02:31:23 +00:00
code-serverandClaude Sonnet 4.5 fcedb37667 feat: cache conversation history + skip Reflect prompt when thinking active
Build Nanobot OAuth / build (push) Successful in 5m36s
Build Nanobot OAuth / cleanup (push) Successful in 0s
- Cache last user message on every API call (5m TTL) so full conversation
  history is a cache read on subsequent turns
- Skip "Reflect on the results" interleave prompt when thinking_budget > 0
  since extended thinking already handles reflection internally; keeps
  message caching valid across tool iterations

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 02:11:05 +00:00
code-serverandClaude Sonnet 4.5 4699bdd09e feat: enable prompt caching for system prompt and tools (1h TTL)
Build Nanobot OAuth / build (push) Successful in 5m43s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Cache system prompt and tool definitions on every API call to reduce
quota burn. Uses 1-hour TTL so context stays warm across conversations.
Also logs cache_write/cache_read token counts in response log line.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 01:51:30 +00:00
code-serverandClaude Sonnet 4.5 71bbefceb1 fix: register WaitForSubagentsTool in main AgentLoop so it's available in live sessions
Build Nanobot OAuth / build (push) Successful in 7m27s
Build Nanobot OAuth / cleanup (push) Successful in 1s
Previously wait_for_subagents was only registered inside _run_subagent
(spawned orchestrators). Main conversation agent had no access to it.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 01:17:43 +00:00
code-server d0b0284189 Merge pull request 'Quota-based model switching + thinking mode fixes' (#9) from feat/rate-limit-tracking into main
Build Nanobot OAuth / build (push) Successful in 52s
Build Nanobot OAuth / cleanup (push) Successful in 0s
2026-02-15 14:14:44 +01:00