tracellm-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- app/__init__.py +1 -0
- app/database/__init__.py +1 -0
- app/database/mongodb.py +94 -0
- app/database/project_service.py +97 -0
- app/database/trace_service.py +417 -0
- app/main.py +44 -0
- app/models/__init__.py +14 -0
- app/models/health.py +5 -0
- app/models/project.py +32 -0
- app/models/trace.py +71 -0
- app/models/trace_model.py +62 -0
- app/routes/__init__.py +1 -0
- app/routes/health.py +10 -0
- app/routes/observability.py +60 -0
- app/routes/projects.py +25 -0
- app/websocket/__init__.py +1 -0
- app/websocket/socket.py +64 -0
- sdk/__init__.py +3 -0
- sdk/tracer.py +8 -0
- tracellm/__init__.py +6 -0
- tracellm/banner.py +34 -0
- tracellm/cli.py +124 -0
- tracellm/db.py +75 -0
- tracellm/exporter.py +65 -0
- tracellm/integrations/__init__.py +4 -0
- tracellm/integrations/langchain.py +186 -0
- tracellm/integrations/openai.py +234 -0
- tracellm/integrations/tool_tracer.py +151 -0
- tracellm/mascot.py +49 -0
- tracellm/monitor.py +381 -0
- tracellm/palette.py +186 -0
- tracellm/replay.py +80 -0
- tracellm/startup.py +121 -0
- tracellm/summary.py +53 -0
- tracellm/trace_stream.py +68 -0
- tracellm/tracer.py +598 -0
- tracellm/tree_renderer.py +78 -0
- tracellm/utils.py +390 -0
- tracellm_cli-0.1.0.dist-info/METADATA +30 -0
- tracellm_cli-0.1.0.dist-info/RECORD +43 -0
- tracellm_cli-0.1.0.dist-info/WHEEL +5 -0
- tracellm_cli-0.1.0.dist-info/entry_points.txt +2 -0
- tracellm_cli-0.1.0.dist-info/top_level.txt +3 -0
tracellm/utils.py
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import time
|
|
3
|
+
import uuid
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from rich.align import Align
|
|
9
|
+
from rich.console import Console, Group
|
|
10
|
+
from rich.live import Live
|
|
11
|
+
from rich.panel import Panel
|
|
12
|
+
from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
|
|
13
|
+
from rich.rule import Rule
|
|
14
|
+
from rich.table import Table
|
|
15
|
+
from rich.text import Text
|
|
16
|
+
from rich.tree import Tree
|
|
17
|
+
|
|
18
|
+
console = Console()
|
|
19
|
+
SLOW_TRACE_THRESHOLD_MS = 1500.0
|
|
20
|
+
WARNING_TRACE_THRESHOLD_MS = 900.0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def estimate_tokens(*parts: Any) -> int:
|
|
24
|
+
text = " ".join(str(part) for part in parts if part is not None)
|
|
25
|
+
if not text.strip():
|
|
26
|
+
return 0
|
|
27
|
+
return max(1, len(text.split()) + len(text) // 4)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_tool_step(
|
|
31
|
+
tool_name: str,
|
|
32
|
+
input_data: dict[str, Any],
|
|
33
|
+
output_data: dict[str, Any],
|
|
34
|
+
duration: float,
|
|
35
|
+
success: bool = True,
|
|
36
|
+
) -> dict[str, Any]:
|
|
37
|
+
return {
|
|
38
|
+
"step_id": str(uuid.uuid4()),
|
|
39
|
+
"tool_name": tool_name,
|
|
40
|
+
"input": input_data,
|
|
41
|
+
"output": output_data,
|
|
42
|
+
"duration": round(duration, 2),
|
|
43
|
+
"success": success,
|
|
44
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def simulate_step(
|
|
49
|
+
steps: list[dict[str, Any]],
|
|
50
|
+
tool_name: str,
|
|
51
|
+
input_data: dict[str, Any],
|
|
52
|
+
output_data: dict[str, Any],
|
|
53
|
+
min_delay: float,
|
|
54
|
+
max_delay: float,
|
|
55
|
+
random_module: Any,
|
|
56
|
+
success: bool = True,
|
|
57
|
+
) -> dict[str, Any]:
|
|
58
|
+
started = time.perf_counter()
|
|
59
|
+
time.sleep(random_module.uniform(min_delay, max_delay))
|
|
60
|
+
duration = round((time.perf_counter() - started) * 1000, 2)
|
|
61
|
+
step = build_tool_step(
|
|
62
|
+
tool_name=tool_name,
|
|
63
|
+
input_data=input_data,
|
|
64
|
+
output_data=output_data,
|
|
65
|
+
duration=duration,
|
|
66
|
+
success=success,
|
|
67
|
+
)
|
|
68
|
+
steps.append(step)
|
|
69
|
+
return step
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def coerce_response(result: Any) -> str:
|
|
73
|
+
if isinstance(result, dict):
|
|
74
|
+
response = result.get("response")
|
|
75
|
+
if response is not None:
|
|
76
|
+
return str(response)
|
|
77
|
+
if result is None:
|
|
78
|
+
return ""
|
|
79
|
+
return str(result)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def coerce_steps(result: Any) -> list[dict[str, Any]]:
|
|
83
|
+
if isinstance(result, dict) and isinstance(result.get("steps"), list):
|
|
84
|
+
return [step for step in result["steps"] if isinstance(step, dict)]
|
|
85
|
+
return []
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def coerce_retry_count(result: Any) -> int:
|
|
89
|
+
if isinstance(result, dict):
|
|
90
|
+
value = result.get("retry_count", 0)
|
|
91
|
+
try:
|
|
92
|
+
return max(0, int(value))
|
|
93
|
+
except (TypeError, ValueError):
|
|
94
|
+
return 0
|
|
95
|
+
return 0
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def coerce_status(result: Any, retry_count: int) -> str:
|
|
99
|
+
if isinstance(result, dict):
|
|
100
|
+
status = str(result.get("status") or "").lower()
|
|
101
|
+
if status in {"success", "warning", "failed"}:
|
|
102
|
+
return status
|
|
103
|
+
if retry_count > 0:
|
|
104
|
+
return "warning"
|
|
105
|
+
return "success"
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def coerce_failure_reason(result: Any) -> str | None:
|
|
109
|
+
if isinstance(result, dict):
|
|
110
|
+
failure_reason = result.get("failure_reason")
|
|
111
|
+
if failure_reason:
|
|
112
|
+
return str(failure_reason)
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def status_style(status: str) -> str:
|
|
117
|
+
normalized = status.lower()
|
|
118
|
+
if normalized == "success":
|
|
119
|
+
return "bold green"
|
|
120
|
+
if normalized == "warning":
|
|
121
|
+
return "bold yellow"
|
|
122
|
+
return "bold red"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def environment_style(environment: str) -> str:
|
|
126
|
+
normalized = environment.lower()
|
|
127
|
+
if normalized == "production":
|
|
128
|
+
return "bold red"
|
|
129
|
+
if normalized == "staging":
|
|
130
|
+
return "bold yellow"
|
|
131
|
+
return "bold cyan"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def latency_style(latency_ms: float) -> str:
|
|
135
|
+
if latency_ms >= SLOW_TRACE_THRESHOLD_MS:
|
|
136
|
+
return "bold red"
|
|
137
|
+
if latency_ms >= WARNING_TRACE_THRESHOLD_MS:
|
|
138
|
+
return "bold yellow"
|
|
139
|
+
return "green"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def ensure_export_dir() -> Path:
|
|
143
|
+
export_dir = Path.cwd() / "exports"
|
|
144
|
+
export_dir.mkdir(parents=True, exist_ok=True)
|
|
145
|
+
return export_dir
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def export_timestamp() -> str:
|
|
149
|
+
return datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def write_csv(path: Path, rows: list[dict[str, Any]], fieldnames: list[str]) -> None:
|
|
153
|
+
with path.open("w", newline="", encoding="utf-8") as csv_file:
|
|
154
|
+
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
|
155
|
+
writer.writeheader()
|
|
156
|
+
writer.writerows(rows)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def render_status_badge(status: str) -> Text:
|
|
160
|
+
normalized = status.lower()
|
|
161
|
+
if normalized == "success":
|
|
162
|
+
return Text(" SUCCESS ", style="bold white on #1a6b3c")
|
|
163
|
+
if normalized == "warning":
|
|
164
|
+
return Text(" WARNING ", style="bold #1a1a1a on #b8860b")
|
|
165
|
+
return Text(" FAILED ", style="bold white on #8b1a1a")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def build_trace_summary_table(trace_data: dict[str, Any]) -> Table:
|
|
169
|
+
table = Table.grid(padding=(0, 3), collapse_padding=True)
|
|
170
|
+
table.add_column(style="bright_black", no_wrap=True)
|
|
171
|
+
table.add_column(style="white")
|
|
172
|
+
table.add_row("Trace ID", str(trace_data["trace_id"]))
|
|
173
|
+
table.add_row("Prompt", str(trace_data["prompt"])[:80])
|
|
174
|
+
table.add_row("Model", str(trace_data["model_name"]))
|
|
175
|
+
table.add_row("Project", str(trace_data.get("project_name") or trace_data.get("project_id") or "default"))
|
|
176
|
+
table.add_row(
|
|
177
|
+
"Environment",
|
|
178
|
+
f'[{environment_style(str(trace_data.get("environment") or "development"))}]{str(trace_data.get("environment") or "development")}[/]',
|
|
179
|
+
)
|
|
180
|
+
latency = float(trace_data["latency"])
|
|
181
|
+
table.add_row("Latency", f'[{latency_style(latency)}]{latency:.2f} ms[/]')
|
|
182
|
+
table.add_row("Token Count", f"{trace_data['token_count']:,}")
|
|
183
|
+
table.add_row("Retries", str(trace_data["retry_count"]))
|
|
184
|
+
table.add_row("Steps", str(len(trace_data["steps"])))
|
|
185
|
+
status_badge = render_status_badge(str(trace_data["status"]))
|
|
186
|
+
table.add_row("Status", status_badge)
|
|
187
|
+
return table
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def build_steps_table(steps: list[dict[str, Any]]) -> Table:
|
|
191
|
+
table = Table(title=" Steps", box=None, padding=(0, 2), header_style="dim")
|
|
192
|
+
table.add_column("#", style="bright_black", width=3)
|
|
193
|
+
table.add_column("Tool", style="white")
|
|
194
|
+
table.add_column("Duration", justify="right", style="bright_black")
|
|
195
|
+
table.add_column("Status", justify="center")
|
|
196
|
+
table.add_column("Detail", style="dim")
|
|
197
|
+
for index, step in enumerate(steps, start=1):
|
|
198
|
+
success = bool(step.get("success", True))
|
|
199
|
+
duration = float(step.get("duration", 0.0))
|
|
200
|
+
detail = ""
|
|
201
|
+
if not success:
|
|
202
|
+
detail = "retry"
|
|
203
|
+
elif duration >= SLOW_TRACE_THRESHOLD_MS:
|
|
204
|
+
detail = "spike"
|
|
205
|
+
table.add_row(
|
|
206
|
+
str(index),
|
|
207
|
+
str(step.get("tool_name", "unknown")),
|
|
208
|
+
f'[{latency_style(duration)}]{duration:.0f} ms[/]',
|
|
209
|
+
"[green]OK[/]" if success else "[red]RETRY[/]",
|
|
210
|
+
detail,
|
|
211
|
+
)
|
|
212
|
+
return table
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def render_trace_panel(trace_data: dict[str, Any], title: str = "Trace") -> Panel:
|
|
216
|
+
return Panel(
|
|
217
|
+
build_trace_summary_table(trace_data),
|
|
218
|
+
title=f"[bold]{title}[/bold]",
|
|
219
|
+
subtitle=f"[{status_style(str(trace_data['status']))}]{str(trace_data['status']).upper()}[/]",
|
|
220
|
+
border_style="bright_black",
|
|
221
|
+
padding=(1, 2),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def render_trace_report(trace_data: dict[str, Any]) -> None:
|
|
226
|
+
console.print()
|
|
227
|
+
console.print(render_trace_panel(trace_data, "TraceLLM Trace"))
|
|
228
|
+
console.print()
|
|
229
|
+
console.print(build_steps_table(trace_data["steps"]))
|
|
230
|
+
console.print()
|
|
231
|
+
response_preview = str(trace_data.get("response") or "")
|
|
232
|
+
if response_preview:
|
|
233
|
+
console.print(
|
|
234
|
+
Panel.fit(
|
|
235
|
+
response_preview[:600] + ("..." if len(response_preview) > 600 else ""),
|
|
236
|
+
title="Response Preview",
|
|
237
|
+
border_style="bright_black",
|
|
238
|
+
padding=(1, 2),
|
|
239
|
+
)
|
|
240
|
+
)
|
|
241
|
+
console.print()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def render_replay_tree(
|
|
245
|
+
steps: list[dict[str, Any]],
|
|
246
|
+
active_index: int | None = None,
|
|
247
|
+
) -> Tree:
|
|
248
|
+
tree = Tree("", hide_root=True)
|
|
249
|
+
for i, step in enumerate(steps, 1):
|
|
250
|
+
tool_name = step.get("tool_name", "unknown")
|
|
251
|
+
duration = float(step.get("duration", 0.0))
|
|
252
|
+
success = bool(step.get("success", True))
|
|
253
|
+
dur_str = f"[bright_black]{duration:.0f}ms[/bright_black]"
|
|
254
|
+
if active_index == i:
|
|
255
|
+
branch = tree.add(f"[cyan]▶[/cyan] [white]{tool_name}[/white] {dur_str}")
|
|
256
|
+
elif active_index is not None and i < active_index:
|
|
257
|
+
status = "[green]OK[/green]" if success else "[red]RETRY[/red]"
|
|
258
|
+
branch = tree.add(f"[green]✓[/green] [dim]{tool_name}[/dim] {dur_str} {status}")
|
|
259
|
+
elif active_index is not None and i > active_index:
|
|
260
|
+
branch = tree.add(f" [dim]{tool_name}[/dim] {dur_str}")
|
|
261
|
+
else:
|
|
262
|
+
status = "[green]OK[/green]" if success else "[red]RETRY[/red]"
|
|
263
|
+
branch = tree.add(f" [white]{tool_name}[/white] {dur_str} {status}")
|
|
264
|
+
return tree
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def render_replay_report(trace_result: dict[str, Any]) -> None:
|
|
268
|
+
steps = trace_result.get("steps", [])
|
|
269
|
+
console.print()
|
|
270
|
+
console.print("Replay complete", style="bold white")
|
|
271
|
+
console.print()
|
|
272
|
+
tree = render_replay_tree(steps, active_index=len(steps))
|
|
273
|
+
console.print(Panel(tree, border_style="bright_black", padding=(1, 2)))
|
|
274
|
+
console.print()
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def build_progress_bar(description: str, total: int) -> Progress:
|
|
278
|
+
progress = Progress(
|
|
279
|
+
SpinnerColumn(style="white"),
|
|
280
|
+
TextColumn("[bright_black]{task.description}"),
|
|
281
|
+
BarColumn(bar_width=24, style="bright_black", pulse_style="white"),
|
|
282
|
+
TextColumn("[bright_black]{task.completed}/{task.total}[/bright_black]"),
|
|
283
|
+
TimeElapsedColumn(),
|
|
284
|
+
expand=True,
|
|
285
|
+
)
|
|
286
|
+
progress.add_task(description, total=total)
|
|
287
|
+
return progress
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def build_live_trace_screen(
|
|
291
|
+
prompt: str,
|
|
292
|
+
model_name: str,
|
|
293
|
+
finished_steps: list[dict[str, Any]],
|
|
294
|
+
current_label: str,
|
|
295
|
+
) -> Panel:
|
|
296
|
+
progress = Progress(
|
|
297
|
+
SpinnerColumn(style="white"),
|
|
298
|
+
TextColumn("[white]{task.description}"),
|
|
299
|
+
BarColumn(bar_width=28, style="bright_black", complete_style="white"),
|
|
300
|
+
TextColumn("[bright_black]{task.completed}/{task.total}[/bright_black]"),
|
|
301
|
+
TimeElapsedColumn(),
|
|
302
|
+
expand=True,
|
|
303
|
+
)
|
|
304
|
+
total = max(1, len(finished_steps) + 1)
|
|
305
|
+
task_id = progress.add_task(current_label, total=total, completed=len(finished_steps))
|
|
306
|
+
|
|
307
|
+
timeline = Table.grid(padding=(0, 2))
|
|
308
|
+
timeline.add_column(style="bright_black", width=3)
|
|
309
|
+
timeline.add_column(style="white")
|
|
310
|
+
timeline.add_column(style="bright_black", justify="right")
|
|
311
|
+
timeline.add_column(style="bright_black")
|
|
312
|
+
|
|
313
|
+
for index, step in enumerate(finished_steps[-5:], start=max(1, len(finished_steps) - 4)):
|
|
314
|
+
duration = float(step.get("duration", 0.0))
|
|
315
|
+
signal = "retry" if not step.get("success", True) else "steady"
|
|
316
|
+
if duration >= SLOW_TRACE_THRESHOLD_MS:
|
|
317
|
+
signal = "spike"
|
|
318
|
+
timeline.add_row(
|
|
319
|
+
str(index),
|
|
320
|
+
str(step.get("tool_name", "unknown")),
|
|
321
|
+
f'[{latency_style(duration)}]{duration:.0f} ms[/]',
|
|
322
|
+
signal,
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
body = Group(
|
|
326
|
+
Align.left(Text(prompt, style="bold white")),
|
|
327
|
+
Text(f"model: {model_name}", style="bright_black"),
|
|
328
|
+
Rule(style="bright_black"),
|
|
329
|
+
progress,
|
|
330
|
+
Rule(style="bright_black"),
|
|
331
|
+
timeline,
|
|
332
|
+
)
|
|
333
|
+
progress.update(task_id, completed=len(finished_steps))
|
|
334
|
+
return Panel(body, title="Live Trace", border_style="bright_black", padding=(1, 2))
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def trace_command_footer(trace_data: dict[str, Any]) -> None:
|
|
338
|
+
status = str(trace_data["status"])
|
|
339
|
+
badge = render_status_badge(status)
|
|
340
|
+
console.print(
|
|
341
|
+
Panel.fit(
|
|
342
|
+
f"[bright_black]trace_id[/bright_black] {trace_data['trace_id']}\n"
|
|
343
|
+
f"[bright_black]model[/bright_black] {trace_data.get('model_name', 'unknown')}\n"
|
|
344
|
+
f"[bright_black]latency[/bright_black] {float(trace_data['latency']):.2f} ms\n"
|
|
345
|
+
f"[bright_black]tokens[/bright_black] {trace_data['token_count']:,}\n"
|
|
346
|
+
f"[bright_black]retries[/bright_black] {trace_data['retry_count']}\n"
|
|
347
|
+
f"{badge}",
|
|
348
|
+
title="Trace Complete",
|
|
349
|
+
border_style="bright_black",
|
|
350
|
+
padding=(1, 2),
|
|
351
|
+
)
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def render_project_credentials(
|
|
356
|
+
project_id: str,
|
|
357
|
+
name: str,
|
|
358
|
+
environment: str,
|
|
359
|
+
api_key: str,
|
|
360
|
+
description: str,
|
|
361
|
+
) -> None:
|
|
362
|
+
console.print()
|
|
363
|
+
console.print(
|
|
364
|
+
Panel.fit(
|
|
365
|
+
f"[bold white]{name}[/bold white]\n\n"
|
|
366
|
+
f"[bright_black]project_id[/bright_black] {project_id}\n"
|
|
367
|
+
f"[bright_black]env[/bright_black] [{environment_style(environment)}]{environment}[/]\n"
|
|
368
|
+
f"[bright_black]api_key[/bright_black] [bold]{api_key}[/bold]\n"
|
|
369
|
+
f"[bright_black]desc[/bright_black] {description or 'n/a'}\n\n"
|
|
370
|
+
f"[dim]Save this key — it will not be shown again.[/dim]",
|
|
371
|
+
title="Project Credentials",
|
|
372
|
+
border_style="bright_black",
|
|
373
|
+
padding=(1, 2),
|
|
374
|
+
)
|
|
375
|
+
)
|
|
376
|
+
console.print()
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def render_export_success(path: Path, count: int) -> None:
|
|
380
|
+
console.print()
|
|
381
|
+
console.print(
|
|
382
|
+
Panel.fit(
|
|
383
|
+
f"[bold white]{count} traces exported[/bold white]\n"
|
|
384
|
+
f"[dim]{path}[/dim]",
|
|
385
|
+
title="Export Complete",
|
|
386
|
+
border_style="bright_black",
|
|
387
|
+
padding=(1, 2),
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
console.print()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tracellm-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: TraceLLM — Open-source LLM observability, tracing, and replay infrastructure.
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastapi
|
|
8
|
+
Requires-Dist: typer
|
|
9
|
+
Requires-Dist: rich
|
|
10
|
+
Requires-Dist: motor
|
|
11
|
+
Requires-Dist: pymongo
|
|
12
|
+
Requires-Dist: python-dotenv
|
|
13
|
+
Requires-Dist: openai
|
|
14
|
+
Requires-Dist: langchain-core
|
|
15
|
+
Requires-Dist: httpx
|
|
16
|
+
|
|
17
|
+
# TraceLLM Backend Package
|
|
18
|
+
|
|
19
|
+
Install in editable mode with:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install -e .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This package exposes:
|
|
26
|
+
|
|
27
|
+
- `from tracellm import trace`
|
|
28
|
+
- `tracellm demo`
|
|
29
|
+
- `tracellm trace`
|
|
30
|
+
- `tracellm replay`
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
app/__init__.py,sha256=JutOO7DgN1mmqlmpKf8ZlqnGhUdE40epGJqL112fado,44
|
|
2
|
+
app/main.py,sha256=e1gnhv_SGW1v2rsgdkZm7MuOQp576mKty_QU7TO1ZWQ,1279
|
|
3
|
+
app/database/__init__.py,sha256=29zIkjz9AWBcYKi9tX5hTNFjDVyZESXgAZITBQ8yQpQ,37
|
|
4
|
+
app/database/mongodb.py,sha256=o5vPtRRywUscrNbVfRH81JnIfK5BCr58v2iC3RidE6M,2535
|
|
5
|
+
app/database/project_service.py,sha256=TCMj8lpV2VUteHrqNvOhJV_nTqa_7X6VXGvDUrtKMes,3505
|
|
6
|
+
app/database/trace_service.py,sha256=m_l5pI-attakMkqhcFxhauTXk_nGLXq1rUV6UrDGcQU,15724
|
|
7
|
+
app/models/__init__.py,sha256=L-pNP1hY9c1-yHusD01UMoP3Wypwgk8RbwGl8dACB8U,361
|
|
8
|
+
app/models/health.py,sha256=evVu_-tvLLCaAj9REnd99uDIKXrmKhJymuZSOjik7dg,83
|
|
9
|
+
app/models/project.py,sha256=95UdSHGX9UWrWzeHqdcl36QUq7IFd9oHDQK0Lh67t3k,701
|
|
10
|
+
app/models/trace.py,sha256=GNJEi3TgF3J_yKpdga83XUCVS7EKYj5ahSBBgPyOzQU,2105
|
|
11
|
+
app/models/trace_model.py,sha256=s-9w0EmvFYmYvEVZsgZUoaF9KRX-IO_IncFFFMjZfNA,1455
|
|
12
|
+
app/routes/__init__.py,sha256=vmvaMIxzv70y1slvUI0gQRArGJsQ3rYL182dEbFGCU4,38
|
|
13
|
+
app/routes/health.py,sha256=H8yvu0QZXgBbIz32d6wQiWlxQJO8oip-zEK3R-Gcsx4,254
|
|
14
|
+
app/routes/observability.py,sha256=yQtHHO2AllKDdeQPLp56oADx8vzDcYlvpMibZ5XIMwM,2075
|
|
15
|
+
app/routes/projects.py,sha256=2nVuKzuhbQ1qnkQ_cMTTnyORBktrLxklfONLM-zpeSA,864
|
|
16
|
+
app/websocket/__init__.py,sha256=AGZnybL2CnfpHb-RXyoKWJ5fGLMG-KQQr-_uz76vqSs,38
|
|
17
|
+
app/websocket/socket.py,sha256=EwCeJgmMDQjm1BkLjpYTaFWp2Z8nbTsdDNmbR1Uaplg,1960
|
|
18
|
+
sdk/__init__.py,sha256=dLvZniY4ws9BEHsDn3-qaqUt_KwzLp9jQYFlJoPV-Rw,182
|
|
19
|
+
sdk/tracer.py,sha256=-X9KVGF6jX_e4BjuoIlXIR3SCxxA32mU06x37ZfP-BE,160
|
|
20
|
+
tracellm/__init__.py,sha256=TiQxkgG6R-117qY-6uMzaFfH2jPrLl57Mj4d03q8yIs,317
|
|
21
|
+
tracellm/banner.py,sha256=qh55DZ-pFuJHPU-ghoObP0iZieYpsiBY5N0JtufDCg4,984
|
|
22
|
+
tracellm/cli.py,sha256=Hg9MGdVB0oRVwPktKnKlEvOyBdcIKLrpFlpmMdNkKmM,4918
|
|
23
|
+
tracellm/db.py,sha256=Arm_4oeN2c4MM7cGh82pz_DJkyV8Z9jSao4aPFwnn_w,2459
|
|
24
|
+
tracellm/exporter.py,sha256=cJ0373hPy2i1ErmPhX01bNVLfcHrx9soa1wceOVpcQ0,2186
|
|
25
|
+
tracellm/mascot.py,sha256=vLagQV1teRmnKOVR01KGymQZaoS186sITVzazVwcmBU,1245
|
|
26
|
+
tracellm/monitor.py,sha256=qXWI5B2IQ68jMyU3oBIATT1ur-zw1VR5SCLXjQta3ms,14441
|
|
27
|
+
tracellm/palette.py,sha256=yyVliLzxaOvfM926VoiethpOFl1vs5NRMY_68Lwz8nY,6231
|
|
28
|
+
tracellm/replay.py,sha256=2nsyAM5OvHWGa6FsEdNloG_ZqshYCSKkXAsS8XJh1SQ,3579
|
|
29
|
+
tracellm/startup.py,sha256=1UbC6V7dnHr_g6cbUJNTYX4cKIs-dVDJjQq7oOmQTbE,3984
|
|
30
|
+
tracellm/summary.py,sha256=fuvN7IVbgzfYkP0-2nivhs_n2Qu44nMgKDBeBv0RtFw,1694
|
|
31
|
+
tracellm/trace_stream.py,sha256=GElD1ZX6y6rwZBKtTML0gRw9ZV4bowEvCEQVLmPJ4wY,2271
|
|
32
|
+
tracellm/tracer.py,sha256=WSEtYRI3OSMnBd28KQU1skhkfSkbJEJC7PCweiT1duE,23119
|
|
33
|
+
tracellm/tree_renderer.py,sha256=8rnJKXGjqv-doA58LHxojNCKj7ja_ZjgCzy5Z1ZNjvI,2416
|
|
34
|
+
tracellm/utils.py,sha256=4ZdRzXSmsARi7KdICAKRQaMVgRzxPSMGunfu3KHG6JM,13291
|
|
35
|
+
tracellm/integrations/__init__.py,sha256=0pYLI4TyWSgLuRXLXUg9XLVTYW4bKSKgMgbhxOL0Nec,203
|
|
36
|
+
tracellm/integrations/langchain.py,sha256=KeZ6dQTdED25sDS4tbOu5pXbvzo1BSWndIvqRU1ByzY,7359
|
|
37
|
+
tracellm/integrations/openai.py,sha256=-JT_TgHqEfG9gEv7x6LHCriCQD7J69xkX--xWIwNiAE,7759
|
|
38
|
+
tracellm/integrations/tool_tracer.py,sha256=yx05HzF1Mo_RdJTvGm0_n2SXZ991_JPF97HpA1uimLI,6066
|
|
39
|
+
tracellm_cli-0.1.0.dist-info/METADATA,sha256=_m8DWOt3Kk4ANAdHW4npZMqrWZC9mXYsXzD2s4vhk1s,651
|
|
40
|
+
tracellm_cli-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
41
|
+
tracellm_cli-0.1.0.dist-info/entry_points.txt,sha256=Z8FCRzoX43LJy-4T0k5PDzTYDyLe8WVhb9Lv97uOl7w,47
|
|
42
|
+
tracellm_cli-0.1.0.dist-info/top_level.txt,sha256=6y0UHevq1y28aKxTBGYIO9YncbN7EuvPQG8v84RvNic,17
|
|
43
|
+
tracellm_cli-0.1.0.dist-info/RECORD,,
|