跳到正文
dsh-market 浏览插件 GitHub EN

guhanfei-ai/dsh-grafana

对话式 Grafana 运维:跨多个命名源站查看实时大盘数据,再通过审批与版本校验安全、可审阅地修改大盘。

Star 数 ★ 7 分类 工具与能力 收录于 2026-09-07 npm dsh-grafana

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add dsh-grafana

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

README

English

一个面向 Agent 的 Grafana 可观测 DeepSeek Harness 插件——读取大盘、查询实时指标、跟踪趋势与告警、跨源对比调查,并能安全、可审查地写回大盘。插件直接操作 Grafana API 与 Dashboard JSON,不需要截图。

项目状态:1.0 前版本。核心写回路径已经具备安全保护和自动化测试,但尚未完成 Grafana 12+ 兼容性认证。

核心能力

  • 通过浏览器 URL 或 UID 获取大盘;超大盘可改用结构化摘要模式,只返回面板/查询/阈值/变量骨架。
  • 按标题和标签搜索大盘。
  • 粘贴大盘或面板视图 URL,直接查询面板背后的真实数据。
  • 把大盘复制为全新大盘,并返回新大盘地址。
  • 通过对话调整面板、查询、阈值、变量和布局。
  • 写回时自动保持大盘所在文件夹。
  • 写入前检测并发修改。
  • 每次写入都必须经过 DSH 原生用户审批。
  • Service Account 凭证只保存在本机 DSH 凭证库。
  • 可配置多个具名 Grafana 源站,每次工具调用按名称指定目标。

环境要求

组件 已支持基线
Node.js 20.11 或更高版本
DeepSeek Harness 0.1.0-rc.6 至 0.2.0-rc.2 的预发布 peer(验证基线:0.1.0-rc.6、0.1.1-rc.2、0.1.2-rc.1、0.1.3-alpha.2、0.1.5-rc.1、0.1.7-rc.2、0.2.0-rc.2;预发布匹配取决于受支持的版本元组)
Grafana Grafana 10/11 文档中的传统 Dashboard HTTP API

Grafana 12 引入了新 Dashboard API。旧接口可能仍然可用,但 Grafana 12+ 暂未进入本插件的正式兼容矩阵。

本插件无构建步骤:纯 ESM JavaScript,安装即可加载,无需编译或打包。

安装

正式使用应安装不可变的 Release tag:

dsh plugin --profile <profile> add github:guhanfei-ai/dsh-grafana#v<version>

仅在测试时安装会持续变化的默认分支:

dsh plugin --profile <profile> add github:guhanfei-ai/dsh-grafana

本地开发:

npm ci
dsh plugin --profile <profile> add link:/绝对路径/dsh-grafana

安装后重启对应 DSH profile。

Windows 可使用 link:C:/path/to/dsh-grafana 形式的绝对路径。插件运行本身支持跨平台;deploy.sh 需要 Git Bash、WSL、macOS 或 Linux。

升级到 0.12.0

两个工具改名。 grafana_query 改为 grafana_panel_query,grafana_health 改为 grafana_status。参数、输出、超时与审批行为均不变。

旧名 新名
grafana_query grafana_panel_query
grafana_health grafana_status

旧名仍以「只报错」的转发 stub 保留在工具列表中:调用 grafana_query 或 grafana_health 会立即失败并指名新工具,进行中的对话一步即可自愈。自定义 prompt 与保存的工作流仍建议改用新名;按代理配置的工具白名单需要换成新名。

浏览器设置卡片需要 DSH 0.1.2 及以上。 在更旧的宿主(0.1.0–0.1.1)上,卡片会显示明确的「宿主过旧」提示而非源站列表——这是版本门槛,不是配置丢失。宿主侧全部工具在这些版本上照常可用,插件本身也仍可安装在 0.1.0-rc.6 及以上。

