Skip to content

Commit 26b4ada

Browse files
committed
fix: auth, middleware, workflows and docs improvements
Consolidate post-PR#6 changes: - docs: simplify README and fix marketplace e2e - chore(auth): surface exact NextAuth client error - test(auth): update login form assertions to match new errors - fix(middleware): allow api access from app's own origin - style(middleware): run prettier to fix ci format check - fix(middleware): handle malformed NEXT_PUBLIC_APP_URL env var - fix(auth): fallback to local workspace when Supabase query fails - fix(workflows): bypass Supabase for local-workspace mode
1 parent 64ea378 commit 26b4ada

7 files changed

Lines changed: 30 additions & 41 deletions

File tree

README.md

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# AgentKit
1+
# AI Agent Builder for ASAP Protocol
22

33
Platform for building, configuring, and running AI agents with tool execution, workflows, and integrations.
44

@@ -7,6 +7,7 @@ Platform for building, configuring, and running AI agents with tool execution, w
77
- **Agents & runs** — Manage agents and view execution history
88
- **Workflow builder** — Visual editor for workflow orchestration (React Flow)
99
- **Connectors** — Central registry for data and tool connections (OAuth, APIs, MCP)
10+
- **Cross-platform integration** — Navigation and auth hand-off with ASAP Protocol
1011
- **MCP** — Model Context Protocol server and tool management
1112
- **Marketplace** — Discover and install integrations
1213
- **Templates** — Reusable workflow and agent templates
@@ -22,31 +23,8 @@ Platform for building, configuring, and running AI agents with tool execution, w
2223
- **Data:** SWR, Recharts
2324
- **Workflow canvas:** React Flow (`@xyflow/react`)
2425

25-
## Getting started
26+
### Cross-platform integration with ASAP Protocol
2627

27-
1. Install dependencies: `npm install`
28-
2. Copy environment variables (see below) and configure a `.env` file.
29-
3. Run development server: `npm run dev`
30-
31-
Required env vars for Supabase (auth and database):
32-
33-
- `NEXT_PUBLIC_SUPABASE_URL`
34-
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
28+
This app is integrated with ASAP Protocol to provide a unified marketplace and navigation experience.
3529

3630
Use the `/setup` route after starting the app to validate the connection and run migrations if needed.
37-
38-
## Scripts
39-
40-
| Script | Description |
41-
| ------------------------ | -------------------------------------------------- |
42-
| `npm run dev` | Development server (port 3000) |
43-
| `npm run build` | Production build |
44-
| `npm run start` | Production server |
45-
| `npm run lint` | ESLint |
46-
| `npm run test` | Unit tests (Vitest, watch) |
47-
| `npm run test:run` | Unit tests (single run) |
48-
| `npm run test:e2e` | E2E tests (Playwright, starts dev on port 3099) |
49-
| `npm run test:e2e:ui` | E2E tests with Playwright UI |
50-
| `npm run test:e2e:reuse` | E2E tests reusing existing dev server on port 3000 |
51-
52-
**E2E notes:** Stop any running `npm run dev` before `npm run test:e2e`, or use `npm run test:e2e:reuse` when dev is already running.

e2e/marketplace.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ test.describe("ASAP Agent Registry", () => {
1010
})
1111

1212
test("shows registry description", async ({ page }) => {
13-
await expect(page.getByText(/Discover agents registered on the ASAP Protocol/i)).toBeVisible()
13+
await expect(
14+
page.getByText(/Discover agents registered on the ASAP Protocol/i).first(),
15+
).toBeVisible()
1416
})
1517

