- Schedules web UI (/settings/crons): list, add, edit, pause/resume, delete jobs - cron task type: full orchestrator tool loop on a schedule, result → notification channel - parse_schedule: monthly/yearly formats (monthly:DD:HH:MM, yearly:MM:DD:HH:MM) - HA inbound webhook tools toggle: orchestrator loop vs. direct LLM, configurable in UI - ae_db_query/describe/show_view: SELECT-only Aether MariaDB access (admin, per-user creds) - /settings/integrations: admin-only page for Aether DB credentials - Schedules nav link added to all settings pages - pymysql added to requirements - Docs updated: HELP.md, MASTER.md, CLAUDE.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
5.4 KiB
HTML
125 lines
5.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Cortex — Integrations</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/pg.css">
|
|
<script>(function(){var t=localStorage.getItem('theme')||(window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');document.documentElement.setAttribute('data-theme',t);})();</script>
|
|
<style>
|
|
details.channel-block {
|
|
border: 1px solid var(--pg-border); border-radius: 8px;
|
|
margin-bottom: 0.75rem; overflow: hidden;
|
|
}
|
|
details.channel-block summary {
|
|
padding: 0.75rem 1rem; font-size: 0.85rem; font-weight: 600;
|
|
color: var(--pg-muted); cursor: pointer; list-style: none;
|
|
display: flex; align-items: center; gap: 0.5rem;
|
|
user-select: none; background: var(--pg-bg);
|
|
}
|
|
details.channel-block summary::-webkit-details-marker { display: none; }
|
|
details.channel-block summary::before {
|
|
content: '▶'; font-size: 0.65rem; color: var(--pg-dimmer);
|
|
transition: transform 0.15s; flex-shrink: 0;
|
|
}
|
|
details.channel-block[open] summary::before { transform: rotate(90deg); }
|
|
details.channel-block[open] summary { border-bottom: 1px solid var(--pg-border); }
|
|
.channel-block-body { padding: 1rem 1rem 0.25rem; }
|
|
.channel-hint {
|
|
font-size: 0.75rem; color: var(--pg-dimmer);
|
|
margin-top: -0.6rem; margin-bottom: 1rem; line-height: 1.5;
|
|
}
|
|
.field-row {
|
|
display: grid; grid-template-columns: 1fr auto; gap: 0.75rem; align-items: end;
|
|
}
|
|
.field-row .field { margin-bottom: 0; }
|
|
.field-narrow input { max-width: 120px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="page-nav">
|
|
<a href="{{ back_href }}" class="nav-link">← Chat</a>
|
|
<a href="{{ help_href }}" class="nav-link">Help</a>
|
|
<a href="/settings" class="nav-link">Settings</a>
|
|
<a href="/settings/notifications" class="nav-link">Notifications</a>
|
|
<a href="/settings/tools" class="nav-link">Tools</a>
|
|
<a href="/settings/crons" class="nav-link">Schedules</a>
|
|
<a href="/settings/integrations" class="nav-link active">Integrations</a>
|
|
<span class="nav-spacer"></span>
|
|
<a href="/logout" class="nav-link nav-logout">Sign out</a>
|
|
</nav>
|
|
<div class="page-wrap">
|
|
<h1 class="page-title">Integrations</h1>
|
|
<p class="page-subtitle">External service connections — admin only.</p>
|
|
|
|
<!-- SUCCESS -->
|
|
<!-- ERROR -->
|
|
|
|
<form method="POST" action="/settings/integrations">
|
|
|
|
<!-- Aether Platform Database -->
|
|
<div class="section">
|
|
<h2>Aether Platform Database</h2>
|
|
<p class="section-note">
|
|
Gives the orchestrator direct read-only access to the Aether MariaDB via the
|
|
<code>ae_db_query</code>, <code>ae_db_describe</code>, and <code>ae_db_show_view</code> tools.
|
|
Only SELECT, SHOW, DESCRIBE, and EXPLAIN are permitted — no writes possible.
|
|
</p>
|
|
|
|
<details class="channel-block" {{ ae_db_host and 'open' or '' }}>
|
|
<summary>Connection</summary>
|
|
<div class="channel-block-body">
|
|
<p class="channel-hint">
|
|
Use the same credentials as <code>agents_sync/mcp/scripts/sql_inspector.py</code>.
|
|
The password field is left blank in the form — leave it blank to keep the stored value.
|
|
</p>
|
|
<div class="field-row">
|
|
<div class="field">
|
|
<label for="ae_db_host">Host</label>
|
|
<input type="text" id="ae_db_host" name="ae_db_host"
|
|
value="{{ ae_db_host }}"
|
|
placeholder="192.168.64.5"
|
|
autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<div class="field field-narrow">
|
|
<label for="ae_db_port">Port</label>
|
|
<input type="number" id="ae_db_port" name="ae_db_port"
|
|
value="{{ ae_db_port }}"
|
|
placeholder="3306" min="1" max="65535"
|
|
autocomplete="off">
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<label for="ae_db_name">Database name</label>
|
|
<input type="text" id="ae_db_name" name="ae_db_name"
|
|
value="{{ ae_db_name }}"
|
|
placeholder="aether_dev"
|
|
autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<div class="field">
|
|
<label for="ae_db_user">Username</label>
|
|
<input type="text" id="ae_db_user" name="ae_db_user"
|
|
value="{{ ae_db_user }}"
|
|
placeholder="aether_dev"
|
|
autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<div class="field">
|
|
<label for="ae_db_password">Password</label>
|
|
<input type="password" id="ae_db_password" name="ae_db_password"
|
|
value=""
|
|
placeholder="Leave blank to keep existing value"
|
|
autocomplete="new-password" spellcheck="false">
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-submit">Save integrations</button>
|
|
</form>
|
|
</div>
|
|
</body>
|
|
</html>
|