feat(integrations): declare which surface each client is, and its version (#7326)
This commit is contained in:
@@ -70,6 +70,38 @@ def test_portable_bundle_is_conformant_and_self_contained(tmp_path: Path) -> Non
|
||||
assert not any(path.is_symlink() for path in root.rglob("*"))
|
||||
|
||||
|
||||
def _harness_identity(root: Path) -> dict[str, str]:
|
||||
"""Read the generated core/_harness_id.py without importing it."""
|
||||
values: dict[str, str] = {}
|
||||
for line in (root / "core" / "_harness_id.py").read_text(encoding="utf-8").splitlines():
|
||||
if "=" in line and not line.lstrip().startswith("#"):
|
||||
name, _, raw = line.partition("=")
|
||||
values[name.strip()] = raw.strip().strip('"')
|
||||
return values
|
||||
|
||||
|
||||
def test_the_portable_bundle_declares_no_host_application(tmp_path: Path) -> None:
|
||||
"""It runs in whatever editor a user drops it into, so it cannot know the host.
|
||||
|
||||
X-Application is allowlisted server-side. A guessed value is silently dropped
|
||||
there, which is the worst outcome: the wire says we know the host and the
|
||||
stored event says we do not.
|
||||
"""
|
||||
identity = _harness_identity(build("mem0-agent-plugin", "portable", tmp_path / "portable"))
|
||||
|
||||
assert identity["PLATFORM_APPLICATION"] == ""
|
||||
# The PostHog-side label is still useful for grouping and stays populated.
|
||||
assert identity["HARNESS_ID"] == "coding-agent"
|
||||
assert identity["PLATFORM_SOURCE"] == "MEM0_PLUGIN"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("host", ["claude-code", "cursor", "codex", "kimi", "antigravity"])
|
||||
def test_a_native_bundle_names_the_host_it_was_built_for(host: str, tmp_path: Path) -> None:
|
||||
identity = _harness_identity(build(host, "native", tmp_path / host))
|
||||
|
||||
assert identity["PLATFORM_APPLICATION"] == host
|
||||
|
||||
|
||||
@pytest.mark.parametrize("host", ["claude-code", "cursor", "codex", "kimi", "antigravity"])
|
||||
def test_native_bundle_is_self_contained(host: str, tmp_path: Path) -> None:
|
||||
root = build(host, "native", tmp_path / host)
|
||||
|
||||
@@ -179,6 +179,33 @@ def test_source_tag_defaults_agree_between_the_two_modules():
|
||||
assert left == right == "KIMI_PLUGIN"
|
||||
|
||||
|
||||
def test_the_plugin_declares_its_surface_in_the_body_and_the_headers():
|
||||
"""Body and headers both, because only the body works on every backend."""
|
||||
core = _core_dir("claude-code-plugin")
|
||||
if not core.exists():
|
||||
pytest.skip("claude-code-plugin is not built in this tree")
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
out = _run(
|
||||
core,
|
||||
Path(tmp),
|
||||
"import json, memory_core\n"
|
||||
"h = memory_core.platform_headers('k')\n"
|
||||
"print(json.dumps({'source': h.get('X-Mem0-Source'),"
|
||||
" 'app': h.get('X-Application'),"
|
||||
" 'client': h.get('X-Mem0-Client'),"
|
||||
" 'auth': h.get('Authorization'),"
|
||||
" 'ctype': h.get('Content-Type')}))",
|
||||
)
|
||||
headers = json.loads(out)
|
||||
assert headers["source"] == "MEM0_PLUGIN"
|
||||
assert headers["app"] == "claude-code"
|
||||
assert headers["client"].startswith("mem0-plugin/")
|
||||
# The transport headers the three call sites relied on must survive.
|
||||
assert headers["auth"] == "Token k"
|
||||
assert headers["ctype"] == "application/json"
|
||||
|
||||
|
||||
def _session_start(core: Path, data_dir: Path) -> list[str]:
|
||||
"""Drive the real hook_runner session-start path and return lifecycle events."""
|
||||
recorded = "\n".join(
|
||||
|
||||
Reference in New Issue
Block a user