arclith-cli 0.11.0__tar.gz → 0.12.0__tar.gz
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.
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/PKG-INFO +2 -2
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/README.md +10 -8
- arclith_cli-0.12.0/arclith_cli/__init__.py +1 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/capabilities.py +2 -2
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/core_scaffold.py +24 -24
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/init_project.py +2 -2
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/main.py +10 -10
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/project_paths.py +2 -2
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/pyproject.toml +2 -2
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/e2e_manual.sh +1 -1
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_core_scaffold.py +22 -15
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_e2e_scaffold.py +8 -6
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/uv.lock +2 -2
- arclith_cli-0.11.0/arclith_cli/__init__.py +0 -1
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/.gitignore +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/LICENSE +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/Makefile +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/adapter_templates.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/add_adapter.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/entity_scanner.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/export_config.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/rename.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/scaffold.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/arclith_cli/updater.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/__init__.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_add_adapter.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_capabilities.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_project_paths.py +0 -0
- {arclith_cli-0.11.0 → arclith_cli-0.12.0}/tests/test_rename.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arclith-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: CLI scaffolding tool for arclith — hexagonal architecture framework
|
|
5
5
|
Author-email: Killian KOPP <killiankopp@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -186,7 +186,7 @@ License: Apache License
|
|
|
186
186
|
License-File: LICENSE
|
|
187
187
|
Keywords: arclith,cli,ddd,hexagonal-architecture,scaffold
|
|
188
188
|
Requires-Python: >=3.13
|
|
189
|
-
Requires-Dist: arclith>=0.
|
|
189
|
+
Requires-Dist: arclith>=0.15.0
|
|
190
190
|
Requires-Dist: httpx>=0.27.0
|
|
191
191
|
Requires-Dist: rich>=13.0.0
|
|
192
192
|
Requires-Dist: typer>=0.15.0
|
|
@@ -96,25 +96,27 @@ Comme `add-entity`, cette commande ne câble pas FastAPI, FastMCP, LangGraph, un
|
|
|
96
96
|
|
|
97
97
|
---
|
|
98
98
|
|
|
99
|
-
### `add-
|
|
99
|
+
### `add-intent-interpreter` — Ajouter un interpréteur d'intention
|
|
100
100
|
|
|
101
|
-
Crée uniquement le fichier minimal d'un
|
|
101
|
+
Crée uniquement le fichier minimal d'un interpréteur d'intention dans
|
|
102
|
+
`src/<package>/application/intent_interpreters/`.
|
|
102
103
|
|
|
103
104
|
```bash
|
|
104
105
|
cd my-recipe-service
|
|
105
|
-
arclith-cli add-
|
|
106
|
-
arclith-cli add-
|
|
106
|
+
arclith-cli add-intent-interpreter IngredientIntent
|
|
107
|
+
arclith-cli add-intent-interpreter command-router
|
|
107
108
|
```
|
|
108
109
|
|
|
109
110
|
Fichier généré :
|
|
110
111
|
|
|
111
112
|
```text
|
|
112
|
-
src/<package>/application/
|
|
113
|
+
src/<package>/application/intent_interpreters/ingredient_intent.py
|
|
113
114
|
```
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
structuré. Il ne remplace pas LangGraph : LangGraph orchestre les nœuds, tandis que
|
|
117
|
-
la traduction d'intention. Le fichier généré reste volontairement vide de
|
|
116
|
+
L'interpréteur d'intention est le composant applicatif qui transforme une demande naturelle en
|
|
117
|
+
commande ou DTO structuré. Il ne remplace pas LangGraph : LangGraph orchestre les nœuds, tandis que
|
|
118
|
+
l'interpréteur porte la traduction d'intention. Le fichier généré reste volontairement vide de
|
|
119
|
+
logique métier.
|
|
118
120
|
|
|
119
121
|
---
|
|
120
122
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.12.0"
|
|
@@ -314,7 +314,7 @@ port: {port}
|
|
|
314
314
|
LLM_CAPABILITY = CapabilitySpec(
|
|
315
315
|
name="llm",
|
|
316
316
|
layer="outbound",
|
|
317
|
-
description="Configuration LLM pour
|
|
317
|
+
description="Configuration LLM pour interpréteurs d'intention et agents via une factory Arclith.",
|
|
318
318
|
activation_config_key=None,
|
|
319
319
|
adapters=(
|
|
320
320
|
AdapterSpec(
|
|
@@ -401,7 +401,7 @@ OPENAI_API_KEY={api_key}
|
|
|
401
401
|
name="anthropic",
|
|
402
402
|
capability="llm",
|
|
403
403
|
layer="outbound",
|
|
404
|
-
description="Modèle Anthropic pour
|
|
404
|
+
description="Modèle Anthropic pour interpréteurs d'intention et agents.",
|
|
405
405
|
config_path="config/adapters/outbound/lm.yaml",
|
|
406
406
|
config_template="""\
|
|
407
407
|
provider: anthropic
|
|
@@ -38,9 +38,9 @@ class {class_name}UseCase({class_name}Port):
|
|
|
38
38
|
raise NotImplementedError("Implement {class_name}UseCase.execute")
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
async def
|
|
43
|
-
raise NotImplementedError("Implement {class_name}
|
|
41
|
+
_INTENT_INTERPRETER_TEMPLATE = """class {class_name}Interpreter:
|
|
42
|
+
async def interpret(self, prompt: str) -> None:
|
|
43
|
+
raise NotImplementedError("Implement {class_name}Interpreter.interpret")
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
46
|
|
|
@@ -61,17 +61,17 @@ class UseCaseNames:
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
@dataclass(frozen=True)
|
|
64
|
-
class
|
|
64
|
+
class IntentInterpreterNames:
|
|
65
65
|
pascal: str
|
|
66
66
|
snake: str
|
|
67
67
|
|
|
68
68
|
@classmethod
|
|
69
|
-
def from_input(cls, raw: str) ->
|
|
69
|
+
def from_input(cls, raw: str) -> IntentInterpreterNames:
|
|
70
70
|
names = EntityNames.from_input(raw)
|
|
71
|
-
pascal =
|
|
72
|
-
snake =
|
|
71
|
+
pascal = _strip_pascal_intent_interpreter_suffix(names.pascal)
|
|
72
|
+
snake = _strip_snake_intent_interpreter_suffix(names.snake)
|
|
73
73
|
if not pascal or not snake:
|
|
74
|
-
console.print(f"[red]✗[/red] Nom
|
|
74
|
+
console.print(f"[red]✗[/red] Nom d'interpréteur d'intention invalide : [bold]{raw}[/bold].")
|
|
75
75
|
raise typer.Exit(1)
|
|
76
76
|
return cls(pascal=pascal, snake=snake)
|
|
77
77
|
|
|
@@ -130,24 +130,24 @@ def add_usecase_cmd(*, project_dir: Path | None = None, usecase_name: str) -> Pa
|
|
|
130
130
|
return usecase_file
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
def
|
|
133
|
+
def add_intent_interpreter_cmd(*, project_dir: Path | None = None, intent_name: str) -> Path:
|
|
134
134
|
project_dir = project_dir or Path.cwd()
|
|
135
|
-
|
|
136
|
-
_assert_project_root(project_dir, command="add-
|
|
137
|
-
_assert_valid_name(
|
|
135
|
+
intent_name = intent_name.strip()
|
|
136
|
+
_assert_project_root(project_dir, command="add-intent-interpreter")
|
|
137
|
+
_assert_valid_name(intent_name, label="interpréteur d'intention")
|
|
138
138
|
|
|
139
139
|
paths = detect_project_paths(project_dir)
|
|
140
|
-
names =
|
|
141
|
-
|
|
142
|
-
_assert_missing(
|
|
140
|
+
names = IntentInterpreterNames.from_input(intent_name)
|
|
141
|
+
intent_file = paths.application_intent_interpreters / f"{names.snake}.py"
|
|
142
|
+
_assert_missing(intent_file, project_dir)
|
|
143
143
|
|
|
144
|
-
_ensure_package_dirs(paths, "application", "
|
|
145
|
-
|
|
144
|
+
_ensure_package_dirs(paths, "application", "intent_interpreters")
|
|
145
|
+
intent_file.write_text(_INTENT_INTERPRETER_TEMPLATE.format(class_name=names.pascal), encoding="utf-8")
|
|
146
146
|
console.print(
|
|
147
|
-
f"[green]✓[/green]
|
|
148
|
-
f"[bold]{
|
|
147
|
+
f"[green]✓[/green] Interpréteur d'intention {names.pascal}Interpreter créé : "
|
|
148
|
+
f"[bold]{intent_file.relative_to(project_dir)}[/bold]"
|
|
149
149
|
)
|
|
150
|
-
return
|
|
150
|
+
return intent_file
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
def _assert_project_root(project_dir: Path, *, command: str) -> None:
|
|
@@ -232,8 +232,8 @@ def _strip_snake_suffix(value: str) -> str:
|
|
|
232
232
|
value = stripped
|
|
233
233
|
|
|
234
234
|
|
|
235
|
-
def
|
|
236
|
-
suffixes = ("
|
|
235
|
+
def _strip_pascal_intent_interpreter_suffix(value: str) -> str:
|
|
236
|
+
suffixes = ("Interpreter",)
|
|
237
237
|
while True:
|
|
238
238
|
stripped = value
|
|
239
239
|
for suffix in suffixes:
|
|
@@ -245,8 +245,8 @@ def _strip_pascal_planner_suffix(value: str) -> str:
|
|
|
245
245
|
value = stripped
|
|
246
246
|
|
|
247
247
|
|
|
248
|
-
def
|
|
249
|
-
suffixes = ("
|
|
248
|
+
def _strip_snake_intent_interpreter_suffix(value: str) -> str:
|
|
249
|
+
suffixes = ("_interpreter",)
|
|
250
250
|
while True:
|
|
251
251
|
stripped = value
|
|
252
252
|
for suffix in suffixes:
|
|
@@ -72,7 +72,7 @@ def _framework_version() -> str:
|
|
|
72
72
|
try:
|
|
73
73
|
return version("arclith")
|
|
74
74
|
except PackageNotFoundError:
|
|
75
|
-
return "0.
|
|
75
|
+
return "0.15.0"
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def _create_package_layout(package_root: Path) -> None:
|
|
@@ -85,7 +85,7 @@ def _create_package_layout(package_root: Path) -> None:
|
|
|
85
85
|
package_root / "domain" / "ports" / "outbound",
|
|
86
86
|
package_root / "application",
|
|
87
87
|
package_root / "application" / "use_cases",
|
|
88
|
-
package_root / "application" / "
|
|
88
|
+
package_root / "application" / "intent_interpreters",
|
|
89
89
|
package_root / "adapters",
|
|
90
90
|
package_root / "adapters" / "inbound",
|
|
91
91
|
package_root / "adapters" / "outbound",
|
|
@@ -15,7 +15,7 @@ from rich.tree import Tree
|
|
|
15
15
|
from . import __version__
|
|
16
16
|
from .add_adapter import add_adapter_cmd
|
|
17
17
|
from .capabilities import CAPABILITY_CATALOG, capability_catalog_as_dict
|
|
18
|
-
from .core_scaffold import add_entity_cmd,
|
|
18
|
+
from .core_scaffold import add_entity_cmd, add_intent_interpreter_cmd, add_usecase_cmd
|
|
19
19
|
from .export_config import export_config_cmd
|
|
20
20
|
from .init_project import init_project_cmd
|
|
21
21
|
from .rename import EntityNames, apply_rename
|
|
@@ -221,17 +221,17 @@ def add_usecase(
|
|
|
221
221
|
add_usecase_cmd(usecase_name=usecase or _prompt_usecase())
|
|
222
222
|
|
|
223
223
|
|
|
224
|
-
@app.command(name="add-
|
|
225
|
-
def
|
|
226
|
-
|
|
224
|
+
@app.command(name="add-intent-interpreter")
|
|
225
|
+
def add_intent_interpreter(
|
|
226
|
+
intent: Annotated[
|
|
227
227
|
str | None,
|
|
228
228
|
typer.Argument(
|
|
229
|
-
help="Nom
|
|
229
|
+
help="Nom de l'interpréteur d'intention. Exemple : IngredientIntent, todo-intent, command-router",
|
|
230
230
|
),
|
|
231
231
|
] = None,
|
|
232
232
|
) -> None:
|
|
233
|
-
"""Créer uniquement le fichier minimal d'un
|
|
234
|
-
|
|
233
|
+
"""Créer uniquement le fichier minimal d'un interpréteur d'intention."""
|
|
234
|
+
add_intent_interpreter_cmd(intent_name=intent or _prompt_intent_interpreter())
|
|
235
235
|
|
|
236
236
|
|
|
237
237
|
@app.command(name="capabilities")
|
|
@@ -327,10 +327,10 @@ def _prompt_usecase() -> str:
|
|
|
327
327
|
return value
|
|
328
328
|
|
|
329
329
|
|
|
330
|
-
def
|
|
331
|
-
console.print("\n[bold]
|
|
330
|
+
def _prompt_intent_interpreter() -> str:
|
|
331
|
+
console.print("\n[bold]Interpréteur d'intention[/bold] [dim](ex : IngredientIntent, todo_intent)[/dim]")
|
|
332
332
|
while True:
|
|
333
|
-
value = Prompt.ask(" [bold green]Nom
|
|
333
|
+
value = Prompt.ask(" [bold green]Nom de l'interpréteur[/bold green]").strip()
|
|
334
334
|
if not value:
|
|
335
335
|
console.print(" [red]Le nom ne peut pas être vide.[/red]")
|
|
336
336
|
elif not _ENTITY_RE.match(value):
|
|
@@ -21,8 +21,8 @@ class ProjectPaths:
|
|
|
21
21
|
return self.package_root / "domain" / "ports" / "inbound"
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
|
-
def
|
|
25
|
-
return self.package_root / "application" / "
|
|
24
|
+
def application_intent_interpreters(self) -> Path:
|
|
25
|
+
return self.package_root / "application" / "intent_interpreters"
|
|
26
26
|
|
|
27
27
|
@property
|
|
28
28
|
def adapters_outbound(self) -> Path:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "arclith-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.12.0"
|
|
8
8
|
description = "CLI scaffolding tool for arclith — hexagonal architecture framework"
|
|
9
9
|
license = { file = "LICENSE" }
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -16,7 +16,7 @@ dependencies = [
|
|
|
16
16
|
"typer>=0.15.0",
|
|
17
17
|
"rich>=13.0.0",
|
|
18
18
|
"httpx>=0.27.0",
|
|
19
|
-
"arclith>=0.
|
|
19
|
+
"arclith>=0.15.0",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[tool.uv.sources]
|
|
@@ -39,7 +39,7 @@ if grep -q '\[tool\.uv\.sources\]' pyproject.toml; then
|
|
|
39
39
|
fi
|
|
40
40
|
|
|
41
41
|
ARCLITH_VERSION=$(grep 'arclith\[' pyproject.toml | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
|
42
|
-
MIN_ARCLITH_VERSION="0.
|
|
42
|
+
MIN_ARCLITH_VERSION="0.15.0"
|
|
43
43
|
if version_lt "$ARCLITH_VERSION" "$MIN_ARCLITH_VERSION"; then
|
|
44
44
|
echo -e "${RED}✗ FAIL: arclith version < $MIN_ARCLITH_VERSION (found: $ARCLITH_VERSION)${NC}"
|
|
45
45
|
exit 1
|
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
import pytest
|
|
4
4
|
import typer
|
|
5
5
|
|
|
6
|
-
from arclith_cli.core_scaffold import add_entity_cmd,
|
|
6
|
+
from arclith_cli.core_scaffold import add_entity_cmd, add_intent_interpreter_cmd, add_usecase_cmd
|
|
7
7
|
from arclith_cli.init_project import init_project_cmd
|
|
8
8
|
|
|
9
9
|
|
|
@@ -47,7 +47,7 @@ def test_init_project_creates_minimal_src_layout_without_entity(tmp_path: Path)
|
|
|
47
47
|
"observability:\n"
|
|
48
48
|
" enabled: []\n"
|
|
49
49
|
)
|
|
50
|
-
assert "arclith[fastapi,mcp]>=0.
|
|
50
|
+
assert "arclith[fastapi,mcp]>=0.15.0" in (generated / "pyproject.toml").read_text(encoding="utf-8")
|
|
51
51
|
assert (package_root / "domain" / "models" / "__init__.py").exists()
|
|
52
52
|
assert (package_root / "domain" / "ports" / "inbound" / "__init__.py").exists()
|
|
53
53
|
assert (package_root / "domain" / "ports" / "outbound" / "__init__.py").exists()
|
|
@@ -97,19 +97,23 @@ def test_add_usecase_creates_minimal_usecase_in_src_package(tmp_path: Path) -> N
|
|
|
97
97
|
assert not (project_dir / "src" / "demo_service" / "adapters").exists()
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
def
|
|
100
|
+
def test_add_intent_interpreter_creates_minimal_interpreter_in_src_package(tmp_path: Path) -> None:
|
|
101
101
|
project_dir = _src_project(tmp_path)
|
|
102
102
|
|
|
103
|
-
generated =
|
|
103
|
+
generated = add_intent_interpreter_cmd(project_dir=project_dir, intent_name="IngredientIntent")
|
|
104
104
|
|
|
105
|
-
assert generated ==
|
|
105
|
+
assert generated == (
|
|
106
|
+
project_dir / "src" / "demo_service" / "application" / "intent_interpreters" / "ingredient_intent.py"
|
|
107
|
+
)
|
|
106
108
|
assert generated.read_text(encoding="utf-8") == (
|
|
107
|
-
"class
|
|
108
|
-
" async def
|
|
109
|
-
' raise NotImplementedError("Implement
|
|
109
|
+
"class IngredientIntentInterpreter:\n"
|
|
110
|
+
" async def interpret(self, prompt: str) -> None:\n"
|
|
111
|
+
' raise NotImplementedError("Implement IngredientIntentInterpreter.interpret")\n'
|
|
110
112
|
)
|
|
111
113
|
assert (project_dir / "src" / "demo_service" / "application" / "__init__.py").exists()
|
|
112
|
-
assert (
|
|
114
|
+
assert (
|
|
115
|
+
project_dir / "src" / "demo_service" / "application" / "intent_interpreters" / "__init__.py"
|
|
116
|
+
).exists()
|
|
113
117
|
assert not (project_dir / "src" / "demo_service" / "adapters").exists()
|
|
114
118
|
|
|
115
119
|
|
|
@@ -129,14 +133,17 @@ def test_add_usecase_strips_repeated_usecase_suffix(tmp_path: Path) -> None:
|
|
|
129
133
|
assert "UseCaseUseCase" not in generated.read_text(encoding="utf-8")
|
|
130
134
|
|
|
131
135
|
|
|
132
|
-
def
|
|
136
|
+
def test_add_intent_interpreter_strips_repeated_interpreter_suffix(tmp_path: Path) -> None:
|
|
133
137
|
project_dir = _src_project(tmp_path)
|
|
134
138
|
|
|
135
|
-
generated =
|
|
139
|
+
generated = add_intent_interpreter_cmd(
|
|
140
|
+
project_dir=project_dir,
|
|
141
|
+
intent_name="ingredient-intent-interpreter-interpreter",
|
|
142
|
+
)
|
|
136
143
|
|
|
137
144
|
assert generated.name == "ingredient_intent.py"
|
|
138
|
-
assert "class
|
|
139
|
-
assert "
|
|
145
|
+
assert "class IngredientIntentInterpreter:" in generated.read_text(encoding="utf-8")
|
|
146
|
+
assert "InterpreterInterpreter" not in generated.read_text(encoding="utf-8")
|
|
140
147
|
|
|
141
148
|
|
|
142
149
|
def test_add_entity_supports_legacy_root_layout(tmp_path: Path) -> None:
|
|
@@ -201,8 +208,8 @@ def test_add_usecase_refuses_to_overwrite_existing_inbound_port(tmp_path: Path)
|
|
|
201
208
|
assert not (project_dir / "src" / "demo_service" / "application" / "use_cases" / "recipe.py").exists()
|
|
202
209
|
|
|
203
210
|
|
|
204
|
-
def
|
|
211
|
+
def test_add_intent_interpreter_rejects_invalid_name(tmp_path: Path) -> None:
|
|
205
212
|
project_dir = _src_project(tmp_path)
|
|
206
213
|
|
|
207
214
|
with pytest.raises(typer.Exit):
|
|
208
|
-
|
|
215
|
+
add_intent_interpreter_cmd(project_dir=project_dir, intent_name="123-intent")
|
|
@@ -225,7 +225,7 @@ def test_scaffold_and_run(temp_workspace: Path):
|
|
|
225
225
|
result = subprocess.run(
|
|
226
226
|
[
|
|
227
227
|
"arclith-cli",
|
|
228
|
-
"add-
|
|
228
|
+
"add-intent-interpreter",
|
|
229
229
|
"ShoppingIntent",
|
|
230
230
|
],
|
|
231
231
|
cwd=project_dir,
|
|
@@ -233,9 +233,11 @@ def test_scaffold_and_run(temp_workspace: Path):
|
|
|
233
233
|
text=True,
|
|
234
234
|
timeout=30,
|
|
235
235
|
)
|
|
236
|
-
assert result.returncode == 0,
|
|
236
|
+
assert result.returncode == 0, (
|
|
237
|
+
f"add-intent-interpreter failed:\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}"
|
|
238
|
+
)
|
|
237
239
|
assert (
|
|
238
|
-
project_dir / "src" / "test_plan_service" / "application" / "
|
|
240
|
+
project_dir / "src" / "test_plan_service" / "application" / "intent_interpreters" / "shopping_intent.py"
|
|
239
241
|
).exists()
|
|
240
242
|
|
|
241
243
|
printed_names = ", ".join(
|
|
@@ -243,7 +245,7 @@ def test_scaffold_and_run(temp_workspace: Path):
|
|
|
243
245
|
"ShoppingItem.__name__",
|
|
244
246
|
"PlanShoppingListPort.__name__",
|
|
245
247
|
"PlanShoppingListUseCase.__name__",
|
|
246
|
-
"
|
|
248
|
+
"ShoppingIntentInterpreter.__name__",
|
|
247
249
|
]
|
|
248
250
|
)
|
|
249
251
|
import_script = "\n".join(
|
|
@@ -251,7 +253,7 @@ def test_scaffold_and_run(temp_workspace: Path):
|
|
|
251
253
|
"from test_plan_service.domain.models.shopping_item import ShoppingItem",
|
|
252
254
|
"from test_plan_service.domain.ports.inbound.plan_shopping_list import PlanShoppingListPort",
|
|
253
255
|
"from test_plan_service.application.use_cases.plan_shopping_list import PlanShoppingListUseCase",
|
|
254
|
-
"from test_plan_service.application.
|
|
256
|
+
"from test_plan_service.application.intent_interpreters.shopping_intent import ShoppingIntentInterpreter",
|
|
255
257
|
f"print({printed_names})",
|
|
256
258
|
]
|
|
257
259
|
)
|
|
@@ -269,7 +271,7 @@ def test_scaffold_and_run(temp_workspace: Path):
|
|
|
269
271
|
timeout=30,
|
|
270
272
|
)
|
|
271
273
|
assert result.returncode == 0, f"Core scaffold import failed:\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}"
|
|
272
|
-
assert "ShoppingItem PlanShoppingListPort PlanShoppingListUseCase
|
|
274
|
+
assert "ShoppingItem PlanShoppingListPort PlanShoppingListUseCase ShoppingIntentInterpreter" in result.stdout
|
|
273
275
|
|
|
274
276
|
# Step 7 — validate non-interactive adapter generation through the CLI entry point
|
|
275
277
|
result = subprocess.run(
|
|
@@ -46,7 +46,7 @@ wheels = [
|
|
|
46
46
|
|
|
47
47
|
[[package]]
|
|
48
48
|
name = "arclith"
|
|
49
|
-
version = "0.
|
|
49
|
+
version = "0.15.0"
|
|
50
50
|
source = { editable = "../" }
|
|
51
51
|
dependencies = [
|
|
52
52
|
{ name = "fastapi" },
|
|
@@ -132,7 +132,7 @@ docs = [
|
|
|
132
132
|
|
|
133
133
|
[[package]]
|
|
134
134
|
name = "arclith-cli"
|
|
135
|
-
version = "0.
|
|
135
|
+
version = "0.12.0"
|
|
136
136
|
source = { editable = "." }
|
|
137
137
|
dependencies = [
|
|
138
138
|
{ name = "arclith" },
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.11.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|