levain-cli 0.1.15__tar.gz → 0.1.16__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.
- {levain_cli-0.1.15 → levain_cli-0.1.16}/PKG-INFO +1 -1
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/models.py +0 -4
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/validate.py +1 -53
- {levain_cli-0.1.15 → levain_cli-0.1.16}/pyproject.toml +1 -1
- {levain_cli-0.1.15 → levain_cli-0.1.16}/.gitignore +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/LICENSE +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/README.md +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/__init__.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/__main__.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/_format.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/_java.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/auth.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/cli.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/codegen.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/graph.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/integrations_check.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/known_recipes.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/mcp.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/parser.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/profile.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/py.typed +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/reducers.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/source_check.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/tlc.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/translate.py +0 -0
- {levain_cli-0.1.15 → levain_cli-0.1.16}/levain_recipe/user_input.py +0 -0
|
@@ -134,10 +134,6 @@ class ValidatedSpec:
|
|
|
134
134
|
routing: list[RoutingTable]
|
|
135
135
|
invariants: list[str] = field(default_factory=list)
|
|
136
136
|
constants: dict[str, Any] = field(default_factory=dict)
|
|
137
|
-
# Lanes the recipe splits its turns into (``\* @lanes [...]``):
|
|
138
|
-
# runs in different lanes may share the agent's workspace at the
|
|
139
|
-
# same time. Empty when the recipe runs one turn at a time.
|
|
140
|
-
lanes: list[str] = field(default_factory=list)
|
|
141
137
|
|
|
142
138
|
|
|
143
139
|
@dataclass(frozen=True)
|
|
@@ -6,12 +6,11 @@ validation (PlusCal + Python source + pyproject.toml).
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import json
|
|
10
9
|
import logging
|
|
11
10
|
import os
|
|
12
11
|
import re
|
|
13
12
|
import shutil
|
|
14
|
-
from typing import
|
|
13
|
+
from typing import cast
|
|
15
14
|
|
|
16
15
|
from ._java import resolve_jar
|
|
17
16
|
from .graph import check_graph
|
|
@@ -53,53 +52,6 @@ _RE_COMMENT_PREFIX = re.compile(r"^\\[*]\s?")
|
|
|
53
52
|
# excluded from the free-form description so the help text never
|
|
54
53
|
# accidentally includes machine-readable metadata.
|
|
55
54
|
_RE_ANNOTATION = re.compile(r"^\\[*]\s*@\w+")
|
|
56
|
-
# Module-level ``\* @lanes ["people"]``: the lanes whose turns may run
|
|
57
|
-
# at once on the agent's persistent workspace. ``people`` is the
|
|
58
|
-
# only lane a recipe can split out today; a trigger delivery or a
|
|
59
|
-
# scheduled fire stays in the default lane.
|
|
60
|
-
_RE_LANES = re.compile(r"^\s*\\[*]\s*@lanes\s+(\[.*\])\s*$")
|
|
61
|
-
KNOWN_LANES = frozenset({"people"})
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def extract_lanes(source: str) -> list[str] | ValidationError:
|
|
65
|
-
r"""The lanes a ``\* @lanes`` line declares; ``[]`` without one."""
|
|
66
|
-
found = [
|
|
67
|
-
(n, m.group(1))
|
|
68
|
-
for n, line in enumerate(source.splitlines(), start=1)
|
|
69
|
-
if (m := _RE_LANES.match(line))
|
|
70
|
-
]
|
|
71
|
-
if not found:
|
|
72
|
-
return []
|
|
73
|
-
line_no, raw = found[0]
|
|
74
|
-
lanes: Any = None
|
|
75
|
-
message: str | None
|
|
76
|
-
if len(found) > 1:
|
|
77
|
-
line_no, message = found[1][0], "@lanes may be declared once"
|
|
78
|
-
else:
|
|
79
|
-
try:
|
|
80
|
-
lanes = json.loads(raw)
|
|
81
|
-
except json.JSONDecodeError as e:
|
|
82
|
-
message = f"Invalid @lanes JSON: {e}"
|
|
83
|
-
else:
|
|
84
|
-
message = _lanes_problem(lanes)
|
|
85
|
-
if message:
|
|
86
|
-
return ValidationError(stage="profile", message=message, line=line_no)
|
|
87
|
-
return cast(list[str], lanes)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def _lanes_problem(lanes: Any) -> str | None:
|
|
91
|
-
if (
|
|
92
|
-
not isinstance(lanes, list)
|
|
93
|
-
or not lanes
|
|
94
|
-
or not all(isinstance(s, str) for s in lanes)
|
|
95
|
-
):
|
|
96
|
-
return "@lanes must be a non-empty JSON list of strings"
|
|
97
|
-
unknown = sorted(set(lanes) - KNOWN_LANES)
|
|
98
|
-
if unknown:
|
|
99
|
-
return f"Unknown lane(s) {unknown}; known: {sorted(KNOWN_LANES)}"
|
|
100
|
-
if len(set(lanes)) != len(lanes):
|
|
101
|
-
return "@lanes repeats a lane"
|
|
102
|
-
return None
|
|
103
55
|
|
|
104
56
|
|
|
105
57
|
def validate(
|
|
@@ -178,9 +130,6 @@ def validate_fast( # noqa: PLR0911
|
|
|
178
130
|
|
|
179
131
|
constants = extract_constants(algo)
|
|
180
132
|
invariants = [d for d in extract_defines(algo) if d not in constants]
|
|
181
|
-
lanes = extract_lanes(source)
|
|
182
|
-
if isinstance(lanes, ValidationError):
|
|
183
|
-
return [lanes]
|
|
184
133
|
|
|
185
134
|
# Stage 3: Graph check. Tell the reachability check that
|
|
186
135
|
# ``interrupt`` nodes count as termination — a chat-shape
|
|
@@ -228,7 +177,6 @@ def validate_fast( # noqa: PLR0911
|
|
|
228
177
|
routing=routing,
|
|
229
178
|
invariants=invariants,
|
|
230
179
|
constants=constants,
|
|
231
|
-
lanes=lanes,
|
|
232
180
|
)
|
|
233
181
|
|
|
234
182
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|