| |
| |
| |
|
|
| from puppet_theater.models import Actor, TheaterSession |
| from puppet_theater.show_bible import resolve_summoned_actor_via_llm_or_default |
| from puppet_theater.trace import add_trace_event |
|
|
|
|
| |
| MAX_ACTORS = 4 |
|
|
|
|
| def throw_prop(session: TheaterSession | None, prop_name: str) -> TheaterSession | None: |
| """ |
| Simulates an audience member throwing a prop onto the stage. |
| |
| What it does: |
| - Cleans up the prop name (removes extra spaces) |
| - Adds it to the session's props list |
| - Records it as the latest prop and audience action |
| - Updates director logs |
| - Emits a trace event for analytics/debugging |
| """ |
| if session is None: |
| return None |
|
|
| prop = " ".join(prop_name.strip().split()) or "mystery prop" |
| session.props.append(prop) |
| session.latest_prop = prop |
| session.latest_audience_action = f"Audience threw {prop} onto the stage." |
| session.director_log.append(session.latest_audience_action) |
| add_trace_event( |
| session, |
| "audience_action", |
| audience_action="throw_prop", |
| prop=prop, |
| action_summary=session.latest_audience_action, |
| ) |
| return session |
|
|
|
|
| def summon_actor(session: TheaterSession | None, actor_name: str) -> TheaterSession | None: |
| """ |
| Allows the audience to summon a new actor onto the stage. |
| |
| Behavior: |
| - Cleans the actor name |
| - Checks if stage has space (MAX_ACTORS limit) |
| - If full, logs a "skipped" action |
| - Otherwise creates a new Actor and adds them to the session |
| - Records the action in logs and trace system |
| """ |
| if session is None: |
| return None |
|
|
| name = " ".join(actor_name.strip().split()) or "Mystery Guest" |
|
|
| |
| if len(session.actors) >= MAX_ACTORS: |
| session.latest_audience_action = "Audience tried to summon an actor, but the stage is full." |
| session.director_log.append(session.latest_audience_action) |
| add_trace_event( |
| session, |
| "audience_action", |
| audience_action="summon_actor", |
| validation_status="skipped_stage_full", |
| fallback_used=False, |
| action_summary=session.latest_audience_action, |
| ) |
| return session |
|
|
| actor, summon_llm_source, summon_llm_fallback_used = resolve_summoned_actor_via_llm_or_default( |
| session, name |
| ) |
| session.actors.append(actor) |
|
|
| session.latest_audience_action = f"Audience summoned {actor.name}." |
| session.director_log.append(session.latest_audience_action) |
| if summon_llm_source: |
| session.director_log.append( |
| f"Summoned puppet profile from {summon_llm_source} (avatar {actor.avatar!s}, tools: {', '.join(actor.tools)})." |
| ) |
| elif summon_llm_fallback_used: |
| session.director_log.append( |
| "Summon LLM did not return usable JSON; used built-in guest puppet profile instead." |
| ) |
|
|
| add_trace_event( |
| session, |
| "audience_action", |
| audience_action="summon_actor", |
| summoned_actor=actor.name, |
| summon_llm_source=summon_llm_source or "built_in", |
| summon_llm_fallback_used=summon_llm_fallback_used, |
| action_summary=session.latest_audience_action, |
| ) |
|
|
| return session |
|
|
|
|
| def request_finale(session: TheaterSession | None) -> TheaterSession | None: |
| """ |
| Marks the session as having a requested finale. |
| |
| What it does: |
| - Sets finale_requested flag to True |
| - Updates latest audience action and director logs |
| - Emits a trace event for analytics/debugging |
| """ |
| if session is None: |
| return None |
|
|
| session.finale_requested = True |
| session.latest_audience_action = "Audience requested the finale." |
| session.director_log.append(session.latest_audience_action) |
|
|
| add_trace_event( |
| session, |
| "audience_action", |
| audience_action="request_finale", |
| action_summary=session.latest_audience_action, |
| ) |
|
|
| return session |