meshagent-cli 0.7.0__py3-none-any.whl → 0.23.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.
- meshagent/cli/agent.py +23 -13
- meshagent/cli/api_keys.py +4 -4
- meshagent/cli/async_typer.py +52 -4
- meshagent/cli/call.py +27 -36
- meshagent/cli/chatbot.py +1559 -177
- meshagent/cli/cli.py +23 -22
- meshagent/cli/cli_mcp.py +92 -28
- meshagent/cli/cli_secrets.py +10 -10
- meshagent/cli/common_options.py +19 -4
- meshagent/cli/containers.py +164 -16
- meshagent/cli/database.py +997 -0
- meshagent/cli/developer.py +3 -3
- meshagent/cli/exec.py +22 -6
- meshagent/cli/helper.py +101 -12
- meshagent/cli/helpers.py +65 -11
- meshagent/cli/host.py +41 -0
- meshagent/cli/mailbot.py +1104 -79
- meshagent/cli/mailboxes.py +223 -0
- meshagent/cli/meeting_transcriber.py +29 -15
- meshagent/cli/messaging.py +7 -10
- meshagent/cli/multi.py +357 -0
- meshagent/cli/oauth2.py +192 -40
- meshagent/cli/participant_token.py +5 -3
- meshagent/cli/port.py +70 -0
- meshagent/cli/queue.py +2 -2
- meshagent/cli/room.py +24 -212
- meshagent/cli/rooms.py +214 -0
- meshagent/cli/services.py +269 -37
- meshagent/cli/sessions.py +5 -5
- meshagent/cli/storage.py +5 -5
- meshagent/cli/sync.py +434 -0
- meshagent/cli/task_runner.py +1317 -0
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +544 -98
- meshagent/cli/webhook.py +7 -7
- meshagent/cli/worker.py +1403 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.23.0.dist-info}/METADATA +15 -13
- meshagent_cli-0.23.0.dist-info/RECORD +45 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.23.0.dist-info}/WHEEL +1 -1
- meshagent_cli-0.7.0.dist-info/RECORD +0 -36
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.23.0.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.23.0.dist-info}/top_level.txt +0 -0
meshagent/cli/chatbot.py
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich import print
|
|
3
|
-
from typing import Annotated, Optional
|
|
4
|
-
from meshagent.tools import Toolkit
|
|
5
|
-
from meshagent.tools.storage import StorageToolkitBuilder
|
|
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
|
+
)
|
|
6
12
|
from meshagent.agents.config import RulesConfig
|
|
13
|
+
from meshagent.agents.widget_schema import widget_schema
|
|
7
14
|
|
|
8
15
|
from meshagent.cli.common_options import (
|
|
9
16
|
ProjectIdOption,
|
|
@@ -15,6 +22,7 @@ from meshagent.api import (
|
|
|
15
22
|
ParticipantToken,
|
|
16
23
|
ApiScope,
|
|
17
24
|
RoomException,
|
|
25
|
+
RemoteParticipant,
|
|
18
26
|
)
|
|
19
27
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
20
28
|
from meshagent.cli import async_typer
|
|
@@ -23,11 +31,12 @@ from meshagent.cli.helper import (
|
|
|
23
31
|
resolve_project_id,
|
|
24
32
|
resolve_room,
|
|
25
33
|
resolve_key,
|
|
34
|
+
cleanup_args,
|
|
26
35
|
)
|
|
27
36
|
|
|
28
37
|
from meshagent.openai import OpenAIResponsesAdapter
|
|
38
|
+
from meshagent.anthropic import AnthropicOpenAIResponsesStreamAdapter
|
|
29
39
|
|
|
30
|
-
from typing import List
|
|
31
40
|
from pathlib import Path
|
|
32
41
|
|
|
33
42
|
from meshagent.openai.tools.responses_adapter import (
|
|
@@ -40,13 +49,36 @@ from meshagent.openai.tools.responses_adapter import (
|
|
|
40
49
|
ApplyPatchConfig,
|
|
41
50
|
ApplyPatchTool,
|
|
42
51
|
ApplyPatchToolkitBuilder,
|
|
52
|
+
ShellToolkitBuilder,
|
|
53
|
+
ShellTool,
|
|
54
|
+
LocalShellToolkitBuilder,
|
|
55
|
+
LocalShellTool,
|
|
56
|
+
ImageGenerationConfig,
|
|
57
|
+
ImageGenerationToolkitBuilder,
|
|
58
|
+
ImageGenerationTool,
|
|
43
59
|
)
|
|
44
60
|
|
|
61
|
+
from meshagent.tools.database import DatabaseToolkitBuilder, DatabaseToolkitConfig
|
|
62
|
+
from meshagent.agents.adapter import MessageStreamLLMAdapter
|
|
63
|
+
|
|
45
64
|
from meshagent.api import RequiredToolkit, RequiredSchema
|
|
46
|
-
from meshagent.api.services import ServiceHost
|
|
47
65
|
import logging
|
|
48
66
|
import os.path
|
|
49
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
|
+
|
|
50
82
|
logger = logging.getLogger("chatbot")
|
|
51
83
|
|
|
52
84
|
app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
@@ -55,7 +87,6 @@ app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
|
55
87
|
def build_chatbot(
|
|
56
88
|
*,
|
|
57
89
|
model: str,
|
|
58
|
-
agent_name: str,
|
|
59
90
|
rule: List[str],
|
|
60
91
|
toolkit: List[str],
|
|
61
92
|
schema: List[str],
|
|
@@ -69,30 +100,34 @@ def build_chatbot(
|
|
|
69
100
|
storage: Optional[str] = None,
|
|
70
101
|
require_image_generation: Optional[str] = None,
|
|
71
102
|
require_local_shell: Optional[str] = None,
|
|
72
|
-
require_shell: Optional[
|
|
103
|
+
require_shell: Optional[bool] = None,
|
|
73
104
|
require_apply_patch: Optional[str] = None,
|
|
74
105
|
require_computer_use: Optional[str] = None,
|
|
75
106
|
require_web_search: Optional[str] = None,
|
|
76
107
|
require_mcp: Optional[str] = None,
|
|
77
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,
|
|
78
114
|
rules_file: Optional[str] = None,
|
|
79
|
-
room_rules_path: Optional[str] = None,
|
|
115
|
+
room_rules_path: Optional[list[str]] = None,
|
|
116
|
+
require_discovery: Optional[str] = None,
|
|
117
|
+
require_document_authoring: Optional[str] = None,
|
|
80
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,
|
|
81
126
|
):
|
|
82
127
|
from meshagent.agents.chat import ChatBot
|
|
83
128
|
|
|
84
129
|
from meshagent.tools.storage import StorageToolkit
|
|
85
130
|
|
|
86
|
-
from meshagent.agents.chat import (
|
|
87
|
-
ChatBotThreadOpenAIImageGenerationToolkitBuilder,
|
|
88
|
-
ChatBotThreadLocalShellToolkitBuilder,
|
|
89
|
-
ChatBotThreadOpenAIImageGenerationTool,
|
|
90
|
-
ChatBotThreadLocalShellTool,
|
|
91
|
-
ChatBotThreadShellTool,
|
|
92
|
-
ChatBotThreadShellToolkitBuilder,
|
|
93
|
-
ImageGenerationConfig,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
131
|
requirements = []
|
|
97
132
|
|
|
98
133
|
toolkits = []
|
|
@@ -109,44 +144,113 @@ def build_chatbot(
|
|
|
109
144
|
try:
|
|
110
145
|
with open(Path(os.path.expanduser(rules_file)).resolve(), "r") as f:
|
|
111
146
|
rules_config = RulesConfig.parse(f.read())
|
|
112
|
-
rule
|
|
147
|
+
rule.extend(rules_config.rules)
|
|
113
148
|
client_rules = rules_config.client_rules
|
|
114
149
|
|
|
115
150
|
except FileNotFoundError:
|
|
116
151
|
print(f"[yellow]rules file not found at {rules_file}[/yellow]")
|
|
117
152
|
|
|
118
153
|
BaseClass = ChatBot
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
raise RuntimeError(
|
|
124
|
-
"Computer use is enabled, but meshagent.computers is not installed."
|
|
125
|
-
)
|
|
126
|
-
BaseClass = ComputerAgent
|
|
127
|
-
llm_adapter = OpenAIResponsesAdapter(
|
|
128
|
-
model=model,
|
|
129
|
-
response_options={
|
|
130
|
-
"reasoning": {"generate_summary": "concise"},
|
|
131
|
-
"truncation": "auto",
|
|
132
|
-
},
|
|
154
|
+
decision_model = None
|
|
155
|
+
if llm_participant:
|
|
156
|
+
llm_adapter = MessageStreamLLMAdapter(
|
|
157
|
+
participant_name=llm_participant,
|
|
133
158
|
)
|
|
134
159
|
else:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
+
)
|
|
138
181
|
|
|
139
182
|
class CustomChatbot(BaseClass):
|
|
140
183
|
def __init__(self):
|
|
141
184
|
super().__init__(
|
|
142
185
|
llm_adapter=llm_adapter,
|
|
143
|
-
name=agent_name,
|
|
144
186
|
requires=requirements,
|
|
145
187
|
toolkits=toolkits,
|
|
146
188
|
rules=rule if len(rule) > 0 else None,
|
|
147
189
|
client_rules=client_rules,
|
|
190
|
+
always_reply=always_reply,
|
|
191
|
+
skill_dirs=skill_dirs,
|
|
192
|
+
decision_model=decision_model,
|
|
148
193
|
)
|
|
149
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
|
+
|
|
150
254
|
async def get_rules(self, *, thread_context, participant):
|
|
151
255
|
rules = await super().get_rules(
|
|
152
256
|
thread_context=thread_context, participant=participant
|
|
@@ -154,43 +258,11 @@ def build_chatbot(
|
|
|
154
258
|
|
|
155
259
|
if room_rules_path is not None:
|
|
156
260
|
for p in room_rules_path:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
rules_txt = room_rules.data.decode()
|
|
161
|
-
|
|
162
|
-
rules_config = RulesConfig.parse(rules_txt)
|
|
163
|
-
|
|
164
|
-
if rules_config.rules is not None:
|
|
165
|
-
rules.extend(rules_config.rules)
|
|
166
|
-
|
|
167
|
-
client = participant.get_attribute("client")
|
|
168
|
-
|
|
169
|
-
if rules_config.client_rules is not None and client is not None:
|
|
170
|
-
cr = rules_config.client_rules.get(client)
|
|
171
|
-
if cr is not None:
|
|
172
|
-
rules.extend(cr)
|
|
173
|
-
|
|
174
|
-
except RoomException:
|
|
175
|
-
try:
|
|
176
|
-
logger.info("attempting to initialize rules file")
|
|
177
|
-
handle = await self.room.storage.open(
|
|
178
|
-
path=p, overwrite=False
|
|
179
|
-
)
|
|
180
|
-
await self.room.storage.write(
|
|
181
|
-
handle=handle,
|
|
182
|
-
data="# Add rules to this file to customize your agent's behavior, lines starting with # will be ignored.\n\n".encode(),
|
|
183
|
-
)
|
|
184
|
-
await self.room.storage.close(handle=handle)
|
|
185
|
-
|
|
186
|
-
except RoomException:
|
|
187
|
-
pass
|
|
188
|
-
logger.info(
|
|
189
|
-
f"unable to load rules from {room_rules_path}, continuing with default rules"
|
|
190
|
-
)
|
|
191
|
-
pass
|
|
261
|
+
rules.extend(
|
|
262
|
+
await self._load_room_rules(path=p, participant=participant)
|
|
263
|
+
)
|
|
192
264
|
|
|
193
|
-
|
|
265
|
+
logging.info(f"using rules {rules}")
|
|
194
266
|
|
|
195
267
|
return rules
|
|
196
268
|
|
|
@@ -199,8 +271,7 @@ def build_chatbot(
|
|
|
199
271
|
|
|
200
272
|
if require_image_generation:
|
|
201
273
|
providers.append(
|
|
202
|
-
|
|
203
|
-
thread_context=thread_context,
|
|
274
|
+
ImageGenerationTool(
|
|
204
275
|
config=ImageGenerationConfig(
|
|
205
276
|
name="image_generation",
|
|
206
277
|
partial_images=3,
|
|
@@ -210,19 +281,24 @@ def build_chatbot(
|
|
|
210
281
|
|
|
211
282
|
if require_local_shell:
|
|
212
283
|
providers.append(
|
|
213
|
-
|
|
284
|
+
LocalShellTool(
|
|
214
285
|
working_directory=working_directory,
|
|
215
|
-
thread_context=thread_context,
|
|
216
286
|
config=LocalShellConfig(name="local_shell"),
|
|
217
287
|
)
|
|
218
288
|
)
|
|
219
289
|
|
|
290
|
+
env = {}
|
|
291
|
+
|
|
292
|
+
if delegate_shell_token:
|
|
293
|
+
env["MESHAGENT_TOKEN"] = self.room.protocol.token
|
|
294
|
+
|
|
220
295
|
if require_shell:
|
|
221
296
|
providers.append(
|
|
222
|
-
|
|
223
|
-
thread_context=thread_context,
|
|
297
|
+
ShellTool(
|
|
224
298
|
working_directory=working_directory,
|
|
225
299
|
config=ShellConfig(name="shell"),
|
|
300
|
+
image=shell_image or "python:3.13",
|
|
301
|
+
env=env,
|
|
226
302
|
)
|
|
227
303
|
)
|
|
228
304
|
|
|
@@ -246,9 +322,80 @@ def build_chatbot(
|
|
|
246
322
|
if require_storage:
|
|
247
323
|
providers.extend(StorageToolkit().tools)
|
|
248
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
|
+
|
|
249
377
|
tk = await super().get_thread_toolkits(
|
|
250
378
|
thread_context=thread_context, participant=participant
|
|
251
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
|
+
|
|
252
399
|
return [
|
|
253
400
|
*(
|
|
254
401
|
[Toolkit(name="tools", tools=providers)]
|
|
@@ -258,34 +405,27 @@ def build_chatbot(
|
|
|
258
405
|
*tk,
|
|
259
406
|
]
|
|
260
407
|
|
|
261
|
-
|
|
408
|
+
def get_toolkit_builders(self):
|
|
262
409
|
providers = []
|
|
263
410
|
|
|
264
411
|
if image_generation:
|
|
265
|
-
providers.append(
|
|
266
|
-
ChatBotThreadOpenAIImageGenerationToolkitBuilder(
|
|
267
|
-
thread_context=thread_context
|
|
268
|
-
)
|
|
269
|
-
)
|
|
412
|
+
providers.append(ImageGenerationToolkitBuilder())
|
|
270
413
|
|
|
271
414
|
if apply_patch:
|
|
272
|
-
providers.append(
|
|
273
|
-
ApplyPatchToolkitBuilder(thread_context=thread_context)
|
|
274
|
-
)
|
|
415
|
+
providers.append(ApplyPatchToolkitBuilder())
|
|
275
416
|
|
|
276
417
|
if local_shell:
|
|
277
418
|
providers.append(
|
|
278
|
-
|
|
279
|
-
thread_context=thread_context,
|
|
419
|
+
LocalShellToolkitBuilder(
|
|
280
420
|
working_directory=working_directory,
|
|
281
421
|
)
|
|
282
422
|
)
|
|
283
423
|
|
|
284
424
|
if shell:
|
|
285
425
|
providers.append(
|
|
286
|
-
|
|
287
|
-
thread_context=thread_context,
|
|
426
|
+
ShellToolkitBuilder(
|
|
288
427
|
working_directory=working_directory,
|
|
428
|
+
image=shell_image,
|
|
289
429
|
)
|
|
290
430
|
)
|
|
291
431
|
|
|
@@ -304,12 +444,14 @@ def build_chatbot(
|
|
|
304
444
|
|
|
305
445
|
|
|
306
446
|
@app.async_command("join")
|
|
307
|
-
async def
|
|
447
|
+
async def join(
|
|
308
448
|
*,
|
|
309
|
-
project_id: ProjectIdOption
|
|
449
|
+
project_id: ProjectIdOption,
|
|
310
450
|
room: RoomOption,
|
|
311
451
|
role: str = "agent",
|
|
312
|
-
agent_name: Annotated[
|
|
452
|
+
agent_name: Annotated[
|
|
453
|
+
Optional[str], typer.Option(..., help="Name of the agent to call")
|
|
454
|
+
] = None,
|
|
313
455
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
314
456
|
room_rules: Annotated[
|
|
315
457
|
List[str],
|
|
@@ -320,17 +462,33 @@ async def make_call(
|
|
|
320
462
|
),
|
|
321
463
|
] = [],
|
|
322
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
|
+
] = [],
|
|
323
477
|
toolkit: Annotated[
|
|
324
478
|
List[str],
|
|
325
|
-
typer.Option(
|
|
479
|
+
typer.Option(
|
|
480
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
481
|
+
),
|
|
326
482
|
] = [],
|
|
327
483
|
schema: Annotated[
|
|
328
484
|
List[str],
|
|
329
|
-
typer.Option(
|
|
485
|
+
typer.Option(
|
|
486
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
487
|
+
),
|
|
330
488
|
] = [],
|
|
331
489
|
model: Annotated[
|
|
332
490
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
333
|
-
] = "gpt-5.
|
|
491
|
+
] = "gpt-5.2",
|
|
334
492
|
image_generation: Annotated[
|
|
335
493
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
336
494
|
] = None,
|
|
@@ -359,7 +517,7 @@ async def make_call(
|
|
|
359
517
|
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
360
518
|
] = False,
|
|
361
519
|
require_image_generation: Annotated[
|
|
362
|
-
Optional[str], typer.Option(..., help="Name of an image gen model"
|
|
520
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
363
521
|
] = None,
|
|
364
522
|
require_computer_use: Annotated[
|
|
365
523
|
Optional[bool],
|
|
@@ -371,25 +529,63 @@ async def make_call(
|
|
|
371
529
|
] = False,
|
|
372
530
|
require_local_shell: Annotated[
|
|
373
531
|
Optional[bool],
|
|
374
|
-
typer.Option(..., help="Enable local shell tool calling"
|
|
532
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
375
533
|
] = False,
|
|
376
534
|
require_shell: Annotated[
|
|
377
535
|
Optional[bool],
|
|
378
|
-
typer.Option(..., help="Enable function shell tool calling"
|
|
536
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
379
537
|
] = False,
|
|
380
538
|
require_apply_patch: Annotated[
|
|
381
539
|
Optional[bool],
|
|
382
|
-
typer.Option(..., help="Enable apply patch tool calling"
|
|
540
|
+
typer.Option(..., help="Enable apply patch tool calling"),
|
|
383
541
|
] = False,
|
|
384
542
|
require_web_search: Annotated[
|
|
385
543
|
Optional[bool],
|
|
386
|
-
typer.Option(..., help="Enable web search tool calling"
|
|
544
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
387
545
|
] = False,
|
|
388
546
|
require_mcp: Annotated[
|
|
389
|
-
Optional[bool], typer.Option(..., help="Enable mcp tool calling"
|
|
547
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
390
548
|
] = False,
|
|
391
549
|
require_storage: Annotated[
|
|
392
|
-
Optional[bool], typer.Option(..., help="Enable storage toolkit"
|
|
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"),
|
|
393
589
|
] = False,
|
|
394
590
|
working_directory: Annotated[
|
|
395
591
|
Optional[str],
|
|
@@ -399,77 +595,126 @@ async def make_call(
|
|
|
399
595
|
str,
|
|
400
596
|
typer.Option("--key", help="an api key to sign the token with"),
|
|
401
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,
|
|
402
622
|
):
|
|
623
|
+
if database_namespace is not None:
|
|
624
|
+
database_namespace = database_namespace.split("::")
|
|
625
|
+
|
|
403
626
|
key = await resolve_key(project_id=project_id, key=key)
|
|
404
627
|
account_client = await get_client()
|
|
405
628
|
try:
|
|
406
629
|
project_id = await resolve_project_id(project_id=project_id)
|
|
407
630
|
room = resolve_room(room)
|
|
408
631
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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)
|
|
412
639
|
|
|
413
|
-
|
|
640
|
+
token = ParticipantToken(
|
|
641
|
+
name=agent_name,
|
|
642
|
+
)
|
|
414
643
|
|
|
415
|
-
|
|
416
|
-
token.add_room_grant(room)
|
|
644
|
+
token.add_api_grant(ApiScope.agent_default(tunnels=require_computer_use))
|
|
417
645
|
|
|
418
|
-
|
|
646
|
+
token.add_role_grant(role=role)
|
|
647
|
+
token.add_room_grant(room)
|
|
419
648
|
|
|
420
|
-
|
|
421
|
-
async with RoomClient(
|
|
422
|
-
protocol=WebSocketClientProtocol(
|
|
423
|
-
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
424
|
-
token=jwt,
|
|
425
|
-
)
|
|
426
|
-
) as client:
|
|
427
|
-
requirements = []
|
|
649
|
+
jwt = token.to_jwt(api_key=key)
|
|
428
650
|
|
|
429
|
-
|
|
430
|
-
requirements.append(RequiredToolkit(name=t))
|
|
651
|
+
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
431
652
|
|
|
432
|
-
|
|
433
|
-
|
|
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
|
+
)
|
|
434
692
|
|
|
435
|
-
|
|
436
|
-
computer_use=computer_use,
|
|
437
|
-
model=model,
|
|
438
|
-
local_shell=local_shell,
|
|
439
|
-
shell=shell,
|
|
440
|
-
apply_patch=apply_patch,
|
|
441
|
-
agent_name=agent_name,
|
|
442
|
-
rule=rule,
|
|
443
|
-
toolkit=toolkit,
|
|
444
|
-
schema=schema,
|
|
445
|
-
rules_file=rules_file,
|
|
446
|
-
image_generation=image_generation,
|
|
447
|
-
web_search=web_search,
|
|
448
|
-
mcp=mcp,
|
|
449
|
-
storage=storage,
|
|
450
|
-
require_apply_patch=require_apply_patch,
|
|
451
|
-
require_web_search=require_web_search,
|
|
452
|
-
require_local_shell=require_local_shell,
|
|
453
|
-
require_shell=require_shell,
|
|
454
|
-
require_image_generation=require_image_generation,
|
|
455
|
-
require_mcp=require_mcp,
|
|
456
|
-
require_storage=require_storage,
|
|
457
|
-
room_rules_path=room_rules,
|
|
458
|
-
working_directory=working_directory,
|
|
459
|
-
)
|
|
693
|
+
bot = CustomChatbot()
|
|
460
694
|
|
|
461
|
-
|
|
695
|
+
if get_deferred():
|
|
696
|
+
from meshagent.cli.host import agents
|
|
462
697
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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,
|
|
468
706
|
)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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()
|
|
472
715
|
|
|
716
|
+
except KeyboardInterrupt:
|
|
717
|
+
await bot.stop()
|
|
473
718
|
finally:
|
|
474
719
|
await account_client.close()
|
|
475
720
|
|
|
@@ -488,17 +733,33 @@ async def service(
|
|
|
488
733
|
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
489
734
|
),
|
|
490
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
|
+
] = [],
|
|
491
748
|
toolkit: Annotated[
|
|
492
749
|
List[str],
|
|
493
|
-
typer.Option(
|
|
750
|
+
typer.Option(
|
|
751
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
752
|
+
),
|
|
494
753
|
] = [],
|
|
495
754
|
schema: Annotated[
|
|
496
755
|
List[str],
|
|
497
|
-
typer.Option(
|
|
756
|
+
typer.Option(
|
|
757
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
758
|
+
),
|
|
498
759
|
] = [],
|
|
499
760
|
model: Annotated[
|
|
500
761
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
501
|
-
] = "gpt-5.
|
|
762
|
+
] = "gpt-5.2",
|
|
502
763
|
image_generation: Annotated[
|
|
503
764
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
504
765
|
] = None,
|
|
@@ -527,7 +788,7 @@ async def service(
|
|
|
527
788
|
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
528
789
|
] = False,
|
|
529
790
|
require_image_generation: Annotated[
|
|
530
|
-
Optional[str], typer.Option(..., help="Name of an image gen model"
|
|
791
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
531
792
|
] = None,
|
|
532
793
|
require_computer_use: Annotated[
|
|
533
794
|
Optional[bool],
|
|
@@ -539,53 +800,136 @@ async def service(
|
|
|
539
800
|
] = False,
|
|
540
801
|
require_local_shell: Annotated[
|
|
541
802
|
Optional[bool],
|
|
542
|
-
typer.Option(..., help="Enable local shell tool calling"
|
|
803
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
543
804
|
] = False,
|
|
544
805
|
require_shell: Annotated[
|
|
545
806
|
Optional[bool],
|
|
546
|
-
typer.Option(..., help="Enable function shell tool calling"
|
|
807
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
547
808
|
] = False,
|
|
548
809
|
require_apply_patch: Annotated[
|
|
549
|
-
Optional[bool], typer.Option(..., help="Enable apply patch tool"
|
|
810
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
550
811
|
] = False,
|
|
551
812
|
require_web_search: Annotated[
|
|
552
813
|
Optional[bool],
|
|
553
|
-
typer.Option(..., help="Enable web search tool calling"
|
|
814
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
554
815
|
] = False,
|
|
555
816
|
require_mcp: Annotated[
|
|
556
|
-
Optional[bool], typer.Option(..., help="Enable mcp tool calling"
|
|
817
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
557
818
|
] = False,
|
|
558
819
|
require_storage: Annotated[
|
|
559
|
-
Optional[bool], typer.Option(..., help="Enable storage toolkit"
|
|
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
|
+
),
|
|
560
851
|
] = False,
|
|
561
852
|
working_directory: Annotated[
|
|
562
853
|
Optional[str],
|
|
563
854
|
typer.Option(..., help="The default working directory for shell commands"),
|
|
564
855
|
] = None,
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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,
|
|
568
897
|
):
|
|
569
|
-
|
|
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
|
+
)
|
|
570
913
|
|
|
571
|
-
service = ServiceHost(host=host, port=port)
|
|
572
914
|
service.add_path(
|
|
915
|
+
identity=agent_name,
|
|
573
916
|
path=path,
|
|
574
917
|
cls=build_chatbot(
|
|
575
918
|
computer_use=computer_use,
|
|
919
|
+
require_computer_use=require_computer_use,
|
|
576
920
|
model=model,
|
|
577
921
|
local_shell=local_shell,
|
|
578
922
|
shell=shell,
|
|
579
923
|
apply_patch=apply_patch,
|
|
580
|
-
agent_name=agent_name,
|
|
581
924
|
rule=rule,
|
|
582
|
-
toolkit=toolkit,
|
|
583
|
-
schema=schema,
|
|
925
|
+
toolkit=require_toolkit + toolkit,
|
|
926
|
+
schema=require_schema + schema,
|
|
584
927
|
rules_file=rules_file,
|
|
585
928
|
web_search=web_search,
|
|
586
929
|
image_generation=image_generation,
|
|
587
930
|
mcp=mcp,
|
|
588
931
|
storage=storage,
|
|
932
|
+
database_namespace=database_namespace,
|
|
589
933
|
require_web_search=require_web_search,
|
|
590
934
|
require_shell=require_shell,
|
|
591
935
|
require_apply_patch=require_apply_patch,
|
|
@@ -593,9 +937,1047 @@ async def service(
|
|
|
593
937
|
require_image_generation=require_image_generation,
|
|
594
938
|
require_mcp=require_mcp,
|
|
595
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,
|
|
596
945
|
room_rules_path=room_rules,
|
|
597
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,
|
|
598
955
|
),
|
|
599
956
|
)
|
|
600
957
|
|
|
601
|
-
|
|
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()
|