diff --git a/apps/docs/app/[lang]/templates/[slug]/file-viewer.tsx b/apps/docs/app/[lang]/templates/[slug]/file-viewer.tsx index e98c8cf98..3f30ab94f 100644 --- a/apps/docs/app/[lang]/templates/[slug]/file-viewer.tsx +++ b/apps/docs/app/[lang]/templates/[slug]/file-viewer.tsx @@ -2,7 +2,9 @@ import { BotIcon, + BoxIcon, BracesIcon, + CalendarClockIcon, ChevronRightIcon, FileTextIcon, type LucideIcon, @@ -32,8 +34,12 @@ interface CategoryStyle { const categoryStyles: Record = { "agent.ts": { icon: SettingsIcon }, "instructions.md": { icon: FileTextIcon }, + "instructions.ts": { icon: FileTextIcon }, + "sandbox.ts": { icon: BoxIcon }, + sandbox: { icon: BoxIcon }, channels: { icon: MessageSquareIcon }, connections: { icon: PlugIcon }, + schedules: { icon: CalendarClockIcon }, skills: { icon: FileTextIcon }, tools: { icon: WrenchIcon }, subagents: { icon: BotIcon }, @@ -41,11 +47,19 @@ const categoryStyles: Record = { }; const defaultStyle: CategoryStyle = { icon: FileTextIcon }; + +// Keys absent from this list render last in encounter order, so every top-level +// name a template can author belongs here. Standalone files lead, folders follow; +// `sandbox` appears twice because templates author it as either a file or a folder. const categoryOrder = [ "agent.ts", "instructions.md", + "instructions.ts", + "sandbox.ts", + "sandbox", "channels", "connections", + "schedules", "skills", "tools", "subagents", diff --git a/apps/docs/app/[lang]/templates/integration-icons.tsx b/apps/docs/app/[lang]/templates/integration-icons.tsx index 034448267..1e2b6582e 100644 --- a/apps/docs/app/[lang]/templates/integration-icons.tsx +++ b/apps/docs/app/[lang]/templates/integration-icons.tsx @@ -1,15 +1,29 @@ import { BracesIcon } from "lucide-react"; import type { ComponentType, SVGProps } from "react"; -import { linearLogo, notionLogo, sentryLogo, slackLogo, webLogo } from "@/lib/integrations/logos"; +import { + githubLogo, + linearLogo, + notionLogo, + resendLogo, + sanityLogo, + sentryLogo, + slackLogo, + typefullyLogo, + webLogo, +} from "@/lib/integrations/logos"; import type { TemplateIntegration } from "@/lib/templates/data"; type IconComponent = ComponentType>; export const integrationIcons: Record = { + GitHub: githubLogo, "HTTP API": BracesIcon, Linear: linearLogo, Notion: notionLogo, + Resend: resendLogo, + Sanity: sanityLogo, Sentry: sentryLogo, Slack: slackLogo, + Typefully: typefullyLogo, "Web chat": webLogo, }; diff --git a/apps/docs/lib/integrations/logos.tsx b/apps/docs/lib/integrations/logos.tsx index 6c2697219..f767dd686 100644 --- a/apps/docs/lib/integrations/logos.tsx +++ b/apps/docs/lib/integrations/logos.tsx @@ -21,6 +21,7 @@ import { SiPosthog, SiPostman, SiRazorpay, + SiSanity, SiSentry, SiSimilarweb, SiStripe, @@ -230,6 +231,8 @@ export const postmanLogo = (props: LogoProps) => ; +export const sanityLogo = (props: LogoProps) => ; + export const sentryLogo = (props: LogoProps) => ; export const similarwebLogo = (props: LogoProps) => ; @@ -240,6 +243,15 @@ export const supabaseLogo = (props: LogoProps) => ; +export const typefullyLogo = (props: LogoProps) => ( + + + +); + export const todoistLogo = (props: LogoProps) => ; export const webflowLogo = (props: LogoProps) => ; diff --git a/apps/docs/lib/templates/data.ts b/apps/docs/lib/templates/data.ts index e6161bfec..9c4a4377a 100644 --- a/apps/docs/lib/templates/data.ts +++ b/apps/docs/lib/templates/data.ts @@ -2,11 +2,15 @@ export type TemplateCategory = "Chat" | "Collaboration" | "Example"; import { templateSourceFiles } from "./sources"; export type TemplateIntegration = + | "GitHub" | "HTTP API" | "Linear" | "Notion" + | "Resend" + | "Sanity" | "Sentry" | "Slack" + | "Typefully" | "Web chat"; export type TemplateSource = "GitHub" | "Vercel Templates"; @@ -76,6 +80,51 @@ export const templateEntries: TemplateEntry[] = [ source: "Vercel Templates", files: templateSourceFiles["eve-slack-agent"], }, + { + slug: "kody", + title: "GitHub", + setupPrompt: + "I want to build a GitHub maintainer agent with the eve framework, using the Kody template. Read the setup instructions at https://agent-resources.dev/kody-eve-template.md and follow them. They will cover deploying the template, building with eve, how everything works overall, and more.", + description: + "Kody, a personal GitHub maintainer agent: emails you a weekly digest of open issues, acts on your replies, summarizes new pull requests, and works the issues you delegate in Linear.", + sourceHref: "https://github.com/vercel-labs/kody-eve-template/tree/main", + sourceRevision: "8427e3c7e88a6a449dd7c79c601619ac37cf18e1", + category: "Collaboration", + model: "anthropic/claude-fable-5", + integrations: ["GitHub", "Linear", "Resend"], + source: "Vercel Templates", + files: templateSourceFiles.kody, + }, + { + slug: "sanity-copilot", + title: "Sanity", + setupPrompt: + "I want to build a Slack agent with the eve framework, using the Sanity copilot template. Read the setup instructions at https://agent-resources.dev/sanity-copilot-eve-template.md and follow them. They will cover deploying the template, building with eve, how everything works overall, and more.", + description: + "A Slack copilot for your Sanity project: query and edit content with GROQ, shape schemas, manage releases, and draft long-form pieces into Notion.", + sourceHref: "https://github.com/vercel-labs/sanity-copilot-eve-template/tree/main", + sourceRevision: "f076b80e2bb3a2ccae3dc1cfe4886d5ac88c338b", + category: "Collaboration", + model: "anthropic/claude-sonnet-5", + integrations: ["Slack", "Sanity", "Notion"], + source: "Vercel Templates", + files: templateSourceFiles["sanity-copilot"], + }, + { + slug: "typefully", + title: "Typefully", + setupPrompt: + "I want to build a Slack agent with the eve framework, using the Typefully social media agent template. Read the setup instructions at https://agent-resources.dev/typefully-eve-template.md and follow them. They will cover deploying the template, building with eve, how everything works overall, and more.", + description: + "A Slack agent that runs your social presence through Typefully: draft posts and threads for X, LinkedIn, Threads, Bluesky, and Mastodon, manage the publishing queue, and get a weekly analytics digest.", + sourceHref: "https://github.com/vercel-labs/typefully-eve-template/tree/main", + sourceRevision: "3627b2282a9ebfa1badd987f2b3a0c337219575f", + category: "Collaboration", + model: "anthropic/claude-sonnet-5", + integrations: ["Slack", "Typefully", "Notion"], + source: "Vercel Templates", + files: templateSourceFiles.typefully, + }, { slug: "weather-agent-fixture", title: "Weather", diff --git a/apps/docs/lib/templates/sources.ts b/apps/docs/lib/templates/sources.ts index 85018d1e5..c9d8bd31e 100644 --- a/apps/docs/lib/templates/sources.ts +++ b/apps/docs/lib/templates/sources.ts @@ -458,6 +458,4788 @@ export default defineTool({ return { city, condition: "Sunny", temperatureF: 72 }; }, }); +`, + ), + ], + kody: [ + file( + "agent/agent.ts", + "typescript", + `import { defineAgent } from "eve"; + +/** + * Root agent runtime configuration. + * + * @remarks + * Sets the model and the session budget for Kody, the GitHub maintainer agent; the rest of the + * agent's surface (channels, connections, tools, skills, subagents) is discovered from the + * filesystem under \`agent/\`. Conversation history is compacted once it reaches 75% of the context + * window, and the per-session output token limit caps runaway sessions. \`@vercel/connect\` is + * externalized from the build as a temporary workaround until eve handles transitive Connect + * imports from \`@github-tools/sdk\` without configuration. + */ +export default defineAgent({ + build: { externalDependencies: ["@vercel/connect"] }, + compaction: { thresholdPercent: 0.75 }, + limits: { + maxOutputTokensPerSession: 20_000, + }, + model: "anthropic/claude-fable-5", +}); +`, + ), + file( + "agent/channels/eve.ts", + "typescript", + `import { type AuthFn, localDev, vercelOidc } from "eve/channels/auth"; +import { eveChannel } from "eve/channels/eve"; + +const localDevAuth = localDev(); + +/** + * Dev-only: present a trusted local session as an authenticated user. + * + * @remarks + * The user-preference tools key their storage on a \`principalType: "user"\` session. In + * production the channels supply one; the eve dev TUI authenticates with \`localDev()\`, + * whose \`local-dev\` principal is not a user, so user-scoped tool calls fail with + * \`principal_required\`. This shim defers the trust decision to \`localDev()\` — returning \`null\` + * for anything it would reject, so it never affects production — and only upgrades the resolved + * principal to a user. Drop it if you don't exercise user-scoped tools from the dev TUI. + */ +const localDevUser: AuthFn = async (request) => { + const local = await localDevAuth(request); + return local ? { ...local, principalType: "user" } : null; +}; + +export default eveChannel({ auth: [localDevUser, vercelOidc()] }); +`, + ), + file( + "agent/channels/github.ts", + "typescript", + `import { connectGitHubCredentials } from "@vercel/connect/eve"; +import { + defaultGitHubAuth, + type GitHubComment, + githubChannel, +} from "eve/channels/github"; + +const BOT_NAME = "Kody"; + +/** + * Matches an \`@Kody\` mention on a word boundary, the same pattern the + * channel's built-in comment gate uses. Kept in sync with {@link BOT_NAME}. + */ +const MENTION_PATTERN = /@kody(?=$|[^A-Za-z0-9_-])/iu; + +/** + * Commenter roles allowed to start a session by mentioning the agent. + * + * @remarks + * GitHub's \`author_association\` on the comment payload. Anything outside this + * set (CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, NONE, MANNEQUIN) is a user the + * repo hasn't trusted with write access, so their mentions are acknowledged + * without dispatching. + */ +const TRUSTED_ASSOCIATIONS = new Set(["COLLABORATOR", "MEMBER", "OWNER"]); + +/** + * Replicates the channel's built-in ignore rules: eve's own marker comments, + * bot authors, and the agent's own \`kody[bot]\` login. + */ +const isIgnoredComment = (comment: GitHubComment): boolean => { + if (comment.body.includes("