@cmdctrl/cursor-cli 0.1.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/dist/adapter/cursor-cli.d.ts +36 -0
- package/dist/adapter/cursor-cli.d.ts.map +1 -0
- package/dist/adapter/cursor-cli.js +332 -0
- package/dist/adapter/cursor-cli.js.map +1 -0
- package/dist/adapter/events.d.ts +33 -0
- package/dist/adapter/events.d.ts.map +1 -0
- package/dist/adapter/events.js +53 -0
- package/dist/adapter/events.js.map +1 -0
- package/dist/client/messages.d.ts +50 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +6 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/client/websocket.d.ts +69 -0
- package/dist/client/websocket.d.ts.map +1 -0
- package/dist/client/websocket.js +272 -0
- package/dist/client/websocket.js.map +1 -0
- package/dist/commands/register.d.ts +10 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +173 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/start.d.ts +9 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +49 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +39 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +5 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +42 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +72 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/config/config.d.ts +60 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +176 -0
- package/dist/config/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
- package/src/adapter/cursor-cli.ts +370 -0
- package/src/adapter/events.ts +77 -0
- package/src/client/messages.ts +75 -0
- package/src/client/websocket.ts +308 -0
- package/src/commands/register.ts +199 -0
- package/src/commands/start.ts +64 -0
- package/src/commands/status.ts +46 -0
- package/src/commands/stop.ts +47 -0
- package/src/commands/update.ts +73 -0
- package/src/config/config.ts +146 -0
- package/src/index.ts +56 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DaemonClient = void 0;
|
|
7
|
+
const ws_1 = __importDefault(require("ws"));
|
|
8
|
+
const url_1 = require("url");
|
|
9
|
+
const cursor_cli_1 = require("../adapter/cursor-cli");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const MAX_RECONNECT_DELAY = 30000; // 30 seconds
|
|
13
|
+
const INITIAL_RECONNECT_DELAY = 1000; // 1 second
|
|
14
|
+
const PING_INTERVAL = 30000; // 30 seconds
|
|
15
|
+
class DaemonClient {
|
|
16
|
+
ws = null;
|
|
17
|
+
config;
|
|
18
|
+
credentials;
|
|
19
|
+
reconnectDelay = INITIAL_RECONNECT_DELAY;
|
|
20
|
+
reconnectTimer = null;
|
|
21
|
+
pingTimer = null;
|
|
22
|
+
shouldReconnect = true;
|
|
23
|
+
adapter;
|
|
24
|
+
constructor(config, credentials) {
|
|
25
|
+
this.config = config;
|
|
26
|
+
this.credentials = credentials;
|
|
27
|
+
this.adapter = new cursor_cli_1.CursorAdapter(this.sendEvent.bind(this));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Connect to the CmdCtrl server via WebSocket
|
|
31
|
+
*/
|
|
32
|
+
async connect() {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const serverUrl = new url_1.URL(this.config.serverUrl);
|
|
35
|
+
const wsProtocol = serverUrl.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
36
|
+
const wsUrl = `${wsProtocol}//${serverUrl.host}/ws/daemon`;
|
|
37
|
+
console.log(`Connecting to ${wsUrl}...`);
|
|
38
|
+
// Read version from package.json
|
|
39
|
+
let daemonVersion = 'unknown';
|
|
40
|
+
try {
|
|
41
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..', 'package.json'), 'utf-8'));
|
|
42
|
+
daemonVersion = pkg.version;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
try {
|
|
46
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
47
|
+
daemonVersion = pkg.version;
|
|
48
|
+
}
|
|
49
|
+
catch { /* use default */ }
|
|
50
|
+
}
|
|
51
|
+
this.ws = new ws_1.default(wsUrl, {
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: `Bearer ${this.credentials.accessToken}`,
|
|
54
|
+
'X-Device-ID': this.config.deviceId,
|
|
55
|
+
'X-Agent-Type': 'cursor_cli',
|
|
56
|
+
'X-Daemon-Version': daemonVersion,
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
this.ws.on('open', () => {
|
|
60
|
+
console.log('WebSocket connected');
|
|
61
|
+
this.reconnectDelay = INITIAL_RECONNECT_DELAY;
|
|
62
|
+
this.startPingInterval();
|
|
63
|
+
this.sendStatus();
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
this.ws.on('message', (data) => {
|
|
67
|
+
this.handleMessage(data.toString());
|
|
68
|
+
});
|
|
69
|
+
this.ws.on('close', (code, reason) => {
|
|
70
|
+
console.log(`WebSocket closed: ${code} ${reason}`);
|
|
71
|
+
this.stopPingInterval();
|
|
72
|
+
this.scheduleReconnect();
|
|
73
|
+
});
|
|
74
|
+
this.ws.on('error', (err) => {
|
|
75
|
+
console.error('WebSocket error:', err.message);
|
|
76
|
+
if (this.ws?.readyState === ws_1.default.CONNECTING) {
|
|
77
|
+
reject(err);
|
|
78
|
+
}
|
|
79
|
+
// For established connections, the 'close' event usually follows 'error',
|
|
80
|
+
// but if the connection was killed abruptly, we may not get a clean close.
|
|
81
|
+
// Force close the socket to ensure 'close' event fires and triggers reconnect.
|
|
82
|
+
if (this.ws?.readyState === ws_1.default.OPEN) {
|
|
83
|
+
this.ws.terminate();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Disconnect from server
|
|
90
|
+
*/
|
|
91
|
+
async disconnect() {
|
|
92
|
+
this.shouldReconnect = false;
|
|
93
|
+
if (this.reconnectTimer) {
|
|
94
|
+
clearTimeout(this.reconnectTimer);
|
|
95
|
+
this.reconnectTimer = null;
|
|
96
|
+
}
|
|
97
|
+
this.stopPingInterval();
|
|
98
|
+
// Stop all running tasks
|
|
99
|
+
await this.adapter.stopAll();
|
|
100
|
+
if (this.ws) {
|
|
101
|
+
this.ws.close(1000, 'Daemon shutting down');
|
|
102
|
+
this.ws = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Send a message to the server
|
|
107
|
+
*/
|
|
108
|
+
send(message) {
|
|
109
|
+
if (this.ws?.readyState === ws_1.default.OPEN) {
|
|
110
|
+
this.ws.send(JSON.stringify(message));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Send an event for a task
|
|
115
|
+
*/
|
|
116
|
+
sendEvent(taskId, eventType, data) {
|
|
117
|
+
this.send({
|
|
118
|
+
type: 'event',
|
|
119
|
+
task_id: taskId,
|
|
120
|
+
event_type: eventType,
|
|
121
|
+
...data
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Send current status to server
|
|
126
|
+
*/
|
|
127
|
+
sendStatus() {
|
|
128
|
+
this.send({
|
|
129
|
+
type: 'status',
|
|
130
|
+
running_tasks: this.adapter.getRunningTasks()
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Handle incoming message from server
|
|
135
|
+
*/
|
|
136
|
+
handleMessage(raw) {
|
|
137
|
+
let msg;
|
|
138
|
+
try {
|
|
139
|
+
msg = JSON.parse(raw);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
console.error('Failed to parse message:', raw);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
switch (msg.type) {
|
|
146
|
+
case 'ping':
|
|
147
|
+
this.send({ type: 'pong' });
|
|
148
|
+
break;
|
|
149
|
+
case 'task_start':
|
|
150
|
+
this.handleTaskStart(msg);
|
|
151
|
+
break;
|
|
152
|
+
case 'task_resume':
|
|
153
|
+
this.handleTaskResume(msg);
|
|
154
|
+
break;
|
|
155
|
+
case 'task_cancel':
|
|
156
|
+
this.handleTaskCancel(msg);
|
|
157
|
+
break;
|
|
158
|
+
case 'version_status':
|
|
159
|
+
this.handleVersionStatus(msg);
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
console.warn('Unknown message type:', msg.type);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Handle task_start message
|
|
167
|
+
*/
|
|
168
|
+
async handleTaskStart(msg) {
|
|
169
|
+
console.log(`Starting task ${msg.task_id}: ${msg.instruction.substring(0, 50)}...`);
|
|
170
|
+
try {
|
|
171
|
+
await this.adapter.startTask(msg.task_id, msg.instruction, msg.project_path);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
console.error(`Failed to start task ${msg.task_id}:`, err);
|
|
175
|
+
this.sendEvent(msg.task_id, 'ERROR', {
|
|
176
|
+
error: err.message
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Handle task_resume message
|
|
182
|
+
*/
|
|
183
|
+
async handleTaskResume(msg) {
|
|
184
|
+
console.log(`Resuming task ${msg.task_id} with session ${msg.session_id}`);
|
|
185
|
+
try {
|
|
186
|
+
await this.adapter.resumeTask(msg.task_id, msg.session_id, msg.message, msg.project_path);
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
console.error(`Failed to resume task ${msg.task_id}:`, err);
|
|
190
|
+
this.sendEvent(msg.task_id, 'ERROR', {
|
|
191
|
+
error: err.message
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Handle task_cancel message
|
|
197
|
+
*/
|
|
198
|
+
async handleTaskCancel(msg) {
|
|
199
|
+
console.log(`Cancelling task ${msg.task_id}`);
|
|
200
|
+
await this.adapter.cancelTask(msg.task_id);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Handle version_status message from server
|
|
204
|
+
*/
|
|
205
|
+
handleVersionStatus(msg) {
|
|
206
|
+
if (msg.status === 'update_required') {
|
|
207
|
+
console.error(`\n✖ Daemon version ${msg.your_version} is no longer supported (minimum: ${msg.min_version})`);
|
|
208
|
+
console.error(` Run: cmdctrl-cursor-cli update`);
|
|
209
|
+
if (msg.changelog_url)
|
|
210
|
+
console.error(` Changelog: ${msg.changelog_url}`);
|
|
211
|
+
if (msg.message)
|
|
212
|
+
console.error(` ${msg.message}`);
|
|
213
|
+
console.error('');
|
|
214
|
+
this.shouldReconnect = false;
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
else if (msg.status === 'update_available') {
|
|
218
|
+
console.warn(`\n⚠ Update available: v${msg.latest_version} (you have v${msg.your_version})`);
|
|
219
|
+
console.warn(` Run: cmdctrl-cursor-cli update`);
|
|
220
|
+
if (msg.changelog_url)
|
|
221
|
+
console.warn(` Changelog: ${msg.changelog_url}`);
|
|
222
|
+
console.warn('');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Schedule reconnection with exponential backoff
|
|
227
|
+
*/
|
|
228
|
+
scheduleReconnect() {
|
|
229
|
+
if (!this.shouldReconnect) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
console.log(`Reconnecting in ${this.reconnectDelay / 1000}s...`);
|
|
233
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
234
|
+
try {
|
|
235
|
+
await this.connect();
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Increase delay with exponential backoff
|
|
239
|
+
this.reconnectDelay = Math.min(this.reconnectDelay * 2, MAX_RECONNECT_DELAY);
|
|
240
|
+
this.scheduleReconnect();
|
|
241
|
+
}
|
|
242
|
+
}, this.reconnectDelay);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Start ping interval to keep connection alive
|
|
246
|
+
*/
|
|
247
|
+
startPingInterval() {
|
|
248
|
+
this.pingTimer = setInterval(() => {
|
|
249
|
+
if (this.ws?.readyState === ws_1.default.OPEN) {
|
|
250
|
+
this.ws.ping();
|
|
251
|
+
}
|
|
252
|
+
}, PING_INTERVAL);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Stop ping interval
|
|
256
|
+
*/
|
|
257
|
+
stopPingInterval() {
|
|
258
|
+
if (this.pingTimer) {
|
|
259
|
+
clearInterval(this.pingTimer);
|
|
260
|
+
this.pingTimer = null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Refresh access token using refresh token
|
|
265
|
+
*/
|
|
266
|
+
async refreshToken() {
|
|
267
|
+
console.log('Token refresh not yet implemented');
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
exports.DaemonClient = DaemonClient;
|
|
272
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface RegisterOptions {
|
|
2
|
+
server: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Register command - implements GitHub CLI style device auth flow
|
|
7
|
+
*/
|
|
8
|
+
export declare function register(options: RegisterOptions): Promise<void>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=register.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAaA,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA4GD;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEtE"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.register = register;
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const http = __importStar(require("http"));
|
|
39
|
+
const https = __importStar(require("https"));
|
|
40
|
+
const url_1 = require("url");
|
|
41
|
+
const config_1 = require("../config/config");
|
|
42
|
+
/**
|
|
43
|
+
* Make an HTTP(S) request
|
|
44
|
+
*/
|
|
45
|
+
function request(url, method, body) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const parsed = new url_1.URL(url);
|
|
48
|
+
const client = parsed.protocol === 'https:' ? https : http;
|
|
49
|
+
const options = {
|
|
50
|
+
hostname: parsed.hostname,
|
|
51
|
+
port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80),
|
|
52
|
+
path: parsed.pathname + parsed.search,
|
|
53
|
+
method,
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
Accept: 'application/json'
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const req = client.request(options, (res) => {
|
|
60
|
+
let data = '';
|
|
61
|
+
res.on('data', (chunk) => (data += chunk));
|
|
62
|
+
res.on('end', () => {
|
|
63
|
+
try {
|
|
64
|
+
const parsed = data ? JSON.parse(data) : {};
|
|
65
|
+
resolve({ status: res.statusCode || 0, data: parsed });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
resolve({ status: res.statusCode || 0, data: {} });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
req.on('error', reject);
|
|
73
|
+
if (body) {
|
|
74
|
+
req.write(JSON.stringify(body));
|
|
75
|
+
}
|
|
76
|
+
req.end();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Poll for token completion (after user verifies in browser)
|
|
81
|
+
*/
|
|
82
|
+
async function pollForToken(serverUrl, deviceCode, interval, expiresIn) {
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const expiresAt = startTime + expiresIn * 1000;
|
|
85
|
+
while (Date.now() < expiresAt) {
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
87
|
+
try {
|
|
88
|
+
const response = await request(`${serverUrl}/api/devices/token`, 'POST', {
|
|
89
|
+
deviceCode
|
|
90
|
+
});
|
|
91
|
+
if (response.status === 200) {
|
|
92
|
+
return response.data;
|
|
93
|
+
}
|
|
94
|
+
// 400 with "authorization_pending" means keep polling
|
|
95
|
+
const data = response.data;
|
|
96
|
+
if (response.status === 400 && data.error === 'authorization_pending') {
|
|
97
|
+
process.stdout.write('.');
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// Other errors should stop polling
|
|
101
|
+
if (response.status >= 400) {
|
|
102
|
+
console.error('\nError polling for token:', data);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error('\nError polling for token:', err);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
console.error('\nDevice code expired. Please try again.');
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Register command - implements GitHub CLI style device auth flow
|
|
116
|
+
*/
|
|
117
|
+
async function register(options) {
|
|
118
|
+
const serverUrl = options.server.replace(/\/$/, ''); // Remove trailing slash
|
|
119
|
+
const deviceName = options.name || `${os.hostname()}-cursor`;
|
|
120
|
+
// Check if already registered
|
|
121
|
+
if ((0, config_1.isRegistered)()) {
|
|
122
|
+
const config = (0, config_1.readConfig)();
|
|
123
|
+
console.log(`Already registered as "${config?.deviceName}" (${config?.deviceId})`);
|
|
124
|
+
console.log(`Server: ${config?.serverUrl}`);
|
|
125
|
+
console.log(`\nTo re-register, run: ${process.argv[1]} unregister`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.log(`Registering Cursor CLI device "${deviceName}" with ${serverUrl}...\n`);
|
|
129
|
+
// Step 1: Request device code
|
|
130
|
+
let codeResponse;
|
|
131
|
+
try {
|
|
132
|
+
const response = await request(`${serverUrl}/api/devices/code`, 'POST', {
|
|
133
|
+
deviceName,
|
|
134
|
+
hostname: os.hostname(),
|
|
135
|
+
agentType: 'cursor_cli'
|
|
136
|
+
});
|
|
137
|
+
if (response.status !== 200) {
|
|
138
|
+
console.error('Failed to get device code:', response.data);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
codeResponse = response.data;
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.error('Failed to connect to server:', err);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
// Step 2: Display instructions to user
|
|
148
|
+
console.log('To complete registration, open this URL in your browser:\n');
|
|
149
|
+
console.log(` ${codeResponse.verificationUrl}\n`);
|
|
150
|
+
console.log('Waiting for verification...');
|
|
151
|
+
// Step 3: Poll for completion
|
|
152
|
+
const tokenResponse = await pollForToken(serverUrl, codeResponse.deviceCode, codeResponse.interval, codeResponse.expiresIn);
|
|
153
|
+
if (!tokenResponse) {
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
// Step 4: Save config and credentials
|
|
157
|
+
const config = {
|
|
158
|
+
serverUrl,
|
|
159
|
+
deviceId: tokenResponse.deviceId,
|
|
160
|
+
deviceName
|
|
161
|
+
};
|
|
162
|
+
const credentials = {
|
|
163
|
+
accessToken: tokenResponse.accessToken,
|
|
164
|
+
refreshToken: tokenResponse.refreshToken,
|
|
165
|
+
expiresAt: Date.now() + tokenResponse.expiresIn * 1000
|
|
166
|
+
};
|
|
167
|
+
(0, config_1.writeConfig)(config);
|
|
168
|
+
(0, config_1.writeCredentials)(credentials);
|
|
169
|
+
console.log('\n\nRegistration complete!');
|
|
170
|
+
console.log(`Device ID: ${tokenResponse.deviceId}`);
|
|
171
|
+
console.log(`\nRun 'cmdctrl-cursor-cli start' to connect to the server.`);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AASA,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+ChE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.start = start;
|
|
4
|
+
const config_1 = require("../config/config");
|
|
5
|
+
const websocket_1 = require("../client/websocket");
|
|
6
|
+
/**
|
|
7
|
+
* Start the daemon
|
|
8
|
+
*/
|
|
9
|
+
async function start(options) {
|
|
10
|
+
// Check if registered
|
|
11
|
+
if (!(0, config_1.isRegistered)()) {
|
|
12
|
+
console.error('Device not registered. Run "cmdctrl-cursor-cli-daemon register" first.');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
// Check if already running
|
|
16
|
+
if ((0, config_1.isDaemonRunning)()) {
|
|
17
|
+
console.error('Daemon is already running. Use "cmdctrl-cursor-cli-daemon stop" to stop it.');
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const config = (0, config_1.readConfig)();
|
|
21
|
+
const credentials = (0, config_1.readCredentials)();
|
|
22
|
+
console.log(`Starting Cursor CLI daemon for device "${config.deviceName}"...`);
|
|
23
|
+
console.log(`Server: ${config.serverUrl}`);
|
|
24
|
+
// Write PID file
|
|
25
|
+
(0, config_1.writePidFile)(process.pid);
|
|
26
|
+
// Create and connect client
|
|
27
|
+
const client = new websocket_1.DaemonClient(config, credentials);
|
|
28
|
+
// Handle shutdown signals
|
|
29
|
+
const shutdown = async (signal) => {
|
|
30
|
+
console.log(`\nReceived ${signal}, shutting down...`);
|
|
31
|
+
await client.disconnect();
|
|
32
|
+
process.exit(0);
|
|
33
|
+
};
|
|
34
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
35
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
36
|
+
try {
|
|
37
|
+
await client.connect();
|
|
38
|
+
console.log('Cursor CLI daemon connected and ready for tasks.');
|
|
39
|
+
// In foreground mode, just keep running
|
|
40
|
+
if (options.foreground) {
|
|
41
|
+
console.log('Running in foreground. Press Ctrl+C to stop.');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error('Failed to connect:', err);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":";;AAgBA,sBA+CC;AA/DD,6CAM0B;AAC1B,mDAAmD;AAMnD;;GAEG;AACI,KAAK,UAAU,KAAK,CAAC,OAAqB;IAC/C,sBAAsB;IACtB,IAAI,CAAC,IAAA,qBAAY,GAAE,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,2BAA2B;IAC3B,IAAI,IAAA,wBAAe,GAAE,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAG,CAAC;IAC7B,MAAM,WAAW,GAAG,IAAA,wBAAe,GAAG,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,0CAA0C,MAAM,CAAC,UAAU,MAAM,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAE3C,iBAAiB;IACjB,IAAA,qBAAY,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1B,4BAA4B;IAC5B,MAAM,MAAM,GAAG,IAAI,wBAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAErD,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QACxC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,oBAAoB,CAAC,CAAC;QACtD,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAEhE,wCAAwC;QACxC,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAkC5C"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.status = status;
|
|
4
|
+
const config_1 = require("../config/config");
|
|
5
|
+
/**
|
|
6
|
+
* Show daemon status
|
|
7
|
+
*/
|
|
8
|
+
async function status() {
|
|
9
|
+
if (!(0, config_1.isRegistered)()) {
|
|
10
|
+
console.log('Status: Not registered');
|
|
11
|
+
console.log('\nRun "cmdctrl-cursor-cli-daemon register" to register this device.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const config = (0, config_1.readConfig)();
|
|
15
|
+
const credentials = (0, config_1.readCredentials)();
|
|
16
|
+
const running = (0, config_1.isDaemonRunning)();
|
|
17
|
+
const pid = (0, config_1.readPidFile)();
|
|
18
|
+
console.log('Cursor CLI Daemon Status');
|
|
19
|
+
console.log('========================');
|
|
20
|
+
console.log(`Device Name: ${config.deviceName}`);
|
|
21
|
+
console.log(`Device ID: ${config.deviceId}`);
|
|
22
|
+
console.log(`Server: ${config.serverUrl}`);
|
|
23
|
+
console.log();
|
|
24
|
+
console.log(`Daemon: ${running ? `Running (PID ${pid})` : 'Stopped'}`);
|
|
25
|
+
if (credentials) {
|
|
26
|
+
const expiresIn = credentials.expiresAt - Date.now();
|
|
27
|
+
const expired = expiresIn <= 0;
|
|
28
|
+
console.log(`Token: ${expired ? 'Expired' : 'Valid'}`);
|
|
29
|
+
if (!expired) {
|
|
30
|
+
const hours = Math.floor(expiresIn / 1000 / 60 / 60);
|
|
31
|
+
const minutes = Math.floor((expiresIn / 1000 / 60) % 60);
|
|
32
|
+
console.log(`Expires in: ${hours}h ${minutes}m`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!running) {
|
|
36
|
+
console.log('\nRun "cmdctrl-cursor-cli-daemon start" to start the daemon.');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":";;AAWA,wBAkCC;AA7CD,6CAM0B;AAE1B;;GAEG;AACI,KAAK,UAAU,MAAM;IAC1B,IAAI,CAAC,IAAA,qBAAY,GAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;QACnF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAG,CAAC;IAC7B,MAAM,WAAW,GAAG,IAAA,wBAAe,GAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAA,wBAAe,GAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAA,oBAAW,GAAE,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,CAAC,CAAC,gBAAgB,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAE5E,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,KAAK,OAAO,GAAG,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC1C"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stop = stop;
|
|
4
|
+
const config_1 = require("../config/config");
|
|
5
|
+
/**
|
|
6
|
+
* Stop the daemon
|
|
7
|
+
*/
|
|
8
|
+
async function stop() {
|
|
9
|
+
if (!(0, config_1.isDaemonRunning)()) {
|
|
10
|
+
console.log('Daemon is not running.');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const pid = (0, config_1.readPidFile)();
|
|
14
|
+
if (!pid) {
|
|
15
|
+
console.log('Could not find daemon PID.');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
console.log(`Stopping Cursor CLI daemon (PID ${pid})...`);
|
|
19
|
+
try {
|
|
20
|
+
// Send SIGTERM to gracefully shutdown
|
|
21
|
+
process.kill(pid, 'SIGTERM');
|
|
22
|
+
// Wait a bit for graceful shutdown
|
|
23
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
24
|
+
// Check if still running
|
|
25
|
+
try {
|
|
26
|
+
process.kill(pid, 0);
|
|
27
|
+
// Still running, send SIGKILL
|
|
28
|
+
console.log('Daemon not responding, force killing...');
|
|
29
|
+
process.kill(pid, 'SIGKILL');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Process is gone
|
|
33
|
+
}
|
|
34
|
+
(0, config_1.deletePidFile)();
|
|
35
|
+
console.log('Daemon stopped.');
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error('Failed to stop daemon:', err);
|
|
39
|
+
(0, config_1.deletePidFile)();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=stop.js.map
|