feat(secret): 敏感信息库前端接入——AgentIO钥匙图标+选择窗数据源(2026-09-17)
- agent_config.py: GENERAL_TOOLS += 6 个 ToolDefinition(category=secret, required 显式声明防 native FC 把可选参数标必填逼 LLM 编值)。 - wwwroot/api/secret_options.dspy: AgentIO 选择窗数据源。身份取自 get_user()/ get_userorgid(),**不接受前端传 user_id/org_id**(否则改参数即可枚举他人凭据名称); 双保险剔除 encrypted_value/fingerprint;未登录返 success:false(区分没登录与没数据)。 RBAC 已被 rp.json 的 /pipeline_core/**(logined) 覆盖,无需额外注册。 - 3 个 .ui 的 AgentIO options 注入 secret_dataurl/secret_format/secret_title/ secret_tip(共4处,含 agent/index.ui 动态建 tab 的 script 字符串)。 未传 secret_dataurl 时钥匙图标不渲染 → 其他宿主应用零影响。 bricks 侧配套(UiText.insertAtCursor / AgentInput 弹窗 / AgentIO 透传)在 bricks 仓库。
This commit is contained in:
parent
17b5a50a04
commit
a243a16941
@ -449,6 +449,57 @@ GENERAL_TOOLS = [
|
||||
required=["table"],
|
||||
category="data",
|
||||
),
|
||||
# ── 用户敏感信息库(2026-09-17):凭据密文入库 + 占位符引用 + 入站自动侦测 ──
|
||||
# 实现在 pipeline_service.secret_vault(handler 签名 (sor, params, ctx))。
|
||||
# 安全不变量:agent 全程只见元数据与占位符,真值只在执行边界以子进程环境变量注入。
|
||||
ToolDefinition(
|
||||
name="list_secrets",
|
||||
description="列出当前用户/机构可用的敏感信息(apikey/token/密码/私钥)。只返回元数据(名称/类型/前缀/长度/使用次数),绝不返回明文值。需要用凭据执行命令前先调这个查有哪些",
|
||||
parameters={"all": "可选:传 1 时含已停用条目"},
|
||||
required=[],
|
||||
category="secret",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="save_secret",
|
||||
description="把一份敏感信息密文入库。用户说「把 X 存为 Y」「保存这个 apikey/token/密码」时调用;用户直接在消息里贴明文时平台入站门禁会自动侦测入库,无需你再调。入库后返回占位符 @@sec:NAME@@ 与环境变量名 $PIPELINE_SEC_NAME",
|
||||
parameters={
|
||||
"value": "明文值(仅本次调用使用,落库即 RC4 加密)",
|
||||
"name": "可选:变量名(大写字母开头,只含大写字母/数字/下划线;缺省按类型自动派生)",
|
||||
"label": "可选:显示名称",
|
||||
"secret_type": "可选:类型(缺省自动识别,如 github_token/api_key/db_password)",
|
||||
"remark": "可选:备注(用途说明)",
|
||||
},
|
||||
required=["value"],
|
||||
category="secret",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="use_secret",
|
||||
description="从敏感信息库选一个插入当前会话(返回占位符 @@sec:NAME@@ 与环境变量名,不返回明文)。用户说「用我的 github token」「插入那个 apikey」时调用",
|
||||
parameters={"name": "变量名(先用 list_secrets 查可用名称)"},
|
||||
required=["name"],
|
||||
category="secret",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_secret",
|
||||
description="删除一条敏感信息(仅本人/本机构条目)",
|
||||
parameters={"name": "变量名", "id": "可选:记录ID(与 name 二选一)"},
|
||||
required=[],
|
||||
category="secret",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="set_secret_status",
|
||||
description="启用/停用一条敏感信息。停用后不再注入执行环境但保留记录(凭据泄露疑似时先停用)",
|
||||
parameters={"name": "变量名", "status": "active(启用)或 disabled(停用)"},
|
||||
required=["name", "status"],
|
||||
category="secret",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="detect_secret",
|
||||
description="只侦测文本中的疑似敏感信息但不入库(返回前4字符+类型+置信度+熵)。用户问「这段有没有泄露风险」时调用",
|
||||
parameters={"text": "待检测文本"},
|
||||
required=["text"],
|
||||
category="secret",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
"event": "click",
|
||||
"actiontype": "script",
|
||||
"target": "self",
|
||||
"script": "var tp=bricks.getWidgetById('session_tabs',bricks.app);if(!tp)return;var sid='s'+Date.now()+'_'+Math.floor(Math.random()*100000);var n=tp.opts.items.length+1;tp.open_tab({name:'session_'+sid,label:'会话 '+n,removable:true,content:{widgettype:'VBox',options:{css:'filler',width:'100%',height:'100%'},subwidgets:[{widgettype:'urlwidget',options:{url:'/pipeline_core/api/agent_menus.dspy?session_id='+sid+'&pipeline_id=sdlc_general',method:'GET'}},{widgettype:'AgentIO',options:{css:'filler',margin:'0 24px 24px 24px',url:'/pipeline_core/api/agent_chat.dspy?session_id='+sid+'&pipeline_id=sdlc_general',model_dataurl:'/pipeline_core/api/agent_model_options.dspy?session_id='+sid+'&pipeline_id=sdlc_general',model_cwidth:14,placeholder:'输入你的需求...'}}]}});"
|
||||
"script": "var tp=bricks.getWidgetById('session_tabs',bricks.app);if(!tp)return;var sid='s'+Date.now()+'_'+Math.floor(Math.random()*100000);var n=tp.opts.items.length+1;tp.open_tab({name:'session_'+sid,label:'会话 '+n,removable:true,content:{widgettype:'VBox',options:{css:'filler',width:'100%',height:'100%'},subwidgets:[{widgettype:'urlwidget',options:{url:'/pipeline_core/api/agent_menus.dspy?session_id='+sid+'&pipeline_id=sdlc_general',method:'GET'}},{widgettype:'AgentIO',options:{css:'filler',margin:'0 24px 24px 24px',url:'/pipeline_core/api/agent_chat.dspy?session_id='+sid+'&pipeline_id=sdlc_general',model_dataurl:'/pipeline_core/api/agent_model_options.dspy?session_id='+sid+'&pipeline_id=sdlc_general',model_cwidth:14,placeholder:'输入你的需求...',secret_dataurl:'/pipeline_core/api/secret_options.dspy',secret_format:'@@sec:{name}@@',secret_title:'选择敏感信息',secret_tip:'插入敏感信息'}}]}});"
|
||||
}]
|
||||
}
|
||||
]
|
||||
@ -52,7 +52,11 @@
|
||||
"url": "/pipeline_core/api/agent_chat.dspy?session_id=default_sdlc_general&pipeline_id=sdlc_general",
|
||||
"model_dataurl": "/pipeline_core/api/agent_model_options.dspy?session_id=default_sdlc_general&pipeline_id=sdlc_general",
|
||||
"model_cwidth": 14,
|
||||
"placeholder": "输入你的需求..."
|
||||
"placeholder": "输入你的需求...",
|
||||
"secret_dataurl": "/pipeline_core/api/secret_options.dspy",
|
||||
"secret_format": "@@sec:{name}@@",
|
||||
"secret_title": "选择敏感信息",
|
||||
"secret_tip": "插入敏感信息"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -31,7 +31,11 @@
|
||||
"url": "/pipeline_core/api/agent_chat_generic.dspy",
|
||||
"model_dataurl": "/pipeline_core/api/agent_model_options.dspy",
|
||||
"model_cwidth": 14,
|
||||
"placeholder": "输入你的需求...(纯通用模式)"
|
||||
"placeholder": "输入你的需求...(纯通用模式)",
|
||||
"secret_dataurl": "/pipeline_core/api/secret_options.dspy",
|
||||
"secret_format": "@@sec:{name}@@",
|
||||
"secret_title": "选择敏感信息",
|
||||
"secret_tip": "插入敏感信息"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
39
wwwroot/api/secret_options.dspy
Normal file
39
wwwroot/api/secret_options.dspy
Normal file
@ -0,0 +1,39 @@
|
||||
# secret_options.dspy — AgentIO「插入敏感信息」选择窗的数据源(2026-09-17)
|
||||
#
|
||||
# 前端:AgentInput 的 opts.secret_dataurl 指向此处(bricks 通用框架不硬编码宿主路径,
|
||||
# 由 pipeline-core 的 agent/index.ui 注入)。
|
||||
# 返回:{"success":true, "secrets":[{name,label,secret_type,prefix_hint,length_hint,
|
||||
# use_count,remark,status}, ...]}
|
||||
#
|
||||
# 安全铁律(与 secret_vault.list_secrets 同源):
|
||||
# - **绝不返回 encrypted_value 或明文**。只给元数据:名称/类型/前缀4字符/长度/使用次数。
|
||||
# 前缀4字符够人类辨认是哪个凭据,拼不出可用值(GitHub PAT 前缀是公开固定值,零熵)。
|
||||
# - 身份取自登录态(get_user/get_userorgid),**不接受前端传 user_id/org_id**——
|
||||
# 否则任意用户改参数即可枚举他人凭据名称(元数据本身也是信息)。
|
||||
# - 未登录返回 success:false,不返回空列表(区分「没登录」与「没数据」,便于前端提示)。
|
||||
|
||||
import json
|
||||
|
||||
uid = await get_user()
|
||||
if not uid:
|
||||
return json.dumps({"success": False, "error": "未登录"}, ensure_ascii=False)
|
||||
|
||||
org_id = (await get_userorgid()) or ''
|
||||
show_all = str((params_kw or {}).get('all', '') or '').strip() in ('1', 'true', 'True')
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
from pipeline_service import secret_vault
|
||||
|
||||
async with DBPools().sqlorContext('pipeline') as sor:
|
||||
rows = await secret_vault.list_secrets(sor, org_id=org_id, user_id=uid,
|
||||
only_active=not show_all)
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
|
||||
# 双保险:即使上游误带出密文字段,这里再剔一次(返回体是安全边界)
|
||||
_safe = []
|
||||
for r in rows:
|
||||
item = {k: v for k, v in r.items()
|
||||
if k not in ('encrypted_value', 'fingerprint')}
|
||||
_safe.append(item)
|
||||
|
||||
return json.dumps({"success": True, "secrets": _safe}, ensure_ascii=False, default=str)
|
||||
@ -17,7 +17,11 @@
|
||||
"url": "/pipeline_core/api/agent_chat.dspy?pipeline_id={{pl_id}}&session_id=m_{{pl_id}}",
|
||||
"model_dataurl": "/pipeline_core/api/agent_model_options.dspy?capabilities=chat&pipeline_id={{pl_id}}&session_id=m_{{pl_id}}",
|
||||
"model_cwidth": 14,
|
||||
"placeholder": "输入你的需求..."
|
||||
"placeholder": "输入你的需求...",
|
||||
"secret_dataurl": "/pipeline_core/api/secret_options.dspy",
|
||||
"secret_format": "@@sec:{name}@@",
|
||||
"secret_title": "选择敏感信息",
|
||||
"secret_tip": "插入敏感信息"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -77,7 +81,11 @@
|
||||
"url": "/pipeline_core/api/agent_chat.dspy",
|
||||
"model_dataurl": "/pipeline_core/api/agent_model_options.dspy?capabilities=chat",
|
||||
"model_cwidth": 14,
|
||||
"placeholder": "输入你的需求..."
|
||||
"placeholder": "输入你的需求...",
|
||||
"secret_dataurl": "/pipeline_core/api/secret_options.dspy",
|
||||
"secret_format": "@@sec:{name}@@",
|
||||
"secret_title": "选择敏感信息",
|
||||
"secret_tip": "插入敏感信息"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user