Skip to content

Add C# as a supported output language#102

Merged
kalil0321 merged 5 commits into
kalil0321:mainfrom
jarsh921:add-csharp-output-language
Jul 22, 2026
Merged

Add C# as a supported output language#102
kalil0321 merged 5 commits into
kalil0321:mainfrom
jarsh921:add-csharp-output-language

Conversation

@jarsh921

@jarsh921 jarsh921 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Follows the exact same pattern as python/javascript/typescript:

  • New prompt partial (prompts/partials/_language_csharp.md): uses System.Net.Http.HttpClient and System.Text.Json - both part of the .NET 5+ base class library, so no NuGet package is needed for HTTP or JSON (unlike Java, .NET's stdlib does include JSON support). Packaged as a minimal .csproj so dotnet run just works. Same auth-hardcoding/refresh guidance as the other languages. No filename vs. class-name naming workaround needed here (unlike Java) - C# doesn't require a public class's name to match its file's name.
  • base_engineer.py: added "csharp" to _OUTPUT_LANGUAGE_EXTENSIONS (.cs), _get_language_name() ("C#"), _get_run_command() ("dotnet run"), and _get_auto_output_files() (ApiClient.csproj, always included - a project file is required to dotnet run regardless of dependencies, matching typescript's "always" precedent rather than javascript/go's conditional one).
  • cli.py: added C# to the interactive output_language config picker.
  • Updated the three docstrings/comments that listed the language set (config.py, engineer.py, prompts/init.py) and README.md's output language line.
  • Tests: mirrored the existing per-language test pattern in test_base_engineer.py (extension, run command, prompt content) and test_prompts.py (partial loading) for C#.

Checked the partial for the literal-brace str.format_map() bug caught in the Java PR before writing this one - no literal {/} anywhere in the new file (confirmed via grep), since C# code snippets weren't needed to convey the guidance here.

Full test suite passes (49/49, run 3x) except the same pre-existing flaky test as the other language PRs
(test_existing_client_language_falls_back_to_newest_file - a mtime-resolution race condition, unrelated to this change, present on a clean main checkout too). ruff check is clean on every file this touches (8 pre-existing lint errors elsewhere on main, none in the touched lines).


Summary by cubic

Adds C# as a supported output language that generates a minimal .NET project and runs with a cwd‑independent dotnet run --project command. The run command resolves and shell‑quotes the project path so it works from any directory, including paths with shell metacharacters.

  • New Features

    • base_engineer: maps csharp -> .cs, language "C#", run command dotnet run --project {scripts_dir}/ApiClient.csproj using shlex.quote and an absolute path, and always includes ApiClient.csproj.
    • New partial prompts/partials/_language_csharp.md using HttpClient/System.Text.Json (available since .NET Core 3.0), with auth hardcoding/refresh, save paths, and adaptive target framework guidance (default net8.0; adjust up or down to match the installed SDK).
    • CLI adds csharp; README/config/engineer/prompt docs updated.
  • Tests

    • tests/test_base_engineer.py: asserts .cs extension; run command points to a resolved, safely quoted project path; handles metacharacters; resolves relative output dirs; C# prompt content included.
    • tests/test_prompts.py: verifies the C# partial loads and renders run_command and paths.

Written for commit 6306e39. Summary will update on new commits.

Review in cubic

Greptile Summary

This PR adds C# as a supported output language. The main changes are:

  • C# prompt guidance using the .NET base class library.
  • .cs and .csproj output handling.
  • An absolute, shell-quoted dotnet run --project command.
  • C# support in settings, documentation, and tests.

Confidence Score: 5/5

This looks safe to merge.

  • The run command now points directly to the generated project from any working directory.
  • The target-framework guidance now handles installed SDK and runtime differences.
  • No blocking issues were found in the updated code.

Important Files Changed

Filename Overview
src/reverse_api/base_engineer.py Adds C# mappings, project output guidance, and a cwd-independent run command.
src/reverse_api/prompts/partials/_language_csharp.md Adds C# generation, authentication, project setup, and target-framework guidance.
src/reverse_api/cli.py Adds C# to the interactive output-language setting.
tests/test_base_engineer.py Adds coverage for C# extensions, prompts, project paths, and shell quoting.
tests/test_prompts.py Adds coverage for loading and rendering the C# prompt partial.

Reviews (2): Last reviewed commit: "Make the C# target-framework guidance di..." | Re-trigger Greptile

Comment thread src/reverse_api/base_engineer.py Outdated
Comment thread src/reverse_api/cli.py
Comment thread src/reverse_api/prompts/partials/_language_csharp.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 10 files

Re-trigger cubic

@kind-agent

kind-agent Bot commented Jul 21, 2026

Copy link
Copy Markdown

⚠️ Error — The test run failed unexpectedly.

Snapshot kind-sandbox is inactive

This is likely a transient issue. You can re-trigger a run from the dashboard.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/reverse_api/base_engineer.py Outdated
Comment thread tests/test_base_engineer.py Outdated
Joshua Dunbar and others added 5 commits July 22, 2026 12:51
Follows the exact same pattern as python/javascript/typescript:

- New prompt partial (prompts/partials/_language_csharp.md): uses
  System.Net.Http.HttpClient and System.Text.Json - both part of the
  .NET 5+ base class library, so no NuGet package is needed for HTTP
  or JSON (unlike Java, .NET's stdlib does include JSON support).
  Packaged as a minimal .csproj so `dotnet run` just works. Same
  auth-hardcoding/refresh guidance as the other languages. No filename
  vs. class-name naming workaround needed here (unlike Java) - C#
  doesn't require a public class's name to match its file's name.
- base_engineer.py: added "csharp" to _OUTPUT_LANGUAGE_EXTENSIONS
  (.cs), _get_language_name() ("C#"), _get_run_command() ("dotnet
  run"), and _get_auto_output_files() (ApiClient.csproj, always
  included - a project file is required to `dotnet run` regardless of
  dependencies, matching typescript's "always" precedent rather than
  javascript/go's conditional one).
- cli.py: added C# to the interactive `output_language` config picker.
- Updated the three docstrings/comments that listed the language set
  (config.py, engineer.py, prompts/__init__.py) and README.md's output
  language line.
- Tests: mirrored the existing per-language test pattern in
  test_base_engineer.py (extension, run command, prompt content) and
  test_prompts.py (partial loading) for C#.

Checked the partial for the literal-brace str.format_map() bug caught
in the Java PR before writing this one - no literal `{`/`}` anywhere
in the new file (confirmed via grep), since C# code snippets weren't
needed to convey the guidance here.

Full test suite passes (49/49, run 3x) except the same pre-existing
flaky test as the other language PRs
(test_existing_client_language_falls_back_to_newest_file - a
mtime-resolution race condition, unrelated to this change, present
on a clean main checkout too). ruff check is clean on every file this
touches (8 pre-existing lint errors elsewhere on main, none in the
touched lines).
Two real bugs caught by greptile-apps on the PR, both verified against
the actual code before fixing:

1. Same class of bug as the Go and Java PRs: the agent's cwd for the
   whole session is scripts_dir.parent.parent (confirmed in engineer.py's
   analyze_and_generate -> ClaudeAgentOptions), not scripts_dir where
   ApiClient.csproj is saved. A bare `dotnet run` only looks for a
   project file in the current directory, so it wouldn't find it.
   _get_run_command() now points --project explicitly at this run's own
   .csproj path, the idiomatic dotnet-CLI way to do this (as opposed to
   Maven's -f flag used for the same fix in the Java PR).

2. The partial described HttpClient/System.Text.Json as available since
   .NET 5+, but then hardcoded the generated project's own
   <TargetFramework> to net8.0 unconditionally — a genuine internal
   contradiction: on a machine with only, say, .NET 6 installed,
   generation would succeed but the required dotnet run test step would
   fail with an unsupported-target-framework error, despite the partial's
   own text implying broader compatibility. Fixed by making the target
   framework adaptive: default to net8.0, but explicitly instructs
   lowering <TargetFramework> and retrying if the installed SDK doesn't
   support it - leaning on the same "test it, up to 5 attempts to fix
   issues" loop every partial already has, rather than assuming one
   hardcoded version always works.

Updated test_get_run_command_csharp to match the new (scripts_dir-
dependent) return value.

A third bot finding (cli.py's `run <id> --file` subcommand only
discovers *.py scripts and always launches them with the shared venv's
python interpreter) is the same pre-existing, cross-cutting gap already
noted on the Java PR - confirmed discover_scripts() in utils.py has
been Python-only since before javascript/typescript were added, so this
isn't specific to C# either. Left out of scope here for the same reason.

Full test suite passes (49/49, run 2x). ruff check clean on the touched
lines (2 pre-existing unused-import warnings elsewhere in
test_base_engineer.py, unrelated).
Same class of bug caught by review bots on the PHP PR, applied here
proactively: _get_run_command()'s "--project \"{path}\"" only looked
safe - manual double-quoting doesn't stop $()/backtick command
substitution inside a double-quoted shell string. Replaced with
shlex.quote(). Added a test with a deliberately hostile path
(embedded $(rm -rf ~)) asserting the command round-trips through
shlex.split() back to the literal path.

Full test suite passes (50/50, run 2x) except the same pre-existing
flaky test noted on the other language PRs.
cubic flagged that a relative --output-dir breaks --project: scripts_dir
stays relative to the original cwd, but once the agent's cwd moves to
scripts_dir.parent.parent (see analyze_and_generate), embedding that same
relative string re-interprets it from the new location and points at a
doubly-nested, nonexistent path. Resolve scripts_dir before interpolating
it so the command is genuinely cwd-independent, matching the intent
already documented in the surrounding comment.
The partial told the agent to *lower* TargetFramework when dotnet run
rejects it, but a machine with only a newer SDK (e.g. .NET 10, no .NET 8
runtime) needs the target *raised* — net8.0 builds fine under SDK 10 but
fails at launch. Observed in live testing: the agent recovered anyway
from dotnet's error message, but the guidance shouldn't point the wrong
way.
@kalil0321
kalil0321 force-pushed the add-csharp-output-language branch from 07c7d22 to 6306e39 Compare July 22, 2026 10:56
@kalil0321

Copy link
Copy Markdown
Owner

@greptile review

@kalil0321
kalil0321 merged commit eb5d1f1 into kalil0321:main Jul 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants