@cmdctrl/cursor-cli 0.2.0 → 0.2.2
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/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +30 -30
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +24 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/session-discovery.d.ts +62 -0
- package/dist/session-discovery.d.ts.map +1 -0
- package/dist/session-discovery.js +324 -0
- package/dist/session-discovery.js.map +1 -0
- package/dist/session-watcher.d.ts +38 -0
- package/dist/session-watcher.d.ts.map +1 -0
- package/dist/session-watcher.js +175 -0
- package/dist/session-watcher.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/start.ts +47 -36
- package/src/commands/update.ts +27 -3
- package/src/session-discovery.ts +328 -0
- package/src/session-watcher.ts +182 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AASA,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA4J3C"}
|
package/dist/commands/start.js
CHANGED
|
@@ -5,7 +5,8 @@ const fs_1 = require("fs");
|
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
const daemon_sdk_1 = require("@cmdctrl/daemon-sdk");
|
|
7
7
|
const cursor_cli_1 = require("../adapter/cursor-cli");
|
|
8
|
-
const
|
|
8
|
+
const session_discovery_1 = require("../session-discovery");
|
|
9
|
+
const session_watcher_1 = require("../session-watcher");
|
|
9
10
|
const configManager = new daemon_sdk_1.ConfigManager('cursor-cli');
|
|
10
11
|
async function start() {
|
|
11
12
|
if (!configManager.isRegistered()) {
|
|
@@ -36,27 +37,23 @@ async function start() {
|
|
|
36
37
|
console.log(` Version: ${daemonVersion}`);
|
|
37
38
|
console.log('');
|
|
38
39
|
configManager.writePidFile(process.pid);
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const
|
|
40
|
+
// Managed session IDs (started via task_start) – excluded from native discovery
|
|
41
|
+
const managedSessionIds = new Set();
|
|
42
|
+
const sessionWatcher = new session_watcher_1.CursorSessionWatcher((event) => {
|
|
43
|
+
// Only send activity for user messages – agent responses are the final
|
|
44
|
+
// answer already shown via the transcript; sending them here duplicates.
|
|
45
|
+
if (event.type !== 'USER_MESSAGE')
|
|
46
|
+
return;
|
|
47
|
+
client.sendSessionActivity(event.sessionId, '', event.content, 1, false, new Date().toISOString());
|
|
48
|
+
}, (completion) => {
|
|
49
|
+
client.sendSessionActivity(completion.sessionId, completion.filePath, completion.lastMessage, completion.messageCount, true);
|
|
50
|
+
});
|
|
42
51
|
// Event callback wired into the DaemonClient below
|
|
43
52
|
let sendEvent;
|
|
44
53
|
const adapter = new cursor_cli_1.CursorAdapter((taskId, eventType, data) => {
|
|
45
54
|
const sessionId = data.session_id;
|
|
46
|
-
// Store initial user message when session starts
|
|
47
55
|
if (eventType === 'SESSION_STARTED' && sessionId) {
|
|
48
|
-
|
|
49
|
-
if (instruction) {
|
|
50
|
-
messageStore.storeMessage(sessionId, 'USER', instruction);
|
|
51
|
-
pendingInstructions.delete(taskId);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Store agent response on completion
|
|
55
|
-
if (eventType === 'TASK_COMPLETE' && data.result) {
|
|
56
|
-
const sid = data.session_id || taskSessionMap.get(taskId);
|
|
57
|
-
if (sid) {
|
|
58
|
-
messageStore.storeMessage(sid, 'AGENT', data.result);
|
|
59
|
-
}
|
|
56
|
+
managedSessionIds.add(sessionId);
|
|
60
57
|
}
|
|
61
58
|
sendEvent(taskId, eventType, data);
|
|
62
59
|
});
|
|
@@ -67,10 +64,14 @@ async function start() {
|
|
|
67
64
|
token: credentials.refreshToken,
|
|
68
65
|
version: daemonVersion,
|
|
69
66
|
});
|
|
70
|
-
|
|
67
|
+
client.setSessionsProvider(() => (0, session_discovery_1.discoverSessions)(managedSessionIds));
|
|
71
68
|
sendEvent = (taskId, eventType, data) => {
|
|
72
|
-
//
|
|
73
|
-
//
|
|
69
|
+
// cursor-agent writes all content to transcript files – suppress OUTPUT events
|
|
70
|
+
// and strip result from TASK_COMPLETE to avoid duplicating transcript content.
|
|
71
|
+
if (eventType === 'OUTPUT')
|
|
72
|
+
return;
|
|
73
|
+
if (eventType === 'TASK_COMPLETE')
|
|
74
|
+
data = { ...data, result: '' };
|
|
74
75
|
client.send({
|
|
75
76
|
type: 'event',
|
|
76
77
|
task_id: taskId,
|
|
@@ -78,8 +79,13 @@ async function start() {
|
|
|
78
79
|
...data,
|
|
79
80
|
});
|
|
80
81
|
};
|
|
82
|
+
client.onWatchSession((sessionId, filePath) => {
|
|
83
|
+
sessionWatcher.watchSession(sessionId, filePath);
|
|
84
|
+
});
|
|
85
|
+
client.onUnwatchSession((sessionId) => {
|
|
86
|
+
sessionWatcher.unwatchSession(sessionId);
|
|
87
|
+
});
|
|
81
88
|
client.onTaskStart(async (task) => {
|
|
82
|
-
pendingInstructions.set(task.taskId, task.instruction);
|
|
83
89
|
try {
|
|
84
90
|
await adapter.startTask(task.taskId, task.instruction, task.projectPath);
|
|
85
91
|
}
|
|
@@ -88,8 +94,6 @@ async function start() {
|
|
|
88
94
|
}
|
|
89
95
|
});
|
|
90
96
|
client.onTaskResume(async (task) => {
|
|
91
|
-
messageStore.storeMessage(task.sessionId, 'USER', task.message);
|
|
92
|
-
taskSessionMap.set(task.taskId, task.sessionId);
|
|
93
97
|
try {
|
|
94
98
|
await adapter.resumeTask(task.taskId, task.sessionId, task.message, task.projectPath);
|
|
95
99
|
}
|
|
@@ -100,14 +104,9 @@ async function start() {
|
|
|
100
104
|
client.onTaskCancel(async (taskId) => {
|
|
101
105
|
await adapter.cancelTask(taskId);
|
|
102
106
|
});
|
|
107
|
+
// cursor-agent always writes to transcript files – use them as the single source of truth
|
|
103
108
|
client.onGetMessages((req) => {
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
messages: result.messages,
|
|
107
|
-
hasMore: result.hasMore,
|
|
108
|
-
oldestUuid: result.oldestUuid,
|
|
109
|
-
newestUuid: result.newestUuid,
|
|
110
|
-
};
|
|
109
|
+
return (0, session_discovery_1.readSessionMessages)(req.sessionId, req.limit, req.beforeUuid, req.afterUuid);
|
|
111
110
|
});
|
|
112
111
|
client.onVersionStatus((msg) => {
|
|
113
112
|
if (msg.status === 'update_available') {
|
|
@@ -116,6 +115,7 @@ async function start() {
|
|
|
116
115
|
});
|
|
117
116
|
const shutdown = async () => {
|
|
118
117
|
console.log('\nShutting down...');
|
|
118
|
+
sessionWatcher.unwatchAll();
|
|
119
119
|
await adapter.stopAll();
|
|
120
120
|
await client.disconnect();
|
|
121
121
|
configManager.deletePidFile();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAmCA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CA0D5C"}
|
package/dist/commands/update.js
CHANGED
|
@@ -4,6 +4,10 @@ exports.update = update;
|
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
+
const daemon_sdk_1 = require("@cmdctrl/daemon-sdk");
|
|
8
|
+
const stop_1 = require("./stop");
|
|
9
|
+
const configManager = new daemon_sdk_1.ConfigManager('cursor-cli');
|
|
10
|
+
// Get the current version from package.json
|
|
7
11
|
function getCurrentVersion() {
|
|
8
12
|
try {
|
|
9
13
|
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
@@ -19,6 +23,7 @@ function getCurrentVersion() {
|
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
}
|
|
26
|
+
// Fetch the latest version from npm registry
|
|
22
27
|
async function getLatestVersion(packageName) {
|
|
23
28
|
try {
|
|
24
29
|
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
@@ -34,6 +39,7 @@ async function getLatestVersion(packageName) {
|
|
|
34
39
|
async function update() {
|
|
35
40
|
const packageName = '@cmdctrl/cursor-cli';
|
|
36
41
|
const currentVersion = getCurrentVersion();
|
|
42
|
+
const wasRunning = configManager.isDaemonRunning();
|
|
37
43
|
console.log(`Current version: ${currentVersion}`);
|
|
38
44
|
console.log(`Checking for updates...`);
|
|
39
45
|
const latestVersion = await getLatestVersion(packageName);
|
|
@@ -45,6 +51,13 @@ async function update() {
|
|
|
45
51
|
console.log(`Already up to date (v${currentVersion}).`);
|
|
46
52
|
return;
|
|
47
53
|
}
|
|
54
|
+
// Stop daemon before updating so the old process doesn't hold stale code
|
|
55
|
+
if (wasRunning) {
|
|
56
|
+
console.log('Stopping daemon before update...');
|
|
57
|
+
(0, stop_1.stop)();
|
|
58
|
+
// Wait for stop to complete (uses setTimeout internally)
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
60
|
+
}
|
|
48
61
|
console.log(`Updating ${packageName}: v${currentVersion} → v${latestVersion}`);
|
|
49
62
|
try {
|
|
50
63
|
(0, child_process_1.execSync)(`npm install -g ${packageName}@latest`, {
|
|
@@ -56,6 +69,7 @@ async function update() {
|
|
|
56
69
|
console.error(` sudo npm install -g ${packageName}@latest`);
|
|
57
70
|
process.exit(1);
|
|
58
71
|
}
|
|
72
|
+
// Verify the update
|
|
59
73
|
try {
|
|
60
74
|
const result = (0, child_process_1.execSync)(`cmdctrl-cursor-cli --version`, { encoding: 'utf-8' }).trim();
|
|
61
75
|
console.log(`\nUpdated successfully to v${result}`);
|
|
@@ -63,7 +77,15 @@ async function update() {
|
|
|
63
77
|
catch {
|
|
64
78
|
console.log(`\nUpdate installed. Run 'cmdctrl-cursor-cli --version' to verify.`);
|
|
65
79
|
}
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
// Restart daemon if it was running before update
|
|
81
|
+
if (wasRunning) {
|
|
82
|
+
console.log('Restarting daemon...');
|
|
83
|
+
const child = (0, child_process_1.spawn)('cmdctrl-cursor-cli', ['start'], {
|
|
84
|
+
detached: true,
|
|
85
|
+
stdio: 'ignore',
|
|
86
|
+
});
|
|
87
|
+
child.unref();
|
|
88
|
+
console.log('Daemon restarted.');
|
|
89
|
+
}
|
|
68
90
|
}
|
|
69
91
|
//# sourceMappingURL=update.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor CLI Session Discovery
|
|
3
|
+
*
|
|
4
|
+
* Scans ~/.cursor/projects/<encoded-path>/agent-transcripts/<session-id>.jsonl
|
|
5
|
+
* to discover existing cursor-agent sessions.
|
|
6
|
+
*
|
|
7
|
+
* File format – each line is a JSON object:
|
|
8
|
+
* { role: "user" | "assistant", message: { content: [{ type: "text", text: "..." }] } }
|
|
9
|
+
*
|
|
10
|
+
* User messages have text wrapped in <user_query>...</user_query> tags.
|
|
11
|
+
* Session ID = filename (UUID, without .jsonl).
|
|
12
|
+
* Project path = decoded from the project directory name (hyphens → slashes).
|
|
13
|
+
*/
|
|
14
|
+
export interface ExternalSession {
|
|
15
|
+
session_id: string;
|
|
16
|
+
slug: string;
|
|
17
|
+
title: string;
|
|
18
|
+
project: string;
|
|
19
|
+
project_name: string;
|
|
20
|
+
file_path: string;
|
|
21
|
+
last_message: string;
|
|
22
|
+
last_activity: string;
|
|
23
|
+
is_active: boolean;
|
|
24
|
+
message_count: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ParsedMessage {
|
|
27
|
+
id: string;
|
|
28
|
+
role: 'user' | 'agent';
|
|
29
|
+
content: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse all messages from a cursor-agent transcript JSONL file.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseTranscriptFile(filePath: string): ParsedMessage[];
|
|
35
|
+
/**
|
|
36
|
+
* Discover all cursor-agent sessions on this device.
|
|
37
|
+
* Scans ~/.cursor/projects/<project>/agent-transcripts/<session>.jsonl
|
|
38
|
+
*/
|
|
39
|
+
export declare function discoverSessions(excludeSessionIDs?: Set<string>): ExternalSession[];
|
|
40
|
+
/**
|
|
41
|
+
* Find the file path for a given session ID.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findSessionFile(sessionId: string): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Read messages from a cursor-agent session for the CmdCtrl get_messages protocol.
|
|
46
|
+
*/
|
|
47
|
+
export declare function readSessionMessages(sessionId: string, limit: number, beforeUuid?: string, afterUuid?: string): {
|
|
48
|
+
messages: Array<{
|
|
49
|
+
uuid: string;
|
|
50
|
+
role: 'USER' | 'AGENT';
|
|
51
|
+
content: string;
|
|
52
|
+
timestamp: string;
|
|
53
|
+
}>;
|
|
54
|
+
hasMore: boolean;
|
|
55
|
+
oldestUuid?: string;
|
|
56
|
+
newestUuid?: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Generate a stable UUID from an input string.
|
|
60
|
+
*/
|
|
61
|
+
export declare function stableUuid(input: string): string;
|
|
62
|
+
//# sourceMappingURL=session-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-discovery.d.ts","sourceRoot":"","sources":["../src/session-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AA0BD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAuCrE;AAyCD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,iBAAiB,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,eAAe,EAAE,CAiF9F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBhE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAgD/J;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAShD"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cursor CLI Session Discovery
|
|
4
|
+
*
|
|
5
|
+
* Scans ~/.cursor/projects/<encoded-path>/agent-transcripts/<session-id>.jsonl
|
|
6
|
+
* to discover existing cursor-agent sessions.
|
|
7
|
+
*
|
|
8
|
+
* File format – each line is a JSON object:
|
|
9
|
+
* { role: "user" | "assistant", message: { content: [{ type: "text", text: "..." }] } }
|
|
10
|
+
*
|
|
11
|
+
* User messages have text wrapped in <user_query>...</user_query> tags.
|
|
12
|
+
* Session ID = filename (UUID, without .jsonl).
|
|
13
|
+
* Project path = decoded from the project directory name (hyphens → slashes).
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.parseTranscriptFile = parseTranscriptFile;
|
|
50
|
+
exports.discoverSessions = discoverSessions;
|
|
51
|
+
exports.findSessionFile = findSessionFile;
|
|
52
|
+
exports.readSessionMessages = readSessionMessages;
|
|
53
|
+
exports.stableUuid = stableUuid;
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
const os = __importStar(require("os"));
|
|
57
|
+
const crypto = __importStar(require("crypto"));
|
|
58
|
+
const ACTIVE_THRESHOLD_MS = 30 * 1000;
|
|
59
|
+
// Cache: file path → { session, fileMtime }
|
|
60
|
+
const sessionCache = new Map();
|
|
61
|
+
// Cache: file path → { messages, fileMtime }
|
|
62
|
+
const messageCache = new Map();
|
|
63
|
+
/**
|
|
64
|
+
* Strip <user_query>...</user_query> wrapper added by cursor-agent.
|
|
65
|
+
*/
|
|
66
|
+
function stripUserQueryTags(text) {
|
|
67
|
+
return text.replace(/^\s*<user_query>\s*/i, '').replace(/\s*<\/user_query>\s*$/i, '').trim();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract plain text from a cursor-agent message content array.
|
|
71
|
+
*/
|
|
72
|
+
function extractText(content) {
|
|
73
|
+
return content
|
|
74
|
+
.filter(b => b.type === 'text' && b.text)
|
|
75
|
+
.map(b => b.text)
|
|
76
|
+
.join('')
|
|
77
|
+
.trim();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Parse all messages from a cursor-agent transcript JSONL file.
|
|
81
|
+
*/
|
|
82
|
+
function parseTranscriptFile(filePath) {
|
|
83
|
+
try {
|
|
84
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
85
|
+
const lines = raw.split('\n').filter(l => l.trim());
|
|
86
|
+
const messages = [];
|
|
87
|
+
let idx = 0;
|
|
88
|
+
for (const line of lines) {
|
|
89
|
+
try {
|
|
90
|
+
const obj = JSON.parse(line);
|
|
91
|
+
if (!obj.role || !obj.message?.content)
|
|
92
|
+
continue;
|
|
93
|
+
let text = extractText(obj.message.content);
|
|
94
|
+
if (!text)
|
|
95
|
+
continue;
|
|
96
|
+
if (obj.role === 'user') {
|
|
97
|
+
text = stripUserQueryTags(text);
|
|
98
|
+
if (!text)
|
|
99
|
+
continue;
|
|
100
|
+
messages.push({ id: `user-${idx++}`, role: 'user', content: text });
|
|
101
|
+
}
|
|
102
|
+
else if (obj.role === 'assistant') {
|
|
103
|
+
// cursor-agent appends thinking after the first blank line – keep only the answer
|
|
104
|
+
const answerEnd = text.indexOf('\n\n');
|
|
105
|
+
if (answerEnd !== -1)
|
|
106
|
+
text = text.slice(0, answerEnd).trim();
|
|
107
|
+
if (!text)
|
|
108
|
+
continue;
|
|
109
|
+
messages.push({ id: `agent-${idx++}`, role: 'agent', content: text });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// skip invalid lines
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return messages;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Attempt to decode a cursor project directory name back to a filesystem path.
|
|
124
|
+
* The encoding replaces '/' with '-' and drops the leading '/'.
|
|
125
|
+
* e.g. "Users-mrwoof-src-testing" → "/Users/mrwoof/src/testing"
|
|
126
|
+
*
|
|
127
|
+
* We try all possible slash placements and return the first existing path.
|
|
128
|
+
* Falls back to returning the encoded name if nothing exists.
|
|
129
|
+
*/
|
|
130
|
+
function decodeProjectPath(encoded) {
|
|
131
|
+
// Simple heuristic: replace all hyphens with slashes and prepend /
|
|
132
|
+
const candidate = '/' + encoded.replace(/-/g, '/');
|
|
133
|
+
if (fs.existsSync(candidate))
|
|
134
|
+
return candidate;
|
|
135
|
+
// Walk all subdirs of ~/ looking for the encoded name match
|
|
136
|
+
// (handles paths with hyphens in component names by trying common prefixes)
|
|
137
|
+
const home = os.homedir();
|
|
138
|
+
const homeEncoded = home.replace(/^\//, '').replace(/\//g, '-');
|
|
139
|
+
if (encoded.startsWith(homeEncoded + '-')) {
|
|
140
|
+
const rest = encoded.slice(homeEncoded.length + 1);
|
|
141
|
+
const restPath = rest.replace(/-/g, '/');
|
|
142
|
+
const tryPath = path.join(home, restPath);
|
|
143
|
+
if (fs.existsSync(tryPath))
|
|
144
|
+
return tryPath;
|
|
145
|
+
}
|
|
146
|
+
return candidate;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Generate title from first user message.
|
|
150
|
+
*/
|
|
151
|
+
function generateTitle(text) {
|
|
152
|
+
const firstLine = text.split('\n')[0].trim();
|
|
153
|
+
if (firstLine.length <= 50)
|
|
154
|
+
return firstLine;
|
|
155
|
+
const truncated = firstLine.slice(0, 50);
|
|
156
|
+
const lastSpace = truncated.lastIndexOf(' ');
|
|
157
|
+
if (lastSpace > 30)
|
|
158
|
+
return truncated.slice(0, lastSpace) + '...';
|
|
159
|
+
return truncated + '...';
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Discover all cursor-agent sessions on this device.
|
|
163
|
+
* Scans ~/.cursor/projects/<project>/agent-transcripts/<session>.jsonl
|
|
164
|
+
*/
|
|
165
|
+
function discoverSessions(excludeSessionIDs = new Set()) {
|
|
166
|
+
const projectsDir = path.join(os.homedir(), '.cursor', 'projects');
|
|
167
|
+
const sessions = [];
|
|
168
|
+
if (!fs.existsSync(projectsDir))
|
|
169
|
+
return sessions;
|
|
170
|
+
let projectDirs;
|
|
171
|
+
try {
|
|
172
|
+
projectDirs = fs.readdirSync(projectsDir);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return sessions;
|
|
176
|
+
}
|
|
177
|
+
for (const projectDir of projectDirs) {
|
|
178
|
+
const transcriptsDir = path.join(projectsDir, projectDir, 'agent-transcripts');
|
|
179
|
+
if (!fs.existsSync(transcriptsDir))
|
|
180
|
+
continue;
|
|
181
|
+
const projectPath = decodeProjectPath(projectDir);
|
|
182
|
+
const projectName = path.basename(projectPath);
|
|
183
|
+
let transcriptFiles;
|
|
184
|
+
try {
|
|
185
|
+
transcriptFiles = fs.readdirSync(transcriptsDir).filter(f => f.endsWith('.jsonl'));
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
for (const file of transcriptFiles) {
|
|
191
|
+
const sessionId = file.replace('.jsonl', '');
|
|
192
|
+
if (excludeSessionIDs.has(sessionId))
|
|
193
|
+
continue;
|
|
194
|
+
const filePath = path.join(transcriptsDir, file);
|
|
195
|
+
try {
|
|
196
|
+
const stat = fs.statSync(filePath);
|
|
197
|
+
const fileMtime = stat.mtimeMs;
|
|
198
|
+
const cached = sessionCache.get(filePath);
|
|
199
|
+
if (cached && cached.fileMtime === fileMtime) {
|
|
200
|
+
const session = { ...cached.session };
|
|
201
|
+
session.is_active = Date.now() - new Date(session.last_activity).getTime() < ACTIVE_THRESHOLD_MS;
|
|
202
|
+
sessions.push(session);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const messages = parseTranscriptFile(filePath);
|
|
206
|
+
if (messages.length === 0)
|
|
207
|
+
continue;
|
|
208
|
+
const firstUser = messages.find(m => m.role === 'user');
|
|
209
|
+
const lastUser = [...messages].reverse().find(m => m.role === 'user');
|
|
210
|
+
const title = generateTitle(firstUser?.content || '') || sessionId.slice(0, 8);
|
|
211
|
+
const lastMessage = lastUser?.content.slice(0, 100) || '';
|
|
212
|
+
const lastActivity = new Date(stat.mtimeMs).toISOString();
|
|
213
|
+
const isActive = Date.now() - stat.mtimeMs < ACTIVE_THRESHOLD_MS;
|
|
214
|
+
const session = {
|
|
215
|
+
session_id: sessionId,
|
|
216
|
+
slug: '',
|
|
217
|
+
title,
|
|
218
|
+
project: projectPath,
|
|
219
|
+
project_name: projectName,
|
|
220
|
+
file_path: filePath,
|
|
221
|
+
last_message: lastMessage,
|
|
222
|
+
last_activity: lastActivity,
|
|
223
|
+
is_active: isActive,
|
|
224
|
+
message_count: messages.length,
|
|
225
|
+
};
|
|
226
|
+
sessionCache.set(filePath, { session, fileMtime });
|
|
227
|
+
sessions.push(session);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
sessions.sort((a, b) => new Date(b.last_activity).getTime() - new Date(a.last_activity).getTime());
|
|
235
|
+
return sessions;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Find the file path for a given session ID.
|
|
239
|
+
*/
|
|
240
|
+
function findSessionFile(sessionId) {
|
|
241
|
+
for (const [filePath, cached] of sessionCache.entries()) {
|
|
242
|
+
if (cached.session.session_id === sessionId)
|
|
243
|
+
return filePath;
|
|
244
|
+
}
|
|
245
|
+
const projectsDir = path.join(os.homedir(), '.cursor', 'projects');
|
|
246
|
+
if (!fs.existsSync(projectsDir))
|
|
247
|
+
return null;
|
|
248
|
+
try {
|
|
249
|
+
for (const projectDir of fs.readdirSync(projectsDir)) {
|
|
250
|
+
const candidate = path.join(projectsDir, projectDir, 'agent-transcripts', `${sessionId}.jsonl`);
|
|
251
|
+
if (fs.existsSync(candidate))
|
|
252
|
+
return candidate;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// ignore
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Read messages from a cursor-agent session for the CmdCtrl get_messages protocol.
|
|
262
|
+
*/
|
|
263
|
+
function readSessionMessages(sessionId, limit, beforeUuid, afterUuid) {
|
|
264
|
+
const filePath = findSessionFile(sessionId);
|
|
265
|
+
if (!filePath)
|
|
266
|
+
return { messages: [], hasMore: false };
|
|
267
|
+
try {
|
|
268
|
+
const stat = fs.statSync(filePath);
|
|
269
|
+
const fileMtime = stat.mtimeMs;
|
|
270
|
+
let parsed;
|
|
271
|
+
const cached = messageCache.get(filePath);
|
|
272
|
+
if (cached && cached.fileMtime === fileMtime) {
|
|
273
|
+
parsed = cached.messages;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
parsed = parseTranscriptFile(filePath);
|
|
277
|
+
messageCache.set(filePath, { messages: parsed, fileMtime });
|
|
278
|
+
}
|
|
279
|
+
// Assign sequential timestamps 1s apart, ending at file mtime, to preserve order
|
|
280
|
+
const total = parsed.filter(m => m.content.length > 0).length;
|
|
281
|
+
let seq = 0;
|
|
282
|
+
let messages = parsed.map(msg => ({
|
|
283
|
+
uuid: stableUuid(sessionId + ':' + msg.id),
|
|
284
|
+
role: (msg.role === 'user' ? 'USER' : 'AGENT'),
|
|
285
|
+
content: msg.content,
|
|
286
|
+
timestamp: new Date(stat.mtimeMs - (total - seq++) * 1000).toISOString(),
|
|
287
|
+
})).filter(m => m.content.length > 0);
|
|
288
|
+
if (beforeUuid) {
|
|
289
|
+
const idx = messages.findIndex(m => m.uuid === beforeUuid);
|
|
290
|
+
if (idx > 0)
|
|
291
|
+
messages = messages.slice(0, idx);
|
|
292
|
+
}
|
|
293
|
+
if (afterUuid) {
|
|
294
|
+
const idx = messages.findIndex(m => m.uuid === afterUuid);
|
|
295
|
+
if (idx >= 0)
|
|
296
|
+
messages = messages.slice(idx + 1);
|
|
297
|
+
}
|
|
298
|
+
const hasMore = messages.length > limit;
|
|
299
|
+
const limited = messages.slice(-limit);
|
|
300
|
+
return {
|
|
301
|
+
messages: limited,
|
|
302
|
+
hasMore,
|
|
303
|
+
oldestUuid: limited[0]?.uuid,
|
|
304
|
+
newestUuid: limited[limited.length - 1]?.uuid,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return { messages: [], hasMore: false };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Generate a stable UUID from an input string.
|
|
313
|
+
*/
|
|
314
|
+
function stableUuid(input) {
|
|
315
|
+
const hash = crypto.createHash('sha256').update(input).digest('hex');
|
|
316
|
+
return [
|
|
317
|
+
hash.slice(0, 8),
|
|
318
|
+
hash.slice(8, 12),
|
|
319
|
+
'4' + hash.slice(13, 16),
|
|
320
|
+
'8' + hash.slice(17, 20),
|
|
321
|
+
hash.slice(20, 32),
|
|
322
|
+
].join('-');
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=session-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-discovery.js","sourceRoot":"","sources":["../src/session-discovery.ts"],"names":[],"mappings":"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"}
|