Unify error handling in all tools used by the dev page builder agent.

[Description of changes]

Both tools now follow this logic

  1. Access check throws, first statement, before the try block. A permission denial is not something the model can act on or retry past — the fix is a role change, not a different prompt — so it should end the turn immediately rather than spend a model call on it:
    if (!$this->currentUser->hasPermission(CanvasAiPermissions::USE_CANVAS_AI)) {
      throw new \Exception('The current user does not have the right permissions to run this tool.');
    }
  2. Every other check accumulates. Parsing, shape, and semantic checks each add to an array<string, list<string>> of messages keyed by the item they belong to (e.g. "Operation 0", "Edit 0") instead of throwing or returning early. A check is skipped only when the value it would read is itself invalid.
  3. One formatting helper. AiResponseValidator::formatErrors(array $errors): string renders the accumulated errors as one Markdown section per item. Reuse it rather than building the message inline.
  4. On any error: log the formatted message to the canvas_ai channel, then $this->setOutput($message) and return. setStructuredOutput() is not called, so nothing is applied.
  5. On no errors: proceed to apply, then setStructuredOutput() and setOutput() as today.

Closes #3591958

Edited by AKHIL BABU

Merge request reports

Loading