From 60ba38a57519c233691ad3c742bffb13ef6f4c8d Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Thu, 11 Jun 2026 10:02:34 +0000 Subject: [PATCH 1/2] Add AgentAd ad schemas as a LogicSRC primitive AgentAd is a disclosed, agent-readable advertising contract for CLI tools and AI agents. LogicSRC owns the canonical schemas; cl1s.tech is the reference network built on them. - packages/schemas: agentad-{ad,placement,ad-request,ad-response, impression,click,campaign} schemas (id under schemas.logicsrc.com) + ad/placement fixtures, exported from @logicsrc/schemas - packages/validators: register the 7 agentad kinds, wire fixture validation, add tests (disclosure.sponsored must be true) - docs/agentad.md: the AgentAd spec - README: list AgentAd under v1 priorities Validators build clean; all fixtures validate; vitest 4/4 green. Co-Authored-By: Claude Opus 4.8 --- README.md | 1 + docs/agentad.md | 65 +++++++++++++++ packages/schemas/fixtures/agentad-ad.yaml | 33 ++++++++ .../schemas/fixtures/agentad-placement.yaml | 21 +++++ packages/schemas/package.json | 11 ++- .../schemas/agentad-ad-request.schema.json | 32 ++++++++ .../schemas/agentad-ad-response.schema.json | 31 ++++++++ .../schemas/schemas/agentad-ad.schema.json | 79 +++++++++++++++++++ .../schemas/agentad-campaign.schema.json | 40 ++++++++++ .../schemas/schemas/agentad-click.schema.json | 23 ++++++ .../schemas/agentad-impression.schema.json | 18 +++++ .../schemas/agentad-placement.schema.json | 46 +++++++++++ packages/validators/package.json | 2 +- packages/validators/src/cli.ts | 2 +- packages/validators/src/index.test.ts | 23 ++++++ packages/validators/src/schemas.ts | 16 +++- 16 files changed, 438 insertions(+), 5 deletions(-) create mode 100644 docs/agentad.md create mode 100644 packages/schemas/fixtures/agentad-ad.yaml create mode 100644 packages/schemas/fixtures/agentad-placement.yaml create mode 100644 packages/schemas/schemas/agentad-ad-request.schema.json create mode 100644 packages/schemas/schemas/agentad-ad-response.schema.json create mode 100644 packages/schemas/schemas/agentad-ad.schema.json create mode 100644 packages/schemas/schemas/agentad-campaign.schema.json create mode 100644 packages/schemas/schemas/agentad-click.schema.json create mode 100644 packages/schemas/schemas/agentad-impression.schema.json create mode 100644 packages/schemas/schemas/agentad-placement.schema.json diff --git a/README.md b/README.md index 7b7b468..80cf8b0 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ It provides read-only resources for docs and schemas, validation/example tools, ## v1.0.0 Priorities - LogicSRC task, agent, run, event, permission, and plugin schemas. +- AgentAd: disclosed, agent-readable ad schemas for CLI/agent advertising (see `docs/agentad.md`); cl1s.tech is the reference network. - LogicSRC CLI, SDK, TUI, PWA, MCP, and curl-compatible API conventions. - CommandBoard.run reference implementation. - Monorepo-maintained plugin system. diff --git a/docs/agentad.md b/docs/agentad.md new file mode 100644 index 0000000..51562c8 --- /dev/null +++ b/docs/agentad.md @@ -0,0 +1,65 @@ +# AgentAd + +AgentAd is a LogicSRC primitive family for advertising to command-line tools and +AI agents. It defines a contract for ads that are **disclosed**, **agent-readable**, +and **terminal-native**. + +LogicSRC owns the AgentAd schemas; **cl1s.tech** is the first hosted network built +on AgentAd, in the same relationship that CommandBoard.run has to the core LogicSRC +primitives. External products may consume the AgentAd contracts directly. + +## Principles + +1. **Disclosure is mandatory.** Every ad carries `disclosure.sponsored: true` and a + visible label. An AgentAd unit must never be presentable as organic output. +2. **Agent-readable.** Ads may carry a `machine_readable` payload so an autonomous + agent can reason about the offer instead of scraping rendered text. +3. **Terminal-native formats.** `text`, `markdown`, `ansi`, `banner`, `json`. +4. **Publisher control.** Placements declare accepted formats, dimensions, + frequency caps, and category blocks. + +## Primitives + +| Type | Schema | Validator kind | Purpose | +| --- | --- | --- | --- | +| `agentad.ad` | `agentad-ad.schema.json` | `agentad-ad` | A single ad unit | +| `agentad.placement` | `agentad-placement.schema.json` | `agentad-placement` | A slot in a CLI/agent | +| `agentad.ad_request` | `agentad-ad-request.schema.json` | `agentad-ad-request` | Request to fill a placement | +| `agentad.ad_response` | `agentad-ad-response.schema.json` | `agentad-ad-response` | Filled ads + tracking tokens | +| `agentad.impression` | `agentad-impression.schema.json` | `agentad-impression` | Confirmed display | +| `agentad.click` | `agentad-click.schema.json` | `agentad-click` | Click / conversion | +| `agentad.campaign` | `agentad-campaign.schema.json` | `agentad-campaign` | Advertiser campaign | + +Schemas are published from `@logicsrc/schemas` and identified under +`https://schemas.logicsrc.com/`. + +## Validate + +```bash +npm --workspace @logicsrc/validators run build +node packages/validators/dist/cli.js agentad-ad packages/schemas/fixtures/agentad-ad.yaml +node packages/validators/dist/cli.js agentad-placement packages/schemas/fixtures/agentad-placement.yaml +``` + +## Human vs. agent consumers + +The `consumer` field on a request changes how an ad is delivered: + +- `human` → rendered string with an `[Sponsored]` header. +- `agent` → structured view with an explicit `sponsored: true` flag and the + `machine_readable` payload, e.g. + +```json +{ + "sponsored": true, + "advertiser": "Railway", + "title": "Ship your CLI to production in 60 seconds", + "url": "https://railway.app/?ref=cl1s", + "data": { "product": "railway", "install": "npm i -g @railway/cli" } +} +``` + +## Reference network + +[cl1s.tech](https://github.com/profullstack/cl1s.tech) is the hosted AgentAd +network: SDK, CLI, and ad-serving service that consume these schemas. diff --git a/packages/schemas/fixtures/agentad-ad.yaml b/packages/schemas/fixtures/agentad-ad.yaml new file mode 100644 index 0000000..6d72c22 --- /dev/null +++ b/packages/schemas/fixtures/agentad-ad.yaml @@ -0,0 +1,33 @@ +type: agentad.ad +version: "0.1" +id: deploy-faster-railway +campaign_id: railway-q3 +advertiser_did: railway.coinpay +format: markdown +title: Ship your CLI to production in 60 seconds +body: Railway deploys any Node, Bun, or Go service straight from your terminal. No YAML wrangling. +url: https://railway.app/?ref=cl1s +cta: Deploy now +disclosure: + sponsored: true + label: Sponsored + advertiser_name: Railway +machine_readable: + product: railway + category: infrastructure + install: "npm i -g @railway/cli" +targeting: + surfaces: + - cli + - agent + keywords: + - deploy + - hosting + - infrastructure + tools: + - claude-code + - gh +pricing: + model: cpc + bid: 0.4 + currency: USDC diff --git a/packages/schemas/fixtures/agentad-placement.yaml b/packages/schemas/fixtures/agentad-placement.yaml new file mode 100644 index 0000000..8f88df4 --- /dev/null +++ b/packages/schemas/fixtures/agentad-placement.yaml @@ -0,0 +1,21 @@ +type: agentad.placement +version: "0.1" +id: cli-footer-slot +publisher_did: mytool.coinpay +surface: cli +accepted_formats: + - text + - ansi + - json +dimensions: + max_width: 80 + max_lines: 4 +context_tags: + - devtools + - deploy +frequency_cap: + max_per_session: 1 + max_per_day: 5 +block_categories: + - gambling + - crypto-tokens diff --git a/packages/schemas/package.json b/packages/schemas/package.json index 8cde0d2..fbc50ec 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -1,7 +1,7 @@ { "name": "@logicsrc/schemas", "version": "0.1.0", - "description": "LogicSRC JSON schemas for tasks, agents, runs, events, and plugins.", + "description": "LogicSRC JSON schemas for tasks, agents, runs, events, plugins, and the AgentAd ad standard.", "type": "module", "exports": { "./task": "./schemas/logicsrc-task.schema.json", @@ -14,7 +14,14 @@ "./account-grant": "./schemas/logicsrc-account-grant.schema.json", "./account-audit-event": "./schemas/logicsrc-account-audit-event.schema.json", "./email-message": "./schemas/logicsrc-email-message.schema.json", - "./social-post": "./schemas/logicsrc-social-post.schema.json" + "./social-post": "./schemas/logicsrc-social-post.schema.json", + "./agentad-ad": "./schemas/agentad-ad.schema.json", + "./agentad-placement": "./schemas/agentad-placement.schema.json", + "./agentad-ad-request": "./schemas/agentad-ad-request.schema.json", + "./agentad-ad-response": "./schemas/agentad-ad-response.schema.json", + "./agentad-impression": "./schemas/agentad-impression.schema.json", + "./agentad-click": "./schemas/agentad-click.schema.json", + "./agentad-campaign": "./schemas/agentad-campaign.schema.json" }, "files": [ "schemas" diff --git a/packages/schemas/schemas/agentad-ad-request.schema.json b/packages/schemas/schemas/agentad-ad-request.schema.json new file mode 100644 index 0000000..66b1f96 --- /dev/null +++ b/packages/schemas/schemas/agentad-ad-request.schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-ad-request.schema.json", + "title": "AgentAd Ad Request", + "description": "A request from a CLI/agent for an ad to fill a placement, with optional runtime context for relevance.", + "type": "object", + "required": ["type", "version", "placement_id"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.ad_request" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "placement_id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "publisher_did": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.[a-z0-9][a-z0-9._-]*$" }, + "consumer": { + "type": "string", + "enum": ["human", "agent"], + "description": "Who will read the ad. Agents SHOULD receive machine_readable payloads and clear disclosure." + }, + "context": { + "type": "object", + "additionalProperties": false, + "properties": { + "tool": { "type": "string", "description": "Host tool identifier, e.g. 'claude-code'." }, + "keywords": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }, + "language": { "type": "string" }, + "locale": { "type": "string" } + } + }, + "format_override": { "type": "string", "enum": ["text", "markdown", "ansi", "banner", "json"] }, + "count": { "type": "integer", "minimum": 1, "maximum": 10, "default": 1 } + } +} diff --git a/packages/schemas/schemas/agentad-ad-response.schema.json b/packages/schemas/schemas/agentad-ad-response.schema.json new file mode 100644 index 0000000..049debd --- /dev/null +++ b/packages/schemas/schemas/agentad-ad-response.schema.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-ad-response.schema.json", + "title": "AgentAd Ad Response", + "description": "The network's response to an ad request: zero or more filled ads plus signed tracking tokens for impression/click events.", + "type": "object", + "required": ["type", "version", "request_id", "ads"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.ad_response" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "request_id": { "type": "string", "minLength": 1 }, + "ads": { + "type": "array", + "items": { + "type": "object", + "required": ["ad", "impression_token"], + "additionalProperties": false, + "properties": { + "ad": { "type": "object", "description": "An agentad.ad document; validate separately against agentad-ad.schema.json." }, + "impression_token": { "type": "string", "minLength": 1, "description": "Opaque token to confirm the impression and to mint a click token." }, + "rendered": { "type": "string", "description": "Server-rendered representation in the requested format." } + } + } + }, + "no_fill_reason": { + "type": "string", + "enum": ["no_inventory", "frequency_capped", "blocked_category", "invalid_request"] + } + } +} diff --git a/packages/schemas/schemas/agentad-ad.schema.json b/packages/schemas/schemas/agentad-ad.schema.json new file mode 100644 index 0000000..843c79d --- /dev/null +++ b/packages/schemas/schemas/agentad-ad.schema.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-ad.schema.json", + "title": "AgentAd Ad", + "description": "A single advertising unit served to CLI tools and AI agents. Ads MUST be disclosed and SHOULD carry a machine-readable payload so agents can reason about them.", + "type": "object", + "required": ["type", "version", "id", "advertiser_did", "format", "title", "url", "disclosure"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.ad" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "id": { "$ref": "#/$defs/id" }, + "campaign_id": { "$ref": "#/$defs/id" }, + "advertiser_did": { "$ref": "#/$defs/did" }, + "format": { + "type": "string", + "enum": ["text", "markdown", "ansi", "banner", "json"], + "description": "Render format. 'json' is the agent-native structured format; 'ansi'/'banner' target human CLI surfaces." + }, + "title": { "type": "string", "minLength": 1, "maxLength": 120 }, + "body": { "type": "string", "maxLength": 2000 }, + "url": { "type": "string", "format": "uri" }, + "cta": { "type": "string", "maxLength": 60, "description": "Call to action label, e.g. 'Install' or 'Read docs'." }, + "disclosure": { + "type": "object", + "description": "Transparency contract. Every ad is labeled as sponsored so humans and agents can distinguish it from organic output.", + "required": ["sponsored", "label"], + "additionalProperties": false, + "properties": { + "sponsored": { "const": true }, + "label": { "type": "string", "minLength": 1, "maxLength": 40, "default": "Sponsored" }, + "advertiser_name": { "type": "string", "maxLength": 120 } + } + }, + "machine_readable": { + "type": "object", + "description": "Optional structured payload an agent can parse instead of (or alongside) the rendered text.", + "additionalProperties": true + }, + "targeting": { "$ref": "#/$defs/targeting" }, + "media": { + "type": "object", + "additionalProperties": false, + "properties": { + "ansi_art": { "type": "string", "description": "Pre-rendered ANSI/ASCII art for banner format." }, + "icon": { "type": "string", "format": "uri" } + } + }, + "pricing": { + "type": "object", + "additionalProperties": false, + "properties": { + "model": { "type": "string", "enum": ["cpm", "cpc", "cpa", "flat"] }, + "bid": { "type": "number", "minimum": 0 }, + "currency": { "type": "string", "minLength": 2, "maxLength": 12 } + } + }, + "expires_at": { "type": "string", "format": "date-time" } + }, + "$defs": { + "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$", "minLength": 1, "maxLength": 64 }, + "did": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.[a-z0-9][a-z0-9._-]*$" }, + "targeting": { + "type": "object", + "additionalProperties": false, + "properties": { + "surfaces": { + "type": "array", + "items": { "type": "string", "enum": ["cli", "tui", "agent", "ci"] }, + "uniqueItems": true + }, + "keywords": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true }, + "tools": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true, "description": "Host CLI/agent identifiers to target, e.g. 'claude-code', 'gh'." }, + "languages": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }, + "exclude_keywords": { "type": "array", "items": { "type": "string" }, "uniqueItems": true } + } + } + } +} diff --git a/packages/schemas/schemas/agentad-campaign.schema.json b/packages/schemas/schemas/agentad-campaign.schema.json new file mode 100644 index 0000000..dbca763 --- /dev/null +++ b/packages/schemas/schemas/agentad-campaign.schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-campaign.schema.json", + "title": "AgentAd Campaign", + "description": "An advertiser campaign grouping one or more ads under a shared budget, schedule, and targeting policy.", + "type": "object", + "required": ["type", "version", "id", "advertiser_did", "name", "budget"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.campaign" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$", "minLength": 1, "maxLength": 64 }, + "advertiser_did": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.[a-z0-9][a-z0-9._-]*$" }, + "name": { "type": "string", "minLength": 1, "maxLength": 120 }, + "status": { "type": "string", "enum": ["draft", "active", "paused", "completed"], "default": "draft" }, + "budget": { + "type": "object", + "required": ["total", "currency"], + "additionalProperties": false, + "properties": { + "total": { "type": "number", "minimum": 0 }, + "daily_cap": { "type": "number", "minimum": 0 }, + "currency": { "type": "string", "minLength": 2, "maxLength": 12 } + } + }, + "schedule": { + "type": "object", + "additionalProperties": false, + "properties": { + "start_at": { "type": "string", "format": "date-time" }, + "end_at": { "type": "string", "format": "date-time" } + } + }, + "ad_ids": { + "type": "array", + "items": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "uniqueItems": true + } + } +} diff --git a/packages/schemas/schemas/agentad-click.schema.json b/packages/schemas/schemas/agentad-click.schema.json new file mode 100644 index 0000000..dc04c71 --- /dev/null +++ b/packages/schemas/schemas/agentad-click.schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-click.schema.json", + "title": "AgentAd Click", + "description": "A consumer action on an ad (a click, install, or conversion). For agents, 'action' records the structured intent taken.", + "type": "object", + "required": ["type", "version", "click_token", "ad_id", "occurred_at"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.click" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "click_token": { "type": "string", "minLength": 1 }, + "ad_id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "placement_id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "action": { + "type": "string", + "enum": ["click", "open_url", "copy_command", "install", "convert"], + "default": "click" + }, + "consumer": { "type": "string", "enum": ["human", "agent"] }, + "occurred_at": { "type": "string", "format": "date-time" } + } +} diff --git a/packages/schemas/schemas/agentad-impression.schema.json b/packages/schemas/schemas/agentad-impression.schema.json new file mode 100644 index 0000000..9ff006d --- /dev/null +++ b/packages/schemas/schemas/agentad-impression.schema.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-impression.schema.json", + "title": "AgentAd Impression", + "description": "A confirmed display of an ad. Recorded only after the ad was actually rendered to the consumer.", + "type": "object", + "required": ["type", "version", "impression_token", "ad_id", "occurred_at"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.impression" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "impression_token": { "type": "string", "minLength": 1 }, + "ad_id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "placement_id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, + "consumer": { "type": "string", "enum": ["human", "agent"] }, + "occurred_at": { "type": "string", "format": "date-time" } + } +} diff --git a/packages/schemas/schemas/agentad-placement.schema.json b/packages/schemas/schemas/agentad-placement.schema.json new file mode 100644 index 0000000..d01f5f8 --- /dev/null +++ b/packages/schemas/schemas/agentad-placement.schema.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.logicsrc.com/agentad-placement.schema.json", + "title": "AgentAd Placement", + "description": "A slot registered by a publisher (a CLI tool or agent) where AgentAd units may be rendered.", + "type": "object", + "required": ["type", "version", "id", "publisher_did", "surface", "accepted_formats"], + "additionalProperties": false, + "properties": { + "type": { "const": "agentad.placement" }, + "version": { "type": "string", "pattern": "^\\d+\\.\\d+(\\.\\d+)?$" }, + "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$", "minLength": 1, "maxLength": 64 }, + "publisher_did": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.[a-z0-9][a-z0-9._-]*$" }, + "surface": { "type": "string", "enum": ["cli", "tui", "agent", "ci"] }, + "accepted_formats": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "enum": ["text", "markdown", "ansi", "banner", "json"] }, + "uniqueItems": true + }, + "dimensions": { + "type": "object", + "additionalProperties": false, + "properties": { + "max_width": { "type": "integer", "minimum": 1, "description": "Max columns for text/ansi rendering." }, + "max_lines": { "type": "integer", "minimum": 1 } + } + }, + "context_tags": { + "type": "array", + "items": { "type": "string", "minLength": 1 }, + "uniqueItems": true, + "description": "Keywords describing the host context, used for relevance matching." + }, + "frequency_cap": { + "type": "object", + "additionalProperties": false, + "properties": { + "max_per_session": { "type": "integer", "minimum": 0 }, + "max_per_day": { "type": "integer", "minimum": 0 } + } + }, + "allow_categories": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }, + "block_categories": { "type": "array", "items": { "type": "string" }, "uniqueItems": true } + } +} diff --git a/packages/validators/package.json b/packages/validators/package.json index a8ff0ea..6d5577b 100644 --- a/packages/validators/package.json +++ b/packages/validators/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "tsc -p tsconfig.json", "test": "vitest run src", - "validate:fixtures": "node dist/cli.js task ../schemas/fixtures/task.yaml && node dist/cli.js agent ../schemas/fixtures/agent.yaml" + "validate:fixtures": "node dist/cli.js task ../schemas/fixtures/task.yaml && node dist/cli.js agent ../schemas/fixtures/agent.yaml && node dist/cli.js agentad-ad ../schemas/fixtures/agentad-ad.yaml && node dist/cli.js agentad-placement ../schemas/fixtures/agentad-placement.yaml" }, "dependencies": { "ajv": "^8.17.1", diff --git a/packages/validators/src/cli.ts b/packages/validators/src/cli.ts index 786133b..150bfe5 100644 --- a/packages/validators/src/cli.ts +++ b/packages/validators/src/cli.ts @@ -7,7 +7,7 @@ function main(argv: string[]) { const [, , kindArg, fileArg] = argv; if (!kindArg || !fileArg) { - console.error("Usage: logicsrc-validate "); + console.error("Usage: logicsrc-validate "); process.exitCode = 2; return; } diff --git a/packages/validators/src/index.test.ts b/packages/validators/src/index.test.ts index 76304b4..c900fb0 100644 --- a/packages/validators/src/index.test.ts +++ b/packages/validators/src/index.test.ts @@ -25,4 +25,27 @@ describe("LogicSRC validators", () => { expect(result.ok).toBe(false); }); + + it("validates the AgentAd ad fixture", () => { + const testDir = dirname(fileURLToPath(import.meta.url)); + const file = resolve(testDir, "../../schemas/fixtures/agentad-ad.yaml"); + const data = parseDocument(readFileSync(file, "utf8"), file); + + expect(validate("agentad-ad", data).ok).toBe(true); + }); + + it("rejects an AgentAd ad that is not disclosed as sponsored", () => { + const result = validate("agentad-ad", { + type: "agentad.ad", + version: "0.1", + id: "undisclosed", + advertiser_did: "acme.coinpay", + format: "text", + title: "Buy now", + url: "https://example.com", + disclosure: { sponsored: false, label: "Sponsored" } + }); + + expect(result.ok).toBe(false); + }); }); diff --git a/packages/validators/src/schemas.ts b/packages/validators/src/schemas.ts index b8f026c..ac3e801 100644 --- a/packages/validators/src/schemas.ts +++ b/packages/validators/src/schemas.ts @@ -9,6 +9,13 @@ import pluginSchema from "../../schemas/schemas/logicsrc-plugin.schema.json" wit import runSchema from "../../schemas/schemas/logicsrc-run.schema.json" with { type: "json" }; import socialPostSchema from "../../schemas/schemas/logicsrc-social-post.schema.json" with { type: "json" }; import taskSchema from "../../schemas/schemas/logicsrc-task.schema.json" with { type: "json" }; +import agentadAdSchema from "../../schemas/schemas/agentad-ad.schema.json" with { type: "json" }; +import agentadPlacementSchema from "../../schemas/schemas/agentad-placement.schema.json" with { type: "json" }; +import agentadAdRequestSchema from "../../schemas/schemas/agentad-ad-request.schema.json" with { type: "json" }; +import agentadAdResponseSchema from "../../schemas/schemas/agentad-ad-response.schema.json" with { type: "json" }; +import agentadImpressionSchema from "../../schemas/schemas/agentad-impression.schema.json" with { type: "json" }; +import agentadClickSchema from "../../schemas/schemas/agentad-click.schema.json" with { type: "json" }; +import agentadCampaignSchema from "../../schemas/schemas/agentad-campaign.schema.json" with { type: "json" }; export const schemas = { agent: agentSchema, @@ -21,7 +28,14 @@ export const schemas = { plugin: pluginSchema, run: runSchema, "social-post": socialPostSchema, - task: taskSchema + task: taskSchema, + "agentad-ad": agentadAdSchema, + "agentad-placement": agentadPlacementSchema, + "agentad-ad-request": agentadAdRequestSchema, + "agentad-ad-response": agentadAdResponseSchema, + "agentad-impression": agentadImpressionSchema, + "agentad-click": agentadClickSchema, + "agentad-campaign": agentadCampaignSchema } as const; export type SchemaKind = keyof typeof schemas; From 9d0919b1db1afae34fefb7577fd9add2b0ade03b Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Thu, 11 Jun 2026 10:44:58 +0000 Subject: [PATCH 2/2] Prepare @logicsrc/schemas for npm publish Add license, repository, homepage, keywords, publishConfig (public), and a package README covering both the logicsrc-* core schemas and the agentad-* family. Co-Authored-By: Claude Opus 4.8 --- packages/schemas/README.md | 34 ++++++++++++++++++++++++++++++++++ packages/schemas/package.json | 11 +++++++++++ 2 files changed, 45 insertions(+) create mode 100644 packages/schemas/README.md diff --git a/packages/schemas/README.md b/packages/schemas/README.md new file mode 100644 index 0000000..ee9a606 --- /dev/null +++ b/packages/schemas/README.md @@ -0,0 +1,34 @@ +# @logicsrc/schemas + +Canonical JSON Schemas (draft 2020-12) for the LogicSRC open coordination +standards, maintained by Profullstack, Inc. + +Two schema families ship from this package: + +- **LogicSRC core** — `logicsrc-*.schema.json`: tasks, agents, runs, events, + plugins, connected accounts, email messages, social posts. +- **AgentAd** — `agentad-*.schema.json`: a disclosed, agent-readable advertising + contract for CLI tools and AI agents (ads, placements, requests, responses, + impressions, clicks, campaigns). See `docs/agentad.md` in the repo; + [cl1s.tech](https://github.com/profullstack/cl1s.tech) is the reference network. + +## Install + +```bash +npm install @logicsrc/schemas +``` + +## Use + +```js +import adSchema from "@logicsrc/schemas/agentad-ad" with { type: "json" }; +import taskSchema from "@logicsrc/schemas/task" with { type: "json" }; +``` + +Schema `$id`s resolve under `https://schemas.logicsrc.com/`. Validate with any +draft 2020-12 validator (e.g. `ajv/dist/2020.js`), or use `@logicsrc/validators` +from the monorepo. + +## License + +MIT © Profullstack, Inc. diff --git a/packages/schemas/package.json b/packages/schemas/package.json index fbc50ec..fe4d7b1 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -2,7 +2,18 @@ "name": "@logicsrc/schemas", "version": "0.1.0", "description": "LogicSRC JSON schemas for tasks, agents, runs, events, plugins, and the AgentAd ad standard.", + "license": "MIT", "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/profullstack/logicsrc.git", + "directory": "packages/schemas" + }, + "homepage": "https://github.com/profullstack/logicsrc/tree/master/packages/schemas", + "keywords": ["logicsrc", "agentad", "json-schema", "agents", "cli", "advertising", "standards"], + "publishConfig": { + "access": "public" + }, "exports": { "./task": "./schemas/logicsrc-task.schema.json", "./agent": "./schemas/logicsrc-agent.schema.json",