sycommon-python-lib 0.2.7a13__py3-none-any.whl → 0.2.7a14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -374,6 +374,8 @@ class AgentConfig(BaseModel):
374
374
  internal_model_name: Optional[str] = None
375
375
  # 敏感检测提示词(应用层可覆盖);未传(None)用基础库 DEFAULT_DETECT_PROMPT
376
376
  sensitive_detect_prompt: Optional[str] = None
377
+ # 命中敏感后的动作:"downgrade"=降级内部模型继续;"block"=直接阻断不执行
378
+ sensitive_action: str = "downgrade"
377
379
 
378
380
  # 系统提示词
379
381
  system_prompt: str = DEFAULT_SYSTEM_PROMPT
@@ -1237,11 +1239,13 @@ async def create_deep_agent(
1237
1239
  # internal_model_name 由应用层透传(避免基础库硬编码应用常量);
1238
1240
  # 未传(None)时 middleware 内部用 get_llm() 读 nacos default 模型兜底。
1239
1241
  # sensitive_detect_prompt 由应用层透传覆盖默认检测提示词。
1242
+ # sensitive_action 决定命中后降级还是阻断。
1240
1243
  guard = SensitiveGuardMiddleware(
1241
1244
  model_tier=config.model_tier,
1242
1245
  enabled=config.sensitive_guard,
1243
1246
  internal_model_name=config.internal_model_name,
1244
1247
  detect_prompt=config.sensitive_detect_prompt,
1248
+ action=config.sensitive_action,
1245
1249
  )
1246
1250
 
1247
1251
  middleware_list = [
@@ -1416,8 +1420,18 @@ async def _sync_skills_to_sandbox(
1416
1420
  _skip_lazy_sync=True)
1417
1421
  if remote_content and remote_content.file_data:
1418
1422
  # FileData 是 TypedDict(dict), 用键访问而非属性
1419
- return _parse_skill_version(
1420
- remote_content.file_data.get("content", "") or "")
1423
+ content = remote_content.file_data.get("content", "") or ""
1424
+ # 沙箱 /read 对大文件( skill-creator 34KB SKILL.md)返回
1425
+ # encoding=base64,直接解析会因找不到 "version:" 行而误判为"无版本"
1426
+ # → 每次新建 Agent 都全量重传。base64 时先解码再解析。
1427
+ encoding = remote_content.file_data.get("encoding", "utf-8")
1428
+ if encoding == "base64" and content:
1429
+ try:
1430
+ import base64 as _b64
1431
+ content = _b64.b64decode(content).decode("utf-8", errors="replace")
1432
+ except Exception:
1433
+ pass
1434
+ return _parse_skill_version(content)
1421
1435
  except Exception:
1422
1436
  pass
1423
1437
  return ""
@@ -18,7 +18,7 @@ from typing import Any, Awaitable, Callable, List, Optional
18
18
  from langchain.agents.middleware.types import (
19
19
  AgentMiddleware, ContextT, ModelRequest, ModelResponse, ResponseT,
20
20
  )
21
- from langchain_core.messages import BaseMessage, HumanMessage
21
+ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
22
22
  from pydantic import BaseModel
23
23
 
24
24
  from sycommon.logging.kafka_log import SYLogger
@@ -228,6 +228,10 @@ class SensitiveGuardMiddleware(AgentMiddleware):
228
228
  state: Optional[DowngradeState] = None,
229
229
  # 应用层可覆盖检测提示词;未传(None)用 DEFAULT_DETECT_PROMPT
230
230
  detect_prompt: Optional[str] = None,
231
+ # 命中敏感后的动作:"downgrade"=降级内部模型继续;"block"=直接阻断(不调任何模型)
232
+ action: str = "downgrade",
233
+ # 阻断模式下的异步提示回调(与 on_downgrade 区分文案);downgrade 模式不用
234
+ on_block: Optional[Callable[[], Awaitable[None]]] = None,
231
235
  # 测试注入:绕过懒加载的真实 get_llm
232
236
  _detector: Any = None,
233
237
  _internal_raw: Any = None,
@@ -236,6 +240,8 @@ class SensitiveGuardMiddleware(AgentMiddleware):
236
240
  # None 时检测器/降级目标都用 get_llm() 读 nacos default 模型,不写死模型名
237
241
  self._internal_name = internal_model_name
238
242
  self._on_downgrade = on_downgrade
243
+ self._on_block = on_block
244
+ self._action = action if action in ("downgrade", "block") else "downgrade"
239
245
  self._enabled = enabled
240
246
  self._state = state or DowngradeState()
241
247
  self._detect_prompt = detect_prompt or DEFAULT_DETECT_PROMPT
@@ -247,6 +253,15 @@ class SensitiveGuardMiddleware(AgentMiddleware):
247
253
  def is_downgraded(self) -> bool:
248
254
  return self._state.is_downgraded
249
255
 
256
+ @property
257
+ def is_blocked(self) -> bool:
258
+ """本会话是否已阻断(命中过敏感且 action=block)。"""
259
+ return self._state.is_downgraded and self._action == "block"
260
+
261
+ @property
262
+ def action(self) -> str:
263
+ return self._action
264
+
250
265
  @property
251
266
  def last_notice_source(self) -> str:
252
267
  """首次命中时的敏感来源(user_input/tool_result/history),供应用层选文案。"""
@@ -338,10 +353,14 @@ class SensitiveGuardMiddleware(AgentMiddleware):
338
353
  if not self._enabled or self._model_tier == "internal":
339
354
  return await handler(request)
340
355
 
341
- # (b) 本会话已降级 → 直接路由内部模型,不再检测;
342
- # 但本次输入若本身不含敏感(敏感来自历史记忆),刷新 last_source=history,
343
- # 供应用层在「后续命中」时选「记忆」提示文案(NOTICE_FROM_HISTORY)。
356
+ # (b) 本会话已命中敏感
344
357
  if self._state.is_downgraded:
358
+ # 阻断模式:直接返回空响应,不再调任何模型;应用层发完提示后会 break stream。
359
+ # 这里构造一个 content 空的 AIMessage,让 langgraph 把本轮当作模型已回完,
360
+ # 不进工具循环(无 tool_calls),干净结束。
361
+ if self._action == "block":
362
+ return ModelResponse(result=[AIMessage(content="")])
363
+ # 降级模式:路由内部模型继续;本次输入若非敏感(来自历史记忆)刷新 source=history
345
364
  await self._refresh_source_if_history(request.messages)
346
365
  return await handler(request.override(model=await self._get_internal_raw()))
347
366
 
@@ -350,8 +369,19 @@ class SensitiveGuardMiddleware(AgentMiddleware):
350
369
  if not check.is_sensitive:
351
370
  return await handler(request)
352
371
 
353
- # (d) 命中 → CAS 抢占降级;仅首个命中者发提示(带来源)
372
+ # (d) 命中 → CAS 抢占;按 action 分流
354
373
  is_first = await self._state.mark_downgraded(check.source)
374
+ if self._action == "block":
375
+ SYLogger.info(
376
+ f"[SensitiveGuard] 命中敏感信息,阻断执行: {check.reason} (source={check.source})")
377
+ if is_first and self._on_block:
378
+ try:
379
+ await self._on_block()
380
+ except Exception as e:
381
+ SYLogger.warning(f"[SensitiveGuard] 阻断提示回调失败: {e}")
382
+ # 不调 handler,返回空响应结束本轮
383
+ return ModelResponse(result=[AIMessage(content="")])
384
+ # downgrade 模式:发提示 + 路由内部模型继续执行
355
385
  SYLogger.info(
356
386
  f"[SensitiveGuard] 命中敏感信息,降级内部模型: {check.reason} (source={check.source})")
357
387
  if is_first and self._on_downgrade:
@@ -133,6 +133,7 @@ class TeamConfig(BaseModel):
133
133
  sensitive_guard: bool = True # 是否启用敏感信息检测守卫
134
134
  internal_model_name: Optional[str] = None # 敏感降级目标内部模型名(应用层透传)
135
135
  sensitive_detect_prompt: Optional[str] = None # 敏感检测提示词(应用层覆盖)
136
+ sensitive_action: str = "downgrade" # "downgrade"=降级继续;"block"=阻断
136
137
 
137
138
  coordinator_prompt: str = ""
138
139
  coordinator_name: str = "项目经理"
@@ -633,6 +634,7 @@ async def create_multi_agent_team(
633
634
  state=shared_downgrade_state,
634
635
  internal_model_name=config.internal_model_name,
635
636
  detect_prompt=config.sensitive_detect_prompt,
637
+ action=config.sensitive_action,
636
638
  )
637
639
 
638
640
  middleware = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.2.7a13
3
+ Version: 0.2.7a14
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -136,8 +136,8 @@ sycommon/services.py,sha256=CwC_gESafo05Qn41KLQgtulx6PfX7s2FkxlBI-hXve4,24861
136
136
  sycommon/agent/__init__.py,sha256=mxceAeUifQ-DKvWp7ZEJIFlmOCb5wpYHPGQw3rwEN8I,4378
137
137
  sycommon/agent/agent_manager.py,sha256=UhhaekEumT7g4v_Z1UB4jTp13X0n8M8erYaQdkGGWkA,13620
138
138
  sycommon/agent/chat_events.py,sha256=t7qWa6OrIWLfqtd1AnqaVP67QWkn1JxpCBTZYQpoLuM,14226
139
- sycommon/agent/deep_agent.py,sha256=N7XjcIlk-yvvWMy4e1hPKRvZtv2SdwdvYlAOJONbIV4,73315
140
- sycommon/agent/multi_agent_team.py,sha256=59TbJtS0Fvm4KlZaKdUiaYWg8Y1GomPfZXtA76bNbtM,30131
139
+ sycommon/agent/deep_agent.py,sha256=Y7xQIOmnIda-v_Cf8iEUn61rDD5lfaAPhiXsgUqocy0,74253
140
+ sycommon/agent/multi_agent_team.py,sha256=HFdTmMvJns07rrEsq70GCmILWKDzGxgSh6ZeyhX9Lc4,30260
141
141
  sycommon/agent/summarization_utils.py,sha256=bqZRFqSekNGlv2mYQPaT_s2QNA5VDTKddi2Va_SkHWc,18376
142
142
  sycommon/agent/acp/__init__.py,sha256=vQGMQYAA5-ZaejYmDZ4r4Fklqs17qH3cDXQ5pZlwj-0,1844
143
143
  sycommon/agent/acp/client.py,sha256=s-K626b9ierwyEq61gejrW0xOysvrY2PIpYFsFqSHjc,27108
@@ -147,7 +147,7 @@ sycommon/agent/acp/tool.py,sha256=yt6ohKL2y7wIZMNiLv-m5oCg5u1p5GAbqgjzQVt285Y,10
147
147
  sycommon/agent/mcp/__init__.py,sha256=iKrdDhIrFsNIkqG_kgcwNe-nOiM6uVfolKv44LfQ-FQ,636
148
148
  sycommon/agent/mcp/models.py,sha256=zda4ho-UTYOJ5oPAZPZ-vxhfDRLghUCsMroHnA2A2QQ,1490
149
149
  sycommon/agent/mcp/tool_loader.py,sha256=OQa-lE7RL2s3Lqh-kNOKaUrb130hvorB_HjyFBqZBZs,10960
150
- sycommon/agent/middleware/sensitive_guard.py,sha256=pn4ImMLkBFMSJ8gxSb_0c1Zg4y9w6pln8ovceA-qHE0,20169
150
+ sycommon/agent/middleware/sensitive_guard.py,sha256=jT-4fNZ5mAvZpoqgVwCuD41iS13zBUdSQvc3up2ziNU,21736
151
151
  sycommon/agent/middleware/sitecustomize.py,sha256=Bt7XFnWV_LJo89l858AGp5VUkXwefpLGmjkCtLe-CMw,4800
152
152
  sycommon/agent/middleware/skill_api_whitelist.py,sha256=e15aJekXegPp64owSCEdUE5y0SmwCQVQCF4jnhReZNU,10958
153
153
  sycommon/agent/middleware/skill_wl_check.py,sha256=rCJ9F6aWPh8tVQBIPmcq2lKDsfwiJQduwSUku_8kXfs,3952
@@ -307,8 +307,8 @@ sycommon/tools/syemail.py,sha256=BDFhgf7WDOQeTcjxJEQdu0dQhnHFPO_p3eI0-Ni3LhQ,561
307
307
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
308
308
  sycommon/xxljob/__init__.py,sha256=7eoBlQxv-B39IfRSCY2bkqdGYs1QRe1umAWd88VMEEM,86
309
309
  sycommon/xxljob/xxljob_service.py,sha256=1yifwIBNGsCIxLnQjHKiBlbsigc_zvPH-dMTZcNxe-Q,7649
310
- sycommon_python_lib-0.2.7a13.dist-info/METADATA,sha256=sthOFqgVTUnIdpJe-da7rVh49-mffEjIe-31TN3ZQoM,7962
311
- sycommon_python_lib-0.2.7a13.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
312
- sycommon_python_lib-0.2.7a13.dist-info/entry_points.txt,sha256=gsR4SssKxDWjRU8ggidzNcdMXDPRSKRS7UaGyNP84Qg,92
313
- sycommon_python_lib-0.2.7a13.dist-info/top_level.txt,sha256=RgphKrg7nJyZ7irJqbxFr-5H2LUYTvI7ivoWZH2hcD0,29
314
- sycommon_python_lib-0.2.7a13.dist-info/RECORD,,
310
+ sycommon_python_lib-0.2.7a14.dist-info/METADATA,sha256=JNchBy3XAiVCP_d1u0Nmz-ft-BiFiEIPKlKiV48ySqw,7962
311
+ sycommon_python_lib-0.2.7a14.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
312
+ sycommon_python_lib-0.2.7a14.dist-info/entry_points.txt,sha256=gsR4SssKxDWjRU8ggidzNcdMXDPRSKRS7UaGyNP84Qg,92
313
+ sycommon_python_lib-0.2.7a14.dist-info/top_level.txt,sha256=RgphKrg7nJyZ7irJqbxFr-5H2LUYTvI7ivoWZH2hcD0,29
314
+ sycommon_python_lib-0.2.7a14.dist-info/RECORD,,