@@ -124,43 +124,30 @@ def wrapper(ctx: SkillContext, *args: Any) -> StepResult:
124124 return decorator
125125
126126
127- def _trace_names (skill : Skill ) -> list [str ]:
128- """Names written to the current ctx.trace scope."""
129- if skill .fn :
130- return [skill .name ]
131- return [name for child in skill .steps for name in _trace_names (child )]
127+ def _trace_names (s : Skill ) -> list [str ]:
128+ return [s .name ] if s .fn else [n for c in s .steps for n in _trace_names (c )]
132129
133130
134- def _duplicate_names (names : list [str ]) -> list [str ]:
135- """Names that appear more than once."""
136- return [name for name , n in Counter (names ).items () if n > 1 ]
131+ def _dups (names : list [str ]) -> list [str ]:
132+ return [n for n , c in Counter (names ).items () if c > 1 ]
137133
138134
139- def _child_scope_duplicates (skill : Skill ) -> list [str ]:
140- """Duplicate names in orchestrator child trace scopes."""
135+ def _child_scope_dups (s : Skill ) -> list [str ]:
141136 return [
142- duplicate
143- for child in skill .steps
144- for duplicate in (
145- _duplicate_trace_names (Skill (name = child .name , steps = child .steps ))
146- if child .fn and child .steps
147- else _child_scope_duplicates ( child )
137+ d
138+ for c in s .steps
139+ for d in (
140+ _dup_trace_names (Skill (name = c .name , steps = c .steps ))
141+ if c .fn and c .steps
142+ else _child_scope_dups ( c )
148143 )
149144 ]
150145
151146
152- def _duplicate_trace_names (skill : Skill ) -> list [str ]:
153- """Duplicate names per trace scope."""
154- child_scope = (
155- _duplicate_names (_trace_names (Skill (name = skill .name , steps = skill .steps )))
156- if skill .fn and skill .steps
157- else []
158- )
159- return [
160- * _duplicate_names (_trace_names (skill )),
161- * child_scope ,
162- * _child_scope_duplicates (skill ),
163- ]
147+ def _dup_trace_names (skill : Skill ) -> list [str ]:
148+ inner = Skill (name = skill .name , steps = skill .steps )
149+ cs = _dups (_trace_names (inner )) if skill .fn and skill .steps else []
150+ return [* _dups (_trace_names (skill )), * cs , * _child_scope_dups (skill )]
164151
165152
166153def _walk (skill : Skill , ctx : SkillContext ):
@@ -169,25 +156,21 @@ def _walk(skill: Skill, ctx: SkillContext):
169156 result = skill .fn (ctx , skill .steps ) if skill .steps else skill .fn (ctx )
170157 if not isinstance (result , StepResult ):
171158 result = StepResult (value = result )
172- ctx .trace [skill .name ] = result
173- ctx .prev = result
159+ ctx .trace [skill .name ] = ctx .prev = result
174160 resolved = result .resolved
175161 yield skill .name , result
176162 return resolved
177163 for child in skill .steps :
178- resolved = yield from _walk (child , ctx )
179- if resolved :
164+ if (yield from _walk (child , ctx )):
180165 return True
181166 return False
182167
183168
184169def _make_entry (entry : Any , kwargs : dict [str , Any ]) -> Any :
185- if kwargs :
186- if entry is not None :
187- msg = "pass either positional entry or kwargs, not both"
188- raise TypeError (msg )
189- return kwargs
190- return entry
170+ if kwargs and entry is not None :
171+ msg = "pass either positional entry or kwargs, not both"
172+ raise TypeError (msg )
173+ return kwargs or entry
191174
192175
193176def iter_skill (
@@ -196,22 +179,17 @@ def iter_skill(
196179 ** kwargs : Any ,
197180) -> Iterator [tuple [str , StepResult ]]:
198181 """Yield (name, result) per executed skill. Stops on resolved=True or after last."""
199- if duplicates := _duplicate_trace_names (skill ):
182+ if duplicates := _dup_trace_names (skill ):
200183 raise ValueError (duplicates )
201184 ctx = SkillContext (entry = _make_entry (entry , kwargs ))
202185 yield from _walk (skill , ctx )
203186
204187
205188def run_skill (skill : Skill , entry : Any = None , ** kwargs : Any ) -> SkillResult :
206189 """Run *skill* to completion."""
207- trace : dict [str , StepResult ] = {}
208- last : StepResult | None = None
209- last_name = "(empty)"
210- for name , result in iter_skill (skill , _make_entry (entry , kwargs )):
211- trace [name ] = result
212- last , last_name = result , name
213- if last is None :
190+ if not (trace := dict (iter_skill (skill , _make_entry (entry , kwargs )))):
214191 return SkillResult (skill = skill .name , resolved_by = (), value = None )
192+ last_name , last = next (reversed (trace .items ()))
215193 return SkillResult (
216194 skill = skill .name ,
217195 resolved_by = (last_name , * last .resolved_by ),
0 commit comments