feat: initialize resume agent with OfferPai sync

This commit is contained in:
Codex
2026-08-05 20:20:18 +08:00
commit 61ec750031
197 changed files with 33291 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
from __future__ import annotations
import json
from typing import Any
from fastapi.testclient import TestClient
BASE = "/ai-api/resume-agent"
def active_component(body: dict[str, Any]) -> dict[str, Any]:
turns = body.get("turns") or ([body["turn"]] if body.get("turn") else [])
for turn in reversed(turns):
for block in reversed(turn["blocks"]):
if block["type"] == "component" and block["lifecycle"] == "active":
return block
raise AssertionError("response has no active component")
def event(
client: TestClient,
session_id: str,
body: dict[str, Any],
event_name: str,
payload: dict[str, Any] | None = None,
headers: dict[str, str] | None = None,
):
block = active_component(body)
return client.post(
f"{BASE}/sessions/{session_id}/component-events",
json={"component_id": block["id"], "event": event_name, "payload": payload or {}},
headers=headers,
)
def start_manual_profile(
client: TestClient,
*,
job_type: str = "campus",
target_position: str | None = "Backend Engineer",
) -> tuple[str, dict[str, Any]]:
created = client.post(f"{BASE}/sessions", json={})
assert created.status_code == 201
body = created.json()
session_id = body["session_id"]
assert body["stage"] == "PRIVACY_CONSENT"
source = event(client, session_id, body, "accept", {"accepted": True})
assert source.status_code == 200
assert source.json()["stage"] == "RESUME_SOURCE_SELECT"
phone_selector = event(client, session_id, source.json(), "select", {"value": "manual"})
assert phone_selector.status_code == 200
assert phone_selector.json()["stage"] == "PHONE_SELECTION"
phone_input = event(client, session_id, phone_selector.json(), "select", {"source": "other"})
assert phone_input.status_code == 200
assert phone_input.json()["stage"] == "MANUAL_PHONE_INPUT"
personal = event(client, session_id, phone_input.json(), "submit", {"phone": "13800138000"})
assert personal.status_code == 200
assert personal.json()["stage"] == "PERSONAL_INFO"
job_selector = event(
client,
session_id,
personal.json(),
"submit",
{"name": "Zhang San", "email": "zhangsan@example.com", "city": "Shanghai"},
)
assert job_selector.status_code == 200
assert job_selector.json()["stage"] == "JOB_TYPE_SELECT"
target = event(client, session_id, job_selector.json(), "select", {"job_type": job_type})
assert target.status_code == 200
assert target.json()["stage"] == "TARGET_POSITION"
if target_position is None:
ready = event(client, session_id, target.json(), "skip")
else:
ready = event(client, session_id, target.json(), "submit", {"target_position": target_position})
assert ready.status_code == 200, ready.text
assert ready.json()["stage"] == "MINIMUM_READY"
return session_id, ready.json()
ANCHOR_CARD_VALUES = {
"school": "Example University",
"major": "Computer Science",
"degree": "Bachelor",
"start_date": "2021-09",
"end_date_or_present": "2025-06",
}
def fill_anchor(
client: TestClient,
session_id: str,
body: dict[str, Any],
values: dict[str, str],
) -> dict[str, Any]:
response = event(client, session_id, body, "submit", values)
assert response.status_code == 200, response.text
return response.json()
def campus_ready(client: TestClient) -> tuple[str, dict[str, Any]]:
return start_manual_profile(client, job_type="campus")
def test_privacy_precedes_resume_source_selection(client: TestClient) -> None:
created = client.post(f"{BASE}/sessions", json={})
session_id = created.json()["session_id"]
source = event(client, session_id, created.json(), "accept", {"accepted": True})
assert source.status_code == 200
body = source.json()
assert body["stage"] == "RESUME_SOURCE_SELECT"
options = active_component(body)["data"]["options"]
assert {option["value"] for option in options} == {"import", "manual"}
def test_manual_phone_is_strict_and_retryable(client: TestClient) -> None:
created = client.post(f"{BASE}/sessions", json={}).json()
session_id = created["session_id"]
source = event(client, session_id, created, "accept", {"accepted": True}).json()
phone_selector = event(client, session_id, source, "select", {"value": "manual"}).json()
phone_input = event(client, session_id, phone_selector, "select", {"source": "other"}).json()
invalid = event(client, session_id, phone_input, "submit", {"phone": "+8613800138000"})
assert invalid.status_code == 422
assert invalid.json()["error"]["code"] == "invalid_phone"
valid = event(client, session_id, phone_input, "submit", {"phone": "13900139000"})
assert valid.status_code == 200
assert valid.json()["stage"] == "PERSONAL_INFO"
def test_target_position_creates_a_basic_resume_without_core_experience(client: TestClient) -> None:
session_id, ready = start_manual_profile(client, job_type="social")
assert ready["gate"]["allowed"] is True
assert ready["missing_fields"] == []
created = client.post(f"{BASE}/sessions/{session_id}/create", json={"idempotency_key": "basic-resume"})
assert created.status_code == 200, created.text
result = created.json()
assert result["created"] is True
assert result["stage"] == "BUILDER_CONVERSATION"
assert result["resume"]["content"]["sections"] == []
def test_full_campus_creation_is_idempotent_and_masks_phone(client: TestClient) -> None:
session_id, ready = campus_ready(client)
first = client.post(f"{BASE}/sessions/{session_id}/create", json={"idempotency_key": "create-once"})
assert first.status_code == 200, first.text
result = first.json()
assert result["created"] is True
assert result["stage"] == "BUILDER_CONVERSATION"
assert result["resume"]["content"]["basics"]["masked_phone"] == "138****8000"
assert "13800138000" not in json.dumps(result, ensure_ascii=False)
second = client.post(f"{BASE}/sessions/{session_id}/create", json={"idempotency_key": "another-key"})
assert second.status_code == 200
assert second.json()["created"] is False
assert second.json()["resume_id"] == result["resume_id"]
def test_target_position_exploration_can_create_without_core_experience(client: TestClient) -> None:
session_id, ready = start_manual_profile(client, job_type="campus", target_position=None)
assert ready["stage"] == "MINIMUM_READY"
assert ready["gate"]["allowed"] is True
assert session_id