clawmoat 0.8.0 → 1.0.0

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.
Files changed (171) hide show
  1. package/.dockerignore +9 -0
  2. package/CHANGELOG.md +18 -0
  3. package/DEMO.md +87 -0
  4. package/Dockerfile +5 -18
  5. package/README.md +232 -8
  6. package/THREAT_MODEL.md +129 -0
  7. package/agent/README.md +131 -0
  8. package/agent/index.js +471 -0
  9. package/agent/install-service.sh +94 -0
  10. package/agent/openclaw-hook.js +453 -0
  11. package/agent/provider-setup.js +649 -0
  12. package/agent/setup.js +274 -0
  13. package/assets/BADGE-USAGE.md +20 -0
  14. package/assets/clawmoat-badge.svg +21 -0
  15. package/bin/clawmoat.js +468 -111
  16. package/docs/affiliates/dashboard.html +124 -0
  17. package/docs/affiliates/index.html +236 -0
  18. package/docs/agent-install.html +183 -0
  19. package/docs/ai-agent-security-scanner.html +10 -6
  20. package/docs/badge/index.html +149 -0
  21. package/docs/badge/scanning.svg +23 -0
  22. package/docs/blog/386-malicious-skills.html +11 -4
  23. package/docs/blog/40000-exposed-openclaw-instances.html +11 -4
  24. package/docs/blog/agent-trust-protocol.html +5 -4
  25. package/docs/blog/ai-agent-earns-commissions.html +230 -0
  26. package/docs/blog/bugmageddon-agent-firewall.html +174 -0
  27. package/docs/blog/calculator-math.html +180 -0
  28. package/docs/blog/clawmoat-vs-llamafirewall-nemo-guardrails.html +10 -4
  29. package/docs/blog/host-guardian-launch.html +18 -8
  30. package/docs/blog/ibm-experts-agent-runtime-protection.html +15 -6
  31. package/docs/blog/index.html +67 -9
  32. package/docs/blog/langchain-security-tutorial.html +18 -8
  33. package/docs/blog/mcp-30-cves-security-crisis.html +11 -4
  34. package/docs/blog/meta-researcher-rogue-agent.html +201 -0
  35. package/docs/blog/microsoft-openclaw-workstation-security.html +5 -4
  36. package/docs/blog/nist-ai-agent-standards-clawmoat.html +16 -8
  37. package/docs/blog/oasis-websocket-hijack.html +11 -4
  38. package/docs/blog/ollama-openclaw-security.html +10 -4
  39. package/docs/blog/openclaw-enterprise-readiness-claw10.html +5 -4
  40. package/docs/blog/openclaw-security-reckoning-2026.html +11 -4
  41. package/docs/blog/owasp-agentic-ai-top10.html +18 -8
  42. package/docs/blog/securing-ai-agents.html +18 -8
  43. package/docs/blog/supply-chain-agents.html +18 -8
  44. package/docs/business/index.html +11 -16
  45. package/docs/business/install.html +21 -7
  46. package/docs/checklist.html +10 -4
  47. package/docs/compare/index.html +122 -0
  48. package/docs/compare/lakera/index.html +62 -0
  49. package/docs/compare/llm-guard/index.html +49 -0
  50. package/docs/compare/snyk-agent-scan/index.html +63 -0
  51. package/docs/compare.html +10 -6
  52. package/docs/dashboard/index.html +520 -0
  53. package/docs/finance/index.html +9 -6
  54. package/docs/guides/business-deployment.html +770 -0
  55. package/docs/hall-of-fame.html +11 -5
  56. package/docs/index.html +266 -137
  57. package/docs/integrations/langchain.html +14 -6
  58. package/docs/integrations/openai.html +14 -6
  59. package/docs/integrations/openclaw.html +55 -7
  60. package/docs/plans/2026-03-26-threat-intel-api.md +255 -0
  61. package/docs/plans/2026-04-14-bugmageddon-marketing-pack.md +329 -0
  62. package/docs/plans/2026-04-14-clawmoat-v1-bugmageddon.md +248 -0
  63. package/docs/plans/2026-04-14-v1-release-update.md +91 -0
  64. package/docs/plans/2026-04-19-supabase-audit.md +68 -0
  65. package/docs/plans/2026-05-12-sales-push.md +303 -0
  66. package/docs/playground/index.html +893 -0
  67. package/docs/playground.html +4 -7
  68. package/docs/rfcs/defense-in-depth.md +467 -0
  69. package/docs/scan/index.html +156 -12
  70. package/docs/services/case-study.html +255 -0
  71. package/docs/services/downloads/install-openclaw.bat +45 -0
  72. package/docs/services/downloads/install-openclaw.command +38 -0
  73. package/docs/services/downloads/install-openclaw.sh +38 -0
  74. package/docs/services/get-started.html +165 -0
  75. package/docs/services/index.html +598 -0
  76. package/docs/services/multi-agent-security.html +284 -0
  77. package/docs/services/one-pager.html +99 -0
  78. package/docs/services/pitch-deck.html +229 -0
  79. package/docs/services/roi-calculator.html +258 -0
  80. package/docs/sitemap.xml +62 -2
  81. package/docs/support/index.html +12 -1
  82. package/docs/templates/customer-service/HEARTBEAT.md +61 -0
  83. package/docs/templates/customer-service/MEMORY.md +89 -0
  84. package/docs/templates/customer-service/SOUL.md +41 -0
  85. package/docs/templates/customer-service/USER.md +56 -0
  86. package/docs/templates/executive/HEARTBEAT.md +86 -0
  87. package/docs/templates/executive/MEMORY.md +92 -0
  88. package/docs/templates/executive/SOUL.md +44 -0
  89. package/docs/templates/executive/USER.md +62 -0
  90. package/docs/templates/finance/HEARTBEAT.md +58 -0
  91. package/docs/templates/finance/MEMORY.md +87 -0
  92. package/docs/templates/finance/SOUL.md +38 -0
  93. package/docs/templates/finance/USER.md +53 -0
  94. package/docs/templates/index.html +115 -0
  95. package/docs/templates/operations/HEARTBEAT.md +63 -0
  96. package/docs/templates/operations/MEMORY.md +68 -0
  97. package/docs/templates/operations/SOUL.md +38 -0
  98. package/docs/templates/operations/USER.md +49 -0
  99. package/docs/templates/sales/HEARTBEAT.md +55 -0
  100. package/docs/templates/sales/MEMORY.md +89 -0
  101. package/docs/templates/sales/SOUL.md +34 -0
  102. package/docs/templates/sales/USER.md +54 -0
  103. package/eslint.config.js +32 -0
  104. package/evals/README.md +29 -0
  105. package/evals/cases.json +390 -0
  106. package/evals/results.md +68 -0
  107. package/evals/run.js +180 -0
  108. package/examples/demo-attack/demo.js +186 -0
  109. package/examples/python-quickstart/README.md +54 -0
  110. package/examples/python-quickstart/clawmoat_client.py +167 -0
  111. package/examples/video-demo/README.md +14 -0
  112. package/examples/video-demo/scene-a-normal.js +29 -0
  113. package/examples/video-demo/scene-b-attack-arrives.js +31 -0
  114. package/examples/video-demo/scene-c-hijack.js +44 -0
  115. package/examples/video-demo/scene-d-clawmoat.js +46 -0
  116. package/integrations/crewai/README.md +32 -0
  117. package/integrations/crewai/clawmoat_crewai/__init__.py +17 -0
  118. package/integrations/crewai/clawmoat_crewai/guard.py +103 -0
  119. package/integrations/crewai/pyproject.toml +21 -0
  120. package/integrations/langchain/README.md +91 -0
  121. package/integrations/langchain/clawmoat_langchain/__init__.py +17 -0
  122. package/integrations/langchain/clawmoat_langchain/callback.py +489 -0
  123. package/integrations/langchain/pyproject.toml +32 -0
  124. package/integrations/litellm/README.md +324 -0
  125. package/integrations/litellm/clawmoat_litellm/__init__.py +21 -0
  126. package/integrations/litellm/clawmoat_litellm/callback.py +329 -0
  127. package/integrations/litellm/clawmoat_litellm/proxy_middleware.py +224 -0
  128. package/integrations/litellm/pyproject.toml +74 -0
  129. package/integrations/openai-agents/README.md +392 -0
  130. package/integrations/openai-agents/clawmoat_openai_agents/__init__.py +20 -0
  131. package/integrations/openai-agents/clawmoat_openai_agents/guardrail.py +431 -0
  132. package/integrations/openai-agents/clawmoat_openai_agents/middleware.py +311 -0
  133. package/integrations/openai-agents/pyproject.toml +76 -0
  134. package/package.json +6 -5
  135. package/plugins/openclaw-adapter/PHASE1.md +439 -0
  136. package/plugins/openclaw-adapter/README.md +103 -0
  137. package/plugins/openclaw-adapter/SPEC.md +1644 -0
  138. package/plugins/openclaw-adapter/package.json +31 -0
  139. package/plugins/openclaw-adapter/src/index.test.ts +226 -0
  140. package/plugins/openclaw-adapter/src/index.ts +140 -0
  141. package/plugins/openclaw-adapter/tsconfig.json +14 -0
  142. package/server/data/threats.json +290 -0
  143. package/server/index.js +142 -7
  144. package/src/adapters/express.js +161 -0
  145. package/src/adapters/index.js +92 -0
  146. package/src/adapters/langchain.js +185 -0
  147. package/src/approval/index.js +456 -0
  148. package/src/ban-scanner.js +200 -0
  149. package/src/boundary-scanner.js +296 -0
  150. package/src/ci-scanner.js +279 -0
  151. package/src/code-scanner.js +245 -0
  152. package/src/enforce.js +166 -0
  153. package/src/formatters/json.js +80 -0
  154. package/src/formatters/sarif.js +388 -0
  155. package/src/guardian/alerts.js +34 -3
  156. package/src/guardian/index.js +41 -2
  157. package/src/index.js +102 -0
  158. package/src/integrations/agentmesh.js +501 -0
  159. package/src/language-detector.js +201 -0
  160. package/src/mcp-scanner.js +253 -0
  161. package/src/multimodal/index.js +579 -0
  162. package/src/obfuscation-scanner.js +457 -0
  163. package/src/policy-engine.js +402 -0
  164. package/src/scanners/dependency-attacks.js +128 -0
  165. package/src/scanners/prompt-injection.js +18 -0
  166. package/src/scanners/supply-chain.js +14 -0
  167. package/src/templates/default-config.yml +90 -0
  168. package/src/vuln-ops/exploitability.js +46 -0
  169. package/src/watch/live-monitor.js +720 -0
  170. package/clawmoat-0.8.0.tgz +0 -0
  171. package/server/index.js.patch +0 -1
