meshagent-cli 0.7.0__py3-none-any.whl → 0.21.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meshagent/cli/agent.py +15 -11
- meshagent/cli/api_keys.py +4 -4
- meshagent/cli/async_typer.py +52 -4
- meshagent/cli/call.py +12 -8
- meshagent/cli/chatbot.py +1007 -129
- meshagent/cli/cli.py +21 -20
- 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 +62 -11
- meshagent/cli/helpers.py +66 -9
- meshagent/cli/host.py +37 -0
- meshagent/cli/mailbot.py +1004 -40
- meshagent/cli/mailboxes.py +223 -0
- meshagent/cli/meeting_transcriber.py +10 -4
- meshagent/cli/messaging.py +7 -7
- meshagent/cli/multi.py +402 -0
- meshagent/cli/oauth2.py +44 -21
- meshagent/cli/participant_token.py +5 -3
- meshagent/cli/port.py +70 -0
- meshagent/cli/queue.py +2 -2
- meshagent/cli/room.py +20 -212
- meshagent/cli/rooms.py +214 -0
- meshagent/cli/services.py +32 -23
- meshagent/cli/sessions.py +5 -5
- meshagent/cli/storage.py +5 -5
- meshagent/cli/task_runner.py +770 -0
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +502 -76
- meshagent/cli/webhook.py +7 -7
- meshagent/cli/worker.py +1327 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/METADATA +13 -13
- meshagent_cli-0.21.0.dist-info/RECORD +44 -0
- meshagent_cli-0.7.0.dist-info/RECORD +0 -36
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/top_level.txt +0 -0
meshagent/cli/chatbot.py
CHANGED
|
@@ -3,7 +3,14 @@ from rich import print
|
|
|
3
3
|
from typing import Annotated, Optional
|
|
4
4
|
from meshagent.tools import Toolkit
|
|
5
5
|
from meshagent.tools.storage import StorageToolkitBuilder
|
|
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,6 +31,7 @@ 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
|
|
@@ -40,13 +49,33 @@ 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
|
+
from meshagent.api.client import ConflictError
|
|
78
|
+
|
|
50
79
|
logger = logging.getLogger("chatbot")
|
|
51
80
|
|
|
52
81
|
app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
@@ -69,30 +98,33 @@ def build_chatbot(
|
|
|
69
98
|
storage: Optional[str] = None,
|
|
70
99
|
require_image_generation: Optional[str] = None,
|
|
71
100
|
require_local_shell: Optional[str] = None,
|
|
72
|
-
require_shell: Optional[
|
|
101
|
+
require_shell: Optional[bool] = None,
|
|
73
102
|
require_apply_patch: Optional[str] = None,
|
|
74
103
|
require_computer_use: Optional[str] = None,
|
|
75
104
|
require_web_search: Optional[str] = None,
|
|
76
105
|
require_mcp: Optional[str] = None,
|
|
77
106
|
require_storage: Optional[str] = None,
|
|
107
|
+
require_table_read: list[str] = None,
|
|
108
|
+
require_table_write: list[str] = None,
|
|
109
|
+
require_read_only_storage: Optional[str] = None,
|
|
110
|
+
require_time: bool = True,
|
|
111
|
+
require_uuid: bool = False,
|
|
78
112
|
rules_file: Optional[str] = None,
|
|
79
|
-
room_rules_path: Optional[str] = None,
|
|
113
|
+
room_rules_path: Optional[list[str]] = None,
|
|
114
|
+
require_discovery: Optional[str] = None,
|
|
115
|
+
require_document_authoring: Optional[str] = None,
|
|
80
116
|
working_directory: Optional[str] = None,
|
|
117
|
+
llm_participant: Optional[str] = None,
|
|
118
|
+
database_namespace: Optional[list[str]] = None,
|
|
119
|
+
always_reply: Optional[bool] = None,
|
|
120
|
+
skill_dirs: Optional[list[str]] = None,
|
|
121
|
+
shell_image: Optional[str] = None,
|
|
122
|
+
log_llm_requests: Optional[bool] = None,
|
|
81
123
|
):
|
|
82
124
|
from meshagent.agents.chat import ChatBot
|
|
83
125
|
|
|
84
126
|
from meshagent.tools.storage import StorageToolkit
|
|
85
127
|
|
|
86
|
-
from meshagent.agents.chat import (
|
|
87
|
-
ChatBotThreadOpenAIImageGenerationToolkitBuilder,
|
|
88
|
-
ChatBotThreadLocalShellToolkitBuilder,
|
|
89
|
-
ChatBotThreadOpenAIImageGenerationTool,
|
|
90
|
-
ChatBotThreadLocalShellTool,
|
|
91
|
-
ChatBotThreadShellTool,
|
|
92
|
-
ChatBotThreadShellToolkitBuilder,
|
|
93
|
-
ImageGenerationConfig,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
128
|
requirements = []
|
|
97
129
|
|
|
98
130
|
toolkits = []
|
|
@@ -109,32 +141,32 @@ def build_chatbot(
|
|
|
109
141
|
try:
|
|
110
142
|
with open(Path(os.path.expanduser(rules_file)).resolve(), "r") as f:
|
|
111
143
|
rules_config = RulesConfig.parse(f.read())
|
|
112
|
-
rule
|
|
144
|
+
rule.extend(rules_config.rules)
|
|
113
145
|
client_rules = rules_config.client_rules
|
|
114
146
|
|
|
115
147
|
except FileNotFoundError:
|
|
116
148
|
print(f"[yellow]rules file not found at {rules_file}[/yellow]")
|
|
117
149
|
|
|
118
150
|
BaseClass = ChatBot
|
|
119
|
-
if
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if ComputerAgent is None:
|
|
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
|
-
},
|
|
151
|
+
if llm_participant:
|
|
152
|
+
llm_adapter = MessageStreamLLMAdapter(
|
|
153
|
+
participant_name=llm_participant,
|
|
133
154
|
)
|
|
134
155
|
else:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
if computer_use or require_computer_use:
|
|
157
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
158
|
+
model=model,
|
|
159
|
+
response_options={
|
|
160
|
+
"reasoning": {"summary": "concise"},
|
|
161
|
+
"truncation": "auto",
|
|
162
|
+
},
|
|
163
|
+
log_requests=log_llm_requests,
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
167
|
+
model=model,
|
|
168
|
+
log_requests=log_llm_requests,
|
|
169
|
+
)
|
|
138
170
|
|
|
139
171
|
class CustomChatbot(BaseClass):
|
|
140
172
|
def __init__(self):
|
|
@@ -145,8 +177,61 @@ def build_chatbot(
|
|
|
145
177
|
toolkits=toolkits,
|
|
146
178
|
rules=rule if len(rule) > 0 else None,
|
|
147
179
|
client_rules=client_rules,
|
|
180
|
+
always_reply=always_reply,
|
|
181
|
+
skill_dirs=skill_dirs,
|
|
148
182
|
)
|
|
149
183
|
|
|
184
|
+
async def start(self, *, room: RoomClient):
|
|
185
|
+
await super().start(room=room)
|
|
186
|
+
|
|
187
|
+
if room_rules_path is not None:
|
|
188
|
+
for p in room_rules_path:
|
|
189
|
+
await self._load_room_rules(path=p)
|
|
190
|
+
|
|
191
|
+
async def _load_room_rules(
|
|
192
|
+
self,
|
|
193
|
+
*,
|
|
194
|
+
path: str,
|
|
195
|
+
participant: Optional[RemoteParticipant] = None,
|
|
196
|
+
):
|
|
197
|
+
rules = []
|
|
198
|
+
try:
|
|
199
|
+
room_rules = await self.room.storage.download(path=path)
|
|
200
|
+
|
|
201
|
+
rules_txt = room_rules.data.decode()
|
|
202
|
+
|
|
203
|
+
rules_config = RulesConfig.parse(rules_txt)
|
|
204
|
+
|
|
205
|
+
if rules_config.rules is not None:
|
|
206
|
+
rules.extend(rules_config.rules)
|
|
207
|
+
|
|
208
|
+
if participant is not None:
|
|
209
|
+
client = participant.get_attribute("client")
|
|
210
|
+
|
|
211
|
+
if rules_config.client_rules is not None and client is not None:
|
|
212
|
+
cr = rules_config.client_rules.get(client)
|
|
213
|
+
if cr is not None:
|
|
214
|
+
rules.extend(cr)
|
|
215
|
+
|
|
216
|
+
except RoomException:
|
|
217
|
+
try:
|
|
218
|
+
logger.info("attempting to initialize rules file")
|
|
219
|
+
handle = await self.room.storage.open(path=path, overwrite=False)
|
|
220
|
+
await self.room.storage.write(
|
|
221
|
+
handle=handle,
|
|
222
|
+
data="# Add rules to this file to customize your agent's behavior, lines starting with # will be ignored.\n\n".encode(),
|
|
223
|
+
)
|
|
224
|
+
await self.room.storage.close(handle=handle)
|
|
225
|
+
|
|
226
|
+
except RoomException:
|
|
227
|
+
pass
|
|
228
|
+
logger.info(
|
|
229
|
+
f"unable to load rules from {path}, continuing with default rules"
|
|
230
|
+
)
|
|
231
|
+
pass
|
|
232
|
+
|
|
233
|
+
return rules
|
|
234
|
+
|
|
150
235
|
async def get_rules(self, *, thread_context, participant):
|
|
151
236
|
rules = await super().get_rules(
|
|
152
237
|
thread_context=thread_context, participant=participant
|
|
@@ -154,43 +239,11 @@ def build_chatbot(
|
|
|
154
239
|
|
|
155
240
|
if room_rules_path is not None:
|
|
156
241
|
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
|
|
242
|
+
rules.extend(
|
|
243
|
+
await self._load_room_rules(path=p, participant=participant)
|
|
244
|
+
)
|
|
192
245
|
|
|
193
|
-
|
|
246
|
+
logging.info(f"using rules {rules}")
|
|
194
247
|
|
|
195
248
|
return rules
|
|
196
249
|
|
|
@@ -199,8 +252,7 @@ def build_chatbot(
|
|
|
199
252
|
|
|
200
253
|
if require_image_generation:
|
|
201
254
|
providers.append(
|
|
202
|
-
|
|
203
|
-
thread_context=thread_context,
|
|
255
|
+
ImageGenerationTool(
|
|
204
256
|
config=ImageGenerationConfig(
|
|
205
257
|
name="image_generation",
|
|
206
258
|
partial_images=3,
|
|
@@ -210,19 +262,18 @@ def build_chatbot(
|
|
|
210
262
|
|
|
211
263
|
if require_local_shell:
|
|
212
264
|
providers.append(
|
|
213
|
-
|
|
265
|
+
LocalShellTool(
|
|
214
266
|
working_directory=working_directory,
|
|
215
|
-
thread_context=thread_context,
|
|
216
267
|
config=LocalShellConfig(name="local_shell"),
|
|
217
268
|
)
|
|
218
269
|
)
|
|
219
270
|
|
|
220
271
|
if require_shell:
|
|
221
272
|
providers.append(
|
|
222
|
-
|
|
223
|
-
thread_context=thread_context,
|
|
273
|
+
ShellTool(
|
|
224
274
|
working_directory=working_directory,
|
|
225
275
|
config=ShellConfig(name="shell"),
|
|
276
|
+
image=shell_image or "python:3.13",
|
|
226
277
|
)
|
|
227
278
|
)
|
|
228
279
|
|
|
@@ -246,9 +297,80 @@ def build_chatbot(
|
|
|
246
297
|
if require_storage:
|
|
247
298
|
providers.extend(StorageToolkit().tools)
|
|
248
299
|
|
|
300
|
+
if len(require_table_read) > 0:
|
|
301
|
+
providers.extend(
|
|
302
|
+
(
|
|
303
|
+
await DatabaseToolkitBuilder().make(
|
|
304
|
+
room=self.room,
|
|
305
|
+
model=model,
|
|
306
|
+
config=DatabaseToolkitConfig(
|
|
307
|
+
tables=require_table_read,
|
|
308
|
+
read_only=True,
|
|
309
|
+
namespace=database_namespace,
|
|
310
|
+
),
|
|
311
|
+
)
|
|
312
|
+
).tools
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if require_time:
|
|
316
|
+
providers.extend((DatetimeToolkit()).tools)
|
|
317
|
+
|
|
318
|
+
if require_uuid:
|
|
319
|
+
providers.extend((UUIDToolkit()).tools)
|
|
320
|
+
|
|
321
|
+
if len(require_table_write) > 0:
|
|
322
|
+
providers.extend(
|
|
323
|
+
(
|
|
324
|
+
await DatabaseToolkitBuilder().make(
|
|
325
|
+
room=self.room,
|
|
326
|
+
model=model,
|
|
327
|
+
config=DatabaseToolkitConfig(
|
|
328
|
+
tables=require_table_write,
|
|
329
|
+
read_only=False,
|
|
330
|
+
namespace=database_namespace,
|
|
331
|
+
),
|
|
332
|
+
)
|
|
333
|
+
).tools
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
if require_read_only_storage:
|
|
337
|
+
providers.extend(StorageToolkit(read_only=True).tools)
|
|
338
|
+
|
|
339
|
+
if require_document_authoring:
|
|
340
|
+
providers.extend(DocumentAuthoringToolkit().tools)
|
|
341
|
+
providers.extend(
|
|
342
|
+
DocumentTypeAuthoringToolkit(
|
|
343
|
+
schema=widget_schema, document_type="widget"
|
|
344
|
+
).tools
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
if require_discovery:
|
|
348
|
+
from meshagent.tools.discovery import DiscoveryToolkit
|
|
349
|
+
|
|
350
|
+
providers.extend(DiscoveryToolkit().tools)
|
|
351
|
+
|
|
249
352
|
tk = await super().get_thread_toolkits(
|
|
250
353
|
thread_context=thread_context, participant=participant
|
|
251
354
|
)
|
|
355
|
+
|
|
356
|
+
if require_computer_use:
|
|
357
|
+
from meshagent.computers.agent import ComputerToolkit
|
|
358
|
+
|
|
359
|
+
def render_screen(image_bytes: bytes):
|
|
360
|
+
for participant in thread_context.participants:
|
|
361
|
+
self.room.messaging.send_message_nowait(
|
|
362
|
+
to=participant,
|
|
363
|
+
type="computer_screen",
|
|
364
|
+
message={},
|
|
365
|
+
attachment=image_bytes,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
computer_toolkit = ComputerToolkit(
|
|
369
|
+
room=self.room, render_screen=render_screen
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
tk.append(computer_toolkit)
|
|
373
|
+
|
|
252
374
|
return [
|
|
253
375
|
*(
|
|
254
376
|
[Toolkit(name="tools", tools=providers)]
|
|
@@ -258,34 +380,27 @@ def build_chatbot(
|
|
|
258
380
|
*tk,
|
|
259
381
|
]
|
|
260
382
|
|
|
261
|
-
|
|
383
|
+
def get_toolkit_builders(self):
|
|
262
384
|
providers = []
|
|
263
385
|
|
|
264
386
|
if image_generation:
|
|
265
|
-
providers.append(
|
|
266
|
-
ChatBotThreadOpenAIImageGenerationToolkitBuilder(
|
|
267
|
-
thread_context=thread_context
|
|
268
|
-
)
|
|
269
|
-
)
|
|
387
|
+
providers.append(ImageGenerationToolkitBuilder())
|
|
270
388
|
|
|
271
389
|
if apply_patch:
|
|
272
|
-
providers.append(
|
|
273
|
-
ApplyPatchToolkitBuilder(thread_context=thread_context)
|
|
274
|
-
)
|
|
390
|
+
providers.append(ApplyPatchToolkitBuilder())
|
|
275
391
|
|
|
276
392
|
if local_shell:
|
|
277
393
|
providers.append(
|
|
278
|
-
|
|
279
|
-
thread_context=thread_context,
|
|
394
|
+
LocalShellToolkitBuilder(
|
|
280
395
|
working_directory=working_directory,
|
|
281
396
|
)
|
|
282
397
|
)
|
|
283
398
|
|
|
284
399
|
if shell:
|
|
285
400
|
providers.append(
|
|
286
|
-
|
|
287
|
-
thread_context=thread_context,
|
|
401
|
+
ShellToolkitBuilder(
|
|
288
402
|
working_directory=working_directory,
|
|
403
|
+
image=shell_image,
|
|
289
404
|
)
|
|
290
405
|
)
|
|
291
406
|
|
|
@@ -306,7 +421,7 @@ def build_chatbot(
|
|
|
306
421
|
@app.async_command("join")
|
|
307
422
|
async def make_call(
|
|
308
423
|
*,
|
|
309
|
-
project_id: ProjectIdOption
|
|
424
|
+
project_id: ProjectIdOption,
|
|
310
425
|
room: RoomOption,
|
|
311
426
|
role: str = "agent",
|
|
312
427
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
@@ -320,17 +435,33 @@ async def make_call(
|
|
|
320
435
|
),
|
|
321
436
|
] = [],
|
|
322
437
|
rules_file: Optional[str] = None,
|
|
438
|
+
require_toolkit: Annotated[
|
|
439
|
+
List[str],
|
|
440
|
+
typer.Option(
|
|
441
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
442
|
+
),
|
|
443
|
+
] = [],
|
|
444
|
+
require_schema: Annotated[
|
|
445
|
+
List[str],
|
|
446
|
+
typer.Option(
|
|
447
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
448
|
+
),
|
|
449
|
+
] = [],
|
|
323
450
|
toolkit: Annotated[
|
|
324
451
|
List[str],
|
|
325
|
-
typer.Option(
|
|
452
|
+
typer.Option(
|
|
453
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
454
|
+
),
|
|
326
455
|
] = [],
|
|
327
456
|
schema: Annotated[
|
|
328
457
|
List[str],
|
|
329
|
-
typer.Option(
|
|
458
|
+
typer.Option(
|
|
459
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
460
|
+
),
|
|
330
461
|
] = [],
|
|
331
462
|
model: Annotated[
|
|
332
463
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
333
|
-
] = "gpt-5.
|
|
464
|
+
] = "gpt-5.2",
|
|
334
465
|
image_generation: Annotated[
|
|
335
466
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
336
467
|
] = None,
|
|
@@ -359,7 +490,7 @@ async def make_call(
|
|
|
359
490
|
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
360
491
|
] = False,
|
|
361
492
|
require_image_generation: Annotated[
|
|
362
|
-
Optional[str], typer.Option(..., help="Name of an image gen model"
|
|
493
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
363
494
|
] = None,
|
|
364
495
|
require_computer_use: Annotated[
|
|
365
496
|
Optional[bool],
|
|
@@ -371,25 +502,63 @@ async def make_call(
|
|
|
371
502
|
] = False,
|
|
372
503
|
require_local_shell: Annotated[
|
|
373
504
|
Optional[bool],
|
|
374
|
-
typer.Option(..., help="Enable local shell tool calling"
|
|
505
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
375
506
|
] = False,
|
|
376
507
|
require_shell: Annotated[
|
|
377
508
|
Optional[bool],
|
|
378
|
-
typer.Option(..., help="Enable function shell tool calling"
|
|
509
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
379
510
|
] = False,
|
|
380
511
|
require_apply_patch: Annotated[
|
|
381
512
|
Optional[bool],
|
|
382
|
-
typer.Option(..., help="Enable apply patch tool calling"
|
|
513
|
+
typer.Option(..., help="Enable apply patch tool calling"),
|
|
383
514
|
] = False,
|
|
384
515
|
require_web_search: Annotated[
|
|
385
516
|
Optional[bool],
|
|
386
|
-
typer.Option(..., help="Enable web search tool calling"
|
|
517
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
387
518
|
] = False,
|
|
388
519
|
require_mcp: Annotated[
|
|
389
|
-
Optional[bool], typer.Option(..., help="Enable mcp tool calling"
|
|
520
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
390
521
|
] = False,
|
|
391
522
|
require_storage: Annotated[
|
|
392
|
-
Optional[bool], typer.Option(..., help="Enable storage toolkit"
|
|
523
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
524
|
+
] = False,
|
|
525
|
+
database_namespace: Annotated[
|
|
526
|
+
Optional[str],
|
|
527
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
528
|
+
] = None,
|
|
529
|
+
require_table_read: Annotated[
|
|
530
|
+
list[str],
|
|
531
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
532
|
+
] = [],
|
|
533
|
+
require_table_write: Annotated[
|
|
534
|
+
list[str],
|
|
535
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
536
|
+
] = [],
|
|
537
|
+
require_read_only_storage: Annotated[
|
|
538
|
+
Optional[bool],
|
|
539
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
540
|
+
] = False,
|
|
541
|
+
require_time: Annotated[
|
|
542
|
+
bool,
|
|
543
|
+
typer.Option(
|
|
544
|
+
...,
|
|
545
|
+
help="Enable time/datetime tools",
|
|
546
|
+
),
|
|
547
|
+
] = True,
|
|
548
|
+
require_uuid: Annotated[
|
|
549
|
+
bool,
|
|
550
|
+
typer.Option(
|
|
551
|
+
...,
|
|
552
|
+
help="Enable UUID generation tools",
|
|
553
|
+
),
|
|
554
|
+
] = False,
|
|
555
|
+
require_document_authoring: Annotated[
|
|
556
|
+
Optional[bool],
|
|
557
|
+
typer.Option(..., help="Enable MeshDocument authoring"),
|
|
558
|
+
] = False,
|
|
559
|
+
require_discovery: Annotated[
|
|
560
|
+
Optional[bool],
|
|
561
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
393
562
|
] = False,
|
|
394
563
|
working_directory: Annotated[
|
|
395
564
|
Optional[str],
|
|
@@ -399,7 +568,30 @@ async def make_call(
|
|
|
399
568
|
str,
|
|
400
569
|
typer.Option("--key", help="an api key to sign the token with"),
|
|
401
570
|
] = None,
|
|
571
|
+
llm_participant: Annotated[
|
|
572
|
+
Optional[str],
|
|
573
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
574
|
+
] = None,
|
|
575
|
+
always_reply: Annotated[
|
|
576
|
+
Optional[bool],
|
|
577
|
+
typer.Option(..., help="Always reply"),
|
|
578
|
+
] = None,
|
|
579
|
+
skill_dir: Annotated[
|
|
580
|
+
list[str],
|
|
581
|
+
typer.Option(..., help="an agent skills directory"),
|
|
582
|
+
] = [],
|
|
583
|
+
shell_image: Annotated[
|
|
584
|
+
Optional[str],
|
|
585
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
586
|
+
] = None,
|
|
587
|
+
log_llm_requests: Annotated[
|
|
588
|
+
Optional[bool],
|
|
589
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
590
|
+
] = False,
|
|
402
591
|
):
|
|
592
|
+
if database_namespace is not None:
|
|
593
|
+
database_namespace = database_namespace.split("::")
|
|
594
|
+
|
|
403
595
|
key = await resolve_key(project_id=project_id, key=key)
|
|
404
596
|
account_client = await get_client()
|
|
405
597
|
try:
|
|
@@ -410,7 +602,7 @@ async def make_call(
|
|
|
410
602
|
name=agent_name,
|
|
411
603
|
)
|
|
412
604
|
|
|
413
|
-
token.add_api_grant(ApiScope.agent_default())
|
|
605
|
+
token.add_api_grant(ApiScope.agent_default(tunnels=require_computer_use))
|
|
414
606
|
|
|
415
607
|
token.add_role_grant(role=role)
|
|
416
608
|
token.add_room_grant(room)
|
|
@@ -424,25 +616,18 @@ async def make_call(
|
|
|
424
616
|
token=jwt,
|
|
425
617
|
)
|
|
426
618
|
) as client:
|
|
427
|
-
requirements = []
|
|
428
|
-
|
|
429
|
-
for t in toolkit:
|
|
430
|
-
requirements.append(RequiredToolkit(name=t))
|
|
431
|
-
|
|
432
|
-
for t in schema:
|
|
433
|
-
requirements.append(RequiredSchema(name=t))
|
|
434
|
-
|
|
435
619
|
CustomChatbot = build_chatbot(
|
|
436
620
|
computer_use=computer_use,
|
|
621
|
+
require_computer_use=require_computer_use,
|
|
437
622
|
model=model,
|
|
438
|
-
local_shell=local_shell,
|
|
439
|
-
shell=shell,
|
|
440
|
-
apply_patch=apply_patch,
|
|
441
623
|
agent_name=agent_name,
|
|
442
624
|
rule=rule,
|
|
443
|
-
toolkit=toolkit,
|
|
444
|
-
schema=schema,
|
|
625
|
+
toolkit=require_toolkit + toolkit,
|
|
626
|
+
schema=require_schema + schema,
|
|
445
627
|
rules_file=rules_file,
|
|
628
|
+
local_shell=local_shell,
|
|
629
|
+
shell=shell,
|
|
630
|
+
apply_patch=apply_patch,
|
|
446
631
|
image_generation=image_generation,
|
|
447
632
|
web_search=web_search,
|
|
448
633
|
mcp=mcp,
|
|
@@ -454,8 +639,21 @@ async def make_call(
|
|
|
454
639
|
require_image_generation=require_image_generation,
|
|
455
640
|
require_mcp=require_mcp,
|
|
456
641
|
require_storage=require_storage,
|
|
642
|
+
require_table_read=require_table_read,
|
|
643
|
+
require_table_write=require_table_write,
|
|
644
|
+
require_read_only_storage=require_read_only_storage,
|
|
645
|
+
require_time=require_time,
|
|
646
|
+
require_uuid=require_uuid,
|
|
457
647
|
room_rules_path=room_rules,
|
|
648
|
+
require_document_authoring=require_document_authoring,
|
|
649
|
+
require_discovery=require_discovery,
|
|
458
650
|
working_directory=working_directory,
|
|
651
|
+
llm_participant=llm_participant,
|
|
652
|
+
always_reply=always_reply,
|
|
653
|
+
database_namespace=database_namespace,
|
|
654
|
+
skill_dirs=skill_dir,
|
|
655
|
+
shell_image=shell_image,
|
|
656
|
+
log_llm_requests=log_llm_requests,
|
|
459
657
|
)
|
|
460
658
|
|
|
461
659
|
bot = CustomChatbot()
|
|
@@ -488,17 +686,33 @@ async def service(
|
|
|
488
686
|
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
489
687
|
),
|
|
490
688
|
] = [],
|
|
689
|
+
require_toolkit: Annotated[
|
|
690
|
+
List[str],
|
|
691
|
+
typer.Option(
|
|
692
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
693
|
+
),
|
|
694
|
+
] = [],
|
|
695
|
+
require_schema: Annotated[
|
|
696
|
+
List[str],
|
|
697
|
+
typer.Option(
|
|
698
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
699
|
+
),
|
|
700
|
+
] = [],
|
|
491
701
|
toolkit: Annotated[
|
|
492
702
|
List[str],
|
|
493
|
-
typer.Option(
|
|
703
|
+
typer.Option(
|
|
704
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
705
|
+
),
|
|
494
706
|
] = [],
|
|
495
707
|
schema: Annotated[
|
|
496
708
|
List[str],
|
|
497
|
-
typer.Option(
|
|
709
|
+
typer.Option(
|
|
710
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
711
|
+
),
|
|
498
712
|
] = [],
|
|
499
713
|
model: Annotated[
|
|
500
714
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
501
|
-
] = "gpt-5.
|
|
715
|
+
] = "gpt-5.2",
|
|
502
716
|
image_generation: Annotated[
|
|
503
717
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
504
718
|
] = None,
|
|
@@ -527,7 +741,7 @@ async def service(
|
|
|
527
741
|
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
528
742
|
] = False,
|
|
529
743
|
require_image_generation: Annotated[
|
|
530
|
-
Optional[str], typer.Option(..., help="Name of an image gen model"
|
|
744
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
531
745
|
] = None,
|
|
532
746
|
require_computer_use: Annotated[
|
|
533
747
|
Optional[bool],
|
|
@@ -539,53 +753,133 @@ async def service(
|
|
|
539
753
|
] = False,
|
|
540
754
|
require_local_shell: Annotated[
|
|
541
755
|
Optional[bool],
|
|
542
|
-
typer.Option(..., help="Enable local shell tool calling"
|
|
756
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
543
757
|
] = False,
|
|
544
758
|
require_shell: Annotated[
|
|
545
759
|
Optional[bool],
|
|
546
|
-
typer.Option(..., help="Enable function shell tool calling"
|
|
760
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
547
761
|
] = False,
|
|
548
762
|
require_apply_patch: Annotated[
|
|
549
|
-
Optional[bool], typer.Option(..., help="Enable apply patch tool"
|
|
763
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
550
764
|
] = False,
|
|
551
765
|
require_web_search: Annotated[
|
|
552
766
|
Optional[bool],
|
|
553
|
-
typer.Option(..., help="Enable web search tool calling"
|
|
767
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
554
768
|
] = False,
|
|
555
769
|
require_mcp: Annotated[
|
|
556
|
-
Optional[bool], typer.Option(..., help="Enable mcp tool calling"
|
|
770
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
557
771
|
] = False,
|
|
558
772
|
require_storage: Annotated[
|
|
559
|
-
Optional[bool], typer.Option(..., help="Enable storage toolkit"
|
|
773
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
774
|
+
] = False,
|
|
775
|
+
database_namespace: Annotated[
|
|
776
|
+
Optional[str],
|
|
777
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
778
|
+
] = None,
|
|
779
|
+
require_table_read: Annotated[
|
|
780
|
+
list[str],
|
|
781
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
782
|
+
] = [],
|
|
783
|
+
require_table_write: Annotated[
|
|
784
|
+
list[str],
|
|
785
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
786
|
+
] = [],
|
|
787
|
+
require_read_only_storage: Annotated[
|
|
788
|
+
Optional[bool],
|
|
789
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
790
|
+
] = False,
|
|
791
|
+
require_time: Annotated[
|
|
792
|
+
bool,
|
|
793
|
+
typer.Option(
|
|
794
|
+
...,
|
|
795
|
+
help="Enable time/datetime tools",
|
|
796
|
+
),
|
|
797
|
+
] = True,
|
|
798
|
+
require_uuid: Annotated[
|
|
799
|
+
bool,
|
|
800
|
+
typer.Option(
|
|
801
|
+
...,
|
|
802
|
+
help="Enable UUID generation tools",
|
|
803
|
+
),
|
|
560
804
|
] = False,
|
|
561
805
|
working_directory: Annotated[
|
|
562
806
|
Optional[str],
|
|
563
807
|
typer.Option(..., help="The default working directory for shell commands"),
|
|
564
808
|
] = None,
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
809
|
+
require_document_authoring: Annotated[
|
|
810
|
+
Optional[bool],
|
|
811
|
+
typer.Option(..., help="Enable document authoring"),
|
|
812
|
+
] = False,
|
|
813
|
+
require_discovery: Annotated[
|
|
814
|
+
Optional[bool],
|
|
815
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
816
|
+
] = False,
|
|
817
|
+
llm_participant: Annotated[
|
|
818
|
+
Optional[str],
|
|
819
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
820
|
+
] = None,
|
|
821
|
+
host: Annotated[
|
|
822
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
823
|
+
] = None,
|
|
824
|
+
port: Annotated[
|
|
825
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
826
|
+
] = None,
|
|
827
|
+
path: Annotated[
|
|
828
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
829
|
+
] = None,
|
|
830
|
+
always_reply: Annotated[
|
|
831
|
+
Optional[bool],
|
|
832
|
+
typer.Option(..., help="Always reply"),
|
|
833
|
+
] = None,
|
|
834
|
+
skill_dir: Annotated[
|
|
835
|
+
list[str],
|
|
836
|
+
typer.Option(..., help="an agent skills directory"),
|
|
837
|
+
] = [],
|
|
838
|
+
shell_image: Annotated[
|
|
839
|
+
Optional[str],
|
|
840
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
841
|
+
] = None,
|
|
842
|
+
log_llm_requests: Annotated[
|
|
843
|
+
Optional[bool],
|
|
844
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
845
|
+
] = False,
|
|
568
846
|
):
|
|
569
|
-
|
|
847
|
+
if database_namespace is not None:
|
|
848
|
+
database_namespace = database_namespace.split("::")
|
|
849
|
+
|
|
850
|
+
service = get_service(host=host, port=port)
|
|
851
|
+
|
|
852
|
+
if path is None:
|
|
853
|
+
path = "/agent"
|
|
854
|
+
i = 0
|
|
855
|
+
while service.has_path(path):
|
|
856
|
+
i += 1
|
|
857
|
+
path = f"/agent{i}"
|
|
858
|
+
|
|
859
|
+
service.agents.append(
|
|
860
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
861
|
+
)
|
|
570
862
|
|
|
571
|
-
service = ServiceHost(host=host, port=port)
|
|
572
863
|
service.add_path(
|
|
864
|
+
identity=agent_name,
|
|
573
865
|
path=path,
|
|
574
866
|
cls=build_chatbot(
|
|
575
867
|
computer_use=computer_use,
|
|
868
|
+
require_computer_use=require_computer_use,
|
|
576
869
|
model=model,
|
|
577
870
|
local_shell=local_shell,
|
|
578
871
|
shell=shell,
|
|
579
872
|
apply_patch=apply_patch,
|
|
580
873
|
agent_name=agent_name,
|
|
581
874
|
rule=rule,
|
|
582
|
-
toolkit=toolkit,
|
|
583
|
-
schema=schema,
|
|
875
|
+
toolkit=require_toolkit + toolkit,
|
|
876
|
+
schema=require_schema + schema,
|
|
584
877
|
rules_file=rules_file,
|
|
585
878
|
web_search=web_search,
|
|
586
879
|
image_generation=image_generation,
|
|
587
880
|
mcp=mcp,
|
|
588
881
|
storage=storage,
|
|
882
|
+
database_namespace=database_namespace,
|
|
589
883
|
require_web_search=require_web_search,
|
|
590
884
|
require_shell=require_shell,
|
|
591
885
|
require_apply_patch=require_apply_patch,
|
|
@@ -593,9 +887,593 @@ async def service(
|
|
|
593
887
|
require_image_generation=require_image_generation,
|
|
594
888
|
require_mcp=require_mcp,
|
|
595
889
|
require_storage=require_storage,
|
|
890
|
+
require_table_write=require_table_write,
|
|
891
|
+
require_table_read=require_table_read,
|
|
892
|
+
require_read_only_storage=require_read_only_storage,
|
|
893
|
+
require_time=require_time,
|
|
894
|
+
require_uuid=require_uuid,
|
|
596
895
|
room_rules_path=room_rules,
|
|
597
896
|
working_directory=working_directory,
|
|
897
|
+
require_document_authoring=require_document_authoring,
|
|
898
|
+
require_discovery=require_discovery,
|
|
899
|
+
llm_participant=llm_participant,
|
|
900
|
+
always_reply=always_reply,
|
|
901
|
+
skill_dirs=skill_dir,
|
|
902
|
+
shell_image=shell_image,
|
|
903
|
+
log_llm_requests=log_llm_requests,
|
|
598
904
|
),
|
|
599
905
|
)
|
|
600
906
|
|
|
601
|
-
|
|
907
|
+
if not get_deferred():
|
|
908
|
+
await run_services()
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
@app.async_command("spec")
|
|
912
|
+
async def spec(
|
|
913
|
+
*,
|
|
914
|
+
service_name: Annotated[str, typer.Option("--service-name", help="service name")],
|
|
915
|
+
service_description: Annotated[
|
|
916
|
+
Optional[str], typer.Option("--service-description", help="service description")
|
|
917
|
+
] = None,
|
|
918
|
+
service_title: Annotated[
|
|
919
|
+
Optional[str],
|
|
920
|
+
typer.Option("--service-title", help="a display name for the service"),
|
|
921
|
+
] = None,
|
|
922
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
923
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
924
|
+
rules_file: Optional[str] = None,
|
|
925
|
+
room_rules: Annotated[
|
|
926
|
+
List[str],
|
|
927
|
+
typer.Option(
|
|
928
|
+
"--room-rules",
|
|
929
|
+
"-rr",
|
|
930
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
931
|
+
),
|
|
932
|
+
] = [],
|
|
933
|
+
require_toolkit: Annotated[
|
|
934
|
+
List[str],
|
|
935
|
+
typer.Option(
|
|
936
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
937
|
+
),
|
|
938
|
+
] = [],
|
|
939
|
+
require_schema: Annotated[
|
|
940
|
+
List[str],
|
|
941
|
+
typer.Option(
|
|
942
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
943
|
+
),
|
|
944
|
+
] = [],
|
|
945
|
+
toolkit: Annotated[
|
|
946
|
+
List[str],
|
|
947
|
+
typer.Option(
|
|
948
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
949
|
+
),
|
|
950
|
+
] = [],
|
|
951
|
+
schema: Annotated[
|
|
952
|
+
List[str],
|
|
953
|
+
typer.Option(
|
|
954
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
955
|
+
),
|
|
956
|
+
] = [],
|
|
957
|
+
model: Annotated[
|
|
958
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
959
|
+
] = "gpt-5.2",
|
|
960
|
+
image_generation: Annotated[
|
|
961
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
962
|
+
] = None,
|
|
963
|
+
local_shell: Annotated[
|
|
964
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
965
|
+
] = False,
|
|
966
|
+
shell: Annotated[
|
|
967
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
968
|
+
] = False,
|
|
969
|
+
apply_patch: Annotated[
|
|
970
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
971
|
+
] = False,
|
|
972
|
+
computer_use: Annotated[
|
|
973
|
+
Optional[bool],
|
|
974
|
+
typer.Option(
|
|
975
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
976
|
+
),
|
|
977
|
+
] = False,
|
|
978
|
+
web_search: Annotated[
|
|
979
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
980
|
+
] = False,
|
|
981
|
+
mcp: Annotated[
|
|
982
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
983
|
+
] = False,
|
|
984
|
+
storage: Annotated[
|
|
985
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
986
|
+
] = False,
|
|
987
|
+
require_image_generation: Annotated[
|
|
988
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
989
|
+
] = None,
|
|
990
|
+
require_computer_use: Annotated[
|
|
991
|
+
Optional[bool],
|
|
992
|
+
typer.Option(
|
|
993
|
+
...,
|
|
994
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
995
|
+
hidden=True,
|
|
996
|
+
),
|
|
997
|
+
] = False,
|
|
998
|
+
require_local_shell: Annotated[
|
|
999
|
+
Optional[bool],
|
|
1000
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
1001
|
+
] = False,
|
|
1002
|
+
require_shell: Annotated[
|
|
1003
|
+
Optional[bool],
|
|
1004
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
1005
|
+
] = False,
|
|
1006
|
+
require_apply_patch: Annotated[
|
|
1007
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1008
|
+
] = False,
|
|
1009
|
+
require_web_search: Annotated[
|
|
1010
|
+
Optional[bool],
|
|
1011
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
1012
|
+
] = False,
|
|
1013
|
+
require_mcp: Annotated[
|
|
1014
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1015
|
+
] = False,
|
|
1016
|
+
require_storage: Annotated[
|
|
1017
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1018
|
+
] = False,
|
|
1019
|
+
database_namespace: Annotated[
|
|
1020
|
+
Optional[str],
|
|
1021
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
1022
|
+
] = None,
|
|
1023
|
+
require_table_read: Annotated[
|
|
1024
|
+
list[str],
|
|
1025
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
1026
|
+
] = [],
|
|
1027
|
+
require_table_write: Annotated[
|
|
1028
|
+
list[str],
|
|
1029
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
1030
|
+
] = [],
|
|
1031
|
+
require_read_only_storage: Annotated[
|
|
1032
|
+
Optional[bool],
|
|
1033
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
1034
|
+
] = False,
|
|
1035
|
+
require_time: Annotated[
|
|
1036
|
+
bool,
|
|
1037
|
+
typer.Option(
|
|
1038
|
+
...,
|
|
1039
|
+
help="Enable time/datetime tools",
|
|
1040
|
+
),
|
|
1041
|
+
] = True,
|
|
1042
|
+
require_uuid: Annotated[
|
|
1043
|
+
bool,
|
|
1044
|
+
typer.Option(
|
|
1045
|
+
...,
|
|
1046
|
+
help="Enable UUID generation tools",
|
|
1047
|
+
),
|
|
1048
|
+
] = False,
|
|
1049
|
+
working_directory: Annotated[
|
|
1050
|
+
Optional[str],
|
|
1051
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
1052
|
+
] = None,
|
|
1053
|
+
require_document_authoring: Annotated[
|
|
1054
|
+
Optional[bool],
|
|
1055
|
+
typer.Option(..., help="Enable document authoring"),
|
|
1056
|
+
] = False,
|
|
1057
|
+
require_discovery: Annotated[
|
|
1058
|
+
Optional[bool],
|
|
1059
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
1060
|
+
] = False,
|
|
1061
|
+
llm_participant: Annotated[
|
|
1062
|
+
Optional[str],
|
|
1063
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
1064
|
+
] = None,
|
|
1065
|
+
host: Annotated[
|
|
1066
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
1067
|
+
] = None,
|
|
1068
|
+
port: Annotated[
|
|
1069
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
1070
|
+
] = None,
|
|
1071
|
+
path: Annotated[
|
|
1072
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
1073
|
+
] = None,
|
|
1074
|
+
always_reply: Annotated[
|
|
1075
|
+
Optional[bool],
|
|
1076
|
+
typer.Option(..., help="Always reply"),
|
|
1077
|
+
] = None,
|
|
1078
|
+
skill_dir: Annotated[
|
|
1079
|
+
list[str],
|
|
1080
|
+
typer.Option(..., help="an agent skills directory"),
|
|
1081
|
+
] = [],
|
|
1082
|
+
shell_image: Annotated[
|
|
1083
|
+
Optional[str],
|
|
1084
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
1085
|
+
] = None,
|
|
1086
|
+
log_llm_requests: Annotated[
|
|
1087
|
+
Optional[bool],
|
|
1088
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1089
|
+
] = False,
|
|
1090
|
+
):
|
|
1091
|
+
if database_namespace is not None:
|
|
1092
|
+
database_namespace = database_namespace.split("::")
|
|
1093
|
+
|
|
1094
|
+
service = get_service(host=host, port=port)
|
|
1095
|
+
|
|
1096
|
+
if path is None:
|
|
1097
|
+
path = "/agent"
|
|
1098
|
+
i = 0
|
|
1099
|
+
while service.has_path(path):
|
|
1100
|
+
i += 1
|
|
1101
|
+
path = f"/agent{i}"
|
|
1102
|
+
|
|
1103
|
+
service.agents.append(
|
|
1104
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
1105
|
+
)
|
|
1106
|
+
|
|
1107
|
+
service.add_path(
|
|
1108
|
+
identity=agent_name,
|
|
1109
|
+
path=path,
|
|
1110
|
+
cls=build_chatbot(
|
|
1111
|
+
computer_use=computer_use,
|
|
1112
|
+
require_computer_use=require_computer_use,
|
|
1113
|
+
model=model,
|
|
1114
|
+
local_shell=local_shell,
|
|
1115
|
+
shell=shell,
|
|
1116
|
+
apply_patch=apply_patch,
|
|
1117
|
+
agent_name=agent_name,
|
|
1118
|
+
rule=rule,
|
|
1119
|
+
toolkit=require_toolkit + toolkit,
|
|
1120
|
+
schema=require_schema + schema,
|
|
1121
|
+
rules_file=rules_file,
|
|
1122
|
+
web_search=web_search,
|
|
1123
|
+
image_generation=image_generation,
|
|
1124
|
+
mcp=mcp,
|
|
1125
|
+
storage=storage,
|
|
1126
|
+
database_namespace=database_namespace,
|
|
1127
|
+
require_web_search=require_web_search,
|
|
1128
|
+
require_shell=require_shell,
|
|
1129
|
+
require_apply_patch=require_apply_patch,
|
|
1130
|
+
require_local_shell=require_local_shell,
|
|
1131
|
+
require_image_generation=require_image_generation,
|
|
1132
|
+
require_mcp=require_mcp,
|
|
1133
|
+
require_storage=require_storage,
|
|
1134
|
+
require_table_write=require_table_write,
|
|
1135
|
+
require_table_read=require_table_read,
|
|
1136
|
+
require_read_only_storage=require_read_only_storage,
|
|
1137
|
+
require_time=require_time,
|
|
1138
|
+
require_uuid=require_uuid,
|
|
1139
|
+
room_rules_path=room_rules,
|
|
1140
|
+
working_directory=working_directory,
|
|
1141
|
+
require_document_authoring=require_document_authoring,
|
|
1142
|
+
require_discovery=require_discovery,
|
|
1143
|
+
llm_participant=llm_participant,
|
|
1144
|
+
always_reply=always_reply,
|
|
1145
|
+
skill_dirs=skill_dir,
|
|
1146
|
+
shell_image=shell_image,
|
|
1147
|
+
log_llm_requests=log_llm_requests,
|
|
1148
|
+
),
|
|
1149
|
+
)
|
|
1150
|
+
|
|
1151
|
+
spec = service_specs()[0]
|
|
1152
|
+
spec.metadata.annotations = {
|
|
1153
|
+
"meshagent.service.id": service_name,
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
spec.metadata.name = service_name
|
|
1157
|
+
spec.metadata.description = service_description
|
|
1158
|
+
spec.container.image = (
|
|
1159
|
+
"us-central1-docker.pkg.dev/meshagent-public/images/cli:{SERVER_VERSION}-esgz"
|
|
1160
|
+
)
|
|
1161
|
+
spec.container.command = shlex.join(
|
|
1162
|
+
["meshagent", "chatbot", "service", *cleanup_args(sys.argv[2:])]
|
|
1163
|
+
)
|
|
1164
|
+
|
|
1165
|
+
print(yaml.dump(spec.model_dump(mode="json", exclude_none=True), sort_keys=False))
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
@app.async_command("deploy")
|
|
1169
|
+
async def deploy(
|
|
1170
|
+
*,
|
|
1171
|
+
service_name: Annotated[str, typer.Option("--service-name", help="service name")],
|
|
1172
|
+
service_description: Annotated[
|
|
1173
|
+
Optional[str], typer.Option("--service-description", help="service description")
|
|
1174
|
+
] = None,
|
|
1175
|
+
service_title: Annotated[
|
|
1176
|
+
Optional[str],
|
|
1177
|
+
typer.Option("--service-title", help="a display name for the service"),
|
|
1178
|
+
] = None,
|
|
1179
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
1180
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
1181
|
+
rules_file: Optional[str] = None,
|
|
1182
|
+
room_rules: Annotated[
|
|
1183
|
+
List[str],
|
|
1184
|
+
typer.Option(
|
|
1185
|
+
"--room-rules",
|
|
1186
|
+
"-rr",
|
|
1187
|
+
help="a path to a rules file within the room that can be used to customize the agent's behavior",
|
|
1188
|
+
),
|
|
1189
|
+
] = [],
|
|
1190
|
+
require_toolkit: Annotated[
|
|
1191
|
+
List[str],
|
|
1192
|
+
typer.Option(
|
|
1193
|
+
"--require-toolkit", "-rt", help="the name or url of a required toolkit"
|
|
1194
|
+
),
|
|
1195
|
+
] = [],
|
|
1196
|
+
require_schema: Annotated[
|
|
1197
|
+
List[str],
|
|
1198
|
+
typer.Option(
|
|
1199
|
+
"--require-schema", "-rs", help="the name or url of a required schema"
|
|
1200
|
+
),
|
|
1201
|
+
] = [],
|
|
1202
|
+
toolkit: Annotated[
|
|
1203
|
+
List[str],
|
|
1204
|
+
typer.Option(
|
|
1205
|
+
"--toolkit", "-t", help="the name or url of a required toolkit", hidden=True
|
|
1206
|
+
),
|
|
1207
|
+
] = [],
|
|
1208
|
+
schema: Annotated[
|
|
1209
|
+
List[str],
|
|
1210
|
+
typer.Option(
|
|
1211
|
+
"--schema", "-s", help="the name or url of a required schema", hidden=True
|
|
1212
|
+
),
|
|
1213
|
+
] = [],
|
|
1214
|
+
model: Annotated[
|
|
1215
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
1216
|
+
] = "gpt-5.2",
|
|
1217
|
+
image_generation: Annotated[
|
|
1218
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1219
|
+
] = None,
|
|
1220
|
+
local_shell: Annotated[
|
|
1221
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
1222
|
+
] = False,
|
|
1223
|
+
shell: Annotated[
|
|
1224
|
+
Optional[bool], typer.Option(..., help="Enable function shell tool calling")
|
|
1225
|
+
] = False,
|
|
1226
|
+
apply_patch: Annotated[
|
|
1227
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1228
|
+
] = False,
|
|
1229
|
+
computer_use: Annotated[
|
|
1230
|
+
Optional[bool],
|
|
1231
|
+
typer.Option(
|
|
1232
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
1233
|
+
),
|
|
1234
|
+
] = False,
|
|
1235
|
+
web_search: Annotated[
|
|
1236
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
1237
|
+
] = False,
|
|
1238
|
+
mcp: Annotated[
|
|
1239
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1240
|
+
] = False,
|
|
1241
|
+
storage: Annotated[
|
|
1242
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1243
|
+
] = False,
|
|
1244
|
+
require_image_generation: Annotated[
|
|
1245
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
1246
|
+
] = None,
|
|
1247
|
+
require_computer_use: Annotated[
|
|
1248
|
+
Optional[bool],
|
|
1249
|
+
typer.Option(
|
|
1250
|
+
...,
|
|
1251
|
+
help="Enable computer use (requires computer-use-preview model)",
|
|
1252
|
+
hidden=True,
|
|
1253
|
+
),
|
|
1254
|
+
] = False,
|
|
1255
|
+
require_local_shell: Annotated[
|
|
1256
|
+
Optional[bool],
|
|
1257
|
+
typer.Option(..., help="Enable local shell tool calling"),
|
|
1258
|
+
] = False,
|
|
1259
|
+
require_shell: Annotated[
|
|
1260
|
+
Optional[bool],
|
|
1261
|
+
typer.Option(..., help="Enable function shell tool calling"),
|
|
1262
|
+
] = False,
|
|
1263
|
+
require_apply_patch: Annotated[
|
|
1264
|
+
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
1265
|
+
] = False,
|
|
1266
|
+
require_web_search: Annotated[
|
|
1267
|
+
Optional[bool],
|
|
1268
|
+
typer.Option(..., help="Enable web search tool calling"),
|
|
1269
|
+
] = False,
|
|
1270
|
+
require_mcp: Annotated[
|
|
1271
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
1272
|
+
] = False,
|
|
1273
|
+
require_storage: Annotated[
|
|
1274
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
1275
|
+
] = False,
|
|
1276
|
+
database_namespace: Annotated[
|
|
1277
|
+
Optional[str],
|
|
1278
|
+
typer.Option(..., help="Use a specific database namespace"),
|
|
1279
|
+
] = None,
|
|
1280
|
+
require_table_read: Annotated[
|
|
1281
|
+
list[str],
|
|
1282
|
+
typer.Option(..., help="Enable table read tools for a specific table"),
|
|
1283
|
+
] = [],
|
|
1284
|
+
require_table_write: Annotated[
|
|
1285
|
+
list[str],
|
|
1286
|
+
typer.Option(..., help="Enable table write tools for a specific table"),
|
|
1287
|
+
] = [],
|
|
1288
|
+
require_read_only_storage: Annotated[
|
|
1289
|
+
Optional[bool],
|
|
1290
|
+
typer.Option(..., help="Enable read only storage toolkit"),
|
|
1291
|
+
] = False,
|
|
1292
|
+
require_time: Annotated[
|
|
1293
|
+
bool,
|
|
1294
|
+
typer.Option(
|
|
1295
|
+
...,
|
|
1296
|
+
help="Enable time/datetime tools",
|
|
1297
|
+
),
|
|
1298
|
+
] = True,
|
|
1299
|
+
require_uuid: Annotated[
|
|
1300
|
+
bool,
|
|
1301
|
+
typer.Option(
|
|
1302
|
+
...,
|
|
1303
|
+
help="Enable UUID generation tools",
|
|
1304
|
+
),
|
|
1305
|
+
] = False,
|
|
1306
|
+
working_directory: Annotated[
|
|
1307
|
+
Optional[str],
|
|
1308
|
+
typer.Option(..., help="The default working directory for shell commands"),
|
|
1309
|
+
] = None,
|
|
1310
|
+
require_document_authoring: Annotated[
|
|
1311
|
+
Optional[bool],
|
|
1312
|
+
typer.Option(..., help="Enable document authoring"),
|
|
1313
|
+
] = False,
|
|
1314
|
+
require_discovery: Annotated[
|
|
1315
|
+
Optional[bool],
|
|
1316
|
+
typer.Option(..., help="Enable discovery of agents and tools"),
|
|
1317
|
+
] = False,
|
|
1318
|
+
llm_participant: Annotated[
|
|
1319
|
+
Optional[str],
|
|
1320
|
+
typer.Option(..., help="Delegate LLM interactions to a remote participant"),
|
|
1321
|
+
] = None,
|
|
1322
|
+
host: Annotated[
|
|
1323
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
1324
|
+
] = None,
|
|
1325
|
+
port: Annotated[
|
|
1326
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
1327
|
+
] = None,
|
|
1328
|
+
path: Annotated[
|
|
1329
|
+
Optional[str], typer.Option(help="HTTP path to mount the service at")
|
|
1330
|
+
] = None,
|
|
1331
|
+
always_reply: Annotated[
|
|
1332
|
+
Optional[bool],
|
|
1333
|
+
typer.Option(..., help="Always reply"),
|
|
1334
|
+
] = None,
|
|
1335
|
+
skill_dir: Annotated[
|
|
1336
|
+
list[str],
|
|
1337
|
+
typer.Option(..., help="an agent skills directory"),
|
|
1338
|
+
] = [],
|
|
1339
|
+
shell_image: Annotated[
|
|
1340
|
+
Optional[str],
|
|
1341
|
+
typer.Option(..., help="an image tag to use to run shell commands in"),
|
|
1342
|
+
] = None,
|
|
1343
|
+
log_llm_requests: Annotated[
|
|
1344
|
+
Optional[bool],
|
|
1345
|
+
typer.Option(..., help="log all requests to the llm"),
|
|
1346
|
+
] = False,
|
|
1347
|
+
project_id: ProjectIdOption,
|
|
1348
|
+
room: Annotated[
|
|
1349
|
+
Optional[str],
|
|
1350
|
+
typer.Option("--room", help="The name of a room to create the service for"),
|
|
1351
|
+
] = None,
|
|
1352
|
+
):
|
|
1353
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
1354
|
+
|
|
1355
|
+
if database_namespace is not None:
|
|
1356
|
+
database_namespace = database_namespace.split("::")
|
|
1357
|
+
|
|
1358
|
+
service = get_service(host=host, port=port)
|
|
1359
|
+
|
|
1360
|
+
if path is None:
|
|
1361
|
+
path = "/agent"
|
|
1362
|
+
i = 0
|
|
1363
|
+
while service.has_path(path):
|
|
1364
|
+
i += 1
|
|
1365
|
+
path = f"/agent{i}"
|
|
1366
|
+
|
|
1367
|
+
service.agents.append(
|
|
1368
|
+
AgentSpec(name=agent_name, annotations={ANNOTATION_AGENT_TYPE: "ChatBot"})
|
|
1369
|
+
)
|
|
1370
|
+
|
|
1371
|
+
service.add_path(
|
|
1372
|
+
identity=agent_name,
|
|
1373
|
+
path=path,
|
|
1374
|
+
cls=build_chatbot(
|
|
1375
|
+
computer_use=computer_use,
|
|
1376
|
+
require_computer_use=require_computer_use,
|
|
1377
|
+
model=model,
|
|
1378
|
+
local_shell=local_shell,
|
|
1379
|
+
shell=shell,
|
|
1380
|
+
apply_patch=apply_patch,
|
|
1381
|
+
agent_name=agent_name,
|
|
1382
|
+
rule=rule,
|
|
1383
|
+
toolkit=require_toolkit + toolkit,
|
|
1384
|
+
schema=require_schema + schema,
|
|
1385
|
+
rules_file=rules_file,
|
|
1386
|
+
web_search=web_search,
|
|
1387
|
+
image_generation=image_generation,
|
|
1388
|
+
mcp=mcp,
|
|
1389
|
+
storage=storage,
|
|
1390
|
+
database_namespace=database_namespace,
|
|
1391
|
+
require_web_search=require_web_search,
|
|
1392
|
+
require_shell=require_shell,
|
|
1393
|
+
require_apply_patch=require_apply_patch,
|
|
1394
|
+
require_local_shell=require_local_shell,
|
|
1395
|
+
require_image_generation=require_image_generation,
|
|
1396
|
+
require_mcp=require_mcp,
|
|
1397
|
+
require_storage=require_storage,
|
|
1398
|
+
require_table_write=require_table_write,
|
|
1399
|
+
require_table_read=require_table_read,
|
|
1400
|
+
require_read_only_storage=require_read_only_storage,
|
|
1401
|
+
require_time=require_time,
|
|
1402
|
+
require_uuid=require_uuid,
|
|
1403
|
+
room_rules_path=room_rules,
|
|
1404
|
+
working_directory=working_directory,
|
|
1405
|
+
require_document_authoring=require_document_authoring,
|
|
1406
|
+
require_discovery=require_discovery,
|
|
1407
|
+
llm_participant=llm_participant,
|
|
1408
|
+
always_reply=always_reply,
|
|
1409
|
+
skill_dirs=skill_dir,
|
|
1410
|
+
shell_image=shell_image,
|
|
1411
|
+
log_llm_requests=log_llm_requests,
|
|
1412
|
+
),
|
|
1413
|
+
)
|
|
1414
|
+
|
|
1415
|
+
spec = service_specs()[0]
|
|
1416
|
+
|
|
1417
|
+
spec.metadata.annotations = {
|
|
1418
|
+
"meshagent.service.id": service_name,
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
spec.metadata.name = service_name
|
|
1422
|
+
spec.metadata.description = service_description
|
|
1423
|
+
spec.container.image = (
|
|
1424
|
+
"us-central1-docker.pkg.dev/meshagent-public/images/cli:{SERVER_VERSION}-esgz"
|
|
1425
|
+
)
|
|
1426
|
+
spec.container.command = shlex.join(
|
|
1427
|
+
["meshagent", "chatbot", "service", *cleanup_args(sys.argv[2:])]
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
project_id = await resolve_project_id(project_id)
|
|
1431
|
+
|
|
1432
|
+
client = await get_client()
|
|
1433
|
+
try:
|
|
1434
|
+
id = None
|
|
1435
|
+
try:
|
|
1436
|
+
if id is None:
|
|
1437
|
+
if room is None:
|
|
1438
|
+
services = await client.list_services(project_id=project_id)
|
|
1439
|
+
else:
|
|
1440
|
+
services = await client.list_room_services(
|
|
1441
|
+
project_id=project_id, room_name=room
|
|
1442
|
+
)
|
|
1443
|
+
|
|
1444
|
+
for s in services:
|
|
1445
|
+
if s.metadata.name == spec.metadata.name:
|
|
1446
|
+
id = s.id
|
|
1447
|
+
|
|
1448
|
+
if id is None:
|
|
1449
|
+
if room is None:
|
|
1450
|
+
id = await client.create_service(
|
|
1451
|
+
project_id=project_id, service=spec
|
|
1452
|
+
)
|
|
1453
|
+
else:
|
|
1454
|
+
id = await client.create_room_service(
|
|
1455
|
+
project_id=project_id, service=spec, room_name=room
|
|
1456
|
+
)
|
|
1457
|
+
|
|
1458
|
+
else:
|
|
1459
|
+
spec.id = id
|
|
1460
|
+
if room is None:
|
|
1461
|
+
await client.update_service(
|
|
1462
|
+
project_id=project_id, service_id=id, service=spec
|
|
1463
|
+
)
|
|
1464
|
+
else:
|
|
1465
|
+
await client.update_room_service(
|
|
1466
|
+
project_id=project_id,
|
|
1467
|
+
service_id=id,
|
|
1468
|
+
service=spec,
|
|
1469
|
+
room_name=room,
|
|
1470
|
+
)
|
|
1471
|
+
|
|
1472
|
+
except ConflictError:
|
|
1473
|
+
print(f"[red]Service name already in use: {spec.metadata.name}[/red]")
|
|
1474
|
+
raise typer.Exit(code=1)
|
|
1475
|
+
else:
|
|
1476
|
+
print(f"[green]Deployed service:[/] {id}")
|
|
1477
|
+
|
|
1478
|
+
finally:
|
|
1479
|
+
await client.close()
|