From d9766098937eac69abbb15591482f28076141fb8 Mon Sep 17 00:00:00 2001 From: ysyneu Date: Wed, 22 Jul 2026 04:36:01 -0700 Subject: [PATCH] regen: sync SDK with monit invoke elapsed-field removal make sync-spec against flashduty-docs main (flashduty-docs#199) + make generate. Drops ToolInvokeResponseResultsItem.AgentElapsedMs/E2eElapsedMs now that monit-webapi keeps those timings server-side only. Also picks up the datasource credential-masking description the vendored copy had missed. --- data_sources.go | 2 +- models_gen.go | 4 ---- openapi/openapi.en.json | 28 +++++++--------------------- openapi/openapi.zh.json | 28 +++++++--------------------- 4 files changed, 15 insertions(+), 47 deletions(-) diff --git a/data_sources.go b/data_sources.go index ad8ff98..67c9b2e 100644 --- a/data_sources.go +++ b/data_sources.go @@ -9,7 +9,7 @@ type DataSourcesService service // Get datasource detail. // -// Retrieve full details of a single data source by its ID, including the `payload` configuration. +// Retrieve full details of a single data source by its ID, including the `payload` configuration, with credential fields masked as `******`. // // API: POST /monit/datasource/info (monit-datasource-read-info). func (s *DataSourcesService) ReadInfo(ctx context.Context, req *IDRequest) (*DataSourceItem, *Response, error) { diff --git a/models_gen.go b/models_gen.go index 25f6336..01a03a7 100644 --- a/models_gen.go +++ b/models_gen.go @@ -8626,12 +8626,8 @@ type ToolInvokeResponseError struct { // ToolInvokeResponseResultsItem is generated from the Flashduty OpenAPI schema. type ToolInvokeResponseResultsItem struct { - // Agent-self-reported tool execution time in milliseconds, excluding network round-trips. May be 0 when the failure occurred before execution started. - AgentElapsedMs int64 `json:"agent_elapsed_ms" toon:"agent_elapsed_ms"` // Tool business payload. Present only on success. Webapi already unwraps the monit-agent result envelope, so there is no nested `data.data`. Data *map[string]any `json:"data,omitempty" toon:"data,omitempty"` - // Webapi-observed end-to-end time in milliseconds (webapi → ws → edge → agent → ws → webapi). A large gap versus `agent_elapsed_ms` indicates network / edge slowness, not a slow tool. - E2eElapsedMs int64 `json:"e2e_elapsed_ms" toon:"e2e_elapsed_ms"` // Per-tool failure. Present only on failure, and mutually exclusive with `data` / `summary` / `truncated`. Error *ToolInvokeResponseResultsItemError `json:"error,omitempty" toon:"error,omitempty"` // Request params echoed back by webapi. Normalized to `{}` when the request omitted them or sent null. diff --git a/openapi/openapi.en.json b/openapi/openapi.en.json index 120de7e..bf4362c 100644 --- a/openapi/openapi.en.json +++ b/openapi/openapi.en.json @@ -14644,12 +14644,12 @@ "post": { "operationId": "monit-datasource-read-info", "summary": "Get datasource detail", - "description": "Retrieve full details of a single data source by its ID, including the `payload` configuration.", + "description": "Retrieve full details of a single data source by its ID, including the `payload` configuration, with credential fields masked as `******`.", "tags": [ "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Credential fields\n\nThe `info` / `create` / `update` responses never return credentials in cleartext. `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and their siblings come back as the placeholder `******`; a field that was never configured still comes back as an empty string. `sls.access_key_id` is an identifier rather than a credential and is returned as-is.\n\nOn update, submitting `******` unchanged means **keep the stored value**, and an empty string is treated the same way. To rotate a credential, submit the new value directly.\n\nOn create there is no stored value to keep — submitting a `******` copied from another response stores the literal string `******`, and the data source will fail to connect.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-info", "metadata": { "sidebarTitle": "Get datasource detail" @@ -14737,7 +14737,7 @@ "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `victorialogs`.\n- `edge_cluster_name` specifies which Monitors edge cluster evaluates rules using this datasource.\n- For `elasticsearch`, set `payload.elasticsearch.deployment` to `cloud` or `self-managed`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `victorialogs`.\n- `edge_cluster_name` specifies which Monitors edge cluster evaluates rules using this datasource.\n- For `elasticsearch`, set `payload.elasticsearch.deployment` to `cloud` or `self-managed`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.\n\n## Credential fields\n\nThe `info` / `create` / `update` responses never return credentials in cleartext. `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and their siblings come back as the placeholder `******`; a field that was never configured still comes back as an empty string. `sls.access_key_id` is an identifier rather than a credential and is returned as-is.\n\nOn update, submitting `******` unchanged means **keep the stored value**, and an empty string is treated the same way. To rotate a credential, submit the new value directly.\n\nOn create there is no stored value to keep — submitting a `******` copied from another response stores the literal string `******`, and the data source will fail to connect.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-create", "metadata": { "sidebarTitle": "Create datasource" @@ -14823,7 +14823,7 @@ "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Every call is recorded in the account audit log. Don't put secrets in request fields.\n\n## Credential fields\n\nThe `info` / `create` / `update` responses never return credentials in cleartext. `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and their siblings come back as the placeholder `******`; a field that was never configured still comes back as an empty string. `sls.access_key_id` is an identifier rather than a credential and is returned as-is.\n\nOn update, submitting `******` unchanged means **keep the stored value**, and an empty string is treated the same way. To rotate a credential, submit the new value directly.\n\nOn create there is no stored value to keep — submitting a `******` copied from another response stores the literal string `******`, and the data source will fail to connect.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-update", "metadata": { "sidebarTitle": "Update datasource" @@ -20372,7 +20372,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- Each result carries two latency fields: `agent_elapsed_ms` (agent-self-reported, excludes network) and `e2e_elapsed_ms` (webapi-observed end-to-end). A large gap between them indicates network / edge slowness rather than slow tool execution.\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`, `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.", "href": "/en/api-reference/monitors/diagnostics/monit-read-tools-invoke", "metadata": { "sidebarTitle": "Invoke target tools" @@ -20455,9 +20455,7 @@ "total_procs": 1036 } }, - "summary": "os.overview cpu=32.66% mem=74.46% swap=not_configured oom_kill_since_boot=2 load1=1.79", - "agent_elapsed_ms": 3120, - "e2e_elapsed_ms": 3188 + "summary": "os.overview cpu=32.66% mem=74.46% swap=not_configured oom_kill_since_boot=2 load1=1.79" }, { "tool": "net.tcp_ping", @@ -20469,9 +20467,7 @@ "error": { "code": "timeout", "message": "tool \"net.tcp_ping\" exceeded 8000ms" - }, - "agent_elapsed_ms": 8048, - "e2e_elapsed_ms": 8217 + } } ] } @@ -43057,16 +43053,6 @@ } }, "x-flashduty-preserve-absence": true - }, - "agent_elapsed_ms": { - "type": "integer", - "format": "int64", - "description": "Agent-self-reported tool execution time in milliseconds, excluding network round-trips. May be 0 when the failure occurred before execution started." - }, - "e2e_elapsed_ms": { - "type": "integer", - "format": "int64", - "description": "Webapi-observed end-to-end time in milliseconds (webapi → ws → edge → agent → ws → webapi). A large gap versus `agent_elapsed_ms` indicates network / edge slowness, not a slow tool." } } } diff --git a/openapi/openapi.zh.json b/openapi/openapi.zh.json index e3e5ee6..3b7c9fe 100644 --- a/openapi/openapi.zh.json +++ b/openapi/openapi.zh.json @@ -14636,12 +14636,12 @@ "post": { "operationId": "monit-datasource-read-info", "summary": "查看数据源详情", - "description": "通过 ID 获取单个数据源的完整信息,包括 `payload` 配置。", + "description": "通过 ID 获取单个数据源的完整信息,包括 `payload` 配置(凭据字段以 `******` 脱敏返回)。", "tags": [ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应不返回凭据明文。`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段一律以 `******` 占位返回;原本就没配置的字段仍返回空字符串。`sls.access_key_id` 是标识而非凭据,照常返回真实值。\n\n更新时把 `******` 原样提交表示**沿用已存值**,留空同样按沿用处理;要轮换凭据就直接提交新值。\n\n创建时没有可沿用的旧值——若把从别处读来的 `******` 当作真实口令提交,存下来的就是字面量 `******`,数据源会连不上。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-read-info", "metadata": { "sidebarTitle": "查看数据源详情" @@ -14729,7 +14729,7 @@ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- `type_ident` 必须为以下之一:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`victorialogs`。\n- `edge_cluster_name` 指定使用该数据源进行规则评估的 Monitors Edge 集群。\n- 对于 `elasticsearch`,`payload.elasticsearch.deployment` 须设为 `cloud` 或 `self-managed`。\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- `type_ident` 必须为以下之一:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`victorialogs`。\n- `edge_cluster_name` 指定使用该数据源进行规则评估的 Monitors Edge 集群。\n- 对于 `elasticsearch`,`payload.elasticsearch.deployment` 须设为 `cloud` 或 `self-managed`。\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应不返回凭据明文。`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段一律以 `******` 占位返回;原本就没配置的字段仍返回空字符串。`sls.access_key_id` 是标识而非凭据,照常返回真实值。\n\n更新时把 `******` 原样提交表示**沿用已存值**,留空同样按沿用处理;要轮换凭据就直接提交新值。\n\n创建时没有可沿用的旧值——若把从别处读来的 `******` 当作真实口令提交,存下来的就是字面量 `******`,数据源会连不上。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-write-create", "metadata": { "sidebarTitle": "创建数据源" @@ -14815,7 +14815,7 @@ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应不返回凭据明文。`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段一律以 `******` 占位返回;原本就没配置的字段仍返回空字符串。`sls.access_key_id` 是标识而非凭据,照常返回真实值。\n\n更新时把 `******` 原样提交表示**沿用已存值**,留空同样按沿用处理;要轮换凭据就直接提交新值。\n\n创建时没有可沿用的旧值——若把从别处读来的 `******` 当作真实口令提交,存下来的就是字面量 `******`,数据源会连不上。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-write-update", "metadata": { "sidebarTitle": "更新数据源" @@ -20364,7 +20364,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- 每条结果带两个耗时字段:`agent_elapsed_ms`(Agent 自报,不含网络)与 `e2e_elapsed_ms`(webapi 观测的端到端)。两者差距较大表示网络 / 边缘侧慢,而非工具执行慢。\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`、`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: {}`。", "href": "/zh/api-reference/monitors/diagnostics/monit-read-tools-invoke", "metadata": { "sidebarTitle": "调用监控对象工具" @@ -20447,9 +20447,7 @@ "total_procs": 1036 } }, - "summary": "os.overview cpu=32.66% mem=74.46% swap=not_configured oom_kill_since_boot=2 load1=1.79", - "agent_elapsed_ms": 3120, - "e2e_elapsed_ms": 3188 + "summary": "os.overview cpu=32.66% mem=74.46% swap=not_configured oom_kill_since_boot=2 load1=1.79" }, { "tool": "net.tcp_ping", @@ -20461,9 +20459,7 @@ "error": { "code": "timeout", "message": "tool \"net.tcp_ping\" exceeded 8000ms" - }, - "agent_elapsed_ms": 8048, - "e2e_elapsed_ms": 8217 + } } ] } @@ -43048,16 +43044,6 @@ } }, "x-flashduty-preserve-absence": true - }, - "agent_elapsed_ms": { - "type": "integer", - "format": "int64", - "description": "Agent 自报的 Tool 执行耗时(毫秒),不含网络往返。若失败发生在执行开始之前,可能为 0。" - }, - "e2e_elapsed_ms": { - "type": "integer", - "format": "int64", - "description": "WebAPI 观测到的端到端耗时(毫秒,webapi → ws → edge → agent → ws → webapi)。与 `agent_elapsed_ms` 差距很大说明是链路慢,而非 Tool 慢。" } } }