Skip to content

Commit 54d88c0

Browse files
randclaude
andcommitted
fix: add rlm_core Python stub package for maturin 1.12 compatibility
Maturin 1.12 (PR #2986) changed the behavior of python-source config: a missing Python module directory is now an error instead of a warning. This broke wheel builds since rlm_core/ didn't exist as a Python package. Creates a proper rlm_core/ package with: - __init__.py: re-exports all types from compiled extension with graceful ImportError - py.typed: PEP 561 marker for type checker discovery - Comprehensive .pyi type stubs for all 50+ PyO3-exported classes across context, memory, LLM, trajectory, complexity, and epistemic modules Bumps version to 0.7.2. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2268cb0 commit 54d88c0

14 files changed

Lines changed: 698 additions & 4 deletions

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"name": "rlm-claude-code",
1111
"source": "./",
1212
"description": "Recursive Language Model integration for Claude Code - Go binary hooks (~5ms startup), cross-plugin event coordination (DP/RLM), version-aware config migration, and intelligent multi-provider routing",
13-
"version": "0.7.1"
13+
"version": "0.7.2"
1414
}
1515
]
1616
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rlm-claude-code",
33
"description": "Recursive Language Model integration for Claude Code - intelligent multi-provider routing and unbounded context handling",
4-
"version": "0.7.1",
4+
"version": "0.7.2",
55
"author": {
66
"name": "Rand",
77
"url": "https://github.com/rand"

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## [0.7.2] - 2026-02-19
4+
5+
### Fixed
6+
- **maturin 1.12 build compatibility**: Created `rlm_core/` Python stub package to satisfy `python-source = "."` config (maturin 1.12 changed missing module directory from warning to error)
7+
- Added PEP 561 `py.typed` marker and comprehensive `.pyi` type stubs for all PyO3-exported types (context, memory, LLM, trajectory, complexity, epistemic)
8+
9+
### Added
10+
- Full IDE type support for `rlm_core` native extension (autocompletion, type checking)
11+
312
## [0.7.1] - 2026-02-19
413

514
### Fixed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "rlm-claude-code"
3-
version = "0.7.1"
3+
version = "0.7.2"
44
description = "Recursive Language Model integration for Claude Code"
55
readme = "README.md"
66
requires-python = ">=3.12"

rlm_core/__init__.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""rlm_core — Rust-native RLM orchestration library with Python bindings.
2+
3+
This package provides Python access to the rlm-core Rust library via PyO3.
4+
All types are defined in the compiled extension module; this file re-exports
5+
them for convenient access and provides a graceful error message if the
6+
native extension is unavailable.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
try:
12+
from rlm_core.rlm_core import * # noqa: F401, F403
13+
from rlm_core.rlm_core import (
14+
# Module-level functions
15+
available_features,
16+
has_feature,
17+
quick_hallucination_check,
18+
version,
19+
version_tuple,
20+
# Context
21+
Message,
22+
Role,
23+
SessionContext,
24+
ToolOutput,
25+
# Memory
26+
HyperEdge,
27+
MemoryStats,
28+
MemoryStore,
29+
Node,
30+
NodeType,
31+
Tier,
32+
# LLM
33+
ChatMessage,
34+
CompletionRequest,
35+
CompletionResponse,
36+
CostTracker,
37+
ModelSpec,
38+
ModelTier,
39+
Provider,
40+
QueryType,
41+
RoutingContext,
42+
RoutingDecision,
43+
SmartRouter,
44+
TokenUsage,
45+
# Trajectory
46+
TrajectoryEvent,
47+
TrajectoryEventType,
48+
# Complexity
49+
ActivationDecision,
50+
PatternClassifier,
51+
# Epistemic
52+
BudgetResult,
53+
Claim,
54+
ClaimCategory,
55+
ClaimExtractor,
56+
EvidenceRef,
57+
EvidenceType,
58+
GroundingStatus,
59+
KL,
60+
Probability,
61+
VerificationConfig,
62+
VerificationStats,
63+
VerificationVerdict,
64+
)
65+
except ImportError as _e:
66+
_msg = (
67+
"rlm_core native extension is not available. "
68+
"This typically means the Rust library was not compiled for your platform. "
69+
"Install from a pre-built wheel: pip install rlm-claude-code\n"
70+
f"Original error: {_e}"
71+
)
72+
raise ImportError(_msg) from _e
73+
74+
__all__ = [
75+
# Functions
76+
"available_features",
77+
"has_feature",
78+
"quick_hallucination_check",
79+
"version",
80+
"version_tuple",
81+
# Context
82+
"Message",
83+
"Role",
84+
"SessionContext",
85+
"ToolOutput",
86+
# Memory
87+
"HyperEdge",
88+
"MemoryStats",
89+
"MemoryStore",
90+
"Node",
91+
"NodeType",
92+
"Tier",
93+
# LLM
94+
"ChatMessage",
95+
"CompletionRequest",
96+
"CompletionResponse",
97+
"CostTracker",
98+
"ModelSpec",
99+
"ModelTier",
100+
"Provider",
101+
"QueryType",
102+
"RoutingContext",
103+
"RoutingDecision",
104+
"SmartRouter",
105+
"TokenUsage",
106+
# Trajectory
107+
"TrajectoryEvent",
108+
"TrajectoryEventType",
109+
# Complexity
110+
"ActivationDecision",
111+
"PatternClassifier",
112+
# Epistemic
113+
"BudgetResult",
114+
"Claim",
115+
"ClaimCategory",
116+
"ClaimExtractor",
117+
"EvidenceRef",
118+
"EvidenceType",
119+
"GroundingStatus",
120+
"KL",
121+
"Probability",
122+
"VerificationConfig",
123+
"VerificationStats",
124+
"VerificationVerdict",
125+
]

rlm_core/__init__.pyi

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Type stubs for the rlm_core native extension module."""
2+
3+
from __future__ import annotations
4+
5+
# Re-export everything from submodules for flat access
6+
from rlm_core._context import Message as Message
7+
from rlm_core._context import Role as Role
8+
from rlm_core._context import SessionContext as SessionContext
9+
from rlm_core._context import ToolOutput as ToolOutput
10+
from rlm_core._memory import HyperEdge as HyperEdge
11+
from rlm_core._memory import MemoryStats as MemoryStats
12+
from rlm_core._memory import MemoryStore as MemoryStore
13+
from rlm_core._memory import Node as Node
14+
from rlm_core._memory import NodeType as NodeType
15+
from rlm_core._memory import Tier as Tier
16+
from rlm_core._llm import ChatMessage as ChatMessage
17+
from rlm_core._llm import CompletionRequest as CompletionRequest
18+
from rlm_core._llm import CompletionResponse as CompletionResponse
19+
from rlm_core._llm import CostTracker as CostTracker
20+
from rlm_core._llm import ModelSpec as ModelSpec
21+
from rlm_core._llm import ModelTier as ModelTier
22+
from rlm_core._llm import Provider as Provider
23+
from rlm_core._llm import QueryType as QueryType
24+
from rlm_core._llm import RoutingContext as RoutingContext
25+
from rlm_core._llm import RoutingDecision as RoutingDecision
26+
from rlm_core._llm import SmartRouter as SmartRouter
27+
from rlm_core._llm import TokenUsage as TokenUsage
28+
from rlm_core._trajectory import TrajectoryEvent as TrajectoryEvent
29+
from rlm_core._trajectory import TrajectoryEventType as TrajectoryEventType
30+
from rlm_core._complexity import ActivationDecision as ActivationDecision
31+
from rlm_core._complexity import PatternClassifier as PatternClassifier
32+
from rlm_core._epistemic import BudgetResult as BudgetResult
33+
from rlm_core._epistemic import Claim as Claim
34+
from rlm_core._epistemic import ClaimCategory as ClaimCategory
35+
from rlm_core._epistemic import ClaimExtractor as ClaimExtractor
36+
from rlm_core._epistemic import EvidenceRef as EvidenceRef
37+
from rlm_core._epistemic import EvidenceType as EvidenceType
38+
from rlm_core._epistemic import GroundingStatus as GroundingStatus
39+
from rlm_core._epistemic import KL as KL
40+
from rlm_core._epistemic import Probability as Probability
41+
from rlm_core._epistemic import VerificationConfig as VerificationConfig
42+
from rlm_core._epistemic import VerificationStats as VerificationStats
43+
from rlm_core._epistemic import VerificationVerdict as VerificationVerdict
44+
45+
def version() -> str: ...
46+
def version_tuple() -> tuple[int, int, int]: ...
47+
def has_feature(feature_name: str) -> bool: ...
48+
def available_features() -> list[str]: ...
49+
def quick_hallucination_check(response: str) -> float: ...

rlm_core/_complexity.pyi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from __future__ import annotations
2+
3+
from rlm_core._context import SessionContext
4+
5+
class ActivationDecision:
6+
should_activate: bool
7+
reason: str
8+
score: int
9+
10+
class PatternClassifier:
11+
def __init__(self) -> None: ...
12+
def should_activate(self, query: str, context: SessionContext) -> ActivationDecision: ...

rlm_core/_context.pyi

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from __future__ import annotations
2+
3+
from typing import Any
4+
5+
class Role:
6+
User: Role
7+
Assistant: Role
8+
System: Role
9+
Tool: Role
10+
11+
class Message:
12+
role: Role
13+
content: str
14+
timestamp: str | None
15+
16+
def __init__(self, role: Role, content: str, timestamp: str | None = None) -> None: ...
17+
@staticmethod
18+
def user(content: str) -> Message: ...
19+
@staticmethod
20+
def assistant(content: str) -> Message: ...
21+
@staticmethod
22+
def system(content: str) -> Message: ...
23+
@staticmethod
24+
def tool(content: str) -> Message: ...
25+
26+
class ToolOutput:
27+
tool_name: str
28+
content: str
29+
exit_code: int | None
30+
timestamp: str | None
31+
32+
def __init__(self, tool_name: str, content: str, exit_code: int | None = None) -> None: ...
33+
def is_success(self) -> bool: ...
34+
35+
class SessionContext:
36+
def __init__(self) -> None: ...
37+
def add_message(self, message: Message) -> None: ...
38+
def add_user_message(self, content: str) -> None: ...
39+
def add_assistant_message(self, content: str) -> None: ...
40+
def cache_file(self, path: str, content: str) -> None: ...
41+
def add_tool_output(self, output: ToolOutput) -> None: ...
42+
def set_memory(self, key: str, value: Any) -> None: ...
43+
def get_memory(self, key: str) -> Any: ...
44+
def messages(self) -> list[Message]: ...
45+
def last_messages(self, n: int) -> list[Message]: ...
46+
def files(self) -> dict[str, str]: ...
47+
def get_file(self, path: str) -> str | None: ...
48+
def tool_outputs(self) -> list[ToolOutput]: ...
49+
def message_count(self) -> int: ...
50+
def file_count(self) -> int: ...
51+
def spans_multiple_directories(self) -> bool: ...
52+
def total_message_tokens(self) -> int: ...

0 commit comments

Comments
 (0)