agentstudio 0.1.0 → 0.1.2
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/.cc-sessions/ppt-editor/session_1756253549429_uau1hm6lh.json +665 -0
- package/.cc-sessions/ppt-editor/session_1756257240855_v0wa26mde.json +394 -0
- package/README.md +39 -41
- package/dist/bin/agentstudio.js +4 -27
- package/dist/bin/agentstudio.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -52
- package/dist/index.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +18 -19
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/commands.d.ts +4 -0
- package/dist/routes/commands.d.ts.map +1 -0
- package/dist/routes/commands.js +395 -0
- package/dist/routes/commands.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +528 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/sessions.d.ts +4 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +733 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/settings.d.ts +4 -0
- package/dist/routes/settings.d.ts.map +1 -0
- package/dist/routes/settings.js +658 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/routes/subagents.d.ts +4 -0
- package/dist/routes/subagents.d.ts.map +1 -0
- package/dist/routes/subagents.js +326 -0
- package/dist/routes/subagents.js.map +1 -0
- package/docs/chat-clean-1.svg +1 -0
- package/docs/chat-clean.md +60 -0
- package/docs/chat-comprehensive-1.svg +1 -0
- package/docs/chat-comprehensive.md +166 -0
- package/docs/chat_api_sequence_diagram.md +58 -0
- package/docs/command-detection-logic.md +306 -0
- package/docs/command-detection-sequence.md +186 -0
- package/frontend/dist/assets/AgentsPage-Dqb_aqAA.js +1 -0
- package/frontend/dist/assets/ChatPage-BvQmXfcP.css +1 -0
- package/frontend/dist/assets/ChatPage-L8Paywyc.js +91 -0
- package/frontend/dist/assets/CommandForm-DLl7EIMS.js +7 -0
- package/frontend/dist/assets/CommandsPage-Bzavq0Ec.js +1 -0
- package/frontend/dist/assets/DashboardPage-B3o4AYFT.js +15 -0
- package/frontend/dist/assets/FileBrowser-DL3ayaqb.js +1 -0
- package/frontend/dist/assets/GeneralSettingsPage-CBN_de-V.js +1 -0
- package/frontend/dist/assets/LandingPage-Dl4ioKos.js +1 -0
- package/frontend/dist/assets/LoginPage-4QqRdiSi.js +12 -0
- package/frontend/dist/assets/McpPage-CY3tYiqj.js +39 -0
- package/frontend/dist/assets/MemorySettingsPage-DGxrok5K.js +1 -0
- package/frontend/dist/assets/ProjectSelector-hgmGYVFh.js +1 -0
- package/frontend/dist/assets/ProjectsPage-D399IM0c.js +14 -0
- package/frontend/dist/assets/SettingsLayout-CL_K-lzJ.js +1 -0
- package/frontend/dist/assets/SubagentForm-DXtTTIKg.js +7 -0
- package/frontend/dist/assets/SubagentsPage-Chbhj8p2.js +1 -0
- package/frontend/dist/assets/ToastTestPage-DT4wuN5C.js +1 -0
- package/frontend/dist/assets/UnifiedToolSelector-CsM9qBvs.js +1 -0
- package/frontend/dist/assets/VersionSettingsPage-74Q-LVgA.js +5 -0
- package/frontend/dist/assets/agents-ClAzIJTw.js +1 -0
- package/frontend/dist/assets/agents-DwCY2K8p.css +1 -0
- package/frontend/dist/assets/authFetch-BATQyPG5.js +1 -0
- package/frontend/dist/assets/data-structures-DLJedtzx.js +27 -0
- package/frontend/dist/assets/dateFormat-CXa8VnEC.js +1 -0
- package/frontend/dist/assets/index-B9YHa7XT.css +1 -0
- package/frontend/dist/assets/index-B_CTNvca.js +268 -0
- package/frontend/dist/assets/monaco-editor-C7Z4sOhS.js +19 -0
- package/frontend/dist/assets/syntax-highlighting-YWvMU4Hm.js +24 -0
- package/frontend/dist/assets/tabManager-DV8urRBM.js +30 -0
- package/frontend/dist/assets/table-D6q1rytw.js +1 -0
- package/frontend/dist/assets/tools-C4EPanYi.js +1 -0
- package/frontend/dist/assets/ui-components-Cw21Epuw.js +481 -0
- package/frontend/dist/assets/useAgents-DwnOE1_k.js +2 -0
- package/frontend/dist/assets/useClaudeVersions-CQdGnCqv.js +1 -0
- package/frontend/dist/assets/useCommands-CCVaurbt.js +1 -0
- package/frontend/dist/cc-studio.png +0 -0
- package/frontend/dist/index.html +68 -84
- package/frontend/dist/vite.svg +1 -0
- package/package.json +26 -27
- package/scripts/README.md +76 -0
- package/scripts/fix-project-names.js +113 -0
- package/scripts/migrate-projects.js +159 -0
- package/shared/index.d.ts +6 -0
- package/shared/index.d.ts.map +1 -0
- package/shared/index.js +7 -0
- package/{dist/types/index.d.ts → shared/types/agents.d.ts} +1 -2
- package/shared/types/agents.d.ts.map +1 -0
- package/{dist/types/index.js → shared/types/agents.js} +3 -8
- package/shared/types/claude-history.d.ts +61 -0
- package/shared/types/claude-history.d.ts.map +1 -0
- package/shared/types/claude-history.js +2 -0
- package/shared/types/claude-versions.d.ts +40 -0
- package/shared/types/claude-versions.d.ts.map +1 -0
- package/shared/types/claude-versions.js +1 -0
- package/shared/types/commands.d.ts +48 -0
- package/shared/types/commands.d.ts.map +1 -0
- package/shared/types/commands.js +19 -0
- package/shared/types/projects.d.ts +35 -0
- package/shared/types/projects.d.ts.map +1 -0
- package/shared/types/projects.js +2 -0
- package/shared/types/subagents.d.ts +26 -0
- package/shared/types/subagents.d.ts.map +1 -0
- package/shared/types/subagents.js +1 -0
- package/shared/utils/agentStorage.d.ts +27 -0
- package/shared/utils/agentStorage.d.ts.map +1 -0
- package/shared/utils/agentStorage.js +392 -0
- package/shared/utils/claudeVersionStorage.d.ts +16 -0
- package/shared/utils/claudeVersionStorage.d.ts.map +1 -0
- package/shared/utils/claudeVersionStorage.js +230 -0
- package/shared/utils/projectMetadataStorage.d.ts +94 -0
- package/shared/utils/projectMetadataStorage.d.ts.map +1 -0
- package/shared/utils/projectMetadataStorage.js +422 -0
- package/shared/utils/toolMapping.d.ts +56 -0
- package/shared/utils/toolMapping.d.ts.map +1 -0
- package/shared/utils/toolMapping.js +71 -0
- package/src/bin/agentstudio.ts +90 -121
- package/src/index.ts +139 -57
- package/src/routes/agents.ts +28 -29
- package/src/routes/{commands.ts.bak → commands.ts} +1 -1
- package/src/routes/{projects.ts.bak → projects.ts} +3 -3
- package/src/routes/{sessions.ts.bak → sessions.ts} +2 -2
- package/src/routes/{settings.ts.bak → settings.ts} +11 -11
- package/src/routes/{subagents.ts.bak → subagents.ts} +1 -1
- package/tsconfig.json +13 -12
- package/dist/types/claude-history.d.ts +0 -48
- package/dist/types/claude-history.d.ts.map +0 -1
- package/dist/types/claude-history.js +0 -2
- package/dist/types/claude-history.js.map +0 -1
- package/dist/types/claude-versions.d.ts +0 -31
- package/dist/types/claude-versions.d.ts.map +0 -1
- package/dist/types/claude-versions.js +0 -2
- package/dist/types/claude-versions.js.map +0 -1
- package/dist/types/commands.d.ts +0 -32
- package/dist/types/commands.d.ts.map +0 -1
- package/dist/types/commands.js +0 -2
- package/dist/types/commands.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/types/subagents.d.ts +0 -88
- package/dist/types/subagents.d.ts.map +0 -1
- package/dist/types/subagents.js +0 -2
- package/dist/types/subagents.js.map +0 -1
- package/dist/utils/agentStorage.d.ts +0 -19
- package/dist/utils/agentStorage.d.ts.map +0 -1
- package/dist/utils/agentStorage.js +0 -110
- package/dist/utils/agentStorage.js.map +0 -1
- package/dist/utils/claudeVersionStorage.d.ts +0 -33
- package/dist/utils/claudeVersionStorage.d.ts.map +0 -1
- package/dist/utils/claudeVersionStorage.js +0 -168
- package/dist/utils/claudeVersionStorage.js.map +0 -1
- package/dist/utils/projectMetadataStorage.d.ts +0 -21
- package/dist/utils/projectMetadataStorage.d.ts.map +0 -1
- package/dist/utils/projectMetadataStorage.js +0 -68
- package/dist/utils/projectMetadataStorage.js.map +0 -1
- package/src/types/claude-history.ts +0 -50
- package/src/types/claude-versions.ts +0 -33
- package/src/types/commands.ts +0 -35
- package/src/types/index.ts +0 -248
- package/src/types/subagents.ts +0 -106
- package/src/utils/agentStorage.ts +0 -126
- package/src/utils/claudeVersionStorage.ts +0 -199
- package/src/utils/projectMetadataStorage.ts +0 -86
package/src/bin/agentstudio.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
2
|
import { program } from 'commander';
|
|
4
3
|
import { startServer } from '../index.js';
|
|
5
|
-
import { spawn } from 'child_process';
|
|
6
4
|
import path from 'path';
|
|
7
5
|
import { fileURLToPath } from 'url';
|
|
8
6
|
|
|
@@ -10,127 +8,98 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
10
8
|
const __dirname = path.dirname(__filename);
|
|
11
9
|
|
|
12
10
|
program
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
.name('agentstudio')
|
|
12
|
+
.description('AgentStudio - AI-powered presentation editor with Claude integration')
|
|
13
|
+
.version('0.1.0');
|
|
16
14
|
|
|
17
15
|
// Start both frontend and backend
|
|
18
16
|
program
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
17
|
+
.command('start')
|
|
18
|
+
.description('Start both frontend and backend servers')
|
|
19
|
+
.option('-p, --port <port>', 'backend server port', '4936')
|
|
20
|
+
.option('-f, --frontend-port <port>', 'frontend server port', '3000')
|
|
21
|
+
.option('-h, --host <host>', 'server host', 'localhost')
|
|
22
|
+
.option('-c, --config <path>', 'path to config file')
|
|
23
|
+
.option('--env <path>', 'path to .env file')
|
|
24
|
+
.option('--no-auth', 'disable authentication (development only)')
|
|
25
|
+
.action(async (options: any) => {
|
|
26
|
+
console.log('🚀 Starting AgentStudio...');
|
|
27
|
+
|
|
28
|
+
// Start backend
|
|
29
|
+
process.env.PORT = options.port;
|
|
30
|
+
process.env.HOST = options.host;
|
|
31
|
+
|
|
32
|
+
if (options.env) {
|
|
33
|
+
process.env.ENV_PATH = options.env;
|
|
34
|
+
}
|
|
35
|
+
if (options.config) {
|
|
36
|
+
process.env.CONFIG_PATH = options.config;
|
|
37
|
+
}
|
|
38
|
+
if (options.noAuth) {
|
|
39
|
+
process.env.NO_AUTH = 'true';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// Start backend server
|
|
44
|
+
await startServer();
|
|
45
|
+
console.log(`✅ Backend running on http://${options.host}:${options.port}`);
|
|
46
|
+
|
|
47
|
+
// Serve frontend static files
|
|
48
|
+
console.log(`✅ Frontend available at http://${options.host}:${options.port}`);
|
|
49
|
+
console.log('📖 Open your browser to start using AgentStudio');
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('❌ Failed to start AgentStudio:', error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
56
55
|
|
|
57
56
|
// Start backend only
|
|
58
57
|
program
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Start frontend only (development mode)
|
|
94
|
-
program
|
|
95
|
-
.command('frontend')
|
|
96
|
-
.description('Start frontend development server only')
|
|
97
|
-
.option('-p, --port <port>', 'frontend server port', '3000')
|
|
98
|
-
.option('-h, --host <host>', 'server host', 'localhost')
|
|
99
|
-
.action((options) => {
|
|
100
|
-
console.log('🚀 Starting AgentStudio Frontend...');
|
|
101
|
-
|
|
102
|
-
const frontendDir = path.join(__dirname, '../../frontend');
|
|
103
|
-
|
|
104
|
-
const frontendProcess = spawn('npm', ['run', 'dev'], {
|
|
105
|
-
cwd: frontendDir,
|
|
106
|
-
stdio: 'inherit',
|
|
107
|
-
shell: true,
|
|
108
|
-
env: {
|
|
109
|
-
...process.env,
|
|
110
|
-
PORT: options.port,
|
|
111
|
-
HOST: options.host
|
|
112
|
-
}
|
|
58
|
+
.command('backend')
|
|
59
|
+
.description('Start backend server only')
|
|
60
|
+
.option('-p, --port <port>', 'server port', '4936')
|
|
61
|
+
.option('-h, --host <host>', 'server host', 'localhost')
|
|
62
|
+
.option('-c, --config <path>', 'path to config file')
|
|
63
|
+
.option('--env <path>', 'path to .env file')
|
|
64
|
+
.option('--no-auth', 'disable authentication (development only)')
|
|
65
|
+
.action(async (options: any) => {
|
|
66
|
+
console.log('🚀 Starting AgentStudio Backend...');
|
|
67
|
+
|
|
68
|
+
process.env.PORT = options.port;
|
|
69
|
+
process.env.HOST = options.host;
|
|
70
|
+
|
|
71
|
+
if (options.env) {
|
|
72
|
+
process.env.ENV_PATH = options.env;
|
|
73
|
+
}
|
|
74
|
+
if (options.config) {
|
|
75
|
+
process.env.CONFIG_PATH = options.config;
|
|
76
|
+
}
|
|
77
|
+
if (options.noAuth) {
|
|
78
|
+
process.env.NO_AUTH = 'true';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
await startServer();
|
|
83
|
+
console.log(`✅ Backend running on http://${options.host}:${options.port}`);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('❌ Failed to start backend:', error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
113
88
|
});
|
|
114
89
|
|
|
115
|
-
frontendProcess.on('error', (error) => {
|
|
116
|
-
console.error('❌ Failed to start frontend:', error);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
90
|
// Initialize configuration
|
|
122
91
|
program
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
92
|
+
.command('init')
|
|
93
|
+
.description('Initialize AgentStudio configuration')
|
|
94
|
+
.option('--env <path>', 'path to create .env file', '.env')
|
|
95
|
+
.action(async (options: any) => {
|
|
96
|
+
console.log('🔧 Initializing AgentStudio configuration...');
|
|
128
97
|
|
|
129
|
-
|
|
130
|
-
|
|
98
|
+
const fs = await import('fs-extra');
|
|
99
|
+
const path = await import('path');
|
|
131
100
|
|
|
132
|
-
|
|
133
|
-
|
|
101
|
+
const envPath = path.default.resolve(options.env);
|
|
102
|
+
const envContent = `# AgentStudio Configuration
|
|
134
103
|
# AI Provider (choose one)
|
|
135
104
|
OPENAI_API_KEY=your_openai_api_key_here
|
|
136
105
|
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
|
@@ -147,15 +116,15 @@ SLIDES_DIR=./slides
|
|
|
147
116
|
CORS_ORIGINS=https://your-frontend.vercel.app,https://custom-domain.com
|
|
148
117
|
`;
|
|
149
118
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
119
|
+
try {
|
|
120
|
+
await fs.default.ensureFile(envPath);
|
|
121
|
+
await fs.default.writeFile(envPath, envContent);
|
|
122
|
+
console.log(`✅ Configuration file created: ${envPath}`);
|
|
123
|
+
console.log('📝 Please edit the .env file with your API keys and settings');
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('❌ Failed to create configuration file:', error);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
160
129
|
|
|
161
130
|
program.parse();
|
package/src/index.ts
CHANGED
|
@@ -2,99 +2,181 @@ import express from 'express';
|
|
|
2
2
|
import cors from 'cors';
|
|
3
3
|
import helmet from 'helmet';
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
|
-
import path from 'path';
|
|
6
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
7
|
|
|
8
|
-
// Import routes
|
|
9
|
-
import agentsRouter from './routes/agents.js';
|
|
10
|
-
import authRouter from './routes/auth.js';
|
|
11
8
|
import filesRouter from './routes/files.js';
|
|
9
|
+
import agentsRouter from './routes/agents.js';
|
|
12
10
|
import mcpRouter from './routes/mcp.js';
|
|
11
|
+
import sessionsRouter from './routes/sessions.js';
|
|
13
12
|
import mediaRouter from './routes/media.js';
|
|
14
|
-
import
|
|
13
|
+
import settingsRouter from './routes/settings.js';
|
|
14
|
+
import commandsRouter from './routes/commands.js';
|
|
15
|
+
import subagentsRouter from './routes/subagents.js';
|
|
16
|
+
import projectsRouter from './routes/projects.js';
|
|
17
|
+
import authRouter from './routes/auth.js';
|
|
18
|
+
import { authMiddleware } from './middleware/auth.js';
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
const __dirname = path.dirname(__filename);
|
|
20
|
+
dotenv.config();
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
dotenv.config({ path: envPath });
|
|
22
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
23
|
+
const __dirname = dirname(__filename);
|
|
22
24
|
|
|
23
25
|
const app = express();
|
|
24
26
|
const PORT = process.env.PORT || 4936;
|
|
25
|
-
const HOST = process.env.HOST || 'localhost';
|
|
26
27
|
|
|
27
|
-
//
|
|
28
|
+
// Middleware
|
|
28
29
|
app.use(helmet({
|
|
29
|
-
crossOriginEmbedderPolicy: false,
|
|
30
30
|
contentSecurityPolicy: {
|
|
31
31
|
directives: {
|
|
32
32
|
defaultSrc: ["'self'"],
|
|
33
33
|
scriptSrc: ["'self'", "'unsafe-inline'"],
|
|
34
|
-
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
35
|
-
|
|
34
|
+
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com", "https://cdn.jsdelivr.net"],
|
|
35
|
+
fontSrc: ["'self'", "https://fonts.gstatic.com", "https://cdn.jsdelivr.net"],
|
|
36
|
+
imgSrc: ["'self'", "data:", "https:"],
|
|
36
37
|
connectSrc: ["'self'", "ws:", "wss:"],
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
frameAncestors: ["'self'", "http://localhost:3000", "https://localhost:3000", "http://localhost:3001"] // Allow iframe embedding
|
|
39
|
+
}
|
|
40
|
+
}
|
|
39
41
|
}));
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'http://localhost:
|
|
46
|
-
'
|
|
47
|
-
'https
|
|
42
|
+
// Configure CORS origins
|
|
43
|
+
const getAllowedOrigins = () => {
|
|
44
|
+
const defaultOrigins = [
|
|
45
|
+
'http://localhost:3000',
|
|
46
|
+
'http://127.0.0.1:3000',
|
|
47
|
+
'http://localhost:3001',
|
|
48
|
+
'https://localhost:3000',
|
|
49
|
+
'https://localhost:3001'
|
|
48
50
|
];
|
|
51
|
+
|
|
52
|
+
// Add custom origins from environment variable
|
|
53
|
+
const customOrigins = process.env.CORS_ORIGINS ?
|
|
54
|
+
process.env.CORS_ORIGINS.split(',').map(origin => origin.trim()) : [];
|
|
55
|
+
|
|
56
|
+
return [...defaultOrigins, ...customOrigins];
|
|
57
|
+
};
|
|
49
58
|
|
|
50
59
|
app.use(cors({
|
|
51
|
-
origin:
|
|
52
|
-
|
|
60
|
+
origin: (origin, callback) => {
|
|
61
|
+
const allowedOrigins = getAllowedOrigins();
|
|
62
|
+
|
|
63
|
+
// Allow requests with no origin (like mobile apps or curl requests)
|
|
64
|
+
if (!origin) return callback(null, true);
|
|
65
|
+
|
|
66
|
+
// Check if the origin is allowed
|
|
67
|
+
if (allowedOrigins.includes(origin)) {
|
|
68
|
+
return callback(null, true);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Allow Vercel preview URLs (*.vercel.app)
|
|
72
|
+
if (origin.endsWith('.vercel.app')) {
|
|
73
|
+
return callback(null, true);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Allow agentstudio.cc and its subdomains (*.agentstudio.cc) - hardcoded
|
|
77
|
+
if (origin === 'https://agentstudio.cc' || origin.endsWith('.agentstudio.cc')) {
|
|
78
|
+
return callback(null, true);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Allow custom domains from environment variable (CORS_ALLOWED_DOMAINS)
|
|
82
|
+
const customDomains = process.env.CORS_ALLOWED_DOMAINS ?
|
|
83
|
+
process.env.CORS_ALLOWED_DOMAINS.split(',').map(domain => domain.trim()) : [];
|
|
84
|
+
|
|
85
|
+
for (const domain of customDomains) {
|
|
86
|
+
// Match exact domain (https://example.com)
|
|
87
|
+
if (origin === `https://${domain}` || origin === `http://${domain}`) {
|
|
88
|
+
return callback(null, true);
|
|
89
|
+
}
|
|
90
|
+
// Match subdomains (https://*.example.com)
|
|
91
|
+
if (origin.endsWith(`.${domain}`)) {
|
|
92
|
+
return callback(null, true);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Allow any localhost with any port for development
|
|
97
|
+
if (origin.match(/^https?:\/\/localhost(:\d+)?$/)) {
|
|
98
|
+
return callback(null, true);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Allow 127.0.0.1 with any port for development
|
|
102
|
+
if (origin.match(/^https?:\/\/127\.0\.0\.1(:\d+)?$/)) {
|
|
103
|
+
return callback(null, true);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const msg = `The CORS policy for this site does not allow access from the specified Origin: ${origin}`;
|
|
107
|
+
return callback(new Error(msg), false);
|
|
108
|
+
},
|
|
109
|
+
credentials: true,
|
|
110
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
|
|
111
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'Cache-Control', 'X-Requested-With'],
|
|
112
|
+
exposedHeaders: ['Content-Range', 'X-Content-Range']
|
|
53
113
|
}));
|
|
114
|
+
app.use(express.json({ limit: '10mb' }));
|
|
115
|
+
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
54
116
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
app.use(express.
|
|
117
|
+
// Static files - serve slides directory
|
|
118
|
+
const slidesDir = join(__dirname, '../..', process.env.SLIDES_DIR || 'slides');
|
|
119
|
+
app.use('/slides', express.static(slidesDir));
|
|
58
120
|
|
|
59
|
-
// Serve static files
|
|
60
|
-
const
|
|
61
|
-
|
|
121
|
+
// Serve frontend static files in production
|
|
122
|
+
const frontendDir = join(__dirname, '../frontend/dist');
|
|
123
|
+
if (process.env.NODE_ENV === 'production') {
|
|
124
|
+
app.use(express.static(frontendDir));
|
|
125
|
+
|
|
126
|
+
// Handle SPA routing - serve index.html for all other routes
|
|
127
|
+
app.get('*', (req, res) => {
|
|
128
|
+
res.sendFile(join(frontendDir, 'index.html'));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
62
131
|
|
|
63
|
-
//
|
|
64
|
-
app.use('/api/agents', agentsRouter);
|
|
132
|
+
// Routes - Public routes
|
|
65
133
|
app.use('/api/auth', authRouter);
|
|
66
|
-
app.use('/api/files', filesRouter);
|
|
67
|
-
app.use('/api/mcp', mcpRouter);
|
|
68
|
-
app.use('/api/media', mediaRouter);
|
|
69
|
-
app.use('/api/slides', slidesRouter);
|
|
70
134
|
|
|
71
|
-
//
|
|
135
|
+
// Protected routes - Require authentication
|
|
136
|
+
app.use('/api/files', authMiddleware, filesRouter);
|
|
137
|
+
app.use('/api/agents', authMiddleware, agentsRouter);
|
|
138
|
+
app.use('/api/mcp', authMiddleware, mcpRouter);
|
|
139
|
+
app.use('/api/sessions', authMiddleware, sessionsRouter);
|
|
140
|
+
app.use('/api/settings', authMiddleware, settingsRouter);
|
|
141
|
+
app.use('/api/commands', authMiddleware, commandsRouter);
|
|
142
|
+
app.use('/api/subagents', authMiddleware, subagentsRouter);
|
|
143
|
+
app.use('/api/projects', authMiddleware, projectsRouter);
|
|
144
|
+
app.use('/media', authMiddleware, mediaRouter);
|
|
145
|
+
|
|
146
|
+
// Health check
|
|
72
147
|
app.get('/api/health', (req, res) => {
|
|
73
|
-
res.json({
|
|
74
|
-
status: 'ok',
|
|
75
|
-
timestamp: new Date().toISOString(),
|
|
76
|
-
version: '0.1.0'
|
|
77
|
-
});
|
|
148
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
78
149
|
});
|
|
79
150
|
|
|
80
|
-
//
|
|
81
|
-
app.
|
|
82
|
-
|
|
151
|
+
// Error handling
|
|
152
|
+
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
153
|
+
console.error('Error:', err);
|
|
154
|
+
res.status(500).json({
|
|
155
|
+
error: 'Internal server error',
|
|
156
|
+
message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong'
|
|
157
|
+
});
|
|
83
158
|
});
|
|
84
159
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
160
|
+
// 404 handler - only for API routes in production
|
|
161
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
162
|
+
app.use('*', (req, res) => {
|
|
163
|
+
res.status(404).json({ error: 'Route not found' });
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function startServer() {
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
const server = app.listen(PORT, () => {
|
|
170
|
+
console.log(`AI PPT Editor backend running on http://localhost:${PORT}`);
|
|
171
|
+
console.log(`Serving slides from: ${slidesDir}`);
|
|
172
|
+
resolve(server);
|
|
93
173
|
});
|
|
174
|
+
|
|
175
|
+
server.on('error', reject);
|
|
94
176
|
});
|
|
95
177
|
}
|
|
96
178
|
|
|
97
|
-
//
|
|
179
|
+
// Start server if this file is run directly
|
|
98
180
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
99
181
|
startServer().catch(console.error);
|
|
100
182
|
}
|
package/src/routes/agents.ts
CHANGED
|
@@ -7,11 +7,11 @@ import { spawn } from 'child_process';
|
|
|
7
7
|
import { exec } from 'child_process';
|
|
8
8
|
import { promisify } from 'util';
|
|
9
9
|
import { query, Options } from '@anthropic-ai/claude-code';
|
|
10
|
-
import { AgentStorage } from '
|
|
11
|
-
import { AgentConfig
|
|
12
|
-
import { ProjectMetadataStorage } from '
|
|
10
|
+
import { AgentStorage } from '@agentstudio/shared/utils/agentStorage';
|
|
11
|
+
import { AgentConfig } from '@agentstudio/shared/types/agents';
|
|
12
|
+
import { ProjectMetadataStorage } from '@agentstudio/shared/utils/projectMetadataStorage';
|
|
13
13
|
import { sessionManager } from '../services/sessionManager.js';
|
|
14
|
-
import { getAllVersions, getDefaultVersionId } from '
|
|
14
|
+
import { getAllVersions, getDefaultVersionId } from '@agentstudio/shared/utils/claudeVersionStorage';
|
|
15
15
|
|
|
16
16
|
const router: express.Router = express.Router();
|
|
17
17
|
const execAsync = promisify(exec);
|
|
@@ -31,6 +31,7 @@ const CreateAgentSchema = z.object({
|
|
|
31
31
|
systemPrompt: z.string().min(1),
|
|
32
32
|
maxTurns: z.number().min(1).max(100).optional().default(25),
|
|
33
33
|
permissionMode: z.enum(['default', 'acceptEdits', 'bypassPermissions', 'plan']).optional().default('acceptEdits'),
|
|
34
|
+
model: z.string().min(1).optional().default('claude-3-5-sonnet-20241022'),
|
|
34
35
|
allowedTools: z.array(z.object({
|
|
35
36
|
name: z.string(),
|
|
36
37
|
enabled: z.boolean(),
|
|
@@ -126,22 +127,22 @@ router.post('/sessions/:sessionId/interrupt', async (req, res) => {
|
|
|
126
127
|
});
|
|
127
128
|
|
|
128
129
|
// Get all agents
|
|
129
|
-
router.get('/',
|
|
130
|
+
router.get('/', (req, res) => {
|
|
130
131
|
try {
|
|
131
132
|
const { enabled, type } = req.query;
|
|
132
|
-
let agents =
|
|
133
|
-
|
|
133
|
+
let agents = globalAgentStorage.getAllAgents();
|
|
134
|
+
|
|
134
135
|
// Filter by enabled status
|
|
135
136
|
if (enabled !== undefined) {
|
|
136
137
|
const isEnabled = enabled === 'true';
|
|
137
138
|
agents = agents.filter(agent => agent.enabled === isEnabled);
|
|
138
139
|
}
|
|
139
|
-
|
|
140
|
+
|
|
140
141
|
// Filter by component type
|
|
141
142
|
if (type && typeof type === 'string') {
|
|
142
143
|
agents = agents.filter(agent => agent.ui.componentType === type);
|
|
143
144
|
}
|
|
144
|
-
|
|
145
|
+
|
|
145
146
|
res.json({ agents });
|
|
146
147
|
} catch (error) {
|
|
147
148
|
console.error('Failed to get agents:', error);
|
|
@@ -153,15 +154,15 @@ router.get('/', async (req, res) => {
|
|
|
153
154
|
|
|
154
155
|
|
|
155
156
|
// Get specific agent
|
|
156
|
-
router.get('/:agentId',
|
|
157
|
+
router.get('/:agentId', (req, res) => {
|
|
157
158
|
try {
|
|
158
159
|
const { agentId } = req.params;
|
|
159
|
-
const agent =
|
|
160
|
-
|
|
160
|
+
const agent = globalAgentStorage.getAgent(agentId);
|
|
161
|
+
|
|
161
162
|
if (!agent) {
|
|
162
163
|
return res.status(404).json({ error: 'Agent not found' });
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
+
|
|
165
166
|
res.json({ agent });
|
|
166
167
|
} catch (error) {
|
|
167
168
|
console.error('Failed to get agent:', error);
|
|
@@ -170,7 +171,7 @@ router.get('/:agentId', async (req, res) => {
|
|
|
170
171
|
});
|
|
171
172
|
|
|
172
173
|
// Create new agent
|
|
173
|
-
router.post('/',
|
|
174
|
+
router.post('/', (req, res) => {
|
|
174
175
|
try {
|
|
175
176
|
const validation = CreateAgentSchema.safeParse(req.body);
|
|
176
177
|
if (!validation.success) {
|
|
@@ -178,16 +179,15 @@ router.post('/', async (req, res) => {
|
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
const agentData = validation.data;
|
|
181
|
-
|
|
182
|
+
|
|
182
183
|
// Check if agent ID already exists
|
|
183
|
-
const existingAgent =
|
|
184
|
+
const existingAgent = globalAgentStorage.getAgent(agentData.id);
|
|
184
185
|
if (existingAgent) {
|
|
185
186
|
return res.status(409).json({ error: 'Agent with this ID already exists' });
|
|
186
187
|
}
|
|
187
188
|
|
|
188
|
-
const agent =
|
|
189
|
+
const agent = globalAgentStorage.createAgent({
|
|
189
190
|
version: '1.0.0',
|
|
190
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
191
191
|
...agentData
|
|
192
192
|
} as Omit<AgentConfig, 'createdAt' | 'updatedAt'>);
|
|
193
193
|
|
|
@@ -199,16 +199,16 @@ router.post('/', async (req, res) => {
|
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
// Update agent
|
|
202
|
-
router.put('/:agentId',
|
|
202
|
+
router.put('/:agentId', (req, res) => {
|
|
203
203
|
try {
|
|
204
204
|
const { agentId } = req.params;
|
|
205
205
|
const validation = UpdateAgentSchema.safeParse(req.body);
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
if (!validation.success) {
|
|
208
208
|
return res.status(400).json({ error: 'Invalid agent data', details: validation.error });
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
const existingAgent =
|
|
211
|
+
const existingAgent = globalAgentStorage.getAgent(agentId);
|
|
212
212
|
if (!existingAgent) {
|
|
213
213
|
return res.status(404).json({ error: 'Agent not found' });
|
|
214
214
|
}
|
|
@@ -220,7 +220,7 @@ router.put('/:agentId', async (req, res) => {
|
|
|
220
220
|
updatedAt: new Date().toISOString()
|
|
221
221
|
};
|
|
222
222
|
|
|
223
|
-
|
|
223
|
+
globalAgentStorage.saveAgent(updatedAgent);
|
|
224
224
|
res.json({ agent: updatedAgent, message: 'Agent updated successfully' });
|
|
225
225
|
} catch (error) {
|
|
226
226
|
console.error('Failed to update agent:', error);
|
|
@@ -229,16 +229,15 @@ router.put('/:agentId', async (req, res) => {
|
|
|
229
229
|
});
|
|
230
230
|
|
|
231
231
|
// Delete agent
|
|
232
|
-
router.delete('/:agentId',
|
|
232
|
+
router.delete('/:agentId', (req, res) => {
|
|
233
233
|
try {
|
|
234
234
|
const { agentId } = req.params;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (!
|
|
235
|
+
const deleted = globalAgentStorage.deleteAgent(agentId);
|
|
236
|
+
|
|
237
|
+
if (!deleted) {
|
|
238
238
|
return res.status(404).json({ error: 'Agent not found' });
|
|
239
239
|
}
|
|
240
|
-
|
|
241
|
-
await globalAgentStorage.deleteAgent(agentId);
|
|
240
|
+
|
|
242
241
|
res.json({ success: true, message: 'Agent deleted successfully' });
|
|
243
242
|
} catch (error) {
|
|
244
243
|
console.error('Failed to delete agent:', error);
|
|
@@ -681,7 +680,7 @@ router.post('/chat', async (req, res) => {
|
|
|
681
680
|
const { message, images, agentId, sessionId, projectPath, mcpTools, permissionMode, model, claudeVersion } = validation.data;
|
|
682
681
|
|
|
683
682
|
// 获取 agent 配置
|
|
684
|
-
const agent =
|
|
683
|
+
const agent = globalAgentStorage.getAgent(agentId);
|
|
685
684
|
if (!agent) {
|
|
686
685
|
return res.status(404).json({ error: 'Agent not found' });
|
|
687
686
|
}
|
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { promisify } from 'util';
|
|
5
5
|
import matter from 'gray-matter';
|
|
6
|
-
import { SlashCommand, SlashCommandCreate, SlashCommandUpdate, SlashCommandFilter } from '
|
|
6
|
+
import { SlashCommand, SlashCommandCreate, SlashCommandUpdate, SlashCommandFilter } from '@agentstudio/shared/types/commands';
|
|
7
7
|
|
|
8
8
|
const router: Router = express.Router();
|
|
9
9
|
const readdir = promisify(fs.readdir);
|