lmnr 0.2.8__py3-none-any.whl → 0.2.10__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.
lmnr/__init__.py CHANGED
@@ -1,8 +1,4 @@
1
1
  from .sdk.endpoint import Laminar
2
- from .types import (
3
- ChatMessage,
4
- EndpointRunError,
5
- EndpointRunResponse,
6
- NodeInput
7
- )
8
- from .sdk.remote_debugger import RemoteDebugger as LaminarRemoteDebugger
2
+ from .types import ChatMessage, EndpointRunError, EndpointRunResponse, NodeInput
3
+ from .sdk.remote_debugger import RemoteDebugger as LaminarRemoteDebugger
4
+ from .sdk.registry import Registry as Pipeline
lmnr/cli/cli.py CHANGED
@@ -1,3 +1,4 @@
1
+ from pathlib import Path
1
2
  import requests
2
3
  from dotenv import load_dotenv
3
4
  import os
@@ -6,6 +7,8 @@ import logging
6
7
  from cookiecutter.main import cookiecutter
7
8
  from pydantic.alias_generators import to_pascal
8
9
 
10
+ from lmnr.cli.zip import zip_directory
11
+
9
12
  from .parser.parser import runnable_graph_to_template_vars
10
13
 
11
14
  logger = logging.getLogger(__name__)
@@ -92,3 +95,42 @@ def pull(pipeline_name, pipeline_version_name, project_api_key, loglevel):
92
95
  no_input=True,
93
96
  overwrite_if_exists=True,
94
97
  )
98
+
99
+
100
+ @cli.command(name="deploy")
101
+ @click.argument("endpoint_id")
102
+ @click.option(
103
+ "-p",
104
+ "--project-api-key",
105
+ help="Project API key",
106
+ )
107
+ def deploy(endpoint_id, project_api_key):
108
+ project_api_key = project_api_key or os.environ.get("LMNR_PROJECT_API_KEY")
109
+ if not project_api_key:
110
+ load_dotenv()
111
+ project_api_key = os.environ.get("LMNR_PROJECT_API_KEY")
112
+ if not project_api_key:
113
+ raise ValueError("LMNR_PROJECT_API_KEY is not set")
114
+
115
+ current_directory = Path.cwd()
116
+ zip_file_path = current_directory / "archive.zip"
117
+
118
+ zip_directory(current_directory, zip_file_path)
119
+
120
+ try:
121
+ url = f"https://api.lmnr.ai/v2/endpoints/{endpoint_id}/deploy-code"
122
+ with open(zip_file_path, "rb") as f:
123
+ headers = {
124
+ "Authorization": f"Bearer {project_api_key}",
125
+ }
126
+ files = {"file": f}
127
+ response = requests.post(url, headers=headers, files=files)
128
+
129
+ if response.status_code != 200:
130
+ raise ValueError(
131
+ f"Error in deploying code: {response.status_code}\n{response.text}"
132
+ )
133
+ except Exception:
134
+ logging.exception("Error in deploying code")
135
+ finally:
136
+ Path.unlink(zip_file_path, missing_ok=True)
@@ -4,21 +4,16 @@ from typing import Optional
4
4
  import uuid
5
5
 
6
6
 
7
- HandleType = str # "String" | "ChatMessageList" | "Any"
8
-
9
-
10
7
  @dataclass
11
8
  class Handle:
12
9
  id: uuid.UUID
13
10
  name: Optional[str]
14
- type: HandleType
15
11
 
16
12
  @classmethod
17
13
  def from_dict(cls, dict: dict) -> "Handle":
18
14
  return cls(
19
15
  id=uuid.UUID(dict["id"]),
20
16
  name=(dict["name"] if "name" in dict else None),
21
- type=dict["type"],
22
17
  )
23
18
 
24
19
 
@@ -12,6 +12,8 @@ class CodeNode(NodeFunctions):
12
12
  inputs: list[Handle]
13
13
  outputs: list[Handle]
14
14
  inputs_mappings: dict[uuid.UUID, uuid.UUID]
15
+ code: str
16
+ fn_name: str
15
17
 