@@ -0,0 +1,311 @@
1
+ """OpenAI Agents SDK middleware for ClawMoat security scanning."""
2
+
3
+ from typing import Dict, Any, List, Optional, AsyncGenerator, Union
4
+ import json
5
+ import time
6
+
7
+
8
+ class ClawMoatAgentMiddleware:
9
+ """Middleware for OpenAI Agents SDK to add comprehensive ClawMoat security.
10
+
11
+ This provides a higher-level integration that can wrap entire agents
12
+ or conversation flows with security scanning and policy enforcement.
13
+ """
14
+
15
+ def __init__(
16
+ self,
17
+ guardrail_config: Optional[Dict[str, Any]] = None,
18
+ enable_conversation_tracking: bool = True,
19
+ max_conversation_length: int = 50,
20
+ audit_all_interactions: bool = True
21
+ ):
22
+ """Initialize ClawMoat agent middleware.
23
+
24
+ Args:
25
+ guardrail_config: Configuration for ClawMoat guardrails
26
+ enable_conversation_tracking: Track conversation history for context
27
+ max_conversation_length: Maximum turns to keep in conversation history
28
+ audit_all_interactions: Whether to audit all agent interactions
29
+ """
30
+ self.guardrail_config = guardrail_config or {}
31
+ self.enable_conversation_tracking = enable_conversation_tracking
32
+ self.max_conversation_length = max_conversation_length
33
+ self.audit_all_interactions = audit_all_interactions
34
+
35
+ # Initialize guardrails
36
+ try:
37
+ from .guardrail import ClawMoatGuardrail
38
+ self.input_guardrail = ClawMoatGuardrail(
39
+ scan_input=True,
40
+ scan_output=False,
41
+ **self.guardrail_config
42
+ )
43
+ self.output_guardrail = ClawMoatGuardrail(
44
+ scan_input=False,
45
+ scan_output=True,
46
+ **self.guardrail_config
47
+ )
48
+ except ImportError as e:
49
+ print(f"Warning: Could not initialize ClawMoat guardrails: {e}")
50
+ self.input_guardrail = None
51
+ self.output_guardrail = None
52
+
53
+ # State tracking
54
+ self.conversation_history = []
55
+ self.interaction_log = []
56
+ self.security_summary = {
57
+ "total_interactions": 0,
58
+ "blocked_inputs": 0,
59
+ "blocked_outputs": 0,
60
+ "threats_detected": 0,
61
+ "last_threat": None
62
+ }
63
+
64
+ def wrap_agent(self, agent):
65
+ """Wrap an OpenAI agent with ClawMoat security middleware.
66
+
67
+ Returns a new agent instance with security guardrails attached.
68
+ """
69
+ try:
70
+ # Add ClawMoat guardrails to the agent
71
+ if hasattr(agent, 'input_guardrails') and self.input_guardrail:
72
+ if not agent.input_guardrails:
73
+ agent.input_guardrails = []
74
+ agent.input_guardrails.append(self.input_guardrail)
75
+
76
+ if hasattr(agent, 'output_guardrails') and self.output_guardrail:
77
+ if not agent.output_guardrails:
78
+ agent.output_guardrails = []
79
+ agent.output_guardrails.append(self.output_guardrail)
80
+
81
+ # Wrap key methods for additional tracking
82
+ original_run = agent.run if hasattr(agent, 'run') else None
83
+ if original_run:
84
+ agent.run = self._wrap_run_method(original_run)
85
+
86
+ return agent
87
+
88
+ except Exception as e:
89
+ print(f"Warning: Could not fully wrap agent with ClawMoat: {e}")
90
+ return agent
91
+
92
+ def _wrap_run_method(self, original_run):
93
+ """Wrap the agent's run method to add security tracking."""
94
+ def wrapped_run(*args, **kwargs):
95
+ interaction_id = f"interaction_{int(time.time() * 1000)}"
96
+ start_time = time.time()
97
+
98
+ # Pre-run security check
99
+ try:
100
+ self.security_summary["total_interactions"] += 1
101
+
102
+ # Log interaction start
103
+ if self.audit_all_interactions:
104
+ self.interaction_log.append({
105
+ "id": interaction_id,
106
+ "timestamp": start_time,
107
+ "type": "agent_run_start",
108
+ "args_count": len(args),
109
+ "kwargs_keys": list(kwargs.keys()) if kwargs else []
110
+ })
111
+
112
+ # Call original run method
113
+ result = original_run(*args, **kwargs)
114
+
115
+ # Post-run processing
116
+ end_time = time.time()
117
+ duration = end_time - start_time
118
+
119
+ if self.audit_all_interactions:
120
+ self.interaction_log.append({
121
+ "id": interaction_id,
122
+ "timestamp": end_time,
123
+ "type": "agent_run_complete",
124
+ "duration": duration,
125
+ "success": True
126
+ })
127
+
128
+ # Update conversation tracking
129
+ if self.enable_conversation_tracking:
130
+ self._update_conversation_tracking(args, kwargs, result)
131
+
132
+ return result
133
+
134
+ except Exception as e:
135
+ # Handle errors
136
+ end_time = time.time()
137
+ duration = end_time - start_time
138
+
139
+ if self.audit_all_interactions:
140
+ self.interaction_log.append({
141
+ "id": interaction_id,
142
+ "timestamp": end_time,
143
+ "type": "agent_run_error",
144
+ "duration": duration,
145
+ "error": str(e),
146
+ "success": False
147
+ })
148
+
149
+ # Check if this was a security block
150
+ if "ClawMoat" in str(e) or "blocked" in str(e).lower():
151
+ self.security_summary["blocked_inputs"] += 1
152
+ self.security_summary["last_threat"] = {
153
+ "timestamp": end_time,
154
+ "type": "input_blocked",
155
+ "error": str(e)
156
+ }
157
+
158
+ # Re-raise the original exception
159
+ raise
160
+
161
+ return wrapped_run
162
+
163
+ def _update_conversation_tracking(self, args, kwargs, result):
164
+ """Update conversation history tracking."""
165
+ try:
166
+ # Extract conversation turn from args/kwargs
167
+ turn_data = {
168
+ "timestamp": time.time(),
169
+ "input": self._extract_input_content(args, kwargs),
170
+ "output": self._extract_output_content(result),
171
+ }
172
+
173
+ # Add to conversation history
174
+ self.conversation_history.append(turn_data)
175
+
176
+ # Trim history if too long
177
+ if len(self.conversation_history) > self.max_conversation_length:
178
+ self.conversation_history = self.conversation_history[-self.max_conversation_length:]
179
+
180
+ except Exception as e:
181
+ # Don't fail the main operation if tracking fails
182
+ if self.guardrail_config.get("verbose", False):
183
+ print(f"Conversation tracking error: {e}")
184
+
185
+ def _extract_input_content(self, args, kwargs) -> str:
186
+ """Extract input content for conversation tracking."""
187
+ content_parts = []
188
+
189
+ # Extract from args
190
+ for arg in args:
191
+ if isinstance(arg, str):
192
+ content_parts.append(arg)
193
+ elif hasattr(arg, 'content'):
194
+ content_parts.append(str(arg.content))
195
+ elif isinstance(arg, dict):
196
+ if 'content' in arg:
197
+ content_parts.append(str(arg['content']))
198
+ elif 'message' in arg:
199
+ content_parts.append(str(arg['message']))
200
+
201
+ # Extract from kwargs
202
+ for key, value in kwargs.items():
203
+ if key in ['message', 'prompt', 'input', 'content']:
204
+ content_parts.append(str(value))
205
+
206
+ return " ".join(content_parts)
207
+
208
+ def _extract_output_content(self, result) -> str:
209
+ """Extract output content for conversation tracking."""
210
+ try:
211
+ if isinstance(result, str):
212
+ return result
213
+ elif hasattr(result, 'content'):
214
+ return str(result.content)
215
+ elif hasattr(result, 'message'):
216
+ return str(result.message)
217
+ elif isinstance(result, dict):
218
+ if 'content' in result:
219
+ return str(result['content'])
220
+ elif 'message' in result:
221
+ return str(result['message'])
222
+ elif 'response' in result:
223
+ return str(result['response'])
224
+ return str(result)
225
+ except Exception:
226
+ return "[Unable to extract content]"
227
+
228
+ def get_security_summary(self) -> Dict[str, Any]:
229
+ """Get comprehensive security summary."""
230
+ summary = {
231
+ **self.security_summary,
232
+ "conversation_length": len(self.conversation_history),
233
+ "total_interactions_logged": len(self.interaction_log),
234
+ }
235
+
236
+ # Add guardrail stats if available
237
+ if self.input_guardrail:
238
+ summary["input_stats"] = self.input_guardrail.get_stats()
239
+ if self.output_guardrail:
240
+ summary["output_stats"] = self.output_guardrail.get_stats()
241
+
242
+ return summary
243
+
244
+ def get_conversation_history(self, limit: int = 10) -> List[Dict[str, Any]]:
245
+ """Get recent conversation history."""
246
+ return self.conversation_history[-limit:] if self.conversation_history else []
247
+
248
+ def get_recent_interactions(self, limit: int = 20) -> List[Dict[str, Any]]:
249
+ """Get recent interaction logs."""
250
+ return self.interaction_log[-limit:] if self.interaction_log else []
251
+
252
+ def get_threat_summary(self) -> Dict[str, Any]:
253
+ """Get summary of detected threats."""
254
+ all_findings = []
255
+
256
+ if self.input_guardrail:
257
+ all_findings.extend(self.input_guardrail.findings)
258
+ if self.output_guardrail:
259
+ all_findings.extend(self.output_guardrail.findings)
260
+
261
+ # Group by threat type
262
+ threat_counts = {}
263
+ for finding in all_findings:
264
+ threat_type = finding.get("type", "unknown")
265
+ severity = finding.get("severity", "unknown")
266
+ key = f"{threat_type}_{severity}"
267
+ threat_counts[key] = threat_counts.get(key, 0) + 1
268
+
269
+ return {
270
+ "total_threats": len(all_findings),
271
+ "threat_breakdown": threat_counts,
272
+ "recent_threats": all_findings[-5:] if all_findings else [],
273
+ "last_threat_time": self.security_summary.get("last_threat", {}).get("timestamp")
274
+ }
275
+
276
+ def export_audit_log(self, format: str = "json") -> str:
277
+ """Export complete audit log for compliance."""
278
+ audit_data = {
279
+ "metadata": {
280
+ "export_timestamp": time.time(),
281
+ "total_interactions": len(self.interaction_log),
282
+ "conversation_turns": len(self.conversation_history),
283
+ "security_summary": self.security_summary
284
+ },
285
+ "interactions": self.interaction_log,
286
+ "conversation_history": self.conversation_history if self.enable_conversation_tracking else [],
287
+ "threat_summary": self.get_threat_summary(),
288
+ "security_stats": self.get_security_summary()
289
+ }
290
+
291
+ if format.lower() == "json":
292
+ return json.dumps(audit_data, indent=2, default=str)
293
+ else:
294
+ raise ValueError(f"Unsupported export format: {format}")
295
+
296
+ def reset_tracking(self) -> None:
297
+ """Reset all tracking data (for testing or cleanup)."""
298
+ self.conversation_history.clear()
299
+ self.interaction_log.clear()
300
+ self.security_summary = {
301
+ "total_interactions": 0,
302
+ "blocked_inputs": 0,
303
+ "blocked_outputs": 0,
304
+ "threats_detected": 0,
305
+ "last_threat": None
306
+ }
307
+
308
+ if self.input_guardrail:
309
+ self.input_guardrail.reset_stats()
310
+ if self.output_guardrail:
311
+ self.output_guardrail.reset_stats()
@@ -0,0 +1,76 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "clawmoat-openai-agents"
7
+ dynamic = ["version"]
8
+ description = "ClawMoat security integration for OpenAI Agents SDK"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = "MIT"
12
+ keywords = ["ai", "security", "openai", "agents", "guardrails", "prompt-injection"]
13
+ authors = [
14
+ { name = "ClawMoat Team", email = "security@clawmoat.com" },
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Topic :: Security",
28
+ "Topic :: Software Development :: Libraries :: Python Modules",
29
+ ]
30
+ dependencies = [
31
+ "requests>=2.25.0",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ openai-agents = [
36
+ "openai-agents-sdk>=1.0.0",
37
+ ]
38
+ dev = [
39
+ "pytest>=6.0",
40
+ "pytest-asyncio",
41
+ "black",
42
+ "isort",
43
+ "flake8",
44
+ ]
45
+
46
+ [project.urls]
47
+ Documentation = "https://github.com/darfaz/clawmoat/tree/main/integrations/openai-agents"
48
+ Issues = "https://github.com/darfaz/clawmoat/issues"
49
+ Source = "https://github.com/darfaz/clawmoat/tree/main/integrations/openai-agents"
50
+ Homepage = "https://github.com/darfaz/clawmoat"
51
+
52
+ [tool.hatch.version]
53
+ path = "clawmoat_openai_agents/__init__.py"
54
+
55
+ [tool.hatch.build.targets.sdist]
56
+ include = [
57
+ "/clawmoat_openai_agents",
58
+ "/README.md",
59
+ ]
60
+
61
+ [tool.hatch.build.targets.wheel]
62
+ packages = ["clawmoat_openai_agents"]
63
+
64
+ [tool.black]
65
+ line-length = 120
66
+ target-version = ['py38']
67
+
68
+ [tool.isort]
69
+ profile = "black"
70
+ line_length = 120
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["tests"]
74
+ python_files = "test_*.py"
75
+ python_classes = "Test*"
76
+ python_functions = "test_*"
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "clawmoat",
3
- "version": "0.8.0",
4
- "description": "Security moat for AI agents. Runtime protection against prompt injection, tool misuse, and data exfiltration.",
3
+ "version": "1.0.0",
4
+ "description": "The open-source agent firewall. Prevent AI agents from leaking data, using dangerous tools, and importing poisoned dependencies.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "clawmoat": "bin/clawmoat.js"
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node src/server.js",
11
- "test": "node --test test/",
11
+ "test": "node --test test/*.test.js",
12
12
  "lint": "eslint src/"
13
13
  },
14
14
  "keywords": [
@@ -30,6 +30,7 @@
30
30
  "engines": {
31
31
  "node": ">=18"
32
32
  },
33
- "dependencies": {},
34
- "devDependencies": {}
33
+ "devDependencies": {
34
+ "eslint": "^10.3.0"
35
+ }
35
36
  }