Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/app/.well-known/agent-registration/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2025-2026 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

export function OPTIONS() {
return corsResponse();
}

export function GET(req: NextRequest) {
const target = new URL("/api/agent/bootstrap", req.url);
return NextResponse.redirect(target, {
status: 307,
headers: CORS_HEADERS,
});
}
12 changes: 3 additions & 9 deletions app/app/.well-known/self-agent-id.json/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,17 @@

import { NextResponse } from "next/server";
import { getAgentDiscoveryJSON } from "@/lib/agent-discovery";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

export function GET() {
return NextResponse.json(getAgentDiscoveryJSON(), {
headers: {
"Access-Control-Allow-Origin": "*",
...CORS_HEADERS,
"Cache-Control": "public, max-age=3600",
},
});
}

export function OPTIONS() {
return new NextResponse(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
return corsResponse();
}
34 changes: 34 additions & 0 deletions app/app/agents.json/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2025-2026 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import { NextResponse } from "next/server";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

const BASE = process.env.NEXT_PUBLIC_APP_URL || "https://app.ai.self.xyz";

export function OPTIONS() {
return corsResponse();
}

export function GET() {
return NextResponse.json(
{
name: "Self Agent ID",
description:
"On-chain AI agent identity registry with proof-of-human verification",
registration: `${BASE}/api/agent/bootstrap`,
discovery: `${BASE}/api/agent-discovery`,
a2a: `${BASE}/api/a2a`,
llms_txt: `${BASE}/llms.txt`,
agent_card: `${BASE}/.well-known/agent-card.json`,
well_known: `${BASE}/.well-known/self-agent-id.json`,
},
{
headers: {
...CORS_HEADERS,
"Cache-Control": "public, max-age=3600",
},
},
);
}
4 changes: 2 additions & 2 deletions app/app/agents/visa/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
setLoading(false);
}
},
[network],

Check warning on line 100 in app/app/agents/visa/page.tsx

View workflow job for this annotation

GitHub Actions / TypeScript Lint & Format

React Hook useCallback has a missing dependency: 'autoMigrate'. Either include it or remove the dependency array
);

