import { executeOmniFocusScript } from '../../utils/scriptExecution.js';
import { queryCache } from '../../utils/cache.js';
import { logger } from '../../utils/logger.js';
const log = logger.child('addOmniFocusTask');
// Interface for repetition rule
export interface RepetitionRule {
frequency: 'daily' | 'weekly' | 'monthly' | 'yearly';
interval?: number; // defaults to 1
daysOfWeek?: number[]; // 0=Sunday, 1=Monday, ..., 6=Saturday
dayOfMonth?: number; // 1-31, mutually exclusive with weekdayOfMonth
weekdayOfMonth?: { // Weekday-of-month pattern, mutually exclusive with dayOfMonth
week: 1 | 2 | 3 | 4 | 5 | -1; // 1=first, 2=second, 3=third, 4=fourth, 5=fifth, -1=last. Note: week 5 may not exist in all months
day: number; // 0=Sunday, 1=Monday, ..., 6=Saturday
};
month?: number; // 1-12
repeatFrom?: 'due' | 'completion'; // defaults to 'due'
}
// Interface for task creation parameters
export interface AddOmniFocusTaskParams {
name: string;
note?: string;
dueDate?: string; // ISO date string
deferDate?: string; // ISO date string
plannedDate?: string; // ISO date string - when you intend to work on this
flagged?: boolean;
estimatedMinutes?: number;
tags?: string[]; // Tag names
projectName?: string; // Project name to add task to
projectId?: string; // Project ID to add task to (alternative to projectName)
parentTaskId?: string; // Parent task ID for subtask creation
parentTaskName?: string; // Parent task name for subtask creation (alternative to ID)
repetitionRule?: RepetitionRule; // Repetition rule for recurring tasks
}
/**
* Validate parent task parameters to prevent conflicts
*/
function validateParentTaskParams(params: AddOmniFocusTaskParams): {valid: boolean, error?: string} {
// Check if both parentTaskId and parentTaskName are provided
if (params.parentTaskId && params.parentTaskName) {
return {
valid: false,
error: "Cannot specify both parentTaskId and parentTaskName. Please use only one."
};
}
// Check if parent task is specified along with project (by name or ID)
if ((params.parentTaskId || params.parentTaskName) && (params.projectName || params.projectId)) {
return {
valid: false,
error: "Cannot specify both parent task and project. Subtasks inherit project from their parent."
};
}
return { valid: true };
}
/**
* Add a task to OmniFocus
* Uses OmniJS to correctly parse ISO date formats and handle special characters
*/
export async function addOmniFocusTask(params: AddOmniFocusTaskParams): Promise<{success: boolean, taskId?: string, error?: string}> {
try {
// Validate parameters
if (!params.name) {
return {
success: false,
error: "Task name is required"
};
}
// Validate parent task parameters
const validation = validateParentTaskParams(params);
if (!validation.valid) {
return {
success: false,
error: validation.error
};
}
const projectInfo = params.projectId ? `ID:${params.projectId}` : (params.projectName || 'inbox');
log.debug('Executing addOmniFocusTask', { name: params.name, project: projectInfo });
// Execute the OmniJS script
const result = await executeOmniFocusScript('@addTask.js', {
name: params.name,
note: params.note || null,
dueDate: params.dueDate || null,
deferDate: params.deferDate || null,
plannedDate: params.plannedDate || null,
flagged: params.flagged || false,
estimatedMinutes: params.estimatedMinutes || null,
tags: params.tags || [],
projectName: params.projectName || null,
projectId: params.projectId || null,
parentTaskId: params.parentTaskId || null,
parentTaskName: params.parentTaskName || null,
repetitionRule: params.repetitionRule || null
});
// Parse result
let parsed;
if (typeof result === 'string') {
try {
parsed = JSON.parse(result);
} catch (e) {
log.error('Failed to parse result as JSON', { error: (e as Error).message });
return {
success: false,
error: `Failed to parse result: ${result}`
};
}
} else {
parsed = result;
}
if (parsed.success) {
// Invalidate cache after successful write
queryCache.invalidateOnWrite();
return {
success: true,
taskId: parsed.taskId
};
} else {
return {
success: false,
error: parsed.error || "Unknown error"
};
}
} catch (error: any) {
log.error('Error in addOmniFocusTask', { error: error?.message });
return {
success: false,
error: error?.message || "Unknown error in addOmniFocusTask"
};
}
}