recoder-code 2.3.0 → 2.3.5
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/cli/interactive.js +194 -125
- package/cli/run.js +61 -19
- package/cli/user-onboarding.js +19 -2
- package/config.js +4 -3
- package/package.json +2 -2
- package/plugins/enhanced-plugin-manager.js +21 -9
- package/plugins/ide-integration-plugin.js +1 -1
- package/plugins/ide-integration-plugin.js.bak +235 -0
- package/plugins/productivity-plugin.js +1 -1
- package/plugins/productivity-plugin.js.bak +215 -0
- package/plugins/sample-plugin.js +1 -1
- package/plugins/sample-plugin.js.bak +7 -0
- package/plugins/team-collaboration-plugin.js +1 -1
- package/plugins/team-collaboration-plugin.js.bak +208 -0
- package/plugins/voice-commands-plugin.js +1 -1
- package/plugins/voice-commands-plugin.js.bak +136 -0
- package/plugins/weather-plugin.js +1 -1
- package/plugins/weather-plugin.js.bak +83 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// Team Collaboration Plugin for Recoder
|
|
2
|
+
// Handle chalk properly
|
|
3
|
+
const chalkModule = require('chalk');
|
|
4
|
+
const chalk = chalkModule.default || chalkModule;
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: 'team-collaboration',
|
|
10
|
+
version: '1.0.0',
|
|
11
|
+
description: 'Enhanced team collaboration features and workflows',
|
|
12
|
+
author: 'Recoder Team',
|
|
13
|
+
enabled: true,
|
|
14
|
+
|
|
15
|
+
async init() {
|
|
16
|
+
console.log(chalk.green('✅ Team collaboration plugin initialized'));
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
async cleanup() {
|
|
20
|
+
console.log('Team collaboration plugin cleaned up');
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
commands: {
|
|
24
|
+
'team-setup': async (args, context) => {
|
|
25
|
+
const chat = context.chat;
|
|
26
|
+
if (!chat.collaborationManager) {
|
|
27
|
+
return '❌ Collaboration manager not available';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let response = '🤝 Team Setup Quick Guide:\n\n';
|
|
31
|
+
response += '1. Create a team workspace:\n /workspace create "My Team" "Project description"\n\n';
|
|
32
|
+
response += '2. Invite team members:\n /team invite alice\n /team invite bob\n\n';
|
|
33
|
+
response += '3. Share your current session:\n /share session\n\n';
|
|
34
|
+
response += '4. Start collaborating:\n /collaborate start\n\n';
|
|
35
|
+
response += 'Team Features:\n';
|
|
36
|
+
response += '• Shared conversations across team members\n';
|
|
37
|
+
response += '• File sharing and collaborative editing\n';
|
|
38
|
+
response += '• Real-time messaging and notifications\n';
|
|
39
|
+
response += '• Workspace-based project organization\n';
|
|
40
|
+
response += '• Session broadcasting and synchronization\n';
|
|
41
|
+
|
|
42
|
+
return response;
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
'quick-share': async (args, context) => {
|
|
46
|
+
const chat = context.chat;
|
|
47
|
+
if (!chat.collaborationManager) {
|
|
48
|
+
return '❌ Collaboration manager not available';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Quick share current conversation
|
|
52
|
+
const currentConv = chat.getCurrentConversation();
|
|
53
|
+
const quickSessionData = {
|
|
54
|
+
name: currentConv.name,
|
|
55
|
+
model: currentConv.model,
|
|
56
|
+
conversation: {
|
|
57
|
+
...currentConv,
|
|
58
|
+
created: currentConv.created.toISOString(),
|
|
59
|
+
lastActive: currentConv.lastActive.toISOString()
|
|
60
|
+
},
|
|
61
|
+
timestamp: new Date().toISOString()
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const sharedId = await chat.collaborationManager.createSharedSession(quickSessionData);
|
|
65
|
+
return `🚀 Quick share created! ID: ${sharedId}\nShare this with your team: /share join ${sharedId}`;
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
'team-status': async (args, context) => {
|
|
69
|
+
const chat = context.chat;
|
|
70
|
+
if (!chat.collaborationManager) {
|
|
71
|
+
return '❌ Collaboration manager not available';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const status = chat.collaborationManager.getCollaborationStatus();
|
|
75
|
+
const workspaces = chat.collaborationManager.listTeamWorkspaces();
|
|
76
|
+
const sharedSessions = chat.collaborationManager.listSharedSessions();
|
|
77
|
+
|
|
78
|
+
let response = '👥 Team Status Dashboard:\n\n';
|
|
79
|
+
response += `Collaboration Mode: ${status.mode}\n`;
|
|
80
|
+
response += `Team Members: ${status.teamMembers.length}\n`;
|
|
81
|
+
response += `Workspaces: ${workspaces.length}\n`;
|
|
82
|
+
response += `Shared Sessions: ${sharedSessions.length}\n`;
|
|
83
|
+
|
|
84
|
+
if (status.collaborationId) {
|
|
85
|
+
response += `\n🤝 Active Collaboration: ${status.collaborationId}\n`;
|
|
86
|
+
response += `Role: ${status.isHost ? 'Host' : 'Participant'}\n`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (workspaces.length > 0) {
|
|
90
|
+
response += '\n📁 Recent Workspaces:\n';
|
|
91
|
+
workspaces.slice(0, 3).forEach(ws => {
|
|
92
|
+
response += `• ${ws.name} (${ws.members.length} members)\n`;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return response;
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
'sync': async (args, context) => {
|
|
100
|
+
const chat = context.chat;
|
|
101
|
+
if (!chat.collaborationManager) {
|
|
102
|
+
return '❌ Collaboration manager not available';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const status = chat.collaborationManager.getCollaborationStatus();
|
|
106
|
+
if (status.mode === 'none') {
|
|
107
|
+
return '⚠️ Not in collaboration mode. Use /collaborate start to begin.';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Simulate syncing with team
|
|
111
|
+
const currentConv = chat.getCurrentConversation();
|
|
112
|
+
await chat.collaborationManager.broadcastMessage(
|
|
113
|
+
`Syncing conversation: ${currentConv.name}`,
|
|
114
|
+
{
|
|
115
|
+
type: 'sync',
|
|
116
|
+
conversationId: chat.currentConversationId,
|
|
117
|
+
messageCount: currentConv.history.length,
|
|
118
|
+
model: currentConv.model
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return '✅ Conversation synced with team';
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
'invite-link': async (args, context) => {
|
|
126
|
+
const chat = context.chat;
|
|
127
|
+
if (!chat.collaborationManager) {
|
|
128
|
+
return '❌ Collaboration manager not available';
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const workspaceId = args[0];
|
|
132
|
+
if (!workspaceId) {
|
|
133
|
+
return '❌ Usage: /invite-link <workspace-id>';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Generate a shareable invitation link (simulated)
|
|
137
|
+
const inviteCode = require('crypto').randomBytes(6).toString('hex');
|
|
138
|
+
|
|
139
|
+
let response = `🔗 Workspace Invitation Generated!\n\n`;
|
|
140
|
+
response += `Workspace ID: ${workspaceId}\n`;
|
|
141
|
+
response += `Invite Code: ${inviteCode}\n\n`;
|
|
142
|
+
response += `Share this with team members:\n`;
|
|
143
|
+
response += `"Join our workspace with: /workspace join ${workspaceId}"\n\n`;
|
|
144
|
+
response += `💡 Tip: Team members can also use /team-setup for guidance`;
|
|
145
|
+
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
// Process messages for collaboration suggestions
|
|
151
|
+
onMessage: async (message, context) => {
|
|
152
|
+
const lowerMessage = message.toLowerCase();
|
|
153
|
+
|
|
154
|
+
// Suggest collaboration features
|
|
155
|
+
if (lowerMessage.includes('team') || lowerMessage.includes('collaborate')) {
|
|
156
|
+
return '💡 Tip: Use /team-setup for collaboration quick start';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (lowerMessage.includes('share') || lowerMessage.includes('send to')) {
|
|
160
|
+
return '💡 Tip: Use /quick-share to instantly share current conversation';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (lowerMessage.includes('workspace') || lowerMessage.includes('project')) {
|
|
164
|
+
return '💡 Tip: Use /workspace create to set up team workspace';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (lowerMessage.includes('invite') || lowerMessage.includes('add member')) {
|
|
168
|
+
return '💡 Tip: Use /team invite <username> to add team members';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return null;
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// Hook into conversation events
|
|
175
|
+
onResponse: async (response, context) => {
|
|
176
|
+
const chat = context.chat;
|
|
177
|
+
|
|
178
|
+
// Auto-sync important responses in collaboration mode
|
|
179
|
+
if (chat.collaborationManager?.getCollaborationStatus().mode !== 'none') {
|
|
180
|
+
if (response.includes('```') || response.length > 500) {
|
|
181
|
+
// This is likely code or a significant response
|
|
182
|
+
console.log(chalk.gray('🔄 Auto-syncing significant response with team'));
|
|
183
|
+
|
|
184
|
+
await chat.collaborationManager.broadcastMessage(
|
|
185
|
+
'Significant AI response generated',
|
|
186
|
+
{
|
|
187
|
+
type: 'ai_response',
|
|
188
|
+
length: response.length,
|
|
189
|
+
hasCode: response.includes('```'),
|
|
190
|
+
conversationId: chat.currentConversationId
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
hooks: {
|
|
198
|
+
beforeResponse: async (data) => {
|
|
199
|
+
// Could add team input processing here
|
|
200
|
+
return data;
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
afterResponse: async (data) => {
|
|
204
|
+
// Could add team notification features here
|
|
205
|
+
return data;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Voice Commands Plugin for Recoder
|
|
2
|
+
// Handle chalk properly
|
|
3
|
+
const chalkModule = require('chalk');
|
|
4
|
+
const chalk = chalkModule.default || chalkModule;
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: 'voice-commands',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
description: 'Enhanced voice command processing and shortcuts',
|
|
10
|
+
author: 'Recoder Team',
|
|
11
|
+
enabled: true,
|
|
12
|
+
|
|
13
|
+
async init() {
|
|
14
|
+
console.log(chalk.green('✅ Voice commands plugin initialized'));
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async cleanup() {
|
|
18
|
+
console.log('Voice commands plugin cleaned up');
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
commands: {
|
|
22
|
+
listen: async (args, context) => {
|
|
23
|
+
const chat = context.chat;
|
|
24
|
+
if (!chat.voiceManager) {
|
|
25
|
+
return '❌ Voice manager not available';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!chat.voiceManager.speechToTextEnabled) {
|
|
29
|
+
return '❌ Speech-to-text not enabled. Use /voice stt on first.';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Start listening mode
|
|
33
|
+
if (chat.voiceManager.isRecording) {
|
|
34
|
+
return '⚠️ Already listening. Use /record to stop.';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const started = await chat.voiceManager.startRecording();
|
|
38
|
+
if (started) {
|
|
39
|
+
return '🎤 Voice listening activated. Press Enter to stop and process.';
|
|
40
|
+
} else {
|
|
41
|
+
return '❌ Failed to start voice recording';
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
quiet: async (args, context) => {
|
|
46
|
+
const chat = context.chat;
|
|
47
|
+
if (!chat.voiceManager) {
|
|
48
|
+
return '❌ Voice manager not available';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await chat.voiceManager.stopSpeaking();
|
|
52
|
+
return '🔇 Voice output stopped';
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
'voice-setup': async (args, context) => {
|
|
56
|
+
const chat = context.chat;
|
|
57
|
+
if (!chat.voiceManager) {
|
|
58
|
+
return '❌ Voice manager not available';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const status = chat.voiceManager.getStatus();
|
|
62
|
+
|
|
63
|
+
let response = '🎤 Voice Setup Quick Guide:\n\n';
|
|
64
|
+
|
|
65
|
+
if (!status.textToSpeechEnabled) {
|
|
66
|
+
response += '🔊 Enable Text-to-Speech: /voice tts on\n';
|
|
67
|
+
} else {
|
|
68
|
+
response += '✅ Text-to-Speech is enabled\n';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!status.speechToTextEnabled) {
|
|
72
|
+
response += '🎙️ Enable Speech-to-Text: /voice stt on\n';
|
|
73
|
+
} else {
|
|
74
|
+
response += '✅ Speech-to-Text is enabled\n';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
response += '\nVoice Commands:\n';
|
|
78
|
+
response += '• /record - Start/stop voice recording\n';
|
|
79
|
+
response += '• /speak <text> - Speak text aloud\n';
|
|
80
|
+
response += '• /listen - Quick voice input\n';
|
|
81
|
+
response += '• /quiet - Stop current speech\n';
|
|
82
|
+
response += '• /voice voices - List available voices\n';
|
|
83
|
+
response += '• /voice set <name> - Change voice\n';
|
|
84
|
+
|
|
85
|
+
return response;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
// Process messages for voice-related suggestions
|
|
90
|
+
onMessage: async (message, context) => {
|
|
91
|
+
const lowerMessage = message.toLowerCase();
|
|
92
|
+
|
|
93
|
+
// Suggest voice commands for common phrases
|
|
94
|
+
if (lowerMessage.includes('speak') || lowerMessage.includes('say')) {
|
|
95
|
+
return '💡 Tip: Use /speak <text> to hear responses aloud';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (lowerMessage.includes('listen') || lowerMessage.includes('voice input')) {
|
|
99
|
+
return '💡 Tip: Use /record or /listen for voice input';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (lowerMessage.includes('voice') || lowerMessage.includes('audio')) {
|
|
103
|
+
return '💡 Tip: Use /voice to manage voice settings';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return null;
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
// Hook into response processing to add voice features
|
|
110
|
+
onResponse: async (response, context) => {
|
|
111
|
+
const chat = context.chat;
|
|
112
|
+
|
|
113
|
+
// Check if response contains code - don't speak code blocks
|
|
114
|
+
if (response.includes('```') && chat.voiceManager?.textToSpeechEnabled) {
|
|
115
|
+
console.log(chalk.gray('🔇 Skipping TTS for code response'));
|
|
116
|
+
|
|
117
|
+
// Stop any current speech and don't speak this response
|
|
118
|
+
await chat.voiceManager.stopSpeaking();
|
|
119
|
+
|
|
120
|
+
// You could override the TTS behavior here
|
|
121
|
+
// by temporarily disabling it for this response
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
hooks: {
|
|
126
|
+
beforeResponse: async (data) => {
|
|
127
|
+
// Could process voice commands before sending to AI
|
|
128
|
+
return data;
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
afterResponse: async (data) => {
|
|
132
|
+
// Could add voice feedback after responses
|
|
133
|
+
return data;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Example Weather Plugin for Recoder
|
|
2
|
+
const axios = require('axios');
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
name: 'weather',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
description: 'Get weather information for any city',
|
|
8
|
+
author: 'Recoder Team',
|
|
9
|
+
enabled: true,
|
|
10
|
+
|
|
11
|
+
// Plugin initialization
|
|
12
|
+
async init() {
|
|
13
|
+
console.log('Weather plugin initialized');
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
// Plugin cleanup
|
|
17
|
+
async cleanup() {
|
|
18
|
+
console.log('Weather plugin cleaned up');
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// Custom commands
|
|
22
|
+
commands: {
|
|
23
|
+
weather: async (args, context) => {
|
|
24
|
+
if (!args.length) {
|
|
25
|
+
return 'Usage: /weather <city>';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const city = args.join(' ');
|
|
29
|
+
try {
|
|
30
|
+
// Using a free weather API (OpenWeatherMap alternative)
|
|
31
|
+
const response = await axios.get(`https://wttr.in/${encodeURIComponent(city)}?format=j1`);
|
|
32
|
+
const data = response.data;
|
|
33
|
+
|
|
34
|
+
if (!data.current_condition) {
|
|
35
|
+
return `Weather data not found for ${city}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const current = data.current_condition[0];
|
|
39
|
+
const location = data.nearest_area[0];
|
|
40
|
+
|
|
41
|
+
return `🌤️ Weather in ${location.areaName[0].value}, ${location.country[0].value}:
|
|
42
|
+
Temperature: ${current.temp_C}°C (${current.temp_F}°F)
|
|
43
|
+
Condition: ${current.weatherDesc[0].value}
|
|
44
|
+
Humidity: ${current.humidity}%
|
|
45
|
+
Wind: ${current.windspeedKmph} km/h ${current.winddir16Point}
|
|
46
|
+
Feels like: ${current.FeelsLikeC}°C`;
|
|
47
|
+
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return `Failed to fetch weather data: ${error.message}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Hook into message processing
|
|
55
|
+
onMessage: async (message, context) => {
|
|
56
|
+
// Auto-detect weather requests
|
|
57
|
+
const weatherKeywords = ['weather', 'temperature', 'forecast', 'climate'];
|
|
58
|
+
const cityPattern = /weather in (\w+)/i;
|
|
59
|
+
|
|
60
|
+
if (weatherKeywords.some(keyword => message.toLowerCase().includes(keyword))) {
|
|
61
|
+
const match = message.match(cityPattern);
|
|
62
|
+
if (match) {
|
|
63
|
+
const city = match[1];
|
|
64
|
+
context.suggestedCommand = `/weather ${city}`;
|
|
65
|
+
return `💡 Suggestion: Use /weather ${city} for current weather`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// Hooks for various events
|
|
72
|
+
hooks: {
|
|
73
|
+
beforeResponse: async (data) => {
|
|
74
|
+
// Could modify the response before it's sent
|
|
75
|
+
return data;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
afterResponse: async (data) => {
|
|
79
|
+
// Could perform actions after response is sent
|
|
80
|
+
return data;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|