@@ -364,15 +364,7 @@ def __init__(self):
364364 self ._data = None
365365 self ._is_root = True
366366
367- @property
368- def is_root (self ) -> bool :
369- """Returns whether this context is the root context."""
370- return self ._is_root
371-
372- @property
373- def is_chat_context (self ) -> bool :
374- """Returns whether this context is a chat context."""
375- return self ._is_chat_context
367+ # factory functions below this line.
376368
377369 @classmethod
378370 def from_previous (
@@ -389,43 +381,64 @@ def from_previous(
389381 x ._previous = previous
390382 x ._data = data
391383 x ._is_root = False
384+ x ._is_chat_context = previous ._is_chat_context
392385 return x
393386
394387 @classmethod
395388 def reset (cls : type [ContextT ]) -> ContextT :
396- """Resets the context to a fresh state ."""
389+ """Returns an empty context for convenience ."""
397390 return cls ()
398391
392+ # Internal functions below this line.
393+
394+ @property
395+ def is_root_node (self ) -> bool :
396+ """Returns whether this context is the root context node."""
397+ return self ._is_root
398+
399399 @property
400- def previous (self ) -> Context | None :
401- """Returns the context from which this context was created."""
400+ def previous_node (self ) -> Context | None :
401+ """Returns the context node from which this context node was created.
402+
403+ Internal use: Users should not need to use this property.
404+ """
402405 return self ._previous
403406
404407 @property
405- def data (self ) -> Component | CBlock | None :
406- """Returns the data associated with this context."""
408+ def node_data (self ) -> Component | CBlock | None :
409+ """Returns the data associated with this context node.
410+
411+ Internal use: Users should not need to use this property.
412+ """
407413 return self ._data
408414
415+ @property
416+ def is_chat_context (self ) -> bool :
417+ """Returns whether this context is a chat context."""
418+ return self ._is_chat_context
419+
420+ # User functions below this line.
421+
409422 def as_list (self , last_n_components : int | None = None ) -> list [Component | CBlock ]:
410423 """Returns a list of the last n components in the context sorted from FIRST TO LAST.
411424
412- If `last_n_elements ` is `None`, then all components are returned."""
425+ If `last_n_components ` is `None`, then all components are returned."""
413426 context_list : list [Component | CBlock ] = []
414427 current_context : Context = self
415428
416429 last_n_count = 0
417- while not current_context .is_root and (
430+ while not current_context .is_root_node and (
418431 last_n_components is None or last_n_count < last_n_components
419432 ):
420- data = current_context .data
433+ data = current_context .node_data
421434 assert data is not None , "Data cannot be None (except for root context)."
422435 assert data not in context_list , (
423436 "There might be a cycle in the context tree. That is not allowed."
424437 )
425438 context_list .append (data )
426439 last_n_count += 1
427440
428- current_context = current_context .previous # type: ignore
441+ current_context = current_context .previous_node # type: ignore
429442 assert current_context is not None , (
430443 "Previous context cannot be None (except for root context)."
431444 )
@@ -440,18 +453,21 @@ def actions_for_available_tools(self) -> list[Component | CBlock] | None:
440453 """
441454 return self .view_for_generation ()
442455
443- def last_output (self ) -> ModelOutputThunk | None :
456+ def last_output (self , check_last_n_components : int = 3 ) -> ModelOutputThunk | None :
444457 """The last output thunk of the context."""
445458
446- for c in self .as_list ()[::- 1 ]:
459+ for c in self .as_list (last_n_components = check_last_n_components )[::- 1 ]:
447460 if isinstance (c , ModelOutputThunk ):
448461 return c
449462 return None
450463
451464 def last_turn (self ):
452- """The last input/output turn of the context."""
465+ """The last input/output turn of the context.
453466
454- history = self .as_list ()
467+ This can be partial. If the last event is an input, then the output is None.
468+ """
469+
470+ history = self .as_list (last_n_components = 2 )
455471
456472 if len (history ) == 0 :
457473 return None
@@ -467,7 +483,7 @@ def last_turn(self):
467483 # if the last element is input element, return partial turn without output
468484 return ContextTurn (last_element , None )
469485
470- # Abstract methods
486+ # Abstract methods below this line.
471487
472488 @abc .abstractmethod
473489 def add (self , c : Component | CBlock ) -> Context :
@@ -482,10 +498,10 @@ def view_for_generation(self) -> list[Component | CBlock] | None:
482498
483499
484500class ChatContext (Context ):
485- """Initializes a linear context with unbounded window_size and is_chat=True by default."""
501+ """Initializes a chat context with unbounded window_size and is_chat=True by default."""
486502
487503 def __init__ (self , * , window_size : int | None = None ):
488- """Constructs a new linear context."""
504+ """Constructs a new chat context."""
489505 super ().__init__ ()
490506 self ._window_size = window_size
491507
0 commit comments