mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
feat(server): Add readOnly mode to Cursor provider for read-only operations
Adds a readOnly option to ExecuteOptions that controls whether the Cursor CLI runs with --force flag (allows edits) or without (suggest-only). Read-only routes now pass readOnly: true: - generate-spec.ts, generate-features-from-spec.ts (we write files ourselves) - validate-issue.ts, generate-suggestions.ts (analysis only) - describe-file.ts, describe-image.ts (description only) - generate-plan.ts, enhance.ts (text generation only) Routes that implement features (auto-mode-service, agent-service) keep the default (readOnly: false) to allow file modifications. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -140,12 +140,18 @@ export class CursorProvider extends CliProvider {
|
|||||||
// shell escaping issues when content contains $(), backticks, etc.
|
// shell escaping issues when content contains $(), backticks, etc.
|
||||||
const cliArgs: string[] = [
|
const cliArgs: string[] = [
|
||||||
'-p', // Print mode (non-interactive)
|
'-p', // Print mode (non-interactive)
|
||||||
'--force', // Allow file modifications
|
|
||||||
'--output-format',
|
'--output-format',
|
||||||
'stream-json',
|
'stream-json',
|
||||||
'--stream-partial-output', // Real-time streaming
|
'--stream-partial-output', // Real-time streaming
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Only add --force if NOT in read-only mode
|
||||||
|
// Without --force, Cursor CLI suggests changes but doesn't apply them
|
||||||
|
// With --force, Cursor CLI can actually edit files
|
||||||
|
if (!options.readOnly) {
|
||||||
|
cliArgs.push('--force');
|
||||||
|
}
|
||||||
|
|
||||||
// Add model if not auto
|
// Add model if not auto
|
||||||
if (model !== 'auto') {
|
if (model !== 'auto') {
|
||||||
cliArgs.push('--model', model);
|
cliArgs.push('--model', model);
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ export interface ExecuteOptions {
|
|||||||
conversationHistory?: ConversationMessage[]; // Previous messages for context
|
conversationHistory?: ConversationMessage[]; // Previous messages for context
|
||||||
sdkSessionId?: string; // Claude SDK session ID for resuming conversations
|
sdkSessionId?: string; // Claude SDK session ID for resuming conversations
|
||||||
settingSources?: Array<'user' | 'project' | 'local'>; // Claude filesystem settings to load
|
settingSources?: Array<'user' | 'project' | 'local'>; // Claude filesystem settings to load
|
||||||
|
/**
|
||||||
|
* If true, the provider should run in read-only mode (no file modifications).
|
||||||
|
* For Cursor CLI, this omits the --force flag, making it suggest-only.
|
||||||
|
* Default: false (allows edits)
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ IMPORTANT: Do not ask for clarification. The specification is provided above. Ge
|
|||||||
maxTurns: 250,
|
maxTurns: 250,
|
||||||
allowedTools: ['Read', 'Glob', 'Grep'],
|
allowedTools: ['Read', 'Glob', 'Grep'],
|
||||||
abortController,
|
abortController,
|
||||||
|
readOnly: true, // Feature generation only reads code, doesn't write
|
||||||
})) {
|
})) {
|
||||||
messageCount++;
|
messageCount++;
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ ${JSON.stringify(specOutputSchema, null, 2)}`;
|
|||||||
maxTurns: 250,
|
maxTurns: 250,
|
||||||
allowedTools: ['Read', 'Glob', 'Grep'],
|
allowedTools: ['Read', 'Glob', 'Grep'],
|
||||||
abortController,
|
abortController,
|
||||||
|
readOnly: true, // Spec generation only reads code, we write the spec ourselves
|
||||||
})) {
|
})) {
|
||||||
messageCount++;
|
messageCount++;
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ Please analyze the current backlog and the user's request, then provide a JSON p
|
|||||||
allowedTools: [], // No tools needed for this
|
allowedTools: [], // No tools needed for this
|
||||||
abortController,
|
abortController,
|
||||||
settingSources: autoLoadClaudeMd ? ['user', 'project'] : undefined,
|
settingSources: autoLoadClaudeMd ? ['user', 'project'] : undefined,
|
||||||
|
readOnly: true, // Plan generation only generates text, doesn't write files
|
||||||
});
|
});
|
||||||
|
|
||||||
let responseText = '';
|
let responseText = '';
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ File: ${fileName}${truncated ? ' (truncated)' : ''}`;
|
|||||||
cwd,
|
cwd,
|
||||||
maxTurns: 1,
|
maxTurns: 1,
|
||||||
allowedTools: [],
|
allowedTools: [],
|
||||||
|
readOnly: true, // File description only reads, doesn't write
|
||||||
})) {
|
})) {
|
||||||
if (msg.type === 'assistant' && msg.message?.content) {
|
if (msg.type === 'assistant' && msg.message?.content) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message.content) {
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ export function createDescribeImageHandler(
|
|||||||
cwd,
|
cwd,
|
||||||
maxTurns: 1,
|
maxTurns: 1,
|
||||||
allowedTools: ['Read'], // Allow Read tool so Cursor can read the image if needed
|
allowedTools: ['Read'], // Allow Read tool so Cursor can read the image if needed
|
||||||
|
readOnly: true, // Image description only reads, doesn't write
|
||||||
})) {
|
})) {
|
||||||
if (msg.type === 'assistant' && msg.message?.content) {
|
if (msg.type === 'assistant' && msg.message?.content) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message.content) {
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ async function executeWithCursor(prompt: string, model: string): Promise<string>
|
|||||||
prompt,
|
prompt,
|
||||||
model,
|
model,
|
||||||
cwd: process.cwd(), // Enhancement doesn't need a specific working directory
|
cwd: process.cwd(), // Enhancement doesn't need a specific working directory
|
||||||
|
readOnly: true, // Prompt enhancement only generates text, doesn't write files
|
||||||
})) {
|
})) {
|
||||||
if (msg.type === 'assistant' && msg.message?.content) {
|
if (msg.type === 'assistant' && msg.message?.content) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message.content) {
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ ${prompt}`;
|
|||||||
prompt: cursorPrompt,
|
prompt: cursorPrompt,
|
||||||
model,
|
model,
|
||||||
cwd: projectPath,
|
cwd: projectPath,
|
||||||
|
readOnly: true, // Issue validation only reads code, doesn't write
|
||||||
})) {
|
})) {
|
||||||
if (msg.type === 'assistant' && msg.message?.content) {
|
if (msg.type === 'assistant' && msg.message?.content) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message.content) {
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ ${JSON.stringify(suggestionsSchema, null, 2)}`;
|
|||||||
maxTurns: 250,
|
maxTurns: 250,
|
||||||
allowedTools: ['Read', 'Glob', 'Grep'],
|
allowedTools: ['Read', 'Glob', 'Grep'],
|
||||||
abortController,
|
abortController,
|
||||||
|
readOnly: true, // Suggestions only reads code, doesn't write
|
||||||
})) {
|
})) {
|
||||||
if (msg.type === 'assistant' && msg.message?.content) {
|
if (msg.type === 'assistant' && msg.message?.content) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message.content) {
|
||||||
|
|||||||
Reference in New Issue
Block a user