*/ public function dependencies(): array { return [ ToolDependency::contextExists('workspace_id', 'Workspace context required'), ]; } public function name(): string { return 'plan_create'; } public function description(): string { return 'Create a new work plan with phases and tasks'; } public function inputSchema(): array { return [ 'type' => 'object', 'properties' => [ 'title' => [ 'type' => 'string', 'description' => 'Plan title', ], 'slug' => [ 'type' => 'string', 'description' => 'URL-friendly identifier (auto-generated if not provided)', ], 'description' => [ 'type' => 'string', 'description' => 'Plan description', ], 'context' => [ 'type' => 'object', 'description' => 'Additional context (related files, dependencies, etc.)', ], 'phases' => [ 'type' => 'array', 'description' => 'Array of phase definitions with name, description, and tasks', 'items' => [ 'type' => 'object', 'properties' => [ 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'tasks' => [ 'type' => 'array', 'items' => ['type' => 'string'], ], ], ], ], ], 'required' => ['title'], ]; } public function handle(array $args, array $context = []): array { try { $title = $this->requireString($args, 'title', 255); $slug = $this->optionalString($args, 'slug', null, 255) ?? Str::slug($title).'-'.Str::random(6); $description = $this->optionalString($args, 'description', null, 10000); } catch (\InvalidArgumentException $e) { return $this->error($e->getMessage()); } if (AgentPlan::where('slug', $slug)->exists()) { return $this->error("Plan with slug '{$slug}' already exists"); } // Determine workspace_id - never fall back to hardcoded value in multi-tenant environment $workspaceId = $context['workspace_id'] ?? null; if ($workspaceId === null) { return $this->error('workspace_id is required but could not be determined from context'); } $plan = AgentPlan::create([ 'slug' => $slug, 'title' => $title, 'description' => $description, 'status' => 'draft', 'context' => $args['context'] ?? [], 'workspace_id' => $workspaceId, ]); // Create phases if provided if (! empty($args['phases'])) { foreach ($args['phases'] as $order => $phaseData) { $tasks = collect($phaseData['tasks'] ?? [])->map(fn ($task) => [ 'name' => $task, 'status' => 'pending', ])->all(); AgentPhase::create([ 'agent_plan_id' => $plan->id, 'name' => $phaseData['name'], 'description' => $phaseData['description'] ?? null, 'order' => $order + 1, 'status' => 'pending', 'tasks' => $tasks, ]); } } $plan->load('agentPhases'); return $this->success([ 'plan' => [ 'slug' => $plan->slug, 'title' => $plan->title, 'status' => $plan->status, 'phases' => $plan->agentPhases->count(), ], ]); } }