Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions rkix-studio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# RKix Studio

AI-powered coding assistant platform with GitHub integration.

## Features
- 💬 AI Chat - Interact with GPT-4o for coding help
- 📋 Task Management - Create and track coding tasks
- 🔗 GitHub Integration - Browse repos, edit files, create branches & PRs
- 🔐 Authentication - Magic Link & Google Sign-in

## Tech Stack
- React + TypeScript
- Tailwind CSS + shadcn/ui
- OpenAI GPT-4o
- GitHub API
- Zite Database

## Structure
- `src/components/` - React components (Layout, ChatView, ReposView, etc.)
- `src/api/` - Backend endpoints (chat, tasks, GitHub operations)
27 changes: 27 additions & 0 deletions rkix-studio/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { Toaster } from '@/components/ui/sonner';
import Layout from '@/components/Layout';
import ChatView from '@/components/ChatView';
import TasksView from '@/components/TasksView';
import TaskDetailView from '@/components/TaskDetailView';
import ReposView from '@/components/ReposView';
import RepoDetailView from '@/components/RepoDetailView';

export default function App() {
return (
<BrowserRouter>
<Toaster />
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<Navigate to="/chat" replace />} />
<Route path="/chat" element={<ChatView />} />
<Route path="/chat/:chatId" element={<ChatView />} />
<Route path="/repos" element={<ReposView />} />
<Route path="/repos/:owner/:repo" element={<RepoDetailView />} />
<Route path="/tasks" element={<TasksView />} />
<Route path="/tasks/:taskId" element={<TaskDetailView />} />
</Route>
</Routes>
</BrowserRouter>
);
}
12 changes: 12 additions & 0 deletions rkix-studio/src/api/createChat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { z } from 'zod';
import { createEndpoint, Chats } from 'zite-integrations-backend-sdk';

export default createEndpoint({
description: 'Create a new chat',
inputSchema: z.object({ title: z.string().optional() }),
outputSchema: z.object({ id: z.string(), title: z.string(), createdAt: z.string().optional() }),
execute: async ({ input }) => {
const chat = await Chats.create({ record: { title: input.title || 'New Chat', createdAt: new Date().toISOString() } });
return { id: chat.id, title: chat.title || 'New Chat', createdAt: chat.createdAt };
},
});
14 changes: 14 additions & 0 deletions rkix-studio/src/api/deleteChat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from 'zod';
import { createEndpoint, Chats, Messages } from 'zite-integrations-backend-sdk';

export default createEndpoint({
description: 'Delete a chat and its messages',
inputSchema: z.object({ chatId: z.string() }),
outputSchema: z.object({ success: z.boolean() }),
execute: async ({ input }) => {
const { records: msgs } = await Messages.findAll({ filters: { chat: input.chatId } });
for (const m of msgs) { await Messages.delete({ id: m.id }); }
await Chats.delete({ id: input.chatId });
return { success: true };
},
});
17 changes: 17 additions & 0 deletions rkix-studio/src/api/getChats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { z } from 'zod';
import { createEndpoint, Chats } from 'zite-integrations-backend-sdk';

export default createEndpoint({
description: 'Get all chats sorted by creation date',
inputSchema: z.object({}),
outputSchema: z.object({ chats: z.array(z.object({ id: z.string(), title: z.string(), createdAt: z.string().optional() })) }),
execute: async () => {
const { records } = await Chats.findAll({ limit: 50 });
const sorted = records.sort((a, b) => {
const da = a.createdAt ? new Date(a.createdAt).getTime() : 0;
const db = b.createdAt ? new Date(b.createdAt).getTime() : 0;
return db - da;
});
return { chats: sorted.map(c => ({ id: c.id, title: c.title || 'New Chat', createdAt: c.createdAt })) };
},
});
17 changes: 17 additions & 0 deletions rkix-studio/src/api/getMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { z } from 'zod';
import { createEndpoint, Messages } from 'zite-integrations-backend-sdk';

export default createEndpoint({
description: 'Get messages for a chat',
inputSchema: z.object({ chatId: z.string() }),
outputSchema: z.object({ messages: z.array(z.object({ id: z.string(), content: z.string(), role: z.string(), createdAt: z.string().optional() })) }),
execute: async ({ input }) => {
const { records } = await Messages.findAll({ filters: { chat: input.chatId }, limit: 200 });
const sorted = records.sort((a, b) => {
const da = a.createdAt ? new Date(a.createdAt).getTime() : 0;
const db = b.createdAt ? new Date(b.createdAt).getTime() : 0;
return da - db;
});
return { messages: sorted.map(m => ({ id: m.id, content: m.content || '', role: (m.role || 'User').toLowerCase(), createdAt: m.createdAt })) };
},
});
19 changes: 19 additions & 0 deletions rkix-studio/src/api/getTasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { z } from 'zod';
import { createEndpoint, Tasks } from 'zite-integrations-backend-sdk';

export default createEndpoint({
description: 'Get all tasks',
inputSchema: z.object({ status: z.string().optional() }),
outputSchema: z.object({ tasks: z.array(z.object({ id: z.string(), title: z.string(), status: z.string(), context: z.string().optional(), log: z.string().optional(), filesChanged: z.string().optional(), createdAt: z.string().optional() })) }),
execute: async ({ input }) => {
const filters: Record<string, unknown> = {};
if (input.status) filters.status = input.status;
const { records } = await Tasks.findAll({ filters, limit: 100 });
const sorted = records.sort((a, b) => {
const da = a.createdAt ? new Date(a.createdAt).getTime() : 0;
const db = b.createdAt ? new Date(b.createdAt).getTime() : 0;
return db - da;
});
return { tasks: sorted.map(t => ({ id: t.id, title: t.title || 'Untitled Task', status: (t.status || 'Queued').toLowerCase(), context: t.context, log: t.log, filesChanged: t.filesChanged, createdAt: t.createdAt })) };
},
});