meshagent-cli 0.22.2__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/__init__.py +3 -0
- meshagent/cli/agent.py +273 -0
- meshagent/cli/api_keys.py +102 -0
- meshagent/cli/async_typer.py +79 -0
- meshagent/cli/auth.py +30 -0
- meshagent/cli/auth_async.py +295 -0
- meshagent/cli/call.py +215 -0
- meshagent/cli/chatbot.py +1983 -0
- meshagent/cli/cli.py +187 -0
- meshagent/cli/cli_mcp.py +408 -0
- meshagent/cli/cli_secrets.py +414 -0
- meshagent/cli/common_options.py +47 -0
- meshagent/cli/containers.py +725 -0
- meshagent/cli/database.py +997 -0
- meshagent/cli/developer.py +70 -0
- meshagent/cli/exec.py +397 -0
- meshagent/cli/helper.py +236 -0
- meshagent/cli/helpers.py +185 -0
- meshagent/cli/host.py +41 -0
- meshagent/cli/mailbot.py +1295 -0
- meshagent/cli/mailboxes.py +223 -0
- meshagent/cli/meeting_transcriber.py +138 -0
- meshagent/cli/messaging.py +157 -0
- meshagent/cli/multi.py +357 -0
- meshagent/cli/oauth2.py +341 -0
- meshagent/cli/participant_token.py +63 -0
- meshagent/cli/port.py +70 -0
- meshagent/cli/projects.py +105 -0
- meshagent/cli/queue.py +91 -0
- meshagent/cli/room.py +26 -0
- meshagent/cli/rooms.py +214 -0
- meshagent/cli/services.py +722 -0
- meshagent/cli/sessions.py +26 -0
- meshagent/cli/storage.py +813 -0
- meshagent/cli/sync.py +434 -0
- meshagent/cli/task_runner.py +1317 -0
- meshagent/cli/version.py +1 -0
- meshagent/cli/voicebot.py +624 -0
- meshagent/cli/webhook.py +100 -0
- meshagent/cli/worker.py +1403 -0
- meshagent_cli-0.22.2.dist-info/METADATA +49 -0
- meshagent_cli-0.22.2.dist-info/RECORD +45 -0
- meshagent_cli-0.22.2.dist-info/WHEEL +5 -0
- meshagent_cli-0.22.2.dist-info/entry_points.txt +2 -0
- meshagent_cli-0.22.2.dist-info/top_level.txt +1 -0
meshagent/cli/chatbot.py
ADDED
|
@@ -0,0 +1,1983 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from rich import print
|
|
3
|
+
from typing import Annotated, Optional, List
|
|
4
|
+
from meshagent.tools import Toolkit, ToolkitConfig
|
|
5
|
+
from meshagent.tools.storage import StorageToolkitBuilder, StorageToolkitConfig
|
|
6
|
+
from meshagent.tools.datetime import DatetimeToolkit
|
|
7
|
+
from meshagent.tools.uuid import UUIDToolkit
|
|
8
|
+
from meshagent.tools.document_tools import (
|
|
9
|
+
DocumentAuthoringToolkit,
|
|
10
|
+
DocumentTypeAuthoringToolkit,
|
|
11
|
+
)
|
|
12
|
+
from meshagent.agents.config import RulesConfig
|
|
13
|
+
from meshagent.agents.widget_schema import widget_schema
|
|
14
|
+
|
|
15
|
+
from meshagent.cli.common_options import (
|
|
16
|
+
ProjectIdOption,
|
|
17
|
+
RoomOption,
|
|
18
|
+
)
|
|
19
|
+
from meshagent.api import (
|
|
20
|
+
RoomClient,
|
|
21
|
+
WebSocketClientProtocol,
|
|
22
|
+
ParticipantToken,
|
|
23
|
+
ApiScope,
|
|
24
|
+
RoomException,
|
|
25
|
+
RemoteParticipant,
|
|
26
|
+
)
|
|
27
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
28
|
+
from meshagent.cli import async_typer
|
|
29
|
+
from meshagent.cli.helper import (
|
|
30
|
+
get_client,
|
|
31
|
+
resolve_project_id,
|
|
32
|
+
resolve_room,
|
|
33
|
+
resolve_key,
|
|
34
|
+
cleanup_args,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
from meshagent.openai import OpenAIResponsesAdapter
|
|
38
|
+
from meshagent.anthropic import AnthropicOpenAIResponsesStreamAdapter
|
|
39
|
+
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
|
|
42
|
+
from meshagent.openai.tools.responses_adapter import (
|
|
43
|
+
WebSearchToolkitBuilder,
|
|
44
|
+
MCPToolkitBuilder,
|
|
45
|
+
WebSearchTool,
|
|
46
|
+
LocalShellConfig,
|
|
47
|
+
ShellConfig,
|
|
48
|
+
WebSearchConfig,
|
|
49
|
+
ApplyPatchConfig,
|
|
50
|
+
ApplyPatchTool,
|
|
51
|
+
ApplyPatchToolkitBuilder,
|
|
52
|
+
ShellToolkitBuilder,
|
|
53
|
+
ShellTool,
|
|
54
|
+
LocalShellToolkitBuilder,
|
|
55
|
+
LocalShellTool,
|
|
56
|
+
ImageGenerationConfig,
|
|
57
|
+
ImageGenerationToolkitBuilder,
|
|
58
|
+
ImageGenerationTool,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
from meshagent.tools.database import DatabaseToolkitBuilder, DatabaseToolkitConfig
|
|
62
|
+
from meshagent.agents.adapter import MessageStreamLLMAdapter
|
|
63
|
+
|
|
64
|
+
from meshagent.api import RequiredToolkit, RequiredSchema
|
|
65
|
+
import logging
|
|
66
|
+
import os.path
|
|
67
|
+
|
|
68
|
+
from meshagent.api.specs.service import AgentSpec, ANNOTATION_AGENT_TYPE
|
|
69
|
+
|
|
70
|
+
from meshagent.cli.host import get_service, run_services, get_deferred, service_specs
|
|
71
|
+
|
|
72
|
+
import yaml
|
|
73
|
+
|
|
74
|
+
import shlex
|
|
75
|
+
import sys
|
|
76
|
+
|
|
77
|
+
import asyncio
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
from meshagent.api.client import ConflictError
|
|
81
|
+
|
|
82
|
+
logger = logging.getLogger("chatbot")
|
|
83
|
+
|
|
84
|
+
app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def build_chatbot(
|
|
88
|
+
*,
|
|
89
|
+
model: str,
|
|
90
|
+
rule: List[str],
|
|
91
|
+
toolkit: List[str],
|
|
92
|
+
schema: List[str],
|
|
93
|
+
image_generation: Optional[str] = None,
|
|
94
|
+
local_shell: Optional[str] = None,
|
|
95
|
+
shell: Optional[str] = None,
|
|
96
|
+
apply_patch: Optional[str] = None,
|
|
97
|
+
computer_use: Optional[str] = None,
|
|
98
|
+
web_search: Optional[str] = None,
|
|
99
|
+
mcp: Optional[str] = None,
|
|
100
|
+
storage: Optional[str] = None,
|
|
101
|
+
require_image_generation: Optional[str] = None,
|
|
102
|
+
require_local_shell: Optional[str] = None,
|
|
103
|
+
require_shell: Optional[bool] = None,
|
|
104
|
+
require_apply_patch: Optional[str] = None,
|
|
105
|
+
require_computer_use: Optional[str] = None,
|
|
106
|
+
require_web_search: Optional[str] = None,
|
|
107
|
+
require_mcp: Optional[str] = None,
|
|
108
|
+
require_storage: Optional[str] = None,
|
|
109
|
+
require_table_read: list[str] = None,
|
|
110
|
+
require_table_write: list[str] = None,
|
|
111
|
+
require_read_only_storage: Optional[str] = None,
|
|
112
|
+
require_time: bool = True,
|
|
113
|
+
require_uuid: bool = False,
|
|
114
|
+
rules_file: Optional[str] = None,
|
|
115
|
+
room_rules_path: Optional[list[str]] = None,
|
|
116
|
+
require_discovery: Optional[str] = None,
|
|
117
|
+
require_document_authoring: Optional[str] = None,
|
|
118
|
+
working_directory: Optional[str] = None,
|
|
119
|
+
llm_participant: Optional[str] = None,
|
|
120
|
+
database_namespace: Optional[list[str]] = None,
|
|
121
|
+
always_reply: Optional[bool] = None,
|
|
122
|
+
skill_dirs: Optional[list[str]] = None,
|
|
123
|
+
shell_image: Optional[str] = None,
|
|
124
|
+
log_llm_requests: Optional[bool] = None,
|
|
125
|
+
delegate_shell_token: Optional[bool] = None,
|
|
126
|
+
):
|
|
127
|
+
from meshagent.agents.chat import ChatBot
|
|
128
|
+
|
|
129
|
+
from meshagent.tools.storage import StorageToolkit
|
|
130
|
+
|
|
131
|
+
requirements = []
|
|
132
|
+
|
|
133
|
+
toolkits = []
|
|
134
|
+
|
|
135
|
+
for t in toolkit:
|
|
136
|
+
requirements.append(RequiredToolkit(name=t))
|
|
137
|
+
|
|
138
|
+
for t in schema:
|
|
139
|
+
requirements.append(RequiredSchema(name=t))
|
|
140
|
+
|
|
141
|
+
client_rules = {}
|
|
142
|
+
|
|
143
|
+
if rules_file is not None:
|
|
144
|
+
try:
|
|
145
|
+
with open(Path(os.path.expanduser(rules_file)).resolve(), "r") as f:
|
|
146
|
+
rules_config = RulesConfig.parse(f.read())
|
|
147
|
+
rule.extend(rules_config.rules)
|
|
148
|
+
client_rules = rules_config.client_rules
|
|
149
|
+
|
|
150
|
+
except FileNotFoundError:
|
|
151
|
+
print(f"[yellow]rules file not found at {rules_file}[/yellow]")
|
|
152
|
+
|
|
153
|
+
BaseClass = ChatBot
|
|
154
|
+
decision_model = None
|
|
155
|
+
if llm_participant:
|
|
156
|
+
llm_adapter = MessageStreamLLMAdapter(
|
|
157
|
+
participant_name=llm_participant,
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
if computer_use or require_computer_use:
|
|
161
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
162
|
+
model=model,
|
|
163
|
+
response_options={
|
|
164
|
+
"reasoning": {"summary": "concise"},
|
|
165
|
+
"truncation": "auto",
|
|
166
|
+
},
|
|
167
|
+
log_requests=log_llm_requests,
|
|
168
|
+
)
|
|
169
|
+
else:
|
|
170
|
+
if model.startswith("claude-"):
|
|
171
|
+
llm_adapter = AnthropicOpenAIResponsesStreamAdapter(
|
|
172
|
+
model=model,
|
|
173
|
+
log_requests=log_llm_requests,
|
|
174
|
+
)
|
|
175
|
+
decision_model = model
|
|
176
|
+
else:
|
|
177
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
178
|
+
model=model,
|
|
179
|
+
log_requests=log_llm_requests,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
class CustomChatbot(BaseClass):
|
|
183
|
+
def __init__(self):
|
|
184
|
+
super().__init__(
|
|
185
|
+
llm_adapter=llm_adapter,
|
|
186
|
+
requires=requirements,
|
|
187
|
+
toolkits=toolkits,
|
|
188
|
+
rules=rule if len(rule) > 0 else None,
|
|
189
|
+
client_rules=client_rules,
|
|
190
|
+
always_reply=always_reply,
|
|
191
|
+
skill_dirs=skill_dirs,
|
|
192
|
+
decision_model=decision_model,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
async def start(self, *, room: RoomClient):
|
|
196
|
+
await super().start(room=room)
|
|
197
|
+
|
|
198
|
+
if room_rules_path is not None:
|
|
199
|
+
for p in room_rules_path:
|
|
200
|
+
await self._load_room_rules(path=p)
|
|
201
|
+
|
|
202
|
+
async def init_chat_context(self):
|
|
203
|
+
from meshagent.cli.helper import init_context_from_spec
|
|
204
|
+
|
|
205
|
+
context = await super().init_chat_context()
|
|
206
|
+
await init_context_from_spec(context)
|
|
207
|
+
|
|
208
|
+
return context
|
|
209
|
+
|
|
210
|
+
async def _load_room_rules(
|
|
211
|
+
self,
|
|
212
|
+
*,
|
|
213
|
+
path: str,
|
|
214
|
+
participant: Optional[RemoteParticipant] = None,
|
|
215
|
+
):
|
|
216
|
+
rules = []
|
|
217
|
+
try:
|
|
218
|
+
room_rules = await self.room.storage.download(path=path)
|
|
219
|
+
|
|
220
|
+
rules_txt = room_rules.data.decode()
|
|
221
|
+
|
|
222
|
+
rules_config = RulesConfig.parse(rules_txt)
|
|
223
|
+
|
|
224
|
+
if rules_config.rules is not None:
|
|
225
|
+
rules.extend(rules_config.rules)
|
|
226
|
+
|
|
227
|
+
if participant is not None:
|
|
228
|
+
client = participant.get_attribute("client")
|
|
229
|
+
|
|
230
|
+
if rules_config.client_rules is not None and client is not None:
|
|
231
|
+
cr = rules_config.client_rules.get(client)
|
|
232
|
+
if cr is not None:
|
|
233
|
+
rules.extend(cr)
|
|
234
|
+
|
|
235
|
+
except RoomException:
|
|
236
|
+
try:
|
|
237
|
+
logger.info("attempting to initialize rules file")
|
|
238
|
+
handle = await self.room.storage.open(path=path, overwrite=False)
|
|
239
|
+
await self.room.storage.write(
|
|
240
|
+
handle=handle,
|
|
241
|
+
data="# Add rules to this file to customize your agent's behavior, lines starting with # will be ignored.\n\n".encode(),
|
|
242
|
+
)
|
|
243
|
+
await self.room.storage.close(handle=handle)
|
|
244
|
+
|
|
245
|
+
except RoomException:
|
|
246
|
+
pass
|
|
247
|
+
logger.info(
|
|
248
|
+
f"unable to load rules from {path}, continuing with default rules"
|
|
249
|
+
)
|
|
250
|
+
pass
|
|
251
|
+
|
|
252
|
+
return rules
|
|
253
|
+
|
|
254
|
+
async def get_rules(self, *, thread_context, participant):
|
|
255
|
+
rules = await super().get_rules(
|
|
256
|
+
thread_context=thread_context, participant=participant
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if room_rules_path is not None:
|
|
260
|
+
for p in room_rules_path:
|
|
261
|
+
rules.extend(
|
|
262
|
+
await self._load_room_rules(path=p, participant=participant)
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
logging.info(f"using rules {rules}")
|
|
266
|
+
|
|
267
|
+
return rules
|
|
268
|
+
|
|
269
|
+
async def get_thread_toolkits(self, *, thread_context, participant):
|
|
270
|
+
providers = []
|
|
271
|
+
|
|
272
|
+
if require_image_generation:
|
|
273
|
+
providers.append(
|
|
274
|
+
ImageGenerationTool(
|
|
275
|
+
config=ImageGenerationConfig(
|
|
276
|
+
name="image_generation",
|
|
277
|
+
partial_images=3,
|
|
278
|
+
),
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
if require_local_shell:
|
|
283
|
+
providers.append(
|
|
284
|
+
LocalShellTool(
|
|
285
|
+
working_directory=working_directory,
|
|
286
|
+
config=LocalShellConfig(name="local_shell"),
|
|
287
|
+
)
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
env = {}
|
|
291
|
+
|
|
292
|
+
if delegate_shell_token:
|
|
293
|
+
env["MESHAGENT_TOKEN"] = self.room.protocol.token
|
|
294
|
+
|
|
295
|
+
if require_shell:
|
|
296
|
+
providers.append(
|
|
297
|
+
ShellTool(
|
|
298
|
+
working_directory=working_directory,
|
|
299
|
+
config=ShellConfig(name="shell"),
|
|
300
|
+
image=shell_image or "python:3.13",
|
|
301
|
+
env=env,
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
if require_apply_patch:
|
|
306
|
+
providers.append(
|
|
307
|
+
ApplyPatchTool(
|
|
308
|
+
config=ApplyPatchConfig(name="apply_patch"),
|
|
309
|
+
)
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
if require_mcp:
|
|
313
|
+
raise Exception(
|
|
314
|
+
"mcp tool cannot be required by cli currently, use 'optional' instead"
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
if require_web_search:
|
|
318
|
+
providers.append(
|
|
319
|
+
WebSearchTool(config=WebSearchConfig(name="web_search"))
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
if require_storage:
|
|
323
|
+
providers.extend(StorageToolkit().tools)
|
|
324
|
+
|
|
325
|
+
if len(require_table_read) > 0:
|
|
326
|
+
providers.extend(
|
|
327
|
+
(
|
|
328
|
+
await DatabaseToolkitBuilder().make(
|
|
329
|
+
room=self.room,
|
|
330
|
+
model=model,
|
|
331
|
+
config=DatabaseToolkitConfig(
|
|
332
|
+
tables=require_table_read,
|
|
333
|
+
read_only=True,
|
|
334
|
+
namespace=database_namespace,
|
|
335
|
+
),
|
|
336
|
+
)
|
|
337
|
+
).tools
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
if require_time:
|
|
341
|
+
providers.extend((DatetimeToolkit()).tools)
|
|
342
|
+
|
|
343
|
+
if require_uuid:
|
|
344
|
+
providers.extend((UUIDToolkit()).tools)
|
|
345
|
+
|
|
346
|
+
if len(require_table_write) > 0:
|
|
347
|
+
providers.extend(
|
|
348
|
+
(
|
|
349
|
+
await DatabaseToolkitBuilder().make(
|
|
350
|
+
room=self.room,
|
|
351
|
+
model=model,
|
|
352
|
+
config=DatabaseToolkitConfig(
|
|
353
|
+
tables=require_table_write,
|
|
354
|
+
read_only=False,
|
|
355
|
+
namespace=database_namespace,
|
|
356
|
+
),
|
|
357
|
+
)
|
|
358
|
+
).tools
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
if require_read_only_storage:
|
|
362
|
+
providers.extend(StorageToolkit(read_only=True).tools)
|
|
363
|
+
|
|
364
|
+
if require_document_authoring:
|
|
365
|
+
providers.extend(DocumentAuthoringToolkit().tools)
|
|
366
|
+
providers.extend(
|
|
367
|
+
DocumentTypeAuthoringToolkit(
|
|
368
|
+
schema=widget_schema, document_type="widget"
|
|
369
|
+
).tools
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
if require_discovery:
|
|
373
|
+
from meshagent.tools.discovery import DiscoveryToolkit
|
|
374
|
+
|
|
375
|
+
providers.extend(DiscoveryToolkit().tools)
|
|
376
|
+
|
|
377
|
+
tk = await super().get_thread_toolkits(
|
|
378
|
+
thread_context=thread_context, participant=participant
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
if require_computer_use:
|
|
382
|
+
from meshagent.computers.agent import ComputerToolkit
|
|
383
|
+
|
|
384
|
+
def render_screen(image_bytes: bytes):
|
|
385
|
+
for participant in thread_context.participants:
|
|
386
|
+
self.room.messaging.send_message_nowait(
|
|
387
|
+
to=participant,
|
|
388
|
+
type="computer_screen",
|
|
389
|
+
message={},
|
|
390
|
+
attachment=image_bytes,
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
computer_toolkit = ComputerToolkit(
|
|
394
|
+
room=self.room, render_screen=render_screen
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
tk.append(computer_toolkit)
|
|
398
|
+
|
|
399
|
+
return [
|
|
400
|
+
*(
|
|
401
|
+
[Toolkit(name="tools", tools=providers)]
|
|
402
|
+
if len(providers) > 0
|
|
403
|
+
else []
|
|
404
|
+
),
|
|
405
|
+
*tk,
|
|
406
|
+
]
|
|
407
|
+
|
|
408
|
+
def get_toolkit_builders(self):
|
|
409
|
+
providers = []
|
|
410
|
+
|
|
411
|
+
if image_generation:
|
|
412
|
+
providers.append(ImageGenerationToolkitBuilder())
|
|
413
|
+
|
|
414
|
+
if apply_patch:
|
|
415
|
+
providers.append(ApplyPatchToolkitBuilder())
|
|
416
|
+
|
|
417
|
+
if local_shell:
|
|
418
|
+
providers.append(
|
|
419
|
+
LocalShellToolkitBuilder(
|
|
420
|
+
working_directory=working_directory,
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
if shell:
|
|
425
|
+
providers.append(
|
|
426
|
+
ShellToolkitBuilder(
|
|
427
|
+
working_directory=working_directory,
|
|
428
|
+
image=shell_image,
|
|
429
|
+
)
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
if mcp:
|
|
433
|
+
providers.append(MCPToolkitBuilder())
|
|
434
|
+
|
|
435
|
+
if web_search:
|
|
436
|
+
providers.append(WebSearchToolkitBuilder())
|
|
437
|
+
|
|
438
|
+
if storage:
|
|
439
|
+
providers.append(StorageToolkitBuilder())
|
|
440
|
+
|
|
441
|
+
return providers
|
|
442
|
+
|
|
443
|
+
return CustomChatbot
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
@app.async_command("join")
|
|
447
|
+
async def join(
|
|
448
|
+
*,
|
|
449
|
+
project_id: ProjectIdOption,
|
|
450
|
+
room: RoomOption,
|
|
451
|
+
role: str = "agent",
|
|
452
|
+
agent_name: Annotated[
|
|
453
|
+
Optional[str], typer.Option(..., help="Name of the agent to call")
|
|
454
|
+
] = None,
|
|
455
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
456
|
+
room_rules: Annotated[
|
|
457
|
+
List[str],
|
|
458
|
+
typer.Option(
|
|
459
|
+
"--room-rules",
|
|
460
|
+
"-rr",
|
|
461
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
462
|
+
),
|
|
463
|
+
] = [],
|
|
464
|
+
rules_file: Optional[str] = None,
|
|
465
|
+
require_toolkit: Annotated[
|
|
466
|
+
List[str],
|
|
467
|
+
typer.Option(
|
|
468
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
469
|
+
),
|
|
470
|
+
] = [],
|
|
471
|
+
require_schema: Annotated[
|
|
472
|
+
List[str],
|
|
473
|
+
typer.Option(
|
|
474
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
475
|
+
),
|
|
476
|
+
] = [],
|
|
477
|
+
toolkit: Annotated[
|
|
478
|
+
List[str],
|
|
479
|
+
typer.Option(
|
|
480
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
481
|
+
),
|
|
482
|
+
] = [],
|
|
483
|
+
schema: Annotated[
|
|
484
|
+
List[str],
|
|
485
|
+
typer.Option(
|
|
486
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
487
|
+
),
|
|
488
|
+
] = [],
|
|
489
|
+
model: Annotated[
|
|
490
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
491
|
+
] = "gpt-5.2",
|
|
492
|
+
image_generation: Annotated[
|
|
493
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
494
|
+
] = None,
|
|
495
|
+
computer_use: Annotated[
|
|
496
|
+
Optional[bool],
|
|
497
|
+
typer.Option(
|
|
498
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
499
|
+
),
|
|
500
|
+
] = False,
|
|
501
|
+
local_shell: Annotated[
|
|
502
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
503
|
+
] = False,
|
|
504
|
+
shell: Annotated[
|
|
505
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
506
|
+
] = False,
|
|
507
|
+
apply_patch: Annotated[
|
|
508
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
509
|
+
] = False,
|
|
510
|
+
web_search: Annotated[
|
|
511
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
512
|
+
] = False,
|
|
513
|
+
mcp: Annotated[
|
|
514
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
515
|
+
] = False,
|
|
516
|
+
storage: Annotated[
|
|
517
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
518
|
+
] = False,
|
|
519
|
+
require_image_generation: Annotated[
|
|
520
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
521
|
+
] = None,
|
|
522
|
+
require_computer_use: Annotated[
|
|
523
|
+
Optional[bool],
|
|
524
|
+
typer.Option(
|
|
525
|
+
...,
|
|
526
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
527
|
+
hidden=True,
|
|
528
|
+
),
|
|
529
|
+
] = False,
|
|
530
|
+
require_local_shell: Annotated[
|
|
531
|
+
Optional[bool],
|
|
532
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
533
|
+
] = False,
|
|
534
|
+
require_shell: Annotated[
|
|
535
|
+
Optional[bool],
|
|
536
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
537
|
+
] = False,
|
|
538
|
+
require_apply_patch: Annotated[
|
|
539
|
+
Optional[bool],
|
|
540
|
+
typer.Option(..., help="Enable apply patch tool calling"),
|
|
541
|
+
] = False,
|
|
542
|
+
require_web_search: Annotated[
|
|
543
|
+
Optional[bool],
|
|
544
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
545
|
+
] = False,
|
|
546
|
+
require_mcp: Annotated[
|
|
547
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
548
|
+
] = False,
|
|
549
|
+
require_storage: Annotated[
|
|
550
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
551
|
+
] = False,
|
|
552
|
+
database_namespace: Annotated[
|
|
553
|
+
Optional[str],
|
|
554
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
555
|
+
] = None,
|
|
556
|
+
require_table_read: Annotated[
|
|
557
|
+
list[str],
|
|
558
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
559
|
+
] = [],
|
|
560
|
+
require_table_write: Annotated[
|
|
561
|
+
list[str],
|
|
562
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
563
|
+
] = [],
|
|
564
|
+
require_read_only_storage: Annotated[
|
|
565
|
+
Optional[bool],
|
|
566
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
567
|
+
] = False,
|
|
568
|
+
require_time: Annotated[
|
|
569
|
+
bool,
|
|
570
|
+
typer.Option(
|
|
571
|
+
...,
|
|
572
|
+
help="Enable time/datetime tools",
|
|
573
|
+
),
|
|
574
|
+
] = True,
|
|
575
|
+
require_uuid: Annotated[
|
|
576
|
+
bool,
|
|
577
|
+
typer.Option(
|
|
578
|
+
...,
|
|
579
|
+
help="Enable UUID generation tools",
|
|
580
|
+
),
|
|
581
|
+
] = False,
|
|
582
|
+
require_document_authoring: Annotated[
|
|
583
|
+
Optional[bool],
|
|
584
|
+
typer.Option(..., help="Enable MeshDocument authoring"),
|
|
585
|
+
] = False,
|
|
586
|
+
require_discovery: Annotated[
|
|
587
|
+
Optional[bool],
|
|
588
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
589
|
+
] = False,
|
|
590
|
+
working_directory: Annotated[
|
|
591
|
+
Optional[str],
|
|
592
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
593
|
+
] = None,
|
|
594
|
+
key: Annotated[
|
|
595
|
+
str,
|
|
596
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
597
|
+
] = None,
|
|
598
|
+
llm_participant: Annotated[
|
|
599
|
+
Optional[str],
|
|
600
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
601
|
+
] = None,
|
|
602
|
+
always_reply: Annotated[
|
|
603
|
+
Optional[bool],
|
|
604
|
+
typer.Option(..., help="Always reply"),
|
|
605
|
+
] = None,
|
|
606
|
+
skill_dir: Annotated[
|
|
607
|
+
list[str],
|
|
608
|
+
typer.Option(..., help="an agent skills directory"),
|
|
609
|
+
] = [],
|
|
610
|
+
shell_image: Annotated[
|
|
611
|
+
Optional[str],
|
|
612
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
613
|
+
] = None,
|
|
614
|
+
delegate_shell_token: Annotated[
|
|
615
|
+
Optional[bool],
|
|
616
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
617
|
+
] = False,
|
|
618
|
+
log_llm_requests: Annotated[
|
|
619
|
+
Optional[bool],
|
|
620
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
621
|
+
] = False,
|
|
622
|
+
):
|
|
623
|
+
if database_namespace is not None:
|
|
624
|
+
database_namespace = database_namespace.split("::")
|
|
625
|
+
|
|
626
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
627
|
+
account_client = await get_client()
|
|
628
|
+
try:
|
|
629
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
630
|
+
room = resolve_room(room)
|
|
631
|
+
|
|
632
|
+
jwt = os.getenv("MESHAGENT_TOKEN")
|
|
633
|
+
if jwt is None:
|
|
634
|
+
if agent_name is None:
|
|
635
|
+
print(
|
|
636
|
+
"[bold red]--agent-name must be specified when the MESHAGENT_TOKEN environment variable is not set[/bold red]"
|
|
637
|
+
)
|
|
638
|
+
raise typer.Exit(1)
|
|
639
|
+
|
|
640
|
+
token = ParticipantToken(
|
|
641
|
+
name=agent_name,
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
token.add_api_grant(ApiScope.agent_default(tunnels=require_computer_use))
|
|
645
|
+
|
|
646
|
+
token.add_role_grant(role=role)
|
|
647
|
+
token.add_room_grant(room)
|
|
648
|
+
|
|
649
|
+
jwt = token.to_jwt(api_key=key)
|
|
650
|
+
|
|
651
|
+
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
652
|
+
|
|
653
|
+
CustomChatbot = build_chatbot(
|
|
654
|
+
computer_use=computer_use,
|
|
655
|
+
require_computer_use=require_computer_use,
|
|
656
|
+
model=model,
|
|
657
|
+
rule=rule,
|
|
658
|
+
toolkit=require_toolkit + toolkit,
|
|
659
|
+
schema=require_schema + schema,
|
|
660
|
+
rules_file=rules_file,
|
|
661
|
+
local_shell=local_shell,
|
|
662
|
+
shell=shell,
|
|
663
|
+
apply_patch=apply_patch,
|
|
664
|
+
image_generation=image_generation,
|
|
665
|
+
web_search=web_search,
|
|
666
|
+
mcp=mcp,
|
|
667
|
+
storage=storage,
|
|
668
|
+
require_apply_patch=require_apply_patch,
|
|
669
|
+
require_web_search=require_web_search,
|
|
670
|
+
require_local_shell=require_local_shell,
|
|
671
|
+
require_shell=require_shell,
|
|
672
|
+
require_image_generation=require_image_generation,
|
|
673
|
+
require_mcp=require_mcp,
|
|
674
|
+
require_storage=require_storage,
|
|
675
|
+
require_table_read=require_table_read,
|
|
676
|
+
require_table_write=require_table_write,
|
|
677
|
+
require_read_only_storage=require_read_only_storage,
|
|
678
|
+
require_time=require_time,
|
|
679
|
+
require_uuid=require_uuid,
|
|
680
|
+
room_rules_path=room_rules,
|
|
681
|
+
require_document_authoring=require_document_authoring,
|
|
682
|
+
require_discovery=require_discovery,
|
|
683
|
+
working_directory=working_directory,
|
|
684
|
+
llm_participant=llm_participant,
|
|
685
|
+
always_reply=always_reply,
|
|
686
|
+
database_namespace=database_namespace,
|
|
687
|
+
skill_dirs=skill_dir,
|
|
688
|
+
shell_image=shell_image,
|
|
689
|
+
delegate_shell_token=delegate_shell_token,
|
|
690
|
+
log_llm_requests=log_llm_requests,
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
bot = CustomChatbot()
|
|
694
|
+
|
|
695
|
+
if get_deferred():
|
|
696
|
+
from meshagent.cli.host import agents
|
|
697
|
+
|
|
698
|
+
agents.append((bot, jwt))
|
|
699
|
+
else:
|
|
700
|
+
async with RoomClient(
|
|
701
|
+
protocol=WebSocketClientProtocol(
|
|
702
|
+
url=websocket_room_url(
|
|
703
|
+
room_name=room, base_url=meshagent_base_url()
|
|
704
|
+
),
|
|
705
|
+
token=jwt,
|
|
706
|
+
)
|
|
707
|
+
) as client:
|
|
708
|
+
await bot.start(room=client)
|
|
709
|
+
try:
|
|
710
|
+
print(
|
|
711
|
+
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]",
|
|
712
|
+
flush=True,
|
|
713
|
+
)
|
|
714
|
+
await client.protocol.wait_for_close()
|
|
715
|
+
|
|
716
|
+
except KeyboardInterrupt:
|
|
717
|
+
await bot.stop()
|
|
718
|
+
finally:
|
|
719
|
+
await account_client.close()
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
@app.async_command("service")
|
|
723
|
+
async def service(
|
|
724
|
+
*,
|
|
725
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
726
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
727
|
+
rules_file: Optional[str] = None,
|
|
728
|
+
room_rules: Annotated[
|
|
729
|
+
List[str],
|
|
730
|
+
typer.Option(
|
|
731
|
+
"--room-rules",
|
|
732
|
+
"-rr",
|
|
733
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
734
|
+
),
|
|
735
|
+
] = [],
|
|
736
|
+
require_toolkit: Annotated[
|
|
737
|
+
List[str],
|
|
738
|
+
typer.Option(
|
|
739
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
740
|
+
),
|
|
741
|
+
] = [],
|
|
742
|
+
require_schema: Annotated[
|
|
743
|
+
List[str],
|
|
744
|
+
typer.Option(
|
|
745
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
746
|
+
),
|
|
747
|
+
] = [],
|
|
748
|
+
toolkit: Annotated[
|
|
749
|
+
List[str],
|
|
750
|
+
typer.Option(
|
|
751
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
752
|
+
),
|
|
753
|
+
] = [],
|
|
754
|
+
schema: Annotated[
|
|
755
|
+
List[str],
|
|
756
|
+
typer.Option(
|
|
757
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
758
|
+
),
|
|
759
|
+
] = [],
|
|
760
|
+
model: Annotated[
|
|
761
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
762
|
+
] = "gpt-5.2",
|
|
763
|
+
image_generation: Annotated[
|
|
764
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
765
|
+
] = None,
|
|
766
|
+
local_shell: Annotated[
|
|
767
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
768
|
+
] = False,
|
|
769
|
+
shell: Annotated[
|
|
770
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
771
|
+
] = False,
|
|
772
|
+
apply_patch: Annotated[
|
|
773
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
774
|
+
] = False,
|
|
775
|
+
computer_use: Annotated[
|
|
776
|
+
Optional[bool],
|
|
777
|
+
typer.Option(
|
|
778
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
779
|
+
),
|
|
780
|
+
] = False,
|
|
781
|
+
web_search: Annotated[
|
|
782
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
783
|
+
] = False,
|
|
784
|
+
mcp: Annotated[
|
|
785
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
786
|
+
] = False,
|
|
787
|
+
storage: Annotated[
|
|
788
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
789
|
+
] = False,
|
|
790
|
+
require_image_generation: Annotated[
|
|
791
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
792
|
+
] = None,
|
|
793
|
+
require_computer_use: Annotated[
|
|
794
|
+
Optional[bool],
|
|
795
|
+
typer.Option(
|
|
796
|
+
...,
|
|
797
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
798
|
+
hidden=True,
|
|
799
|
+
),
|
|
800
|
+
] = False,
|
|
801
|
+
require_local_shell: Annotated[
|
|
802
|
+
Optional[bool],
|
|
803
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
804
|
+
] = False,
|
|
805
|
+
require_shell: Annotated[
|
|
806
|
+
Optional[bool],
|
|
807
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
808
|
+
] = False,
|
|
809
|
+
require_apply_patch: Annotated[
|
|
810
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
811
|
+
] = False,
|
|
812
|
+
require_web_search: Annotated[
|
|
813
|
+
Optional[bool],
|
|
814
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
815
|
+
] = False,
|
|
816
|
+
require_mcp: Annotated[
|
|
817
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
818
|
+
] = False,
|
|
819
|
+
require_storage: Annotated[
|
|
820
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
821
|
+
] = False,
|
|
822
|
+
database_namespace: Annotated[
|
|
823
|
+
Optional[str],
|
|
824
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
825
|
+
] = None,
|
|
826
|
+
require_table_read: Annotated[
|
|
827
|
+
list[str],
|
|
828
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
829
|
+
] = [],
|
|
830
|
+
require_table_write: Annotated[
|
|
831
|
+
list[str],
|
|
832
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
833
|
+
] = [],
|
|
834
|
+
require_read_only_storage: Annotated[
|
|
835
|
+
Optional[bool],
|
|
836
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
837
|
+
] = False,
|
|
838
|
+
require_time: Annotated[
|
|
839
|
+
bool,
|
|
840
|
+
typer.Option(
|
|
841
|
+
...,
|
|
842
|
+
help="Enable time/datetime tools",
|
|
843
|
+
),
|
|
844
|
+
] = True,
|
|
845
|
+
require_uuid: Annotated[
|
|
846
|
+
bool,
|
|
847
|
+
typer.Option(
|
|
848
|
+
...,
|
|
849
|
+
help="Enable UUID generation tools",
|
|
850
|
+
),
|
|
851
|
+
] = False,
|
|
852
|
+
working_directory: Annotated[
|
|
853
|
+
Optional[str],
|
|
854
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
855
|
+
] = None,
|
|
856
|
+
require_document_authoring: Annotated[
|
|
857
|
+
Optional[bool],
|
|
858
|
+
typer.Option(..., help="Enable document authoring"),
|
|
859
|
+
] = False,
|
|
860
|
+
require_discovery: Annotated[
|
|
861
|
+
Optional[bool],
|
|
862
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
863
|
+
] = False,
|
|
864
|
+
llm_participant: Annotated[
|
|
865
|
+
Optional[str],
|
|
866
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
867
|
+
] = None,
|
|
868
|
+
host: Annotated[
|
|
869
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
870
|
+
] = None,
|
|
871
|
+
port: Annotated[
|
|
872
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
873
|
+
] = None,
|
|
874
|
+
path: Annotated[
|
|
875
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
876
|
+
] = None,
|
|
877
|
+
always_reply: Annotated[
|
|
878
|
+
Optional[bool],
|
|
879
|
+
typer.Option(..., help="Always reply"),
|
|
880
|
+
] = None,
|
|
881
|
+
skill_dir: Annotated[
|
|
882
|
+
list[str],
|
|
883
|
+
typer.Option(..., help="an agent skills directory"),
|
|
884
|
+
] = [],
|
|
885
|
+
shell_image: Annotated[
|
|
886
|
+
Optional[str],
|
|
887
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
888
|
+
] = None,
|
|
889
|
+
delegate_shell_token: Annotated[
|
|
890
|
+
Optional[bool],
|
|
891
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
892
|
+
] = False,
|
|
893
|
+
log_llm_requests: Annotated[
|
|
894
|
+
Optional[bool],
|
|
895
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
896
|
+
] = False,
|
|
897
|
+
):
|
|
898
|
+
if database_namespace is not None:
|
|
899
|
+
database_namespace = database_namespace.split("::")
|
|
900
|
+
|
|
901
|
+
service = get_service(host=host, port=port)
|
|
902
|
+
|
|
903
|
+
if path is None:
|
|
904
|
+
path = "/agent"
|
|
905
|
+
i = 0
|
|
906
|
+
while service.has_path(path):
|
|
907
|
+
i += 1
|
|
908
|
+
path = f"/agent{i}"
|
|
909
|
+
|
|
910
|
+
service.agents.append(
|
|
911
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
912
|
+
)
|
|
913
|
+
|
|
914
|
+
service.add_path(
|
|
915
|
+
identity=agent_name,
|
|
916
|
+
path=path,
|
|
917
|
+
cls=build_chatbot(
|
|
918
|
+
computer_use=computer_use,
|
|
919
|
+
require_computer_use=require_computer_use,
|
|
920
|
+
model=model,
|
|
921
|
+
local_shell=local_shell,
|
|
922
|
+
shell=shell,
|
|
923
|
+
apply_patch=apply_patch,
|
|
924
|
+
rule=rule,
|
|
925
|
+
toolkit=require_toolkit + toolkit,
|
|
926
|
+
schema=require_schema + schema,
|
|
927
|
+
rules_file=rules_file,
|
|
928
|
+
web_search=web_search,
|
|
929
|
+
image_generation=image_generation,
|
|
930
|
+
mcp=mcp,
|
|
931
|
+
storage=storage,
|
|
932
|
+
database_namespace=database_namespace,
|
|
933
|
+
require_web_search=require_web_search,
|
|
934
|
+
require_shell=require_shell,
|
|
935
|
+
require_apply_patch=require_apply_patch,
|
|
936
|
+
require_local_shell=require_local_shell,
|
|
937
|
+
require_image_generation=require_image_generation,
|
|
938
|
+
require_mcp=require_mcp,
|
|
939
|
+
require_storage=require_storage,
|
|
940
|
+
require_table_write=require_table_write,
|
|
941
|
+
require_table_read=require_table_read,
|
|
942
|
+
require_read_only_storage=require_read_only_storage,
|
|
943
|
+
require_time=require_time,
|
|
944
|
+
require_uuid=require_uuid,
|
|
945
|
+
room_rules_path=room_rules,
|
|
946
|
+
working_directory=working_directory,
|
|
947
|
+
require_document_authoring=require_document_authoring,
|
|
948
|
+
require_discovery=require_discovery,
|
|
949
|
+
llm_participant=llm_participant,
|
|
950
|
+
always_reply=always_reply,
|
|
951
|
+
skill_dirs=skill_dir,
|
|
952
|
+
shell_image=shell_image,
|
|
953
|
+
delegate_shell_token=delegate_shell_token,
|
|
954
|
+
log_llm_requests=log_llm_requests,
|
|
955
|
+
),
|
|
956
|
+
)
|
|
957
|
+
|
|
958
|
+
if not get_deferred():
|
|
959
|
+
await run_services()
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
@app.async_command("spec")
|
|
963
|
+
async def spec(
|
|
964
|
+
*,
|
|
965
|
+
service_name: Annotated[str, typer.Option("--service-name", help="service name")],
|
|
966
|
+
service_description: Annotated[
|
|
967
|
+
Optional[str], typer.Option("--service-description", help="service description")
|
|
968
|
+
] = None,
|
|
969
|
+
service_title: Annotated[
|
|
970
|
+
Optional[str],
|
|
971
|
+
typer.Option("--service-title", help="a display name for the service"),
|
|
972
|
+
] = None,
|
|
973
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
974
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
975
|
+
rules_file: Optional[str] = None,
|
|
976
|
+
room_rules: Annotated[
|
|
977
|
+
List[str],
|
|
978
|
+
typer.Option(
|
|
979
|
+
"--room-rules",
|
|
980
|
+
"-rr",
|
|
981
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
982
|
+
),
|
|
983
|
+
] = [],
|
|
984
|
+
require_toolkit: Annotated[
|
|
985
|
+
List[str],
|
|
986
|
+
typer.Option(
|
|
987
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
988
|
+
),
|
|
989
|
+
] = [],
|
|
990
|
+
require_schema: Annotated[
|
|
991
|
+
List[str],
|
|
992
|
+
typer.Option(
|
|
993
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
994
|
+
),
|
|
995
|
+
] = [],
|
|
996
|
+
toolkit: Annotated[
|
|
997
|
+
List[str],
|
|
998
|
+
typer.Option(
|
|
999
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
1000
|
+
),
|
|
1001
|
+
] = [],
|
|
1002
|
+
schema: Annotated[
|
|
1003
|
+
List[str],
|
|
1004
|
+
typer.Option(
|
|
1005
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
1006
|
+
),
|
|
1007
|
+
] = [],
|
|
1008
|
+
model: Annotated[
|
|
1009
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
1010
|
+
] = "gpt-5.2",
|
|
1011
|
+
image_generation: Annotated[
|
|
1012
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1013
|
+
] = None,
|
|
1014
|
+
local_shell: Annotated[
|
|
1015
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
1016
|
+
] = False,
|
|
1017
|
+
shell: Annotated[
|
|
1018
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
1019
|
+
] = False,
|
|
1020
|
+
apply_patch: Annotated[
|
|
1021
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1022
|
+
] = False,
|
|
1023
|
+
computer_use: Annotated[
|
|
1024
|
+
Optional[bool],
|
|
1025
|
+
typer.Option(
|
|
1026
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
1027
|
+
),
|
|
1028
|
+
] = False,
|
|
1029
|
+
web_search: Annotated[
|
|
1030
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
1031
|
+
] = False,
|
|
1032
|
+
mcp: Annotated[
|
|
1033
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1034
|
+
] = False,
|
|
1035
|
+
storage: Annotated[
|
|
1036
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1037
|
+
] = False,
|
|
1038
|
+
require_image_generation: Annotated[
|
|
1039
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1040
|
+
] = None,
|
|
1041
|
+
require_computer_use: Annotated[
|
|
1042
|
+
Optional[bool],
|
|
1043
|
+
typer.Option(
|
|
1044
|
+
...,
|
|
1045
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
1046
|
+
hidden=True,
|
|
1047
|
+
),
|
|
1048
|
+
] = False,
|
|
1049
|
+
require_local_shell: Annotated[
|
|
1050
|
+
Optional[bool],
|
|
1051
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
1052
|
+
] = False,
|
|
1053
|
+
require_shell: Annotated[
|
|
1054
|
+
Optional[bool],
|
|
1055
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
1056
|
+
] = False,
|
|
1057
|
+
require_apply_patch: Annotated[
|
|
1058
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1059
|
+
] = False,
|
|
1060
|
+
require_web_search: Annotated[
|
|
1061
|
+
Optional[bool],
|
|
1062
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
1063
|
+
] = False,
|
|
1064
|
+
require_mcp: Annotated[
|
|
1065
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1066
|
+
] = False,
|
|
1067
|
+
require_storage: Annotated[
|
|
1068
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1069
|
+
] = False,
|
|
1070
|
+
database_namespace: Annotated[
|
|
1071
|
+
Optional[str],
|
|
1072
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
1073
|
+
] = None,
|
|
1074
|
+
require_table_read: Annotated[
|
|
1075
|
+
list[str],
|
|
1076
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
1077
|
+
] = [],
|
|
1078
|
+
require_table_write: Annotated[
|
|
1079
|
+
list[str],
|
|
1080
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
1081
|
+
] = [],
|
|
1082
|
+
require_read_only_storage: Annotated[
|
|
1083
|
+
Optional[bool],
|
|
1084
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
1085
|
+
] = False,
|
|
1086
|
+
require_time: Annotated[
|
|
1087
|
+
bool,
|
|
1088
|
+
typer.Option(
|
|
1089
|
+
...,
|
|
1090
|
+
help="Enable time/datetime tools",
|
|
1091
|
+
),
|
|
1092
|
+
] = True,
|
|
1093
|
+
require_uuid: Annotated[
|
|
1094
|
+
bool,
|
|
1095
|
+
typer.Option(
|
|
1096
|
+
...,
|
|
1097
|
+
help="Enable UUID generation tools",
|
|
1098
|
+
),
|
|
1099
|
+
] = False,
|
|
1100
|
+
working_directory: Annotated[
|
|
1101
|
+
Optional[str],
|
|
1102
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
1103
|
+
] = None,
|
|
1104
|
+
require_document_authoring: Annotated[
|
|
1105
|
+
Optional[bool],
|
|
1106
|
+
typer.Option(..., help="Enable document authoring"),
|
|
1107
|
+
] = False,
|
|
1108
|
+
require_discovery: Annotated[
|
|
1109
|
+
Optional[bool],
|
|
1110
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
1111
|
+
] = False,
|
|
1112
|
+
llm_participant: Annotated[
|
|
1113
|
+
Optional[str],
|
|
1114
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
1115
|
+
] = None,
|
|
1116
|
+
host: Annotated[
|
|
1117
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
1118
|
+
] = None,
|
|
1119
|
+
port: Annotated[
|
|
1120
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
1121
|
+
] = None,
|
|
1122
|
+
path: Annotated[
|
|
1123
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
1124
|
+
] = None,
|
|
1125
|
+
always_reply: Annotated[
|
|
1126
|
+
Optional[bool],
|
|
1127
|
+
typer.Option(..., help="Always reply"),
|
|
1128
|
+
] = None,
|
|
1129
|
+
skill_dir: Annotated[
|
|
1130
|
+
list[str],
|
|
1131
|
+
typer.Option(..., help="an agent skills directory"),
|
|
1132
|
+
] = [],
|
|
1133
|
+
shell_image: Annotated[
|
|
1134
|
+
Optional[str],
|
|
1135
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
1136
|
+
] = None,
|
|
1137
|
+
delegate_shell_token: Annotated[
|
|
1138
|
+
Optional[bool],
|
|
1139
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1140
|
+
] = False,
|
|
1141
|
+
log_llm_requests: Annotated[
|
|
1142
|
+
Optional[bool],
|
|
1143
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1144
|
+
] = False,
|
|
1145
|
+
):
|
|
1146
|
+
if database_namespace is not None:
|
|
1147
|
+
database_namespace = database_namespace.split("::")
|
|
1148
|
+
|
|
1149
|
+
service = get_service(host=host, port=port)
|
|
1150
|
+
|
|
1151
|
+
if path is None:
|
|
1152
|
+
path = "/agent"
|
|
1153
|
+
i = 0
|
|
1154
|
+
while service.has_path(path):
|
|
1155
|
+
i += 1
|
|
1156
|
+
path = f"/agent{i}"
|
|
1157
|
+
|
|
1158
|
+
service.agents.append(
|
|
1159
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
1160
|
+
)
|
|
1161
|
+
|
|
1162
|
+
service.add_path(
|
|
1163
|
+
identity=agent_name,
|
|
1164
|
+
path=path,
|
|
1165
|
+
cls=build_chatbot(
|
|
1166
|
+
computer_use=computer_use,
|
|
1167
|
+
require_computer_use=require_computer_use,
|
|
1168
|
+
model=model,
|
|
1169
|
+
local_shell=local_shell,
|
|
1170
|
+
shell=shell,
|
|
1171
|
+
apply_patch=apply_patch,
|
|
1172
|
+
rule=rule,
|
|
1173
|
+
toolkit=require_toolkit + toolkit,
|
|
1174
|
+
schema=require_schema + schema,
|
|
1175
|
+
rules_file=rules_file,
|
|
1176
|
+
web_search=web_search,
|
|
1177
|
+
image_generation=image_generation,
|
|
1178
|
+
mcp=mcp,
|
|
1179
|
+
storage=storage,
|
|
1180
|
+
database_namespace=database_namespace,
|
|
1181
|
+
require_web_search=require_web_search,
|
|
1182
|
+
require_shell=require_shell,
|
|
1183
|
+
require_apply_patch=require_apply_patch,
|
|
1184
|
+
require_local_shell=require_local_shell,
|
|
1185
|
+
require_image_generation=require_image_generation,
|
|
1186
|
+
require_mcp=require_mcp,
|
|
1187
|
+
require_storage=require_storage,
|
|
1188
|
+
require_table_write=require_table_write,
|
|
1189
|
+
require_table_read=require_table_read,
|
|
1190
|
+
require_read_only_storage=require_read_only_storage,
|
|
1191
|
+
require_time=require_time,
|
|
1192
|
+
require_uuid=require_uuid,
|
|
1193
|
+
room_rules_path=room_rules,
|
|
1194
|
+
working_directory=working_directory,
|
|
1195
|
+
require_document_authoring=require_document_authoring,
|
|
1196
|
+
require_discovery=require_discovery,
|
|
1197
|
+
llm_participant=llm_participant,
|
|
1198
|
+
always_reply=always_reply,
|
|
1199
|
+
skill_dirs=skill_dir,
|
|
1200
|
+
shell_image=shell_image,
|
|
1201
|
+
delegate_shell_token=delegate_shell_token,
|
|
1202
|
+
log_llm_requests=log_llm_requests,
|
|
1203
|
+
),
|
|
1204
|
+
)
|
|
1205
|
+
|
|
1206
|
+
spec = service_specs()[0]
|
|
1207
|
+
spec.metadata.annotations = {
|
|
1208
|
+
"meshagent.service.id": service_name,
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
spec.metadata.name = service_name
|
|
1212
|
+
spec.metadata.description = service_description
|
|
1213
|
+
spec.container.image = (
|
|
1214
|
+
"us-central1-docker.pkg.dev/meshagent-public/images/cli:{SERVER_VERSION}-esgz"
|
|
1215
|
+
)
|
|
1216
|
+
spec.container.command = shlex.join(
|
|
1217
|
+
["meshagent", "chatbot", "service", *cleanup_args(sys.argv[2:])]
|
|
1218
|
+
)
|
|
1219
|
+
|
|
1220
|
+
print(yaml.dump(spec.model_dump(mode="json", exclude_none=True), sort_keys=False))
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
@app.async_command("deploy")
|
|
1224
|
+
async def deploy(
|
|
1225
|
+
*,
|
|
1226
|
+
service_name: Annotated[str, typer.Option("--service-name", help="service name")],
|
|
1227
|
+
service_description: Annotated[
|
|
1228
|
+
Optional[str], typer.Option("--service-description", help="service description")
|
|
1229
|
+
] = None,
|
|
1230
|
+
service_title: Annotated[
|
|
1231
|
+
Optional[str],
|
|
1232
|
+
typer.Option("--service-title", help="a display name for the service"),
|
|
1233
|
+
] = None,
|
|
1234
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
1235
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
1236
|
+
rules_file: Optional[str] = None,
|
|
1237
|
+
room_rules: Annotated[
|
|
1238
|
+
List[str],
|
|
1239
|
+
typer.Option(
|
|
1240
|
+
"--room-rules",
|
|
1241
|
+
"-rr",
|
|
1242
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
1243
|
+
),
|
|
1244
|
+
] = [],
|
|
1245
|
+
require_toolkit: Annotated[
|
|
1246
|
+
List[str],
|
|
1247
|
+
typer.Option(
|
|
1248
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
1249
|
+
),
|
|
1250
|
+
] = [],
|
|
1251
|
+
require_schema: Annotated[
|
|
1252
|
+
List[str],
|
|
1253
|
+
typer.Option(
|
|
1254
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
1255
|
+
),
|
|
1256
|
+
] = [],
|
|
1257
|
+
toolkit: Annotated[
|
|
1258
|
+
List[str],
|
|
1259
|
+
typer.Option(
|
|
1260
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
1261
|
+
),
|
|
1262
|
+
] = [],
|
|
1263
|
+
schema: Annotated[
|
|
1264
|
+
List[str],
|
|
1265
|
+
typer.Option(
|
|
1266
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
1267
|
+
),
|
|
1268
|
+
] = [],
|
|
1269
|
+
model: Annotated[
|
|
1270
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
1271
|
+
] = "gpt-5.2",
|
|
1272
|
+
image_generation: Annotated[
|
|
1273
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1274
|
+
] = None,
|
|
1275
|
+
local_shell: Annotated[
|
|
1276
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
1277
|
+
] = False,
|
|
1278
|
+
shell: Annotated[
|
|
1279
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
1280
|
+
] = False,
|
|
1281
|
+
apply_patch: Annotated[
|
|
1282
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1283
|
+
] = False,
|
|
1284
|
+
computer_use: Annotated[
|
|
1285
|
+
Optional[bool],
|
|
1286
|
+
typer.Option(
|
|
1287
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
1288
|
+
),
|
|
1289
|
+
] = False,
|
|
1290
|
+
web_search: Annotated[
|
|
1291
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
1292
|
+
] = False,
|
|
1293
|
+
mcp: Annotated[
|
|
1294
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1295
|
+
] = False,
|
|
1296
|
+
storage: Annotated[
|
|
1297
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1298
|
+
] = False,
|
|
1299
|
+
require_image_generation: Annotated[
|
|
1300
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1301
|
+
] = None,
|
|
1302
|
+
require_computer_use: Annotated[
|
|
1303
|
+
Optional[bool],
|
|
1304
|
+
typer.Option(
|
|
1305
|
+
...,
|
|
1306
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
1307
|
+
hidden=True,
|
|
1308
|
+
),
|
|
1309
|
+
] = False,
|
|
1310
|
+
require_local_shell: Annotated[
|
|
1311
|
+
Optional[bool],
|
|
1312
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
1313
|
+
] = False,
|
|
1314
|
+
require_shell: Annotated[
|
|
1315
|
+
Optional[bool],
|
|
1316
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
1317
|
+
] = False,
|
|
1318
|
+
require_apply_patch: Annotated[
|
|
1319
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1320
|
+
] = False,
|
|
1321
|
+
require_web_search: Annotated[
|
|
1322
|
+
Optional[bool],
|
|
1323
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
1324
|
+
] = False,
|
|
1325
|
+
require_mcp: Annotated[
|
|
1326
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1327
|
+
] = False,
|
|
1328
|
+
require_storage: Annotated[
|
|
1329
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1330
|
+
] = False,
|
|
1331
|
+
database_namespace: Annotated[
|
|
1332
|
+
Optional[str],
|
|
1333
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
1334
|
+
] = None,
|
|
1335
|
+
require_table_read: Annotated[
|
|
1336
|
+
list[str],
|
|
1337
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
1338
|
+
] = [],
|
|
1339
|
+
require_table_write: Annotated[
|
|
1340
|
+
list[str],
|
|
1341
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
1342
|
+
] = [],
|
|
1343
|
+
require_read_only_storage: Annotated[
|
|
1344
|
+
Optional[bool],
|
|
1345
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
1346
|
+
] = False,
|
|
1347
|
+
require_time: Annotated[
|
|
1348
|
+
bool,
|
|
1349
|
+
typer.Option(
|
|
1350
|
+
...,
|
|
1351
|
+
help="Enable time/datetime tools",
|
|
1352
|
+
),
|
|
1353
|
+
] = True,
|
|
1354
|
+
require_uuid: Annotated[
|
|
1355
|
+
bool,
|
|
1356
|
+
typer.Option(
|
|
1357
|
+
...,
|
|
1358
|
+
help="Enable UUID generation tools",
|
|
1359
|
+
),
|
|
1360
|
+
] = False,
|
|
1361
|
+
working_directory: Annotated[
|
|
1362
|
+
Optional[str],
|
|
1363
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
1364
|
+
] = None,
|
|
1365
|
+
require_document_authoring: Annotated[
|
|
1366
|
+
Optional[bool],
|
|
1367
|
+
typer.Option(..., help="Enable document authoring"),
|
|
1368
|
+
] = False,
|
|
1369
|
+
require_discovery: Annotated[
|
|
1370
|
+
Optional[bool],
|
|
1371
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
1372
|
+
] = False,
|
|
1373
|
+
llm_participant: Annotated[
|
|
1374
|
+
Optional[str],
|
|
1375
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
1376
|
+
] = None,
|
|
1377
|
+
host: Annotated[
|
|
1378
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
1379
|
+
] = None,
|
|
1380
|
+
port: Annotated[
|
|
1381
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
1382
|
+
] = None,
|
|
1383
|
+
path: Annotated[
|
|
1384
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
1385
|
+
] = None,
|
|
1386
|
+
always_reply: Annotated[
|
|
1387
|
+
Optional[bool],
|
|
1388
|
+
typer.Option(..., help="Always reply"),
|
|
1389
|
+
] = None,
|
|
1390
|
+
skill_dir: Annotated[
|
|
1391
|
+
list[str],
|
|
1392
|
+
typer.Option(..., help="an agent skills directory"),
|
|
1393
|
+
] = [],
|
|
1394
|
+
shell_image: Annotated[
|
|
1395
|
+
Optional[str],
|
|
1396
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
1397
|
+
] = None,
|
|
1398
|
+
delegate_shell_token: Annotated[
|
|
1399
|
+
Optional[bool],
|
|
1400
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1401
|
+
] = False,
|
|
1402
|
+
log_llm_requests: Annotated[
|
|
1403
|
+
Optional[bool],
|
|
1404
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1405
|
+
] = False,
|
|
1406
|
+
project_id: ProjectIdOption,
|
|
1407
|
+
room: Annotated[
|
|
1408
|
+
Optional[str],
|
|
1409
|
+
typer.Option("--room", help="The name of a room to create the service for"),
|
|
1410
|
+
] = None,
|
|
1411
|
+
):
|
|
1412
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
1413
|
+
|
|
1414
|
+
if database_namespace is not None:
|
|
1415
|
+
database_namespace = database_namespace.split("::")
|
|
1416
|
+
|
|
1417
|
+
service = get_service(host=host, port=port)
|
|
1418
|
+
|
|
1419
|
+
if path is None:
|
|
1420
|
+
path = "/agent"
|
|
1421
|
+
i = 0
|
|
1422
|
+
while service.has_path(path):
|
|
1423
|
+
i += 1
|
|
1424
|
+
path = f"/agent{i}"
|
|
1425
|
+
|
|
1426
|
+
service.agents.append(
|
|
1427
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
service.add_path(
|
|
1431
|
+
identity=agent_name,
|
|
1432
|
+
path=path,
|
|
1433
|
+
cls=build_chatbot(
|
|
1434
|
+
computer_use=computer_use,
|
|
1435
|
+
require_computer_use=require_computer_use,
|
|
1436
|
+
model=model,
|
|
1437
|
+
local_shell=local_shell,
|
|
1438
|
+
shell=shell,
|
|
1439
|
+
apply_patch=apply_patch,
|
|
1440
|
+
rule=rule,
|
|
1441
|
+
toolkit=require_toolkit + toolkit,
|
|
1442
|
+
schema=require_schema + schema,
|
|
1443
|
+
rules_file=rules_file,
|
|
1444
|
+
web_search=web_search,
|
|
1445
|
+
image_generation=image_generation,
|
|
1446
|
+
mcp=mcp,
|
|
1447
|
+
storage=storage,
|
|
1448
|
+
database_namespace=database_namespace,
|
|
1449
|
+
require_web_search=require_web_search,
|
|
1450
|
+
require_shell=require_shell,
|
|
1451
|
+
require_apply_patch=require_apply_patch,
|
|
1452
|
+
require_local_shell=require_local_shell,
|
|
1453
|
+
require_image_generation=require_image_generation,
|
|
1454
|
+
require_mcp=require_mcp,
|
|
1455
|
+
require_storage=require_storage,
|
|
1456
|
+
require_table_write=require_table_write,
|
|
1457
|
+
require_table_read=require_table_read,
|
|
1458
|
+
require_read_only_storage=require_read_only_storage,
|
|
1459
|
+
require_time=require_time,
|
|
1460
|
+
require_uuid=require_uuid,
|
|
1461
|
+
room_rules_path=room_rules,
|
|
1462
|
+
working_directory=working_directory,
|
|
1463
|
+
require_document_authoring=require_document_authoring,
|
|
1464
|
+
require_discovery=require_discovery,
|
|
1465
|
+
llm_participant=llm_participant,
|
|
1466
|
+
always_reply=always_reply,
|
|
1467
|
+
skill_dirs=skill_dir,
|
|
1468
|
+
shell_image=shell_image,
|
|
1469
|
+
delegate_shell_token=delegate_shell_token,
|
|
1470
|
+
log_llm_requests=log_llm_requests,
|
|
1471
|
+
),
|
|
1472
|
+
)
|
|
1473
|
+
|
|
1474
|
+
spec = service_specs()[0]
|
|
1475
|
+
|
|
1476
|
+
for port in spec.ports:
|
|
1477
|
+
port
|
|
1478
|
+
|
|
1479
|
+
spec.metadata.annotations = {
|
|
1480
|
+
"meshagent.service.id": service_name,
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
spec.metadata.name = service_name
|
|
1484
|
+
spec.metadata.description = service_description
|
|
1485
|
+
spec.container.image = (
|
|
1486
|
+
"us-central1-docker.pkg.dev/meshagent-public/images/cli:{SERVER_VERSION}-esgz"
|
|
1487
|
+
)
|
|
1488
|
+
spec.container.command = shlex.join(
|
|
1489
|
+
["meshagent", "chatbot", "service", *cleanup_args(sys.argv[2:])]
|
|
1490
|
+
)
|
|
1491
|
+
|
|
1492
|
+
project_id = await resolve_project_id(project_id)
|
|
1493
|
+
|
|
1494
|
+
client = await get_client()
|
|
1495
|
+
try:
|
|
1496
|
+
id = None
|
|
1497
|
+
try:
|
|
1498
|
+
if id is None:
|
|
1499
|
+
if room is None:
|
|
1500
|
+
services = await client.list_services(project_id=project_id)
|
|
1501
|
+
else:
|
|
1502
|
+
services = await client.list_room_services(
|
|
1503
|
+
project_id=project_id, room_name=room
|
|
1504
|
+
)
|
|
1505
|
+
|
|
1506
|
+
for s in services:
|
|
1507
|
+
if s.metadata.name == spec.metadata.name:
|
|
1508
|
+
id = s.id
|
|
1509
|
+
|
|
1510
|
+
if id is None:
|
|
1511
|
+
if room is None:
|
|
1512
|
+
id = await client.create_service(
|
|
1513
|
+
project_id=project_id, service=spec
|
|
1514
|
+
)
|
|
1515
|
+
else:
|
|
1516
|
+
id = await client.create_room_service(
|
|
1517
|
+
project_id=project_id, service=spec, room_name=room
|
|
1518
|
+
)
|
|
1519
|
+
|
|
1520
|
+
else:
|
|
1521
|
+
spec.id = id
|
|
1522
|
+
if room is None:
|
|
1523
|
+
await client.update_service(
|
|
1524
|
+
project_id=project_id, service_id=id, service=spec
|
|
1525
|
+
)
|
|
1526
|
+
else:
|
|
1527
|
+
await client.update_room_service(
|
|
1528
|
+
project_id=project_id,
|
|
1529
|
+
service_id=id,
|
|
1530
|
+
service=spec,
|
|
1531
|
+
room_name=room,
|
|
1532
|
+
)
|
|
1533
|
+
|
|
1534
|
+
except ConflictError:
|
|
1535
|
+
print(f"[red]Service name already in use: {spec.metadata.name}[/red]")
|
|
1536
|
+
raise typer.Exit(code=1)
|
|
1537
|
+
else:
|
|
1538
|
+
print(f"[green]Deployed service:[/] {id}")
|
|
1539
|
+
|
|
1540
|
+
finally:
|
|
1541
|
+
await client.close()
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
async def chat_with(
|
|
1545
|
+
*,
|
|
1546
|
+
participant_name: str,
|
|
1547
|
+
project_id: str,
|
|
1548
|
+
room: str,
|
|
1549
|
+
thread_path: str,
|
|
1550
|
+
message: Optional[str] = None,
|
|
1551
|
+
use_web_search: bool = False,
|
|
1552
|
+
use_image_gen: bool = False,
|
|
1553
|
+
use_storage: bool = False,
|
|
1554
|
+
):
|
|
1555
|
+
from prompt_toolkit.shortcuts import PromptSession
|
|
1556
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
1557
|
+
from meshagent.agents.chat import ChatBotClient
|
|
1558
|
+
|
|
1559
|
+
kb = KeyBindings()
|
|
1560
|
+
|
|
1561
|
+
session = PromptSession("> ", key_bindings=kb)
|
|
1562
|
+
|
|
1563
|
+
account_client = await get_client()
|
|
1564
|
+
try:
|
|
1565
|
+
connection = await account_client.connect_room(project_id=project_id, room=room)
|
|
1566
|
+
async with RoomClient(
|
|
1567
|
+
protocol=WebSocketClientProtocol(
|
|
1568
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
1569
|
+
token=connection.jwt,
|
|
1570
|
+
),
|
|
1571
|
+
) as user_client:
|
|
1572
|
+
await user_client.messaging.enable()
|
|
1573
|
+
|
|
1574
|
+
if thread_path is None:
|
|
1575
|
+
thread_path = f".threads/{participant_name}/{user_client.local_participant.get_attribute('name')}.thread"
|
|
1576
|
+
|
|
1577
|
+
async with ChatBotClient(
|
|
1578
|
+
room=user_client,
|
|
1579
|
+
participant_name=participant_name,
|
|
1580
|
+
thread_path=thread_path,
|
|
1581
|
+
) as chat_client:
|
|
1582
|
+
|
|
1583
|
+
@kb.add("c-l")
|
|
1584
|
+
def _(event):
|
|
1585
|
+
event.app.renderer.clear()
|
|
1586
|
+
asyncio.ensure_future(chat_client.clear())
|
|
1587
|
+
|
|
1588
|
+
while True:
|
|
1589
|
+
user_input = message or await session.prompt_async()
|
|
1590
|
+
|
|
1591
|
+
if user_input == "/clear":
|
|
1592
|
+
await chat_client.clear()
|
|
1593
|
+
|
|
1594
|
+
else:
|
|
1595
|
+
tools: list[ToolkitConfig] = []
|
|
1596
|
+
|
|
1597
|
+
if use_web_search:
|
|
1598
|
+
tools.append(WebSearchConfig())
|
|
1599
|
+
|
|
1600
|
+
elif use_image_gen:
|
|
1601
|
+
tools.append(ImageGenerationConfig())
|
|
1602
|
+
|
|
1603
|
+
elif use_storage:
|
|
1604
|
+
tools.append(StorageToolkitConfig())
|
|
1605
|
+
|
|
1606
|
+
await chat_client.send(text=user_input, tools=tools)
|
|
1607
|
+
|
|
1608
|
+
response = await chat_client.receive()
|
|
1609
|
+
|
|
1610
|
+
print(response)
|
|
1611
|
+
|
|
1612
|
+
if message:
|
|
1613
|
+
break
|
|
1614
|
+
|
|
1615
|
+
except asyncio.CancelledError:
|
|
1616
|
+
pass
|
|
1617
|
+
|
|
1618
|
+
finally:
|
|
1619
|
+
await account_client.close()
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
@app.async_command("run")
|
|
1623
|
+
async def run(
|
|
1624
|
+
*,
|
|
1625
|
+
project_id: ProjectIdOption,
|
|
1626
|
+
room: RoomOption,
|
|
1627
|
+
role: str = "agent",
|
|
1628
|
+
agent_name: Annotated[
|
|
1629
|
+
Optional[str], typer.Option(..., help="Name of the agent to call")
|
|
1630
|
+
] = None,
|
|
1631
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
1632
|
+
room_rules: Annotated[
|
|
1633
|
+
List[str],
|
|
1634
|
+
typer.Option(
|
|
1635
|
+
"--room-rules",
|
|
1636
|
+
"-rr",
|
|
1637
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
1638
|
+
),
|
|
1639
|
+
] = [],
|
|
1640
|
+
rules_file: Optional[str] = None,
|
|
1641
|
+
require_toolkit: Annotated[
|
|
1642
|
+
List[str],
|
|
1643
|
+
typer.Option(
|
|
1644
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
1645
|
+
),
|
|
1646
|
+
] = [],
|
|
1647
|
+
require_schema: Annotated[
|
|
1648
|
+
List[str],
|
|
1649
|
+
typer.Option(
|
|
1650
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
1651
|
+
),
|
|
1652
|
+
] = [],
|
|
1653
|
+
toolkit: Annotated[
|
|
1654
|
+
List[str],
|
|
1655
|
+
typer.Option(
|
|
1656
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
1657
|
+
),
|
|
1658
|
+
] = [],
|
|
1659
|
+
schema: Annotated[
|
|
1660
|
+
List[str],
|
|
1661
|
+
typer.Option(
|
|
1662
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
1663
|
+
),
|
|
1664
|
+
] = [],
|
|
1665
|
+
model: Annotated[
|
|
1666
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
1667
|
+
] = "gpt-5.2",
|
|
1668
|
+
image_generation: Annotated[
|
|
1669
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1670
|
+
] = None,
|
|
1671
|
+
computer_use: Annotated[
|
|
1672
|
+
Optional[bool],
|
|
1673
|
+
typer.Option(
|
|
1674
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
1675
|
+
),
|
|
1676
|
+
] = False,
|
|
1677
|
+
local_shell: Annotated[
|
|
1678
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
1679
|
+
] = False,
|
|
1680
|
+
shell: Annotated[
|
|
1681
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
1682
|
+
] = False,
|
|
1683
|
+
apply_patch: Annotated[
|
|
1684
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1685
|
+
] = False,
|
|
1686
|
+
web_search: Annotated[
|
|
1687
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
1688
|
+
] = False,
|
|
1689
|
+
mcp: Annotated[
|
|
1690
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1691
|
+
] = False,
|
|
1692
|
+
storage: Annotated[
|
|
1693
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1694
|
+
] = False,
|
|
1695
|
+
require_image_generation: Annotated[
|
|
1696
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1697
|
+
] = None,
|
|
1698
|
+
require_computer_use: Annotated[
|
|
1699
|
+
Optional[bool],
|
|
1700
|
+
typer.Option(
|
|
1701
|
+
...,
|
|
1702
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
1703
|
+
hidden=True,
|
|
1704
|
+
),
|
|
1705
|
+
] = False,
|
|
1706
|
+
require_local_shell: Annotated[
|
|
1707
|
+
Optional[bool],
|
|
1708
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
1709
|
+
] = False,
|
|
1710
|
+
require_shell: Annotated[
|
|
1711
|
+
Optional[bool],
|
|
1712
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
1713
|
+
] = False,
|
|
1714
|
+
require_apply_patch: Annotated[
|
|
1715
|
+
Optional[bool],
|
|
1716
|
+
typer.Option(..., help="Enable apply patch tool calling"),
|
|
1717
|
+
] = False,
|
|
1718
|
+
require_web_search: Annotated[
|
|
1719
|
+
Optional[bool],
|
|
1720
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
1721
|
+
] = False,
|
|
1722
|
+
require_mcp: Annotated[
|
|
1723
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1724
|
+
] = False,
|
|
1725
|
+
require_storage: Annotated[
|
|
1726
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1727
|
+
] = False,
|
|
1728
|
+
database_namespace: Annotated[
|
|
1729
|
+
Optional[str],
|
|
1730
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
1731
|
+
] = None,
|
|
1732
|
+
require_table_read: Annotated[
|
|
1733
|
+
list[str],
|
|
1734
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
1735
|
+
] = [],
|
|
1736
|
+
require_table_write: Annotated[
|
|
1737
|
+
list[str],
|
|
1738
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
1739
|
+
] = [],
|
|
1740
|
+
require_read_only_storage: Annotated[
|
|
1741
|
+
Optional[bool],
|
|
1742
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
1743
|
+
] = False,
|
|
1744
|
+
require_time: Annotated[
|
|
1745
|
+
bool,
|
|
1746
|
+
typer.Option(
|
|
1747
|
+
...,
|
|
1748
|
+
help="Enable time/datetime tools",
|
|
1749
|
+
),
|
|
1750
|
+
] = True,
|
|
1751
|
+
require_uuid: Annotated[
|
|
1752
|
+
bool,
|
|
1753
|
+
typer.Option(
|
|
1754
|
+
...,
|
|
1755
|
+
help="Enable UUID generation tools",
|
|
1756
|
+
),
|
|
1757
|
+
] = False,
|
|
1758
|
+
require_document_authoring: Annotated[
|
|
1759
|
+
Optional[bool],
|
|
1760
|
+
typer.Option(..., help="Enable MeshDocument authoring"),
|
|
1761
|
+
] = False,
|
|
1762
|
+
require_discovery: Annotated[
|
|
1763
|
+
Optional[bool],
|
|
1764
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
1765
|
+
] = False,
|
|
1766
|
+
working_directory: Annotated[
|
|
1767
|
+
Optional[str],
|
|
1768
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
1769
|
+
] = None,
|
|
1770
|
+
key: Annotated[
|
|
1771
|
+
str,
|
|
1772
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
1773
|
+
] = None,
|
|
1774
|
+
llm_participant: Annotated[
|
|
1775
|
+
Optional[str],
|
|
1776
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
1777
|
+
] = None,
|
|
1778
|
+
always_reply: Annotated[
|
|
1779
|
+
Optional[bool],
|
|
1780
|
+
typer.Option(..., help="Always reply"),
|
|
1781
|
+
] = None,
|
|
1782
|
+
skill_dir: Annotated[
|
|
1783
|
+
list[str],
|
|
1784
|
+
typer.Option(..., help="an agent skills directory"),
|
|
1785
|
+
] = [],
|
|
1786
|
+
shell_image: Annotated[
|
|
1787
|
+
Optional[str],
|
|
1788
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
1789
|
+
] = None,
|
|
1790
|
+
delegate_shell_token: Annotated[
|
|
1791
|
+
Optional[bool],
|
|
1792
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1793
|
+
] = False,
|
|
1794
|
+
log_llm_requests: Annotated[
|
|
1795
|
+
Optional[bool],
|
|
1796
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1797
|
+
] = False,
|
|
1798
|
+
thread_path: Annotated[
|
|
1799
|
+
Optional[str],
|
|
1800
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1801
|
+
] = None,
|
|
1802
|
+
message: Annotated[
|
|
1803
|
+
Optional[str],
|
|
1804
|
+
typer.Option(..., help="the input message to use"),
|
|
1805
|
+
] = None,
|
|
1806
|
+
use_web_search: Annotated[
|
|
1807
|
+
Optional[bool],
|
|
1808
|
+
typer.Option(..., help="request the web search tool"),
|
|
1809
|
+
] = None,
|
|
1810
|
+
use_image_gen: Annotated[
|
|
1811
|
+
Optional[bool],
|
|
1812
|
+
typer.Option(..., help="request the image gen tool"),
|
|
1813
|
+
] = None,
|
|
1814
|
+
use_storage: Annotated[
|
|
1815
|
+
Optional[bool],
|
|
1816
|
+
typer.Option(..., help="request the storage tool"),
|
|
1817
|
+
] = None,
|
|
1818
|
+
):
|
|
1819
|
+
root = logging.getLogger()
|
|
1820
|
+
root.setLevel(logging.ERROR)
|
|
1821
|
+
|
|
1822
|
+
if database_namespace is not None:
|
|
1823
|
+
database_namespace = database_namespace.split("::")
|
|
1824
|
+
|
|
1825
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
1826
|
+
account_client = await get_client()
|
|
1827
|
+
try:
|
|
1828
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
1829
|
+
room = resolve_room(room)
|
|
1830
|
+
|
|
1831
|
+
jwt = os.getenv("MESHAGENT_TOKEN")
|
|
1832
|
+
if jwt is None:
|
|
1833
|
+
if agent_name is None:
|
|
1834
|
+
print(
|
|
1835
|
+
"[bold red]--agent-name must be specified when the MESHAGENT_TOKEN environment variable is not set[/bold red]"
|
|
1836
|
+
)
|
|
1837
|
+
raise typer.Exit(1)
|
|
1838
|
+
|
|
1839
|
+
token = ParticipantToken(
|
|
1840
|
+
name=agent_name,
|
|
1841
|
+
)
|
|
1842
|
+
|
|
1843
|
+
token.add_api_grant(ApiScope.agent_default(tunnels=require_computer_use))
|
|
1844
|
+
|
|
1845
|
+
token.add_role_grant(role=role)
|
|
1846
|
+
token.add_room_grant(room)
|
|
1847
|
+
|
|
1848
|
+
jwt = token.to_jwt(api_key=key)
|
|
1849
|
+
|
|
1850
|
+
async with RoomClient(
|
|
1851
|
+
protocol=WebSocketClientProtocol(
|
|
1852
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
1853
|
+
token=jwt,
|
|
1854
|
+
)
|
|
1855
|
+
) as client:
|
|
1856
|
+
CustomChatbot = build_chatbot(
|
|
1857
|
+
computer_use=computer_use,
|
|
1858
|
+
require_computer_use=require_computer_use,
|
|
1859
|
+
model=model,
|
|
1860
|
+
rule=rule,
|
|
1861
|
+
toolkit=require_toolkit + toolkit,
|
|
1862
|
+
schema=require_schema + schema,
|
|
1863
|
+
rules_file=rules_file,
|
|
1864
|
+
local_shell=local_shell,
|
|
1865
|
+
shell=shell,
|
|
1866
|
+
apply_patch=apply_patch,
|
|
1867
|
+
image_generation=image_generation,
|
|
1868
|
+
web_search=web_search,
|
|
1869
|
+
mcp=mcp,
|
|
1870
|
+
storage=storage,
|
|
1871
|
+
require_apply_patch=require_apply_patch,
|
|
1872
|
+
require_web_search=require_web_search,
|
|
1873
|
+
require_local_shell=require_local_shell,
|
|
1874
|
+
require_shell=require_shell,
|
|
1875
|
+
require_image_generation=require_image_generation,
|
|
1876
|
+
require_mcp=require_mcp,
|
|
1877
|
+
require_storage=require_storage,
|
|
1878
|
+
require_table_read=require_table_read,
|
|
1879
|
+
require_table_write=require_table_write,
|
|
1880
|
+
require_read_only_storage=require_read_only_storage,
|
|
1881
|
+
require_time=require_time,
|
|
1882
|
+
require_uuid=require_uuid,
|
|
1883
|
+
room_rules_path=room_rules,
|
|
1884
|
+
require_document_authoring=require_document_authoring,
|
|
1885
|
+
require_discovery=require_discovery,
|
|
1886
|
+
working_directory=working_directory,
|
|
1887
|
+
llm_participant=llm_participant,
|
|
1888
|
+
always_reply=always_reply,
|
|
1889
|
+
database_namespace=database_namespace,
|
|
1890
|
+
skill_dirs=skill_dir,
|
|
1891
|
+
shell_image=shell_image,
|
|
1892
|
+
delegate_shell_token=delegate_shell_token,
|
|
1893
|
+
log_llm_requests=log_llm_requests,
|
|
1894
|
+
)
|
|
1895
|
+
|
|
1896
|
+
bot = CustomChatbot()
|
|
1897
|
+
|
|
1898
|
+
await bot.start(room=client)
|
|
1899
|
+
|
|
1900
|
+
_, pending = await asyncio.wait(
|
|
1901
|
+
[
|
|
1902
|
+
asyncio.create_task(client.protocol.wait_for_close()),
|
|
1903
|
+
asyncio.create_task(
|
|
1904
|
+
chat_with(
|
|
1905
|
+
participant_name=client.local_participant.get_attribute(
|
|
1906
|
+
"name"
|
|
1907
|
+
),
|
|
1908
|
+
room=room,
|
|
1909
|
+
project_id=project_id,
|
|
1910
|
+
thread_path=thread_path,
|
|
1911
|
+
message=message,
|
|
1912
|
+
use_web_search=use_web_search,
|
|
1913
|
+
use_image_gen=use_image_gen,
|
|
1914
|
+
use_storage=use_storage,
|
|
1915
|
+
)
|
|
1916
|
+
),
|
|
1917
|
+
],
|
|
1918
|
+
return_when="FIRST_COMPLETED",
|
|
1919
|
+
)
|
|
1920
|
+
|
|
1921
|
+
for t in pending:
|
|
1922
|
+
t.cancel()
|
|
1923
|
+
|
|
1924
|
+
except asyncio.CancelledError:
|
|
1925
|
+
return
|
|
1926
|
+
|
|
1927
|
+
finally:
|
|
1928
|
+
await account_client.close()
|
|
1929
|
+
|
|
1930
|
+
|
|
1931
|
+
@app.async_command("use")
|
|
1932
|
+
async def use(
|
|
1933
|
+
*,
|
|
1934
|
+
project_id: ProjectIdOption,
|
|
1935
|
+
room: RoomOption,
|
|
1936
|
+
agent_name: Annotated[
|
|
1937
|
+
Optional[str], typer.Option(..., help="Name of the agent to call")
|
|
1938
|
+
] = None,
|
|
1939
|
+
thread_path: Annotated[
|
|
1940
|
+
Optional[str],
|
|
1941
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1942
|
+
] = None,
|
|
1943
|
+
message: Annotated[
|
|
1944
|
+
Optional[str],
|
|
1945
|
+
typer.Option(..., help="the input message to use"),
|
|
1946
|
+
] = None,
|
|
1947
|
+
use_web_search: Annotated[
|
|
1948
|
+
Optional[bool],
|
|
1949
|
+
typer.Option(..., help="request the web search tool"),
|
|
1950
|
+
] = None,
|
|
1951
|
+
use_image_gen: Annotated[
|
|
1952
|
+
Optional[bool],
|
|
1953
|
+
typer.Option(..., help="request the image gen tool"),
|
|
1954
|
+
] = None,
|
|
1955
|
+
use_storage: Annotated[
|
|
1956
|
+
Optional[bool],
|
|
1957
|
+
typer.Option(..., help="request the storage tool"),
|
|
1958
|
+
] = None,
|
|
1959
|
+
):
|
|
1960
|
+
root = logging.getLogger()
|
|
1961
|
+
root.setLevel(logging.ERROR)
|
|
1962
|
+
|
|
1963
|
+
account_client = await get_client()
|
|
1964
|
+
try:
|
|
1965
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
1966
|
+
room = resolve_room(room)
|
|
1967
|
+
|
|
1968
|
+
await chat_with(
|
|
1969
|
+
participant_name=agent_name,
|
|
1970
|
+
room=room,
|
|
1971
|
+
project_id=project_id,
|
|
1972
|
+
thread_path=thread_path,
|
|
1973
|
+
message=message,
|
|
1974
|
+
use_web_search=use_web_search,
|
|
1975
|
+
use_image_gen=use_image_gen,
|
|
1976
|
+
use_storage=use_storage,
|
|
1977
|
+
)
|
|
1978
|
+
|
|
1979
|
+
except asyncio.CancelledError:
|
|
1980
|
+
return
|
|
1981
|
+
|
|
1982
|
+
finally:
|
|
1983
|
+
await account_client.close()
|