cycode 3.22.2.dev2__py3-none-any.whl → 3.23.0__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.
cycode/__init__.py CHANGED
@@ -5,4 +5,4 @@ import time as _time
5
5
  # end-to-end scan duration from the moment the user actually triggered it.
6
6
  _BOOT_WALL: float = _time.time()
7
7
 
8
- __version__ = '3.22.2.dev2' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
8
+ __version__ = '3.23.0' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -54,6 +54,22 @@ def collect_all_session_contexts() -> tuple[dict[str, dict], dict]:
54
54
  return config_files_by_ide, plugins
55
55
 
56
56
 
57
+ def collect_all_skills() -> list[dict]:
58
+ """Sweep every registered IDE's user-scope skills, regardless of which IDE triggered the hook.
59
+
60
+ Returns ``[{"path", "content"}]`` deduplicated by path and sorted, so two IDEs sharing a skills
61
+ directory report it once and the session-context digest stays stable across registry order.
62
+ Skills a plugin ships are not here - those ride on their plugin entry, which carries the
63
+ marketplace provenance.
64
+ """
65
+ skills_by_path: dict[str, dict] = {}
66
+ for ide in IDES.values():
67
+ for skill in ide.get_skills():
68
+ skills_by_path.setdefault(skill['path'], skill)
69
+
70
+ return [skills_by_path[path] for path in sorted(skills_by_path)]
71
+
72
+
57
73
  def resolve_ides(name: str) -> list[IDE]:
58
74
  """Resolve an ``--ide`` argument to one or all IDE instances.
59
75
 
@@ -0,0 +1,103 @@
1
+ """Shared skill-collection helpers for IDE integrations.
2
+
3
+ A skill is a directory holding a ``SKILL.md``: ``<skills root>/<skill name>/SKILL.md``.
4
+ The same layout is used for user-scope skills (``~/.claude/skills/``) and for the skills a
5
+ plugin ships (``<plugin dir>/skills/``), so one walker serves both.
6
+
7
+ Unlike an MCP config - a small JSON file at a known path - a ``SKILL.md`` body is unbounded
8
+ prose, and the number of installed skills is unbounded too. Both are capped here rather than
9
+ downstream: the whole session-context report is one request, so an oversized skill would cost
10
+ the device its MCP inventory as well.
11
+ """
12
+
13
+ from pathlib import Path
14
+ from typing import Optional
15
+
16
+ from cycode.logger import get_logger
17
+
18
+ logger = get_logger('AI Guardrails Skills')
19
+
20
+ SKILL_FILE_NAME = 'SKILL.md'
21
+
22
+ # Where a plugin keeps its skills, relative to the plugin directory. A property of the plugin format
23
+ # rather than of any one IDE, so Claude Code, Codex and Copilot plugins all use it.
24
+ PLUGIN_SKILLS_SUBDIR = 'skills'
25
+
26
+ # A skill is instructions, not data. Anything larger is not a skill we can usefully inventory,
27
+ # and sending it would push the one-request report toward the API's body limit.
28
+ MAX_SKILL_FILE_BYTES = 256 * 1024
29
+
30
+ # Per skills root, not per device: a developer with more installed skills than this in one place
31
+ # is an outlier we would rather truncate than let define the payload size.
32
+ MAX_SKILLS_PER_ROOT = 200
33
+
34
+
35
+ def _read_skill_file(skill_file: Path) -> Optional[dict]:
36
+ """Read one ``SKILL.md`` into the session-context file shape, or None if unusable."""
37
+ try:
38
+ size = skill_file.stat().st_size
39
+ except OSError as e:
40
+ logger.debug('Failed to stat skill file, %s', {'path': str(skill_file)}, exc_info=e)
41
+ return None
42
+
43
+ if size > MAX_SKILL_FILE_BYTES:
44
+ logger.debug(
45
+ 'Skill file exceeds the size cap; skipping, %s',
46
+ {'path': str(skill_file), 'size': size, 'cap': MAX_SKILL_FILE_BYTES},
47
+ )
48
+ return None
49
+
50
+ try:
51
+ content = skill_file.read_text(encoding='utf-8')
52
+ except Exception as e:
53
+ logger.debug('Failed to read skill file, %s', {'path': str(skill_file)}, exc_info=e)
54
+ return None
55
+
56
+ if not content.strip():
57
+ return None
58
+
59
+ return {'path': str(skill_file), 'content': content}
60
+
61
+
62
+ def walk_skill_dirs(skills_root: Path) -> list[dict]:
63
+ """Collect every ``<skills_root>/<name>/SKILL.md`` as ``{"path", "content"}``.
64
+
65
+ Exactly one directory level is scanned. A skill directory may hold nested references and
66
+ scripts, but its ``SKILL.md`` always sits at the top of it, so there is nothing to recurse
67
+ into - which is also what keeps this bounded without a depth cap.
68
+
69
+ Results are sorted by path: the session-context report is deduplicated by hashing the whole
70
+ payload, so an unstable order would re-send an unchanged inventory.
71
+ """
72
+ if not skills_root.is_dir():
73
+ return []
74
+
75
+ try:
76
+ skill_dirs = sorted(d for d in skills_root.iterdir() if d.is_dir())
77
+ except OSError as e:
78
+ logger.debug('Failed to list skills root, %s', {'path': str(skills_root)}, exc_info=e)
79
+ return []
80
+
81
+ skills: list[dict] = []
82
+ for skill_dir in skill_dirs:
83
+ if len(skills) >= MAX_SKILLS_PER_ROOT:
84
+ logger.debug(
85
+ 'Skills root exceeds the count cap; truncating, %s',
86
+ {'path': str(skills_root), 'cap': MAX_SKILLS_PER_ROOT},
87
+ )
88
+ break
89
+
90
+ skill = _read_skill_file(skill_dir / SKILL_FILE_NAME)
91
+ if skill:
92
+ skills.append(skill)
93
+
94
+ return skills
95
+
96
+
97
+ def walk_plugin_skills(plugin_dir: Path) -> list[dict]:
98
+ """Collect the skills a plugin ships, from ``<plugin_dir>/skills/<name>/SKILL.md``.
99
+
100
+ Shared by every IDE with a plugin system: the layout belongs to the plugin format, so a plugin
101
+ shipping skills is inventoried whichever IDE loaded it.
102
+ """
103
+ return walk_skill_dirs(plugin_dir / PLUGIN_SKILLS_SUBDIR)
@@ -189,3 +189,17 @@ class IDE(ABC):
189
189
  Override to surface MCP/plugin inventory.
190
190
  """
191
191
  return None, {}
192
+
193
+ def get_skills(self) -> list[dict]:
194
+ """Return the IDE's user-scope skills as ``[{"path", "content"}]``.
195
+
196
+ A skill is a ``SKILL.md`` under a per-skill directory. Raw content is returned rather
197
+ than parsed frontmatter: the backend owns parsing, because the device connectors that
198
+ read these files off endpoints can only ever return raw content.
199
+
200
+ Kept separate from ``get_session_context`` rather than folded into its
201
+ ``global_config_file`` slot, which is normalized to an MCP server map.
202
+
203
+ Default: ``[]`` (the IDE has no skill system). Override to surface skills.
204
+ """
205
+ return []
@@ -13,6 +13,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
13
13
  resolve_cached_plugin_dir,
14
14
  walk_enabled_plugins,
15
15
  )
16
+ from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
16
17
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
17
18
  from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
18
19
  from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
@@ -169,6 +170,15 @@ def load_claude_settings(settings_path: Optional[Path] = None) -> Optional[dict]
169
170
  return None
170
171
 
171
172
 
173
+ def _claude_skills_dir() -> Path:
174
+ """Claude Code's user-scope skills: ``~/.claude/skills/<name>/SKILL.md``.
175
+
176
+ A function, not a module constant: resolving ``Path.home()`` at import time pins the directory to
177
+ whatever home the process started with, which a test filesystem then cannot redirect.
178
+ """
179
+ return Path.home() / '.claude' / 'skills'
180
+
181
+
172
182
  def _plugins_cache_dir() -> Path:
173
183
  """Claude Code's local plugin content cache: ``~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/``."""
174
184
  return Path.home() / '.claude' / 'plugins' / 'cache'
@@ -187,10 +197,11 @@ def _resolve_marketplace_path(marketplace: dict) -> Optional[Path]:
187
197
 
188
198
 
189
199
  def _read_claude_plugin(plugin_dir: Path) -> tuple[dict, dict]:
190
- """Read one Claude Code plugin's manifest + MCP servers.
200
+ """Read one Claude Code plugin's manifest, MCP servers and skills.
191
201
 
192
202
  Claude hardcodes the MCP file at ``<plugin_dir>/.mcp.json`` and always
193
- wraps it as ``{"mcpServers": {...}}``.
203
+ wraps it as ``{"mcpServers": {...}}``, and a plugin's skills at
204
+ ``<plugin_dir>/skills/<name>/SKILL.md``.
194
205
  """
195
206
  manifest = load_plugin_json(plugin_dir / '.claude-plugin' / 'plugin.json') or {}
196
207
  entry: dict = {}
@@ -198,6 +209,12 @@ def _read_claude_plugin(plugin_dir: Path) -> tuple[dict, dict]:
198
209
  if field in manifest:
199
210
  entry[field] = manifest[field]
200
211
 
212
+ # Attached to the plugin entry rather than the top-level skills list so the backend keeps the
213
+ # plugin provenance (marketplace, plugin, version) that a marketplace-installed skill has.
214
+ skill_files = walk_plugin_skills(plugin_dir)
215
+ if skill_files:
216
+ entry['skill_files'] = skill_files
217
+
201
218
  mcp_config_path = plugin_dir / '.mcp.json'
202
219
  mcp_config = load_plugin_json(mcp_config_path) or {}
203
220
  servers: dict = mcp_config.get('mcpServers') or {}
@@ -387,3 +404,6 @@ class ClaudeCode(IDE):
387
404
  enriched_plugins = resolve_plugins(settings) if settings else {}
388
405
 
389
406
  return global_config_file, enriched_plugins
407
+
408
+ def get_skills(self) -> list[dict]:
409
+ return walk_skill_dirs(_claude_skills_dir())
@@ -20,6 +20,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
20
20
  resolve_cached_plugin_dir,
21
21
  walk_enabled_plugins,
22
22
  )
23
+ from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
23
24
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
24
25
  from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
25
26
  from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
@@ -53,6 +54,11 @@ def _codex_home() -> Path:
53
54
  return Path.home() / _CONFIG_DIR_NAME
54
55
 
55
56
 
57
+ def _codex_skills_dir() -> Path:
58
+ """User-scope Codex skills directory (honors ``$CODEX_HOME``)."""
59
+ return _codex_home() / 'skills'
60
+
61
+
56
62
  def _codex_config_toml_path(scope: str, repo_path: Optional[Path] = None) -> Path:
57
63
  """Return the Codex ``config.toml`` path for the given scope."""
58
64
  if scope == 'repo' and repo_path:
@@ -121,6 +127,12 @@ def _read_codex_plugin(plugin_dir: Path) -> tuple[dict, dict]:
121
127
  if field in manifest:
122
128
  entry[field] = manifest[field]
123
129
 
130
+ # Same plugin-format layout as every other IDE's plugins, so a plugin shipping skills is
131
+ # inventoried whichever IDE loaded it.
132
+ skill_files = walk_plugin_skills(plugin_dir)
133
+ if skill_files:
134
+ entry['skill_files'] = skill_files
135
+
124
136
  mcp_ref = manifest.get('mcpServers')
125
137
  if not mcp_ref:
126
138
  return entry, {}
@@ -304,3 +316,6 @@ class Codex(IDE):
304
316
  global_config_file = build_global_config_file(config_path, config.get('mcp_servers'))
305
317
  enriched_plugins = _resolve_codex_plugins(config)
306
318
  return global_config_file, enriched_plugins
319
+
320
+ def get_skills(self) -> list[dict]:
321
+ return walk_skill_dirs(_codex_skills_dir())
@@ -37,6 +37,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
37
37
  load_plugin_json,
38
38
  walk_enabled_plugins,
39
39
  )
40
+ from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
40
41
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
41
42
  from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
42
43
  from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
@@ -105,6 +106,11 @@ def _copilot_home() -> Path:
105
106
  return Path.home() / '.copilot'
106
107
 
107
108
 
109
+ def _copilot_skills_dir() -> Path:
110
+ """User-scope Copilot skills directory (honors ``$COPILOT_HOME``)."""
111
+ return _copilot_home() / 'skills'
112
+
113
+
108
114
  def _vscode_agent_plugins_dir() -> Path:
109
115
  # Resolved at call time (not a module-level Path constant): on py<=3.10 a Path
110
116
  # instance binds its filesystem accessor at creation, which breaks fake-fs tests
@@ -178,6 +184,12 @@ def _read_copilot_plugin(plugin_dir: Path) -> tuple[dict, dict]:
178
184
  if field in manifest:
179
185
  entry[field] = manifest[field]
180
186
 
187
+ # Same plugin-format layout as every other IDE's plugins, so a plugin shipping skills is
188
+ # inventoried whichever IDE loaded it.
189
+ skill_files = walk_plugin_skills(plugin_dir)
190
+ if skill_files:
191
+ entry['skill_files'] = skill_files
192
+
181
193
  mcp_ref = manifest.get('mcpServers')
182
194
  mcp_config_path = plugin_dir / mcp_ref if isinstance(mcp_ref, str) else plugin_dir / '.mcp.json'
183
195
  mcp_doc = load_plugin_json(mcp_config_path) or {}
@@ -481,3 +493,6 @@ class Copilot(IDE):
481
493
  build_global_config_file(_vscode_mcp_config_path(), config.get('servers')) if config else None
482
494
  )
483
495
  return global_config_file, _collect_installed_plugins()
496
+
497
+ def get_skills(self) -> list[dict]:
498
+ return walk_skill_dirs(_copilot_skills_dir())
@@ -7,6 +7,7 @@ from typing import ClassVar, Optional
7
7
 
8
8
  from cycode.cli.apps.ai_guardrails.consts import CYCODE_SCAN_PROMPT_COMMAND, CYCODE_SESSION_START_COMMAND
9
9
  from cycode.cli.apps.ai_guardrails.ides._plugin_utils import build_global_config_file
10
+ from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_skill_dirs
10
11
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
11
12
  from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
12
13
  from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
@@ -45,6 +46,11 @@ def _cursor_mcp_config_path() -> Path:
45
46
  return Path.home() / '.cursor' / _MCP_CONFIG_FILENAME
46
47
 
47
48
 
49
+ def _cursor_skills_dir() -> Path:
50
+ """User-scope Cursor skills directory (``~/.cursor/skills``, all platforms)."""
51
+ return Path.home() / '.cursor' / 'skills'
52
+
53
+
48
54
  def _load_cursor_mcp_config(config_path: Optional[Path] = None) -> Optional[dict]:
49
55
  """Load and parse `~/.cursor/mcp.json`. Returns None if missing/invalid."""
50
56
  path = config_path or _cursor_mcp_config_path()
@@ -125,3 +131,6 @@ class Cursor(IDE):
125
131
  config_path = _cursor_mcp_config_path()
126
132
  global_config_file = build_global_config_file(config_path, config.get('mcpServers'))
127
133
  return global_config_file, {}
134
+
135
+ def get_skills(self) -> list[dict]:
136
+ return walk_skill_dirs(_cursor_skills_dir())
@@ -9,7 +9,12 @@ from typing import TYPE_CHECKING, Annotated, Optional
9
9
 
10
10
  import typer
11
11
 
12
- from cycode.cli.apps.ai_guardrails.ides import DEFAULT_IDE_NAME, collect_all_session_contexts, get_ide
12
+ from cycode.cli.apps.ai_guardrails.ides import (
13
+ DEFAULT_IDE_NAME,
14
+ collect_all_session_contexts,
15
+ collect_all_skills,
16
+ get_ide,
17
+ )
13
18
  from cycode.cli.apps.ai_guardrails.scan.utils import read_stdin_text, safe_json_parse
14
19
  from cycode.cli.apps.auth.auth_common import get_authorization_info
15
20
  from cycode.cli.apps.auth.auth_manager import AuthManager
@@ -75,8 +80,9 @@ def _report_session_context(
75
80
  ) -> None:
76
81
  """Report the device + cross-IDE session context to the AI security manager. Never raises.
