benchflow 0.7.2.dev1980__py3-none-any.whl → 0.7.2.dev1986__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.
- benchflow/cli/traj.py +109 -1
- benchflow/trajectories/viewer.py +78 -67
- {benchflow-0.7.2.dev1980.dist-info → benchflow-0.7.2.dev1986.dist-info}/METADATA +1 -1
- {benchflow-0.7.2.dev1980.dist-info → benchflow-0.7.2.dev1986.dist-info}/RECORD +7 -7
- {benchflow-0.7.2.dev1980.dist-info → benchflow-0.7.2.dev1986.dist-info}/WHEEL +0 -0
- {benchflow-0.7.2.dev1980.dist-info → benchflow-0.7.2.dev1986.dist-info}/entry_points.txt +0 -0
- {benchflow-0.7.2.dev1980.dist-info → benchflow-0.7.2.dev1986.dist-info}/licenses/LICENSE +0 -0
benchflow/cli/traj.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import json
|
|
5
6
|
import os
|
|
6
7
|
import shutil
|
|
7
8
|
import subprocess
|
|
@@ -29,6 +30,7 @@ from benchflow.publish.traj_capture import (
|
|
|
29
30
|
stage_trajectory_artifacts,
|
|
30
31
|
validate_email,
|
|
31
32
|
validate_github_id,
|
|
33
|
+
validate_source_id,
|
|
32
34
|
)
|
|
33
35
|
from benchflow.publish.traj_report import (
|
|
34
36
|
DEFAULT_PREVIEW_STEPS,
|
|
@@ -127,6 +129,7 @@ class _UploadOptions:
|
|
|
127
129
|
github_id: str | None
|
|
128
130
|
email: str | None
|
|
129
131
|
source_id: str | None
|
|
132
|
+
repo: bool
|
|
130
133
|
direct: bool
|
|
131
134
|
container_url: str | None
|
|
132
135
|
dry_run: bool
|
|
@@ -223,6 +226,14 @@ def register_traj(app: typer.Typer) -> None:
|
|
|
223
226
|
str | None,
|
|
224
227
|
typer.Option("--source-id", help="Stable contributor source identifier"),
|
|
225
228
|
] = None,
|
|
229
|
+
repo: Annotated[
|
|
230
|
+
bool,
|
|
231
|
+
typer.Option(
|
|
232
|
+
"--repo/--no-repo",
|
|
233
|
+
help="Tag the upload with the session's repository "
|
|
234
|
+
"(owner/name from its git remote) as the source id",
|
|
235
|
+
),
|
|
236
|
+
] = True,
|
|
226
237
|
direct: Annotated[
|
|
227
238
|
bool,
|
|
228
239
|
typer.Option("--direct", help="Upload with local Azure credentials"),
|
|
@@ -254,6 +265,7 @@ def register_traj(app: typer.Typer) -> None:
|
|
|
254
265
|
github_id=github_id,
|
|
255
266
|
email=email,
|
|
256
267
|
source_id=source_id,
|
|
268
|
+
repo=repo,
|
|
257
269
|
direct=direct,
|
|
258
270
|
container_url=container_url,
|
|
259
271
|
dry_run=dry_run,
|
|
@@ -268,7 +280,17 @@ def register_traj(app: typer.Typer) -> None:
|
|
|
268
280
|
def _run_upload(options: _UploadOptions) -> None:
|
|
269
281
|
prompted = options.path is None
|
|
270
282
|
path = options.path or _prompt_for_path()
|
|
271
|
-
|
|
283
|
+
repo_slug: str | None = None
|
|
284
|
+
if options.source_id is not None:
|
|
285
|
+
source_id = options.source_id
|
|
286
|
+
else:
|
|
287
|
+
if options.repo:
|
|
288
|
+
repo_slug = _detect_repo_slug(path)
|
|
289
|
+
source_id = f"repo/{repo_slug}" if repo_slug else default_source_id(path)
|
|
290
|
+
if repo_slug:
|
|
291
|
+
# Contributor-visible metadata: surface the tag so private-repo
|
|
292
|
+
# sessions can opt out before anything leaves the machine.
|
|
293
|
+
console.print(f"Repo: {repo_slug} (use --no-repo to omit)")
|
|
272
294
|
destination = _resolve_destination(options)
|
|
273
295
|
|
|
274
296
|
with (
|
|
@@ -381,6 +403,92 @@ def _infer_email() -> str:
|
|
|
381
403
|
return ""
|
|
382
404
|
|
|
383
405
|
|
|
406
|
+
_SESSION_CWD_SCAN_LINES = 50
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _detect_repo_slug(path: Path) -> str | None:
|
|
410
|
+
"""Best-effort ``owner/name`` for the repository the session was about.
|
|
411
|
+
|
|
412
|
+
Reads the working directory the session recorded (Claude events carry a
|
|
413
|
+
``cwd`` field; Codex ``session_meta`` payloads do too), asks that
|
|
414
|
+
directory's git for the ``origin`` remote, and falls back to the
|
|
415
|
+
invocation directory. Every failure is silent — repo tagging must never
|
|
416
|
+
break an upload — and local-path remotes never produce a tag, so no
|
|
417
|
+
local absolute path can leak into the manifest.
|
|
418
|
+
"""
|
|
419
|
+
for candidate in (_session_cwd(path), Path.cwd()):
|
|
420
|
+
if candidate is None or not candidate.is_dir():
|
|
421
|
+
continue
|
|
422
|
+
remote = _command_stdout(
|
|
423
|
+
"git", "-C", str(candidate), "remote", "get-url", "origin"
|
|
424
|
+
)
|
|
425
|
+
slug = _repo_slug_from_remote(remote) if remote else None
|
|
426
|
+
if slug:
|
|
427
|
+
return slug
|
|
428
|
+
return None
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _session_cwd(path: Path) -> Path | None:
|
|
432
|
+
"""Working directory recorded by the first session event that has one."""
|
|
433
|
+
session = path.expanduser()
|
|
434
|
+
if not session.is_file():
|
|
435
|
+
return None
|
|
436
|
+
try:
|
|
437
|
+
with session.open(encoding="utf-8", errors="replace") as stream:
|
|
438
|
+
for line_number, line in enumerate(stream):
|
|
439
|
+
if line_number >= _SESSION_CWD_SCAN_LINES:
|
|
440
|
+
break
|
|
441
|
+
body = line.strip()
|
|
442
|
+
if not body:
|
|
443
|
+
continue
|
|
444
|
+
try:
|
|
445
|
+
event = json.loads(body)
|
|
446
|
+
except json.JSONDecodeError:
|
|
447
|
+
continue
|
|
448
|
+
if not isinstance(event, dict):
|
|
449
|
+
continue
|
|
450
|
+
cwd = event.get("cwd")
|
|
451
|
+
if isinstance(cwd, str) and cwd:
|
|
452
|
+
return Path(cwd)
|
|
453
|
+
payload = event.get("payload")
|
|
454
|
+
if (
|
|
455
|
+
event.get("type") == "session_meta"
|
|
456
|
+
and isinstance(payload, dict)
|
|
457
|
+
and isinstance(payload.get("cwd"), str)
|
|
458
|
+
and payload["cwd"]
|
|
459
|
+
):
|
|
460
|
+
return Path(payload["cwd"])
|
|
461
|
+
except OSError:
|
|
462
|
+
return None
|
|
463
|
+
return None
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def _repo_slug_from_remote(remote: str) -> str | None:
|
|
467
|
+
"""Normalize an https/ssh git remote URL to ``owner/name``.
|
|
468
|
+
|
|
469
|
+
Only URL-shaped remotes qualify; a filesystem-path remote returns
|
|
470
|
+
``None`` so local paths never enter the uploaded source id.
|
|
471
|
+
"""
|
|
472
|
+
value = remote.strip()
|
|
473
|
+
if "://" in value:
|
|
474
|
+
_, _, rest = value.partition("://")
|
|
475
|
+
_, _, repo_path = rest.partition("/")
|
|
476
|
+
elif ":" in value and "@" in value.partition(":")[0]:
|
|
477
|
+
repo_path = value.partition(":")[2]
|
|
478
|
+
else:
|
|
479
|
+
return None
|
|
480
|
+
repo_path = repo_path.strip("/").removesuffix(".git")
|
|
481
|
+
segments = [segment for segment in repo_path.split("/") if segment]
|
|
482
|
+
if len(segments) < 2:
|
|
483
|
+
return None
|
|
484
|
+
slug = f"{segments[-2]}/{segments[-1]}"
|
|
485
|
+
try:
|
|
486
|
+
validate_source_id(f"repo/{slug}")
|
|
487
|
+
except ValueError:
|
|
488
|
+
return None
|
|
489
|
+
return slug
|
|
490
|
+
|
|
491
|
+
|
|
384
492
|
def _git_config(key: str) -> str | None:
|
|
385
493
|
return _command_stdout("git", "config", "--get", key)
|
|
386
494
|
|
benchflow/trajectories/viewer.py
CHANGED
|
@@ -14,6 +14,78 @@ _ARGS_PREVIEW = 300 # max chars for tool args display
|
|
|
14
14
|
_CONTENT_PREVIEW = 200 # max chars for write/agent content preview
|
|
15
15
|
_RESULT_PREVIEW = 300 # max chars for result summary
|
|
16
16
|
|
|
17
|
+
# Shared stylesheet for all viewer pages, matching the www.benchflow.ai design
|
|
18
|
+
# language (light monochrome: near-white page, white cards, near-black ink,
|
|
19
|
+
# pure-black accent, Satoshi/Google Sans Code with system-safe fallbacks, dark
|
|
20
|
+
# code blocks). Kept inline so pages work fully offline with no external
|
|
21
|
+
# requests; one constant so the three templates stop drifting apart.
|
|
22
|
+
_VIEWER_CSS = """\
|
|
23
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
24
|
+
:root {
|
|
25
|
+
--background: #fafafa; --card: #ffffff;
|
|
26
|
+
--ink: #0a0a0a; --ink-secondary: #404040; --muted: #737373; --faint: #a1a1a1;
|
|
27
|
+
--border: #e5e5e5; --rule-strong: #c7c7c7; --secondary: #f5f5f5;
|
|
28
|
+
--code-bg: #141414; --code-ink: #ececec;
|
|
29
|
+
--radius: 8px;
|
|
30
|
+
--font-sans: "Satoshi", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
31
|
+
--font-mono: "Google Sans Code", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
32
|
+
}
|
|
33
|
+
body { font-family: var(--font-sans); background: var(--background); color: var(--ink); padding: 28px 20px 48px; max-width: 960px; margin: 0 auto; line-height: 1.6; -webkit-font-smoothing: antialiased; }
|
|
34
|
+
::selection { background: var(--secondary); color: var(--ink); }
|
|
35
|
+
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
36
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
37
|
+
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 9999px; }
|
|
38
|
+
::-webkit-scrollbar-thumb:hover { background: var(--muted); }
|
|
39
|
+
.wordmark { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
|
|
40
|
+
.wordmark svg { width: 18px; height: 18px; flex: none; color: var(--ink); }
|
|
41
|
+
.wordmark .brand { font-weight: 600; font-size: 15px; letter-spacing: -0.01em; color: var(--ink); }
|
|
42
|
+
.wordmark .app { font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; color: var(--ink-secondary); background: var(--secondary); border: 1px solid var(--border); border-radius: 9999px; padding: 3px 10px; }
|
|
43
|
+
.header { border-bottom: 1px solid var(--border); padding-bottom: 18px; margin-bottom: 24px; }
|
|
44
|
+
.header h1 { font-size: 20px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 10px; overflow-wrap: anywhere; }
|
|
45
|
+
.meta { display: flex; gap: 8px; flex-wrap: wrap; font-size: 13px; color: var(--muted); }
|
|
46
|
+
.meta span { font-family: var(--font-mono); font-size: 11px; font-weight: 500; color: var(--ink-secondary); background: var(--secondary); padding: 3px 9px; border-radius: 4px; border: 1px solid var(--border); }
|
|
47
|
+
.step { margin-bottom: 8px; padding: 12px 16px; border-radius: var(--radius); background: var(--card); border: 1px solid var(--border); box-shadow: 0 1px 2px rgba(10, 10, 10, 0.04); }
|
|
48
|
+
.step.prompt { background: var(--secondary); border-color: var(--rule-strong); margin-bottom: 14px; }
|
|
49
|
+
.step.output { background: var(--code-bg); border-color: var(--code-bg); padding: 10px 16px; }
|
|
50
|
+
.step.output pre { color: var(--code-ink); font-family: var(--font-mono); font-size: 12px; line-height: 1.7; white-space: pre-wrap; word-break: break-word; }
|
|
51
|
+
.step.result { background: var(--ink); border-color: var(--ink); margin-top: 14px; }
|
|
52
|
+
.step.result .msg { color: var(--background); }
|
|
53
|
+
.step-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
54
|
+
.label { display: inline-flex; align-items: center; font-family: var(--font-mono); padding: 2px 10px; border-radius: 9999px; font-weight: 600; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; }
|
|
55
|
+
.label.prompt { background: var(--ink); color: var(--background); }
|
|
56
|
+
.label.result { background: var(--background); color: var(--ink); }
|
|
57
|
+
.meta-inline { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
|
|
58
|
+
.step.result .meta-inline { color: var(--faint); }
|
|
59
|
+
.msg { font-size: 14px; line-height: 1.65; white-space: pre-wrap; word-break: break-word; }
|
|
60
|
+
.thinking { font-size: 13px; color: var(--muted); font-style: italic; margin-bottom: 8px; padding: 8px 12px; background: var(--secondary); border-radius: 4px; border-left: 2px solid var(--rule-strong); white-space: pre-wrap; word-break: break-word; }
|
|
61
|
+
.tool { margin-bottom: 6px; }
|
|
62
|
+
.tool-name { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--ink); background: var(--secondary); border: 1px solid var(--border); padding: 2px 9px; border-radius: 4px; }
|
|
63
|
+
.tool-args { margin-top: 6px; font-family: var(--font-mono); font-size: 12px; line-height: 1.7; color: var(--code-ink); background: var(--code-bg); padding: 10px 12px; border-radius: 6px; white-space: pre-wrap; word-break: break-word; }
|
|
64
|
+
.metrics { font-family: var(--font-mono); font-size: 11px; color: var(--faint); margin-top: 4px; }
|
|
65
|
+
.turn-divider { border-top: 1px solid var(--border); margin: 24px 0; }
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
# Small BenchFlow wordmark header (inline SVG logo from the site's icon set —
|
|
69
|
+
# no external requests) shown above the page title on every viewer page.
|
|
70
|
+
_WORDMARK_HTML = (
|
|
71
|
+
'<div class="wordmark">'
|
|
72
|
+
'<svg viewBox="0 0 514 512" fill="currentColor" aria-hidden="true">'
|
|
73
|
+
'<path fill-rule="evenodd" clip-rule="evenodd" d="M445.422 66.4597L511.882 0'
|
|
74
|
+
"L389.022 293.965L295.129 387.859L0 511.882L69.3042 442.577L81.0101 454.283"
|
|
75
|
+
"L89.0554 446.238L77.3493 434.532L130.65 381.232L162.469 413.051L170.514 40"
|
|
76
|
+
"5.006L138.695 373.187L191.995 319.887L203.701 331.593L211.746 323.547L200."
|
|
77
|
+
"04 311.841L253.34 258.541L285.16 290.36L293.205 282.315L261.386 250.496L31"
|
|
78
|
+
"4.686 197.196L326.392 208.902L334.437 200.856L322.731 189.15L376.031 135.8"
|
|
79
|
+
"5L407.851 167.669L415.896 159.624L384.077 127.805L437.377 74.5049L449.083 "
|
|
80
|
+
"86.2108L457.128 78.1656L445.422 66.4597ZM399.127 389.865V299.369L513.197 2"
|
|
81
|
+
"6.4333V503.935L399.127 389.865ZM391.061 397.931L505.132 512.001H29.1594L30"
|
|
82
|
+
'0.605 397.931H391.061Z"/>'
|
|
83
|
+
"</svg>"
|
|
84
|
+
'<span class="brand">BenchFlow</span>'
|
|
85
|
+
'<span class="app">trajectory viewer</span>'
|
|
86
|
+
"</div>"
|
|
87
|
+
)
|
|
88
|
+
|
|
17
89
|
|
|
18
90
|
def render_turn(events: list[dict], turn_number: int, prompt: str = "") -> str:
|
|
19
91
|
"""Render one turn's events as HTML blocks."""
|
|
@@ -260,33 +332,11 @@ def render_rollout(rollout_dir: Path, prompts: list[str] | None = None) -> str:
|
|
|
260
332
|
<meta charset="utf-8">
|
|
261
333
|
<title>benchflow — {rollout_dir.name}</title>
|
|
262
334
|
<style>
|
|
263
|
-
|
|
264
|
-
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0d1117; color: #c9d1d9; padding: 20px; max-width: 960px; margin: 0 auto; }}
|
|
265
|
-
.header {{ border-bottom: 1px solid #30363d; padding-bottom: 16px; margin-bottom: 24px; }}
|
|
266
|
-
.header h1 {{ font-size: 20px; color: #f0f6fc; margin-bottom: 8px; }}
|
|
267
|
-
.meta {{ display: flex; gap: 12px; flex-wrap: wrap; font-size: 13px; color: #8b949e; }}
|
|
268
|
-
.meta span {{ background: #161b22; padding: 4px 10px; border-radius: 6px; border: 1px solid #30363d; }}
|
|
269
|
-
.step {{ margin-bottom: 4px; padding: 10px 14px; border-radius: 6px; }}
|
|
270
|
-
.step.prompt {{ background: #0d1f3c; border: 1px solid #1f3a5f; margin-bottom: 12px; }}
|
|
271
|
-
.step.agent {{ background: #161b22; border: 1px solid #30363d; }}
|
|
272
|
-
.step.output {{ background: #0d1117; border-left: 3px solid #238636; padding: 6px 14px; }}
|
|
273
|
-
.step.output pre {{ color: #7ee787; font-size: 12px; white-space: pre-wrap; word-break: break-word; }}
|
|
274
|
-
.step.result {{ background: #1a2f1a; border: 1px solid #238636; margin-top: 12px; }}
|
|
275
|
-
.step-header {{ display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }}
|
|
276
|
-
.label {{ padding: 2px 8px; border-radius: 4px; font-weight: 600; font-size: 11px; text-transform: uppercase; }}
|
|
277
|
-
.label.prompt {{ background: #1f3a5f; color: #58a6ff; }}
|
|
278
|
-
.label.result {{ background: #1a2f1a; color: #3fb950; }}
|
|
279
|
-
.meta-inline {{ font-size: 12px; color: #8b949e; }}
|
|
280
|
-
.msg {{ font-size: 14px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }}
|
|
281
|
-
.thinking {{ font-size: 13px; color: #8b949e; font-style: italic; margin-bottom: 6px; padding: 8px; background: #0d1117; border-radius: 4px; border-left: 3px solid #484f58; }}
|
|
282
|
-
.tool {{ margin-bottom: 4px; }}
|
|
283
|
-
.tool-name {{ background: #2d333b; color: #f0883e; padding: 2px 8px; border-radius: 4px; font-family: monospace; font-size: 13px; font-weight: 600; }}
|
|
284
|
-
.tool-args {{ margin-top: 4px; font-size: 12px; color: #c9d1d9; background: #0d1117; padding: 8px; border-radius: 4px; white-space: pre-wrap; word-break: break-word; }}
|
|
285
|
-
.turn-divider {{ border-top: 2px solid #30363d; margin: 20px 0; padding-top: 8px; }}
|
|
286
|
-
</style>
|
|
335
|
+
{_VIEWER_CSS}</style>
|
|
287
336
|
</head>
|
|
288
337
|
<body>
|
|
289
338
|
<div class="header">
|
|
339
|
+
{_WORDMARK_HTML}
|
|
290
340
|
<h1>{html.escape(rollout_dir.name)}</h1>
|
|
291
341
|
<div class="meta">
|
|
292
342
|
<span>model: {html.escape(model)}</span>
|
|
@@ -392,25 +442,8 @@ def _render_acp_events(
|
|
|
392
442
|
return f"""<!DOCTYPE html>
|
|
393
443
|
<html><head><meta charset="utf-8"><title>benchflow — {html.escape(title)}</title>
|
|
394
444
|
<style>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
.header {{ border-bottom: 1px solid #30363d; padding-bottom: 16px; margin-bottom: 24px; }}
|
|
398
|
-
.header h1 {{ font-size: 20px; color: #f0f6fc; }}
|
|
399
|
-
.step {{ margin-bottom: 4px; padding: 10px 14px; border-radius: 6px; }}
|
|
400
|
-
.step.prompt {{ background: #0d1f3c; border: 1px solid #1f3a5f; margin-bottom: 12px; }}
|
|
401
|
-
.step.agent {{ background: #161b22; border: 1px solid #30363d; }}
|
|
402
|
-
.step.result {{ background: #1a2f1a; border: 1px solid #238636; margin-top: 12px; }}
|
|
403
|
-
.step-header {{ margin-bottom: 6px; }}
|
|
404
|
-
.label {{ padding: 2px 8px; border-radius: 4px; font-weight: 600; font-size: 11px; text-transform: uppercase; }}
|
|
405
|
-
.label.prompt {{ background: #1f3a5f; color: #58a6ff; }}
|
|
406
|
-
.label.result {{ background: #1a2f1a; color: #3fb950; }}
|
|
407
|
-
.msg {{ font-size: 14px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }}
|
|
408
|
-
.thinking {{ font-size: 13px; color: #8b949e; font-style: italic; padding: 8px; background: #0d1117; border-radius: 4px; border-left: 3px solid #484f58; }}
|
|
409
|
-
.tool {{ margin-bottom: 4px; }}
|
|
410
|
-
.tool-name {{ background: #2d333b; color: #f0883e; padding: 2px 8px; border-radius: 4px; font-family: monospace; font-size: 13px; font-weight: 600; }}
|
|
411
|
-
.metrics {{ font-size: 11px; color: #484f58; margin-top: 4px; }}
|
|
412
|
-
</style></head><body>
|
|
413
|
-
<div class="header"><h1>{html.escape(title)}</h1></div>
|
|
445
|
+
{_VIEWER_CSS}</style></head><body>
|
|
446
|
+
<div class="header">{_WORDMARK_HTML}<h1>{html.escape(title)}</h1></div>
|
|
414
447
|
{"".join(blocks)}
|
|
415
448
|
</body></html>"""
|
|
416
449
|
|
|
@@ -526,33 +559,11 @@ def _stream_json_page(title: str, events: list[dict], turn_blocks: list[str]) ->
|
|
|
526
559
|
<meta charset="utf-8">
|
|
527
560
|
<title>benchflow — {html.escape(title)}</title>
|
|
528
561
|
<style>
|
|
529
|
-
|
|
530
|
-
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0d1117; color: #c9d1d9; padding: 20px; max-width: 960px; margin: 0 auto; }}
|
|
531
|
-
.header {{ border-bottom: 1px solid #30363d; padding-bottom: 16px; margin-bottom: 24px; }}
|
|
532
|
-
.header h1 {{ font-size: 20px; color: #f0f6fc; margin-bottom: 8px; }}
|
|
533
|
-
.meta {{ display: flex; gap: 12px; flex-wrap: wrap; font-size: 13px; color: #8b949e; }}
|
|
534
|
-
.meta span {{ background: #161b22; padding: 4px 10px; border-radius: 6px; border: 1px solid #30363d; }}
|
|
535
|
-
.step {{ margin-bottom: 4px; padding: 10px 14px; border-radius: 6px; }}
|
|
536
|
-
.step.prompt {{ background: #0d1f3c; border: 1px solid #1f3a5f; margin-bottom: 12px; }}
|
|
537
|
-
.step.agent {{ background: #161b22; border: 1px solid #30363d; }}
|
|
538
|
-
.step.output {{ background: #0d1117; border-left: 3px solid #238636; padding: 6px 14px; }}
|
|
539
|
-
.step.output pre {{ color: #7ee787; font-size: 12px; white-space: pre-wrap; word-break: break-word; }}
|
|
540
|
-
.step.result {{ background: #1a2f1a; border: 1px solid #238636; margin-top: 12px; }}
|
|
541
|
-
.step-header {{ display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }}
|
|
542
|
-
.label {{ padding: 2px 8px; border-radius: 4px; font-weight: 600; font-size: 11px; text-transform: uppercase; }}
|
|
543
|
-
.label.prompt {{ background: #1f3a5f; color: #58a6ff; }}
|
|
544
|
-
.label.result {{ background: #1a2f1a; color: #3fb950; }}
|
|
545
|
-
.meta-inline {{ font-size: 12px; color: #8b949e; }}
|
|
546
|
-
.msg {{ font-size: 14px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }}
|
|
547
|
-
.thinking {{ font-size: 13px; color: #8b949e; font-style: italic; margin-bottom: 6px; padding: 8px; background: #0d1117; border-radius: 4px; border-left: 3px solid #484f58; }}
|
|
548
|
-
.tool {{ margin-bottom: 4px; }}
|
|
549
|
-
.tool-name {{ background: #2d333b; color: #f0883e; padding: 2px 8px; border-radius: 4px; font-family: monospace; font-size: 13px; font-weight: 600; }}
|
|
550
|
-
.tool-args {{ margin-top: 4px; font-size: 12px; color: #c9d1d9; background: #0d1117; padding: 8px; border-radius: 4px; white-space: pre-wrap; word-break: break-word; }}
|
|
551
|
-
.turn-divider {{ border-top: 2px solid #30363d; margin: 20px 0; padding-top: 8px; }}
|
|
552
|
-
</style>
|
|
562
|
+
{_VIEWER_CSS}</style>
|
|
553
563
|
</head>
|
|
554
564
|
<body>
|
|
555
565
|
<div class="header">
|
|
566
|
+
{_WORDMARK_HTML}
|
|
556
567
|
<h1>{html.escape(title)}</h1>
|
|
557
568
|
<div class="meta">
|
|
558
569
|
<span>model: {html.escape(model)}</span>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: benchflow
|
|
3
|
-
Version: 0.7.2.
|
|
3
|
+
Version: 0.7.2.dev1986
|
|
4
4
|
Summary: Multi-turn agent benchmarking with ACP — run any agent, any model, any provider.
|
|
5
5
|
Project-URL: Homepage, https://github.com/benchflow-ai/benchflow
|
|
6
6
|
Project-URL: Repository, https://github.com/benchflow-ai/benchflow
|
|
@@ -116,7 +116,7 @@ benchflow/cli/skills.py,sha256=2Apv1iqvmstWEhY6O-PRdxKc8RYwR6f7MvbYfl2dWm0,7497
|
|
|
116
116
|
benchflow/cli/tasks.py,sha256=b1XP1EZ79ZtK_1shF65qZyv27EcKKFZYV35M4DzxYKI,18534
|
|
117
117
|
benchflow/cli/trace_import.py,sha256=NHDieFdiKQ-2Sr1-GF8Z5EDcbGsz2qq_kFE0rXacC2o,14705
|
|
118
118
|
benchflow/cli/train.py,sha256=MIP_JxptitH348bWWURpcWt-TmDAw1s8d-RUU7jBaIg,23635
|
|
119
|
-
benchflow/cli/traj.py,sha256=
|
|
119
|
+
benchflow/cli/traj.py,sha256=2QlXCLNywIKsm8uQVsQ1TAEnaafV6b0dfLx37O2wEsU,23691
|
|
120
120
|
benchflow/continue_run/__init__.py,sha256=dWidng7kJphVUtbP1a1Ma0Lyjxj5yLgQZIApaKCJUew,1479
|
|
121
121
|
benchflow/continue_run/batch.py,sha256=8BNSInyp_Ol6Fcrg4ezBJdi3cBS12nC8mf963_x4fIg,4146
|
|
122
122
|
benchflow/continue_run/orchestrator.py,sha256=wYoseBNE_rZ0EjNwWDyqfave54xNRe43sCd_O4VJjyk,27676
|
|
@@ -291,9 +291,9 @@ benchflow/trajectories/sessions.py,sha256=u_6x1WyT8YtKUVOb6b3myTCHhqn58a8NHCLAvQ
|
|
|
291
291
|
benchflow/trajectories/tree.py,sha256=c0jyoP9OurDQq-zRtPc66edzWUvLGwQQz0jgtyqSw2U,5576
|
|
292
292
|
benchflow/trajectories/trl_sft_tokenization.py,sha256=-Ef0bP9cuzfzOz5nIv2mEF3taQIEw68h6SM1YO-Mwn4,8643
|
|
293
293
|
benchflow/trajectories/types.py,sha256=aSJclec3dOCUlfFNDL8GfzvkAcBo5r-dvlHE0MnGdMo,27554
|
|
294
|
-
benchflow/trajectories/viewer.py,sha256=
|
|
295
|
-
benchflow-0.7.2.
|
|
296
|
-
benchflow-0.7.2.
|
|
297
|
-
benchflow-0.7.2.
|
|
298
|
-
benchflow-0.7.2.
|
|
299
|
-
benchflow-0.7.2.
|
|
294
|
+
benchflow/trajectories/viewer.py,sha256=59wr8pcWWsCYzuI_sFzTSFJFHeXzH6Yklrh8UsF1ksg,26561
|
|
295
|
+
benchflow-0.7.2.dev1986.dist-info/METADATA,sha256=D7gO4mBmAwaKA5_bFHpuy2Hu2_vfMEBQLdPfVoCyFEk,15261
|
|
296
|
+
benchflow-0.7.2.dev1986.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
297
|
+
benchflow-0.7.2.dev1986.dist-info/entry_points.txt,sha256=qPMBVtH4qz3P4nMALEAdTbvpxvsVch9RhqshZKQn1dE,84
|
|
298
|
+
benchflow-0.7.2.dev1986.dist-info/licenses/LICENSE,sha256=ohnbHkuBylrTtOvaZJk9Hz7dRwmaEEGAb5ZcBV4Xuhw,10779
|
|
299
|
+
benchflow-0.7.2.dev1986.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|