Files
Elydora-Node-SDK/src/plugins/cursor-io.ts
T
雷电芽衣 81ecb372ba chore(node-sdk): audit providers claudecode codex cursor gemini
Add plugins/shell-command.ts for the shared quoting and command parsers; runtime status checks go through managed-runtime-status; Codex and Cursor write through managed-transaction.

Claude-Session: https://claude.ai/code/session_01Agoc9bRVE9KL7mmWtey9Vq
2026-09-02 21:41:26 -04:00

57 lines
1.6 KiB
TypeScript

import os from 'node:os';
import path from 'node:path';
import {
AGENT_KEY,
CONFIG_FILE,
type CursorDocument,
type RenderedDocument,
type RuntimeContract,
createDocument,
parseDocument,
} from './cursor-contract.js';
import { readPhysicalFile } from './managed-files.js';
import { managedRuntimePresent } from './managed-runtime-status.js';
import {
commitManagedTransaction,
prepareManagedFileChange,
} from './managed-transaction.js';
export function cursorConfigPath(): string {
return path.join(os.homedir(), '.cursor', CONFIG_FILE);
}
export async function readDocument(): Promise<CursorDocument> {
const filePath = cursorConfigPath();
const snapshot = await readPhysicalFile(filePath, 'Cursor user hooks');
return snapshot ? parseDocument(filePath, snapshot.contents) : createDocument(filePath);
}
export async function writeDocument(rendered: RenderedDocument): Promise<void> {
if (!rendered.changed) return;
const change = await prepareManagedFileChange({
filePath: rendered.document.filePath,
label: 'Cursor user hooks',
next: rendered.next,
mode: 0o600,
expectedSource: rendered.document.raw,
verifyExpectedSource: true,
});
if (!change) return;
await commitManagedTransaction({
displayName: 'Cursor',
operation: 'uninstall',
directories: [{
path: path.dirname(rendered.document.filePath),
label: 'Cursor hooks directory',
}],
changes: [change],
});
}
export async function runtimeFilesExist(contracts: RuntimeContract[]): Promise<boolean> {
for (const contract of contracts) {
if (await managedRuntimePresent(contract, AGENT_KEY)) return true;
}
return false;
}