Skip to content

Commit 8508310

Browse files
tedjamesclaude
andauthored
feat: add Fuma-docs documentation site with Vercel deployment (#2)
* feat(docs): add Fuma-docs documentation site Create a new documentation app at apps/docs using Fuma-docs framework with TanStack Router. - Set up Fuma-docs with TanStack Start and Vite - Migrate existing docs from /docs to MDX format - Create structured navigation with sections for: - Getting Started - Configuration - Test Scenarios (YAML syntax, assertions) - Adapters (database, agent, vector-store, traces-provider) - CLI Reference - Add root scripts: docs:dev, docs:build - Update pnpm-workspace.yaml to include apps/* Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * ci: add Vercel deployment workflow for docs - Add docs.yml workflow for preview and production deployments - Preview deploys on PRs that touch apps/docs/ - Production deploys on main branch merges - Add PR comment with preview URL - Update CI workflow to cache apps/*/node_modules Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: add changeset for docs site Also fix changeset config to use correct package names Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(docs): resolve lint and type-check errors - Add ignores to eslint config for build output directories - Fix import ordering in route files - Fix array type style (string[] -> Array<string>) - Add ts-expect-error for fumadocs-mdx type inference issue - Update tsconfig to use allowJs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(docs): configure Nitro for Vercel deployment - Add vercel.json with outputDirectory config - Set Nitro preset to 'vercel' in vite config Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ci): add permissions for PR comments in docs workflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8de4696 commit 8508310

41 files changed

Lines changed: 9464 additions & 1531 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
"access": "public",
1111
"baseBranch": "main",
1212
"updateInternalDependencies": "patch",
13-
"ignore": ["demo-agent"]
13+
"ignore": ["@agent-qa/demo-agent", "@agent-qa/docs"]
1414
}

.changeset/silver-monkeys-wave.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
---
3+
4+
Add Fuma-docs documentation site with Vercel deployment
5+
6+
- Create documentation app at `apps/docs` using Fuma-docs framework
7+
- Migrate existing markdown docs to MDX format with structured navigation
8+
- Add GitHub Actions workflow for automated Vercel deployments
9+
- Preview deployments on PRs, production deployments on main merges

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
node_modules
2828
packages/*/node_modules
2929
examples/*/node_modules
30+
apps/*/node_modules
3031
key: modules-${{ hashFiles('pnpm-lock.yaml') }}
3132

3233
lint:
@@ -47,6 +48,7 @@ jobs:
4748
node_modules
4849
packages/*/node_modules
4950
examples/*/node_modules
51+
apps/*/node_modules
5052
key: modules-${{ hashFiles('pnpm-lock.yaml') }}
5153
- name: Lint
5254
run: pnpm lint
@@ -69,6 +71,7 @@ jobs:
6971
node_modules
7072
packages/*/node_modules
7173
examples/*/node_modules
74+
apps/*/node_modules
7275
key: modules-${{ hashFiles('pnpm-lock.yaml') }}
7376
- name: Build (required for type-check)
7477
run: pnpm build
@@ -93,6 +96,7 @@ jobs:
9396
node_modules
9497
packages/*/node_modules
9598
examples/*/node_modules
99+
apps/*/node_modules
96100
key: modules-${{ hashFiles('pnpm-lock.yaml') }}
97101
- name: Build (required for tests)
98102
run: pnpm build

.github/workflows/docs.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Docs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'apps/docs/**'
8+
- '.github/workflows/docs.yml'
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- 'apps/docs/**'
13+
- '.github/workflows/docs.yml'
14+
15+
permissions:
16+
contents: read
17+
pull-requests: write
18+
19+
env:
20+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
21+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
22+
23+
jobs:
24+
deploy-preview:
25+
if: github.event_name == 'pull_request'
26+
runs-on: ubuntu-latest
27+
environment:
28+
name: preview
29+
url: ${{ steps.deploy.outputs.url }}
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Setup pnpm
34+
uses: pnpm/action-setup@v4
35+
36+
- name: Setup Node.js
37+
uses: actions/setup-node@v4
38+
with:
39+
node-version: '20'
40+
cache: 'pnpm'
41+
42+
- name: Install dependencies
43+
run: pnpm install --frozen-lockfile
44+
45+
- name: Install Vercel CLI
46+
run: pnpm add -g vercel@latest
47+
48+
- name: Pull Vercel environment
49+
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
50+
working-directory: apps/docs
51+
52+
- name: Build
53+
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
54+
working-directory: apps/docs
55+
56+
- name: Deploy to Vercel (Preview)
57+
id: deploy
58+
run: |
59+
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
60+
echo "url=$url" >> $GITHUB_OUTPUT
61+
working-directory: apps/docs
62+
63+
- name: Comment PR with preview URL
64+
uses: actions/github-script@v7
65+
with:
66+
script: |
67+
github.rest.issues.createComment({
68+
issue_number: context.issue.number,
69+
owner: context.repo.owner,
70+
repo: context.repo.repo,
71+
body: `📚 Docs preview deployed to: ${{ steps.deploy.outputs.url }}`
72+
})
73+
74+
deploy-production:
75+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
76+
runs-on: ubuntu-latest
77+
environment:
78+
name: production
79+
url: ${{ steps.deploy.outputs.url }}
80+
steps:
81+
- uses: actions/checkout@v4
82+
83+
- name: Setup pnpm
84+
uses: pnpm/action-setup@v4
85+
86+
- name: Setup Node.js
87+
uses: actions/setup-node@v4
88+
with:
89+
node-version: '20'
90+
cache: 'pnpm'
91+
92+
- name: Install dependencies
93+
run: pnpm install --frozen-lockfile
94+
95+
- name: Install Vercel CLI
96+
run: pnpm add -g vercel@latest
97+
98+
- name: Pull Vercel environment
99+
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
100+
working-directory: apps/docs
101+
102+
- name: Build
103+
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
104+
working-directory: apps/docs
105+
106+
- name: Deploy to Vercel (Production)
107+
id: deploy
108+
run: |
109+
url=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
110+
echo "url=$url" >> $GITHUB_OUTPUT
111+
working-directory: apps/docs

