feat(nubi): add query timeout flag, resilient polling, and recovery hints - #115
Conversation
…ints - Add --timeout / -t flag to nbctl nubi query (default: 0 / unlimited) - Add resilient polling in nubi query to retry transient errors and update spinner - Display Session ID, Conversation ID, nbctl nubi get command, and browser URL when query times out or is canceled - Emit structured JSON error payload when -o json / --format json is requested on trigger failure or timeout - Provide contextual diagnostic hints when account-level access is denied - Fix RunWithMockServer test isolation by ensuring NBCTL_TESTING=true is set - Add comprehensive test coverage for query timeouts, retries, and access errors
There was a problem hiding this comment.
Code Review
This pull request introduces a --timeout flag to the nubi query command, improves error handling for timeouts and cancellations (with detailed user guidance for both text and JSON outputs), and refactors the polling mechanism to tolerate transient errors and use a ticker. It also adds comprehensive tests for these scenarios. The review feedback suggests improving sub-second duration rounding to avoid displaying 0s and enhancing context error checks in the polling loop to ensure robust handling of cancellations and timeouts.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a '--timeout' flag to the 'nubi query' command, enhances error handling and recovery messaging for timeouts and cancellations (supporting both text and JSON outputs), and refactors the polling mechanism to use a ticker with transient error retries. The review feedback highlights several improvement opportunities, including addressing a potential data race with the spinner suffix, avoiding thread-unsafe dynamic environment variable modifications in tests, robustly distinguishing trigger errors from polling errors instead of relying on string matching, and ensuring non-zero exit codes are returned on failure in JSON mode.
…arameters, and include account in recovery hints - cmd/nubi_get.go: Add --account-id flag and use resolveAccountID(cmd) to allow account overrides; return non-zero error in JSON mode when conversation is not found. - pkg/nubi/nubi.go: Send only conversationId when available, or only sessionId otherwise in GetConversation to prevent mutually exclusive AND filter failures in ai_get_conversation_v3. - cmd/nubi_query.go: Append --account-id to nubi get commands in text and JSON recovery hints. - cmd/nubi_test.go, pkg/nubi/nubi_test.go: Add unit tests for account scoping, parameter isolation, and JSON error handling.
Summary of Changes
1. Add
--timeout/-tflag tonbctl nubi query--timeout 5m,-t 2m).0(unlimited / wait until complete or canceled, preserving existing behavior).2. Fix Polling Parameter Isolation (
pkg/nubi/nubi.go)GetConversationset bothconversationIdandsessionIdtoidToUsewhen polling by session ID.ai_get_conversation_v3, the backend filterWHERE ($3::uuid IS NULL OR c.id = $3::uuid) AND ($4::text IS NULL OR c.session_id = $4::text)caused 0 rows to match because conversation UUID never equals session UUID.conversationIdwhen available, or onlysessionIdotherwise.3. Add
--account-idFlag tonbctl nubi get(cmd/nubi_get.go)--account-idflag tonubiGetCmdand resolved account ID viaresolveAccountID(cmd)to allow overriding profile default account.-o json), returns a non-zero error when the conversation is not found for the account rather than exiting 0 with an empty response.4. Account Scoping in Recovery Hints
--account-id <id>to suggestednbctl nubi getcommands.5. Resilient Polling & Live Progress Updates
statusTextfromGetConversation.6. Clear Post-Timeout & Post-Cancellation Guidance
When a query times out or is canceled:
Query timed out after <duration>.orRequest canceled.--format json/-o json):7. Machine-Readable Trigger Errors & Access Hints
--async -o jsonor synchronous-o jsonencounters a trigger error (such asapi: user does not have access), it outputs structured JSON onstdout.8. Test Isolation Fix in
pkg/testutil/helpers.goRunWithMockServersetsNBCTL_TESTING=trueduring mock execution to prevent tests from reading~/.nudgebee/configand connecting to production.Verification
TestNubiClient_GetConversation_ParameterIsolationinpkg/nubi/nubi_test.go.TestNubiCmd_Get_WithAccountId,TestNubiCmd_Get_SessionId_WithAccountId,TestNubiCmd_Get_NotFound_JSON, andTestNubiCmd_SyncQuery_SessionIdDiffersFromConversationIdincmd/nubi_test.go.go test -v ./...).make lint/golangci-lint runwith 0 issues).