Skip to content

Commit e9b81df

Browse files
Use default Mock AI provider
1 parent c0f285e commit e9b81df

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

multilingualprogramming/__main__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from multilingualprogramming.exceptions import UnsupportedLanguageError
4343
from multilingualprogramming.lexer.lexer import Lexer
4444
from multilingualprogramming.parser.parser import Parser
45+
from multilingualprogramming.runtime.ai_runtime import AIRuntime, MockProvider
4546
from multilingualprogramming.source_extensions import (
4647
find_package_init,
4748
has_source_extension,
@@ -86,6 +87,14 @@ def _read_source_file(path: str) -> str:
8687
sys.exit(1)
8788

8889

90+
def _ensure_default_ai_provider() -> None:
91+
"""Register the CLI's default mock provider when none is active."""
92+
try:
93+
AIRuntime.get_provider()
94+
except RuntimeError:
95+
AIRuntime.register(MockProvider())
96+
97+
8998
def _parse_program_from_file(path: str, lang: str | None):
9099
source = _read_source_file(path)
91100
lexer = Lexer(source, language=lang)
@@ -98,6 +107,7 @@ def _parse_program_from_file(path: str, lang: str | None):
98107
def cmd_run(args):
99108
"""Execute a multilingual source file."""
100109
source = _read_source_file(args.file)
110+
_ensure_default_ai_provider()
101111

102112
# Determine package context so that relative imports work.
103113
# Walk up from the file's directory while package initializer files exist;

tests/language_completeness_cli_test.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from multilingualprogramming.keyword.language_pack_validator import (
3131
LanguagePackValidator,
3232
)
33+
from multilingualprogramming.runtime.ai_runtime import AIRuntime, MockProvider
3334

3435

3536
def _parse(source, lang="en"):
@@ -420,6 +421,54 @@ def test_cmd_run_show_backend_writes_report_to_stderr(self):
420421
self.assertEqual(stdout.getvalue(), "hello\n")
421422
self.assertIn("[backend] python (python-codegen-exec)", stderr.getvalue())
422423

424+
def test_cmd_run_registers_default_mock_provider_for_ai_programs(self):
425+
with tempfile.NamedTemporaryFile(
426+
"w", suffix=".multi", delete=False, encoding="utf-8"
427+
) as tmp:
428+
tmp.write(
429+
'fn main() uses ai:\n'
430+
' print(prompt @claude-sonnet: "hello")\n'
431+
'main()\n'
432+
)
433+
tmp_path = tmp.name
434+
435+
args = Namespace(file=tmp_path, lang="en", show_backend=False)
436+
stdout = io.StringIO()
437+
try:
438+
AIRuntime.reset()
439+
with patch("sys.stdout", stdout):
440+
cmd_run(args)
441+
finally:
442+
AIRuntime.reset()
443+
Path(tmp_path).unlink(missing_ok=True)
444+
445+
self.assertIn("mock response to:", stdout.getvalue())
446+
447+
def test_cmd_run_preserves_existing_registered_provider(self):
448+
with tempfile.NamedTemporaryFile(
449+
"w", suffix=".multi", delete=False, encoding="utf-8"
450+
) as tmp:
451+
tmp.write(
452+
'fn main() uses ai:\n'
453+
' print(prompt @claude-sonnet: "hello")\n'
454+
'main()\n'
455+
)
456+
tmp_path = tmp.name
457+
458+
args = Namespace(file=tmp_path, lang="en", show_backend=False)
459+
stdout = io.StringIO()
460+
provider = MockProvider().add_response("custom provider response")
461+
try:
462+
AIRuntime.reset()
463+
AIRuntime.register(provider)
464+
with patch("sys.stdout", stdout):
465+
cmd_run(args)
466+
finally:
467+
AIRuntime.reset()
468+
Path(tmp_path).unlink(missing_ok=True)
469+
470+
self.assertEqual(stdout.getvalue().strip(), "custom provider response")
471+
423472

424473
# ---------------------------------------------------------------
425474
# WS7: REPL improvements

0 commit comments

Comments
 (0)