#447

fix: fall back to user input when the task title call fails

Openlalith0407wants to merge intofrom

Description of the Change

Problem

GetTaskTitle treats any error from its one model call as fatal, so NewTaskWorker fails and the flow gets no task. A single 429 on this cosmetic call is enough. Seen on the Gemini free tier. Possibly what users hit in #85.

Solution

  • On an error or a blank answer, build the title from the input: first non-blank line, whitespace collapsed, cut to 150 characters with "…". Empty input gets "Untitled task". A warning is logged with the error.
  • No extra retries. The model is still called once, so a failing provider doesn't add delay before the task starts.
  • A canceled context still returns the error, so a stopped flow doesn't get a task created.
  • Fix the "flow title" wording in the task title error messages. Name the 150 limit taskTitleLimit; the prompt and the fallback both use it.

Closes #446

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)

Areas Affected

  • Core Services (Frontend UI/Backend API)

Testing and Verification

Test Configuration

PentAGI Version: 2.2.0-ce (843dfeb)
Docker Version: 29.9.1
Host OS: Linux
LLM Provider: Gemini (where it was first hit), OpenAI (live check)
Enabled Features: none

Test Steps

  1. go test ./pkg/providers/ -run TestTaskTitle
  2. go test ./pkg/providers/... ./pkg/controller/..., go vet, golangci-lint run ./pkg/providers/ ./pkg/controller/
  3. Live: put a local proxy in front of the OpenAI endpoint (OPEN_AI_SERVER_URL) that returns 429 for every task title prompt and forwards everything else, then start a flow.

Test Results

  • Unit tests:
    • Normal success path: unchanged.
    • One 429: falls back right away, 1 call.
    • Persistent failure, blank answer, input with newlines and tabs, long input, emoji/multibyte (valid UTF-8, within the limit), empty input: all handled.
    • Canceled context: returns the error, no fallback.
  • Live, unpatched: the flow ended with 0 tasks.
  • Live, patched: the task got the input as its title, ran hostname, and finished.

Security Considerations

None. The fallback title is the user's own input, which is already stored as the task input.

Performance Impact

None on the success path. On failure, the task starts as soon as the model call returns, with no extra retries.

Documentation Updates

None.

Deployment Notes

None.

Checklist

  • I have added tests to cover my changes
  • All new and existing tests pass
  • I have run go fmt and go vet (for Go code)
  • Changes are backward compatible

Additional Notes

PentAGI's provider wrapper (backend/pkg/providers/provider/wrapper.go:22-23, 165-185) still retries 429s up to 10 times before the call returns. Against the test proxy that was 10 calls and 95s before the fallback. This change doesn't touch that. Gemini's 429 text (Error 429, Message: ...) doesn't match isTooManyRequestsError, so with Gemini the fallback happens right away.

HUMAN:

I was running PentAGI locally on Gemini's free tier to see how flows work, and my second flow died about 12 seconds in. The sandbox was already up, but the call that names the task hit a 429, and that one failure ended the whole flow with no tasks. Since the title only shows up in the UI, I made it fall back to the user's input instead of failing. I kept it to a single call with no extra retries so it doesn't hold up the task. I also fixed the "flow title" wording in those error messages, which confused me while I was debugging. If you'd rather have the fallback cover the flow title and language steps too, I'm happy to extend it.