olly-molly 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/bin/cli.js +137 -52
- package/package.json +4 -15
- package/app/api/agent/execute/route.ts +0 -157
- package/app/api/agent/status/route.ts +0 -38
- package/app/api/check-api-key/route.ts +0 -12
- package/app/api/conversations/[id]/route.ts +0 -35
- package/app/api/conversations/route.ts +0 -24
- package/app/api/members/[id]/route.ts +0 -37
- package/app/api/members/route.ts +0 -12
- package/app/api/pm/breakdown/route.ts +0 -142
- package/app/api/pm/tickets/route.ts +0 -147
- package/app/api/projects/[id]/route.ts +0 -56
- package/app/api/projects/active/route.ts +0 -15
- package/app/api/projects/route.ts +0 -53
- package/app/api/tickets/[id]/logs/route.ts +0 -16
- package/app/api/tickets/[id]/route.ts +0 -60
- package/app/api/tickets/[id]/work-logs/route.ts +0 -16
- package/app/api/tickets/route.ts +0 -37
- package/app/design-system/page.tsx +0 -242
- package/app/favicon.ico +0 -0
- package/app/globals.css +0 -318
- package/app/layout.tsx +0 -37
- package/app/page.tsx +0 -331
- package/components/ThemeProvider.tsx +0 -56
- package/components/ThemeToggle.tsx +0 -31
- package/components/activity/ActivityLog.tsx +0 -96
- package/components/activity/index.ts +0 -1
- package/components/kanban/ConversationList.tsx +0 -75
- package/components/kanban/ConversationView.tsx +0 -132
- package/components/kanban/KanbanBoard.tsx +0 -179
- package/components/kanban/KanbanColumn.tsx +0 -80
- package/components/kanban/SortableTicket.tsx +0 -58
- package/components/kanban/TicketCard.tsx +0 -98
- package/components/kanban/TicketModal.tsx +0 -510
- package/components/kanban/TicketSidebar.tsx +0 -448
- package/components/kanban/index.ts +0 -8
- package/components/pm/PMRequestModal.tsx +0 -196
- package/components/pm/index.ts +0 -1
- package/components/project/ProjectSelector.tsx +0 -211
- package/components/project/index.ts +0 -1
- package/components/team/MemberCard.tsx +0 -147
- package/components/team/TeamPanel.tsx +0 -57
- package/components/team/index.ts +0 -2
- package/components/ui/ApiKeyModal.tsx +0 -101
- package/components/ui/Avatar.tsx +0 -95
- package/components/ui/Badge.tsx +0 -59
- package/components/ui/Button.tsx +0 -60
- package/components/ui/Card.tsx +0 -64
- package/components/ui/Input.tsx +0 -41
- package/components/ui/Modal.tsx +0 -76
- package/components/ui/ResizablePane.tsx +0 -97
- package/components/ui/Select.tsx +0 -45
- package/components/ui/Textarea.tsx +0 -41
- package/components/ui/index.ts +0 -8
- package/db/dev.sqlite +0 -0
- package/db/dev.sqlite-shm +0 -0
- package/db/dev.sqlite-wal +0 -0
- package/db/schema-conversations.sql +0 -26
- package/db/schema-projects.sql +0 -29
- package/db/schema.sql +0 -94
- package/lib/agent-jobs.ts +0 -232
- package/lib/db.ts +0 -564
- package/next.config.ts +0 -10
- package/postcss.config.mjs +0 -7
- package/public/app-icon.png +0 -0
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/next.svg +0 -1
- package/public/profiles/designer.png +0 -0
- package/public/profiles/dev-backend.png +0 -0
- package/public/profiles/dev-frontend.png +0 -0
- package/public/profiles/pm.png +0 -0
- package/public/profiles/qa.png +0 -0
- package/public/vercel.svg +0 -1
- package/public/window.svg +0 -1
- package/tsconfig.json +0 -34
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ olly-molly
|
|
|
89
89
|
### Development
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
git clone https://github.com/
|
|
92
|
+
git clone https://github.com/ruucm/olly-molly.git
|
|
93
93
|
cd olly-molly
|
|
94
94
|
npm install
|
|
95
95
|
npm run dev
|
|
@@ -128,7 +128,7 @@ We love contributions! Here's how you can help:
|
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
130
|
# Clone the repo
|
|
131
|
-
git clone https://github.com/
|
|
131
|
+
git clone https://github.com/ruucm/olly-molly.git
|
|
132
132
|
cd olly-molly
|
|
133
133
|
|
|
134
134
|
# Install dependencies
|
|
@@ -173,7 +173,7 @@ olly-molly/
|
|
|
173
173
|
|
|
174
174
|
## License
|
|
175
175
|
|
|
176
|
-
MIT ©
|
|
176
|
+
MIT © ruucm
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
package/bin/cli.js
CHANGED
|
@@ -3,64 +3,149 @@
|
|
|
3
3
|
const { spawn, execSync } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const https = require('https');
|
|
6
8
|
|
|
7
|
-
const
|
|
9
|
+
const APP_NAME = 'olly-molly';
|
|
10
|
+
const REPO = 'ruucm/olly-molly';
|
|
11
|
+
const APP_DIR = path.join(os.homedir(), '.olly-molly');
|
|
12
|
+
const TARBALL_URL = `https://github.com/${REPO}/archive/refs/heads/main.tar.gz`;
|
|
8
13
|
|
|
9
14
|
console.log('\n🐙 Olly Molly - Your AI Development Team\n');
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
function downloadAndExtract(url, destDir) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const tempFile = path.join(os.tmpdir(), 'olly-molly.tar.gz');
|
|
19
|
+
const file = fs.createWriteStream(tempFile);
|
|
20
|
+
|
|
21
|
+
console.log('📥 Downloading...');
|
|
22
|
+
|
|
23
|
+
const download = (downloadUrl) => {
|
|
24
|
+
https.get(downloadUrl, (response) => {
|
|
25
|
+
// Handle redirects
|
|
26
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
27
|
+
download(response.headers.location);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (response.statusCode !== 200) {
|
|
32
|
+
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
response.pipe(file);
|
|
37
|
+
file.on('finish', () => {
|
|
38
|
+
file.close();
|
|
39
|
+
|
|
40
|
+
console.log('📦 Extracting...');
|
|
41
|
+
|
|
42
|
+
// Create dest directory
|
|
43
|
+
if (!fs.existsSync(destDir)) {
|
|
44
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Extract tarball
|
|
48
|
+
try {
|
|
49
|
+
execSync(`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`, {
|
|
50
|
+
stdio: 'pipe'
|
|
51
|
+
});
|
|
52
|
+
fs.unlinkSync(tempFile);
|
|
53
|
+
resolve();
|
|
54
|
+
} catch (err) {
|
|
55
|
+
reject(err);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}).on('error', reject);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
download(url);
|
|
62
|
+
});
|
|
24
63
|
}
|
|
25
64
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
65
|
+
async function main() {
|
|
66
|
+
const args = process.argv.slice(2);
|
|
67
|
+
|
|
68
|
+
// Update flag
|
|
69
|
+
if (args.includes('--update') || args.includes('-u')) {
|
|
70
|
+
console.log('🔄 Updating Olly Molly...\n');
|
|
71
|
+
if (fs.existsSync(APP_DIR)) {
|
|
72
|
+
fs.rmSync(APP_DIR, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Download if not exists
|
|
77
|
+
if (!fs.existsSync(APP_DIR)) {
|
|
78
|
+
console.log('📦 First run - downloading Olly Molly...\n');
|
|
79
|
+
try {
|
|
80
|
+
await downloadAndExtract(TARBALL_URL, APP_DIR);
|
|
81
|
+
console.log('✅ Downloaded!\n');
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('❌ Download failed:', error.message);
|
|
84
|
+
console.error('\n Make sure the repository is public at:');
|
|
85
|
+
console.error(` https://github.com/${REPO}\n`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Install dependencies if needed
|
|
91
|
+
const nodeModulesPath = path.join(APP_DIR, 'node_modules');
|
|
92
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
93
|
+
console.log('📦 Installing dependencies (first time only)...\n');
|
|
94
|
+
try {
|
|
95
|
+
execSync('npm install --production', {
|
|
96
|
+
cwd: APP_DIR,
|
|
97
|
+
stdio: 'inherit'
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('❌ Failed to install dependencies');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Build if needed
|
|
106
|
+
const nextPath = path.join(APP_DIR, '.next');
|
|
107
|
+
if (!fs.existsSync(nextPath)) {
|
|
108
|
+
console.log('🔨 Building app (first time only)...\n');
|
|
109
|
+
try {
|
|
110
|
+
execSync('npm run build', {
|
|
111
|
+
cwd: APP_DIR,
|
|
112
|
+
stdio: 'inherit'
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('❌ Failed to build');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
38
118
|
}
|
|
119
|
+
|
|
120
|
+
console.log('\n🚀 Starting on http://localhost:1234\n');
|
|
121
|
+
console.log(' Press Ctrl+C to stop');
|
|
122
|
+
console.log(' Run "npx olly-molly -u" to update\n');
|
|
123
|
+
|
|
124
|
+
// Start the server
|
|
125
|
+
const server = spawn('npm', ['run', 'start', '--', '--port', '1234'], {
|
|
126
|
+
cwd: APP_DIR,
|
|
127
|
+
stdio: 'inherit',
|
|
128
|
+
shell: true
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
server.on('error', (error) => {
|
|
132
|
+
console.error('❌ Failed to start:', error.message);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
server.on('close', (code) => {
|
|
137
|
+
process.exit(code || 0);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Graceful shutdown
|
|
141
|
+
process.on('SIGINT', () => {
|
|
142
|
+
console.log('\n👋 Bye!');
|
|
143
|
+
server.kill('SIGINT');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
process.on('SIGTERM', () => {
|
|
147
|
+
server.kill('SIGTERM');
|
|
148
|
+
});
|
|
39
149
|
}
|
|
40
150
|
|
|
41
|
-
|
|
42
|
-
console.log('🚀 Starting Olly Molly on http://localhost:1234\n');
|
|
43
|
-
|
|
44
|
-
const server = spawn('npm', ['run', 'start', '--', '--port', '1234'], {
|
|
45
|
-
cwd: packageDir,
|
|
46
|
-
stdio: 'inherit',
|
|
47
|
-
shell: true
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
server.on('error', (error) => {
|
|
51
|
-
console.error('❌ Failed to start server:', error.message);
|
|
52
|
-
process.exit(1);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
server.on('close', (code) => {
|
|
56
|
-
process.exit(code || 0);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Handle graceful shutdown
|
|
60
|
-
process.on('SIGINT', () => {
|
|
61
|
-
server.kill('SIGINT');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
process.on('SIGTERM', () => {
|
|
65
|
-
server.kill('SIGTERM');
|
|
66
|
-
});
|
|
151
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "olly-molly",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Your AI Development Team, Running Locally - Manage AI agents (PM, Frontend, Backend, QA) from a beautiful kanban board",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -16,34 +16,23 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "https://github.com/ruucm/olly-molly.git"
|
|
19
|
+
"url": "git+https://github.com/ruucm/olly-molly.git"
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/ruucm/olly-molly#readme",
|
|
22
22
|
"bugs": {
|
|
23
23
|
"url": "https://github.com/ruucm/olly-molly/issues"
|
|
24
24
|
},
|
|
25
25
|
"bin": {
|
|
26
|
-
"olly-molly": "
|
|
26
|
+
"olly-molly": "bin/cli.js"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
|
-
"bin"
|
|
30
|
-
"app",
|
|
31
|
-
"components",
|
|
32
|
-
"db",
|
|
33
|
-
"lib",
|
|
34
|
-
"public",
|
|
35
|
-
"types",
|
|
36
|
-
"next.config.ts",
|
|
37
|
-
"postcss.config.mjs",
|
|
38
|
-
"tsconfig.json",
|
|
39
|
-
"package.json"
|
|
29
|
+
"bin"
|
|
40
30
|
],
|
|
41
31
|
"scripts": {
|
|
42
32
|
"dev": "next dev --port 1234",
|
|
43
33
|
"build": "next build",
|
|
44
34
|
"start": "next start",
|
|
45
35
|
"lint": "eslint",
|
|
46
|
-
"prepublishOnly": "npm run build",
|
|
47
36
|
"tauri": "tauri",
|
|
48
37
|
"tauri:dev": "tauri dev",
|
|
49
38
|
"tauri:build": "tauri build",
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { ticketService, memberService, projectService, activityService, conversationService } from '@/lib/db';
|
|
3
|
-
import { startBackgroundJob, AgentProvider } from '@/lib/agent-jobs';
|
|
4
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
-
|
|
6
|
-
interface AgentExecuteRequest {
|
|
7
|
-
ticket_id: string;
|
|
8
|
-
feedback?: string;
|
|
9
|
-
provider?: AgentProvider;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function buildAgentPrompt(ticket: {
|
|
13
|
-
title: string;
|
|
14
|
-
description?: string | null;
|
|
15
|
-
}, agent: {
|
|
16
|
-
name: string;
|
|
17
|
-
role: string;
|
|
18
|
-
system_prompt: string;
|
|
19
|
-
}, project: {
|
|
20
|
-
name: string;
|
|
21
|
-
path: string;
|
|
22
|
-
}, feedback?: string): string {
|
|
23
|
-
// Check if role is QA to add specific port instructions
|
|
24
|
-
const isQA = agent.role === 'QA';
|
|
25
|
-
const qaInstruction = isQA
|
|
26
|
-
? `\nIMPORTANT:
|
|
27
|
-
1. PORT CONFIGURATION: When running tests or starting servers for the TARGET PROJECT, you MUST use port 3001 (or any port other than 1234) to avoid conflict with this dashboard app. Use "PORT=3001 npm run dev" or equivalent.
|
|
28
|
-
2. TOOL USAGE: You MUST use the **Playwright MCP** (https://github.com/microsoft/playwright-mcp) tools for automated testing. verify the available tools and use them for browser automation and testing. Do NOT rely solely on manual terminal commands.`
|
|
29
|
-
: '';
|
|
30
|
-
|
|
31
|
-
const feedbackSection = feedback
|
|
32
|
-
? `\n\nIMPORTANT FEEDBACK FROM USER:\n${feedback}\n\nPlease address this feedback specifically in your implementation.`
|
|
33
|
-
: '';
|
|
34
|
-
|
|
35
|
-
return `You are acting as ${agent.name} (${agent.role}) for the project "${project.name}".
|
|
36
|
-
|
|
37
|
-
${agent.system_prompt}
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
TASK TO COMPLETE:
|
|
42
|
-
Title: ${ticket.title}
|
|
43
|
-
${ticket.description ? `Description: ${ticket.description}` : ''}
|
|
44
|
-
${feedbackSection}
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
INSTRUCTIONS:
|
|
49
|
-
1. Analyze the task requirements carefully
|
|
50
|
-
2. Make the necessary code changes to complete this task
|
|
51
|
-
3. Focus only on what's needed for this specific task
|
|
52
|
-
4. Write clean, well-documented code
|
|
53
|
-
5. After completing, provide a brief summary of changes made
|
|
54
|
-
6. If you make changes, commit them with a meaningful message
|
|
55
|
-
7. CRITICAL: You are working on the external project "${project.name}". When starting its server, ALWAYS use port 3001 (e.g. "PORT=3001 npm run dev"). NEVER use port 1234.${qaInstruction}
|
|
56
|
-
|
|
57
|
-
Please complete this task now.`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export async function POST(request: NextRequest) {
|
|
61
|
-
try {
|
|
62
|
-
const body: AgentExecuteRequest = await request.json();
|
|
63
|
-
|
|
64
|
-
if (!body.ticket_id) {
|
|
65
|
-
return NextResponse.json({ error: 'ticket_id is required' }, { status: 400 });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Get ticket
|
|
69
|
-
const ticket = ticketService.getById(body.ticket_id);
|
|
70
|
-
if (!ticket) {
|
|
71
|
-
return NextResponse.json({ error: 'Ticket not found' }, { status: 404 });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Get assignee (agent)
|
|
75
|
-
if (!ticket.assignee_id) {
|
|
76
|
-
return NextResponse.json({ error: 'Ticket has no assignee' }, { status: 400 });
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const agent = memberService.getById(ticket.assignee_id);
|
|
80
|
-
if (!agent) {
|
|
81
|
-
return NextResponse.json({ error: 'Agent not found' }, { status: 404 });
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Get active project
|
|
85
|
-
const project = projectService.getActive();
|
|
86
|
-
if (!project) {
|
|
87
|
-
return NextResponse.json({ error: 'No active project selected. Please select a project first.' }, { status: 400 });
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Build prompt
|
|
91
|
-
const prompt = buildAgentPrompt(ticket, agent, project, body.feedback);
|
|
92
|
-
|
|
93
|
-
// Use provided provider or default to 'claude'
|
|
94
|
-
const provider: AgentProvider = body.provider || 'claude';
|
|
95
|
-
|
|
96
|
-
// Generate job ID
|
|
97
|
-
const jobId = uuidv4();
|
|
98
|
-
|
|
99
|
-
// Update ticket status to IN_PROGRESS
|
|
100
|
-
ticketService.update(body.ticket_id, { status: 'IN_PROGRESS' }, agent.id);
|
|
101
|
-
|
|
102
|
-
// Create conversation for this execution
|
|
103
|
-
const conversation = conversationService.create({
|
|
104
|
-
ticket_id: body.ticket_id,
|
|
105
|
-
agent_id: agent.id,
|
|
106
|
-
provider,
|
|
107
|
-
prompt,
|
|
108
|
-
feedback: body.feedback,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Log activity
|
|
112
|
-
activityService.log({
|
|
113
|
-
ticket_id: body.ticket_id,
|
|
114
|
-
member_id: agent.id,
|
|
115
|
-
action: 'AGENT_WORK_STARTED',
|
|
116
|
-
details: `${agent.name} started working on this task using ${provider === 'opencode' ? 'OpenCode' : 'Claude Code'}`,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Start background job (non-blocking)
|
|
120
|
-
startBackgroundJob({
|
|
121
|
-
jobId,
|
|
122
|
-
conversationId: conversation.id,
|
|
123
|
-
ticketId: body.ticket_id,
|
|
124
|
-
agentId: agent.id,
|
|
125
|
-
agentName: agent.name,
|
|
126
|
-
projectPath: project.path,
|
|
127
|
-
prompt,
|
|
128
|
-
provider,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Return immediately with job info
|
|
132
|
-
return NextResponse.json({
|
|
133
|
-
success: true,
|
|
134
|
-
job_id: jobId,
|
|
135
|
-
conversation_id: conversation.id,
|
|
136
|
-
message: `${agent.name} started working on the task. The job is running in the background.`,
|
|
137
|
-
agent: {
|
|
138
|
-
id: agent.id,
|
|
139
|
-
name: agent.name,
|
|
140
|
-
role: agent.role,
|
|
141
|
-
avatar: agent.avatar,
|
|
142
|
-
},
|
|
143
|
-
project: {
|
|
144
|
-
id: project.id,
|
|
145
|
-
name: project.name,
|
|
146
|
-
path: project.path,
|
|
147
|
-
},
|
|
148
|
-
ticket_status: 'IN_PROGRESS',
|
|
149
|
-
});
|
|
150
|
-
} catch (error) {
|
|
151
|
-
console.error('Error executing agent:', error);
|
|
152
|
-
return NextResponse.json({
|
|
153
|
-
error: 'Failed to execute agent',
|
|
154
|
-
details: String(error)
|
|
155
|
-
}, { status: 500 });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { getRunningJobs, getJobByTicketId, getJobOutput, cancelJob } from '@/lib/agent-jobs';
|
|
3
|
-
|
|
4
|
-
// Get all running jobs
|
|
5
|
-
export async function GET(request: NextRequest) {
|
|
6
|
-
const url = new URL(request.url);
|
|
7
|
-
const ticketId = url.searchParams.get('ticket_id');
|
|
8
|
-
const jobId = url.searchParams.get('job_id');
|
|
9
|
-
|
|
10
|
-
if (jobId) {
|
|
11
|
-
// Get specific job output
|
|
12
|
-
const output = getJobOutput(jobId);
|
|
13
|
-
return NextResponse.json({ output });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (ticketId) {
|
|
17
|
-
// Get job for specific ticket
|
|
18
|
-
const job = getJobByTicketId(ticketId);
|
|
19
|
-
return NextResponse.json({ job });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Get all running jobs
|
|
23
|
-
const jobs = getRunningJobs();
|
|
24
|
-
return NextResponse.json({ jobs });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Cancel a job
|
|
28
|
-
export async function DELETE(request: NextRequest) {
|
|
29
|
-
const url = new URL(request.url);
|
|
30
|
-
const jobId = url.searchParams.get('job_id');
|
|
31
|
-
|
|
32
|
-
if (!jobId) {
|
|
33
|
-
return NextResponse.json({ error: 'job_id is required' }, { status: 400 });
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const cancelled = cancelJob(jobId);
|
|
37
|
-
return NextResponse.json({ success: cancelled });
|
|
38
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
|
|
3
|
-
export async function GET(request: NextRequest) {
|
|
4
|
-
try {
|
|
5
|
-
// Check if OPENAI_API_KEY exists in environment
|
|
6
|
-
const hasKey = !!process.env.OPENAI_API_KEY;
|
|
7
|
-
|
|
8
|
-
return NextResponse.json({ hasKey });
|
|
9
|
-
} catch (error) {
|
|
10
|
-
return NextResponse.json({ hasKey: false }, { status: 500 });
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { conversationService, conversationMessageService } from '@/lib/db';
|
|
3
|
-
|
|
4
|
-
interface RouteParams {
|
|
5
|
-
params: Promise<{
|
|
6
|
-
id: string;
|
|
7
|
-
}>;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// GET /api/conversations/[id]
|
|
11
|
-
export async function GET(request: NextRequest, { params }: RouteParams) {
|
|
12
|
-
try {
|
|
13
|
-
// Await params for Next.js 15+
|
|
14
|
-
const { id } = await params;
|
|
15
|
-
|
|
16
|
-
const conversation = conversationService.getById(id);
|
|
17
|
-
|
|
18
|
-
if (!conversation) {
|
|
19
|
-
return NextResponse.json({ error: 'Conversation not found' }, { status: 404 });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const messages = conversationMessageService.getByConversationId(id);
|
|
23
|
-
|
|
24
|
-
return NextResponse.json({
|
|
25
|
-
conversation,
|
|
26
|
-
messages
|
|
27
|
-
});
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.error('Error fetching conversation:', error);
|
|
30
|
-
return NextResponse.json({
|
|
31
|
-
error: 'Failed to fetch conversation',
|
|
32
|
-
details: String(error)
|
|
33
|
-
}, { status: 500 });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { conversationService, conversationMessageService } from '@/lib/db';
|
|
3
|
-
|
|
4
|
-
// GET /api/conversations?ticket_id=xxx
|
|
5
|
-
export async function GET(request: NextRequest) {
|
|
6
|
-
try {
|
|
7
|
-
const { searchParams } = new URL(request.url);
|
|
8
|
-
const ticketId = searchParams.get('ticket_id');
|
|
9
|
-
|
|
10
|
-
if (!ticketId) {
|
|
11
|
-
return NextResponse.json({ error: 'ticket_id is required' }, { status: 400 });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const conversations = conversationService.getByTicketId(ticketId);
|
|
15
|
-
|
|
16
|
-
return NextResponse.json({ conversations });
|
|
17
|
-
} catch (error) {
|
|
18
|
-
console.error('Error fetching conversations:', error);
|
|
19
|
-
return NextResponse.json({
|
|
20
|
-
error: 'Failed to fetch conversations',
|
|
21
|
-
details: String(error)
|
|
22
|
-
}, { status: 500 });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { memberService } from '@/lib/db';
|
|
3
|
-
|
|
4
|
-
export async function GET(
|
|
5
|
-
request: NextRequest,
|
|
6
|
-
{ params }: { params: Promise<{ id: string }> }
|
|
7
|
-
) {
|
|
8
|
-
try {
|
|
9
|
-
const { id } = await params;
|
|
10
|
-
const member = memberService.getById(id);
|
|
11
|
-
if (!member) {
|
|
12
|
-
return NextResponse.json({ error: 'Member not found' }, { status: 404 });
|
|
13
|
-
}
|
|
14
|
-
return NextResponse.json(member);
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error('Error fetching member:', error);
|
|
17
|
-
return NextResponse.json({ error: 'Failed to fetch member' }, { status: 500 });
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function PATCH(
|
|
22
|
-
request: NextRequest,
|
|
23
|
-
{ params }: { params: Promise<{ id: string }> }
|
|
24
|
-
) {
|
|
25
|
-
try {
|
|
26
|
-
const { id } = await params;
|
|
27
|
-
const body = await request.json();
|
|
28
|
-
const member = memberService.update(id, body);
|
|
29
|
-
if (!member) {
|
|
30
|
-
return NextResponse.json({ error: 'Member not found' }, { status: 404 });
|
|
31
|
-
}
|
|
32
|
-
return NextResponse.json(member);
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.error('Error updating member:', error);
|
|
35
|
-
return NextResponse.json({ error: 'Failed to update member' }, { status: 500 });
|
|
36
|
-
}
|
|
37
|
-
}
|
package/app/api/members/route.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server';
|
|
2
|
-
import { memberService } from '@/lib/db';
|
|
3
|
-
|
|
4
|
-
export async function GET() {
|
|
5
|
-
try {
|
|
6
|
-
const members = memberService.getAll();
|
|
7
|
-
return NextResponse.json(members);
|
|
8
|
-
} catch (error) {
|
|
9
|
-
console.error('Error fetching members:', error);
|
|
10
|
-
return NextResponse.json({ error: 'Failed to fetch members' }, { status: 500 });
|
|
11
|
-
}
|
|
12
|
-
}
|