netra-zen 1.1.2__py3-none-any.whl → 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netra-zen
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: Multi-instance Claude orchestrator for parallel task execution
5
5
  Home-page: https://github.com/netra-systems/zen
6
6
  Author: Systems
@@ -1,10 +1,10 @@
1
1
  zen_orchestrator.py,sha256=hKeP2dW6eJgEhtUHYylnhIgP_HgaxrDAwCnlS7mKkgU,156167
2
2
  agent_interface/__init__.py,sha256=OsbOKzElHsxhVgak87oOx_u46QNgKmz-Reis-plAMwk,525
3
3
  agent_interface/base_agent.py,sha256=GNskG9VaZgno7X24lQTpFdxUoQE0yJHLh0UPFJvOPn4,11098
4
- netra_zen-1.1.2.dist-info/licenses/LICENSE.md,sha256=PZrP0UDn58i4LjV4zijIQTnsQPvWm4zq9Fet9i7qgwI,80
4
+ netra_zen-1.2.0.dist-info/licenses/LICENSE.md,sha256=PZrP0UDn58i4LjV4zijIQTnsQPvWm4zq9Fet9i7qgwI,80
5
5
  scripts/__init__.py,sha256=r6jX6e9SaisREml6B7uDoV-_rzIW0_yQXMm6OhNgbIw,52
6
6
  scripts/__main__.py,sha256=NSqyN47EijNf7m_8QsoxeYevKYgH2sNtNPFZcwKWMs0,160
7
- scripts/agent_cli.py,sha256=Ut_7iou5M5Meeb9Ulvn_zZZrEGmpmDi0vDJAEP_fUtA,340749
7
+ scripts/agent_cli.py,sha256=ATQIWoVx7GthFV1WeiV6Co8PzoXYXhlJjOerU-JocJ0,345625
8
8
  scripts/agent_logs.py,sha256=ppseAtUCvS2N-iEDSUQh84I9Ov-gBEw5ElxYajNdpJs,11218
9
9
  scripts/bump_version.py,sha256=fjABzzRVXJ00CbYMpUIUMwcOHwafLYtFL6NvUga-i6M,4183
10
10
  scripts/demo_log_collection.py,sha256=5XladS8j4lz-jJdVzSeDSxopChqHKX7HLNJUzSWR40c,5623
@@ -23,8 +23,8 @@ zen/telemetry/__init__.py,sha256=zyH7YcK_eWxwaQZW0MRefu1bX5hEgfRljr_dsqNU-tw,452
23
23
  zen/telemetry/apex_telemetry.py,sha256=FAkiHXOuzZFL-51oYetTC4wbjCL5UH-qOghwcaaOVgE,9685
24
24
  zen/telemetry/embedded_credentials.py,sha256=z-j_TfuVIz3nX-Vvh4O6_iDQhtteEyQgfc-xSslVbXU,1716
25
25
  zen/telemetry/manager.py,sha256=Rdbpnjbjel9xZEJyvLqy2M-4amvkr80abRiWnqHghIQ,9980
26
- netra_zen-1.1.2.dist-info/METADATA,sha256=-7DFDTlxlMX9NnptWNy-LW09GsKyYGiPC5cyuANh3Gk,46283
27
- netra_zen-1.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- netra_zen-1.1.2.dist-info/entry_points.txt,sha256=oDehCnPGZezG0m9ZWspxjHLHyQ3eERX87eojR4ljaRo,45
29
- netra_zen-1.1.2.dist-info/top_level.txt,sha256=OhiyXmoXftBijCF6ck-RS1dN2NBJv9wdd7kBG1Es7zA,77
30
- netra_zen-1.1.2.dist-info/RECORD,,
26
+ netra_zen-1.2.0.dist-info/METADATA,sha256=sb-1CUEfEqK3rmHbqxqrNeMi4t5d_hZ34xhBoPT1a90,46283
27
+ netra_zen-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ netra_zen-1.2.0.dist-info/entry_points.txt,sha256=oDehCnPGZezG0m9ZWspxjHLHyQ3eERX87eojR4ljaRo,45
29
+ netra_zen-1.2.0.dist-info/top_level.txt,sha256=OhiyXmoXftBijCF6ck-RS1dN2NBJv9wdd7kBG1Es7zA,77
30
+ netra_zen-1.2.0.dist-info/RECORD,,
scripts/agent_cli.py CHANGED
@@ -2883,22 +2883,49 @@ class WebSocketClient:
2883
2883
  self.connected = True
