mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-22 19:47:28 +00:00
Merge pull request #14 from eigent-ai/feat/remote-sub-agent
move default value
This commit is contained in:
commit
027d6f57df
20 changed files with 190 additions and 51 deletions
|
|
@ -31,7 +31,7 @@ from app.remote_sub_agent.types import (
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
_DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
|
||||
_DEFAULT_AGENT = "waverunner"
|
||||
_DEFAULT_AGENT = ""
|
||||
_TERMINAL_SUCCESS_STATUSES = {"completed"}
|
||||
_TERMINAL_FAILURE_STATUSES = {"failed", "cancelled", "expired", "incomplete"}
|
||||
_UNSUPPORTED_ACTION_STATUSES = {"requires_action"}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ async def test_validate_remote_sub_agent_rejects_missing_fields():
|
|||
provider="gemini_agents",
|
||||
api_key="",
|
||||
base_url="https://example.test/v1beta",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ async def test_validate_remote_sub_agent_success(monkeypatch):
|
|||
provider="gemini_agents",
|
||||
api_key=" test-key ",
|
||||
base_url=" https://example.test/v1beta ",
|
||||
agent_name=" waverunner ",
|
||||
agent_name=" antigravity-preview-05-2026 ",
|
||||
timeout_seconds=12,
|
||||
)
|
||||
)
|
||||
|
|
@ -76,7 +76,7 @@ async def test_validate_remote_sub_agent_success(monkeypatch):
|
|||
"gemini_agents": {
|
||||
"api_key": "test-key",
|
||||
"base_url": "https://example.test/v1beta",
|
||||
"agent_name": "waverunner",
|
||||
"agent_name": "antigravity-preview-05-2026",
|
||||
},
|
||||
}
|
||||
assert seen["timeout"] == 12
|
||||
|
|
@ -98,7 +98,7 @@ async def test_validate_remote_sub_agent_failure(monkeypatch):
|
|||
provider="gemini_agents",
|
||||
api_key="bad-key",
|
||||
base_url="https://example.test/v1beta",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ async def test_provider_posts_agent_interaction():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"environment_id": "env-1",
|
||||
"status": "completed",
|
||||
"outputs": [{"type": "text", "text": "done"}],
|
||||
|
|
@ -58,7 +58,7 @@ async def test_provider_posts_agent_interaction():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -77,7 +77,7 @@ async def test_provider_posts_agent_interaction():
|
|||
|
||||
body = seen["body"]
|
||||
assert isinstance(body, dict)
|
||||
assert body["agent"] == "waverunner"
|
||||
assert body["agent"] == "antigravity-preview-05-2026"
|
||||
assert body["input"] == [{"type": "text", "text": "research this"}]
|
||||
assert body["stream"] is False
|
||||
assert body["environment"] == {"enabled": True}
|
||||
|
|
@ -102,7 +102,7 @@ async def test_provider_validation_posts_background_probe():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-validation",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"environment_id": "env-validation",
|
||||
"status": "in_progress",
|
||||
},
|
||||
|
|
@ -110,7 +110,7 @@ async def test_provider_validation_posts_background_probe():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -119,7 +119,7 @@ async def test_provider_validation_posts_background_probe():
|
|||
|
||||
body = seen["body"]
|
||||
assert isinstance(body, dict)
|
||||
assert body["agent"] == "waverunner"
|
||||
assert body["agent"] == "antigravity-preview-05-2026"
|
||||
assert body["stream"] is False
|
||||
assert body["background"] is True
|
||||
assert body["environment"] == {"enabled": True}
|
||||
|
|
@ -148,14 +148,14 @@ async def test_provider_validation_falls_back_without_background():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-validation",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "completed",
|
||||
},
|
||||
)
|
||||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -178,7 +178,7 @@ async def test_provider_uses_configured_agent_over_display_name():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "completed",
|
||||
"outputs": [{"type": "text", "text": "done"}],
|
||||
},
|
||||
|
|
@ -186,7 +186,7 @@ async def test_provider_uses_configured_agent_over_display_name():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -205,7 +205,7 @@ async def test_provider_uses_configured_agent_over_display_name():
|
|||
|
||||
body = seen["body"]
|
||||
assert isinstance(body, dict)
|
||||
assert body["agent"] == "waverunner"
|
||||
assert body["agent"] == "antigravity-preview-05-2026"
|
||||
assert events[-1].content == "done"
|
||||
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ async def test_provider_concatenates_chunked_outputs_without_extra_newlines():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "completed",
|
||||
"outputs": [
|
||||
{"type": "text", "text": "sha256sum orders"},
|
||||
|
|
@ -229,7 +229,7 @@ async def test_provider_concatenates_chunked_outputs_without_extra_newlines():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -257,7 +257,7 @@ async def test_provider_merges_system_instruction_for_agent():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "completed",
|
||||
"outputs": [{"type": "text", "text": "done"}],
|
||||
},
|
||||
|
|
@ -265,7 +265,7 @@ async def test_provider_merges_system_instruction_for_agent():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
transport=httpx.MockTransport(handler),
|
||||
)
|
||||
|
|
@ -302,7 +302,7 @@ async def test_provider_polls_background_agent_until_completed():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "in_progress",
|
||||
},
|
||||
)
|
||||
|
|
@ -310,7 +310,7 @@ async def test_provider_polls_background_agent_until_completed():
|
|||
200,
|
||||
json={
|
||||
"id": "interaction-1",
|
||||
"agent": "waverunner",
|
||||
"agent": "antigravity-preview-05-2026",
|
||||
"status": "completed",
|
||||
"outputs": [{"type": "text", "text": "done"}],
|
||||
"usage": {"total_tokens": 42},
|
||||
|
|
@ -319,7 +319,7 @@ async def test_provider_polls_background_agent_until_completed():
|
|||
|
||||
provider = GeminiAgentsProvider(
|
||||
api_key="test-key",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
base_url="https://example.test/v1beta",
|
||||
poll_interval_seconds=0,
|
||||
transport=httpx.MockTransport(handler),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ def _config() -> dict:
|
|||
"gemini_agents": {
|
||||
"api_key": "test-key",
|
||||
"base_url": "https://example.test/v1beta",
|
||||
"agent_name": "waverunner",
|
||||
"agent_name": "antigravity-preview-05-2026",
|
||||
"max_wall_time_seconds": 900,
|
||||
"poll_interval_seconds": 7,
|
||||
},
|
||||
|
|
@ -62,7 +62,7 @@ def test_registry_builds_gemini_provider_from_provider_config():
|
|||
assert provider.name == "gemini_agents"
|
||||
assert provider.api_key == "test-key"
|
||||
assert provider.base_url == "https://example.test/v1beta"
|
||||
assert provider.agent_name == "waverunner"
|
||||
assert provider.agent_name == "antigravity-preview-05-2026"
|
||||
assert provider.poll_interval_seconds == 7
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ def _valid_config() -> dict:
|
|||
"gemini_agents": {
|
||||
"api_key": "test-key",
|
||||
"base_url": "https://generativelanguage.googleapis.com/v1beta",
|
||||
"agent_name": "waverunner",
|
||||
"agent_name": "antigravity-preview-05-2026",
|
||||
"max_wall_time_seconds": 900,
|
||||
"poll_interval_seconds": 5,
|
||||
},
|
||||
|
|
@ -58,7 +58,7 @@ async def test_toolkit_returns_message_when_config_is_incomplete():
|
|||
"gemini_agents": {
|
||||
"api_key": "",
|
||||
"base_url": "https://generativelanguage.googleapis.com/v1beta",
|
||||
"agent_name": "waverunner",
|
||||
"agent_name": "antigravity-preview-05-2026",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,15 +44,18 @@ class RemoteSubAgentProviderIn(BaseModel):
|
|||
config: dict | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_enabled_config(self):
|
||||
if self.enabled and (
|
||||
def validate_provider_config(self):
|
||||
if not self.provider_name.strip():
|
||||
raise ValueError("Remote sub agent provider requires provider_name.")
|
||||
|
||||
if (
|
||||
not self.api_key.strip()
|
||||
or not self.endpoint_url.strip()
|
||||
or not self.agent_name.strip()
|
||||
):
|
||||
raise ValueError(
|
||||
"Enabled remote sub agent provider requires api_key, "
|
||||
"endpoint_url, and agent_name."
|
||||
"Remote sub agent provider requires api_key, endpoint_url, "
|
||||
"and agent_name."
|
||||
)
|
||||
return self
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,24 @@ from app.model.remote_sub_agent.provider import RemoteSubAgentProviderIn
|
|||
|
||||
|
||||
class TestRemoteSubAgentProviderSchema:
|
||||
def test_disabled_provider_allows_incomplete_credentials(self):
|
||||
def test_disabled_provider_requires_credentials(self):
|
||||
with pytest.raises(ValidationError):
|
||||
RemoteSubAgentProviderIn(
|
||||
provider_name="gemini_agents",
|
||||
enabled=False,
|
||||
)
|
||||
|
||||
def test_disabled_provider_accepts_agent_configuration(self):
|
||||
config = RemoteSubAgentProviderIn(
|
||||
provider_name="gemini_agents",
|
||||
enabled=False,
|
||||
api_key="test-key",
|
||||
endpoint_url="https://generativelanguage.googleapis.com/v1beta",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
config={
|
||||
"max_wall_time_seconds": 900,
|
||||
"poll_interval_seconds": 5,
|
||||
},
|
||||
)
|
||||
|
||||
assert config.provider_name == "gemini_agents"
|
||||
|
|
@ -47,7 +61,7 @@ class TestRemoteSubAgentProviderSchema:
|
|||
enabled=True,
|
||||
api_key="test-key",
|
||||
endpoint_url="https://generativelanguage.googleapis.com/v1beta",
|
||||
agent_name="waverunner",
|
||||
agent_name="antigravity-preview-05-2026",
|
||||
config={
|
||||
"max_wall_time_seconds": 900,
|
||||
"poll_interval_seconds": 5,
|
||||
|
|
|
|||
|
|
@ -178,6 +178,15 @@
|
|||
"models-default-setting-title": "الإعداد الافتراضي",
|
||||
"models-default-setting-description": "اختر أحد النماذج المكوّنة ليكون النموذج الافتراضي لـ Eigent، وسيتم تطبيقه عالميًا عبر مساحة العمل الخاصة بك.",
|
||||
"models-configuration": "التكوين",
|
||||
"sub-agents": "الوكلاء الفرعيون",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "فوّض المهام المناسبة إلى صندوق عزل مُدار لوكيل بعيد.",
|
||||
"agent-provider": "موفّر الوكيل",
|
||||
"agent-id": "معرّف الوكيل",
|
||||
"max-wall-time-seconds": "الحد الأقصى لوقت التشغيل (بالثواني)",
|
||||
"poll-interval-seconds": "فاصل الاستعلام (بالثواني)",
|
||||
"remote-sub-agent-required-fields": "API Key و API Host و Agent ID مطلوبة عند تفعيل Sub Agent.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -238,6 +238,15 @@
|
|||
"models-default-setting-title": "Standard-Einstellung",
|
||||
"models-default-setting-description": "Wähle eines deiner konfigurierten Modelle als Standardmodell für Eigent. Es wird global in deinem Arbeitsbereich angewendet.",
|
||||
"models-configuration": "Konfiguration",
|
||||
"sub-agents": "Sub-Agents",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Delegiere geeignete Aufgaben an eine verwaltete Remote-Agent-Sandbox.",
|
||||
"agent-provider": "Agent-Anbieter",
|
||||
"agent-id": "Agent-ID",
|
||||
"max-wall-time-seconds": "Max. Laufzeit (Sekunden)",
|
||||
"poll-interval-seconds": "Abfrageintervall (Sekunden)",
|
||||
"remote-sub-agent-required-fields": "API-Schlüssel, API-Host und Agent-ID sind erforderlich, wenn Sub Agent aktiviert ist.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@
|
|||
"sub-agents": "Sub Agents",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Delegate suitable tasks to a managed Waverunner-compatible remote agent sandbox.",
|
||||
"remote-sub-agent-description": "Delegate suitable tasks to a managed remote agent sandbox.",
|
||||
"agent-provider": "Agent Provider",
|
||||
"agent-id": "Agent ID",
|
||||
"max-wall-time-seconds": "Max Wall Time (Seconds)",
|
||||
|
|
|
|||
|
|
@ -238,6 +238,15 @@
|
|||
"models-default-setting-title": "Configuración predeterminada",
|
||||
"models-default-setting-description": "Elige uno de tus modelos configurados como modelo predeterminado para Eigent. Se aplicará globalmente en tu espacio de trabajo.",
|
||||
"models-configuration": "Configuración",
|
||||
"sub-agents": "Subagentes",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Delega tareas adecuadas a un sandbox de agente remoto administrado.",
|
||||
"agent-provider": "Proveedor de agente",
|
||||
"agent-id": "ID de agente",
|
||||
"max-wall-time-seconds": "Tiempo máximo de ejecución (segundos)",
|
||||
"poll-interval-seconds": "Intervalo de sondeo (segundos)",
|
||||
"remote-sub-agent-required-fields": "API Key, API Host y Agent ID son obligatorios cuando Sub Agent está habilitado.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -221,6 +221,15 @@
|
|||
"models-default-setting-title": "Paramètre par défaut",
|
||||
"models-default-setting-description": "Choisissez l'un de vos modèles configurés comme modèle par défaut pour Eigent. Il sera appliqué globalement dans votre espace de travail.",
|
||||
"models-configuration": "Configuration",
|
||||
"sub-agents": "Sous-agents",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Déléguez les tâches adaptées à un bac à sable d'agent distant géré.",
|
||||
"agent-provider": "Fournisseur d'agent",
|
||||
"agent-id": "ID de l'agent",
|
||||
"max-wall-time-seconds": "Temps d'exécution maximal (secondes)",
|
||||
"poll-interval-seconds": "Intervalle d'interrogation (secondes)",
|
||||
"remote-sub-agent-required-fields": "La clé API, l'hôte API et l'ID de l'agent sont requis lorsque Sub Agent est activé.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -238,6 +238,15 @@
|
|||
"models-default-setting-title": "Impostazione predefinita",
|
||||
"models-default-setting-description": "Seleziona uno dei modelli configurati come modello predefinito per Eigent. Verrà applicato globalmente nel tuo spazio di lavoro.",
|
||||
"models-configuration": "Configurazione",
|
||||
"sub-agents": "Sub-agent",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Delega le attività adatte a una sandbox di agent remoto gestita.",
|
||||
"agent-provider": "Provider agent",
|
||||
"agent-id": "ID agent",
|
||||
"max-wall-time-seconds": "Tempo massimo di esecuzione (secondi)",
|
||||
"poll-interval-seconds": "Intervallo di polling (secondi)",
|
||||
"remote-sub-agent-required-fields": "API Key, API Host e Agent ID sono obbligatori quando Sub Agent è abilitato.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -239,6 +239,15 @@
|
|||
"models-default-setting-title": "デフォルト設定",
|
||||
"models-default-setting-description": "設定済みモデルの中から、Eigent のデフォルトモデルを1つ選択します。ワークスペース全体にグローバルに適用されます。",
|
||||
"models-configuration": "構成",
|
||||
"sub-agents": "サブエージェント",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "適したタスクを管理されたリモートエージェントのサンドボックスに委任します。",
|
||||
"agent-provider": "エージェントプロバイダー",
|
||||
"agent-id": "エージェント ID",
|
||||
"max-wall-time-seconds": "最大実行時間(秒)",
|
||||
"poll-interval-seconds": "ポーリング間隔(秒)",
|
||||
"remote-sub-agent-required-fields": "Sub Agent を有効にするには、API Key、API Host、Agent ID が必要です。",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -239,6 +239,15 @@
|
|||
"models-default-setting-title": "기본 설정",
|
||||
"models-default-setting-description": "구성된 모델 중 하나를 Eigent의 기본 모델로 선택하세요. 워크스페이스 전체에 전역으로 적용됩니다.",
|
||||
"models-configuration": "구성",
|
||||
"sub-agents": "서브 에이전트",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "적합한 작업을 관리형 원격 에이전트 샌드박스에 위임합니다.",
|
||||
"agent-provider": "에이전트 제공자",
|
||||
"agent-id": "에이전트 ID",
|
||||
"max-wall-time-seconds": "최대 실행 시간(초)",
|
||||
"poll-interval-seconds": "폴링 간격(초)",
|
||||
"remote-sub-agent-required-fields": "Sub Agent를 활성화하려면 API Key, API Host, Agent ID가 필요합니다.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -238,6 +238,15 @@
|
|||
"models-default-setting-title": "Настройка по умолчанию",
|
||||
"models-default-setting-description": "Выберите одну из настроенных моделей как модель по умолчанию для Eigent. Она будет применяться глобально во всём рабочем пространстве.",
|
||||
"models-configuration": "Конфигурация",
|
||||
"sub-agents": "Суб-агенты",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "Делегируйте подходящие задачи управляемой песочнице удалённого агента.",
|
||||
"agent-provider": "Поставщик агента",
|
||||
"agent-id": "ID агента",
|
||||
"max-wall-time-seconds": "Макс. время выполнения (секунды)",
|
||||
"poll-interval-seconds": "Интервал опроса (секунды)",
|
||||
"remote-sub-agent-required-fields": "API Key, API Host и Agent ID обязательны, когда Sub Agent включён.",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@
|
|||
"sub-agents": "Sub Agents",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "把适合远程执行的任务委托给 Waverunner 兼容的托管智能体沙盒。",
|
||||
"remote-sub-agent-description": "把适合远程执行的任务委托给托管远程智能体沙盒。",
|
||||
"agent-provider": "Agent Provider",
|
||||
"agent-id": "Agent ID",
|
||||
"max-wall-time-seconds": "最长运行时间(秒)",
|
||||
|
|
|
|||
|
|
@ -167,6 +167,15 @@
|
|||
"models-default-setting-title": "預設設定",
|
||||
"models-default-setting-description": "從已配置的模型中選擇一個作為 Eigent 的預設模型,它將全域套用於您的工作區。",
|
||||
"models-configuration": "配置",
|
||||
"sub-agents": "Sub Agents",
|
||||
"gemini-agent": "Gemini Agents API",
|
||||
"gemini-remote-sub-agent": "Gemini Agents API",
|
||||
"remote-sub-agent-description": "把適合遠端執行的任務委託給託管遠端智能體沙盒。",
|
||||
"agent-provider": "Agent Provider",
|
||||
"agent-id": "Agent ID",
|
||||
"max-wall-time-seconds": "最長執行時間(秒)",
|
||||
"poll-interval-seconds": "輪詢間隔(秒)",
|
||||
"remote-sub-agent-required-fields": "啟用 Sub Agent 時,需要填寫 API Key、API Host 和 Agent ID。",
|
||||
|
||||
"gemini-3-pro-preview-name": "Gemini 3 Pro Preview",
|
||||
"gemini-3.1-pro-preview-name": "Gemini 3.1 Pro Preview",
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export const REMOTE_SUB_AGENT_PROVIDER = 'gemini_agents';
|
|||
export const REMOTE_SUB_AGENT_PROVIDER_ID = REMOTE_SUB_AGENT_PROVIDER;
|
||||
export const REMOTE_SUB_AGENT_DEFAULT_BASE_URL =
|
||||
'https://generativelanguage.googleapis.com/v1beta';
|
||||
export const REMOTE_SUB_AGENT_DEFAULT_AGENT = 'waverunner';
|
||||
export const REMOTE_SUB_AGENT_DEFAULT_AGENT = '';
|
||||
export const REMOTE_SUB_AGENT_DEFAULT_MAX_WALL_TIME_SECONDS = '900';
|
||||
export const REMOTE_SUB_AGENT_DEFAULT_POLL_INTERVAL_SECONDS = '5';
|
||||
|
||||
|
|
@ -101,6 +101,12 @@ export function toRemoteSubAgentProviderPayload(form: RemoteSubAgentFormState) {
|
|||
const agentName = form.agentName.trim();
|
||||
const maxWallTimeSeconds = Number(form.maxWallTimeSeconds);
|
||||
const pollIntervalSeconds = Number(form.pollIntervalSeconds);
|
||||
const fallbackMaxWallTimeSeconds = Number(
|
||||
REMOTE_SUB_AGENT_DEFAULT_MAX_WALL_TIME_SECONDS
|
||||
);
|
||||
const fallbackPollIntervalSeconds = Number(
|
||||
REMOTE_SUB_AGENT_DEFAULT_POLL_INTERVAL_SECONDS
|
||||
);
|
||||
|
||||
return {
|
||||
provider_name: REMOTE_SUB_AGENT_PROVIDER_ID,
|
||||
|
|
@ -110,12 +116,14 @@ export function toRemoteSubAgentProviderPayload(form: RemoteSubAgentFormState) {
|
|||
agent_name: agentName,
|
||||
model_name: '',
|
||||
config: {
|
||||
max_wall_time_seconds: Number.isFinite(maxWallTimeSeconds)
|
||||
? maxWallTimeSeconds
|
||||
: Number(REMOTE_SUB_AGENT_DEFAULT_MAX_WALL_TIME_SECONDS),
|
||||
poll_interval_seconds: Number.isFinite(pollIntervalSeconds)
|
||||
? pollIntervalSeconds
|
||||
: Number(REMOTE_SUB_AGENT_DEFAULT_POLL_INTERVAL_SECONDS),
|
||||
max_wall_time_seconds:
|
||||
Number.isFinite(maxWallTimeSeconds) && maxWallTimeSeconds > 0
|
||||
? maxWallTimeSeconds
|
||||
: fallbackMaxWallTimeSeconds,
|
||||
poll_interval_seconds:
|
||||
Number.isFinite(pollIntervalSeconds) && pollIntervalSeconds > 0
|
||||
? pollIntervalSeconds
|
||||
: fallbackPollIntervalSeconds,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,10 +75,22 @@ export default function SubAgents() {
|
|||
return t('setting.validate-failed');
|
||||
};
|
||||
|
||||
const getRemoteSubAgentRequiredError = (form: RemoteSubAgentFormState) => {
|
||||
const getRemoteSubAgentRequiredError = (
|
||||
form: RemoteSubAgentFormState,
|
||||
requireFields = form.enabled
|
||||
) => {
|
||||
const maxWallTimeSeconds = Number(form.maxWallTimeSeconds.trim());
|
||||
const pollIntervalSeconds = Number(form.pollIntervalSeconds.trim());
|
||||
|
||||
if (
|
||||
form.enabled &&
|
||||
(!form.apiKey.trim() || !form.baseUrl.trim() || !form.agentName.trim())
|
||||
requireFields &&
|
||||
(!form.apiKey.trim() ||
|
||||
!form.baseUrl.trim() ||
|
||||
!form.agentName.trim() ||
|
||||
!Number.isFinite(maxWallTimeSeconds) ||
|
||||
maxWallTimeSeconds <= 0 ||
|
||||
!Number.isFinite(pollIntervalSeconds) ||
|
||||
pollIntervalSeconds <= 0)
|
||||
) {
|
||||
return t('setting.remote-sub-agent-required-fields');
|
||||
}
|
||||
|
|
@ -105,8 +117,17 @@ export default function SubAgents() {
|
|||
});
|
||||
};
|
||||
|
||||
const persistRemoteSubAgentForm = async (form: RemoteSubAgentFormState) => {
|
||||
const requiredError = getRemoteSubAgentRequiredError(form);
|
||||
const persistRemoteSubAgentForm = async (
|
||||
form: RemoteSubAgentFormState,
|
||||
{
|
||||
requireFields = form.enabled,
|
||||
validateConnection = form.enabled,
|
||||
}: {
|
||||
requireFields?: boolean;
|
||||
validateConnection?: boolean;
|
||||
} = {}
|
||||
) => {
|
||||
const requiredError = getRemoteSubAgentRequiredError(form, requireFields);
|
||||
if (requiredError) {
|
||||
setRemoteSubAgentError(requiredError);
|
||||
toast.error(requiredError);
|
||||
|
|
@ -116,7 +137,7 @@ export default function SubAgents() {
|
|||
setRemoteSubAgentSaving(true);
|
||||
setRemoteSubAgentError(null);
|
||||
try {
|
||||
if (form.enabled) {
|
||||
if (validateConnection) {
|
||||
await validateRemoteSubAgentConfig(form);
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +166,10 @@ export default function SubAgents() {
|
|||
};
|
||||
|
||||
const handleRemoteSubAgentSave = async () => {
|
||||
await persistRemoteSubAgentForm(remoteSubAgentForm);
|
||||
await persistRemoteSubAgentForm(remoteSubAgentForm, {
|
||||
requireFields: true,
|
||||
validateConnection: true,
|
||||
});
|
||||
};
|
||||
|
||||
const handleRemoteSubAgentToggle = async (checked: boolean) => {
|
||||
|
|
@ -155,7 +179,13 @@ export default function SubAgents() {
|
|||
enabled: checked,
|
||||
};
|
||||
|
||||
const requiredError = getRemoteSubAgentRequiredError(nextForm);
|
||||
if (!checked && !remoteSubAgentForm.provider_id) {
|
||||
setRemoteSubAgentForm(nextForm);
|
||||
setRemoteSubAgentError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const requiredError = getRemoteSubAgentRequiredError(nextForm, checked);
|
||||
if (requiredError) {
|
||||
setRemoteSubAgentError(requiredError);
|
||||
toast.error(requiredError);
|
||||
|
|
@ -163,7 +193,10 @@ export default function SubAgents() {
|
|||
}
|
||||
|
||||
setRemoteSubAgentForm(nextForm);
|
||||
const saved = await persistRemoteSubAgentForm(nextForm);
|
||||
const saved = await persistRemoteSubAgentForm(nextForm, {
|
||||
requireFields: checked,
|
||||
validateConnection: checked,
|
||||
});
|
||||
if (!saved) {
|
||||
setRemoteSubAgentForm(previousForm);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue