diff --git a/docs.json b/docs.json index cc744bd9..b0cf9588 100644 --- a/docs.json +++ b/docs.json @@ -2027,6 +2027,13 @@ "zh/monitors/alert-rules/description-template" ] }, + { + "group": "监控对象", + "icon": "desktop", + "pages": [ + "zh/monitors/targets/overview" + ] + }, { "group": "活跃告警", "icon": "bell", @@ -3407,6 +3414,13 @@ "en/monitors/alert-rules/description-template" ] }, + { + "group": "Monitoring Objects", + "icon": "desktop", + "pages": [ + "en/monitors/targets/overview" + ] + }, { "group": "Active Alerts", "icon": "bell", diff --git a/en/ai-sre/sessions.mdx b/en/ai-sre/sessions.mdx index 25845546..c2bcdae6 100644 --- a/en/ai-sre/sessions.mdx +++ b/en/ai-sre/sessions.mdx @@ -158,6 +158,16 @@ While a turn is running, **the Send button changes to a Stop button**. Clicking The input box remains active while a turn is running: you can keep typing and send messages, which are queued and executed in order after the current turn completes. Queued messages appear in a collapsible card above the input box, with a header showing the queue count (e.g. "3 queued"); each queued message can be edited or removed individually, and when more than one message is queued, the card also offers a **Clear all** action in its top-right corner. +The queue is authoritative server-side: messages you have sent but the agent (actor) has not read yet live in the server-side session queue, projected by the `pending_messages` field of the `POST /safari/session/get` response (in execution order). Before the agent starts processing one, you can **withdraw** it — the endpoint is `POST /safari/session/message/cancel`, whose request body carries `session_id` and `invocation_id` (the call ID the 202 ack / `user_message_enqueued` frame handed you when the message was sent); the response's `result` field tells you what happened: + +| Result | Meaning | +|---|---| +| `removed` | The message was removed from the queue and will **never be executed**; the server pushes a `user_message_cancelled` frame to every subscriber, and clients drop the corresponding pending bubble | +| `consumed` | The actor had already read the message — it belongs to the running turn; the withdrawal does not take effect and that turn still executes ("too late") | +| `forbidden` | Only the message's author may withdraw it; a call by anyone else returns `ErrAccessDenied` | + +Withdrawal only touches the waiting queue: an envelope the actor has already read can no longer be withdrawn (it returns `consumed`) — to interrupt a turn that is actually executing, use **Stop**. Only plain human messages can be withdrawn — question answers (`function_response`) and internal-producer envelopes (automation, child-session notifications, parent initial messages) are not included. The capability also applies to queued messages sent through API integration. The caller needs **participate permission** on the session (the same gate as sending a message or interrupting), and only the message's author can actually withdraw it — both conditions must hold for the result to be `removed`. + ### Environment Initialization The first time a session runs, an **environment initialization** card appears in the chat stream and steps through how the runtime environment (the sandbox) becomes ready: **set up a cloud container → start the runtime**; if the cloud template carries a setup script, init and reclaim runs add a third phase, **run the setup script** (resuming an existing sandbox never reruns it). The phases run serially, showing only the step currently in progress; once everything is done, the card collapses into a single result line that reflects whether this run created, resumed, or rebuilt the sandbox: @@ -190,10 +200,16 @@ Tools the agent invokes during a turn (reading and writing files, querying monit For multi-step tasks, the agent places a clickable progress badge in the chat stream (shaped like "Step X / N," with a ring progress indicator); clicking it expands into a task plan list, with each step carrying a status icon (Pending / In progress / Completed / Cancelled) and a priority tag (High / Medium / Low). If the agent ends its turn while a step is still "In progress," that step is shown as "Paused," signaling that you need to send a new message before it can proceed — it is not still running in the background. +The task plan is maintained only on surfaces that actually have someone watching it: `write_todos` (the built-in tool that maintains the list) is available only in console (`web`) and IM sessions — the web panel renders the TodoList card, and the IM side renders it as a progress card. **Automation (`automation`) and API (`api`) sessions do not get the tool**: the agent cannot call `write_todos` there and receives no "keep your todo list current" nudge, so multi-step work runs directly without producing a progress list (an automation run can still be opened in the console to see the full messages and tool calls, but there is no checklist). Dispatched child sessions (Subagent / A2A) are excluded as well — todo state is per-session, and a child writing todos would clobber the parent's list. + +A list is only created when the task genuinely is multi-step: **three or more distinct steps** (previously judged as "2+ tool calls," now tightened). Single-step lookups and pure conversation with no investigation behind it produce no list. Session entry kinds are described under "Session entry kind" above. + ### Agent Questions While troubleshooting, the agent may need you to clarify something, in which case it inserts an interactive question card into the chat stream: single-select (picking an option automatically advances to the next question), multi-select (after checking options you must click **Confirm** / **Next** to proceed), or free-text input (press Enter to submit). The **✕** button in the top-right corner of the card skips the whole question (not shown for required questions); a multi-question batch also shows a "Question i of N" pager, which you can navigate with the ←→ keys or by clicking, and returning to an already-answered question preserves your previous selection. Keyboard shortcuts: ↑↓ to move between options, Enter to confirm, Esc to skip. +**A parked question is auto-skipped by a new message**: when the model is parked on a question card waiting for your answer, sending a new message marks the parked question as skipped — the server writes a `function_response` (`reason=user_replied_with_message`, one entry per question in a batch) **without driving the model**; your new message runs immediately as the next turn, and the model in that turn sees "question skipped + what you said" instead of being blocked by the parked question. Conversely, **a late answer never resumes that question branch**: submitting an answer to a question that already has a user-side response (auto-skipped, or answered from another device) converts the answer into a plain message (rendered as the answer text — e.g. "(skipped)") that joins the next turn — the same question is never resumed twice. + ### When Authorization Is Required When a tool or MCP call is blocked because it lacks credentials or has not completed OAuth authorization, an **"Authorize [resource name] to continue"** card appears inline in the chat stream, in one of two forms: @@ -489,13 +505,43 @@ Every session determines a **reply language** at creation time. The agent replie The response `Content-Type` is `application/x-ndjson`. The **first line is always** a `session_meta` envelope containing the session's metadata; subsequent lines are session events. When `include_subagents=true`, each `subagent_dispatch` line is immediately followed by the complete event stream of the child session, which also begins with its own `session_meta` line. ``` -{"type":"session_meta","session_id":"...","app_name":"..."} // first line: session metadata -{"type":"message","..."} // subsequent: event lines (type varies) -{"type":"subagent_dispatch","child_session_id":"..."} // subagent dispatch marker -{"type":"session_meta","session_id":"","..."} // child session metadata -{"type":"message","..."} // child session events +{"type":"session_meta","session_id":"s_...","app_name":"ai-sre","entry_kind":"web","started_at":"2026-09-08T08:00:00Z","ended_at":"2026-09-08T08:05:00Z","model":"deepseek-v4-pro"} // first line: session metadata (has no seq) +{"type":"user_message","seq":1,"session_id":"s_...","content":"help me investigate this incident","ts":"2026-09-08T08:00:01Z"} // user message +{"type":"tool_call","seq":2,"session_id":"s_...","name":"bash","input":{"command":"..."},"status":"ok","call_id":"call_abc","ts":"2026-09-08T08:00:02Z"} // tool call (model request side) +{"type":"tool_call","seq":3,"session_id":"s_...","name":"bash","output":"...","output_bytes":123,"status":"ok","call_id":"call_abc","ts":"2026-09-08T08:00:03Z"} // tool call (runtime response side) +{"type":"subagent_dispatch","seq":4,"session_id":"s_...","agent_name":"explore","call_id":"call_def","ts":"2026-09-08T08:00:04Z"} // subagent dispatch +{"type":"session_meta","session_id":"sub-tsk_...","parent_session_id":"s_...","app_name":"ai-sre","entry_kind":"web","model":"deepseek-v4-pro"} // child session metadata (inlined when include_subagents=true) +{"type":"user_message","seq":1,"session_id":"sub-tsk_...","content":"...","ts":"..."} // child session events +{"type":"final_answer","seq":5,"session_id":"s_...","content":"...","usage":{"input_tokens":0,"output_tokens":0,"cache_read":0,"cache_creation":0},"ts":"2026-09-08T08:05:00Z"} // turn-final answer ``` +#### Line types + +The export stream contains only the line types below (the `type` field); no other types occur: + +| Line type | When it appears | Key fields | +|---|---|---| +| `session_meta` | **First line of every session** (both the main session and inlined child sessions) | `session_id`, `account_id`, `app_name`, `parent_session_id` (child sessions), `entry_kind` (`web` / `im` / `api` / `automation`; empty normalized to `web`), `started_at` / `ended_at` (session created / updated time), `model` | +| `user_message` | User message events | `content` (extracted text: multiple text parts joined with `\n`; reasoning / thought parts skipped; user rows never carry `usage`) | +| `system_reminder` | User rows whose text starts with `` | `content` (harness context injected by the system — locale / env / knowledge / memory / channel-guide / mount — not something you typed) | +| `tool_call` | Model tool request (`function_call` part) or runtime response (`function_response` part), **one line per part** | Request side: `name`, `input` (args object), `status` (optimistically `ok`), `call_id`; response side: `name`, `output` (response JSON serialized to a string), `output_bytes`, `status` (`ok` / `error`; a row-level error also carries `error`), `call_id` | +| `subagent_dispatch` | Model initiates an `agent_dispatch` call (one line per call) | `agent_name`, `call_id`; with `include_subagents=true` the child's full event stream is inlined right after this line | +| `final_answer` | Turn-complete assistant event (takes priority over `llm_call`) | `content`, `usage` | +| `llm_call` | Text-only model response that carries token usage | `content`, `usage`, `model`, `ended_at` | +| `agent_text` | Assistant prose with no usage and not turn-complete (fallback type) | `content` | +| `session_fork` | The "Forked from conversation" divider row | `content` | +| `error` | Appended at the end of the stream when an error occurs after streaming started, or inlined when a child session is unavailable under `include_subagents` | `content` (error text; consumers must inspect this line to tell whether the stream completed — see the Warning below) | + +#### Fields and behavioral conventions + +- **`seq`**: a monotonic counter over **lines emitted**, starting at 1 (reset per child session; never reset across pages). When one DB event yields several lines (see below), the lines are numbered consecutively in part order. `session_meta` lines carry no `seq`. +- **`call_id` (the pairing key)**: the ADK `function_call` / `function_response` id (both sides of a call share the same `id`). A single model response can bundle several tool calls into **one DB event** (e.g. 2 `agent_dispatch` calls + 1 `bash` call in the same event); the export emits one line per part, in the original part order, and `call_id` lets a consumer re-pair a response line with its call line without relying on emission order. +- **`usage` (token counts)**: per-event totals (`input_tokens` / `output_tokens` / `cache_read` / `cache_creation`), emitted as `0` rather than omitted when absent. It is **stamped on the first line of the event only** — the lines of a batched dispatch share one usage figure, so a consumer that sums per line is not over-counted N times. +- **`model`**: the model on `session_meta` and `llm_call` lines is the **session's own bound chatmodel** (set on the first turn's weighted pool draw and on any later failover rebind), which can and does disagree with the app's static config default (e.g. config default qwen, the session's actual model deepseek); sessions that never bound one fall back to the app config default, and unregistered apps get an empty value. +- **Timing**: `ts` is the event's write time (RFC 3339). `llm_call` and `tool_call` lines use it as an approximation of the **end time** (`ended_at`); start times and durations (`started_at` / `duration_ms`) are not provided (empty / 0). +- **`include_subagents=true`**: each `subagent_dispatch` line is immediately followed by the child session's complete export stream, recursively (every dispatch line of a batch is inlined, not just the first); the child's `seq` restarts at 1 and its `session_meta` carries `parent_session_id`. If a child session is missing or fails to export, the parent stream is not interrupted — an inlined `error` line is emitted and the stream continues. +- Some bookkeeping rows produce no export line (e.g. OAuth-authorized markers), so the line count can be lower than the session's event count. + If an error occurs after streaming has already begun, the server cannot switch to a standard JSON error envelope. Instead, a JSON-encoded error object is appended as the final line of the stream. Consumers must inspect this last line to determine whether the stream completed successfully. diff --git a/en/changelog/changelog.mdx b/en/changelog/changelog.mdx index d183f6f1..776b6319 100644 --- a/en/changelog/changelog.mdx +++ b/en/changelog/changelog.mdx @@ -4,6 +4,37 @@ description: "This page documents important updates and feature releases for Fla keywords: ["Changelog", "Product Release", "Feature Updates", "Flashduty", "Version History"] --- + + +### Copy silence rules + +Each rule in the silence-rule list gains a **Copy** action (quick-silence rules excluded) that copies the rule to the current or another escalation space: + +- **Entry**: the "Copy" button in the rule list actions; the new rule name is automatically prefixed with "Copy" and can be edited along with the description +- **Cross-space copy**: when copying to another escalation space, a "Copy succeeded" confirmation dialog shows the target space, new rule name, description, creator, and a "View" jump link +- **Copied fields**: silence conditions, silence behavior (`is_directly_discard` / `is_auto_delete`) and time filters are copied with the rule; `rule_id` and `from_incident_id` are not carried over +- **Length limits**: in the copy dialog the rule name is limited to 39 characters and the description to 500 characters + +### Batch acknowledge/close with custom forms (union interaction) + +The combination of batch acknowledge/close in the incident list with custom forms is streamlined: + +- **No-form incidents execute first**: selected incidents that need no form are acknowledged/closed immediately and deselected; the rest open a combined union form +- **Union form**: one submission writes the form content to every remaining incident; mixed scenarios show a summary at the top of the dialog (N acknowledged / M pending) +- **Abandon protection**: closing the dialog without submitting warns "N acknowledged; the remaining M incidents were neither filled nor handled" + +### Member search and SSO default-reference protection + +- **Member ID search**: the member list search box also exactly matches the member ID for pure-numeric input (alongside fuzzy name/email match and exact phone match) +- **SSO default roles/teams cannot be deleted directly**: a role or team selected as the default role or default team in any SAML2.0 / OIDC / CAS SSO configuration is rejected on deletion (reference error) until it is unselected in the SSO configuration's default options — this applies even when SSO or the corresponding sync switch is disabled, and forced deletion does not exempt it + +### ServiceMap retirement on the monitor targets page and monit-agent host diagnostics + +- **Monitor targets page**: ServiceMap-related columns (topology status/capture mode/observed at) and topology drawers are removed; column selection, per-row AI analysis and the rest of the target list remain +- **monit-agent host diagnostics retired**: the `fduty monit-agent` command tree and the `monit targets` / `monit tools-catalog` / `monit tools-invoke` / servicemap operations are removed together with the host-tool API; host diagnostics use `monit-query diagnose`, and database/middleware diagnostics use `monit datasource-tools-invoke` + + + ### SSO sync configuration: role and team sync diff --git a/en/developer/cli.mdx b/en/developer/cli.mdx index 85a9e681..478208b8 100644 --- a/en/developer/cli.mdx +++ b/en/developer/cli.mdx @@ -500,7 +500,7 @@ Common flags for `data`: ### monit datasource-tools-invoke — Datasource diagnostics -`monit datasource-tools-invoke` executes **one deterministic read-only tool** against a configured datasource — the current path for structured datasource diagnostics (replacing `monit-query diagnose` and the agent's diagnostic role). Get the datasource ID from the `id` field of `monit datasource-list`: +`monit datasource-tools-invoke` executes **one deterministic read-only tool** against a configured datasource — the current path for structured datasource diagnostics (replacing `monit-query diagnose`). Get the datasource ID from the `id` field of `monit datasource-list`: ```bash flashduty monit datasource-list --type redis_node --json | jq '.[] | {id, name, type_ident, address}' @@ -523,7 +523,7 @@ Semantics and limits: - The datasource must have `enabled=true`; `alerting_enabled=false` does not block diagnostics. - Response: `data` (tool-specific JSON evidence, preserved without conversion, never null, no legacy diagnose envelope), `tool`, `datasource_id`, optional `summary`, and a `truncated` object (with `reason`; its presence indicates truncation). -Errors are returned as-is; common codes: `edge_upgrade_required` (Edge too old), `mixed_edge_versions` (mixed Edge versions in the cluster), `no_active_edge` (no routable online Edge), `tool_not_supported` (tool unavailable), `invalid_request` (fix the parameters), `source_too_large` / `result_too_large` (narrow the request). On Edge version issues, do not rotate Edges or fall back to the Agent/legacy diagnose. +Errors are returned as-is; common codes: `edge_upgrade_required` (Edge too old), `mixed_edge_versions` (mixed Edge versions in the cluster), `no_active_edge` (no routable online Edge), `tool_not_supported` (tool unavailable), `invalid_request` (fix the parameters), `source_too_large` / `result_too_large` (narrow the request). On Edge version issues, do not rotate Edges or fall back to the legacy diagnose. ### monit — Datasource and alert-expression preview @@ -654,7 +654,7 @@ In `json`/`toon` mode the rows default to the compact fields `incident_id`, `tit ### Full command coverage -Beyond the curated commands above, the CLI now provides **full coverage** of the Flashduty OpenAPI through a spec-driven code generator. The current OpenAPI contains **348 API operations**, and the CLI generates resource-organized commands for **345** of them; the remaining operations (e.g. `session-read-export`) are provided by hand-written commands (`session export` / `safari session-export`). In addition to the On-call domain (incident, incident-trigger-subscription, change, channel, field, status-page, template, and more), it also covers: +Beyond the curated commands above, the CLI now provides **full coverage** of the Flashduty OpenAPI through a spec-driven code generator. The current OpenAPI contains **340 API operations**, and the CLI generates resource-organized commands for **337** of them; the remaining operations (e.g. `session-read-export`) are provided by hand-written commands (`session export` / `safari session-export`). In addition to the On-call domain (incident, incident-trigger-subscription, change, channel, field, status-page, template, and more), it also covers: - **AI SRE (`safari`)**: a2a-agents, artifacts, automations, knowledge, mcp-servers, sessions, skills, and more - **Alerting & noise reduction**: alert, alert-event, enrichment (alert-rules, rule-sets), route diff --git a/en/developer/go-sdk.mdx b/en/developer/go-sdk.mdx index 6fb65aae..d52c5b49 100644 --- a/en/developer/go-sdk.mdx +++ b/en/developer/go-sdk.mdx @@ -187,7 +187,7 @@ Endpoints are grouped by service and hang off the client: the call convention is `client.Diagnostics` (diagnostics) provides datasource query methods: `QueryData` runs a synchronous query via `POST /monit/query/data` and returns a stable `query_result.v1` structured result (`format` is always `query_result.v1`; `result.kind` is one of `frames` / `records` / `samples`). This API requires monit-edge v0.65.0 or later. `QueryDiagnose` (`POST /monit/query/diagnose`) runs pre-clustered RCA analysis (log patterns or metric trends) and can take up to 35 seconds — **but it is deprecated**: migrate to `client.DataSources.ToolsInvoke` using the `prometheus.metric_trends`, `loki.log_patterns`, or `victorialogs.log_patterns` tools. It is retained for existing consumers; the legacy request and response remain unchanged. -`client.DataSources.ToolsInvoke` (`POST /monit/datasource/tools/invoke`, `monit-datasource-tools-invoke`) executes one deterministic tool against a configured datasource: `tool` is a single tool name prefixed by the datasource type (e.g. `mysql.overview`), and `params` is the tool-specific JSON parameters (omitted means `{}`; an explicit `null` is invalid). Free SQL goes through `/monit/query/data`; `mysql.query` and `postgres.query` are unsupported. It requires all currently online routable Edge sessions in the cluster to support the v0.71.0 base invoke protocol (individual tools may require a newer implementation), and there is no tool catalog, no automatic replay, and no fallback to Agent or legacy diagnose. The request body limit is 128 KiB, the complete success response limit is 1 MiB, and the tool timeout is at most 25 seconds; the response is a `DatasourceToolResult` (`data` is tool-specific JSON, never null, `summary` is optional, and a `truncated` object with `reason` indicates truncation). +`client.DataSources.ToolsInvoke` (`POST /monit/datasource/tools/invoke`, `monit-datasource-tools-invoke`) executes one deterministic tool against a configured datasource: `tool` is a single tool name prefixed by the datasource type (e.g. `mysql.overview`), and `params` is the tool-specific JSON parameters (omitted means `{}`; an explicit `null` is invalid). Free SQL goes through `/monit/query/data`; `mysql.query` and `postgres.query` are unsupported. It requires all currently online routable Edge sessions in the cluster to support the v0.71.0 base invoke protocol (individual tools may require a newer implementation), and there is no tool catalog, no automatic replay, and no fallback to legacy diagnose. The request body limit is 128 KiB, the complete success response limit is 1 MiB, and the tool timeout is at most 25 seconds; the response is a `DatasourceToolResult` (`data` is tool-specific JSON, never null, `summary` is optional, and a `truncated` object with `reason` indicates truncation). For `client.DataSources`, the `payload` selects a type-specific configuration block by `type_ident`. Fifteen `type_ident` values are allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, plus the new diagnostic-only types `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, and `kafka` — diagnostic-only types always have `alerting_enabled` false (which does not block non-alerting queries or tools) and reject true. Connection address rules: Redis/MongoDB diagnostic types take a single `host:port` (bracket IPv6), with no URI, userinfo, or query; `kafka` takes 1–32 unique comma-separated `host:port` bootstrap addresses (at most 4096 characters after normalization, and the payload has no broker list); for `mongodb_mongod` / `mongodb_mongos` the configuration block's `auth_source` defaults to `admin`, username and password must be configured together, and client certificates are unsupported; the Redis node configuration's `database` defaults to 0. Sensitive fields such as the diagnostic types' `password` and Kafka's `tls_key` support `${env:NAME}` references: literal values are omitted from responses (only `${env:...}` references are echoed back), omitting the fields on update preserves the stored values, and explicitly sending an empty string clears them. diff --git a/en/developer/overview.mdx b/en/developer/overview.mdx index 0bbccd39..59924e36 100644 --- a/en/developer/overview.mdx +++ b/en/developer/overview.mdx @@ -58,7 +58,7 @@ See the [Command-line tool](/en/developer/cli) guide for the full installation m ## Go SDK -go-flashduty is the official Go SDK for Flashduty. Built in the go-github style, it provides a typed wrapper over the Flashduty OpenAPI covering 349 API operations across 39 services, so you can call them directly from Go with full type safety and autocompletion. +go-flashduty is the official Go SDK for Flashduty. Built in the go-github style, it provides a typed wrapper over the Flashduty OpenAPI covering 340 API operations across 38 services, so you can call them directly from Go with full type safety and autocompletion. The module is `github.com/flashcatcloud/go-flashduty` and requires Go 1.24+. Install with one command: diff --git a/en/monitors/targets/overview.mdx b/en/monitors/targets/overview.mdx new file mode 100644 index 00000000..8e7d27c4 --- /dev/null +++ b/en/monitors/targets/overview.mdx @@ -0,0 +1,58 @@ +--- +title: "Targets" +description: "View the monitoring targets recently observed for the current tenant (target inventory projection), customize visible columns and order, search by locator prefix, and run AI analysis on a single target." +keywords: ["targets", "target inventory", "projection view", "AI analysis", "column preferences"] +--- + +The Targets page displays the monitoring targets recently observed for the current tenant as a list. The list comes from the target inventory projection view (route projection) reported by the alert engine or collector: targets reported by the alert engine (Edge) or collector components appear here automatically once observed — no manual creation is needed. The page is a read-only inventory for confirming which targets have been observed, which Edge reported them, and when they were last observed. + +The page lives at `/monit/targets` and requires the `MonitTargetVisit` permission. In the current release, the Monitors sidebar menu does not show a "Targets" entry; it can be reached by navigating directly to that URL. + +## List fields + +Each row corresponds to one observed target. The columns shown by default are: + +| Column | Field | Description | +|--------|-------|-------------| +| Type | `target_kind` | Kind of the target | +| Locator | `target_locator` | Locator identifying the target, rendered as code; hover to see the full value | +| Agent version | `agent_version` | Version of the agent that reported this target | +| Host ID | `host_id` | Host ID | +| Edge cluster | `cluster_name` | Name of the Edge cluster that reported this target | +| Edge address | `edge_ipport` | Address (IP:port) of the Edge that reported this target | +| Last observed | `updated_at` | Time of the latest observation/report, formatted as `YYYY-MM-DD HH:mm:ss` | + +Optional fields (`agent_version`, `host_id`, `cluster_name`, `edge_ipport`) render as `-` when the target did not report them. + +## Customizing columns + +Click the **Columns** button in the list toolbar (it shows the visible/total count, e.g. `6/7`) to open the column picker: + +- **Show/hide**: check or uncheck a column to toggle its visibility. +- **Reorder**: drag the grip handle to the right of a column name to change the order; the change takes effect on drop. +- **Keep at least one column**: hiding the last visible column shows a "Keep at least one table column visible." warning — you cannot hide all columns. + +Column preferences are stored per user in browser `localStorage` under the key `monit.targets.columnPrefs` (structure version 2), with two arrays: `visibleKeys` (visible columns) and `orderedKeys` (column order). Six columns are visible by default (Type, Locator, Agent version, Edge cluster, Edge address, Last observed); **Host ID is hidden by default**. Unknown or obsolete column keys are filtered out and never cause errors when read. + +## Search + +The search box matches the **target locator prefix**; input is debounced 300ms before a request is sent. Search supports ASCII only and cannot contain whitespace, control characters, or `|`; invalid input does not trigger a search. When nothing matches, the list area shows "No matching targets". + +## Pagination + +The list is paginated by cursor, with 20 rows per page by default. Pages already visited keep their cursors as you move forward; changing the page size restarts from the first page. + +## Per-row AI analysis + +When AI SRE is enabled for the account and you hold the `AiSreChatVisit` permission, a pinned **Actions** column appears on the right, with an **AI Analysis** button on each row. Clicking it: + +1. Fetches the tool catalog for the target by its `target_kind` / `target_locator` (`/monit/tools/catalog`; failures are ignored silently). +2. Opens the AI SRE analysis panel (source `monit-targets`) with context that includes the target's `target_kind`, `target_locator`, `host_id`, `agent_version`, `cluster_name`, `edge_ipport`, `updated_at`, plus the available tool catalog and the invoke contract (`/api/monit/tools/invoke`). + +## ServiceMap display retired + +ServiceMap display on the Targets page was retired on 2026-09-07 (commit `299ec66`): the "ServiceMap hosts" toolbar button, the "Topology" button in the actions column, the three ServiceMap columns ("ServiceMap status", "Capture mode", "Topology observed at"), and the "Some ServiceMap statuses are temporarily unavailable" notice were all removed. The page no longer shows service topology — it is a pure target inventory list. The three ServiceMap column keys were also removed from the selectable column set, and stale keys left in older browsers' local storage are filtered out. + +## Empty state + +When the tenant has no reported targets yet, the page shows a "No targets yet" empty state with a **Connect** button that opens the installation documentation; the product's current empty-state copy reads "Install and connect monitagent by following the guide." The first load and search-in-progress show a loading state instead of rendering an empty table header. diff --git a/en/on-call/channel/escalation-rule.mdx b/en/on-call/channel/escalation-rule.mdx index 42623085..61b9aaf7 100644 --- a/en/on-call/channel/escalation-rule.mdx +++ b/en/on-call/channel/escalation-rule.mdx @@ -22,6 +22,19 @@ An escalation rule contains six core elements. The system matches rules from top You can enable or disable individual escalation rules. Disabled rules are skipped during matching and will not trigger notifications. You can also copy an escalation rule to the current channel or another channel to quickly reuse existing configurations. +### Copy an Escalation Rule + +Each escalation rule card shows a **Copy** icon on hover. Clicking it opens the copy dialog (the same component used for copying silence rules), which contains: + +| Field | Description | +| :--- | :--- | +| **Rule name** | Required; pre-filled with "Copy " plus the original name, **39 characters max** (the backend limit is 40) — overlong input is truncated in the field | +| **Channel** | Choose **This channel** or **Another channel**. Copying to another channel requires picking the target from a dropdown that excludes the source rule's channel; non-admin users only see channels they manage | +| **Description** | Optional; pre-filled with the original description, **500 characters max** — overlong input is truncated in the field | + +- The copy reuses the source rule's full configuration (trigger conditions, notification targets, notification methods, delay window, notification template, and escalation levels), but the **priority (list matching order) is not copied** — reposition the new rule in the list after copying +- Copying to the current channel makes the new rule appear in the list immediately; copying to another channel shows the **Copy succeeded** result dialog with the target channel, rule name, description, and creator. Click **Go to view** to open the target channel and locate the new rule + ### 1. Trigger Conditions Determines which incidents trigger the current rule. diff --git a/en/on-call/channel/noise-reduction.mdx b/en/on-call/channel/noise-reduction.mdx index 5d6db1e6..32337770 100644 --- a/en/on-call/channel/noise-reduction.mdx +++ b/en/on-call/channel/noise-reduction.mdx @@ -323,6 +323,25 @@ When creating a quick silence, the drawer shows "N labels identified, M labels a When repeatedly using quick silence on the same incident, it edits the original rule rather than creating a new one. +### Copy a Silence Rule + +Every rule card in the silence rule list (except rules created by **Quick Silence**) shows a **Copy** icon on hover. Clicking it opens the copy dialog, where you can set the new rule's name and description and choose the target channel: + +| Configuration | Description | +| :--- | :--- | +| **Rule name** | Required; pre-filled with "Copy " plus the original name (e.g. `Copy Database Maintenance`), **39 characters max** — overlong input is truncated in the field | +| **Description** | Pre-filled with the original description, **500 characters max** — overlong input is truncated in the field | +| **Channel** | Choose **This channel** (the current one) or **Another channel**. Copying to another channel requires picking the target from a dropdown that excludes the source rule's channel; non-admin users only see channels they manage | + +The result is **a new, independent rule**: it reuses the source rule's silence conditions, silence behavior (Drop directly / Retain and mark), auto-delete-on-expiration setting, and schedule (one-time or recurring), but it does not carry over identity fields such as `rule_id` or `from_incident_id`, nor the quick-silence link to the source incident. + +- **Copying to the current channel**: on success, the new rule appears in the list immediately and a "Copied" toast is shown. +- **Copying to another channel**: on success, a **Copy succeeded** dialog appears showing the target channel, rule name, description, and creator. Click **Go to view** to open the target channel and jump straight to the new rule's detail page. + + + **Quick silence** rules cannot be copied: a quick-silence rule is bound to its source incident (repeating the action on the same incident edits the original rule), so its card has no **Copy** action. + + ## Inhibit Rules {/* diff --git a/en/on-call/configuration/custom-forms.mdx b/en/on-call/configuration/custom-forms.mdx index b4d2a0df..bc7fd0f2 100644 --- a/en/on-call/configuration/custom-forms.mdx +++ b/en/on-call/configuration/custom-forms.mdx @@ -47,6 +47,23 @@ These forms also work in the Flashduty App: creating, acknowledging, and closing If an action has no configured form elements, or no element is visible for the current incident and user, Flashduty runs the normal create, acknowledge, or close flow without asking for additional input. +## Union interaction for batch operations + +When you select **multiple** incidents in the incident list and batch **acknowledge** or batch **close** them, the system first splits the selection into two groups by form applicability, then handles each group separately: + +- **Incidents that don't need the form**: the action has no configured form elements, or no element is visible for the current incident/user. Clicking **Acknowledge / Close** **executes immediately** and deselects them from the selection, then the form for the remaining incidents is shown +- **Incidents that need the form**: a **union form** is shown — you fill it once and the values are written to every listed incident in a single request (all-or-nothing; on failure the dialog stays open so you can retry) + +The union form's fields are the union of all incidents awaiting the form: an element appears if any incident can see it and is required if any incident requires it. + +**Overview in mixed scenarios**: when the selection contains both no-form and form incidents, the dialog starts with an overview — "N incidents acknowledged / M incidents pending acknowledgment" ("closed / pending closure" for the close action) — noting that "the incidents below require the form before acknowledgment and the form values are written to each of them". If every selected incident needs the form, the dialog goes straight to the form with no overview. + +**Abandon warning**: if you close the dialog without submitting (Cancel or the top-right close) after some incidents have already been executed, a warning appears — "N acknowledged, M remaining not filled in and not processed" ("closed" for the close action) — so you don't assume the whole batch was completed. + + + **Fallback when the form cannot be resolved**: for single-incident acknowledge/close, the existing semantics hold — a resolution failure raises the error and is not silently bypassed; for batch acknowledge/close, a resolution failure does not block the action and the whole batch is executed as if no form existed (consistent with the backend's degradation for form-less batch requests). + + ## Recommendations - Use custom fields for information you need to filter, report on, or reuse; use **Summary** for one-off action notes. diff --git a/en/on-call/integration/alert-integration/alert-pipelines.mdx b/en/on-call/integration/alert-integration/alert-pipelines.mdx index 5db87c0e..ea7a849b 100644 --- a/en/on-call/integration/alert-integration/alert-pipelines.mdx +++ b/en/on-call/integration/alert-integration/alert-pipelines.mdx @@ -56,6 +56,10 @@ Go to **Integration Center** => Select created integration => **Alert Processing Alert processing configuration entry + +**An empty rule list disables alert processing**: Processing rules can be saved as an empty list. After you delete all processing rules and save, the integration no longer performs any alert processing, matching the integration's initial state. To re-enable processing, click **Add processing rule** on the edit page; after you delete the last rule, the edit page shows the **No pipeline rules** empty state with an add button. + + ## Core Features and Scenarios ### Custom Severity diff --git a/en/on-call/integration/alert-integration/label-enhancement.mdx b/en/on-call/integration/alert-integration/label-enhancement.mdx index 19c125a2..d57ff972 100644 --- a/en/on-call/integration/alert-integration/label-enhancement.mdx +++ b/en/on-call/integration/alert-integration/label-enhancement.mdx @@ -31,6 +31,10 @@ Labels are used throughout Flashduty On-call's alert processing workflow: Go to Integration Details → **Label Enhancement** → **Add Rule**. + +**An empty rule list disables label enhancement**: Label enhancement rules can be saved as an empty list. After you delete all rules and save, the integration no longer performs any label enhancement, matching the integration's initial state; this applies to both alert events and change events. After you delete the last rule, the edit page shows the **No label rules** empty state — click **Add label rule** to configure rules again. + + ### Enhancement Types | Type | Description | Example | diff --git a/en/on-call/integration/sso/role-team-sync.mdx b/en/on-call/integration/sso/role-team-sync.mdx index 24ce58bc..03717ab9 100644 --- a/en/on-call/integration/sso/role-team-sync.mdx +++ b/en/on-call/integration/sso/role-team-sync.mdx @@ -66,6 +66,12 @@ Role/team name matching happens on the Flashduty server, with these rules: - Default teams: must **exist and not be deleted**, otherwise they are skipped. - The resolved role IDs / team IDs are deduplicated and sorted in ascending order. + +**A role or team selected as a default role or default team cannot be deleted.** The delete request returns `ReferenceExist` (the resource is still referenced by other entities and cannot be deleted): role deletion is blocked before the member-binding check runs, and forced deletion (`is_force`) does not bypass it either — forced deletion only revokes member assignments; SSO default references must be removed first. Unselect the target role or team in that SSO configuration's **Default Roles / Default Teams** options and save before you can delete it. + +The check looks at the **saved** defaults: even when SSO or the corresponding sync switch is currently off, the reference remains as long as `default_role_ids` / `default_team_ids` still hold the value — re-enabling the configuration must not restore dangling IDs. + + ## Where Each Protocol Reads the Names | Protocol | Source of role/team names | diff --git a/en/openapi/api-catalog.mdx b/en/openapi/api-catalog.mdx index 8bfcaddd..86fadfc5 100644 --- a/en/openapi/api-catalog.mdx +++ b/en/openapi/api-catalog.mdx @@ -465,6 +465,21 @@ All endpoint URLs use `https://api.flashcat.cloud` as the base, authenticated vi | POST | [`/safari/session/export`](/en/api-reference/ai-sre/sessions/session-read-export) | Export session transcript | | POST | [`/safari/session/delete`](/en/api-reference/ai-sre/sessions/session-write-delete) | Delete session | + +The `POST /safari/session/get` response includes a new `pending_messages` field, alongside `events`: the server-side projection of the human messages sitting in the session queue that the agent (actor) has not read yet, **in execution order** (head first), always an array (an empty array, never `null`, when nothing is queued). Each element has these fields: + +| Field | Type | Description | +|---|---|---| +| `invocation_id` | string | The call ID of the message (the ID handed out by the 202 ack / `user_message_enqueued` frame when the message was sent) | +| `client_msg_id` | string | Client-side message ID (optional) | +| `person_id` | int | Member ID of the message's author | +| `steering` | boolean | Whether this is an interrupting (steer) message (optional) | +| `query` | string | The message text, consistent with the send-ack frame | +| `parts` | array | The message's parts (`text` / `file` / `ref` / `skill`), passed through verbatim (optional) | + +Only plain human messages are projected: rows produced by internal producers (automation, child-session notifications, parent initial messages — they carry `source`) and question answers (`function_response`) are excluded; if the queue cannot be read, the field degrades to an empty array instead of failing the request. The projection matches the `user_message_enqueued` frame payload and is what clients use to render "sent but not yet handled" pending bubbles. + + ### Automations | Method | Endpoint | Description | diff --git a/en/platform/configure-sso.mdx b/en/platform/configure-sso.mdx index 5151934b..946d77a0 100644 --- a/en/platform/configure-sso.mdx +++ b/en/platform/configure-sso.mdx @@ -151,6 +151,10 @@ Roles and teams **match and fall back independently**. For example, if roles mat | On | No matches, with valid defaults | New members receive the corresponding defaults; existing members keep their assignments | | On | No matches and no valid defaults | Does not run this sync: new members follow the existing creation flow; existing members keep their roles or teams | + +**A role or team selected as a default role or default team in any saved SSO configuration cannot be deleted.** Deleting the role or team returns `ReferenceExist` (the resource is still referenced by other entities and cannot be deleted). Unselect it in the corresponding SSO configuration's **Default Roles / Default Teams** options and save first. The restriction also applies when SSO or the corresponding sync switch is currently off — the defaults are already saved and re-enabling the configuration must not restore dangling IDs; forced role deletion (`is_force`) does not bypass it either. + + **Valid mappings replace assignments; they do not append to them.** On an existing member's next SSO sign-in, valid mapping results can still replace manually assigned roles or teams. A dimension with no matches remains unchanged. To manage roles or teams entirely by hand, disable the corresponding sync option instead of only clearing its defaults. diff --git a/en/platform/permission-design.mdx b/en/platform/permission-design.mdx index 345ee4a1..85ce8ebe 100644 --- a/en/platform/permission-design.mdx +++ b/en/platform/permission-design.mdx @@ -192,6 +192,7 @@ In addition to preset roles, you can create custom roles for more granular permi - System preset roles (Admin, Responder, Viewer) cannot be modified or deleted - Custom roles support editing, copying, enabling/disabling, and deletion +- A custom role selected as a **default role** (`default_role_ids`) in any saved SAML2.0 / OIDC / CAS SSO configuration cannot be deleted: deletion returns `ReferenceExist` (the resource is still referenced by other entities and cannot be deleted), and forced deletion (`is_force`) does not bypass it either — forced deletion only revokes member assignments; SSO default references must be unselected first. Unselect the role in the corresponding SSO configuration's default role options before deleting it. The restriction also applies when SSO or role sync is currently disabled - A member can hold multiple roles simultaneously; their effective permissions are the union of all assigned roles diff --git a/en/platform/team-members.mdx b/en/platform/team-members.mdx index 0caaf17a..ca21aaf0 100644 --- a/en/platform/team-members.mdx +++ b/en/platform/team-members.mdx @@ -52,6 +52,7 @@ Click a team name to enter the team detail page, where you can: - Before deleting, confirm whether any channels, escalation rules, etc. are associated with this team + - A team selected as a **default team** (`default_team_ids`) in any saved SAML2.0 / OIDC / CAS SSO configuration cannot be deleted: deletion returns `ReferenceExist` (the resource is still referenced by other entities and cannot be deleted). Unselect the team in the corresponding SSO configuration's default team options first. The restriction also applies when SSO or team sync is currently disabled - After deletion, associated configurations will immediately become invalid and cannot be recovered. Please proceed with caution @@ -61,6 +62,16 @@ Click a team name to enter the team detail page, where you can: In the member list, a warning icon appears next to unverified email addresses or phone numbers. Unverified contact methods cannot receive alert notifications. Please remind members to complete verification promptly. The list also shows each member's **Time Zone**: members without a personal time zone follow the organization time zone — see [Organization Information](/en/platform/organization-info) and [Personal Settings](/en/on-call/configuration/personal-settings) for details. +### Searching Members + +The search box in the member list matches with **OR** semantics — a member is returned when any of the following conditions is met: + +- **Name or email**: fuzzy match containing the keyword +- **Phone number**: exact match when the input parses as a valid phone number +- **Member ID**: when the input is purely numeric, an additional exact match against the member ID (`member_id`) + +For example, entering a member's ID (purely numeric) locates that member directly without knowing their name, email, or phone number. + ### Invitation Methods diff --git a/zh/ai-sre/sessions.mdx b/zh/ai-sre/sessions.mdx index ade29416..41258fbe 100644 --- a/zh/ai-sre/sessions.mdx +++ b/zh/ai-sre/sessions.mdx @@ -158,6 +158,16 @@ Subagent / A2A 子会话本身也不能单独开启分享——分享只能在** 回合运行期间输入框依然可用:您可以继续输入并发送,消息会进入队列,在当前回合结束后依次执行。排队消息以一张可折叠的卡片展示在输入框上方,标题显示排队条数(如「3 条排队」);队列中的消息可逐条编辑或移除,超过一条时卡片右上角还提供 **全部清空** 一键清空整个队列。 +队列以服务端为准:已发送但 Agent(Actor)尚未读取的消息保存在服务端队列中,`POST /safari/session/get` 响应的 `pending_messages` 字段就是它的投影(按执行顺序排列)。在 Agent 开始处理前,您可以**撤回**一条这样的消息——撤回接口为 `POST /safari/session/message/cancel`,请求体携带 `session_id` 与 `invocation_id`(即发送消息时 202 回执 / `user_message_enqueued` 帧下发的调用 ID),响应中的 `result` 字段给出结果: + +| 结果 | 含义 | +|---|---| +| `removed` | 消息已从队列移除,**永远不会执行**;服务端向所有订阅方推送 `user_message_cancelled` 帧,各客户端据此丢弃对应的待处理(pending)气泡 | +| `consumed` | Agent 已读取该消息,它属于运行中的回合——撤回不生效,该回合照常执行(「来不及了」) | +| `forbidden` | 只有消息作者本人可以撤回;非作者调用返回 `ErrAccessDenied` | + +撤回只触碰等待队列:Agent 已读取的信封不再可撤回(返回 `consumed`),想中断正在执行的回合请使用**停止**。只有「普通人类消息」可撤回——提问作答(`function_response`)、内部生产者(自动化、子会话通知、父会话初启消息等)的信封不在其列。该能力同样适用于 API 集成发送的排队消息。调用方需要具备该会话的**参与权限**(与发送消息、中断同一门控),并且只有消息作者本人能成功撤回——两个条件都满足才是 `removed`。 + ### 运行环境初始化 会话首次运行时,对话流中会出现一张 **运行环境初始化** 卡片,分步展示运行环境(沙箱)的就绪过程:**建立云端容器 → 启动运行时**;若云端模板本身带有启动脚本,新建或重建时还会追加第三个阶段 **运行 setup 脚本**(恢复已有沙箱时不会重跑该脚本)。各阶段串行推进,每次只显示当前正在进行的一步;全部完成后卡片折叠为一行结果,按本次是新建、恢复还是重建分别显示: @@ -190,10 +200,16 @@ Agent 在回合中调用的工具(读写文件、查询监控、执行命令 执行多步骤任务时,Agent 会在对话流中放置一枚可点击的进度徽标(形如「第 X / N 步」,带环形进度指示),点击展开为任务计划清单:每一步都带状态图标(未开始 / 执行中 / 已完成 / 已取消)与优先级标签(高 / 中 / 低)。当 Agent 结束回合但某一步仍处于「执行中」时,该步会呈现为「已暂停」,提示您需要发送新消息才能推进,而不是仍在后台运行。 +任务计划只在**确实有人看清单**的渠道维护:`write_todos`(维护清单的内置工具)仅在控制台(`web`)与 IM 渠道会话中提供——web 面板渲染 TodoList 卡片,IM 侧渲染为进度卡。**自动化(`automation`)与 API(`api`)会话没有该工具**:Agent 在这些会话中调用不到 `write_todos`,也收不到「请维护待办清单」的提醒,多步任务直接执行、不产出进度清单(自动化运行仍可在控制台查看完整消息与工具调用记录,但没有清单)。被派发的子会话(Subagent / A2A)同样不提供该工具——待办状态按会话隔离,子会话写入会覆盖父会话的清单。 + +清单只在任务确实多步时才建立:**三个及以上独立步骤**的任务才会触发(此前按「2 次及以上工具调用」判定,已收紧)。单步查询、以及没有排查性质的纯对话不会生成清单。会话入口类型见上文「会话入口类型(entry_kind)」。 + ### Agent 提问 排障过程中,Agent 可能需要您澄清信息,这时会在对话流中插入一张交互式提问卡片:单选(点击选项即自动进入下一题)、多选(勾选后需点击 **确认** / **下一步** 才继续)或自定义文本输入(回车提交)。卡片右上角的 **✕** 按钮可跳过整卡提问(必答题不显示该按钮);多题批次时会额外显示「第 i / N 题」的翻页控件,可用键盘 ←→ 或点击翻页在题目间切换,切换回已答过的题目会保留之前的选择。支持键盘操作:↑↓ 移动选项、Enter 确认、Esc 跳过。 +**挂起中的提问会被新消息自动跳过**:当模型停在提问卡片上等待回答(卡片挂起)时,您直接发送一条新消息,挂起的提问会被自动标记为跳过——服务端写入一条 `function_response`(`reason=user_replied_with_message`,多题批次按题逐条标记),**不驱动模型**;您的新消息作为下一回合立即执行,该回合模型同时看到「提问已跳过 + 你说的话」,不会被挂起的问题挡住。反过来,**迟到的作答不会恢复该提问分支**:对已经有过用户侧响应(已被自动跳过,或已在其它设备作答)的提问,再提交答案会被转换为一条普通消息(按「(已跳过)」或答案文本方式渲染)参与下一回合——同一个提问绝不会被恢复执行两次。 + ### 需要授权时 当工具或 MCP 调用因缺少凭证或未完成 OAuth 授权而受阻时,对话流中会内联出现一张 **授权〈资源名〉以继续** 卡片,按授权方式分两种: @@ -489,13 +505,43 @@ Fork 会话会清理只属于运行中的临时状态,例如当前回合缓存 响应的 `Content-Type` 为 `application/x-ndjson`,**第一行始终**是 `session_meta` 类型的会话元数据信封,后续各行为会话事件。启用 `include_subagents=true` 时,每遇到一条 `subagent_dispatch` 类型的行,其后紧跟该子会话的完整事件流,子会话同样以自己的 `session_meta` 行作为起始。 ``` -{"type":"session_meta","session_id":"...","app_name":"..."} // 第一行:会话元数据 -{"type":"message","..."} // 后续:事件行(类型依内容而异) -{"type":"subagent_dispatch","child_session_id":"..."} // 子 Agent 派发标记 -{"type":"session_meta","session_id":"","..."} // 子会话元数据 -{"type":"message","..."} // 子会话事件 +{"type":"session_meta","session_id":"s_...","app_name":"ai-sre","entry_kind":"web","started_at":"2026-09-08T08:00:00Z","ended_at":"2026-09-08T08:05:00Z","model":"deepseek-v4-pro"} // 第一行:会话元数据(不携带 seq) +{"type":"user_message","seq":1,"session_id":"s_...","content":"帮我排查一下这个故障","ts":"2026-09-08T08:00:01Z"} // 用户消息 +{"type":"tool_call","seq":2,"session_id":"s_...","name":"bash","input":{"command":"..."},"status":"ok","call_id":"call_abc","ts":"2026-09-08T08:00:02Z"} // 工具调用(模型请求侧) +{"type":"tool_call","seq":3,"session_id":"s_...","name":"bash","output":"...","output_bytes":123,"status":"ok","call_id":"call_abc","ts":"2026-09-08T08:00:03Z"} // 工具调用(运行时回执侧) +{"type":"subagent_dispatch","seq":4,"session_id":"s_...","agent_name":"explore","call_id":"call_def","ts":"2026-09-08T08:00:04Z"} // 子 Agent 派发 +{"type":"session_meta","session_id":"sub-tsk_...","parent_session_id":"s_...","app_name":"ai-sre","entry_kind":"web","model":"deepseek-v4-pro"} // 子会话元数据(include_subagents=true 时内联) +{"type":"user_message","seq":1,"session_id":"sub-tsk_...","content":"...","ts":"..."} // 子会话事件 +{"type":"final_answer","seq":5,"session_id":"s_...","content":"...","usage":{"input_tokens":0,"output_tokens":0,"cache_read":0,"cache_creation":0},"ts":"2026-09-08T08:05:00Z"} // 回合结束的最终回答 ``` +#### 行类型 + +导出流只包含以下行类型(`type` 字段),不会出现其它类型: + +| 行类型 | 出现时机 | 关键字段 | +|---|---|---| +| `session_meta` | **每个会话的第一行**(主会话与内联子会话都有) | `session_id`、`account_id`、`app_name`、`parent_session_id`(子会话时)、`entry_kind`(`web` / `im` / `api` / `automation`,空值归一为 `web`)、`started_at` / `ended_at`(会话创建 / 更新时间)、`model` | +| `user_message` | 用户消息事件 | `content`(提取的文本:多个 text part 按 `\n` 连接,推理 / thought part 跳过;用户消息不携带 `usage`) | +| `system_reminder` | 以 `` 开头的用户行 | `content`(locale / env / knowledge / memory / channel-guide / mount 等系统注入的上下文,不是用户输入) | +| `tool_call` | 模型请求工具(`function_call` part)或运行时回执(`function_response` part),**每个 part 一行** | 请求侧:`name`、`input`(参数对象)、`status`(乐观标记 `ok`)、`call_id`;回执侧:`name`、`output`(回执 JSON 序列化为字符串)、`output_bytes`、`status`(`ok` / `error`;行级错误时另带 `error` 信息)、`call_id` | +| `subagent_dispatch` | 模型发起 `agent_dispatch` 调用(每个调用一行) | `agent_name`、`call_id`;`include_subagents=true` 时该行之后内联子会话的完整事件流 | +| `final_answer` | 回合结束的 assistant 事件(优先于 `llm_call`) | `content`、`usage` | +| `llm_call` | 纯文本模型响应且携带 token 用量 | `content`、`usage`、`model`、`ended_at` | +| `agent_text` | 无用量、非回合结束的助手文本(兜底类型) | `content` | +| `session_fork` | 「Fork 新对话」分隔线行 | `content` | +| `error` | 流已开始后出错时追加在流末尾;或 `include_subagents` 下子会话不可用时内联 | `content`(错误文本;消费方需检测该行以判断流是否完整,见下方 Warning) | + +#### 字段与行为约定 + +- **`seq`**:从 1 开始、按**输出行**计数的单调序号(按子会话重置;跨分页不重置)。一个 DB 事件产生多行时(见下),多行按 part 顺序连续编号。`session_meta` 行不携带 `seq`。 +- **`call_id`(配对依据)**:ADK `function_call` / `function_response` 的 ID(两侧共用同一个 `id`)。一个模型响应可以把多次工具调用**合并进一个 DB 事件**(例如同一事件里 2 个 `agent_dispatch` + 1 个 `bash`);导出按 part 各输出一行(顺序与原事件一致),`call_id` 让消费方把回执行与对应的调用行重新配对,而不依赖输出顺序。 +- **`usage`(token 用量)**:事件级计数(`input_tokens` / `output_tokens` / `cache_read` / `cache_creation`),无值时输出 `0` 而非省略。**只在事件的首行盖章**——一次批处理派发的多条行共享同一份用量,按行累计的消费方不会被多算 N 倍。 +- **`model`**:`session_meta` 与 `llm_call` 行的模型取自**会话自身绑定的 chatmodel**(首次回合加权池抽取、以及后续故障切换重绑定的结果),可能与应用的配置默认不同(例如配置默认 qwen、会话实际 deepseek);未绑定模型的会话回退到应用配置默认,应用未注册时为空。 +- **时间与耗时**:`ts` 为事件写入时间(RFC 3339)。`llm_call` 与 `tool_call` 行以该时间近似**结束时间**(`ended_at`);开始时间与耗时(`started_at` / `duration_ms`)当前不提供(为空 / 0)。 +- **`include_subagents=true`**:每个 `subagent_dispatch` 行之后立即递归内联该子会话的完整导出流(批量派发的每个 dispatch 行都会内联一次);子会话的 `seq` 从 1 重新计数,其 `session_meta` 携带 `parent_session_id`。子会话不存在或导出失败时不中断父流,输出一条内联的 `error` 行继续。 +- 部分簿记行不产生导出行(例如 OAuth 授权成功标记),因此事件行数可能少于会话事件数。 + 若流式传输已开始后发生错误,服务器**无法**切换回标准 JSON 错误包。此时会在流末尾追加一行 JSON 编码的错误对象,消费方需检测该行以判断流是否完整。 diff --git a/zh/changelog/changelog.mdx b/zh/changelog/changelog.mdx index db10fc5f..cac27e7b 100644 --- a/zh/changelog/changelog.mdx +++ b/zh/changelog/changelog.mdx @@ -4,6 +4,37 @@ description: "本页面记录 Flashduty 产品的重要更新和功能发布" keywords: ["更新日志", "产品发布", "功能更新", "Flashduty", "版本记录"] --- + + +### 静默策略复制 + +静默策略列表每条规则新增**复制**操作(快速静默规则除外),可将静默策略复制到当前或其它协作空间: + +- **复制入口**:规则列表操作栏「复制」按钮;复制时新规则名称自动加「复制」前缀,可修改名称与描述 +- **跨空间复制**:复制到其它协作空间后弹出「复制成功」结果确认框,展示目标空间、新规则名称、描述、创建者,并提供「去查看」跳转链接 +- **复制字段**:静默条件、静默行为(`is_directly_discard` / `is_auto_delete`)与时间过滤随规则一并复制;`rule_id`、`from_incident_id` 不携带 +- **长度限制**:复制弹窗中规则名称最多 39 字符、描述最多 500 字符 + +### 批量认领/关闭与自定义表单(并集交互) + +故障列表批量认领/关闭与自定义表单的组合交互得到优化: + +- **无需填表的故障先行执行**:选中项中不需要填表单的故障立即执行认领/关闭并反选,剩余故障弹出并集表单 +- **并集表单**:表单内容一次提交、同时写入每一条待处理故障;混合场景下弹窗顶部展示概览(已认领 N 条 / 待认领 M 条) +- **放弃保护**:未提交表单关闭弹窗时,提示「已认领 N 条,其余 M 条未填写表单、未处理」 + +### 成员搜索与 SSO 默认引用保护 + +- **成员 ID 搜索**:成员列表搜索框支持纯数字**精确匹配成员 ID**(与姓名/邮箱模糊匹配、手机号精确匹配并存) +- **SSO 默认角色/团队不可直接删除**:被任一 SAML2.0 / OIDC / CAS SSO 配置选为默认角色或默认团队的角色与团队,删除会被拒绝(引用错误),需先在 SSO 配置的默认选项中取消选择;SSO 或同步开关关闭时同样生效,强制删除也不豁免 + +### 监控对象页 ServiceMap 下线与 monit-agent 主机诊断退役 + +- **监控对象页**:移除 ServiceMap 相关列(拓扑状态/采集模式/观测时间)与拓扑浮层;监控对象列表的列选择、每行 AI 分析等能力保留 +- **monit-agent 主机诊断退役**:`fduty monit-agent` 命令树与 `monit targets` / `monit tools-catalog` / `monit tools-invoke` / servicemap 操作随 host-tool API 一并下架;主机诊断以 `monit-query diagnose`、数据库与中间件诊断以 `monit datasource-tools-invoke` 为准 + + + ### SSO 同步配置:角色与团队同步 diff --git a/zh/developer/cli.mdx b/zh/developer/cli.mdx index 98deb0cc..1a31e606 100644 --- a/zh/developer/cli.mdx +++ b/zh/developer/cli.mdx @@ -500,7 +500,7 @@ flashduty monit-query data [flags] # 结构化数据源查询 ### monit datasource-tools-invoke — 数据源诊断工具 -`monit datasource-tools-invoke` 对已配置的数据源执行**一次确定性的只读工具调用**,是结构化数据源诊断的现行路径(取代 `monit-query diagnose` 与 Agent 的诊断角色)。数据源 ID 从 `monit datasource-list` 的 `id` 字段获取: +`monit datasource-tools-invoke` 对已配置的数据源执行**一次确定性的只读工具调用**,是结构化数据源诊断的现行路径(取代 `monit-query diagnose`)。数据源 ID 从 `monit datasource-list` 的 `id` 字段获取: ```bash flashduty monit datasource-list --type redis_node --json | jq '.[] | {id, name, type_ident, address}' @@ -523,7 +523,7 @@ flashduty monit datasource-tools-invoke --tool 'redis_node.slowl - 需要数据源 `enabled=true`;`alerting_enabled=false` 不阻塞诊断。 - 返回值:`data`(工具特定的 JSON 证据,原样保留、永不为 null,不含旧 diagnose 信封)、`tool`、`datasource_id`、可选 `summary`,以及 `truncated` 对象(含 `reason`,存在即表示结果被截断)。 -错误按原样返回,常见错误码:`edge_upgrade_required`(Edge 版本过低)、`mixed_edge_versions`(集群内 Edge 版本混合)、`no_active_edge`(无可用在线 Edge)、`tool_not_supported`(工具不支持)、`invalid_request`(修正参数)、`source_too_large` / `result_too_large`(收窄请求范围)。出现 Edge 版本问题时不要轮换 Edge 或回退到 Agent/旧 diagnose。 +错误按原样返回,常见错误码:`edge_upgrade_required`(Edge 版本过低)、`mixed_edge_versions`(集群内 Edge 版本混合)、`no_active_edge`(无可用在线 Edge)、`tool_not_supported`(工具不支持)、`invalid_request`(修正参数)、`source_too_large` / `result_too_large`(收窄请求范围)。出现 Edge 版本问题时不要轮换 Edge 或回退到旧版 diagnose。 ### monit — 监控数据源与规则表达式预览 @@ -654,7 +654,7 @@ flashduty insight incident-export [flags] # 导出筛选后的故障列表为 ### 全量命令覆盖 -除上述精选命令外,CLI 现已通过 spec 驱动的代码生成实现对 Flashduty OpenAPI 的**全量覆盖**。当前 OpenAPI 含 **348 个 API 操作**,CLI 为其中 **345 个** 生成对应命令,其余操作(如 `session-read-export`)以手工实现命令提供(`session export` / `safari session-export`),并按资源组织为顶层命令组。除 On-call 域(incident、incident-trigger-subscription、change、channel、field、status-page、template 等)外,还覆盖了: +除上述精选命令外,CLI 现已通过 spec 驱动的代码生成实现对 Flashduty OpenAPI 的**全量覆盖**。当前 OpenAPI 含 **340 个 API 操作**,CLI 为其中 **337 个** 生成对应命令,其余操作(如 `session-read-export`)以手工实现命令提供(`session export` / `safari session-export`),并按资源组织为顶层命令组。除 On-call 域(incident、incident-trigger-subscription、change、channel、field、status-page、template 等)外,还覆盖了: - **AI SRE(`safari`)**:a2a-agents、artifacts、automations、knowledge、mcp-servers、sessions、skills 等 - **告警与降噪**:alert、alert-event、enrichment(alert-rules、rule-sets)、route diff --git a/zh/developer/go-sdk.mdx b/zh/developer/go-sdk.mdx index fd10b631..467f2408 100644 --- a/zh/developer/go-sdk.mdx +++ b/zh/developer/go-sdk.mdx @@ -187,7 +187,7 @@ client, err := flashduty.NewClient("YOUR_APP_KEY", `client.Diagnostics`(诊断)提供数据源查询方法:`QueryData` 通过 `POST /monit/query/data` 执行同步查询,返回稳定的 `query_result.v1` 结构化结果(`format` 固定为 `query_result.v1`,`result.kind` 为 `frames` / `records` / `samples` 之一),该接口要求 monit-edge v0.65.0 及以上版本;`QueryDiagnose`(`POST /monit/query/diagnose`)用于预聚合 RCA 分析(日志模式或指标趋势),最长运行 35 秒,**但已弃用**——请迁移到 `client.DataSources.ToolsInvoke` 并使用 `prometheus.metric_trends`、`loki.log_patterns` 或 `victorialogs.log_patterns` 工具;该接口为既有调用方保留,旧请求与响应格式不变。 -`client.DataSources.ToolsInvoke`(`POST /monit/datasource/tools/invoke`,`monit-datasource-tools-invoke`)在某个已配置数据源上执行一个确定性工具:`tool` 名称由数据源类型前缀修饰(如 `mysql.overview`),`params` 为工具专属 JSON 参数(省略视为 `{}`,显式 `null` 非法);自由 SQL 请走 `/monit/query/data`,`mysql.query` 与 `postgres.query` 不受支持。该接口要求集群中所有在线可路由的 Edge 会话都支持 v0.71.0 基础调用协议(单个工具可能要求更新的实现),无工具目录、无自动重放、也不会回退到 Agent 或旧版 diagnose。请求体上限 128 KiB,完整成功响应上限 1 MiB,单工具超时至多 25 秒;响应为 `DatasourceToolResult`(`data` 为工具专属 JSON、永不为 null,`summary` 可选,出现 `truncated` 时其 `reason` 说明截断原因)。 +`client.DataSources.ToolsInvoke`(`POST /monit/datasource/tools/invoke`,`monit-datasource-tools-invoke`)在某个已配置数据源上执行一个确定性工具:`tool` 名称由数据源类型前缀修饰(如 `mysql.overview`),`params` 为工具专属 JSON 参数(省略视为 `{}`,显式 `null` 非法);自由 SQL 请走 `/monit/query/data`,`mysql.query` 与 `postgres.query` 不受支持。该接口要求集群中所有在线可路由的 Edge 会话都支持 v0.71.0 基础调用协议(单个工具可能要求更新的实现),无工具目录、无自动重放、也不会回退到旧版 diagnose。请求体上限 128 KiB,完整成功响应上限 1 MiB,单工具超时至多 25 秒;响应为 `DatasourceToolResult`(`data` 为工具专属 JSON、永不为 null,`summary` 可选,出现 `truncated` 时其 `reason` 说明截断原因)。 `client.DataSources` 的 `payload` 按 `type_ident` 选择类型专属配置块。当前允许的 `type_ident` 共 15 种:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`,以及新增的诊断专用类型 `redis_node`、`redis_sentinel`、`mongodb_mongod`、`mongodb_mongos`、`kafka`——诊断专用类型的 `alerting_enabled` 恒为 false(不阻止非告警查询与工具调用),且拒绝传 true。连接地址规则:Redis/MongoDB 诊断类型为单个 `host:port`(IPv6 需加方括号),不接受 URI、userinfo 或 query;`kafka` 为 1–32 个以逗号分隔、互不重复的 `host:port` bootstrap 地址(规范化后至多 4096 字符,`payload` 中不再有 broker 列表);`mongodb_mongod` / `mongodb_mongos` 的配置块中 `auth_source` 默认为 `admin`,用户名与密码必须成对配置,不支持客户端证书;Redis 节点配置的 `database` 默认为 0。诊断类型的 `password` 与 Kafka 的 `tls_key` 等敏感字段支持 `${env:NAME}` 引用:响应中字面值会被省略(仅当存储值本身就是 `${env:...}` 引用时才回显),更新时省略这些字段即保留原值,显式传空字符串则清除。 diff --git a/zh/developer/overview.mdx b/zh/developer/overview.mdx index 25c24eaf..141c9934 100644 --- a/zh/developer/overview.mdx +++ b/zh/developer/overview.mdx @@ -58,7 +58,7 @@ curl -sSL https://static.flashcat.cloud/flashduty-cli/install.sh | sh ## Go SDK -go-flashduty 是 Flashduty 官方的 Go SDK,采用 go-github 风格的设计,对 Flashduty OpenAPI 进行类型化封装,覆盖 349 个 API 操作、39 个服务。您可以在 Go 程序中直接调用,享受完整的类型安全和自动补全。 +go-flashduty 是 Flashduty 官方的 Go SDK,采用 go-github 风格的设计,对 Flashduty OpenAPI 进行类型化封装,覆盖 340 个 API 操作、38 个服务。您可以在 Go 程序中直接调用,享受完整的类型安全和自动补全。 模块为 `github.com/flashcatcloud/go-flashduty`,要求 Go 1.24+,一行命令安装: diff --git a/zh/monitors/targets/overview.mdx b/zh/monitors/targets/overview.mdx new file mode 100644 index 00000000..1e0f5005 --- /dev/null +++ b/zh/monitors/targets/overview.mdx @@ -0,0 +1,58 @@ +--- +title: "监控对象" +description: "查看当前租户最近观测到的监控对象(target inventory 投影视图),自定义展示列与顺序、按标识前缀搜索,并对单个对象发起 AI 分析。" +keywords: ["监控对象", "Targets", "target inventory", "投影视图", "AI 分析", "列偏好"] +--- + +监控对象(Targets)页面以清单形式展示当前租户最近观测到的监控对象。列表来自告警引擎/采集组件上报的 target inventory 投影视图(route projection):对象由告警引擎(Edge)或采集组件上报,系统观测到后会在这里自动出现,不需要手工创建。页面本身是只读清单,你可以确认哪些对象已被观测、由哪台 Edge 上报,以及最近一次观测时间。 + +页面地址为 `/monit/targets`,访问需要 `MonitTargetVisit` 权限。当前版本 Monitors 侧边栏菜单未展示「监控对象」入口,可通过直接访问该 URL 进入。 + +## 列表字段 + +列表每行对应一个观测到的对象,默认展示以下列: + +| 列 | 字段 | 说明 | +|------|------|------| +| 类型 | `target_kind` | 对象类型 | +| 标识 | `target_locator` | 对象的定位标识(locator),以代码样式展示,悬停可查看完整值 | +| Agent 版本 | `agent_version` | 上报该对象的 Agent 版本 | +| Host ID | `host_id` | 主机 ID | +| Edge 集群 | `cluster_name` | 上报该对象所属的 Edge 集群名 | +| Edge 地址 | `edge_ipport` | 上报该对象的 Edge 地址(IP:端口) | +| 最近更新时间 | `updated_at` | 最近一次观测/上报时间,格式 `YYYY-MM-DD HH:mm:ss` | + +可选项(如 `agent_version`、`host_id`、`cluster_name`、`edge_ipport`)在对象未上报对应字段时显示为 `-`。 + +## 自定义展示列 + +点击列表工具栏的 **展示列** 按钮(显示当前可见列数/总数,例如 `6/7`)打开列选择器: + +- **显示/隐藏**:点击列名前的复选框切换列的可见性。 +- **调整顺序**:拖动列名右侧的拖拽手柄调整列的先后顺序,松手后立即生效。 +- **至少保留一列**:尝试隐藏最后一列时会提示「请至少保留一列表格列」,无法全部隐藏。 + +列偏好按用户保存在浏览器 `localStorage` 中,键为 `monit.targets.columnPrefs`(结构版本 2),包含 `visibleKeys`(可见列)与 `orderedKeys`(列顺序)两个数组。默认可见 6 列(类型、标识、Agent 版本、Edge 集群、Edge 地址、最近更新时间),**Host ID 默认隐藏**。未知或已不存在的列键会被过滤,读取时不会报错。 + +## 搜索 + +搜索框按 **target locator 前缀** 搜索,输入防抖 300ms 后自动发起请求。搜索仅支持 ASCII,且不能包含空白字符、控制字符或 `|`;不满足条件的输入不会发起搜索。没有匹配结果时列表区域显示「没有匹配的 target」。 + +## 分页 + +列表按游标分页(cursor),默认每页 20 条。逐页向后浏览时页面会记住已走过的游标;修改每页条数后会从第一页重新开始。 + +## 每行 AI 分析 + +当账户启用 AI SRE 且你具备 `AiSreChatVisit` 权限时,表格右侧会出现固定的 **操作** 列,每行提供 **AI分析** 按钮。点击后: + +1. 按该对象的 `target_kind` / `target_locator` 获取其工具目录(`/monit/tools/catalog`,失败时静默继续)。 +2. 打开 AI SRE 分析面板(来源标记为 `monit-targets`),上下文包含该对象的 `target_kind`、`target_locator`、`host_id`、`agent_version`、`cluster_name`、`edge_ipport`、`updated_at`,以及可用的工具目录与调用契约(`/api/monit/tools/invoke`)。 + +## ServiceMap 展示已下线 + +监控对象页的 ServiceMap 展示已于 2026-09-07 下线(提交 `299ec66`):移除了工具栏「ServiceMap 主机」按钮、操作列「拓扑」按钮、「ServiceMap 状态 / 采集模式 / 拓扑观测时间」三列,以及「部分 ServiceMap 状态不可用」提示条。当前页面不展示服务拓扑信息,只保留 target inventory 清单;三个 ServiceMap 列键也已从可选列集合移除,老用户本地存储中残留的对应键会被过滤。 + +## 空列表状态 + +当租户内尚无任何对象上报时,页面展示「暂无监控对象」空态,并提供「去接入」按钮跳转到安装文档;产品当前空态文案为「请先按文档安装并接入monitagent」。首屏加载或搜索中会先展示加载状态,避免渲染空表头。 diff --git a/zh/on-call/channel/escalation-rule.mdx b/zh/on-call/channel/escalation-rule.mdx index 672a0cdd..7eb923f5 100644 --- a/zh/on-call/channel/escalation-rule.mdx +++ b/zh/on-call/channel/escalation-rule.mdx @@ -23,6 +23,19 @@ src="https://download.flashcat.cloud/flashduty/video/escalate-rule.mp4" 您可以对每条分派策略进行启用或禁用操作。禁用的策略在匹配时会被跳过,不会触发通知。此外,您还可以将分派策略复制到当前协作空间或其他协作空间,快速复用已有配置。 +### 复制分派策略 + +每条分派策略卡片在悬停时显示 **复制** 图标按钮,点击后弹出复制弹窗(与静默策略复制共用同一弹窗组件),包含以下字段: + +| 字段 | 说明 | +| :--- | :--- | +| **策略名称** | 必填,默认以「复制 」加原策略名称填充,最多 **39 个字符**(后端限制 40),超长输入会被直接截断 | +| **协作空间** | 选择 **此协作空间** 或 **其他协作空间**。选择其他空间时需从下拉列表指定目标空间,列表会自动排除源策略所在空间;非管理员用户仅显示自己管理的空间 | +| **策略描述** | 可选,默认沿用原策略描述,最多 **500 个字符**,超长输入会被直接截断 | + +- 复制策略复用原策略的完整配置(触发条件、通知对象、通知方式、延迟窗口、通知模板、升级规则),但 **优先级(列表匹配顺序)不随复制携带**,复制后请在列表中调整新策略到合适的位置 +- 复制到当前协作空间成功后,新策略立即出现在列表中;复制到其他协作空间后弹出 **复制成功** 结果对话框,展示目标协作空间、策略名称、策略描述和创建者,点击 **去查看** 可打开目标空间并定位到该策略 + ### 1. 触发条件 决定了哪些故障会触发当前策略。 diff --git a/zh/on-call/channel/noise-reduction.mdx b/zh/on-call/channel/noise-reduction.mdx index 84a54aa8..8fb42d3f 100644 --- a/zh/on-call/channel/noise-reduction.mdx +++ b/zh/on-call/channel/noise-reduction.mdx @@ -324,6 +324,25 @@ src="https://download.flashcat.cloud/flashduty/video/silence.mp4" 同一故障重复操作快速静默时,会编辑原规则而非创建新规则。 +### 复制静默策略 + +静默策略列表中的每条规则卡片(**快速静默** 生成的规则除外)在悬停时显示 **复制** 图标按钮。点击后弹出复制弹窗,可设置新规则的名称、描述并选择目标协作空间: + +| 配置项 | 说明 | +| :--- | :--- | +| **策略名称** | 必填,默认以「复制 」加原规则名称填充(如 `复制 数据库维护`),最多 **39 个字符**,超长输入会被直接截断 | +| **策略描述** | 默认沿用原规则描述,最多 **500 个字符**,超长输入会被直接截断 | +| **协作空间** | 选择 **此协作空间**(当前空间)或 **其他协作空间**。选择其他空间时需从下拉列表指定目标空间,列表会自动排除源规则所在空间;非管理员用户仅显示自己管理的空间 | + +复制生成的是 **一条独立的新规则**:复用原规则的静默条件、静默行为(直接丢弃 / 保留标记)、到期自动删除设置和静默时间(单次或周期),但不会携带原规则的 `rule_id`、`from_incident_id` 等身份信息,也不会继承快速静默与来源故障的关联关系。 + +- **复制到当前协作空间**:复制成功后新规则立即出现在列表中,并提示「复制成功」。 +- **复制到其他协作空间**:复制成功后弹出 **复制成功** 结果对话框,展示目标协作空间、策略名称、策略描述和创建者;点击 **去查看** 可打开新规则所在空间,并直接定位到该规则详情页。 + + + **快速静默** 规则不可复制:快速静默与来源故障绑定(对同一故障重复操作会编辑原规则),其卡片上不显示「复制」操作。 + + ## 抑制策略 {/* diff --git a/zh/on-call/configuration/custom-forms.mdx b/zh/on-call/configuration/custom-forms.mdx index 5f354a70..1758c5a7 100644 --- a/zh/on-call/configuration/custom-forms.mdx +++ b/zh/on-call/configuration/custom-forms.mdx @@ -47,6 +47,23 @@ keywords: ["自定义表单", "故障创建", "故障认领", "故障关闭", " 如果某个操作没有配置表单元素,或当前故障和用户不满足表单元素的显示条件,系统会直接执行原有的创建、认领或关闭流程,不会额外要求填写内容。 +## 批量操作与自定义表单的并集交互 + +在故障列表中勾选 **多条** 故障后批量 **认领** 或 **关闭** 时,系统会先按表单的适用情况把选中项拆成两类,再分别处理: + +- **无需填表的故障**:该操作没有配置表单元素,或当前故障/用户不满足任何元素的显示条件——点击 **认领 / 关闭** 后 **立即执行**,并从选中列表中反选移除,随后才为其余项弹出填写表单 +- **需要填表的故障**:弹出 **并集表单**,填写一次,内容通过一次请求同时写入每一条故障(整体成败;失败时弹窗保持打开,可直接重试) + +并集表单的字段由所有待填写故障的并集决定:任一故障可见的元素即出现,任一故障必填的元素即必填。 + +**混合场景的概览**:当选中项中既有无需填表的、又有需要填表的时,弹窗顶部先显示概览——「已认领 N 条故障 / 待认领 M 条故障」(关闭操作对应「已关闭 / 待关闭」),并注明「以下故障需填写表单后认领,表单内容会同时写入每一条」;如果全部选中项都需要填表,则直接进入表单,不显示概览。 + +**中途放弃的提示**:如果未提交就关闭弹窗(如点击取消或右上角关闭),且此前已有部分故障被先行执行,会提示「已认领 N 条,其余 M 条未填写表单、未处理」(关闭操作对应「已关闭…」),避免误以为整批操作都已完成。 + + + **表单解析异常时的兜底**:单条认领 / 关闭保持原有语义——解析失败直接提示错误,不会静默绕过;批量认领 / 关闭时解析失败不拦截操作,按「无需填表」直接执行整批(与后端对无表单批量请求的降级行为一致)。 + + ## 使用建议 - 将需要筛选、统计或复用的内容建成自定义字段;将一次性的处理说明放在 **说明** 元素中。 diff --git a/zh/on-call/integration/alert-integration/alert-pipelines.mdx b/zh/on-call/integration/alert-integration/alert-pipelines.mdx index 275c2fc9..c8436eba 100644 --- a/zh/on-call/integration/alert-integration/alert-pipelines.mdx +++ b/zh/on-call/integration/alert-integration/alert-pipelines.mdx @@ -57,6 +57,10 @@ Pipeline 位于 **标签增强** 和 **路由分发** 之间。它的执行逻 告警处理配置入口 + +**空规则列表 = 不启用告警处理**:处理规则允许保存为空列表。删除全部处理规则并保存后,该集成不再执行任何告警处理,与集成初始状态一致。如需重新启用处理,在编辑页点击 **添加处理规则** 即可;删除最后一条规则后,编辑页会显示 **暂无处理规则** 空态并提供添加按钮。 + + ## 核心功能与场景 ### 严重程度自定义 diff --git a/zh/on-call/integration/alert-integration/label-enhancement.mdx b/zh/on-call/integration/alert-integration/label-enhancement.mdx index 8abe7e8c..6d291bb2 100644 --- a/zh/on-call/integration/alert-integration/label-enhancement.mdx +++ b/zh/on-call/integration/alert-integration/label-enhancement.mdx @@ -31,6 +31,10 @@ keywords: ["标签增强", "自动标签", "数据提取", "字段映射", "告 进入 集成详情 → **标签增强** → **添加规则**。 + +**空规则列表 = 不启用标签增强**:标签增强规则允许保存为空列表。删除全部规则并保存后,该集成不再执行任何标签增强,与集成初始状态一致;该行为对告警事件和变更事件均适用。删除最后一条规则后,编辑页显示 **暂无标签规则** 空态,点击 **添加标签规则** 即可重新配置。 + + ### 增强类型 | 类型 | 说明 | 示例 | diff --git a/zh/on-call/integration/sso/role-team-sync.mdx b/zh/on-call/integration/sso/role-team-sync.mdx index d5306355..167dbfe1 100644 --- a/zh/on-call/integration/sso/role-team-sync.mdx +++ b/zh/on-call/integration/sso/role-team-sync.mdx @@ -66,6 +66,12 @@ keywords: ["SSO", "单点登录", "角色同步", "团队同步", "同步配置" - 默认团队:必须**存在且未被删除**,否则跳过。 - 最终解析出的角色 ID / 团队 ID 会去重并按 ID 升序排列。 + +**被选为默认角色或默认团队的角色或团队无法删除。** 删除请求会返回 `ReferenceExist`(该资源仍被其他实体引用,无法删除)错误:角色删除在检查成员绑定之前即被拦截,勾选强制删除(`is_force`)也不会绕过——强制删除仅解除成员绑定,SSO 默认引用必须先取消。须先在该 SSO 配置的**默认角色 / 默认团队**选项中取消选择目标角色或团队并保存,才能删除。 + +该检查针对**已保存**的默认值:即使 SSO 或对应同步开关当前关闭,只要配置里仍保留 `default_role_ids` / `default_team_ids`,引用就依然存在——重新启用配置后不能出现悬空的 ID。 + + ## 各协议取值来源 | 协议 | 角色/团队名称的取值来源 | diff --git a/zh/openapi/api-catalog.mdx b/zh/openapi/api-catalog.mdx index ebc42976..a3d21972 100644 --- a/zh/openapi/api-catalog.mdx +++ b/zh/openapi/api-catalog.mdx @@ -465,6 +465,21 @@ Flashduty Open API 提供 **354** 个接口,覆盖 On-call、Monitors、RUM、 | POST | [`/safari/session/export`](/zh/api-reference/ai-sre/sessions/session-read-export) | 导出会话记录 | | POST | [`/safari/session/delete`](/zh/api-reference/ai-sre/sessions/session-write-delete) | 删除会话 | + +`POST /safari/session/get` 的响应在 `events` 之外新增 `pending_messages` 字段:会话队列中、Agent(Actor)尚未读取的人类消息的服务端投影,**按执行顺序排列**(队首在前),始终为数组(没有排队消息时是空数组,不会是 `null`)。每个元素的字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `invocation_id` | string | 该消息的调用 ID(发送消息时 202 回执 / `user_message_enqueued` 帧下发的 ID) | +| `client_msg_id` | string | 客户端消息 ID(可选) | +| `person_id` | int | 消息作者的成员 ID | +| `steering` | boolean | 是否为插话消息(可选) | +| `query` | string | 消息文本,与发送回执帧一致 | +| `parts` | array | 消息携带的 parts(`text` / `file` / `ref` / `skill`,原样透传,可选) | + +只有「普通人类消息」会被投影:带 `source` 的内部生产者消息(自动化、子会话通知、父会话初启消息等)与提问作答(`function_response`)所在的消息不在其中;队列读取失败时降级为空数组,不会导致请求失败。该投影与 `user_message_enqueued` 帧的载荷一致,用于渲染「已发送但尚未被处理」的待处理气泡。 + + ### 自动化 | 方法 | 接口 | 描述 | diff --git a/zh/platform/configure-sso.mdx b/zh/platform/configure-sso.mdx index 211b12ec..5991fd09 100644 --- a/zh/platform/configure-sso.mdx +++ b/zh/platform/configure-sso.mdx @@ -152,6 +152,10 @@ OIDC、SAML2.0 和 CAS 支持按身份提供商返回的**角色名称、团队 | 开启 | 没有匹配结果,有有效默认值 | 新建成员使用该项默认值;已有成员保持原值 | | 开启 | 没有匹配结果,也没有有效默认值 | 不执行该项同步:新建成员沿用原有创建流程;已有成员保留原有角色或团队 | + +**被任一已保存的 SSO 配置选为默认角色或默认团队的角色或团队无法删除。** 删除该角色或团队会返回 `ReferenceExist`(该资源仍被其他实体引用,无法删除)错误,须先在对应 SSO 配置的**默认角色 / 默认团队**选项中取消选择并保存。该限制在 SSO 或对应同步开关关闭时同样生效——默认值已保存在配置中,重新启用后不能出现悬空的 ID;强制删除角色(`is_force`)也不会绕过。 + + **有效映射是覆盖更新,不是追加。** 已有成员在下次 SSO 登录时,手工分配的角色或团队仍可能被有效映射结果替换;没有匹配结果的那一项保持不变。若完全由管理员维护角色或团队,请关闭对应同步开关,而不是仅清空默认值。 diff --git a/zh/platform/permission-design.mdx b/zh/platform/permission-design.mdx index 8343785b..e575d2eb 100644 --- a/zh/platform/permission-design.mdx +++ b/zh/platform/permission-design.mdx @@ -192,6 +192,7 @@ Flashduty 的权限点分为两类: - 系统预置角色(Admin、Responder、Viewer)不可修改或删除 - 自定义角色支持编辑、复制、启用/禁用和删除操作 +- 被任一已保存的 SAML2.0 / OIDC / CAS SSO 配置选为**默认角色**(`default_role_ids`)的自定义角色无法删除:删除会返回 `ReferenceExist`(该资源仍被其他实体引用,无法删除)错误,强制删除(`is_force`)也不会绕过——强制删除仅解除成员绑定,SSO 默认引用须先取消。须先在对应的单点登录配置的默认角色选项中取消选择该角色;该限制在 SSO 或角色同步开关关闭时同样生效 - 一个成员可以同时拥有多个角色,其权限为所有角色权限的并集 diff --git a/zh/platform/team-members.mdx b/zh/platform/team-members.mdx index 7756f9af..f5bde6f4 100644 --- a/zh/platform/team-members.mdx +++ b/zh/platform/team-members.mdx @@ -53,6 +53,7 @@ keywords: ["团队管理", "成员管理", "邀请成员", "组织架构", "角 - 删除前请先确认是否有协作空间、分派策略等与该团队有关联 + - 被任一已保存的 SAML2.0 / OIDC / CAS SSO 配置选为**默认团队**(`default_team_ids`)的团队无法删除:删除会返回 `ReferenceExist`(该资源仍被其他实体引用,无法删除)错误,须先在对应单点登录配置的默认团队选项中取消选择该团队;该限制在 SSO 或团队同步开关关闭时同样生效 - 删除后关联的配置将即刻失效且不可恢复,请谨慎操作 @@ -62,6 +63,16 @@ keywords: ["团队管理", "成员管理", "邀请成员", "组织架构", "角 成员列表中,未验证的邮箱或手机号旁会显示警告图标。未验证的联系方式无法接收告警通知,请提醒成员及时完成验证。列表同时展示每位成员的**时区**:未单独设置个人时区的成员显示为跟随组织,按组织时区生效,详见[组织信息](/zh/platform/organization-info)与[个人设置](/zh/on-call/configuration/personal-settings)。 +### 成员搜索 + +成员列表的搜索框对以下条件做 **OR** 匹配,命中任一条件即返回: + +- **姓名或邮箱**:包含关键字的模糊匹配 +- **手机号**:输入可解析为有效电话号码时精确匹配 +- **成员 ID**:输入为纯数字时,额外精确匹配成员 ID(`member_id`) + +例如输入某成员的 ID(纯数字)即可直接定位该成员,无需知道姓名、邮箱或手机号。 + ### 邀请方式