91 lines
6.0 KiB
Python
91 lines
6.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Built-in agent: UI copy edits (logo/headline/subtitle/footer/chips/bullets). No server or model needed."""
|
|
import json, os, re, sys
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
os.environ.pop("AGENT_MARKET_LLM_API_KEY_FILE", None)
|
|
from market.theme import parse_look_command
|
|
from market.copyedit import DEFAULT_COPY
|
|
from market import agent
|
|
|
|
results = []
|
|
def check(name, ok, d=""):
|
|
results.append(bool(ok)); print(("PASS " if ok else "FAIL ") + name + (f" [{d}]" if d else ""))
|
|
|
|
def copy_of(text, theme=None):
|
|
r = parse_look_command(text, theme or {})
|
|
return (r[0], (r[1] or {}).get("copy")) if r else (None, None)
|
|
|
|
LOGO = [
|
|
"replace agent market to new internet on the top left corner", # the user's exact phrasing
|
|
"change Agent Market to New Internet in the top left", "rename the logo to New Internet", "call the site New Internet",
|
|
"top left should say New Internet", "replace Agent Market with New Internet", "change the top left text to New Internet",
|
|
"make the logo say new internet", "I want the header to say New Internet", "logo: New Internet", "use New Internet as the site name",
|
|
"change the brand to new internet please", "rename the website to new internet", "name the site new internet",
|
|
"change agent market into new internet", "swap Agent Market for New Internet", 'replace "Agent Market" with "New Internet"',
|
|
"Please change the site name to New Internet.", "the top-left corner should read New Internet",
|
|
]
|
|
for p in LOGO:
|
|
reply, c = copy_of(p)
|
|
check(f"logo: {p}", c == {"logo": "New Internet"}, f"{c} / {reply}")
|
|
|
|
cases = [
|
|
("change the title to Hello World", {"headline": "Hello World"}),
|
|
("change the headline to Retro vibes", {"headline": "Retro vibes"}),
|
|
("replace A marketplace you can just talk to. with Buy and sell anything nearby", {"headline": "Buy and sell anything nearby"}),
|
|
("replace marketplace with bazaar", {"headline": "A bazaar you can just talk to."}),
|
|
("set the subtitle to Fast and free", {"subhead": "Fast and free"}),
|
|
("swap the tagline with Shop by chatting", {"subhead": "Shop by chatting"}),
|
|
("swap the footer to Made for testing", {"footer": "Made for testing"}),
|
|
("replace market with Internet in the logo", {"logo": "Agent Internet"}),
|
|
("the top left should read NEW INTERNET", {"logo": "NEW INTERNET"}),
|
|
("change the logo to new Internet", {"logo": "new Internet"}), # mixed case typed -> kept exactly
|
|
]
|
|
for p, want in cases:
|
|
reply, c = copy_of(p)
|
|
check(f"copy: {p}", c == want, f"{c}")
|
|
reply, c = copy_of("rename Tutoring to Lessons")
|
|
check("chip label edited, emoji + action kept", c and c["chips"][1] == {"label": "📐 Lessons", "say": "find tutoring services"} and c["chips"][3].get("event") == "sell", c and c["chips"][:4])
|
|
reply, c = copy_of("replace $0 fee with no fee")
|
|
check("bullet edited by find-and-replace", c and c["bullets"][1].startswith("no fee when you meet"), c)
|
|
reply, c = copy_of("replace New Internet with Agent Hub", {"copy": {"logo": "New Internet"}})
|
|
check("find-and-replace uses the visitor's current text", c == {"logo": "Agent Hub"}, c)
|
|
|
|
# unclear -> says what it understood + closest option, never silently nothing / listings
|
|
r = parse_look_command("replace agent with robot", {})
|
|
check("ambiguous text -> asks where", r and r[1] is None and "more than one place" in r[0], r and r[0])
|
|
r = parse_look_command("replace agnet markt with New Internet", {})
|
|
check("typo -> offers the closest slot", r and r[1] is None and "Closest is the top-left logo text" in r[0], r and r[0])
|
|
r = parse_look_command("replace foo bar with baz", {})
|
|
check("not found -> lists what can be edited", r and r[1] is None and "can't find" in r[0], r and r[0])
|
|
|
|
# no hijacking of look commands, search or selling
|
|
for p, key in (("change the background to a sunset gradient", "background"), ("switch to light mode with a green accent", "mode"),
|
|
("use a serif font and make the text bigger", "font"), ("replace the background with blue", "background"),
|
|
("move the chat to the left", "chat"), ("hide the bullet points", "sections")):
|
|
r = parse_look_command(p, {})
|
|
check(f"look command still works: {p}", r and r[1] and key in r[1] and "copy" not in r[1], r and r[1])
|
|
for p in ("show me bikes", "change my order to cash", "I'd like to sell my lamp for $20", "find tutoring services"):
|
|
check(f"not a copy edit: {p}", parse_look_command(p, {}) is None)
|
|
r = parse_look_command("make it look retro", {})
|
|
check("preset still works", r and r[1] == {"preset": "retro"})
|
|
r = parse_look_command("use the Inter font", {})
|
|
check("font names are word-bounded (Inter font still works)", r and r[1].get("font") == "Inter")
|
|
check("'internet' is not the Inter font", "font" not in (parse_look_command("make the headline say internet rocks", {})[1] or {}))
|
|
|
|
# end to end through the built-in agent (what /api/chat returns when no model answers)
|
|
out = agent.fallback_agent(None, "replace agent market to new internet on the top left corner", [], "t", {})
|
|
check("built-in agent: user's exact phrasing -> set_theme copy.logo, no listings",
|
|
[a["type"] for a in out["actions"]] == ["set_theme"] and out["actions"][0]["payload"]["copy"] == {"logo": "New Internet"}, out["reply"])
|
|
out = agent.fallback_agent(None, "replace agent with robot", [], "t", {})
|
|
check("built-in agent: unclear edit -> explanation only", out["actions"] == [] and "agent" in out["reply"])
|
|
|
|
# server copy defaults match the React app's defaults
|
|
app = open(os.path.join(os.path.dirname(__file__), "..", "web", "src", "App.tsx"), encoding="utf-8").read()
|
|
ok = all(s in app for s in (DEFAULT_COPY["logo"], DEFAULT_COPY["headline"], DEFAULT_COPY["subhead"]) ) and \
|
|
all(c["label"] in app for c in DEFAULT_COPY["chips"]) and all(b.split("{fee}% ")[-1] in app for b in DEFAULT_COPY["bullets"])
|
|
check("DEFAULT_COPY in sync with web/src/App.tsx", ok)
|
|
check("model prompt explains top-left = logo and includes PAGE_TEXT", "TOP-LEFT" in agent.UI_SCHEMA and '"logo": "Agent Market"' in agent._page_text("{}"))
|
|
|
|
print(f"\n{sum(results)}/{len(results)} passed")
|
|
sys.exit(0 if all(results) else 1)
|