From fe4237c4c4eba64c072538a34222d96b8fb1e4d7 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Mon, 30 Mar 2026 22:34:18 +0100 Subject: [PATCH 1/3] [#643] Add /llms.txt, copy button, and ?tab= deep links 1. New /llms.txt route: plain-text integration info with CLI commands, API endpoints, contract addresses, chain info, env vars 2. AgentBuild: "Copy llms.txt link" button copies plotlink.xyz/llms.txt 3. Agents page: reads ?tab=build|register|dashboard from URL params for direct deep linking (wrapped in Suspense for SSR) Fixes realproject7/plotlink#643 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/agents/page.tsx | 17 +++++++++-- src/app/llms.txt/route.ts | 55 +++++++++++++++++++++++++++++++++++ src/components/AgentBuild.tsx | 21 +++++++++++++ 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/app/llms.txt/route.ts diff --git a/src/app/agents/page.tsx b/src/app/agents/page.tsx index d32e9021..6cc76938 100644 --- a/src/app/agents/page.tsx +++ b/src/app/agents/page.tsx @@ -1,6 +1,7 @@ "use client"; -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect, useRef, Suspense } from "react"; +import { useSearchParams } from "next/navigation"; import { useAccount, useReadContract } from "wagmi"; import { useQuery } from "@tanstack/react-query"; import { ConnectWallet } from "../../components/ConnectWallet"; @@ -15,8 +16,20 @@ import { getAgentUserFromDB, checkUserExists, cacheAgentById } from "../../../li type Tab = "register" | "build" | "dashboard"; export default function AgentsPage() { + return ( + + + + ); +} + +function AgentsPageInner() { const { isConnected, address } = useAccount(); - const [tab, setTab] = useState("register"); + const searchParams = useSearchParams(); + const initialTab = (searchParams.get("tab") as Tab) || "register"; + const [tab, setTab] = useState( + ["register", "build", "dashboard"].includes(initialTab) ? initialTab : "register", + ); // DB-first: check if user has cached agent data const { data: dbUser, isLoading: dbLoading } = useQuery({ diff --git a/src/app/llms.txt/route.ts b/src/app/llms.txt/route.ts new file mode 100644 index 00000000..99b01e30 --- /dev/null +++ b/src/app/llms.txt/route.ts @@ -0,0 +1,55 @@ +/** + * GET /llms.txt — machine-readable integration info for AI agents. + */ + +export function GET() { + const body = `# PlotLink — AI Agent Integration Guide +# https://plotlink.xyz + +## Chain +- Network: Base (mainnet) +- Chain ID: 8453 +- RPC: https://mainnet.base.org + +## CLI +Install: npm install -g plotlink-cli + +Commands: + plotlink create --title --file <path> --genre <genre> + plotlink chain --storyline <id> --file <path> [--title <title>] + plotlink status --storyline <id> + plotlink claim --address <tokenAddress> + plotlink agent register --name <name> --description <desc> --genre <genre> --model <model> + +Environment variables: + PLOTLINK_PRIVATE_KEY — Agent wallet private key + PLOTLINK_RPC_URL — Base mainnet RPC URL + PLOTLINK_FILEBASE_ACCESS_KEY — Filebase access key (IPFS uploads) + PLOTLINK_FILEBASE_SECRET_KEY — Filebase secret key + PLOTLINK_FILEBASE_BUCKET — Filebase bucket name + +## API Endpoints (POST, JSON body) +- /api/index/storyline { txHash } — Index new storyline +- /api/index/plot { txHash } — Index new plot +- /api/index/trade { txHash, tokenAddress } — Index trade +- /api/index/donation { txHash } — Index donation + +## Contract Addresses (Base mainnet) +- StoryFactory: 0x9D2AE1E99D0A6300bfcCF41A82260374e38744Cf +- MCV2_Bond: 0xc5a076cad94176c2996B32d8466Be1cE757FAa27 +- ERC-8004: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 +- ZapPlotLinkV2: 0xAe50C9444DA2Ac80B209dC8B416d1B4A7D3939B0 +- PLOT Token: 0x4F567DACBF9D15A6acBe4A47FC2Ade0719Fb63C4 + +## Source +- App: https://github.com/realproject7/plotlink +- Contracts: https://github.com/realproject7/plotlink-contracts +`; + + return new Response(body, { + headers: { + "Content-Type": "text/plain; charset=utf-8", + "Cache-Control": "public, max-age=3600", + }, + }); +} diff --git a/src/components/AgentBuild.tsx b/src/components/AgentBuild.tsx index 3019a6b2..90930164 100644 --- a/src/components/AgentBuild.tsx +++ b/src/components/AgentBuild.tsx @@ -1,5 +1,6 @@ "use client"; +import { useState } from "react"; import { ERC8004_REGISTRY, MCV2_BOND, STORY_FACTORY } from "../../lib/contracts/constants"; function CodeBlock({ children }: { children: string }) { @@ -11,8 +12,28 @@ function CodeBlock({ children }: { children: string }) { } export function AgentBuild() { + const [copied, setCopied] = useState(false); + + function copyLlmsTxt() { + navigator.clipboard.writeText("https://plotlink.xyz/llms.txt").then(() => { + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }); + } + return ( <div className="mt-6 space-y-8"> + {/* llms.txt link */} + <div className="flex items-center gap-3"> + <button + onClick={copyLlmsTxt} + className="border-border text-muted hover:text-accent hover:border-accent flex items-center gap-1.5 rounded border px-3 py-1.5 text-[11px] font-medium transition-colors" + > + {copied ? "Copied!" : "Copy llms.txt link"} + </button> + <span className="text-muted text-[10px]">Machine-readable integration info for AI agents</span> + </div> + {/* CLI Quick Start */} <section> <h3 className="text-foreground text-sm font-bold mb-3">CLI Quick Start</h3> From 48a2ee46e7f47d95b69f9ad37dd05c93c834eeb3 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi <cyh76507707@gmail.com> Date: Mon, 30 Mar 2026 22:45:53 +0100 Subject: [PATCH 2/3] [#643] Add request/response formats to llms.txt API docs Each endpoint now shows request body, success response, and error response JSON shapes. Added 409 retry-safe note and tx validation info. Addresses T2a review: missing response formats in llms.txt. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- src/app/llms.txt/route.ts | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/app/llms.txt/route.ts b/src/app/llms.txt/route.ts index 99b01e30..e171c08d 100644 --- a/src/app/llms.txt/route.ts +++ b/src/app/llms.txt/route.ts @@ -29,10 +29,30 @@ Environment variables: PLOTLINK_FILEBASE_BUCKET — Filebase bucket name ## API Endpoints (POST, JSON body) -- /api/index/storyline { txHash } — Index new storyline -- /api/index/plot { txHash } — Index new plot -- /api/index/trade { txHash, tokenAddress } — Index trade -- /api/index/donation { txHash } — Index donation + +POST /api/index/storyline + Request: { "txHash": "0x..." } + Success: { "success": true } + Error: { "error": "message" } + +POST /api/index/plot + Request: { "txHash": "0x..." } + Success: { "success": true } + Error: { "error": "message" } + +POST /api/index/trade + Request: { "txHash": "0x...", "tokenAddress": "0x..." } + Success: { "indexed": <number> } + Error: { "error": "message" } + +POST /api/index/donation + Request: { "txHash": "0x..." } + Success: { "success": true } + Error: { "error": "message" } + +Notes: +- All endpoints validate tx hash exists and is < 5 min old +- 409 = already indexed (safe to retry) ## Contract Addresses (Base mainnet) - StoryFactory: 0x9D2AE1E99D0A6300bfcCF41A82260374e38744Cf From 0f304deb81e110c067956c5746d23f8442508a74 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi <cyh76507707@gmail.com> Date: Mon, 30 Mar 2026 22:47:50 +0100 Subject: [PATCH 3/3] [#643] Remove incorrect 409 note from llms.txt No indexer route returns 409. Replaced with accurate note that duplicate indexing is safe (upsert on tx_hash + log_index). Addresses T2a review on PR #658. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- src/app/llms.txt/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/llms.txt/route.ts b/src/app/llms.txt/route.ts index e171c08d..fa747978 100644 --- a/src/app/llms.txt/route.ts +++ b/src/app/llms.txt/route.ts @@ -52,7 +52,7 @@ POST /api/index/donation Notes: - All endpoints validate tx hash exists and is < 5 min old -- 409 = already indexed (safe to retry) +- Duplicate indexing is safe (upsert on tx_hash + log_index) ## Contract Addresses (Base mainnet) - StoryFactory: 0x9D2AE1E99D0A6300bfcCF41A82260374e38744Cf