16
18
  def handles_mapping(
17
19
  self, output_handle_id_to_node_name: dict[str, str]
@@ -24,4 +26,11 @@ class CodeNode(NodeFunctions):
24
26
  return "Code"
25
27
 
26
28
  def config(self) -> dict:
27
- return {}
29
+ return {
30
+ "code": self.code,
31
+ "fn_name": self.fn_name,
32
+ "fn_inputs": ", ".join(
33
+ f"{handle.name}=input_to_code_node_arg({handle.name})"
34
+ for handle in self.inputs
35
+ ),
36
+ }
@@ -2,7 +2,7 @@ from dataclasses import dataclass
2
2
  from typing import Optional
3
3
  import uuid
4
4
 
5
- from lmnr.cli.parser.nodes import Handle, HandleType, NodeFunctions
5
+ from lmnr.cli.parser.nodes import Handle, NodeFunctions
6
6
  from lmnr.types import NodeInput
7
7
 
8
8
 
@@ -12,7 +12,6 @@ class InputNode(NodeFunctions):
12
12
  name: str
13
13
  outputs: list[Handle]
14
14
  input: Optional[NodeInput]
15
- input_type: HandleType
16
15
 
17
16
  def handles_mapping(
18
17
  self, output_handle_id_to_node_name: dict[str, str]
@@ -0,0 +1,29 @@
1
+ from dataclasses import dataclass
2
+
3
+ import uuid
4
+
5
+ from lmnr.cli.parser.nodes import Handle, NodeFunctions
6
+ from lmnr.cli.parser.utils import map_handles
7
+
8
+
9
+ @dataclass
10
+ class JsonExtractorNode(NodeFunctions):
11
+ id: uuid.UUID
12
+ name: str
13
+ inputs: list[Handle]
14
+ outputs: list[Handle]
15
+ inputs_mappings: dict[uuid.UUID, uuid.UUID]
16
+ template: str
17
+
18
+ def handles_mapping(
19
+ self, output_handle_id_to_node_name: dict[str, str]
20
+ ) -> list[tuple[str, str]]:
21
+ return map_handles(
22
+ self.inputs, self.inputs_mappings, output_handle_id_to_node_name
23
+ )
24
+
25
+ def node_type(self) -> str:
26
+ return "JsonExtractor"
27
+
28
+ def config(self) -> dict:
29
+ return {"template": self.template}
@@ -44,8 +44,13 @@ class LLMNode(NodeFunctions):
44
44
  "model": model,
45
45
  "model_params": self.model_params,
46
46
  "stream": self.stream,
47
- "structured_output_enabled": self.structured_output_enabled,
47
+ "enable_structured_output": self.structured_output_enabled
48
+ and self.structured_output_schema is not None,
48
49
  "structured_output_max_retries": self.structured_output_max_retries,
49
50
  "structured_output_schema": self.structured_output_schema,
50
- "structured_output_schema_target": self.structured_output_schema_target,
51
+ "structured_output_schema_target_str": (
52
+ "None"
53
+ if self.structured_output_schema_target is None
54
+ else f'"{self.structured_output_schema_target}"'
55
+ ),
51
56
  }
@@ -5,6 +5,7 @@ from lmnr.cli.parser.nodes import Handle
5
5
  from lmnr.cli.parser.nodes.code import CodeNode
6
6
  from lmnr.cli.parser.nodes.condition import ConditionNode
7
7
  from lmnr.cli.parser.nodes.input import InputNode
8
+ from lmnr.cli.parser.nodes.json_extractor import JsonExtractorNode
8
9
  from lmnr.cli.parser.nodes.llm import LLMNode
9
10
  from lmnr.cli.parser.nodes.output import OutputNode
10
11
  from lmnr.cli.parser.nodes.router import Route, RouterNode
@@ -32,6 +33,7 @@ Node = Union[
32
33
  RouterNode,
33
34
  SemanticSearchNode,
34
35
  CodeNode,
36
+ JsonExtractorNode,
35
37
  ]
36
38
 
37
39
 
@@ -42,7 +44,6 @@ def node_from_dict(node_dict: dict) -> Node:
42
44
  name=node_dict["name"],
43
45
  outputs=[Handle.from_dict(handle) for handle in node_dict["outputs"]],
44
46
  input=node_input_from_json(node_dict["input"]),
45
- input_type=node_dict["inputType"],
46
47
  )
47
48
  elif node_dict["type"] == "Output":
48
49
  return OutputNode(
@@ -86,11 +87,14 @@ def node_from_dict(node_dict: dict) -> Node:
86
87
  node_dict["modelParams"] if "modelParams" in node_dict else None
87
88
  ),
88
89
  stream=False,
89
- # TODO: Implement structured output
90
- structured_output_enabled=False,
91
- structured_output_max_retries=3,
92
- structured_output_schema=None,
93
- structured_output_schema_target=None,
90
+ structured_output_enabled=node_dict.get("structuredOutputEnabled", False),
91
+ structured_output_max_retries=node_dict.get(
92
+ "structuredOutputMaxRetries", 0
93
+ ),
94
+ structured_output_schema=node_dict.get("structuredOutputSchema", None),
95
+ structured_output_schema_target=node_dict.get(
96
+ "structuredOutputSchemaTarget", None
97
+ ),
94
98
  )
95
99
  elif node_dict["type"] == "Router":
96
100
  return RouterNode(
@@ -130,6 +134,20 @@ def node_from_dict(node_dict: dict) -> Node:
130
134
  uuid.UUID(k): uuid.UUID(v)
131
135
  for k, v in node_dict["inputsMappings"].items()
132
136
  },
137
+ code=node_dict["code"],
138
+ fn_name=node_dict["fnName"],
139
+ )
140
+ elif node_dict["type"] == "JsonExtractor":
141
+ return JsonExtractorNode(
142
+ id=uuid.UUID(node_dict["id"]),
143
+ name=node_dict["name"],
144
+ inputs=[Handle.from_dict(handle) for handle in node_dict["inputs"]],
145
+ outputs=[Handle.from_dict(handle) for handle in node_dict["outputs"]],
146
+ inputs_mappings={
147
+ uuid.UUID(k): uuid.UUID(v)
148
+ for k, v in node_dict["inputsMappings"].items()
149
+ },
150
+ template=node_dict["template"],
133
151
  )
134
152
  else:
135
153
  raise ValueError(f"Node type {node_dict['type']} not supported")
lmnr/cli/parser/parser.py CHANGED
@@ -1,3 +1,4 @@
1
+ from lmnr.cli.parser.utils import replace_spaces_with_underscores
1
2
  from .nodes.types import node_from_dict
2
3
 
3
4
 
@@ -8,6 +9,9 @@ def runnable_graph_to_template_vars(graph: dict) -> dict:
8
9
  node_id_to_node_name = {}
9
10
  output_handle_id_to_node_name: dict[str, str] = {}
10
11
  for node in graph["nodes"].values():
12
+ # override node names in the graph itself to be safe
13
+ node["name"] = replace_spaces_with_underscores(node["name"])
14
+
11
15
  node_id_to_node_name[node["id"]] = node["name"]
12
16
  for handle in node["outputs"]:
13
17
  output_handle_id_to_node_name[handle["id"]] = node["name"]
lmnr/cli/parser/utils.py CHANGED
@@ -23,3 +23,27 @@ def map_handles(
23
23
  (input_name, output_handle_id_to_node_name[str(output_id)])
24
24
  for input_name, output_id in mapping
25
25
  ]
26
+
27
+
28
+ def replace_spaces_with_underscores(s: str):
29
+ spaces = [
30
+ "\u0020",
31
+ "\u00A0",
32
+ "\u1680",
33
+ "\u2000",
34
+ "\u2001",
35
+ "\u2002",
36
+ "\u2003",
37
+ "\u2004",
38
+ "\u2005",
39
+ "\u2006",
40
+ "\u2007",
41
+ "\u2008",
42
+ "\u2009",
43
+ "\u200A",
44
+ "\u200B",
45
+ "\u202F",
46
+ "\u205F",
47
+ "\u3000",
48
+ ]
49
+ return s.translate({ord(space): "_" for space in spaces})
lmnr/cli/zip.py ADDED
@@ -0,0 +1,12 @@
1
+ import os
2
+ from pathlib import Path
3
+ import zipfile
4
+
5
+
6
+ def zip_directory(directory_path: Path, zip_file_path: Path):
7
+ with zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_DEFLATED) as zipf:
8
+ for root, _, files in os.walk(directory_path):
9
+ for file in files:
10
+ file_path = os.path.join(root, file)
11
+ arcname = os.path.relpath(file_path, directory_path)
12
+ zipf.write(file_path, arcname)
lmnr/sdk/__init__.py ADDED
File without changes
lmnr/sdk/registry.py ADDED
@@ -0,0 +1,29 @@
1
+ from typing import Callable
2
+
3
+ from lmnr.types import NodeFunction, NodeInput
4
+
5
+
6
+ class Registry:
7
+ """
8
+ Class to register and resolve node functions based on their node names.
9
+
10
+ Node names cannot have space in their name.
11
+ """
12
+
13
+ functions: dict[str, NodeFunction]
14
+
15
+ def __init__(self):
16
+ self.functions = {}
17
+
18
+ def add(self, node_name: str, function: Callable[..., NodeInput]):
19
+ self.functions[node_name] = NodeFunction(node_name, function)
20
+
21
+ def func(self, node_name: str):
22
+ def decorator(f: Callable[..., NodeInput]):
23
+ self.add(node_name, f)
24
+ return f
25
+
26
+ return decorator
27
+
28
+ def get(self, node_name: str) -> Callable[..., NodeInput]:
29
+ return self.functions[node_name].function
@@ -1,34 +1,45 @@
1
- from typing import Callable, Optional
1
+ from typing import Callable, Optional, Union
2
2
  from websockets.sync.client import connect
3
3
  import pydantic
4
4
  import websockets
5
5
  from lmnr.types import (
6
- DeregisterDebuggerRequest, NodeInput, RegisterDebuggerRequest,
7
- SDKError, ToolCallError, ToolCallRequest, ToolCallResponse
6
+ DeregisterDebuggerRequest,
7
+ NodeFunction,
8
+ NodeInput,
9
+ RegisterDebuggerRequest,
10
+ SDKError,
11
+ ToolCallError,
12
+ ToolCallRequest,
13
+ ToolCallResponse,
8
14
  )
9
15
  import uuid
10
16
  import json
11
17
  from threading import Thread
12
18
 
19
+
13
20
  class RemoteDebugger:
14
21
  def __init__(
15
22
  self,
16
23
  project_api_key: str,
17
- tools: list[Callable[..., NodeInput]] = []
24
+ tools: Union[dict[str, NodeFunction], list[Callable[..., NodeInput]]] = [],
18
25
  ):
26
+ # for simplicity and backwards compatibility, we allow the user to pass a list
27
+ if isinstance(tools, list):
28
+ tools = {f.__name__: NodeFunction(f.__name__, f) for f in tools}
29
+
19
30
  self.project_api_key = project_api_key
20
- self.url = 'wss://api.lmnr.ai/v2/endpoint/ws'
31
+ self.url = "wss://api.lmnr.ai/v2/endpoint/ws"
21
32
  self.tools = tools
22
33
  self.thread = Thread(target=self._run)
23
34
  self.stop_flag = False
24
35
  self.session = None
25
-
36
+
26
37
  def start(self) -> Optional[str]:
27
38
  self.stop_flag = False
28
39
  self.session = self._generate_session_id()
29
40
  self.thread.start()
30
41
  return self.session
31
-
42
+
32
43
  def stop(self):
33
44
  self.stop_flag = True
34
45
  self.thread.join()
@@ -37,17 +48,13 @@ class RemoteDebugger:
37
48
  # a new thread
38
49
  # in case the user wants to start the debugger again
39
50
  self.thread = Thread(target=self._run)
40
-
41
- def get_session_id(self) -> str:
42
- return self.session
43
-
51
+
44
52
  def _run(self):
53
+ assert self.session is not None, "Session ID not set"
45
54
  request = RegisterDebuggerRequest(debuggerSessionId=self.session)
46
55
  with connect(
47
56
  self.url,
48
- additional_headers={
49
- 'Authorization': f'Bearer {self.project_api_key}'
50
- }
57
+ additional_headers={"Authorization": f"Bearer {self.project_api_key}"},
51
58
  ) as websocket:
52
59
  websocket.send(request.model_dump_json())
53
60
  print(self._format_session_id_and_registerd_functions())
@@ -55,7 +62,7 @@ class RemoteDebugger:
55
62
 
56
63
  while not self.stop_flag:
57
64
  try:
58
- # blocks the thread until a message
65
+ # blocks the thread until a message
59
66
  # is received or a timeout (3 seconds) occurs
60
67
  message = websocket.recv(3)
61
68
  except TimeoutError:
@@ -66,55 +73,48 @@ class RemoteDebugger:
66
73
  try:
67
74
  tool_call = ToolCallRequest.model_validate_json(message)
68
75
  req_id = tool_call.reqId
69
- except:
70
- raise SDKError(f'Invalid message received:\n{message}')
71
- matching_tools = [
72
- tool for tool in self.tools
73
- if tool.__name__ == tool_call.toolCall.function.name
74
- ]
75
- if not matching_tools:
76
- error_message = \
77
- f'Tool {tool_call.toolCall.function.name} not found' +\
78
- '. Registered tools: ' +\
79
- {", ".join([tool.__name__ for tool in self.tools])}
76
+ except Exception:
77
+ raise SDKError(f"Invalid message received:\n{message}")
78
+ matching_tool = self.tools.get(tool_call.toolCall.function.name)
79
+ if matching_tool is None:
80
+ error_message = (
81
+ f"Tool {tool_call.toolCall.function.name} not found"
82
+ + ". Registered tools: "
83
+ + ", ".join(self.tools.keys())
84
+ )
80
85
  e = ToolCallError(error=error_message, reqId=req_id)
81
86
  websocket.send(e.model_dump_json())
82
87
  continue
83
- tool = matching_tools[0]
84
- if tool.__name__ == tool_call.toolCall.function.name:
85
- # default the arguments to an empty dictionary
86
- arguments = {}
87
- try:
88
- arguments = json.loads(
89
- tool_call.toolCall.function.arguments)
90
- except:
91
- pass
92
- try:
93
- response = tool(**arguments)
94
- except Exception as e:
95
- error_message = 'Error occurred while running tool' +\
96
- f'{tool.__name__}: {e}'
97
- e = ToolCallError(error=error_message, reqId=req_id)
98
- websocket.send(e.model_dump_json())
99
- continue
100
- formatted_response = None
101
- try:
102
- formatted_response = ToolCallResponse(
103
- reqId=tool_call.reqId,
104
- response=response
105
- )
106
- except pydantic.ValidationError as e:
107
- formatted_response = ToolCallResponse(
108
- reqId=tool_call.reqId,
109
- response=str(response)
110
- )
111
- websocket.send(
112
- formatted_response.model_dump_json()
88
+ tool = matching_tool.function
89
+
90
+ # default the arguments to an empty dictionary
91
+ arguments = {}
92
+ try:
93
+ arguments = json.loads(tool_call.toolCall.function.arguments)
94
+ except Exception:
95
+ pass
96
+ try:
97
+ response = tool(**arguments)
98
+ except Exception as e:
99
+ error_message = (
100
+ "Error occurred while running tool" + f"{tool.__name__}: {e}"
101
+ )
102
+ e = ToolCallError(error=error_message, reqId=req_id)
103
+ websocket.send(e.model_dump_json())
104
+ continue
105
+ formatted_response = None
106
+ try:
107
+ formatted_response = ToolCallResponse(
108
+ reqId=tool_call.reqId, response=response
113
109
  )
110
+ except pydantic.ValidationError:
111
+ formatted_response = ToolCallResponse(
112
+ reqId=tool_call.reqId, response=str(response)
113
+ )
114
+ websocket.send(formatted_response.model_dump_json())
114
115
  websocket.send(
115
116
  DeregisterDebuggerRequest(
116
- debuggerSessionId=self.session,
117
- deregister=True
117
+ debuggerSessionId=self.session, deregister=True
118
118
  ).model_dump_json()
119
119
  )
120
120
 
@@ -122,10 +122,8 @@ class RemoteDebugger:
122
122
  return uuid.uuid4().urn[9:]
123
123
 
124
124
  def _format_session_id_and_registerd_functions(self) -> str:
125
- registered_functions = \
126
- ',\n'.join(['- ' + tool.__name__ for tool in self.tools])
127
- return \
128
- f"""
125
+ registered_functions = ",\n".join(["- " + k for k in self.tools.keys()])
126
+ return f"""
129
127
  ========================================
130
128
  Debugger Session ID:
131
129
  {self.session}
@@ -136,5 +134,3 @@ Registered functions:
136
134
 
137
135
  ========================================
138
136
  """
139
-
140
-
lmnr/types.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import requests
2
2
  import pydantic
3
3
  import uuid
4
- from typing import Union, Optional
4
+ from typing import Callable, Union, Optional
5
5
 
6
6
 
7
7
  class ChatMessage(pydantic.BaseModel):
@@ -90,3 +90,12 @@ class RegisterDebuggerRequest(pydantic.BaseModel):
90
90
  class DeregisterDebuggerRequest(pydantic.BaseModel):
91
91
  debuggerSessionId: str
92
92
  deregister: bool
93
+
94
+
95
+ class NodeFunction:
96
+ node_name: str
97
+ function: Callable[..., NodeInput]
98
+
99
+ def __init__(self, node_name: str, function: Callable[..., NodeInput]):
100
+ self.node_name = node_name
101
+ self.function = function
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lmnr
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: Python SDK for Laminar AI
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -14,7 +14,9 @@ Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: black (>=24.4.2,<25.0.0)
15
15
  Requires-Dist: click (>=8.1.7,<9.0.0)
16
16
  Requires-Dist: cookiecutter (>=2.6.0,<3.0.0)
17
+ Requires-Dist: lmnr-baml (>=0.40.0,<0.41.0)
17
18
  Requires-Dist: pydantic (>=2.7.4,<3.0.0)
19
+ Requires-Dist: pystache (>=0.6.5,<0.7.0)
18
20
  Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
19
21
  Requires-Dist: requests (>=2.32.3,<3.0.0)
20
22
  Requires-Dist: websockets (>=12.0,<13.0)
@@ -0,0 +1,28 @@
1
+ lmnr/__init__.py,sha256=BBJ87AiHC_OpaYOCzF8QSsf7eO3LlJPOCBXHNKurbE4,235
2
+ lmnr/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ lmnr/cli/__main__.py,sha256=8hDtWlaFZK24KhfNq_ZKgtXqYHsDQDetukOCMlsbW0Q,59
4
+ lmnr/cli/cli.py,sha256=qG3-aY2EJIW3BSD-_s1vUsxHcxC9kiuIeAO8aVUq3ik,4103
5
+ lmnr/cli/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ lmnr/cli/parser/nodes/__init__.py,sha256=2MkPdKulb1kuNe6aT71CaqBA8iBrXyb5pq5bu_EvCb8,1052
7
+ lmnr/cli/parser/nodes/code.py,sha256=8lTPBibUzaw_t-9QoPljhxH3KA4CLn9DJjA-iWpprOA,933
8
+ lmnr/cli/parser/nodes/condition.py,sha256=AJny0ILXbSy1hTwsRvZvDUqts9INNx63yQSkD7Dp7KU,740
9
+ lmnr/cli/parser/nodes/input.py,sha256=o8EfCmBbNyQL8FzmAtgnNDFlWqZmRAgkbw4HzKXZepU,539
10
+ lmnr/cli/parser/nodes/json_extractor.py,sha256=CnVwZ-wU_Ro4WkJLw9Uk_SS3yvZ66UPa5mK4JdkM8w4,723
11
+ lmnr/cli/parser/nodes/llm.py,sha256=Wpmo9cfNiYN9DRbj7oBS6RYcKXLwlGtF6RdF4jFQm5I,1866
12
+ lmnr/cli/parser/nodes/output.py,sha256=1XBppSscxM01kfZhE9oOh2GgdCVzyPVe2RAxLI5HmUc,665
13
+ lmnr/cli/parser/nodes/router.py,sha256=dmCx4ho8_GdFJXQa8UevMf_uEP7AKBv_MJ2zpLC6Vck,894
14
+ lmnr/cli/parser/nodes/semantic_search.py,sha256=DWDPpV78XZ7vPIaPd86FbeDFAnKah4e61M1TOzwnt84,1352
15
+ lmnr/cli/parser/nodes/types.py,sha256=OVXj-iMEDY9nPKCX1-zddtoszZcUL3CXYYryI7O3et0,6094
16
+ lmnr/cli/parser/parser.py,sha256=yDa-ysAkh6si_hHU8Gw8EdtNWc4pFc5RbvgWEXGEPys,2370
17
+ lmnr/cli/parser/utils.py,sha256=1oy6BApHXOF7BTXbP8v3Oi9bwOdWZjoxDlRIOfXVxro,1169
18
+ lmnr/cli/zip.py,sha256=DpAfSVg6k0Ly55SY7rsIZkX0XG6U6IPD-HzsNi5Cf-U,445
19
+ lmnr/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ lmnr/sdk/endpoint.py,sha256=0HjcxMUcJz-klFZO2f5xtTaoLjcaEb8vrJ_YldTWUc8,7467
21
+ lmnr/sdk/registry.py,sha256=sEYQFOjO72YvgBSEkBrvoewFExoyBzx6nELgBarvD6Y,755
22
+ lmnr/sdk/remote_debugger.py,sha256=BYAN13KUDxH412qD3HXdDH0RfokrePquDt35fzB7GUg,5010
23
+ lmnr/types.py,sha256=3HpLBQZr6F5YMISHYLnzzyrTwUttNqJxpyobw31YYJQ,2347
24
+ lmnr-0.2.10.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
25
+ lmnr-0.2.10.dist-info/METADATA,sha256=STv0WzrtahyFBUaq_uLDuPVts5pd3dLgCfjdeQJ0Oyk,5565
26
+ lmnr-0.2.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
27
+ lmnr-0.2.10.dist-info/entry_points.txt,sha256=Qg7ZRax4k-rcQsZ26XRYQ8YFSBiyY2PNxYfq4a6PYXI,41
28
+ lmnr-0.2.10.dist-info/RECORD,,
@@ -1,24 +0,0 @@
1
- lmnr/__init__.py,sha256=NWHDZ-KAl3pQGDnKUbBbZaW4es-0-9Xt6gP-UrjyuEQ,207
2
- lmnr/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- lmnr/cli/__main__.py,sha256=8hDtWlaFZK24KhfNq_ZKgtXqYHsDQDetukOCMlsbW0Q,59
4
- lmnr/cli/cli.py,sha256=0Qw_dxE_N9F38asUB7pMbILJGVi-pPtqiao4aTjQQGM,2769
5
- lmnr/cli/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- lmnr/cli/parser/nodes/__init__.py,sha256=BNbbfn0WwbFDA6TNhLOaT_Ji69rCL5voUibqMD7Knng,1163
7
- lmnr/cli/parser/nodes/code.py,sha256=GXqOxN6tdiStZGWLbN3WZCmDfzwYIgSRmZ5t72AOIXc,661
8
- lmnr/cli/parser/nodes/condition.py,sha256=AJny0ILXbSy1hTwsRvZvDUqts9INNx63yQSkD7Dp7KU,740
9
- lmnr/cli/parser/nodes/input.py,sha256=Xwktcih7Mezqv4cEejfPkpG8uJxDsbqRytBvKmlJDYE,578
10
- lmnr/cli/parser/nodes/llm.py,sha256=iQWYFnQi5PcQD9WJpTSHbSzClM6s0wBOoEqyN5c4yQo,1674
11
- lmnr/cli/parser/nodes/output.py,sha256=1XBppSscxM01kfZhE9oOh2GgdCVzyPVe2RAxLI5HmUc,665
12
- lmnr/cli/parser/nodes/router.py,sha256=dmCx4ho8_GdFJXQa8UevMf_uEP7AKBv_MJ2zpLC6Vck,894
13
- lmnr/cli/parser/nodes/semantic_search.py,sha256=DWDPpV78XZ7vPIaPd86FbeDFAnKah4e61M1TOzwnt84,1352
14
- lmnr/cli/parser/nodes/types.py,sha256=XJQUg5VTbpc8LKN3-DMZkDMDiweGtKlA05edTcMYbr0,5257
15
- lmnr/cli/parser/parser.py,sha256=kAZEeg358lyj_Q1IIhQB_bA7LW3Aw6RduShIfUSmLqQ,2173
16
- lmnr/cli/parser/utils.py,sha256=wVaqHVOR9VXl8Og9nkVyCVgHIcgbtYGkDOEGPtmjZ8g,715
17
- lmnr/sdk/endpoint.py,sha256=0HjcxMUcJz-klFZO2f5xtTaoLjcaEb8vrJ_YldTWUc8,7467
18
- lmnr/sdk/remote_debugger.py,sha256=tC8OywEkxzeUCAHrpfhlL-iMP_0Rqh9qC2DtoYEGJjU,5174
19
- lmnr/types.py,sha256=OR9xRAQ5uTTwpJTDL_e3jZqxYJWvyX96CCoxr3oo94g,2112
20
- lmnr-0.2.8.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
21
- lmnr-0.2.8.dist-info/METADATA,sha256=kfHTeQtkFVsk3JK3LopVuvfr5OQkjG0YGXyoRrrqPq4,5479
22
- lmnr-0.2.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
23
- lmnr-0.2.8.dist-info/entry_points.txt,sha256=Qg7ZRax4k-rcQsZ26XRYQ8YFSBiyY2PNxYfq4a6PYXI,41
24
- lmnr-0.2.8.dist-info/RECORD,,
File without changes
File without changes