@edgedive/cli 0.2.1 → 0.3.1

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 (53) hide show
  1. package/dist/api/client.d.ts +12 -0
  2. package/dist/api/client.js +40 -0
  3. package/dist/commands/local.d.ts +3 -1
  4. package/dist/commands/local.js +31 -3
  5. package/dist/constants.js +1 -1
  6. package/dist/index.js +2 -0
  7. package/package.json +1 -1
  8. package/.env +0 -2
  9. package/.env.local +0 -2
  10. package/.turbo/turbo-build.log +0 -4
  11. package/.turbo/turbo-dev.log +0 -8
  12. package/.turbo/turbo-typecheck.log +0 -4
  13. package/AGENTS.md +0 -135
  14. package/CLAUDE.md +0 -3
  15. package/dist/api/client.d.ts.map +0 -1
  16. package/dist/api/client.js.map +0 -1
  17. package/dist/auth/oauth-flow.d.ts.map +0 -1
  18. package/dist/auth/oauth-flow.js.map +0 -1
  19. package/dist/auth/pkce.d.ts.map +0 -1
  20. package/dist/auth/pkce.js.map +0 -1
  21. package/dist/commands/local.d.ts.map +0 -1
  22. package/dist/commands/local.js.map +0 -1
  23. package/dist/commands/login.d.ts.map +0 -1
  24. package/dist/commands/login.js.map +0 -1
  25. package/dist/commands/logout.d.ts.map +0 -1
  26. package/dist/commands/logout.js.map +0 -1
  27. package/dist/commands/takeover.d.ts.map +0 -1
  28. package/dist/commands/takeover.js.map +0 -1
  29. package/dist/config/config-manager.d.ts.map +0 -1
  30. package/dist/config/config-manager.js.map +0 -1
  31. package/dist/constants.d.ts.map +0 -1
  32. package/dist/constants.js.map +0 -1
  33. package/dist/index.d.ts.map +0 -1
  34. package/dist/index.js.map +0 -1
  35. package/dist/utils/claude-launcher.d.ts.map +0 -1
  36. package/dist/utils/claude-launcher.js.map +0 -1
  37. package/dist/utils/git-utils.d.ts.map +0 -1
  38. package/dist/utils/git-utils.js.map +0 -1
  39. package/dist/utils/session-downloader.d.ts.map +0 -1
  40. package/dist/utils/session-downloader.js.map +0 -1
  41. package/src/api/client.ts +0 -202
  42. package/src/auth/oauth-flow.ts +0 -278
  43. package/src/auth/pkce.ts +0 -27
  44. package/src/commands/local.ts +0 -286
  45. package/src/commands/login.ts +0 -48
  46. package/src/commands/logout.ts +0 -29
  47. package/src/config/config-manager.ts +0 -120
  48. package/src/constants.ts +0 -34
  49. package/src/index.ts +0 -62
  50. package/src/utils/claude-launcher.ts +0 -94
  51. package/src/utils/git-utils.ts +0 -179
  52. package/src/utils/session-downloader.ts +0 -56
  53. package/tsconfig.json +0 -20