2884
2884
  return True
2885
2885
  else:
2886
- # Handshake failed - backend might be using old reactive model
2886
+ # Handshake failed - server not ready to process messages
2887
2887
  self.debug.debug_print(
2888
- "WARNING: No proactive handshake received from server",
2888
+ "WARNING: Server handshake not completed - server not ready",
2889
2889
  DebugLevel.BASIC,
2890
2890
  style="yellow"
2891
2891
  )
2892
2892
  self.debug.debug_print(
2893
- "Server may be using pre-2025-10-09 architecture (reactive handshake)",
2893
+ "Server still completing lifecycle phases (Initialize → Authenticate → Handshake → Prepare → Processing)",
2894
2894
  DebugLevel.VERBOSE,
2895
2895
  style="yellow"
2896
2896
  )
2897
2897
 
2898
- # Still mark as connected for backward compatibility
2899
- # Old backends might work without the proactive handshake
2900
- self.connected = True
2901
- return True
2898
+ # Wait briefly for server to complete its phases and retry
2899
+ safe_console_print("⏳ Waiting for server to complete initialization...", style="yellow",
2900
+ json_mode=self.config.json_mode, ci_mode=self.config.ci_mode)
2901
+ await asyncio.sleep(3.0) # Give server time to reach PROCESSING phase
2902
+
2903
+ # Retry handshake once more
2904
+ self.debug.debug_print(
2905
+ "Retrying handshake after delay...",
2906
+ DebugLevel.VERBOSE,
2907
+ style="cyan"
2908
+ )
2909
+ handshake_success = await self._perform_handshake()
2910
+ if handshake_success:
2911
+ safe_console_print(f"✅ Connected with thread ID: {self.current_thread_id}", style="green",
2912
+ json_mode=self.config.json_mode, ci_mode=self.config.ci_mode)
2913
+ self.connected = True
2914
+ return True
2915
+ else:
2916
+ # Server still not ready - fail the connection
2917
+ self.debug.debug_print(
2918
+ "ERROR: Server not ready after retry",
2919
+ DebugLevel.BASIC,
2920
+ style="red"
2921
+ )
2922
+ safe_console_print("❌ Server not ready to process messages. Please try again.", style="red",
2923
+ json_mode=self.config.json_mode, ci_mode=self.config.ci_mode)
2924
+
2925
+ # Close WebSocket and fail gracefully
2926
+ if self.ws:
2927
+ await self.ws.close()
2928
+ return False
2902
2929
  except Exception as e:
2903
2930
  self.debug.log_connection_attempt(method_name, self.config.ws_url, success=False, error=str(e))
2904
2931
  self.debug.debug_print(
@@ -3027,7 +3054,8 @@ class WebSocketClient:
3027
3054
 
3028
3055
  # Server enters HANDSHAKING phase after authentication
3029
3056
  # and proactively sends handshake_response
3030
- handshake_timeout = 10.0 # Wait up to 10 seconds
3057
+ # Use configured timeout or default to 10 seconds
3058
+ handshake_timeout = self.handshake_timeout if hasattr(self, 'handshake_timeout') and self.handshake_timeout else 10.0
3031
3059
  start_time = asyncio.get_event_loop().time()
3032
3060
 
3033
3061
  try:
@@ -3274,14 +3302,64 @@ class WebSocketClient:
3274
3302
  )
3275
3303
 
3276
3304
  # CRITICAL: Send acknowledgment with the SAME thread_id
