mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 22:37:29 +00:00
feat(agentad): AgentAd Marketplace PRD + reference exchange (M5)
Add the AgentBBS M5 "AgentAd marketplace" spec and a working reference
implementation built on the existing @logicsrc/schemas AgentAd contracts.
- docs/agentad-marketplace.md: two-sided exchange PRD (buy/sell sides,
match -> auction -> pace -> serve -> meter -> settle, CoinPay settlement,
AgentBBS as reference publisher, milestones M5.0-M5.5).
- packages/agentad (@logicsrc/agentad): reference exchange
- builders that emit schema-valid, always-disclosed ad/campaign/placement docs
- HMAC-signed, single-use impression/click tracking tokens
- AgentAdExchange: targeting/format/category matching, second-price auction,
budget pacing + daily caps, frequency capping, token-driven metering
- pluggable settlement (InMemorySettlement) that can't overspend escrow
- runtime validation against the canonical agentad-*.schema.json
- 22 vitest cases (builders, tokens, full serve/meter/settle lifecycle).
- Wire package into root build; link the PRD from README + docs/agentad.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0bca203527
commit
7d62e3b661
18 changed files with 1862 additions and 2 deletions
62
packages/agentad/src/builders.test.ts
Normal file
62
packages/agentad/src/builders.test.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { createAd, createCampaign, createPlacement, createAdRequest } from "./builders.js";
|
||||
import { validate } from "./validate.js";
|
||||
|
||||
describe("AgentAd builders", () => {
|
||||
it("builds a schema-valid, disclosed ad and always forces sponsored:true", () => {
|
||||
const ad = createAd({
|
||||
advertiser_did: "railway.app",
|
||||
campaign_id: "cmp-1",
|
||||
format: "json",
|
||||
title: "Ship your CLI in 60s",
|
||||
url: "https://railway.app/?ref=cl1s",
|
||||
pricing: { model: "cpc", bid: 0.5, currency: "USD" },
|
||||
machine_readable: { product: "railway" }
|
||||
});
|
||||
|
||||
expect(ad.type).toBe("agentad.ad");
|
||||
expect(ad.disclosure).toEqual({ sponsored: true, label: "Sponsored" });
|
||||
expect(validate("agentad-ad", ad).ok).toBe(true);
|
||||
});
|
||||
|
||||
it("honors a custom disclosure label and advertiser name", () => {
|
||||
const ad = createAd({
|
||||
advertiser_did: "acme.dev",
|
||||
format: "text",
|
||||
title: "Acme",
|
||||
url: "https://acme.dev",
|
||||
disclosure: { label: "Ad", advertiser_name: "Acme, Inc." }
|
||||
});
|
||||
expect(ad.disclosure.label).toBe("Ad");
|
||||
expect(ad.disclosure.advertiser_name).toBe("Acme, Inc.");
|
||||
expect(ad.disclosure.sponsored).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults a campaign to draft and validates", () => {
|
||||
const campaign = createCampaign({
|
||||
advertiser_did: "railway.app",
|
||||
name: "Launch",
|
||||
budget: { total: 100, currency: "USD" }
|
||||
});
|
||||
expect(campaign.status).toBe("draft");
|
||||
expect(validate("agentad-campaign", campaign).ok).toBe(true);
|
||||
});
|
||||
|
||||
it("builds valid placements and requests", () => {
|
||||
const placement = createPlacement({
|
||||
publisher_did: "agentbbs.sh",
|
||||
surface: "agent",
|
||||
accepted_formats: ["json"]
|
||||
});
|
||||
const request = createAdRequest({ placement_id: placement.id, consumer: "agent" });
|
||||
|
||||
expect(validate("agentad-placement", placement).ok).toBe(true);
|
||||
expect(validate("agentad-ad-request", request).ok).toBe(true);
|
||||
});
|
||||
|
||||
it("generates unique ids across calls", () => {
|
||||
const a = createPlacement({ publisher_did: "p.p", surface: "cli", accepted_formats: ["text"] });
|
||||
const b = createPlacement({ publisher_did: "p.p", surface: "cli", accepted_formats: ["text"] });
|
||||
expect(a.id).not.toBe(b.id);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue