meshagent-cli 0.0.35__py3-none-any.whl → 0.0.36__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 meshagent-cli might be problematic. Click here for more details.

meshagent/cli/chatbot.py CHANGED
@@ -11,7 +11,7 @@ from meshagent.agents.chat import ChatBot
11
11
  from meshagent.openai import OpenAIResponsesAdapter
12
12
  from meshagent.openai.tools.responses_adapter import LocalShellTool
13
13
  from meshagent.api.services import ServiceHost
14
-
14
+ from meshagent.computers.agent import ComputerAgent
15
15
  from meshagent.agents.chat import ChatBotThreadOpenAIImageGenerationTool
16
16
 
17
17
  from typing import List
@@ -20,6 +20,77 @@ from meshagent.api import RequiredToolkit, RequiredSchema
20
20
 
21
21
  app = async_typer.AsyncTyper()
22
22
 
23
+
24
+ def build_chatbot(*,
25
+ model: str,
26
+ agent_name: str,
27
+ rule: List[str],
28
+ toolkit: List[str],
29
+ schema: List[str],
30
+ image_generation: Optional[str] = None,
31
+ local_shell: bool,
32
+ computer_use: bool
33
+ ):
34
+
35
+ requirements = []
36
+
37
+ toolkits = []
38
+
39
+ for t in toolkit:
40
+ requirements.append(RequiredToolkit(name=t))
41
+
42
+ for t in schema:
43
+ requirements.append(RequiredSchema(name=t))
44
+
45
+ BaseClass = ChatBot
46
+ if computer_use:
47
+ BaseClass = ComputerAgent
48
+
49
+ llm_adapter = OpenAIResponsesAdapter(
50
+ model=model,
51
+ response_options={
52
+ "reasoning" : {
53
+ "generate_summary" : "concise"
54
+ },
55
+ "truncation" : "auto"
56
+ }
57
+ )
58
+ else:
59
+ llm_adapter = OpenAIResponsesAdapter(
60
+ model=model
61
+ )
62
+ class CustomChatbot(BaseClass):
63
+ def __init__(self):
64
+ super().__init__(
65
+ llm_adapter=llm_adapter,
66
+ name=agent_name,
67
+ requires=requirements,
68
+ toolkits=toolkits,
69
+ rules=rule if len(rule) > 0 else None
70
+ )
71
+
72
+ async def get_thread_toolkits(self, *, thread_context, participant):
73
+ toolkits = await super().get_thread_toolkits(thread_context=thread_context, participant=participant)
74
+
75
+ thread_toolkit = Toolkit(name="thread_toolkit", tools=[])
76
+
77
+ if local_shell:
78
+ thread_toolkit.tools.append(LocalShellTool())
79
+
80
+ if image_generation != None:
81
+
82
+ print("adding openai image gen to thread", flush=True)
83
+ thread_toolkit.tools.append(ChatBotThreadOpenAIImageGenerationTool(
84
+ model=image_generation,
85
+ thread_context=thread_context,
86
+ partial_images=3
87
+ ))
88
+
89
+ toolkits.append(thread_toolkit)
90
+ return toolkits
91
+
92
+ return CustomChatbot
93
+
23
94
  @app.async_command("join")
