Skip to content

Commit 04197cb

Browse files
Small improvements to onboarding workflow (#11)
1 parent d3cd06b commit 04197cb

File tree

7 files changed

+76
-33
lines changed

7 files changed

+76
-33
lines changed

.github/workflows/ci.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
name: CI
22
on:
33
push:
4-
paths-ignore:
5-
- '**.md'
4+
branches:
5+
- main
66
tags-ignore:
77
- 'v*'
8+
pull_request:
9+
branches:
10+
- '**'
811

912
concurrency:
1013
group: ${{ github.ref }}

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
1010
![](./README_resources/header.png)
1111

12-
**`CustomCode-Analyzer-Generator` is a command line tool to generate ODC External Library solutions complete with unit tests**. See examples of generated solutions [here](./README_resources/example_generations/RedisConnector/) (_**>** Connect to a redis database set up on my secure gateway (port 6379). password and key will be input params. return the key value_) and [here](./README_resources/example_generations/PythonRunner/) (_**>** Take a python program in a string as input and return the stdout in the output_). ⚡
12+
**`CustomCode-Analyzer-Generator` is a command-line tool to generate validated OutSytems Developer Cloud (ODC) External Library projects complete with unit tests.**. See examples of generated solutions [here](./README_resources/example_generations/RedisConnector/) (_**>** Connect to a redis database set up on my secure gateway (port 6379). password and key will be input params. return the key value_) and [here](./README_resources/example_generations/PythonRunner/) (_**>** Take a python program in a string as input and return the stdout in the output_). ⚡
1313

1414
## Overview
1515

16-
The BSD-3 licensed [`CustomCode-Analyzer`](https://github.com/jonathanalgar/CustomCode-Analyzer) component was released to give you real-time feedback your C# code as you build an external library in your IDE of choice. But more generally `CustomCode-Analyzer` can be thought of as a way of locally validating an external library at the point of build. This makes it a powerful component in an end-to-end Large Language Model (LLM) pipeline for generating an ODC external library:
16+
The BSD-3 licensed [`CustomCode-Analyzer`](https://github.com/jonathanalgar/CustomCode-Analyzer) component was released to give you real-time feedback your C# code as you build an external library in your IDE of choice. But more generally `CustomCode-Analyzer` can be thought of as a way of locally validating an external library project at the point of build. This makes it a powerful component in an end-to-end Large Language Model (LLM) pipeline for generating an ODC external library:
1717

1818
![](./README_resources/diagram.png)
1919

@@ -65,7 +65,7 @@ This means a range of models and prompts can be programatically benchmarked. The
6565

6666
Test cases covered include [binary data](./agents/evaluation/ground_truth/pdf.yml) and [network access through the secure gateway](./agents/evaluation/ground_truth/redis.yml). The test set is currently limited to single action (but with support for multi-parameter using an LLM to do name mapping) and single type output.
6767

68-
Consolidated no-repetition results for 2x OpenAI models with one-shot prompt (current default prompt):
68+
Summary of consolidated no-repetition results for 2x OpenAI models with one-shot prompt (current default prompt):
6969

7070
![](README_resources/runs.png)
7171

@@ -89,4 +89,4 @@ See [here](https://github.com/jonathanalgar/CustomCode-Analyzer/issues?q=is%3Aop
8989

9090
Please report bugs and feature requests [here](https://github.com/jonathanalgar/CustomCode-Analyzer/issues/new/choose).
9191

92-
PRs are welcome. In particular, code quality improvements, new unit/integration tests, new ground truths, and documentation improvements are all welcome 🤗 All changes to code should pass all existing tests (which are lacking and need to be expanded!). Please format any new code with [Mypy and Flake8 for Python](./Makefile) and [Csharpier for C#](./Makefile).
92+
PRs are welcome. In particular, code quality improvements, new unit/integration tests, new ground truths, and documentation improvements are all welcome 🤗 All changes to code should pass all existing tests (which are lacking and need to be expanded!). Please format any new code with [Mypy and Flake8 for Python](https://github.com/jonathanalgar/CustomCode-Analyzer-Generator/blob/d3cd06bd8f3fb962a1bb5459a15f098f9fc4b0c1/Makefile#L10-L12) and [Csharpier for C#](https://github.com/jonathanalgar/CustomCode-Analyzer-Generator/blob/d3cd06bd8f3fb962a1bb5459a15f098f9fc4b0c1/Makefile#L14-L15).

agents/generate_and_validate.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ def generate_and_validate(
3434
logger.info(f"Generating solution for: {use_case}")
3535

3636
env_retain = os.getenv("RETAIN_ON_FAILURE")
37-
if env_retain is not None:
37+
if env_retain and env_retain.strip():
3838
retain_on_failure = env_retain.lower() in ["true", "1", "yes", "y"]
3939
logger.info(f"Using RETAIN_ON_FAILURE={retain_on_failure} from .env")
4040
else:
4141
retain_input = input("Retain solution even if build fails? (y/n) [default: y]: ")
4242
retain_on_failure = retain_input.lower() in ["y", "yes"] or retain_input == ""
43-
print("(Tip: add RETAIN_ON_FAILURE=true or RETAIN_ON_FAILURE=true to .env to skip this input prompt)")
43+
print("(Tip: add RETAIN_ON_FAILURE=true or RETAIN_ON_FAILURE=true to .env to skip this input prompt in future)")
4444

4545
llm_inputs = LLMInputs(
4646
use_case=use_case,

agents/generate_library.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def get_user_input() -> str:
3030
`---._.--- CustomCode-Analyzer-Generator, an experimental project -ja---._.---'"""
3131

3232
print(banner)
33-
print("\n\nPlease describe what functionality you want the ODC external library to provide.")
33+
print("\n\nPlease describe what functionality you want the ODC External Library to provide.")
3434
print("Example: 'take a string and return the sha1 hash'")
3535
print("\nEnter the functionality:")
3636

@@ -56,9 +56,7 @@ def _get_model_from_env_or_prompt(available_models: dict, model_type: str, env_v
5656
print(f"Using {env_model_name} for {model_type} (from environment variable)")
5757
return models[env_model_name]
5858
print(f"Warning: Model '{env_model_name}' specified in {env_var_name} not found. Prompting for selection.")
59-
60-
print(f"(Tip: add {env_var_name} to .env to skip this input prompt)")
61-
return select_model(available_models, model_type)
59+
return select_model(available_models, model_type, env_var_name)
6260

6361

6462
def main() -> None:
@@ -68,9 +66,10 @@ def main() -> None:
6866
raise EnvironmentError("No OpenAI API key found in .env file. Please add OPENAI_API_KEY")
6967

7068
available_models = get_available_models(api_keys)
69+
7170
use_case = get_user_input()
7271

73-
print("\nSelect models for library generation:")
72+
print("\nNow let's select which LLMs to use to generate the library..")
7473
search_term_llm = _get_model_from_env_or_prompt(available_models, "NuGet package search", "SEARCH_TERM_LLM")
7574

7675
code_generation_llm = _get_model_from_env_or_prompt(available_models, "code generation", "CODE_GENERATION_LLM")

agents/utils/model_definitions.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,19 @@ def get_model(model_name: str) -> BaseChatModel:
4545
raise KeyError(f"Model {model_name} not found in any provider.")
4646

4747

48-
def select_model(available_models: Dict[str, Dict[str, Any]], purpose: str) -> Any:
48+
def select_model(available_models: Dict[str, Dict[str, Any]], purpose: str, env_var_name: str) -> Any:
4949
"""Prompts the user to select a model from the available models based on the given purpose."""
50-
print(f"\nSelect model for {purpose}:")
50+
print(f"\nSelect model for {purpose} (Tip: add {env_var_name} to .env to skip this input prompt in future):")
5151
options = _get_model_options(available_models, purpose)
5252
default_option = options[0]
53-
5453
for idx, (name, _) in enumerate(options, start=1):
5554
if idx == 1:
5655
print(f"{idx}. {name} (default - press Enter)")
5756
else:
5857
print(f"{idx}. {name}")
58+
print(
59+
"! If you are using the free tier of the OpenAI API, only gpt4o-mini model will work (see https://platform.openai.com/docs/guides/rate-limits)"
60+
)
5961

6062
while True:
6163
choice = input("Enter your choice (number or press Enter for default): ").strip()

agents/validation/utils.py

-2
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,3 @@ def extract_class_name(code: str) -> str:
5454
return class_name
5555
finally:
5656
tmp_path.unlink(missing_ok=True)
57-
58-

windows_setup.ps1

+56-15
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,41 @@ $envContent = $envLines -join "`n"
264264
$utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $false
265265
[System.IO.File]::WriteAllText($envPath, $envContent, $utf8NoBomEncoding)
266266

267-
# Write file with UTF8 encoding without BOM
268-
$utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $false
269-
[System.IO.File]::WriteAllText($envPath, $envContent, $utf8NoBomEncoding)
267+
# Function to create Desktop shortcut
268+
function Create-DesktopShortcut {
269+
param(
270+
[string]$TargetPath,
271+
[string]$ShortcutName
272+
)
273+
274+
$desktopPath = [Environment]::GetFolderPath("Desktop")
275+
$shortcutPath = Join-Path $desktopPath "$ShortcutName.lnk"
276+
277+
$WshShell = New-Object -ComObject WScript.Shell
278+
$Shortcut = $WshShell.CreateShortcut($shortcutPath)
279+
$Shortcut.TargetPath = $TargetPath
280+
$Shortcut.WorkingDirectory = Split-Path -Parent $TargetPath
281+
$Shortcut.IconLocation = "powershell.exe,0"
282+
$Shortcut.Description = "Run CustomCode-Analyzer-Generator"
283+
$Shortcut.Save()
284+
285+
return $shortcutPath
286+
}
287+
288+
# Ask user if they want to create a desktop shortcut
289+
$createShortcut = Read-Host "`nDo you want to create a desktop shortcut? (y/n)"
290+
if ($createShortcut -eq 'y' -or $createShortcut -eq 'Y') {
291+
$shortcutPath = Create-DesktopShortcut -TargetPath "powershell.exe" -ShortcutName "CustomCode-Analyzer-Generator"
292+
293+
# Update shortcut properties to run the script
294+
$WshShell = New-Object -ComObject WScript.Shell
295+
$Shortcut = $WshShell.CreateShortcut($shortcutPath)
296+
$Shortcut.Arguments = "-ExecutionPolicy Bypass -File `"$mainScriptPath`""
297+
$Shortcut.WorkingDirectory = $installPath
298+
$Shortcut.Save()
299+
300+
Write-Host "Desktop shortcut created at: $shortcutPath" -ForegroundColor Green
301+
}
270302

271303
Write-Host "`nInstallation Complete!"
272304
Write-Host "-------------------------"
@@ -284,19 +316,28 @@ Write-Host "2. Navigate to the installation directory:"
284316
Write-Host " cd `"$installPath`""
285317
Write-Host "3. Run the script:"
286318
Write-Host " .\customcode-analyzer-generator.ps1"
287-
288-
$effectivePolicy = Get-ExecutionPolicy -Scope Process
289-
if ($effectivePolicy -eq "Undefined") {
290-
$effectivePolicy = Get-ExecutionPolicy -Scope CurrentUser
319+
if ($createShortcut -eq 'y' -or $createShortcut -eq 'Y') {
320+
Write-Host "`nOr simply double-click the desktop shortcut that was created."
291321
}
292-
if ($effectivePolicy -eq "Restricted" -or $effectivePolicy -eq "AllSigned") {
293-
Write-Host "`nPowerShell is blocking script execution!" -ForegroundColor Yellow
294-
Write-Host "Detected Execution Policy: $effectivePolicy"
295-
Write-Host "`nTo allow the script to run, choose one of these two options:"
296-
Write-Host " - (Recommended) Change policy to allow local scripts:"
297-
Write-Host " Set-ExecutionPolicy RemoteSigned -Scope CurrentUser"
298-
Write-Host " - (One-time use) Run the script with temporary permission:"
299-
Write-Host " powershell -ExecutionPolicy Bypass -File .\customcode-analyzer-generator.ps1"
322+
323+
# Check execution policy for all scopes
324+
$processPolicy = Get-ExecutionPolicy -Scope Process
325+
$userPolicy = Get-ExecutionPolicy -Scope CurrentUser
326+
$machinePolicy = Get-ExecutionPolicy -Scope LocalMachine
327+
328+
# If any relevant scope is Restricted or AllSigned, warn the user
329+
if ($processPolicy -eq "Restricted" -or $processPolicy -eq "AllSigned" -or
330+
($processPolicy -eq "Undefined" -and ($userPolicy -eq "Restricted" -or $userPolicy -eq "AllSigned" -or
331+
($userPolicy -eq "Undefined" -and ($machinePolicy -eq "Restricted" -or $machinePolicy -eq "AllSigned"))))) {
332+
333+
Write-Host "`nPowerShell is blocking script execution!" -ForegroundColor Red
334+
Write-Host "Current effective policy prevents running scripts." -ForegroundColor Yellow
335+
336+
Write-Host "`nTo allow the script to run, choose one of these options:"
337+
Write-Host " - (Recommended) Change policy to allow local scripts:" -ForegroundColor Cyan
338+
Write-Host " Set-ExecutionPolicy RemoteSigned -Scope CurrentUser"
339+
Write-Host " - (One-time use) Run the script with this command:" -ForegroundColor Cyan
340+
Write-Host " powershell -ExecutionPolicy Bypass -File .\customcode-analyzer-generator.ps1"
300341
Write-Host "`nAfter fixing the execution policy, return to Step 3 and run the script."
301342
}
302343

0 commit comments

Comments
 (0)