@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.
Files changed (131) hide show
  1. package/dist/lib/gait-path.d.ts +13 -0
  2. package/dist/lib/gait-path.js +57 -0
  3. package/dist/lib/project-paths.d.ts +13 -0
  4. package/dist/lib/project-paths.js +57 -0
  5. package/dist/lib/storage/file-storage.d.ts +28 -0
  6. package/dist/lib/storage/file-storage.js +224 -0
  7. package/dist/lib/symlinks/symlink-manager.d.ts +66 -0
  8. package/dist/lib/symlinks/symlink-manager.js +444 -0
  9. package/dist/lib/symlinks/types.d.ts +23 -0
  10. package/dist/lib/symlinks/types.js +4 -0
  11. package/dist/lib/terminal/context-helper.d.ts +11 -0
  12. package/dist/lib/terminal/context-helper.js +164 -0
  13. package/dist/lib/terminal/global-manager.d.ts +2 -0
  14. package/dist/lib/terminal/global-manager.js +15 -0
  15. package/dist/lib/terminal/shell-utils.d.ts +33 -0
  16. package/dist/lib/terminal/shell-utils.js +176 -0
  17. package/dist/lib/terminal/terminal-manager.d.ts +26 -0
  18. package/dist/lib/terminal/terminal-manager.js +276 -0
  19. package/dist/lib/user-preferences.d.ts +48 -0
  20. package/dist/lib/user-preferences.js +87 -0
  21. package/dist/lib/utils.d.ts +2 -0
  22. package/dist/lib/utils.js +5 -0
  23. package/dist/routes/api/symlink-status/route.d.ts +1 -0
  24. package/dist/routes/api/symlink-status/route.js +37 -0
  25. package/dist/routes/api/symlinks/[id]/route.d.ts +19 -0
  26. package/dist/routes/api/symlinks/[id]/route.js +95 -0
  27. package/dist/routes/api/symlinks/[id]/toggle/route.d.ts +11 -0
  28. package/dist/routes/api/symlinks/[id]/toggle/route.js +32 -0
  29. package/dist/routes/api/symlinks/debug/route.d.ts +1 -0
  30. package/dist/routes/api/symlinks/debug/route.js +35 -0
  31. package/dist/routes/api/symlinks/route.d.ts +9 -0
  32. package/dist/routes/api/symlinks/route.js +72 -0
  33. package/dist/routes/api/toggle-symlink/route.d.ts +2 -0
  34. package/dist/routes/api/toggle-symlink/route.js +94 -0
  35. package/dist/routes/api/v1/agents/[id]/index.d.ts +1 -0
  36. package/dist/routes/api/v1/agents/[id]/index.js +1 -0
  37. package/dist/routes/api/v1/agents/[id]/route.d.ts +3 -0
  38. package/dist/routes/api/v1/agents/[id]/route.js +163 -0
  39. package/dist/routes/api/v1/agents/index.d.ts +1 -0
  40. package/dist/routes/api/v1/agents/index.js +1 -0
  41. package/dist/routes/api/v1/agents/route.d.ts +3 -0
  42. package/dist/routes/api/v1/agents/route.js +133 -0
  43. package/dist/routes/api/v1/ai/index.d.ts +3 -0
  44. package/dist/routes/api/v1/ai/index.js +5 -0
  45. package/dist/routes/api/v1/ai/route.d.ts +8 -0
  46. package/dist/routes/api/v1/ai/route.js +86 -0
  47. package/dist/routes/api/v1/chats/[id]/index.d.ts +3 -0
  48. package/dist/routes/api/v1/chats/[id]/index.js +6 -0
  49. package/dist/routes/api/v1/chats/[id]/route.d.ts +12 -0
  50. package/dist/routes/api/v1/chats/[id]/route.js +31 -0
  51. package/dist/routes/api/v1/chats/index.d.ts +3 -0
  52. package/dist/routes/api/v1/chats/index.js +6 -0
  53. package/dist/routes/api/v1/chats/route.d.ts +32 -0
  54. package/dist/routes/api/v1/chats/route.js +67 -0
  55. package/dist/routes/api/v1/config/index.d.ts +3 -0
  56. package/dist/routes/api/v1/config/index.js +5 -0
  57. package/dist/routes/api/v1/config/route.d.ts +9 -0
  58. package/dist/routes/api/v1/config/route.js +29 -0
  59. package/dist/routes/api/v1/context/[...path]/route.d.ts +16 -0
  60. package/dist/routes/api/v1/context/[...path]/route.js +107 -0
  61. package/dist/routes/api/v1/context/architecture/route.d.ts +3 -0
  62. package/dist/routes/api/v1/context/architecture/route.js +198 -0
  63. package/dist/routes/api/v1/context/index.d.ts +3 -0
  64. package/dist/routes/api/v1/context/index.js +9 -0
  65. package/dist/routes/api/v1/context/knowledge/[filename]/index.d.ts +1 -0
  66. package/dist/routes/api/v1/context/knowledge/[filename]/index.js +1 -0
  67. package/dist/routes/api/v1/context/knowledge/[filename]/route.d.ts +3 -0
  68. package/dist/routes/api/v1/context/knowledge/[filename]/route.js +165 -0
  69. package/dist/routes/api/v1/context/knowledge/index.d.ts +1 -0
  70. package/dist/routes/api/v1/context/knowledge/index.js +1 -0
  71. package/dist/routes/api/v1/context/knowledge/route.d.ts +3 -0
  72. package/dist/routes/api/v1/context/knowledge/route.js +121 -0
  73. package/dist/routes/api/v1/context/project/route.d.ts +3 -0
  74. package/dist/routes/api/v1/context/project/route.js +153 -0
  75. package/dist/routes/api/v1/proposals/[id]/route.d.ts +337 -0
  76. package/dist/routes/api/v1/proposals/[id]/route.js +99 -0
  77. package/dist/routes/api/v1/proposals/index.d.ts +3 -0
  78. package/dist/routes/api/v1/proposals/index.js +10 -0
  79. package/dist/routes/api/v1/proposals/route.d.ts +315 -0
  80. package/dist/routes/api/v1/proposals/route.js +103 -0
  81. package/dist/routes/api/v1/resources/[id]/index.d.ts +3 -0
  82. package/dist/routes/api/v1/resources/[id]/index.js +7 -0
  83. package/dist/routes/api/v1/resources/[id]/route.d.ts +46 -0
  84. package/dist/routes/api/v1/resources/[id]/route.js +143 -0
  85. package/dist/routes/api/v1/resources/[id]/thumbnail/index.d.ts +3 -0
  86. package/dist/routes/api/v1/resources/[id]/thumbnail/index.js +5 -0
  87. package/dist/routes/api/v1/resources/[id]/thumbnail/route.d.ts +2 -0
  88. package/dist/routes/api/v1/resources/[id]/thumbnail/route.js +50 -0
  89. package/dist/routes/api/v1/resources/index.d.ts +3 -0
  90. package/dist/routes/api/v1/resources/index.js +6 -0
  91. package/dist/routes/api/v1/resources/route.d.ts +51 -0
  92. package/dist/routes/api/v1/resources/route.js +147 -0
  93. package/dist/routes/api/v1/search/route.d.ts +3 -0
  94. package/dist/routes/api/v1/search/route.js +39 -0
  95. package/dist/routes/api/v1/terminal/[proposalId]/create/index.d.ts +3 -0
  96. package/dist/routes/api/v1/terminal/[proposalId]/create/index.js +5 -0
  97. package/dist/routes/api/v1/terminal/[proposalId]/create/route.d.ts +10 -0
  98. package/dist/routes/api/v1/terminal/[proposalId]/create/route.js +27 -0
  99. package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.d.ts +3 -0
  100. package/dist/routes/api/v1/terminal/[proposalId]/destroy/index.js +5 -0
  101. package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.d.ts +10 -0
  102. package/dist/routes/api/v1/terminal/[proposalId]/destroy/route.js +21 -0
  103. package/dist/routes/api/v1/terminal/[proposalId]/resize/index.d.ts +3 -0
  104. package/dist/routes/api/v1/terminal/[proposalId]/resize/index.js +5 -0
  105. package/dist/routes/api/v1/terminal/[proposalId]/resize/route.d.ts +10 -0
  106. package/dist/routes/api/v1/terminal/[proposalId]/resize/route.js +21 -0
  107. package/dist/routes/api/v1/terminal/sessions/index.d.ts +3 -0
  108. package/dist/routes/api/v1/terminal/sessions/index.js +5 -0
  109. package/dist/routes/api/v1/terminal/sessions/route.d.ts +6 -0
  110. package/dist/routes/api/v1/terminal/sessions/route.js +29 -0
  111. package/dist/routes/api/v1/user/index.d.ts +3 -0
  112. package/dist/routes/api/v1/user/index.js +5 -0
  113. package/dist/routes/api/v1/user/preferences/route.d.ts +11 -0
  114. package/dist/routes/api/v1/user/preferences/route.js +31 -0
  115. package/dist/routes/api/v1/user/profile/route.d.ts +11 -0
  116. package/dist/routes/api/v1/user/profile/route.js +31 -0
  117. package/dist/routes/api/v1/user/settings/index.d.ts +1 -0
  118. package/dist/routes/api/v1/user/settings/index.js +1 -0
  119. package/dist/routes/api/v1/user/settings/route.d.ts +3 -0
  120. package/dist/routes/api/v1/user/settings/route.js +51 -0
  121. package/dist/server-with-static.d.ts +4 -0
  122. package/dist/server-with-static.js +144 -0
  123. package/dist/server.d.ts +1 -0
  124. package/dist/server.js +91 -0
  125. package/package.json +42 -0
  126. package/static/assets/index-BvTnrm0O.js +576 -0
  127. package/static/assets/index-Cm5dZHTl.css +33 -0
  128. package/static/assets/index-ORkAkJNi.js +576 -0
  129. package/static/assets/index-_Keadpms.js +576 -0
  130. package/static/index.html +17 -0
  131. package/static/vite.svg +1 -0
@@ -0,0 +1,37 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { promises as fs } from 'fs';
3
+ import { getSymlinkPath } from '@/lib/project-paths';
4
+ export async function GET() {
5
+ try {
6
+ const symlinkPath = await getSymlinkPath();
7
+ try {
8
+ const stats = await fs.lstat(symlinkPath);
9
+ const exists = stats.isSymbolicLink();
10
+ return NextResponse.json({
11
+ success: true,
12
+ exists,
13
+ path: symlinkPath
14
+ });
15
+ }
16
+ catch (error) {
17
+ if (error.code === 'ENOENT') {
18
+ return NextResponse.json({
19
+ success: true,
20
+ exists: false,
21
+ path: symlinkPath
22
+ });
23
+ }
24
+ throw error;
25
+ }
26
+ }
27
+ catch (error) {
28
+ console.error('Error checking symlink status:', error);
29
+ return NextResponse.json({
30
+ success: false,
31
+ error: {
32
+ code: 'SYMLINK_STATUS_ERROR',
33
+ message: error.message
34
+ }
35
+ }, { status: 500 });
36
+ }
37
+ }
@@ -0,0 +1,19 @@
1
+ import { NextRequest } from 'next/server';
2
+ interface RouteParams {
3
+ params: {
4
+ id: string;
5
+ };
6
+ }
7
+ /**
8
+ * GET /api/symlinks/[id] - Get a specific symlink configuration
9
+ */
10
+ export declare function GET(request: NextRequest, { params }: RouteParams): Promise<any>;
11
+ /**
12
+ * PATCH /api/symlinks/[id] - Update a symlink configuration
13
+ */
14
+ export declare function PATCH(request: NextRequest, { params }: RouteParams): Promise<any>;
15
+ /**
16
+ * DELETE /api/symlinks/[id] - Delete a symlink configuration
17
+ */
18
+ export declare function DELETE(request: NextRequest, { params }: RouteParams): Promise<any>;
19
+ export {};
@@ -0,0 +1,95 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { getSymlinkManager } from '@/lib/symlinks/symlink-manager';
3
+ /**
4
+ * GET /api/symlinks/[id] - Get a specific symlink configuration
5
+ */
6
+ export async function GET(request, { params }) {
7
+ try {
8
+ const manager = await getSymlinkManager();
9
+ const symlink = await manager.getSymlink(params.id);
10
+ if (!symlink) {
11
+ return NextResponse.json({
12
+ success: false,
13
+ error: {
14
+ code: 'NOT_FOUND',
15
+ message: `Symlink with ID ${params.id} not found`
16
+ }
17
+ }, { status: 404 });
18
+ }
19
+ return NextResponse.json({
20
+ success: true,
21
+ symlink
22
+ });
23
+ }
24
+ catch (error) {
25
+ console.error('Error fetching symlink:', error);
26
+ return NextResponse.json({
27
+ success: false,
28
+ error: {
29
+ code: 'FETCH_SYMLINK_ERROR',
30
+ message: error.message
31
+ }
32
+ }, { status: 500 });
33
+ }
34
+ }
35
+ /**
36
+ * PATCH /api/symlinks/[id] - Update a symlink configuration
37
+ */
38
+ export async function PATCH(request, { params }) {
39
+ try {
40
+ const body = await request.json();
41
+ const manager = await getSymlinkManager();
42
+ const result = await manager.updateSymlink(params.id, body);
43
+ if (!result.success) {
44
+ return NextResponse.json({
45
+ success: false,
46
+ error: {
47
+ code: 'UPDATE_SYMLINK_ERROR',
48
+ message: result.message,
49
+ details: result.error
50
+ }
51
+ }, { status: 400 });
52
+ }
53
+ return NextResponse.json(result);
54
+ }
55
+ catch (error) {
56
+ console.error('Error updating symlink:', error);
57
+ return NextResponse.json({
58
+ success: false,
59
+ error: {
60
+ code: 'UPDATE_SYMLINK_ERROR',
61
+ message: error.message
62
+ }
63
+ }, { status: 500 });
64
+ }
65
+ }
66
+ /**
67
+ * DELETE /api/symlinks/[id] - Delete a symlink configuration
68
+ */
69
+ export async function DELETE(request, { params }) {
70
+ try {
71
+ const manager = await getSymlinkManager();
72
+ const result = await manager.deleteSymlink(params.id);
73
+ if (!result.success) {
74
+ return NextResponse.json({
75
+ success: false,
76
+ error: {
77
+ code: 'DELETE_SYMLINK_ERROR',
78
+ message: result.message,
79
+ details: result.error
80
+ }
81
+ }, { status: 400 });
82
+ }
83
+ return NextResponse.json(result);
84
+ }
85
+ catch (error) {
86
+ console.error('Error deleting symlink:', error);
87
+ return NextResponse.json({
88
+ success: false,
89
+ error: {
90
+ code: 'DELETE_SYMLINK_ERROR',
91
+ message: error.message
92
+ }
93
+ }, { status: 500 });
94
+ }
95
+ }
@@ -0,0 +1,11 @@
1
+ import { NextRequest } from 'next/server';
2
+ interface RouteParams {
3
+ params: {
4
+ id: string;
5
+ };
6
+ }
7
+ /**
8
+ * POST /api/symlinks/[id]/toggle - Toggle a symlink on/off
9
+ */
10
+ export declare function POST(request: NextRequest, { params }: RouteParams): Promise<any>;
11
+ export {};
@@ -0,0 +1,32 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { getSymlinkManager } from '@/lib/symlinks/symlink-manager';
3
+ /**
4
+ * POST /api/symlinks/[id]/toggle - Toggle a symlink on/off
5
+ */
6
+ export async function POST(request, { params }) {
7
+ try {
8
+ const manager = await getSymlinkManager();
9
+ const result = await manager.toggleSymlink(params.id);
10
+ if (!result.success) {
11
+ return NextResponse.json({
12
+ success: false,
13
+ error: {
14
+ code: 'TOGGLE_SYMLINK_ERROR',
15
+ message: result.message,
16
+ details: result.error
17
+ }
18
+ }, { status: 400 });
19
+ }
20
+ return NextResponse.json(result);
21
+ }
22
+ catch (error) {
23
+ console.error('Error toggling symlink:', error);
24
+ return NextResponse.json({
25
+ success: false,
26
+ error: {
27
+ code: 'TOGGLE_SYMLINK_ERROR',
28
+ message: error.message
29
+ }
30
+ }, { status: 500 });
31
+ }
32
+ }
@@ -0,0 +1 @@
1
+ export declare function GET(): Promise<any>;
@@ -0,0 +1,35 @@
1
+ import { NextResponse } from 'next/server';
2
+ import path from 'path';
3
+ import { promises as fs } from 'fs';
4
+ export async function GET() {
5
+ const cwd = process.cwd();
6
+ const calculatedRoot = path.resolve(cwd, '../..');
7
+ const envRoot = process.env.GAIT_PROJECT_ROOT;
8
+ // Check what files exist
9
+ const checks = {
10
+ cwd,
11
+ calculatedRoot,
12
+ envRoot: envRoot || 'not set',
13
+ gaitDirExists: false,
14
+ symlinksJsonExists: false,
15
+ symlinksJsonPath: path.join(calculatedRoot, '.gait', 'symlinks.json'),
16
+ actualFiles: []
17
+ };
18
+ try {
19
+ await fs.access(path.join(calculatedRoot, '.gait'));
20
+ checks.gaitDirExists = true;
21
+ const files = await fs.readdir(path.join(calculatedRoot, '.gait'));
22
+ checks.actualFiles = files;
23
+ try {
24
+ await fs.access(checks.symlinksJsonPath);
25
+ checks.symlinksJsonExists = true;
26
+ }
27
+ catch {
28
+ // File doesn't exist
29
+ }
30
+ }
31
+ catch {
32
+ // Directory doesn't exist
33
+ }
34
+ return NextResponse.json(checks);
35
+ }
@@ -0,0 +1,9 @@
1
+ import { NextRequest } from 'next/server';
2
+ /**
3
+ * GET /api/symlinks - Get all symlink configurations
4
+ */
5
+ export declare function GET(): Promise<any>;
6
+ /**
7
+ * POST /api/symlinks - Add a new symlink configuration
8
+ */
9
+ export declare function POST(request: NextRequest): Promise<any>;
@@ -0,0 +1,72 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { getSymlinkManager } from '@/lib/symlinks/symlink-manager';
3
+ /**
4
+ * GET /api/symlinks - Get all symlink configurations
5
+ */
6
+ export async function GET() {
7
+ try {
8
+ const manager = await getSymlinkManager();
9
+ const symlinks = await manager.getSymlinks();
10
+ return NextResponse.json({
11
+ success: true,
12
+ symlinks
13
+ });
14
+ }
15
+ catch (error) {
16
+ console.error('Error fetching symlinks:', error);
17
+ return NextResponse.json({
18
+ success: false,
19
+ error: {
20
+ code: 'FETCH_SYMLINKS_ERROR',
21
+ message: error.message
22
+ }
23
+ }, { status: 500 });
24
+ }
25
+ }
26
+ /**
27
+ * POST /api/symlinks - Add a new symlink configuration
28
+ */
29
+ export async function POST(request) {
30
+ try {
31
+ const body = await request.json();
32
+ const { name, description, linkPath, targetPath, isActive } = body;
33
+ if (!name || !linkPath || !targetPath) {
34
+ return NextResponse.json({
35
+ success: false,
36
+ error: {
37
+ code: 'INVALID_REQUEST',
38
+ message: 'Missing required fields: name, linkPath, targetPath'
39
+ }
40
+ }, { status: 400 });
41
+ }
42
+ const manager = await getSymlinkManager();
43
+ const result = await manager.addSymlink({
44
+ name,
45
+ description,
46
+ linkPath,
47
+ targetPath,
48
+ isActive: isActive || false
49
+ });
50
+ if (!result.success) {
51
+ return NextResponse.json({
52
+ success: false,
53
+ error: {
54
+ code: 'ADD_SYMLINK_ERROR',
55
+ message: result.message,
56
+ details: result.error
57
+ }
58
+ }, { status: 400 });
59
+ }
60
+ return NextResponse.json(result);
61
+ }
62
+ catch (error) {
63
+ console.error('Error adding symlink:', error);
64
+ return NextResponse.json({
65
+ success: false,
66
+ error: {
67
+ code: 'ADD_SYMLINK_ERROR',
68
+ message: error.message
69
+ }
70
+ }, { status: 500 });
71
+ }
72
+ }
@@ -0,0 +1,2 @@
1
+ import { NextRequest } from 'next/server';
2
+ export declare function POST(request: NextRequest): Promise<any>;
@@ -0,0 +1,94 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ import { getSymlinkPath, getTargetPath } from '@/lib/project-paths';
5
+ export async function POST(request) {
6
+ try {
7
+ const body = await request.json();
8
+ const { active } = body;
9
+ const symlinkPath = await getSymlinkPath();
10
+ const targetPath = await getTargetPath();
11
+ if (active) {
12
+ // Create symlink
13
+ try {
14
+ // Ensure the target directory and file exist
15
+ await fs.mkdir(path.dirname(targetPath), { recursive: true });
16
+ // Check if target file exists, create if not
17
+ try {
18
+ await fs.access(targetPath);
19
+ }
20
+ catch {
21
+ await fs.writeFile(targetPath, `# Claude Rules
22
+
23
+ This file contains project-specific rules and guidelines for Claude AI assistant.
24
+
25
+ ## Project Context
26
+ Add project-specific context and guidelines here.
27
+
28
+ ## Coding Standards
29
+ Add coding standards and conventions here.
30
+
31
+ ## Best Practices
32
+ Add best practices and patterns specific to this project.
33
+ `);
34
+ }
35
+ // Remove existing file/symlink if it exists
36
+ try {
37
+ await fs.unlink(symlinkPath);
38
+ }
39
+ catch (error) {
40
+ if (error.code !== 'ENOENT')
41
+ throw error;
42
+ }
43
+ // Create the symlink
44
+ await fs.symlink(targetPath, symlinkPath);
45
+ return NextResponse.json({
46
+ success: true,
47
+ message: 'Symlink created successfully',
48
+ active: true,
49
+ symlinkPath,
50
+ targetPath
51
+ });
52
+ }
53
+ catch (error) {
54
+ throw new Error(`Failed to create symlink: ${error.message}`);
55
+ }
56
+ }
57
+ else {
58
+ // Remove symlink
59
+ try {
60
+ const stats = await fs.lstat(symlinkPath);
61
+ if (stats.isSymbolicLink()) {
62
+ await fs.unlink(symlinkPath);
63
+ }
64
+ return NextResponse.json({
65
+ success: true,
66
+ message: 'Symlink removed successfully',
67
+ active: false,
68
+ symlinkPath
69
+ });
70
+ }
71
+ catch (error) {
72
+ if (error.code === 'ENOENT') {
73
+ return NextResponse.json({
74
+ success: true,
75
+ message: 'No symlink to remove',
76
+ active: false,
77
+ symlinkPath
78
+ });
79
+ }
80
+ throw new Error(`Failed to remove symlink: ${error.message}`);
81
+ }
82
+ }
83
+ }
84
+ catch (error) {
85
+ console.error('Error toggling symlink:', error);
86
+ return NextResponse.json({
87
+ success: false,
88
+ error: {
89
+ code: 'TOGGLE_SYMLINK_ERROR',
90
+ message: error.message
91
+ }
92
+ }, { status: 500 });
93
+ }
94
+ }
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,163 @@
1
+ import { Hono } from 'hono';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ import matter from 'gray-matter';
5
+ const app = new Hono();
6
+ function getAgentsPath() {
7
+ const basePath = process.env.GAIT_DATA_PATH ?
8
+ path.resolve(process.env.GAIT_DATA_PATH, '.gait') :
9
+ path.resolve(process.cwd(), '.gait');
10
+ return path.join(basePath, 'agents');
11
+ }
12
+ function generateFilename(name) {
13
+ // Convert name to filename-safe format
14
+ return name
15
+ .toLowerCase()
16
+ .replace(/[^a-z0-9\s-]/g, '') // Remove special characters
17
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
18
+ .replace(/--+/g, '-') // Replace multiple hyphens with single
19
+ .replace(/^-|-$/g, '') // Remove leading/trailing hyphens
20
+ + '.md';
21
+ }
22
+ /**
23
+ * GET /api/v1/agents/:id
24
+ * Load a specific agent document
25
+ */
26
+ app.get('/:id', async (c) => {
27
+ try {
28
+ const id = c.req.param('id');
29
+ const agentsPath = getAgentsPath();
30
+ const filename = id.endsWith('.md') ? id : `${id}.md`;
31
+ const filePath = path.join(agentsPath, filename);
32
+ const fileContent = await fs.readFile(filePath, 'utf-8');
33
+ const { data, content } = matter(fileContent);
34
+ // Extract title from name in frontmatter or use filename
35
+ const title = data.name ||
36
+ filename.replace('.md', '').replace(/[_-]/g, ' ').replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase());
37
+ const document = {
38
+ filename,
39
+ metadata: {
40
+ name: data.name || title,
41
+ description: data.description || '',
42
+ color: data.color,
43
+ tools: data.tools,
44
+ ...data
45
+ },
46
+ content,
47
+ title
48
+ };
49
+ return c.json({
50
+ success: true,
51
+ document
52
+ });
53
+ }
54
+ catch (error) {
55
+ if (error.code === 'ENOENT') {
56
+ return c.json({ success: false, error: 'Agent document not found' }, 404);
57
+ }
58
+ console.error('Error loading agent document:', error);
59
+ return c.json({ success: false, error: 'Failed to load agent document' }, 500);
60
+ }
61
+ });
62
+ /**
63
+ * PUT /api/v1/agents/:id
64
+ * Update a specific agent document
65
+ */
66
+ app.put('/:id', async (c) => {
67
+ try {
68
+ const id = c.req.param('id');
69
+ const body = await c.req.json();
70
+ const agentsPath = getAgentsPath();
71
+ const filename = id.endsWith('.md') ? id : `${id}.md`;
72
+ const filePath = path.join(agentsPath, filename);
73
+ // Check if file exists
74
+ try {
75
+ await fs.access(filePath);
76
+ }
77
+ catch {
78
+ return c.json({ success: false, error: 'Agent document not found' }, 404);
79
+ }
80
+ // Read current content
81
+ const currentContent = await fs.readFile(filePath, 'utf-8');
82
+ const { data: currentData, content: currentMarkdown } = matter(currentContent);
83
+ // Prepare updated content
84
+ const updatedContent = body.content !== undefined ? body.content : currentMarkdown;
85
+ const updatedMetadata = {
86
+ ...currentData,
87
+ ...body.metadata,
88
+ name: body.name !== undefined ? body.name : currentData.name,
89
+ description: body.description !== undefined ? body.description : currentData.description
90
+ };
91
+ // Handle name change - might need to rename file
92
+ let newFilename = filename;
93
+ let newFilePath = filePath;
94
+ if (body.name && body.name !== currentData.name) {
95
+ newFilename = generateFilename(body.name);
96
+ newFilePath = path.join(agentsPath, newFilename);
97
+ // Check if new filename conflicts with existing file (unless it's the same file)
98
+ if (newFilename !== filename) {
99
+ try {
100
+ await fs.access(newFilePath);
101
+ return c.json({ success: false, error: 'An agent with this name already exists' }, 409);
102
+ }
103
+ catch {
104
+ // File doesn't exist, which is what we want
105
+ }
106
+ }
107
+ }
108
+ // Create the updated markdown content with frontmatter
109
+ const fileContent = matter.stringify(updatedContent, updatedMetadata);
110
+ // Write to new location (or same location if filename unchanged)
111
+ await fs.writeFile(newFilePath, fileContent, 'utf-8');
112
+ // If filename changed, delete old file
113
+ if (newFilename !== filename) {
114
+ await fs.unlink(filePath);
115
+ }
116
+ // Extract updated title
117
+ const title = updatedMetadata.name ||
118
+ newFilename.replace('.md', '').replace(/[_-]/g, ' ').replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase());
119
+ return c.json({
120
+ success: true,
121
+ document: {
122
+ filename: newFilename,
123
+ title,
124
+ metadata: updatedMetadata,
125
+ content: updatedContent
126
+ }
127
+ });
128
+ }
129
+ catch (error) {
130
+ console.error('Error updating agent document:', error);
131
+ return c.json({ success: false, error: 'Failed to update agent document' }, 500);
132
+ }
133
+ });
134
+ /**
135
+ * DELETE /api/v1/agents/:id
136
+ * Delete a specific agent document
137
+ */
138
+ app.delete('/:id', async (c) => {
139
+ try {
140
+ const id = c.req.param('id');
141
+ const agentsPath = getAgentsPath();
142
+ const filename = id.endsWith('.md') ? id : `${id}.md`;
143
+ const filePath = path.join(agentsPath, filename);
144
+ // Check if file exists
145
+ try {
146
+ await fs.access(filePath);
147
+ }
148
+ catch {
149
+ return c.json({ success: false, error: 'Agent document not found' }, 404);
150
+ }
151
+ // Delete the file
152
+ await fs.unlink(filePath);
153
+ return c.json({
154
+ success: true,
155
+ message: 'Agent document deleted successfully'
156
+ });
157
+ }
158
+ catch (error) {
159
+ console.error('Error deleting agent document:', error);
160
+ return c.json({ success: false, error: 'Failed to delete agent document' }, 500);
161
+ }
162
+ });
163
+ export default app;
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;