dograh/docs/api-reference/openapi.json

1 line
355 KiB
JSON
Raw Normal View History

feat: add tool test panel for HTTP API tools (#547) * feat: add tool test panel for HTTP API tools Lets developers run a saved HTTP API tool against its real endpoint from the tool detail page, without needing a live call. Reuses the production execute_http_tool path so test behavior matches call-time behavior. - New POST /tools/{tool_uuid}/test route - Test panel with per-parameter typed inputs and auto-detected context variable inputs (from preset parameter templates) - Validate parameter name uniqueness on save, matching the existing transferParameters check - Fix stale FunctionCallsFromLLMInfoFrame import causing test collection failures against pipecat-ai 1.5.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: revert local-venv pipecat drift fix, apply ruff import formatting test_custom_tools.py and test_unregistered_function_call.py were edited locally to drop FunctionCallsFromLLMInfoFrame after hitting an ImportError — that error was from a stale local pipecat-ai package, not a real drift. CI's pipecat build emits this frame and the test asserted on it, so removing it broke test_llm_calls_custom_tool_handler and its unregistered-call counterpart. Reverted both files to match main. Also applied ruff's import-sort/format fix to test_mcp_tool_route.py to clear the drift-check job (split the aliased import into its own `from ... import (...)` block, wrapped a long monkeypatch.setattr call). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: avoid pytest collecting test_tool import as a test, sync OpenAPI spec pytest's default discovery matches any top-level test_* name in a test module, including imported functions — importing the route handler as `test_tool as test_tool_route` still matched the pattern, so pytest tried to run it as a test and failed injecting fixtures for tool_uuid/ request/user. Renamed the alias to call_test_tool_route. Also regenerated docs/api-reference/openapi.json for the new POST /tools/{tool_uuid}/test route and its two schemas (couldn't run the dump script locally — pipecat-ai version mismatch documented separately — so hand-built the diff to exactly match FastAPI's get_openapi() output format, verified against neighboring routes). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address cubic review findings on test panel - Resolve dotted context-variable keys into nested objects before posting the test request. render_template's get_nested_value walks nested dicts, so a flat key like "runtime_configuration.realtime_model" never matched — templates referencing nested context always resolved to empty. - Restrict isHttpApiTool to an explicit category equality check instead of inferring it from exclusions. native/integration tools are currently disabled in the create-tool UI so this wasn't reachable today, but the exclusion list silently goes stale as new categories are added. - Stop showing a green success badge for non-2xx responses. execute_http_tool returns status: "success" for any HTTP exchange that completes, regardless of status code — only transport-level errors (timeout, connection failure) get status: "error". The test panel now checks status_code is in the 2xx range before treating the call as a success. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address second round of cubic/greptile findings - Guard setNestedValue against prototype-pollution keys (__proto__, constructor, prototype) in the dotted context-var path before traversing. - Normalize status to "error" in the test route when the upstream status_code is >= 400. execute_http_tool only distinguishes transport-level failures (timeout, connection error) from "success" — a completed 4xx/5xx exchange still came back as "success" from the executor. - Seed testArgValues defaults for number/boolean parameters via a useEffect keyed on the parameters array, so a required number or boolean field isn't silently omitted from the test request if the user never touches its input. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: only seed test-arg defaults for required number/boolean params Seeding optional number/boolean parameters silently changed the test request — an optional boolean flag the tester never touched was sent as true, which can flip upstream behavior unintentionally. Restrict seeding to required parameters. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: match whitespace and fallback-filter syntax in context var detection extractContextVars required an exact {{initial_context.foo}} with no whitespace and no filter suffix, but the backend's TEMPLATE_VAR_PATTERN (and render_template) accepts {{ initial_context.foo }} and {{initial_context.foo | fallback:value}}. A preset parameter saved with either of those forms resolved fine in production but showed no input in the test panel, so testing always sent it empty context. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tool-test): add hint and request_* fields to ToolTestResponse Extends ToolTestResponse with hint, request_method, request_url, request_body, and request_params so the frontend can surface what was actually sent and a human-readable hint about why a test call failed. * feat(tool-test): add status-code hints and request_method/url/body/params to test_tool() * style: ruff-format test_mcp_tool_route.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tool-test): wire hint banner and request block into result panel Backend has returned hint/request_method/request_url/request_body/ request_params since d45ea851/60aaf31d but the frontend never displayed them. Extends ToolTestResult with the new fields and renders an amber hint banner (for 400/401/403/404/405/408/409/415/422/429/5xx) plus a Request block above the response showing exactly what was sent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tool-test): include resolved preset params in request_body/params Found via live GET/POST testing: the Request preview showed only the model-provided arguments, not what execute_http_tool actually sends. execute_http_tool merges resolved_arguments = {**arguments, **preset_arguments} before building the outbound body/params — preset params (e.g. {{initial_context.metadata.channel}}) are invisible to the model but still go out on the wire. The preview now mirrors that merge via the same _resolve_preset_parameters helper, so a dev sees exactly what was sent, not just what the model provided. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tool-test): add generateSampleValue helper for sample-fill button * feat(tool-test): add Fill sample values button for arguments and context vars Moved generateSampleValue out of page.tsx into a sibling helpers module: Next.js's typed-route checker rejects extra named exports on a page.tsx file (tsc error TS2344 on .next/types), so the helper and its test import now live in testPanelHelpers.ts instead. * feat(tool-test): add JSON edit modal state and handlers * feat(tool-test): collapsed preview + edit modal for object/array test parameters * fix(tool-test): validate JSON on modal open, not just on edit Opening the JSON edit modal on an untouched object/array param (no value yet in testArgValues) loaded an empty draft with jsonEditError hardcoded to null, so Save was enabled despite invalid JSON and silently no-op'd on click. Now runs the same JSON.parse check used by the live textarea validation when the modal opens. * chore: regenerate openapi.json for ToolTestResponse hint/request_* fields drift-check on PR #547 was failing because the earlier hint/request_method/ request_url/request_body/request_params fields added to ToolTestResponse were never reflected in the dumped spec. Regenerated via scripts.dump_docs_openapi. * fix(tool-test): serialize object/array args for GET/DELETE query params, add unsaved-changes banner httpx raises a TypeError when a query param value is a dict/list, which was silently caught and surfaced as a generic tool-execution error — this is what actually broke test requests, not just the "[object Object]" display. JSON-stringify object/array arguments before they become query params, in both the live execute_http_tool() path and the test route's request_params display shaping. Also adds an unsaved-changes warning banner above Test Tool, shown when the live form state diverges from the last-saved HTTP API config, since Test Tool always runs the saved config. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(tool-test): keep empty request body in preview; normalize headers in snapshot - POST/PUT/PATCH with no arguments now shows `{}` in the request body preview instead of null — matches what execute_http_tool actually sends over the wire (json={}) - buildHttpToolTestSnapshot normalizes headers from KeyValueItem[] to a deduped key→value map before serializing, matching the shape saved to the backend; duplicate header keys no longer cause a false unsaved- changes warning Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(tool-test): update assertion for empty POST body preview test_tool_test_no_arguments_leaves_body_and_params_none expected request_body=None for a POST with no arguments. The fix to preserve {} in the preview makes request_body={} the correct assertion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tools): refine HTTP tool testing --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-07-18 16:00:50 +05:30
{"openapi":"3.1.0","info":{"title":"Dograh API","description":"API for the Dograh app","version":"1.0.0"},"servers":[{"url":"https://app.dograh.com","description":"Production"},{"url":"http://localhost:8000","description":"Local development"}],"paths":{"/api/v1/telephony/initiate-call":{"post":{"tags":["main"],"summary":"Initiate Call","description":"Initiate a call using the configured telephony provider from web browser. This is\nsupposed to be a test call method for the draft version of the agent.","operationId":"initiate_call_api_v1_telephony_initiate_call_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateCallRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-sdk-method":"test_phone_call","x-sdk-description":"Place a test call from a workflow to a phone number."}},"/api/v1/telephony/inbound/run":{"post":{"tags":["main"],"summary":"Handle Inbound Run","description":"Workflow-agnostic inbound dispatcher.\n\nAll providers can point a single webhook at this endpoint instead of one\nURL per workflow. The dispatcher resolves the org from the webhook's\naccount_id and the workflow from the called number's\n``inbound_workflow_id``. This is what ``configure_inbound`` writes into\neach provider's resource so per-workflow webhook bookkeeping disappears.\n\nProvider-specific signature/timestamp headers are not enumerated here \u2014\neach provider's ``verify_inbound_signature`` reads its own headers from\nthe dict, so adding a new provider doesn't require changes to this route.","operationId":"handle_inbound_run_api_v1_telephony_inbound_run_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found"}}}},"/api/v1/telephony/inbound/fallback":{"post":{"tags":["main"],"summary":"Handle Inbound Fallback","description":"Fallback endpoint that returns audio message when calls cannot be processed.","operationId":"handle_inbound_fallback_api_v1_telephony_inbound_fallback_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found"}}}},"/api/v1/telephony/inbound/{workflow_id}":{"post":{"tags":["main"],"summary":"Handle Inbound Telephony","description":"[LEGACY] Per-workflow inbound webhook.\n\nSuperseded by ``POST /inbound/run``, which resolves the workflow from\nthe called number's ``inbound_workflow_id`` and lets a single webhook\nURL serve every workflow in the org. New integrations should point\ntheir provider at ``/inbound/run``; this route is kept only for\nexisting provider configurations that still encode ``workflow_id``\nin the URL.","operationId":"handle_inbound_telephony_api_v1_telephony_inbound__workflow_id__post","deprecated":true,"parameters":[{"name":"workflow_id","in":"path","required":true,"schema":{"type":"integer","title":"Workflow Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/telephony/transfer-result/{transfer_id}":{"post":{"tags":["main"],"summary":"Complete Transfer Function Call","description":"Webhook endpoint to complete the function call with transfer result.\n\nCalled by Twilio's StatusCallback when the transfer call status changes.","operationId":"complete_transfer_function_call_api_v1_telephony_transfer_result__transfer_id__post","parameters":