refactor: rename coding-agent executor to cursor-agent (closes #33)

- Rename coding-agent.ts → cursor-agent.ts
- Rename coding-agent.test.ts → cursor-agent.test.ts
- Rename CodingEffect → CursorEffect
- Rename createCodingExecutor → createCursorExecutor
- Update all imports, re-exports, and CONTRIBUTING.md references

Made-with: Cursor

Co-authored-by: 小橘 <xiaoju@shazhou.work>
This commit is contained in:
小橘 🍊
2026-04-14 22:42:15 +08:00
committed by GitHub
parent 7d73efd298
commit d3bdf09a7e
4 changed files with 28 additions and 28 deletions
@@ -1,5 +1,5 @@
/**
* Tests for coding-agent executor.
* Tests for cursor-agent executor.
*
* Uses stub binaries to avoid actually spawning Cursor Agent.
* Verifies prompt file content, error handling, and result structure.
@@ -16,7 +16,7 @@ import {
} from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { type CodingEffect, createCodingExecutor } from './coding-agent.js';
import { type CursorEffect, createCursorExecutor } from './cursor-agent.js';
const TEST_TMP = join(tmpdir(), `pulse-coding-test-${process.pid}`);
const STUB_DIR = join(TEST_TMP, 'stubs');
@@ -38,7 +38,7 @@ function makeStub(name: string, script: string): string {
return path;
}
function makeEffect(overrides?: Partial<CodingEffect>): CodingEffect {
function makeEffect(overrides?: Partial<CursorEffect>): CursorEffect {
return {
type: 'coding-task',
prompt: 'Fix the broken test in store.test.ts',
@@ -48,9 +48,9 @@ function makeEffect(overrides?: Partial<CodingEffect>): CodingEffect {
};
}
describe('createCodingExecutor', () => {
describe('createCursorExecutor', () => {
test('returns a function', () => {
const exec = createCodingExecutor({ tmpDir: TEST_TMP });
const exec = createCursorExecutor({ tmpDir: TEST_TMP });
expect(typeof exec).toBe('function');
});
@@ -76,20 +76,20 @@ describe('createCodingExecutor', () => {
test('rejects unexpected effect type', async () => {
const agentStub = makeStub('agent-type-check', 'exit 0');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-key',
agentBin: agentStub,
});
const badEffect = { ...makeEffect(), type: 'other-task' } as CodingEffect;
const badEffect = { ...makeEffect(), type: 'other-task' } as CursorEffect;
expect(exec(badEffect)).rejects.toThrow('Unexpected effect type');
});
});
describe('CodingEffect structure', () => {
describe('CursorEffect structure', () => {
test('required fields', () => {
const effect: CodingEffect = {
const effect: CursorEffect = {
type: 'coding-task',
prompt: 'do something',
scenario: 'debug',
@@ -103,7 +103,7 @@ describe('CodingEffect structure', () => {
});
test('optional timeoutMs', () => {
const effect: CodingEffect = {
const effect: CursorEffect = {
type: 'coding-task',
prompt: 'do something',
scenario: 'ci-fix',
@@ -145,7 +145,7 @@ describe('prompt assembly', () => {
// Stub reads the prompt file path (last positional arg) and cats it
const catLastArg = 'cat "$' + '{@: -1}"';
const agentStub = makeStub(`agent-${scenario}`, catLastArg);
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-api-key',
agentBin: agentStub,
@@ -162,7 +162,7 @@ describe('prompt assembly', () => {
describe('temp file cleanup', () => {
test('prompt file is deleted after execution', async () => {
const agentStub = makeStub('agent-cleanup', 'exit 0');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-key',
agentBin: agentStub,
@@ -179,7 +179,7 @@ describe('temp file cleanup', () => {
test('prompt file is deleted even on failure', async () => {
const agentStub = makeStub('agent-cleanup-fail', 'exit 1');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-key',
agentBin: agentStub,
@@ -197,7 +197,7 @@ describe('temp file cleanup', () => {
describe('error handling', () => {
test('missing apiKey and failed apiKeyCommand throws', async () => {
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKeyCommand: '/nonexistent/path/to/binary',
agentBin: '/bin/echo',
@@ -211,7 +211,7 @@ describe('error handling', () => {
test('agent exit code 1 returns success=false', async () => {
const failStub = makeStub('agent-fail', 'exit 1');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-key',
agentBin: failStub,
@@ -225,7 +225,7 @@ describe('error handling', () => {
test('agent exit code 0 returns success=true', async () => {
const okStub = makeStub('agent-ok', 'echo "task done"; exit 0');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'test-key',
agentBin: okStub,
@@ -244,7 +244,7 @@ describe('API key caching', () => {
test('apiKey is resolved once and cached', async () => {
const keyStub = makeStub('key-counter', `echo "cached-key-$(date +%s%N)"`);
const agentStub = makeStub('agent-cache', 'exit 0');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKeyCommand: keyStub,
agentBin: agentStub,
@@ -259,7 +259,7 @@ describe('API key caching', () => {
test('direct apiKey skips command resolution', async () => {
const agentStub = makeStub('agent-direct', 'exit 0');
const exec = createCodingExecutor({
const exec = createCursorExecutor({
tmpDir: TEST_TMP,
apiKey: 'direct-key',
apiKeyCommand: '/nonexistent/should-not-be-called',
@@ -1,8 +1,8 @@
/**
* executors/coding-agent.ts Coding Agent Executor
* executors/cursor-agent.ts Cursor Agent Executor
*
* Spawns a Cursor Agent CLI process to execute coding tasks.
* The executor is intentionally thin: it only translates a CodingEffect
* The executor is intentionally thin: it only translates a CursorEffect
* into a CLI invocation. All intelligence (clone, branch, test, PR)
* lives in the coding agent driven by repo conventions and scenario prompts.
*
@@ -22,7 +22,7 @@ export type CodingScenario =
| 'ci-fix'
| 'refactor';
export interface CodingEffect {
export interface CursorEffect {
type: 'coding-task';
/** Task description assembled by the triggering Rule. */
prompt: string;
@@ -96,10 +96,10 @@ const SCENARIO_PREAMBLES: Record<CodingScenario, string> = {
/**
* Create a coding agent executor with the given options.
*
* Returns an async function that accepts a CodingEffect and spawns
* Returns an async function that accepts a CursorEffect and spawns
* the Cursor Agent CLI to execute the task.
*/
export function createCodingExecutor(opts: CodingExecutorOptions = {}) {
export function createCursorExecutor(opts: CodingExecutorOptions = {}) {
const {
agentBin = `${process.env.HOME}/.local/bin/agent`,
apiKey: directApiKey,
@@ -111,7 +111,7 @@ export function createCodingExecutor(opts: CodingExecutorOptions = {}) {
let cachedApiKey: string | undefined = directApiKey;
return async function executeCodingTask(
effect: CodingEffect,
effect: CursorEffect,
): Promise<CodingResult> {
if (effect.type !== 'coding-task') {
throw new Error(`Unexpected effect type: ${effect.type}`);
+3 -3
View File
@@ -1,7 +1,7 @@
export {
type CodingEffect,
type CodingExecutorOptions,
type CodingResult,
type CodingScenario,
createCodingExecutor,
} from './coding-agent.js';
type CursorEffect,
createCursorExecutor,
} from './cursor-agent.js';