synthos 0.7.1 → 0.8.0
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.
- package/README.md +215 -65
- package/default-pages/application.json +1 -0
- package/default-pages/json_tools.json +1 -1
- package/default-pages/oregon_trail.html +321 -0
- package/default-pages/oregon_trail.json +12 -0
- package/default-pages/sidebar_page.json +1 -0
- package/default-pages/solar_explorer.html +10 -18
- package/default-pages/solar_explorer.json +2 -2
- package/default-pages/two-panel_page.json +1 -0
- package/default-pages/us_map.html +192 -0
- package/default-pages/us_map.json +12 -0
- package/default-pages/us_map_1850.html +325 -0
- package/default-pages/us_map_1850.json +12 -0
- package/default-pages/western_cities_1850.html +526 -0
- package/default-pages/western_cities_1850.json +12 -0
- package/default-themes/{nebula-dawn.css → nebula-dawn.v2.css} +24 -0
- package/default-themes/{nebula-dusk.css → nebula-dusk.v2.css} +24 -0
- package/dist/agents/a2a/a2aProvider.d.ts +3 -0
- package/dist/agents/a2a/a2aProvider.d.ts.map +1 -0
- package/dist/agents/a2a/a2aProvider.js +126 -0
- package/dist/agents/a2a/a2aProvider.js.map +1 -0
- package/dist/agents/discovery.d.ts +30 -0
- package/dist/agents/discovery.d.ts.map +1 -0
- package/dist/agents/discovery.js +52 -0
- package/dist/agents/discovery.js.map +1 -0
- package/dist/agents/index.d.ts +7 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +19 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/openclaw/gatewayManager.d.ts +113 -0
- package/dist/agents/openclaw/gatewayManager.d.ts.map +1 -0
- package/dist/agents/openclaw/gatewayManager.js +470 -0
- package/dist/agents/openclaw/gatewayManager.js.map +1 -0
- package/dist/agents/openclaw/openclawProvider.d.ts +3 -0
- package/dist/agents/openclaw/openclawProvider.d.ts.map +1 -0
- package/dist/agents/openclaw/openclawProvider.js +239 -0
- package/dist/agents/openclaw/openclawProvider.js.map +1 -0
- package/dist/agents/openclaw/sshTunnelManager.d.ts +23 -0
- package/dist/agents/openclaw/sshTunnelManager.d.ts.map +1 -0
- package/dist/agents/openclaw/sshTunnelManager.js +340 -0
- package/dist/agents/openclaw/sshTunnelManager.js.map +1 -0
- package/dist/agents/types.d.ts +64 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +6 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/connectors/airtable/connector.json +27 -0
- package/dist/connectors/alpha-vantage/connector.json +26 -0
- package/dist/connectors/brave-search/connector.json +26 -0
- package/dist/connectors/cloudinary/connector.json +27 -0
- package/dist/connectors/deepl/connector.json +28 -0
- package/dist/connectors/elevenlabs/connector.json +30 -0
- package/dist/connectors/giphy/connector.json +27 -0
- package/dist/connectors/github/connector.json +29 -0
- package/dist/connectors/huggingface/connector.json +27 -0
- package/dist/connectors/imgur/connector.json +29 -0
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.d.ts.map +1 -1
- package/dist/connectors/instagram/connector.json +43 -0
- package/dist/connectors/jira/connector.json +28 -0
- package/dist/connectors/mapbox/connector.json +26 -0
- package/dist/connectors/nasa/connector.json +27 -0
- package/dist/connectors/newsapi/connector.json +27 -0
- package/dist/connectors/notion/connector.json +28 -0
- package/dist/connectors/open-exchange-rates/connector.json +27 -0
- package/dist/connectors/openweathermap/connector.json +26 -0
- package/dist/connectors/pexels/connector.json +27 -0
- package/dist/connectors/registry.d.ts.map +1 -1
- package/dist/connectors/registry.js +42 -96
- package/dist/connectors/registry.js.map +1 -1
- package/dist/connectors/resend/connector.json +29 -0
- package/dist/connectors/rss2json/connector.json +27 -0
- package/dist/connectors/sendgrid/connector.json +27 -0
- package/dist/connectors/spoonacular/connector.json +28 -0
- package/dist/connectors/stability-ai/connector.json +27 -0
- package/dist/connectors/twilio/connector.json +28 -0
- package/dist/connectors/types.d.ts +23 -0
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/connectors/unsplash/connector.json +27 -0
- package/dist/connectors/wolfram-alpha/connector.json +26 -0
- package/dist/connectors/youtube-data/connector.json +30 -0
- package/dist/files.d.ts +1 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +16 -1
- package/dist/files.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +28 -0
- package/dist/init.js.map +1 -1
- package/dist/migrations.d.ts +3 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +122 -138
- package/dist/migrations.js.map +1 -1
- package/dist/models/anthropic.d.ts +22 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +76 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/chainOfThought.d.ts +12 -0
- package/dist/models/chainOfThought.d.ts.map +1 -0
- package/dist/models/chainOfThought.js +45 -0
- package/dist/models/chainOfThought.js.map +1 -0
- package/dist/models/fireworksai.d.ts +30 -0
- package/dist/models/fireworksai.d.ts.map +1 -0
- package/dist/models/fireworksai.js +133 -0
- package/dist/models/fireworksai.js.map +1 -0
- package/dist/models/index.d.ts +7 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +19 -1
- package/dist/models/index.js.map +1 -1
- package/dist/models/logCompletePrompt.d.ts +3 -0
- package/dist/models/logCompletePrompt.d.ts.map +1 -0
- package/dist/models/logCompletePrompt.js +23 -0
- package/dist/models/logCompletePrompt.js.map +1 -0
- package/dist/models/openai.d.ts +24 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +80 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/providers.d.ts +1 -0
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +12 -4
- package/dist/models/providers.js.map +1 -1
- package/dist/models/types.d.ts +34 -2
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +16 -0
- package/dist/models/types.js.map +1 -1
- package/dist/models/utils.d.ts +6 -0
- package/dist/models/utils.d.ts.map +1 -0
- package/dist/models/utils.js +21 -0
- package/dist/models/utils.js.map +1 -0
- package/dist/scripts.d.ts +2 -1
- package/dist/scripts.d.ts.map +1 -1
- package/dist/scripts.js +4 -3
- package/dist/scripts.js.map +1 -1
- package/dist/service/createCompletePrompt.d.ts +1 -1
- package/dist/service/createCompletePrompt.d.ts.map +1 -1
- package/dist/service/createCompletePrompt.js +9 -6
- package/dist/service/createCompletePrompt.js.map +1 -1
- package/dist/service/generateImage.d.ts +1 -1
- package/dist/service/generateImage.d.ts.map +1 -1
- package/dist/service/generateImage.js +3 -3
- package/dist/service/generateImage.js.map +1 -1
- package/dist/service/server.d.ts.map +1 -1
- package/dist/service/server.js +3 -0
- package/dist/service/server.js.map +1 -1
- package/dist/service/transformPage.d.ts +4 -2
- package/dist/service/transformPage.d.ts.map +1 -1
- package/dist/service/transformPage.js +74 -6
- package/dist/service/transformPage.js.map +1 -1
- package/dist/service/useAgentRoutes.d.ts +4 -0
- package/dist/service/useAgentRoutes.d.ts.map +1 -0
- package/dist/service/useAgentRoutes.js +389 -0
- package/dist/service/useAgentRoutes.js.map +1 -0
- package/dist/service/useApiRoutes.d.ts.map +1 -1
- package/dist/service/useApiRoutes.js +157 -16
- package/dist/service/useApiRoutes.js.map +1 -1
- package/dist/service/useConnectorRoutes.d.ts.map +1 -1
- package/dist/service/useConnectorRoutes.js +14 -3
- package/dist/service/useConnectorRoutes.js.map +1 -1
- package/dist/service/useGatewayRoutes.d.ts +4 -0
- package/dist/service/useGatewayRoutes.d.ts.map +1 -0
- package/dist/service/useGatewayRoutes.js +168 -0
- package/dist/service/useGatewayRoutes.js.map +1 -0
- package/dist/service/usePageRoutes.d.ts.map +1 -1
- package/dist/service/usePageRoutes.js +16 -5
- package/dist/service/usePageRoutes.js.map +1 -1
- package/dist/settings.d.ts +2 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +4 -8
- package/dist/settings.js.map +1 -1
- package/dist/themes.d.ts +14 -0
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +86 -13
- package/dist/themes.js.map +1 -1
- package/package.json +10 -5
- package/page-scripts/helpers-v2.js +222 -0
- package/page-scripts/page-v2.js +656 -0
- package/required-pages/builder.html +1 -27
- package/required-pages/pages.html +745 -22
- package/required-pages/settings.html +819 -21
- package/required-pages/synthos_apis.html +56 -1
- package/src/agents/a2a/a2aProvider.ts +110 -0
- package/src/agents/discovery.ts +74 -0
- package/src/agents/index.ts +6 -0
- package/src/agents/openclaw/gatewayManager.ts +559 -0
- package/src/agents/openclaw/openclawProvider.ts +261 -0
- package/src/agents/openclaw/sshTunnelManager.ts +385 -0
- package/src/agents/types.ts +82 -0
- package/src/connectors/airtable/connector.json +27 -0
- package/src/connectors/alpha-vantage/connector.json +26 -0
- package/src/connectors/brave-search/connector.json +26 -0
- package/src/connectors/cloudinary/connector.json +27 -0
- package/src/connectors/deepl/connector.json +28 -0
- package/src/connectors/elevenlabs/connector.json +30 -0
- package/src/connectors/giphy/connector.json +27 -0
- package/src/connectors/github/connector.json +29 -0
- package/src/connectors/huggingface/connector.json +27 -0
- package/src/connectors/imgur/connector.json +29 -0
- package/src/connectors/index.ts +2 -0
- package/src/connectors/instagram/connector.json +43 -0
- package/src/connectors/jira/connector.json +28 -0
- package/src/connectors/mapbox/connector.json +26 -0
- package/src/connectors/nasa/connector.json +27 -0
- package/src/connectors/newsapi/connector.json +27 -0
- package/src/connectors/notion/connector.json +28 -0
- package/src/connectors/open-exchange-rates/connector.json +27 -0
- package/src/connectors/openweathermap/connector.json +26 -0
- package/src/connectors/pexels/connector.json +27 -0
- package/src/connectors/registry.ts +21 -97
- package/src/connectors/resend/connector.json +29 -0
- package/src/connectors/rss2json/connector.json +27 -0
- package/src/connectors/sendgrid/connector.json +27 -0
- package/src/connectors/spoonacular/connector.json +28 -0
- package/src/connectors/stability-ai/connector.json +27 -0
- package/src/connectors/twilio/connector.json +28 -0
- package/src/connectors/types.ts +25 -0
- package/src/connectors/unsplash/connector.json +27 -0
- package/src/connectors/wolfram-alpha/connector.json +26 -0
- package/src/connectors/youtube-data/connector.json +30 -0
- package/src/files.ts +14 -0
- package/src/init.ts +27 -0
- package/src/migrations.ts +121 -138
- package/src/models/anthropic.ts +89 -0
- package/src/models/chainOfThought.ts +56 -0
- package/src/models/fireworksai.ts +136 -0
- package/src/models/index.ts +7 -1
- package/src/models/logCompletePrompt.ts +25 -0
- package/src/models/openai.ts +90 -0
- package/src/models/providers.ts +12 -3
- package/src/models/types.ts +67 -2
- package/src/models/utils.ts +16 -0
- package/src/scripts.ts +2 -2
- package/src/service/createCompletePrompt.ts +3 -1
- package/src/service/generateImage.ts +2 -2
- package/src/service/server.ts +4 -0
- package/src/service/transformPage.ts +81 -8
- package/src/service/useAgentRoutes.ts +423 -0
- package/src/service/useApiRoutes.ts +173 -18
- package/src/service/useConnectorRoutes.ts +14 -3
- package/src/service/usePageRoutes.ts +20 -6
- package/src/settings.ts +6 -10
- package/src/themes.ts +84 -12
- package/tests/README.md +12 -0
- package/tests/anthropic.spec.ts +84 -0
- package/tests/chainOfThought.spec.ts +108 -0
- package/tests/ensureScripts.spec.ts +82 -0
- package/tests/files.spec.ts +233 -0
- package/tests/fireworksai.spec.ts +92 -0
- package/tests/logCompletePrompt.spec.ts +74 -0
- package/tests/migrations.spec.ts +169 -0
- package/tests/openai.spec.ts +71 -0
- package/tests/pages.spec.ts +328 -0
- package/tests/providers.spec.ts +144 -0
- package/tests/scripts.spec.ts +209 -0
- package/tests/transformPage.spec.ts +931 -0
- package/tests/types.spec.ts +23 -0
- package/default-pages/app_builder.json +0 -1
- package/default-pages/sidebar_builder.json +0 -1
- package/default-pages/two-panel_builder.json +0 -1
- package/images/home.png +0 -0
- package/images/page-management.png +0 -0
- package/images/settings.png +0 -0
- package/images/synthos-square.png +0 -0
- /package/default-pages/{app_builder.html → application.html} +0 -0
- /package/default-pages/{sidebar_builder.html → sidebar_page.html} +0 -0
- /package/default-pages/{two-panel_builder.html → two-panel_page.html} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<title>SynthOS - Settings</title>
|
|
5
5
|
<script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
|
|
6
6
|
<link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
|
|
7
|
-
<style>.settings-title{font-size:22px;font-weight:700;min-height:var(--header-min-height);padding:var(--header-padding-vertical) var(--header-padding-horizontal);line-height:var(--header-line-height);display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;border-radius:12px 12px 0 0;width:100%;box-shadow:0 6px 25px var(--accent-glow);letter-spacing:2px;text-shadow:0 2px 10px rgba(0,0,0,.3)}.settings-container{display:flex;flex-direction:column;width:100%;flex-grow:1;background:rgba(15,15,35,.8);border-radius:0 0 12px 12px;border:1px solid rgba(138,43,226,.2);border-top:none;overflow:hidden}.accordion-section{display:flex;flex-direction:column;flex-shrink:0;overflow:hidden;border-bottom:1px solid var(--border-color)}.accordion-section:last-child{border-bottom:none}.accordion-section.active{flex-shrink:1;flex-grow:1;min-height:0}.accordion-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px 25px;background:none;border:none;color:var(--text-primary);font-size:15px;font-weight:600;cursor:pointer;transition:background .3s;letter-spacing:.5px;flex-shrink:0}.accordion-header:hover{background:rgba(138,43,226,.05)}.accordion-section.active .accordion-header{background:rgba(138,43,226,.08)}.accordion-chevron{font-size:11px;color:var(--text-secondary);transition:transform .3s}.accordion-section.active .accordion-chevron{transform:rotate(180deg)}.accordion-body{display:none;flex-direction:column;flex-grow:1;min-height:0;overflow:hidden}.accordion-section.active .accordion-body{display:flex}.accordion-content{display:flex;flex-direction:column;gap:15px;overflow-y:auto;padding:20px 25px;flex-grow:1}.button-row{display:flex;justify-content:flex-end;padding:15px 25px;border-top:1px solid var(--border-color);flex-shrink:0}.apply-btn{padding:12px 30px;border:none;border-radius:12px;font-size:15px;background:linear-gradient(135deg,var(--accent-primary) 0,var(--accent-secondary) 50%,var(--accent-tertiary) 100%);color:#fff;cursor:pointer;transition:.3s;font-weight:600;letter-spacing:1px;box-shadow:0 4px 20px rgba(102,126,234,.4)}.apply-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(102,126,234,.6)}.apply-btn:active{transform:translateY(0)}.form-group{display:flex;flex-direction:column;width:100%}.form-group label{display:block;margin-bottom:8px;color:var(--text-secondary);font-weight:600;font-size:14px}.form-group input,.form-group select,.form-group textarea{width:100%;padding:14px 18px;border-radius:12px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:14px;transition:.3s;box-shadow:inset 0 2px 10px rgba(0,0,0,.3)}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:0;border-color:rgba(183,148,246,.6);box-shadow:inset 0 2px 10px rgba(0,0,0,.3),0 0 20px var(--accent-glow)}.form-group input::placeholder,.form-group textarea::placeholder{color:rgba(183,148,246,.5)}.form-group textarea{resize:vertical;min-height:100px}.form-group select{cursor:pointer;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23b794f6' d='M6 8L1 3h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 15px center}.form-group select option{background:var(--bg-tertiary);color:var(--text-primary);padding:10px}.info-text{color:rgba(183,148,246,.7);font-size:13px;line-height:1.6;text-align:center;padding:15px;background:rgba(15,15,35,.4);border-radius:10px;border:1px solid var(--border-color)}.info-text a{color:var(--accent-tertiary);text-decoration:none;transition:.3s;font-weight:500}.info-text a:hover{color:var(--text-secondary);text-shadow:0 0 10px var(--accent-glow)}.config-required-banner{padding:12px 20px;background:rgba(255,180,50,.12);border:1px solid rgba(255,180,50,.3);border-radius:10px;color:rgba(255,200,100,.9);font-size:13px;font-weight:500;text-align:center;line-height:1.5}.model-card{border:1px solid var(--border-color);border-radius:12px;padding:18px;display:flex;flex-direction:column;gap:12px;background:rgba(15,15,35,.3)}.model-card-title{font-size:14px;font-weight:700;color:var(--text-primary);letter-spacing:.5px;margin:0}.filter-bar{display:flex;align-items:center;gap:8px;flex-wrap:nowrap}.filter-btn{padding:6px 14px;border-radius:20px;border:1px solid var(--border-color);background:0 0;color:var(--text-secondary);font-size:13px;cursor:pointer;transition:.2s;white-space:nowrap;flex-shrink:0}.filter-btn:hover{border-color:var(--accent-primary);color:var(--accent-primary)}.filter-btn.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;border-color:transparent}.services-grid{display:grid;grid-template-columns:1fr;gap:12px}.service-card{border-radius:12px;border:1px solid var(--border-color);background:rgba(15,15,35,.5);padding:18px;transition:.3s}.service-card:hover{border-color:rgba(138,43,226,.3)}.service-card-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.service-card-name{font-size:15px;font-weight:600;color:var(--text-primary)}.service-card-category{font-size:11px;color:var(--text-secondary);background:rgba(138,43,226,.15);padding:2px 8px;border-radius:10px}.service-card-desc{font-size:13px;color:var(--text-secondary);line-height:1.5;margin-bottom:12px}.service-card-fields{display:flex;flex-direction:column;gap:8px}.service-card-fields input{width:100%;padding:10px 14px;border-radius:8px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:13px;transition:.3s;box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.service-card-fields input:focus{outline:0;border-color:rgba(183,148,246,.6);box-shadow:inset 0 2px 8px rgba(0,0,0,.2),0 0 15px var(--accent-glow)}.service-card-fields input::placeholder{color:rgba(183,148,246,.5)}.toggle-switch{position:relative;width:44px;height:24px;flex-shrink:0}.toggle-switch input{opacity:0;width:0;height:0}.toggle-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:rgba(100,100,100,.4);border-radius:24px;transition:.3s}.toggle-slider:before{content:"";position:absolute;height:18px;width:18px;left:3px;bottom:3px;background:#fff;border-radius:50%;transition:.3s}.toggle-switch input:checked+.toggle-slider{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary))}.toggle-switch input:checked+.toggle-slider:before{transform:translateX(20px)}.light-mode .settings-container{background:rgba(255,255,255,.8)}.light-mode .accordion-header:hover{background:rgba(118,75,162,.05)}.light-mode .accordion-section.active .accordion-header{background:rgba(118,75,162,.06)}.light-mode .form-group input,.light-mode .form-group select,.light-mode .form-group textarea{background:rgba(255,255,255,.8);box-shadow:inset 0 2px 10px rgba(118,75,162,.05)}.light-mode .form-group input:focus,.light-mode .form-group select:focus,.light-mode .form-group textarea:focus{box-shadow:inset 0 2px 10px rgba(118,75,162,.05),0 0 20px var(--accent-glow)}.light-mode .form-group input::placeholder,.light-mode .form-group textarea::placeholder{color:rgba(107,79,138,.5)}.light-mode .info-text{color:rgba(107,79,138,.7);background:rgba(255,255,255,.4)}.light-mode .config-required-banner{background:rgba(200,150,50,.1);border-color:rgba(200,150,50,.3);color:rgba(160,120,30,.9)}.light-mode .model-card{background:rgba(255,255,255,.3)}.light-mode .service-card{background:rgba(255,255,255,.5)}.light-mode .service-card-fields input{background:rgba(255,255,255,.8);box-shadow:inset 0 2px 8px rgba(118,75,162,.05)}.light-mode .service-card-fields input:focus{box-shadow:inset 0 2px 8px rgba(118,75,162,.05),0 0 15px var(--accent-glow)}.light-mode .service-card-fields input::placeholder{color:rgba(107,79,138,.5)}.model-card.disabled{opacity:0.35;pointer-events:none;user-select:none;transition:opacity .3s}.wizard-hidden{display:none !important}.more-settings-link{display:inline-block;color:var(--accent-tertiary);font-size:13px;cursor:pointer;text-decoration:none;padding:4px 0;transition:.3s;user-select:none}.more-settings-link:hover{color:var(--text-secondary);text-shadow:0 0 10px var(--accent-glow)}.light-mode .model-card.disabled{opacity:0.35}.accordion-section.disabled .accordion-header{opacity:0.35;pointer-events:none;cursor:default}.apply-btn:disabled{opacity:0.35;pointer-events:none;cursor:default}.connector-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px}.connector-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px 12px;border-radius:14px;border:1px solid var(--border-color);background:linear-gradient(160deg,rgba(30,30,60,.6),rgba(20,20,50,.8));cursor:pointer;transition:transform .2s,box-shadow .2s,border-color .2s;gap:8px}.connector-tile:hover{transform:translateY(-3px);box-shadow:0 6px 20px var(--accent-glow);border-color:var(--accent-primary)}.connector-tile.configured{background:linear-gradient(160deg,rgba(60,30,90,.6),rgba(40,20,70,.8));border-color:var(--accent-secondary);box-shadow:0 2px 12px var(--accent-glow)}.connector-tile-name{font-size:14px;font-weight:600;color:var(--text-primary)}.connector-category{font-size:11px;color:var(--text-secondary);background:rgba(138,43,226,.15);padding:2px 8px;border-radius:10px}.search-input{flex:1;min-width:100px;padding:6px 14px;border-radius:20px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:13px;transition:.3s}.search-input:focus{outline:0;border-color:rgba(183,148,246,.6)}.search-input::placeholder{color:rgba(183,148,246,.5)}.filter-buttons-container{display:flex;gap:8px;flex-wrap:nowrap}.conn-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;z-index:1000}.conn-modal-content{background:rgba(20,20,50,.95);border:1px solid var(--border-color);border-radius:16px;padding:28px;max-width:420px;width:90%;display:flex;flex-direction:column;gap:16px;box-shadow:0 8px 40px rgba(0,0,0,.5)}.conn-modal-title{font-size:18px;font-weight:700;color:var(--text-primary)}.conn-modal-desc{font-size:13px;color:var(--text-secondary);line-height:1.5}.conn-modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:8px}.conn-modal-btn{padding:12px 24px;border:none;border-radius:12px;font-size:14px;background:linear-gradient(135deg,var(--accent-primary) 0,var(--accent-secondary) 50%,var(--accent-tertiary) 100%);color:#fff;cursor:pointer;transition:.3s;font-weight:600;letter-spacing:.5px;box-shadow:0 4px 20px rgba(102,126,234,.4)}.conn-modal-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(102,126,234,.6)}.conn-modal-btn.cancel{background:rgba(100,100,100,.4);box-shadow:none}.conn-modal-btn.cancel:hover{background:rgba(100,100,100,.6);transform:translateY(-1px)}.conn-modal-btn.remove{background:rgba(180,50,50,.6);box-shadow:none}.conn-modal-btn.remove:hover{background:rgba(200,60,60,.8);transform:translateY(-1px)}.light-mode .connector-tile{background:linear-gradient(160deg,rgba(240,235,255,.8),rgba(250,248,255,.9))}.light-mode .connector-tile.configured{background:linear-gradient(160deg,rgba(220,200,255,.8),rgba(235,220,255,.9))}.light-mode .search-input{background:rgba(255,255,255,.8)}.light-mode .search-input::placeholder{color:rgba(107,79,138,.5)}.light-mode .conn-modal-content{background:rgba(250,248,255,.98)}</style>
|
|
7
|
+
<style>.settings-title{font-size:22px;font-weight:700;min-height:var(--header-min-height);padding:var(--header-padding-vertical) var(--header-padding-horizontal);line-height:var(--header-line-height);display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;border-radius:12px 12px 0 0;width:100%;box-shadow:0 6px 25px var(--accent-glow);letter-spacing:2px;text-shadow:0 2px 10px rgba(0,0,0,.3)}.settings-container{display:flex;flex-direction:column;width:100%;flex-grow:1;background:rgba(15,15,35,.8);border-radius:0 0 12px 12px;border:1px solid rgba(138,43,226,.2);border-top:none;overflow:hidden}.accordion-section{display:flex;flex-direction:column;flex-shrink:0;overflow:hidden;border-bottom:1px solid var(--border-color)}.accordion-section:last-child{border-bottom:none}.accordion-section.active{flex-shrink:1;flex-grow:1;min-height:0}.accordion-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px 25px;background:none;border:none;color:var(--text-primary);font-size:15px;font-weight:600;cursor:pointer;transition:background .3s;letter-spacing:.5px;flex-shrink:0}.accordion-header:hover{background:rgba(138,43,226,.05)}.accordion-section.active .accordion-header{background:rgba(138,43,226,.08)}.accordion-chevron{font-size:11px;color:var(--text-secondary);transition:transform .3s}.accordion-section.active .accordion-chevron{transform:rotate(180deg)}.accordion-body{display:none;flex-direction:column;flex-grow:1;min-height:0;overflow:hidden}.accordion-section.active .accordion-body{display:flex}.accordion-content{display:flex;flex-direction:column;gap:15px;overflow-y:auto;padding:20px 25px;flex-grow:1}.button-row{display:flex;justify-content:flex-end;padding:15px 25px;border-top:1px solid var(--border-color);flex-shrink:0}.apply-btn{padding:12px 30px;border:none;border-radius:12px;font-size:15px;background:linear-gradient(135deg,var(--accent-primary) 0,var(--accent-secondary) 50%,var(--accent-tertiary) 100%);color:#fff;cursor:pointer;transition:.3s;font-weight:600;letter-spacing:1px;box-shadow:0 4px 20px rgba(102,126,234,.4)}.apply-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(102,126,234,.6)}.apply-btn:active{transform:translateY(0)}.form-group{display:flex;flex-direction:column;width:100%}.form-group label{display:block;margin-bottom:8px;color:var(--text-secondary);font-weight:600;font-size:14px}.form-group input,.form-group select,.form-group textarea{width:100%;padding:14px 18px;border-radius:12px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:14px;transition:.3s;box-shadow:inset 0 2px 10px rgba(0,0,0,.3)}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:0;border-color:rgba(183,148,246,.6);box-shadow:inset 0 2px 10px rgba(0,0,0,.3),0 0 20px var(--accent-glow)}.form-group input::placeholder,.form-group textarea::placeholder{color:rgba(183,148,246,.5)}.form-group textarea{resize:vertical;min-height:100px}.form-group select{cursor:pointer;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23b794f6' d='M6 8L1 3h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 15px center}.form-group select option{background:var(--bg-tertiary);color:var(--text-primary);padding:10px}.info-text{color:rgba(183,148,246,.7);font-size:13px;line-height:1.6;text-align:center;padding:15px;background:rgba(15,15,35,.4);border-radius:10px;border:1px solid var(--border-color)}.info-text a{color:var(--accent-tertiary);text-decoration:none;transition:.3s;font-weight:500}.info-text a:hover{color:var(--text-secondary);text-shadow:0 0 10px var(--accent-glow)}.config-required-banner{padding:12px 20px;background:rgba(255,180,50,.12);border:1px solid rgba(255,180,50,.3);border-radius:10px;color:rgba(255,200,100,.9);font-size:13px;font-weight:500;text-align:center;line-height:1.5}.model-card{border:1px solid var(--border-color);border-radius:12px;padding:18px;display:flex;flex-direction:column;gap:12px;background:rgba(15,15,35,.3)}.model-card-title{font-size:14px;font-weight:700;color:var(--text-primary);letter-spacing:.5px;margin:0}.filter-bar{display:flex;align-items:center;gap:8px;flex-wrap:nowrap}.filter-btn{padding:6px 14px;border-radius:20px;border:1px solid var(--border-color);background:0 0;color:var(--text-secondary);font-size:13px;cursor:pointer;transition:.2s;white-space:nowrap;flex-shrink:0}.filter-btn:hover{border-color:var(--accent-primary);color:var(--accent-primary)}.filter-btn.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;border-color:transparent}.services-grid{display:grid;grid-template-columns:1fr;gap:12px}.service-card{border-radius:12px;border:1px solid var(--border-color);background:rgba(15,15,35,.5);padding:18px;transition:.3s}.service-card:hover{border-color:rgba(138,43,226,.3)}.service-card-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.service-card-name{font-size:15px;font-weight:600;color:var(--text-primary)}.service-card-category{font-size:11px;color:var(--text-secondary);background:rgba(138,43,226,.15);padding:2px 8px;border-radius:10px}.service-card-desc{font-size:13px;color:var(--text-secondary);line-height:1.5;margin-bottom:12px}.service-card-fields{display:flex;flex-direction:column;gap:8px}.service-card-fields input{width:100%;padding:10px 14px;border-radius:8px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:13px;transition:.3s;box-shadow:inset 0 2px 8px rgba(0,0,0,.2)}.service-card-fields input:focus{outline:0;border-color:rgba(183,148,246,.6);box-shadow:inset 0 2px 8px rgba(0,0,0,.2),0 0 15px var(--accent-glow)}.service-card-fields input::placeholder{color:rgba(183,148,246,.5)}.toggle-switch{position:relative;width:44px;height:24px;flex-shrink:0}.toggle-switch input{opacity:0;width:0;height:0}.toggle-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:rgba(100,100,100,.4);border-radius:24px;transition:.3s}.toggle-slider:before{content:"";position:absolute;height:18px;width:18px;left:3px;bottom:3px;background:#fff;border-radius:50%;transition:.3s}.toggle-switch input:checked+.toggle-slider{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary))}.toggle-switch input:checked+.toggle-slider:before{transform:translateX(20px)}.light-mode .settings-container{background:rgba(255,255,255,.8)}.light-mode .accordion-header:hover{background:rgba(118,75,162,.05)}.light-mode .accordion-section.active .accordion-header{background:rgba(118,75,162,.06)}.light-mode .form-group input,.light-mode .form-group select,.light-mode .form-group textarea{background:rgba(255,255,255,.8);box-shadow:inset 0 2px 10px rgba(118,75,162,.05)}.light-mode .form-group input:focus,.light-mode .form-group select:focus,.light-mode .form-group textarea:focus{box-shadow:inset 0 2px 10px rgba(118,75,162,.05),0 0 20px var(--accent-glow)}.light-mode .form-group input::placeholder,.light-mode .form-group textarea::placeholder{color:rgba(107,79,138,.5)}.light-mode .info-text{color:rgba(107,79,138,.7);background:rgba(255,255,255,.4)}.light-mode .config-required-banner{background:rgba(200,150,50,.1);border-color:rgba(200,150,50,.3);color:rgba(160,120,30,.9)}.light-mode .model-card{background:rgba(255,255,255,.3)}.light-mode .service-card{background:rgba(255,255,255,.5)}.light-mode .service-card-fields input{background:rgba(255,255,255,.8);box-shadow:inset 0 2px 8px rgba(118,75,162,.05)}.light-mode .service-card-fields input:focus{box-shadow:inset 0 2px 8px rgba(118,75,162,.05),0 0 15px var(--accent-glow)}.light-mode .service-card-fields input::placeholder{color:rgba(107,79,138,.5)}.model-card.disabled{opacity:0.35;pointer-events:none;user-select:none;transition:opacity .3s}.wizard-hidden{display:none !important}.more-settings-link{display:inline-block;color:var(--accent-tertiary);font-size:13px;cursor:pointer;text-decoration:none;padding:4px 0;transition:.3s;user-select:none}.more-settings-link:hover{color:var(--text-secondary);text-shadow:0 0 10px var(--accent-glow)}.light-mode .model-card.disabled{opacity:0.35}.accordion-section.disabled .accordion-header{opacity:0.35;pointer-events:none;cursor:default}.apply-btn:disabled{opacity:0.35;pointer-events:none;cursor:default}.connector-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px}.connector-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px 12px;border-radius:14px;border:1px solid var(--border-color);background:linear-gradient(160deg,rgba(30,30,60,.6),rgba(20,20,50,.8));cursor:pointer;transition:transform .2s,box-shadow .2s,border-color .2s;gap:8px}.connector-tile:hover{transform:translateY(-3px);box-shadow:0 6px 20px var(--accent-glow);border-color:var(--accent-primary)}.connector-tile.configured{background:linear-gradient(160deg,rgba(60,30,90,.6),rgba(40,20,70,.8));border-color:var(--accent-secondary);box-shadow:0 2px 12px var(--accent-glow)}.connector-tile-name{font-size:14px;font-weight:600;color:var(--text-primary)}.connector-category{font-size:11px;color:var(--text-secondary);background:rgba(138,43,226,.15);padding:2px 8px;border-radius:10px}.search-input{margin-left:auto;width:180px;min-width:120px;flex-shrink:0;padding:6px 14px;border-radius:20px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:13px;transition:.3s}.search-input:focus{outline:0;border-color:rgba(183,148,246,.6)}.search-input::placeholder{color:rgba(183,148,246,.5)}.filter-buttons-container{display:flex;gap:8px;flex-shrink:1;min-width:0;overflow:hidden;flex-wrap:nowrap}.conn-modal-content{background:rgba(20,20,50,.95);border:1px solid var(--border-color);border-radius:16px;padding:28px;max-width:520px;width:90%;max-height:85vh;display:flex;flex-direction:column;gap:16px;box-shadow:0 8px 40px rgba(0,0,0,.5);overflow-y:auto}.conn-modal-title{font-size:18px;font-weight:700;color:var(--text-primary)}.conn-modal-desc{font-size:13px;color:var(--text-secondary);line-height:1.5}.conn-modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:8px}.conn-modal-btn{padding:12px 24px;border:none;border-radius:12px;font-size:14px;background:linear-gradient(135deg,var(--accent-primary) 0,var(--accent-secondary) 50%,var(--accent-tertiary) 100%);color:#fff;cursor:pointer;transition:.3s;font-weight:600;letter-spacing:.5px;box-shadow:0 4px 20px rgba(102,126,234,.4)}.conn-modal-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(102,126,234,.6)}.conn-modal-btn.cancel{background:rgba(100,100,100,.4);box-shadow:none}.conn-modal-btn.cancel:hover{background:rgba(100,100,100,.6);transform:translateY(-1px)}.conn-modal-btn.remove{background:rgba(180,50,50,.6);box-shadow:none}.conn-modal-btn.remove:hover{background:rgba(200,60,60,.8);transform:translateY(-1px)}.light-mode .connector-tile{background:linear-gradient(160deg,rgba(240,235,255,.8),rgba(250,248,255,.9))}.light-mode .connector-tile.configured{background:linear-gradient(160deg,rgba(220,200,255,.8),rgba(235,220,255,.9))}.light-mode .search-input{background:rgba(255,255,255,.8)}.light-mode .search-input::placeholder{color:rgba(107,79,138,.5)}.more-dropdown{position:relative;flex-shrink:0}.more-btn{position:relative}.more-menu{position:absolute;top:100%;left:0;margin-top:4px;min-width:150px;max-height:250px;overflow-y:auto;border-radius:8px;padding:4px 0;box-shadow:0 8px 30px rgba(0,0,0,.4);display:none;border:1px solid var(--border-color);background:rgba(30,30,50,.95);z-index:100}.more-menu.show{display:block}.more-menu-item{padding:8px 16px;font-size:13px;cursor:pointer;color:var(--text-primary);transition:background .15s;white-space:nowrap}.more-menu-item:hover{background:linear-gradient(135deg,rgba(102,126,234,.3) 0,rgba(118,75,162,.3) 100%)}.more-menu-item.active{background:linear-gradient(135deg,rgba(102,126,234,.2) 0,rgba(118,75,162,.2) 100%);color:var(--accent-tertiary)}.conn-tooltip{position:fixed;padding:8px 12px;background:var(--bg-tertiary,#0f0f23);color:var(--text-secondary,#b794f6);border:1px solid var(--border-color,rgba(138,43,226,0.3));border-radius:8px;font-size:12px;line-height:1.5;max-width:260px;pointer-events:none;z-index:10000;box-shadow:0 4px 16px rgba(0,0,0,.4);opacity:0;transition:opacity .15s}.conn-tooltip.visible{opacity:1}.light-mode .more-menu{background:rgba(255,255,255,.97);box-shadow:0 8px 30px rgba(0,0,0,.15)}.light-mode .conn-modal-content{background:rgba(250,248,255,.98)}.agent-toggle-row{display:flex;align-items:center;gap:10px}.agent-list{display:flex;flex-direction:column;gap:0;max-height:400px;overflow-y:auto;border:1px solid var(--border-color);border-radius:12px}.agent-row{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border-color);cursor:pointer;transition:background .15s}.agent-row:last-child{border-bottom:none}.agent-row:hover{background:rgba(138,43,226,.06)}.agent-row.selected{background:rgba(138,43,226,.1)}.agent-row-info{flex:1;min-width:0;display:flex;align-items:center;gap:10px}.agent-row-name{font-size:14px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-row-desc{font-size:12px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.agent-row-badge{font-size:11px;color:var(--text-secondary);background:rgba(138,43,226,.15);padding:2px 8px;border-radius:10px;white-space:nowrap;flex-shrink:0}.agent-status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.agent-status-dot.connected{background:#4ade80}.agent-status-dot.disconnected{background:rgba(100,100,100,.5)}.agent-row-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.agent-chat-panel{border:1px solid var(--border-color);border-radius:12px;margin-top:12px;overflow:hidden;display:none}.agent-chat-panel.open{display:flex;flex-direction:column}.agent-chat-header{display:flex;justify-content:space-between;align-items:center;padding:10px 16px;background:rgba(138,43,226,.08);font-size:13px;font-weight:600;color:var(--text-primary)}.agent-chat-close{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;padding:0 4px}.agent-chat-close:hover{color:var(--text-primary)}.agent-chat-messages{max-height:250px;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:8px;font-size:13px}.agent-chat-msg{padding:8px 12px;border-radius:10px;max-width:85%;line-height:1.5;word-wrap:break-word;white-space:pre-wrap}.agent-chat-msg.user{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;align-self:flex-end}.agent-chat-msg.agent{background:rgba(15,15,35,.4);color:var(--text-primary);align-self:flex-start;border:1px solid var(--border-color)}.agent-chat-msg.error{background:rgba(180,50,50,.2);color:rgba(255,150,150,.9);align-self:center;font-size:12px}.agent-chat-msg.status{color:var(--text-secondary);align-self:center;font-size:12px;font-style:italic}.agent-chat-input-row{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--border-color)}.agent-chat-input{flex:1;padding:10px 14px;border-radius:10px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:13px}.agent-chat-input:focus{outline:0;border-color:rgba(183,148,246,.6)}.agent-chat-input::placeholder{color:rgba(183,148,246,.5)}.agent-chat-send{padding:10px 18px;border:none;border-radius:10px;font-size:13px;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;cursor:pointer;font-weight:600;transition:.2s}.agent-chat-send:hover{transform:translateY(-1px)}.agent-chat-send:disabled{opacity:.5;pointer-events:none}.light-mode .agent-list{border-color:rgba(118,75,162,.15)}.light-mode .agent-row:hover{background:rgba(118,75,162,.05)}.light-mode .agent-row.selected{background:rgba(118,75,162,.08)}.light-mode .agent-chat-msg.agent{background:rgba(255,255,255,.6)}.light-mode .agent-chat-input{background:rgba(255,255,255,.8)}</style>
|
|
8
8
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
|
|
9
9
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.1/marked.min.js"></script>
|
|
10
10
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.1.0/mermaid.min.js"></script>
|
|
@@ -136,13 +136,17 @@
|
|
|
136
136
|
|
|
137
137
|
<div class="accordion-section" data-section="connectors">
|
|
138
138
|
<button class="accordion-header">
|
|
139
|
-
<span>Connectors</span>
|
|
139
|
+
<span>Connectors <span style="display:inline-block;margin-left:6px;padding:1px 7px;font-size:10px;font-weight:600;letter-spacing:.5px;border-radius:6px;background:var(--accent-tertiary, #8a2be2);color:#fff;vertical-align:middle;line-height:16px;text-transform:uppercase;">Preview</span></span>
|
|
140
140
|
<span class="accordion-chevron">▾</span>
|
|
141
141
|
</button>
|
|
142
142
|
<div class="accordion-body">
|
|
143
143
|
<div class="accordion-content">
|
|
144
144
|
<div class="filter-bar" id="connectorFilterBar">
|
|
145
145
|
<div class="filter-buttons-container" id="connectorFilterButtons"></div>
|
|
146
|
+
<div class="more-dropdown" id="connMoreDropdown" style="display:none;">
|
|
147
|
+
<button class="filter-btn more-btn" id="connMoreBtn">More ▾</button>
|
|
148
|
+
<div class="more-menu" id="connMoreMenu"></div>
|
|
149
|
+
</div>
|
|
146
150
|
<input type="text" class="search-input" id="connectorSearch" placeholder="Search connectors...">
|
|
147
151
|
</div>
|
|
148
152
|
<div class="connector-grid" id="connectorGrid"></div>
|
|
@@ -150,13 +154,119 @@
|
|
|
150
154
|
</div>
|
|
151
155
|
</div>
|
|
152
156
|
|
|
157
|
+
<div class="accordion-section" data-section="agents">
|
|
158
|
+
<button class="accordion-header">
|
|
159
|
+
<span>Agents <span style="display:inline-block;margin-left:6px;padding:1px 7px;font-size:10px;font-weight:600;letter-spacing:.5px;border-radius:6px;background:var(--accent-tertiary, #8a2be2);color:#fff;vertical-align:middle;line-height:16px;text-transform:uppercase;">Preview</span></span>
|
|
160
|
+
<span class="accordion-chevron">▾</span>
|
|
161
|
+
</button>
|
|
162
|
+
<div class="accordion-body">
|
|
163
|
+
<div class="accordion-content">
|
|
164
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
|
|
165
|
+
<div style="font-size:13px;color:var(--text-secondary);">Configure agents (A2A or OpenClaw) that your pages can communicate with.</div>
|
|
166
|
+
<button class="conn-modal-btn" id="addAgentBtn" style="padding:8px 18px;font-size:13px;">+ Add Agent</button>
|
|
167
|
+
</div>
|
|
168
|
+
<div class="agent-list" id="agentList"></div>
|
|
169
|
+
<div id="agentEmptyState" style="display:none;text-align:center;padding:30px;color:var(--text-secondary);font-size:14px;">
|
|
170
|
+
No agents configured yet. Click "+ Add Agent" to get started.
|
|
171
|
+
</div>
|
|
172
|
+
<div class="agent-chat-panel" id="agentChatPanel">
|
|
173
|
+
<div class="agent-chat-header">
|
|
174
|
+
<span id="agentChatTitle">Chat with Agent</span>
|
|
175
|
+
<button class="agent-chat-close" id="agentChatClose">×</button>
|
|
176
|
+
</div>
|
|
177
|
+
<div class="agent-chat-messages" id="agentChatMessages"></div>
|
|
178
|
+
<div class="agent-chat-input-row">
|
|
179
|
+
<input type="text" class="agent-chat-input" id="agentChatInput" placeholder="Type a test message...">
|
|
180
|
+
<button class="agent-chat-send" id="agentChatSendBtn">Send</button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
153
187
|
</div>
|
|
154
188
|
<div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
|
|
155
189
|
</div>
|
|
156
|
-
<div class="
|
|
190
|
+
<div class="modal-overlay" id="agentModal" style="display:none;">
|
|
191
|
+
<div class="conn-modal-content">
|
|
192
|
+
<div class="conn-modal-title" id="agentModalTitle">Add Agent</div>
|
|
193
|
+
<div id="agentFormGroup">
|
|
194
|
+
<div class="form-group" style="margin-bottom:10px;">
|
|
195
|
+
<label>Agent Type</label>
|
|
196
|
+
<div style="display:flex;gap:8px;">
|
|
197
|
+
<button class="filter-btn active" id="agentTypeA2A">A2A Agent</button>
|
|
198
|
+
<button class="filter-btn" id="agentTypeOpenClaw">OpenClaw Agent</button>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
<div class="form-group" style="margin-bottom:10px;">
|
|
202
|
+
<label for="agentUrl">Agent URL</label>
|
|
203
|
+
<div style="display:flex;gap:8px;">
|
|
204
|
+
<input type="text" id="agentUrl" placeholder="https://example.com" style="flex:1;">
|
|
205
|
+
<button class="conn-modal-btn" id="agentDiscoverBtn" style="padding:10px 16px;white-space:nowrap;font-size:13px;">Discover</button>
|
|
206
|
+
</div>
|
|
207
|
+
<div id="agentUrlHint" style="font-size:11px;color:var(--text-secondary);margin-top:4px;">Enter a URL and click Discover to auto-fill from the agent card, or fill in the fields manually.</div>
|
|
208
|
+
</div>
|
|
209
|
+
<div class="form-group" id="agentTokenGroup" style="margin-bottom:10px;display:none;">
|
|
210
|
+
<label for="agentToken">Token</label>
|
|
211
|
+
<input type="password" id="agentToken" placeholder="Gateway authentication token">
|
|
212
|
+
</div>
|
|
213
|
+
<div class="form-group" id="agentSessionKeyGroup" style="margin-bottom:10px;display:none;">
|
|
214
|
+
<label for="agentSessionKey">Default Session Key</label>
|
|
215
|
+
<input type="text" id="agentSessionKey" placeholder="e.g. agent:main:main">
|
|
216
|
+
</div>
|
|
217
|
+
<div id="agentSshTunnelGroup" style="display:none;margin-bottom:10px;">
|
|
218
|
+
<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;cursor:pointer;" id="agentSshTunnelToggleHeader">
|
|
219
|
+
<span style="font-size:12px;color:var(--text-secondary);" id="agentSshTunnelArrow">▶</span>
|
|
220
|
+
<label style="margin:0;cursor:pointer;font-size:13px;font-weight:600;color:var(--text-secondary);">SSH Tunnel</label>
|
|
221
|
+
<label class="toggle-switch" style="margin-left:auto;" onclick="event.stopPropagation();">
|
|
222
|
+
<input type="checkbox" id="agentSshTunnelEnabled">
|
|
223
|
+
<span class="toggle-slider"></span>
|
|
224
|
+
</label>
|
|
225
|
+
</div>
|
|
226
|
+
<div id="agentSshTunnelFields" style="display:none;padding-left:4px;">
|
|
227
|
+
<div class="form-group" style="margin-bottom:8px;">
|
|
228
|
+
<label for="agentSshCommand" style="font-size:12px;">SSH Command</label>
|
|
229
|
+
<input type="text" id="agentSshCommand" placeholder="ssh -p 22 -N -L 18789:127.0.0.1:43901 root@0.0.0.0">
|
|
230
|
+
</div>
|
|
231
|
+
<div class="form-group" style="margin-bottom:8px;">
|
|
232
|
+
<label for="agentSshPassword" style="font-size:12px;">Password</label>
|
|
233
|
+
<input type="password" id="agentSshPassword" placeholder="SSH password">
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
<div class="form-group" style="margin-bottom:10px;">
|
|
238
|
+
<label for="agentName">Name</label>
|
|
239
|
+
<input type="text" id="agentName" placeholder="My Agent">
|
|
240
|
+
</div>
|
|
241
|
+
<div class="form-group" style="margin-bottom:10px;">
|
|
242
|
+
<label for="agentDescription">Description</label>
|
|
243
|
+
<textarea id="agentDescription" placeholder="Describe what this agent does and when to use it..." style="min-height:60px;"></textarea>
|
|
244
|
+
</div>
|
|
245
|
+
<div id="agentSkillsPreview" style="display:none;padding:10px;border-radius:8px;border:1px solid var(--border-color);background:rgba(15,15,35,.3);margin-bottom:10px;">
|
|
246
|
+
<div style="font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:4px;">Discovered Skills</div>
|
|
247
|
+
<div id="agentSkillsList" style="font-size:12px;color:var(--text-secondary);"></div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="conn-modal-actions">
|
|
251
|
+
<button class="conn-modal-btn" id="agentSaveBtn">Save</button>
|
|
252
|
+
<button class="conn-modal-btn cancel" id="agentCancelBtn">Cancel</button>
|
|
253
|
+
<button class="conn-modal-btn remove" id="agentRemoveBtn" style="display:none;">Remove</button>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
<div class="modal-overlay" id="connectorModal" style="display:none;">
|
|
157
258
|
<div class="conn-modal-content">
|
|
158
259
|
<div class="conn-modal-title" id="connectorModalTitle"></div>
|
|
159
260
|
<div class="conn-modal-desc" id="connectorModalDesc"></div>
|
|
261
|
+
<div id="connectorOnboarding" style="display:none;">
|
|
262
|
+
<a id="connectorOnboardingLink" href="#" target="_blank"
|
|
263
|
+
style="color:var(--accent-tertiary);font-size:13px;font-weight:500;text-decoration:none;transition:.3s;">
|
|
264
|
+
Get your API key →
|
|
265
|
+
</a>
|
|
266
|
+
<ol id="connectorOnboardingSteps"
|
|
267
|
+
style="font-size:13px;color:var(--text-secondary);margin:8px 0 0;padding-left:20px;line-height:1.8;">
|
|
268
|
+
</ol>
|
|
269
|
+
</div>
|
|
160
270
|
<div id="connectorApiKeyGroup" class="form-group">
|
|
161
271
|
<label for="connectorApiKey">API Key</label>
|
|
162
272
|
<input type="password" id="connectorApiKey" placeholder="Enter your API key">
|
|
@@ -231,46 +341,223 @@ document.querySelectorAll('.accordion-header').forEach(function(header) {
|
|
|
231
341
|
// --- URL param: open requested tab ---
|
|
232
342
|
var params = new URLSearchParams(window.location.search);
|
|
233
343
|
var tabParam = params.get('tab');
|
|
234
|
-
if (tabParam && ['general', 'models', 'connectors'].indexOf(tabParam) !== -1) {
|
|
344
|
+
if (tabParam && ['general', 'models', 'connectors', 'agents'].indexOf(tabParam) !== -1) {
|
|
235
345
|
openSection(tabParam);
|
|
236
346
|
}
|
|
237
347
|
|
|
238
348
|
// --- Connectors logic ---
|
|
239
349
|
var connectorList = [], activeConnectorCategory = 'All', currentConnectorId = null;
|
|
350
|
+
var connVisibleCats = [], connOverflowCats = [];
|
|
351
|
+
|
|
352
|
+
// MRU: most-recently-used categories get priority for visible slots
|
|
353
|
+
var connMru = (function() {
|
|
354
|
+
try { return JSON.parse(localStorage.getItem('synthos_connMru')) || []; }
|
|
355
|
+
catch(e) { return []; }
|
|
356
|
+
})();
|
|
357
|
+
function connMruTouch(cat) {
|
|
358
|
+
if (cat === 'All' || cat === 'Enabled') return;
|
|
359
|
+
connMru = connMru.filter(function(c) { return c !== cat; });
|
|
360
|
+
connMru.unshift(cat);
|
|
361
|
+
if (connMru.length > 20) connMru.length = 20;
|
|
362
|
+
try { localStorage.setItem('synthos_connMru', JSON.stringify(connMru)); } catch(e) {}
|
|
363
|
+
}
|
|
240
364
|
|
|
241
|
-
function
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
365
|
+
function getAllConnectorCategories() {
|
|
366
|
+
var cats = new Set();
|
|
367
|
+
connectorList.forEach(function(c) { cats.add(c.category); });
|
|
368
|
+
return Array.from(cats).sort();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function calculateConnectorVisibleCats() {
|
|
372
|
+
var allCats = getAllConnectorCategories();
|
|
373
|
+
var filterBar = document.getElementById('connectorFilterBar');
|
|
374
|
+
var searchEl = document.getElementById('connectorSearch');
|
|
375
|
+
var moreDropdown = document.getElementById('connMoreDropdown');
|
|
376
|
+
if (!filterBar) return;
|
|
377
|
+
|
|
378
|
+
var availableWidth = filterBar.offsetWidth - (searchEl.offsetWidth + 8) - 16;
|
|
379
|
+
|
|
380
|
+
// Measure button widths
|
|
381
|
+
var temp = document.createElement('button');
|
|
382
|
+
temp.className = 'filter-btn';
|
|
383
|
+
temp.style.visibility = 'hidden';
|
|
384
|
+
temp.style.position = 'absolute';
|
|
385
|
+
document.body.appendChild(temp);
|
|
386
|
+
|
|
387
|
+
// Measure "All" button
|
|
388
|
+
temp.textContent = 'All';
|
|
389
|
+
var allBtnWidth = temp.offsetWidth + 8;
|
|
390
|
+
|
|
391
|
+
// Measure "Enabled" button (always shown)
|
|
392
|
+
temp.textContent = 'Enabled';
|
|
393
|
+
var enabledBtnWidth = temp.offsetWidth + 8;
|
|
394
|
+
|
|
395
|
+
// Measure "More" button
|
|
396
|
+
temp.textContent = 'More \u25BE';
|
|
397
|
+
var moreBtnWidth = temp.offsetWidth + 8;
|
|
398
|
+
|
|
399
|
+
// Measure each category button
|
|
400
|
+
var catWidths = {};
|
|
401
|
+
allCats.forEach(function(cat) {
|
|
402
|
+
temp.textContent = cat;
|
|
403
|
+
catWidths[cat] = temp.offsetWidth + 8;
|
|
404
|
+
});
|
|
405
|
+
document.body.removeChild(temp);
|
|
406
|
+
|
|
407
|
+
// Sort categories: MRU first, then alphabetical
|
|
408
|
+
var sorted = allCats.slice().sort(function(a, b) {
|
|
409
|
+
var ai = connMru.indexOf(a);
|
|
410
|
+
var bi = connMru.indexOf(b);
|
|
411
|
+
var aInMru = ai !== -1;
|
|
412
|
+
var bInMru = bi !== -1;
|
|
413
|
+
if (aInMru && !bInMru) return -1;
|
|
414
|
+
if (!aInMru && bInMru) return 1;
|
|
415
|
+
if (aInMru && bInMru) return ai - bi;
|
|
416
|
+
return a.localeCompare(b);
|
|
246
417
|
});
|
|
418
|
+
|
|
419
|
+
connVisibleCats = [];
|
|
420
|
+
connOverflowCats = [];
|
|
421
|
+
var usedWidth = allBtnWidth + enabledBtnWidth;
|
|
422
|
+
var overflowing = false;
|
|
423
|
+
|
|
424
|
+
for (var i = 0; i < sorted.length; i++) {
|
|
425
|
+
var cat = sorted[i];
|
|
426
|
+
var remaining = sorted.length - i;
|
|
427
|
+
// When we'd start overflowing, reserve space for the More button
|
|
428
|
+
var widthIfAdded = usedWidth + catWidths[cat];
|
|
429
|
+
if (!overflowing && remaining > 1) widthIfAdded += moreBtnWidth;
|
|
430
|
+
|
|
431
|
+
if (!overflowing && usedWidth + catWidths[cat] <= availableWidth - (remaining > 1 ? moreBtnWidth : 0)) {
|
|
432
|
+
connVisibleCats.push(cat);
|
|
433
|
+
usedWidth += catWidths[cat];
|
|
434
|
+
} else {
|
|
435
|
+
overflowing = true;
|
|
436
|
+
connOverflowCats.push(cat);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// If only one overflow, try to fit it without the More button
|
|
441
|
+
if (connOverflowCats.length === 1) {
|
|
442
|
+
if (usedWidth + catWidths[connOverflowCats[0]] <= availableWidth) {
|
|
443
|
+
connVisibleCats.push(connOverflowCats.pop());
|
|
444
|
+
}
|
|
445
|
+
}
|
|
247
446
|
}
|
|
248
447
|
|
|
249
448
|
function renderConnectorFilterBar() {
|
|
449
|
+
calculateConnectorVisibleCats();
|
|
250
450
|
var container = document.getElementById('connectorFilterButtons');
|
|
451
|
+
var moreDropdown = document.getElementById('connMoreDropdown');
|
|
452
|
+
var moreBtn = document.getElementById('connMoreBtn');
|
|
453
|
+
var moreMenu = document.getElementById('connMoreMenu');
|
|
251
454
|
container.innerHTML = '';
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
455
|
+
moreMenu.innerHTML = '';
|
|
456
|
+
|
|
457
|
+
// "All" button
|
|
458
|
+
var allBtn = document.createElement('button');
|
|
459
|
+
allBtn.className = 'filter-btn' + (activeConnectorCategory === 'All' ? ' active' : '');
|
|
460
|
+
allBtn.textContent = 'All';
|
|
461
|
+
allBtn.addEventListener('click', function() { setConnectorCategory('All'); });
|
|
462
|
+
container.appendChild(allBtn);
|
|
463
|
+
|
|
464
|
+
// "Enabled" button (fixed, always visible)
|
|
465
|
+
var enabledBtn = document.createElement('button');
|
|
466
|
+
enabledBtn.className = 'filter-btn' + (activeConnectorCategory === 'Enabled' ? ' active' : '');
|
|
467
|
+
enabledBtn.textContent = 'Enabled';
|
|
468
|
+
enabledBtn.addEventListener('click', function() { setConnectorCategory('Enabled'); });
|
|
469
|
+
container.appendChild(enabledBtn);
|
|
470
|
+
|
|
471
|
+
// Visible category buttons
|
|
472
|
+
connVisibleCats.forEach(function(cat) {
|
|
256
473
|
var btn = document.createElement('button');
|
|
257
474
|
btn.className = 'filter-btn' + (activeConnectorCategory === cat ? ' active' : '');
|
|
258
475
|
btn.textContent = cat;
|
|
259
|
-
btn.addEventListener('click', function() {
|
|
260
|
-
activeConnectorCategory = cat;
|
|
261
|
-
renderConnectorFilterBar();
|
|
262
|
-
renderConnectorGrid();
|
|
263
|
-
});
|
|
476
|
+
btn.addEventListener('click', function() { setConnectorCategory(cat); });
|
|
264
477
|
container.appendChild(btn);
|
|
265
478
|
});
|
|
479
|
+
|
|
480
|
+
// Overflow dropdown
|
|
481
|
+
if (connOverflowCats.length > 0) {
|
|
482
|
+
moreDropdown.style.display = '';
|
|
483
|
+
moreBtn.className = 'filter-btn more-btn' + (connOverflowCats.indexOf(activeConnectorCategory) !== -1 ? ' active' : '');
|
|
484
|
+
connOverflowCats.forEach(function(cat) {
|
|
485
|
+
var item = document.createElement('div');
|
|
486
|
+
item.className = 'more-menu-item' + (activeConnectorCategory === cat ? ' active' : '');
|
|
487
|
+
item.textContent = cat;
|
|
488
|
+
item.addEventListener('click', function() {
|
|
489
|
+
setConnectorCategory(cat);
|
|
490
|
+
moreMenu.classList.remove('show');
|
|
491
|
+
});
|
|
492
|
+
moreMenu.appendChild(item);
|
|
493
|
+
});
|
|
494
|
+
} else {
|
|
495
|
+
moreDropdown.style.display = 'none';
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function setConnectorCategory(cat) {
|
|
500
|
+
activeConnectorCategory = cat;
|
|
501
|
+
connMruTouch(cat);
|
|
502
|
+
renderConnectorFilterBar();
|
|
503
|
+
renderConnectorGrid();
|
|
266
504
|
}
|
|
267
505
|
|
|
506
|
+
function loadConnectors() {
|
|
507
|
+
fetch('/api/connectors').then(function(r) { return r.json(); }).then(function(list) {
|
|
508
|
+
connectorList = list;
|
|
509
|
+
renderConnectorFilterBar();
|
|
510
|
+
renderConnectorGrid();
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// --- Connector tooltip ---
|
|
515
|
+
var connTip = document.createElement('div');
|
|
516
|
+
connTip.className = 'conn-tooltip';
|
|
517
|
+
document.body.appendChild(connTip);
|
|
518
|
+
var connTipTimer = null;
|
|
519
|
+
|
|
520
|
+
function showConnTip(el, text) {
|
|
521
|
+
clearTimeout(connTipTimer);
|
|
522
|
+
connTip.textContent = text;
|
|
523
|
+
connTip.style.display = 'block';
|
|
524
|
+
connTip.classList.remove('visible');
|
|
525
|
+
var r = el.getBoundingClientRect();
|
|
526
|
+
var tw = connTip.offsetWidth;
|
|
527
|
+
var th = connTip.offsetHeight;
|
|
528
|
+
// Position below the tile by default
|
|
529
|
+
var left = r.left + (r.width / 2) - (tw / 2);
|
|
530
|
+
var top = r.bottom + 6;
|
|
531
|
+
// Clamp horizontal
|
|
532
|
+
if (left < 4) left = 4;
|
|
533
|
+
if (left + tw > window.innerWidth - 4) left = window.innerWidth - tw - 4;
|
|
534
|
+
// Flip above if it would go off bottom
|
|
535
|
+
if (top + th > window.innerHeight - 4) {
|
|
536
|
+
top = r.top - th - 6;
|
|
537
|
+
}
|
|
538
|
+
connTip.style.left = left + 'px';
|
|
539
|
+
connTip.style.top = top + 'px';
|
|
540
|
+
void connTip.offsetWidth;
|
|
541
|
+
connTip.classList.add('visible');
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function hideConnTip() {
|
|
545
|
+
clearTimeout(connTipTimer);
|
|
546
|
+
connTip.classList.remove('visible');
|
|
547
|
+
connTip.style.display = 'none';
|
|
548
|
+
}
|
|
549
|
+
hideConnTip();
|
|
550
|
+
|
|
268
551
|
function renderConnectorGrid() {
|
|
269
552
|
var grid = document.getElementById('connectorGrid');
|
|
270
553
|
var searchTerm = (document.getElementById('connectorSearch').value || '').toLowerCase();
|
|
271
554
|
grid.innerHTML = '';
|
|
272
555
|
connectorList.filter(function(c) {
|
|
273
|
-
if (activeConnectorCategory
|
|
556
|
+
if (activeConnectorCategory === 'Enabled') {
|
|
557
|
+
if (!c.configured) return false;
|
|
558
|
+
} else if (activeConnectorCategory !== 'All' && c.category !== activeConnectorCategory) {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
274
561
|
if (searchTerm && c.name.toLowerCase().indexOf(searchTerm) === -1) return false;
|
|
275
562
|
return true;
|
|
276
563
|
}).forEach(function(c) {
|
|
@@ -278,6 +565,11 @@ function renderConnectorGrid() {
|
|
|
278
565
|
tile.className = 'connector-tile' + (c.configured ? ' configured' : '');
|
|
279
566
|
tile.addEventListener('click', function() { openConnectorModal(c.id); });
|
|
280
567
|
|
|
568
|
+
tile.addEventListener('mouseenter', function() {
|
|
569
|
+
connTipTimer = setTimeout(function() { showConnTip(tile, c.description); }, 400);
|
|
570
|
+
});
|
|
571
|
+
tile.addEventListener('mouseleave', hideConnTip);
|
|
572
|
+
|
|
281
573
|
var name = document.createElement('div');
|
|
282
574
|
name.className = 'connector-tile-name';
|
|
283
575
|
name.textContent = c.name;
|
|
@@ -300,6 +592,19 @@ function openConnectorModal(id) {
|
|
|
300
592
|
currentConnectorDetail = detail;
|
|
301
593
|
document.getElementById('connectorModalTitle').textContent = detail.name;
|
|
302
594
|
document.getElementById('connectorModalDesc').textContent = detail.description;
|
|
595
|
+
|
|
596
|
+
var onboardingEl = document.getElementById('connectorOnboarding');
|
|
597
|
+
if (detail.onboarding && detail.onboarding.url) {
|
|
598
|
+
document.getElementById('connectorOnboardingLink').href = detail.onboarding.url;
|
|
599
|
+
var stepsOl = document.getElementById('connectorOnboardingSteps');
|
|
600
|
+
stepsOl.innerHTML = (detail.onboarding.steps || []).map(function(s) {
|
|
601
|
+
return '<li>' + s + '</li>';
|
|
602
|
+
}).join('');
|
|
603
|
+
onboardingEl.style.display = '';
|
|
604
|
+
} else {
|
|
605
|
+
onboardingEl.style.display = 'none';
|
|
606
|
+
}
|
|
607
|
+
|
|
303
608
|
document.getElementById('connectorEnabled').checked = detail.enabled;
|
|
304
609
|
document.getElementById('connectorRemoveBtn').style.display = (detail.configured || detail.hasKey) ? '' : 'none';
|
|
305
610
|
|
|
@@ -381,8 +686,11 @@ function closeConnectorModal() {
|
|
|
381
686
|
|
|
382
687
|
document.getElementById('connectorCancelBtn').addEventListener('click', closeConnectorModal);
|
|
383
688
|
|
|
689
|
+
var connectorModalMouseDownTarget = null;
|
|
690
|
+
document.getElementById('connectorModal').addEventListener('mousedown', function(e) { connectorModalMouseDownTarget = e.target; });
|
|
384
691
|
document.getElementById('connectorModal').addEventListener('click', function(e) {
|
|
385
|
-
if (e.target === this) closeConnectorModal();
|
|
692
|
+
if (e.target === this && connectorModalMouseDownTarget === this) closeConnectorModal();
|
|
693
|
+
connectorModalMouseDownTarget = null;
|
|
386
694
|
});
|
|
387
695
|
|
|
388
696
|
document.getElementById('connectorSaveBtn').addEventListener('click', function() {
|
|
@@ -454,6 +762,24 @@ document.getElementById('connectorRemoveBtn').addEventListener('click', function
|
|
|
454
762
|
|
|
455
763
|
document.getElementById('connectorSearch').addEventListener('input', renderConnectorGrid);
|
|
456
764
|
|
|
765
|
+
// More dropdown toggle
|
|
766
|
+
document.getElementById('connMoreBtn').addEventListener('click', function(e) {
|
|
767
|
+
e.stopPropagation();
|
|
768
|
+
document.getElementById('connMoreMenu').classList.toggle('show');
|
|
769
|
+
});
|
|
770
|
+
document.addEventListener('click', function() {
|
|
771
|
+
document.getElementById('connMoreMenu').classList.remove('show');
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// Resize observer — recalculate visible categories when filter bar resizes
|
|
775
|
+
var connFilterBar = document.getElementById('connectorFilterBar');
|
|
776
|
+
if (connFilterBar && typeof ResizeObserver !== 'undefined') {
|
|
777
|
+
var connResizeObserver = new ResizeObserver(function() {
|
|
778
|
+
if (connectorList.length > 0) renderConnectorFilterBar();
|
|
779
|
+
});
|
|
780
|
+
connResizeObserver.observe(connFilterBar);
|
|
781
|
+
}
|
|
782
|
+
|
|
457
783
|
// Detect OAuth success/error from URL params
|
|
458
784
|
var connectedParam = params.get('connected');
|
|
459
785
|
var errorParam = params.get('error');
|
|
@@ -474,6 +800,475 @@ if (errorParam) {
|
|
|
474
800
|
history.replaceState(null, '', cleanUrl2);
|
|
475
801
|
}
|
|
476
802
|
|
|
803
|
+
// --- Agents logic ---
|
|
804
|
+
var agentList = [], currentAgentId = null, currentAgentSkills = null, currentAgentCapabilities = null;
|
|
805
|
+
var currentAgentType = 'a2a';
|
|
806
|
+
var chatAgentId = null;
|
|
807
|
+
|
|
808
|
+
function loadAgents() {
|
|
809
|
+
fetch('/api/agents').then(function(r) { return r.json(); }).then(function(list) {
|
|
810
|
+
agentList = list;
|
|
811
|
+
renderAgentList();
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
function renderAgentList() {
|
|
816
|
+
var listEl = document.getElementById('agentList');
|
|
817
|
+
var emptyState = document.getElementById('agentEmptyState');
|
|
818
|
+
listEl.innerHTML = '';
|
|
819
|
+
listEl.style.display = agentList.length === 0 ? 'none' : '';
|
|
820
|
+
emptyState.style.display = agentList.length === 0 ? '' : 'none';
|
|
821
|
+
|
|
822
|
+
agentList.forEach(function(a) {
|
|
823
|
+
var row = document.createElement('div');
|
|
824
|
+
row.className = 'agent-row';
|
|
825
|
+
|
|
826
|
+
// Status dot (openclaw only)
|
|
827
|
+
if (a.provider === 'openclaw') {
|
|
828
|
+
var dot = document.createElement('div');
|
|
829
|
+
dot.className = 'agent-status-dot ' + (a.connected ? 'connected' : 'disconnected');
|
|
830
|
+
dot.title = a.connected ? 'Connected' : 'Disconnected';
|
|
831
|
+
row.appendChild(dot);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Info section
|
|
835
|
+
var info = document.createElement('div');
|
|
836
|
+
info.className = 'agent-row-info';
|
|
837
|
+
|
|
838
|
+
var nameEl = document.createElement('div');
|
|
839
|
+
nameEl.className = 'agent-row-name';
|
|
840
|
+
nameEl.textContent = a.name;
|
|
841
|
+
|
|
842
|
+
var descEl = document.createElement('div');
|
|
843
|
+
descEl.className = 'agent-row-desc';
|
|
844
|
+
descEl.textContent = a.description || '';
|
|
845
|
+
|
|
846
|
+
info.appendChild(nameEl);
|
|
847
|
+
info.appendChild(descEl);
|
|
848
|
+
row.appendChild(info);
|
|
849
|
+
|
|
850
|
+
// Badge
|
|
851
|
+
var badge = document.createElement('div');
|
|
852
|
+
badge.className = 'agent-row-badge';
|
|
853
|
+
badge.textContent = a.provider === 'openclaw' ? 'OpenClaw' : 'A2A';
|
|
854
|
+
row.appendChild(badge);
|
|
855
|
+
|
|
856
|
+
// Actions
|
|
857
|
+
var actions = document.createElement('div');
|
|
858
|
+
actions.className = 'agent-row-actions';
|
|
859
|
+
|
|
860
|
+
// Chat or Reconnect button (depending on connection state)
|
|
861
|
+
var isDisconnected = a.provider === 'openclaw' && a.enabled !== false && !a.connected;
|
|
862
|
+
var chatBtn = document.createElement('button');
|
|
863
|
+
chatBtn.className = 'filter-btn';
|
|
864
|
+
chatBtn.style.fontSize = '12px';
|
|
865
|
+
chatBtn.style.padding = '4px 10px';
|
|
866
|
+
if (isDisconnected) {
|
|
867
|
+
chatBtn.textContent = 'Reconnect';
|
|
868
|
+
chatBtn.addEventListener('click', (function(agent) {
|
|
869
|
+
return function(e) {
|
|
870
|
+
e.stopPropagation();
|
|
871
|
+
chatBtn.disabled = true;
|
|
872
|
+
chatBtn.textContent = 'Connecting...';
|
|
873
|
+
fetch('/api/agents/' + encodeURIComponent(agent.id) + '/connect', { method: 'POST' })
|
|
874
|
+
.then(function() { loadAgents(); })
|
|
875
|
+
.catch(function() { chatBtn.disabled = false; chatBtn.textContent = 'Reconnect'; });
|
|
876
|
+
};
|
|
877
|
+
})(a));
|
|
878
|
+
} else {
|
|
879
|
+
chatBtn.textContent = 'Chat';
|
|
880
|
+
chatBtn.addEventListener('click', function(e) {
|
|
881
|
+
e.stopPropagation();
|
|
882
|
+
openAgentChat(a);
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
actions.appendChild(chatBtn);
|
|
886
|
+
|
|
887
|
+
// Edit button
|
|
888
|
+
var editBtn = document.createElement('button');
|
|
889
|
+
editBtn.className = 'filter-btn';
|
|
890
|
+
editBtn.textContent = 'Edit';
|
|
891
|
+
editBtn.style.fontSize = '12px';
|
|
892
|
+
editBtn.style.padding = '4px 10px';
|
|
893
|
+
editBtn.addEventListener('click', function(e) {
|
|
894
|
+
e.stopPropagation();
|
|
895
|
+
openAgentEditModal(a);
|
|
896
|
+
});
|
|
897
|
+
actions.appendChild(editBtn);
|
|
898
|
+
|
|
899
|
+
// Enable/disable toggle
|
|
900
|
+
var toggleLabel = document.createElement('label');
|
|
901
|
+
toggleLabel.className = 'toggle-switch';
|
|
902
|
+
var toggleInput = document.createElement('input');
|
|
903
|
+
toggleInput.type = 'checkbox';
|
|
904
|
+
toggleInput.checked = a.enabled !== false;
|
|
905
|
+
toggleInput.addEventListener('click', function(e) { e.stopPropagation(); });
|
|
906
|
+
toggleInput.addEventListener('change', (function(agentId, inp) {
|
|
907
|
+
return function() {
|
|
908
|
+
fetch('/api/agents/' + encodeURIComponent(agentId), {
|
|
909
|
+
method: 'PATCH',
|
|
910
|
+
headers: { 'Content-Type': 'application/json' },
|
|
911
|
+
body: JSON.stringify({ enabled: inp.checked })
|
|
912
|
+
}).then(function() { loadAgents(); });
|
|
913
|
+
};
|
|
914
|
+
})(a.id, toggleInput));
|
|
915
|
+
var toggleSlider = document.createElement('span');
|
|
916
|
+
toggleSlider.className = 'toggle-slider';
|
|
917
|
+
toggleLabel.appendChild(toggleInput);
|
|
918
|
+
toggleLabel.appendChild(toggleSlider);
|
|
919
|
+
actions.appendChild(toggleLabel);
|
|
920
|
+
|
|
921
|
+
row.appendChild(actions);
|
|
922
|
+
listEl.appendChild(row);
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// --- Agent quick chat ---
|
|
927
|
+
function openAgentChat(agent) {
|
|
928
|
+
chatAgentId = agent.id;
|
|
929
|
+
document.getElementById('agentChatTitle').textContent = 'Chat with ' + agent.name;
|
|
930
|
+
document.getElementById('agentChatMessages').innerHTML = '';
|
|
931
|
+
document.getElementById('agentChatInput').value = '';
|
|
932
|
+
var panel = document.getElementById('agentChatPanel');
|
|
933
|
+
panel.classList.add('open');
|
|
934
|
+
document.getElementById('agentChatInput').focus();
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
function closeAgentChat() {
|
|
938
|
+
chatAgentId = null;
|
|
939
|
+
document.getElementById('agentChatPanel').classList.remove('open');
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
function addChatMsg(role, text) {
|
|
943
|
+
var msgs = document.getElementById('agentChatMessages');
|
|
944
|
+
var div = document.createElement('div');
|
|
945
|
+
div.className = 'agent-chat-msg ' + role;
|
|
946
|
+
div.textContent = text;
|
|
947
|
+
msgs.appendChild(div);
|
|
948
|
+
msgs.scrollTop = msgs.scrollHeight;
|
|
949
|
+
return div;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function sendAgentChatMessage() {
|
|
953
|
+
if (!chatAgentId) return;
|
|
954
|
+
var input = document.getElementById('agentChatInput');
|
|
955
|
+
var message = input.value.trim();
|
|
956
|
+
if (!message) return;
|
|
957
|
+
|
|
958
|
+
input.value = '';
|
|
959
|
+
addChatMsg('user', message);
|
|
960
|
+
|
|
961
|
+
var sendBtn = document.getElementById('agentChatSendBtn');
|
|
962
|
+
sendBtn.disabled = true;
|
|
963
|
+
sendBtn.textContent = '...';
|
|
964
|
+
|
|
965
|
+
// Check if agent supports streaming
|
|
966
|
+
var agent = agentList.find(function(a) { return a.id === chatAgentId; });
|
|
967
|
+
var supportsStreaming = agent && agent.capabilities && agent.capabilities.streaming;
|
|
968
|
+
|
|
969
|
+
if (supportsStreaming) {
|
|
970
|
+
// Use streaming
|
|
971
|
+
var responseDiv = addChatMsg('agent', '');
|
|
972
|
+
var responseText = '';
|
|
973
|
+
|
|
974
|
+
fetch('/api/agents/' + encodeURIComponent(chatAgentId) + '/stream', {
|
|
975
|
+
method: 'POST',
|
|
976
|
+
headers: { 'Content-Type': 'application/json' },
|
|
977
|
+
body: JSON.stringify({ message: message })
|
|
978
|
+
}).then(function(res) {
|
|
979
|
+
if (!res.ok) return res.json().then(function(d) { throw new Error(d.error || 'Send failed'); });
|
|
980
|
+
var reader = res.body.getReader();
|
|
981
|
+
var decoder = new TextDecoder();
|
|
982
|
+
var buffer = '';
|
|
983
|
+
function pump() {
|
|
984
|
+
return reader.read().then(function(result) {
|
|
985
|
+
if (result.done) { sendBtn.disabled = false; sendBtn.textContent = 'Send'; return; }
|
|
986
|
+
buffer += decoder.decode(result.value, { stream: true });
|
|
987
|
+
var lines = buffer.split('\n');
|
|
988
|
+
buffer = lines.pop() || '';
|
|
989
|
+
for (var i = 0; i < lines.length; i++) {
|
|
990
|
+
var line = lines[i];
|
|
991
|
+
if (line.indexOf('data: ') === 0) {
|
|
992
|
+
var data = line.substring(6);
|
|
993
|
+
if (data === '[DONE]') { sendBtn.disabled = false; sendBtn.textContent = 'Send'; return; }
|
|
994
|
+
try {
|
|
995
|
+
var evt = JSON.parse(data);
|
|
996
|
+
if (evt.kind === 'text' && evt.data) {
|
|
997
|
+
responseText += evt.data;
|
|
998
|
+
responseDiv.textContent = responseText;
|
|
999
|
+
document.getElementById('agentChatMessages').scrollTop = document.getElementById('agentChatMessages').scrollHeight;
|
|
1000
|
+
} else if (evt.kind === 'error') {
|
|
1001
|
+
addChatMsg('error', 'Error: ' + (evt.data || 'Unknown error'));
|
|
1002
|
+
sendBtn.disabled = false; sendBtn.textContent = 'Send';
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
} catch (e) {}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
return pump();
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
return pump();
|
|
1012
|
+
}).catch(function(err) {
|
|
1013
|
+
if (!responseText) responseDiv.remove();
|
|
1014
|
+
addChatMsg('error', 'Error: ' + err.message);
|
|
1015
|
+
sendBtn.disabled = false; sendBtn.textContent = 'Send';
|
|
1016
|
+
});
|
|
1017
|
+
} else {
|
|
1018
|
+
// Non-streaming
|
|
1019
|
+
addChatMsg('status', 'Waiting for response...');
|
|
1020
|
+
fetch('/api/agents/' + encodeURIComponent(chatAgentId) + '/send', {
|
|
1021
|
+
method: 'POST',
|
|
1022
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1023
|
+
body: JSON.stringify({ message: message })
|
|
1024
|
+
}).then(function(r) {
|
|
1025
|
+
if (!r.ok) return r.json().then(function(d) { throw new Error(d.error || 'Send failed'); });
|
|
1026
|
+
return r.json();
|
|
1027
|
+
}).then(function(result) {
|
|
1028
|
+
// Remove "waiting" status
|
|
1029
|
+
var msgs = document.getElementById('agentChatMessages');
|
|
1030
|
+
var last = msgs.lastElementChild;
|
|
1031
|
+
if (last && last.classList.contains('status')) last.remove();
|
|
1032
|
+
addChatMsg('agent', result.text || JSON.stringify(result.raw, null, 2));
|
|
1033
|
+
}).catch(function(err) {
|
|
1034
|
+
var msgs = document.getElementById('agentChatMessages');
|
|
1035
|
+
var last = msgs.lastElementChild;
|
|
1036
|
+
if (last && last.classList.contains('status')) last.remove();
|
|
1037
|
+
addChatMsg('error', 'Error: ' + err.message);
|
|
1038
|
+
}).finally(function() {
|
|
1039
|
+
sendBtn.disabled = false; sendBtn.textContent = 'Send';
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
document.getElementById('agentChatClose').addEventListener('click', closeAgentChat);
|
|
1045
|
+
document.getElementById('agentChatSendBtn').addEventListener('click', sendAgentChatMessage);
|
|
1046
|
+
document.getElementById('agentChatInput').addEventListener('keydown', function(e) {
|
|
1047
|
+
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendAgentChatMessage(); }
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
function setAgentType(type) {
|
|
1051
|
+
currentAgentType = type;
|
|
1052
|
+
document.getElementById('agentTypeA2A').className = 'filter-btn' + (type === 'a2a' ? ' active' : '');
|
|
1053
|
+
document.getElementById('agentTypeOpenClaw').className = 'filter-btn' + (type === 'openclaw' ? ' active' : '');
|
|
1054
|
+
document.getElementById('agentTokenGroup').style.display = type === 'openclaw' ? '' : 'none';
|
|
1055
|
+
document.getElementById('agentSessionKeyGroup').style.display = type === 'openclaw' ? '' : 'none';
|
|
1056
|
+
document.getElementById('agentSshTunnelGroup').style.display = type === 'openclaw' ? '' : 'none';
|
|
1057
|
+
document.getElementById('agentUrlHint').textContent = type === 'openclaw'
|
|
1058
|
+
? 'Enter the gateway HTTP URL and token, then click Discover to verify connectivity.'
|
|
1059
|
+
: 'Enter a URL and click Discover to auto-fill from the agent card, or fill in the fields manually.';
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
function resetAgentModal() {
|
|
1063
|
+
currentAgentId = null;
|
|
1064
|
+
currentAgentSkills = null;
|
|
1065
|
+
currentAgentCapabilities = null;
|
|
1066
|
+
setAgentType('a2a');
|
|
1067
|
+
document.getElementById('agentUrl').value = '';
|
|
1068
|
+
document.getElementById('agentToken').value = '';
|
|
1069
|
+
document.getElementById('agentSessionKey').value = '';
|
|
1070
|
+
document.getElementById('agentName').value = '';
|
|
1071
|
+
document.getElementById('agentDescription').value = '';
|
|
1072
|
+
document.getElementById('agentSkillsPreview').style.display = 'none';
|
|
1073
|
+
document.getElementById('agentSkillsList').innerHTML = '';
|
|
1074
|
+
document.getElementById('agentRemoveBtn').style.display = 'none';
|
|
1075
|
+
// Reset SSH tunnel fields
|
|
1076
|
+
document.getElementById('agentSshTunnelEnabled').checked = false;
|
|
1077
|
+
document.getElementById('agentSshCommand').value = '';
|
|
1078
|
+
document.getElementById('agentSshPassword').value = '';
|
|
1079
|
+
document.getElementById('agentSshTunnelFields').style.display = 'none';
|
|
1080
|
+
document.getElementById('agentSshTunnelArrow').innerHTML = '▶';
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
function openAgentAddModal() {
|
|
1084
|
+
resetAgentModal();
|
|
1085
|
+
document.getElementById('agentModalTitle').textContent = 'Add Agent';
|
|
1086
|
+
document.getElementById('agentModal').style.display = 'flex';
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
function openAgentEditModal(agent) {
|
|
1090
|
+
resetAgentModal();
|
|
1091
|
+
currentAgentId = agent.id;
|
|
1092
|
+
setAgentType(agent.provider || 'a2a');
|
|
1093
|
+
document.getElementById('agentModalTitle').textContent = 'Edit Agent';
|
|
1094
|
+
document.getElementById('agentUrl').value = agent.url || '';
|
|
1095
|
+
document.getElementById('agentName').value = agent.name || '';
|
|
1096
|
+
document.getElementById('agentDescription').value = agent.description || '';
|
|
1097
|
+
// Token is stripped by the server — show placeholder in edit mode for openclaw
|
|
1098
|
+
if (agent.provider === 'openclaw') {
|
|
1099
|
+
document.getElementById('agentToken').placeholder = '(token saved — leave blank to keep)';
|
|
1100
|
+
document.getElementById('agentSessionKey').value = agent.sessionKey || '';
|
|
1101
|
+
// Populate SSH tunnel fields (password is stripped by server)
|
|
1102
|
+
if (agent.sshTunnel) {
|
|
1103
|
+
document.getElementById('agentSshTunnelEnabled').checked = !!agent.sshTunnel.enabled;
|
|
1104
|
+
document.getElementById('agentSshCommand').value = agent.sshTunnel.command || '';
|
|
1105
|
+
document.getElementById('agentSshPassword').placeholder = '(password saved — leave blank to keep)';
|
|
1106
|
+
if (agent.sshTunnel.enabled) {
|
|
1107
|
+
document.getElementById('agentSshTunnelFields').style.display = '';
|
|
1108
|
+
document.getElementById('agentSshTunnelArrow').innerHTML = '▼';
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
document.getElementById('agentRemoveBtn').style.display = '';
|
|
1113
|
+
document.getElementById('agentModal').style.display = 'flex';
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
function closeAgentModal() {
|
|
1117
|
+
document.getElementById('agentModal').style.display = 'none';
|
|
1118
|
+
resetAgentModal();
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
function renderSkillsList(skills) {
|
|
1122
|
+
var container = document.getElementById('agentSkillsList');
|
|
1123
|
+
var wrapper = document.getElementById('agentSkillsPreview');
|
|
1124
|
+
if (!skills || skills.length === 0) {
|
|
1125
|
+
wrapper.style.display = 'none';
|
|
1126
|
+
container.innerHTML = '';
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
wrapper.style.display = '';
|
|
1130
|
+
container.innerHTML = skills.map(function(s) {
|
|
1131
|
+
var label = s.name || s.id || 'Skill';
|
|
1132
|
+
var desc = s.description ? ' — ' + s.description : '';
|
|
1133
|
+
return '<span style="display:inline-block;padding:2px 8px;margin:2px;border-radius:8px;background:rgba(138,43,226,.15);font-size:11px;">' + label + desc + '</span>';
|
|
1134
|
+
}).join('');
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
document.getElementById('agentTypeA2A').addEventListener('click', function() { setAgentType('a2a'); });
|
|
1138
|
+
document.getElementById('agentTypeOpenClaw').addEventListener('click', function() { setAgentType('openclaw'); });
|
|
1139
|
+
|
|
1140
|
+
// SSH Tunnel collapsible section
|
|
1141
|
+
document.getElementById('agentSshTunnelToggleHeader').addEventListener('click', function() {
|
|
1142
|
+
var fields = document.getElementById('agentSshTunnelFields');
|
|
1143
|
+
var arrow = document.getElementById('agentSshTunnelArrow');
|
|
1144
|
+
var isOpen = fields.style.display !== 'none';
|
|
1145
|
+
fields.style.display = isOpen ? 'none' : '';
|
|
1146
|
+
arrow.innerHTML = isOpen ? '▶' : '▼';
|
|
1147
|
+
});
|
|
1148
|
+
document.getElementById('agentSshTunnelEnabled').addEventListener('change', function() {
|
|
1149
|
+
if (this.checked) {
|
|
1150
|
+
document.getElementById('agentSshTunnelFields').style.display = '';
|
|
1151
|
+
document.getElementById('agentSshTunnelArrow').innerHTML = '▼';
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
document.getElementById('addAgentBtn').addEventListener('click', function(e) {
|
|
1156
|
+
e.stopPropagation();
|
|
1157
|
+
openAgentAddModal();
|
|
1158
|
+
});
|
|
1159
|
+
document.getElementById('agentCancelBtn').addEventListener('click', closeAgentModal);
|
|
1160
|
+
|
|
1161
|
+
var agentModalMouseDownTarget = null;
|
|
1162
|
+
document.getElementById('agentModal').addEventListener('mousedown', function(e) { agentModalMouseDownTarget = e.target; });
|
|
1163
|
+
document.getElementById('agentModal').addEventListener('click', function(e) {
|
|
1164
|
+
if (e.target === this && agentModalMouseDownTarget === this) closeAgentModal();
|
|
1165
|
+
agentModalMouseDownTarget = null;
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
document.getElementById('agentDiscoverBtn').addEventListener('click', function() {
|
|
1169
|
+
var url = document.getElementById('agentUrl').value.trim();
|
|
1170
|
+
if (!url) return;
|
|
1171
|
+
var btn = this;
|
|
1172
|
+
btn.disabled = true;
|
|
1173
|
+
btn.textContent = 'Discovering...';
|
|
1174
|
+
|
|
1175
|
+
var body = { url: url, type: currentAgentType };
|
|
1176
|
+
if (currentAgentType === 'openclaw') {
|
|
1177
|
+
var token = document.getElementById('agentToken').value.trim();
|
|
1178
|
+
if (!token) { alert('Token is required for OpenClaw discovery.'); btn.disabled = false; btn.textContent = 'Discover'; return; }
|
|
1179
|
+
body.token = token;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
fetch('/api/agents/discover', {
|
|
1183
|
+
method: 'POST',
|
|
1184
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1185
|
+
body: JSON.stringify(body)
|
|
1186
|
+
}).then(function(r) {
|
|
1187
|
+
if (!r.ok) return r.json().then(function(d) { throw new Error(d.error || 'Discovery failed'); });
|
|
1188
|
+
return r.json();
|
|
1189
|
+
}).then(function(result) {
|
|
1190
|
+
var nameEl = document.getElementById('agentName');
|
|
1191
|
+
var descEl = document.getElementById('agentDescription');
|
|
1192
|
+
if (!nameEl.value.trim() && result.name) nameEl.value = result.name;
|
|
1193
|
+
if (!descEl.value.trim() && result.description) descEl.value = result.description;
|
|
1194
|
+
if (result.skills) {
|
|
1195
|
+
currentAgentSkills = result.skills;
|
|
1196
|
+
renderSkillsList(currentAgentSkills);
|
|
1197
|
+
}
|
|
1198
|
+
if (result.capabilities) {
|
|
1199
|
+
currentAgentCapabilities = result.capabilities;
|
|
1200
|
+
}
|
|
1201
|
+
if (currentAgentType === 'openclaw' && result.verified) {
|
|
1202
|
+
alert('Gateway verified successfully!');
|
|
1203
|
+
}
|
|
1204
|
+
}).catch(function(err) {
|
|
1205
|
+
alert('Discovery failed: ' + err.message);
|
|
1206
|
+
}).finally(function() {
|
|
1207
|
+
btn.disabled = false;
|
|
1208
|
+
btn.textContent = 'Discover';
|
|
1209
|
+
});
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
document.getElementById('agentSaveBtn').addEventListener('click', function() {
|
|
1213
|
+
var name = document.getElementById('agentName').value.trim();
|
|
1214
|
+
var url = document.getElementById('agentUrl').value.trim();
|
|
1215
|
+
var description = document.getElementById('agentDescription').value.trim();
|
|
1216
|
+
if (!name) { alert('Name is required.'); return; }
|
|
1217
|
+
if (!url) { alert('Agent URL is required.'); return; }
|
|
1218
|
+
if (!description) { alert('Description is required — explain what this agent does so pages know when to use it.'); return; }
|
|
1219
|
+
|
|
1220
|
+
var body = {
|
|
1221
|
+
url: url,
|
|
1222
|
+
name: name,
|
|
1223
|
+
description: description,
|
|
1224
|
+
enabled: true,
|
|
1225
|
+
provider: currentAgentType
|
|
1226
|
+
};
|
|
1227
|
+
if (currentAgentId) body.id = currentAgentId;
|
|
1228
|
+
if (currentAgentSkills) body.skills = currentAgentSkills;
|
|
1229
|
+
if (currentAgentCapabilities) body.capabilities = currentAgentCapabilities;
|
|
1230
|
+
|
|
1231
|
+
// Include token for openclaw agents
|
|
1232
|
+
if (currentAgentType === 'openclaw') {
|
|
1233
|
+
var token = document.getElementById('agentToken').value.trim();
|
|
1234
|
+
if (token) body.token = token;
|
|
1235
|
+
// For new openclaw agents, token is required
|
|
1236
|
+
if (!token && !currentAgentId) { alert('Token is required for OpenClaw agents.'); return; }
|
|
1237
|
+
// Set streaming capability by default for openclaw
|
|
1238
|
+
if (!body.capabilities) body.capabilities = { streaming: true };
|
|
1239
|
+
var sessionKey = document.getElementById('agentSessionKey').value.trim();
|
|
1240
|
+
if (sessionKey) body.sessionKey = sessionKey;
|
|
1241
|
+
|
|
1242
|
+
// SSH tunnel config
|
|
1243
|
+
var sshEnabled = document.getElementById('agentSshTunnelEnabled').checked;
|
|
1244
|
+
var sshCommand = document.getElementById('agentSshCommand').value.trim();
|
|
1245
|
+
var sshPassword = document.getElementById('agentSshPassword').value;
|
|
1246
|
+
if (sshEnabled || sshCommand) {
|
|
1247
|
+
body.sshTunnel = {
|
|
1248
|
+
enabled: sshEnabled,
|
|
1249
|
+
command: sshCommand
|
|
1250
|
+
};
|
|
1251
|
+
// Only include password if provided (otherwise server preserves existing)
|
|
1252
|
+
if (sshPassword) body.sshTunnel.password = sshPassword;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
fetch('/api/agents', {
|
|
1257
|
+
method: 'POST',
|
|
1258
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1259
|
+
body: JSON.stringify(body)
|
|
1260
|
+
}).then(function(r) {
|
|
1261
|
+
if (r.ok) { closeAgentModal(); loadAgents(); }
|
|
1262
|
+
});
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
document.getElementById('agentRemoveBtn').addEventListener('click', function() {
|
|
1266
|
+
if (!currentAgentId) return;
|
|
1267
|
+
fetch('/api/agents/' + encodeURIComponent(currentAgentId), { method: 'DELETE' }).then(function(r) {
|
|
1268
|
+
if (r.ok) { closeAgentModal(); loadAgents(); }
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
1271
|
+
|
|
477
1272
|
// --- Save logic ---
|
|
478
1273
|
function saveAllSettings() {
|
|
479
1274
|
var builderApiKey = document.getElementById('serviceApiKey-builder').value;
|
|
@@ -574,7 +1369,8 @@ document.getElementById('provider-chat').addEventListener('change', function() {
|
|
|
574
1369
|
// --- Provider signup instructions ---
|
|
575
1370
|
var providerInstructions = {
|
|
576
1371
|
'Anthropic': 'Sign up at <a href="https://platform.claude.com" target="_blank">platform.claude.com</a>, then get your key at <a href="https://console.anthropic.com/settings/keys" target="_blank">console.anthropic.com/settings/keys</a>.',
|
|
577
|
-
'OpenAI': 'Sign up at <a href="https://auth.openai.com/create-account" target="_blank">auth.openai.com/create-account</a>, then get your key at <a href="https://platform.openai.com/api-keys" target="_blank">platform.openai.com/api-keys</a>.'
|
|
1372
|
+
'OpenAI': 'Sign up at <a href="https://auth.openai.com/create-account" target="_blank">auth.openai.com/create-account</a>, then get your key at <a href="https://platform.openai.com/api-keys" target="_blank">platform.openai.com/api-keys</a>.',
|
|
1373
|
+
'FireworksAI': 'Sign up at <a href="https://fireworks.ai" target="_blank">fireworks.ai</a>, then get your key at <a href="https://fireworks.ai/account/api-keys" target="_blank">fireworks.ai/account/api-keys</a>.'
|
|
578
1374
|
};
|
|
579
1375
|
|
|
580
1376
|
// --- "More settings" toggle state (works for all users) ---
|
|
@@ -761,6 +1557,7 @@ Promise.all([
|
|
|
761
1557
|
document.getElementById('theme').value = currentTheme;
|
|
762
1558
|
|
|
763
1559
|
loadConnectors();
|
|
1560
|
+
loadAgents();
|
|
764
1561
|
|
|
765
1562
|
var isFirstRun = params.get('firstRun') === '1';
|
|
766
1563
|
|
|
@@ -804,6 +1601,7 @@ Promise.all([
|
|
|
804
1601
|
// Disable other accordion tabs
|
|
805
1602
|
document.querySelector('.accordion-section[data-section="general"]').classList.add('disabled');
|
|
806
1603
|
document.querySelector('.accordion-section[data-section="connectors"]').classList.add('disabled');
|
|
1604
|
+
document.querySelector('.accordion-section[data-section="agents"]').classList.add('disabled');
|
|
807
1605
|
|
|
808
1606
|
// Clear any existing values so wizard starts fresh
|
|
809
1607
|
document.getElementById('provider-builder').value = '';
|