0xray 2.0.1 → 2.1.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.
- package/.opencode/codex.codex +1 -1
- package/AGENTS.md +1 -1
- package/dist/AGENTS.md +1 -1
- package/dist/benchmark/performance-benchmark.d.ts +2 -2
- package/dist/benchmark/performance-benchmark.js +3 -3
- package/dist/cli/commands/hermes-install.js +4 -4
- package/dist/cli/commands/mcp-install.js +1 -1
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/commands/plugin-commands.js +2 -2
- package/dist/cli/commands/publish-agent.js +5 -5
- package/dist/cli/commands/skill-install.js +1 -1
- package/dist/cli/commands/status.js +3 -3
- package/dist/cli/commands/storyteller.js +2 -2
- package/dist/cli/index.js +8 -8
- package/dist/cli/server.js +1 -1
- package/dist/core/agent-spawn-gate.d.ts +1 -1
- package/dist/core/agent-spawn-gate.js +1 -1
- package/dist/core/boot-orchestrator.d.ts +4 -4
- package/dist/core/boot-orchestrator.js +26 -26
- package/dist/core/bridge.mjs +22 -22
- package/dist/core/codex-formatter.js +2 -2
- package/dist/core/codex-injector.d.ts +4 -3
- package/dist/core/codex-injector.js +11 -10
- package/dist/core/config-loader.d.ts +5 -4
- package/dist/core/config-loader.js +4 -2
- package/dist/core/config-paths.d.ts +9 -8
- package/dist/core/config-paths.js +24 -23
- package/dist/core/context-loader.d.ts +4 -3
- package/dist/core/context-loader.js +7 -5
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/orchestrator.d.ts +1 -0
- package/dist/core/orchestrator.js +3 -2
- package/dist/core/system-prompt-generator.js +2 -2
- package/dist/core/xray-activation.d.ts +4 -4
- package/dist/core/xray-activation.js +29 -24
- package/dist/delegation/agent-delegator.d.ts +3 -3
- package/dist/delegation/agent-delegator.js +3 -3
- package/dist/delegation/metrics-aggregator.d.ts +11 -11
- package/dist/delegation/session-coordinator.d.ts +3 -3
- package/dist/delegation/voting-coordinator.d.ts +3 -3
- package/dist/enforcement/enforcer-tools.js +2 -2
- package/dist/enforcement/loaders/codex-loader.d.ts +1 -1
- package/dist/enforcement/loaders/codex-loader.js +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +6 -6
- package/dist/inference/deploy-verifier.js +1 -1
- package/dist/inference/inference-cycle.js +7 -7
- package/dist/integrations/base/README.md +2 -2
- package/dist/integrations/governance/index.js +1 -1
- package/dist/integrations/grok/grok-cli.d.ts +1 -1
- package/dist/integrations/grok/grok-cli.js +6 -6
- package/dist/integrations/grok/hooks/pre-tool-use.js +1 -1
- package/dist/integrations/grok/plugin/0xray/.mcp.json +3 -3
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/dist/integrations/hermes-agent/__init__.py +77 -71
- package/dist/integrations/hermes-agent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/schemas.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/test_plugin.cpython-313-pytest-9.0.2.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/test_plugin.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/tools.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/after-install.md +14 -14
- package/dist/integrations/hermes-agent/bridge.mjs +14 -14
- package/dist/integrations/hermes-agent/logs/framework/routing-outcomes.json +1 -0
- package/dist/integrations/hermes-agent/plugin.yaml +5 -5
- package/dist/integrations/hermes-agent/schemas.py +12 -12
- package/dist/integrations/hermes-agent/test_plugin.py +128 -125
- package/dist/integrations/hermes-agent/tools.py +85 -23
- package/dist/integrations/openclaw/README.md +16 -16
- package/dist/integrations/openclaw/api-server.d.ts +4 -4
- package/dist/integrations/openclaw/api-server.js +9 -9
- package/dist/integrations/openclaw/config.js +1 -1
- package/dist/integrations/openclaw/hooks/{strray-hooks.d.ts → xray-hooks.d.ts} +4 -4
- package/dist/integrations/openclaw/index.d.ts +4 -4
- package/dist/integrations/openclaw/index.js +4 -4
- package/dist/integrations/openclaw/types.d.ts +1 -1
- package/dist/integrations/plugins/plugin-registry.js +2 -2
- package/dist/mcps/architect-tools.server.d.ts +2 -2
- package/dist/mcps/architect-tools.server.js +3 -3
- package/dist/mcps/auto-format.server.d.ts +2 -2
- package/dist/mcps/auto-format.server.js +3 -3
- package/dist/mcps/boot-orchestrator.server.d.ts +2 -2
- package/dist/mcps/boot-orchestrator.server.js +3 -3
- package/dist/mcps/config/server-config-registry.d.ts +1 -1
- package/dist/mcps/config/server-config-registry.js +7 -7
- package/dist/mcps/connection/mcp-connection.js +1 -1
- package/dist/mcps/enforcer-tools.server.d.ts +2 -2
- package/dist/mcps/enforcer-tools.server.js +3 -3
- package/dist/mcps/framework-compliance-audit.server.d.ts +2 -2
- package/dist/mcps/framework-compliance-audit.server.js +3 -3
- package/dist/mcps/framework-help.server.js +6 -6
- package/dist/mcps/in-process-skill-registry.js +6 -6
- package/dist/mcps/knowledge-skills/api-design.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/api-design.server.js +3 -3
- package/dist/mcps/knowledge-skills/architecture-patterns.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/architecture-patterns.server.js +3 -3
- package/dist/mcps/knowledge-skills/code-review.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/code-review.server.js +3 -3
- package/dist/mcps/knowledge-skills/database-design.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/database-design.server.js +3 -3
- package/dist/mcps/knowledge-skills/devops-deployment.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/devops-deployment.server.js +3 -3
- package/dist/mcps/knowledge-skills/git-workflow.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/git-workflow.server.js +3 -3
- package/dist/mcps/knowledge-skills/mobile-development.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/mobile-development.server.js +3 -3
- package/dist/mcps/knowledge-skills/performance-optimization.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/performance-optimization.server.js +3 -3
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +3 -3
- package/dist/mcps/knowledge-skills/security-audit.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/security-audit.server.js +3 -3
- package/dist/mcps/knowledge-skills/tech-writer.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/tech-writer.server.js +3 -3
- package/dist/mcps/knowledge-skills/testing-best-practices.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/testing-best-practices.server.js +3 -3
- package/dist/mcps/knowledge-skills/testing-strategy.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/testing-strategy.server.js +3 -3
- package/dist/mcps/knowledge-skills/ui-ux-design.server.d.ts +2 -2
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +5 -5
- package/dist/mcps/lint.server.d.ts +2 -2
- package/dist/mcps/lint.server.js +5 -5
- package/dist/mcps/mcp-client.js +3 -3
- package/dist/mcps/model-health-check.server.d.ts +2 -2
- package/dist/mcps/model-health-check.server.js +3 -3
- package/dist/mcps/orchestrator/server.js +2 -2
- package/dist/mcps/performance-analysis.server.d.ts +2 -2
- package/dist/mcps/performance-analysis.server.js +3 -3
- package/dist/mcps/processor-pipeline.server.d.ts +2 -2
- package/dist/mcps/processor-pipeline.server.js +3 -3
- package/dist/mcps/researcher.server.d.ts +3 -3
- package/dist/mcps/researcher.server.js +4 -4
- package/dist/mcps/security-scan.server.d.ts +2 -2
- package/dist/mcps/security-scan.server.js +3 -3
- package/dist/mcps/simulation/server-simulations.js +3 -3
- package/dist/metrics/agent-metrics.d.ts +4 -4
- package/dist/metrics/agent-metrics.js +1 -1
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.d.ts +2 -2
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +2 -2
- package/dist/orchestrator/intelligent-commit-batcher.d.ts +1 -1
- package/dist/orchestrator/intelligent-commit-batcher.js +3 -3
- package/dist/orchestrator/multi-agent-orchestration-coordinator.d.ts +3 -3
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +9 -9
- package/dist/orchestrator/orchestrator.d.ts +3 -2
- package/dist/orchestrator/orchestrator.js +8 -6
- package/dist/plugin/xray-codex-injection.d.ts +1 -1
- package/dist/plugin/xray-codex-injection.js +8 -7
- package/dist/postprocessor/PostProcessor.d.ts +2 -2
- package/dist/postprocessor/PostProcessor.js +1 -1
- package/dist/postprocessor/monitoring/MonitoringEngine.d.ts +2 -2
- package/dist/postprocessor/services/RegressionAnalysisService.js +2 -2
- package/dist/postprocessor/triggers/GitHookTrigger.js +14 -14
- package/dist/processors/implementations/agents-md-validation-processor.js +2 -2
- package/dist/processors/implementations/inference-improvement-processor.js +2 -2
- package/dist/processors/implementations/log-protection-processor.d.ts +1 -1
- package/dist/processors/implementations/log-protection-processor.js +2 -2
- package/dist/processors/implementations/publish-preflight-processor.d.ts +1 -1
- package/dist/processors/implementations/publish-preflight-processor.js +3 -3
- package/dist/processors/implementations/regression-testing-processor.js +2 -2
- package/dist/processors/implementations/session-summary-processor.js +2 -2
- package/dist/processors/implementations/storytelling-trigger-processor.js +2 -2
- package/dist/processors/processor-manager.d.ts +2 -2
- package/dist/public/about.html +6 -6
- package/dist/public/enterprise.html +1 -1
- package/dist/public/features.html +2 -2
- package/dist/public/index.html +4 -4
- package/dist/reporting/report-formatter.js +1 -1
- package/dist/scripts/activate-kernel-pipeline.js +2 -2
- package/dist/scripts/pre-command +1 -1
- package/dist/services/inference-tuner.js +2 -2
- package/dist/session/session-cleanup-manager.d.ts +3 -3
- package/dist/session/session-monitor.d.ts +3 -3
- package/dist/session/session-state-manager.d.ts +3 -3
- package/dist/skills/hermes-agent/SKILL.md +11 -11
- package/dist/skills/storyteller/SKILL.md +1 -1
- package/dist/skills/xray-orchestrator/SKILL.md +141 -0
- package/dist/skills/xray-orchestrator/index.d.ts +13 -0
- package/dist/skills/xray-orchestrator/index.js +224 -0
- package/dist/state/index.d.ts +2 -1
- package/dist/state/index.js +2 -1
- package/dist/state/state-manager.d.ts +2 -2
- package/dist/state/state-manager.js +5 -4
- package/dist/utils/import-resolver.js +1 -1
- package/dist/utils/path-resolver.js +2 -2
- package/dist/utils/token-manager.js +1 -1
- package/dist/validation/estimation-validator.js +1 -1
- package/package.json +2 -2
- package/scripts/hooks/pre-command +1 -1
- package/scripts/hooks/run-hook.js +2 -2
- package/scripts/node/auto-reflection-generator.mjs +2 -2
- package/scripts/node/postinstall.cjs +1 -1
- package/scripts/node/release.js +6 -6
- package/scripts/node/release.mjs +10 -10
- package/scripts/node/version-manager.mjs +1 -1
- package/src/integrations/grok/plugin/0xray/.mcp.json +3 -3
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/src/mcps/architect-tools.server.ts +3 -3
- package/src/mcps/auto-format.server.ts +3 -3
- package/src/mcps/boot-orchestrator.server.ts +3 -3
- package/src/mcps/config/server-config-registry.ts +7 -7
- package/src/mcps/connection/mcp-connection.ts +1 -1
- package/src/mcps/enforcer-tools.server.ts +3 -3
- package/src/mcps/framework-compliance-audit.server.ts +3 -3
- package/src/mcps/framework-help.server.ts +6 -6
- package/src/mcps/in-process-skill-registry.ts +6 -6
- package/src/mcps/knowledge-skills/api-design.server.test.ts +8 -8
- package/src/mcps/knowledge-skills/api-design.server.ts +3 -3
- package/src/mcps/knowledge-skills/architecture-patterns.server.ts +3 -3
- package/src/mcps/knowledge-skills/code-review.server.ts +3 -3
- package/src/mcps/knowledge-skills/database-design.server.ts +3 -3
- package/src/mcps/knowledge-skills/devops-deployment.server.ts +3 -3
- package/src/mcps/knowledge-skills/git-workflow.server.ts +3 -3
- package/src/mcps/knowledge-skills/mobile-development.server.ts +3 -3
- package/src/mcps/knowledge-skills/performance-optimization.server.ts +3 -3
- package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +3 -3
- package/src/mcps/knowledge-skills/security-audit.server.test.ts +23 -23
- package/src/mcps/knowledge-skills/security-audit.server.ts +3 -3
- package/src/mcps/knowledge-skills/tech-writer.server.ts +3 -3
- package/src/mcps/knowledge-skills/testing-best-practices.server.test.ts +28 -28
- package/src/mcps/knowledge-skills/testing-best-practices.server.ts +3 -3
- package/src/mcps/knowledge-skills/testing-strategy.server.test.ts +19 -19
- package/src/mcps/knowledge-skills/testing-strategy.server.ts +3 -3
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +5 -5
- package/src/mcps/lint.server.ts +5 -5
- package/src/mcps/mcp-client.ts +3 -3
- package/src/mcps/model-health-check.server.ts +3 -3
- package/src/mcps/orchestrator/server.ts +2 -2
- package/src/mcps/performance-analysis.server.ts +3 -3
- package/src/mcps/processor-pipeline.server.ts +3 -3
- package/src/mcps/researcher.server.ts +4 -4
- package/src/mcps/security-scan.server.ts +3 -3
- package/src/mcps/simulation/server-simulations.ts +3 -3
- package/src/opencode/codex.codex +1 -1
- package/src/skills/hermes-agent/SKILL.md +11 -11
- package/src/skills/storyteller/SKILL.md +1 -1
- package/src/skills/xray-orchestrator/SKILL.md +141 -0
- package/src/skills/xray-orchestrator/index.ts +268 -0
- package/scripts/validate-stringray-comprehensive.js +0 -636
- /package/dist/integrations/openclaw/hooks/{strray-hooks.js → xray-hooks.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Xray Hermes Plugin — full framework pipeline integration.
|
|
2
2
|
|
|
3
3
|
Mirrors the OpenCode xray-codex-injection.ts behavior:
|
|
4
4
|
1. Captures ALL tool calls and logs to disk
|
|
@@ -29,24 +29,30 @@ except ImportError:
|
|
|
29
29
|
schemas = importlib.import_module("schemas")
|
|
30
30
|
tools = importlib.import_module("tools")
|
|
31
31
|
|
|
32
|
-
logger = logging.getLogger("
|
|
32
|
+
logger = logging.getLogger("xray-hermes")
|
|
33
33
|
|
|
34
34
|
# ── Paths ─────────────────────────────────────────────────────
|
|
35
35
|
|
|
36
36
|
PLUGIN_DIR = Path(__file__).resolve().parent
|
|
37
37
|
BRIDGE_PATH = PLUGIN_DIR / "bridge.mjs"
|
|
38
38
|
|
|
39
|
-
# Project root: find the
|
|
39
|
+
# Project root: find the Xray project directory
|
|
40
40
|
# The plugin lives at ~/.hermes/plugins/ which is NOT inside any project tree,
|
|
41
41
|
# so walking up from PLUGIN_DIR will never find the project. Instead:
|
|
42
|
-
# 1. Check
|
|
43
|
-
# 2. Walk up from cwd looking for node_modules/0xray
|
|
42
|
+
# 1. Check XRAY_PROJECT_ROOT env var (explicit override)
|
|
43
|
+
# 2. Walk up from cwd looking for node_modules/0xray (consumer install)
|
|
44
|
+
|
|
45
|
+
def _find_project_root():
|
|
46
|
+
cwd = os.getcwd()
|
|
47
|
+
home = Path.home()
|
|
48
|
+
d = Path(cwd).resolve()
|
|
49
|
+
while True:
|
|
44
50
|
...
|
|
45
51
|
# node_modules/0xray — consumer install marker
|
|
46
|
-
if (d / "node_modules" / "0xray" / "package.json").exists()
|
|
52
|
+
if (d / "node_modules" / "0xray" / "package.json").exists():
|
|
47
53
|
return d
|
|
48
|
-
# .opencode/
|
|
49
|
-
if (d / ".opencode" / "
|
|
54
|
+
# .opencode/xray — dev repo marker
|
|
55
|
+
if (d / ".opencode" / "xray" / "features.json").exists():
|
|
50
56
|
return d
|
|
51
57
|
# package.json but not home dir
|
|
52
58
|
if d != home and (d / "package.json").exists():
|
|
@@ -79,20 +85,20 @@ _TOOL_AGENT_MAP = {
|
|
|
79
85
|
"delegate_task": ("orchestrator", "delegation"),
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
# Tools where
|
|
88
|
+
# Tools where Xray has a better alternative
|
|
83
89
|
# terminal: only nudge when the command looks lint/security/search related
|
|
84
|
-
|
|
85
|
-
"search_files": "Use
|
|
90
|
+
_BETTER_WITH_XRAY = {
|
|
91
|
+
"search_files": "Use mcp_xray_researcher_search_codebase for code pattern searches",
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
# Patterns that suggest the terminal command should use an MCP tool instead
|
|
89
95
|
_TERMINAL_NUDGE_PATTERNS = {
|
|
90
|
-
"grep": "Use
|
|
91
|
-
"rg ": "Use
|
|
92
|
-
"eslint": "Use
|
|
93
|
-
"npx eslint": "Use
|
|
94
|
-
"npm audit": "Use
|
|
95
|
-
"yarn audit": "Use
|
|
96
|
+
"grep": "Use mcp_xray_researcher_search_codebase instead of grep",
|
|
97
|
+
"rg ": "Use mcp_xray_researcher_search_codebase instead of ripgrep",
|
|
98
|
+
"eslint": "Use mcp_xray_lint_lint instead of raw eslint",
|
|
99
|
+
"npx eslint": "Use mcp_xray_lint_lint instead of raw eslint",
|
|
100
|
+
"npm audit": "Use mcp_xray_security_scan_security_scan instead of npm audit",
|
|
101
|
+
"yarn audit": "Use mcp_xray_security_scan_security_scan instead of yarn audit",
|
|
96
102
|
"find ": "Use search_files(target='files') instead of find",
|
|
97
103
|
"sed ": "Use patch tool instead of sed",
|
|
98
104
|
"awk ": "Use patch tool instead of awk",
|
|
@@ -108,7 +114,7 @@ _session_stats = {
|
|
|
108
114
|
"session_id": None,
|
|
109
115
|
"code_operations": 0,
|
|
110
116
|
"total_tool_calls": 0,
|
|
111
|
-
"
|
|
117
|
+
"xray_mcp_calls": 0,
|
|
112
118
|
"native_tool_calls": 0,
|
|
113
119
|
"quality_gate_runs": 0,
|
|
114
120
|
"quality_gate_blocks": 0,
|
|
@@ -184,8 +190,8 @@ def _call_bridge(command: dict, timeout: int = 10) -> dict:
|
|
|
184
190
|
|
|
185
191
|
# ── Hook: pre_tool_call ───────────────────────────────────────
|
|
186
192
|
|
|
187
|
-
def
|
|
188
|
-
return tool_name.startswith("
|
|
193
|
+
def _is_xray_mcp(tool_name: str) -> bool:
|
|
194
|
+
return tool_name.startswith("mcp_xray_")
|
|
189
195
|
|
|
190
196
|
|
|
191
197
|
def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
|
|
@@ -195,17 +201,17 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
|
|
|
195
201
|
1. Track stats
|
|
196
202
|
2. Log tool-start event to disk
|
|
197
203
|
3. For code-producing tools: run quality gate + pre-processors via bridge
|
|
198
|
-
4. For non-code tools: nudge if
|
|
204
|
+
4. For non-code tools: nudge if Xray alternative exists
|
|
199
205
|
"""
|
|
200
206
|
_session_stats["total_tool_calls"] += 1
|
|
201
207
|
|
|
202
208
|
# Log start event
|
|
203
209
|
_log_tool_event("start", tool_name, args)
|
|
204
210
|
|
|
205
|
-
#
|
|
206
|
-
if
|
|
207
|
-
_session_stats["
|
|
208
|
-
_log_to_file("activity.log", f"[quality-gate] SKIP (
|
|
211
|
+
# Xray MCP tools — track but don't interfere
|
|
212
|
+
if _is_xray_mcp(tool_name):
|
|
213
|
+
_session_stats["xray_mcp_calls"] += 1
|
|
214
|
+
_log_to_file("activity.log", f"[quality-gate] SKIP (xray-mcp): {tool_name}")
|
|
209
215
|
return
|
|
210
216
|
|
|
211
217
|
# delegate_task: snapshot working tree so post_hook can validate changes
|
|
@@ -252,7 +258,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
|
|
|
252
258
|
_log_to_file("activity.log",
|
|
253
259
|
f"[quality-gate] BLOCKED: tool={tool_name} violations={violation_msg}")
|
|
254
260
|
logger.warning(
|
|
255
|
-
"[
|
|
261
|
+
"[xray] Quality gate BLOCKED %s: %s",
|
|
256
262
|
tool_name, violation_msg,
|
|
257
263
|
)
|
|
258
264
|
else:
|
|
@@ -277,10 +283,10 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
|
|
|
277
283
|
f"[bridge] ERROR in pre-process: {bridge_result.get('error', 'unknown')}")
|
|
278
284
|
return
|
|
279
285
|
|
|
280
|
-
# Non-code tools: nudge for
|
|
281
|
-
if tool_name in
|
|
282
|
-
tip =
|
|
283
|
-
logger.info("[
|
|
286
|
+
# Non-code tools: nudge for Xray alternatives
|
|
287
|
+
if tool_name in _BETTER_WITH_XRAY:
|
|
288
|
+
tip = _BETTER_WITH_XRAY[tool_name]
|
|
289
|
+
logger.info("[xray] Tip: %s — %s", tool_name, tip)
|
|
284
290
|
_log_to_file("activity.log",
|
|
285
291
|
f"[nudge] {tool_name}: {tip}")
|
|
286
292
|
|
|
@@ -290,7 +296,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
|
|
|
290
296
|
if isinstance(cmd, str):
|
|
291
297
|
for pattern, tip in _TERMINAL_NUDGE_PATTERNS.items():
|
|
292
298
|
if pattern in cmd:
|
|
293
|
-
logger.info("[
|
|
299
|
+
logger.info( "[xray] Tip: %s — %s", tool_name, tip)
|
|
294
300
|
_log_to_file("activity.log",
|
|
295
301
|
f"[nudge] {tool_name}: {tip}")
|
|
296
302
|
break
|
|
@@ -378,14 +384,14 @@ def _on_post_tool_call(tool_name: str, args: dict, result, task_id: str, **kwarg
|
|
|
378
384
|
if calls - _last_tune_tool_call_count >= _INFERENCE_TUNE_INTERVAL:
|
|
379
385
|
_last_tune_tool_call_count = calls
|
|
380
386
|
logger.info(
|
|
381
|
-
"[
|
|
387
|
+
"[xray] Triggering inference tuning cycle (tool call #%d)", calls
|
|
382
388
|
)
|
|
383
389
|
_log_to_file("activity.log",
|
|
384
390
|
f"[inference-tune] auto-cycle at tool call #{calls}")
|
|
385
391
|
try:
|
|
386
392
|
_run_inference_tune()
|
|
387
393
|
except Exception as e:
|
|
388
|
-
logger.warning("[
|
|
394
|
+
logger.warning("[xray] Inference tuning failed: %s", e)
|
|
389
395
|
|
|
390
396
|
|
|
391
397
|
# ── Hook: session_start ───────────────────────────────────────
|
|
@@ -394,7 +400,7 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
|
|
|
394
400
|
"""Fires when a new session starts. Resets stats, logs to disk."""
|
|
395
401
|
_session_stats["started_at"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
|
396
402
|
_session_stats["session_id"] = session_id
|
|
397
|
-
for key in ("code_operations", "total_tool_calls", "
|
|
403
|
+
for key in ("code_operations", "total_tool_calls", "xray_mcp_calls",
|
|
398
404
|
"native_tool_calls", "quality_gate_runs", "quality_gate_blocks",
|
|
399
405
|
"pre_processor_runs", "post_processor_runs",
|
|
400
406
|
"bridge_calls", "bridge_errors",
|
|
@@ -406,23 +412,23 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
|
|
|
406
412
|
_ensure_log_dir()
|
|
407
413
|
_log_to_file("activity.log",
|
|
408
414
|
f"[session-start] session={session_id} platform={platform}")
|
|
409
|
-
logger.info("[
|
|
415
|
+
logger.info("[xray] Session %s started on %s", session_id, platform)
|
|
410
416
|
|
|
411
417
|
|
|
412
418
|
# ── Slash command ─────────────────────────────────────────────
|
|
413
419
|
|
|
414
|
-
def
|
|
415
|
-
"""Slash command handler: /
|
|
420
|
+
def _xray_command(args: str) -> str:
|
|
421
|
+
"""Slash command handler: /xray [status|stats|help]"""
|
|
416
422
|
cmd = (args or "status").strip().lower()
|
|
417
423
|
|
|
418
424
|
if cmd == "stats":
|
|
419
425
|
return (
|
|
420
|
-
f"
|
|
426
|
+
f"Xray Session Stats\n"
|
|
421
427
|
f" Session: {_session_stats['session_id'] or 'N/A'}\n"
|
|
422
428
|
f" Started: {_session_stats['started_at'] or 'N/A'}\n"
|
|
423
429
|
f" Tool calls: {_session_stats['total_tool_calls']}\n"
|
|
424
430
|
f" Code operations: {_session_stats['code_operations']}\n"
|
|
425
|
-
f"
|
|
431
|
+
f" Xray MCP: {_session_stats['xray_mcp_calls']}\n"
|
|
426
432
|
f" Native tools: {_session_stats['native_tool_calls']}\n"
|
|
427
433
|
f" Quality gate runs: {_session_stats['quality_gate_runs']}\n"
|
|
428
434
|
f" Quality gate blocks: {_session_stats['quality_gate_blocks']}\n"
|
|
@@ -437,19 +443,19 @@ def _strray_command(args: str) -> str:
|
|
|
437
443
|
|
|
438
444
|
if cmd == "help":
|
|
439
445
|
return (
|
|
440
|
-
"
|
|
441
|
-
" /
|
|
442
|
-
" /
|
|
443
|
-
" /
|
|
446
|
+
"Xray Commands:\n"
|
|
447
|
+
" /xray status — Plugin and framework health\n"
|
|
448
|
+
" /xray stats — Session pipeline statistics\n"
|
|
449
|
+
" /xray help — This message"
|
|
444
450
|
)
|
|
445
451
|
|
|
446
452
|
# Default: status (calls bridge health)
|
|
447
453
|
bridge_result = _call_bridge({"command": "health"}, timeout=10)
|
|
448
454
|
if "error" in bridge_result:
|
|
449
|
-
return f"
|
|
455
|
+
return f"Xray plugin loaded. Bridge: {bridge_result['error']}"
|
|
450
456
|
|
|
451
457
|
return (
|
|
452
|
-
f"
|
|
458
|
+
f"Xray Hermes Plugin Status\n"
|
|
453
459
|
f" Framework: {bridge_result.get('framework', 'unknown')}\n"
|
|
454
460
|
f" Version: {bridge_result.get('version', 'unknown')}\n"
|
|
455
461
|
f" Quality Gate: {'ready' if bridge_result.get('components', {}).get('qualityGate') else 'not loaded'}\n"
|
|
@@ -518,7 +524,7 @@ def _record_tool_outcome(tool_name: str, args: dict, success: bool):
|
|
|
518
524
|
with open(_OUTCOMES_PATH, "w") as f:
|
|
519
525
|
json.dump(outcomes, f, indent=2)
|
|
520
526
|
except Exception as e:
|
|
521
|
-
logger.debug("[
|
|
527
|
+
logger.debug("[xray] outcome recording failed: %s", e)
|
|
522
528
|
|
|
523
529
|
|
|
524
530
|
# ── Inference tuning (auto-calibration) ────────────────────────
|
|
@@ -560,7 +566,7 @@ def _run_inference_tune():
|
|
|
560
566
|
# ── Registration ──────────────────────────────────────────────
|
|
561
567
|
|
|
562
568
|
# ── Subagent (delegate_task) enforcement ────────────────────
|
|
563
|
-
# Subagents bypass all
|
|
569
|
+
# Subagents bypass all Xray hooks because they run in isolated
|
|
564
570
|
# contexts. We enforce by snapshotting the working tree before dispatch
|
|
565
571
|
# and validating all changed files after return.
|
|
566
572
|
|
|
@@ -647,7 +653,7 @@ def _validate_subagent_changes(task_id: str, **kwargs):
|
|
|
647
653
|
f"[subagent-validate] BLOCKED: {rel_path} "
|
|
648
654
|
f"violations={'; '.join(str(v) for v in violations[:3])}")
|
|
649
655
|
logger.warning(
|
|
650
|
-
"[
|
|
656
|
+
"[xray] Subagent BLOCKED %s: %s",
|
|
651
657
|
rel_path, violations[:3],
|
|
652
658
|
)
|
|
653
659
|
else:
|
|
@@ -659,28 +665,28 @@ def register(ctx):
|
|
|
659
665
|
"""Wire schemas to handlers and register lifecycle hooks."""
|
|
660
666
|
# ── Register tools ────────────────────────────────────────
|
|
661
667
|
ctx.register_tool(
|
|
662
|
-
name="
|
|
663
|
-
toolset="
|
|
664
|
-
schema=schemas.
|
|
665
|
-
handler=tools.
|
|
668
|
+
name="xray_validate",
|
|
669
|
+
toolset="0xray-hermes",
|
|
670
|
+
schema=schemas.XRAY_VALIDATE,
|
|
671
|
+
handler=tools.xray_validate,
|
|
666
672
|
)
|
|
667
673
|
ctx.register_tool(
|
|
668
|
-
name="
|
|
669
|
-
toolset="
|
|
670
|
-
schema=schemas.
|
|
671
|
-
handler=tools.
|
|
674
|
+
name="xray_codex_check",
|
|
675
|
+
toolset="0xray-hermes",
|
|
676
|
+
schema=schemas.XRAY_CODEX_CHECK,
|
|
677
|
+
handler=tools.xray_codex_check,
|
|
672
678
|
)
|
|
673
679
|
ctx.register_tool(
|
|
674
|
-
name="
|
|
675
|
-
toolset="
|
|
676
|
-
schema=schemas.
|
|
677
|
-
handler=tools.
|
|
680
|
+
name="xray_health",
|
|
681
|
+
toolset="0xray-hermes",
|
|
682
|
+
schema=schemas.XRAY_HEALTH,
|
|
683
|
+
handler=tools.xray_health,
|
|
678
684
|
)
|
|
679
685
|
ctx.register_tool(
|
|
680
|
-
name="
|
|
681
|
-
toolset="
|
|
682
|
-
schema=schemas.
|
|
683
|
-
handler=tools.
|
|
686
|
+
name="xray_hooks",
|
|
687
|
+
toolset="0xray-hermes",
|
|
688
|
+
schema=schemas.XRAY_HOOKS,
|
|
689
|
+
handler=tools.xray_hooks,
|
|
684
690
|
)
|
|
685
691
|
|
|
686
692
|
# ── Register hooks ────────────────────────────────────────
|
|
@@ -691,28 +697,28 @@ def register(ctx):
|
|
|
691
697
|
try:
|
|
692
698
|
ctx.register_hook("on_session_start", _on_session_start)
|
|
693
699
|
except (AttributeError, TypeError):
|
|
694
|
-
logger.debug("[
|
|
700
|
+
logger.debug("[xray] on_session_start hook not yet available")
|
|
695
701
|
|
|
696
702
|
# ── Register slash command ────────────────────────────────
|
|
697
703
|
try:
|
|
698
704
|
ctx.register_command(
|
|
699
|
-
name="
|
|
700
|
-
handler=
|
|
701
|
-
description="
|
|
705
|
+
name="xray",
|
|
706
|
+
handler=_xray_command,
|
|
707
|
+
description="Xray status, stats, hooks, and enforcement info",
|
|
702
708
|
args_hint="[status|stats|help]",
|
|
703
709
|
aliases=("sr",),
|
|
704
710
|
)
|
|
705
711
|
except (AttributeError, TypeError):
|
|
706
|
-
logger.debug("[
|
|
712
|
+
logger.debug("[xray] Slash command registration not yet available")
|
|
707
713
|
|
|
708
714
|
# ── Bootstrap ─────────────────────────────────────────────
|
|
709
715
|
_ensure_log_dir()
|
|
710
716
|
_log_to_file("activity.log",
|
|
711
|
-
f"[plugin-loaded]
|
|
717
|
+
f"[plugin-loaded] Xray Hermes Plugin v2.2 — "
|
|
712
718
|
f"4 tools, 2 hooks, subagent enforcement, bridge={BRIDGE_PATH.exists()}")
|
|
713
719
|
|
|
714
720
|
logger.info(
|
|
715
|
-
"[
|
|
721
|
+
"[xray] Plugin v2.2 loaded: 4 tools, 2 hooks, "
|
|
716
722
|
"subagent enforcement active, bridge=%s",
|
|
717
723
|
BRIDGE_PATH.exists(),
|
|
718
724
|
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Xray Hermes Plugin Installed
|
|
2
2
|
|
|
3
3
|
**Restart your Hermes session** for the plugin to take effect.
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
| Component | Description |
|
|
8
8
|
|-----------|-------------|
|
|
9
|
-
| `
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
12
|
-
| `
|
|
9
|
+
| `xray_validate` | Pre-commit validation with quality gates |
|
|
10
|
+
| `xray_codex_check` | Code review against 60 Codex error-prevention rules |
|
|
11
|
+
| `xray_health` | Framework health check |
|
|
12
|
+
| `xray_hooks` | Git hooks management (install, uninstall, list, status) |
|
|
13
13
|
| `pre_tool_call` hook | Quality gates + nudges before every tool call |
|
|
14
14
|
| `post_tool_call` hook | Post-processors after every tool call |
|
|
15
15
|
|
|
@@ -27,24 +27,24 @@ The plugin can install git hooks for automated validation:
|
|
|
27
27
|
### Install Hooks
|
|
28
28
|
|
|
29
29
|
```
|
|
30
|
-
/
|
|
30
|
+
/xray hooks install
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Or use the tool directly:
|
|
34
34
|
```
|
|
35
|
-
|
|
35
|
+
xray_hooks(action="install")
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
### Check Hook Status
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
/
|
|
41
|
+
/xray hooks status
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
### Uninstall Hooks
|
|
45
45
|
|
|
46
46
|
```
|
|
47
|
-
/
|
|
47
|
+
/xray hooks uninstall
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
## Quick Test
|
|
@@ -52,20 +52,20 @@ strray_hooks(action="install")
|
|
|
52
52
|
After restarting Hermes, try:
|
|
53
53
|
|
|
54
54
|
```
|
|
55
|
-
/
|
|
56
|
-
/
|
|
55
|
+
/xray status
|
|
56
|
+
/xray stats
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Or use the tools directly — `
|
|
59
|
+
Or use the tools directly — `xray_health` will confirm the bridge is connected.
|
|
60
60
|
|
|
61
61
|
## MCP Servers
|
|
62
62
|
|
|
63
|
-
The plugin works alongside
|
|
63
|
+
The plugin works alongside Xray's MCP servers (if configured in your
|
|
64
64
|
Hermes config). The plugin's native tools provide offline/offline-first
|
|
65
65
|
validation, while MCP servers offer deeper framework integration.
|
|
66
66
|
|
|
67
67
|
## Files
|
|
68
68
|
|
|
69
|
-
The plugin lives at `~/.hermes/plugins/
|
|
69
|
+
The plugin lives at `~/.hermes/plugins/xray-hermes/`. It is auto-updated
|
|
70
70
|
when you run `npm install` or `npm update` in a project with `0xray`
|
|
71
71
|
as a dependency.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Xray Framework Bridge for Hermes Agent
|
|
5
5
|
*
|
|
6
|
-
* Provides direct access to
|
|
6
|
+
* Provides direct access to Xray framework components
|
|
7
7
|
* (ProcessorManager, QualityGate, StateManager) from Python.
|
|
8
8
|
* Uses JSON stdin/stdout protocol for IPC.
|
|
9
9
|
*
|
|
@@ -237,7 +237,7 @@ async function runProcessors(tool, args, phase, projectRoot, logDir) {
|
|
|
237
237
|
const logger = new BridgeLogger(logDir);
|
|
238
238
|
|
|
239
239
|
try {
|
|
240
|
-
const stateDir = join(projectRoot, ".
|
|
240
|
+
const stateDir = join(projectRoot, ".xray", "state");
|
|
241
241
|
const stateManager = new StrRayStateManager(stateDir);
|
|
242
242
|
const processorManager = new ProcessorManager(stateManager);
|
|
243
243
|
|
|
@@ -575,7 +575,7 @@ function handleHooks(input, projectRoot) {
|
|
|
575
575
|
const { action, hooks } = input;
|
|
576
576
|
const hookTypes = hooks || ["pre-commit", "post-commit", "pre-push", "post-push"];
|
|
577
577
|
const gitHooksDir = join(projectRoot, ".git", "hooks");
|
|
578
|
-
const
|
|
578
|
+
const xrayHooksDir = join(projectRoot, "hooks");
|
|
579
579
|
|
|
580
580
|
if (!existsSync(gitHooksDir)) {
|
|
581
581
|
return { error: "Not a git repository — no .git/hooks directory" };
|
|
@@ -587,7 +587,7 @@ function handleHooks(input, projectRoot) {
|
|
|
587
587
|
if (action === "list" || action === "status") {
|
|
588
588
|
for (const hookName of hookTypes) {
|
|
589
589
|
const gitHook = join(gitHooksDir, hookName);
|
|
590
|
-
const
|
|
590
|
+
const xrayHook = join(xrayHooksDir, hookName);
|
|
591
591
|
|
|
592
592
|
if (!existsSync(gitHook)) {
|
|
593
593
|
result.missing.push(hookName);
|
|
@@ -604,8 +604,8 @@ function handleHooks(input, projectRoot) {
|
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
// Check if
|
|
608
|
-
if (!existsSync(
|
|
607
|
+
// Check if xray source hook exists
|
|
608
|
+
if (!existsSync(xrayHook)) {
|
|
609
609
|
result.stale.push(hookName);
|
|
610
610
|
}
|
|
611
611
|
}
|
|
@@ -615,7 +615,7 @@ function handleHooks(input, projectRoot) {
|
|
|
615
615
|
action,
|
|
616
616
|
hooks: result,
|
|
617
617
|
gitHooksDir,
|
|
618
|
-
|
|
618
|
+
xrayHooksDir,
|
|
619
619
|
};
|
|
620
620
|
}
|
|
621
621
|
|
|
@@ -626,7 +626,7 @@ function handleHooks(input, projectRoot) {
|
|
|
626
626
|
const errors = [];
|
|
627
627
|
|
|
628
628
|
for (const hookName of hookTypes) {
|
|
629
|
-
const src = join(
|
|
629
|
+
const src = join(xrayHooksDir, hookName);
|
|
630
630
|
const dst = join(gitHooksDir, hookName);
|
|
631
631
|
|
|
632
632
|
if (!existsSync(src)) {
|
|
@@ -635,11 +635,11 @@ function handleHooks(input, projectRoot) {
|
|
|
635
635
|
}
|
|
636
636
|
|
|
637
637
|
try {
|
|
638
|
-
// Backup existing non-
|
|
638
|
+
// Backup existing non-xray hooks
|
|
639
639
|
if (existsSync(dst)) {
|
|
640
640
|
const content = readFileSync(dst, "utf-8");
|
|
641
641
|
if (!content.includes("StringRay") && !content.includes("strray") && !content.includes("run-hook.js")) {
|
|
642
|
-
renameSync(dst, `${dst}.
|
|
642
|
+
renameSync(dst, `${dst}.xray-backup`);
|
|
643
643
|
} else {
|
|
644
644
|
unlinkSync(dst);
|
|
645
645
|
}
|
|
@@ -671,15 +671,15 @@ function handleHooks(input, projectRoot) {
|
|
|
671
671
|
|
|
672
672
|
for (const hookName of hookTypes) {
|
|
673
673
|
const dst = join(gitHooksDir, hookName);
|
|
674
|
-
const backup = `${dst}.
|
|
674
|
+
const backup = `${dst}.xray-backup`;
|
|
675
675
|
|
|
676
676
|
if (!existsSync(dst)) continue;
|
|
677
677
|
|
|
678
678
|
try {
|
|
679
679
|
const content = readFileSync(dst, "utf-8");
|
|
680
|
-
const
|
|
680
|
+
const isXray = content.includes("StringRay") || content.includes("strray") || content.includes("run-hook.js");
|
|
681
681
|
|
|
682
|
-
if (
|
|
682
|
+
if (isXray || lstatSync(dst).isSymbolicLink()) {
|
|
683
683
|
unlinkSync(dst);
|
|
684
684
|
|
|
685
685
|
// Restore backup if exists
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: 0xray-hermes
|
|
2
2
|
version: 2.2.0
|
|
3
3
|
description: 0xRay AI integration plugin — auto-enforcement hooks, quality gates, git hooks, and tool awareness for Hermes Agent
|
|
4
4
|
author: 0xRay AI
|
|
5
5
|
provides_tools:
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
6
|
+
- xray_validate
|
|
7
|
+
- xray_codex_check
|
|
8
|
+
- xray_health
|
|
9
|
+
- xray_hooks
|
|
10
10
|
provides_hooks:
|
|
11
11
|
- pre_tool_call
|
|
12
12
|
- post_tool_call
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Tool schemas — what the LLM sees."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
"name": "
|
|
3
|
+
XRAY_VALIDATE = {
|
|
4
|
+
"name": "xray_validate",
|
|
5
5
|
"description": (
|
|
6
|
-
"Run
|
|
6
|
+
"Run Xray pre-commit validation on specified files. "
|
|
7
7
|
"Checks codex compliance, rule validation, and quality gates. "
|
|
8
8
|
"Use this before committing any code changes. Returns pass/fail "
|
|
9
9
|
"with actionable remediation for any violations."
|
|
@@ -26,8 +26,8 @@ STRRAY_VALIDATE = {
|
|
|
26
26
|
},
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
"name": "
|
|
29
|
+
XRAY_CODEX_CHECK = {
|
|
30
|
+
"name": "xray_codex_check",
|
|
31
31
|
"description": (
|
|
32
32
|
"Validate code against the Universal Development Codex (60 error-prevention terms). "
|
|
33
33
|
"Checks error-handling, type-safety, performance, security, and architecture patterns. "
|
|
@@ -57,12 +57,12 @@ STRRAY_CODEX_CHECK = {
|
|
|
57
57
|
},
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
"name": "
|
|
60
|
+
XRAY_HEALTH = {
|
|
61
|
+
"name": "xray_health",
|
|
62
62
|
"description": (
|
|
63
|
-
"Run
|
|
63
|
+
"Run Xray framework health check. Returns version, agent count, "
|
|
64
64
|
"MCP server status, and enforcement statistics. Use to verify the "
|
|
65
|
-
"
|
|
65
|
+
"Xray integration is working correctly."
|
|
66
66
|
),
|
|
67
67
|
"parameters": {
|
|
68
68
|
"type": "object",
|
|
@@ -70,10 +70,10 @@ STRRAY_HEALTH = {
|
|
|
70
70
|
},
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
"name": "
|
|
73
|
+
XRAY_HOOKS = {
|
|
74
|
+
"name": "xray_hooks",
|
|
75
75
|
"description": (
|
|
76
|
-
"Manage
|
|
76
|
+
"Manage Xray git hooks (install, uninstall, list, status). "
|
|
77
77
|
"Installs pre-commit, post-commit, pre-push, and post-push hooks "
|
|
78
78
|
"that run TypeScript validation, Codex checks, and monitoring. "
|
|
79
79
|
"Use 'install' to set up all hooks, 'list' to see current status."
|