@edgedive/cli 0.2.0 → 0.2.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.
package/.env ADDED
@@ -0,0 +1,2 @@
1
+ EDGEDIVE_CLIENT_ID=edgedive-cli
2
+ EDGEDIVE_API_URL=http://localhost:5001
package/.env.local ADDED
@@ -0,0 +1,2 @@
1
+ EDGEDIVE_CLIENT_ID=edgedive-cli
2
+ EDGEDIVE_API_URL=http://localhost:5001
@@ -1,5 +1,4 @@
1
-
2
- 
3
- > @edgedive/cli@0.1.8 build /Users/nimesh/edgedive/nimesh-workstream-2/packages/edgedive-cli
4
- > tsc
5
-
1
+
2
+ > @edgedive/cli@0.2.0 build /Users/nimesh/edgedive/nimesh-workstream-3/packages/edgedive-cli
3
+ > tsc
4
+
@@ -1,8 +1,8 @@
1
1
 
2
- > @edgedive/cli@0.1.8 dev /Users/nimesh/edgedive/nimesh-workstream-2/packages/edgedive-cli
2
+ > @edgedive/cli@0.2.0 dev /Users/nimesh/edgedive/edgedive-monorepo/packages/edgedive-cli
3
3
  > tsc --watch
4
4
 
5
- [4:52:03 PM] Starting compilation in watch mode...
5
+ [12:59:03 AM] Starting compilation in watch mode...
6
6
 
7
- [4:52:04 PM] Found 0 errors. Watching for file changes.
7
+ [12:59:04 AM] Found 0 errors. Watching for file changes.
8
8
 
@@ -1,4 +1,4 @@
1
1
 
2
- > @edgedive/cli@0.1.7 typecheck /Users/nimesh/edgedive/nimesh-workstream-2/packages/edgedive-cli
2
+ > @edgedive/cli@0.2.0 typecheck /Users/nimesh/edgedive/edgedive-monorepo/packages/edgedive-cli
3
3
  > tsc --noEmit
