Merge pull request #237 from multica-ai/forrestchang/remove-fe-mocks
refactor(web): remove frontend mock data
This commit is contained in:
commit
e9555b8a22
6 changed files with 41 additions and 733 deletions
|
|
@ -8,7 +8,7 @@ import {
|
|||
Send,
|
||||
} from "lucide-react";
|
||||
import type { Issue, Comment } from "@multica/types";
|
||||
import { STATUS_CONFIG, PRIORITY_CONFIG } from "../_data/mock";
|
||||
import { STATUS_CONFIG, PRIORITY_CONFIG } from "../_data/config";
|
||||
import { StatusIcon, PriorityIcon } from "../page";
|
||||
import { api } from "../../../../lib/api";
|
||||
import { useAuth } from "../../../../lib/auth-context";
|
||||
|
|
|
|||
25
apps/web/app/(dashboard)/issues/_data/config.ts
Normal file
25
apps/web/app/(dashboard)/issues/_data/config.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import type { IssueStatus, IssuePriority } from "@multica/types";
|
||||
|
||||
export const STATUS_CONFIG: Record<
|
||||
IssueStatus,
|
||||
{ label: string; iconColor: string }
|
||||
> = {
|
||||
backlog: { label: "Backlog", iconColor: "text-muted-foreground" },
|
||||
todo: { label: "Todo", iconColor: "text-muted-foreground" },
|
||||
in_progress: { label: "In Progress", iconColor: "text-yellow-500" },
|
||||
in_review: { label: "In Review", iconColor: "text-blue-500" },
|
||||
done: { label: "Done", iconColor: "text-green-500" },
|
||||
blocked: { label: "Blocked", iconColor: "text-red-500" },
|
||||
cancelled: { label: "Cancelled", iconColor: "text-muted-foreground/50" },
|
||||
};
|
||||
|
||||
export const PRIORITY_CONFIG: Record<
|
||||
IssuePriority,
|
||||
{ label: string; bars: number; color: string }
|
||||
> = {
|
||||
urgent: { label: "Urgent", bars: 4, color: "text-orange-500" },
|
||||
high: { label: "High", bars: 3, color: "text-orange-400" },
|
||||
medium: { label: "Medium", bars: 2, color: "text-yellow-500" },
|
||||
low: { label: "Low", bars: 1, color: "text-blue-400" },
|
||||
none: { label: "No priority", bars: 0, color: "text-muted-foreground" },
|
||||
};
|
||||
|
|
@ -1,441 +0,0 @@
|
|||
import type { IssueStatus, IssuePriority } from "@multica/types";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Extended types for mock UI
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface MockAssignee {
|
||||
id: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
type: "member" | "agent";
|
||||
}
|
||||
|
||||
export interface MockComment {
|
||||
id: string;
|
||||
author: MockAssignee;
|
||||
body: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface MockActivity {
|
||||
id: string;
|
||||
actor: MockAssignee;
|
||||
action: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface MockIssue {
|
||||
id: string;
|
||||
key: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
status: IssueStatus;
|
||||
priority: IssuePriority;
|
||||
assignee: MockAssignee | null;
|
||||
creator: MockAssignee;
|
||||
dueDate: string | null;
|
||||
comments: MockComment[];
|
||||
activity: MockActivity[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// People & Agents
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const PEOPLE: Record<string, MockAssignee> = {
|
||||
jiayuan: { id: "usr_1", name: "Jiayuan", avatar: "JY", type: "member" },
|
||||
bohan: { id: "usr_2", name: "Bohan", avatar: "BH", type: "member" },
|
||||
yuzhen: { id: "usr_3", name: "Yuzhen", avatar: "YZ", type: "member" },
|
||||
claude1: { id: "agent_1", name: "Claude-1", avatar: "C1", type: "agent" },
|
||||
codex1: { id: "agent_2", name: "Codex-1", avatar: "CX", type: "agent" },
|
||||
reviewBot: { id: "agent_3", name: "Review Bot", avatar: "RB", type: "agent" },
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Status & Priority config
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const STATUS_ORDER: IssueStatus[] = [
|
||||
"backlog",
|
||||
"todo",
|
||||
"in_progress",
|
||||
"in_review",
|
||||
"done",
|
||||
"cancelled",
|
||||
];
|
||||
|
||||
export const STATUS_CONFIG: Record<
|
||||
IssueStatus,
|
||||
{ label: string; iconColor: string }
|
||||
> = {
|
||||
backlog: { label: "Backlog", iconColor: "text-muted-foreground" },
|
||||
todo: { label: "Todo", iconColor: "text-muted-foreground" },
|
||||
in_progress: { label: "In Progress", iconColor: "text-yellow-500" },
|
||||
in_review: { label: "In Review", iconColor: "text-blue-500" },
|
||||
done: { label: "Done", iconColor: "text-green-500" },
|
||||
blocked: { label: "Blocked", iconColor: "text-red-500" },
|
||||
cancelled: { label: "Cancelled", iconColor: "text-muted-foreground/50" },
|
||||
};
|
||||
|
||||
export const PRIORITY_CONFIG: Record<
|
||||
IssuePriority,
|
||||
{ label: string; bars: number; color: string }
|
||||
> = {
|
||||
urgent: { label: "Urgent", bars: 4, color: "text-orange-500" },
|
||||
high: { label: "High", bars: 3, color: "text-orange-400" },
|
||||
medium: { label: "Medium", bars: 2, color: "text-yellow-500" },
|
||||
low: { label: "Low", bars: 1, color: "text-blue-400" },
|
||||
none: { label: "No priority", bars: 0, color: "text-muted-foreground" },
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mock Issues
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const jiayuan = PEOPLE["jiayuan"]!;
|
||||
const bohan = PEOPLE["bohan"]!;
|
||||
const yuzhen = PEOPLE["yuzhen"]!;
|
||||
const claude1 = PEOPLE["claude1"]!;
|
||||
const codex1 = PEOPLE["codex1"]!;
|
||||
const reviewBot = PEOPLE["reviewBot"]!;
|
||||
|
||||
export const MOCK_ISSUES: MockIssue[] = [
|
||||
// ---- Backlog ----
|
||||
{
|
||||
id: "iss_20",
|
||||
key: "MUL-20",
|
||||
title: "Add multi-workspace support",
|
||||
description:
|
||||
"Allow users to create and switch between multiple workspaces. Each workspace should have isolated issues, agents, and knowledge base.",
|
||||
status: "backlog",
|
||||
priority: "low",
|
||||
assignee: null,
|
||||
creator: jiayuan,
|
||||
dueDate: null,
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_20_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-18T10:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-18T10:00:00Z",
|
||||
updatedAt: "2026-03-18T10:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_21",
|
||||
key: "MUL-21",
|
||||
title: "Agent long-term memory persistence",
|
||||
description:
|
||||
"Implement a memory system for agents that persists across task executions. Should support both vector embeddings and structured key-value storage.",
|
||||
status: "backlog",
|
||||
priority: "medium",
|
||||
assignee: null,
|
||||
creator: bohan,
|
||||
dueDate: null,
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_21_1", actor: bohan, action: "created this issue", createdAt: "2026-03-19T08:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-19T08:00:00Z",
|
||||
updatedAt: "2026-03-19T08:00:00Z",
|
||||
},
|
||||
|
||||
// ---- Todo ----
|
||||
{
|
||||
id: "iss_15",
|
||||
key: "MUL-15",
|
||||
title: "Design the agent config UI",
|
||||
description:
|
||||
"We need a configuration panel where users can set up their local agents — select runtime type, set concurrency limits, and manage API keys. This should live in the Settings page for now.",
|
||||
status: "todo",
|
||||
priority: "high",
|
||||
assignee: jiayuan,
|
||||
creator: bohan,
|
||||
dueDate: "2026-03-25T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_15_1",
|
||||
author: bohan,
|
||||
body: "Let's keep this simple for MVP — just runtime selection and concurrency slider.",
|
||||
createdAt: "2026-03-20T09:00:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_15_1", actor: bohan, action: "created this issue", createdAt: "2026-03-20T08:00:00Z" },
|
||||
{ id: "act_15_2", actor: bohan, action: "assigned this to Jiayuan", createdAt: "2026-03-20T08:00:00Z" },
|
||||
{ id: "act_15_3", actor: bohan, action: "set priority to High", createdAt: "2026-03-20T08:01:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-20T08:00:00Z",
|
||||
updatedAt: "2026-03-20T09:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_16",
|
||||
key: "MUL-16",
|
||||
title: "Implement knowledge base document editor",
|
||||
description:
|
||||
"Build a Markdown editor for creating and editing knowledge base documents. Should support basic formatting, code blocks, and image uploads.",
|
||||
status: "todo",
|
||||
priority: "medium",
|
||||
assignee: codex1,
|
||||
creator: yuzhen,
|
||||
dueDate: "2026-03-28T00:00:00Z",
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_16_1", actor: yuzhen, action: "created this issue", createdAt: "2026-03-19T14:00:00Z" },
|
||||
{ id: "act_16_2", actor: yuzhen, action: "assigned this to Codex-1", createdAt: "2026-03-19T14:01:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-19T14:00:00Z",
|
||||
updatedAt: "2026-03-19T14:01:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_17",
|
||||
key: "MUL-17",
|
||||
title: "Add issue dependency tracking",
|
||||
description: "Support blocking/blocked-by relationships between issues. Show dependency graph in issue detail view.",
|
||||
status: "todo",
|
||||
priority: "low",
|
||||
assignee: null,
|
||||
creator: jiayuan,
|
||||
dueDate: null,
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_17_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-20T11:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-20T11:00:00Z",
|
||||
updatedAt: "2026-03-20T11:00:00Z",
|
||||
},
|
||||
|
||||
// ---- In Progress ----
|
||||
{
|
||||
id: "iss_9",
|
||||
key: "MUL-9",
|
||||
title: "Implement issue list API endpoint",
|
||||
description:
|
||||
"Build the REST API endpoint for listing and filtering issues.\n\n## Requirements\n- Pagination with cursor-based approach\n- Filter by status, priority, assignee\n- Sort by priority, status, created_at\n- Include assignee info in response",
|
||||
status: "in_progress",
|
||||
priority: "high",
|
||||
assignee: claude1,
|
||||
creator: jiayuan,
|
||||
dueDate: "2026-03-22T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_9_1",
|
||||
author: claude1,
|
||||
body: "Started working on this. Using sqlc for the query generation. I'll implement cursor-based pagination with the `created_at` + `id` compound cursor.",
|
||||
createdAt: "2026-03-20T14:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "cmt_9_2",
|
||||
author: jiayuan,
|
||||
body: "Sounds good. Make sure to add an index on (status, created_at) for the filtered queries.",
|
||||
createdAt: "2026-03-20T14:30:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_9_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-19T10:00:00Z" },
|
||||
{ id: "act_9_2", actor: jiayuan, action: "assigned this to Claude-1", createdAt: "2026-03-19T10:00:00Z" },
|
||||
{ id: "act_9_3", actor: claude1, action: "moved this to In Progress", createdAt: "2026-03-20T13:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-19T10:00:00Z",
|
||||
updatedAt: "2026-03-20T14:30:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_12",
|
||||
key: "MUL-12",
|
||||
title: "Implement OAuth login flow",
|
||||
description:
|
||||
"Set up Google OAuth for user authentication. Include PKCE flow for the SPA and session management on the server side.",
|
||||
status: "in_progress",
|
||||
priority: "urgent",
|
||||
assignee: claude1,
|
||||
creator: jiayuan,
|
||||
dueDate: "2026-03-21T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_12_1",
|
||||
author: claude1,
|
||||
body: "I need clarification on the authentication flow. The current OAuth implementation uses PKCE, but the design doc references a session-based approach. Which one should I follow?",
|
||||
createdAt: "2026-03-21T05:32:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_12_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-18T09:00:00Z" },
|
||||
{ id: "act_12_2", actor: jiayuan, action: "assigned this to Claude-1", createdAt: "2026-03-18T09:01:00Z" },
|
||||
{ id: "act_12_3", actor: claude1, action: "moved this to In Progress", createdAt: "2026-03-20T10:00:00Z" },
|
||||
{ id: "act_12_4", actor: claude1, action: "marked as Blocked", createdAt: "2026-03-21T05:32:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-18T09:00:00Z",
|
||||
updatedAt: "2026-03-21T05:32:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_10",
|
||||
key: "MUL-10",
|
||||
title: "Set up pgvector for knowledge base embeddings",
|
||||
description:
|
||||
"Configure pgvector extension and create the embeddings table for semantic search in the knowledge base.",
|
||||
status: "in_progress",
|
||||
priority: "medium",
|
||||
assignee: yuzhen,
|
||||
creator: yuzhen,
|
||||
dueDate: "2026-03-24T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_10_1",
|
||||
author: yuzhen,
|
||||
body: "@jiayuan Can you take a look at the database schema? I want to make sure the vector embeddings table is set up correctly before we start indexing.",
|
||||
createdAt: "2026-03-20T18:30:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_10_1", actor: yuzhen, action: "created this issue", createdAt: "2026-03-19T11:00:00Z" },
|
||||
{ id: "act_10_2", actor: yuzhen, action: "moved this to In Progress", createdAt: "2026-03-20T09:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-19T11:00:00Z",
|
||||
updatedAt: "2026-03-20T18:30:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_14",
|
||||
key: "MUL-14",
|
||||
title: "Add WebSocket event types for agent status",
|
||||
description: "Define and implement WebSocket message types for real-time agent status updates (idle, working, blocked, error, offline).",
|
||||
status: "in_progress",
|
||||
priority: "high",
|
||||
assignee: bohan,
|
||||
creator: bohan,
|
||||
dueDate: "2026-03-23T00:00:00Z",
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_14_1", actor: bohan, action: "created this issue", createdAt: "2026-03-20T08:00:00Z" },
|
||||
{ id: "act_14_2", actor: bohan, action: "moved this to In Progress", createdAt: "2026-03-20T16:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-20T08:00:00Z",
|
||||
updatedAt: "2026-03-20T16:00:00Z",
|
||||
},
|
||||
|
||||
// ---- In Review ----
|
||||
{
|
||||
id: "iss_8",
|
||||
key: "MUL-8",
|
||||
title: "Add WebSocket reconnection logic",
|
||||
description:
|
||||
"Implement exponential backoff for WebSocket reconnection in the daemon. Include configurable max retry attempts.",
|
||||
status: "in_review",
|
||||
priority: "high",
|
||||
assignee: codex1,
|
||||
creator: bohan,
|
||||
dueDate: "2026-03-21T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_8_1",
|
||||
author: codex1,
|
||||
body: "PR #47 submitted. Chose exponential backoff over linear retry because of the bursty reconnection pattern observed in daemon logs.",
|
||||
createdAt: "2026-03-21T04:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "cmt_8_2",
|
||||
author: reviewBot,
|
||||
body: "Code review passed. No security issues found. Minor suggestion: consider adding jitter to the backoff to avoid thundering herd.",
|
||||
createdAt: "2026-03-21T04:30:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_8_1", actor: bohan, action: "created this issue", createdAt: "2026-03-17T10:00:00Z" },
|
||||
{ id: "act_8_2", actor: bohan, action: "assigned this to Codex-1", createdAt: "2026-03-17T10:01:00Z" },
|
||||
{ id: "act_8_3", actor: codex1, action: "moved this to In Progress", createdAt: "2026-03-19T08:00:00Z" },
|
||||
{ id: "act_8_4", actor: codex1, action: "moved this to In Review", createdAt: "2026-03-21T04:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-17T10:00:00Z",
|
||||
updatedAt: "2026-03-21T04:30:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_11",
|
||||
key: "MUL-11",
|
||||
title: "Implement inbox notification API",
|
||||
description: "Build REST endpoints for inbox CRUD — list, mark read, archive. Include filtering by severity and type.",
|
||||
status: "in_review",
|
||||
priority: "medium",
|
||||
assignee: claude1,
|
||||
creator: jiayuan,
|
||||
dueDate: "2026-03-22T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_11_1",
|
||||
author: claude1,
|
||||
body: "PR #48 is ready. All tests pass, including the new integration tests for batch mark-as-read.",
|
||||
createdAt: "2026-03-21T02:00:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_11_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-18T14:00:00Z" },
|
||||
{ id: "act_11_2", actor: jiayuan, action: "assigned this to Claude-1", createdAt: "2026-03-18T14:00:00Z" },
|
||||
{ id: "act_11_3", actor: claude1, action: "moved this to In Review", createdAt: "2026-03-21T02:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-18T14:00:00Z",
|
||||
updatedAt: "2026-03-21T02:00:00Z",
|
||||
},
|
||||
|
||||
// ---- Done ----
|
||||
{
|
||||
id: "iss_3",
|
||||
key: "MUL-3",
|
||||
title: "Set up CI/CD pipeline",
|
||||
description: "Configure GitHub Actions for build, test, and lint on every push to main.",
|
||||
status: "done",
|
||||
priority: "high",
|
||||
assignee: bohan,
|
||||
creator: bohan,
|
||||
dueDate: "2026-03-18T00:00:00Z",
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_3_1", actor: bohan, action: "created this issue", createdAt: "2026-03-15T09:00:00Z" },
|
||||
{ id: "act_3_2", actor: bohan, action: "moved this to Done", createdAt: "2026-03-20T15:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-15T09:00:00Z",
|
||||
updatedAt: "2026-03-20T15:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_6",
|
||||
key: "MUL-6",
|
||||
title: "Standardize API error handling",
|
||||
description: "Create a consistent error response format across all API endpoints. Add error codes enum and panic recovery middleware.",
|
||||
status: "done",
|
||||
priority: "medium",
|
||||
assignee: claude1,
|
||||
creator: jiayuan,
|
||||
dueDate: "2026-03-20T00:00:00Z",
|
||||
comments: [
|
||||
{
|
||||
id: "cmt_6_1",
|
||||
author: claude1,
|
||||
body: "All acceptance criteria passed. PR #45 created and CI is green.",
|
||||
createdAt: "2026-03-20T22:10:00Z",
|
||||
},
|
||||
],
|
||||
activity: [
|
||||
{ id: "act_6_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-16T10:00:00Z" },
|
||||
{ id: "act_6_2", actor: jiayuan, action: "assigned this to Claude-1", createdAt: "2026-03-16T10:00:00Z" },
|
||||
{ id: "act_6_3", actor: claude1, action: "moved this to Done", createdAt: "2026-03-20T22:10:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-16T10:00:00Z",
|
||||
updatedAt: "2026-03-20T22:10:00Z",
|
||||
},
|
||||
{
|
||||
id: "iss_1",
|
||||
key: "MUL-1",
|
||||
title: "Initialize monorepo structure",
|
||||
description: "Set up the polyglot monorepo with Go backend, Next.js frontend, and shared TypeScript packages.",
|
||||
status: "done",
|
||||
priority: "urgent",
|
||||
assignee: jiayuan,
|
||||
creator: jiayuan,
|
||||
dueDate: "2026-03-15T00:00:00Z",
|
||||
comments: [],
|
||||
activity: [
|
||||
{ id: "act_1_1", actor: jiayuan, action: "created this issue", createdAt: "2026-03-14T08:00:00Z" },
|
||||
{ id: "act_1_2", actor: jiayuan, action: "moved this to Done", createdAt: "2026-03-15T18:00:00Z" },
|
||||
],
|
||||
createdAt: "2026-03-14T08:00:00Z",
|
||||
updatedAt: "2026-03-15T18:00:00Z",
|
||||
},
|
||||
];
|
||||
|
|
@ -30,7 +30,7 @@ import {
|
|||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import type { Issue, IssueStatus, IssuePriority } from "@multica/types";
|
||||
import { STATUS_CONFIG, PRIORITY_CONFIG } from "./_data/mock";
|
||||
import { STATUS_CONFIG, PRIORITY_CONFIG } from "./_data/config";
|
||||
import { api } from "../../../lib/api";
|
||||
import { useAuth } from "../../../lib/auth-context";
|
||||
import { useWSEvent } from "../../../lib/ws-context";
|
||||
|
|
|
|||
|
|
@ -1,282 +0,0 @@
|
|||
export interface KBDocument {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
createdBy: string;
|
||||
updatedAt: string;
|
||||
referencedBy: string[];
|
||||
}
|
||||
|
||||
export const MOCK_DOCUMENTS: KBDocument[] = [
|
||||
{
|
||||
id: "kb_1",
|
||||
title: "Product Vision & Positioning",
|
||||
content: `Multica is an AI-native task management platform — like Linear, but with AI agents as first-class citizens.
|
||||
|
||||
## Target Users
|
||||
|
||||
- 2–10 person technical teams / startups
|
||||
- Teams that already use AI coding agents daily (Claude Code, Codex, etc.)
|
||||
- Current toolchain: Linear/GitHub Issues + Claude Code/Codex + GitHub + IM
|
||||
|
||||
## Core Value Proposition
|
||||
|
||||
| Dimension | Existing Tools (Linear) | Multica |
|
||||
|-----------|------------------------|---------|
|
||||
| Task executor | Humans only | Humans + Agents |
|
||||
| Context | Manual copy-paste | Auto-aggregated, agents read directly |
|
||||
| Task flow | Human-driven status changes | Agents auto-flow + notify humans when decisions needed |
|
||||
| Concurrency | Limited by team size | Parallel agent dispatch |
|
||||
|
||||
## What We Are NOT
|
||||
|
||||
- Not a general-purpose project management tool (no Gantt charts, resource planning)
|
||||
- Not an AI agent framework (we orchestrate, not build agents)
|
||||
- Not a chat product (Inbox is action-oriented, not conversational)`,
|
||||
createdBy: "Jiayuan",
|
||||
updatedAt: "2026-03-20T10:00:00Z",
|
||||
referencedBy: ["MUL-1"],
|
||||
},
|
||||
{
|
||||
id: "kb_2",
|
||||
title: "Architecture Overview",
|
||||
content: `## System Architecture
|
||||
|
||||
Polyglot monorepo — Go backend + TypeScript frontend.
|
||||
|
||||
\`\`\`
|
||||
server/ — Go backend (Chi + sqlc + gorilla/websocket)
|
||||
apps/web/ — Next.js 16 frontend
|
||||
packages/ — Shared TypeScript packages (ui, types, sdk, store, hooks, utils)
|
||||
\`\`\`
|
||||
|
||||
## Backend
|
||||
|
||||
- **HTTP Framework**: Chi router
|
||||
- **Database**: PostgreSQL 17 with pgvector extension
|
||||
- **ORM/Query**: sqlc (type-safe SQL → Go code generation)
|
||||
- **WebSocket**: gorilla/websocket for real-time agent status updates
|
||||
- **Auth**: Google OAuth with JWT tokens
|
||||
|
||||
## Frontend
|
||||
|
||||
- **Framework**: Next.js 16 (App Router)
|
||||
- **UI Components**: shadcn/ui (Radix + Tailwind CSS v4)
|
||||
- **State**: Zustand
|
||||
- **Styling**: Tailwind CSS v4, OKLCH color system
|
||||
|
||||
## Agent Communication
|
||||
|
||||
\`\`\`
|
||||
Server ←→ WebSocket Gateway ←→ Daemon (local machine)
|
||||
↓
|
||||
Claude Code / Codex / etc.
|
||||
\`\`\`
|
||||
|
||||
The Daemon is a local process that maintains a persistent WebSocket connection to the server, receives task assignments, and delegates to the underlying AI runtime.`,
|
||||
createdBy: "Jiayuan",
|
||||
updatedAt: "2026-03-19T14:00:00Z",
|
||||
referencedBy: ["MUL-9", "MUL-14"],
|
||||
},
|
||||
{
|
||||
id: "kb_3",
|
||||
title: "API Error Handling Convention",
|
||||
content: `## Error Response Format
|
||||
|
||||
All API errors follow this structure:
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"error": {
|
||||
"code": "ISSUE_NOT_FOUND",
|
||||
"message": "Issue with id 'iss_999' not found",
|
||||
"details": {}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Error Codes
|
||||
|
||||
| Code | HTTP Status | Description |
|
||||
|------|-------------|-------------|
|
||||
| VALIDATION_ERROR | 400 | Request body/params validation failed |
|
||||
| UNAUTHORIZED | 401 | Missing or invalid auth token |
|
||||
| FORBIDDEN | 403 | Valid token but insufficient permissions |
|
||||
| NOT_FOUND | 404 | Resource does not exist |
|
||||
| CONFLICT | 409 | State conflict (e.g. duplicate) |
|
||||
| INTERNAL_ERROR | 500 | Unhandled server error |
|
||||
|
||||
## Panic Recovery
|
||||
|
||||
The server uses a recovery middleware that catches panics, logs the stack trace, and returns a 500 with \`INTERNAL_ERROR\`. Never expose stack traces to clients.`,
|
||||
createdBy: "Claude-1",
|
||||
updatedAt: "2026-03-20T22:00:00Z",
|
||||
referencedBy: ["MUL-6"],
|
||||
},
|
||||
{
|
||||
id: "kb_4",
|
||||
title: "Agent Onboarding Guide",
|
||||
content: `## How Agents Work in Multica
|
||||
|
||||
When an issue is assigned to an agent, the following happens:
|
||||
|
||||
1. Server pushes the task to the agent's inbox via WebSocket
|
||||
2. Daemon receives the task and reads the issue context
|
||||
3. Agent retrieves relevant Knowledge Base documents
|
||||
4. Agent executes via the underlying runtime (Claude Code, Codex, etc.)
|
||||
5. Progress is reported back through WebSocket status updates
|
||||
6. On completion, agent creates a PR and moves the issue to "In Review"
|
||||
|
||||
## Agent Capabilities
|
||||
|
||||
- Receive and execute issues
|
||||
- Create new issues (when blocked or discovering sub-tasks)
|
||||
- Comment on issues (progress updates, questions)
|
||||
- Change issue status
|
||||
- Read Knowledge Base documents
|
||||
- Create branches, commits, and pull requests
|
||||
|
||||
## When Agents Get Blocked
|
||||
|
||||
If an agent cannot proceed, it should:
|
||||
1. Change the issue status to "Blocked"
|
||||
2. Leave a comment explaining what it needs
|
||||
3. Create an inbox notification for the assignee with severity "action_required"
|
||||
4. Wait for human input before continuing`,
|
||||
createdBy: "Bohan",
|
||||
updatedAt: "2026-03-19T16:00:00Z",
|
||||
referencedBy: ["MUL-12", "MUL-15"],
|
||||
},
|
||||
{
|
||||
id: "kb_5",
|
||||
title: "Database Schema: Issues",
|
||||
content: `## Issues Table
|
||||
|
||||
\`\`\`sql
|
||||
CREATE TABLE issues (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_nanoid(),
|
||||
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'backlog',
|
||||
priority TEXT NOT NULL DEFAULT 'none',
|
||||
assignee_type TEXT, -- 'member' | 'agent'
|
||||
assignee_id TEXT,
|
||||
creator_type TEXT NOT NULL,
|
||||
creator_id TEXT NOT NULL,
|
||||
parent_issue_id TEXT REFERENCES issues(id),
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
due_date TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
\`\`\`
|
||||
|
||||
## Indexes
|
||||
|
||||
\`\`\`sql
|
||||
CREATE INDEX idx_issues_workspace_status ON issues(workspace_id, status);
|
||||
CREATE INDEX idx_issues_assignee ON issues(assignee_type, assignee_id);
|
||||
CREATE INDEX idx_issues_workspace_created ON issues(workspace_id, created_at);
|
||||
\`\`\`
|
||||
|
||||
## Status Values
|
||||
|
||||
\`backlog\`, \`todo\`, \`in_progress\`, \`in_review\`, \`done\`, \`blocked\`, \`cancelled\`
|
||||
|
||||
## Priority Values
|
||||
|
||||
\`urgent\`, \`high\`, \`medium\`, \`low\`, \`none\``,
|
||||
createdBy: "Yuzhen",
|
||||
updatedAt: "2026-03-18T11:00:00Z",
|
||||
referencedBy: ["MUL-9"],
|
||||
},
|
||||
{
|
||||
id: "kb_6",
|
||||
title: "PR & Code Review Guidelines",
|
||||
content: `## Branch Naming
|
||||
|
||||
\`\`\`
|
||||
feat/short-description
|
||||
fix/short-description
|
||||
refactor/short-description
|
||||
\`\`\`
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Follow conventional commits:
|
||||
|
||||
\`\`\`
|
||||
feat(scope): add new feature
|
||||
fix(scope): fix a bug
|
||||
refactor(scope): code restructure
|
||||
docs: documentation only
|
||||
test(scope): add or update tests
|
||||
chore(scope): maintenance
|
||||
\`\`\`
|
||||
|
||||
## PR Requirements
|
||||
|
||||
- Keep PRs small and focused (< 400 lines when possible)
|
||||
- Include a description of what and why
|
||||
- All CI checks must pass
|
||||
- At least one human review required for agent-authored PRs
|
||||
- Agent PRs are auto-labeled with \`agent-authored\`
|
||||
|
||||
## Review Checklist
|
||||
|
||||
- [ ] Does the code do what the issue describes?
|
||||
- [ ] Are there tests for new behavior?
|
||||
- [ ] No security vulnerabilities introduced
|
||||
- [ ] No hardcoded secrets or credentials
|
||||
- [ ] Error handling is appropriate`,
|
||||
createdBy: "Bohan",
|
||||
updatedAt: "2026-03-17T09:00:00Z",
|
||||
referencedBy: ["MUL-3", "MUL-8"],
|
||||
},
|
||||
{
|
||||
id: "kb_7",
|
||||
title: "WebSocket Protocol",
|
||||
content: `## Connection
|
||||
|
||||
\`\`\`
|
||||
ws://localhost:8080/ws?token=<jwt>
|
||||
\`\`\`
|
||||
|
||||
## Message Format
|
||||
|
||||
All messages use JSON:
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "agent.status_update",
|
||||
"payload": { ... },
|
||||
"timestamp": "2026-03-20T10:00:00Z"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Event Types
|
||||
|
||||
### Server → Client
|
||||
- \`agent.status_update\` — Agent status changed (idle/working/blocked/error/offline)
|
||||
- \`issue.updated\` — Issue fields changed
|
||||
- \`inbox.new_item\` — New inbox notification
|
||||
- \`task.progress\` — Agent reports execution progress
|
||||
|
||||
### Client → Server
|
||||
- \`agent.heartbeat\` — Daemon sends periodic heartbeat
|
||||
- \`task.started\` — Agent began executing a task
|
||||
- \`task.completed\` — Agent finished a task
|
||||
- \`task.failed\` — Agent failed a task
|
||||
|
||||
## Reconnection
|
||||
|
||||
Daemon uses exponential backoff with jitter:
|
||||
- Initial delay: 1s
|
||||
- Max delay: 30s
|
||||
- Jitter: ±25%`,
|
||||
createdBy: "Bohan",
|
||||
updatedAt: "2026-03-21T04:00:00Z",
|
||||
referencedBy: ["MUL-8", "MUL-14"],
|
||||
},
|
||||
];
|
||||
|
|
@ -7,8 +7,6 @@ import {
|
|||
Search,
|
||||
Link as LinkIcon,
|
||||
} from "lucide-react";
|
||||
import { MOCK_DOCUMENTS, type KBDocument } from "./_data/mock";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -21,6 +19,15 @@ function timeAgo(dateStr: string): string {
|
|||
return `${days}d ago`;
|
||||
}
|
||||
|
||||
interface KBDocument {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
createdBy: string;
|
||||
updatedAt: string;
|
||||
referencedBy: string[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Simple Markdown-ish renderer (handles headers, code blocks, tables, lists)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -268,18 +275,17 @@ function DocDetail({ doc }: { doc: KBDocument }) {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
export default function KnowledgeBasePage() {
|
||||
const [selectedId, setSelectedId] = useState<string>(
|
||||
MOCK_DOCUMENTS[0]?.id ?? ""
|
||||
);
|
||||
const [documents] = useState<KBDocument[]>([]);
|
||||
const [selectedId, setSelectedId] = useState<string>("");
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const filtered = search
|
||||
? MOCK_DOCUMENTS.filter((d) =>
|
||||
? documents.filter((d) =>
|
||||
d.title.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
: MOCK_DOCUMENTS;
|
||||
: documents;
|
||||
|
||||
const selected = MOCK_DOCUMENTS.find((d) => d.id === selectedId) ?? null;
|
||||
const selected = documents.find((d) => d.id === selectedId) ?? null;
|
||||
|
||||
return (
|
||||
<div className="flex h-full">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue