lm-deluge 0.0.67__py3-none-any.whl → 0.0.88__py3-none-any.whl
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.
Potentially problematic release.
This version of lm-deluge might be problematic. Click here for more details.
- lm_deluge/__init__.py +25 -2
- lm_deluge/api_requests/anthropic.py +92 -17
- lm_deluge/api_requests/base.py +47 -11
- lm_deluge/api_requests/bedrock.py +7 -4
- lm_deluge/api_requests/chat_reasoning.py +4 -0
- lm_deluge/api_requests/gemini.py +138 -18
- lm_deluge/api_requests/openai.py +114 -21
- lm_deluge/client.py +282 -49
- lm_deluge/config.py +15 -3
- lm_deluge/mock_openai.py +643 -0
- lm_deluge/models/__init__.py +12 -1
- lm_deluge/models/anthropic.py +17 -2
- lm_deluge/models/arcee.py +16 -0
- lm_deluge/models/deepseek.py +36 -4
- lm_deluge/models/google.py +29 -0
- lm_deluge/models/grok.py +24 -0
- lm_deluge/models/kimi.py +36 -0
- lm_deluge/models/minimax.py +10 -0
- lm_deluge/models/openai.py +100 -0
- lm_deluge/models/openrouter.py +86 -8
- lm_deluge/models/together.py +11 -0
- lm_deluge/models/zai.py +1 -0
- lm_deluge/pipelines/gepa/__init__.py +95 -0
- lm_deluge/pipelines/gepa/core.py +354 -0
- lm_deluge/pipelines/gepa/docs/samples.py +696 -0
- lm_deluge/pipelines/gepa/examples/01_synthetic_keywords.py +140 -0
- lm_deluge/pipelines/gepa/examples/02_gsm8k_math.py +261 -0
- lm_deluge/pipelines/gepa/examples/03_hotpotqa_multihop.py +300 -0
- lm_deluge/pipelines/gepa/examples/04_batch_classification.py +271 -0
- lm_deluge/pipelines/gepa/examples/simple_qa.py +129 -0
- lm_deluge/pipelines/gepa/optimizer.py +435 -0
- lm_deluge/pipelines/gepa/proposer.py +235 -0
- lm_deluge/pipelines/gepa/util.py +165 -0
- lm_deluge/{llm_tools → pipelines}/score.py +2 -2
- lm_deluge/{llm_tools → pipelines}/translate.py +5 -3
- lm_deluge/prompt.py +224 -40
- lm_deluge/request_context.py +7 -2
- lm_deluge/tool/__init__.py +1118 -0
- lm_deluge/tool/builtin/anthropic/__init__.py +300 -0
- lm_deluge/tool/builtin/gemini.py +59 -0
- lm_deluge/tool/builtin/openai.py +74 -0
- lm_deluge/tool/cua/__init__.py +173 -0
- lm_deluge/tool/cua/actions.py +148 -0
- lm_deluge/tool/cua/base.py +27 -0
- lm_deluge/tool/cua/batch.py +215 -0
- lm_deluge/tool/cua/converters.py +466 -0
- lm_deluge/tool/cua/kernel.py +702 -0
- lm_deluge/tool/cua/trycua.py +989 -0
- lm_deluge/tool/prefab/__init__.py +45 -0
- lm_deluge/tool/prefab/batch_tool.py +156 -0
- lm_deluge/tool/prefab/docs.py +1119 -0
- lm_deluge/tool/prefab/email.py +294 -0
- lm_deluge/tool/prefab/filesystem.py +1711 -0
- lm_deluge/tool/prefab/full_text_search/__init__.py +285 -0
- lm_deluge/tool/prefab/full_text_search/tantivy_index.py +396 -0
- lm_deluge/tool/prefab/memory.py +458 -0
- lm_deluge/tool/prefab/otc/__init__.py +165 -0
- lm_deluge/tool/prefab/otc/executor.py +281 -0
- lm_deluge/tool/prefab/otc/parse.py +188 -0
- lm_deluge/tool/prefab/random.py +212 -0
- lm_deluge/tool/prefab/rlm/__init__.py +296 -0
- lm_deluge/tool/prefab/rlm/executor.py +349 -0
- lm_deluge/tool/prefab/rlm/parse.py +144 -0
- lm_deluge/tool/prefab/sandbox.py +1621 -0
- lm_deluge/tool/prefab/sheets.py +385 -0
- lm_deluge/tool/prefab/subagents.py +233 -0
- lm_deluge/tool/prefab/todos.py +342 -0
- lm_deluge/tool/prefab/tool_search.py +169 -0
- lm_deluge/tool/prefab/web_search.py +199 -0
- lm_deluge/tracker.py +16 -13
- lm_deluge/util/schema.py +412 -0
- lm_deluge/warnings.py +8 -0
- {lm_deluge-0.0.67.dist-info → lm_deluge-0.0.88.dist-info}/METADATA +22 -9
- lm_deluge-0.0.88.dist-info/RECORD +117 -0
- lm_deluge/built_in_tools/anthropic/__init__.py +0 -128
- lm_deluge/built_in_tools/openai.py +0 -28
- lm_deluge/presets/cerebras.py +0 -17
- lm_deluge/presets/meta.py +0 -13
- lm_deluge/tool.py +0 -849
- lm_deluge-0.0.67.dist-info/RECORD +0 -72
- lm_deluge/{llm_tools → pipelines}/__init__.py +1 -1
- /lm_deluge/{llm_tools → pipelines}/classify.py +0 -0
- /lm_deluge/{llm_tools → pipelines}/extract.py +0 -0
- /lm_deluge/{llm_tools → pipelines}/locate.py +0 -0
- /lm_deluge/{llm_tools → pipelines}/ocr.py +0 -0
- /lm_deluge/{built_in_tools → tool/builtin}/anthropic/bash.py +0 -0
- /lm_deluge/{built_in_tools → tool/builtin}/anthropic/computer_use.py +0 -0
- /lm_deluge/{built_in_tools → tool/builtin}/anthropic/editor.py +0 -0
- /lm_deluge/{built_in_tools → tool/builtin}/base.py +0 -0
- {lm_deluge-0.0.67.dist-info → lm_deluge-0.0.88.dist-info}/WHEEL +0 -0
- {lm_deluge-0.0.67.dist-info → lm_deluge-0.0.88.dist-info}/licenses/LICENSE +0 -0
- {lm_deluge-0.0.67.dist-info → lm_deluge-0.0.88.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RLM (Recursive Language Model) code parsing and validation.
|
|
3
|
+
|
|
4
|
+
Extends OTC's security model with additional modules for context analysis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import ast
|
|
8
|
+
import collections
|
|
9
|
+
import json
|
|
10
|
+
import math
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
# Import OTC's base security definitions
|
|
14
|
+
from ..otc.parse import (
|
|
15
|
+
FORBIDDEN_CALLS,
|
|
16
|
+
SAFE_BUILTINS,
|
|
17
|
+
ASTValidator,
|
|
18
|
+
OTCSecurityError,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# RLM uses the same builtins as OTC
|
|
22
|
+
RLM_SAFE_BUILTINS = SAFE_BUILTINS.copy()
|
|
23
|
+
|
|
24
|
+
# Modules available in RLM - imports of these are stripped (no-ops)
|
|
25
|
+
RLM_ALLOWED_IMPORTS = {"re", "math", "collections", "json"}
|
|
26
|
+
|
|
27
|
+
# Modules and common imports available in RLM (injected into globals)
|
|
28
|
+
RLM_MODULES = {
|
|
29
|
+
# Full modules
|
|
30
|
+
"re": re,
|
|
31
|
+
"math": math,
|
|
32
|
+
"collections": collections,
|
|
33
|
+
"json": json,
|
|
34
|
+
# Common imports from collections
|
|
35
|
+
"Counter": collections.Counter,
|
|
36
|
+
"defaultdict": collections.defaultdict,
|
|
37
|
+
"deque": collections.deque,
|
|
38
|
+
"namedtuple": collections.namedtuple,
|
|
39
|
+
"OrderedDict": collections.OrderedDict,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RLMSecurityError(OTCSecurityError):
|
|
44
|
+
"""Raised when RLM code violates security constraints."""
|
|
45
|
+
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class RLMExecutionError(Exception):
|
|
50
|
+
"""Raised when RLM code execution fails."""
|
|
51
|
+
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class RLMASTValidator(ASTValidator):
|
|
56
|
+
"""Validates RLM code with additional checks.
|
|
57
|
+
|
|
58
|
+
Import statements for allowed modules are stripped (no-ops).
|
|
59
|
+
Imports of disallowed modules raise errors.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(self, allowed_names: set[str] | None = None):
|
|
63
|
+
super().__init__(allowed_tool_names=set())
|
|
64
|
+
self.allowed_names = allowed_names or set()
|
|
65
|
+
|
|
66
|
+
def visit(self, node: ast.AST) -> None:
|
|
67
|
+
# Check imports - allowed ones will be stripped later, disallowed ones error
|
|
68
|
+
if isinstance(node, ast.Import):
|
|
69
|
+
for alias in node.names:
|
|
70
|
+
if alias.name not in RLM_ALLOWED_IMPORTS:
|
|
71
|
+
self.errors.append(
|
|
72
|
+
f"Forbidden import: {alias.name} at line {node.lineno}. "
|
|
73
|
+
f"Available modules: {', '.join(sorted(RLM_ALLOWED_IMPORTS))}"
|
|
74
|
+
)
|
|
75
|
+
self.generic_visit(node)
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
if isinstance(node, ast.ImportFrom):
|
|
79
|
+
if node.module not in RLM_ALLOWED_IMPORTS:
|
|
80
|
+
self.errors.append(
|
|
81
|
+
f"Forbidden import: from {node.module} at line {node.lineno}. "
|
|
82
|
+
f"Available modules: {', '.join(sorted(RLM_ALLOWED_IMPORTS))}"
|
|
83
|
+
)
|
|
84
|
+
self.generic_visit(node)
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
# For all other nodes, use parent validation
|
|
88
|
+
super().visit(node)
|
|
89
|
+
|
|
90
|
+
def visit_Call(self, node: ast.Call) -> None:
|
|
91
|
+
if isinstance(node.func, ast.Name):
|
|
92
|
+
if node.func.id in FORBIDDEN_CALLS:
|
|
93
|
+
self.errors.append(
|
|
94
|
+
f"Forbidden function call: {node.func.id} at line {node.lineno}"
|
|
95
|
+
)
|
|
96
|
+
self.generic_visit(node)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ImportStripper(ast.NodeTransformer):
|
|
100
|
+
"""Strips import statements for allowed modules from the AST."""
|
|
101
|
+
|
|
102
|
+
def visit_Import(self, node: ast.Import) -> ast.AST | None:
|
|
103
|
+
# Keep only imports of non-allowed modules (which will error at validation)
|
|
104
|
+
remaining = [
|
|
105
|
+
alias for alias in node.names if alias.name not in RLM_ALLOWED_IMPORTS
|
|
106
|
+
]
|
|
107
|
+
if not remaining:
|
|
108
|
+
return None # Remove the entire import statement
|
|
109
|
+
node.names = remaining
|
|
110
|
+
return node
|
|
111
|
+
|
|
112
|
+
def visit_ImportFrom(self, node: ast.ImportFrom) -> ast.AST | None:
|
|
113
|
+
# Strip imports from allowed modules
|
|
114
|
+
if node.module in RLM_ALLOWED_IMPORTS:
|
|
115
|
+
return None # Remove the entire import statement
|
|
116
|
+
return node
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def validate_rlm_code(code: str) -> ast.Module:
|
|
120
|
+
"""Parse and validate RLM code, returning AST if valid.
|
|
121
|
+
|
|
122
|
+
Import statements for allowed modules (re, math, collections, json) are
|
|
123
|
+
stripped from the AST since these modules are already in the namespace.
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
tree = ast.parse(code)
|
|
127
|
+
except SyntaxError as e:
|
|
128
|
+
raise RLMSecurityError(f"Syntax error: {e}")
|
|
129
|
+
|
|
130
|
+
# Validate first (before stripping)
|
|
131
|
+
validator = RLMASTValidator()
|
|
132
|
+
errors = validator.validate(tree)
|
|
133
|
+
|
|
134
|
+
if errors:
|
|
135
|
+
raise RLMSecurityError(
|
|
136
|
+
"Security violations:\n" + "\n".join(f" - {e}" for e in errors)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Strip allowed imports (they're no-ops since modules are pre-loaded)
|
|
140
|
+
stripper = ImportStripper()
|
|
141
|
+
tree = stripper.visit(tree)
|
|
142
|
+
ast.fix_missing_locations(tree)
|
|
143
|
+
|
|
144
|
+
return tree
|