@lovelybunch/api 1.0.7
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/dist/lib/gait-path.d.ts +13 -0
- package/dist/lib/gait-path.js +57 -0
- package/dist/lib/project-paths.d.ts +13 -0
- package/dist/lib/project-paths.js +57 -0
- package/dist/lib/storage/file-storage.d.ts +28 -0
- package/dist/lib/storage/file-storage.js +224 -0
- package/dist/lib/symlinks/symlink-manager.d.ts +66 -0
- package/dist/lib/symlinks/symlink-manager.js +444 -0
- package/dist/lib/symlinks/types.d.ts +23 -0
- package/dist/lib/symlinks/types.js +4 -0
- package/dist/lib/terminal/context-helper.d.ts +11 -0
- package/dist/lib/terminal/context-helper.js +164 -0
- package/dist/lib/terminal/global-manager.d.ts +2 -0
- package/dist/lib/terminal/global-manager.js +15 -0
- package/dist/lib/terminal/shell-utils.d.ts +33 -0
- package/dist/lib/terminal/shell-utils.js +176 -0
- package/dist/lib/terminal/terminal-manager.d.ts +26 -0
- package/dist/lib/terminal/terminal-manager.js +276 -0
- package/dist/lib/user-preferences.d.ts +48 -0
- package/dist/lib/user-preferences.js +87 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/routes/api/symlink-status/route.d.ts +1 -0
- package/dist/routes/api/symlink-status/route.js +37 -0
- package/dist/routes/api/symlinks/[id]/route.d.ts +19 -0
- package/dist/routes/api/symlinks/[id]/route.js +95 -0
- package/dist/routes/api/symlinks/[id]/toggle/route.d.ts +11 -0
- package/dist/routes/api/symlinks/[id]/toggle/route.js +32 -0
- package/dist/routes/api/symlinks/debug/route.d.ts +1 -0
- package/dist/routes/api/symlinks/debug/route.js +35 -0
- package/dist/routes/api/symlinks/route.d.ts +9 -0
- package/dist/routes/api/symlinks/route.js +72 -0
- package/dist/routes/api/toggle-symlink/route.d.ts +2 -0
- package/dist/routes/api/toggle-symlink/route.js +94 -0
- package/dist/routes/api/v1/agents/[id]/index.d.ts +1 -0
- package/dist/routes/api/v1/agents/[id]/index.js +1 -0
- package/dist/routes/api/v1/agents/[id]/route.d.ts +3 -0
- package/dist/routes/api/v1/agents/[id]/route.js +163 -0
- package/dist/routes/api/v1/agents/index.d.ts +1 -0
- package/dist/routes/api/v1/agents/index.js +1 -0
- package/dist/routes/api/v1/agents/route.d.ts +3 -0
- package/dist/routes/api/v1/agents/route.js +133 -0
- package/dist/routes/api/v1/ai/index.d.ts +3 -0
- package/dist/routes/api/v1/ai/index.js +5 -0
- package/dist/routes/api/v1/ai/route.d.ts +8 -0
- package/dist/routes/api/v1/ai/route.js +86 -0
- package/dist/routes/api/v1/chats/[id]/index.d.ts +3 -0
- package/dist/routes/api/v1/chats/[id]/index.js +6 -0
- package/dist/routes/api/v1/chats/[id]/route.d.ts +12 -0
- package/dist/routes/api/v1/chats/[id]/route.js +31 -0
- package/dist/routes/api/v1/chats/index.d.ts +3 -0
- package/dist/routes/api/v1/chats/index.js +6 -0
- package/dist/routes/api/v1/chats/route.d.ts +32 -0
- package/dist/routes/api/v1/chats/route.js +67 -0
- package/dist/routes/api/v1/config/index.d.ts +3 -0
- package/dist/routes/api/v1/config/index.js +5 -0
- package/dist/routes/api/v1/config/route.d.ts +9 -0
- package/dist/routes/api/v1/config/route.js +29 -0
- package/dist/routes/api/v1/context/[...path]/route.d.ts +16 -0
- package/dist/routes/api/v1/context/[...path]/route.js +107 -0
- package/dist/routes/api/v1/context/architecture/route.d.ts +3 -0
- package/dist/routes/api/v1/context/architecture/route.js +198 -0
- package/dist/routes/api/v1/context/index.d.ts +3 -0
- package/dist/routes/api/v1/context/index.js +9 -0
- package/dist/routes/api/v1/context/knowledge/[filename]/index.d.ts +1 -0
- package/dist/routes/api/v1/context/knowledge/[filename]/index.js +1 -0
- package/dist/routes/api/v1/context/knowledge/[filename]/route.d.ts +3 -0
- package/dist/routes/api/v1/context/knowledge/[filename]/route.js +165 -0
- package/dist/routes/api/v1/context/knowledge/index.d.ts +1 -0
- package/dist/routes/api/v1/context/knowledge/index.js +1 -0
- package/dist/routes/api/v1/context/knowledge/route.d.ts +3 -0
- package/dist/routes/api/v1/context/knowledge/route.js +121 -0
- package/dist/routes/api/v1/context/project/route.d.ts +3 -0
- package/dist/routes/api/v1/context/project/route.js +153 -0
- package/dist/routes/api/v1/proposals/[id]/route.d.ts +337 -0
- package/dist/routes/api/v1/proposals/[id]/route.js +99 -0
- package/dist/routes/api/v1/proposals/index.d.ts +3 -0
- package/dist/routes/api/v1/proposals/index.js +10 -0
- package/dist/routes/api/v1/proposals/route.d.ts +315 -0
- package/dist/routes/api/v1/proposals/route.js +103 -0
- package/dist/routes/api/v1/resources/[id]/index.d.ts +3 -0
- package/dist/routes/api/v1/resources/[id]/index.js +7 -0
- package/dist/routes/api/v1/resources/[id]/route.d.ts +46 -0
- package/dist/routes/api/v1/resources/[id]/route.js +143 -0
- package/dist/routes/api/v1/resources/[id]/thumbnail/index.d.ts +3 -0
- package/dist/routes/api/v1/resources/[id]/thumbnail/index.js +5 -0
- package/dist/routes/api/v1/resources/[id]/thumbnail/route.d.ts +2 -0
- package/dist/routes/api/v1/resources/[id]/thumbnail/route.js +50 -0
- package/dist/routes/api/v1/resources/index.d.ts +3 -0
- package/dist/routes/api/v1/resources/index.js +6 -0
- package/dist/routes/api/v1/resources/route.d.ts +51 -0
- package/dist/routes/api/v1/resources/route.js +147 -0
- package/dist/routes/api/v1/search/route.d.ts +3 -0
- package/dist/routes/api/v1/search/route.js +39 -0
- package/dist/routes/api/v1/terminal/[proposalId]/create/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[proposalId]/create/index.js +5 -0
- package/dist/routes/api/v1/terminal/[proposalId]/create/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[proposalId]/create/route.js +27 -0
- package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.js +5 -0
- package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.js +21 -0
- package/dist/routes/api/v1/terminal/[proposalId]/resize/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/[proposalId]/resize/index.js +5 -0
- package/dist/routes/api/v1/terminal/[proposalId]/resize/route.d.ts +10 -0
- package/dist/routes/api/v1/terminal/[proposalId]/resize/route.js +21 -0
- package/dist/routes/api/v1/terminal/sessions/index.d.ts +3 -0
- package/dist/routes/api/v1/terminal/sessions/index.js +5 -0
- package/dist/routes/api/v1/terminal/sessions/route.d.ts +6 -0
- package/dist/routes/api/v1/terminal/sessions/route.js +29 -0
- package/dist/routes/api/v1/user/index.d.ts +3 -0
- package/dist/routes/api/v1/user/index.js +5 -0
- package/dist/routes/api/v1/user/preferences/route.d.ts +11 -0
- package/dist/routes/api/v1/user/preferences/route.js +31 -0
- package/dist/routes/api/v1/user/profile/route.d.ts +11 -0
- package/dist/routes/api/v1/user/profile/route.js +31 -0
- package/dist/routes/api/v1/user/settings/index.d.ts +1 -0
- package/dist/routes/api/v1/user/settings/index.js +1 -0
- package/dist/routes/api/v1/user/settings/route.d.ts +3 -0
- package/dist/routes/api/v1/user/settings/route.js +51 -0
- package/dist/server-with-static.d.ts +4 -0
- package/dist/server-with-static.js +144 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +91 -0
- package/package.json +42 -0
- package/static/assets/index-BvTnrm0O.js +576 -0
- package/static/assets/index-Cm5dZHTl.css +33 -0
- package/static/assets/index-ORkAkJNi.js +576 -0
- package/static/assets/index-_Keadpms.js +576 -0
- package/static/index.html +17 -0
- package/static/vite.svg +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
success: true;
|
|
4
|
+
data: {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
size: number;
|
|
9
|
+
uploadedAt: string;
|
|
10
|
+
metadata: {
|
|
11
|
+
tags?: string[];
|
|
12
|
+
description?: string;
|
|
13
|
+
};
|
|
14
|
+
path: string;
|
|
15
|
+
thumbnailPath?: string;
|
|
16
|
+
}[];
|
|
17
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
18
|
+
success: false;
|
|
19
|
+
error: {
|
|
20
|
+
code: string;
|
|
21
|
+
message: any;
|
|
22
|
+
};
|
|
23
|
+
}, 500, "json">)>;
|
|
24
|
+
export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
25
|
+
success: false;
|
|
26
|
+
error: {
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
31
|
+
success: true;
|
|
32
|
+
data: {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
size: number;
|
|
37
|
+
uploadedAt: string;
|
|
38
|
+
metadata: {
|
|
39
|
+
tags?: string[];
|
|
40
|
+
description?: string;
|
|
41
|
+
};
|
|
42
|
+
path: string;
|
|
43
|
+
thumbnailPath?: string;
|
|
44
|
+
};
|
|
45
|
+
}, 201, "json">) | (Response & import("hono").TypedResponse<{
|
|
46
|
+
success: false;
|
|
47
|
+
error: {
|
|
48
|
+
code: string;
|
|
49
|
+
message: any;
|
|
50
|
+
};
|
|
51
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
// Generate a random ID
|
|
4
|
+
function generateId() {
|
|
5
|
+
return `res-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
6
|
+
}
|
|
7
|
+
const RESOURCES_DIR = '.gait/resources';
|
|
8
|
+
const FILES_DIR = path.join(RESOURCES_DIR, 'files');
|
|
9
|
+
const METADATA_DIR = path.join(RESOURCES_DIR, 'metadata');
|
|
10
|
+
const THUMBNAILS_DIR = path.join(RESOURCES_DIR, 'thumbnails');
|
|
11
|
+
async function ensureDirectories() {
|
|
12
|
+
await fs.mkdir(FILES_DIR, { recursive: true });
|
|
13
|
+
await fs.mkdir(METADATA_DIR, { recursive: true });
|
|
14
|
+
await fs.mkdir(THUMBNAILS_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
async function getResourceMetadata(id) {
|
|
17
|
+
try {
|
|
18
|
+
const metadataPath = path.join(METADATA_DIR, `${id}.json`);
|
|
19
|
+
const content = await fs.readFile(metadataPath, 'utf-8');
|
|
20
|
+
return JSON.parse(content);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code === 'ENOENT')
|
|
24
|
+
return null;
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function saveResourceMetadata(resource) {
|
|
29
|
+
const metadataPath = path.join(METADATA_DIR, `${resource.id}.json`);
|
|
30
|
+
await fs.writeFile(metadataPath, JSON.stringify(resource, null, 2), 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
async function listAllResources() {
|
|
33
|
+
try {
|
|
34
|
+
const files = await fs.readdir(METADATA_DIR);
|
|
35
|
+
const resources = await Promise.all(files
|
|
36
|
+
.filter(f => f.endsWith('.json'))
|
|
37
|
+
.map(async (file) => {
|
|
38
|
+
const content = await fs.readFile(path.join(METADATA_DIR, file), 'utf-8');
|
|
39
|
+
return JSON.parse(content);
|
|
40
|
+
}));
|
|
41
|
+
return resources.sort((a, b) => new Date(b.uploadedAt).getTime() - new Date(a.uploadedAt).getTime());
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error.code === 'ENOENT')
|
|
45
|
+
return [];
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function generateThumbnail(imageBuffer, id, mimeType) {
|
|
50
|
+
// For now, we'll create a simple placeholder thumbnail
|
|
51
|
+
// In a production environment, you'd use a library like Sharp for proper image processing
|
|
52
|
+
const thumbnailName = `${id}_thumb.jpg`;
|
|
53
|
+
const thumbnailPath = path.join(THUMBNAILS_DIR, thumbnailName);
|
|
54
|
+
try {
|
|
55
|
+
// This is a placeholder - in production, use Sharp or similar
|
|
56
|
+
// For now, we'll just copy the original image as the thumbnail
|
|
57
|
+
await fs.writeFile(thumbnailPath, imageBuffer);
|
|
58
|
+
return thumbnailName;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error('Failed to generate thumbnail:', error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function GET(c) {
|
|
66
|
+
try {
|
|
67
|
+
await ensureDirectories();
|
|
68
|
+
const resources = await listAllResources();
|
|
69
|
+
return c.json({
|
|
70
|
+
success: true,
|
|
71
|
+
data: resources
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error('Error listing resources:', error);
|
|
76
|
+
return c.json({
|
|
77
|
+
success: false,
|
|
78
|
+
error: {
|
|
79
|
+
code: 'LIST_RESOURCES_ERROR',
|
|
80
|
+
message: error.message
|
|
81
|
+
}
|
|
82
|
+
}, 500);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function POST(c) {
|
|
86
|
+
try {
|
|
87
|
+
await ensureDirectories();
|
|
88
|
+
const formData = await c.req.formData();
|
|
89
|
+
const file = formData.get('file');
|
|
90
|
+
const tags = formData.get('tags');
|
|
91
|
+
const description = formData.get('description');
|
|
92
|
+
if (!file) {
|
|
93
|
+
return c.json({
|
|
94
|
+
success: false,
|
|
95
|
+
error: {
|
|
96
|
+
code: 'NO_FILE_PROVIDED',
|
|
97
|
+
message: 'No file was provided'
|
|
98
|
+
}
|
|
99
|
+
}, 400);
|
|
100
|
+
}
|
|
101
|
+
const id = generateId();
|
|
102
|
+
const fileExtension = path.extname(file.name);
|
|
103
|
+
const fileName = `${id}${fileExtension}`;
|
|
104
|
+
const filePath = path.join(FILES_DIR, fileName);
|
|
105
|
+
// Save the file
|
|
106
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
107
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
108
|
+
await fs.writeFile(filePath, buffer);
|
|
109
|
+
// Create resource metadata
|
|
110
|
+
const resource = {
|
|
111
|
+
id,
|
|
112
|
+
name: file.name,
|
|
113
|
+
type: file.type,
|
|
114
|
+
size: file.size,
|
|
115
|
+
uploadedAt: new Date().toISOString(),
|
|
116
|
+
metadata: {
|
|
117
|
+
tags: tags ? tags.split(',').map(t => t.trim()) : [],
|
|
118
|
+
description: description || undefined
|
|
119
|
+
},
|
|
120
|
+
path: fileName
|
|
121
|
+
};
|
|
122
|
+
// Generate thumbnail for images
|
|
123
|
+
if (file.type.startsWith('image/')) {
|
|
124
|
+
try {
|
|
125
|
+
resource.thumbnailPath = await generateThumbnail(buffer, id, file.type);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.warn('Failed to generate thumbnail:', error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
await saveResourceMetadata(resource);
|
|
132
|
+
return c.json({
|
|
133
|
+
success: true,
|
|
134
|
+
data: resource
|
|
135
|
+
}, 201);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error('Error uploading resource:', error);
|
|
139
|
+
return c.json({
|
|
140
|
+
success: false,
|
|
141
|
+
error: {
|
|
142
|
+
code: 'UPLOAD_RESOURCE_ERROR',
|
|
143
|
+
message: error.message
|
|
144
|
+
}
|
|
145
|
+
}, 500);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { FileStorageAdapter } from '@/lib/storage/file-storage';
|
|
3
|
+
// Force dynamic rendering for this route since it uses searchParams
|
|
4
|
+
export const dynamic = 'force-dynamic';
|
|
5
|
+
const storage = new FileStorageAdapter();
|
|
6
|
+
export async function GET(request) {
|
|
7
|
+
try {
|
|
8
|
+
const searchParams = request.nextUrl.searchParams;
|
|
9
|
+
const query = searchParams.get('q');
|
|
10
|
+
if (!query) {
|
|
11
|
+
return NextResponse.json({
|
|
12
|
+
success: false,
|
|
13
|
+
error: {
|
|
14
|
+
code: 'MISSING_QUERY',
|
|
15
|
+
message: 'Query parameter "q" is required'
|
|
16
|
+
}
|
|
17
|
+
}, { status: 400 });
|
|
18
|
+
}
|
|
19
|
+
const results = await storage.searchCPs(query);
|
|
20
|
+
return NextResponse.json({
|
|
21
|
+
success: true,
|
|
22
|
+
data: results,
|
|
23
|
+
metadata: {
|
|
24
|
+
query,
|
|
25
|
+
resultCount: results.length
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error('Error searching proposals:', error);
|
|
31
|
+
return NextResponse.json({
|
|
32
|
+
success: false,
|
|
33
|
+
error: {
|
|
34
|
+
code: 'SEARCH_ERROR',
|
|
35
|
+
message: error.message
|
|
36
|
+
}
|
|
37
|
+
}, { status: 500 });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
error: string;
|
|
4
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
5
|
+
sessionId: string;
|
|
6
|
+
proposalId: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
9
|
+
error: string;
|
|
10
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
|
|
2
|
+
import { loadUserSettings } from '../../../../../../lib/user-preferences.js';
|
|
3
|
+
export async function POST(c) {
|
|
4
|
+
try {
|
|
5
|
+
const proposalId = c.req.param('proposalId');
|
|
6
|
+
const body = await c.req.json().catch(() => ({}));
|
|
7
|
+
const { enableLogging = false } = body;
|
|
8
|
+
if (!proposalId) {
|
|
9
|
+
return c.json({ error: 'Proposal ID is required' }, 400);
|
|
10
|
+
}
|
|
11
|
+
// Load user settings to get shell preference
|
|
12
|
+
const userSettings = await loadUserSettings();
|
|
13
|
+
const shellPreference = (userSettings.preferences.terminalShell || 'bash');
|
|
14
|
+
// Create a new terminal session for this proposal
|
|
15
|
+
const terminalManager = getGlobalTerminalManager();
|
|
16
|
+
const session = await terminalManager.createSession(proposalId, enableLogging, shellPreference);
|
|
17
|
+
return c.json({
|
|
18
|
+
sessionId: session.id,
|
|
19
|
+
proposalId: session.proposalId,
|
|
20
|
+
createdAt: session.createdAt,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error('Error creating terminal session:', error);
|
|
25
|
+
return c.json({ error: 'Failed to create terminal session' }, 500);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
error: string;
|
|
4
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
5
|
+
error: string;
|
|
6
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
7
|
+
success: true;
|
|
8
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
9
|
+
error: string;
|
|
10
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
|
|
2
|
+
export async function POST(c) {
|
|
3
|
+
try {
|
|
4
|
+
const proposalId = c.req.param('proposalId');
|
|
5
|
+
const body = await c.req.json();
|
|
6
|
+
const { sessionId } = body;
|
|
7
|
+
if (!sessionId) {
|
|
8
|
+
return c.json({ error: 'Session ID is required' }, 400);
|
|
9
|
+
}
|
|
10
|
+
const terminalManager = getGlobalTerminalManager();
|
|
11
|
+
const success = terminalManager.destroySession(sessionId);
|
|
12
|
+
if (!success) {
|
|
13
|
+
return c.json({ error: 'Session not found' }, 404);
|
|
14
|
+
}
|
|
15
|
+
return c.json({ success: true });
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
console.error('Error destroying terminal session:', error);
|
|
19
|
+
return c.json({ error: 'Failed to destroy terminal session' }, 500);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function POST(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
error: string;
|
|
4
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
5
|
+
error: string;
|
|
6
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
7
|
+
success: true;
|
|
8
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
9
|
+
error: string;
|
|
10
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
|
|
2
|
+
export async function POST(c) {
|
|
3
|
+
try {
|
|
4
|
+
const proposalId = c.req.param('proposalId');
|
|
5
|
+
const body = await c.req.json();
|
|
6
|
+
const { sessionId, cols, rows } = body;
|
|
7
|
+
if (!sessionId || !cols || !rows) {
|
|
8
|
+
return c.json({ error: 'Session ID, cols, and rows are required' }, 400);
|
|
9
|
+
}
|
|
10
|
+
const terminalManager = getGlobalTerminalManager();
|
|
11
|
+
const success = terminalManager.resizeSession(sessionId, cols, rows);
|
|
12
|
+
if (!success) {
|
|
13
|
+
return c.json({ error: 'Session not found or resize failed' }, 404);
|
|
14
|
+
}
|
|
15
|
+
return c.json({ success: true });
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
console.error('Error resizing terminal session:', error);
|
|
19
|
+
return c.json({ error: 'Failed to resize terminal session' }, 500);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
3
|
+
sessions: any;
|
|
4
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
5
|
+
error: string;
|
|
6
|
+
}, 500, "json">)>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getGlobalTerminalManager } from '../../../../../lib/terminal/global-manager.js';
|
|
2
|
+
export async function GET(c) {
|
|
3
|
+
try {
|
|
4
|
+
const url = new URL(c.req.url);
|
|
5
|
+
const searchParams = url.searchParams;
|
|
6
|
+
const proposalId = searchParams.get('proposalId');
|
|
7
|
+
const terminalManager = getGlobalTerminalManager();
|
|
8
|
+
let sessions;
|
|
9
|
+
if (proposalId) {
|
|
10
|
+
sessions = terminalManager.getSessionsByProposal(proposalId);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
sessions = terminalManager.getAllSessions();
|
|
14
|
+
}
|
|
15
|
+
// Return session info without the PTY instance
|
|
16
|
+
const sessionInfo = sessions.map(session => ({
|
|
17
|
+
id: session.id,
|
|
18
|
+
proposalId: session.proposalId,
|
|
19
|
+
createdAt: session.createdAt,
|
|
20
|
+
lastActivity: session.lastActivity,
|
|
21
|
+
connected: !!session.websocket,
|
|
22
|
+
}));
|
|
23
|
+
return c.json({ sessions: sessionInfo });
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error('Error getting terminal sessions:', error);
|
|
27
|
+
return c.json({ error: 'Failed to get terminal sessions' }, 500);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/v1/user/preferences
|
|
4
|
+
* Get user preferences
|
|
5
|
+
*/
|
|
6
|
+
export declare function GET(): Promise<any>;
|
|
7
|
+
/**
|
|
8
|
+
* PUT /api/v1/user/preferences
|
|
9
|
+
* Update user preferences
|
|
10
|
+
*/
|
|
11
|
+
export declare function PUT(request: NextRequest): Promise<any>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { updateUserPreferences, loadUserSettings } from '@/lib/user-preferences';
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/v1/user/preferences
|
|
5
|
+
* Get user preferences
|
|
6
|
+
*/
|
|
7
|
+
export async function GET() {
|
|
8
|
+
try {
|
|
9
|
+
const settings = await loadUserSettings();
|
|
10
|
+
return NextResponse.json({ success: true, data: settings.preferences });
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.error('Failed to load user preferences:', error);
|
|
14
|
+
return NextResponse.json({ success: false, error: 'Failed to load user preferences' }, { status: 500 });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* PUT /api/v1/user/preferences
|
|
19
|
+
* Update user preferences
|
|
20
|
+
*/
|
|
21
|
+
export async function PUT(request) {
|
|
22
|
+
try {
|
|
23
|
+
const preferences = await request.json();
|
|
24
|
+
const settings = await updateUserPreferences(preferences);
|
|
25
|
+
return NextResponse.json({ success: true, data: settings.preferences });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
console.error('Failed to update user preferences:', error);
|
|
29
|
+
return NextResponse.json({ success: false, error: 'Failed to update user preferences' }, { status: 500 });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/v1/user/profile
|
|
4
|
+
* Get user profile information
|
|
5
|
+
*/
|
|
6
|
+
export declare function GET(): Promise<any>;
|
|
7
|
+
/**
|
|
8
|
+
* PUT /api/v1/user/profile
|
|
9
|
+
* Update user profile information
|
|
10
|
+
*/
|
|
11
|
+
export declare function PUT(request: NextRequest): Promise<any>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { updateUserProfile, loadUserSettings } from '@/lib/user-preferences';
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/v1/user/profile
|
|
5
|
+
* Get user profile information
|
|
6
|
+
*/
|
|
7
|
+
export async function GET() {
|
|
8
|
+
try {
|
|
9
|
+
const settings = await loadUserSettings();
|
|
10
|
+
return NextResponse.json({ success: true, data: settings.profile });
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.error('Failed to load user profile:', error);
|
|
14
|
+
return NextResponse.json({ success: false, error: 'Failed to load user profile' }, { status: 500 });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* PUT /api/v1/user/profile
|
|
19
|
+
* Update user profile information
|
|
20
|
+
*/
|
|
21
|
+
export async function PUT(request) {
|
|
22
|
+
try {
|
|
23
|
+
const profile = await request.json();
|
|
24
|
+
const settings = await updateUserProfile(profile);
|
|
25
|
+
return NextResponse.json({ success: true, data: settings.profile });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
console.error('Failed to update user profile:', error);
|
|
29
|
+
return NextResponse.json({ success: false, error: 'Failed to update user profile' }, { status: 500 });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './route.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './route.js';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { loadUserSettings, saveUserSettings } from '../../../../../lib/user-preferences.js';
|
|
3
|
+
const app = new Hono();
|
|
4
|
+
/**
|
|
5
|
+
* GET /api/v1/user/settings
|
|
6
|
+
* Load user settings from ~/.gait/user-settings.json
|
|
7
|
+
*/
|
|
8
|
+
app.get('/', async (c) => {
|
|
9
|
+
try {
|
|
10
|
+
const settings = await loadUserSettings();
|
|
11
|
+
return c.json({ success: true, data: settings });
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error('Failed to load user settings:', error);
|
|
15
|
+
return c.json({ success: false, error: 'Failed to load user settings' }, 500);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* PUT /api/v1/user/settings
|
|
20
|
+
* Update complete user settings
|
|
21
|
+
*/
|
|
22
|
+
app.put('/', async (c) => {
|
|
23
|
+
try {
|
|
24
|
+
const body = await c.req.json();
|
|
25
|
+
const { profile, preferences } = body;
|
|
26
|
+
if (!profile && !preferences) {
|
|
27
|
+
return c.json({ success: false, error: 'Profile or preferences data required' }, 400);
|
|
28
|
+
}
|
|
29
|
+
let settings = await loadUserSettings();
|
|
30
|
+
if (profile) {
|
|
31
|
+
settings.profile = { ...settings.profile, ...profile };
|
|
32
|
+
}
|
|
33
|
+
if (preferences) {
|
|
34
|
+
settings.preferences = {
|
|
35
|
+
...settings.preferences,
|
|
36
|
+
...preferences,
|
|
37
|
+
notifications: {
|
|
38
|
+
...settings.preferences.notifications,
|
|
39
|
+
...preferences.notifications,
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
await saveUserSettings(settings);
|
|
44
|
+
return c.json({ success: true, data: settings });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('Failed to update user settings:', error);
|
|
48
|
+
return c.json({ success: false, error: 'Failed to update user settings' }, 500);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
export default app;
|