diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 00000000..9d078a8f --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,15 @@ +name: agent-teams-codeql + +paths: + - src + - packages + - agent-teams-controller + - mcp-server + - scripts + - .github/workflows + +paths-ignore: + - '**/node_modules/**' + - 'test/**' + - 'landing/**' + - 'build/**' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..f9242127 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,67 @@ +name: CodeQL + +on: + push: + branches: [main, dev] + paths: + - 'src/**' + - 'packages/**' + - 'agent-teams-controller/**' + - 'mcp-server/**' + - 'scripts/**' + - '.github/workflows/**' + - '.github/codeql/**' + - 'package.json' + - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - 'tsconfig*.json' + pull_request: + paths: + - 'src/**' + - 'packages/**' + - 'agent-teams-controller/**' + - 'mcp-server/**' + - 'scripts/**' + - '.github/workflows/**' + - '.github/codeql/**' + - 'package.json' + - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - 'tsconfig*.json' + schedule: + - cron: '34 3 * * 1' + +permissions: + contents: read + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: + - actions + - javascript-typescript + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: /language:${{ matrix.language }} diff --git a/.github/workflows/reviewrouter-interaction.yml b/.github/workflows/reviewrouter-interaction.yml index a018d65c..773b68d5 100644 --- a/.github/workflows/reviewrouter-interaction.yml +++ b/.github/workflows/reviewrouter-interaction.yml @@ -21,7 +21,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' || ((github.event_name != 'issue_comment' || github.event.issue.pull_request) && github.event.comment.user.type != 'Bot') }} env: REVIEWROUTER_API_URL: "https://api.reviewrouter.site" - REVIEWROUTER_ACTION_VERSION: "c23ae97660c3674a2ebc9076bb5cd4f1bbd85657" + REVIEWROUTER_ACTION_VERSION: "1603215454b4c5cf3387b40ae674a46eeb7ee96b" REVIEWROUTER_OIDC_AUDIENCE: "reviewrouter" REVIEWROUTER_RUNTIME_CONFIG_MODE: "oidc" REVIEWROUTER_STATIC_CONFIG_FALLBACK: "true" @@ -42,7 +42,7 @@ jobs: - name: Preflight ReviewRouter interaction id: preflight - uses: 777genius/review-router@c23ae97660c3674a2ebc9076bb5cd4f1bbd85657 + uses: 777genius/review-router@1603215454b4c5cf3387b40ae674a46eeb7ee96b env: GITHUB_TOKEN: ${{ github.token }} REVIEW_ROUTER_MODE: "interaction-preflight" @@ -78,7 +78,7 @@ jobs: - name: Run ReviewRouter interaction if: ${{ steps.preflight.outputs.should_run == 'true' }} - uses: 777genius/review-router@c23ae97660c3674a2ebc9076bb5cd4f1bbd85657 + uses: 777genius/review-router@1603215454b4c5cf3387b40ae674a46eeb7ee96b env: GITHUB_TOKEN: ${{ github.token }} REVIEW_ROUTER_MODE: "interaction" diff --git a/README.md b/README.md index af6e04b0..e23d747c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@

Agent Teams

- You're the CTO, agents are your team. They handle tasks themselves, message each other, review each other. You just look at the kanban board and drink coffee. + You're the boss, agents are your team. They handle tasks themselves, message each other, review each other. You just look at the kanban board and drink coffee.

