MCPcopy
hub / github.com/StructuredLabs/preswald / rerun

Method rerun

preswald/engine/runner.py:116–230  ·  view source on GitHub ↗

Rerun the script in response to updated widget state. This uses DAG-based dependency tracking (from AST instrumentation in Phase 3) to determine which atoms are affected and should be recomputed. Fallback to full rerun is triggered if affected atoms cannot be deter

(self, new_widget_states: dict[str, Any] | None = None)

Source from the content-addressed store, hash-verified

114 raise
115
116 async def rerun(self, new_widget_states: dict[str, Any] | None = None):
117 """
118 Rerun the script in response to updated widget state.
119
120 This uses DAG-based dependency tracking (from AST instrumentation in Phase 3)
121 to determine which atoms are affected and should be recomputed.
122
123 Fallback to full rerun is triggered if affected atoms cannot be determined.
124
125 Args:
126 new_widget_states (dict[str, Any] | None): Updated component states (by ID).
127 """
128
129 # Basic debouncing - skip if last run was too recent
130 current_time = time.time()
131 if current_time - self._last_run_time < 0.1:
132 logger.info("[ScriptRunner] Skipping rerun due to debounce")
133 return
134
135 if not new_widget_states:
136 logger.info("[ScriptRunner] No new states for rerun")
137 return
138
139 if not self._service.is_reactivity_enabled:
140 logger.info("[ScriptRunner] Reactivity disabled — rerunning entire script with updated widget state")
141 return await self.run_script()
142
143 try:
144 with self._lock:
145 for component_id, value in new_widget_states.items():
146 old_value = self.widget_states.get(component_id)
147 self.widget_states[component_id] = value
148 if logger.isEnabledFor(logging.DEBUG):
149 logger.debug(f"[ScriptRunner] Updated state: {component_id=} -> {value=} (was {old_value=})")
150 self._run_count += 1
151 self._last_run_time = current_time
152
153 # determine affected components and force recomputation
154 changed_component_ids = set(new_widget_states.keys())
155 workflow = self._service.get_workflow()
156
157 changed_atoms = set()
158 for cid in changed_component_ids:
159 atom = workflow.get_component_producer(cid)
160 if atom:
161 changed_atoms.add(atom)
162 else:
163 logger.warning(f"[ScriptRunner] No producer found for component_id: {cid}")
164
165 affected_atoms = workflow._get_affected_atoms(changed_atoms)
166
167 # Inject updated widget states into workflow context before executing
168 for component_id, new_value in self.widget_states.items():
169 producer_atom = workflow.get_component_producer(component_id)
170 if producer_atom:
171 workflow.context.set_variable(producer_atom, new_value)
172
173 if not changed_atoms and not affected_atoms:

Callers 1

Calls 15

run_scriptMethod · 0.95
send_messageMethod · 0.95
_send_errorMethod · 0.95
get_workflowMethod · 0.80
_get_affected_atomsMethod · 0.80
set_variableMethod · 0.80
disable_reactivityMethod · 0.80
resetMethod · 0.80
clear_componentsMethod · 0.80
force_recomputeMethod · 0.80
executeMethod · 0.80

Tested by

no test coverage detected