77
82
 
78
- The device context is always reported. MCP configs are collected from every registered IDE,
79
- not just the triggering one. Unchanged payloads are skipped via a hash cache until the TTL expires.
83
+ The device context is always reported. MCP configs and skills are collected from every
84
+ registered IDE, not just the triggering one. Unchanged payloads are skipped via a hash cache
85
+ until the TTL expires.
80
86
  """
81
87
  try:
82
88
  config_files_by_ide, enabled_plugins = collect_all_session_contexts()
@@ -89,6 +95,9 @@ def _report_session_context(
89
95
  # Sorted by path so the digest is stable regardless of IDE registry order.
90
96
  'config_files': sorted(config_files_by_ide.values(), key=lambda f: f['path']),
91
97
  'enabled_plugins': enabled_plugins,
98
+ # Already deduplicated and sorted by path, for the same digest-stability reason.
99
+ # Editing a skill body changes the digest and so re-reports the device's inventory.
100
+ 'skill_files': collect_all_skills(),
92
101
  'user_email': user_email,
93
102
  }
94
103
 
@@ -101,6 +101,7 @@ class AISecurityManagerClient:
101
101
  last_login_user: Optional[str] = None,
102
102
  config_files: Optional[list[dict]] = None,
103
103
  enabled_plugins: Optional[dict] = None,
104
+ skill_files: Optional[list[dict]] = None,
104
105
  user_email: Optional[str] = None,
105
106
  ) -> bool:
106
107
  """Report session context to the backend. Returns whether the report was accepted."""
@@ -113,6 +114,7 @@ class AISecurityManagerClient:
113
114
  'user_email': user_email,
114
115
  'config_files': config_files,
115
116
  'enabled_plugins': enabled_plugins,
117
+ 'skill_files': skill_files,
116
118
  }
117
119
 
118
120
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycode
3
- Version: 3.22.2.dev2
3
+ Version: 3.23.0
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  License-Expression: MIT
6
6
  License-File: LICENCE
@@ -1,4 +1,4 @@
1
- cycode/__init__.py,sha256=LNL09OLJXSC9YMkpi3Nw41M-MqVo1xGDFIqA6PzRyrc,396
1
+ cycode/__init__.py,sha256=feTFapUTrWfpbaK9lj2xg10SCAEYfQu3xdCQdNyPlpw,391
2
2
  cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
3
3
  cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cycode/cli/app.py,sha256=AlR2durAEbsa47PDfIj7JtMvJDWA_Dq6wPtVuMJYSCs,10250
@@ -8,13 +8,14 @@ cycode/cli/apps/ai_guardrails/__init__.py,sha256=NsqB1Ca83BIjJMcDSt6suec6Ed0iNna
8
8
  cycode/cli/apps/ai_guardrails/command_utils.py,sha256=NVwd0-2RGRKIqhsQ-4LNDR1D0gVm_o7n-z5LxG2bqAo,800
9
9
  cycode/cli/apps/ai_guardrails/consts.py,sha256=U9lToL22ik3oX6bcZxT5de79Fu0eZA5D5p-q9daE5Iw,778
10
10
  cycode/cli/apps/ai_guardrails/hooks_manager.py,sha256=zLUtZJ3yFu9n0r71lhhx9gUUXclTwgCyU38ULbVB--0,9329
11
- cycode/cli/apps/ai_guardrails/ides/__init__.py,sha256=9FPz984poZWPX6S6abuo-PThiXgJ_WpoUv47wiSXnKQ,2639
11
+ cycode/cli/apps/ai_guardrails/ides/__init__.py,sha256=5odqWNfvvbFfAtR8ioEytXZ5VczWAOGyr1xuASC_OnQ,3346
12
12
  cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py,sha256=XPIc9pZFEgdGVTSSAl9yqI48F88GKlFnJ5FsLUhHjCE,3981
13
- cycode/cli/apps/ai_guardrails/ides/base.py,sha256=gyCxeDxuXaRBpYFzbgKHJAyJ6a1cDcXCGA3FKh67soM,7333
14
- cycode/cli/apps/ai_guardrails/ides/claude_code.py,sha256=r15sdxksQw5lyvn90HV7sFoxh9p_XAxIO9XY9I_TJKs,14770
15
- cycode/cli/apps/ai_guardrails/ides/codex.py,sha256=eHdd2_F5JB74RJV2b35oIxRT2Bc6o46ypzfRz26_HZg,11756
16
- cycode/cli/apps/ai_guardrails/ides/copilot.py,sha256=oMJs54TES_7Q1cnFjxEO4a_qp8-AZ6Janspi5Wjs5K0,21305
17
- cycode/cli/apps/ai_guardrails/ides/cursor.py,sha256=nZjarVu_zju05_R-1smWtq7U40axk6XnCmzWA-aCZqI,5514
13
+ cycode/cli/apps/ai_guardrails/ides/_skill_utils.py,sha256=Xk8z-uquTMvg4JxNwZxnclR79ME7ZKq7rxht3aFQUeo,3972
14
+ cycode/cli/apps/ai_guardrails/ides/base.py,sha256=B_wrSO48Hl__Xk92X4rKmwnY0RkP8jAJtE84wIW-Qnk,7985
15
+ cycode/cli/apps/ai_guardrails/ides/claude_code.py,sha256=JCSB2PRPtZETFSskxV02hUwNRKExx7mXxtEmdxt_ruE,15707
16
+ cycode/cli/apps/ai_guardrails/ides/codex.py,sha256=P3dCa2bHLoeKs10TN6OmwP6BjcuJkNMkfUFa4T7n9Vo,12335
17
+ cycode/cli/apps/ai_guardrails/ides/copilot.py,sha256=XK2CLdB3oLJrP5Z-pGNsLbnwfehv4AW4vTLdvSE3eb0,21894
18
+ cycode/cli/apps/ai_guardrails/ides/cursor.py,sha256=cqi12ELV5ZF7ANUA9n33gc8Hj9hURqEBLJ3gzf-v68w,5850
18
19
  cycode/cli/apps/ai_guardrails/install_command.py,sha256=3IV_MHpc7R-OJ2kUTDAtemkGZUQ9YAWX3lJBgTsi0zo,4190
19
20
  cycode/cli/apps/ai_guardrails/scan/__init__.py,sha256=qJc82XiQGiAuc1sYY8Ij_A-qXpxgLPuayQq8xWlouMA,48
20
21
  cycode/cli/apps/ai_guardrails/scan/consts.py,sha256=drAslw6vW3kxmbCs2qPCUbUPR7PJouT2lsXtu5sD-lQ,1094
@@ -25,7 +26,7 @@ cycode/cli/apps/ai_guardrails/scan/policy.py,sha256=BZoNNdDQ9tqnfwhB4X1-bDtudaOQ
25
26
  cycode/cli/apps/ai_guardrails/scan/scan_command.py,sha256=YpfGVmP05qjeoCr_6UVW3rO_MAJ6CJZDfrR1v2OJZ8Y,7465
26
27
  cycode/cli/apps/ai_guardrails/scan/types.py,sha256=ybQm242QN0l_4SSNX4xMHXxzqEK-MW-hfIOixI7zvGU,1497
27
28
  cycode/cli/apps/ai_guardrails/scan/utils.py,sha256=QzR_zmivDYwg2-F8g4bFfsycHhNo-pPuJly0P_l0gm8,2879
28
- cycode/cli/apps/ai_guardrails/session_start_command.py,sha256=05Li-ON2U1BU_8CR2YYw1y5HVvoWPTf19ne--EgPqmQ,5921
29
+ cycode/cli/apps/ai_guardrails/session_start_command.py,sha256=OxpqSROhN3NTKE3TiDTsKrYu8dXRrUDdwUEUzlRxnlQ,6215
29
30
  cycode/cli/apps/ai_guardrails/status_command.py,sha256=Uqss68TEPCYPXpLix6Bh-4J3g-khxWsAqlIGYH5x4bQ,3203
30
31
  cycode/cli/apps/ai_guardrails/uninstall_command.py,sha256=dOmePfZmlHAPy2zEJM1yMtSuDqvzDwtqgmLKYK-T9PI,2698
31
32
  cycode/cli/apps/ai_remediation/__init__.py,sha256=8vYthY9RQeJqEni3AIF5sryz8n-XJQ6VNqG4aEFBAdY,553
@@ -194,7 +195,7 @@ cycode/cli/utils/version_checker.py,sha256=0f5PaTk02ZkDxzBqZOeMV9mU_CWcx6HKW80jU
194
195
  cycode/cli/utils/yaml_utils.py,sha256=ty4FlwrM49OoYSMv8U6ZGlB0JRds8nxaijHQZebBVoU,2991
195
196
  cycode/config.py,sha256=jHORGZQcAXkAGSf2XreC-RQoc8sdNWja69QKtPWTbWo,1044
196
197
  cycode/cyclient/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
197
- cycode/cyclient/ai_security_manager_client.py,sha256=C74tmzCF220eEcv-WdK8aVv-zjsL-R4cXg4q54YkV74,4849
198
+ cycode/cyclient/ai_security_manager_client.py,sha256=Ljv93RQvh0cy-dh84zGw7UnVdN2KPulmmSvrvFfXdNw,4939
198
199
  cycode/cyclient/ai_security_manager_service_config.py,sha256=83pQzgOb93JW6E-dznJkI4c0NEXmQRlx9YZKMmjVwp8,808
199
200
  cycode/cyclient/auth_client.py,sha256=TwbmZ358Ancf-Q-IZolvfljZ8691_6botsqd0R0PLPk,2105
200
201
  cycode/cyclient/base_token_auth_client.py,sha256=mn5580d7A8Z2_zcdFKIJk78ADK7mViwTcV-4QCpRCGo,4369
@@ -215,8 +216,8 @@ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ
215
216
  cycode/cyclient/scan_client.py,sha256=DqAZ7u6Z_cvw9A9RlLkAQUgLRwPCCAsUq5U9umt4F7Y,16955
216
217
  cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
217
218
  cycode/logger.py,sha256=EfZGRK6VC5rE_LAjIcRrHFiQCueylCDXoG6bvGkrIME,2111
218
- cycode-3.22.2.dev2.dist-info/METADATA,sha256=tkSO38WhV7tKuYCZpFAtVUBd4E1Kwwr2HNKpWzWtjiI,93687
219
- cycode-3.22.2.dev2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
220
- cycode-3.22.2.dev2.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
221
- cycode-3.22.2.dev2.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
222
- cycode-3.22.2.dev2.dist-info/RECORD,,
219
+ cycode-3.23.0.dist-info/METADATA,sha256=ymVRL8wqyQvkIYQr5Dodr8bA32cRs0ewsvtE8DPdGNM,93682
220
+ cycode-3.23.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
221
+ cycode-3.23.0.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
222
+ cycode-3.23.0.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
223
+ cycode-3.23.0.dist-info/RECORD,,