feat: improve landing page (#33)
This commit is contained in:
@@ -1,50 +1,5 @@
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@kandev/ui/card';
|
||||
import Link from 'next/link';
|
||||
|
||||
const blogPosts = [
|
||||
{
|
||||
title: 'Introducing kandev.ai: AI-Powered Kanban for Developers',
|
||||
description: 'Learn how kandev.ai combines Kanban boards with AI agents, isolated worktrees, and Docker containers to accelerate your development workflow.',
|
||||
date: 'January 10, 2026',
|
||||
slug: 'introducing-kandev',
|
||||
author: 'Kandev Team',
|
||||
},
|
||||
{
|
||||
title: 'Running Multiple AI Agents in Parallel: Best Practices',
|
||||
description: 'Discover how to effectively manage multiple AI coding agents working simultaneously on different tasks using isolated environments and approval workflows.',
|
||||
date: 'January 5, 2026',
|
||||
slug: 'parallel-ai-agents',
|
||||
author: 'Kandev Team',
|
||||
},
|
||||
];
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function BlogPage() {
|
||||
return (
|
||||
<div className="container mx-auto max-w-6xl py-24 px-4">
|
||||
<h1 className="text-4xl font-bold mb-4">Blog</h1>
|
||||
<p className="text-lg text-muted-foreground mb-12">
|
||||
Insights and updates from the kandev.ai team.
|
||||
</p>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
{blogPosts.map((post) => (
|
||||
<Link key={post.slug} href={`/blog/${post.slug}`}>
|
||||
<Card className="h-full transition-transform hover:scale-[1.02] cursor-pointer">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground mb-2">
|
||||
<span>{post.date}</span>
|
||||
<span>•</span>
|
||||
<span>{post.author}</span>
|
||||
</div>
|
||||
<CardTitle className="text-2xl">{post.title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="text-base">{post.description}</CardDescription>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
redirect('/changelog');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc';
|
||||
import { getChangelogEntry, getChangelogSlugs } from '@/lib/changelog';
|
||||
import { mdxComponents } from '@/components/mdx-components';
|
||||
|
||||
function formatDate(date: string) {
|
||||
if (!date) return '';
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(new Date(date));
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const slugs = await getChangelogSlugs();
|
||||
return slugs.map((slug) => ({ slug }));
|
||||
}
|
||||
|
||||
export default async function ChangelogEntryPage({
|
||||
params,
|
||||
}: {
|
||||
params: { slug?: string } | Promise<{ slug?: string }>;
|
||||
}) {
|
||||
const resolvedParams = await Promise.resolve(params);
|
||||
const slug = resolvedParams.slug;
|
||||
|
||||
if (!slug) {
|
||||
notFound();
|
||||
}
|
||||
const entry = await getChangelogEntry(slug);
|
||||
|
||||
if (!entry) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative overflow-hidden">
|
||||
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
|
||||
<div className="container mx-auto max-w-4xl px-4 pb-24 pt-24">
|
||||
<div className="mb-10">
|
||||
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">{entry.surface}</p>
|
||||
<h1 className="mt-4 text-4xl font-semibold text-foreground md:text-5xl">{entry.title}</h1>
|
||||
<p className="mt-4 text-sm text-muted-foreground">{formatDate(entry.date)}</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{entry.summary.map((line) => (
|
||||
<p key={line} className="text-lg text-muted-foreground">
|
||||
{line}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-10 border-t border-border/60 pt-8">
|
||||
<MDXRemote source={entry.content} components={mdxComponents} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import Link from 'next/link';
|
||||
import { getChangelogEntries } from '@/lib/changelog';
|
||||
|
||||
function formatDate(date: string) {
|
||||
if (!date) return '';
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(new Date(date));
|
||||
}
|
||||
|
||||
export default async function ChangelogPage() {
|
||||
const entries = await getChangelogEntries();
|
||||
|
||||
return (
|
||||
<div className="relative overflow-hidden">
|
||||
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
|
||||
<div className="container mx-auto max-w-6xl px-4 pb-24 pt-24">
|
||||
<div className="mb-12">
|
||||
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">Changelog</p>
|
||||
<h1 className="mt-4 text-4xl font-semibold text-foreground md:text-5xl">Product updates</h1>
|
||||
<p className="mt-4 max-w-2xl text-lg text-muted-foreground">
|
||||
A running log of kandev.ai releases, shipped features, and operational improvements.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-12">
|
||||
{entries.map((entry, index) => (
|
||||
<article
|
||||
key={entry.slug}
|
||||
className="grid gap-6 border-b border-border/60 pb-12 md:grid-cols-[180px_1fr]"
|
||||
>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<p className="font-medium text-foreground">{entry.surface}</p>
|
||||
<p>{formatDate(entry.date)}</p>
|
||||
{index === 0 ? (
|
||||
<span className="mt-3 inline-flex items-center rounded-full border border-border bg-background px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.2em] text-foreground">
|
||||
Latest
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-2xl font-semibold text-foreground">
|
||||
<Link href={`/changelog/${entry.slug}`} className="hover:text-primary">
|
||||
{entry.title}
|
||||
</Link>
|
||||
</h2>
|
||||
<div className="mt-4 space-y-3 text-muted-foreground">
|
||||
{entry.summary.map((line) => (
|
||||
<p key={line}>{line}</p>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<Link
|
||||
href={`/changelog/${entry.slug}`}
|
||||
className="text-sm font-semibold text-primary hover:text-primary/80"
|
||||
>
|
||||
Read full update →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function AgentsDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Features"
|
||||
title="AI Agents"
|
||||
description="Agents are containerized workers that execute tasks. They communicate with the backend using ACP, a JSON-RPC protocol over stdin/stdout."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="Agent lifecycle">
|
||||
<ol className="space-y-2 list-decimal list-inside">
|
||||
<li>Container starts with agentctl on port 9999.</li>
|
||||
<li>Backend calls <code>initialize</code> and <code>session/new</code>.</li>
|
||||
<li>Tasks are sent via <code>session/prompt</code>.</li>
|
||||
<li>Agent streams <code>session/update</code> notifications.</li>
|
||||
</ol>
|
||||
</DocsCard>
|
||||
<DocsCard title="What agents can do" variant="accent">
|
||||
<ul className="space-y-2">
|
||||
<li>Read and edit files inside the worktree</li>
|
||||
<li>Run shell commands with approval gates</li>
|
||||
<li>Stream progress updates to the UI</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<DocsCard title="ACP example" variant="muted">
|
||||
<DocsCode>{`{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"1.0"}}`}</DocsCode>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
const stages = [
|
||||
{ title: 'Backlog', desc: 'Collect ideas and future work.' },
|
||||
{ title: 'In Progress', desc: 'Active tasks owned by agents.' },
|
||||
{ title: 'Review', desc: 'Approvals and QA before merge.' },
|
||||
{ title: 'Done', desc: 'Completed and shipped items.' },
|
||||
];
|
||||
|
||||
export default function BoardsDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Core Concepts"
|
||||
title="Boards"
|
||||
description="Boards are the Kanban surface for your workspace. Each board defines columns that represent the lifecycle of a task, from backlog to review to done."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{stages.map((stage) => (
|
||||
<DocsCard key={stage.title} title={stage.title}>
|
||||
<p>{stage.desc}</p>
|
||||
</DocsCard>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<DocsCard title="Example board config" variant="muted">
|
||||
<p>Keep columns minimal and apply WIP limits where review capacity is tight.</p>
|
||||
<DocsCode>{`board:
|
||||
name: "Product Roadmap"
|
||||
columns:
|
||||
- name: "Backlog"
|
||||
wipLimit: null
|
||||
- name: "In Progress"
|
||||
wipLimit: 4
|
||||
- name: "Review"
|
||||
wipLimit: 2
|
||||
- name: "Done"
|
||||
wipLimit: null`}</DocsCode>
|
||||
</DocsCard>
|
||||
|
||||
<DocsCard title="Tips" variant="accent">
|
||||
<ul className="space-y-2">
|
||||
<li>Use a single “Review” column so approvals are centralized.</li>
|
||||
<li>Keep WIP limits low to prevent agent overload.</li>
|
||||
<li>Archive finished tasks weekly to keep focus on active work.</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function DockerDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Features"
|
||||
title="Docker Execution"
|
||||
description="Every agent runs inside a Docker container to keep execution isolated from your host machine. Containers are created per task and destroyed after completion."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="What is mounted">
|
||||
<ul className="space-y-2">
|
||||
<li><code>/workspace</code> — your repository worktree</li>
|
||||
<li><code>/root/.augment/sessions</code> — agent session storage (when enabled)</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
<DocsCard title="Why containers" variant="accent">
|
||||
<ol className="space-y-2 list-decimal list-inside">
|
||||
<li>Consistent, reproducible environments</li>
|
||||
<li>Security boundaries for file and network access</li>
|
||||
<li>Easy cleanup after task completion</li>
|
||||
</ol>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<DocsCard title="Sample run (conceptual)" variant="muted">
|
||||
<DocsCode>{`docker run -it --rm \
|
||||
-v /path/to/repo:/workspace \
|
||||
-e TASK_DESCRIPTION="Fix the login bug" \
|
||||
kandev/augment-agent:latest`}</DocsCode>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function InstallationDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Getting Started"
|
||||
title="Installation"
|
||||
description="These steps outline a typical local installation. Exact commands may change as we finalize the installer, but the flow remains the same."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="Prerequisites" variant="accent">
|
||||
<ul className="space-y-2">
|
||||
<li>Docker Desktop (or Docker Engine)</li>
|
||||
<li>Git 2.30+</li>
|
||||
<li>Node.js 20+</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
<DocsCard title="Install the repo">
|
||||
<DocsCode>{`git clone https://github.com/kdlbs/kandev.git
|
||||
cd kandev
|
||||
pnpm install`}</DocsCode>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<DocsCard title="Run the services" variant="muted">
|
||||
<p>Start the backend, app, and landing site in separate terminals.</p>
|
||||
<DocsCode>{`pnpm --filter @kandev/backend dev
|
||||
pnpm --filter @kandev/web dev
|
||||
pnpm --filter @kandev/landing dev`}</DocsCode>
|
||||
</DocsCard>
|
||||
|
||||
<DocsCard title="Verify">
|
||||
<p>
|
||||
Open the UI and create a test workspace. The system should start an agent container on demand and stream
|
||||
progress back over WebSocket.
|
||||
</p>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -2,9 +2,11 @@ import { DocsSidebar } from '@/components/docs-sidebar';
|
||||
|
||||
export default function DocsLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex min-h-screen pt-16 justify-center">
|
||||
<DocsSidebar />
|
||||
<main className="flex-1 max-w-4xl py-8 px-6">{children}</main>
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]">
|
||||
<div className="mx-auto flex w-full max-w-6xl gap-8 px-6">
|
||||
<DocsSidebar />
|
||||
<main className="flex-1 py-16">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+45
-143
@@ -1,149 +1,51 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function DocsPage() {
|
||||
return (
|
||||
<div className="prose prose-slate dark:prose-invert max-w-none">
|
||||
<div className="not-prose mb-8">
|
||||
<h1 className="text-4xl font-bold mb-4">Getting Started with kandev.ai</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
kandev.ai combines Kanban task management with AI-powered development workflows. Manage tasks visually,
|
||||
execute them with AI agents in isolated environments, and ship faster with confidence.
|
||||
</p>
|
||||
</div>
|
||||
<DocsShell
|
||||
eyebrow="Getting Started"
|
||||
title="Documentation"
|
||||
description="Learn how kandev.ai orchestrates AI agents across isolated worktrees, Docker containers, and a WebSocket-first control plane."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="What is kandev.ai?" variant="accent">
|
||||
<p>
|
||||
kandev.ai is a WebSocket-first platform that pairs Kanban task management with AI-assisted execution.
|
||||
Every task runs inside a dedicated git worktree and a Docker container, with approvals for sensitive
|
||||
operations.
|
||||
</p>
|
||||
</DocsCard>
|
||||
<DocsCard title="Why teams use it">
|
||||
<ul className="space-y-2">
|
||||
<li>Ship in parallel without branch conflicts.</li>
|
||||
<li>Keep execution auditable and reviewable.</li>
|
||||
<li>Stream progress updates in real time.</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<div className="not-prose mb-8 p-6 bg-muted/50 rounded-lg border border-border">
|
||||
<h2 className="text-2xl font-bold mb-3">What is kandev.ai?</h2>
|
||||
<p className="text-muted-foreground">
|
||||
kandev.ai is a development tool that bridges project management and AI-assisted coding. Each task on your
|
||||
Kanban board can be executed by AI agents working in isolated git worktrees and Docker containers.
|
||||
</p>
|
||||
</div>
|
||||
<DocsCard title="Core workflow" variant="muted">
|
||||
<p>From task creation to approval, kandev.ai follows a consistent loop.</p>
|
||||
<DocsCode>{`1. Create task on the board
|
||||
2. Start agent container via agentctl
|
||||
3. Initialize ACP session
|
||||
4. Stream progress over WebSocket
|
||||
5. Review and approve output`}</DocsCode>
|
||||
</DocsCard>
|
||||
|
||||
<h2 className="text-2xl font-bold mt-8 mb-4">Key Features</h2>
|
||||
<div className="grid gap-4 not-prose mb-8">
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Visual Task Management</h3>
|
||||
<p className="text-sm text-muted-foreground">Organize development work with Kanban boards</p>
|
||||
</div>
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Isolated Worktrees</h3>
|
||||
<p className="text-sm text-muted-foreground">Each task gets its own git worktree for parallel development</p>
|
||||
</div>
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Local Docker Execution</h3>
|
||||
<p className="text-sm text-muted-foreground">AI agents run in secure Docker containers on your machine</p>
|
||||
</div>
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Multiple AI Agents</h3>
|
||||
<p className="text-sm text-muted-foreground">Support for Claude Code, OpenAI Codex, Augment, and more</p>
|
||||
</div>
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Approval Workflows</h3>
|
||||
<p className="text-sm text-muted-foreground">Review and approve agent changes before merging</p>
|
||||
</div>
|
||||
<div className="p-4 border border-border rounded-lg">
|
||||
<h3 className="font-semibold mb-2">Multiple Workspaces</h3>
|
||||
<p className="text-sm text-muted-foreground">Organize projects by client, team, or product</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold mt-8 mb-4">How It Works</h2>
|
||||
<div className="not-prose space-y-4 mb-8">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">1</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">Create a Task</h3>
|
||||
<p className="text-sm text-muted-foreground">Add a task to your Kanban board with a description of what needs to be done</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">2</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">Configure Repository</h3>
|
||||
<p className="text-sm text-muted-foreground">Select a repository and base branch for the task</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">3</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">Choose AI Agent</h3>
|
||||
<p className="text-sm text-muted-foreground">Select which AI agent should work on the task</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">4</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">Isolated Environment</h3>
|
||||
<p className="text-sm text-muted-foreground">kandev creates an isolated git worktree and Docker container</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">5</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">AI Execution</h3>
|
||||
<p className="text-sm text-muted-foreground">The AI agent executes the task in the secure environment</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">6</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">Review & Approve</h3>
|
||||
<p className="text-sm text-muted-foreground">Review the changes and approve them for merging</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="not-prose mb-8 p-6 bg-primary/10 rounded-lg border border-primary/20">
|
||||
<h2 className="text-2xl font-bold mb-3">Why kandev.ai?</h2>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
Traditional development workflows require constant context switching. kandev.ai eliminates this by:
|
||||
</p>
|
||||
<ul className="space-y-2">
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-primary">✓</span>
|
||||
<span className="text-sm">Visualizing all work in progress on a single board</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-primary">✓</span>
|
||||
<span className="text-sm">Enabling parallel development without branch conflicts</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-primary">✓</span>
|
||||
<span className="text-sm">Automating routine tasks with AI agents</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-primary">✓</span>
|
||||
<span className="text-sm">Maintaining security through isolated execution environments</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="not-prose mb-8 p-6 bg-accent/10 rounded-lg border border-accent/20">
|
||||
<h2 className="text-2xl font-bold mb-3">Security & Control</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Every operation performed by AI agents is logged and requires approval. Agents run in isolated Docker
|
||||
containers with restricted permissions, ensuring your codebase and system remain secure.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="not-prose mt-12 p-8 bg-gradient-to-br from-primary/10 to-accent/10 rounded-lg border border-border text-center">
|
||||
<h2 className="text-2xl font-bold mb-4">Ready to Get Started?</h2>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Check out our guides to install and configure kandev.ai
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center">
|
||||
<a
|
||||
href="/docs/installation"
|
||||
className="inline-flex items-center justify-center px-6 py-3 rounded-md bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors"
|
||||
>
|
||||
Installation Guide
|
||||
</a>
|
||||
<a
|
||||
href="/docs/quick-start"
|
||||
className="inline-flex items-center justify-center px-6 py-3 rounded-md border border-border bg-background hover:bg-muted font-medium transition-colors"
|
||||
>
|
||||
Quick Start Tutorial
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section className="grid gap-4 md:grid-cols-3">
|
||||
<DocsCard title="Workspaces">
|
||||
<p>Group repositories, boards, and team settings.</p>
|
||||
</DocsCard>
|
||||
<DocsCard title="Boards" variant="accent">
|
||||
<p>Model your workflow with Kanban columns.</p>
|
||||
</DocsCard>
|
||||
<DocsCard title="Tasks">
|
||||
<p>Define the scope, constraints, and agent requirements.</p>
|
||||
</DocsCard>
|
||||
</section>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
step: '1. Create a workspace',
|
||||
body: 'Create a workspace for the repository you want to manage.',
|
||||
},
|
||||
{
|
||||
step: '2. Add a board and task',
|
||||
body: 'Add a board with columns, then create a task that describes the desired change.',
|
||||
},
|
||||
{
|
||||
step: '3. Run an agent',
|
||||
body: 'Start an agent from the task. The UI should stream progress updates as the agent works.',
|
||||
},
|
||||
{
|
||||
step: '4. Review and merge',
|
||||
body: 'Review the diff, approve any gated actions, and merge the worktree.',
|
||||
},
|
||||
];
|
||||
|
||||
export default function QuickStartDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Getting Started"
|
||||
title="Quick Start"
|
||||
description="This guide walks through a minimal workflow so you can see the agent loop end-to-end."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
{steps.map((item) => (
|
||||
<DocsCard key={item.step} title={item.step}>
|
||||
<p>{item.body}</p>
|
||||
</DocsCard>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<DocsCard title="Example task prompt" variant="muted">
|
||||
<DocsCode>{`Task: Update onboarding copy
|
||||
Constraints: Touch only apps/landing
|
||||
Acceptance: Copy updated and passes lint`}</DocsCode>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function TasksDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Core Concepts"
|
||||
title="Tasks"
|
||||
description="Tasks capture the work that agents will execute. A good task includes a goal, constraints, and the desired output so the agent can plan accurately."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="Recommended fields">
|
||||
<ul className="space-y-2">
|
||||
<li>Title and description</li>
|
||||
<li>Priority and due date</li>
|
||||
<li>Repository and base branch</li>
|
||||
<li>Agent type and environment</li>
|
||||
<li>Approval requirements</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
<DocsCard title="Writing effective tasks" variant="accent">
|
||||
<ol className="space-y-2 list-decimal list-inside">
|
||||
<li>State the outcome, not the steps.</li>
|
||||
<li>Call out sensitive files or commands.</li>
|
||||
<li>Include acceptance criteria.</li>
|
||||
</ol>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<DocsCard title="Example task" variant="muted">
|
||||
<DocsCode>{`Title: Add changelog page
|
||||
Repo: github.com/kdlbs/kandev
|
||||
Branch: main
|
||||
Agent: augment-agent
|
||||
Goal: Replace blog with changelog
|
||||
Constraints: Keep existing navbar/footer
|
||||
Output: New route + MDX entries`}</DocsCode>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
export default function WorkspacesDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Core Concepts"
|
||||
title="Workspaces"
|
||||
description="Workspaces are the top-level container in kandev.ai. They group repositories, boards, agent settings, and members so teams can ship without stepping on each other."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-2">
|
||||
<DocsCard title="What a workspace includes">
|
||||
<ul className="space-y-2">
|
||||
<li>Boards that define workflow stages</li>
|
||||
<li>Repositories connected to those boards</li>
|
||||
<li>Default agent settings and approvals</li>
|
||||
<li>Member roles and permissions</li>
|
||||
</ul>
|
||||
</DocsCard>
|
||||
<DocsCard title="Best practices" variant="accent">
|
||||
<ol className="space-y-2 list-decimal list-inside">
|
||||
<li>Use one workspace per product or client.</li>
|
||||
<li>Keep board naming consistent across teams.</li>
|
||||
<li>Set approvals at the workspace level.</li>
|
||||
</ol>
|
||||
</DocsCard>
|
||||
</section>
|
||||
|
||||
<DocsCard title="Example structure" variant="muted">
|
||||
<p>A workspace keeps everything organized in one place.</p>
|
||||
<DocsCode>{`Workspace: "Core Platform"
|
||||
Boards:
|
||||
- Product Roadmap
|
||||
- Incident Response
|
||||
Repositories:
|
||||
- github.com/kdlbs/kandev
|
||||
- github.com/kdlbs/kandev-docs`}</DocsCode>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { DocsShell } from '@/components/docs-shell';
|
||||
import { DocsCard } from '@/components/docs-card';
|
||||
import { DocsCode } from '@/components/docs-code';
|
||||
|
||||
const benefits = [
|
||||
{ title: 'Parallel tasks', desc: 'Multiple agents can work without branch collisions.' },
|
||||
{ title: 'Clean diffs', desc: 'Each task produces an isolated patch.' },
|
||||
{ title: 'Fast setup', desc: 'No extra clones required.' },
|
||||
];
|
||||
|
||||
export default function WorktreesDocsPage() {
|
||||
return (
|
||||
<DocsShell
|
||||
eyebrow="Features"
|
||||
title="Git Worktrees"
|
||||
description="kandev.ai uses git worktrees to isolate each agent run. Every task gets its own directory that shares the same repository history while keeping file changes separate."
|
||||
>
|
||||
<section className="grid gap-4 md:grid-cols-3">
|
||||
{benefits.map((item) => (
|
||||
<DocsCard key={item.title} title={item.title}>
|
||||
<p>{item.desc}</p>
|
||||
</DocsCard>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<DocsCard title="How it looks on disk" variant="muted">
|
||||
<DocsCode>{`/repos/kandev
|
||||
/main (primary checkout)
|
||||
/.worktrees/task-123
|
||||
/.worktrees/task-124`}</DocsCode>
|
||||
</DocsCard>
|
||||
|
||||
<DocsCard title="Cleanup" variant="accent">
|
||||
<p>
|
||||
When a task is completed and merged, the worktree can be safely removed without affecting the main checkout.
|
||||
</p>
|
||||
</DocsCard>
|
||||
</DocsShell>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
type ChangelogVideoProps = {
|
||||
src: string;
|
||||
poster?: string;
|
||||
caption?: string;
|
||||
} & HTMLAttributes<HTMLVideoElement>;
|
||||
|
||||
export function ChangelogVideo({ src, poster, caption, className, ...props }: ChangelogVideoProps) {
|
||||
return (
|
||||
<figure className="mt-6">
|
||||
<video
|
||||
className={`w-full rounded-2xl border border-border bg-muted/40 ${className ?? ''}`}
|
||||
src={src}
|
||||
poster={poster}
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
preload="metadata"
|
||||
{...props}
|
||||
/>
|
||||
{caption ? (
|
||||
<figcaption className="mt-2 text-sm text-muted-foreground">{caption}</figcaption>
|
||||
) : null}
|
||||
</figure>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export function DocsCard({
|
||||
title,
|
||||
children,
|
||||
variant = 'default',
|
||||
}: {
|
||||
title: string;
|
||||
children: ReactNode;
|
||||
variant?: 'default' | 'accent' | 'muted';
|
||||
}) {
|
||||
const base =
|
||||
'rounded-2xl border border-border/60 bg-card/50 p-6 shadow-[0_12px_40px_-28px_rgba(37,99,235,0.5)] backdrop-blur';
|
||||
const variants: Record<typeof variant, string> = {
|
||||
default: 'bg-card/50',
|
||||
accent: 'border-primary/30 bg-primary/10',
|
||||
muted: 'bg-muted/30',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${base} ${variants[variant]}`}>
|
||||
<h2 className="text-lg font-semibold text-foreground">{title}</h2>
|
||||
<div className="mt-3 text-sm text-muted-foreground">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export function DocsCode({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<pre className="mt-4 rounded-xl border border-primary/30 bg-background/80 p-4 text-sm text-foreground shadow-[0_16px_30px_-24px_rgba(59,130,246,0.6)]">
|
||||
<code>{children}</code>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export function DocsShell({
|
||||
eyebrow,
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
}: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
description: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="relative overflow-hidden">
|
||||
<div className="absolute inset-0 -z-10 " />
|
||||
<div className="space-y-10">
|
||||
<header className="space-y-3">
|
||||
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">{eyebrow}</p>
|
||||
<h1 className="text-4xl font-semibold text-foreground">{title}</h1>
|
||||
<p className="text-lg text-muted-foreground">{description}</p>
|
||||
</header>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -29,34 +29,13 @@ const sections = [
|
||||
{ title: 'Docker Execution', href: '/docs/docker' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Integrations',
|
||||
items: [
|
||||
{ title: 'MCP Servers', href: '/docs/mcp' },
|
||||
{ title: 'GitHub', href: '/docs/github' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
items: [
|
||||
{ title: 'Approval Workflows', href: '/docs/approvals' },
|
||||
{ title: 'Audit Logs', href: '/docs/audit-logs' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Advanced',
|
||||
items: [
|
||||
{ title: 'Configuration', href: '/docs/configuration' },
|
||||
{ title: 'CLI Reference', href: '/docs/cli' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function DocsSidebar() {
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<aside className="sticky top-14 h-[calc(100vh-3.5rem)] w-64 shrink-0 overflow-y-auto border-r border-border py-8 pr-6">
|
||||
<aside className="sticky top-22 h-[calc(100vh-3.5rem)] w-64 shrink-0 overflow-y-auto border-r border-border py-8 pr-6">
|
||||
<nav className="space-y-6">
|
||||
{sections.map((section) => (
|
||||
<div key={section.title}>
|
||||
|
||||
@@ -36,8 +36,8 @@ export function Footer() {
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/blog" className="text-muted-foreground hover:text-foreground">
|
||||
Blog
|
||||
<Link href="/changelog" className="text-muted-foreground hover:text-foreground">
|
||||
Changelog
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -16,56 +16,48 @@ export function HeroSection() {
|
||||
|
||||
return (
|
||||
<section className="relative overflow-hidden">
|
||||
{/* Animated gradient cloud */}
|
||||
<div className="absolute inset-0 -z-10 flex items-center justify-center">
|
||||
<div
|
||||
className="absolute w-[800px] h-[800px] rounded-full filter blur-3xl opacity-60 animate-pulse-slow"
|
||||
style={{
|
||||
background: 'radial-gradient(circle, rgba(133, 110, 232, 0.3) 0%, rgba(177, 140, 254, 0.15) 40%, transparent 70%)'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="container mx-auto max-w-6xl flex flex-col items-center gap-8 px-4 pt-32 pb-16 md:pt-40 md:pb-24">
|
||||
<Badge variant="secondary" className="cursor-pointer border border-border px-6 py-3">
|
||||
<span className="text-sm">kandev.ai – AI-powered Kanban for developers</span>
|
||||
</Badge>
|
||||
<h1 className="max-w-4xl text-center text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl">
|
||||
Kanban meets <span className="text-primary">AI development</span>
|
||||
</h1>
|
||||
<p className="max-w-2xl text-center text-lg text-muted-foreground md:text-xl">
|
||||
Manage development tasks with isolated git worktrees, secure Docker execution, and AI agents.
|
||||
Ship faster without breaking your workflow.
|
||||
</p>
|
||||
<div className="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<Button size="lg" asChild className="cursor-pointer">
|
||||
<a href="#features">Get Started</a>
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" asChild className="cursor-pointer">
|
||||
<a href="#demo">Watch Demo</a>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-8 w-full max-w-2xl">
|
||||
<div className="flex items-center justify-center gap-2 rounded-lg border border-border bg-card p-4">
|
||||
<code className="flex-1 text-sm font-mono text-foreground">npx kandev</code>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
onClick={copyCommand}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{copied ? (
|
||||
<IconCheck className="h-4 w-4 text-green-500" />
|
||||
) : (
|
||||
<IconCopy className="h-4 w-4" />
|
||||
)}
|
||||
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
|
||||
<div className="container mx-auto max-w-6xl flex flex-col items-center gap-8 px-4 pt-16 pb-16 md:pb-24">
|
||||
<Badge variant="secondary" className="cursor-pointer border border-border px-6 py-3">
|
||||
<span className="text-sm">kandev.ai – AI-powered Kanban for developers</span>
|
||||
</Badge>
|
||||
<h1 className="max-w-4xl text-center text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl">
|
||||
Kanban meets <span className="text-primary">AI development</span>
|
||||
</h1>
|
||||
<p className="max-w-2xl text-center text-lg text-muted-foreground md:text-xl">
|
||||
Manage development tasks with isolated git worktrees, secure Docker execution, and AI agents.
|
||||
Ship faster without breaking your workflow.
|
||||
</p>
|
||||
<div className="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<Button size="lg" asChild className="cursor-pointer">
|
||||
<a href="#features">Get Started</a>
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" asChild className="cursor-pointer">
|
||||
<a href="#demo">Watch Demo</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 w-full max-w-5xl">
|
||||
<div className="aspect-video rounded-lg border border-border bg-muted flex items-center justify-center">
|
||||
<p className="text-muted-foreground">Video placeholder</p>
|
||||
<div className="mt-8 w-full max-w-2xl">
|
||||
<div className="flex items-center justify-center gap-2 rounded-lg border border-border bg-card p-4">
|
||||
<code className="flex-1 text-sm font-mono text-foreground">npx kandev</code>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
onClick={copyCommand}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{copied ? (
|
||||
<IconCheck className="h-4 w-4 text-green-500" />
|
||||
) : (
|
||||
<IconCopy className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 w-full max-w-5xl">
|
||||
<div className="aspect-video rounded-lg border border-border bg-muted flex items-center justify-center">
|
||||
<p className="text-muted-foreground">Video placeholder</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { ComponentProps, ReactElement } from 'react';
|
||||
import { ChangelogVideo } from '@/components/changelog-video';
|
||||
|
||||
function MdxHeading({ className, ...props }: ComponentProps<'h2'>) {
|
||||
return <h2 className={`mt-10 text-2xl font-semibold text-foreground ${className ?? ''}`} {...props} />;
|
||||
}
|
||||
|
||||
function MdxSubheading({ className, ...props }: ComponentProps<'h3'>) {
|
||||
return <h3 className={`mt-8 text-xl font-semibold text-foreground ${className ?? ''}`} {...props} />;
|
||||
}
|
||||
|
||||
function MdxParagraph({ className, ...props }: ComponentProps<'p'>) {
|
||||
return <p className={`mt-4 text-base leading-relaxed text-muted-foreground ${className ?? ''}`} {...props} />;
|
||||
}
|
||||
|
||||
function MdxList({ className, ...props }: ComponentProps<'ul'>) {
|
||||
return <ul className={`mt-4 space-y-2 pl-6 text-muted-foreground ${className ?? ''}`} {...props} />;
|
||||
}
|
||||
|
||||
function MdxListItem({ className, ...props }: ComponentProps<'li'>) {
|
||||
return <li className={`list-disc text-base ${className ?? ''}`} {...props} />;
|
||||
}
|
||||
|
||||
function MdxImage({ className, alt, ...props }: ComponentProps<'img'>): ReactElement {
|
||||
return (
|
||||
<img
|
||||
className={`mt-6 w-full rounded-2xl border border-border bg-muted/40 ${className ?? ''}`}
|
||||
alt={alt ?? ''}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const mdxComponents = {
|
||||
h2: MdxHeading,
|
||||
h3: MdxSubheading,
|
||||
p: MdxParagraph,
|
||||
ul: MdxList,
|
||||
li: MdxListItem,
|
||||
img: MdxImage,
|
||||
ChangelogVideo,
|
||||
};
|
||||
@@ -37,13 +37,13 @@ export function Navbar() {
|
||||
Documentation
|
||||
</Link>
|
||||
<Link
|
||||
href="/blog"
|
||||
href="/changelog"
|
||||
className={cn(
|
||||
'text-sm font-medium transition-colors hover:text-foreground cursor-pointer',
|
||||
pathname?.startsWith('/blog') ? 'text-foreground' : 'text-muted-foreground'
|
||||
pathname?.startsWith('/changelog') ? 'text-foreground' : 'text-muted-foreground'
|
||||
)}
|
||||
>
|
||||
Blog
|
||||
Changelog
|
||||
</Link>
|
||||
</nav>
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "kandev.ai Launch"
|
||||
date: "2026-01-17"
|
||||
surface: "Platform"
|
||||
summary:
|
||||
- "kandev.ai ships a WebSocket-first Kanban + AI agent workflow for developer teams."
|
||||
- "Tasks run inside isolated git worktrees and Docker containers with approval gates."
|
||||
---
|
||||
|
||||
## What is kandev.ai?
|
||||
|
||||
kandev.ai is a Kanban-native development platform that pairs task management with AI agents. Every task can be executed by an agent in a clean, isolated environment, while you keep control over approvals and merge decisions.
|
||||
|
||||

|
||||
|
||||
## Initial launch features
|
||||
|
||||
- **Kanban boards for engineering work** with task metadata, priorities, and agent selection.
|
||||
- **Isolated git worktrees** so parallel tasks never collide.
|
||||
- **Docker-based execution** for secure, repeatable runs.
|
||||
- **Agent control plane** via `agentctl` with start/stop/status and ACP relays.
|
||||
- **WebSocket-only client API** for real-time orchestration and updates.
|
||||
- **Approval gates** for sensitive paths and commands.
|
||||
|
||||
## How it works (high level)
|
||||
|
||||
1. The client opens a single WebSocket connection to the backend.
|
||||
2. The backend spins up an agent container with `agentctl` as a sidecar.
|
||||
3. The backend initializes ACP over stdin/stdout and creates a session.
|
||||
4. The task prompt is streamed to the agent and progress events flow back in real time.
|
||||
5. Results are reviewed, approved, and merged back into the main branch.
|
||||
|
||||

|
||||
|
||||
### What’s next
|
||||
|
||||
Expect expanded agent types, richer approvals, and deeper task analytics in upcoming releases.
|
||||
@@ -0,0 +1,71 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import matter from 'gray-matter';
|
||||
|
||||
export type ChangelogEntry = {
|
||||
slug: string;
|
||||
title: string;
|
||||
date: string;
|
||||
surface: string;
|
||||
summary: string[];
|
||||
content: string;
|
||||
};
|
||||
|
||||
const changelogRoot = path.join(process.cwd(), 'content', 'changelog');
|
||||
|
||||
function normalizeSummary(summary: unknown): string[] {
|
||||
if (Array.isArray(summary)) {
|
||||
return summary.filter((item): item is string => typeof item === 'string');
|
||||
}
|
||||
if (typeof summary === 'string') {
|
||||
return [summary];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function parseEntry(slug: string, fileContent: string): ChangelogEntry {
|
||||
const { data, content } = matter(fileContent);
|
||||
|
||||
return {
|
||||
slug,
|
||||
title: String(data.title ?? slug),
|
||||
date: String(data.date ?? ''),
|
||||
surface: String(data.surface ?? 'Product'),
|
||||
summary: normalizeSummary(data.summary),
|
||||
content,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getChangelogEntries(): Promise<ChangelogEntry[]> {
|
||||
const entries = await fs.readdir(changelogRoot, { withFileTypes: true });
|
||||
const slugs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
||||
|
||||
const items = await Promise.all(
|
||||
slugs.map(async (slug) => {
|
||||
const entryPath = path.join(changelogRoot, slug, 'index.mdx');
|
||||
const fileContent = await fs.readFile(entryPath, 'utf8');
|
||||
return parseEntry(slug, fileContent);
|
||||
})
|
||||
);
|
||||
|
||||
return items.sort((a, b) => {
|
||||
const aTime = new Date(a.date).getTime();
|
||||
const bTime = new Date(b.date).getTime();
|
||||
return bTime - aTime;
|
||||
});
|
||||
}
|
||||
|
||||
export async function getChangelogEntry(slug: string): Promise<ChangelogEntry | null> {
|
||||
const entryPath = path.join(changelogRoot, slug, 'index.mdx');
|
||||
try {
|
||||
const fileContent = await fs.readFile(entryPath, 'utf8');
|
||||
return parseEntry(slug, fileContent);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getChangelogSlugs(): Promise<string[]> {
|
||||
const entries = await fs.readdir(changelogRoot, { withFileTypes: true });
|
||||
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
||||
}
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/types/routes.d.ts";
|
||||
import "./.next/dev/types/routes.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
"clsx": "^2.1.1",
|
||||
"next": "16.1.1",
|
||||
"next-themes": "^0.4.6",
|
||||
"next-mdx-remote": "^5.0.0",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"gray-matter": "^4.0.3",
|
||||
"shadcn": "^3.6.3",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tw-animate-css": "^1.4.0"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<svg width="1200" height="640" viewBox="0 0 1200 640" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1200" height="640" rx="32" fill="#0B1220"/>
|
||||
<rect x="80" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="360" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="640" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="920" y="120" width="200" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
|
||||
<path d="M320 180H360" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
|
||||
<path d="M600 180H640" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
|
||||
<path d="M880 180H920" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
|
||||
<text x="110" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Client WS</text>
|
||||
<text x="390" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Backend</text>
|
||||
<text x="670" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">agentctl</text>
|
||||
<text x="950" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Agent</text>
|
||||
<rect x="80" y="300" width="1040" height="200" rx="24" fill="#0F172A" stroke="#1E293B" stroke-width="2"/>
|
||||
<text x="120" y="360" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">orchestrator.start → /api/v1/start → ACP initialize/session/prompt → session/update</text>
|
||||
<text x="120" y="400" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">Real-time progress streamed back over WebSocket</text>
|
||||
<text x="96" y="96" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="24" font-weight="600">High-level execution flow</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg width="1200" height="640" viewBox="0 0 1200 640" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1200" height="640" rx="32" fill="#0B1120"/>
|
||||
<rect x="64" y="72" width="1072" height="496" rx="28" fill="#111827" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="104" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="448" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="792" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
|
||||
<rect x="104" y="272" width="640" height="44" rx="14" fill="#1E293B"/>
|
||||
<rect x="104" y="332" width="560" height="44" rx="14" fill="#1E293B"/>
|
||||
<rect x="104" y="392" width="480" height="44" rx="14" fill="#1E293B"/>
|
||||
<circle cx="980" cy="364" r="82" fill="#0F172A" stroke="#38BDF8" stroke-width="3"/>
|
||||
<path d="M940 364L968 392L1024 336" stroke="#38BDF8" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="104" y="112" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="24" font-weight="600">kandev.ai Launch</text>
|
||||
<text x="104" y="500" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">Kanban + AI agents with secure execution</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
Generated
+470
-2
@@ -29,9 +29,15 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
gray-matter:
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3
|
||||
next:
|
||||
specifier: 16.1.1
|
||||
version: 16.1.1(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next-mdx-remote:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0(@types/react@19.2.8)(react@19.2.3)
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
@@ -68,7 +74,7 @@ importers:
|
||||
version: 9.39.2(jiti@2.6.1)
|
||||
eslint-config-next:
|
||||
specifier: 16.1.1
|
||||
version: 16.1.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||
version: 16.1.1(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||
tailwindcss:
|
||||
specifier: ^4.0.0
|
||||
version: 4.1.18
|
||||
@@ -373,7 +379,7 @@ importers:
|
||||
version: 9.39.2(jiti@2.6.1)
|
||||
eslint-config-next:
|
||||
specifier: 16.1.1
|
||||
version: 16.1.1(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||
version: 16.1.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||
happy-dom:
|
||||
specifier: ^20.1.0
|
||||
version: 20.1.0
|
||||
@@ -1122,6 +1128,15 @@ packages:
|
||||
'@marijn/find-cluster-break@1.0.2':
|
||||
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
|
||||
|
||||
'@mdx-js/mdx@3.1.1':
|
||||
resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
|
||||
|
||||
'@mdx-js/react@3.1.1':
|
||||
resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
|
||||
peerDependencies:
|
||||
'@types/react': '>=16'
|
||||
react: '>=16'
|
||||
|
||||
'@modelcontextprotocol/sdk@1.25.2':
|
||||
resolution: {integrity: sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2268,6 +2283,9 @@ packages:
|
||||
'@types/mdast@4.0.4':
|
||||
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
|
||||
|
||||
'@types/mdx@2.0.13':
|
||||
resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
|
||||
|
||||
'@types/ms@2.1.0':
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
|
||||
@@ -2572,6 +2590,9 @@ packages:
|
||||
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
argparse@1.0.10:
|
||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
@@ -2625,6 +2646,10 @@ packages:
|
||||
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
astring@1.9.0:
|
||||
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
|
||||
hasBin: true
|
||||
|
||||
async-function@1.0.0:
|
||||
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2769,6 +2794,9 @@ packages:
|
||||
codemirror@6.0.2:
|
||||
resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
|
||||
|
||||
collapse-white-space@2.1.0:
|
||||
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -3095,6 +3123,12 @@ packages:
|
||||
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esast-util-from-estree@2.0.0:
|
||||
resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
|
||||
|
||||
esast-util-from-js@2.0.1:
|
||||
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
|
||||
|
||||
esbuild@0.21.5:
|
||||
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -3232,9 +3266,24 @@ packages:
|
||||
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
estree-util-attach-comments@3.0.0:
|
||||
resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
|
||||
|
||||
estree-util-build-jsx@3.0.1:
|
||||
resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
|
||||
|
||||
estree-util-is-identifier-name@3.0.0:
|
||||
resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
|
||||
|
||||
estree-util-scope@1.0.0:
|
||||
resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
|
||||
|
||||
estree-util-to-js@2.0.0:
|
||||
resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
|
||||
|
||||
estree-util-visit@2.0.0:
|
||||
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
@@ -3279,6 +3328,10 @@ packages:
|
||||
resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
extend-shallow@2.0.1:
|
||||
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
extend@3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
|
||||
@@ -3478,6 +3531,10 @@ packages:
|
||||
resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==}
|
||||
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
|
||||
|
||||
gray-matter@4.0.3:
|
||||
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
|
||||
engines: {node: '>=6.0'}
|
||||
|
||||
happy-dom@20.1.0:
|
||||
resolution: {integrity: sha512-ebvqjBqzenBk2LjzNEAzoj7yhw7rW/R2/wVevMu6Mrq3MXtcI/RUz4+ozpcOcqVLEWPqLfg2v9EAU7fFXZUUJw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
@@ -3509,6 +3566,9 @@ packages:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hast-util-to-estree@3.1.3:
|
||||
resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
|
||||
|
||||
hast-util-to-jsx-runtime@2.3.6:
|
||||
resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
|
||||
|
||||
@@ -3654,6 +3714,10 @@ packages:
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
hasBin: true
|
||||
|
||||
is-extendable@0.1.1:
|
||||
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-extglob@2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3811,6 +3875,10 @@ packages:
|
||||
js-tokens@9.0.1:
|
||||
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
|
||||
|
||||
js-yaml@3.14.2:
|
||||
resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
|
||||
hasBin: true
|
||||
|
||||
js-yaml@4.1.1:
|
||||
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
|
||||
hasBin: true
|
||||
@@ -3857,6 +3925,10 @@ packages:
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
kind-of@6.0.3:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
kleur@3.0.3:
|
||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3986,6 +4058,10 @@ packages:
|
||||
magic-string@0.30.21:
|
||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||
|
||||
markdown-extensions@2.0.0:
|
||||
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
markdown-table@3.0.4:
|
||||
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
|
||||
|
||||
@@ -4023,6 +4099,9 @@ packages:
|
||||
mdast-util-mdx-jsx@3.2.0:
|
||||
resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
|
||||
|
||||
mdast-util-mdx@3.0.0:
|
||||
resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
|
||||
|
||||
mdast-util-mdxjs-esm@2.0.1:
|
||||
resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
|
||||
|
||||
@@ -4080,12 +4159,30 @@ packages:
|
||||
micromark-extension-gfm@3.0.0:
|
||||
resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
|
||||
|
||||
micromark-extension-mdx-expression@3.0.1:
|
||||
resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
|
||||
|
||||
micromark-extension-mdx-jsx@3.0.2:
|
||||
resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
|
||||
|
||||
micromark-extension-mdx-md@2.0.0:
|
||||
resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
|
||||
|
||||
micromark-extension-mdxjs-esm@3.0.0:
|
||||
resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
|
||||
|
||||
micromark-extension-mdxjs@3.0.0:
|
||||
resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
|
||||
|
||||
micromark-factory-destination@2.0.1:
|
||||
resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
|
||||
|
||||
micromark-factory-label@2.0.1:
|
||||
resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
|
||||
|
||||
micromark-factory-mdx-expression@2.0.3:
|
||||
resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
|
||||
|
||||
micromark-factory-space@2.0.1:
|
||||
resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
|
||||
|
||||
@@ -4116,6 +4213,9 @@ packages:
|
||||
micromark-util-encode@2.0.1:
|
||||
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
|
||||
|
||||
micromark-util-events-to-acorn@2.0.3:
|
||||
resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
|
||||
|
||||
micromark-util-html-tag-name@2.0.1:
|
||||
resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
|
||||
|
||||
@@ -4215,6 +4315,12 @@ packages:
|
||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
next-mdx-remote@5.0.0:
|
||||
resolution: {integrity: sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ==}
|
||||
engines: {node: '>=14', npm: '>=7'}
|
||||
peerDependencies:
|
||||
react: '>=16'
|
||||
|
||||
next-themes@0.4.6:
|
||||
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
|
||||
peerDependencies:
|
||||
@@ -4597,6 +4703,20 @@ packages:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
recma-build-jsx@1.0.0:
|
||||
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
|
||||
|
||||
recma-jsx@1.0.1:
|
||||
resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
|
||||
recma-parse@1.0.0:
|
||||
resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
|
||||
|
||||
recma-stringify@1.0.0:
|
||||
resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -4605,12 +4725,18 @@ packages:
|
||||
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
rehype-recma@1.0.0:
|
||||
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
|
||||
|
||||
remark-breaks@4.0.0:
|
||||
resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==}
|
||||
|
||||
remark-gfm@4.0.1:
|
||||
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
|
||||
|
||||
remark-mdx@3.1.1:
|
||||
resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
|
||||
|
||||
remark-parse@11.0.0:
|
||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||
|
||||
@@ -4692,6 +4818,10 @@ packages:
|
||||
scheduler@0.27.0:
|
||||
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||
|
||||
section-matter@1.0.0:
|
||||
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
semver@6.3.1:
|
||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||
hasBin: true
|
||||
@@ -4783,9 +4913,16 @@ packages:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map@0.7.6:
|
||||
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
space-separated-tokens@2.0.2:
|
||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||
|
||||
sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
|
||||
stable-hash@0.0.5:
|
||||
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
||||
|
||||
@@ -4856,6 +4993,10 @@ packages:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-bom-string@1.0.0:
|
||||
resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
strip-bom@3.0.0:
|
||||
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -5059,15 +5200,27 @@ packages:
|
||||
unified@11.0.5:
|
||||
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
||||
|
||||
unist-util-is@5.2.1:
|
||||
resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
|
||||
|
||||
unist-util-is@6.0.1:
|
||||
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
||||
|
||||
unist-util-position-from-estree@2.0.0:
|
||||
resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
|
||||
|
||||
unist-util-position@5.0.0:
|
||||
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
|
||||
|
||||
unist-util-remove@3.1.1:
|
||||
resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==}
|
||||
|
||||
unist-util-stringify-position@4.0.0:
|
||||
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
|
||||
|
||||
unist-util-visit-parents@5.1.3:
|
||||
resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
|
||||
|
||||
unist-util-visit-parents@6.0.2:
|
||||
resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
|
||||
|
||||
@@ -5139,6 +5292,9 @@ packages:
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
|
||||
|
||||
vfile-matter@5.0.1:
|
||||
resolution: {integrity: sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw==}
|
||||
|
||||
vfile-message@4.0.3:
|
||||
resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
|
||||
|
||||
@@ -5289,6 +5445,11 @@ packages:
|
||||
yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
|
||||
yaml@2.8.2:
|
||||
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
yargs-parser@21.1.1:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -6176,6 +6337,42 @@ snapshots:
|
||||
|
||||
'@marijn/find-cluster-break@1.0.2': {}
|
||||
|
||||
'@mdx-js/mdx@3.1.1':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree-jsx': 1.0.5
|
||||
'@types/hast': 3.0.4
|
||||
'@types/mdx': 2.0.13
|
||||
acorn: 8.15.0
|
||||
collapse-white-space: 2.1.0
|
||||
devlop: 1.1.0
|
||||
estree-util-is-identifier-name: 3.0.0
|
||||
estree-util-scope: 1.0.0
|
||||
estree-walker: 3.0.3
|
||||
hast-util-to-jsx-runtime: 2.3.6
|
||||
markdown-extensions: 2.0.0
|
||||
recma-build-jsx: 1.0.0
|
||||
recma-jsx: 1.0.1(acorn@8.15.0)
|
||||
recma-stringify: 1.0.0
|
||||
rehype-recma: 1.0.0
|
||||
remark-mdx: 3.1.1
|
||||
remark-parse: 11.0.0
|
||||
remark-rehype: 11.1.2
|
||||
source-map: 0.7.6
|
||||
unified: 11.0.5
|
||||
unist-util-position-from-estree: 2.0.0
|
||||
unist-util-stringify-position: 4.0.0
|
||||
unist-util-visit: 5.0.0
|
||||
vfile: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@mdx-js/react@3.1.1(@types/react@19.2.8)(react@19.2.3)':
|
||||
dependencies:
|
||||
'@types/mdx': 2.0.13
|
||||
'@types/react': 19.2.8
|
||||
react: 19.2.3
|
||||
|
||||
'@modelcontextprotocol/sdk@1.25.2(hono@4.11.3)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@hono/node-server': 1.19.8(hono@4.11.3)
|
||||
@@ -7284,6 +7481,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
'@types/mdx@2.0.13': {}
|
||||
|
||||
'@types/ms@2.1.0': {}
|
||||
|
||||
'@types/node@20.19.28':
|
||||
@@ -7591,6 +7790,10 @@ snapshots:
|
||||
|
||||
ansis@4.2.0: {}
|
||||
|
||||
argparse@1.0.10:
|
||||
dependencies:
|
||||
sprintf-js: 1.0.3
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
aria-hidden@1.2.6:
|
||||
@@ -7674,6 +7877,8 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
astring@1.9.0: {}
|
||||
|
||||
async-function@1.0.0: {}
|
||||
|
||||
available-typed-arrays@1.0.7:
|
||||
@@ -7831,6 +8036,8 @@ snapshots:
|
||||
'@codemirror/state': 6.5.3
|
||||
'@codemirror/view': 6.39.10
|
||||
|
||||
collapse-white-space@2.1.0: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -8170,6 +8377,20 @@ snapshots:
|
||||
is-date-object: 1.1.0
|
||||
is-symbol: 1.1.1
|
||||
|
||||
esast-util-from-estree@2.0.0:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
devlop: 1.1.0
|
||||
estree-util-visit: 2.0.0
|
||||
unist-util-position-from-estree: 2.0.0
|
||||
|
||||
esast-util-from-js@2.0.1:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
acorn: 8.15.0
|
||||
esast-util-from-estree: 2.0.0
|
||||
vfile-message: 4.0.3
|
||||
|
||||
esbuild@0.21.5:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.21.5
|
||||
@@ -8454,8 +8675,35 @@ snapshots:
|
||||
|
||||
estraverse@5.3.0: {}
|
||||
|
||||
estree-util-attach-comments@3.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
|
||||
estree-util-build-jsx@3.0.1:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
devlop: 1.1.0
|
||||
estree-util-is-identifier-name: 3.0.0
|
||||
estree-walker: 3.0.3
|
||||
|
||||
estree-util-is-identifier-name@3.0.0: {}
|
||||
|
||||
estree-util-scope@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
devlop: 1.1.0
|
||||
|
||||
estree-util-to-js@2.0.0:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
astring: 1.9.0
|
||||
source-map: 0.7.6
|
||||
|
||||
estree-util-visit@2.0.0:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
estree-walker@3.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
@@ -8548,6 +8796,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
extend-shallow@2.0.1:
|
||||
dependencies:
|
||||
is-extendable: 0.1.1
|
||||
|
||||
extend@3.0.2: {}
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
@@ -8738,6 +8990,13 @@ snapshots:
|
||||
|
||||
graphql@16.12.0: {}
|
||||
|
||||
gray-matter@4.0.3:
|
||||
dependencies:
|
||||
js-yaml: 3.14.2
|
||||
kind-of: 6.0.3
|
||||
section-matter: 1.0.0
|
||||
strip-bom-string: 1.0.0
|
||||
|
||||
happy-dom@20.1.0:
|
||||
dependencies:
|
||||
'@types/node': 20.19.28
|
||||
@@ -8771,6 +9030,27 @@ snapshots:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
hast-util-to-estree@3.1.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree-jsx': 1.0.5
|
||||
'@types/hast': 3.0.4
|
||||
comma-separated-tokens: 2.0.3
|
||||
devlop: 1.1.0
|
||||
estree-util-attach-comments: 3.0.0
|
||||
estree-util-is-identifier-name: 3.0.0
|
||||
hast-util-whitespace: 3.0.0
|
||||
mdast-util-mdx-expression: 2.0.1
|
||||
mdast-util-mdx-jsx: 3.2.0
|
||||
mdast-util-mdxjs-esm: 2.0.1
|
||||
property-information: 7.1.0
|
||||
space-separated-tokens: 2.0.2
|
||||
style-to-js: 1.1.21
|
||||
unist-util-position: 5.0.0
|
||||
zwitch: 2.0.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
hast-util-to-jsx-runtime@2.3.6:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
@@ -8923,6 +9203,8 @@ snapshots:
|
||||
|
||||
is-docker@3.0.0: {}
|
||||
|
||||
is-extendable@0.1.1: {}
|
||||
|
||||
is-extglob@2.1.1: {}
|
||||
|
||||
is-finalizationregistry@1.1.1:
|
||||
@@ -9050,6 +9332,11 @@ snapshots:
|
||||
|
||||
js-tokens@9.0.1: {}
|
||||
|
||||
js-yaml@3.14.2:
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
esprima: 4.0.1
|
||||
|
||||
js-yaml@4.1.1:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
@@ -9091,6 +9378,8 @@ snapshots:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
||||
kind-of@6.0.3: {}
|
||||
|
||||
kleur@3.0.3: {}
|
||||
|
||||
kleur@4.1.5: {}
|
||||
@@ -9199,6 +9488,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
markdown-extensions@2.0.0: {}
|
||||
|
||||
markdown-table@3.0.4: {}
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
@@ -9312,6 +9603,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
mdast-util-mdx@3.0.0:
|
||||
dependencies:
|
||||
mdast-util-from-markdown: 2.0.2
|
||||
mdast-util-mdx-expression: 2.0.1
|
||||
mdast-util-mdx-jsx: 3.2.0
|
||||
mdast-util-mdxjs-esm: 2.0.1
|
||||
mdast-util-to-markdown: 2.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
mdast-util-mdxjs-esm@2.0.1:
|
||||
dependencies:
|
||||
'@types/estree-jsx': 1.0.5
|
||||
@@ -9446,6 +9747,57 @@ snapshots:
|
||||
micromark-util-combine-extensions: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-extension-mdx-expression@3.0.1:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
devlop: 1.1.0
|
||||
micromark-factory-mdx-expression: 2.0.3
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-events-to-acorn: 2.0.3
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-extension-mdx-jsx@3.0.2:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
devlop: 1.1.0
|
||||
estree-util-is-identifier-name: 3.0.0
|
||||
micromark-factory-mdx-expression: 2.0.3
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-events-to-acorn: 2.0.3
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
vfile-message: 4.0.3
|
||||
|
||||
micromark-extension-mdx-md@2.0.0:
|
||||
dependencies:
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-extension-mdxjs-esm@3.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
devlop: 1.1.0
|
||||
micromark-core-commonmark: 2.0.3
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-events-to-acorn: 2.0.3
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
unist-util-position-from-estree: 2.0.0
|
||||
vfile-message: 4.0.3
|
||||
|
||||
micromark-extension-mdxjs@3.0.0:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
micromark-extension-mdx-expression: 3.0.1
|
||||
micromark-extension-mdx-jsx: 3.0.2
|
||||
micromark-extension-mdx-md: 2.0.0
|
||||
micromark-extension-mdxjs-esm: 3.0.0
|
||||
micromark-util-combine-extensions: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-factory-destination@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
@@ -9459,6 +9811,18 @@ snapshots:
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-factory-mdx-expression@2.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
devlop: 1.1.0
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-events-to-acorn: 2.0.3
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
unist-util-position-from-estree: 2.0.0
|
||||
vfile-message: 4.0.3
|
||||
|
||||
micromark-factory-space@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
@@ -9511,6 +9875,16 @@ snapshots:
|
||||
|
||||
micromark-util-encode@2.0.1: {}
|
||||
|
||||
micromark-util-events-to-acorn@2.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/unist': 3.0.3
|
||||
devlop: 1.1.0
|
||||
estree-util-visit: 2.0.0
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
vfile-message: 4.0.3
|
||||
|
||||
micromark-util-html-tag-name@2.0.1: {}
|
||||
|
||||
micromark-util-normalize-identifier@2.0.1:
|
||||
@@ -9635,6 +10009,19 @@ snapshots:
|
||||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
next-mdx-remote@5.0.0(@types/react@19.2.8)(react@19.2.3):
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.28.6
|
||||
'@mdx-js/mdx': 3.1.1
|
||||
'@mdx-js/react': 3.1.1(@types/react@19.2.8)(react@19.2.3)
|
||||
react: 19.2.3
|
||||
unist-util-remove: 3.1.1
|
||||
vfile: 6.0.3
|
||||
vfile-matter: 5.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
- supports-color
|
||||
|
||||
next-themes@0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
react: 19.2.3
|
||||
@@ -10110,6 +10497,35 @@ snapshots:
|
||||
tiny-invariant: 1.3.3
|
||||
victory-vendor: 36.9.2
|
||||
|
||||
recma-build-jsx@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
estree-util-build-jsx: 3.0.1
|
||||
vfile: 6.0.3
|
||||
|
||||
recma-jsx@1.0.1(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
estree-util-to-js: 2.0.0
|
||||
recma-parse: 1.0.0
|
||||
recma-stringify: 1.0.0
|
||||
unified: 11.0.5
|
||||
|
||||
recma-parse@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
esast-util-from-js: 2.0.1
|
||||
unified: 11.0.5
|
||||
vfile: 6.0.3
|
||||
|
||||
recma-stringify@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
estree-util-to-js: 2.0.0
|
||||
unified: 11.0.5
|
||||
vfile: 6.0.3
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@@ -10130,6 +10546,14 @@ snapshots:
|
||||
gopd: 1.2.0
|
||||
set-function-name: 2.0.2
|
||||
|
||||
rehype-recma@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/hast': 3.0.4
|
||||
hast-util-to-estree: 3.1.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-breaks@4.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@@ -10147,6 +10571,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-mdx@3.1.1:
|
||||
dependencies:
|
||||
mdast-util-mdx: 3.0.0
|
||||
micromark-extension-mdxjs: 3.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-parse@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@@ -10271,6 +10702,11 @@ snapshots:
|
||||
|
||||
scheduler@0.27.0: {}
|
||||
|
||||
section-matter@1.0.0:
|
||||
dependencies:
|
||||
extend-shallow: 2.0.1
|
||||
kind-of: 6.0.3
|
||||
|
||||
semver@6.3.1: {}
|
||||
|
||||
semver@7.7.3: {}
|
||||
@@ -10451,8 +10887,12 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
source-map@0.7.6: {}
|
||||
|
||||
space-separated-tokens@2.0.2: {}
|
||||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
stable-hash@0.0.5: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
@@ -10551,6 +10991,8 @@ snapshots:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
strip-bom-string@1.0.0: {}
|
||||
|
||||
strip-bom@3.0.0: {}
|
||||
|
||||
strip-final-newline@2.0.0: {}
|
||||
@@ -10746,18 +11188,37 @@ snapshots:
|
||||
trough: 2.2.0
|
||||
vfile: 6.0.3
|
||||
|
||||
unist-util-is@5.2.1:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
|
||||
unist-util-is@6.0.1:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
unist-util-position-from-estree@2.0.0:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
unist-util-position@5.0.0:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
unist-util-remove@3.1.1:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
unist-util-is: 5.2.1
|
||||
unist-util-visit-parents: 5.1.3
|
||||
|
||||
unist-util-stringify-position@4.0.0:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
unist-util-visit-parents@5.1.3:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
unist-util-is: 5.2.1
|
||||
|
||||
unist-util-visit-parents@6.0.2:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@@ -10843,6 +11304,11 @@ snapshots:
|
||||
- '@types/react'
|
||||
- '@types/react-dom'
|
||||
|
||||
vfile-matter@5.0.1:
|
||||
dependencies:
|
||||
vfile: 6.0.3
|
||||
yaml: 2.8.2
|
||||
|
||||
vfile-message@4.0.3:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@@ -11020,6 +11486,8 @@ snapshots:
|
||||
|
||||
yallist@3.1.1: {}
|
||||
|
||||
yaml@2.8.2: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
yargs@17.7.2:
|
||||
|
||||
Reference in New Issue
Block a user