recoder-code 2.5.2 โ†’ 2.5.3

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 (44) hide show
  1. package/dist/index.js +0 -0
  2. package/dist/src/commands/context/index.js +2 -2
  3. package/dist/src/commands/mcp/marketplace.d.ts +6 -0
  4. package/dist/src/commands/mcp/marketplace.js +448 -0
  5. package/dist/src/commands/mcp.js +2 -0
  6. package/dist/src/commands/parallel.d.ts +20 -0
  7. package/dist/src/commands/parallel.js +133 -0
  8. package/dist/src/commands/recoderWeb.js +184 -5
  9. package/dist/src/commands/web/diff.d.ts +13 -0
  10. package/dist/src/commands/web/diff.js +235 -0
  11. package/dist/src/commands/web/link.d.ts +11 -0
  12. package/dist/src/commands/web/link.js +96 -0
  13. package/dist/src/commands/web/pull.d.ts +13 -0
  14. package/dist/src/commands/web/pull.js +203 -0
  15. package/dist/src/commands/web/status.d.ts +10 -0
  16. package/dist/src/commands/web/status.js +104 -0
  17. package/dist/src/commands/web/unlink.d.ts +10 -0
  18. package/dist/src/commands/web/unlink.js +45 -0
  19. package/dist/src/commands/web/watch.d.ts +14 -0
  20. package/dist/src/commands/web/watch.js +360 -0
  21. package/dist/src/commands/web.js +12 -0
  22. package/dist/src/config/config.js +6 -2
  23. package/dist/src/config/defaultMcpServers.d.ts +1 -0
  24. package/dist/src/config/defaultMcpServers.js +46 -0
  25. package/dist/src/gemini.js +10 -0
  26. package/dist/src/parallel/git-utils.d.ts +42 -0
  27. package/dist/src/parallel/git-utils.js +161 -0
  28. package/dist/src/parallel/index.d.ts +14 -0
  29. package/dist/src/parallel/index.js +14 -0
  30. package/dist/src/parallel/parallel-mode.d.ts +48 -0
  31. package/dist/src/parallel/parallel-mode.js +224 -0
  32. package/dist/src/services/AgentBridgeService.d.ts +61 -0
  33. package/dist/src/services/AgentBridgeService.js +253 -0
  34. package/dist/src/services/BuiltinCommandLoader.js +7 -0
  35. package/dist/src/services/PlatformSyncService.d.ts +154 -0
  36. package/dist/src/services/PlatformSyncService.js +588 -0
  37. package/dist/src/ui/commands/workflowCommands.d.ts +16 -0
  38. package/dist/src/ui/commands/workflowCommands.js +291 -0
  39. package/dist/src/ui/commands/workspaceCommand.d.ts +11 -0
  40. package/dist/src/ui/commands/workspaceCommand.js +329 -0
  41. package/dist/src/zed-integration/schema.d.ts +30 -30
  42. package/package.json +29 -10
  43. package/src/postinstall.cjs +3 -2
  44. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Git utilities for parallel mode