useEffect(() => {
Expand Down Expand Up @@ -468,11 +468,11 @@
<VisaUpgradeFlow
oldAgentId={agent.agentId}
chainId={agent.chainId}
walletAddress={walletAddress!}
walletAddress={walletAddress}
blockExplorer={network.blockExplorer}
onComplete={() => {
setUpgradingAgent(null);
void loadAgents(walletAddress!);
void loadAgents(walletAddress);
}}
onCancel={() => setUpgradingAgent(null)}
/>
Expand Down
40 changes: 40 additions & 0 deletions app/app/api/[...catchall]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2025-2026 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import { NextResponse } from "next/server";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

const BASE = process.env.NEXT_PUBLIC_APP_URL || "https://app.ai.self.xyz";

const body = {
error: "Not found",
message: "This API endpoint does not exist.",
discovery: {
bootstrap: `${BASE}/api/agent/bootstrap`,
agent_discovery: `${BASE}/api/agent-discovery`,
a2a: `${BASE}/api/a2a`,
docs: `${BASE}/api-docs`,
llms_txt: `${BASE}/llms.txt`,
},
};

export function OPTIONS() {
return corsResponse();
}

export function GET() {
return NextResponse.json(body, { status: 404, headers: CORS_HEADERS });
}

export function POST() {
return NextResponse.json(body, { status: 404, headers: CORS_HEADERS });
}

export function PUT() {
return NextResponse.json(body, { status: 404, headers: CORS_HEADERS });
}

export function DELETE() {
return NextResponse.json(body, { status: 404, headers: CORS_HEADERS });
}
12 changes: 3 additions & 9 deletions app/app/api/agent-discovery/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,17 @@

import { NextResponse } from "next/server";
import { getAgentDiscoveryJSON } from "@/lib/agent-discovery";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

export function GET() {
return NextResponse.json(getAgentDiscoveryJSON(), {
headers: {
"Access-Control-Allow-Origin": "*",
...CORS_HEADERS,
"Cache-Control": "public, max-age=3600",
},
});
}

export function OPTIONS() {
return new NextResponse(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
return corsResponse();
}
14 changes: 3 additions & 11 deletions app/app/api/agent/bootstrap/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// Stateless, no auth, cacheable.

import { NextResponse } from "next/server";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

const spec = {
openapi: "3.1.0",
Expand Down Expand Up @@ -256,24 +257,15 @@ const spec = {
},
} as const;

const CORS_HEADERS = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
};

export function GET() {
return NextResponse.json(spec, {
headers: {
"Cache-Control": "public, max-age=3600",
...CORS_HEADERS,
"Cache-Control": "public, max-age=3600",
},
});
}

export function OPTIONS() {
return new NextResponse(null, {
status: 204,
headers: CORS_HEADERS,
});
return corsResponse();
}
26 changes: 26 additions & 0 deletions app/app/api/health/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: 2025-2026 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import { NextResponse } from "next/server";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

export function OPTIONS() {
return corsResponse();
}

export function GET() {
return NextResponse.json(
{
status: "ok",
service: "self-agent-id",
timestamp: new Date().toISOString(),
},
{
headers: {
...CORS_HEADERS,
"Cache-Control": "no-cache, no-store",
},
},
);
}
9 changes: 5 additions & 4 deletions app/app/demo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
useMemo,
useState,
} from "react";
import Link from "next/link";
import { ethers } from "ethers";
import MatrixText from "@/components/MatrixText";
import {
Expand Down Expand Up @@ -2397,19 +2398,19 @@ export default function DemoPage() {
</p>
<p className="text-xs text-subtle max-w-lg mx-auto mt-2">
Don&apos;t have an agent yet?{" "}
<a
<Link
href="/agents/register"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
Register via dApp
</a>{" "}
</Link>{" "}
or use the{" "}
<a
<Link
href="/cli"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
CLI
</a>{" "}
</Link>{" "}
for terminal and agent-guided workflows.
</p>
</div>
Expand Down
15 changes: 15 additions & 0 deletions app/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ export default function RootLayout({
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(getJsonLd()) }}
/>
<meta
name="agent-registration"
content="https://app.ai.self.xyz/api/agent/bootstrap"
/>
<link
rel="agent-api"
href="/api/agent/bootstrap"
type="application/json"
/>
<link
rel="agent-card"
href="/.well-known/agent-card.json"
type="application/json"
/>
<link rel="llms-txt" href="/llms.txt" type="text/plain" />
</head>
<body className={`${geist.variable} ${geistMono.variable} antialiased`}>
<ClientProviders>
Expand Down
12 changes: 3 additions & 9 deletions app/app/llms.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,18 @@

import { NextResponse } from "next/server";
import { getAgentDiscoveryText } from "@/lib/agent-discovery";
import { CORS_HEADERS, corsResponse } from "@/lib/api-helpers";

export function GET() {
return new NextResponse(getAgentDiscoveryText(), {
headers: {
...CORS_HEADERS,
"Content-Type": "text/plain; charset=utf-8",
"Access-Control-Allow-Origin": "*",
"Cache-Control": "public, max-age=3600",
},
});
}

export function OPTIONS() {
return new NextResponse(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
return corsResponse();
}
62 changes: 62 additions & 0 deletions app/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2025-2026 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import Link from "next/link";
import { Button } from "@/components/Button";

export default function NotFound() {
return (
<main className="min-h-[60vh] flex items-center justify-center px-6">
<div className="text-center max-w-md">
<h1 className="text-4xl font-bold text-foreground mb-2">404</h1>
<p className="text-muted mb-6">
This page doesn&apos;t exist. Here are some useful links:
</p>

<div className="flex flex-col sm:flex-row gap-3 justify-center mb-8">
<Link href="/agents/register">
<Button variant="primary" size="sm">
Register Agent
</Button>
</Link>
<Link href="/agents">
<Button variant="secondary" size="sm">
My Agents
</Button>
</Link>
<Link href="/">
<Button variant="secondary" size="sm">
Home
</Button>
</Link>
</div>

{/* Machine-readable discovery hints (visually subtle) */}
<p className="text-xs text-subtle">
Developers:{" "}
<Link
href="/api-docs"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
API Docs
</Link>
{" · "}
<Link
href="/llms.txt"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
llms.txt
</Link>
{" · "}
<Link
href="/api/agent/bootstrap"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
Bootstrap API
</Link>
</p>
</div>
</main>
);
}
15 changes: 15 additions & 0 deletions app/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,21 @@ export default function Home() {
</div>
</Card>
</div>

{/* Agent quick-start hint */}
<p className="mt-6 text-center text-xs text-muted">
Building an agent?{" "}
<code className="text-foreground bg-surface-2 rounded px-1.5 py-0.5 font-mono">
curl https://app.ai.self.xyz/api/agent/bootstrap
</code>{" "}
or read{" "}
<Link
href="/llms.txt"
className="text-accent hover:text-accent-2 underline underline-offset-2"
>
/llms.txt
</Link>
</p>
</div>
</section>

Expand Down
Loading
Loading