From 707d4855f12985d99d77578f4b97b7ed8169defe Mon Sep 17 00:00:00 2001 From: ysyneu <9045284+ysyneu@users.noreply.github.com> Date: Thu, 23 Jul 2026 04:32:53 +0000 Subject: [PATCH] chore: sync OpenAPI spec from flashduty-docs + regenerate --- incidents.go | 14 ++ models_gen.go | 65 +++++- openapi/openapi.en.json | 483 ++++++++++++++++++++++------------------ openapi/openapi.zh.json | 483 ++++++++++++++++++++++------------------ roundtrip_gen_test.go | 1 + 5 files changed, 610 insertions(+), 436 deletions(-) diff --git a/incidents.go b/incidents.go index 0e62390..ac815c9 100644 --- a/incidents.go +++ b/incidents.go @@ -21,6 +21,20 @@ func (s *IncidentsService) ReadGetWarRoomDefaultObservers(ctx context.Context, r return out, resp, nil } +// Get ServiceDeskPlus linked incidents. +// +// List synchronization mappings between ServiceDeskPlus requests and Flashduty incidents. +// +// API: POST /incident/sdp/request/list (incident-service-desk-plus-request-read-list). +func (s *IncidentsService) ServiceDeskPlusRequestReadList(ctx context.Context, req *ServiceDeskPlusRequestListRequest) (*ServiceDeskPlusRequestListResponse, *Response, error) { + out := new(ServiceDeskPlusRequestListResponse) + resp, err := s.client.do(ctx, "/incident/sdp/request/list", req, out) + if err != nil { + return nil, resp, err + } + return out, resp, nil +} + // Add war-room member. // // Add one or more members to the IM war room bound to an incident integration. diff --git a/models_gen.go b/models_gen.go index 01a03a7..eba04fb 100644 --- a/models_gen.go +++ b/models_gen.go @@ -6552,6 +6552,63 @@ type ScheduleUpsertRequest struct { TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } +// ServiceDeskPlusRequestListRequest is generated from the Flashduty OpenAPI schema. +type ServiceDeskPlusRequestListRequest struct { + ListOptions + // When `true`, sort by internal record ID ascending; otherwise descending. + Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` + // Channel IDs to filter by. + ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` + // Window end, Unix seconds. Must be greater than or equal to `start_time`. Optional when `incident_id` is provided. + EndTime int64 `json:"end_time,omitempty" toon:"end_time,omitempty"` + // Flashduty incident ID. When set, the time window can be omitted. + IncidentID string `json:"incident_id,omitempty" toon:"incident_id,omitempty"` + // ServiceDeskPlus integration ID. + IntegrationID int64 `json:"integration_id,omitempty" toon:"integration_id,omitempty"` + // ServiceDeskPlus request ID. + RequestID string `json:"request_id,omitempty" toon:"request_id,omitempty"` + // Window start, Unix seconds. Optional when `incident_id` is provided. + StartTime int64 `json:"start_time,omitempty" toon:"start_time,omitempty"` + // Synchronization status filter. + Status string `json:"status,omitempty" toon:"status,omitempty"` +} + +// ServiceDeskPlusRequestListResponse is generated from the Flashduty OpenAPI schema. +type ServiceDeskPlusRequestListResponse struct { + // True when more results are available. + HasNextPage bool `json:"has_next_page" toon:"has_next_page"` + // Synchronization records on the current page. + Items []ServiceDeskPlusRequestMappingItem `json:"items" toon:"items"` + // Cursor for the next page. Empty when no more data is available. + SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` + // Total number of matching records, capped at 1,000 for counting. + Total int64 `json:"total" toon:"total"` +} + +// ServiceDeskPlusRequestMappingItem is generated from the Flashduty OpenAPI schema. +type ServiceDeskPlusRequestMappingItem struct { + // Channel ID for the incident. + ChannelID int64 `json:"channel_id" toon:"channel_id"` + // Channel name for the incident. + ChannelName string `json:"channel_name" toon:"channel_name"` + // Mapping record creation time, Unix seconds. + CreatedAt Timestamp `json:"created_at" toon:"created_at"` + // Error message when synchronization failed. Usually absent on successful records. + ErrorMessage string `json:"error_message" toon:"error_message"` + // Associated Flashduty incident ID. + IncidentID string `json:"incident_id" toon:"incident_id"` + // Associated incident title. + IncidentTitle string `json:"incident_title" toon:"incident_title"` + // ServiceDeskPlus integration ID. + IntegrationID int64 `json:"integration_id" toon:"integration_id"` + // ServiceDeskPlus request ID. + RequestID string `json:"request_id" toon:"request_id"` + // ServiceDeskPlus request detail URL. + RequestLink string `json:"request_link" toon:"request_link"` + // Synchronization status. + Status string `json:"status" toon:"status"` +} + // SessionDeleteRequest is generated from the Flashduty OpenAPI schema. type SessionDeleteRequest struct { // Target session ID. @@ -7635,9 +7692,7 @@ type TimeFilter struct { type ToolCatalogRequest struct { // Optional consistency check. Must equal the authenticated account when supplied. AccountID int64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // When true, each tool entry includes its `output_shape` JSON Schema. Defaults to false to keep responses small for LLM consumption. - IncludeOutputShape bool `json:"include_output_shape,omitempty" toon:"include_output_shape,omitempty"` - // Optional target kind. When omitted webapi auto-infers across currently known kinds. Built-in kinds: `host`, `mysql`. Required on retry when the previous call returned `ambiguous_target_kind`. + // Optional target kind. When omitted, webapi infers it from current target routing. If the call returns `ambiguous_target_kind`, retry with a value from `target_kinds`. TargetKind string `json:"target_kind,omitempty" toon:"target_kind,omitempty"` // Target identifier (host name, MySQL address, …). Max 256 bytes; no whitespace, control characters, or `|`. TargetLocator string `json:"target_locator,omitempty" toon:"target_locator,omitempty"` @@ -8603,8 +8658,6 @@ type ToolCatalogResponseToolsItem struct { InputSchema map[string]any `json:"input_schema" toon:"input_schema"` // Tool name; pass into `/monit/tools/invoke` as `tools[].tool`. Name string `json:"name" toon:"name"` - // JSON Schema of the tool result. Returned only when the request set `include_output_shape` to true. - OutputShape *map[string]any `json:"output_shape,omitempty" toon:"output_shape,omitempty"` // Target kind this tool applies to. TargetKind string `json:"target_kind" toon:"target_kind"` } @@ -8763,7 +8816,7 @@ type RuleConfigsCheckThresholdRecovery struct { // ToolInvokeResponseResultsItemError is generated from the Flashduty OpenAPI schema. type ToolInvokeResponseResultsItemError struct { - // Common values: `timeout`, `target_unavailable`, `edge_unsupported`, `invalid_tool_result`, `internal`, `invalid_args`, `unknown_tool`, `unknown_tool_version`, `unknown_toolset_hash`, `target_not_owned`, `wrong_agent`, `overloaded`, `denied`, `permission_denied`, `credential_unavailable`, `target_unreachable`. + // Common WebAPI codes: `timeout`, `target_unavailable`, `invalid_tool_result`, `internal`, `invalid_args`, `unsupported_syntax`, `path_not_found`, and `catalog_changed`. Agent-specific tool errors may also be returned unchanged. Code string `json:"code" toon:"code"` Message string `json:"message" toon:"message"` } diff --git a/openapi/openapi.en.json b/openapi/openapi.en.json index bf4362c..7fd5a80 100644 --- a/openapi/openapi.en.json +++ b/openapi/openapi.en.json @@ -316,6 +316,99 @@ } } }, + "/incident/sdp/request/list": { + "post": { + "operationId": "incident-service-desk-plus-request-read-list", + "summary": "Get ServiceDeskPlus linked incidents", + "description": "List synchronization mappings between ServiceDeskPlus requests and Flashduty incidents.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** (`on-call`) |\n\n## Usage\n\n- Use this endpoint to inspect synchronization mappings between ServiceDeskPlus requests and Flashduty incidents, including the external request link and sync status.\n- When `incident_id` is not provided, `start_time` and `end_time` are required Unix-second timestamps; the time window cannot exceed 30 days.\n- `status` accepts only `success` and `failed`, representing successful and failed synchronization records.\n- Results are sorted by the internal record ID. Set `asc` to `true` for ascending order; otherwise records are returned descending. Pass the returned `search_after_ctx` to continue pagination.", + "href": "/en/api-reference/on-call/incidents/incident-service-desk-plus-request-read-list", + "metadata": { + "sidebarTitle": "Get ServiceDeskPlus linked incidents" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "created_at": 1779514631, + "status": "success", + "request_id": "100000000001", + "request_link": "https://servicedesk.example.com/app/itdesk/ui/requests/100000000001/details", + "integration_id": 98765, + "incident_id": "685d7f4e51b9a9a6d4d0c123", + "incident_title": "Checkout API 5xx rate increased", + "channel_id": 12345, + "channel_name": "Payments" + } + ], + "total": 1, + "has_next_page": false, + "search_after_ctx": "" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestListRequest" + }, + "example": { + "start_time": 1779513600, + "end_time": 1779600000, + "status": "success", + "channel_ids": [ + 12345 + ], + "limit": 20 + } + } + } + } + } + }, "/incident/info": { "post": { "operationId": "incidentInfo", @@ -20065,7 +20158,7 @@ "Monitors/Diagnostics" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **600 requests/minute**; **10 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n\n## Usage\n\n- Use `target_locator` to identify the target; `target_kind` is optional and is auto-inferred when omitted. Built-in target kinds are `host` and `mysql`.\n- If multiple kinds match the same locator, the response is HTTP 200 with `data.error.code = \"ambiguous_target_kind\"` and a `target_kinds` list — retry with an explicit `target_kind`.\n- The catalog is a *candidate capability* view, not an execution guarantee. The target Agent may go offline between catalog and invoke, or local Agent policy may block individual tools at invoke time.\n- Set `include_output_shape: true` to additionally receive each tool's `output_shape`. Default is `false` to keep the response small for LLM consumption.\n- Business errors (`target_unavailable`, `unknown_toolset_hash`, `ambiguous_target_kind`) come back as HTTP 200 with `data.error` present and `data.tools = []`. Only protocol / auth / internal errors use the standard error envelope.\n- The response uses **sparse fields**: on success `error` is omitted rather than sent as `null`, and `target` is omitted when the locator could not be uniquely resolved. `tools` is always present.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **600 requests/minute**; **10 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n\n## Usage\n\n- Use `target_locator` to identify the target; `target_kind` is optional and is inferred from current target routing when omitted.\n- If multiple kinds match the same locator, the response is HTTP 200 with `data.error.code = \"ambiguous_target_kind\"` and a `target_kinds` list — retry with an explicit `target_kind`.\n- The catalog is a candidate capability view, not an execution guarantee. The target Agent may go offline between catalog and invoke, or local Agent policy may block individual tools at invoke time.\n- Each tool entry exposes only `name`, `target_kind`, `description`, and `input_schema`. It does not expose tool versions, output contracts, catalog revisions, or execution limits.\n- Business errors (`target_unavailable`, `timeout`, `forward_failed`, `invalid_tool_result`, `ambiguous_target_kind`) return HTTP 200 with `data.error` present and `data.tools = []`. Only protocol, authentication, and internal errors use the standard error envelope.\n- The response uses **sparse fields**: on success `error` is omitted rather than sent as `null`, and `target` is omitted when the locator could not be uniquely resolved. `tools` is always present.", "href": "/en/api-reference/monitors/diagnostics/monit-read-tools-catalog", "metadata": { "sidebarTitle": "List target tool catalog" @@ -20080,8 +20173,7 @@ }, "example": { "account_id": 10001, - "target_locator": "web-01", - "include_output_shape": true + "target_locator": "web-01" } } } @@ -20122,144 +20214,6 @@ "type": "object", "additionalProperties": false, "properties": {} - }, - "output_shape": { - "properties": { - "data": { - "properties": { - "cpu": { - "type": "object" - }, - "degradation_reasons": { - "items": { - "type": "string" - }, - "minItems": 1, - "type": "array" - }, - "disk": { - "description": "Filesystems sorted by used_pct desc; rootfs always present; capped at host.disk.top_n. Sizes are in GB; used_pct/inode_used_pct in percent.", - "type": "array" - }, - "disk_errors": { - "description": "Mount points whose statfs returned a syscall error (EACCES / ENOENT / EIO / stale, etc.); each entry is `: `.", - "type": "array" - }, - "disk_io": { - "description": "Per-device disk I/O rates (util_pct, IOPS, throughput, await). Sorted by util_pct desc; capped at host.disk_io.top_n. Only whole-disk devices shown.", - "type": "object" - }, - "disk_timeouts": { - "description": "Mount points whose statfs hit per-mount timeout.", - "type": "array" - }, - "load": { - "type": "object" - }, - "memory": { - "description": "Memory and swap sizes are in MB; percentages are 0..100. Swap fields are always present when memory collection succeeds, including zero when swap is not configured.", - "properties": { - "available_mb": { - "type": "integer" - }, - "swap_configured": { - "description": "True when the kernel reports a non-zero SwapTotal.", - "type": "boolean" - }, - "swap_total_mb": { - "type": "integer" - }, - "swap_used_mb": { - "type": "integer" - }, - "swap_used_pct": { - "type": "number" - }, - "total_mb": { - "type": "integer" - }, - "used_mb": { - "type": "integer" - }, - "used_pct": { - "type": "number" - } - }, - "required": [ - "total_mb", - "available_mb", - "used_mb", - "used_pct", - "swap_configured", - "swap_total_mb", - "swap_used_mb", - "swap_used_pct" - ], - "type": "object" - }, - "network_io": { - "description": "Per-interface network throughput and error rates. Sorted by total traffic desc; capped at host.network_io.top_n. Virtual/container interfaces excluded by default.", - "type": "object" - }, - "procs": { - "type": "object" - }, - "sample_interval_sec": { - "description": "Shared sampling interval for CPU, disk_io, network_io counter-diff calculations.", - "type": "number" - }, - "tcp_connections": { - "description": "TCP connection state distribution via netlink SOCK_DIAG. Shows counts per state (established, time_wait, close_wait, listen, syn_recv, other, total).", - "type": "object" - }, - "uptime_sec": { - "type": "number" - }, - "vmstat": { - "description": "Sparse cumulative counters since the current boot; use them as historical clues, not current rates.", - "properties": { - "oom_kill_since_boot": { - "description": "OOM kills accumulated since boot; omitted when this kernel does not expose the counter.", - "type": "integer" - }, - "pgmajfault_since_boot": { - "description": "Major page faults accumulated since boot.", - "type": "integer" - } - }, - "required": [ - "pgmajfault_since_boot" - ], - "type": "object" - } - }, - "required": [ - "sample_interval_sec" - ], - "type": "object" - }, - "summary": { - "minLength": 1, - "type": "string" - }, - "truncated": { - "additionalProperties": false, - "properties": { - "reason": { - "minLength": 1, - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - } - }, - "required": [ - "data" - ], - "type": "object" } }, { @@ -20281,65 +20235,6 @@ "type": "integer" } } - }, - "output_shape": { - "properties": { - "data": { - "properties": { - "avg_ms": { - "type": "number" - }, - "max_ms": { - "type": "number" - }, - "min_ms": { - "type": "number" - }, - "probes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "latency_ms": { - "type": "number" - } - }, - "type": "object" - }, - "type": "array" - }, - "reachable": { - "type": "boolean" - }, - "resolved_ip": { - "type": "string" - } - }, - "type": "object" - }, - "summary": { - "minLength": 1, - "type": "string" - }, - "truncated": { - "additionalProperties": false, - "properties": { - "reason": { - "minLength": 1, - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - } - }, - "required": [ - "data" - ], - "type": "object" } } ] @@ -20372,7 +20267,7 @@ "Monitors/Diagnostics" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **600 requests/minute**; **10 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n\n## Usage\n\n- Up to **8** tools per call (`MaxToolsPerInvoke`); larger batches must be split client-side. The 8-tool cap aligns with the per-target agent concurrency.\n- Tools execute in parallel on the agent; webapi returns `results[]` aligned with the request `tools[]` order.\n- Long-running: set client timeouts to **at least 35 s**. The endpoint is intended for AI-SRE / human-RCA flows, not interactive UI.\n- Request-level errors (`target_unavailable`, `ambiguous_target_kind`, `unknown_toolset_hash`, `forward_failed`) appear as HTTP 200 with `data.error` set and `data.results = []`.\n- Per-tool failures appear as HTTP 200 with `data.error` absent and `results[i].error` populated — always check **all three** layers (outer envelope `error`, `data.error`, then each `results[i].error`).\n- The response uses **sparse fields**: absent means empty. On success `error` is omitted entirely rather than sent as `null`; on failure `data`, `summary` and `truncated` are omitted. Do not key logic off placeholder `null` fields, and do not expect `target` when the locator could not be uniquely resolved.\n- `results[i].data` is the tool payload with the monit-agent result envelope **already unwrapped** — there is no nested `data.data`. The one-line distillation is `results[i].summary`, and `results[i].truncated` (carrying a `reason`) appears only when the result was genuinely truncated.\n- `results[i].params` echoes the params webapi received for that tool, so batched calls stay correlatable even when an individual tool fails.\n- Construct `tools[].params` against the `input_schema` returned by `/monit/tools/catalog`. For no-arg tools always pass `params: {}` explicitly.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **600 requests/minute**; **10 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n\n## Usage\n\n- Up to **8** tools per call (`MaxToolsPerInvoke`); larger batches must be split client-side. The 8-tool cap aligns with the per-target agent concurrency.\n- Tools execute in parallel on the agent; webapi returns `results[]` aligned with the request `tools[]` order.\n- Long-running: set client timeouts to **at least 35 s**. The endpoint is intended for AI-SRE / human-RCA flows, not interactive UI.\n- Request-level errors (`target_unavailable`, `ambiguous_target_kind`, `forward_failed`) appear as HTTP 200 with `data.error` set and `data.results = []`.\n- Per-tool failures appear as HTTP 200 with `data.error` absent and `results[i].error` populated — always check **all three** layers (outer envelope `error`, `data.error`, then each `results[i].error`).\n- The response uses **sparse fields**: absent means empty. On success `error` is omitted entirely rather than sent as `null`; on failure `data`, `summary` and `truncated` are omitted. Do not key logic off placeholder `null` fields, and do not expect `target` when the locator could not be uniquely resolved.\n- `results[i].data` is the tool payload with the monit-agent result envelope **already unwrapped** — there is no nested `data.data`. The one-line distillation is `results[i].summary`, and `results[i].truncated` (carrying a `reason`) appears only when the result was genuinely truncated.\n- `results[i].params` echoes the params webapi received for that tool, so batched calls stay correlatable even when an individual tool fails.\n- Construct `tools[].params` against the `input_schema` returned by `/monit/tools/catalog`. For no-arg tools always pass `params: {}` explicitly.", "href": "/en/api-reference/monitors/diagnostics/monit-read-tools-invoke", "metadata": { "sidebarTitle": "Invoke target tools" @@ -42856,12 +42751,7 @@ }, "target_kind": { "type": "string", - "description": "Optional target kind. When omitted webapi auto-infers across currently known kinds. Built-in kinds: `host`, `mysql`. Required on retry when the previous call returned `ambiguous_target_kind`." - }, - "include_output_shape": { - "type": "boolean", - "description": "When true, each tool entry includes its `output_shape` JSON Schema. Defaults to false to keep responses small for LLM consumption.", - "default": false + "description": "Optional target kind. When omitted, webapi infers it from current target routing. If the call returns `ambiguous_target_kind`, retry with a value from `target_kinds`." } } }, @@ -42902,11 +42792,6 @@ "input_schema": { "type": "object", "description": "JSON Schema for `tools[].params`." - }, - "output_shape": { - "type": "object", - "description": "JSON Schema of the tool result. Returned only when the request set `include_output_shape` to true.", - "x-flashduty-preserve-absence": true } } } @@ -42919,7 +42804,9 @@ "type": "string", "enum": [ "target_unavailable", - "unknown_toolset_hash", + "timeout", + "forward_failed", + "invalid_tool_result", "ambiguous_target_kind" ] }, @@ -43046,7 +42933,7 @@ "properties": { "code": { "type": "string", - "description": "Common values: `timeout`, `target_unavailable`, `edge_unsupported`, `invalid_tool_result`, `internal`, `invalid_args`, `unknown_tool`, `unknown_tool_version`, `unknown_toolset_hash`, `target_not_owned`, `wrong_agent`, `overloaded`, `denied`, `permission_denied`, `credential_unavailable`, `target_unreachable`." + "description": "Common WebAPI codes: `timeout`, `target_unavailable`, `invalid_tool_result`, `internal`, `invalid_args`, `unsupported_syntax`, `path_not_found`, and `catalog_changed`. Agent-specific tool errors may also be returned unchanged." }, "message": { "type": "string" @@ -43065,7 +42952,6 @@ "type": "string", "enum": [ "target_unavailable", - "unknown_toolset_hash", "forward_failed", "ambiguous_target_kind" ] @@ -49204,6 +49090,173 @@ "p95", "max" ] + }, + "ServiceDeskPlusRequestListRequest": { + "type": "object", + "description": "Filters for listing ServiceDeskPlus request synchronization records. A time window is optional when querying by incident ID; otherwise provide a Unix-second window no longer than 30 days.", + "properties": { + "start_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Window start, Unix seconds. Optional when `incident_id` is provided." + }, + "end_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Window end, Unix seconds. Must be greater than or equal to `start_time`. Optional when `incident_id` is provided." + }, + "status": { + "type": "string", + "enum": [ + "success", + "failed" + ], + "description": "Synchronization status filter." + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Channel IDs to filter by." + }, + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "ServiceDeskPlus integration ID." + }, + "incident_id": { + "type": "string", + "maxLength": 64, + "description": "Flashduty incident ID. When set, the time window can be omitted." + }, + "request_id": { + "type": "string", + "maxLength": 64, + "description": "ServiceDeskPlus request ID." + }, + "asc": { + "type": "boolean", + "description": "When `true`, sort by internal record ID ascending; otherwise descending." + }, + "p": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Page number starting at 1. Ignored when `search_after_ctx` is set." + }, + "limit": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 100, + "default": 20, + "description": "Page size. Defaults to 20; maximum 100." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor returned by the previous page." + } + } + }, + "ServiceDeskPlusRequestMappingItem": { + "type": "object", + "description": "A synchronization mapping between a ServiceDeskPlus request and a Flashduty incident.", + "required": [ + "created_at", + "status", + "request_id", + "request_link", + "integration_id", + "incident_id", + "incident_title", + "channel_id", + "channel_name" + ], + "properties": { + "created_at": { + "type": "integer", + "format": "int64", + "description": "Mapping record creation time, Unix seconds." + }, + "status": { + "type": "string", + "enum": [ + "success", + "failed" + ], + "description": "Synchronization status." + }, + "request_id": { + "type": "string", + "description": "ServiceDeskPlus request ID." + }, + "request_link": { + "type": "string", + "description": "ServiceDeskPlus request detail URL." + }, + "integration_id": { + "type": "integer", + "format": "int64", + "description": "ServiceDeskPlus integration ID." + }, + "incident_id": { + "type": "string", + "description": "Associated Flashduty incident ID." + }, + "incident_title": { + "type": "string", + "description": "Associated incident title." + }, + "channel_id": { + "type": "integer", + "format": "int64", + "description": "Channel ID for the incident." + }, + "channel_name": { + "type": "string", + "description": "Channel name for the incident." + }, + "error_message": { + "type": "string", + "description": "Error message when synchronization failed. Usually absent on successful records." + } + } + }, + "ServiceDeskPlusRequestListResponse": { + "type": "object", + "description": "Paginated list of ServiceDeskPlus request synchronization records.", + "required": [ + "items", + "total", + "has_next_page" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestMappingItem" + }, + "description": "Synchronization records on the current page." + }, + "total": { + "type": "integer", + "format": "int64", + "description": "Total number of matching records, capped at 1,000 for counting." + }, + "has_next_page": { + "type": "boolean", + "description": "True when more results are available." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor for the next page. Empty when no more data is available." + } + } } } } diff --git a/openapi/openapi.zh.json b/openapi/openapi.zh.json index 3b7c9fe..9c6d941 100644 --- a/openapi/openapi.zh.json +++ b/openapi/openapi.zh.json @@ -316,6 +316,99 @@ } } }, + "/incident/sdp/request/list": { + "post": { + "operationId": "incident-service-desk-plus-request-read-list", + "summary": "获取 ServiceDeskPlus 关联故障", + "description": "分页查询 ServiceDeskPlus 请求与 Flashduty 故障的同步映射记录。", + "tags": [ + "On-call/故障管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **故障查看**(`on-call`) |\n\n## 使用说明\n\n- 查询 ServiceDeskPlus 请求与 Flashduty 故障之间的同步映射记录,用于排查 ITSM 同步状态或定位外部请求链接。\n- 不按 `incident_id` 查询时,`start_time` 和 `end_time` 必填,均为 Unix 秒时间戳;时间范围不能超过 30 天。\n- `status` 仅支持 `success` 和 `failed`,分别表示同步成功和同步失败。\n- 响应按内部记录 ID 排序;`asc` 为 `true` 时升序,否则降序。继续翻页时传入上次响应的 `search_after_ctx`。", + "href": "/zh/api-reference/on-call/incidents/incident-service-desk-plus-request-read-list", + "metadata": { + "sidebarTitle": "获取 ServiceDeskPlus 关联故障" + } + }, + "responses": { + "200": { + "description": "成功", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "created_at": 1779514631, + "status": "success", + "request_id": "100000000001", + "request_link": "https://servicedesk.example.com/app/itdesk/ui/requests/100000000001/details", + "integration_id": 98765, + "incident_id": "685d7f4e51b9a9a6d4d0c123", + "incident_title": "Checkout API 5xx rate increased", + "channel_id": 12345, + "channel_name": "Payments" + } + ], + "total": 1, + "has_next_page": false, + "search_after_ctx": "" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestListRequest" + }, + "example": { + "start_time": 1779513600, + "end_time": 1779600000, + "status": "success", + "channel_ids": [ + 12345 + ], + "limit": 20 + } + } + } + } + } + }, "/incident/info": { "post": { "operationId": "incidentInfo", @@ -20057,7 +20150,7 @@ "Monitors/诊断分析" ], "x-mint": { - "content": "## 调用限制\n\n| 项 | 值 |\n| ------ | ----- |\n| 速率限制 | **600 次/分钟**;**10 次/秒** 每账户 |\n| 权限 | 任意有效的 `app_key`(只读;不受特定权限分类约束) |\n\n## 使用说明\n\n- 使用 `target_locator` 标识监控对象;`target_kind` 可选,省略时自动推断。内置的 target kind 包括 `host` 与 `mysql`。\n- 若同一 locator 匹配多个 kind,响应为 HTTP 200,`data.error.code = \"ambiguous_target_kind\"`,并附带 `target_kinds` 列表——请带上显式的 `target_kind` 重试。\n- 工具能力清单是*候选能力*视图,并非执行保证。目标 Agent 可能在拿到清单与发起调用之间下线,本地 Agent 策略也可能在调用时拦截某些工具。\n- 设置 `include_output_shape: true` 可额外返回每个工具的 `output_shape`。默认为 `false`,以便为 LLM 消费保持响应精简。\n- 业务错误(`target_unavailable`、`unknown_toolset_hash`、`ambiguous_target_kind`)以 HTTP 200 返回,`data.error` 存在且 `data.tools = []`。只有协议 / 鉴权 / 内部错误才使用标准错误信封。\n- 响应采用**稀疏字段**:成功时 `error` 直接省略而非返回 `null`;当 locator 无法唯一解析时 `target` 不输出。`tools` 字段恒存在。", + "content": "## 调用限制\n\n| 项 | 值 |\n| ------ | ----- |\n| 速率限制 | **600 次/分钟**;**10 次/秒** 每账户 |\n| 权限 | 任意有效的 `app_key`(只读;不受特定权限分类约束) |\n\n## 使用说明\n\n- 使用 `target_locator` 标识监控对象;`target_kind` 可选,省略时按当前监控对象路由自动推断。\n- 若同一 locator 匹配多个 kind,响应为 HTTP 200,`data.error.code = \"ambiguous_target_kind\"`,并附带 `target_kinds` 列表——请带上显式的 `target_kind` 重试。\n- 工具能力清单是候选能力视图,并非执行保证。目标 Agent 可能在拿到清单与发起调用之间下线,本地 Agent 策略也可能在调用时拦截某些工具。\n- 每个工具条目只返回 `name`、`target_kind`、`description` 和 `input_schema`,不会暴露工具版本、输出契约、目录版本或执行限制。\n- 业务错误(`target_unavailable`、`timeout`、`forward_failed`、`invalid_tool_result`、`ambiguous_target_kind`)以 HTTP 200 返回,`data.error` 存在且 `data.tools = []`。只有协议、鉴权和内部错误才使用标准错误信封。\n- 响应采用**稀疏字段**:成功时 `error` 直接省略而非返回 `null`;当 locator 无法唯一解析时,`target` 不输出。`tools` 字段恒存在。", "href": "/zh/api-reference/monitors/diagnostics/monit-read-tools-catalog", "metadata": { "sidebarTitle": "查询监控对象工具能力清单" @@ -20072,8 +20165,7 @@ }, "example": { "account_id": 10001, - "target_locator": "web-01", - "include_output_shape": true + "target_locator": "web-01" } } } @@ -20114,144 +20206,6 @@ "type": "object", "additionalProperties": false, "properties": {} - }, - "output_shape": { - "properties": { - "data": { - "properties": { - "cpu": { - "type": "object" - }, - "degradation_reasons": { - "items": { - "type": "string" - }, - "minItems": 1, - "type": "array" - }, - "disk": { - "description": "Filesystems sorted by used_pct desc; rootfs always present; capped at host.disk.top_n. Sizes are in GB; used_pct/inode_used_pct in percent.", - "type": "array" - }, - "disk_errors": { - "description": "Mount points whose statfs returned a syscall error (EACCES / ENOENT / EIO / stale, etc.); each entry is `: `.", - "type": "array" - }, - "disk_io": { - "description": "Per-device disk I/O rates (util_pct, IOPS, throughput, await). Sorted by util_pct desc; capped at host.disk_io.top_n. Only whole-disk devices shown.", - "type": "object" - }, - "disk_timeouts": { - "description": "Mount points whose statfs hit per-mount timeout.", - "type": "array" - }, - "load": { - "type": "object" - }, - "memory": { - "description": "Memory and swap sizes are in MB; percentages are 0..100. Swap fields are always present when memory collection succeeds, including zero when swap is not configured.", - "properties": { - "available_mb": { - "type": "integer" - }, - "swap_configured": { - "description": "True when the kernel reports a non-zero SwapTotal.", - "type": "boolean" - }, - "swap_total_mb": { - "type": "integer" - }, - "swap_used_mb": { - "type": "integer" - }, - "swap_used_pct": { - "type": "number" - }, - "total_mb": { - "type": "integer" - }, - "used_mb": { - "type": "integer" - }, - "used_pct": { - "type": "number" - } - }, - "required": [ - "total_mb", - "available_mb", - "used_mb", - "used_pct", - "swap_configured", - "swap_total_mb", - "swap_used_mb", - "swap_used_pct" - ], - "type": "object" - }, - "network_io": { - "description": "Per-interface network throughput and error rates. Sorted by total traffic desc; capped at host.network_io.top_n. Virtual/container interfaces excluded by default.", - "type": "object" - }, - "procs": { - "type": "object" - }, - "sample_interval_sec": { - "description": "Shared sampling interval for CPU, disk_io, network_io counter-diff calculations.", - "type": "number" - }, - "tcp_connections": { - "description": "TCP connection state distribution via netlink SOCK_DIAG. Shows counts per state (established, time_wait, close_wait, listen, syn_recv, other, total).", - "type": "object" - }, - "uptime_sec": { - "type": "number" - }, - "vmstat": { - "description": "Sparse cumulative counters since the current boot; use them as historical clues, not current rates.", - "properties": { - "oom_kill_since_boot": { - "description": "OOM kills accumulated since boot; omitted when this kernel does not expose the counter.", - "type": "integer" - }, - "pgmajfault_since_boot": { - "description": "Major page faults accumulated since boot.", - "type": "integer" - } - }, - "required": [ - "pgmajfault_since_boot" - ], - "type": "object" - } - }, - "required": [ - "sample_interval_sec" - ], - "type": "object" - }, - "summary": { - "minLength": 1, - "type": "string" - }, - "truncated": { - "additionalProperties": false, - "properties": { - "reason": { - "minLength": 1, - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - } - }, - "required": [ - "data" - ], - "type": "object" } }, { @@ -20273,65 +20227,6 @@ "type": "integer" } } - }, - "output_shape": { - "properties": { - "data": { - "properties": { - "avg_ms": { - "type": "number" - }, - "max_ms": { - "type": "number" - }, - "min_ms": { - "type": "number" - }, - "probes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "latency_ms": { - "type": "number" - } - }, - "type": "object" - }, - "type": "array" - }, - "reachable": { - "type": "boolean" - }, - "resolved_ip": { - "type": "string" - } - }, - "type": "object" - }, - "summary": { - "minLength": 1, - "type": "string" - }, - "truncated": { - "additionalProperties": false, - "properties": { - "reason": { - "minLength": 1, - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - } - }, - "required": [ - "data" - ], - "type": "object" } } ] @@ -20364,7 +20259,7 @@ "Monitors/诊断分析" ], "x-mint": { - "content": "## 调用限制\n\n| 项 | 值 |\n| ------ | ----- |\n| 速率限制 | **600 次/分钟**;**10 次/秒** 每账户 |\n| 权限 | 任意有效的 `app_key`(只读;不受特定权限分类约束) |\n\n## 使用说明\n\n- 单次调用至多 **8** 个工具(`MaxToolsPerInvoke`);超出需在客户端拆分。8 个工具的上限与单监控对象 Agent 的并发能力对齐。\n- 工具在 Agent 上并行执行;webapi 返回的 `results[]` 与请求中的 `tools[]` 顺序对齐。\n- 长耗时:客户端超时至少设置 **35 秒**。该接口面向 AI-SRE / 人工排障流程,不适用于交互式 UI。\n- 请求级错误(`target_unavailable`、`ambiguous_target_kind`、`unknown_toolset_hash`、`forward_failed`)以 HTTP 200 返回,`data.error` 不为空,`data.results = []`。\n- 单工具失败以 HTTP 200 返回,`data.error` 不输出,`results[i].error` 被填充——务必同时检查**三层**(外层信封 `error`、`data.error`、再到每个 `results[i].error`)。\n- 响应采用**稀疏字段**:字段不存在即表示为空。成功时 `error` 直接省略而非返回 `null`;失败时 `data`、`summary`、`truncated` 均不输出。不要依赖占位的 `null` 字段做判断;当 locator 无法唯一解析时,`target` 同样不会出现。\n- `results[i].data` 是 Tool 的业务数据,monit-agent 的 result envelope **已被解开**——不会出现嵌套的 `data.data`。一行摘要位于 `results[i].summary`;`results[i].truncated`(内含 `reason`)仅在结果确实被截断时出现。\n- `results[i].params` 回显 webapi 收到的该 Tool 调用参数,便于在批量调用中关联结果——即使其中某个 Tool 失败也能对上号。\n- 按 `/monit/tools/catalog` 返回的 `input_schema` 构造 `tools[].params`。对于无参工具,务必显式传 `params: {}`。", + "content": "## 调用限制\n\n| 项 | 值 |\n| ------ | ----- |\n| 速率限制 | **600 次/分钟**;**10 次/秒** 每账户 |\n| 权限 | 任意有效的 `app_key`(只读;不受特定权限分类约束) |\n\n## 使用说明\n\n- 单次调用至多 **8** 个工具(`MaxToolsPerInvoke`);超出需在客户端拆分。8 个工具的上限与单监控对象 Agent 的并发能力对齐。\n- 工具在 Agent 上并行执行;webapi 返回的 `results[]` 与请求中的 `tools[]` 顺序对齐。\n- 长耗时:客户端超时至少设置 **35 秒**。该接口面向 AI-SRE / 人工排障流程,不适用于交互式 UI。\n- 请求级错误(`target_unavailable`、`ambiguous_target_kind`、`forward_failed`)以 HTTP 200 返回,`data.error` 不为空,`data.results = []`。\n- 单工具失败以 HTTP 200 返回,`data.error` 不输出,`results[i].error` 被填充——务必同时检查**三层**(外层信封 `error`、`data.error`、再到每个 `results[i].error`)。\n- 响应采用**稀疏字段**:字段不存在即表示为空。成功时 `error` 直接省略而非返回 `null`;失败时 `data`、`summary`、`truncated` 均不输出。不要依赖占位的 `null` 字段做判断;当 locator 无法唯一解析时,`target` 同样不会出现。\n- `results[i].data` 是 Tool 的业务数据,monit-agent 的 result envelope **已被解开**——不会出现嵌套的 `data.data`。一行摘要位于 `results[i].summary`;`results[i].truncated`(内含 `reason`)仅在结果确实被截断时出现。\n- `results[i].params` 回显 webapi 收到的该 Tool 调用参数,便于在批量调用中关联结果——即使其中某个 Tool 失败也能对上号。\n- 按 `/monit/tools/catalog` 返回的 `input_schema` 构造 `tools[].params`。对于无参工具,务必显式传 `params: {}`。", "href": "/zh/api-reference/monitors/diagnostics/monit-read-tools-invoke", "metadata": { "sidebarTitle": "调用监控对象工具" @@ -42847,12 +42742,7 @@ }, "target_kind": { "type": "string", - "description": "可选的 target kind。省略时 webapi 在当前已知的 kind 中自动推断。内置 kind:`host`、`mysql`。上次返回 `ambiguous_target_kind` 时,重试必须传入此字段。" - }, - "include_output_shape": { - "type": "boolean", - "description": "为 true 时,每个工具条目额外返回其 `output_shape` JSON Schema。默认 false,以便为 LLM 消费保持响应精简。", - "default": false + "description": "可选的 target kind。省略时 webapi 会按当前监控对象路由自动推断。若返回 `ambiguous_target_kind`,请从 `target_kinds` 中选择一个值重试。" } } }, @@ -42893,11 +42783,6 @@ "input_schema": { "type": "object", "description": "用于 `tools[].params` 的 JSON Schema。" - }, - "output_shape": { - "type": "object", - "description": "Tool 结果的 JSON Schema。仅当请求将 `include_output_shape` 置为 true 时返回。", - "x-flashduty-preserve-absence": true } } } @@ -42910,7 +42795,9 @@ "type": "string", "enum": [ "target_unavailable", - "unknown_toolset_hash", + "timeout", + "forward_failed", + "invalid_tool_result", "ambiguous_target_kind" ] }, @@ -43037,7 +42924,7 @@ "properties": { "code": { "type": "string", - "description": "常见取值:`timeout`、`target_unavailable`、`edge_unsupported`、`invalid_tool_result`、`internal`、`invalid_args`、`unknown_tool`、`unknown_tool_version`、`unknown_toolset_hash`、`target_not_owned`、`wrong_agent`、`overloaded`、`denied`、`permission_denied`、`credential_unavailable`、`target_unreachable`。" + "description": "常见 WebAPI 错误码:`timeout`、`target_unavailable`、`invalid_tool_result`、`internal`、`invalid_args`、`unsupported_syntax`、`path_not_found` 和 `catalog_changed`。Agent 特有的工具错误也可能原样返回。" }, "message": { "type": "string" @@ -43056,7 +42943,6 @@ "type": "string", "enum": [ "target_unavailable", - "unknown_toolset_hash", "forward_failed", "ambiguous_target_kind" ] @@ -49195,6 +49081,173 @@ "p95", "max" ] + }, + "ServiceDeskPlusRequestListRequest": { + "type": "object", + "description": "查询 ServiceDeskPlus 请求同步记录的过滤条件。按故障 ID 查询时可不传时间窗口;否则必须传入不超过 30 天的 Unix 秒时间窗口。", + "properties": { + "start_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "时间窗口起点(Unix 秒)。按 `incident_id` 查询时可省略。" + }, + "end_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "时间窗口终点(Unix 秒),必须大于等于 `start_time`。按 `incident_id` 查询时可省略。" + }, + "status": { + "type": "string", + "enum": [ + "success", + "failed" + ], + "description": "同步状态过滤。" + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "协作空间 ID 列表。" + }, + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "ServiceDeskPlus 集成 ID。" + }, + "incident_id": { + "type": "string", + "maxLength": 64, + "description": "Flashduty 故障 ID。提供后可不传时间窗口。" + }, + "request_id": { + "type": "string", + "maxLength": 64, + "description": "ServiceDeskPlus 请求 ID。" + }, + "asc": { + "type": "boolean", + "description": "为 `true` 时按内部记录 ID 升序返回;否则降序。" + }, + "p": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "页码,从 1 开始。使用 `search_after_ctx` 时忽略。" + }, + "limit": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 100, + "default": 20, + "description": "分页大小,默认 20,最大 100。" + }, + "search_after_ctx": { + "type": "string", + "description": "上一页返回的翻页游标。" + } + } + }, + "ServiceDeskPlusRequestMappingItem": { + "type": "object", + "description": "ServiceDeskPlus 请求与 Flashduty 故障之间的一条同步映射记录。", + "required": [ + "created_at", + "status", + "request_id", + "request_link", + "integration_id", + "incident_id", + "incident_title", + "channel_id", + "channel_name" + ], + "properties": { + "created_at": { + "type": "integer", + "format": "int64", + "description": "映射记录创建时间(Unix 秒)。" + }, + "status": { + "type": "string", + "enum": [ + "success", + "failed" + ], + "description": "同步状态。" + }, + "request_id": { + "type": "string", + "description": "ServiceDeskPlus 请求 ID。" + }, + "request_link": { + "type": "string", + "description": "ServiceDeskPlus 请求详情链接。" + }, + "integration_id": { + "type": "integer", + "format": "int64", + "description": "ServiceDeskPlus 集成 ID。" + }, + "incident_id": { + "type": "string", + "description": "关联的 Flashduty 故障 ID。" + }, + "incident_title": { + "type": "string", + "description": "关联故障标题。" + }, + "channel_id": { + "type": "integer", + "format": "int64", + "description": "故障所属协作空间 ID。" + }, + "channel_name": { + "type": "string", + "description": "故障所属协作空间名称。" + }, + "error_message": { + "type": "string", + "description": "同步失败时的错误信息。成功记录通常不返回该字段。" + } + } + }, + "ServiceDeskPlusRequestListResponse": { + "type": "object", + "description": "分页的 ServiceDeskPlus 请求同步记录列表。", + "required": [ + "items", + "total", + "has_next_page" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceDeskPlusRequestMappingItem" + }, + "description": "当前页同步记录。" + }, + "total": { + "type": "integer", + "format": "int64", + "description": "匹配记录总数,最多统计 1000 条。" + }, + "has_next_page": { + "type": "boolean", + "description": "是否还有更多页。" + }, + "search_after_ctx": { + "type": "string", + "description": "下一页翻页游标。无更多数据时为空。" + } + } } } } diff --git a/roundtrip_gen_test.go b/roundtrip_gen_test.go index 76ae2d3..b2e5c49 100644 --- a/roundtrip_gen_test.go +++ b/roundtrip_gen_test.go @@ -75,6 +75,7 @@ var exampleDataDecoders = map[string]func(json.RawMessage) error{ "POST /incident/post-mortem/list": func(d json.RawMessage) error { var v ListPostMortemsResponse; return json.Unmarshal(d, &v) }, "POST /incident/post-mortem/template/list": func(d json.RawMessage) error { var v ListPostMortemTemplatesResponse; return json.Unmarshal(d, &v) }, "POST /incident/post-mortem/template/upsert": func(d json.RawMessage) error { var v PostMortemTemplate; return json.Unmarshal(d, &v) }, + "POST /incident/sdp/request/list": func(d json.RawMessage) error { var v ServiceDeskPlusRequestListResponse; return json.Unmarshal(d, &v) }, "POST /incident/war-room/add-member": func(d json.RawMessage) error { var v string; return json.Unmarshal(d, &v) }, "POST /incident/war-room/create": func(d json.RawMessage) error { var v WarRoom; return json.Unmarshal(d, &v) }, "POST /incident/war-room/default-observers": func(d json.RawMessage) error { var v GetWarRoomDefaultObserversResponse; return json.Unmarshal(d, &v) },