Skip to content

Commit b10bac2

Browse files
fix(ci): install tracing extra in test workflow
CI was missing --extra tracing, so mlflow wasn't installed and all 26 tracing tests failed with ImportError. Also applies Black formatting.
1 parent 3bb0d12 commit b10bac2

40 files changed

Lines changed: 689 additions & 266 deletions

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
uses: astral-sh/setup-uv@v7
2828

2929
- name: Install dependencies
30-
run: uv sync --extra mcp
30+
run: uv sync --extra mcp --extra tracing
3131

3232
- name: Run tests with coverage
3333
run: |

ace/cli/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@
22

33
import click
44

5-
from ace.cli.cloud import upload, traces, run, insights, prompts, status, materialize, batch, setup, integrations
5+
from ace.cli.cloud import (
6+
upload,
7+
traces,
8+
run,
9+
insights,
10+
prompts,
11+
status,
12+
materialize,
13+
batch,
14+
setup,
15+
integrations,
16+
)
617

718

819
@click.group()

ace/cli/cloud.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ def traces_list(as_json, api_key, base_url):
141141
return
142142

143143
# Table header
144-
click.echo(f" {'ID':<36} {'Filename':<40} {'Type':<6} {'Size':>8} {'Uploaded'}")
144+
click.echo(
145+
f" {'ID':<36} {'Filename':<40} {'Type':<6} {'Size':>8} {'Uploaded'}"
146+
)
145147
click.echo(f" {'-' * 36} {'-' * 40} {'-' * 6} {'-' * 8} {'-' * 10}")
146148
for t in items:
147149
tid = t.get("id", "?")
@@ -243,7 +245,9 @@ def traces_upload(paths, file_type, api_key, base_url):
243245
if item == "-":
244246
content = sys.stdin.read()
245247
ft = file_type or "txt"
246-
trace_list.append({"filename": "stdin.txt", "content": content, "fileType": ft})
248+
trace_list.append(
249+
{"filename": "stdin.txt", "content": content, "fileType": ft}
250+
)
247251
continue
248252

