agentstudio 0.1.4 → 0.1.6

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 (37) hide show
  1. package/dist/bin/agentstudio.js +1 -1
  2. package/dist/bin/agentstudio.js.map +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +4 -3
  6. package/dist/index.js.map +1 -1
  7. package/package.json +2 -3
  8. package/.cc-sessions/ppt-editor/session_1756253549429_uau1hm6lh.json +0 -665
  9. package/.cc-sessions/ppt-editor/session_1756257240855_v0wa26mde.json +0 -394
  10. package/docs/chat-clean-1.svg +0 -1
  11. package/docs/chat-clean.md +0 -60
  12. package/docs/chat-comprehensive-1.svg +0 -1
  13. package/docs/chat-comprehensive.md +0 -166
  14. package/docs/chat_api_sequence_diagram.md +0 -58
  15. package/docs/command-detection-logic.md +0 -306
  16. package/docs/command-detection-sequence.md +0 -186
  17. package/scripts/README.md +0 -76
  18. package/scripts/fix-project-names.js +0 -113
  19. package/scripts/migrate-projects.js +0 -159
  20. package/src/bin/agentstudio.ts +0 -130
  21. package/src/index.ts +0 -182
  22. package/src/middleware/auth.ts +0 -26
  23. package/src/routes/agents.ts +0 -884
  24. package/src/routes/auth.ts +0 -73
  25. package/src/routes/commands.ts +0 -441
  26. package/src/routes/files.ts +0 -352
  27. package/src/routes/mcp.ts +0 -751
  28. package/src/routes/media.ts +0 -140
  29. package/src/routes/projects.ts +0 -601
  30. package/src/routes/sessions.ts +0 -809
  31. package/src/routes/settings.ts +0 -718
  32. package/src/routes/slides.ts +0 -170
  33. package/src/routes/subagents.ts +0 -364
  34. package/src/services/claudeSession.ts +0 -293
  35. package/src/services/messageQueue.ts +0 -71
  36. package/src/services/sessionManager.ts +0 -532
  37. package/src/utils/jwt.ts +0 -36
