diff --git a/app/about/page.tsx b/app/about/page.tsx index f942815..1a6569c 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -97,7 +97,7 @@ export default function AboutPage() {

About AgentNine

What an AgentNine listing tells you.

- Each listing links to its upstream source and records available setup and system-access details. + Each listing links to the original project and records available setup and system-access details.

What a listing covers

-

Listings record setup steps, version details, hardware requirements, system access, and removal instructions when those details are available from the upstream project.

+

Listings record setup steps, version details, hardware requirements, system access, and removal instructions when those details are available from the original project.

How listing details are checked

We use the linked repository and project documentation. Read how verification and freshness are recorded to see what those checks do and do not establish.

Selection and removal

-

Projects need a clear upstream source and a documented first-run path. We may mark or remove a listing if its source breaks, setup details become misleading, or a serious issue makes continued listing inappropriate. We do not audit upstream security, licensing, or legal compliance.

+

Projects need a clearly identified original source and documented first-run instructions. We may mark or remove a listing if its source breaks, setup details become misleading, or a serious issue makes continued listing inappropriate. We do not audit the project’s security, licensing, or legal compliance.

Independent by design

We are not affiliated with the creators or repositories listed here. A listing is not a partnership, endorsement, or security certification. If you spot a broken detail, tell us.

diff --git a/app/compare/page.tsx b/app/compare/page.tsx index 9f70727..b9e91cd 100644 --- a/app/compare/page.tsx +++ b/app/compare/page.tsx @@ -27,7 +27,7 @@ const rows: Array<[string, (agent: Agent) => string]> = [ ["Network access", (agent) => agent.network_access || "Not recorded"], ["File access", (agent) => agent.file_access || "Not recorded"], ["Hardware", (agent) => agent.hardware_requirements || "Not recorded"], - ["Upstream changes since verification", (agent) => agent.upstream_changed_since_verification ? "Changed since verification" : "No change recorded"], + ["Project changes since verification", (agent) => agent.upstream_changed_since_verification ? "Changed since verification" : "No change recorded"], ]; export default async function ComparePage({ searchParams }: { searchParams: Promise<{ agents?: string }> }) { diff --git a/app/globals.css b/app/globals.css index a063c42..8be4569 100644 --- a/app/globals.css +++ b/app/globals.css @@ -610,9 +610,10 @@ body:has(.faq-page) .floating-contact { display: none; } .search-page-heading h1 { margin-bottom: 0; } .search-shell { max-width: 1040px; margin-top: 0; } .search-input-wrap { position: relative; min-height: 78px; background: color-mix(in srgb, var(--field) 88%, transparent); border: 1px solid color-mix(in srgb, var(--ink) 16%, var(--line)); border-radius: var(--radius-card); display: flex; align-items: center; padding: 0 22px; box-shadow: none; transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease; } -.search-input-wrap:focus-within { border-color: color-mix(in srgb, var(--blue) 65%, var(--line)); box-shadow: 0 22px 60px color-mix(in srgb, var(--blue) 12%, transparent), 0 0 0 4px color-mix(in srgb, var(--focus-ring) 12%, transparent); transform: translateY(-1px); } +.search-input-wrap:focus-within { border-color: color-mix(in srgb, var(--blue-text) 65%, var(--line)); outline: 2px solid color-mix(in srgb, var(--blue-text) 35%, transparent); outline-offset: 3px; } .search-icon { display: grid; width: 28px; height: 28px; place-items: center; border: 1px solid color-mix(in srgb, var(--blue) 45%, var(--line)); border-radius: 50%; color: var(--blue-text); line-height: 1; opacity: .95; } .search-input-wrap input { flex: 1; min-width: 0; border: 0; outline: 0; padding: 22px 16px; background: transparent; color: var(--ink); font-size: 19px; letter-spacing: -.025em; } +.search-input-wrap input:focus-visible { outline: none; box-shadow: none; } .search-scope { margin: 9px 2px 0; color: var(--muted); font-size: var(--font-size-sm); line-height: 1.5; } .recent-agent-searches { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin: 12px 2px 0; color: var(--muted); font-size: var(--font-size-xs); } .recent-agent-searches > span { margin-right: 2px; font-weight: 700; } @@ -1064,10 +1065,16 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r .command-card strong { display: block; margin-bottom: 8px; font-size: var(--font-size-sm); text-transform: uppercase; letter-spacing: .08em; color: var(--blue-text); } .command-card pre { margin: 0; white-space: pre-wrap; font: 12px/1.7 var(--font-geist-mono), monospace; } .setup-guide { display: grid; gap: 10px; } -.setup-platform { border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); } -.setup-platform summary { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-height: 52px; padding: 12px 14px; cursor: pointer; color: var(--ink); font-size: var(--font-size-sm); font-weight: 700; } -.setup-platform summary::marker { color: var(--blue-text); } +.setup-platform { border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); interpolate-size: allow-keywords; } +.setup-platform summary { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-height: 52px; padding: 12px 14px; list-style: none; cursor: pointer; color: var(--ink); font-size: var(--font-size-sm); font-weight: 700; } +.setup-platform summary::-webkit-details-marker { display: none; } +.setup-platform summary::after { width: 8px; height: 8px; flex: 0 0 8px; margin: -4px 4px 0 0; border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted); content: ""; transform: rotate(45deg); transition: transform 200ms cubic-bezier(.2, .75, .25, 1), border-color 160ms ease; } +.setup-platform summary:hover { color: var(--blue-text); } +.setup-platform summary:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; } .setup-platform[open] summary { border-bottom: 1px solid var(--line); } +.setup-platform[open] summary::after { border-color: var(--blue-text); transform: rotate(225deg); } +.setup-platform::details-content { display: block; block-size: 0; overflow: clip; opacity: 0; transition: block-size 240ms cubic-bezier(.22, 1, .36, 1), opacity 150ms ease-out, content-visibility 240ms allow-discrete; } +.setup-platform[open]::details-content { block-size: auto; opacity: 1; } .setup-code-row { display: grid; gap: 10px; margin: 14px; } .setup-code-row h4, .setup-code-row p { margin: 0; color: var(--ink); font-size: var(--font-size-sm); } .setup-code-row .command-card { margin: 0; } @@ -1702,6 +1709,16 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r .recent-section { background: var(--hero-surface); } .recent-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; } .recent-grid .agent-card { min-width: 0; } +.home-news-section { border-top: 1px solid var(--line); } +.home-news-heading { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 30px; } +.home-news-heading h2 { margin: 0; font-size: clamp(34px, 4.5vw, 58px); line-height: .98; letter-spacing: -.07em; } +.home-news-all-link { display: inline-flex; min-height: 44px; align-items: center; gap: 7px; color: var(--blue-text); font-size: var(--font-size-md); font-weight: 700; text-underline-offset: 4px; } +.home-news-all-link:hover { text-decoration: underline; } +.home-news-all-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; } +.home-news-list { max-width: none; } +.home-news-list > li { padding: 22px 0 24px; } +.home-news-list h3 { margin: 0; font-size: clamp(1.25rem, 2vw, 1.65rem); letter-spacing: -.04em; line-height: 1.2; } +.home-news-list h3 a:hover { color: var(--blue-text); text-decoration: underline; text-underline-offset: 4px; } .new-standards { border-top: 1px solid var(--line); } .new-standards .container { display: grid; grid-template-columns: minmax(260px, .8fr) 1.5fr; gap: 80px; align-items: start; } .standards-intro > p:last-child { max-width: 330px; margin-top: 24px; color: var(--muted); line-height: 1.6; } @@ -1709,6 +1726,7 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r .new-standards .feature-item { padding-top: 18px; border-top: 2px solid var(--ink); } .new-standards .feature-item h3 { font-size: 24px; letter-spacing: -.05em; } @media (max-width: 800px) { + .home-news-heading { align-items: start; } .new-standards .container { grid-template-columns: 1fr; gap: 44px; } .new-standards .standards-intro h2 { font-size: clamp(34px, 10vw, 48px); } .new-standards .standards-intro > p:last-child { max-width: 34rem; } @@ -1806,6 +1824,7 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r .fey-meteor-shower i { animation: none; } .fey-card, .fey-card:hover, .fey-card:hover ~ .fey-card { transition: none; translate: none; rotate: none; } .home-faq-chevron, .home-faq-answer, .home-faq-answer-inner, + .setup-platform::details-content, .setup-platform summary::after, .faq-item-chevron, .faq-answer, .faq-answer-inner { transition: none; } } @media (max-height: 560px) { @@ -1832,6 +1851,7 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r [data-theme="dark"] .button-light, [data-theme="dark"] .contact-form input, [data-theme="dark"] .contact-form textarea { background: var(--surface); border-color: var(--line); color: var(--ink); } +[data-theme="dark"] .search-input-wrap:focus-within { border-color: var(--blue-text); } [data-theme="dark"] .admin-toolbar, [data-theme="dark"] .admin-table thead th, [data-theme="dark"] .admin-table tbody tr:hover { background: var(--surface-soft); } @@ -2060,6 +2080,8 @@ kbd { color: var(--muted); border: 1px solid var(--line); border-radius: var(--r .news-editor-markdown-input { min-height: 240px; } } @media (max-width: 560px) { + .home-news-heading { gap: 12px; } + .home-news-heading h2 { font-size: clamp(32px, 9vw, 42px); } .agents-name-list { grid-template-columns: 1fr; } .agents-name-list li:nth-child(odd) { padding-right: 0; border-right: 0; } .agents-name-list li:nth-child(even) { padding-left: 0; } diff --git a/app/methodology/page.tsx b/app/methodology/page.tsx index 39d51ed..1088f32 100644 --- a/app/methodology/page.tsx +++ b/app/methodology/page.tsx @@ -16,22 +16,22 @@ export default function MethodologyPage() {

Trust and methodology

Evidence, freshness, and clear limits.

-

AgentNine separates what was checked from what is only visible in the upstream repository. Missing data stays missing.

+

AgentNine separates what was checked from what is only visible in the project repository. Missing data stays missing.

Verification states

-

Verified means all five checklist items have recorded evidence, repository freshness is current, and no later upstream change is recorded.

+

Verified means all five checklist items have recorded evidence, repository freshness is current, and no later project change is recorded.

Partially verified means only some of those items are recorded. A record without evidence is left as unverified rather than treated as tested.

Freshness signals

-

A repository metadata check date is used when available. Otherwise, freshness uses the latest recorded upstream commit. A stale flag or a date older than 180 days marks the record Needs review, including records with all five checklist items complete.

-

If neither a metadata check date nor an upstream commit date is available, freshness is unknown and the record is not labeled Verified. The setup-review date describes when checklist evidence was recorded; it does not determine repository freshness.

+

A repository metadata check date is used when available. Otherwise, freshness uses the latest recorded commit to the project repository. A stale flag or a date older than 180 days marks the record Needs review, including records with all five checklist items complete.

+

If neither a metadata check date nor a project commit date is available, freshness is unknown and the record is not labeled Verified. The setup-review date describes when checklist evidence was recorded; it does not determine repository freshness.

What this is not

-

A score is not a safety certification, security audit, endorsement, or guarantee that upstream behavior has stayed unchanged.

+

A score is not a safety certification, security audit, endorsement, or guarantee that the project has stayed unchanged.

Read the source repository, license, permissions, provider terms, and current issues before running an agent.

diff --git a/app/page.tsx b/app/page.tsx index 70e29f1..8c273a3 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -19,7 +19,7 @@ export default function Home() { "@id": `${SITE_URL}/#website`, url: SITE_URL, name: "AgentNine", - description: "Compare AI agent projects by source, setup requirements, and documented access.", + description: "Find open-source AI agents in AgentNine's directory. Browse by category, compare listings, and review setup, source, and access details.", publisher: { "@id": `${SITE_URL}/#organization` }, }, { @@ -50,7 +50,7 @@ export default function Home() {

Each listing keeps those details separate so you can review them before a first run.

-
A

Source

Open the upstream repository and review the release or commit behind the record.

+
A

Source

Open the project repository and review the release or commit behind the record.

B

Setup

Check installation commands, environment requirements, and first-run guidance.

C

Access

Review network, file, memory, port, and provider details before local execution.

@@ -89,6 +89,6 @@ export default function Home() { export const metadata = createPublicPageMetadata({ title: "Open-Source AI Agent Directory", - description: "Browse an open-source AI agent directory with project sources, setup guides, system requirements, and documented access details.", + description: "Find open-source AI agents in AgentNine's directory. Browse by category, compare listings, and review setup guides, source links, and access details.", path: "/", }); diff --git a/app/terms/page.tsx b/app/terms/page.tsx index 8ee3d9a..fd9eb50 100644 --- a/app/terms/page.tsx +++ b/app/terms/page.tsx @@ -35,7 +35,7 @@ export default function TermsPage() {

AgentNine is a public directory of AI-agent projects. It provides listings, editorial context, setup notes, recorded verification information, search and comparison tools, and - links to upstream sources. Public browsing does not require an account. + links to the original project sources. Public browsing does not require an account.

Google Analytics and Meta Pixel are optional and are enabled only if you allow them. You @@ -55,15 +55,15 @@ export default function TermsPage() { AgentNine does not grant a license to third-party projects listed in the directory. Software, names, logos, documentation, and other materials remain subject to their respective owners' terms and licenses. Before downloading or running a project, review - its upstream license, security posture, dependencies, permissions, and applicable + its license, security posture, dependencies, permissions, and applicable provider terms. You are responsible for your use of external software.

Verification scores, dates, and evidence describe checks recorded at a point in time. They are not safety certifications, endorsements, security audits, warranties, or guarantees of compatibility or performance. Listings, instructions, prices, dependencies, and links may - be incomplete, outdated, or unavailable. Check important details against the upstream - project before relying on them. + be incomplete, outdated, or unavailable. Check important details against the project’s + own documentation before relying on them.

Some listed projects may be dual-use, including tools that can be used for security diff --git a/components/HomeFaqAccordion.tsx b/components/HomeFaqAccordion.tsx index c0f0ddb..2dbdf0a 100644 --- a/components/HomeFaqAccordion.tsx +++ b/components/HomeFaqAccordion.tsx @@ -11,12 +11,12 @@ const questions = [ { question: "What does “verified” mean?", answer: - "All five checklist items have recorded evidence, the listing is not marked stale, and no later upstream change is recorded. A review date appears only when one has been recorded. This is not a safety certification.", + "All five checklist items have recorded evidence, the listing is not marked stale, and no later project change is recorded. A review date appears only when one has been recorded. This is not a safety certification.", }, { question: "Where does a listing’s information come from?", answer: - "Each published listing links to its upstream repository. Open that source to check the current code, setup instructions, and license.", + "Each published listing links to its project repository. Open that source to check the current code, setup instructions, and license.", }, ]; diff --git a/components/SetupGuidePanel.tsx b/components/SetupGuidePanel.tsx index 5853e4e..de7fcf4 100644 --- a/components/SetupGuidePanel.tsx +++ b/components/SetupGuidePanel.tsx @@ -30,7 +30,7 @@ export function SetupGuidePanel({ guide }: { return

{label} {platform?.install_route ?

{platform.install_route}

: null} - {unsupported ?

The upstream project does not support this OS.

: <> + {unsupported ?

The project does not support this OS.

: <> {/* If there's no platform data or no commands, show a clear message so the panel has visible content and users know why it may be empty. */} {/* If there is no platform entry for this OS: show either a reviewed-empty message or the unreviewed placeholders depending on whether the source was checked. */} {(!platform) && (sourceChecked diff --git a/components/SetupStepper.tsx b/components/SetupStepper.tsx index dec9c2f..2c37645 100644 --- a/components/SetupStepper.tsx +++ b/components/SetupStepper.tsx @@ -80,7 +80,7 @@ export function SetupStepper({ steps, storageKey, sourceUrl }: { steps: string[] if (!steps.length) { const readmeUrl = sourceUrl?.replace(/\/+$/, "").replace(/\.git$/, "").replace(/\/blob\/.*$/, "") + "/blob/HEAD/README.md"; - return
Setup steps not recorded

AgentNine has not validated setup steps for this listing yet. This is a documentation gap, not a setup failure.

{sourceUrl ? Open the project README :

The source repository is not recorded, so an upstream README link is unavailable.

}
; + return
Setup steps not recorded

AgentNine has not validated setup steps for this listing yet. This is a documentation gap, not a setup failure.

{sourceUrl ? Open the project README :

The source repository is not recorded, so a project README link is unavailable.

}
; } return
{completedThrough >= 0 ? `Step ${Math.min(completedThrough + 1, steps.length)} of ${steps.length} reached` : "No steps completed yet"}
{copyError ?

Copy failed. Select the text manually and press Ctrl+C (or Cmd+C).

: null}{progressError ?

Setup progress could not be saved. Try again.

: null}
    {steps.map((step, index) =>
  1. {String(index + 1).padStart(2, "0")}

    {step}

  2. )}
; diff --git a/lib/faq.ts b/lib/faq.ts index 7e65169..6fd3e07 100644 --- a/lib/faq.ts +++ b/lib/faq.ts @@ -43,13 +43,13 @@ export const faqGroups: FaqGroup[] = [ id: "ollama", question: "Why do some agents mention Ollama?", answer: - "A locally run model can keep inference prompts from going to a hosted model provider. An agent may still contact other services through tools or its configuration, so check the listing's access details and the upstream documentation.", + "A locally run model can keep inference prompts from going to a hosted model provider. An agent may still contact other services through tools or its configuration, so check the listing's access details and the project documentation.", }, { id: "verified-meaning", question: "What does verified mean?", answer: - "It means we completed the checklist shown on the listing at the displayed date. Projects change, so check the upstream repository before you run anything.", + "It means we completed the checklist shown on the listing at the displayed date. Projects change, so check the project repository before you run anything.", }, ], }, diff --git a/lib/llms.ts b/lib/llms.ts index fa60f29..020ca25 100644 --- a/lib/llms.ts +++ b/lib/llms.ts @@ -34,7 +34,7 @@ export function createLlmIndex({ agents, categories, siteUrl }: LlmCatalog): str }), "", "## Trust boundary", - "Checklist evidence records information available to AgentNine; it is not an independent security, legal, licensing, or operational certification. Listings can be incomplete or out of date. Review the upstream project, its license, and current setup instructions; pin a version before running it.", + "Checklist evidence records information available to AgentNine; it is not an independent security, legal, licensing, or operational certification. Listings can be incomplete or out of date. Review the project, its license, and current setup instructions; pin a version before running it.", ]; return lines.join("\n"); } diff --git a/lib/trust.ts b/lib/trust.ts index 266cdcf..b0eab0c 100644 --- a/lib/trust.ts +++ b/lib/trust.ts @@ -42,9 +42,9 @@ export function getAgentTrustState(agent: Agent, now = Date.now()): TrustState { const freshnessUnknown = metadataAt === null && commitAt === null; return { key: changed ? "changed" : freshnessUnknown ? "freshness-unknown" : "verified", - label: changed ? "Changed upstream" : freshnessUnknown ? "Freshness unknown" : "Verified", + label: changed ? "Project changed" : freshnessUnknown ? "Freshness unknown" : "Verified", detail: changed - ? "The upstream repository changed after the recorded verification." + ? "The project repository changed after the recorded verification." : freshnessUnknown ? "All five checklist items have recorded evidence, but no repository freshness signal is available." : "All five AgentNine checklist items have recorded evidence.", @@ -84,7 +84,7 @@ export function getFreshnessNote(agent: Agent, includeUpstreamActivity = true): if (metadataDate) return `Repository metadata checked ${metadataDate}.`; if (includeUpstreamActivity) { const commitDate = formatCatalogDate(agent.last_commit_at); - if (commitDate) return `Latest upstream commit recorded ${commitDate}.`; + if (commitDate) return `Latest project commit recorded ${commitDate}.`; } return ""; } diff --git a/tests/trust.test.ts b/tests/trust.test.ts index 3fb6e0a..58b8c7e 100644 --- a/tests/trust.test.ts +++ b/tests/trust.test.ts @@ -65,13 +65,13 @@ describe("agent trust state freshness", () => { expect(state.label).toBe("Verified"); }); - it("keeps changed upstream as the stronger signal when freshness is unknown", () => { + it("keeps project changes as the stronger signal when freshness is unknown", () => { const state = getAgentTrustState(createAgent({ verification_score: 5, upstream_changed_since_verification: true, }), now); expect(state.key).toBe("changed"); - expect(state.label).toBe("Changed upstream"); + expect(state.label).toBe("Project changed"); }); });