ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
@@ -0,0 +1,348 @@
#!/usr/bin/env python3
"""Fail-closed validator for retained historical 10-3 evidence of current Experiment 10-3."""
from __future__ import annotations
import argparse
import hashlib
import json
import re
from pathlib import Path
from typing import Any
TOOL_NAME = "initiate_phone_call_agent"
ARK_PROVIDER = "Volcengine ARK"
ARK_ENDPOINT = "https://ark.cn-beijing.volces.com/api/v3"
INPUT_NAMES = {"experiment_input.json"}
ARTIFACT_NAMES = {
"acceptance_report.json",
"decision.json",
"form_submission_receipt.json",
"message_timeline.json",
"raw_decision_request.json",
"raw_decision_response.json",
"validation_report.json",
}
SOURCE_NAMES = {
"browser.py",
"bus.py",
"decision.py",
"demo.py",
"models.py",
"orchestration.py",
"run_acceptance.py",
"validate_acceptance.py",
"voice.py",
"webrtc_channel.py",
}
CREDENTIAL_PATTERN = re.compile(
r"(?i)(?:sk-[A-Za-z0-9_-]{12,}|gho_[A-Za-z0-9_-]{12,}|"
r"github_pat_[A-Za-z0-9_-]{12,}|authorization.{0,16}bearer\s+[A-Za-z0-9._-]{12,})"
)
class ValidationFailure(RuntimeError):
"""Raised when retained evidence does not prove its claims."""
def _require(condition: bool, message: str) -> None:
if not condition:
raise ValidationFailure(message)
def _load_json(path: Path) -> dict[str, Any]:
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
raise ValidationFailure(f"cannot read JSON evidence {path.name}: {exc}") from exc
_require(isinstance(value, dict), f"{path.name} must contain a JSON object")
return value
def _sha256(path: Path) -> str:
try:
return hashlib.sha256(path.read_bytes()).hexdigest()
except OSError as exc:
raise ValidationFailure(f"cannot hash {path}: {exc}") from exc
def _validate_hash_map(
*,
expected_names: set[str],
hashes: Any,
base: Path,
label: str,
) -> None:
_require(isinstance(hashes, dict), f"manifest {label} must be an object")
names = set(hashes)
_require(names == expected_names, f"manifest {label} names differ: {sorted(names)}")
for name, expected in hashes.items():
_require(
isinstance(expected, str) and len(expected) == 64, f"invalid {label} hash for {name}"
)
_require(_sha256(base / name) == expected, f"{label} hash mismatch for {name}")
def _tool_call(response: dict[str, Any]) -> dict[str, Any]:
choices = response.get("choices")
_require(isinstance(choices, list) and len(choices) == 1, "raw response must have one choice")
choice = choices[0]
_require(
choice.get("finish_reason") == "tool_calls", "raw response did not finish with tool_calls"
)
message = choice.get("message", {})
calls = message.get("tool_calls")
_require(isinstance(calls, list) and len(calls) == 1, "raw response must have one tool call")
call = calls[0]
_require(call.get("type") == "function", "raw response tool call must be a function")
function = call.get("function", {})
_require(function.get("name") == TOOL_NAME, "raw response selected the wrong tool")
return function
def _normalized_required_info(
raw_arguments: dict[str, Any], decision: dict[str, Any]
) -> list[dict[str, Any]]:
discovered = decision.get("discovered_fields")
_require(isinstance(discovered, list), "normalized decision lacks discovered_fields")
by_name = {str(field.get("name", "")): field for field in discovered}
by_label = {str(field.get("label", "")).casefold(): field for field in discovered}
known = set(decision.get("known_fields", []))
normalized = []
for item in raw_arguments.get("required_info", []):
_require(isinstance(item, dict), "raw required_info entries must be objects")
candidate = by_name.get(str(item.get("name", ""))) or by_label.get(
str(item.get("label", "")).casefold()
)
_require(candidate is not None, "raw tool arguments reference an unknown field")
if candidate["name"] not in known and candidate not in normalized:
normalized.append(candidate)
return normalized
def validate_run(
run_dir: Path,
*,
source_root: Path | None = None,
require_validation_report: bool = True,
) -> dict[str, Any]:
"""Validate one retained run and return a deterministic validation report."""
run_dir = run_dir.resolve()
source_root = (source_root or Path(__file__).parent).resolve()
manifest = _load_json(run_dir / "manifest.json")
_require(manifest.get("schema_version") == 2, "manifest schema_version must be 2")
_require(manifest.get("experiment") == "10-3", "manifest experiment must be 10-3")
artifact_names = (
ARTIFACT_NAMES if require_validation_report else ARTIFACT_NAMES - {"validation_report.json"}
)
expected_run_names = {"manifest.json"} | INPUT_NAMES | artifact_names
actual_run_names = {path.name for path in run_dir.iterdir()}
_require(
actual_run_names == expected_run_names,
f"retained run files differ: {sorted(actual_run_names)}",
)
input_hashes = manifest.get("input_sha256")
_validate_hash_map(
expected_names=INPUT_NAMES,
hashes=input_hashes,
base=run_dir,
label="input_sha256",
)
_validate_hash_map(
expected_names=artifact_names,
hashes=manifest.get("artifact_sha256"),
base=run_dir,
label="artifact_sha256",
)
source_hashes = manifest.get("source_sha256")
_require(isinstance(source_hashes, dict), "manifest source_sha256 must be an object")
_require(set(source_hashes) == SOURCE_NAMES, "manifest source_sha256 names differ")
for name, expected in source_hashes.items():
_require(_sha256(source_root / name) == expected, f"source_sha256 hash mismatch for {name}")
_require(
re.fullmatch(r"[0-9a-f]{40}", str(manifest.get("git_head_at_run", ""))) is not None,
"manifest git_head_at_run is invalid",
)
experiment_input = _load_json(run_dir / "experiment_input.json")
raw_request = _load_json(run_dir / "raw_decision_request.json")
raw_response = _load_json(run_dir / "raw_decision_response.json")
decision = _load_json(run_dir / "decision.json")
acceptance = _load_json(run_dir / "acceptance_report.json")
form_receipt = _load_json(run_dir / "form_submission_receipt.json")
timeline = json.loads((run_dir / "message_timeline.json").read_text(encoding="utf-8"))
_require(raw_request.get("provider") == ARK_PROVIDER, "raw request is not an ARK request")
_require(raw_request.get("endpoint") == ARK_ENDPOINT, "raw request uses an unexpected endpoint")
_require(
raw_request.get("credential_fields_retained") == [],
"raw request retained credential fields",
)
request = raw_request.get("request", {})
_require(request.get("tool_choice") == "auto", "raw request did not use tool_choice=auto")
tools = request.get("tools")
_require(
isinstance(tools, list) and len(tools) == 1, "raw request must expose one optional tool"
)
_require(
tools[0].get("function", {}).get("name") == TOOL_NAME, "raw request tool schema differs"
)
_require(raw_response.get("provider") == ARK_PROVIDER, "raw response is not from ARK")
_require(decision.get("provider") == ARK_PROVIDER, "normalized decision is not from ARK")
latency = raw_response.get("latency_seconds")
_require(
isinstance(latency, (int, float)) and latency > 0, "raw response lacks positive latency"
)
response = raw_response.get("response", {})
_require(
response.get("id") == decision.get("provider_response_id"),
"response ID differs from decision",
)
_require(request.get("model") == decision.get("model"), "request model differs from decision")
_require(response.get("model") == decision.get("model"), "response model differs from decision")
usage = response.get("usage", {})
normalized_usage = {
key: usage[key]
for key in ("prompt_tokens", "completion_tokens", "total_tokens")
if key in usage
}
_require(
normalized_usage == decision.get("provider_usage"), "response usage differs from decision"
)
function = _tool_call(response)
try:
raw_arguments = json.loads(function["arguments"])
except (KeyError, TypeError, json.JSONDecodeError) as exc:
raise ValidationFailure("raw tool-call arguments are not valid JSON") from exc
_require(isinstance(raw_arguments, dict), "raw tool-call arguments must be an object")
_require(
set(raw_arguments) == {"purpose", "required_info"},
"raw tool-call arguments contain unexpected fields",
)
_require(isinstance(raw_arguments["required_info"], list), "raw required_info must be a list")
_require(decision.get("tool_called") == TOOL_NAME, "normalized decision records the wrong tool")
_require(
raw_arguments.get("purpose") == decision.get("purpose"), "raw purpose differs from decision"
)
_require(
_normalized_required_info(raw_arguments, decision) == decision.get("required_info"),
"raw tool-call arguments do not normalize exactly to decision.json",
)
messages = request.get("messages")
_require(
isinstance(messages, list) and len(messages) == 2, "raw request messages are incomplete"
)
try:
user_observation = json.loads(messages[1]["content"])
except (KeyError, TypeError, json.JSONDecodeError) as exc:
raise ValidationFailure("raw request user observation is invalid") from exc
_require(
user_observation.get("page_url") == experiment_input.get("page_url"),
"input page URL differs",
)
visible_decision_fields = [
{
"name": field["name"],
"label": field["label"],
"type": field["input_type"],
"required": field["required"],
"format_hint": field["format_hint"],
"options": field["options"],
}
for field in decision["discovered_fields"]
]
_require(
user_observation.get("form_fields") == visible_decision_fields,
"raw page observation differs",
)
_require(
experiment_input.get("form_html_sha256")
== hashlib.sha256(experiment_input.get("form_html", "").encode("utf-8")).hexdigest(),
"input form HTML hash differs",
)
_require(acceptance.get("overall_status") == "pass", "acceptance status is not pass")
gates = acceptance.get("gates", {})
_require(
gates and all(item.get("status") == "pass" for item in gates.values()),
"an acceptance gate failed",
)
_require(
manifest.get("acceptance")
== {
"overall_status": "pass",
"gate_count": len(gates),
"passed_gate_count": len(gates),
},
"manifest acceptance summary differs",
)
if require_validation_report:
_require(
manifest.get("retained_evidence_validation") == "pass",
"manifest retained-evidence status is not pass",
)
_require(isinstance(timeline, list), "message timeline must be a list")
collected = [row for row in timeline if row.get("type") == "info_collected"]
_require(collected, "message timeline has no collected fields")
_require(
all(row.get("payload", {}).get("value") == "<redacted>" for row in collected),
"participant values are not redacted",
)
_require(
acceptance.get("webrtc_receipt", {}).get("raw_audio_retained") is False,
"raw audio retained",
)
_require(
acceptance.get("webrtc_receipt", {}).get("transcripts_retained") is False,
"transcripts retained",
)
_require(
experiment_input.get("participant_values_retained") is False, "input claims values retained"
)
_require(form_receipt.get("raw_values_retained") is False, "form receipt retained raw values")
retained_text = "\n".join(
path.read_text(encoding="utf-8") for path in sorted(run_dir.iterdir()) if path.is_file()
)
_require(
not CREDENTIAL_PATTERN.search(retained_text), "retained evidence contains a credential"
)
result = {
"schema_version": 1,
"experiment": "10-3",
"status": "pass",
"checks": {
"source_hashes": "pass",
"artifact_hashes": "pass",
"input_hashes": "pass",
"raw_ark_request_tool_choice_auto": "pass",
"raw_ark_response_metadata": "pass",
"raw_arguments_normalize_to_decision": "pass",
"participant_privacy": "pass",
"acceptance_gates": "pass",
},
}
if require_validation_report:
_require(
_load_json(run_dir / "validation_report.json") == result,
"retained validation report differs from recomputed result",
)
return result
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("run_dir", type=Path)
parser.add_argument("--source-root", type=Path, default=Path(__file__).parent)
args = parser.parse_args()
report = validate_run(args.run_dir, source_root=args.source_root)
print(json.dumps(report, ensure_ascii=False, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())