apps/docs/.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
6+
count.txt
7+
.env
8+
.nitro
9+
.tanstack
10+
.wrangler
11+
.output
12+
.vinxi
13+
todos.json
14+
.source
15+
.vercel

apps/docs/.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package-lock.json
2+
pnpm-lock.yaml
3+
yarn.lock
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
title: Agent Adapter
3+
description: Implementing custom agent adapters for Agent QA
4+
---
5+
6+
# Agent Adapter
7+
8+
The `AgentAdapter` interface allows you to customize how Agent QA communicates with your AI agent.
9+
10+
## Interface
11+
12+
```typescript
13+
interface AgentAdapter {
14+
chat(options: ChatOptions): Promise<AgentResponse>;
15+
cleanup?(): Promise<void>;
16+
}
17+
18+
interface ChatOptions {
19+
message: string;
20+
userId: string;
21+
conversationId?: string;
22+
maxToolCalls?: number;
23+
timeout?: number;
24+
}
25+
26+
interface AgentResponse {
27+
text: string;
28+
toolCalls: ToolCall[];
29+
conversationId: string;
30+
correlationId?: string;
31+
usage?: TokenUsage;
32+
detailedUsage?: DetailedUsage;
33+
}
34+
```
35+
36+
## Built-in HTTP Adapter
37+
38+
The default adapter communicates via HTTP:
39+
40+
```typescript
41+
import { createHttpAgentFromConfig } from '@agent-qa/core';
42+
43+
const adapter = createHttpAgentFromConfig({
44+
baseUrl: 'http://localhost:4000',
45+
token: 'your-token',
46+
chatEndpoint: '/v1/chat',
47+
});
48+
```
49+
50+
## Example: WebSocket Adapter
51+
52+
```typescript
53+
import type { AgentAdapter, ChatOptions, AgentResponse } from '@agent-qa/core';
54+
55+
export function createWebSocketAdapter(url: string): AgentAdapter {
56+
let ws: WebSocket | null = null;
57+
58+
return {
59+
async chat(options: ChatOptions): Promise<AgentResponse> {
60+
if (!ws || ws.readyState !== WebSocket.OPEN) {
61+
ws = new WebSocket(url);
62+
await new Promise((resolve, reject) => {
63+
ws!.onopen = resolve;
64+
ws!.onerror = reject;
65+
});
66+
}
67+
68+
return new Promise((resolve, reject) => {
69+
const timeout = setTimeout(() => {
70+
reject(new Error('Chat timeout'));
71+
}, options.timeout ?? 60000);
72+
73+
ws!.onmessage = (event) => {
74+
clearTimeout(timeout);
75+
const data = JSON.parse(event.data);
76+
resolve({
77+
text: data.response,
78+
toolCalls: data.toolCalls ?? [],
79+
conversationId: data.conversationId,
80+
correlationId: data.correlationId,
81+
usage: data.usage,
82+
});
83+
};
84+
85+
ws!.send(JSON.stringify({
86+
message: options.message,
87+
userId: options.userId,
88+
conversationId: options.conversationId,
89+
}));
90+
});
91+
},
92+
93+
async cleanup(): Promise<void> {
94+
if (ws) {
95+
ws.close();
96+
ws = null;
97+
}
98+
},
99+
};
100+
}
101+
```
102+
103+
## Using Custom Agent Adapter
104+
105+
```typescript
106+
// agentqa.config.ts
107+
import { defineConfig } from '@agent-qa/core';
108+
import { createWebSocketAdapter } from './ws-adapter';
109+
110+
export default defineConfig({
111+
name: 'MyApp',
112+
113+
agent: {
114+
adapter: createWebSocketAdapter('ws://localhost:4000/chat'),
115+
},
116+
});
117+
```
118+
119+
## Programmatic Usage
120+
121+
```typescript
122+
import { createTestRunner } from '@agent-qa/core';
123+
import { createWebSocketAdapter } from './ws-adapter';
124+
125+
const runner = createTestRunner(config, {
126+
agent: createWebSocketAdapter('ws://localhost:4000/chat'),
127+
});
128+
```

0 commit comments

Comments
 (0)