@@ -1,159 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * 项目迁移工具 - 扫描现有项目并添加到代理配置
5
- * 这是一个一次性的开发工具,用于迁移历史项目
6
- *
7
- * 使用方法:
8
- * node scripts/migrate-projects.js
9
- * npm run migrate-projects
10
- */
11
-
12
- import fs from 'fs';
13
- import path from 'path';
14
- import os from 'os';
15
- import { fileURLToPath } from 'url';
16
-
17
- const __filename = fileURLToPath(import.meta.url);
18
- const __dirname = path.dirname(__filename);
19
-
20
- // 简化的 AgentStorage 类,避免复杂的依赖
21
- class SimpleAgentStorage {
22
- constructor() {
23
- this.agentsDir = path.join(os.homedir(), '.claude-agent', 'agents');
24
- this.ensureDirectoriesExist();
25
- }
26
-
27
- ensureDirectoriesExist() {
28
- if (!fs.existsSync(this.agentsDir)) {
29
- fs.mkdirSync(this.agentsDir, { recursive: true });
30
- }
31
- }
32
-
33
- getAllAgents() {
34
- const agentFiles = fs.readdirSync(this.agentsDir)
35
- .filter(file => file.endsWith('.json'));
36
-
37
- const agents = [];
38
- for (const file of agentFiles) {
39
- try {
40
- const filePath = path.join(this.agentsDir, file);
41
- const agentData = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
42
- agents.push(agentData);
43
- } catch (error) {
44
- console.error(`Failed to read agent file ${file}:`, error);
45
- }
46
- }
47
-
48
- return agents;
49
- }
50
-
51
- saveAgent(agent) {
52
- try {
53
- agent.updatedAt = new Date().toISOString();
54
- const filePath = path.join(this.agentsDir, `${agent.id}.json`);
55
- fs.writeFileSync(filePath, JSON.stringify(agent, null, 2), 'utf-8');
56
- } catch (error) {
57
- console.error(`Failed to save agent ${agent.id}:`, error);
58
- throw error;
59
- }
60
- }
61
- }
62
-
63
- // 扫描现有项目并添加到代理配置
64
- function migrateExistingProjects() {
65
- console.log('🔍 开始扫描现有项目...');
66
-
67
- const agentStorage = new SimpleAgentStorage();
68
- const agents = agentStorage.getAllAgents();
69
- const projectsDir = path.join(os.homedir(), 'claude-code-projects');
70
-
71
- if (!fs.existsSync(projectsDir)) {
72
- console.log(`📁 项目目录不存在: ${projectsDir}`);
73
- return;
74
- }
75
-
76
- const projectDirs = fs.readdirSync(projectsDir).filter(item => {
77
- const itemPath = path.join(projectsDir, item);
78
- return fs.statSync(itemPath).isDirectory() && !item.startsWith('.');
79
- });
80
-
81
- console.log(`📁 找到 ${projectDirs.length} 个项目目录`);
82
-
83
- let totalAdded = 0;
84
-
85
- for (const projectDir of projectDirs) {
86
- const projectPath = path.join(projectsDir, projectDir);
87
- const sessionsDir = path.join(projectPath, '.cc-sessions');
88
-
89
- console.log(`\n📂 检查项目: ${projectDir}`);
90
-
91
- if (!fs.existsSync(sessionsDir)) {
92
- console.log(` ⚠️ 未找到会话目录,跳过`);
93
- continue;
94
- }
95
-
96
- // 检查哪些代理在此项目中有会话
97
- const agentDirs = fs.readdirSync(sessionsDir).filter(item => {
98
- const itemPath = path.join(sessionsDir, item);
99
- return fs.statSync(itemPath).isDirectory() && !item.startsWith('.');
100
- });
101
-
102
- console.log(` 👤 找到代理会话: ${agentDirs.join(', ') || '无'}`);
103
-
104
- for (const agentId of agentDirs) {
105
- const agent = agents.find(a => a.id === agentId);
106
- if (!agent) {
107
- console.log(` ❌ 代理 ${agentId} 不存在,跳过`);
108
- continue;
109
- }
110
-
111
- // 初始化 projects 数组
112
- if (!agent.projects) {
113
- agent.projects = [];
114
- }
115
-
116
- // 添加项目路径(如果不存在)
117
- const normalizedPath = path.resolve(projectPath);
118
- if (!agent.projects.includes(normalizedPath)) {
119
- agent.projects.push(normalizedPath);
120
- agent.updatedAt = new Date().toISOString();
121
- console.log(` ✅ 添加项目到代理 ${agentId}: ${normalizedPath}`);
122
- totalAdded++;
123
- } else {
124
- console.log(` ℹ️ 项目已存在于代理 ${agentId} 中`);
125
- }
126
- }
127
- }
128
-
129
- // 保存所有更新的代理
130
- console.log('\n💾 保存代理配置...');
131
- for (const agent of agents) {
132
- if (agent.projects && agent.projects.length > 0) {
133
- agentStorage.saveAgent(agent);
134
- console.log(` ✅ 已保存代理: ${agent.name} (${agent.projects.length} 个项目)`);
135
- }
136
- }
137
-
138
- console.log(`\n🎉 迁移完成!总共添加了 ${totalAdded} 个项目`);
139
- }
140
-
141
- // 主函数
142
- function main() {
143
- console.log('🚀 AI Editor 项目迁移工具');
144
- console.log('=====================================');
145
-
146
- try {
147
- migrateExistingProjects();
148
- } catch (error) {
149
- console.error('\n❌ 迁移失败:', error);
150
- process.exit(1);
151
- }
152
- }
153
-
154
- // 运行
155
- if (import.meta.url === `file://${process.argv[1]}`) {
156
- main();
157
- }
158
-
159
- export { migrateExistingProjects };
@@ -1,130 +0,0 @@
1
- #!/usr/bin/env node
2
- import { program } from 'commander';
3
- import { startServer } from '../index.js';
4
- import path from 'path';
5
- import { fileURLToPath } from 'url';
6
-
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
-
10
- program
11
- .name('agentstudio')
12
- .description('AgentStudio - AI-powered presentation editor with Claude integration')
13
- .version('0.1.0');
14
-
15
- // Start both frontend and backend
16
- program
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
- });
55
-
56
- // Start backend only
57
- program
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
- }
88
- });
89
-
90
- // Initialize configuration
91
- program
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...');
97
-
98
- const fs = await import('fs-extra');
99
- const path = await import('path');
100
-
101
- const envPath = path.default.resolve(options.env);
102
- const envContent = `# AgentStudio Configuration
103
- # AI Provider (choose one)
104
- OPENAI_API_KEY=your_openai_api_key_here
105
- ANTHROPIC_API_KEY=your_anthropic_api_key_here
106
-
107
- # Server Configuration
108
- PORT=4936
109
- NODE_ENV=production
110
-
111
- # File System
112
- SLIDES_DIR=./slides
113
-
114
- # CORS Configuration (optional)
115
- # Add custom origins for production deployments
116
- CORS_ORIGINS=https://your-frontend.vercel.app,https://custom-domain.com
117
- `;
118
-
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
- });
129
-
130
- program.parse();
package/src/index.ts DELETED
@@ -1,182 +0,0 @@
1
- import express from 'express';
2
- import cors from 'cors';
3
- import helmet from 'helmet';
4
- import dotenv from 'dotenv';
5
- import { fileURLToPath } from 'url';
6
- import { dirname, join } from 'path';
7
-
8
- import filesRouter from './routes/files.js';
9
- import agentsRouter from './routes/agents.js';
10
- import mcpRouter from './routes/mcp.js';
11
- import sessionsRouter from './routes/sessions.js';
12
- import mediaRouter from './routes/media.js';
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';
19
-
20
- dotenv.config();
21
-
22
- const __filename = fileURLToPath(import.meta.url);
23
- const __dirname = dirname(__filename);
24
-
25
- const app = express();
26
- const PORT = process.env.PORT || 4936;
27
-
28
- // Middleware
29
- app.use(helmet({
30
- contentSecurityPolicy: {
31
- directives: {
32
- defaultSrc: ["'self'"],
33
- scriptSrc: ["'self'", "'unsafe-inline'"],
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:"],
37
- connectSrc: ["'self'", "ws:", "wss:"],
38
- frameAncestors: ["'self'", "http://localhost:3000", "https://localhost:3000", "http://localhost:3001"] // Allow iframe embedding
39
- }
40
- }
41
- }));
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'
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
- };
58
-
59
- app.use(cors({
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']
113
- }));
114
- app.use(express.json({ limit: '10mb' }));
115
- app.use(express.urlencoded({ extended: true, limit: '10mb' }));
116
-
117
- // Static files - serve slides directory
118
- const slidesDir = join(__dirname, '../..', process.env.SLIDES_DIR || 'slides');
119
- app.use('/slides', express.static(slidesDir));
120
-
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
- }
131
-
132
- // Routes - Public routes
133
- app.use('/api/auth', authRouter);
134
-
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
147
- app.get('/api/health', (req, res) => {
148
- res.json({ status: 'ok', timestamp: new Date().toISOString() });
149
- });
150
-
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
- });
158
- });
159
-
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);
173
- });
174
-
175
- server.on('error', reject);
176
- });
177
- }
178
-
179
- // Start server if this file is run directly
180
- if (import.meta.url === `file://${process.argv[1]}`) {
181
- startServer().catch(console.error);
182
- }
@@ -1,26 +0,0 @@
1
- import { Request, Response, NextFunction } from 'express';
2
- import { verifyToken } from '../utils/jwt.js';
3
-
4
- /**
5
- * Middleware to authenticate requests using JWT token
6
- * Expects token in Authorization header as "Bearer <token>"
7
- */
8
- export function authMiddleware(req: Request, res: Response, next: NextFunction): void {
9
- const authHeader = req.headers.authorization;
10
-
11
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
12
- res.status(401).json({ error: 'Unauthorized: No token provided' });
13
- return;
14
- }
15
-
16
- const token = authHeader.substring(7); // Remove "Bearer " prefix
17
- const payload = verifyToken(token);
18
-
19
- if (!payload) {
20
- res.status(401).json({ error: 'Unauthorized: Invalid or expired token' });
21
- return;
22
- }
23
-
24
- // Token is valid, proceed to next middleware
25
- next();
26
- }