From 51e2aaf1c749441362a23c56382de2bee568b235 Mon Sep 17 00:00:00 2001 From: LeNooby09 Date: Sat, 15 Nov 2025 02:26:03 +0100 Subject: [PATCH] synthesis on mention interval --- bsky.py | 62 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/bsky.py b/bsky.py index 532805e..b03c947 100644 --- a/bsky.py +++ b/bsky.py @@ -97,6 +97,11 @@ MAX_PROCESSED_NOTIFICATIONS = 10000 message_counters = defaultdict(int) start_time = time.time() +# Synthesis cycle configuration (normal mode uses cycles, synthesis-only uses time interval) +SYNTHESIS_CYCLES = 10 # trigger synthesis after this many successful mentions +MENTIONS_SINCE_LAST_SYNTHESIS = 0 +SYNTHESIS_MODE = "mentions" # normal mode synthesis trigger: "mentions" or "time" + # Testing mode flag TESTING_MODE = False @@ -1220,6 +1225,22 @@ def load_and_process_queued_notifications(void_agent, atproto_client, testing_mo success = process_mention(void_agent, atproto_client, notif_data, queue_filepath=filepath, testing_mode=testing_mode) if success: message_counters['mentions'] += 1 + # Increment synthesis cycle counter and trigger if threshold reached + global MENTIONS_SINCE_LAST_SYNTHESIS, SYNTHESIS_CYCLES, last_synthesis_time, SYNTHESIS_MODE + if SYNTHESIS_MODE == 'mentions' and SYNTHESIS_CYCLES > 0: + MENTIONS_SINCE_LAST_SYNTHESIS += 1 + logger.debug(f"Mentions since last synthesis: {MENTIONS_SINCE_LAST_SYNTHESIS}/{SYNTHESIS_CYCLES}") + if MENTIONS_SINCE_LAST_SYNTHESIS >= SYNTHESIS_CYCLES: + logger.info( + f"🧠 Synthesis threshold reached: {MENTIONS_SINCE_LAST_SYNTHESIS}/{SYNTHESIS_CYCLES} mentions. Triggering synthesis." + ) + try: + send_synthesis_message(CLIENT, void_agent.id, void_agent.name, atproto_client) + last_synthesis_time = time.time() + except Exception as e: + logger.error(f"Error during synthesis trigger: {e}") + finally: + MENTIONS_SINCE_LAST_SYNTHESIS = 0 elif notif_data['reason'] == "reply": success = process_mention(void_agent, atproto_client, notif_data, queue_filepath=filepath, testing_mode=testing_mode) if success: @@ -1478,8 +1499,9 @@ def process_notifications(void_agent, atproto_client, testing_mode=False): def send_synthesis_message(client: Letta, agent_id: str, agent_name: str = "void", atproto_client=None) -> None: """ - Send a synthesis message to the agent every 10 minutes. - This prompts the agent to synthesize its recent experiences. + Send a synthesis message to the agent. + This is typically triggered periodically based on the configured schedule + (time-based or mention-based) and prompts the agent to synthesize recent experiences. Args: client: Letta client @@ -1846,7 +1868,9 @@ def main(): # --rich option removed as we now use simple text formatting parser.add_argument('--reasoning', action='store_true', help='Display reasoning in panels and set reasoning log level to INFO') parser.add_argument('--cleanup-interval', type=int, default=10, help='Run user block cleanup every N cycles (default: 10, 0 to disable)') - parser.add_argument('--synthesis-interval', type=int, default=600, help='Send synthesis message every N seconds (default: 600 = 10 minutes, 0 to disable)') + parser.add_argument('--synthesis-interval', type=int, default=600, help='Synthesis-only mode: send synthesis every N seconds (default: 600 = 10 minutes); used in normal mode when --synthesis-mode=time') + parser.add_argument('--synthesis-cycles', type=int, default=10, help='Normal mode: trigger synthesis after N successful mentions (default: 10, 0 to disable)') + parser.add_argument('--synthesis-mode', choices=['mentions', 'time'], default='mentions', help='Normal mode: choose synthesis trigger mechanism: mentions (after N successful mentions) or time (every N seconds). Default: mentions') parser.add_argument('--synthesis-only', action='store_true', help='Run in synthesis-only mode (only send synthesis messages, no notification processing)') parser.add_argument('--debug', action='store_true', help='Enable debug logging') args = parser.parse_args() @@ -1921,10 +1945,7 @@ def main(): # Create handler with custom formatter handler = logging.StreamHandler() - if not args.simple_logs: - handler.setFormatter(SymbolFormatter(bot_name)) - else: - handler.setFormatter(logging.Formatter(log_format)) + handler.setFormatter(SymbolFormatter(bot_name)) # Configure root logger logging.root.setLevel(logging.INFO) @@ -2033,9 +2054,12 @@ def main(): atproto_client = None logger.info("Skipping Bluesky connection (test mode)") - # Configure intervals + # Configure intervals / counters CLEANUP_INTERVAL = args.cleanup_interval - SYNTHESIS_INTERVAL = args.synthesis_interval + SYNTHESIS_INTERVAL = args.synthesis_interval # used in synthesis-only mode and in normal mode if synthesis-mode=time + global SYNTHESIS_CYCLES, MENTIONS_SINCE_LAST_SYNTHESIS, SYNTHESIS_MODE + SYNTHESIS_CYCLES = args.synthesis_cycles + SYNTHESIS_MODE = args.synthesis_mode # Synthesis-only mode if SYNTHESIS_ONLY: @@ -2073,25 +2097,31 @@ def main(): else: logger.info("User block cleanup disabled") - if SYNTHESIS_INTERVAL > 0: - logger.info(f"Synthesis messages enabled every {SYNTHESIS_INTERVAL} seconds ({SYNTHESIS_INTERVAL/60:.1f} minutes)") - else: - logger.info("Synthesis messages disabled") + if SYNTHESIS_MODE == 'mentions': + if SYNTHESIS_CYCLES > 0: + logger.info(f"Synthesis enabled (mode=mentions): every {SYNTHESIS_CYCLES} successful mentions") + else: + logger.info("Synthesis disabled in normal mode (mode=mentions, cycles=0)") + else: # time-based in normal mode + if SYNTHESIS_INTERVAL > 0: + logger.info(f"Synthesis enabled (mode=time): every {SYNTHESIS_INTERVAL} seconds ({SYNTHESIS_INTERVAL/60:.1f} minutes)") + else: + logger.info("Synthesis disabled in normal mode (mode=time, interval=0)") while True: try: cycle_count += 1 process_notifications(void_agent, atproto_client, TESTING_MODE) - # Check if synthesis interval has passed - if SYNTHESIS_INTERVAL > 0: + # If using time-based synthesis in normal mode, check timer + if SYNTHESIS_MODE == 'time' and SYNTHESIS_INTERVAL > 0: current_time = time.time() global last_synthesis_time if current_time - last_synthesis_time >= SYNTHESIS_INTERVAL: logger.info(f"⏰ {SYNTHESIS_INTERVAL/60:.1f} minutes have passed, triggering synthesis") send_synthesis_message(CLIENT, void_agent.id, void_agent.name, atproto_client) last_synthesis_time = current_time - + # Run periodic cleanup every N cycles if CLEANUP_INTERVAL > 0 and cycle_count % CLEANUP_INTERVAL == 0: logger.debug(f"Running periodic user block cleanup (cycle {cycle_count})") -- 2.39.5