@@ -1,179 +0,0 @@
1
- import { promisify } from 'util';
2
- import { exec as execCb } from 'child_process';
3
- import * as path from 'path';
4
- import * as fs from 'fs/promises';
5
-
6
- const exec = promisify(execCb);
7
-
8
- export interface RepoVerification {
9
- rootPath: string;
10
- remoteUrl: string;
11
- }
12
-
13
- function parseGithubRemote(remoteUrl: string): { owner: string; repo: string } | null {
14
- const patterns = [/github\.com[:/](?<owner>[^/]+)\/(?<repo>[^/.]+)(?:\.git)?$/];
15
-
16
- for (const pattern of patterns) {
17
- const match = remoteUrl.match(pattern);
18
- if (match && match.groups) {
19
- return {
20
- owner: match.groups.owner.toLowerCase(),
21
- repo: match.groups.repo.toLowerCase(),
22
- };
23
- }
24
- }
25
-
26
- return null;
27
- }
28
-
29
- async function runGit(command: string, cwd: string): Promise<string> {
30
- const { stdout } = await exec(`git ${command}`, { cwd });
31
- return stdout.trim();
32
- }
33
-
34
- export class GitUtils {
35
- static async getRepoRoot(cwd: string): Promise<string> {
36
- return runGit('rev-parse --show-toplevel', cwd);
37
- }
38
-
39
- static async verifyRepoMatches(
40
- expectedOwner: string,
41
- expectedName: string,
42
- cwd: string
43
- ): Promise<RepoVerification> {
44
- const rootPath = await this.getRepoRoot(cwd);
45
- const remoteUrl = await runGit('remote get-url origin', rootPath);
46
-
47
- const parsed = parseGithubRemote(remoteUrl);
48
- if (!parsed) {
49
- throw new Error(
50
- 'Could not parse the origin remote URL. Ensure this repository is linked to GitHub.'
51
- );
52
- }
53
-
54
- const matchesOwner = parsed.owner === expectedOwner.toLowerCase();
55
- const matchesRepo = parsed.repo === expectedName.toLowerCase();
56
-
57
- if (!matchesOwner || !matchesRepo) {
58
- throw new Error(
59
- `This repository (${parsed.owner}/${parsed.repo}) does not match the PR source ${expectedOwner}/${expectedName}.`
60
- );
61
- }
62
-
63
- return { rootPath, remoteUrl };
64
- }
65
-
66
- static async ensureBranchCheckedOut(branch: string, rootPath: string): Promise<void> {
67
- // Get current branch
68
- const currentBranch = await runGit('rev-parse --abbrev-ref HEAD', rootPath);
69
-
70
- // Check if local branch exists
71
- const localBranchExists = await exec(`git rev-parse --verify ${branch}`, { cwd: rootPath })
72
- .then(() => true)
73
- .catch(() => false);
74
-
75
- // Try to fetch from remote (non-blocking - remote branch may not exist yet)
76
- let remoteBranchExists = false;
77
- try {
78
- await runGit(`fetch origin ${branch}`, rootPath);
79
- // Verify the remote branch exists
80
- await runGit(`rev-parse --verify origin/${branch}`, rootPath);
81
- remoteBranchExists = true;
82
- } catch {
83
- // Remote branch doesn't exist or fetch failed, continue anyway
84
- remoteBranchExists = false;
85
- }
86
-
87
- // If already on the target branch
88
- if (currentBranch === branch) {
89
- // Pull from remote if it exists
90
- if (remoteBranchExists) {
91
- await runGit(`pull origin ${branch}`, rootPath);
92
- }
93
- return;
94
- }
95
-
96
- // If local branch exists, check it out
97
- if (localBranchExists) {
98
- await runGit(`checkout ${branch}`, rootPath);
99
- // Pull from remote if it exists
100
- if (remoteBranchExists) {
101
- await runGit(`pull origin ${branch}`, rootPath);
102
- }
103
- return;
104
- }
105
-
106
- // Local branch doesn't exist, create it
107
- if (remoteBranchExists) {
108
- // Create from remote
109
- await runGit(`checkout -b ${branch} origin/${branch}`, rootPath);
110
- } else {
111
- // Remote doesn't exist, create from current HEAD
112
- await runGit(`checkout -b ${branch}`, rootPath);
113
- }
114
- }
115
-
116
- /**
117
- * Ensure a branch exists in a git worktree at a sibling directory.
118
- * Returns the path to the worktree.
119
- */
120
- static async ensureBranchInWorktree(branch: string, rootPath: string): Promise<string> {
121
- // Sanitize branch name for directory: replace slashes with dashes
122
- const sanitizedBranchName = branch.replace(/\//g, '-');
123
-
124
- // Calculate worktree path as sibling directory
125
- const parentDir = path.dirname(rootPath);
126
- const worktreePath = path.join(parentDir, sanitizedBranchName);
127
-
128
- // Check if worktree already exists
129
- try {
130
- await fs.access(worktreePath);
131
- // Worktree directory exists, verify it's a valid git worktree
132
- try {
133
- await runGit('rev-parse --git-dir', worktreePath);
134
- // It's a valid git directory, return the path
135
- return worktreePath;
136
- } catch {
137
- // Directory exists but is not a git worktree
138
- throw new Error(
139
- `Directory ${worktreePath} already exists but is not a git worktree. ` +
140
- `Please remove it or choose a different branch name.`
141
- );
142
- }
143
- } catch {
144
- // Worktree doesn't exist, we'll create it
145
- }
146
-
147
- // Check if local branch exists
148
- const localBranchExists = await exec(`git rev-parse --verify ${branch}`, { cwd: rootPath })
149
- .then(() => true)
150
- .catch(() => false);
151
-
152
- // Try to fetch from remote
153
- let remoteBranchExists = false;
154
- try {
155
- await runGit(`fetch origin ${branch}`, rootPath);
156
- await runGit(`rev-parse --verify origin/${branch}`, rootPath);
157
- remoteBranchExists = true;
158
- } catch {
159
- remoteBranchExists = false;
160
- }
161
-
162
- // Create worktree based on what exists
163
- if (localBranchExists) {
164
- // Local branch exists, create worktree from it
165
- await runGit(`worktree add "${worktreePath}" ${branch}`, rootPath);
166
- } else if (remoteBranchExists) {
167
- // Remote branch exists, create worktree tracking it
168
- await runGit(
169
- `worktree add --track -b ${branch} "${worktreePath}" origin/${branch}`,
170
- rootPath
171
- );
172
- } else {
173
- // Neither exists, create new branch in worktree from current HEAD
174
- await runGit(`worktree add -b ${branch} "${worktreePath}"`, rootPath);
175
- }
176
-
177
- return worktreePath;
178
- }
179
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * Utility for downloading agent session files from S3
3
- */
4
-
5
- import fs from 'fs/promises';
6
- import path from 'path';
7
- import os from 'os';
8
- import axios from 'axios';
9
- import { LOCAL_CONFIG, TIMEOUTS } from '../constants.js';
10
- import type { TakeoverResponse } from '../api/client.js';
11
-
12
- export class SessionDownloader {
13
- private sanitizeWorkspacePath(workspacePath: string): string {
14
- return workspacePath.replace(/[\\/_.]/g, '-');
15
- }
16
-
17
- private getClaudeProjectDir(workspacePath: string): string {
18
- const homeDir = os.homedir();
19
- const sanitized = this.sanitizeWorkspacePath(workspacePath);
20
- return path.join(homeDir, LOCAL_CONFIG.CLAUDE_DIR, LOCAL_CONFIG.CLAUDE_PROJECTS_DIR, sanitized);
21
- }
22
-
23
- private async downloadFile(url: string, targetPath: string): Promise<void> {
24
- try {
25
- const response = await axios.get(url, {
26
- responseType: 'arraybuffer',
27
- timeout: TIMEOUTS.DEFAULT_REQUEST_MS,
28
- });
29
-
30
- await fs.writeFile(targetPath, Buffer.from(response.data));
31
- } catch (error: any) {
32
- throw new Error(`Failed to download file to ${targetPath}: ${error.message}`);
33
- }
34
- }
35
-
36
- async downloadSession(
37
- sessionData: TakeoverResponse,
38
- workspacePath: string
39
- ): Promise<{ claudeSessionId: string; claudeSessionPath: string }> {
40
- let claudeSessionId = sessionData.session_id;
41
-
42
- if (!sessionData.download_urls.claude_session) {
43
- throw new Error('No Claude session file available for this agent session.');
44
- }
45
-
46
- const claudeProjectDir = this.getClaudeProjectDir(workspacePath);
47
- await fs.mkdir(claudeProjectDir, { recursive: true });
48
-
49
- const claudeSessionPath = path.join(claudeProjectDir, `${claudeSessionId}.jsonl`);
50
- await this.downloadFile(sessionData.download_urls.claude_session, claudeSessionPath);
51
-
52
- console.log(`\nšŸ“ Restored Claude session to: ${claudeSessionPath}\n`);
53
-
54
- return { claudeSessionId, claudeSessionPath };
55
- }
56
- }
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "lib": ["ES2022"],
6
- "moduleResolution": "node",
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "resolveJsonModule": true,
14
- "declaration": true,
15
- "declarationMap": true,
16
- "sourceMap": true
17
- },
18
- "include": ["src/**/*"],
19
- "exclude": ["node_modules", "dist"]
20
- }