配置自动迁移。 升级前 settings.yaml.imported 中的具名源站优先于旧单源凭证;否则旧单源配置会物化为名为 default 的源站(Base URL 与已存令牌不变)。导入文件位于 $DSH_HOME/settings.yaml.imported,未设置 DSH_HOME 时位于 ~/.dsh/settings.yaml.imported。可选依赖 js-yaml 用于完整 YAML 解析,缺失时由内置解析器处理已知的 Grafana 段结构。迁移不会覆盖运行期间并发保存的配置。

配置

在 DSH Web 中打开 设置 → 插件 → Grafana 助手。

提示:设置页按 Host 端的 settings 命名空间(grafana)派发插件卡片。命名空间列表只在设置文档变更或连接重置时刷新,因此升级插件后如果卡片没有出现,刷新页面(或重连 Web UI)即可。

需要配置:

  • Service Account Token:例如 glsa_...。
  • Grafana URL:例如 https://grafana.example.com 或 https://example.com/grafana。

Token 使用 DSH 仅允许 loopback same-origin 访问的特权凭证 RPC:仅写不读,保存后的值不会被读取或回显。URL 存储在 grafana settings namespace 的非 secret 字段中,因此可读回明文并在卡片中显示以便核对。界面支持替换和删除。

HTTP 与 HTTPS 开箱即用,内网未配置证书的环境可直接填写 http:// 地址,无需额外设置。注意:HTTP 会明文传输服务账号令牌,不可信网络环境请务必使用 HTTPS。如需强制仅允许 HTTPS,可在插件配置中关闭:

allowInsecureHttp: false

只读模式面向监控排障等不应修改大盘的角色:

readOnly: true

启用后 grafana_push 与 grafana_clone 完全不注册——模型没有可调用的写入工具。设置卡片顶部提供只读模式开关(开 = 只读,关 = 读写),当前模式一目了然;切换只写插件级 readOnly 配置,不影响已配置的源站与默认源站。

切换到只读立即生效:即使写入工具在启动时已注册,审批门也会在运行时拒绝它们。从只读切回读写可能需要重启 DSH(或重新加载插件),取决于插件加载时的模式:以只读模式启动的插件从未注册写入工具,重启或重载之后才会恢复。

settings 中的 baseUrl 为权威来源;早期版本存在 GRAFANA_BASE_URL 凭证中的 URL 会在启动时自动迁移到 settings,之后凭证值仅作兜底。Token 凭证名默认为 GRAFANA_TOKEN,可通过 tokenRef 修改。

多个 Grafana 源站

设置卡片管理的是一个具名 Grafana 源站列表,而不再是单组 URL/令牌。每个源站包含:

  • 源站名称(必填、唯一):中英文皆可。它就是调用工具时传入 source 参数用以指定目标源站的值。
  • UID(只读):自动生成、全球唯一,以淡色小字显示在名称正下方。它是内部稳定主键——改名不会改变 UID,也不会影响已存令牌,且用户无法编辑。
  • Grafana URL 与 Service Account Token:每个源站各自独立。令牌以仅写不读的方式存入 DSH 凭证库。新源站使用 GRAFANA_TOKEN_<uid> 引用;轮换已保存的令牌时生成新引用。迁移保留原有引用,包括自定义引用。

点击新增源站创建,移除源站删除,设为默认选择省略 source 时使用哪一台。保存当前源站只保存该卡片,保存全部源站保存所有卡片;写入前校验名称和 URL。移除源站会清除其令牌,但仍被其它源站使用或引用状态无法确认的凭证会保留。清理失败时,卡片会提示并提供重试按钮。

保存前必须成功读取配置。读取失败或返回畸形数据时,卡片保持只读,并提供重新读取按钮。宿主提供配置版本号时,写入会携带该版本,防止陈旧页面覆盖其它页面的新修改。

令牌变更通过一次配置写入切换到新凭证引用。宿主明确拒绝时,旧配置继续生效;应答丢失时,会保留新凭证,等待确认实际保存状态。清理凭证前会检查是否仍有源站引用。成功保存的令牌草稿会清空,其它未保存的编辑予以保留。

每个工具都接受可选的 source 参数(源站名称),省略则用默认源站。调用 grafana_sources 可列出已配置的名称、UID、URL、令牌是否已配以及哪一台是默认源站。写操作的审批文案首行始终标明目标源站名称与 URL,方便确认改的是哪一台;写入与该源站绑定:等待审批期间默认源站若被改掉,写入会被拒绝,而不是发到执行时随手解析到的那一台。读取—审批—写入整条链路还绑定源站的 URL 与凭证引用,改掉源站地址会使其改前取得的快照失效——id/uid/version 相同并不能证明两次响应来自同一实例。早期版本的单源配置会在启动时迁移为一个名为 default 的源站,并保留其原有的自定义 tokenRef。allowInsecureHttp 仍是全局设置,对所有源站生效。

Grafana 权限

优先使用最小权限 RBAC,只授予目标大盘及文件夹所需范围:

  • dashboards:read
  • dashboards:write
  • 目标文件夹的 folders:read
  • grafana_panel_query 需要 datasources:query 以及对所查数据源的访问权限

不支持细粒度 RBAC 时才使用 Editor 角色,避免使用 Admin token。

各工具所需的具体权限:

工具 Grafana 权限
grafana_get dashboards:read
grafana_push dashboards:read + dashboards:write
grafana_clone dashboards:read + dashboards:write
grafana_panel_query dashboards:read + datasources:query
grafana_datasources datasources:read
grafana_metric datasources:read + datasources:query
grafana_compare datasources:read + datasources:query(每台源站各自)
grafana_trend dashboards:read + datasources:query
grafana_alerts alert.instances:read;definitions: true 另需 alert.provisioning:read;ruleStates: true 另需规则读取权限(被拒时就地报出缺失的 scope)
grafana_search dashboards:read
grafana_status dashboards:read(见下注)
grafana_sources 无(只读本机插件配置)

以读为主的配置可用 Viewer 基础角色叠加 Grafana 固定的只读 Alerting 角色;只有跑 grafana_push / grafana_clone 的令牌才需要追加 dashboards:write(或 Editor 基础角色)。关于 grafana_status:/api/health 无需鉴权,故该工具改为调用 GET /api/search 验证凭证,并从 /api/health 的 database 字段读取实例健康状态(该接口没有 status 字段)。

能力覆盖

与单一用途的 Grafana 桥接插件相比,本插件的差异点:

  • 多具名源站(至多 50 个):每个工具都接受可选的 source 参数,写入审批会标明目标实例,一个插件即可服务一整套 Grafana。
  • 凭证不落入配置文档:令牌以只写方式存进 DSH 凭证库,经特权回环 RPC 访问,绝不会被回读、展示或同步。
  • 浏览器设置卡片:源站的增删改与校验都在原生设置界面完成,无需手工编辑配置文件。

工具面覆盖从读到写的完整闭环:

能力 工具
读大盘(完整 JSON 或结构化摘要) grafana_get
改大盘 grafana_push
写 / 新建 grafana_push、grafana_clone
克隆大盘 grafana_clone
搜索大盘 grafana_search
面板实时值 grafana_panel_query
大盘序列趋势 grafana_trend
裸查询(PromQL / LogQL) grafana_metric
跨源站指标横向比较 grafana_compare
数据源发现 grafana_datasources
活跃告警与规则定义 grafana_alerts
源站与凭证健康 grafana_status、grafana_sources
多源站 所有工具经 source 参数

工具

每个工具都接受可选的 source 参数(已配置的源站名称)用以指定目标 Grafana 实例;省略则用默认源站。详见多个 Grafana 源站。

工具 行为
grafana_get 获取完整大盘,并保存一个短期可信的版本和目录快照。传 summary: true 时改为返回结构化摘要(面板、查询、阈值、变量),不记录写快照,适合超大盘。
grafana_push 在审批、身份校验、版本校验和目录保持后写回最近读取的大盘。
grafana_clone 把大盘复制为全新大盘(全新 UID、版本 1),默认留在源文件夹,并返回新大盘完整地址。同样需要审批,继续写入前必须先调用 grafana_get。
grafana_panel_query 执行粘贴的大盘或面板视图 URL(?viewPanel= 限定单面板;沿用 URL 里的 from/to 时间范围)背后的面板数据源查询,返回有界的实时数据摘要。模板变量默认使用大盘保存状态,可通过 variables 参数覆盖——单值({"env":"prod"})、多值({"host":["www","m"]},按查询中使用的格式修饰符展开)或 adhoc 过滤(见模板变量覆盖)。adhoc 过滤按数据源类型翻译:Elasticsearch 拼进各 target 的 Lucene 查询串,Prometheus/Loki 向每个 vector/stream selector 注入 label matcher,SQL 数据源替换 rawSql 中的 ${__adhoc} 占位符;其它数据源类型存在生效的 adhoc 时显式报错并列出支持矩阵。adhoc 覆盖为整体替换保存态,[] 表示清空,并按 target 的数据源 uid 逐个生效——绑定某个数据源的变量不会影响其它数据源。不支持的运算符/数据源组合显式报错,绝不静默忽略。仅支持 query/custom/interval/adhoc/textbox/constant/datasource 类型变量覆盖(datasource 型变量传 uid 字符串),不支持的类型会显式报错。Prometheus/Loki target 中裸多值变量渲染为 `(a
grafana_datasources 列出源站上已配置的数据源(uid、插件类型、显示名、是否默认、访问模式、以及配置的 URL——url="(empty)" 的行通常意味着该数据源配置有误、一查即失败,请换用其它 uid)。可按精确插件类型或大小写不敏感的名称子串过滤。结果分页返回(默认每页 40 行;limit 调整页大小,page 翻页),末尾一行披露当前页、总数与如何继续。调用 grafana_metric 前先用它确认要查询的 uid 或名称。只读。
grafana_metric 无需大盘,直接对 Prometheus 或 Loki 数据源执行一条裸文本查询(PromQL 如 up 或 rate(http_requests_total[5m]),或 LogQL 流选择器),数据源按 uid 或精确显示名寻址。mode: "instant"(默认)在区间末端求值一次;mode: "range" 对序列采样并给出每条序列的统计、上升/下降/持平判定与火花线——首行披露实际采样步长(step=),每条序列披露实际返回点数(points=),回答的精度与覆盖范围可见(对 Loki 的 range 查询返回的是日志行而非数值采样点,故这类序列只报行数与末行;Loki 的 instant 模式只接受 metric 查询,日志流选择器需用 range)。其它插件类型与服务端表达式会被拒绝并指向 grafana_panel_query。只读,不记录写快照。
grafana_compare 在多台已配置 Grafana 源站(一次 2-10 台)上并发执行同一 PromQL 查询,按源站独立解析数据源(同名会分别解到各自的 UID),并返回紧凑的横向比较结果;任一源站失败/无数据/多 series 都不会拖累其它成功源站,所有错误均经脱敏截断。全部请求源站都成功且各自返回单个可比较标量时,尾部附数学 summary(最高/最低/均值/比率);range 模式的「可比较标量」指带完整 first/last/min/max/avg 的序列,无时间轴的表格或日志结果只按 per-source 详情呈现并说明不可直接比较。只读,不记写快照也不进审批门。
grafana_trend 一次调用回答大盘的「在涨还是在跌」:把每个可见查询目标以较粗的区间查询重跑,每条序列给出实际返回点数、桶数、首/末/最小/最大/均值、方向判定与火花线;首行披露实际采样步长。表格型结果报告行数与统计并标 trend=n/a,不伪造方向。与 grafana_panel_query 共用同一套面板管线(变量、adhoc 过滤、旧格式数据源引用、逐面板降级)。时间范围最长 90 天。只读,不记录写快照。
grafana_alerts 从内置 Alertmanager 列出源站当前正在告警的条目(默认 state=firing;"suppressed" 表示被静默/抑制,"all" 两者都要)。上游的 active 状态(Alertmanager v2 的活动告警状态)统一报为 state=firing,正常告警不会被当成未知状态漏掉。可按文件夹、跨标签与注解的大小写不敏感子串、或大盘 URL/uid 过滤。活跃告警按 limit 参数封顶(默认 30、上限 100),丢弃的部分在末尾预算行披露。definitions: true 另发一次请求追加 provisioning 的规则定义(独立权限、独立故障隔离)。ruleStates: true 再追加每条规则的评估状态(rule-state 行:inactive、pending、firing、recording、unknown,来自 Prometheus 兼容规则接口)——pending 表示条件已满足但 for 时长未满,这是 Alertmanager 视角回答不了的;该段可用 ruleState 过滤。两个规则段共用 rulesPage 分页(每页 100 条),并披露总数与下一页参数。只读;告警文本是不可信数据。
grafana_search 按标题和精确标签搜索,最多返回 50 条。
grafana_status 检查 Grafana 连通性与 Service Account 凭证。
grafana_sources 列出已配置的 Grafana 源站:每个源站的名称、只读 UID、URL、令牌是否已配,以及哪一台是默认源站。只读,绝不返回令牌值。在向其它工具传 source 之前,可用它发现合法的源站名称。

跨源站比较示例(grafana_compare)

grafana_compare 在所列每台源站上对同一 PromQL 查询发请求,汇总成一张紧凑的横向比较视图——把原本三次工具调用 + 手动对比缩成一次调用。常见用法:

Region 对比——同一 P99 延迟在多个区域:

{
  "sources": ["tokyo", "singapore", "us"],
  "datasource": "Prometheus",
  "query": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{service=\"payment\"}[5m])))"
}

环境对比——production 与 staging 之间的错误率:

{
  "sources": ["prod", "staging"],
  "datasource": "Prometheus",
  "query": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))"
}

集群对比——跨 Grafana 集群 A/B/C 的节点 CPU,带更宽的窗口:

{
  "sources": ["cluster-a", "cluster-b", "cluster-c"],
  "datasource": "Prometheus",
  "query": "100 - (avg by (instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[2m])) * 100)",
  "mode": "range",
  "from": "now-15m",
  "to": "now",
  "points": 60
}

全部请求源站都成功且各自返回单个可比较标量时,输出末尾会附数学 summary(最高、最低、均值、max/min 比率);mode: "range" 下这要求每台源站的序列都带完整的 first/last/min/max/avg。一旦任一源站多 series、失败、无数据,或返回的形状在当前 mode 下不可比较(range 模式遇到无时间轴的表格/日志帧),summary 就不出,每个源站按各自的 per-series 摘要或清洗后的错误单独呈现,并说明不可直接比较的原因——高基数或部分失败的结果永远不会被当成直接标量比较读出来。

模板变量覆盖(grafana_panel_query)

variables 参数是一个以变量名为键的 JSON 对象。大盘中所有可覆盖变量(query/custom/interval/adhoc/textbox/constant/datasource 类型)均可覆盖;不支持的类型显式报错。

单值——替换该变量出现的所有位置($env、${env}):

{ "env": "prod" }

多值——传数组,展开方式遵循查询里使用的 Grafana 格式修饰符,为多选变量编写的大盘无需改动即可工作:

{ "host": ["www.example.com", "m.example.com"] }

Prometheus / Loki target 里无修饰符的裸多值引用($host)渲染为 (www.example.com|m.example.com)——即 =~ label matcher 里可用的交替形式,与 Grafana 自身渲染一致。值不做正则转义(Grafana 也不转义;双引号 PromQL 字符串里把 . 转义成 \. 是语法错误)。需要精确匹配时使用显式 ${host:regex} 修饰符。

查询占位符 展开结果
$host / ${host} www.example.com,m.example.com(CSV,Grafana 默认)
${host:csv} www.example.com,m.example.com
${host:doublequote} "www.example.com","m.example.com"
${host:singlequote} 'www.example.com','m.example.com'
${host:json} ["www.example.com","m.example.com"]
${host:raw} www.example.com,m.example.com
${host:pipe} www.example.com|m.example.com
${host:percent} 逐值 URL 编码后逗号连接(www.example.com,m.example.com;["a b"] → a%20b)
${host:querystring} host=www.example.com&host=m.example.com(以变量名为键)
${host:regex} www\.example\.com|m\.example\.com(逐值正则转义后以 | 连接)
${host:lucene} 逐值 Lucene 转义后以空格连接
${host:sqlstring} 'www.example.com','m.example.com'(值内单引号翻倍)

无修饰符的单值变量展开为裸值(与 String(value) 逐字节一致);修饰符对单值同样生效(${host:json} → "www.example.com",${host:pipe} → www.example.com)。未知格式修饰符显式报错。内建变量($__interval、$__rate_interval、${__from:date} 等)始终原样透传。

adhoc 过滤覆盖——整体替换大盘保存的 adhoc filters([] 表示清空):

{
  "adhoc": [
    { "key": "host.keyword", "operator": "=", "value": "www.example.com" },
    { "key": "status", "operator": "!=", "value": "404" }
  ]
}

未绑定的 adhoc 条目对所有数据源生效;加 "datasourceUid": "<uid>" 可绑定到单个数据源。翻译方式取决于数据源类型:

数据源类型 翻译方式 支持的运算符
Elasticsearch Lucene 条件拼进各 target 的查询串(host.keyword:"www.example.com";面板自带查询串非空时括号包裹后以 AND 连接) = != 恒可;> < 仅数字;=~ !~ 映射为 Lucene 正则 field:/pattern/(模式内的 / 会转义;空模式报错)
Prometheus label matcher 注入每个 vector selector(host="www.example.com";裸 metric 名补上 {...}) = != =~ !~;> < 报错
Loki matcher 注入 stream selector({app="api", host="www.example.com"});pipeline 阶段不动 = != =~ !~;> < 报错
SQL(MySQL/Postgres/MSSQL/MariaDB/SQLite/ClickHouse) rawSql 中的 ${__adhoc} / $__adhoc 占位符替换为 WHERE 风格条件(host = 'www.example.com';值做单引号转义) = != > <(数字)、=~ !~(映射为 LIKE/NOT LIKE)
其它类型 显式报错并列出支持类型 —

datasource 型变量——用数据源 uid 字符串覆盖:

{ "datasource": "prom-prod" }

datasource 引用了该变量的面板({"type":"prometheus","uid":"$datasource"})会改查指定的 uid。传入非字符串值(数字、数组)会显式报错。

旧格式 datasource 引用(grafana_panel_query)

旧版大盘的 datasource 引用形状无法直接用于 /api/ds/query,grafana_panel_query 会透明解析:

面板 datasource 形状 解析方式
纯字符串 uid(Grafana 8 及更早) 经 GET /api/datasources 查找,随查询发送解析出的 {type, uid}
{"uid":"$datasource"} / {"type":"prometheus","uid":"$datasource"}(datasource 型模板变量) 用该变量保存的 current 值插值进 uid
保存值为 "default" 映射到服务端默认数据源("default" 是 /api/ds/query 不接受的保留伪 uid)
索引不可用(403)或 uid 未知 裸 {uid} 透传,由 Grafana 自行报错;若此时还有生效的 adhoc 过滤无法对未知类型翻译,则显式报错

数据源索引按需懒加载——仅当大盘确实存在需要解析的引用时才请求一次。当所有面板都被跳过时,报错会列出每个面板的 id、标题与跳过原因,而不是一句干巴巴的 "no executable query"。

真机验收矩阵(变量覆盖 × 运算符 × 数据源类型、旧格式大盘形状)记录于 INTEGRATION.md。

安全写回流程

  1. 让 DSH 获取大盘 URL 或 UID。
  2. 描述需要修改的内容。
  3. 检查审批窗口中的大盘身份和变更摘要。
  4. 批准或拒绝写回。
  5. 刷新 Grafana;再次写入前重新获取大盘。

grafana_push 默认使用 overwrite: false。写回前会立即重新读取大盘并拒绝过期版本,同时自动保持当前目录。移动目录需要 allowFolderMove: true;强制覆盖需要 forceOverwrite: true,且仍会触发审批。

审批弹窗中展示的大盘身份(UID、标题、版本、所在文件夹)以及「快照于 X 分钟前获取」全部来自 grafana_get 保存的服务端可信快照,而不是模型提交的大盘 JSON,因此模型幻觉或被篡改的标题不会误导审批。没有可信快照时,弹窗会直接说明写回会被拒绝并要求先 grafana_get。审批弹出前插件还会实时核对 Grafana 端当前状态:版本或文件夹与快照不一致时,弹窗会给出醒目警示并列出两侧版本号;无法连接 Grafana 时,弹窗会注明「无法确认当前状态」。实时复核只用于丰富审批文案,写入前的最终校验始终在写回时重新执行。实时复核成功时,弹窗还会附上有界且经过清洗的内容 diff(新增/删除/修改的面板、模板变量与顶层字段),让审批人核对真实改动,而不只是模型自述的变更摘要。

安全与数据边界

  • Token 不会进入工具参数、模型消息、日志或 Git。
  • 带凭证的请求拒绝 HTTP 重定向,避免凭证被转发到其他来源。
  • 非本机明文 HTTP 默认允许(可通过配置关闭)。
  • 请求支持取消、超时、响应大小限制和 Dashboard 输入大小限制。
  • API 错误只暴露有限的状态和消息。
  • Grafana 返回内容始终作为不可信数据处理,而不是模型指令。

Dashboard JSON 仍可能包含 SQL、内部域名、链接、标签和业务信息。获取大盘会把这些 JSON 作为工具上下文发送给当前模型提供商。在处理机密大盘前,请先确认模型提供商的数据政策。

漏洞报告和支持策略参见 SECURITY.md。

开发验证

npm ci
npm run verify
npm pack --dry-run --ignore-scripts

自动化测试使用 Node 内置测试运行器和模拟 Grafana 响应。CI 覆盖 Node 20、22 和 24。

更多信息参见 CONTRIBUTING.md 和 CHANGELOG.md。

发布

普通手工 git push 不会触发版本号、tag 或 Release。发布是一个显式的三步流程,要求 main 工作区干净且变更已提交:

./deploy.sh release   # 锁版本:递增版本、提交、打 tag、推送(patch/minor/major 或 x.y.z)
./deploy.sh build     # 验证并打包,产物输出到 dist/
./deploy.sh publish   # 先将安装包发布到 npm,再创建 GitHub Release 并上传同一产物

直接运行 ./deploy.sh(不带参数)可查看内置帮助。首次发布前需要运行一次 gh auth login 和 npm login。每一步都有自我守卫:all 与 release 在开始前会先预检 GitHub 与 npm 登录状态(避免版本锁定、tag 推送之后才发现凭证失效白跑一遍),release 要求 main 干净且与远端同步,build 要求 tag 已锁定在 HEAD 上,publish 要求打包产物存在且 GitHub 与 npm 凭证就绪;所有会改动远端的操作都会先要求明确确认。

publish 会先把 dist/ 里的安装包发布到 npm,再把同一个文件上传到 GitHub Release,两个渠道分发的产物字节完全一致。npm 版本号不可变:如果 dsh-grafana@<version> 已在 npm 上存在,则跳过 npm 步骤、只创建 GitHub Release;脚本也绝不会覆盖已存在的 GitHub Release。

npm 前置条件

首次 npm 发布前的一次性准备:

  1. 使用已验证邮箱、并为写操作开启双因素认证的 npmjs.com 账号。
  2. 执行 npm login,再用 npm whoami 确认身份。
  3. 无作用域名称 dsh-grafana 已由包所有者账号占用。如需改用 @guhanfei-ai/dsh-grafana 这类组织作用域名称,请先修改 package.json;deploy.sh 会从其中读取包名。

开启写操作 2FA 后,npm publish 会交互式提示输入一次性验证码;非交互场景可通过 NPM_OTP 环境变量传入。

如需供应链来源证明,建议改用独立 CI 工作流配置 npm Trusted Publishing 并加 --provenance;本地登录不具备可信来源证明所需的 CI OIDC 身份。

许可证

MIT

内容来自项目 README(GitHub)↗

评论

评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。