From cbe8d194ef6bffee9d42e52761f7449882011fff Mon Sep 17 00:00:00 2001 From: 777genius Date: Sun, 10 May 2026 21:29:07 +0300 Subject: [PATCH] chore: sync current frontend updates --- .../page-2026-05-07T11-17-03-761Z.yml | 6 - landing/composables/usePageSeo.ts | 90 ++++++-- landing/data/i18n.ts | 10 + landing/locales/ar.json | 4 +- landing/locales/de.json | 4 +- landing/locales/en.json | 4 +- landing/locales/es.json | 4 +- landing/locales/fr.json | 4 +- landing/locales/hi.json | 4 +- landing/locales/ja.json | 4 +- landing/locales/pt.json | 4 +- landing/locales/ru.json | 4 +- landing/locales/zh.json | 4 +- landing/nuxt.config.ts | 11 +- landing/pages/download.vue | 2 +- landing/product-docs/.vitepress/config.ts | 66 +++++- .../.vitepress/theme/DocsCardGrid.vue | 45 +++- .../.vitepress/theme/DocsHeroVisual.vue | 51 +++-- .../.vitepress/theme/InstallBlock.vue | 37 ++- .../.vitepress/theme/ZoomImage.vue | 3 +- .../product-docs/.vitepress/theme/custom.css | 168 ++++++++++++-- landing/product-docs/guide/agent-workflow.md | 5 + landing/product-docs/guide/code-review.md | 44 ++++ landing/product-docs/guide/create-team.md | 5 + landing/product-docs/guide/installation.md | 5 + landing/product-docs/guide/quickstart.md | 47 ++++ landing/product-docs/guide/runtime-setup.md | 63 ++++++ landing/product-docs/guide/troubleshooting.md | 10 + landing/product-docs/index.md | 2 + landing/product-docs/reference/concepts.md | 13 +- landing/product-docs/reference/faq.md | 39 ++++ .../reference/privacy-local-data.md | 32 +++ .../reference/providers-runtimes.md | 48 ++++ .../product-docs/ru/guide/agent-workflow.md | 6 + landing/product-docs/ru/guide/code-review.md | 45 ++++ landing/product-docs/ru/guide/create-team.md | 6 + landing/product-docs/ru/guide/installation.md | 6 + landing/product-docs/ru/guide/quickstart.md | 48 ++++ .../product-docs/ru/guide/runtime-setup.md | 64 ++++++ .../product-docs/ru/guide/troubleshooting.md | 11 + landing/product-docs/ru/index.md | 2 + landing/product-docs/ru/reference/concepts.md | 19 +- landing/product-docs/ru/reference/faq.md | 35 +++ .../ru/reference/privacy-local-data.md | 28 +++ .../ru/reference/providers-runtimes.md | 44 ++++ landing/server/routes/llms.txt.ts | 52 +++++ landing/server/routes/robots.txt.ts | 2 +- landing/server/routes/sitemap.xml.ts | 36 ++- .../agent-graph/src/canvas/draw-agents.ts | 48 ++++ .../agent-graph/src/layout/stableSlots.ts | 6 +- .../renderer/adapters/TeamGraphAdapter.ts | 5 +- .../renderer/hooks/useTeamGraphAdapter.ts | 18 +- .../hooks/useTeamGraphSurfaceActions.ts | 8 +- .../renderer/ui/GraphNodePopover.tsx | 20 +- src/main/ipc/teams.ts | 49 +++- .../team/TeamMemberRuntimeAdvisoryService.ts | 6 +- .../OpenCodeRuntimeDeliveryAdvisoryPolicy.ts | 118 +--------- .../OpenCodeRuntimeDeliveryDiagnostics.ts | 87 ++----- .../runtime/RuntimeDiagnosticClassifier.ts | 213 ++++++++++++++++++ .../components/team/activity/ActivityItem.tsx | 99 +++++++- .../team/dialogs/OptionalSettingsSection.tsx | 162 +++++++++---- .../team/messages/MessagesPanel.tsx | 2 + src/renderer/store/slices/teamSlice.ts | 83 ++++++- src/renderer/utils/memberHelpers.ts | 14 ++ src/renderer/utils/teamMessageFiltering.ts | 4 +- src/shared/constants/teamGraphLayoutMode.ts | 3 + src/shared/types/team.ts | 1 + src/shared/utils/teamAutomationMessages.ts | 4 + test/main/ipc/teams.test.ts | 147 +++++++++--- ...nCodeRuntimeDeliveryAdvisoryPolicy.test.ts | 24 ++ ...OpenCodeRuntimeDeliveryDiagnostics.test.ts | 19 ++ .../team/RuntimeDiagnosticClassifier.test.ts | 73 ++++++ .../TeamMemberRuntimeAdvisoryService.test.ts | 1 + .../team/activity/ActivityItem.test.ts | 43 ++++ .../agent-graph/GraphNodePopover.test.ts | 52 ++++- .../agent-graph/TeamGraphAdapter.test.ts | 15 +- .../features/agent-graph/drawAgents.test.ts | 37 ++- .../agent-graph/useGraphSimulation.test.ts | 46 +++- test/renderer/store/teamSlice.test.ts | 55 ++++- test/renderer/utils/memberHelpers.test.ts | 14 ++ .../utils/teamMessageFiltering.test.ts | 51 +++++ 81 files changed, 2355 insertions(+), 418 deletions(-) delete mode 100644 .playwright-mcp/page-2026-05-07T11-17-03-761Z.yml create mode 100644 landing/server/routes/llms.txt.ts create mode 100644 src/main/services/team/runtime/RuntimeDiagnosticClassifier.ts create mode 100644 src/shared/constants/teamGraphLayoutMode.ts create mode 100644 test/main/services/team/RuntimeDiagnosticClassifier.test.ts diff --git a/.playwright-mcp/page-2026-05-07T11-17-03-761Z.yml b/.playwright-mcp/page-2026-05-07T11-17-03-761Z.yml deleted file mode 100644 index 80eb866f..00000000 --- a/.playwright-mcp/page-2026-05-07T11-17-03-761Z.yml +++ /dev/null @@ -1,6 +0,0 @@ -- generic [ref=e1]: - - img - - img [ref=e2] - - generic [ref=e12]: - - generic [ref=e13]: Agent Teams AI - - generic [ref=e15]: Get more done by doing less. \ No newline at end of file diff --git a/landing/composables/usePageSeo.ts b/landing/composables/usePageSeo.ts index 86c8dca6..9eeccec6 100644 --- a/landing/composables/usePageSeo.ts +++ b/landing/composables/usePageSeo.ts @@ -1,5 +1,5 @@ import { computed } from "vue"; -import { supportedLocales, defaultLocale } from "~/data/i18n"; +import { supportedLocales, defaultLocale, getLocaleMeta } from "~/data/i18n"; import { getContent } from "~/data/content"; import type { LocaleCode } from "~/data/i18n"; @@ -21,15 +21,20 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa const { t, locale } = useI18n(); const route = useRoute(); const config = useRuntimeConfig(); - const siteUrl = config.public.siteUrl || "https://example.com"; - const siteName = (config as any)?.site?.name || "Agent Teams"; + const siteUrl = ((config.public.siteUrl as string) || "https://example.com").replace(/\/+$/, ""); + const siteName = "Agent Teams"; const switchLocale = useSwitchLocalePath(); const title = computed(() => t(titleKey)); const description = computed(() => t(descriptionKey)); const canonicalPath = computed(() => route.path); - const canonicalUrl = computed(() => `${siteUrl}${canonicalPath.value}`); + const toSiteUrl = (pathOrUrl: string) => { + if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl; + const path = pathOrUrl === "/" ? "/" : `/${pathOrUrl.replace(/^\/+/, "")}`; + return `${siteUrl}${path}`; + }; + const canonicalUrl = computed(() => toSiteUrl(canonicalPath.value)); const resolvedImage = computed(() => { if (options.image) return options.image; @@ -38,14 +43,14 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa width: 1200, height: 630, type: "image/png", - alt: `${siteName} — AI agent orchestration` + alt: `${siteName} - AI agent orchestration` }; }); const resolvedImageUrl = computed(() => { - // Если сборщик вернул относительный путь — сделаем абсолютный. + // Если сборщик вернул относительный путь - сделаем абсолютный. const url = resolvedImage.value.url; - return url.startsWith("http") ? url : new URL(url, siteUrl).toString(); + return toSiteUrl(url); }); useSeoMeta({ @@ -57,7 +62,7 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa ogSiteName: siteName, ogUrl: canonicalUrl, ogImage: resolvedImageUrl, - ogImageType: computed(() => resolvedImage.value.type) as any, + ogImageType: computed(() => resolvedImage.value.type), ogImageWidth: computed(() => (resolvedImage.value.width ? String(resolvedImage.value.width) : undefined)), ogImageHeight: computed(() => (resolvedImage.value.height ? String(resolvedImage.value.height) : undefined)), ogImageAlt: computed(() => resolvedImage.value.alt), @@ -72,32 +77,70 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa }); useHead(() => { + const currentLocale = getLocaleMeta(locale.value as LocaleCode); const links: { rel: string; hreflang?: string; href: string }[] = supportedLocales.map((locale) => { const path = switchLocale(locale.code) || canonicalPath.value; return { rel: "alternate", - hreflang: locale.code, - href: `${siteUrl}${path}` + hreflang: locale.iso, + href: toSiteUrl(path) }; }); const defaultPath = switchLocale(defaultLocale) || canonicalPath.value; - links.push({ rel: "alternate", hreflang: "x-default", href: `${siteUrl}${defaultPath}` }); + links.push({ rel: "alternate", hreflang: "x-default", href: toSiteUrl(defaultPath) }); links.push({ rel: "canonical", href: canonicalUrl.value }); - const jsonLd: any[] = [ + const ogLocale = currentLocale.iso.replace("-", "_"); + const ogAlternateLocales = supportedLocales + .filter((locale) => locale.iso !== currentLocale.iso) + .map((locale) => locale.iso.replace("-", "_")); + + const normalizedPath = canonicalPath.value === "/" ? "/" : canonicalPath.value.replace(/\/+$/, ""); + const localizedHomePath = currentLocale.code === defaultLocale ? "/" : `/${currentLocale.code}`; + const isHome = normalizedPath === localizedHomePath; + const isDownload = normalizedPath.endsWith("/download"); + const organizationId = `${siteUrl}/#organization`; + const websiteId = `${siteUrl}/#website`; + const softwareId = `${siteUrl}/#software`; + const webpageId = `${canonicalUrl.value}#webpage`; + + const jsonLd: Record[] = [ { "@context": "https://schema.org", "@type": "WebSite", + "@id": websiteId, name: siteName, - url: siteUrl + url: siteUrl, + inLanguage: currentLocale.iso, + publisher: { "@id": organizationId } + }, + { + "@context": "https://schema.org", + "@type": "WebPage", + "@id": webpageId, + name: title.value, + description: description.value, + url: canonicalUrl.value, + inLanguage: currentLocale.iso, + isPartOf: { "@id": websiteId }, + about: { "@id": softwareId }, + publisher: { "@id": organizationId }, + primaryImageOfPage: { + "@type": "ImageObject", + "@id": `${resolvedImageUrl.value}#primaryimage`, + url: resolvedImageUrl.value, + width: resolvedImage.value.width, + height: resolvedImage.value.height + } }, { "@context": "https://schema.org", "@type": "Organization", + "@id": organizationId, name: siteName, url: siteUrl, - logo: `${siteUrl}/favicon.ico`, + logo: toSiteUrl("/logo-192.png"), sameAs: [ `https://github.com/${config.public.githubRepo}` ] @@ -105,17 +148,22 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa ]; // Для главной и страницы скачивания добавим более "вкусную" разметку. - const isDownload = canonicalPath.value.endsWith("/download"); - const isHome = canonicalPath.value === "/"; if (isHome || isDownload) { jsonLd.push({ "@context": "https://schema.org", "@type": "SoftwareApplication", + "@id": softwareId, name: siteName, applicationCategory: "BusinessApplication", operatingSystem: "Windows, macOS, Linux", description: description.value, url: canonicalUrl.value, + mainEntityOfPage: { "@id": webpageId }, + author: { "@id": organizationId }, + publisher: { "@id": organizationId }, + image: resolvedImageUrl.value, + screenshot: toSiteUrl("/screenshots/1.jpg"), + softwareVersion: "latest", offers: { "@type": "Offer", price: "0", @@ -125,13 +173,16 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa }); } - // FAQ rich snippets — Google показывает их прямо в выдаче + // FAQ rich snippets - Google показывает их прямо в выдаче if (isHome) { const content = getContent(locale.value as LocaleCode); if (content.faq?.length) { jsonLd.push({ "@context": "https://schema.org", "@type": "FAQPage", + "@id": `${canonicalUrl.value}#faq`, + inLanguage: currentLocale.iso, + isPartOf: { "@id": webpageId }, mainEntity: content.faq.map((item) => ({ "@type": "Question", name: item.question, @@ -146,7 +197,7 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa } return { - htmlAttrs: { lang: locale.value || "en" }, + htmlAttrs: { lang: currentLocale.iso, dir: "dir" in currentLocale ? currentLocale.dir : "ltr" }, link: links, meta: [ { name: "author", content: "Agent Teams" }, @@ -154,6 +205,9 @@ export const usePageSeo = (titleKey: string, descriptionKey: string, options: Pa { name: "apple-mobile-web-app-title", content: siteName }, { name: "format-detection", content: "telephone=no" }, { name: "theme-color", content: "#00f0ff" }, + { name: "googlebot", content: options.robots || "index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" }, + { property: "og:locale", content: ogLocale }, + ...ogAlternateLocales.map((content) => ({ property: "og:locale:alternate", content })), { name: "keywords", content: "claude code, agent teams, AI agents, kanban board, code review, multi-agent orchestration, desktop app, free, open source" } ], script: jsonLd.map((item) => ({ diff --git a/landing/data/i18n.ts b/landing/data/i18n.ts index 3b332b76..7ae03c5c 100644 --- a/landing/data/i18n.ts +++ b/landing/data/i18n.ts @@ -26,6 +26,16 @@ export const sitemapPages = [ "/download" ] as const; +export type SitemapPagePath = (typeof sitemapPages)[number]; + +export const getLocaleMeta = (localeCode: LocaleCode) => + supportedLocales.find((locale) => locale.code === localeCode) ?? supportedLocales[0]; + +export const getLocalizedPagePath = (page: SitemapPagePath, localeCode: LocaleCode): string => { + if (localeCode === defaultLocale) return page; + return page === "/" ? `/${localeCode}` : `/${localeCode}${page}`; +}; + /** Generates i18n routes for a given list of pages */ const buildI18nRoutes = (source: readonly string[]): string[] => { const routes: string[] = []; diff --git a/landing/locales/ar.json b/landing/locales/ar.json index 295142a1..b2ca4cff 100644 --- a/landing/locales/ar.json +++ b/landing/locales/ar.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - تنسيق وكلاء الذكاء الاصطناعي للمطورين", - "homeDescription": "تطبيق سطح مكتب مجاني ومفتوح المصدر لتشكيل فرق وكلاء الذكاء الاصطناعي. لوحة كانبان، مراجعة الكود، تواصل بين الفرق. يعمل محلياً بالكامل." + "homeDescription": "تطبيق سطح مكتب مجاني ومفتوح المصدر لتشكيل فرق وكلاء الذكاء الاصطناعي. لوحة كانبان، مراجعة الكود، تواصل بين الفرق. يعمل محلياً بالكامل.", + "downloadTitle": "تنزيل Agent Teams لنظام macOS وWindows وLinux", + "downloadDescription": "نزّل Agent Teams لنظام macOS وWindows وLinux. تطبيق سطح مكتب مجاني ومفتوح المصدر لفرق وكلاء Claude وCodex وOpenCode." }, "error": { "notFoundTitle": "الصفحة غير موجودة", diff --git a/landing/locales/de.json b/landing/locales/de.json index 76257315..d38f3e22 100644 --- a/landing/locales/de.json +++ b/landing/locales/de.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - KI-Agenten-Orchestrierung für Entwickler", - "homeDescription": "Kostenlose Open-Source-Desktop-App für KI-Agenten-Teams. Kanban-Board, Code-Review, teamübergreifende Kommunikation. Läuft vollständig lokal." + "homeDescription": "Kostenlose Open-Source-Desktop-App für KI-Agenten-Teams. Kanban-Board, Code-Review, teamübergreifende Kommunikation. Läuft vollständig lokal.", + "downloadTitle": "Agent Teams für macOS, Windows und Linux herunterladen", + "downloadDescription": "Laden Sie Agent Teams für macOS, Windows und Linux herunter. Kostenlose Open-Source-Desktop-App für Claude-, Codex- und OpenCode-Agententeams." }, "error": { "notFoundTitle": "Seite nicht gefunden", diff --git a/landing/locales/en.json b/landing/locales/en.json index da3c26cb..bb81047e 100644 --- a/landing/locales/en.json +++ b/landing/locales/en.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - AI Agent Orchestration for Developers", - "homeDescription": "Free, open-source desktop app for assembling AI agent teams. Kanban board, code review, cross-team communication. Runs entirely locally." + "homeDescription": "Free, open-source desktop app for assembling AI agent teams. Kanban board, code review, cross-team communication. Runs entirely locally.", + "downloadTitle": "Download Agent Teams for macOS, Windows, and Linux", + "downloadDescription": "Download Agent Teams for macOS, Windows, and Linux. Free open-source desktop app for Claude, Codex, and OpenCode agent teams." }, "error": { "notFoundTitle": "Page not found", diff --git a/landing/locales/es.json b/landing/locales/es.json index 5cb5c78d..6d61f236 100644 --- a/landing/locales/es.json +++ b/landing/locales/es.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - Orquestación de agentes IA para desarrolladores", - "homeDescription": "App de escritorio gratuita y de código abierto para montar equipos de agentes IA. Tablero kanban, revisión de código, comunicación entre equipos. Funciona completamente en local." + "homeDescription": "App de escritorio gratuita y de código abierto para montar equipos de agentes IA. Tablero kanban, revisión de código, comunicación entre equipos. Funciona completamente en local.", + "downloadTitle": "Descargar Agent Teams para macOS, Windows y Linux", + "downloadDescription": "Descarga Agent Teams para macOS, Windows y Linux. App de escritorio gratis y open source para equipos de agentes Claude, Codex y OpenCode." }, "error": { "notFoundTitle": "Página no encontrada", diff --git a/landing/locales/fr.json b/landing/locales/fr.json index 3566ed88..28ed6d5a 100644 --- a/landing/locales/fr.json +++ b/landing/locales/fr.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - Orchestration d'agents IA pour développeurs", - "homeDescription": "Application desktop gratuite et open source pour gérer des équipes d'agents IA. Tableau kanban, revue de code, communication inter-équipes. Fonctionne entièrement en local." + "homeDescription": "Application desktop gratuite et open source pour gérer des équipes d'agents IA. Tableau kanban, revue de code, communication inter-équipes. Fonctionne entièrement en local.", + "downloadTitle": "Télécharger Agent Teams pour macOS, Windows et Linux", + "downloadDescription": "Téléchargez Agent Teams pour macOS, Windows et Linux. Application desktop gratuite et open source pour équipes d'agents Claude, Codex et OpenCode." }, "error": { "notFoundTitle": "Page introuvable", diff --git a/landing/locales/hi.json b/landing/locales/hi.json index ff06e28a..45542eec 100644 --- a/landing/locales/hi.json +++ b/landing/locales/hi.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - डेवलपर्स के लिए AI एजेंट ऑर्केस्ट्रेशन", - "homeDescription": "AI एजेंट टीमें बनाने के लिए मुफ़्त, ओपन-सोर्स डेस्कटॉप ऐप। कानबन बोर्ड, कोड रिव्यू, क्रॉस-टीम संचार। पूरी तरह लोकल चलता है।" + "homeDescription": "AI एजेंट टीमें बनाने के लिए मुफ़्त, ओपन-सोर्स डेस्कटॉप ऐप। कानबन बोर्ड, कोड रिव्यू, क्रॉस-टीम संचार। पूरी तरह लोकल चलता है।", + "downloadTitle": "macOS, Windows और Linux के लिए Agent Teams डाउनलोड करें", + "downloadDescription": "macOS, Windows और Linux के लिए Agent Teams डाउनलोड करें। Claude, Codex और OpenCode एजेंट टीमों के लिए मुफ़्त ओपन-सोर्स डेस्कटॉप ऐप।" }, "error": { "notFoundTitle": "पेज नहीं मिला", diff --git a/landing/locales/ja.json b/landing/locales/ja.json index 04b1c92c..0698a615 100644 --- a/landing/locales/ja.json +++ b/landing/locales/ja.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - 開発者向けAIエージェントオーケストレーション", - "homeDescription": "AIエージェントチームを管理する無料のオープンソースデスクトップアプリ。カンバンボード、コードレビュー、チーム間通信。完全にローカルで動作。" + "homeDescription": "AIエージェントチームを管理する無料のオープンソースデスクトップアプリ。カンバンボード、コードレビュー、チーム間通信。完全にローカルで動作。", + "downloadTitle": "macOS、Windows、Linux向けAgent Teamsをダウンロード", + "downloadDescription": "macOS、Windows、Linux向けAgent Teamsをダウンロード。Claude、Codex、OpenCodeエージェントチーム用の無料オープンソースデスクトップアプリ。" }, "error": { "notFoundTitle": "ページが見つかりません", diff --git a/landing/locales/pt.json b/landing/locales/pt.json index f13006b6..4544c341 100644 --- a/landing/locales/pt.json +++ b/landing/locales/pt.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - Orquestração de agentes IA para desenvolvedores", - "homeDescription": "App desktop gratuito e open source para montar equipes de agentes IA. Quadro kanban, revisão de código, comunicação entre equipes. Roda totalmente local." + "homeDescription": "App desktop gratuito e open source para montar equipes de agentes IA. Quadro kanban, revisão de código, comunicação entre equipes. Roda totalmente local.", + "downloadTitle": "Baixar Agent Teams para macOS, Windows e Linux", + "downloadDescription": "Baixe o Agent Teams para macOS, Windows e Linux. App desktop gratuito e open source para equipes de agentes Claude, Codex e OpenCode." }, "error": { "notFoundTitle": "Página não encontrada", diff --git a/landing/locales/ru.json b/landing/locales/ru.json index bde5b30e..dd9c82a4 100644 --- a/landing/locales/ru.json +++ b/landing/locales/ru.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - Оркестрация ИИ-агентов для разработчиков", - "homeDescription": "Бесплатное десктопное приложение с открытым кодом для управления командами ИИ-агентов. Канбан-доска, код-ревью, межкомандная коммуникация. Работает полностью локально." + "homeDescription": "Бесплатное десктопное приложение с открытым кодом для управления командами ИИ-агентов. Канбан-доска, код-ревью, межкомандная коммуникация. Работает полностью локально.", + "downloadTitle": "Скачать Agent Teams для macOS, Windows и Linux", + "downloadDescription": "Скачайте Agent Teams для macOS, Windows и Linux. Бесплатное open-source приложение для команд агентов Claude, Codex и OpenCode." }, "error": { "notFoundTitle": "Страница не найдена", diff --git a/landing/locales/zh.json b/landing/locales/zh.json index 712972a3..67031b0b 100644 --- a/landing/locales/zh.json +++ b/landing/locales/zh.json @@ -105,7 +105,9 @@ }, "meta": { "homeTitle": "Agent Teams - 面向开发者的 AI 智能体编排", - "homeDescription": "免费开源桌面应用,用于组建 AI 智能体团队。看板、代码审查、跨团队通信。完全本地运行。" + "homeDescription": "免费开源桌面应用,用于组建 AI 智能体团队。看板、代码审查、跨团队通信。完全本地运行。", + "downloadTitle": "下载适用于 macOS、Windows 和 Linux 的 Agent Teams", + "downloadDescription": "下载适用于 macOS、Windows 和 Linux 的 Agent Teams。面向 Claude、Codex 和 OpenCode 智能体团队的免费开源桌面应用。" }, "error": { "notFoundTitle": "页面未找到", diff --git a/landing/nuxt.config.ts b/landing/nuxt.config.ts index 8c5fe8d0..c1f6d4cc 100644 --- a/landing/nuxt.config.ts +++ b/landing/nuxt.config.ts @@ -1,8 +1,9 @@ import vuetify from "vite-plugin-vuetify"; import { generateI18nRoutes, supportedLocales } from "./data/i18n"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -declare const process: any; +declare const process: { + env: Record; +}; const siteUrl = process.env.NUXT_PUBLIC_SITE_URL || "https://777genius.github.io/agent-teams-ai"; const githubRepo = process.env.NUXT_PUBLIC_GITHUB_REPO || "777genius/agent-teams-ai"; @@ -20,6 +21,7 @@ export default defineNuxtConfig({ { rel: "icon", type: "image/x-icon", href: `${baseURL}favicon.ico` }, { rel: "icon", type: "image/png", sizes: "32x32", href: `${baseURL}favicon-32.png` }, { rel: "apple-touch-icon", sizes: "192x192", href: `${baseURL}logo-192.png` }, + { rel: "alternate", type: "text/plain", title: "llms.txt", href: `${baseURL}llms.txt` }, { rel: "dns-prefetch", href: "https://api.github.com" }, { rel: "preconnect", href: "https://fonts.googleapis.com" }, { rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "" }, @@ -65,7 +67,8 @@ export default defineNuxtConfig({ routes: [ ...generateI18nRoutes(), "/sitemap.xml", - "/robots.txt" + "/robots.txt", + "/llms.txt" ] } }, @@ -76,7 +79,7 @@ export default defineNuxtConfig({ }, i18n: { restructureDir: false, - locales: [...supportedLocales] as any, + locales: [...supportedLocales], defaultLocale: "en", strategy: "prefix_except_default", lazy: true, diff --git a/landing/pages/download.vue b/landing/pages/download.vue index 1998b6d0..463dff44 100644 --- a/landing/pages/download.vue +++ b/landing/pages/download.vue @@ -1,7 +1,7 @@ @@ -61,8 +62,10 @@ const cards = computed(() => { } .docs-card { + position: relative; + overflow: hidden; display: grid; - grid-template-columns: auto 1fr; + grid-template-columns: auto 1fr auto; grid-template-rows: auto auto; column-gap: 12px; row-gap: 4px; @@ -72,24 +75,27 @@ const cards = computed(() => { background: var(--at-c-surface-soft); color: var(--at-c-text); text-decoration: none !important; + box-shadow: var(--at-shadow-card); transition: border-color var(--at-transition-base), background-color var(--at-transition-base), - transform var(--at-transition-base); + transform var(--at-transition-base), + box-shadow var(--at-transition-base); } .docs-card:hover { border-color: var(--at-c-border-strong); background: var(--at-glass-bg-hover); - transform: translateY(-2px); + transform: translateY(-3px); + box-shadow: var(--at-shadow-cyan-md); } .docs-card__icon { grid-row: 1 / -1; display: grid; place-items: center; - width: 36px; - height: 36px; + width: 40px; + height: 40px; border-radius: var(--at-radius-md); background: var(--at-gradient-panel); color: var(--at-c-cyan); @@ -101,17 +107,44 @@ const cards = computed(() => { .docs-card strong { color: var(--at-c-text); font-size: 15px; + line-height: 1.3; } -.docs-card span:last-child { +.docs-card > span:nth-of-type(2) { color: var(--at-c-text-muted); font-size: 13px; line-height: 1.45; } +.docs-card__arrow { + grid-column: 3; + align-self: end; + color: var(--at-c-cyan); + font-family: var(--at-font-mono); + font-size: 16px; + opacity: 0.55; + transform: translateX(-4px); + transition: + opacity var(--at-transition-base), + transform var(--at-transition-base); +} + +.docs-card:hover .docs-card__arrow { + opacity: 1; + transform: translateX(0); +} + @media (max-width: 640px) { .docs-card-grid { grid-template-columns: 1fr; } + + .docs-card { + grid-template-columns: auto 1fr; + } + + .docs-card__arrow { + display: none; + } } diff --git a/landing/product-docs/.vitepress/theme/DocsHeroVisual.vue b/landing/product-docs/.vitepress/theme/DocsHeroVisual.vue index 56dd7377..3b3fed24 100644 --- a/landing/product-docs/.vitepress/theme/DocsHeroVisual.vue +++ b/landing/product-docs/.vitepress/theme/DocsHeroVisual.vue @@ -18,6 +18,7 @@ const workflowVideoSrc = "https://github.com/user-attachments/assets/35e27989-72
+
@@ -25,11 +26,23 @@ const workflowVideoSrc = "https://github.com/user-attachments/assets/35e27989-72 diff --git a/landing/product-docs/.vitepress/theme/InstallBlock.vue b/landing/product-docs/.vitepress/theme/InstallBlock.vue index d885d931..0174ed29 100644 --- a/landing/product-docs/.vitepress/theme/InstallBlock.vue +++ b/landing/product-docs/.vitepress/theme/InstallBlock.vue @@ -37,40 +37,61 @@ async function copy() { .install-block { display: inline-flex; align-items: center; + justify-content: space-between; max-width: 100%; - gap: 12px; + width: 100%; + gap: 14px; margin: 12px 0 4px; - padding: 12px 16px; + padding: 14px 16px; border: var(--at-glass-border); - border-radius: var(--at-radius-lg); + border-radius: var(--at-radius-xl); background: var(--at-c-surface-soft); color: var(--at-c-text); cursor: pointer; + box-shadow: var(--at-shadow-card); transition: border-color var(--at-transition-base), background-color var(--at-transition-base), - transform var(--at-transition-base); + transform var(--at-transition-base), + box-shadow var(--at-transition-base); } .install-block:hover { border-color: var(--at-c-border-strong); background: var(--at-glass-bg-hover); - transform: translateY(-1px); + transform: translateY(-2px); + box-shadow: var(--at-shadow-cyan-md); } .install-block code { - overflow: hidden; + min-width: 0; color: var(--at-c-text); font-family: var(--at-font-mono); font-size: 13px; - text-overflow: ellipsis; - white-space: nowrap; + line-height: 1.4; + text-align: left; + white-space: normal; } .install-block span { flex-shrink: 0; + padding: 6px 10px; + border-radius: var(--at-radius-pill); + background: color-mix(in srgb, var(--at-c-cyan) 12%, transparent); color: var(--at-c-cyan); font-family: var(--at-font-mono); font-size: 12px; + white-space: nowrap; +} + +@media (max-width: 640px) { + .install-block { + align-items: flex-start; + flex-direction: column; + } + + .install-block span { + align-self: flex-start; + } } diff --git a/landing/product-docs/.vitepress/theme/ZoomImage.vue b/landing/product-docs/.vitepress/theme/ZoomImage.vue index 93a4d8f0..817c1061 100644 --- a/landing/product-docs/.vitepress/theme/ZoomImage.vue +++ b/landing/product-docs/.vitepress/theme/ZoomImage.vue @@ -23,8 +23,8 @@ defineProps<{ .zoom-image img { display: block; width: 100%; - border: var(--at-glass-border); border-radius: var(--at-radius-xl); + border: var(--at-glass-border); background: var(--at-c-dark-1); box-shadow: var(--at-shadow-card); cursor: zoom-in; @@ -34,6 +34,7 @@ defineProps<{ margin-top: 8px; color: var(--at-c-text-muted); font-size: 13px; + line-height: 1.5; text-align: center; } diff --git a/landing/product-docs/.vitepress/theme/custom.css b/landing/product-docs/.vitepress/theme/custom.css index 34272ee4..5abda64f 100644 --- a/landing/product-docs/.vitepress/theme/custom.css +++ b/landing/product-docs/.vitepress/theme/custom.css @@ -52,10 +52,14 @@ html { background: var(--vp-c-bg); + scroll-behavior: smooth; } body { letter-spacing: 0; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + font-feature-settings: "liga" 1, "calt" 1, "kern" 1; } .Layout { @@ -70,6 +74,8 @@ body { z-index: -2; pointer-events: none; background: + radial-gradient(circle at 18% -8%, rgba(0, 240, 255, 0.16), transparent 34%), + radial-gradient(circle at 82% 0%, rgba(255, 0, 255, 0.09), transparent 26%), linear-gradient(180deg, rgba(0, 240, 255, 0.08), transparent 320px), linear-gradient(135deg, rgba(255, 0, 255, 0.055), transparent 42%), var(--vp-c-bg); @@ -82,8 +88,10 @@ body { z-index: -1; pointer-events: none; background: - linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--vp-c-bg) 72%, transparent) 58%, var(--vp-c-bg) 100%); - opacity: 0.8; + linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--vp-c-bg) 72%, transparent) 58%, var(--vp-c-bg) 100%), + linear-gradient(90deg, transparent 0, transparent calc(100% - 1px), var(--vp-c-divider) calc(100% - 1px), var(--vp-c-divider) 100%); + background-size: auto, 72px 72px; + opacity: 0.6; } .VPNavBar { @@ -91,6 +99,7 @@ body { background: var(--vp-nav-bg-color) !important; backdrop-filter: blur(var(--at-blur-md)) !important; -webkit-backdrop-filter: blur(var(--at-blur-md)) !important; + box-shadow: 0 10px 30px -24px rgba(15, 23, 42, 0.35); } .VPNavBarTitle .logo { @@ -102,6 +111,7 @@ body { .VPNavBarTitle .title { font-family: var(--at-font-mono); font-size: 14px; + font-weight: 700; letter-spacing: 0; } @@ -114,24 +124,33 @@ body { .VPHero .text { max-width: 760px; + text-wrap: balance; + font-size: clamp(2.4rem, 6vw, 4.95rem); + line-height: 0.96; + letter-spacing: -0.05em; } .VPHero .tagline { max-width: 680px; color: var(--vp-c-text-2); + font-size: 17px; + line-height: 1.7; + text-wrap: balance; } .VPHero .actions { + display: flex; align-items: center; gap: 12px; margin-top: 28px; + flex-wrap: wrap; } .VPHero.has-image { position: relative; overflow: hidden; min-height: 560px; - padding: 96px 24px 76px; + padding: 108px 24px 88px; } .VPHero.has-image .container { @@ -145,8 +164,32 @@ body { .VPHero.has-image .main { position: relative; z-index: 2; - max-width: 820px !important; - padding: 38px 0; + max-width: 780px !important; + padding: 30px 32px 32px; + border: 1px solid color-mix(in srgb, var(--vp-c-border) 72%, transparent); + border-radius: 28px; + background: + linear-gradient(180deg, color-mix(in srgb, var(--vp-c-bg-elv) 74%, transparent), color-mix(in srgb, var(--vp-c-bg-soft) 56%, transparent)), + color-mix(in srgb, var(--vp-c-bg-elv) 70%, transparent); + box-shadow: var(--at-shadow-cyan-lg); + backdrop-filter: blur(var(--at-blur-lg)); +} + +.VPHero.has-image .main::before { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + pointer-events: none; + background: + radial-gradient(circle at 20% 0%, rgba(0, 240, 255, 0.14), transparent 42%), + radial-gradient(circle at 82% 12%, rgba(255, 0, 255, 0.08), transparent 30%); + opacity: 0.9; +} + +.VPHero.has-image .main > * { + position: relative; + z-index: 1; } .VPHero.has-image .image { @@ -220,16 +263,28 @@ body { } .VPFeature { + position: relative; + overflow: hidden; border: var(--at-glass-border) !important; border-radius: var(--at-radius-xl) !important; background: var(--vp-c-bg-soft) !important; backdrop-filter: blur(var(--at-blur-sm)); + box-shadow: var(--at-shadow-card); transition: transform var(--at-transition-base), border-color var(--at-transition-base), box-shadow var(--at-transition-base) !important; } +.VPFeature::after { + content: ""; + position: absolute; + inset: auto 0 0; + height: 2px; + background: linear-gradient(90deg, transparent, rgba(0, 240, 255, 0.35), transparent); + opacity: 0.8; +} + .VPFeature:hover { border-color: var(--at-c-border-strong) !important; box-shadow: var(--at-shadow-cyan-md); @@ -239,9 +294,11 @@ body { .VPFeature .box { display: grid !important; grid-template-columns: 42px 1fr !important; - grid-template-rows: auto auto !important; + grid-template-rows: auto auto auto !important; column-gap: 12px !important; align-items: center !important; + min-height: 100%; + padding-bottom: 10px; } .VPFeature .box > .icon { @@ -249,8 +306,8 @@ body { grid-column: 1 !important; display: grid; place-items: center; - width: 36px; - height: 36px; + width: 40px; + height: 40px; margin-bottom: 0 !important; border-radius: var(--at-radius-md); background: var(--at-gradient-panel); @@ -262,17 +319,20 @@ body { .VPFeature .box > .title { grid-row: 1 !important; grid-column: 2 !important; + line-height: 1.25; } .VPFeature .box > .details { grid-row: 2 !important; grid-column: 1 / -1 !important; + margin-top: 4px; + line-height: 1.6; } .VPFeature .box > .link-text { grid-row: 3 !important; grid-column: 1 / -1 !important; - margin-top: 8px !important; + margin-top: 10px !important; } .VPFeature .box > .link-text .link-text-value { @@ -295,11 +355,14 @@ body { .vp-doc h2, .vp-doc h3 { letter-spacing: 0; + text-wrap: balance; } .vp-doc h1 { color: var(--vp-c-text-1); font-weight: 800; + font-size: clamp(2rem, 3.5vw, 3.25rem); + line-height: 1.05; } .dark .vp-doc h1 { @@ -311,11 +374,17 @@ body { .vp-doc p, .vp-doc li { - line-height: 1.75; + line-height: 1.8; + color: var(--vp-c-text-1); } .vp-doc a { text-underline-offset: 4px; + transition: color var(--at-transition-fast); +} + +.vp-doc a:hover { + color: var(--vp-c-brand-1); } .VPNavBarMenuLink[target="_self"].vp-external-link-icon::after, @@ -330,6 +399,14 @@ body { border-radius: var(--at-radius-xl); overflow: hidden; background: var(--vp-c-bg-soft); + box-shadow: var(--at-shadow-card); + border-collapse: separate; + border-spacing: 0; +} + +.vp-doc th, +.vp-doc td { + padding: 12px 14px; } .vp-doc th { @@ -339,6 +416,14 @@ body { background: rgba(0, 240, 255, 0.05); } +.vp-doc tbody tr:nth-child(2n) { + background: color-mix(in srgb, var(--vp-c-bg) 92%, transparent); +} + +.vp-doc tbody tr:hover { + background: color-mix(in srgb, var(--vp-c-brand-soft) 30%, transparent); +} + :root:not(.dark) .vp-doc th, :root:not(.dark) .docs-card__icon, :root:not(.dark) .install-block span { @@ -353,17 +438,31 @@ body { .vp-doc :not(pre) > code { border: 1px solid rgba(0, 240, 255, 0.1); border-radius: var(--at-radius-xs); + padding: 0.15em 0.38em; + background: color-mix(in srgb, var(--vp-c-brand-soft) 28%, transparent); + color: var(--vp-code-color); font-size: 0.9em; } .vp-doc div[class*="language-"] { - border: 1px solid rgba(0, 240, 255, 0.12); + border: 1px solid color-mix(in srgb, var(--vp-c-border) 86%, transparent); border-radius: var(--at-radius-xl); box-shadow: var(--at-shadow-card); + overflow: hidden; + background: + linear-gradient(180deg, color-mix(in srgb, var(--vp-c-bg-elv) 84%, transparent), color-mix(in srgb, var(--vp-c-bg-soft) 72%, transparent)), + var(--vp-code-block-bg); +} + +.vp-doc div[class*="language-"] pre, +.vp-doc div[class*="language-"] code { + font-size: 13px; + line-height: 1.7; } .vp-doc .custom-block { border-radius: var(--at-radius-xl); + box-shadow: var(--at-shadow-card); } .vp-doc .custom-block.tip { @@ -401,21 +500,58 @@ body { z-index: 9999; } +@media (max-width: 960px) { + .VPHero.has-image .main { + padding: 26px 24px 26px; + border-radius: 24px; + } +} + @media (max-width: 768px) { .VPHero.has-image { - min-height: 520px; - padding: 72px 20px 56px; + min-height: 0; + padding: 68px 16px 44px; } .VPHero.has-image .main { - padding: 24px 0; + padding: 24px 18px 22px; } .VPFeature .box { - grid-template-columns: 36px 1fr !important; + grid-template-columns: 38px 1fr !important; + } + + .VPFeature .box > .icon { + width: 38px; + height: 38px; } .VPHero .text { - font-size: 34px; + font-size: clamp(2rem, 10vw, 3.25rem); + } + + .VPHero .tagline { + font-size: 16px; + } + + .VPHero .actions { + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .VPHero .actions .VPButton { + width: 100%; + max-width: 220px; + } + + .vp-doc th, + .vp-doc td { + padding: 10px 12px; + } + + .vp-doc div[class*="language-"] pre, + .vp-doc div[class*="language-"] code { + font-size: 12.5px; } } diff --git a/landing/product-docs/guide/agent-workflow.md b/landing/product-docs/guide/agent-workflow.md index 7e63c6f4..b98f7b0a 100644 --- a/landing/product-docs/guide/agent-workflow.md +++ b/landing/product-docs/guide/agent-workflow.md @@ -1,3 +1,8 @@ +--- +title: Agent Workflow – Agent Teams Docs +description: Understand task lifecycle, kanban board, messages, task logs, parallel work, live processes, and cross-team communication. +--- + # Agent Workflow Agent Teams makes agent work visible as task state, messages, logs, and reviewable code changes. diff --git a/landing/product-docs/guide/code-review.md b/landing/product-docs/guide/code-review.md index 48771c1c..9bb15f03 100644 --- a/landing/product-docs/guide/code-review.md +++ b/landing/product-docs/guide/code-review.md @@ -1,3 +1,8 @@ +--- +title: Code Review – Agent Teams Docs +description: Inspect task-scoped diffs, accept or reject hunks, leave inline comments, and manage review states from none to approved. +--- + # Code Review Code review in Agent Teams is task-centered. You inspect what changed for a specific task instead of hunting through a large unstructured diff. @@ -19,6 +24,15 @@ Accept small correct changes and reject isolated mistakes without throwing away If a diff is mostly correct, accept the good hunks first and request changes only for the parts that need fixing. This keeps the board moving. ::: +Use hunk-level decisions for: + +| Situation | Action | +| --- | --- | +| Correct scoped change | Accept the hunk | +| Correct idea, wrong file or broad refactor | Reject the hunk and request a narrower fix | +| Unclear behavior change | Comment and ask for verification | +| Generated formatting noise | Reject unless formatting was part of the task | + ## Initiating review 1. Open a completed task @@ -27,6 +41,22 @@ If a diff is mostly correct, accept the good hunks first and request changes onl During review the task is not yet considered done, so other teammates or the lead can still comment on it. +## Review loop + +A healthy review loop looks like this: + +1. The owner posts a result comment with changed scope and verification +2. The reviewer opens the task diff and checks hunks against the task description +3. The reviewer accepts good hunks, rejects bad hunks, or requests changes +4. The owner fixes only the requested scope and posts a follow-up comment +5. The reviewer approves when the task result and diff match + +Example request-changes comment: + +```text +Please keep the copy improvements, but revert the unrelated runtime wording in the provider table. Add a docs build result before resubmitting. +``` + ## Review states | State | Meaning | @@ -40,6 +70,8 @@ During review the task is not yet considered done, so other teammates or the lea Teams can review each other's work before you make the final call. This catches obvious regressions and keeps the board honest, but you should still review risky areas yourself. +Agent review is most useful when the reviewer has a clear rubric. For example, tell a reviewer to check only docs clarity, only IPC safety, or only test coverage. Broad "review everything" requests tend to produce weaker feedback. + ## Review participants The team lead is the default reviewer. You can configure additional reviewers in the Kanban settings if you want peers to review each other's work. @@ -58,6 +90,18 @@ Prioritize these areas when reviewing: Prefer focused verification commands. Broad formatting or lint-fix commands should not be used unless the task explicitly intends broad formatting churn. +Good verification comments include the command and result: + +```text +Verified with `pnpm --dir landing docs:build`. Build passed. +``` + +When verification is skipped, the task comment should say why: + +```text +Docs-only wording change. Build not run because the existing dev server was busy; checked Markdown links manually. +``` + ::: warning Do not auto-format across the whole project Unless the task is specifically about formatting, avoid running `pnpm lint:fix` on unrelated files. It creates noise in the review surface. ::: diff --git a/landing/product-docs/guide/create-team.md b/landing/product-docs/guide/create-team.md index 838ad85f..df2b8dd5 100644 --- a/landing/product-docs/guide/create-team.md +++ b/landing/product-docs/guide/create-team.md @@ -1,3 +1,8 @@ +--- +title: Create a Team – Agent Teams Docs +description: Define roles, assign providers and models, write a team brief, and configure worktree isolation and autonomy levels. +--- + # Create a Team A team is a named group of agents with roles, a lead, a target project, and a coordination prompt. diff --git a/landing/product-docs/guide/installation.md b/landing/product-docs/guide/installation.md index 8d536585..67131b65 100644 --- a/landing/product-docs/guide/installation.md +++ b/landing/product-docs/guide/installation.md @@ -1,3 +1,8 @@ +--- +title: Installation – Agent Teams Docs +description: Download and install Agent Teams for macOS, Windows, or Linux. Covers packaged builds, source setup, auto-updates, and requirements. +--- + # Installation Agent Teams is distributed as a desktop app for macOS, Windows, and Linux. diff --git a/landing/product-docs/guide/quickstart.md b/landing/product-docs/guide/quickstart.md index 8d466f6a..5feb7aba 100644 --- a/landing/product-docs/guide/quickstart.md +++ b/landing/product-docs/guide/quickstart.md @@ -1,3 +1,8 @@ +--- +title: Quickstart – Agent Teams Docs +description: Get from a fresh install to a running AI agent team in a few minutes. Covers installation, runtime selection, team creation, and first code review. +--- + # Quickstart This guide gets you from a fresh install to a running team in a few minutes. @@ -18,6 +23,14 @@ Launch the app and select the project directory you want agents to work in. Agen Pick a Git-tracked project for the best experience. Worktree isolation and diff-based review both rely on Git. ::: +Before launching a team, check that the project has a clean enough baseline: + +```bash +git status --short +``` + +You do not need a perfectly clean tree, but you should know which changes are yours before agents start editing. This makes task diffs and hunk-level review much easier to trust. + ## 3. Choose a runtime path The setup flow auto-detects installed runtimes on your machine. A common first setup is: @@ -34,12 +47,32 @@ Gemini support is in development and will appear in the runtime list when availa See [Runtime setup](/guide/runtime-setup) for detailed configuration per provider. +To verify the selected runtime outside the app, run the matching version command: + +```bash +claude --version +codex --version +opencode --version +``` + +If the command fails in your terminal, fix the runtime installation or `PATH` first. Team prompts cannot work around a missing binary or missing provider auth. + ## 4. Create your first team Create a team with a lead and one or more specialists. Keep the first team small: one lead, one implementation agent, and one review-oriented agent is enough to validate the workflow. See [Create a team](/guide/create-team) for the recommended structure and tips. +For the first launch, prefer a team shape like this: + +| Member | Responsibility | Notes | +| --- | --- | --- | +| Lead | Split the goal into tasks and coordinate status | Keep on the most reliable provider you have | +| Builder | Implement scoped tasks | Give clear file or feature boundaries | +| Reviewer | Review completed work | Ask it to focus on regressions and missing tests | + +Avoid starting with five or more teammates. More agents increase concurrency, logs, provider usage, and conflict risk before you know the setup is healthy. + ## 5. Give the lead a concrete goal Write the goal like you would brief an engineering lead: @@ -48,6 +81,14 @@ Write the goal like you would brief an engineering lead: Improve the onboarding flow. Split the work into tasks, keep changes small, and ask for review before broad refactors. ``` +Good first prompts include concrete scope, safety boundaries, and verification: + +```text +Improve the docs quickstart. Keep edits inside landing/product-docs. Add practical examples, preserve existing VitePress syntax, and run the docs build before marking tasks done. +``` + +Avoid vague prompts such as "make the app better" for the first run. The lead can break down large goals, but better input produces smaller tasks and cleaner review. + The lead creates tasks, assigns work, and coordinates teammates. You can watch progress on the kanban board and intervene with comments or direct messages at any time. ## 6. Review results @@ -56,6 +97,12 @@ Open completed or review-ready tasks, inspect the diff, and accept, reject, or c See [Code review](/guide/code-review) for the full review workflow. +Before approving the first task, check three things: + +1. The task comment explains what changed +2. The changed files match the task scope +3. The verification result is visible in the task comment or logs + ## Next steps - [Create a team](/guide/create-team) — recommended team shapes and brief writing diff --git a/landing/product-docs/guide/runtime-setup.md b/landing/product-docs/guide/runtime-setup.md index 0d92a793..0c83ccaa 100644 --- a/landing/product-docs/guide/runtime-setup.md +++ b/landing/product-docs/guide/runtime-setup.md @@ -1,3 +1,13 @@ +--- +title: Runtime Setup +description: Configure Claude Code, Codex, or OpenCode runtimes and provider authentication for agent teams. +--- + +--- +title: Runtime Setup – Agent Teams Docs +description: Configure Claude Code, Codex, or OpenCode runtimes. Covers auth, provider access, multimodel mode, and prelaunch checks. +--- + # Runtime Setup Agent Teams is a coordination layer. The actual model work runs through supported local runtimes and providers. @@ -9,11 +19,22 @@ Before launching a team, make sure: - The runtime binary is installed and on your `PATH`. - Your provider account has active access to the model you intend to use. - The project path exists and is readable. +- The app and your terminal use the same home/config environment when you test auth manually. ::: tip Start with a single teammate and one provider. Confirm one launch works before adding multimodel lanes. ::: +Quick terminal checks: + +```bash +command -v claude +command -v codex +command -v opencode +``` + +Run the command for the runtime you plan to use. If it prints nothing, install the runtime or fix `PATH` before launching a team. + ## Supported paths | Path | Default CLI | Typical providers | Use when | @@ -24,6 +45,8 @@ Start with a single teammate and one provider. Confirm one launch works before a The app detects supported runtimes and guides setup from the UI when possible. +Gemini appears in some internal provider lists but is currently hidden from the main team creation UI while its launch experience is still marked in development. + ## Provider access Agent Teams has no paid tier of its own. You bring the provider access you already have: subscriptions, local runtime auth, or API keys depending on the path you choose. @@ -47,6 +70,8 @@ Then verify the CLI is reachable: claude --version ``` +If the packaged app reports "not logged in" while your terminal works, compare the `$HOME` and `PATH` seen by the app with the terminal you used for login. The auth diagnostic log described in [Troubleshooting](/guide/troubleshooting#auth-diagnostic-log) is the best starting point. + ### Codex Install and authenticate via OpenAI's CLI flow: @@ -55,6 +80,14 @@ Install and authenticate via OpenAI's CLI flow: codex login ``` +Then verify the runtime is reachable: + +```bash +codex --version +``` + +Codex-native launches use Codex account state and model catalog data when available. If a model is missing from the UI, refresh provider status before editing team prompts. + ### OpenCode Create or edit `~/.opencode/config.json` (or the equivalent path on your platform) with the provider key you want: @@ -71,6 +104,16 @@ Create or edit `~/.opencode/config.json` (or the equivalent path on your platfor Use the exact provider name that OpenCode expects. If you set a custom provider name, double-check it against the provider ID you use in the model string (for example `openrouter/moonshotai/kimi-k2.6` would use the `openrouter` block). +Example model strings: + +| Model string | Provider block that must exist | +| --- | --- | +| `openrouter/moonshotai/kimi-k2.6` | `openrouter` | +| `openai/gpt-5.4` | `openai` | +| `anthropic/claude-sonnet-4-6` | `anthropic` | + +If OpenCode launches but a teammate never becomes deliverable, inspect lane evidence before assuming the model ignored the prompt. See [Troubleshooting](/guide/troubleshooting#opencode-registered-but-bootstrap-unconfirmed). + ## Multimodel mode Multimodel mode can route work through many provider backends via OpenCode-compatible configuration. Use it when you need provider flexibility or want teammates to use different model lanes. @@ -79,6 +122,16 @@ Multimodel mode can route work through many provider backends via OpenCode-compa Each teammate can use a different `providerId` + `model` pair. In the team edit UI, expand member options to override the global defaults. ::: +A conservative multimodel setup: + +| Role | Provider | Why | +| --- | --- | --- | +| Lead | Claude or Codex | Keep coordination on the provider you trust most | +| Builder | OpenCode | Use broad model routing for implementation work | +| Reviewer | Claude, Codex, or a second OpenCode model | Separate review judgment from the builder lane | + +Avoid mixing many unfamiliar providers in the first launch. Confirm one small task per lane before assigning broad work. + ## Prelaunch checklist Before launching a team: @@ -96,3 +149,13 @@ Switch when the current path is blocked by model availability, rate limits, prov ::: warning Treat setup errors as setup problems If auth fails, a model name is rejected, or the runtime binary cannot be found, fix the setup first. Do not change team prompts or project code to work around a runtime configuration issue. ::: + +Use this decision table: + +| Symptom | Better first action | +| --- | --- | +| Binary not found | Fix installation or `PATH` | +| Login works in terminal but not app | Check Electron auth diagnostic log and environment | +| Model rejected | Verify exact model id in the provider runtime | +| Repeated 429s | Lower concurrency or switch model/provider | +| OpenCode lane stuck | Inspect lane manifest and `opencode-sessions.json` | diff --git a/landing/product-docs/guide/troubleshooting.md b/landing/product-docs/guide/troubleshooting.md index 8d2adfd7..9bf941f0 100644 --- a/landing/product-docs/guide/troubleshooting.md +++ b/landing/product-docs/guide/troubleshooting.md @@ -1,3 +1,13 @@ +--- +title: Troubleshooting +description: Fix launch failures, missing agent replies, rate limits, auth issues, and lane bootstrap problems in Agent Teams. +--- + +--- +title: Troubleshooting – Agent Teams Docs +description: Fix team launch issues, missing agent replies, rate limits, CLI auth problems, and lane bootstrap stalls with local diagnostics. +--- + # Troubleshooting Most team issues fall into one of four buckets: runtime setup, launch confirmation, task parsing, and provider limits. diff --git a/landing/product-docs/index.md b/landing/product-docs/index.md index e9de982b..682111df 100644 --- a/landing/product-docs/index.md +++ b/landing/product-docs/index.md @@ -1,4 +1,6 @@ --- +title: Agent Teams Docs – Run AI Agent Teams from a Local Desktop App +description: Documentation for Agent Teams, a free desktop app for AI agent orchestration. Create teams, watch work on a kanban board, review code changes, and coordinate Claude, Codex, OpenCode, and multimodel workflows. layout: home hero: name: Agent Teams Docs diff --git a/landing/product-docs/reference/concepts.md b/landing/product-docs/reference/concepts.md index 1788d04a..4277d17d 100644 --- a/landing/product-docs/reference/concepts.md +++ b/landing/product-docs/reference/concepts.md @@ -1,3 +1,8 @@ +--- +title: Concepts +description: Core vocabulary for Agent Teams — teams, leads, teammates, tasks, kanban, inboxes, runtimes, and review. +--- + # Concepts This page defines the core terms used across Agent Teams. Use it as the shared vocabulary for the app, task board, messages, and review flow. @@ -6,16 +11,20 @@ This page defines the core terms used across Agent Teams. Use it as the shared v A team is a named group of agents attached to one project path. It has a lead, optional teammates, runtime/provider settings, prompts, inboxes, tasks, and local launch state. -## Lead +## Lead {#lead} The lead is the coordinator for the team. It turns a user goal into tasks, assigns or redirects teammates, tracks blockers, asks for review, and keeps work moving through the board. +[Teammate →](#teammate) + Lead messages use a different delivery path from teammate messages: the app relays lead inbox entries into the lead runtime, while teammates read their own inbox files between turns. -## Teammate +## Teammate {#teammate} A teammate is a non-lead agent in the team. Teammates usually own focused roles such as builder, reviewer, researcher, or tester. A teammate can receive direct messages, task assignments, task comments, and review requests. +[Lead ↑](#lead) + ## Task A task is the durable unit of work. It has an id, status, owner, description, comments, logs, attachments, task references, and reviewable changes. diff --git a/landing/product-docs/reference/faq.md b/landing/product-docs/reference/faq.md index dd85f710..108b567b 100644 --- a/landing/product-docs/reference/faq.md +++ b/landing/product-docs/reference/faq.md @@ -1,3 +1,18 @@ +--- +title: FAQ +description: Frequently asked questions about Agent Teams — pricing, model access, runtimes, privacy, review, and troubleshooting. +--- + +--- +title: FAQ – Agent Teams Docs +description: Frequently asked questions about pricing, model access, runtime setup, data privacy, worktree isolation, and code review. +--- + +--- +title: FAQ – Agent Teams Docs +description: Frequently asked questions about Agent Teams — pricing, model access, runtimes, privacy, review, and debugging. +--- + # FAQ ## Is Agent Teams free? @@ -18,6 +33,18 @@ Not always. The app guides runtime detection and setup from the UI. Some paths s OpenCode setup is separate from Claude Code and Codex setup. If a launch fails, check runtime status and provider auth before changing the team prompt. +## How do I check whether a runtime is ready? + +Run the runtime command in a terminal first: + +```bash +claude --version +codex --version +opencode --version +``` + +Then confirm provider auth for the path you selected. If the command or auth check fails outside Agent Teams, fix setup before launching a team. + ## Does it upload my code to Agent Teams servers? No. Agent Teams is not a cloud code-sync service. Provider-backed model calls may receive prompt context depending on your selected runtime. @@ -34,6 +61,14 @@ Prompt context, selected file contents, tool results, command output, task text, Yes. Agents can message teammates, comment on tasks, coordinate across teams, and use task references to keep conversations attached to work. +## What should I put in the first team prompt? + +Give the lead a concrete outcome, file or feature boundaries, risk limits, and verification expectations. For example: + +```text +Improve the docs quickstart. Keep edits inside landing/product-docs, add practical examples, and run the docs build before marking work done. +``` + ## Can I review code before accepting it? Yes. The review flow is built around task-scoped diffs and hunk-level decisions. @@ -46,6 +81,10 @@ An Agent Block is hidden agent-only text wrapped in markers such as `