4
4
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Takeover command - download agent session for local development
3
+ */
4
+ interface TakeoverOptions {
5
+ prUrl?: string;
6
+ issueUrl?: string;
7
+ }
8
+ export declare function takeoverCommand({ prUrl, issueUrl }: TakeoverOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=takeover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"takeover.d.ts","sourceRoot":"","sources":["../../src/commands/takeover.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA6HzF"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Takeover command - download agent session for local development
3
+ */
4
+ import chalk from 'chalk';
5
+ import { ConfigManager } from '../config/config-manager.js';
6
+ import { EdgediveApiClient } from '../api/client.js';
7
+ import { SessionDownloader } from '../utils/session-downloader.js';
8
+ import { GitUtils } from '../utils/git-utils.js';
9
+ import { launchClaudeSession } from '../utils/claude-launcher.js';
10
+ export async function takeoverCommand({ prUrl, issueUrl }) {
11
+ const configManager = new ConfigManager();
12
+ const apiClient = new EdgediveApiClient(configManager);
13
+ const downloader = new SessionDownloader();
14
+ try {
15
+ console.log(chalk.bold('\nšŸ”§ Edgedive Session Takeover\n'));
16
+ // Check for Windows platform
17
+ if (process.platform === 'win32') {
18
+ console.log(chalk.red('āŒ Windows is not currently supported for the takeover command.\n'));
19
+ console.log(chalk.yellow('Please use macOS or Linux to takeover agent sessions.\n'));
20
+ process.exit(1);
21
+ }
22
+ // Check if authenticated
23
+ if (!(await configManager.isAuthenticated())) {
24
+ console.log(chalk.red('āŒ You are not logged in.\n'));
25
+ console.log(chalk.yellow('Please run: edgedive login\n'));
26
+ process.exit(1);
27
+ }
28
+ if (!prUrl && !issueUrl) {
29
+ console.log(chalk.red('āŒ Missing takeover identifier.\n'));
30
+ console.log(chalk.yellow('Provide either --pr-url https://github.com/owner/repo/pull/123 or --issue-url https://linear.app/...\n'));
31
+ process.exit(1);
32
+ }
33
+ let takeoverData;
34
+ if (prUrl) {
35
+ // Validate PR URL format
36
+ const prUrlPattern = /^https?:\/\/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/;
37
+ if (!prUrlPattern.test(prUrl)) {
38
+ console.log(chalk.red('āŒ Invalid PR URL format.\n'));
39
+ console.log(chalk.yellow('Expected format: https://github.com/owner/repo/pull/123\n'));
40
+ process.exit(1);
41
+ }
42
+ console.log(chalk.dim(`PR URL: ${prUrl}\n`));
43
+ console.log('šŸ” Fetching session information...\n');
44
+ takeoverData = await apiClient.getTakeoverByPrUrl(prUrl);
45
+ }
46
+ else {
47
+ console.log(chalk.dim(`Linear Issue URL: ${issueUrl}\n`));
48
+ console.log('šŸ” Fetching session information...\n');
49
+ takeoverData = await apiClient.getTakeoverByLinearIssueUrl(issueUrl);
50
+ }
51
+ console.log(chalk.green('āœ… Found agent session!\n'));
52
+ if (takeoverData.github_pr?.url) {
53
+ console.log(chalk.dim(`PR URL: ${takeoverData.github_pr.url}`));
54
+ }
55
+ console.log(chalk.bold('Session Information:'));
56
+ console.log(chalk.dim(` Session ID: ${takeoverData.session_id}`));
57
+ console.log(chalk.dim(` Agent Type: ${takeoverData.agent_type}`));
58
+ console.log(chalk.dim(` Status: ${takeoverData.status}`));
59
+ console.log(chalk.dim(` Repository: ${takeoverData.repository.owner}/${takeoverData.repository.name}`));
60
+ console.log(chalk.dim(` Branch: ${takeoverData.repository.branch}`));
61
+ if (takeoverData.linear_issue) {
62
+ console.log(chalk.dim(` Linear Issue: ${takeoverData.linear_issue.identifier}`));
63
+ console.log(chalk.dim(` Linear URL: ${takeoverData.linear_issue.url}`));
64
+ }
65
+ // Verify current repository matches PR source
66
+ const cwd = process.cwd();
67
+ let repoInfo;
68
+ try {
69
+ repoInfo = await GitUtils.verifyRepoMatches(takeoverData.repository.owner, takeoverData.repository.name, cwd);
70
+ }
71
+ catch (error) {
72
+ console.error(chalk.red(`\nāŒ ${error.message}\n`));
73
+ console.log(chalk.yellow('Run this command from within the target repository checked out locally.'));
74
+ process.exit(1);
75
+ }
76
+ console.log(chalk.green(`āœ… Using repository at ${repoInfo.rootPath}`));
77
+ // Download session files into Claude projects directory
78
+ const { claudeSessionId, claudeSessionPath } = await downloader.downloadSession(takeoverData, repoInfo.rootPath);
79
+ // Ensure PR branch is checked out locally
80
+ try {
81
+ await GitUtils.ensureBranchCheckedOut(takeoverData.repository.branch, repoInfo.rootPath);
82
+ console.log(chalk.green(`āœ… Checked out branch ${takeoverData.repository.branch}`));
83
+ }
84
+ catch (error) {
85
+ console.error(chalk.red(`\nāŒ Failed to checkout branch ${takeoverData.repository.branch}: ${error.message}\n`));
86
+ console.log(chalk.yellow('Resolve the git issue above and rerun the takeover command.'));
87
+ process.exit(1);
88
+ }
89
+ console.log(chalk.blue(`\nšŸš€ Launching Claude session ${claudeSessionId}...\n`));
90
+ try {
91
+ await launchClaudeSession(claudeSessionId, repoInfo.rootPath);
92
+ console.log(chalk.green('\nāœ… Claude session closed. Happy debugging!\n'));
93
+ }
94
+ catch (error) {
95
+ console.error(chalk.red(`\nāŒ Failed to start Claude automatically: ${error.message}\n`));
96
+ console.log(chalk.yellow(`You can resume manually with: claude -r ${claudeSessionId} (from ${repoInfo.rootPath})`));
97
+ process.exit(1);
98
+ }
99
+ }
100
+ catch (error) {
101
+ console.error(chalk.red(`\nāŒ Takeover failed: ${error.message}\n`));
102
+ if (error.message.includes('401') || error.message.includes('Unauthorized')) {
103
+ console.log(chalk.yellow('Your session may have expired. Please run: edgedive login\n'));
104
+ }
105
+ process.exit(1);
106
+ }
107
+ }
108
+ //# sourceMappingURL=takeover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"takeover.js","sourceRoot":"","sources":["../../src/commands/takeover.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedive/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Edgedive CLI for agent session takeover and management",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api/client.ts CHANGED
@@ -27,6 +27,10 @@ export interface TakeoverResponse {
27
27
  identifier: string;
28
28
  url: string;
29
29
  };
30
+ asana_task?: {
31
+ gid: string;
32
+ url: string;
33
+ };
30
34
  status: string;
31
35
  agent_type: string;
32
36
  download_urls: {
@@ -136,6 +140,46 @@ export class EdgediveApiClient {
136
140
  }
137
141
  }
138
142
 
143
+ /**
144
+ * Get session takeover information by Asana task URL
145
+ */
146
+ async getTakeoverByAsanaTaskUrl(asanaTaskUrl: string): Promise<TakeoverResponse> {
147
+ try {
148
+ const response = await this.client.get<TakeoverResponse>(API_CONFIG.TAKEOVER_PATH, {
149
+ params: {
150
+ asana_task_url: asanaTaskUrl,
151
+ },
152
+ });
153
+ return response.data;
154
+ } catch (error: any) {
155
+ if (error.response) {
156
+ const errorData = error.response.data;
157
+ throw new Error(errorData?.error || `API request failed: ${error.response.status}`);
158
+ }
159
+ throw new Error(`API request failed: ${error.message}`);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Get session takeover information by session URL (share link)
165
+ */
166
+ async getTakeoverBySessionUrl(sessionUrl: string): Promise<TakeoverResponse> {
167
+ try {
168
+ const response = await this.client.get<TakeoverResponse>(API_CONFIG.TAKEOVER_PATH, {
169
+ params: {
170
+ session_url: sessionUrl,
171
+ },
172
+ });
173
+ return response.data;
174
+ } catch (error: any) {
175
+ if (error.response) {
176
+ const errorData = error.response.data;
177
+ throw new Error(errorData?.error || `API request failed: ${error.response.status}`);
178
+ }
179
+ throw new Error(`API request failed: ${error.message}`);
180
+ }
181
+ }
182
+
139
183
  /**
140
184
  * Upload Claude session file for an agent session
141
185
  */
@@ -13,6 +13,8 @@ interface LocalOptions {
13
13
  prUrl?: string;
14
14
  issueUrl?: string;
15
15
  threadUrl?: string;
16
+ taskUrl?: string;
17
+ sessionUrl?: string;
16
18
  worktree?: boolean;
17
19
  }
18
20
 
@@ -20,6 +22,8 @@ export async function localCommand({
20
22
  prUrl,
21
23
  issueUrl,
22
24
  threadUrl,
25
+ taskUrl,
26
+ sessionUrl,
23
27
  worktree,
24
28
  }: LocalOptions): Promise<void> {
25
29
  const configManager = new ConfigManager();
@@ -43,14 +47,16 @@ export async function localCommand({
43
47
  process.exit(1);
44
48
  }
45
49
 
46
- if (!prUrl && !issueUrl && !threadUrl) {
50
+ if (!prUrl && !issueUrl && !threadUrl && !taskUrl && !sessionUrl) {
47
51
  console.log(chalk.red('āŒ Missing session identifier.\n'));
48
52
  console.log(
49
53
  chalk.yellow(
50
54
  'Provide one of:\n' +
51
55
  ' --pr-url https://github.com/owner/repo/pull/123\n' +
52
56
  ' --issue-url https://linear.app/...\n' +
53
- ' --thread-url https://workspace.slack.com/archives/C12345/p1234567890123456\n'
57
+ ' --thread-url https://workspace.slack.com/archives/C12345/p1234567890123456\n' +
58
+ ' --task-url https://app.asana.com/0/PROJECT_ID/TASK_ID\n' +
59
+ ' --session-url https://app.edgedive.com/agent-sessions?session={session_id}\n'
54
60
  )
55
61
  );
56
62
  process.exit(1);
@@ -74,6 +80,37 @@ export async function localCommand({
74
80
  console.log(chalk.dim(`Linear Issue URL: ${issueUrl}\n`));
75
81
  console.log('šŸ” Fetching session information...\n');
76
82
  sessionData = await apiClient.getTakeoverByLinearIssueUrl(issueUrl);
83
+ } else if (taskUrl) {
84
+ // Validate it's an Asana URL — let the server handle detailed format parsing
85
+ const asanaTaskPattern = /^https?:\/\/app\.asana\.com\//;
86
+ if (!asanaTaskPattern.test(taskUrl)) {
87
+ console.log(
88
+ chalk.red(
89
+ 'āŒ Invalid Asana task URL. Expected a URL starting with https://app.asana.com/\n'
90
+ )
91
+ );
92
+ process.exit(1);
93
+ }
94
+
95
+ console.log(chalk.dim(`Asana Task URL: ${taskUrl}\n`));
96
+ console.log('šŸ” Fetching session information...\n');
97
+ sessionData = await apiClient.getTakeoverByAsanaTaskUrl(taskUrl);
98
+ } else if (sessionUrl) {
99
+ // Validate session URL format
100
+ const sessionUrlPattern = /^https?:\/\/[^\/]+\/agent-sessions\?session=([a-f0-9-]+)/i;
101
+ if (!sessionUrlPattern.test(sessionUrl)) {
102
+ console.log(chalk.red('āŒ Invalid session URL format.\n'));
103
+ console.log(
104
+ chalk.yellow(
105
+ 'Expected format: https://app.edgedive.com/agent-sessions?session={session_id}\n'
106
+ )
107
+ );
108
+ process.exit(1);
109
+ }
110
+
111
+ console.log(chalk.dim(`Session URL: ${sessionUrl}\n`));
112
+ console.log('šŸ” Fetching session information...\n');
113
+ sessionData = await apiClient.getTakeoverBySessionUrl(sessionUrl);
77
114
  } else {
78
115
  // Validate Slack thread URL format
79
116
  const slackThreadPattern = /^https?:\/\/[^\/]+\.slack\.com\/archives\/([A-Z0-9]+)\/p(\d{16})/;
@@ -110,6 +147,10 @@ export async function localCommand({
110
147
  console.log(chalk.dim(` Linear URL: ${sessionData.linear_issue.url}`));
111
148
  }
112
149
 
150
+ if (sessionData.asana_task) {
151
+ console.log(chalk.dim(` Asana Task: ${sessionData.asana_task.url}`));
152
+ }
153
+
113
154
  // Verify current repository matches PR source
114
155
  const cwd = process.cwd();
115
156
  let repoInfo;
package/src/constants.ts CHANGED
@@ -13,7 +13,7 @@ export const OAUTH_CONFIG = {
13
13
 
14
14
  // API configuration
15
15
  export const API_CONFIG = {
16
- BASE_URL: 'https://api.edgedive.com',
16
+ BASE_URL: process.env.EDGEDIVE_API_URL || 'https://api.edgedive.com',
17
17
  AUTHORIZE_PATH: '/api/oauth/authorize',
18
18
  TOKEN_PATH: '/api/oauth/token',
19
19
  TAKEOVER_PATH: '/api/agents/agent-sessions/takeover',
package/src/index.ts CHANGED
@@ -43,12 +43,16 @@ program
43
43
  .option('--pr-url <prUrl>', 'GitHub PR URL to load locally')
44
44
  .option('--issue-url <issueUrl>', 'Linear issue URL to load locally')
45
45
  .option('--thread-url <threadUrl>', 'Slack thread URL to load locally')
46
+ .option('--task-url <taskUrl>', 'Asana task URL to load locally')
47
+ .option('--session-url <sessionUrl>', 'Session share URL to load locally')
46
48
  .option('--worktree', 'Create branch in a worktree instead of checking out')
47
49
  .action(
48
50
  async (options: {
49
51
  prUrl?: string;
50
52
  issueUrl?: string;
51
53
  threadUrl?: string;
54
+ taskUrl?: string;
55
+ sessionUrl?: string;
52
56
  worktree?: boolean;
53
57
  }) => {
54
58
  await localCommand(options);