3305
+ # Per WebSocket Client Lifecycle Guide, use "handshake_acknowledged"
3277
3306
  ack_message = {
3278
- "type": "session_acknowledged",
3307
+ "type": "handshake_acknowledged",
3279
3308
  "thread_id": backend_thread_id, # Echo back the same ID
3280
3309
  "timestamp": datetime.now(timezone.utc).isoformat()
3281
3310
  }
3282
3311
 
3283
3312
  await self.ws.send(json.dumps(ack_message))
3284
3313
 
3314
+ # Per WebSocket Client Lifecycle Guide, wait for handshake_complete
3315
+ # and then add delay for server to enter Phase 5 (Processing)
3316
+ self.debug.debug_print(
3317
+ "Waiting for handshake_complete confirmation...",
3318
+ DebugLevel.VERBOSE,
3319
+ style="cyan"
3320
+ )
3321
+
3322
+ # Wait briefly for handshake_complete message
3323
+ try:
3324
+ complete_msg = await asyncio.wait_for(self.ws.recv(), timeout=2.0)
3325
+ complete_data = json.loads(complete_msg)
3326
+ if complete_data.get('type') == 'handshake_complete':
3327
+ self.debug.debug_print(
3328
+ "✅ Received handshake_complete - Server at Phase 4 (Ready)",
3329
+ DebugLevel.VERBOSE,
3330
+ style="green"
3331
+ )
3332
+
3333
+ # CRITICAL: Add delay for server to enter Phase 5 (Processing)
3334
+ # Per documentation, 500ms is recommended
3335
+ self.debug.debug_print(
3336
+ "Waiting 500ms for server to enter Phase 5 (Processing)...",
3337
+ DebugLevel.VERBOSE,
3338
+ style="cyan"
3339
+ )
3340
+ await asyncio.sleep(0.5)
3341
+
3342
+ self.debug.debug_print(
3343
+ "✅ Server should now be in Phase 5 (Processing) - ready for messages",
3344
+ DebugLevel.VERBOSE,
3345
+ style="green"
3346
+ )
3347
+ except asyncio.TimeoutError:
3348
+ # If no handshake_complete, still add a delay to be safe
3349
+ self.debug.debug_print(
3350
+ "No handshake_complete received, adding safety delay",
3351
+ DebugLevel.VERBOSE,
3352
+ style="yellow"
3353
+ )
3354
+ await asyncio.sleep(0.5)
3355
+ except Exception as e:
3356
+ self.debug.debug_print(
3357
+ f"Error waiting for handshake_complete: {e}",
3358
+ DebugLevel.VERBOSE,
3359
+ style="yellow"
3360
+ )
3361
+ await asyncio.sleep(0.5)
3362
+
3285
3363
  return True
3286
3364
 
3287
3365
  def _get_platform_cache_path(self) -> Path:
@@ -3622,6 +3700,27 @@ class WebSocketClient:
3622
3700
  if not self.ws:
3623
3701
  raise RuntimeError("WebSocket not connected")
3624
3702
 
3703
+ # Check if connection handshake is fully complete
3704
+ if not self.connected:
3705
+ self.debug.debug_print(
3706
+ "ERROR: Connection not ready - handshake not complete",
3707
+ DebugLevel.BASIC,
3708
+ style="red"
3709
+ )
3710
+ safe_console_print(
3711
+ "\n❌ ERROR: Cannot send message - server not ready",
3712
+ style="red",
3713
+ json_mode=self.config.json_mode,
3714
+ ci_mode=self.config.ci_mode
3715
+ )
3716
+ safe_console_print(
3717
+ "The server is still completing its initialization phases.",
3718
+ style="yellow",
3719
+ json_mode=self.config.json_mode,
3720
+ ci_mode=self.config.ci_mode
3721
+ )
3722
+ raise RuntimeError("Connection not ready - handshake incomplete. Server needs to reach Processing phase.")
3723
+
3625
3724
  # Generate run_id
3626
3725
  self.run_id = f"cli_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{os.getpid()}"
3627
3726