1618
test("has search input", async ({ page }) => {

src/components/auth/login-form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ export function LoginForm({ fromAsap }: LoginFormProps) {
3131
try {
3232
const result = await signIn("github", { callbackUrl: "/", redirect: false })
3333
if (result && !result.ok) {
34-
toast.error("Failed to sign in with GitHub")
34+
toast.error("Failed to sign in: " + result.error)
3535
setIsLoading(false)
3636
} else if (result?.url) {
3737
window.location.href = result.url
3838
}
39-
} catch {
40-
toast.error("Failed to sign in with GitHub")
39+
} catch (err: any) {
40+
toast.error("Failed to sign in catch: " + (err?.message || "Unknown error"))
4141
setIsLoading(false)
4242
}
4343
}

src/lib/db/workflows.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if (process.env.NODE_ENV !== "production") globalForWorkflows.memoryWorkflows =
1010

1111
export async function getWorkflows(workspaceId: string): Promise<Workflow[]> {
1212
const supabase = await getSupabaseServerClient()
13-
if (!supabase) return Array.from(memoryWorkflows.values())
13+
if (!supabase || workspaceId === "local-workspace") return Array.from(memoryWorkflows.values())
1414
const { data, error } = await supabase
1515
.from("workflows")
1616
.select("*")
@@ -35,7 +35,7 @@ export async function createWorkflow(
3535
workflow: Omit<Workflow, "id" | "version" | "createdAt" | "updatedAt">,
3636
): Promise<Workflow> {
3737
const supabase = await getSupabaseServerClient()
38-
if (!supabase) {
38+
if (!supabase || workspaceId === "local-workspace") {
3939
const newWorkflow: Workflow = {
4040
id: crypto.randomUUID(),
4141
workspaceId,

src/lib/db/workspaces.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ export async function getCurrentWorkspace() {
1616
.limit(1)
1717
.single()
1818

19-
if (error) return null
19+
if (error || !data?.workspaces) {
20+
return { id: "local-workspace", name: "Local Workspace" } as any
21+
}
2022
return data.workspaces as any
2123
}
2224

@@ -33,7 +35,9 @@ export async function getUserWorkspaces() {
3335
.select("workspace_id, role, workspaces(*)")
3436
.eq("user_id", user.id)
3537

36-
if (error) return []
38+
if (error || !data?.length) {
39+
return [{ id: "local-workspace", name: "Local Workspace", role: "admin" }] as any
40+
}
3741
return data.map((item) => ({ ...item.workspaces, role: item.role }))
3842
}
3943

src/middleware.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ const ratelimit =
2020
: null
2121

2222
export async function middleware(request: NextRequest) {
23-
const allowedOrigin =
24-
process.env.NEXT_PUBLIC_ASAP_PROTOCOL_URL || "https://asap-protocol.vercel.app"
23+
const allowedOriginAsap = process.env.NEXT_PUBLIC_ASAP_PROTOCOL_URL?.startsWith("http")
24+
? process.env.NEXT_PUBLIC_ASAP_PROTOCOL_URL
25+
: "https://asap-protocol.vercel.app"
26+
const allowedOriginSelf = process.env.NEXT_PUBLIC_APP_URL?.startsWith("http")
27+
? process.env.NEXT_PUBLIC_APP_URL
28+
: "https://open-agentic-flow.vercel.app"
2529
const requestOrigin = request.headers.get("origin")
2630

2731
// For /api routes, reject non-allowlisted cross-origin requests
@@ -46,15 +50,16 @@ export async function middleware(request: NextRequest) {
4650

4751
if (
4852
requestOrigin &&
49-
!requestOrigin.startsWith(allowedOrigin) &&
53+
!requestOrigin.startsWith(allowedOriginAsap) &&
54+
!requestOrigin.startsWith(allowedOriginSelf) &&
5055
!requestOrigin.startsWith("http://localhost")
5156
) {
5257
return new NextResponse("Forbidden", { status: 403 })
5358
}
5459

5560
if (request.method === "OPTIONS") {
5661
const preflightHeaders = {
57-
"Access-Control-Allow-Origin": requestOrigin || allowedOrigin,
62+
"Access-Control-Allow-Origin": requestOrigin || allowedOriginSelf,
5863
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
5964
"Access-Control-Allow-Headers": "Content-Type, Authorization",
6065
}
@@ -63,7 +68,7 @@ export async function middleware(request: NextRequest) {
6368

6469
// Pass the request along with CORS headers attached to the response
6570
const response = NextResponse.next()
66-
response.headers.set("Access-Control-Allow-Origin", requestOrigin || allowedOrigin)
71+
response.headers.set("Access-Control-Allow-Origin", requestOrigin || allowedOriginSelf)
6772
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
6873
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization")
6974
return response

tests/components/login-form.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe("LoginForm", () => {
7676
await user.click(screen.getByRole("button", { name: /sign in with github/i }))
7777

7878
await waitFor(() => {
79-
expect(toast.error).toHaveBeenCalledWith("Failed to sign in with GitHub")
79+
expect(toast.error).toHaveBeenCalledWith("Failed to sign in catch: Auth failed")
8080
})
8181
})
8282

@@ -95,7 +95,7 @@ describe("LoginForm", () => {
9595
await user.click(screen.getByRole("button", { name: /sign in with github/i }))
9696

9797
await waitFor(() => {
98-
expect(toast.error).toHaveBeenCalledWith("Failed to sign in with GitHub")
98+
expect(toast.error).toHaveBeenCalledWith("Failed to sign in: OAuthError")
9999
})
100100
})
101101
})

0 commit comments

Comments
 (0)