roadmodel 0.2.1__tar.gz → 0.2.2__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.
- {roadmodel-0.2.1 → roadmodel-0.2.2}/PKG-INFO +1 -1
- {roadmodel-0.2.1 → roadmodel-0.2.2}/pyproject.toml +1 -1
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/__init__.py +1 -1
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/recommend.py +14 -2
- {roadmodel-0.2.1 → roadmodel-0.2.2}/.gitignore +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/LICENSE +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/NOTICE +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/README.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/docs/catalog.json +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/docs/model-selector.txt +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/docs/model-tier-cost-scale.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/docs/templates/phase-roadmap-template.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/docs/user-context.example.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/hatch_build.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/infra/README.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/infra/supabase/README.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/roadmodel/data/catalog.json +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/roadmodel/data/model-selector.txt +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/roadmodel/data/model-tier-cost-scale.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/roadmodel/data/phase-roadmap-template.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/roadmodel/data/user-context.example.md +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/__main__.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/cli.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/config.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/cost.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/errors.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/mcp_server.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/providers/__init__.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/providers/anthropic.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/providers/google.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/providers/openai.py +0 -0
- {roadmodel-0.2.1 → roadmodel-0.2.2}/src/roadmodel/user_context.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roadmodel
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: BYO-key CLI that recommends the right AI model, platform, and settings for a prompt.
|
|
5
5
|
Project-URL: Homepage, https://roadmodel.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/nathanramoscfa/roadmodel
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# src/roadmodel/__init__.py
|
|
2
|
-
__version__ = "0.2.
|
|
2
|
+
__version__ = "0.2.2"
|
|
@@ -24,12 +24,19 @@ BUNDLED_USER_CONTEXT_TEMPLATE_PATH: Traversable = (
|
|
|
24
24
|
|
|
25
25
|
_REQUIRED_KEYS: Final = ("model", "platform", "max_mode", "thinking", "conversation", "rationale")
|
|
26
26
|
|
|
27
|
+
# ORCHESTRATION is optional in the response block: the bundled selector
|
|
28
|
+
# emits it on Claude Code surfaces (Ultracode), and not at all elsewhere.
|
|
29
|
+
# Pre-orchestration responses (and any provider that omits the line) must
|
|
30
|
+
# still parse, so the line is wrapped in a non-capturing optional group.
|
|
31
|
+
# The captured value is intentionally not propagated into the parsed dict
|
|
32
|
+
# yet — surfacing it via recommend_structured is a separate change.
|
|
27
33
|
_RESPONSE_BLOCK_RE: Final = re.compile(
|
|
28
34
|
r"(?:^\s*PROMPT:\s*[^\n]*\n\s*)*"
|
|
29
35
|
r"MODEL:\s*(?P<model>[^\n]+)\s*\n"
|
|
30
36
|
r"PLATFORM:\s*(?P<platform>[^\n]+)\s*\n"
|
|
31
37
|
r"MAX\s+MODE:\s*(?P<max_mode>[^\n]+)\s*\n"
|
|
32
38
|
r"THINKING:\s*(?P<thinking>[^\n]+)\s*\n"
|
|
39
|
+
r"(?:ORCHESTRATION:\s*(?P<orchestration>[^\n]+)\s*\n)?"
|
|
33
40
|
r"CONVERSATION:\s*(?P<conversation>[^\n]+)\s*\n"
|
|
34
41
|
r"RATIONALE:\s*(?P<rationale>.+?)(?=\n\s*(?:PROMPT:|MODEL:)|\Z)",
|
|
35
42
|
flags=re.IGNORECASE | re.MULTILINE | re.DOTALL,
|
|
@@ -100,9 +107,14 @@ def parse_response(text: str) -> dict[str, str]:
|
|
|
100
107
|
|
|
101
108
|
regex_match = _RESPONSE_BLOCK_RE.search(text)
|
|
102
109
|
if regex_match:
|
|
103
|
-
|
|
110
|
+
# The ORCHESTRATION group is optional and captures None when absent;
|
|
111
|
+
# coerce None → "" so .strip() doesn't crash. orchestration is
|
|
112
|
+
# consumed silently — not yet surfaced via the returned dict.
|
|
113
|
+
parsed_block = {
|
|
114
|
+
key: (value.strip() if value else "") for key, value in regex_match.groupdict().items()
|
|
115
|
+
}
|
|
104
116
|
if all(parsed_block.get(key) for key in _REQUIRED_KEYS):
|
|
105
|
-
return parsed_block
|
|
117
|
+
return {key: parsed_block[key] for key in _REQUIRED_KEYS}
|
|
106
118
|
|
|
107
119
|
raise MalformedResponseError(text)
|
|
108
120
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|