@kenhkl/agent-moss 0.14.0 → 0.15.1

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.
@@ -686,7 +686,8 @@ function countRulesL2() {
686
686
  function countEnabledL2() {
687
687
  const text = countEnabled(state.config.L2_rules, 'L2_logic_rules');
688
688
  const layerOn = state.config.layers?.L2_logic_rules !== false;
689
- const ltlOn = layerOn ? (state.config.L2_2?.ltl_rules || []).filter(r => r.enabled !== false).length : 0;
689
+ const catOn = state.config.L2_2?.category_enabled !== false;
690
+ const ltlOn = (layerOn && catOn) ? (state.config.L2_2?.ltl_rules || []).filter(r => r.enabled !== false).length : 0;
690
691
  return text + ltlOn;
691
692
  }
692
693
 
@@ -712,6 +713,14 @@ async function toggleCategory(layer, category) {
712
713
  showToast(t('分类已', 'Category ') + (!cur ? t('启用', 'enabled') : t('禁用', 'disabled')));
713
714
  } catch (e) { showToast(t('操作失败: ', 'Operation failed: ') + e.message, 'error'); }
714
715
  }
716
+ // LTL 大类开关(L2.2 的 category_enabled 存于 view 的顶层,而非 category dict 内)
717
+ async function toggleLtlCategory(en) {
718
+ try {
719
+ state.config = await apiPut('categories/enabled', { layer: 'L2_2', category: 'ltl_rules', enabled: en });
720
+ renderCurrent();
721
+ showToast(t('LTL 大类已', 'LTL category ') + (en ? t('启用', 'enabled') : t('禁用', 'disabled')));
722
+ } catch (e) { showToast(t('操作失败: ', 'Operation failed: ') + e.message, 'error'); }
723
+ }
715
724
  async function toggleSkillCategory(category) {
716
725
  try {
717
726
  const cur = state.config.L3_skills?.[category]?.category_enabled !== false;
@@ -834,13 +843,17 @@ function renderLtlCard(containerId) {
834
843
  const l22 = state.config.L2_2 || {};
835
844
  const ltl = l22.ltl_rules || [];
836
845
  const isL2On = state.config.layers?.L2_logic_rules !== false;
846
+ const catOn = l22.category_enabled !== false;
837
847
  // 与其他分类一致:默认折叠,用户展开过则保持(expandedCats)
838
848
  const expanded = expandedCats.has(`${containerId}-ltl_rules`);
849
+ // 大类总开关显示状态 = 层级开 && 大类开;大类关时内部单条规则开关禁用(无意义)
850
+ const catSwitchOn = isL2On && catOn;
851
+ const enabledCount = catSwitchOn ? ltl.filter(r => r.enabled !== false).length : 0;
839
852
  let html = `<div class="ag-card">
840
853
  <div class="ag-cat-header" onclick="toggleExpand('${containerId}-ltl_rules')">
841
- <div class="ag-cat-name">${t('⏱️ 时序攻击模式 (LTL)', '⏱️ Timing Attack Patterns (LTL)')} <span class="ag-cat-count">${isL2On ? ltl.filter(r => r.enabled !== false).length : 0}/${ltl.length} ${t('启用', 'enabled')}</span></div>
854
+ <div class="ag-cat-name">${t('⏱️ 时序攻击模式 (LTL)', '⏱️ Timing Attack Patterns (LTL)')} <span class="ag-cat-count">${enabledCount}/${ltl.length} ${t('启用', 'enabled')}</span></div>
842
855
  <div class="ag-cat-controls">
843
- <div onclick="event.stopPropagation()">${toggle(isL2On && ltl.some(r => r.enabled !== false), !isL2On, '')}</div>
856
+ <div onclick="event.stopPropagation()">${toggle(catSwitchOn, !isL2On, `toggleLtlCategory(${!catOn})`)}</div>
844
857
  <span class="ag-expand-icon ${expanded ? 'open' : ''}" id="expand-${containerId}-ltl_rules">▼</span>
845
858
  </div>
846
859
  </div>
@@ -851,12 +864,13 @@ function renderLtlCard(containerId) {
851
864
  } else {
852
865
  for (const r of ltl) {
853
866
  const action = r.action === 'block' ? t('拦截', 'Block') : (r.action === 'approval' ? t('审批', 'Approval') : t(r.action || '', r.action || ''));
867
+ const itemOn = catSwitchOn && r.enabled !== false;
854
868
  html += `<div class="ag-rule-item"><div class="ag-rule-body">
855
869
  <div class="ag-rule-tags">${riskBadge(r.risk_level)}</div>
856
870
  <div class="ag-rule-pattern"><span class="ag-rule-field-label">${t('检测', 'Detects')}:</span> ${escapeHtml(r.human || r.reason || r.id)}</div>
857
871
  <div class="ag-rule-reason"><span class="ag-rule-field-label">${t('规则说明', 'Description')}:</span> ${escapeHtml(r.reason || '')} <span class="ag-rule-id">[${escapeHtml(r.id)}]</span></div>
858
872
  <div class="ag-rule-id">${t('动作', 'Action')}: ${action}</div>
859
- </div><div class="ag-rule-controls">${toggle(r.enabled !== false, false, `toggleRule('L2_2','ltl_rules','${r.id}',${!(r.enabled !== false)})`)}</div></div>`;
873
+ </div><div class="ag-rule-controls">${toggle(itemOn, !catSwitchOn, `toggleRule('L2_2','ltl_rules','${r.id}',${!(r.enabled !== false)})`)}</div></div>`;
860
874
  }
861
875
  }
862
876
  html += '</div></div>';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenhkl/agent-moss",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "Multi-layer security analysis engine for AI agents (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",