diff --git a/agent-teams-controller/package.json b/agent-teams-controller/package.json index 902e6d05..9d486238 100644 --- a/agent-teams-controller/package.json +++ b/agent-teams-controller/package.json @@ -14,6 +14,6 @@ "test:watch": "vitest --config vitest.config.js" }, "engines": { - "node": ">=24.16.0 <25" + "node": ">=24.15.0 <25" } } diff --git a/landing/.gitignore b/landing/.gitignore index 392f1564..f4956f78 100644 --- a/landing/.gitignore +++ b/landing/.gitignore @@ -5,6 +5,7 @@ node_modules .env --host/ product-docs/.vitepress/dist/ +product-docs/.vitepress/cache/ # Large video files public/video/*.mp4 diff --git a/landing/README.md b/landing/README.md index fb679a08..566c0b0f 100644 --- a/landing/README.md +++ b/landing/README.md @@ -14,9 +14,35 @@ pnpm generate pnpm preview ``` +## Render static sites + +Landing and docs are deployed as separate Render Static Sites from the `main` branch. + +Landing: + +```bash +corepack enable && pnpm install --frozen-lockfile --ignore-scripts && NUXT_PUBLIC_SITE_URL=$RENDER_EXTERNAL_URL NUXT_PUBLIC_DOCS_SITE_URL=https://agent-teams-ai-docs.onrender.com NUXT_PUBLIC_ROBOTS="index, follow" pnpm --filter agent-teams-landing generate +``` + +Publish path: `landing/.output/public` + +Docs: + +```bash +corepack enable && pnpm install --frozen-lockfile --ignore-scripts && VITEPRESS_BASE=/ VITEPRESS_SITE_URL=$RENDER_EXTERNAL_URL VITEPRESS_LANDING_SITE_URL=https://agent-teams-ai-landing.onrender.com pnpm --filter agent-teams-landing docs:build +``` + +Publish path: `landing/product-docs/.vitepress/dist` + +Both sites set `NODE_VERSION=24.16.0` and `SKIP_INSTALL_DEPS=true`; the build command runs the pnpm install step explicitly with `--ignore-scripts`. + +When a custom landing domain is attached, update `VITEPRESS_LANDING_SITE_URL` on the docs site. When a custom docs domain is attached, `VITEPRESS_SITE_URL=$RENDER_EXTERNAL_URL` can stay unchanged for the Render preview URL or be replaced with the custom domain for canonical SEO. + ## Notes + - Static-first (SSG) by design. - Locale auto-detection: cookie -> browser settings -> fallback `en`. - Theme auto-detection: localStorage -> system preference -> fallback `light`. - Hero video uses the Mux Player embed. Set `NUXT_PUBLIC_MUX_PLAYBACK_ID` to override the default playback id without changing the code. - Hero background can use a separate Mux asset via `NUXT_PUBLIC_MUX_BACKGROUND_PLAYBACK_ID`; otherwise it reuses `NUXT_PUBLIC_MUX_PLAYBACK_ID`. +- Set `NUXT_PUBLIC_DOCS_SITE_URL` when the docs are deployed as a separate static site. diff --git a/landing/assets/styles/cyberpunk-hero.scss b/landing/assets/styles/cyberpunk-hero.scss index e87b0f5e..14de0691 100644 --- a/landing/assets/styles/cyberpunk-hero.scss +++ b/landing/assets/styles/cyberpunk-hero.scss @@ -1943,8 +1943,12 @@ } @media (max-width: 767px) { + #hero.cyber-hero { + padding-top: 64px; + } + .cyber-hero { - padding: 84px 0 36px; + padding: 64px 0 8px; } .cyber-hero__background { @@ -1962,19 +1966,21 @@ } .cyber-hero__container { - width: min(100% - 32px, 680px); + width: min(100% - 24px, 680px); + max-width: min(100% - 24px, 680px) !important; + padding-inline: 0 !important; } .cyber-hero__layout { min-width: 0; - gap: 0; - overflow: hidden; + gap: 8px; + overflow: visible; } .cyber-hero__copy { width: 100%; max-width: 100%; - padding-bottom: 0; + padding: 8px 0 0; } .cyber-hero__brand-lockup { @@ -1988,28 +1994,40 @@ } .cyber-hero__title { - gap: 0.12em; - font-size: clamp(2rem, 9.4vw, 3.1rem); + flex-wrap: wrap; + gap: 0.06em 0.12em; + margin-bottom: 16px; + max-width: 9.4em; + font-size: 2.35rem; + line-height: 0.96; + white-space: normal; } .cyber-hero__slogan { display: flex; width: 100%; - padding: 10px 14px; - letter-spacing: 0.04em; + margin-bottom: 16px; + padding: 9px 13px; + flex-wrap: wrap; + font-size: 0.72rem; + letter-spacing: 0.03em; + overflow-wrap: anywhere; } .cyber-hero__description { - font-size: 1rem; - line-height: 1.62; + margin-bottom: 18px; + max-width: 100%; + font-size: 0.95rem; + line-height: 1.5; + overflow-wrap: break-word; } .cyber-hero__providers { - margin-bottom: 22px; + margin-bottom: 18px; } .cyber-hero__provider-list { - gap: 12px 18px; + gap: 10px 14px; } .cyber-hero__provider { @@ -2033,31 +2051,49 @@ .cyber-hero__actions { display: grid; grid-template-columns: 1fr; + gap: 12px; + margin-bottom: 12px; } .cyber-action-button.v-btn { width: 100%; - min-height: 72px !important; + min-height: 60px !important; min-width: 0 !important; - padding-inline: 20px !important; + padding-inline: 16px !important; + } + + .cyber-action-button.v-btn .v-btn__content { + gap: 12px; + } + + .cyber-action-button__icon { + width: 30px; + height: 30px; + } + + .cyber-action-button__label { + font-size: 0.92rem; + } + + .cyber-action-button__subtitle { + font-size: 0.62rem; } .cyber-hero__terminal-note { - display: inline-flex; - font-size: 0.68rem; + display: none; } .cyber-scene { min-height: auto; aspect-ratio: auto; - padding: 96px 0 14px; + padding: 86px 0 2px; transform: none; } .cyber-hero__scene { width: 100%; max-width: 100%; - margin-top: 8px; + margin-top: 14px; overflow: hidden; } @@ -2070,17 +2106,20 @@ position: relative; left: auto; top: auto; - width: 100%; + width: min(100%, 320px); + margin-inline: auto; transform: none; } .cyber-scene__robots { inset: 0 0 auto; - height: 96px; + z-index: 7; + height: 76px; display: flex; align-items: flex-end; justify-content: center; - gap: clamp(18px, 6vw, 34px); + gap: 18px; + overflow: visible; } .cyber-agent { @@ -2089,7 +2128,7 @@ display: none; left: auto; top: auto; - width: clamp(58px, 18vw, 74px); + width: 54px; transform: none; } @@ -2099,7 +2138,7 @@ .cyber-agent[data-agent="planner"] { z-index: auto; - width: clamp(58px, 18vw, 74px); + width: 54px; transform: none; } @@ -2145,93 +2184,18 @@ display: none; } - .cyber-feature-rail { - grid-template-columns: 1fr; - gap: 20px; - padding: 0 4px; - } - .cyber-feature-rail-shell { - margin-top: clamp(104px, 24vw, 128px); - } - - .cyber-feature-rail__collaboration { - left: 31%; - bottom: calc(100% + 8px); - width: clamp(96px, 30vw, 124px); - } - - .cyber-feature-rail__reviewer { - --reviewer-robot-width: clamp(58px, 18vw, 72px); - - right: clamp(6px, 3vw, 16px); - bottom: calc(100% + 8px); - gap: 0; - } - - .cyber-feature-rail__reviewer-card, - .cyber-feature-rail__reviewer-bubble { display: none; } +} - .cyber-feature-rail__robot { - top: 4px; +@media (max-width: 360px) { + .cyber-hero__title { + font-size: 2.1rem; } - .cyber-feature-rail__item { - grid-template-columns: 48px 44px minmax(0, 1fr); - grid-template-rows: auto; - align-items: center; - justify-items: start; - gap: 10px; - padding: 0; - text-align: left; - } - - .cyber-feature-rail__icon { - width: 44px; - height: 44px; - } - - .cyber-feature-rail__icon::before, - .cyber-feature-rail__icon::after { - width: 12px; - height: 12px; - } - - .cyber-feature-rail__icon .v-icon { - font-size: 26px !important; - } - - .cyber-feature-rail__node { - width: 40px; - height: 40px; - font-size: 0.8rem; - } - - .cyber-feature-rail__node::before { - display: none; - } - - .cyber-feature-rail__copy { - max-width: none; - padding: 8px 10px 9px; - } - - .cyber-feature-rail__copy::before { - inset: 0 -6px; - border-radius: 14px; - backdrop-filter: blur(9px) saturate(1.06); - } - - .cyber-feature-rail__title { - margin-bottom: 5px; - font-size: 0.92rem; - } - - .cyber-feature-rail__text { - font-size: 0.78rem; - line-height: 1.42; + .cyber-hero__provider-list { + gap: 9px 12px; } } diff --git a/landing/components/layout/AppFooter.vue b/landing/components/layout/AppFooter.vue index 52be6429..e5a8b025 100644 --- a/landing/components/layout/AppFooter.vue +++ b/landing/components/layout/AppFooter.vue @@ -1,15 +1,18 @@