agent-tune-kit 2.3.5__tar.gz → 2.4.1__tar.gz
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.
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/.codex-plugin/plugin.json +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/PKG-INFO +3 -3
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/README.en.md +2 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/README.md +2 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/__init__.py +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/projects.py +74 -18
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/records.py +3 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/shared/base.css +3 -11
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/app.js +90 -60
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/page.html +2 -4
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/styles.css +21 -3
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/traces/app.js +123 -64
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/traces/page.html +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/traces/styles.css +13 -4
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/trace.py +14 -7
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/traces.py +50 -30
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/trace-dashboard-design.md +16 -14
- agent_tune_kit-2.4.1/docs/trace-project-attribution-design.md +99 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/trace-swimlane-design.md +7 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/trace-tuning.md +18 -11
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/pyproject.toml +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/validate_skill_pack.py +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-detect/SKILL.md +5 -3
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-diagnose/SKILL.md +13 -11
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-init/SKILL.md +4 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-optimize/SKILL.md +5 -3
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-verify/SKILL.md +4 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-visualize-trace/SKILL.md +4 -2
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_install_plugin.py +1 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_release_scripts.py +1 -1
- agent_tune_kit-2.4.1/tests/test_trace_projects.py +147 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_visualize_trace.py +33 -1
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_visualize_traces.py +32 -6
- agent_tune_kit-2.4.1/tests/trace-controls.cjs +54 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-dashboard.cjs +144 -58
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-event-layout.cjs +18 -6
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-fragments.cjs +39 -4
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-issue-cards.cjs +4 -4
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-projects.cjs +81 -71
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-stage-cards.cjs +29 -1
- agent_tune_kit-2.3.5/agent_tune_kit/visualize/assets/shared/project-menu.js +0 -32
- agent_tune_kit-2.3.5/docs/trace-project-attribution-design.md +0 -246
- agent_tune_kit-2.3.5/tests/test_trace_projects.py +0 -65
- agent_tune_kit-2.3.5/tests/trace-controls.cjs +0 -86
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/.gitignore +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/__main__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/dataset.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/evaluation.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/main.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/output.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/results.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/trace.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/cli/visualize.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/datasets/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/datasets/prepare.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/datasets/truth.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/datasets/updates.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/datasets/validation.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/errors.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/calibration.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/logs.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/rules.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/runner.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/runtime.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/execution/tracing.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/installer.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/assessment.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/evidence.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/judgments.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/summary.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/results/versions.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/archive.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/capture.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/categories.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/langfuse.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/migrate.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/progress.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/query.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/segments.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/traces/store.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/utils/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/utils/csv_io.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/utils/files.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/dataset/app.js +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/dataset/page.html +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/dataset/styles.css +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/dataset/vendor/echarts.min.js +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/failures/app.js +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/failures/page.html +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/failures/styles.css +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/lanes.js +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/vendor/markdown-it.LICENSE +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/vendor/markdown-it.min.js +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/dataset.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/failures.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/fields.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/history.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/render.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/timeline.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/workspace.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/agent_tune_kit_evaluation.png +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/agent_tune_kit_trace.png +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/arch-en.png +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/arch.png +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/architecture.en.svg +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/assets/architecture.svg +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/ato-atk-project-boundary-recommendation-2026-11-05.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/cli-skill-modularization-plan.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/codex_agent_tuning_prd.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/execution-evidence-and-tracing-plan.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/ground-truth-and-grading-assessment-2026-10-25.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/local-context.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/shared-versioning-and-confirmation.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/skill-template-pack-usage.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/surginame-atk-capability-review-2026-10-27.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/trace-change-verification-readability-diagnosis.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/trace-tuning-validation.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/docs/truth-and-assessment.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/check-release.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/dev-refresh-install.sh +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/install_plugin.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/publish-pypi.sh +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/publish-release.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/release-version.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/scripts/release-version.sh +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-dataset/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-dataset/scripts/update_dataset.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-diagnose/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-eval/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-init/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-optimize/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-report/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-trace-capture/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-visualize-dataset/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-visualize-dataset/scripts/generate_dataset_browser.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-visualize-failures/SKILL.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/skills/atk-visualize-failures/scripts/generate_failure_browser.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/templates/.atk/runner/eval_runner.py.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/templates/.atk/runner/failure_rule.py.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/templates/.atk/runner/import_evidence.py.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/templates/.gitkeep +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/__init__.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/conftest.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/fixtures/legacy_eval_runner.py.txt +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/fixtures/managed_v1.py.md +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_assessment_contract.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_atk_init_contract.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_cli_workflow.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_dataset_updates.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_diagnosis.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_evidence_import.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_evidence_judgments.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_evidence_packaging.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_evidence_versions.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_execution_evidence.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_execution_outcomes.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_execution_tracing.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_generate_dataset_browser.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_generate_failure_browser.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_judge_calibration.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_local_context.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_plugin_cache.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_runner_output_columns.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_runner_template_row_logging.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_runtime_contracts.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_snapshot_reads.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_capture.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_categories.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_cli.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_event_list.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_langfuse.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_progress.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_query.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_records.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_scroll_layout.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_segments.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_trace_store.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_truth_browser.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_truth_cli.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_truth_contract.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_truth_runner.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/test_v2_progress.py +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-event-detail.cjs +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-event-list.cjs +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-event-wheel.cjs +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-preview-scroll.cjs +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-scroll-layout.cjs +0 -0
- {agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/tests/trace-selection-reason.cjs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-tune-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Local Codex plugin for batch Agent evaluation and session trace tuning with evidence-backed issues, focused changes, verification and offline review.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "hustyichi",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-tune-kit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: Local Codex plugin for iterative Agent tuning with guided Skills, reusable runner templates, versioned results, and static validation.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hustyichi/agent-tune-kit
|
|
6
6
|
Project-URL: Repository, https://github.com/hustyichi/agent-tune-kit
|
|
@@ -196,6 +196,6 @@ Each session archive is stored under `.atk/traces/<session_id>/` in your Agent p
|
|
|
196
196
|
|
|
197
197
|
[Trace tuning guide for source configuration, supported formats, and archive layout](docs/trace-tuning.md)
|
|
198
198
|
|
|
199
|
-
[Multi-project attribution and filtering
|
|
199
|
+
[Multi-project attribution and filtering details (Chinese)](docs/trace-project-attribution-design.md)
|
|
200
200
|
|
|
201
|
-
Use `atk trace project` to register workspace projects and submodules.
|
|
201
|
+
Use `atk trace project` to register workspace projects and submodules. Record associated projects with reasonable causal explanations for human review, and filter them in the dashboard and session issue list. Associations do not require a completed or verified fix; reasons describe uncertainty, and repair details describe modification locations.
|
|
@@ -182,6 +182,6 @@ Each session archive is stored under `.atk/traces/<session_id>/` in your Agent p
|
|
|
182
182
|
|
|
183
183
|
[Trace tuning guide for source configuration, supported formats, and archive layout](docs/trace-tuning.md)
|
|
184
184
|
|
|
185
|
-
[Multi-project attribution and filtering
|
|
185
|
+
[Multi-project attribution and filtering details (Chinese)](docs/trace-project-attribution-design.md)
|
|
186
186
|
|
|
187
|
-
Use `atk trace project` to register workspace projects and submodules.
|
|
187
|
+
Use `atk trace project` to register workspace projects and submodules. Record associated projects with reasonable causal explanations for human review, and filter them in the dashboard and session issue list. Associations do not require a completed or verified fix; reasons describe uncertainty, and repair details describe modification locations.
|
|
@@ -182,6 +182,6 @@ $atk-trace-verify 验证 <session-id> 的 ISSUE-001 对应候选,并检查相
|
|
|
182
182
|
|
|
183
183
|
[轨迹调优指南,包含来源配置、支持格式和归档结构](docs/trace-tuning.md)
|
|
184
184
|
|
|
185
|
-
[
|
|
185
|
+
[多工程关联与项目筛选说明](docs/trace-project-attribution-design.md)
|
|
186
186
|
|
|
187
|
-
支持通过 `atk trace project`
|
|
187
|
+
支持通过 `atk trace project` 登记工作区及子模块;诊断按合理的原因解释记录“关联项目”,供人工审核,大盘与会话问题栏均可筛选。关联不以修复完成或验证通过为前提;不确定性写在关联理由中,修改位置在修复详情中说明。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Workspace project registry and
|
|
1
|
+
"""Workspace project registry and issue associations for human review."""
|
|
2
2
|
|
|
3
3
|
import configparser
|
|
4
4
|
import hashlib
|
|
@@ -150,14 +150,12 @@ def validate_links(session_dir, links):
|
|
|
150
150
|
projects = project_map(Path(session_dir).parent)
|
|
151
151
|
seen = set()
|
|
152
152
|
for link in links:
|
|
153
|
-
if not isinstance(link, dict):
|
|
153
|
+
if not isinstance(link, dict) or set(link) - {"project_id", "reason", "evidence", "source_paths"}:
|
|
154
154
|
raise UserActionRequired("Invalid project link.")
|
|
155
|
-
key =
|
|
156
|
-
if not
|
|
155
|
+
key = link.get("project_id")
|
|
156
|
+
if not isinstance(key, str) or key not in projects or key in seen:
|
|
157
157
|
raise UserActionRequired("Unknown or duplicate project link.")
|
|
158
158
|
seen.add(key)
|
|
159
|
-
if key[1] not in {"root_cause", "improvement"} or link.get("evidence_state") not in {"hypothesis", "supported"}:
|
|
160
|
-
raise UserActionRequired("Invalid project attribution state.")
|
|
161
159
|
if (
|
|
162
160
|
not isinstance(link.get("reason"), str)
|
|
163
161
|
or not link["reason"].strip()
|
|
@@ -176,26 +174,84 @@ def validate_links(session_dir, links):
|
|
|
176
174
|
return links
|
|
177
175
|
|
|
178
176
|
|
|
179
|
-
def
|
|
180
|
-
|
|
177
|
+
def _display_name(entry, project_id):
|
|
178
|
+
return entry.get("abbreviation") or entry.get("name") or project_id
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def linked_projects(root, issue, projects=None):
|
|
182
|
+
"""Return the display identity of each project an issue links to, once per project.
|
|
183
|
+
|
|
184
|
+
Pages only need the stable ID, the shown name and aliases for search; the rest of the registry stays out of them.
|
|
185
|
+
Pass ``projects`` (from ``project_map``) when resolving many issues so the registry is read once.
|
|
186
|
+
"""
|
|
187
|
+
projects = project_map(root) if projects is None else projects
|
|
181
188
|
result = []
|
|
182
189
|
links = issue.get("project_links", [])
|
|
183
190
|
if not isinstance(links, list):
|
|
184
191
|
return result
|
|
192
|
+
seen = set()
|
|
185
193
|
for link in links:
|
|
186
|
-
if (
|
|
187
|
-
not isinstance(link, dict)
|
|
188
|
-
or not isinstance(link.get("project_id"), str)
|
|
189
|
-
or link.get("role") != "root_cause"
|
|
190
|
-
):
|
|
194
|
+
if not isinstance(link, dict) or not isinstance(link.get("project_id"), str) or link["project_id"] in seen:
|
|
191
195
|
continue
|
|
192
|
-
|
|
196
|
+
project_id = link["project_id"]
|
|
197
|
+
seen.add(project_id)
|
|
198
|
+
entry = projects.get(project_id, {})
|
|
199
|
+
aliases = entry.get("aliases")
|
|
200
|
+
result.append(
|
|
201
|
+
{
|
|
202
|
+
"id": project_id,
|
|
203
|
+
"name": _display_name(entry, project_id),
|
|
204
|
+
"aliases": [alias for alias in aliases if isinstance(alias, str)] if isinstance(aliases, list) else [],
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
return result
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def project_index(root, linked, projects=None):
|
|
211
|
+
"""Summarize the projects that issues actually link to, for the pages' single-choice project filter.
|
|
212
|
+
|
|
213
|
+
``linked`` yields ``(session_key, linked_projects)`` per issue. Registered projects without any linked issue are
|
|
214
|
+
left out: nothing could be found by choosing them. A linked ID missing from the registry stays in, shown by its ID,
|
|
215
|
+
so its issues remain reachable. Counts are per project; an issue linked to several projects counts once in each,
|
|
216
|
+
so the entries must not be added up as an issue total.
|
|
217
|
+
"""
|
|
218
|
+
projects = project_map(root) if projects is None else projects
|
|
219
|
+
found = {}
|
|
220
|
+
for session, items in linked:
|
|
221
|
+
for item in items:
|
|
222
|
+
entry = found.setdefault(
|
|
223
|
+
item["id"], {"id": item["id"], "name": item["name"], "issues": 0, "sessions": set()}
|
|
224
|
+
)
|
|
225
|
+
entry["issues"] += 1
|
|
226
|
+
entry["sessions"].add(session)
|
|
227
|
+
names = {}
|
|
228
|
+
for entry in found.values():
|
|
229
|
+
names.setdefault(entry["name"], []).append(entry["id"])
|
|
230
|
+
result = []
|
|
231
|
+
for entry in found.values():
|
|
232
|
+
registered = projects.get(entry["id"])
|
|
233
|
+
name = entry["name"]
|
|
234
|
+
if len(names[name]) > 1:
|
|
235
|
+
# Two projects share an abbreviation: tell the filter's choices apart by where each one lives.
|
|
236
|
+
tail = Path(registered["path"]).name if registered and registered.get("path") else entry["id"]
|
|
237
|
+
name = f"{name} · {tail or entry['id']}"
|
|
193
238
|
result.append(
|
|
194
239
|
{
|
|
195
|
-
|
|
196
|
-
"
|
|
197
|
-
"
|
|
198
|
-
"
|
|
240
|
+
"id": entry["id"],
|
|
241
|
+
"name": name,
|
|
242
|
+
"issues": entry["issues"],
|
|
243
|
+
"sessions": len(entry["sessions"]),
|
|
244
|
+
"registered": registered is not None,
|
|
245
|
+
"deprecated": bool(registered and registered.get("deprecated") is True),
|
|
199
246
|
}
|
|
200
247
|
)
|
|
248
|
+
result.sort(
|
|
249
|
+
key=lambda item: (
|
|
250
|
+
item["deprecated"],
|
|
251
|
+
not item["registered"],
|
|
252
|
+
-item["issues"],
|
|
253
|
+
item["name"].casefold(),
|
|
254
|
+
item["id"],
|
|
255
|
+
)
|
|
256
|
+
)
|
|
201
257
|
return result
|
|
@@ -172,6 +172,7 @@ def prepare_issue(session_dir, data, *, dry_run=False):
|
|
|
172
172
|
"created_at": now(),
|
|
173
173
|
"status": "open",
|
|
174
174
|
"segments": [],
|
|
175
|
+
"project_links": [],
|
|
175
176
|
}
|
|
176
177
|
)
|
|
177
178
|
if "project_links" in data:
|
|
@@ -347,9 +348,10 @@ def save_diagnosis(session_dir, issue_id, text, diagnosis_id=None, expected_revi
|
|
|
347
348
|
"description": issue["description"],
|
|
348
349
|
"evidence": issue["evidence"],
|
|
349
350
|
"segments": issue.get("segments", []),
|
|
351
|
+
"project_links": validate_links(directory, issue.get("project_links", [])),
|
|
350
352
|
"created_at": now(),
|
|
351
353
|
}
|
|
352
|
-
for optional in ("selection_reason", "category"
|
|
354
|
+
for optional in ("selection_reason", "category"):
|
|
353
355
|
if optional in issue:
|
|
354
356
|
snapshot[optional] = issue[optional]
|
|
355
357
|
if issue.get("project_links"):
|
{agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/shared/base.css
RENAMED
|
@@ -63,15 +63,15 @@ h3 { font-size: 14px }
|
|
|
63
63
|
.progress-dot.excluded { background: transparent; box-shadow: inset 0 0 0 1.5px var(--p-pending) }
|
|
64
64
|
.category-tag { display: inline-block; max-width: 100%; background: #fff8f1; color: var(--accent); font-size: 11px; line-height: 1.5; padding: 2px 6px; border-radius: 4px; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
65
65
|
a.category-tag:hover { background: #ffe8d2 }
|
|
66
|
-
input:not([type=checkbox]), select
|
|
66
|
+
input:not([type=checkbox]), select {
|
|
67
67
|
display: block; height: var(--control-height); min-width: 0; max-width: 100%; padding: 0 11px;
|
|
68
68
|
font-size: 13px; line-height: normal; border-color: #cdd8e1;
|
|
69
69
|
}
|
|
70
|
-
select
|
|
70
|
+
select {
|
|
71
71
|
appearance: none; padding-right: 32px; text-overflow: ellipsis;
|
|
72
72
|
background: white url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e") no-repeat right 11px center / 14px;
|
|
73
73
|
}
|
|
74
|
-
input:not([type=checkbox]):hover, select:hover
|
|
74
|
+
input:not([type=checkbox]):hover, select:hover { border-color: #9baebb }
|
|
75
75
|
input[type=checkbox] { width: 16px; height: 16px; margin: 0; padding: 0; flex-shrink: 0; accent-color: var(--brand) }
|
|
76
76
|
@media (forced-colors: active) {
|
|
77
77
|
select { appearance: auto; background-image: none; padding-right: 8px }
|
|
@@ -96,11 +96,3 @@ input[type=checkbox] { width: 16px; height: 16px; margin: 0; padding: 0; flex-sh
|
|
|
96
96
|
.drawer-resizer { display: none }
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
/* Project attribution belongs to issues; the menu is shared by both issue views. */
|
|
100
|
-
.project-choice { position: relative; min-width: 0; max-width: 100%; margin-bottom: 7px; font-size: 13px }
|
|
101
|
-
.project-choice > summary { line-height: calc(var(--control-height) - 2px); list-style: none; white-space: nowrap; overflow: hidden; border: 1px solid #cdd8e1; border-radius: 6px }
|
|
102
|
-
.project-choice > summary::-webkit-details-marker { display: none }
|
|
103
|
-
.project-choice[open] > summary { border-color: #deb493; color: var(--accent) }
|
|
104
|
-
.project-menu { position: fixed; z-index: 20; width: min(300px, calc(100vw - 16px)); max-height: min(320px, calc(100dvh - 16px)); overflow: auto; overscroll-behavior: contain; padding: 12px; border: 1px solid var(--line); border-radius: 6px; background: white; box-shadow: 0 6px 20px #0002 }
|
|
105
|
-
.project-menu p { margin: 0 0 8px }
|
|
106
|
-
#project-filter label { display: flex; align-items: center; gap: 8px; padding: 6px 0; overflow-wrap: anywhere }
|
|
@@ -23,26 +23,14 @@
|
|
|
23
23
|
const captureById = new Map(data.captures.map(c => [c.id, c]));
|
|
24
24
|
const issueById = new Map(data.issues.map(item => [item.record.id, item]));
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
const label = el("label"), input = el("input");
|
|
35
|
-
input.type = "checkbox"; input.value = p.id;
|
|
36
|
-
input.checked = projectSelection.has(p.id);
|
|
37
|
-
label.append(input, document.createTextNode(p.abbreviation || p.name));
|
|
38
|
-
$("project-filter").append(label); projectInputs.push(input);
|
|
39
|
-
input.onchange = () => $("project-filter").onchange();
|
|
40
|
-
}
|
|
41
|
-
const updateProjectSummary = () => {
|
|
42
|
-
$("project-summary").textContent = projectSelection.size ? `关联项目:已选 ${projectSelection.size} 项` : "关联项目:全部";
|
|
43
|
-
};
|
|
44
|
-
updateProjectSummary();
|
|
45
|
-
$("project-clear").onclick = () => { projectInputs.forEach(input => { input.checked = false; }); $("project-filter").onchange(); };
|
|
26
|
+
// One linked project at a time, or every issue. Only projects this session's issues link to are offered.
|
|
27
|
+
const PROJECTS = data.project_index || [];
|
|
28
|
+
const PROJECT = new Map(PROJECTS.map(entry => [entry.id, entry]));
|
|
29
|
+
// Older links may carry several projects or the removed empty-association value: keep the first one still offered.
|
|
30
|
+
const projectFrom = params => params.getAll("project").find(id => PROJECT.has(id)) || "";
|
|
31
|
+
let railProject = projectFrom(new URLSearchParams(location.hash.slice(1)));
|
|
32
|
+
const projectMatches = item => !railProject || (item.linked_projects || []).some(project => project.id === railProject);
|
|
33
|
+
const projectLabel = entry => `${entry.name}${entry.deprecated ? "(已弃用)" : entry.registered === false ? "(未登记)" : ""}`;
|
|
46
34
|
|
|
47
35
|
const filters = ["trace-filter", "type-filter", "trace-search", "record-mode"];
|
|
48
36
|
const list = $("trace-list"), scroller = $("trace-scroll");
|
|
@@ -69,11 +57,11 @@
|
|
|
69
57
|
const dashboardHash = params => `../index.html#${params}`;
|
|
70
58
|
const projectLabels = item => {
|
|
71
59
|
const row = el("p", "关联项目:", "issue-projects");
|
|
72
|
-
const projects = item.
|
|
73
|
-
if (!projects.length) row.append(document.createTextNode("
|
|
60
|
+
const projects = item.linked_projects || [];
|
|
61
|
+
if (!projects.length) row.append(document.createTextNode("无"));
|
|
74
62
|
projects.forEach((project, index) => {
|
|
75
63
|
if (index) row.append(document.createTextNode("、"));
|
|
76
|
-
const name = project.name
|
|
64
|
+
const name = project.name;
|
|
77
65
|
const label = el(data.dashboard.available ? "a" : "span", name);
|
|
78
66
|
if (data.dashboard.available) {
|
|
79
67
|
label.href = dashboardHash(`view=category&project=${encodeURIComponent(project.id)}`);
|
|
@@ -108,7 +96,6 @@
|
|
|
108
96
|
onRoot: index => openEventDrawer(currentCapture.nodes[index], document.activeElement),
|
|
109
97
|
onIssueBadge: track => {
|
|
110
98
|
$("issue-search").value = "";
|
|
111
|
-
$("issue-status").value = "";
|
|
112
99
|
railFilter = {track, ids: data.issues.filter(item => item.fragments.some(part => part.capture_id === currentCapture?.id && part.track === track)).map(item => item.record.id)};
|
|
113
100
|
renderIssueRail();
|
|
114
101
|
},
|
|
@@ -321,6 +308,16 @@
|
|
|
321
308
|
const headings = headingNodes.map(node => node.textContent);
|
|
322
309
|
const structured = headings.join("|") === "问题描述|问题根因|最小修复方案"
|
|
323
310
|
|| headings.join("|") === "Issue description|Root cause|Minimal fix";
|
|
311
|
+
if (snapshot?.project_links) {
|
|
312
|
+
const entries = new Map((snapshot.project_registry?.projects || []).map(p => [p.id, p]));
|
|
313
|
+
const associations = el("div");
|
|
314
|
+
associations.append(el("p", "诊断时的关联项目:" + (snapshot.project_links.length ? "" : "无")));
|
|
315
|
+
for (const link of snapshot.project_links) {
|
|
316
|
+
const entry = entries.get(link.project_id);
|
|
317
|
+
associations.append(el("p", `${entry?.abbreviation || entry?.name || link.project_id}:${link.reason}`));
|
|
318
|
+
}
|
|
319
|
+
body.prepend(associations);
|
|
320
|
+
}
|
|
324
321
|
if (index === 0 && structured) {
|
|
325
322
|
container.append(body);
|
|
326
323
|
continue;
|
|
@@ -335,11 +332,6 @@
|
|
|
335
332
|
container.append(description);
|
|
336
333
|
}
|
|
337
334
|
const details = el("details", undefined, "detail-section");
|
|
338
|
-
if (snapshot?.project_links) {
|
|
339
|
-
const entries = new Map((snapshot.project_registry?.projects || []).map(p => [p.id, p]));
|
|
340
|
-
const names = snapshot.project_links.filter(p => p.role === "root_cause").map(p => { const entry = entries.get(p.project_id); return (entry?.abbreviation || entry?.name || p.project_id) + (p.evidence_state === "supported" ? "" : "(待确认)"); });
|
|
341
|
-
body.prepend(el("p", `诊断时的关联项目:${names.join("、") || "待归因"}`));
|
|
342
|
-
}
|
|
343
335
|
const name = diagnosis.reference.path.split("/").pop();
|
|
344
336
|
details.append(el("summary", `展开原诊断 · ${name}`), body);
|
|
345
337
|
container.append(details);
|
|
@@ -431,7 +423,7 @@
|
|
|
431
423
|
const issue = item.record;
|
|
432
424
|
openDrawer(`${issue.id} · ${issue.title || "问题详情"}`, "issue");
|
|
433
425
|
const tabs = el("nav", undefined, "stage-tabs"); tabs.setAttribute("aria-label", "问题处理阶段");
|
|
434
|
-
for (const [key, label] of [["issue", "
|
|
426
|
+
for (const [key, label] of [["issue", "问题详情"], ["diagnoses", "诊断与方案"], ["changes", "修改候选"], ["verifications", "实际验证"]]) {
|
|
435
427
|
const tab = button(label, () => showIssue(item, key), key === stage ? "active" : "");
|
|
436
428
|
tab.setAttribute("aria-pressed", String(key === stage)); tabs.append(tab);
|
|
437
429
|
}
|
|
@@ -447,17 +439,6 @@
|
|
|
447
439
|
}
|
|
448
440
|
const segments = issue.segments || [];
|
|
449
441
|
if (!segments.length) $("drawer-content").append(el("p", "该问题尚未圈定片段,可查看已记录的关联证据。", "muted"));
|
|
450
|
-
if (segments.length) {
|
|
451
|
-
const box = section("关联片段");
|
|
452
|
-
segments.forEach((segment, index) => {
|
|
453
|
-
const row = el("div", undefined, "detail-section");
|
|
454
|
-
const title = `${segment.id || `S${index + 1}`} · ${segment.summary || "未命名片段"}`;
|
|
455
|
-
row.append(button(title, () => startIssue(item, item.fragments.findIndex(part => part.id === segment.id || (!part.id && index === item.fragments.indexOf(part))))));
|
|
456
|
-
appendReferences(row, segment.evidence || []);
|
|
457
|
-
box.append(row);
|
|
458
|
-
});
|
|
459
|
-
$("drawer-content").append(box);
|
|
460
|
-
}
|
|
461
442
|
if ((issue.evidence || []).length) {
|
|
462
443
|
const evidence = section(segments.length ? "额外证据" : "关联证据");
|
|
463
444
|
appendReferences(evidence, issue.evidence);
|
|
@@ -639,16 +620,31 @@
|
|
|
639
620
|
return (left.at ?? Infinity) - (right.at ?? Infinity) || left.track - right.track || a - b;
|
|
640
621
|
});
|
|
641
622
|
}
|
|
642
|
-
|
|
623
|
+
const rows = candidates.filter(i => {
|
|
643
624
|
const n = currentCapture.nodes[i];
|
|
644
625
|
if ((track !== null && n.track !== track) || (type && n.type !== type)) return false;
|
|
645
|
-
if (mode === "error" && !eventState(n).failed) return false;
|
|
646
626
|
if (query) {
|
|
647
627
|
if (!searchable.has(n)) searchable.set(n, pretty(n).toLocaleLowerCase());
|
|
648
628
|
return searchable.get(n).includes(query);
|
|
649
629
|
}
|
|
650
630
|
return true;
|
|
651
631
|
});
|
|
632
|
+
// The failure switch shows its count before it is chosen, so count within every other active scope and filter.
|
|
633
|
+
const failed = rows.filter(i => eventState(currentCapture.nodes[i]).failed);
|
|
634
|
+
return {rows: mode === "error" ? failed : rows, total: rows.length, failed: failed.length};
|
|
635
|
+
}
|
|
636
|
+
function syncRecordMode(failed) {
|
|
637
|
+
const only = $("record-mode").value === "error";
|
|
638
|
+
$("record-all").setAttribute("aria-pressed", String(!only));
|
|
639
|
+
$("record-failed").setAttribute("aria-pressed", String(only));
|
|
640
|
+
$("record-failed-count").textContent = String(failed);
|
|
641
|
+
// Keep an active switch usable at zero so the selection stays visible; otherwise zero means nothing to look at.
|
|
642
|
+
$("record-failed").disabled = !only && failed === 0;
|
|
643
|
+
$("record-failed").title = failed || only ? `只看执行失败的事件(${failed} 条)` : "当前范围没有执行失败的事件";
|
|
644
|
+
}
|
|
645
|
+
function setRecordMode(mode) {
|
|
646
|
+
$("record-mode").value = mode;
|
|
647
|
+
renderTraces();
|
|
652
648
|
}
|
|
653
649
|
function eventState(n) {
|
|
654
650
|
const out = n.output, input = n.input;
|
|
@@ -867,7 +863,7 @@
|
|
|
867
863
|
if (state.failed) {
|
|
868
864
|
row.classList.add("is-error");
|
|
869
865
|
const icon = el("span", "⚠", "event-error-icon");
|
|
870
|
-
icon.setAttribute("role", "img"); icon.setAttribute("aria-label", "
|
|
866
|
+
icon.setAttribute("role", "img"); icon.setAttribute("aria-label", "执行失败"); icon.title = "执行失败";
|
|
871
867
|
label.append(icon);
|
|
872
868
|
}
|
|
873
869
|
label.append(el("span", name, "node-name"));
|
|
@@ -971,9 +967,12 @@
|
|
|
971
967
|
$("summary").textContent = notes.join(" · ");
|
|
972
968
|
$("session-stats").textContent = `${native.length} Trace · ${order.length} 条事件 · ${data.issues.length} 问题`;
|
|
973
969
|
scroller.parentElement.classList.toggle("single", tracks.length === 1 || displayedScope !== null);
|
|
974
|
-
|
|
970
|
+
const filtered = filteredRows();
|
|
971
|
+
streamRows = filtered.rows;
|
|
972
|
+
syncRecordMode(filtered.failed);
|
|
975
973
|
displayRows = buildDisplayRows(streamRows);
|
|
976
|
-
$("trace-count").textContent =
|
|
974
|
+
$("trace-count").textContent = $("record-mode").value === "error"
|
|
975
|
+
? `失败 ${streamRows.length} / ${filtered.total} 条` : `${streamRows.length} 条`;
|
|
977
976
|
if (eventFocus) $("trace-count").textContent = streamRows.length === eventFocus.indices.length
|
|
978
977
|
? `${streamRows.length} 条事件` : `${streamRows.length} / ${eventFocus.indices.length} 条事件`;
|
|
979
978
|
const related = new Set((investigation?.item.fragments || []).filter(p => p.capture_id === currentCapture?.id).flatMap(p => p.anchors));
|
|
@@ -1116,16 +1115,51 @@
|
|
|
1116
1115
|
if (mine && investigation.index >= 2) card.querySelectorAll(".seg-more").forEach(more => { more.open = true; });
|
|
1117
1116
|
}
|
|
1118
1117
|
}
|
|
1118
|
+
const searchMatches = (item, text) => !text || pretty(item.record).toLocaleLowerCase().includes(text) ||
|
|
1119
|
+
progressOf(item).label.toLocaleLowerCase().includes(text) || (item.linked_projects || []).some(p => [p.name, ...(p.aliases || [])].some(name => name.toLocaleLowerCase().includes(text)));
|
|
1120
|
+
function chooseProject(id) {
|
|
1121
|
+
railProject = railProject === id ? "" : id;
|
|
1122
|
+
syncHash(); renderIssueRail();
|
|
1123
|
+
}
|
|
1124
|
+
// Project counts follow the search only: the lane filter and the chosen project leave every project's real size.
|
|
1125
|
+
function renderProjectChoice(text) {
|
|
1126
|
+
const box = $("project-legend");
|
|
1127
|
+
box.replaceChildren();
|
|
1128
|
+
const issues = data.issues.filter(item => searchMatches(item, text));
|
|
1129
|
+
const counts = new Map();
|
|
1130
|
+
for (const item of issues) for (const project of item.linked_projects || []) {
|
|
1131
|
+
if (PROJECT.has(project.id)) counts.set(project.id, (counts.get(project.id) || 0) + 1);
|
|
1132
|
+
}
|
|
1133
|
+
const order = new Map(PROJECTS.map((entry, index) => [entry.id, index]));
|
|
1134
|
+
const shown = PROJECTS.filter(entry => counts.get(entry.id) || entry.id === railProject).sort((a, b) =>
|
|
1135
|
+
Number(Boolean(a.deprecated)) - Number(Boolean(b.deprecated)) || Number(a.registered === false) - Number(b.registered === false) ||
|
|
1136
|
+
(counts.get(b.id) || 0) - (counts.get(a.id) || 0) || order.get(a.id) - order.get(b.id));
|
|
1137
|
+
// A single project that holds every issue filters nothing, so the row would only repeat the total. This is judged on
|
|
1138
|
+
// the whole session, not the search, so the row does not vanish while typing.
|
|
1139
|
+
box.hidden = !PROJECTS.length || (PROJECTS.length === 1 && !railProject && PROJECTS[0].issues === data.issues.length);
|
|
1140
|
+
if (box.hidden) return;
|
|
1141
|
+
const choice = (name, n, id, title) => {
|
|
1142
|
+
const item = button("", () => chooseProject(id), "project-item");
|
|
1143
|
+
item.setAttribute("role", "radio");
|
|
1144
|
+
item.setAttribute("aria-checked", String(railProject === id));
|
|
1145
|
+
item.title = title;
|
|
1146
|
+
item.append(el("span", name, "project-name"), el("span", String(n), "project-count"));
|
|
1147
|
+
if (!n) item.classList.add("is-empty");
|
|
1148
|
+
return item;
|
|
1149
|
+
};
|
|
1150
|
+
box.append(choice("全部", issues.length, "", "显示全部问题"));
|
|
1151
|
+
for (const entry of shown) {
|
|
1152
|
+
box.append(choice(projectLabel(entry), counts.get(entry.id) || 0, entry.id,
|
|
1153
|
+
railProject === entry.id ? `取消筛选 ${projectLabel(entry)}` : `只看关联 ${projectLabel(entry)} 的问题`));
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1119
1156
|
function renderIssueRail() {
|
|
1120
1157
|
const text = $("issue-search").value.toLocaleLowerCase();
|
|
1121
|
-
|
|
1158
|
+
renderProjectChoice(text);
|
|
1122
1159
|
const filtered = data.issues.filter(item => {
|
|
1123
1160
|
if (!projectMatches(item) && new URLSearchParams(location.hash.slice(1)).get("issue") !== item.record.id) return false;
|
|
1124
1161
|
if (railFilter && !railFilter.ids.includes(item.record.id)) return false;
|
|
1125
|
-
|
|
1126
|
-
if (status && progress !== status) return false;
|
|
1127
|
-
if (!text) return true;
|
|
1128
|
-
return pretty(item.record).toLocaleLowerCase().includes(text) || progress.toLocaleLowerCase().includes(text);
|
|
1162
|
+
return searchMatches(item, text);
|
|
1129
1163
|
});
|
|
1130
1164
|
$("rail-count").textContent = `${filtered.length}/${data.issues.length}`;
|
|
1131
1165
|
const box = $("issue-rail-list"); box.replaceChildren();
|
|
@@ -1206,7 +1240,7 @@
|
|
|
1206
1240
|
syncRailSelection();
|
|
1207
1241
|
}
|
|
1208
1242
|
function syncHash() {
|
|
1209
|
-
const parts =
|
|
1243
|
+
const parts = railProject ? [`project=${encodeURIComponent(railProject)}`] : [];
|
|
1210
1244
|
if (investigation) {
|
|
1211
1245
|
parts.push(`issue=${encodeURIComponent(investigation.item.record.id)}`);
|
|
1212
1246
|
const part = partNow();
|
|
@@ -1223,9 +1257,7 @@
|
|
|
1223
1257
|
if (hash !== location.hash) history.replaceState(null, "", hash || location.pathname + location.search);
|
|
1224
1258
|
const raw = hash.slice(1);
|
|
1225
1259
|
const params = new URLSearchParams(raw.includes("=") ? raw : `issue=${raw}`);
|
|
1226
|
-
|
|
1227
|
-
for (const input of projectInputs) input.checked = projectSelection.has(input.value);
|
|
1228
|
-
updateProjectSummary();
|
|
1260
|
+
railProject = projectFrom(params);
|
|
1229
1261
|
const issueId = params.get("issue");
|
|
1230
1262
|
const seg = params.get("seg");
|
|
1231
1263
|
const event = params.get("event");
|
|
@@ -1262,14 +1294,12 @@
|
|
|
1262
1294
|
$("capture-filter").closest("label").hidden = Boolean(currentCapture?.current);
|
|
1263
1295
|
options($("capture-filter"), data.captures.map(c => c.id));
|
|
1264
1296
|
if (currentCapture) $("capture-filter").value = currentCapture.id;
|
|
1265
|
-
$("project-filter").onchange = () => { projectSelection.clear(); for (const input of projectInputs) if (input.checked) projectSelection.add(input.value); updateProjectSummary(); const params = new URLSearchParams(location.hash.slice(1)); params.delete("project"); for (const id of projectSelection) params.append("project", id); history.replaceState(null, "", `#${params}`); renderIssueRail(); };
|
|
1266
1297
|
$("capture-filter").onchange = () => { investigation = null; scopeBefore = null; railFilter = null; chooseCapture(); renderIssueRail(); renderTraces(); };
|
|
1267
1298
|
$("trace-filter").onchange = () => focusTrace(scope());
|
|
1268
|
-
for (const id of ["trace-search","type-filter"
|
|
1269
|
-
|
|
1270
|
-
|
|
1299
|
+
for (const id of ["trace-search","type-filter"]) $(id).addEventListener(id === "trace-search" ? "input" : "change", () => renderTraces());
|
|
1300
|
+
$("record-all").onclick = () => setRecordMode("");
|
|
1301
|
+
$("record-failed").onclick = () => setRecordMode("error");
|
|
1271
1302
|
$("issue-search").oninput = () => { railFilter = null; renderIssueRail(); };
|
|
1272
|
-
$("issue-status").onchange = () => { railFilter = null; renderIssueRail(); };
|
|
1273
1303
|
const collapsed = localStorage.getItem(RAIL_KEY) === "1";
|
|
1274
1304
|
document.body.classList.toggle("rail-collapsed", collapsed);
|
|
1275
1305
|
$("rail-toggle").setAttribute("aria-expanded", String(!collapsed));
|
{agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/page.html
RENAMED
|
@@ -21,8 +21,7 @@
|
|
|
21
21
|
</div>
|
|
22
22
|
<div class="rail-filters">
|
|
23
23
|
<label class="search-label"><span class="sr-only">搜索问题</span><input id="issue-search" type="search" placeholder="搜索问题"></label>
|
|
24
|
-
<
|
|
25
|
-
<label><span class="sr-only">状态</span><select id="issue-status"></select></label>
|
|
24
|
+
<div id="project-legend" class="rail-projects" role="radiogroup" aria-label="关联项目" hidden></div>
|
|
26
25
|
</div>
|
|
27
26
|
<div id="issue-rail-list" class="rail-list" tabindex="0" aria-label="问题列表"></div>
|
|
28
27
|
</aside>
|
|
@@ -61,9 +60,8 @@
|
|
|
61
60
|
</section>
|
|
62
61
|
<section class="record-panel" aria-labelledby="records-title">
|
|
63
62
|
<div class="records-heading">
|
|
64
|
-
<div class="records-title"><h2 id="records-title">事件</h2><span id="event-range" class="muted" hidden></span><span id="trace-count" class="muted" aria-live="polite"></span><button id="event-reset" type="button" hidden>返回全部</button></div>
|
|
63
|
+
<div class="records-title"><h2 id="records-title">事件</h2><div class="record-mode" role="group" aria-label="事件范围"><input id="record-mode" type="hidden" value=""><button id="record-all" type="button" aria-pressed="true">全部</button><button id="record-failed" type="button" aria-pressed="false"><span class="record-failed-icon" aria-hidden="true">⚠</span>失败 <span id="record-failed-count" class="record-failed-count">0</span></button></div><span id="event-range" class="muted" hidden></span><span id="trace-count" class="muted" aria-live="polite"></span><button id="event-reset" type="button" hidden>返回全部</button></div>
|
|
65
64
|
<div class="toolbar record-filters">
|
|
66
|
-
<label><span class="sr-only">事件范围</span><select id="record-mode"><option value="">全部事件</option><option value="error">仅看异常</option></select></label>
|
|
67
65
|
<label><span class="sr-only">类型</span><select id="type-filter"></select></label>
|
|
68
66
|
<label class="search-label"><span class="sr-only">搜索事件</span><input id="trace-search" type="search" placeholder="搜索事件或输入输出"></label>
|
|
69
67
|
</div>
|
{agent_tune_kit-2.3.5 → agent_tune_kit-2.4.1}/agent_tune_kit/visualize/assets/trace/styles.css
RENAMED
|
@@ -33,7 +33,14 @@ body.rail-collapsed #rail-toggle { transform: rotate(180deg) }
|
|
|
33
33
|
.rail-filters .search-label { flex: 1 0 100%; min-width: 0 }
|
|
34
34
|
.rail-filters > label { min-width: 0; max-width: 100% }
|
|
35
35
|
.rail-filters input[type=search] { width: 100% }
|
|
36
|
-
|
|
36
|
+
/* Project choice: one linked project or all issues; each count is the issues linked to that project. */
|
|
37
|
+
.rail-projects { display: flex; flex-wrap: wrap; gap: 4px; flex: 1 0 100%; min-width: 0 }
|
|
38
|
+
.project-item { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; min-width: 0; padding: 2px 8px; border: 1px solid var(--line); border-radius: 6px; background: white; color: var(--muted); font-size: 12px; line-height: 1.5 }
|
|
39
|
+
.project-item:hover { background: var(--tint) }
|
|
40
|
+
.project-item[aria-checked=true] { background: var(--tint); color: var(--accent); border-color: #eabda0 }
|
|
41
|
+
.project-item .project-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
42
|
+
.project-item .project-count { font-weight: 700 }
|
|
43
|
+
.project-item.is-empty { opacity: .6 }
|
|
37
44
|
.rail-list { flex: 1; min-height: 0; overflow: auto; scrollbar-gutter: stable; scrollbar-width: thin; padding: 12px; display: flex; flex-direction: column; gap: 12px }
|
|
38
45
|
.issue-card { display: flex; flex: none; flex-direction: column; gap: 10px; width: 100%; min-width: 0; text-align: left; padding: 16px; border-radius: 12px }
|
|
39
46
|
.issue-card:hover, .issue-card[aria-current=true] { background: var(--paper) }
|
|
@@ -146,13 +153,24 @@ body.rail-collapsed .rail-list { padding-inline: 4px }
|
|
|
146
153
|
.toolbar { flex-wrap: wrap; gap: 8px }
|
|
147
154
|
.record-filters { gap: 8px; max-width: 100% }
|
|
148
155
|
.record-filters label { display: block; min-width: 0 }
|
|
149
|
-
|
|
156
|
+
/* Failure-only viewing is a visible two-state switch next to the title, not a dropdown, so the failure count shows
|
|
157
|
+
before anyone filters. */
|
|
158
|
+
.record-mode { display: inline-flex; flex-shrink: 0; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: white }
|
|
159
|
+
.record-mode button { display: inline-flex; align-items: center; gap: 4px; min-height: 26px; padding: 2px 10px; border: 0; border-radius: 0; background: transparent; color: var(--muted); font-size: 12px; white-space: nowrap }
|
|
160
|
+
.record-mode button + button { border-left: 1px solid var(--line) }
|
|
161
|
+
.record-mode button:hover:not(:disabled) { background: var(--tint) }
|
|
162
|
+
.record-mode button[aria-pressed=true] { background: var(--tint); color: var(--accent); font-weight: 600 }
|
|
163
|
+
.record-mode #record-failed[aria-pressed=true] { background: #fff2f1; color: #b12c21; box-shadow: inset 0 -2px #c0392b }
|
|
164
|
+
.record-failed-icon, .record-failed-count { color: #b12c21 }
|
|
165
|
+
.record-failed-count { font-weight: 600; font-variant-numeric: tabular-nums }
|
|
166
|
+
.record-mode button:disabled { opacity: 1; color: #9aa8b2 }
|
|
167
|
+
.record-mode button:disabled :is(.record-failed-icon, .record-failed-count) { color: inherit; font-weight: 400 }
|
|
150
168
|
#type-filter { width: 142px }
|
|
151
169
|
#trace-search { width: 208px }
|
|
152
170
|
.toolbar select:has(option:checked:not([value=""])) { border-color: #deb493; color: var(--accent) }
|
|
153
171
|
@container (max-width: 650px) {
|
|
154
172
|
.record-filters { display: grid; width: 100%; grid-template-columns: repeat(2,minmax(0,1fr)) }
|
|
155
|
-
.record-filters :is(#
|
|
173
|
+
.record-filters :is(#type-filter,#trace-search) { width: 100% }
|
|
156
174
|
.record-filters .search-label { grid-column: 1/-1 }
|
|
157
175
|
}
|
|
158
176
|
.stream { overflow: hidden; max-height: 100vh; max-height: 100dvh }
|