meshagent-cli 0.7.0__py3-none-any.whl → 0.21.0__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.
Files changed (41) hide show
  1. meshagent/cli/agent.py +15 -11
  2. meshagent/cli/api_keys.py +4 -4
  3. meshagent/cli/async_typer.py +52 -4
  4. meshagent/cli/call.py +12 -8
  5. meshagent/cli/chatbot.py +1007 -129
  6. meshagent/cli/cli.py +21 -20
  7. meshagent/cli/cli_mcp.py +92 -28
  8. meshagent/cli/cli_secrets.py +10 -10
  9. meshagent/cli/common_options.py +19 -4
  10. meshagent/cli/containers.py +164 -16
  11. meshagent/cli/database.py +997 -0
  12. meshagent/cli/developer.py +3 -3
  13. meshagent/cli/exec.py +22 -6
  14. meshagent/cli/helper.py +62 -11
  15. meshagent/cli/helpers.py +66 -9
  16. meshagent/cli/host.py +37 -0
  17. meshagent/cli/mailbot.py +1004 -40
  18. meshagent/cli/mailboxes.py +223 -0
  19. meshagent/cli/meeting_transcriber.py +10 -4
  20. meshagent/cli/messaging.py +7 -7
  21. meshagent/cli/multi.py +402 -0
  22. meshagent/cli/oauth2.py +44 -21
  23. meshagent/cli/participant_token.py +5 -3
  24. meshagent/cli/port.py +70 -0
  25. meshagent/cli/queue.py +2 -2
  26. meshagent/cli/room.py +20 -212
  27. meshagent/cli/rooms.py +214 -0
  28. meshagent/cli/services.py +32 -23
  29. meshagent/cli/sessions.py +5 -5
  30. meshagent/cli/storage.py +5 -5
  31. meshagent/cli/task_runner.py +770 -0
  32. meshagent/cli/version.py +1 -1
  33. meshagent/cli/voicebot.py +502 -76
  34. meshagent/cli/webhook.py +7 -7
  35. meshagent/cli/worker.py +1327 -0
  36. {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/METADATA +13 -13
  37. meshagent_cli-0.21.0.dist-info/RECORD +44 -0
  38. meshagent_cli-0.7.0.dist-info/RECORD +0 -36
  39. {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/WHEEL +0 -0
  40. {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/entry_points.txt +0 -0
  41. {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,770 @@
1
+ import typer
2
+ import json
3
+ from rich import print
4
+ from typing import Annotated, Optional
5
+ from meshagent.tools import Toolkit
6
+ from meshagent.tools.storage import StorageToolkitBuilder
7
+ from meshagent.tools.document_tools import (
8
+ DocumentAuthoringToolkit,
9
+ DocumentTypeAuthoringToolkit,
10
+ )
11
+ from meshagent.agents.config import RulesConfig
12
+ from meshagent.agents.widget_schema import widget_schema
13
+
14
+ from meshagent.cli.common_options import (
15
+ ProjectIdOption,
16
+ RoomOption,
17
+ )
18
+ from meshagent.api import (
19
+ RoomClient,
20
+ WebSocketClientProtocol,
21
+ ParticipantToken,
22
+ ApiScope,
23
+ RoomException,
24
+ )
25
+ from meshagent.api.helpers import meshagent_base_url, websocket_room_url
26
+ from meshagent.cli import async_typer
27
+ from meshagent.cli.helper import (
28
+ get_client,
29
+ resolve_project_id,
30
+ resolve_room,
31
+ resolve_key,
32
+ )
33
+
34
+ from meshagent.openai import OpenAIResponsesAdapter
35
+
36
+ from typing import List
37
+ from pathlib import Path
38
+
39
+ from meshagent.openai.tools.responses_adapter import (
40
+ WebSearchToolkitBuilder,
41
+ MCPToolkitBuilder,
42
+ WebSearchTool,
43
+ LocalShellConfig,
44
+ ShellConfig,
45
+ WebSearchConfig,
46
+ ApplyPatchConfig,
47
+ ApplyPatchTool,
48
+ ApplyPatchToolkitBuilder,
49
+ ShellToolkitBuilder,
50
+ ShellTool,
51
+ LocalShellToolkitBuilder,
52
+ LocalShellTool,
53
+ ImageGenerationConfig,
54
+ ImageGenerationToolkitBuilder,
55
+ ImageGenerationTool,
56
+ )
57
+
58
+ from meshagent.tools.database import DatabaseToolkitBuilder, DatabaseToolkitConfig
59
+ from meshagent.agents.adapter import MessageStreamLLMAdapter
60
+ from meshagent.agents.context import AgentCallContext
61
+
62
+ from meshagent.api import RequiredToolkit, RequiredSchema
63
+ from meshagent.api.services import ServiceHost
64
+ import logging
65
+ import os.path
66
+
67
+ from urllib.request import urlopen
68
+
69
+ logger = logging.getLogger("taskrunner")
70
+
71
+ app = async_typer.AsyncTyper(help="Join a taskrunner to a room")
72
+
73
+
74
+ def build_task_runner(
75
+ *,
76
+ model: str,
77
+ agent_name: str,
78
+ rule: List[str],
79
+ toolkit: List[str],
80
+ schema: List[str],
81
+ image_generation: Optional[str] = None,
82
+ local_shell: Optional[str] = None,
83
+ shell: Optional[str] = None,
84
+ apply_patch: Optional[str] = None,
85
+ web_search: Optional[str] = None,
86
+ mcp: Optional[str] = None,
87
+ storage: Optional[str] = None,
88
+ require_image_generation: Optional[str] = None,
89
+ require_local_shell: Optional[str] = None,
90
+ require_shell: Optional[bool] = None,
91
+ require_apply_patch: Optional[str] = None,
92
+ require_web_search: Optional[str] = None,
93
+ require_mcp: Optional[str] = None,
94
+ require_storage: Optional[str] = None,
95
+ require_table_read: list[str] = None,
96
+ require_table_write: list[str] = None,
97
+ require_read_only_storage: Optional[str] = None,
98
+ rules_file: Optional[str] = None,
99
+ room_rules_path: Optional[list[str]] = None,
100
+ require_discovery: Optional[str] = None,
101
+ require_document_authoring: Optional[str] = None,
102
+ working_directory: Optional[str] = None,
103
+ llm_participant: Optional[str] = None,
104
+ output_schema_path: Optional[str] = None,
105
+ output_schema_str: Optional[str] = None,
106
+ annotations: list[dict[str, str]],
107
+ title: Optional[str] = None,
108
+ description: Optional[str] = None,
109
+ shell_image: Optional[str] = None,
110
+ ):
111
+ output_schema = None
112
+ if output_schema_str is not None:
113
+ output_schema = json.loads(output_schema_str)
114
+ elif output_schema_path is not None:
115
+ if output_schema_path.startswith("http://") or output_schema_path.startswith(
116
+ "https://"
117
+ ):
118
+ with urlopen(output_schema_path) as r:
119
+ output_schema = json.loads(r.read())
120
+ else:
121
+ with open(Path(os.path.expanduser(rules_file)).resolve(), "r") as f:
122
+ output_schema = json.loads(f.read())
123
+
124
+ from meshagent.agents.llmrunner import LLMTaskRunner
125
+
126
+ from meshagent.tools.storage import StorageToolkit
127
+
128
+ requirements = []
129
+
130
+ toolkits = []
131
+
132
+ for t in toolkit:
133
+ requirements.append(RequiredToolkit(name=t))
134
+
135
+ for t in schema:
136
+ requirements.append(RequiredSchema(name=t))
137
+
138
+ client_rules = {}
139
+
140
+ if rules_file is not None:
141
+ try:
142
+ with open(Path(os.path.expanduser(rules_file)).resolve(), "r") as f:
143
+ rules_config = RulesConfig.parse(f.read())
144
+ rule.extend(rules_config.rules)
145
+ client_rules = rules_config.client_rules
146
+
147
+ except FileNotFoundError:
148
+ print(f"[yellow]rules file not found at {rules_file}[/yellow]")
149
+
150
+ BaseClass = LLMTaskRunner
151
+ if llm_participant:
152
+ llm_adapter = MessageStreamLLMAdapter(
153
+ participant_name=llm_participant,
154
+ )
155
+ else:
156
+ llm_adapter = OpenAIResponsesAdapter(
157
+ model=model,
158
+ )
159
+
160
+ class CustomTaskRunner(BaseClass):
161
+ def __init__(self):
162
+ super().__init__(
163
+ llm_adapter=llm_adapter,
164
+ name=agent_name,
165
+ requires=requirements,
166
+ toolkits=toolkits,
167
+ rules=rule if len(rule) > 0 else None,
168
+ client_rules=client_rules,
169
+ output_schema=output_schema,
170
+ annotations=annotations,
171
+ title=title,
172
+ description=description,
173
+ )
174
+
175
+ async def start(self, *, room: RoomClient):
176
+ await super().start(room=room)
177
+
178
+ if room_rules_path is not None:
179
+ for p in room_rules_path:
180
+ await self._load_room_rules(path=p)
181
+
182
+ async def _load_room_rules(
183
+ self,
184
+ *,
185
+ path: str,
186
+ context: AgentCallContext,
187
+ ):
188
+ participant = context.caller
189
+ rules = []
190
+ try:
191
+ room_rules = await self.room.storage.download(path=path)
192
+
193
+ rules_txt = room_rules.data.decode()
194
+
195
+ rules_config = RulesConfig.parse(rules_txt)
196
+
197
+ if rules_config.rules is not None:
198
+ rules.extend(rules_config.rules)
199
+
200
+ if participant is not None:
201
+ client = participant.get_attribute("client")
202
+
203
+ if rules_config.client_rules is not None and client is not None:
204
+ cr = rules_config.client_rules.get(client)
205
+ if cr is not None:
206
+ rules.extend(cr)
207
+
208
+ except RoomException:
209
+ try:
210
+ logger.info("attempting to initialize rules file")
211
+ handle = await self.room.storage.open(path=path, overwrite=False)
212
+ await self.room.storage.write(
213
+ handle=handle,
214
+ data="# Add rules to this file to customize your agent's behavior, lines starting with # will be ignored.\n\n".encode(),
215
+ )
216
+ await self.room.storage.close(handle=handle)
217
+
218
+ except RoomException:
219
+ pass
220
+ logger.info(
221
+ f"unable to load rules from {path}, continuing with default rules"
222
+ )
223
+ pass
224
+
225
+ return rules
226
+
227
+ async def get_rules(self, *, context: AgentCallContext):
228
+ rules = await super().get_rules(context=context)
229
+
230
+ if room_rules_path is not None:
231
+ for p in room_rules_path:
232
+ rules.extend(await self._load_room_rules(path=p, context=context))
233
+
234
+ logging.info(f"using rules {rules}")
235
+
236
+ return rules
237
+
238
+ async def get_context_toolkits(self, *, context: AgentCallContext):
239
+ providers = []
240
+
241
+ if require_image_generation:
242
+ providers.append(
243
+ ImageGenerationTool(
244
+ config=ImageGenerationConfig(
245
+ name="image_generation",
246
+ partial_images=3,
247
+ ),
248
+ )
249
+ )
250
+
251
+ if require_local_shell:
252
+ providers.append(
253
+ LocalShellTool(
254
+ working_directory=working_directory,
255
+ config=LocalShellConfig(name="local_shell"),
256
+ )
257
+ )
258
+
259
+ if require_shell:
260
+ providers.append(
261
+ ShellTool(
262
+ working_directory=working_directory,
263
+ config=ShellConfig(name="shell"),
264
+ image=shell_image or "python:3.13",
265
+ )
266
+ )
267
+
268
+ if require_apply_patch:
269
+ providers.append(
270
+ ApplyPatchTool(
271
+ config=ApplyPatchConfig(name="apply_patch"),
272
+ )
273
+ )
274
+
275
+ if require_mcp:
276
+ raise Exception(
277
+ "mcp tool cannot be required by cli currently, use 'optional' instead"
278
+ )
279
+
280
+ if require_web_search:
281
+ providers.append(
282
+ WebSearchTool(config=WebSearchConfig(name="web_search"))
283
+ )
284
+
285
+ if require_storage:
286
+ providers.extend(StorageToolkit().tools)
287
+
288
+ if len(require_table_read) > 0:
289
+ providers.extend(
290
+ (
291
+ await DatabaseToolkitBuilder().make(
292
+ room=self.room,
293
+ model=model,
294
+ config=DatabaseToolkitConfig(
295
+ tables=require_table_read, read_only=True
296
+ ),
297
+ )
298
+ ).tools
299
+ )
300
+
301
+ if len(require_table_write) > 0:
302
+ providers.extend(
303
+ (
304
+ await DatabaseToolkitBuilder().make(
305
+ room=self.room,
306
+ model=model,
307
+ config=DatabaseToolkitConfig(
308
+ tables=require_table_write, read_only=False
309
+ ),
310
+ )
311
+ ).tools
312
+ )
313
+
314
+ if require_read_only_storage:
315
+ providers.extend(StorageToolkit(read_only=True).tools)
316
+
317
+ if require_document_authoring:
318
+ providers.extend(DocumentAuthoringToolkit().tools)
319
+ providers.extend(
320
+ DocumentTypeAuthoringToolkit(
321
+ schema=widget_schema, document_type="widget"
322
+ ).tools
323
+ )
324
+
325
+ if require_discovery:
326
+ from meshagent.tools.discovery import DiscoveryToolkit
327
+
328
+ providers.extend(DiscoveryToolkit().tools)
329
+
330
+ tk = await super().get_context_toolkits(context=context)
331
+ return [
332
+ *(
333
+ [Toolkit(name="tools", tools=providers)]
334
+ if len(providers) > 0
335
+ else []
336
+ ),
337
+ *tk,
338
+ ]
339
+
340
+ def get_toolkit_builders(self):
341
+ providers = []
342
+
343
+ if image_generation:
344
+ providers.append(ImageGenerationToolkitBuilder())
345
+
346
+ if apply_patch:
347
+ providers.append(ApplyPatchToolkitBuilder())
348
+
349
+ if local_shell:
350
+ providers.append(
351
+ LocalShellToolkitBuilder(
352
+ working_directory=working_directory,
353
+ )
354
+ )
355
+
356
+ if shell:
357
+ providers.append(
358
+ ShellToolkitBuilder(
359
+ working_directory=working_directory,
360
+ )
361
+ )
362
+
363
+ if mcp:
364
+ providers.append(MCPToolkitBuilder())
365
+
366
+ if web_search:
367
+ providers.append(WebSearchToolkitBuilder())
368
+
369
+ if storage:
370
+ providers.append(StorageToolkitBuilder())
371
+
372
+ return providers
373
+
374
+ return CustomTaskRunner
375
+
376
+
377
+ @app.async_command("join")
378
+ async def make_call(
379
+ *,
380
+ project_id: ProjectIdOption,
381
+ room: RoomOption,
382
+ role: str = "agent",
383
+ agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
384
+ rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
385
+ room_rules: Annotated[
386
+ List[str],
387
+ typer.Option(
388
+ "--room-rules",
389
+ "-rr",
390
+ help="a path to a rules file within the room that can be used to customize the agent's behavior",
391
+ ),
392
+ ] = [],
393
+ rules_file: Optional[str] = None,
394
+ toolkit: Annotated[
395
+ List[str],
396
+ typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
397
+ ] = [],
398
+ schema: Annotated[
399
+ List[str],
400
+ typer.Option("--schema", "-s", help="the name or url of a required schema"),
401
+ ] = [],
402
+ model: Annotated[
403
+ str, typer.Option(..., help="Name of the LLM model to use for the task runner")
404
+ ] = "gpt-5.2",
405
+ image_generation: Annotated[
406
+ Optional[str], typer.Option(..., help="Name of an image gen model")
407
+ ] = None,
408
+ local_shell: Annotated[
409
+ Optional[bool], typer.Option(..., help="Enable local shell tool calling")
410
+ ] = False,
411
+ shell: Annotated[
412
+ Optional[bool], typer.Option(..., help="Enable function shell tool calling")
413
+ ] = False,
414
+ apply_patch: Annotated[
415
+ Optional[bool], typer.Option(..., help="Enable apply patch tool")
416
+ ] = False,
417
+ web_search: Annotated[
418
+ Optional[bool], typer.Option(..., help="Enable web search tool calling")
419
+ ] = False,
420
+ mcp: Annotated[
421
+ Optional[bool], typer.Option(..., help="Enable mcp tool calling")
422
+ ] = False,
423
+ storage: Annotated[
424
+ Optional[bool], typer.Option(..., help="Enable storage toolkit")
425
+ ] = False,
426
+ require_image_generation: Annotated[
427
+ Optional[str], typer.Option(..., help="Name of an image gen model", hidden=True)
428
+ ] = None,
429
+ require_local_shell: Annotated[
430
+ Optional[bool],
431
+ typer.Option(..., help="Enable local shell tool calling", hidden=True),
432
+ ] = False,
433
+ require_shell: Annotated[
434
+ Optional[bool],
435
+ typer.Option(..., help="Enable function shell tool calling", hidden=True),
436
+ ] = False,
437
+ require_apply_patch: Annotated[
438
+ Optional[bool],
439
+ typer.Option(..., help="Enable apply patch tool calling", hidden=True),
440
+ ] = False,
441
+ require_web_search: Annotated[
442
+ Optional[bool],
443
+ typer.Option(..., help="Enable web search tool calling", hidden=True),
444
+ ] = False,
445
+ require_mcp: Annotated[
446
+ Optional[bool], typer.Option(..., help="Enable mcp tool calling", hidden=True)
447
+ ] = False,
448
+ require_storage: Annotated[
449
+ Optional[bool], typer.Option(..., help="Enable storage toolkit", hidden=True)
450
+ ] = False,
451
+ require_table_read: Annotated[
452
+ list[str],
453
+ typer.Option(
454
+ ..., help="Enable table read tools for a specific table", hidden=True
455
+ ),
456
+ ] = [],
457
+ require_table_write: Annotated[
458
+ list[str],
459
+ typer.Option(
460
+ ..., help="Enable table write tools for a specific table", hidden=True
461
+ ),
462
+ ] = [],
463
+ require_read_only_storage: Annotated[
464
+ Optional[bool],
465
+ typer.Option(..., help="Enable read only storage toolkit", hidden=True),
466
+ ] = False,
467
+ require_document_authoring: Annotated[
468
+ Optional[bool],
469
+ typer.Option(..., help="Enable MeshDocument authoring", hidden=True),
470
+ ] = False,
471
+ require_discovery: Annotated[
472
+ Optional[bool],
473
+ typer.Option(..., help="Enable discovery of agents and tools", hidden=True),
474
+ ] = False,
475
+ working_directory: Annotated[
476
+ Optional[str],
477
+ typer.Option(..., help="The default working directory for shell commands"),
478
+ ] = None,
479
+ key: Annotated[
480
+ str,
481
+ typer.Option("--key", help="an api key to sign the token with"),
482
+ ] = None,
483
+ llm_participant: Annotated[
484
+ Optional[str],
485
+ typer.Option(
486
+ ..., help="Delegate LLM interactions to a remote participant", hidden=True
487
+ ),
488
+ ] = None,
489
+ output_schema: Annotated[
490
+ Optional[str],
491
+ typer.Option(..., help="an output schema to use", hidden=True),
492
+ ] = None,
493
+ output_schema_path: Annotated[
494
+ Optional[str],
495
+ typer.Option(..., help="the path or url to output schema to use", hidden=True),
496
+ ] = None,
497
+ annotations: Annotated[
498
+ str,
499
+ typer.Option(
500
+ "--annotations", "-a", help='annotations in json format {"name":"value"}'
501
+ ),
502
+ ] = '{"meshagent.task-runner.attachment-format":"tar"}',
503
+ title: Annotated[
504
+ Optional[str], typer.Option(..., help="a friendly name for the task runner")
505
+ ] = None,
506
+ description: Annotated[
507
+ Optional[str], typer.Option(..., help="a description for the task runner")
508
+ ] = None,
509
+ ):
510
+ key = await resolve_key(project_id=project_id, key=key)
511
+ account_client = await get_client()
512
+ try:
513
+ project_id = await resolve_project_id(project_id=project_id)
514
+ room = resolve_room(room)
515
+
516
+ token = ParticipantToken(
517
+ name=agent_name,
518
+ )
519
+
520
+ token.add_api_grant(ApiScope.agent_default())
521
+
522
+ token.add_role_grant(role=role)
523
+ token.add_room_grant(room)
524
+
525
+ jwt = token.to_jwt(api_key=key)
526
+
527
+ print("[bold green]Connecting to room...[/bold green]", flush=True)
528
+ async with RoomClient(
529
+ protocol=WebSocketClientProtocol(
530
+ url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
531
+ token=jwt,
532
+ )
533
+ ) as client:
534
+ requirements = []
535
+
536
+ for t in toolkit:
537
+ requirements.append(RequiredToolkit(name=t))
538
+
539
+ for t in schema:
540
+ requirements.append(RequiredSchema(name=t))
541
+
542
+ CustomTaskRunner = build_task_runner(
543
+ title=title,
544
+ description=description,
545
+ model=model,
546
+ local_shell=local_shell,
547
+ shell=shell,
548
+ apply_patch=apply_patch,
549
+ agent_name=agent_name,
550
+ rule=rule,
551
+ toolkit=toolkit,
552
+ schema=schema,
553
+ rules_file=rules_file,
554
+ image_generation=image_generation,
555
+ web_search=web_search,
556
+ mcp=mcp,
557
+ storage=storage,
558
+ require_apply_patch=require_apply_patch,
559
+ require_web_search=require_web_search,
560
+ require_local_shell=require_local_shell,
561
+ require_shell=require_shell,
562
+ require_image_generation=require_image_generation,
563
+ require_mcp=require_mcp,
564
+ require_storage=require_storage,
565
+ require_table_read=require_table_read,
566
+ require_table_write=require_table_write,
567
+ require_read_only_storage=require_read_only_storage,
568
+ room_rules_path=room_rules,
569
+ require_document_authoring=require_document_authoring,
570
+ require_discovery=require_discovery,
571
+ working_directory=working_directory,
572
+ llm_participant=llm_participant,
573
+ output_schema_str=output_schema,
574
+ output_schema_path=output_schema_path,
575
+ annotations=json.loads(annotations) if annotations != "" else {},
576
+ )
577
+
578
+ bot = CustomTaskRunner()
579
+
580
+ await bot.start(room=client)
581
+ try:
582
+ print(
583
+ f"[bold green]Open the studio to interact with your agent: {meshagent_base_url().replace('api.', 'studio.')}/projects/{project_id}/rooms/{client.room_name}[/bold green]",
584
+ flush=True,
585
+ )
586
+ await client.protocol.wait_for_close()
587
+ except KeyboardInterrupt:
588
+ await bot.stop()
589
+
590
+ finally:
591
+ await account_client.close()
592
+
593
+
594
+ @app.async_command("service")
595
+ async def service(
596
+ *,
597
+ agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
598
+ rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
599
+ rules_file: Optional[str] = None,
600
+ room_rules: Annotated[
601
+ List[str],
602
+ typer.Option(
603
+ "--room-rules",
604
+ "-rr",
605
+ help="a path to a rules file within the room that can be used to customize the agent's behavior",
606
+ ),
607
+ ] = [],
608
+ toolkit: Annotated[
609
+ List[str],
610
+ typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
611
+ ] = [],
612
+ schema: Annotated[
613
+ List[str],
614
+ typer.Option("--schema", "-s", help="the name or url of a required schema"),
615
+ ] = [],
616
+ model: Annotated[
617
+ str, typer.Option(..., help="Name of the LLM model to use for the task runner")
618
+ ] = "gpt-5.2",
619
+ image_generation: Annotated[
620
+ Optional[str], typer.Option(..., help="Name of an image gen model")
621
+ ] = None,
622
+ local_shell: Annotated[
623
+ Optional[bool], typer.Option(..., help="Enable local shell tool calling")
624
+ ] = False,
625
+ shell: Annotated[
626
+ Optional[bool], typer.Option(..., help="Enable function shell tool calling")
627
+ ] = False,
628
+ apply_patch: Annotated[
629
+ Optional[bool], typer.Option(..., help="Enable apply patch tool")
630
+ ] = False,
631
+ web_search: Annotated[
632
+ Optional[bool], typer.Option(..., help="Enable web search tool calling")
633
+ ] = False,
634
+ mcp: Annotated[
635
+ Optional[bool], typer.Option(..., help="Enable mcp tool calling")
636
+ ] = False,
637
+ storage: Annotated[
638
+ Optional[bool], typer.Option(..., help="Enable storage toolkit")
639
+ ] = False,
640
+ require_image_generation: Annotated[
641
+ Optional[str], typer.Option(..., help="Name of an image gen model", hidden=True)
642
+ ] = None,
643
+ require_local_shell: Annotated[
644
+ Optional[bool],
645
+ typer.Option(..., help="Enable local shell tool calling", hidden=True),
646
+ ] = False,
647
+ require_shell: Annotated[
648
+ Optional[bool],
649
+ typer.Option(..., help="Enable function shell tool calling", hidden=True),
650
+ ] = False,
651
+ require_apply_patch: Annotated[
652
+ Optional[bool], typer.Option(..., help="Enable apply patch tool", hidden=True)
653
+ ] = False,
654
+ require_web_search: Annotated[
655
+ Optional[bool],
656
+ typer.Option(..., help="Enable web search tool calling", hidden=True),
657
+ ] = False,
658
+ require_mcp: Annotated[
659
+ Optional[bool], typer.Option(..., help="Enable mcp tool calling", hidden=True)
660
+ ] = False,
661
+ require_storage: Annotated[
662
+ Optional[bool], typer.Option(..., help="Enable storage toolkit", hidden=True)
663
+ ] = False,
664
+ require_table_read: Annotated[
665
+ list[str],
666
+ typer.Option(
667
+ ..., help="Enable table read tools for a specific table", hidden=True
668
+ ),
669
+ ] = [],
670
+ require_table_write: Annotated[
671
+ list[str],
672
+ typer.Option(
673
+ ..., help="Enable table write tools for a specific table", hidden=True
674
+ ),
675
+ ] = [],
676
+ require_read_only_storage: Annotated[
677
+ Optional[bool],
678
+ typer.Option(..., help="Enable read only storage toolkit", hidden=True),
679
+ ] = False,
680
+ working_directory: Annotated[
681
+ Optional[str],
682
+ typer.Option(..., help="The default working directory for shell commands"),
683
+ ] = None,
684
+ require_document_authoring: Annotated[
685
+ Optional[bool],
686
+ typer.Option(..., help="Enable document authoring", hidden=True),
687
+ ] = False,
688
+ require_discovery: Annotated[
689
+ Optional[bool],
690
+ typer.Option(..., help="Enable discovery of agents and tools", hidden=True),
691
+ ] = False,
692
+ llm_participant: Annotated[
693
+ Optional[str],
694
+ typer.Option(
695
+ ..., help="Delegate LLM interactions to a remote participant", hidden=True
696
+ ),
697
+ ] = None,
698
+ host: Annotated[
699
+ Optional[str], typer.Option(help="Host to bind the service on")
700
+ ] = None,
701
+ port: Annotated[
702
+ Optional[int], typer.Option(help="Port to bind the service on")
703
+ ] = None,
704
+ path: Annotated[
705
+ str, typer.Option(help="HTTP path to mount the service at")
706
+ ] = "/agent",
707
+ output_schema: Annotated[
708
+ Optional[str],
709
+ typer.Option(..., help="an output schema to use", hidden=True),
710
+ ] = None,
711
+ output_schema_path: Annotated[
712
+ Optional[str],
713
+ typer.Option(..., help="the path or url to output schema to use", hidden=True),
714
+ ] = None,
715
+ annotations: Annotated[
716
+ str,
717
+ typer.Option(
718
+ "--annotations", "-a", help='annotations in json format {"name":"value"}'
719
+ ),
720
+ ] = '{"meshagent.task-runner.attachment-format":"tar"}',
721
+ title: Annotated[
722
+ Optional[str], typer.Option(..., help="a friendly name for the task runner")
723
+ ] = None,
724
+ description: Annotated[
725
+ Optional[str], typer.Option(..., help="a description for the task runner")
726
+ ] = None,
727
+ ):
728
+ print("[bold green]Connecting to room...[/bold green]", flush=True)
729
+
730
+ service = ServiceHost(host=host, port=port)
731
+ service.add_path(
732
+ path=path,
733
+ cls=build_task_runner(
734
+ model=model,
735
+ local_shell=local_shell,
736
+ shell=shell,
737
+ apply_patch=apply_patch,
738
+ agent_name=agent_name,
739
+ title=title,
740
+ description=description,
741
+ rule=rule,
742
+ toolkit=toolkit,
743
+ schema=schema,
744
+ rules_file=rules_file,
745
+ web_search=web_search,
746
+ image_generation=image_generation,
747
+ mcp=mcp,
748
+ storage=storage,
749
+ require_web_search=require_web_search,
750
+ require_shell=require_shell,
751
+ require_apply_patch=require_apply_patch,
752
+ require_local_shell=require_local_shell,
753
+ require_image_generation=require_image_generation,
754
+ require_mcp=require_mcp,
755
+ require_storage=require_storage,
756
+ require_table_write=require_table_write,
757
+ require_table_read=require_table_read,
758
+ require_read_only_storage=require_read_only_storage,
759
+ room_rules_path=room_rules,
760
+ working_directory=working_directory,
761
+ require_document_authoring=require_document_authoring,
762
+ require_discovery=require_discovery,
763
+ llm_participant=llm_participant,
764
+ output_schema_str=output_schema,
765
+ output_schema_path=output_schema_path,
766
+ annotations=json.loads(annotations) if annotations != "" else {},
767
+ ),
768
+ )
769
+
770
+ await service.run()