@agentlee5/agent-skills 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/.leeway/config.json +133 -0
- package/LICENSE +21 -0
- package/LeeWay-Standards/LICENSE +21 -0
- package/LeeWay-Standards/README.md +324 -0
- package/LeeWay-Standards/examples/NexusButton.tsx +90 -0
- package/LeeWay-Standards/examples/example-agent.js +89 -0
- package/LeeWay-Standards/package.json +61 -0
- package/LeeWay-Standards/schemas/leeway-config.schema.json +81 -0
- package/LeeWay-Standards/schemas/leeway-header.schema.json +63 -0
- package/LeeWay-Standards/src/agents/discovery/architecture-map-agent.js +134 -0
- package/LeeWay-Standards/src/agents/discovery/docs-agent.js +126 -0
- package/LeeWay-Standards/src/agents/discovery/explain-agent.js +95 -0
- package/LeeWay-Standards/src/agents/discovery/intent-registry-agent.js +119 -0
- package/LeeWay-Standards/src/agents/discovery/schema-agent.js +116 -0
- package/LeeWay-Standards/src/agents/discovery/sitemap-agent.js +88 -0
- package/LeeWay-Standards/src/agents/governance/align-agent.js +155 -0
- package/LeeWay-Standards/src/agents/governance/assess-agent.js +161 -0
- package/LeeWay-Standards/src/agents/governance/audit-agent.js +185 -0
- package/LeeWay-Standards/src/agents/integrity/circular-dependency-agent.js +88 -0
- package/LeeWay-Standards/src/agents/integrity/dependency-graph-agent.js +107 -0
- package/LeeWay-Standards/src/agents/integrity/duplicate-logic-agent.js +108 -0
- package/LeeWay-Standards/src/agents/integrity/import-agent.js +83 -0
- package/LeeWay-Standards/src/agents/integrity/module-policy-agent.js +94 -0
- package/LeeWay-Standards/src/agents/integrity/refactor-scan-agent.js +113 -0
- package/LeeWay-Standards/src/agents/integrity/syntax-agent.js +84 -0
- package/LeeWay-Standards/src/agents/mcp/endpoint-agent.js +106 -0
- package/LeeWay-Standards/src/agents/mcp/env-agent.js +111 -0
- package/LeeWay-Standards/src/agents/mcp/health-agent-lite.js +119 -0
- package/LeeWay-Standards/src/agents/mcp/manifest-agent.js +87 -0
- package/LeeWay-Standards/src/agents/mcp/port-agent.js +125 -0
- package/LeeWay-Standards/src/agents/mcp/process-agent.js +124 -0
- package/LeeWay-Standards/src/agents/mcp/runtime-agent.js +108 -0
- package/LeeWay-Standards/src/agents/mcp/transport-agent.js +78 -0
- package/LeeWay-Standards/src/agents/orchestration/doctor-agent.js +149 -0
- package/LeeWay-Standards/src/agents/orchestration/memory-agent-lite.js +125 -0
- package/LeeWay-Standards/src/agents/orchestration/router-agent.js +110 -0
- package/LeeWay-Standards/src/agents/security/permission-agent.js +98 -0
- package/LeeWay-Standards/src/agents/security/policy-agent.js +100 -0
- package/LeeWay-Standards/src/agents/security/privacy-agent.js +83 -0
- package/LeeWay-Standards/src/agents/security/prompt-security-agent.js +103 -0
- package/LeeWay-Standards/src/agents/security/secret-scan-agent.js +108 -0
- package/LeeWay-Standards/src/agents/security/tool-access-agent.js +105 -0
- package/LeeWay-Standards/src/agents/standards/authority-agent.js +114 -0
- package/LeeWay-Standards/src/agents/standards/discovery-pipeline-agent.js +91 -0
- package/LeeWay-Standards/src/agents/standards/header-agent.js +120 -0
- package/LeeWay-Standards/src/agents/standards/placement-agent.js +96 -0
- package/LeeWay-Standards/src/agents/standards/region-agent.js +99 -0
- package/LeeWay-Standards/src/agents/standards/registry-agent.js +153 -0
- package/LeeWay-Standards/src/agents/standards/tag-agent.js +111 -0
- package/LeeWay-Standards/src/cli/leeway.js +225 -0
- package/LeeWay-Standards/src/core/compliance-scorer.js +168 -0
- package/LeeWay-Standards/src/core/compliance-scorer.test.js +121 -0
- package/LeeWay-Standards/src/core/header-parser.js +207 -0
- package/LeeWay-Standards/src/core/header-parser.test.js +198 -0
- package/LeeWay-Standards/src/core/region-classifier.js +137 -0
- package/LeeWay-Standards/src/core/region-classifier.test.js +100 -0
- package/LeeWay-Standards/src/core/tag-validator.js +139 -0
- package/LeeWay-Standards/src/core/tag-validator.test.js +109 -0
- package/LeeWay-Standards/src/index.js +83 -0
- package/README.md +217 -0
- package/agent-config.yaml +456 -0
- package/agentbage.png.png +0 -0
- package/bin/leeway-skills-badge.js +52 -0
- package/bin/leeway-skills-mcp.js +48 -0
- package/bin/leeway-skills.js +160 -0
- package/bin/leeway-standards.js +49 -0
- package/config/.skillsignore +63 -0
- package/config/skills-config.json +70 -0
- package/documents/AGENT_LEARNING_REFERENCE.md +329 -0
- package/documents/AGENT_LEE_INTEGRATION.md +534 -0
- package/documents/COMPLETE_SYSTEM_OVERVIEW.md +502 -0
- package/documents/COMPREHENSIVE_SKILL_INTEGRATION_PLAN.md +644 -0
- package/documents/DIRECTORY_MAP.md +323 -0
- package/documents/EXTENDING.md +514 -0
- package/documents/FILE_DIRECTORY_GUIDE.md +427 -0
- package/documents/LEEWAY_BADGE_INTEGRATION.md +76 -0
- package/documents/LEEWAY_IMPLEMENTATION_SUMMARY.md +384 -0
- package/documents/LEEWAY_INTEGRATION_GUIDE.md +414 -0
- package/documents/LEEWAY_NPM_SDK.md +66 -0
- package/documents/LEEWAY_QUICK_START.md +288 -0
- package/documents/LEEWAY_SKILLS_BRANDING.md +375 -0
- package/documents/LEEWAY_SKILLS_MCP_SUMMARY.md +593 -0
- package/documents/LEEWAY_STANDARDS_COMPLIANCE.md +361 -0
- package/documents/LEEWAY_UNIFIED_ARCHITECTURE.md +473 -0
- package/documents/LEEWAY_WORKFLOWS_QUICK_REFERENCE.md +307 -0
- package/documents/LEEWAY_WORKFLOWS_STRATEGIC_PLAN.md +515 -0
- package/documents/LIFELONG_LEARNING_LAYER.md +478 -0
- package/documents/MCP_ARCHITECTURE.md +683 -0
- package/documents/QUICK_REFERENCE.md +301 -0
- package/documents/SETUP.md +325 -0
- package/documents/SETUP_SUMMARY.md +413 -0
- package/documents/SKILL_ACQUISITION_EXECUTIVE_SUMMARY.md +373 -0
- package/documents/SKILL_ACQUISITION_IMPLEMENTATION.md +692 -0
- package/documents/SKILL_ACQUISITION_MANIFEST.md +404 -0
- package/documents/SKILL_ACQUISITION_QUICK_REFERENCE.md +349 -0
- package/documents/SKILL_WORKFLOW_COMPOSITION_MATRIX.md +537 -0
- package/documents/STRUCTURE.md +382 -0
- package/documents/SYSTEM_TRANSFORMATION_SUMMARY.md +560 -0
- package/documents/USAGE.md +390 -0
- package/documents/WORKFLOW_ACQUISITION_MANIFEST.md +576 -0
- package/documents/aiskills.txt +460 -0
- package/mcp-server/README.md +697 -0
- package/mcp-server/dist/badge-proof.d.ts +66 -0
- package/mcp-server/dist/badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/badge-proof.js +324 -0
- package/mcp-server/dist/badge-proof.js.map +1 -0
- package/mcp-server/dist/index.d.ts +64 -0
- package/mcp-server/dist/index.d.ts.map +1 -0
- package/mcp-server/dist/index.js +263 -0
- package/mcp-server/dist/index.js.map +1 -0
- package/mcp-server/dist/install-badge-proof.d.ts +3 -0
- package/mcp-server/dist/install-badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/install-badge-proof.js +109 -0
- package/mcp-server/dist/install-badge-proof.js.map +1 -0
- package/mcp-server/package.json +43 -0
- package/mcp-server/src/badge-proof.ts +469 -0
- package/mcp-server/src/index.ts +355 -0
- package/mcp-server/src/install-badge-proof.ts +132 -0
- package/mcp-server/tsconfig.json +22 -0
- package/package.json +84 -0
- package/scripts/init-leeway.js +217 -0
- package/scripts/leeway-agents/compliance-monitor.js +374 -0
- package/scripts/leeway-agents/header-injector.js +321 -0
- package/scripts/skill-integration-toolkit.py +319 -0
- package/scripts/skills-registry.json +1117 -0
- package/scripts/sync-skills.ps1 +275 -0
- package/scripts/verify-leeway-setup.js +249 -0
- package/scripts/workflow-integration-toolkit.py +522 -0
- package/sdk/application-installer.js +92 -0
- package/sdk/index.js +43 -0
- package/sdk/paths.js +167 -0
- package/skills/agent-autonomy/autonomous-conductor/SKILL.md +206 -0
- package/skills/agent-autonomy/full-stack-delivery/SKILL.md +206 -0
- package/skills/agent-orchestration/multi-agent-orchestration/SKILL.md +68 -0
- package/skills/agent-patterns/agent-design-patterns/SKILL.md +70 -0
- package/skills/ai-ml/llm-prompting/SKILL.md +71 -0
- package/skills/ai-ml/ml-model-development/SKILL.md +67 -0
- package/skills/ai-ml/multimodal-systems/SKILL.md +71 -0
- package/skills/ai-ml/retrieval-generation-fine-tuning/SKILL.md +71 -0
- package/skills/architecture/system-design/SKILL.md +67 -0
- package/skills/code-analysis/refactoring/SKILL.md +64 -0
- package/skills/code-analysis/security-vulnerability-scanning/SKILL.md +71 -0
- package/skills/code-analysis/static-analysis/SKILL.md +64 -0
- package/skills/code-generation/full-stack-application/SKILL.md +70 -0
- package/skills/code-generation/microservices-architecture/SKILL.md +71 -0
- package/skills/code-generation/python-codegen/SKILL.md +64 -0
- package/skills/code-generation/typescript-codegen/SKILL.md +64 -0
- package/skills/data-analysis/advanced-analytics/SKILL.md +71 -0
- package/skills/data-analysis/pandas-analysis/SKILL.md +66 -0
- package/skills/database-design/database-design-optimization/SKILL.md +70 -0
- package/skills/debugging/javascript-debugging/SKILL.md +67 -0
- package/skills/debugging/python-debugging/SKILL.md +67 -0
- package/skills/devops/dockerfile-creation/SKILL.md +64 -0
- package/skills/devops/kubernetes-deployment/SKILL.md +65 -0
- package/skills/documentation/api-documentation/SKILL.md +67 -0
- package/skills/error-handling/resilience-patterns/SKILL.md +70 -0
- package/skills/git-workflow/git-collaboration/SKILL.md +67 -0
- package/skills/infrastructure/cicd-pipelines/SKILL.md +70 -0
- package/skills/infrastructure/infrastructure-as-code/SKILL.md +70 -0
- package/skills/observability/monitoring-and-observability/SKILL.md +70 -0
- package/skills/performance-optimization/performance-engineering/SKILL.md +70 -0
- package/skills/prompt-optimization/prompt-engineering-advanced/SKILL.md +70 -0
- package/skills/quality-assurance/deployment-validator/SKILL.md +382 -0
- package/skills/quality-assurance/web-security-sweep/SKILL.md +320 -0
- package/skills/rag-knowledge/rag-systems/SKILL.md +70 -0
- package/skills/research/knowledge-synthesis/SKILL.md +71 -0
- package/skills/security/authentication-authorization/SKILL.md +71 -0
- package/skills/security/code-security/SKILL.md +66 -0
- package/skills/security/secure-architecture/SKILL.md +71 -0
- package/skills/self-optimization/dev-loop-optimizer/SKILL.md +344 -0
- package/skills/self-optimization/memory-learning/SKILL.md +335 -0
- package/skills/self-optimization/runtime-self-profiling/SKILL.md +250 -0
- package/skills/testing/advanced-testing-strategies/SKILL.md +71 -0
- package/skills/testing/integration-testing/SKILL.md +66 -0
- package/skills/testing/load-testing-capacity/SKILL.md +71 -0
- package/skills/testing/unit-testing/SKILL.md +66 -0
- package/skills/tool-integration/custom-tool-creation/SKILL.md +70 -0
- package/skills/web-development/advanced-frontend-patterns/SKILL.md +71 -0
- package/skills/web-development/api-design/SKILL.md +71 -0
- package/skills/web-development/css-styling/SKILL.md +67 -0
- package/skills/web-development/react-development/SKILL.md +79 -0
- package/skills/workflow-composition/workflow-orchestration/SKILL.md +70 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Leeway Workflow Integration Toolkit
|
|
4
|
+
|
|
5
|
+
Normalizes workflow definitions from multiple frameworks (GitHub Agentics, CrewAI, AutoGen, etc.)
|
|
6
|
+
into Leeway WORKFLOW.md standard format, builds executable registry, and enables direct invocation.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 workflow-integration-toolkit.py audit-repos
|
|
10
|
+
python3 workflow-integration-toolkit.py normalize [source-path] [category]
|
|
11
|
+
python3 workflow-integration-toolkit.py build-registry
|
|
12
|
+
python3 workflow-integration-toolkit.py execute [workflow-id] [inputs]
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import json
|
|
17
|
+
import yaml
|
|
18
|
+
import re
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Dict, List, Optional, Tuple
|
|
21
|
+
from datetime import datetime
|
|
22
|
+
from dataclasses import dataclass, asdict
|
|
23
|
+
import subprocess
|
|
24
|
+
import sys
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class WorkflowMetadata:
|
|
29
|
+
"""Leeway WORKFLOW.md standard metadata"""
|
|
30
|
+
id: str
|
|
31
|
+
name: str
|
|
32
|
+
category: str
|
|
33
|
+
subtype: str # sequential | hierarchical | event-driven | fsm | dag | crew
|
|
34
|
+
skill_bundle: List[str]
|
|
35
|
+
composition_pattern: str # CrewAI | LangGraph | AutoGen | GitHub Agentics | SuperAGI
|
|
36
|
+
trigger: str # schedule | event | manual | api
|
|
37
|
+
version: str
|
|
38
|
+
source: Dict # {repo, url, acquired_date, original_path}
|
|
39
|
+
compliance: Dict # {governance, required_skills_present, skill_coverage}
|
|
40
|
+
estimated_runtime: str
|
|
41
|
+
success_metrics: List[Dict]
|
|
42
|
+
execution_code: Optional[str] = None
|
|
43
|
+
description: Optional[str] = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class WorkflowNormalizer:
|
|
47
|
+
"""Normalizes workflow definitions from different frameworks to Leeway standard"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, workflows_root: str):
|
|
50
|
+
self.workflows_root = Path(workflows_root)
|
|
51
|
+
self.workflows_root.mkdir(exist_ok=True, parents=True)
|
|
52
|
+
self.registry = {}
|
|
53
|
+
self.dedup_index = {}
|
|
54
|
+
|
|
55
|
+
def audit_source_repos(self, sources_root: str) -> Dict:
|
|
56
|
+
"""
|
|
57
|
+
Audit all source workflow repositories and catalog workflows.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
{
|
|
61
|
+
"github_agentics": {count, workflows: [...]},
|
|
62
|
+
"crewai": {...},
|
|
63
|
+
...
|
|
64
|
+
"total": number
|
|
65
|
+
}
|
|
66
|
+
"""
|
|
67
|
+
sources_path = Path(sources_root)
|
|
68
|
+
audit_results = {"total": 0}
|
|
69
|
+
|
|
70
|
+
# GitHub Agentics audit
|
|
71
|
+
agentics_path = sources_path / "agentics" / "docs"
|
|
72
|
+
if agentics_path.exists():
|
|
73
|
+
agentics_workflows = self._audit_github_agentics(agentics_path)
|
|
74
|
+
audit_results["github_agentics"] = {
|
|
75
|
+
"count": len(agentics_workflows),
|
|
76
|
+
"workflows": agentics_workflows
|
|
77
|
+
}
|
|
78
|
+
audit_results["total"] += len(agentics_workflows)
|
|
79
|
+
|
|
80
|
+
# CrewAI audit
|
|
81
|
+
crewai_path = sources_path / "crewai" / "examples"
|
|
82
|
+
if crewai_path.exists():
|
|
83
|
+
crewai_workflows = self._audit_crewai(crewai_path)
|
|
84
|
+
audit_results["crewai"] = {
|
|
85
|
+
"count": len(crewai_workflows),
|
|
86
|
+
"workflows": crewai_workflows
|
|
87
|
+
}
|
|
88
|
+
audit_results["total"] += len(crewai_workflows)
|
|
89
|
+
|
|
90
|
+
# AutoGen audit
|
|
91
|
+
autogen_path = sources_path / "autogen" / "python"
|
|
92
|
+
if autogen_path.exists():
|
|
93
|
+
autogen_workflows = self._audit_autogen(autogen_path)
|
|
94
|
+
audit_results["autogen"] = {
|
|
95
|
+
"count": len(autogen_workflows),
|
|
96
|
+
"workflows": autogen_workflows
|
|
97
|
+
}
|
|
98
|
+
audit_results["total"] += len(autogen_workflows)
|
|
99
|
+
|
|
100
|
+
# LangGraph audit
|
|
101
|
+
langgraph_path = sources_path / "langgraph" / "examples"
|
|
102
|
+
if langgraph_path.exists():
|
|
103
|
+
langgraph_workflows = self._audit_langgraph(langgraph_path)
|
|
104
|
+
audit_results["langgraph"] = {
|
|
105
|
+
"count": len(langgraph_workflows),
|
|
106
|
+
"workflows": langgraph_workflows
|
|
107
|
+
}
|
|
108
|
+
audit_results["total"] += len(langgraph_workflows)
|
|
109
|
+
|
|
110
|
+
# SuperAGI audit
|
|
111
|
+
superagi_path = sources_path / "SuperAGI"
|
|
112
|
+
if superagi_path.exists():
|
|
113
|
+
superagi_workflows = self._audit_superagi(superagi_path)
|
|
114
|
+
audit_results["superagi"] = {
|
|
115
|
+
"count": len(superagi_workflows),
|
|
116
|
+
"workflows": superagi_workflows
|
|
117
|
+
}
|
|
118
|
+
audit_results["total"] += len(superagi_workflows)
|
|
119
|
+
|
|
120
|
+
return audit_results
|
|
121
|
+
|
|
122
|
+
def _audit_github_agentics(self, docs_path: Path) -> List[str]:
|
|
123
|
+
"""Extract GitHub Agentics workflows (markdown files in docs/)"""
|
|
124
|
+
workflows = []
|
|
125
|
+
for md_file in docs_path.glob("*.md"):
|
|
126
|
+
if md_file.stem not in ["README", "index"]:
|
|
127
|
+
workflows.append(md_file.stem)
|
|
128
|
+
return sorted(workflows)
|
|
129
|
+
|
|
130
|
+
def _audit_crewai(self, examples_path: Path) -> List[str]:
|
|
131
|
+
"""Extract CrewAI examples (directories in examples/)"""
|
|
132
|
+
workflows = []
|
|
133
|
+
for d in examples_path.iterdir():
|
|
134
|
+
if d.is_dir() and (d / "crew.py").exists():
|
|
135
|
+
workflows.append(d.name)
|
|
136
|
+
return sorted(workflows)
|
|
137
|
+
|
|
138
|
+
def _audit_autogen(self, python_path: Path) -> List[str]:
|
|
139
|
+
"""Extract AutoGen workflow examples"""
|
|
140
|
+
workflows = []
|
|
141
|
+
for root, dirs, files in os.walk(python_path):
|
|
142
|
+
for f in files:
|
|
143
|
+
if f.endswith("_agent.py") or f == "agent.py":
|
|
144
|
+
workflows.append(Path(root).relative_to(python_path).name)
|
|
145
|
+
return sorted(set(workflows))
|
|
146
|
+
|
|
147
|
+
def _audit_langgraph(self, examples_path: Path) -> List[str]:
|
|
148
|
+
"""Extract LangGraph examples"""
|
|
149
|
+
workflows = []
|
|
150
|
+
for py_file in examples_path.rglob("*.py"):
|
|
151
|
+
if "graph" in py_file.name.lower():
|
|
152
|
+
workflows.append(py_file.stem)
|
|
153
|
+
return sorted(set(workflows))
|
|
154
|
+
|
|
155
|
+
def _audit_superagi(self, root_path: Path) -> List[str]:
|
|
156
|
+
"""Extract SuperAGI workflows from superagi/workflows"""
|
|
157
|
+
workflows = []
|
|
158
|
+
workflows_dir = root_path / "superagi" / "workflows"
|
|
159
|
+
if workflows_dir.exists():
|
|
160
|
+
for d in workflows_dir.iterdir():
|
|
161
|
+
if d.is_dir() and (d / "workflow.yaml").exists():
|
|
162
|
+
workflows.append(d.name)
|
|
163
|
+
return sorted(workflows)
|
|
164
|
+
|
|
165
|
+
def normalize_github_agentics(self, md_path: Path, category: str, workflow_id: str) -> WorkflowMetadata:
|
|
166
|
+
"""
|
|
167
|
+
Normalize a GitHub Agentics workflow (markdown) to WORKFLOW.md format
|
|
168
|
+
|
|
169
|
+
Example GitHub Agentics workflow structure:
|
|
170
|
+
---
|
|
171
|
+
# Issue Triage
|
|
172
|
+
|
|
173
|
+
[Description]
|
|
174
|
+
...
|
|
175
|
+
"""
|
|
176
|
+
with open(md_path) as f:
|
|
177
|
+
content = f.read()
|
|
178
|
+
|
|
179
|
+
# Parse title
|
|
180
|
+
title_match = re.search(r"^# (.+)$", content, re.MULTILINE)
|
|
181
|
+
name = title_match.group(1) if title_match else md_path.stem
|
|
182
|
+
|
|
183
|
+
# Extract trigger type from description
|
|
184
|
+
trigger = "manual"
|
|
185
|
+
if "schedule" in content.lower(): trigger = "schedule"
|
|
186
|
+
if "event" in content.lower() or "GitHub event" in content: trigger = "event"
|
|
187
|
+
if "trigger" in content.lower() and "api" in content.lower(): trigger = "api"
|
|
188
|
+
|
|
189
|
+
# Infer skill bundle from content
|
|
190
|
+
skills = self._extract_mentioned_skills(content)
|
|
191
|
+
|
|
192
|
+
metadata = WorkflowMetadata(
|
|
193
|
+
id=workflow_id or f"workflow.{md_path.stem}",
|
|
194
|
+
name=name,
|
|
195
|
+
category=category,
|
|
196
|
+
subtype="event-driven", # GitHub Agentics is primarily event-driven
|
|
197
|
+
skill_bundle=skills,
|
|
198
|
+
composition_pattern="GitHub Agentics",
|
|
199
|
+
trigger=trigger,
|
|
200
|
+
version="1.0.0",
|
|
201
|
+
source={
|
|
202
|
+
"repo": "githubnext/agentics",
|
|
203
|
+
"url": f"https://github.com/githubnext/agentics/blob/main/docs/{md_path.name}",
|
|
204
|
+
"acquired_date": datetime.now().isoformat(),
|
|
205
|
+
"original_path": str(md_path)
|
|
206
|
+
},
|
|
207
|
+
compliance={
|
|
208
|
+
"governance": "leeway-standards-1.0.0",
|
|
209
|
+
"required_skills_present": len(skills) > 0,
|
|
210
|
+
"skill_coverage": min(100, len(skills) * 20) # Estimate
|
|
211
|
+
},
|
|
212
|
+
estimated_runtime="5min - 60min",
|
|
213
|
+
success_metrics=[
|
|
214
|
+
{"metric_name": "Workflow completion", "target": "> 95%"},
|
|
215
|
+
{"metric_name": "Processing time", "target": "< estimated runtime"}
|
|
216
|
+
],
|
|
217
|
+
description=self._extract_first_paragraph(content)
|
|
218
|
+
)
|
|
219
|
+
return metadata
|
|
220
|
+
|
|
221
|
+
def normalize_crewai(self, crew_py_path: Path, category: str, workflow_id: str) -> WorkflowMetadata:
|
|
222
|
+
"""
|
|
223
|
+
Normalize a CrewAI example (Python) to WORKFLOW.md format
|
|
224
|
+
|
|
225
|
+
Reads crew.py and config/agents.yaml, config/tasks.yaml
|
|
226
|
+
"""
|
|
227
|
+
with open(crew_py_path) as f:
|
|
228
|
+
crew_code = f.read()
|
|
229
|
+
|
|
230
|
+
# Infer workflow name and type
|
|
231
|
+
name = Path(crew_py_path).parent.name.replace("_", " ").title()
|
|
232
|
+
|
|
233
|
+
# Determine if Crew or Flow
|
|
234
|
+
is_flow = "Flow" in crew_code
|
|
235
|
+
subtype = "hierarchical" if "hierarchical" in crew_code.lower() else "sequential"
|
|
236
|
+
if is_flow:
|
|
237
|
+
subtype = "event-driven" if "@listen" in crew_code or "@router" in crew_code else "sequential"
|
|
238
|
+
|
|
239
|
+
# Extract skill requirements from config
|
|
240
|
+
config_dir = Path(crew_py_path).parent / "config"
|
|
241
|
+
agents = []
|
|
242
|
+
if (config_dir / "agents.yaml").exists():
|
|
243
|
+
with open(config_dir / "agents.yaml") as f:
|
|
244
|
+
agents_data = yaml.safe_load(f)
|
|
245
|
+
if agents_data:
|
|
246
|
+
agents = list(agents_data.keys())
|
|
247
|
+
|
|
248
|
+
# Infer skills from agent roles
|
|
249
|
+
skills = self._extract_skills_from_crew_roles(agents, config_dir)
|
|
250
|
+
|
|
251
|
+
metadata = WorkflowMetadata(
|
|
252
|
+
id=workflow_id or f"workflow.{Path(crew_py_path).parent.name}",
|
|
253
|
+
name=name,
|
|
254
|
+
category=category,
|
|
255
|
+
subtype=subtype,
|
|
256
|
+
skill_bundle=skills,
|
|
257
|
+
composition_pattern="CrewAI",
|
|
258
|
+
trigger="manual", # CrewAI examples are typically manual
|
|
259
|
+
version="1.0.0",
|
|
260
|
+
source={
|
|
261
|
+
"repo": "crewai",
|
|
262
|
+
"url": f"https://github.com/crewai/crewai-examples/tree/main/{Path(crew_py_path).parent.name}",
|
|
263
|
+
"acquired_date": datetime.now().isoformat(),
|
|
264
|
+
"original_path": str(crew_py_path)
|
|
265
|
+
},
|
|
266
|
+
compliance={
|
|
267
|
+
"governance": "leeway-standards-1.0.0",
|
|
268
|
+
"required_skills_present": len(skills) > 0,
|
|
269
|
+
"skill_coverage": min(100, len(agents) * 20)
|
|
270
|
+
},
|
|
271
|
+
estimated_runtime="1min - 15min",
|
|
272
|
+
success_metrics=[
|
|
273
|
+
{"metric_name": "Task completion", "target": "> 90%"},
|
|
274
|
+
{"metric_name": "Agent coordination", "target": "100%"}
|
|
275
|
+
],
|
|
276
|
+
execution_code=crew_code[:500] # First 500 chars for reference
|
|
277
|
+
)
|
|
278
|
+
return metadata
|
|
279
|
+
|
|
280
|
+
def _extract_mentioned_skills(self, content: str) -> List[str]:
|
|
281
|
+
"""Extract skill names mentioned in content"""
|
|
282
|
+
# Simple heuristic: look for "skill-*" patterns, agent roles, etc.
|
|
283
|
+
skills = []
|
|
284
|
+
skill_patterns = [
|
|
285
|
+
r"(?:skill|ability|capability)[\s-]*(?::\s*)?(?:of\s+)?([a-z\-]+)",
|
|
286
|
+
r"(?:expert|specialist)\s+(?:in\s+)?([a-z\-]+)",
|
|
287
|
+
r"(?:reviews?|analyzes?|generates?|creates?)\s+([a-z\-]+)",
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
for pattern in skill_patterns:
|
|
291
|
+
matches = re.findall(pattern, content.lower())
|
|
292
|
+
skills.extend(matches)
|
|
293
|
+
|
|
294
|
+
return sorted(set(skills))[:10] # Top 10
|
|
295
|
+
|
|
296
|
+
def _extract_skills_from_crew_roles(self, agents: List[str], config_dir: Path) -> List[str]:
|
|
297
|
+
"""Extract skills from CrewAI agent roles"""
|
|
298
|
+
skills = []
|
|
299
|
+
agents_yaml_path = config_dir / "agents.yaml"
|
|
300
|
+
|
|
301
|
+
if agents_yaml_path.exists():
|
|
302
|
+
with open(agents_yaml_path) as f:
|
|
303
|
+
agents_data = yaml.safe_load(f)
|
|
304
|
+
if agents_data:
|
|
305
|
+
for agent_name, agent_config in agents_data.items():
|
|
306
|
+
if isinstance(agent_config, dict):
|
|
307
|
+
role = agent_config.get("role", "")
|
|
308
|
+
goal = agent_config.get("goal", "")
|
|
309
|
+
# Extract keywords as pseudo-skills
|
|
310
|
+
for word in (role + " " + goal).split():
|
|
311
|
+
if len(word) > 3 and word not in ["the", "and", "for", "with"]:
|
|
312
|
+
skills.append(word.lower().strip(".,;:"))
|
|
313
|
+
|
|
314
|
+
return sorted(set(skills))[:10]
|
|
315
|
+
|
|
316
|
+
def _extract_first_paragraph(self, content: str) -> str:
|
|
317
|
+
"""Extract first paragraph of content"""
|
|
318
|
+
lines = content.split("\n")
|
|
319
|
+
para = []
|
|
320
|
+
for line in lines:
|
|
321
|
+
if line.startswith("#"): continue
|
|
322
|
+
if line.strip() == "" and para: break
|
|
323
|
+
if line.strip(): para.append(line.strip())
|
|
324
|
+
return " ".join(para)[:200]
|
|
325
|
+
|
|
326
|
+
def write_workflow_file(self, metadata: WorkflowMetadata, output_dir: Path) -> Path:
|
|
327
|
+
"""
|
|
328
|
+
Write normalized workflow to WORKFLOW.md file in category/workflow_id/ directory
|
|
329
|
+
"""
|
|
330
|
+
workflow_dir = output_dir / metadata.category / metadata.id.replace("workflow.", "")
|
|
331
|
+
workflow_dir.mkdir(parents=True, exist_ok=True)
|
|
332
|
+
|
|
333
|
+
workflow_md = workflow_dir / "WORKFLOW.md"
|
|
334
|
+
|
|
335
|
+
# Generate WORKFLOW.md content
|
|
336
|
+
content = f"""---
|
|
337
|
+
id: {metadata.id}
|
|
338
|
+
name: "{metadata.name}"
|
|
339
|
+
category: {metadata.category}
|
|
340
|
+
subtype: {metadata.subtype}
|
|
341
|
+
skill_bundle: {json.dumps(metadata.skill_bundle)}
|
|
342
|
+
composition_pattern: {metadata.composition_pattern}
|
|
343
|
+
trigger: {metadata.trigger}
|
|
344
|
+
version: "{metadata.version}"
|
|
345
|
+
source:
|
|
346
|
+
repo: {metadata.source['repo']}
|
|
347
|
+
url: {metadata.source['url']}
|
|
348
|
+
acquired_date: {metadata.source['acquired_date']}
|
|
349
|
+
compliance:
|
|
350
|
+
governance: {metadata.compliance['governance']}
|
|
351
|
+
required_skills_present: {str(metadata.compliance['required_skills_present']).lower()}
|
|
352
|
+
skill_coverage: {metadata.compliance['skill_coverage']}
|
|
353
|
+
estimated_runtime: "{metadata.estimated_runtime}"
|
|
354
|
+
success_metrics:
|
|
355
|
+
{chr(10).join(f" - {json.dumps(m)}" for m in metadata.success_metrics)}
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
# {metadata.name}
|
|
359
|
+
|
|
360
|
+
## Purpose
|
|
361
|
+
|
|
362
|
+
{metadata.description or "[Generated from source workflow]"}
|
|
363
|
+
|
|
364
|
+
## Skill Bundle
|
|
365
|
+
|
|
366
|
+
Required skills (auto-loaded when workflow is invoked):
|
|
367
|
+
|
|
368
|
+
{chr(10).join(f"- `{skill}`: [Loaded from skill registry]" for skill in metadata.skill_bundle)}
|
|
369
|
+
|
|
370
|
+
## Execution Pattern
|
|
371
|
+
|
|
372
|
+
**Framework**: {metadata.composition_pattern}
|
|
373
|
+
**Subtype**: {metadata.subtype}
|
|
374
|
+
**Trigger**: {metadata.trigger}
|
|
375
|
+
|
|
376
|
+
## Orchestration
|
|
377
|
+
|
|
378
|
+
This workflow is defined in the {metadata.composition_pattern} framework.
|
|
379
|
+
See source for full implementation:
|
|
380
|
+
|
|
381
|
+
**Source**: `{metadata.source['original_path']}`
|
|
382
|
+
|
|
383
|
+
## Success Criteria
|
|
384
|
+
|
|
385
|
+
{chr(10).join(f"- {m['metric_name']}: {m['target']}" for m in metadata.success_metrics)}
|
|
386
|
+
|
|
387
|
+
## Execution
|
|
388
|
+
|
|
389
|
+
Once generated, this workflow can be executed via Agent Lee MCP:
|
|
390
|
+
```
|
|
391
|
+
agent_lee.execute_workflow(workflow_id="{metadata.id}", inputs={{...}})
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Related Skills
|
|
395
|
+
|
|
396
|
+
This workflow depends on:
|
|
397
|
+
{chr(10).join(f"- `{skill}`" for skill in metadata.skill_bundle)}
|
|
398
|
+
|
|
399
|
+
To see available skills, check the Leeway Skills registry.
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
**Acquired**: {metadata.source['acquired_date']}
|
|
404
|
+
**Framework**: {metadata.composition_pattern}
|
|
405
|
+
**Status**: Ready for execution
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
with open(workflow_md, 'w') as f:
|
|
409
|
+
f.write(content)
|
|
410
|
+
|
|
411
|
+
return workflow_md
|
|
412
|
+
|
|
413
|
+
def build_workflow_registry(self, workflows_root: Path) -> Dict:
|
|
414
|
+
"""
|
|
415
|
+
Walk all workflows/ and build a comprehensive registry
|
|
416
|
+
"""
|
|
417
|
+
registry = {
|
|
418
|
+
"version": "1.0.0",
|
|
419
|
+
"generated": datetime.now().isoformat(),
|
|
420
|
+
"total_workflows": 0,
|
|
421
|
+
"by_category": {},
|
|
422
|
+
"workflows": {}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
for category_dir in (workflows_root / "workflows").iterdir():
|
|
426
|
+
if not category_dir.is_dir(): continue
|
|
427
|
+
|
|
428
|
+
category = category_dir.name
|
|
429
|
+
registry["by_category"][category] = []
|
|
430
|
+
|
|
431
|
+
for workflow_dir in category_dir.iterdir():
|
|
432
|
+
if not workflow_dir.is_dir(): continue
|
|
433
|
+
|
|
434
|
+
workflow_md = workflow_dir / "WORKFLOW.md"
|
|
435
|
+
if not workflow_md.exists(): continue
|
|
436
|
+
|
|
437
|
+
# Parse WORKFLOW.md frontmatter
|
|
438
|
+
with open(workflow_md) as f:
|
|
439
|
+
content = f.read()
|
|
440
|
+
frontmatter = re.search(r"^---\n(.*?)\n---", content, re.DOTALL)
|
|
441
|
+
if frontmatter:
|
|
442
|
+
try:
|
|
443
|
+
metadata = yaml.safe_load(frontmatter.group(1))
|
|
444
|
+
workflow_id = metadata.get("id")
|
|
445
|
+
registry["workflows"][workflow_id] = {
|
|
446
|
+
"name": metadata.get("name"),
|
|
447
|
+
"category": category,
|
|
448
|
+
"skills": metadata.get("skill_bundle", []),
|
|
449
|
+
"framework": metadata.get("composition_pattern"),
|
|
450
|
+
"path": str(workflow_md)
|
|
451
|
+
}
|
|
452
|
+
registry["by_category"][category].append(workflow_id)
|
|
453
|
+
registry["total_workflows"] += 1
|
|
454
|
+
except:
|
|
455
|
+
pass
|
|
456
|
+
|
|
457
|
+
return registry
|
|
458
|
+
|
|
459
|
+
def save_registry(self, registry: Dict, output_path: str):
|
|
460
|
+
"""Save workflow registry to JSON"""
|
|
461
|
+
with open(output_path, 'w') as f:
|
|
462
|
+
json.dump(registry, f, indent=2)
|
|
463
|
+
|
|
464
|
+
def generate_integration_report(self, audit: Dict, registry: Dict) -> str:
|
|
465
|
+
"""Generate human-readable report of acquisition status"""
|
|
466
|
+
report = f"""
|
|
467
|
+
# Leeway Workflow Acquisition Report
|
|
468
|
+
|
|
469
|
+
**Generated**: {datetime.now().isoformat()}
|
|
470
|
+
|
|
471
|
+
## Audit Results
|
|
472
|
+
|
|
473
|
+
Total workflows discovered: {audit.get('total', 0)}
|
|
474
|
+
|
|
475
|
+
Per-source breakdown:
|
|
476
|
+
"""
|
|
477
|
+
for source, data in audit.items():
|
|
478
|
+
if source != 'total' and isinstance(data, dict):
|
|
479
|
+
report += f"- **{source.replace('_', ' ').title()}**: {data.get('count', 0)} workflows\n"
|
|
480
|
+
|
|
481
|
+
report += f"""
|
|
482
|
+
## Registry Status
|
|
483
|
+
|
|
484
|
+
Total workflows indexed: {registry.get('total_workflows', 0)}
|
|
485
|
+
|
|
486
|
+
By category:
|
|
487
|
+
"""
|
|
488
|
+
for category, workflows in registry.get('by_category', {}).items():
|
|
489
|
+
report += f"- **{category}**: {len(workflows)} workflows\n"
|
|
490
|
+
|
|
491
|
+
return report
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def main():
|
|
495
|
+
"""CLI entry point"""
|
|
496
|
+
toolkit = WorkflowNormalizer("c:/Tools/AIskills/workflows")
|
|
497
|
+
|
|
498
|
+
if len(sys.argv) < 2:
|
|
499
|
+
print(__doc__)
|
|
500
|
+
return
|
|
501
|
+
|
|
502
|
+
command = sys.argv[1]
|
|
503
|
+
|
|
504
|
+
if command == "audit-repos":
|
|
505
|
+
print("Auditing workflow source repositories...")
|
|
506
|
+
audit = toolkit.audit_source_repos("c:/Tools/AIskills/sources-workflows")
|
|
507
|
+
print(json.dumps(audit, indent=2))
|
|
508
|
+
|
|
509
|
+
elif command == "build-registry":
|
|
510
|
+
print("Building workflow registry...")
|
|
511
|
+
registry = toolkit.build_workflow_registry(Path("c:/Tools/AIskills"))
|
|
512
|
+
toolkit.save_registry(registry, "workflow-registry.json")
|
|
513
|
+
report = toolkit.generate_integration_report({}, registry)
|
|
514
|
+
print(report)
|
|
515
|
+
|
|
516
|
+
else:
|
|
517
|
+
print(f"Unknown command: {command}")
|
|
518
|
+
print(__doc__)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
if __name__ == "__main__":
|
|
522
|
+
main()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: LEEWAY.SKILLS.SDK
|
|
5
|
+
TAG: LEEWAY.SKILLS.SDK.APPLICATION_INSTALLER
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=package-open
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Installer for materializing the full packaged Leeway Skills application into a target directory
|
|
18
|
+
WHY = Teams may want a standalone copy of the full application after installing the npm package
|
|
19
|
+
WHO = Leeway Industries (By Leonard Jerome Lee)
|
|
20
|
+
WHERE = sdk/application-installer.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Copies the curated packaged asset set into an empty target directory while preserving structure
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
INSTALL
|
|
26
|
+
DEPLOY
|
|
27
|
+
|
|
28
|
+
LICENSE:
|
|
29
|
+
MIT
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import fs from "node:fs/promises";
|
|
33
|
+
import path from "node:path";
|
|
34
|
+
import { getPackageRoot } from "./paths.js";
|
|
35
|
+
|
|
36
|
+
const PACKAGE_COPY_ITEMS = [
|
|
37
|
+
".leeway/config.json",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"README.md",
|
|
40
|
+
"agent-config.yaml",
|
|
41
|
+
"agentbage.png.png",
|
|
42
|
+
"bin",
|
|
43
|
+
"config",
|
|
44
|
+
"documents",
|
|
45
|
+
"LeeWay-Standards/LICENSE",
|
|
46
|
+
"LeeWay-Standards/README.md",
|
|
47
|
+
"LeeWay-Standards/examples",
|
|
48
|
+
"LeeWay-Standards/package.json",
|
|
49
|
+
"LeeWay-Standards/schemas",
|
|
50
|
+
"LeeWay-Standards/src",
|
|
51
|
+
"mcp-server/README.md",
|
|
52
|
+
"mcp-server/dist",
|
|
53
|
+
"mcp-server/package.json",
|
|
54
|
+
"mcp-server/src",
|
|
55
|
+
"mcp-server/tsconfig.json",
|
|
56
|
+
"scripts",
|
|
57
|
+
"sdk",
|
|
58
|
+
"skills",
|
|
59
|
+
"package.json",
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
export async function extractLeewayApplication(options) {
|
|
63
|
+
const targetDir = path.resolve(options?.targetDir ?? "leeway-agent-skills-app");
|
|
64
|
+
const overwrite = options?.overwrite ?? false;
|
|
65
|
+
|
|
66
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
67
|
+
const existingEntries = await fs.readdir(targetDir);
|
|
68
|
+
if (existingEntries.length > 0 && !overwrite) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Target directory is not empty: ${targetDir}. Choose an empty directory or pass overwrite: true.`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const packageRoot = getPackageRoot();
|
|
75
|
+
const copied = [];
|
|
76
|
+
|
|
77
|
+
for (const relativePath of PACKAGE_COPY_ITEMS) {
|
|
78
|
+
const sourcePath = path.join(packageRoot, relativePath);
|
|
79
|
+
const destinationPath = path.join(targetDir, relativePath);
|
|
80
|
+
await fs.mkdir(path.dirname(destinationPath), { recursive: true });
|
|
81
|
+
await fs.cp(sourcePath, destinationPath, {
|
|
82
|
+
recursive: true,
|
|
83
|
+
force: overwrite,
|
|
84
|
+
});
|
|
85
|
+
copied.push(destinationPath);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
targetDir,
|
|
90
|
+
copied,
|
|
91
|
+
};
|
|
92
|
+
}
|
package/sdk/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: LEEWAY.SKILLS.SDK
|
|
5
|
+
TAG: LEEWAY.SKILLS.SDK.ENTRY
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=package
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Main npm SDK entry point for the full Leeway Skills application bundle
|
|
18
|
+
WHY = Gives consumers one import surface for package paths, badge tooling, governance utilities, and MCP server access
|
|
19
|
+
WHO = Leeway Industries (By Leonard Jerome Lee)
|
|
20
|
+
WHERE = sdk/index.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Re-exports internal package helpers, standards toolkit modules, and packaged MCP utilities
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
DISCOVER
|
|
26
|
+
EXECUTE
|
|
27
|
+
INTROSPECT
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export * from "./paths.js";
|
|
34
|
+
export * from "./application-installer.js";
|
|
35
|
+
export * from "../LeeWay-Standards/src/index.js";
|
|
36
|
+
export {
|
|
37
|
+
createLeewaySkillsProof,
|
|
38
|
+
installLeewaySkillsBadgeBundle,
|
|
39
|
+
} from "../mcp-server/dist/badge-proof.js";
|
|
40
|
+
export {
|
|
41
|
+
LeewaySkillsMCPServer,
|
|
42
|
+
startLeewaySkillsMCPServer,
|
|
43
|
+
} from "../mcp-server/dist/index.js";
|