3
+ * Based on Kilo Code (Apache-2.0 License)
4
+ */
5
+ import simpleGit from 'simple-git';
6
+ /**
7
+ * Get Git repository information for a given directory
8
+ */
9
+ export async function getGitInfo(cwd) {
10
+ const defaultResult = {
11
+ branch: null,
12
+ isClean: true,
13
+ isRepo: false,
14
+ };
15
+ if (!cwd) {
16
+ return defaultResult;
17
+ }
18
+ try {
19
+ const git = simpleGit(cwd);
20
+ // Check if it's a git repository
21
+ const isRepo = await git.checkIsRepo();
22
+ if (!isRepo) {
23
+ return defaultResult;
24
+ }
25
+ // Get current branch
26
+ const branch = await git.revparse(['--abbrev-ref', 'HEAD']);
27
+ // Check if working directory is clean
28
+ const status = await git.status();
29
+ const isClean = status.files.length === 0;
30
+ return {
31
+ branch: branch.trim() || null,
32
+ isClean,
33
+ isRepo: true,
34
+ };
35
+ }
36
+ catch (error) {
37
+ console.debug('Failed to get git info:', error);
38
+ return defaultResult;
39
+ }
40
+ }
41
+ /**
42
+ * Get just the branch name (faster than full git info)
43
+ */
44
+ export async function getGitBranch(cwd) {
45
+ if (!cwd) {
46
+ return null;
47
+ }
48
+ try {
49
+ const git = simpleGit(cwd);
50
+ const isRepo = await git.checkIsRepo();
51
+ if (!isRepo) {
52
+ return null;
53
+ }
54
+ const branch = await git.revparse(['--abbrev-ref', 'HEAD']);
55
+ return branch.trim() || null;
56
+ }
57
+ catch (error) {
58
+ console.debug('Failed to get git branch:', error);
59
+ return null;
60
+ }
61
+ }
62
+ /**
63
+ * Check if a branch exists in the repository
64
+ */
65
+ export async function branchExists(cwd, branchName) {
66
+ if (!cwd || !branchName) {
67
+ return false;
68
+ }
69
+ try {
70
+ const git = simpleGit(cwd);
71
+ const isRepo = await git.checkIsRepo();
72
+ if (!isRepo) {
73
+ return false;
74
+ }
75
+ // Get all branches (local and remote)
76
+ const branches = await git.branch();
77
+ // Check if branch exists in local branches
78
+ return branches.all.includes(branchName) || branches.all.includes(`remotes/origin/${branchName}`);
79
+ }
80
+ catch (error) {
81
+ console.debug('Failed to check if branch exists:', error);
82
+ return false;
83
+ }
84
+ }
85
+ /**
86
+ * Generate a valid git branch name from a prompt
87
+ * Sanitizes the prompt to create a safe branch name
88
+ */
89
+ export function generateBranchName(prompt) {
90
+ // Take first 50 chars, convert to lowercase, replace spaces and special chars with hyphens
91
+ const sanitized = prompt
92
+ .slice(0, 50)
93
+ .toLowerCase()
94
+ .replace(/[^a-z0-9]+/g, '-')
95
+ .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
96
+ .replace(/-+/g, '-'); // Collapse multiple hyphens
97
+ // Add timestamp to ensure uniqueness
98
+ const timestamp = Date.now();
99
+ return `recoder/${sanitized || 'task'}-${timestamp}`;
100
+ }
101
+ /**
102
+ * Check if a directory is a git worktree
103
+ */
104
+ export async function isGitWorktree(cwd) {
105
+ if (!cwd) {
106
+ return false;
107
+ }
108
+ try {
109
+ const git = simpleGit(cwd);
110
+ const isRepo = await git.checkIsRepo();
111
+ if (!isRepo) {
112
+ return false;
113
+ }
114
+ // In a worktree, --git-dir points to .git/worktrees/<name>
115
+ // In a normal repo, --git-dir points to .git
116
+ const gitDir = await git.revparse(['--git-dir']);
117
+ return gitDir.trim().includes('worktrees');
118
+ }
119
+ catch (error) {
120
+ console.debug('Failed to check if git worktree:', error);
121
+ return false;
122
+ }
123
+ }
124
+ /**
125
+ * Create a git worktree
126
+ */
127
+ export async function createWorktree(cwd, worktreePath, branchName, isNewBranch) {
128
+ const git = simpleGit(cwd);
129
+ const args = isNewBranch
130
+ ? ['worktree', 'add', '-b', branchName, worktreePath]
131
+ : ['worktree', 'add', worktreePath, branchName];
132
+ await git.raw(args);
133
+ }
134
+ /**
135
+ * Remove a git worktree
136
+ */
137
+ export async function removeWorktree(cwd, worktreePath) {
138
+ const git = simpleGit(cwd);
139
+ await git.raw(['worktree', 'remove', worktreePath]);
140
+ }
141
+ /**
142
+ * List all worktrees for a repository
143
+ */
144
+ export async function listWorktrees(cwd) {
145
+ try {
146
+ const git = simpleGit(cwd);
147
+ const result = await git.raw(['worktree', 'list', '--porcelain']);
148
+ const worktrees = [];
149
+ const lines = result.split('\n');
150
+ for (const line of lines) {
151
+ if (line.startsWith('worktree ')) {
152
+ worktrees.push(line.replace('worktree ', '').trim());
153
+ }
154
+ }
155
+ return worktrees;
156
+ }
157
+ catch (error) {
158
+ console.debug('Failed to list worktrees:', error);
159
+ return [];
160
+ }
161
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Parallel Mode - Git Worktree-based Parallel Execution
3
+ *
4
+ * Allows multiple Recoder instances to work on the same repository
5
+ * without conflicts by using separate git worktrees.
6
+ *
7
+ * Usage:
8
+ * recoder --parallel "implement feature X"
9
+ * recoder --parallel --existing-branch recoder/feature-x-123 "continue work"
10
+ *
11
+ * Based on Kilo Code (Apache-2.0 License)
12
+ */
13
+ export { startParallelMode, finishParallelMode, getParallelModeParams, listParallelWorktrees, cleanupStaleWorktrees, type ParallelModeInput, type ParallelModeParams, type ParallelModeResult, } from './parallel-mode.js';
14
+ export { getGitInfo, getGitBranch, branchExists, generateBranchName, isGitWorktree, createWorktree, removeWorktree, listWorktrees, type GitInfo, } from './git-utils.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Parallel Mode - Git Worktree-based Parallel Execution
3
+ *
4
+ * Allows multiple Recoder instances to work on the same repository
5
+ * without conflicts by using separate git worktrees.
6
+ *
7
+ * Usage:
8
+ * recoder --parallel "implement feature X"
9
+ * recoder --parallel --existing-branch recoder/feature-x-123 "continue work"
10
+ *
11
+ * Based on Kilo Code (Apache-2.0 License)
12
+ */
13
+ export { startParallelMode, finishParallelMode, getParallelModeParams, listParallelWorktrees, cleanupStaleWorktrees, } from './parallel-mode.js';
14
+ export { getGitInfo, getGitBranch, branchExists, generateBranchName, isGitWorktree, createWorktree, removeWorktree, listWorktrees, } from './git-utils.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Parallel Mode - Execute multiple tasks simultaneously using git worktrees
3
+ * Based on Kilo Code (Apache-2.0 License)
4
+ *
5
+ * Parallel mode allows multiple Recoder instances to work on the same repository
6
+ * without conflicts. Each instance operates in a separate git worktree.
7
+ */
8
+ export declare const COMMIT_COMPLETION_TIMEOUT = 40000;
9
+ export interface ParallelModeInput {
10
+ cwd: string;
11
+ prompt: string;
12
+ timeout?: number;
13
+ existingBranch?: string;
14
+ }
15
+ export interface ParallelModeParams {
16
+ worktreeBranch: string;
17
+ worktreePath: string;
18
+ }
19
+ export interface ParallelModeResult {
20
+ success: boolean;
21
+ branch: string;
22
+ worktreePath: string;
23
+ message: string;
24
+ }
25
+ /**
26
+ * Determine the branch and worktree path for parallel mode
27
+ */
28
+ export declare function determineParallelBranch({ cwd, prompt, existingBranch, }: ParallelModeInput): Promise<ParallelModeParams>;
29
+ /**
30
+ * Get parameters for parallel mode execution
31
+ */
32
+ export declare function getParallelModeParams({ cwd, prompt, existingBranch, }: ParallelModeInput): Promise<ParallelModeParams>;
33
+ /**
34
+ * Finish parallel mode by committing changes and cleaning up worktree
35
+ */
36
+ export declare function finishParallelMode(worktreePath: string, worktreeBranch: string, originalCwd: string): Promise<ParallelModeResult>;
37
+ /**
38
+ * Start parallel mode - creates worktree and returns the working directory
39
+ */
40
+ export declare function startParallelMode(cwd: string, prompt: string, existingBranch?: string): Promise<ParallelModeParams>;
41
+ /**
42
+ * List active parallel mode worktrees
43
+ */
44
+ export declare function listParallelWorktrees(cwd: string): Promise<string[]>;
45
+ /**
46
+ * Clean up stale parallel mode worktrees
47
+ */
48
+ export declare function cleanupStaleWorktrees(cwd: string): Promise<number>;
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Parallel Mode - Execute multiple tasks simultaneously using git worktrees
3
+ * Based on Kilo Code (Apache-2.0 License)
4
+ *
5
+ * Parallel mode allows multiple Recoder instances to work on the same repository
6
+ * without conflicts. Each instance operates in a separate git worktree.
7
+ */
8
+ import path from 'path';
9
+ import os from 'os';
10
+ import simpleGit from 'simple-git';
11
+ import { getGitInfo, generateBranchName, branchExists, createWorktree, removeWorktree, } from './git-utils.js';
12
+ export const COMMIT_COMPLETION_TIMEOUT = 40000;
13
+ /**
14
+ * Determine the branch and worktree path for parallel mode
15
+ */
16
+ export async function determineParallelBranch({ cwd, prompt, existingBranch, }) {
17
+ const { isRepo, branch } = await getGitInfo(cwd);
18
+ if (!isRepo) {
19
+ throw new Error('Parallel mode requires the current working directory to be a git repository');
20
+ }
21
+ if (!branch) {
22
+ throw new Error('Could not determine current git branch');
23
+ }
24
+ // Determine the branch to use
25
+ let worktreeBranch;
26
+ if (existingBranch) {
27
+ // Check if the existing branch exists
28
+ const exists = await branchExists(cwd, existingBranch);
29
+ if (!exists) {
30
+ throw new Error(`Branch "${existingBranch}" does not exist`);
31
+ }
32
+ worktreeBranch = existingBranch;
33
+ console.log(`๐Ÿ“Œ Using existing branch: ${worktreeBranch}`);
34
+ }
35
+ else {
36
+ // Generate branch name from prompt
37
+ worktreeBranch = generateBranchName(prompt);
38
+ console.log(`๐ŸŒฟ Creating new branch: ${worktreeBranch}`);
39
+ }
40
+ // Create worktree directory path in OS temp directory
41
+ const tempDir = os.tmpdir();
42
+ const worktreePath = path.join(tempDir, `recoder-worktree-${worktreeBranch.replace(/\//g, '-')}`);
43
+ // Create worktree
44
+ try {
45
+ await createWorktree(cwd, worktreePath, worktreeBranch, !existingBranch);
46
+ console.log(`๐Ÿ“ Created worktree at: ${worktreePath}`);
47
+ }
48
+ catch (error) {
49
+ console.error('Failed to create worktree:', error);
50
+ throw error;
51
+ }
52
+ return { worktreeBranch, worktreePath };
53
+ }
54
+ /**
55
+ * Get parameters for parallel mode execution
56
+ */
57
+ export async function getParallelModeParams({ cwd, prompt, existingBranch, }) {
58
+ try {
59
+ return await determineParallelBranch({ cwd, prompt, existingBranch });
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : String(error);
63
+ console.error(`Failed to start parallel mode: ${message}`);
64
+ throw error;
65
+ }
66
+ }
67
+ /**
68
+ * Helper function to commit changes with a fallback message
69
+ */
70
+ async function commitWithFallback(cwd) {
71
+ const fallbackMessage = 'chore: recoder parallel mode task completion';
72
+ const git = simpleGit(cwd);
73
+ await git.commit(fallbackMessage);
74
+ console.log('๐Ÿ“ Changes committed with fallback message');
75
+ }
76
+ /**
77
+ * Poll git status to check if commit is complete
78
+ * Returns true if commit was made, false if timeout reached
79
+ */
80
+ async function waitForCommitCompletion(cwd) {
81
+ const pollIntervalMs = 1000;
82
+ const startTime = Date.now();
83
+ const git = simpleGit(cwd);
84
+ while (Date.now() - startTime < COMMIT_COMPLETION_TIMEOUT) {
85
+ try {
86
+ const stagedDiff = await git.diff(['--staged']);
87
+ // If no staged changes, commit was successful
88
+ if (!stagedDiff.trim()) {
89
+ return true;
90
+ }
91
+ // Wait before next poll
92
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
93
+ }
94
+ catch (error) {
95
+ console.error('Error checking commit status:', error);
96
+ return false;
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ /**
102
+ * Finish parallel mode by committing changes and cleaning up worktree
103
+ */
104
+ export async function finishParallelMode(worktreePath, worktreeBranch, originalCwd) {
105
+ const git = simpleGit(worktreePath);
106
+ try {
107
+ const status = await git.status();
108
+ if (!status.isClean()) {
109
+ console.log('๐Ÿ“ฆ Staging all changes...');
110
+ await git.add('-A');
111
+ const diff = await git.diff(['--staged']);
112
+ if (!diff.trim()) {
113
+ console.warn('โš ๏ธ No staged changes found after git add');
114
+ }
115
+ else {
116
+ console.log('๐Ÿ“ Committing changes...');
117
+ await commitWithFallback(worktreePath);
118
+ }
119
+ }
120
+ else {
121
+ console.log('โœจ No changes to commit');
122
+ }
123
+ // Print completion message
124
+ const green = '\x1b[32m';
125
+ const cyan = '\x1b[36m';
126
+ const yellow = '\x1b[33m';
127
+ const bold = '\x1b[1m';
128
+ const reset = '\x1b[0m';
129
+ console.log('\n' + cyan + 'โ”€'.repeat(80) + reset);
130
+ console.log(`${green}โœ“${reset} ${bold}Parallel mode complete!${reset} Changes committed to: ${cyan}${worktreeBranch}${reset}`);
131
+ console.log(`\n${bold}Review and merge changes:${reset}`);
132
+ console.log(` ${yellow}git diff ...${worktreeBranch}${reset}`);
133
+ console.log(` ${yellow}git merge ${worktreeBranch}${reset}`);
134
+ console.log(`\n${bold}๐Ÿ’ก Tip:${reset} Resume work with ${yellow}--existing-branch${reset}:`);
135
+ console.log(` ${yellow}recoder --parallel --existing-branch ${worktreeBranch} "<prompt>"${reset}`);
136
+ console.log(cyan + 'โ”€'.repeat(80) + reset + '\n');
137
+ return {
138
+ success: true,
139
+ branch: worktreeBranch,
140
+ worktreePath,
141
+ message: `Changes committed to branch: ${worktreeBranch}`,
142
+ };
143
+ }
144
+ catch (error) {
145
+ const errorMessage = error instanceof Error ? error.message : String(error);
146
+ console.error('Failed to commit changes:', errorMessage);
147
+ return {
148
+ success: false,
149
+ branch: worktreeBranch,
150
+ worktreePath,
151
+ message: `Failed to commit: ${errorMessage}`,
152
+ };
153
+ }
154
+ finally {
155
+ // Clean up worktree
156
+ try {
157
+ console.log(`๐Ÿงน Removing worktree at: ${worktreePath}`);
158
+ await removeWorktree(originalCwd, worktreePath);
159
+ console.log('โœ… Worktree removed successfully');
160
+ }
161
+ catch (error) {
162
+ const errorMessage = error instanceof Error ? error.message : String(error);
163
+ console.warn('โš ๏ธ Failed to remove worktree:', errorMessage);
164
+ }
165
+ }
166
+ }
167
+ /**
168
+ * Start parallel mode - creates worktree and returns the working directory
169
+ */
170
+ export async function startParallelMode(cwd, prompt, existingBranch) {
171
+ console.log('\n๐Ÿš€ Starting Recoder Parallel Mode...\n');
172
+ const params = await getParallelModeParams({
173
+ cwd,
174
+ prompt,
175
+ existingBranch,
176
+ });
177
+ console.log(`\nโœ… Parallel mode ready!`);
178
+ console.log(`๐Ÿ“ Working in: ${params.worktreePath}`);
179
+ console.log(`๐ŸŒฟ Branch: ${params.worktreeBranch}\n`);
180
+ return params;
181
+ }
182
+ /**
183
+ * List active parallel mode worktrees
184
+ */
185
+ export async function listParallelWorktrees(cwd) {
186
+ const git = simpleGit(cwd);
187
+ try {
188
+ const result = await git.raw(['worktree', 'list', '--porcelain']);
189
+ const worktrees = [];
190
+ const lines = result.split('\n');
191
+ for (const line of lines) {
192
+ if (line.startsWith('worktree ')) {
193
+ const path = line.replace('worktree ', '').trim();
194
+ // Only include recoder worktrees
195
+ if (path.includes('recoder-worktree-')) {
196
+ worktrees.push(path);
197
+ }
198
+ }
199
+ }
200
+ return worktrees;
201
+ }
202
+ catch (error) {
203
+ console.debug('Failed to list worktrees:', error);
204
+ return [];
205
+ }
206
+ }
207
+ /**
208
+ * Clean up stale parallel mode worktrees
209
+ */
210
+ export async function cleanupStaleWorktrees(cwd) {
211
+ const worktrees = await listParallelWorktrees(cwd);
212
+ let cleaned = 0;
213
+ for (const worktreePath of worktrees) {
214
+ try {
215
+ await removeWorktree(cwd, worktreePath);
216
+ cleaned++;
217
+ console.log(`๐Ÿงน Removed stale worktree: ${worktreePath}`);
218
+ }
219
+ catch (error) {
220
+ console.debug(`Failed to remove worktree ${worktreePath}:`, error);
221
+ }
222
+ }
223
+ return cleaned;
224
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Agent Bridge Service
3
+ *
4
+ * Connects recoder-code CLI to the A2A workspace system on docker-backend
5
+ * via WebSocket. Enables local agents to:
6
+ * - Register as workspace members
7
+ * - Receive task assignments in real-time
8
+ * - Report task progress and results
9
+ * - Participate in channel conversations
10
+ *
11
+ * Uses existing RecoderAuthService for authentication tokens.
12
+ * Auto-reconnects with exponential backoff (same pattern as PlatformSyncService).
13
+ */
14
+ import { EventEmitter } from 'events';
15
+ export interface TaskAssignment {
16
+ taskId: string;
17
+ prompt: string;
18
+ context: Record<string, unknown>;
19
+ worktreeBranch?: string;
20
+ }
21
+ export interface ChannelMessageEvent {
22
+ channelId: string;
23
+ from: string;
24
+ content: string;
25
+ }
26
+ export interface WorkspaceAgent {
27
+ agentId: string;
28
+ status: string;
29
+ isLocal: boolean;
30
+ capabilities: string[];
31
+ }
32
+ export declare class AgentBridgeService extends EventEmitter {
33
+ private ws;
34
+ private reconnectTimeout;
35
+ private heartbeatInterval;
36
+ private connected;
37
+ private agentId;
38
+ private workspaceId;
39
+ private reconnectAttempts;
40
+ private readonly maxReconnectDelay;
41
+ private getToken;
42
+ constructor(getToken: () => Promise<string | null>, agentId?: string);
43
+ connect(workspaceId: string, capabilities?: string[]): Promise<void>;
44
+ private connectWebSocket;
45
+ disconnect(): void;
46
+ private scheduleReconnect;
47
+ private startHeartbeat;
48
+ private stopHeartbeat;
49
+ private send;
50
+ joinWorkspace(workspaceId: string): void;
51
+ leaveWorkspace(workspaceId: string): void;
52
+ sendProgress(taskId: string, progress: number, output: string): void;
53
+ completeTask(taskId: string, result: unknown): void;
54
+ failTask(taskId: string, error: string): void;
55
+ sendChannelMessage(channelId: string, content: string): void;
56
+ private handleMessage;
57
+ isConnected(): boolean;
58
+ getAgentId(): string;
59
+ getWorkspaceId(): string | null;
60
+ displayStatus(): void;
61
+ }