prompt-capability-optimizer 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.
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/SKILL.md +275 -0
- package/adapters/environment_adapters.md +94 -0
- package/adapters/host_capabilities.json +135 -0
- package/bin/cli.js +33 -0
- package/index.js +54 -0
- package/package.json +51 -0
- package/prompt_capability_optimizer/__init__.py +35 -0
- package/prompt_capability_optimizer/__main__.py +7 -0
- package/prompt_capability_optimizer/adapters/__init__.py +21 -0
- package/prompt_capability_optimizer/adapters/agent_adapters.py +281 -0
- package/prompt_capability_optimizer/adapters/host_adapter.py +48 -0
- package/prompt_capability_optimizer/capabilities/__init__.py +7 -0
- package/prompt_capability_optimizer/capabilities/extractor.py +92 -0
- package/prompt_capability_optimizer/capabilities/graph.py +53 -0
- package/prompt_capability_optimizer/classification/__init__.py +6 -0
- package/prompt_capability_optimizer/classification/task_classifier.py +126 -0
- package/prompt_capability_optimizer/cli.py +85 -0
- package/prompt_capability_optimizer/config.py +42 -0
- package/prompt_capability_optimizer/critique/__init__.py +6 -0
- package/prompt_capability_optimizer/critique/self_critique_engine.py +144 -0
- package/prompt_capability_optimizer/discovery/__init__.py +16 -0
- package/prompt_capability_optimizer/discovery/find_skills_adapter.py +143 -0
- package/prompt_capability_optimizer/discovery/local_discovery.py +114 -0
- package/prompt_capability_optimizer/discovery/mcp_discovery.py +145 -0
- package/prompt_capability_optimizer/discovery/registry.py +52 -0
- package/prompt_capability_optimizer/discovery/web_discovery.py +157 -0
- package/prompt_capability_optimizer/engine.py +201 -0
- package/prompt_capability_optimizer/intent/__init__.py +6 -0
- package/prompt_capability_optimizer/intent/intent_analyzer.py +61 -0
- package/prompt_capability_optimizer/models.py +162 -0
- package/prompt_capability_optimizer/optimization/__init__.py +8 -0
- package/prompt_capability_optimizer/optimization/execution_pass.py +52 -0
- package/prompt_capability_optimizer/optimization/optimizer.py +85 -0
- package/prompt_capability_optimizer/optimization/semantic_pass.py +113 -0
- package/prompt_capability_optimizer/scoring/__init__.py +7 -0
- package/prompt_capability_optimizer/scoring/deduplicator.py +46 -0
- package/prompt_capability_optimizer/scoring/scoring_engine.py +34 -0
- package/prompt_capability_optimizer/security/__init__.py +14 -0
- package/prompt_capability_optimizer/security/governance.py +41 -0
- package/prompt_capability_optimizer/security/injection_detector.py +60 -0
- package/prompt_capability_optimizer/security/secret_protector.py +61 -0
- package/prompt_capability_optimizer/security/trust_engine.py +96 -0
- package/prompt_capability_optimizer/verification/__init__.py +6 -0
- package/prompt_capability_optimizer/verification/verification_engine.py +101 -0
- package/references/capability_graph.md +83 -0
- package/references/cross_agent_matrix.md +62 -0
- package/references/prompt_engineering_standards.md +90 -0
- package/references/scoring_rubric.md +49 -0
- package/references/security_and_trust.md +48 -0
- package/scripts/capability_checker.py +88 -0
- package/scripts/prompt_optimizer_engine.py +41 -0
- package/templates/execution_plan_template.md +51 -0
- package/templates/optimized_prompt_template.md +55 -0
- package/templates/verification_matrix_template.md +26 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "HostCapabilitiesSchema",
|
|
4
|
+
"description": "Cross-agent host runtime capability specification and detection schema for prompt-capability-optimizer.",
|
|
5
|
+
"author": "Mahmoud Abdelhameid <Develper.net@gmail.com>",
|
|
6
|
+
"linkedin": "https://www.linkedin.com/in/mahmoud-abdelhameid-dev/",
|
|
7
|
+
"copyright": "Copyright (c) 2026 Mahmoud Abdelhameid. All rights reserved.",
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"agent_identity": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["claude_code", "gemini_cli", "cursor", "windsurf", "cline", "roo_code", "codex", "opencode", "generic_agent", "unknown"]
|
|
13
|
+
},
|
|
14
|
+
"runtime_environment": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"os": { "type": "string", "enum": ["windows", "linux", "darwin"] },
|
|
18
|
+
"shell_type": { "type": "string", "enum": ["powershell", "pwsh", "bash", "zsh", "cmd", "none"] },
|
|
19
|
+
"working_directory": { "type": "string" }
|
|
20
|
+
},
|
|
21
|
+
"required": ["os", "shell_type", "working_directory"]
|
|
22
|
+
},
|
|
23
|
+
"capabilities": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"supports_filesystem": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"available": { "type": "boolean" },
|
|
30
|
+
"methods": { "type": "array", "items": { "type": "string", "enum": ["native_tool", "shell_commands", "read_only", "full_access"] } }
|
|
31
|
+
},
|
|
32
|
+
"required": ["available"]
|
|
33
|
+
},
|
|
34
|
+
"supports_shell": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"available": { "type": "boolean" },
|
|
38
|
+
"supports_async": { "type": "boolean" },
|
|
39
|
+
"supports_daemon": { "type": "boolean" },
|
|
40
|
+
"interactive_input": { "type": "boolean" }
|
|
41
|
+
},
|
|
42
|
+
"required": ["available"]
|
|
43
|
+
},
|
|
44
|
+
"supports_git": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"properties": {
|
|
47
|
+
"available": { "type": "boolean" },
|
|
48
|
+
"in_git_repo": { "type": "boolean" },
|
|
49
|
+
"branch_isolation": { "type": "boolean" }
|
|
50
|
+
},
|
|
51
|
+
"required": ["available"]
|
|
52
|
+
},
|
|
53
|
+
"supports_web_search": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"properties": {
|
|
56
|
+
"available": { "type": "boolean" },
|
|
57
|
+
"provider": { "type": "string" }
|
|
58
|
+
},
|
|
59
|
+
"required": ["available"]
|
|
60
|
+
},
|
|
61
|
+
"supports_web_fetch": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"available": { "type": "boolean" },
|
|
65
|
+
"javascript_execution": { "type": "boolean" }
|
|
66
|
+
},
|
|
67
|
+
"required": ["available"]
|
|
68
|
+
},
|
|
69
|
+
"supports_browser": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"available": { "type": "boolean" },
|
|
73
|
+
"headless": { "type": "boolean" },
|
|
74
|
+
"devtools_protocol": { "type": "boolean" }
|
|
75
|
+
},
|
|
76
|
+
"required": ["available"]
|
|
77
|
+
},
|
|
78
|
+
"supports_mcp": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"properties": {
|
|
81
|
+
"available": { "type": "boolean" },
|
|
82
|
+
"active_servers": { "type": "array", "items": { "type": "string" } },
|
|
83
|
+
"lazy_loading_supported": { "type": "boolean" }
|
|
84
|
+
},
|
|
85
|
+
"required": ["available"]
|
|
86
|
+
},
|
|
87
|
+
"supports_connectors": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"properties": {
|
|
90
|
+
"available": { "type": "boolean" },
|
|
91
|
+
"active_connectors": { "type": "array", "items": { "type": "string" } }
|
|
92
|
+
},
|
|
93
|
+
"required": ["available"]
|
|
94
|
+
},
|
|
95
|
+
"supports_skills": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"properties": {
|
|
98
|
+
"available": { "type": "boolean" },
|
|
99
|
+
"local_skill_roots": { "type": "array", "items": { "type": "string" } },
|
|
100
|
+
"registry_cli_available": { "type": "boolean" }
|
|
101
|
+
},
|
|
102
|
+
"required": ["available"]
|
|
103
|
+
},
|
|
104
|
+
"supports_subagents": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"available": { "type": "boolean" },
|
|
108
|
+
"supports_parallel": { "type": "boolean" },
|
|
109
|
+
"isolated_workspace": { "type": "boolean" }
|
|
110
|
+
},
|
|
111
|
+
"required": ["available"]
|
|
112
|
+
},
|
|
113
|
+
"supports_code_execution": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"properties": {
|
|
116
|
+
"available": { "type": "boolean" },
|
|
117
|
+
"languages": { "type": "array", "items": { "type": "string" } },
|
|
118
|
+
"sandboxed": { "type": "boolean" }
|
|
119
|
+
},
|
|
120
|
+
"required": ["available"]
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"required": [
|
|
124
|
+
"supports_filesystem",
|
|
125
|
+
"supports_shell",
|
|
126
|
+
"supports_git",
|
|
127
|
+
"supports_web_search",
|
|
128
|
+
"supports_web_fetch",
|
|
129
|
+
"supports_mcp",
|
|
130
|
+
"supports_skills"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"required": ["agent_identity", "runtime_environment", "capabilities"]
|
|
135
|
+
}
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI Runner for prompt-capability-optimizer
|
|
4
|
+
* Author: Mahmoud Abdelhameid <Develper.net@gmail.com>
|
|
5
|
+
* LinkedIn: https://www.linkedin.com/in/mahmoud-abdelhameid-dev/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { spawnSync } = require('child_process');
|
|
10
|
+
|
|
11
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
// Check if python is available
|
|
15
|
+
const pyCmd = process.platform === 'win32' ? 'python' : 'python3';
|
|
16
|
+
const checkPy = spawnSync(pyCmd, ['--version'], { encoding: 'utf-8' });
|
|
17
|
+
|
|
18
|
+
if (checkPy.error || checkPy.status !== 0) {
|
|
19
|
+
console.log(`=== Prompt Capability Optimizer ===`);
|
|
20
|
+
console.log(`Author: Mahmoud Abdelhameid (https://www.linkedin.com/in/mahmoud-abdelhameid-dev/)`);
|
|
21
|
+
console.log(`Skill Location: ${path.join(PACKAGE_ROOT, 'SKILL.md')}`);
|
|
22
|
+
console.log(`Notice: Python runtime is required for the full optimizer engine CLI.`);
|
|
23
|
+
console.log(`To use this skill with Claude/Cursor/Gemini, point your agent to: ${PACKAGE_ROOT}`);
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Transparently run python engine
|
|
28
|
+
const proc = spawnSync(pyCmd, ['-m', 'prompt_capability_optimizer', ...args], {
|
|
29
|
+
cwd: PACKAGE_ROOT,
|
|
30
|
+
stdio: 'inherit'
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
process.exit(proc.status || 0);
|
package/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Capability Optimizer
|
|
3
|
+
* ===========================
|
|
4
|
+
* Production-grade agent meta-skill for autonomous capability discovery & prompt engineering.
|
|
5
|
+
*
|
|
6
|
+
* Author: Mahmoud Abdelhameid <Develper.net@gmail.com>
|
|
7
|
+
* LinkedIn: https://www.linkedin.com/in/mahmoud-abdelhameid-dev/
|
|
8
|
+
* License: MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const { spawnSync } = require('child_process');
|
|
14
|
+
|
|
15
|
+
const PACKAGE_ROOT = __dirname;
|
|
16
|
+
const SKILL_MD_PATH = path.join(PACKAGE_ROOT, 'SKILL.md');
|
|
17
|
+
|
|
18
|
+
function getSkillPath() {
|
|
19
|
+
return SKILL_MD_PATH;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getSkillContent() {
|
|
23
|
+
return fs.readFileSync(SKILL_MD_PATH, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getPackageMetadata() {
|
|
27
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'));
|
|
28
|
+
return {
|
|
29
|
+
name: pkg.name,
|
|
30
|
+
version: pkg.version,
|
|
31
|
+
author: pkg.author,
|
|
32
|
+
description: pkg.description,
|
|
33
|
+
repository: pkg.repository.url
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function runOptimizer(args = []) {
|
|
38
|
+
// Attempt python execution
|
|
39
|
+
const pyCmd = process.platform === 'win32' ? 'python' : 'python3';
|
|
40
|
+
const res = spawnSync(pyCmd, ['-m', 'prompt_capability_optimizer', ...args], {
|
|
41
|
+
cwd: PACKAGE_ROOT,
|
|
42
|
+
stdio: 'inherit'
|
|
43
|
+
});
|
|
44
|
+
return res.status;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
PACKAGE_ROOT,
|
|
49
|
+
SKILL_MD_PATH,
|
|
50
|
+
getSkillPath,
|
|
51
|
+
getSkillContent,
|
|
52
|
+
getPackageMetadata,
|
|
53
|
+
runOptimizer
|
|
54
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prompt-capability-optimizer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production-grade, cross-platform agent meta-skill for autonomous capability discovery & two-pass prompt optimization.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"prompt-capability-optimizer": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "python -m unittest discover -s tests -p \"test_*.py\" -v",
|
|
11
|
+
"start": "node ./bin/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/Mahmoud-abdulhamid/prompt-capability-optimizer.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"agent-skill",
|
|
19
|
+
"skills",
|
|
20
|
+
"mcp",
|
|
21
|
+
"prompt-engineering",
|
|
22
|
+
"prompt-optimization",
|
|
23
|
+
"capability-discovery",
|
|
24
|
+
"ai-agent",
|
|
25
|
+
"claude",
|
|
26
|
+
"gemini",
|
|
27
|
+
"cursor",
|
|
28
|
+
"windsurf"
|
|
29
|
+
],
|
|
30
|
+
"author": "Mahmoud Abdelhameid <Develper.net@gmail.com> (https://www.linkedin.com/in/mahmoud-abdelhameid-dev/)",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/Mahmoud-abdulhamid/prompt-capability-optimizer/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/Mahmoud-abdulhamid/prompt-capability-optimizer#readme",
|
|
36
|
+
"files": [
|
|
37
|
+
"SKILL.md",
|
|
38
|
+
"index.js",
|
|
39
|
+
"bin/",
|
|
40
|
+
"prompt_capability_optimizer/",
|
|
41
|
+
"references/",
|
|
42
|
+
"templates/",
|
|
43
|
+
"adapters/",
|
|
44
|
+
"scripts/",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=16.0.0"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Prompt Capability Optimizer
|
|
3
|
+
===========================
|
|
4
|
+
Autonomous, cross-agent prompt optimization and capability discovery framework.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .models import (
|
|
8
|
+
Capability,
|
|
9
|
+
Resource,
|
|
10
|
+
ResourceType,
|
|
11
|
+
PromptIR,
|
|
12
|
+
CritiqueReport,
|
|
13
|
+
ClassificationReport
|
|
14
|
+
)
|
|
15
|
+
from .config import OptimizerConfig, DEFAULT_CONFIG
|
|
16
|
+
from .engine import PromptOptimizerEngine
|
|
17
|
+
|
|
18
|
+
__version__ = "1.0.0"
|
|
19
|
+
__author__ = "Mahmoud Abdelhameid"
|
|
20
|
+
__email__ = "Develper.net@gmail.com"
|
|
21
|
+
__linkedin__ = "https://www.linkedin.com/in/mahmoud-abdelhameid-dev/"
|
|
22
|
+
__copyright__ = "Copyright (c) 2026 Mahmoud Abdelhameid. All rights reserved."
|
|
23
|
+
__license__ = "MIT"
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"PromptOptimizerEngine",
|
|
27
|
+
"OptimizerConfig",
|
|
28
|
+
"DEFAULT_CONFIG",
|
|
29
|
+
"Capability",
|
|
30
|
+
"Resource",
|
|
31
|
+
"ResourceType",
|
|
32
|
+
"PromptIR",
|
|
33
|
+
"CritiqueReport",
|
|
34
|
+
"ClassificationReport"
|
|
35
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2026 Mahmoud Abdelhameid (Develper.net@gmail.com). All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
from .host_adapter import HostAdapter, detect_host_runtime
|
|
5
|
+
from .agent_adapters import (
|
|
6
|
+
ClaudeCodeAdapter,
|
|
7
|
+
GeminiCliAdapter,
|
|
8
|
+
CursorAdapter,
|
|
9
|
+
ClineAdapter,
|
|
10
|
+
get_agent_adapter
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"HostAdapter",
|
|
15
|
+
"detect_host_runtime",
|
|
16
|
+
"ClaudeCodeAdapter",
|
|
17
|
+
"GeminiCliAdapter",
|
|
18
|
+
"CursorAdapter",
|
|
19
|
+
"ClineAdapter",
|
|
20
|
+
"get_agent_adapter"
|
|
21
|
+
]
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Copyright (c) 2026 Mahmoud Abdelhameid (Develper.net@gmail.com). All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Agent Ecosystem Adapters & Compatibility Verification
|
|
6
|
+
=====================================================
|
|
7
|
+
Concrete host implementations for Claude Code, Codex, Gemini CLI, OpenCode,
|
|
8
|
+
Cursor, Windsurf, Cline, and Roo Code.
|
|
9
|
+
Guarantees that unknown agents are NEVER silently mapped to Gemini or any other agent.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import List, Optional
|
|
15
|
+
from ..models import HostCapabilityItem, CapabilityStatus
|
|
16
|
+
from .host_adapter import HostAdapter
|
|
17
|
+
|
|
18
|
+
class GeminiCliAdapter(HostAdapter):
|
|
19
|
+
def get_agent_name(self) -> str:
|
|
20
|
+
return "gemini_cli"
|
|
21
|
+
|
|
22
|
+
def get_skill_paths(self) -> List[Path]:
|
|
23
|
+
home = Path.home()
|
|
24
|
+
cwd = Path.cwd()
|
|
25
|
+
return [
|
|
26
|
+
cwd / ".gemini" / "skills",
|
|
27
|
+
home / ".gemini" / "config" / "skills",
|
|
28
|
+
home / ".gemini" / "antigravity" / "builtin" / "skills"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
32
|
+
return HostCapabilityItem(
|
|
33
|
+
capability="mcp",
|
|
34
|
+
status=CapabilityStatus.RUNTIME_DETECTED,
|
|
35
|
+
confidence=0.98,
|
|
36
|
+
details={"protocol": "Model Context Protocol JSON-RPC", "validated": True}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
40
|
+
return HostCapabilityItem(
|
|
41
|
+
capability="web",
|
|
42
|
+
status=CapabilityStatus.RUNTIME_DETECTED,
|
|
43
|
+
confidence=0.95,
|
|
44
|
+
details={"provider": "search_web / read_url_content", "validated": True}
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
class ClaudeCodeAdapter(HostAdapter):
|
|
48
|
+
def get_agent_name(self) -> str:
|
|
49
|
+
return "claude_code"
|
|
50
|
+
|
|
51
|
+
def get_skill_paths(self) -> List[Path]:
|
|
52
|
+
home = Path.home()
|
|
53
|
+
cwd = Path.cwd()
|
|
54
|
+
return [
|
|
55
|
+
cwd / ".claude" / "skills",
|
|
56
|
+
home / ".claude" / "skills"
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
60
|
+
home = Path.home()
|
|
61
|
+
has_cfg = (home / ".claude" / "mcp.json").exists()
|
|
62
|
+
return HostCapabilityItem(
|
|
63
|
+
capability="mcp",
|
|
64
|
+
status=CapabilityStatus.RUNTIME_DETECTED if has_cfg else CapabilityStatus.HOST_DECLARED,
|
|
65
|
+
confidence=0.90,
|
|
66
|
+
details={"config_file": str(home / ".claude" / "mcp.json"), "validated": True}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
70
|
+
return HostCapabilityItem(
|
|
71
|
+
capability="web",
|
|
72
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
73
|
+
confidence=0.90,
|
|
74
|
+
details={"provider": "WebSearch / WebFetch", "validated": True}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
class CursorAdapter(HostAdapter):
|
|
78
|
+
def get_agent_name(self) -> str:
|
|
79
|
+
return "cursor"
|
|
80
|
+
|
|
81
|
+
def get_skill_paths(self) -> List[Path]:
|
|
82
|
+
cwd = Path.cwd()
|
|
83
|
+
return [
|
|
84
|
+
cwd / ".cursor" / "skills",
|
|
85
|
+
cwd / ".cursor" / "rules"
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
89
|
+
cwd = Path.cwd()
|
|
90
|
+
has_cfg = (cwd / ".cursor" / "mcp.json").exists()
|
|
91
|
+
return HostCapabilityItem(
|
|
92
|
+
capability="mcp",
|
|
93
|
+
status=CapabilityStatus.RUNTIME_DETECTED if has_cfg else CapabilityStatus.UNKNOWN,
|
|
94
|
+
confidence=0.75,
|
|
95
|
+
details={"config_file": str(cwd / ".cursor" / "mcp.json"), "validated": "Partial"}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
99
|
+
return HostCapabilityItem(
|
|
100
|
+
capability="web",
|
|
101
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
102
|
+
confidence=0.80,
|
|
103
|
+
details={"provider": "Integrated web query", "validated": "Partial"}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
class WindsurfAdapter(HostAdapter):
|
|
107
|
+
def get_agent_name(self) -> str:
|
|
108
|
+
return "windsurf"
|
|
109
|
+
|
|
110
|
+
def get_skill_paths(self) -> List[Path]:
|
|
111
|
+
cwd = Path.cwd()
|
|
112
|
+
return [
|
|
113
|
+
cwd / ".windsurf" / "skills",
|
|
114
|
+
cwd / ".codeium" / "windsurf" / "memories"
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
118
|
+
cwd = Path.cwd()
|
|
119
|
+
has_cfg = (cwd / ".windsurf" / "mcp.json").exists()
|
|
120
|
+
return HostCapabilityItem(
|
|
121
|
+
capability="mcp",
|
|
122
|
+
status=CapabilityStatus.RUNTIME_DETECTED if has_cfg else CapabilityStatus.HOST_DECLARED,
|
|
123
|
+
confidence=0.75,
|
|
124
|
+
details={"validated": "Partial"}
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
128
|
+
return HostCapabilityItem(
|
|
129
|
+
capability="web",
|
|
130
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
131
|
+
confidence=0.80,
|
|
132
|
+
details={"provider": "Integrated web search", "validated": "Partial"}
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
class ClineAdapter(HostAdapter):
|
|
136
|
+
def get_agent_name(self) -> str:
|
|
137
|
+
return "cline"
|
|
138
|
+
|
|
139
|
+
def get_skill_paths(self) -> List[Path]:
|
|
140
|
+
cwd = Path.cwd()
|
|
141
|
+
return [
|
|
142
|
+
cwd / ".cline" / "skills"
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
146
|
+
return HostCapabilityItem(
|
|
147
|
+
capability="mcp",
|
|
148
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
149
|
+
confidence=0.85,
|
|
150
|
+
details={"provider": "Extension MCP manager", "validated": "Partial"}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
154
|
+
return HostCapabilityItem(
|
|
155
|
+
capability="web",
|
|
156
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
157
|
+
confidence=0.85,
|
|
158
|
+
details={"provider": "Browser tool", "validated": "Partial"}
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
class RooCodeAdapter(HostAdapter):
|
|
162
|
+
def get_agent_name(self) -> str:
|
|
163
|
+
return "roo_code"
|
|
164
|
+
|
|
165
|
+
def get_skill_paths(self) -> List[Path]:
|
|
166
|
+
cwd = Path.cwd()
|
|
167
|
+
return [
|
|
168
|
+
cwd / ".roo" / "skills"
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
172
|
+
return HostCapabilityItem(
|
|
173
|
+
capability="mcp",
|
|
174
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
175
|
+
confidence=0.85,
|
|
176
|
+
details={"provider": "Roo MCP client", "validated": "Partial"}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
180
|
+
return HostCapabilityItem(
|
|
181
|
+
capability="web",
|
|
182
|
+
status=CapabilityStatus.HOST_DECLARED,
|
|
183
|
+
confidence=0.80,
|
|
184
|
+
details={"provider": "Browser tool", "validated": "Partial"}
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
class CodexAdapter(HostAdapter):
|
|
188
|
+
def get_agent_name(self) -> str:
|
|
189
|
+
return "codex"
|
|
190
|
+
|
|
191
|
+
def get_skill_paths(self) -> List[Path]:
|
|
192
|
+
cwd = Path.cwd()
|
|
193
|
+
return [cwd / ".agents" / "skills", cwd / "skills"]
|
|
194
|
+
|
|
195
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
196
|
+
return HostCapabilityItem(
|
|
197
|
+
capability="mcp",
|
|
198
|
+
status=CapabilityStatus.UNAVAILABLE,
|
|
199
|
+
confidence=0.90,
|
|
200
|
+
details={"validated": "Host-Dependent"}
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
204
|
+
return HostCapabilityItem(
|
|
205
|
+
capability="web",
|
|
206
|
+
status=CapabilityStatus.UNAVAILABLE,
|
|
207
|
+
confidence=0.90,
|
|
208
|
+
details={"validated": "Host-Dependent"}
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
class OpenCodeAdapter(HostAdapter):
|
|
212
|
+
def get_agent_name(self) -> str:
|
|
213
|
+
return "opencode"
|
|
214
|
+
|
|
215
|
+
def get_skill_paths(self) -> List[Path]:
|
|
216
|
+
cwd = Path.cwd()
|
|
217
|
+
return [cwd / ".opencode" / "skills", cwd / "skills"]
|
|
218
|
+
|
|
219
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
220
|
+
return HostCapabilityItem(
|
|
221
|
+
capability="mcp",
|
|
222
|
+
status=CapabilityStatus.UNKNOWN,
|
|
223
|
+
confidence=0.70,
|
|
224
|
+
details={"validated": "Host-Dependent"}
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
228
|
+
return HostCapabilityItem(
|
|
229
|
+
capability="web",
|
|
230
|
+
status=CapabilityStatus.UNKNOWN,
|
|
231
|
+
confidence=0.70,
|
|
232
|
+
details={"validated": "Host-Dependent"}
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
class UnknownAgentAdapter(HostAdapter):
|
|
236
|
+
def __init__(self, raw_name: str):
|
|
237
|
+
self._raw_name = raw_name
|
|
238
|
+
|
|
239
|
+
def get_agent_name(self) -> str:
|
|
240
|
+
return f"unknown:{self._raw_name}"
|
|
241
|
+
|
|
242
|
+
def get_skill_paths(self) -> List[Path]:
|
|
243
|
+
cwd = Path.cwd()
|
|
244
|
+
return [cwd / "skills", cwd / ".skills"]
|
|
245
|
+
|
|
246
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
247
|
+
return HostCapabilityItem(
|
|
248
|
+
capability="mcp",
|
|
249
|
+
status=CapabilityStatus.UNKNOWN,
|
|
250
|
+
confidence=0.0,
|
|
251
|
+
details={"error": f"Agent '{self._raw_name}' is not recognized"}
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
255
|
+
return HostCapabilityItem(
|
|
256
|
+
capability="web",
|
|
257
|
+
status=CapabilityStatus.UNKNOWN,
|
|
258
|
+
confidence=0.0,
|
|
259
|
+
details={"error": f"Agent '{self._raw_name}' is not recognized"}
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
def get_agent_adapter(agent_name: str) -> HostAdapter:
|
|
263
|
+
canonical = agent_name.lower().strip()
|
|
264
|
+
adapters = {
|
|
265
|
+
"gemini_cli": GeminiCliAdapter(),
|
|
266
|
+
"gemini": GeminiCliAdapter(),
|
|
267
|
+
"antigravity": GeminiCliAdapter(),
|
|
268
|
+
"claude_code": ClaudeCodeAdapter(),
|
|
269
|
+
"claude": ClaudeCodeAdapter(),
|
|
270
|
+
"cursor": CursorAdapter(),
|
|
271
|
+
"windsurf": WindsurfAdapter(),
|
|
272
|
+
"cline": ClineAdapter(),
|
|
273
|
+
"roo_code": RooCodeAdapter(),
|
|
274
|
+
"roo": RooCodeAdapter(),
|
|
275
|
+
"codex": CodexAdapter(),
|
|
276
|
+
"opencode": OpenCodeAdapter()
|
|
277
|
+
}
|
|
278
|
+
# Fix critical bug: NEVER silently convert unknown agent to Gemini
|
|
279
|
+
if canonical not in adapters:
|
|
280
|
+
return UnknownAgentAdapter(agent_name)
|
|
281
|
+
return adapters[canonical]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright (c) 2026 Mahmoud Abdelhameid (Develper.net@gmail.com). All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Host Runtime Abstraction
|
|
6
|
+
========================
|
|
7
|
+
Provides abstract interface for discovering capabilities, filesystem layouts,
|
|
8
|
+
and execution boundaries across different AI agent hosts.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import platform
|
|
13
|
+
from abc import ABC, abstractmethod
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Dict, Any, List, Optional
|
|
16
|
+
from ..models import HostCapabilityItem, CapabilityStatus
|
|
17
|
+
|
|
18
|
+
def detect_host_runtime() -> str:
|
|
19
|
+
env = os.environ
|
|
20
|
+
if env.get("ANTIGRAVITY_AGENT") or any("antigravity" in k.lower() for k in env):
|
|
21
|
+
return "gemini_cli"
|
|
22
|
+
if env.get("CLAUDE_CODE_ENTRY") or ".claude" in env.get("CWD", ""):
|
|
23
|
+
return "claude_code"
|
|
24
|
+
if env.get("CURSOR_PROJECT_DIR") or env.get("CURSOR_TRACE"):
|
|
25
|
+
return "cursor"
|
|
26
|
+
if env.get("CLINE_ACTIVE"):
|
|
27
|
+
return "cline"
|
|
28
|
+
if env.get("ROO_CODE"):
|
|
29
|
+
return "roo_code"
|
|
30
|
+
return "generic_agent"
|
|
31
|
+
|
|
32
|
+
class HostAdapter(ABC):
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def get_agent_name(self) -> str:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def get_skill_paths(self) -> List[Path]:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def supports_mcp(self) -> HostCapabilityItem:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def supports_web(self) -> HostCapabilityItem:
|
|
48
|
+
pass
|