249253
p = Path(item)
@@ -302,8 +306,16 @@ def traces_upload(paths, file_type, api_key, base_url):
302306
@_api_key_option
303307
@_base_url_option
304308
def run(
305-
trace_ids, select_all, model, epochs, reflector_mode, anthropic_key, wait, as_json,
306-
api_key, base_url,
309+
trace_ids,
310+
select_all,
311+
model,
312+
epochs,
313+
reflector_mode,
314+
anthropic_key,
315+
wait,
316+
as_json,
317+
api_key,
318+
base_url,
307319
):
308320
"""Run the analysis pipeline on selected traces.
309321

ace/cli/setup.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
validate_connection,
3434
)
3535

36-
3736
# ---------------------------------------------------------------------------
3837
# Terminal helpers
3938
# ---------------------------------------------------------------------------
@@ -396,10 +395,10 @@ def main() -> None:
396395
)
397396

398397
# ace models
399-
models_parser = subparsers.add_parser(
400-
"models", help="Search available models"
398+
models_parser = subparsers.add_parser("models", help="Search available models")
399+
models_parser.add_argument(
400+
"query", nargs="*", default=[], help="Search query (multiple terms = match all)"
401401
)
402-
models_parser.add_argument("query", nargs="*", default=[], help="Search query (multiple terms = match all)")
403402
models_parser.add_argument("--provider", default=None, help="Filter by provider")
404403
models_parser.add_argument(
405404
"--limit", type=int, default=20, help="Max results (default: 20)"
@@ -462,7 +461,9 @@ def _cmd_models(query: str, provider: str | None, limit: int) -> None:
462461
in_cost = f"${m.input_cost_per_m:.2f}" if m.input_cost_per_m else "-"
463462
out_cost = f"${m.output_cost_per_m:.2f}" if m.output_cost_per_m else "-"
464463
key_status = f"{GREEN}\u2713{RESET}" if m.key_found else f"{RED}\u2717{RESET}"
465-
print(f"{m.model:<45} {m.provider:<15} {in_cost:<10} {out_cost:<11} {key_status}")
464+
print(
465+
f"{m.model:<45} {m.provider:<15} {in_cost:<10} {out_cost:<11} {key_status}"
466+
)
466467

467468
if total > limit:
468469
print()

ace/core/context.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from .outputs import AgentOutput, ReflectorOutput
1111
from .skillbook import Skill, Skillbook, UpdateBatch
1212

13-
1413
# ---------------------------------------------------------------------------
1514
# ACESample — structural protocol for step access
1615
# ---------------------------------------------------------------------------

ace/core/skillbook.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
# Constants
3030
# ---------------------------------------------------------------------------
3131

32-
VALID_SKILL_TAGS: FrozenSet[str] = frozenset({"helpful", "harmful", "neutral"}) # deprecated
32+
VALID_SKILL_TAGS: FrozenSet[str] = frozenset(
33+
{"helpful", "harmful", "neutral"}
34+
) # deprecated
3335

3436
# ---------------------------------------------------------------------------
3537
# Update operations
@@ -399,9 +401,7 @@ def to_dict(self, exclude_embeddings: bool = False) -> Dict[str, object]:
399401
del skill_dict["embedding"]
400402
# Use InsightSource.to_dict() for clean sparse serialization
401403
# instead of the recursive asdict() which dumps empty/null fields.
402-
skill_dict["sources"] = [
403-
source.to_dict() for source in skill.sources
404-
]
404+
skill_dict["sources"] = [source.to_dict() for source in skill.sources]
405405
skills_serialized[skill_id] = skill_dict
406406
return {
407407
"skills": skills_serialized,
@@ -588,9 +588,7 @@ def source_summary(self) -> Dict[str, Any]:
588588
source_systems[src.source_system] = (
589589
source_systems.get(src.source_system, 0) + 1
590590
)
591-
trace_uids[src.trace_uid] = (
592-
trace_uids.get(src.trace_uid, 0) + 1
593-
)
591+
trace_uids[src.trace_uid] = trace_uids.get(src.trace_uid, 0) + 1
594592
sq = src.sample_question or ""
595593
if sq:
596594
sample_questions[sq] = sample_questions.get(sq, 0) + 1

ace/deduplication/detector.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ def _embed_litellm(self, text: str) -> Optional[List[float]]:
6767
)
6868
return response.data[0]["embedding"]
6969
except Exception as e:
70-
logger.warning("Failed to compute embedding via LiteLLM (%s): %s", type(e).__name__, e)
70+
logger.warning(
71+
"Failed to compute embedding via LiteLLM (%s): %s", type(e).__name__, e
72+
)
7173
return None
7274

7375
def _embed_batch_litellm(self, texts: List[str]) -> List[Optional[List[float]]]:
@@ -80,7 +82,11 @@ def _embed_batch_litellm(self, texts: List[str]) -> List[Optional[List[float]]]:
8082
response = litellm.embedding(model=self.config.embedding_model, input=texts)
8183
return [item["embedding"] for item in response.data]
8284
except Exception as e:
83-
logger.warning("Failed to compute batch embeddings via LiteLLM (%s): %s", type(e).__name__, e)
85+
logger.warning(
86+
"Failed to compute batch embeddings via LiteLLM (%s): %s",
87+
type(e).__name__,
88+
e,
89+
)
8490
return [None] * len(texts)
8591

8692
# ------------------------------------------------------------------
@@ -98,7 +104,8 @@ def _embed_st(self, text: str) -> Optional[List[float]]:
98104
except Exception as e:
99105
logger.warning(
100106
"Failed to compute embedding via sentence-transformers (%s): %s",
101-
type(e).__name__, e,
107+
type(e).__name__,
108+
e,
102109
)
103110
return None
104111

@@ -113,7 +120,8 @@ def _embed_batch_st(self, texts: List[str]) -> List[Optional[List[float]]]:
113120
except Exception as e:
114121
logger.warning(
115122
"Failed to compute batch embeddings via sentence-transformers (%s): %s",
116-
type(e).__name__, e,
123+
type(e).__name__,
124+
e,
117125
)
118126
return [None] * len(texts)
119127

ace/deduplication/manager.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ def parse_consolidation_operations(
134134
)
135135
)
136136
except Exception as e:
137-
logger.warning("Failed to parse consolidation operation (%s): %s", type(e).__name__, e)
137+
logger.warning(
138+
"Failed to parse consolidation operation (%s): %s",
139+
type(e).__name__,
140+
e,
141+
)
138142

139143
logger.info("Parsed %d consolidation operations", len(operations))
140144
return operations

ace/deduplication/prompts.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ def generate_similarity_report(
5757
)
5858
)
5959

60-
parts.append(
61-
"""
60+
parts.append("""
6261
## Consolidation Operations Format
6362
6463
Include consolidation operations in your response under a `consolidation_operations` key.
@@ -101,8 +100,7 @@ def generate_similarity_report(
101100
- UPDATE to add context tags like "[Batch Jobs]" or "[User-Facing API]" to differentiate
102101
- DELETE only when one is clearly redundant with no unique value
103102
104-
"""
105-
)
103+
""")
106104

107105
return "".join(parts)
108106

ace/implementations/skill_manager.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ def update_skills(
104104
"root_cause_analysis": r.root_cause_analysis,
105105
"correct_approach": r.correct_approach,
106106
"key_insight": r.key_insight,
107-
"extracted_learnings": [
108-
l.model_dump() for l in r.extracted_learnings
109-
],
107+
"extracted_learnings": [l.model_dump() for l in r.extracted_learnings],
110108
}
111109
for r in reflections
112110
]

0 commit comments

Comments
 (0)