24
95
  async def make_call(
25
96
  *,
@@ -29,11 +100,15 @@ async def make_call(
29
100
  name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
30
101
  role: str = "agent",
31
102
  agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
103
+ token_path: Annotated[Optional[str], typer.Option()] = None,
104
+
32
105
  rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
33
106
  toolkit: Annotated[List[str], typer.Option("--toolkit", "-t", help="the name or url of a required toolkit")] = [],
34
- schema: Annotated[List[str], typer.Option("--schema", "-s", help="the name or url of a required schema")] = [],
35
- token_path: Annotated[Optional[str], typer.Option()] = None,
36
- image_generation: Annotated[Optional[str], typer.Option(..., help="Name of an image gen provider (openai)")] = None,
107
+ schema: Annotated[List[str], typer.Option("--schema", "-s", help="the name or url of a required schema")] = [],
108
+ model: Annotated[str, typer.Option(..., help="Name of the LLM model to use for the chatbot")] = "gpt-4o",
109
+ image_generation: Annotated[Optional[str], typer.Option(..., help="Name of an image gen model")] = None,
110
+ computer_use: Annotated[Optional[bool], typer.Option(..., help="Enable computer use (requires computer-use-preview model)")] = False,
111
+ local_shell: Annotated[Optional[bool], typer.Option(..., help="Enable local shell tool calling")] = False,
37
112
  ):
38
113
  account_client = await get_client()
39
114
  try:
@@ -43,7 +118,7 @@ async def make_call(
43
118
  room = resolve_room(room)
44
119
  jwt = await resolve_token_jwt(project_id=project_id, api_key_id=api_key_id, token_path=token_path, name=name, role=role, room=room)
45
120
 
46
- print("[bold green]Connecting to room...[/bold green]")
121
+ print("[bold green]Connecting to room...[/bold green]", flush=True)
47
122
  async with RoomClient(
48
123
  protocol=WebSocketClientProtocol(
49
124
  url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
@@ -61,21 +136,7 @@ async def make_call(
61
136
  for t in schema:
62
137
  requirements.append(RequiredSchema(name=t))
63
138
 
64
- class CustomChatbot(ChatBot):
65
-
66
- async def get_thread_toolkits(self, *, thread_context, participant):
67
- toolkits = await super().get_thread_toolkits(thread_context=thread_context, participant=participant)
68
-
69
- thread_toolkit = Toolkit(name="thread_toolkit", tools=[])
70
- if image_generation != None:
71
- if image_generation == "openai":
72
- print("adding openai image gen to thread")
73
- thread_toolkit.tools.append(ChatBotThreadOpenAIImageGenerationTool(thread_context=thread_context, partial_images=3))
74
- else:
75
- raise Exception("image-generation must be openai")
76
- toolkits.append(thread_toolkit)
77
- return toolkits
78
-
139
+ CustomChatbot = build_chatbot(computer_use=computer_use, model=model, local_shell=local_shell, agent_name=agent_name, rule=rule, toolkit=toolkit, schema=schema, image_generation=image_generation)
79
140
 
80
141
  bot = CustomChatbot(
81
142
  llm_adapter=OpenAIResponsesAdapter(),
@@ -106,7 +167,10 @@ async def service(
106
167
  rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
107
168
  toolkit: Annotated[List[str], typer.Option("--toolkit", "-t", help="the name or url of a required toolkit")] = [],
108
169
  schema: Annotated[List[str], typer.Option("--schema", "-s", help="the name or url of a required schema")] = [],
109
- image_generation: Annotated[Optional[str], typer.Option(..., help="Name of an image gen provider (openai)")] = None,
170
+ model: Annotated[str, typer.Option(..., help="Name of the LLM model to use for the chatbot")] = "gpt-4o",
171
+ image_generation: Annotated[Optional[str], typer.Option(..., help="Name of an image gen model")] = None,
172
+ local_shell: Annotated[Optional[bool], typer.Option(..., help="Enable local shell tool calling")] = False,
173
+ computer_use: Annotated[Optional[bool], typer.Option(..., help="Enable computer use (requires computer-use-preview model)")] = False,
110
174
 
111
175
  host: Annotated[Optional[str], typer.Option()] = None,
112
176
  port: Annotated[Optional[int], typer.Option()] = None,
@@ -115,48 +179,12 @@ async def service(
115
179
 
116
180
  room = resolve_room(room)
117
181
 
118
- print("[bold green]Connecting to room...[/bold green]")
119
-
120
- requirements = []
121
-
122
- toolkits = []
123
-
124
- for t in toolkit:
125
- requirements.append(RequiredToolkit(name=t))
126
-
127
- for t in schema:
128
- requirements.append(RequiredSchema(name=t))
129
-
130
- class CustomChatbot(ChatBot):
131
-
132
- async def get_thread_toolkits(self, *, thread_context, participant):
133
- toolkits = await super().get_thread_toolkits(thread_context=thread_context, participant=participant)
134
-
135
- thread_toolkit = Toolkit(name="thread_toolkit", tools=[])
136
- if image_generation != None:
137
- if image_generation == "openai":
138
- print("adding openai image gen to thread")
139
- thread_toolkit.tools.append(ChatBotThreadOpenAIImageGenerationTool(thread_context=thread_context, partial_images=3))
140
- else:
141
- raise Exception("image-generation must be openai")
142
- toolkits.append(thread_toolkit)
143
- return toolkits
144
-
182
+ print("[bold green]Connecting to room...[/bold green]", flush=True)
145
183
 
146
184
  service = ServiceHost(
147
185
  host=host,
148
186
  port=port
149
187
  )
150
-
151
- @service.path(path=path)
152
- class CustomChatbot(ChatBot):
153
- def __init__(self):
154
- super().__init__(
155
- llm_adapter=OpenAIResponsesAdapter(),
156
- name=agent_name,
157
- requires=requirements,
158
- toolkits=toolkits,
159
- rules=rule if len(rule) > 0 else None
160
- )
188
+ service.add_path(path=path, cls=build_chatbot(computer_use=computer_use, model=model, local_shell=local_shell, agent_name=agent_name, rule=rule, toolkit=toolkit, schema=schema, image_generation=image_generation))
161
189
 
162
190
  await service.run()
meshagent/cli/cli.py CHANGED
@@ -20,6 +20,16 @@ from meshagent.cli import chatbot
20
20
  from meshagent.cli import voicebot
21
21
  from meshagent.cli import tty
22
22
 
23
+ from meshagent.cli import otel
24
+
25
+ import logging
26
+
27
+ otel.init(level=logging.INFO)
28
+
29
+ # Turn down OpenAI logs, they are a bit noisy
30
+ logging.getLogger("openai").setLevel(logging.ERROR)
31
+ logging.getLogger("httpx").setLevel(logging.ERROR)
32
+
23
33
  app = typer.Typer()
24
34
  app.add_typer(call.app, name="call")
25
35
  app.add_typer(auth.app, name="auth")
meshagent/cli/otel.py ADDED
@@ -0,0 +1,118 @@
1
+ from opentelemetry.sdk.resources import SERVICE_NAME, Resource
2
+ from opentelemetry import trace
3
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
4
+ from opentelemetry.sdk.trace import TracerProvider
5
+ from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
6
+
7
+ from opentelemetry import metrics
8
+ from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
9
+ from opentelemetry.sdk._logs.export import ConsoleLogExporter
10
+ from opentelemetry.sdk.metrics import MeterProvider
11
+ from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader, ConsoleMetricExporter
12
+ from opentelemetry import _logs
13
+ from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
14
+ from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
15
+ from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
16
+ from opentelemetry.sdk.metrics.export import AggregationTemporality
17
+ from opentelemetry.sdk.metrics import Counter, Histogram
18
+ import logging
19
+
20
+ import os
21
+
22
+ def _call_once(fn):
23
+ called = False
24
+ result = None
25
+
26
+ def wrapper(*args, **kwargs):
27
+ nonlocal called, result
28
+ if not called:
29
+ result = fn(*args, **kwargs)
30
+ called = True
31
+ return result
32
+ return wrapper
33
+
34
+
35
+ attributes = {
36
+ SERVICE_NAME: "room-server",
37
+ }
38
+
39
+ if os.getenv("MESHAGENT_PROJECT_ID") != None:
40
+ attributes["project"] = os.getenv("MESHAGENT_PROJECT_ID")
41
+
42
+ if os.getenv("MESHAGENT_SESSION_ID") != None:
43
+ attributes["session"] = os.getenv("MESHAGENT_SESSION_ID")
44
+
45
+ if os.getenv("MESHAGENT_ROOM") != None:
46
+ attributes["room"] = os.getenv("MESHAGENT_ROOM")
47
+
48
+ resource = Resource.create(attributes=attributes)
49
+
50
+ logger_provider = None
51
+ tracer_provider = None
52
+ meter_provider = None
53
+
54
+ add_console_exporters = False
55
+
56
+ otel_endpoint = os.getenv("OTEL_ENDPOINT")
57
+
58
+ if otel_endpoint != None:
59
+
60
+ otel_logs_endpoint = otel_endpoint + "/v1/logs"
61
+ otel_traces_endpoint = otel_endpoint + "/v1/traces"
62
+ otel_metrics_endpoint = otel_endpoint + "/v1/metrics"
63
+
64
+ if otel_logs_endpoint != None:
65
+ logs_exporter = OTLPLogExporter(
66
+ endpoint=otel_logs_endpoint,
67
+ )
68
+ logger_provider = LoggerProvider(resource=resource)
69
+ _logs.set_logger_provider(logger_provider)
70
+
71
+ logger_provider.add_log_record_processor(
72
+ BatchLogRecordProcessor(logs_exporter)
73
+ )
74
+
75
+ if add_console_exporters:
76
+ logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter()))
77
+
78
+
79
+ if otel_traces_endpoint != None:
80
+ tracer_provider = TracerProvider(resource=resource)
81
+ processor = BatchSpanProcessor(OTLPSpanExporter(endpoint=otel_traces_endpoint))
82
+ tracer_provider.add_span_processor(processor)
83
+ if add_console_exporters:
84
+ tracer_provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
85
+ trace.set_tracer_provider(tracer_provider)
86
+
87
+ if otel_metrics_endpoint != None:
88
+ reader = PeriodicExportingMetricReader(
89
+ exporter=OTLPMetricExporter(
90
+ endpoint=otel_metrics_endpoint,
91
+ preferred_temporality={
92
+ Counter: AggregationTemporality.DELTA,
93
+ Histogram: AggregationTemporality.DELTA,
94
+ },
95
+ ),
96
+ export_interval_millis=1000
97
+ )
98
+
99
+ readers = [
100
+ reader,
101
+ ]
102
+ if add_console_exporters:
103
+ readers.append(PeriodicExportingMetricReader(
104
+ ConsoleMetricExporter()
105
+ ))
106
+
107
+ meter_provider = MeterProvider(resource=resource, metric_readers=readers)
108
+ metrics.set_meter_provider(meter_provider)
109
+
110
+ @_call_once
111
+ def init(level):
112
+ if logger_provider != None:
113
+ logging_handler = LoggingHandler(level=level, logger_provider=logger_provider)
114
+ root = logging.getLogger()
115
+ root.setLevel(level)
116
+ root.addHandler(logging_handler)
117
+ else:
118
+ logging.basicConfig(level=level)
meshagent/cli/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.35"
1
+ __version__ = "0.0.36"
meshagent/cli/voicebot.py CHANGED
@@ -53,7 +53,7 @@ async def make_call(
53
53
  room = resolve_room(room)
54
54
  jwt = await resolve_token_jwt(project_id=project_id, api_key_id=api_key_id, token_path=token_path, name=name, role=role, room=room)
55
55
 
56
- print("[bold green]Connecting to room...[/bold green]")
56
+ print("[bold green]Connecting to room...[/bold green]", flush=True)
57
57
  async with RoomClient(
58
58
  protocol=WebSocketClientProtocol(url=websocket_room_url(room_name=room, base_url=meshagent_base_url()), token=jwt)
59
59
  ) as client:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-cli
3
- Version: 0.0.35
3
+ Version: 0.0.36
4
4
  Summary: CLI for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -10,12 +10,14 @@ Requires-Python: >=3.12
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: typer~=0.15
12
12
  Requires-Dist: pydantic-yaml~=1.4
13
- Requires-Dist: meshagent-api~=0.0.35
14
- Requires-Dist: meshagent-agents~=0.0.35
15
- Requires-Dist: meshagent-tools~=0.0.35
16
- Requires-Dist: meshagent-mcp~=0.0.35
13
+ Requires-Dist: meshagent-api~=0.0.36
14
+ Requires-Dist: meshagent-agents~=0.0.36
15
+ Requires-Dist: meshagent-tools~=0.0.36
16
+ Requires-Dist: meshagent-mcp~=0.0.36
17
17
  Requires-Dist: supabase~=2.15
18
18
  Requires-Dist: fastmcp~=2.8
19
+ Requires-Dist: opentelemetry-distro~=0.54b1
20
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http~=1.33
19
21
 
20
22
  ### Meshagent CLI
21
23
 
@@ -5,24 +5,25 @@ meshagent/cli/async_typer.py,sha256=GCeSefBDbpd-V4V8LrvHGUTBMth3HspVMfFa-HUZ0cg,
5
5
  meshagent/cli/auth.py,sha256=pZQwYTNWQOWTqpyDrkQLNKuidH-wn9GNE5yEJoxn3-g,767
6
6
  meshagent/cli/auth_async.py,sha256=run_J11mRPJQ6BI_aAtV_3O3h52eAl1EOnHuotwhoqQ,4018
7
7
  meshagent/cli/call.py,sha256=-6Bf5PCVcsuLMgDpG1g3GiY3S5rgs_-CWgWX4C6AXwg,4739
8
- meshagent/cli/chatbot.py,sha256=_ZuEpWwj1tYpu4CxuoQ4OXAk4LEkD1Qfmt-bOsjkkBU,6437
9
- meshagent/cli/cli.py,sha256=L3DaoAy03buBemBiltTSgcV9aq9I044pkg6zoZPKzYc,5937
8
+ meshagent/cli/chatbot.py,sha256=1MDzQOdNPyyux50D3rre_HhqXlySo8tBVfnDu2_std4,7455
9
+ meshagent/cli/cli.py,sha256=HbMyzks8LTDz-D6pGV97OHZAiAX39VqS3DrZZB06Y5A,6166
10
10
  meshagent/cli/cli_mcp.py,sha256=SG0r-cL3P7eu-fbwB-1WgjQPCmxKqQBh-X3kTKDli-E,9536
11
11
  meshagent/cli/cli_secrets.py,sha256=U0kdzN3zt7JIqzdRLynAjxdvAsI0enesBd_m7TeXjnQ,13629
12
12
  meshagent/cli/developer.py,sha256=5eoDr3kfi-IufA5d6OESqNr739Bdut_IFBtT3nq0xZU,3002
13
13
  meshagent/cli/helper.py,sha256=39_oznxO4sCi3namCJzYC0eWqeeGNlen1zlOuWF43os,4785
14
14
  meshagent/cli/messaging.py,sha256=bHMecKtVwY8P11itXMIvaLxPv-Zm6SpgrXnLDppb4Gc,6282
15
+ meshagent/cli/otel.py,sha256=6XaCrffRwPnQWp2KqGBAz4oPZUdlT6xh5kc-JKanJm4,4056
15
16
  meshagent/cli/participant_token.py,sha256=uCGmlUgNOfarYGkDZpzreXwnv9AJrM76tu5Lt690vYU,1456
16
17
  meshagent/cli/projects.py,sha256=EQfbO9_GQKkjlFcaSHQfIxqIxsmFR3FbH5Fd17I5IPk,3305
17
18
  meshagent/cli/services.py,sha256=pMAyLg0eEO33fhRiin5q0KbNVoTzQyT5wSDgvDqeRYM,11241
18
19
  meshagent/cli/sessions.py,sha256=WWvuztYqRfthSq6ztwL_eQ_sz9JRc33jcN6p7YyM_Fs,782
19
20
  meshagent/cli/storage.py,sha256=Se_4xhxiihIovSR1ajlEWo_YZ12G7eUY_-lvifJ8pjo,33806
20
21
  meshagent/cli/tty.py,sha256=DkgeYQckjil191HNoEGHmheniCi41XNUSMpYY1ilAic,4099
21
- meshagent/cli/version.py,sha256=QmUV3Ydc9xA0pOuihDI_wM1kvEzVZrdkq2eiedTW2UA,23
22
- meshagent/cli/voicebot.py,sha256=5vB0yzcKVvQ-nq2in51Xlf-rWbJB8Mjc8V44me6mUD4,4701
22
+ meshagent/cli/version.py,sha256=oSKhQHo_8dYEVv3A19nCmQysoh4TbOzHl508xX9iHoo,23
23
+ meshagent/cli/voicebot.py,sha256=lkiFHL2vhQuknQU5b2fbLafqzfycDik8DGZ8PkuK1z0,4713
23
24
  meshagent/cli/webhook.py,sha256=KBl8U1TcOX3z2uoyH4YMuUuw0vSVX7xpRxYvzxI5c-Y,2811
24
- meshagent_cli-0.0.35.dist-info/METADATA,sha256=5tcx5aulHPt6KgjOIdaih5sXkMGB1Dp7SiLPIg5H7o4,627
25
- meshagent_cli-0.0.35.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- meshagent_cli-0.0.35.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
27
- meshagent_cli-0.0.35.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
28
- meshagent_cli-0.0.35.dist-info/RECORD,,
25
+ meshagent_cli-0.0.36.dist-info/METADATA,sha256=TW6N-7Duj-FnJA6C5NkWpKBF3ovNE18HHcNK6MQKCHM,731
26
+ meshagent_cli-0.0.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ meshagent_cli-0.0.36.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
28
+ meshagent_cli-0.0.36.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
29
+ meshagent_cli-0.0.36.dist-info/RECORD,,