feat(autotask): Update form to use /api/autotask/create endpoint
- Change autotask form from /compile to /create for one-click execution - Update button text to 'Create & Execute'
This commit is contained in:
parent
1df0df222f
commit
410f799fb2
5 changed files with 1259 additions and 461 deletions
|
|
@ -8,6 +8,7 @@
|
|||
<!-- HTMX (local) -->
|
||||
<script src="/js/vendor/htmx.min.js"></script>
|
||||
<script src="/js/vendor/htmx-ws.js"></script>
|
||||
<script src="/js/vendor/htmx-json-enc.js"></script>
|
||||
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" href="/css/base.css" />
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
<span class="section-icon">💡</span>
|
||||
<h2>What would you like to accomplish?</h2>
|
||||
</div>
|
||||
<form class="intent-form" id="intent-form" hx-post="/api/autotask/compile" hx-target="#compilation-result" hx-indicator="#compile-spinner">
|
||||
<form class="intent-form" id="intent-form" hx-post="/api/autotask/create" hx-target="#compilation-result" hx-indicator="#compile-spinner">
|
||||
<div class="intent-input-wrapper">
|
||||
<textarea
|
||||
name="intent"
|
||||
|
|
@ -59,9 +59,9 @@
|
|||
<option value="low">Low</option>
|
||||
<option value="background">Background</option>
|
||||
</select>
|
||||
<button type="submit" class="btn-compile">
|
||||
<button type="submit" class="btn-create">
|
||||
<span class="btn-icon">🚀</span>
|
||||
Compile & Plan
|
||||
Create & Execute
|
||||
<span class="spinner" id="compile-spinner"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,7 @@
|
|||
min-height: 0;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: var(
|
||||
--font-family,
|
||||
system-ui, -apple-system, sans-serif
|
||||
);
|
||||
font-family: var(--font-family, system-ui, -apple-system, sans-serif);
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
|
|
@ -110,7 +107,10 @@
|
|||
border: none;
|
||||
border-radius: 6px;
|
||||
color: var(--text-secondary);
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system,
|
||||
sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
|
|
@ -791,13 +791,11 @@
|
|||
}
|
||||
|
||||
.step-item:first-child {
|
||||
border-radius: 8px 8px
|
||||
6px 6px;
|
||||
border-radius: 8px 8px 6px 6px;
|
||||
}
|
||||
|
||||
.step-item:last-child {
|
||||
border-radius: 6px 6px
|
||||
8px 8px;
|
||||
border-radius: 6px 6px 8px 8px;
|
||||
}
|
||||
|
||||
.step-item:only-child {
|
||||
|
|
@ -1097,3 +1095,218 @@
|
|||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
PENDING INFO, GOALS, SCHEDULERS, MONITORS
|
||||
============================================================================= */
|
||||
|
||||
/* Status pill variants */
|
||||
.status-pill.pending-info {
|
||||
background: var(--warning-light, #fef3c7);
|
||||
color: var(--warning-dark, #92400e);
|
||||
}
|
||||
|
||||
.status-pill.goals {
|
||||
background: var(--primary-light, #dbeafe);
|
||||
color: var(--primary-dark, #1e40af);
|
||||
}
|
||||
|
||||
.status-pill.schedulers {
|
||||
background: var(--info-light, #e0e7ff);
|
||||
color: var(--info-dark, #3730a3);
|
||||
}
|
||||
|
||||
.status-pill.monitors {
|
||||
background: var(--success-light, #d1fae5);
|
||||
color: var(--success-dark, #065f46);
|
||||
}
|
||||
|
||||
/* Goal Progress Section */
|
||||
.goal-progress-section {
|
||||
padding: 16px;
|
||||
background: var(--surface-hover);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.goal-progress-bar {
|
||||
height: 12px;
|
||||
background: var(--border);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.goal-progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, var(--primary), var(--success));
|
||||
border-radius: 6px;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
.goal-progress-stats {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.goal-last-action {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* Pending Info Fill Section */
|
||||
.pending-fill-section {
|
||||
padding: 16px;
|
||||
background: var(--warning-light, #fef3c7);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid var(--warning, #f59e0b);
|
||||
}
|
||||
|
||||
.pending-reason {
|
||||
font-size: 13px;
|
||||
color: var(--warning-dark, #92400e);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.pending-fill-form .form-group {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.pending-fill-form label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.pending-fill-form .form-input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Scheduler Info Section */
|
||||
.scheduler-info-section {
|
||||
padding: 16px;
|
||||
background: var(--info-light, #e0e7ff);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.scheduler-cron {
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--info-dark, #3730a3);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.scheduler-next,
|
||||
.scheduler-file {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Monitor Info Section */
|
||||
.monitor-info-section {
|
||||
padding: 16px;
|
||||
background: var(--success-light, #d1fae5);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.monitor-target {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--success-dark, #065f46);
|
||||
margin-bottom: 8px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.monitor-interval,
|
||||
.monitor-last-check,
|
||||
.monitor-last-value {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Pending Summary Panel */
|
||||
.pending-summary-panel {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
max-width: 320px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--warning, #f59e0b);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
z-index: 100;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pending-summary-panel:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pending-summary-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
background: var(--warning-light, #fef3c7);
|
||||
border-bottom: 1px solid var(--warning, #f59e0b);
|
||||
}
|
||||
|
||||
.pending-summary-header h4 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--warning-dark, #92400e);
|
||||
}
|
||||
|
||||
.pending-summary-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.pending-summary-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.pending-summary-item:hover {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
.pending-summary-item .pending-app {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pending-summary-item .pending-field {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.pending-summary-item .pending-action {
|
||||
padding: 4px 8px;
|
||||
background: var(--primary);
|
||||
color: var(--accent-foreground, #000);
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -15,6 +15,7 @@ if (typeof TasksState === "undefined") {
|
|||
tasks: [],
|
||||
wsConnection: null,
|
||||
agentLogPaused: false,
|
||||
selectedItemType: "task", // task, goal, pending, scheduler, monitor
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -640,6 +641,238 @@ style.textContent = `
|
|||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// =============================================================================
|
||||
// GOALS, PENDING INFO, SCHEDULERS, MONITORS
|
||||
// =============================================================================
|
||||
|
||||
// Select a goal and show its details
|
||||
window.selectGoal = function (goalId) {
|
||||
TasksState.selectedItemType = "goal";
|
||||
window.selectedTaskId = goalId;
|
||||
|
||||
document.querySelectorAll(".task-item, .task-card").forEach((el) => {
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
const selectedEl = document.querySelector(`[data-goal-id="${goalId}"]`);
|
||||
if (selectedEl) {
|
||||
selectedEl.classList.add("selected");
|
||||
}
|
||||
|
||||
document.getElementById("task-detail-empty").style.display = "none";
|
||||
document.getElementById("task-detail-content").style.display = "block";
|
||||
|
||||
// Hide other sections, show goal section
|
||||
hideAllDetailSections();
|
||||
document.getElementById("goal-progress-section").style.display = "block";
|
||||
|
||||
fetch(`/api/goals/${goalId}`)
|
||||
.then((response) => response.json())
|
||||
.then((goal) => {
|
||||
document.getElementById("detail-title").textContent =
|
||||
goal.goal_text || "Untitled Goal";
|
||||
document.getElementById("detail-status-text").textContent =
|
||||
goal.status || "active";
|
||||
document.getElementById("detail-priority-text").textContent = "Goal";
|
||||
document.getElementById("detail-description").textContent =
|
||||
goal.goal_text || "";
|
||||
|
||||
const percent =
|
||||
goal.target_value > 0
|
||||
? Math.round((goal.current_value / goal.target_value) * 100)
|
||||
: 0;
|
||||
document.getElementById("goal-progress-fill").style.width = `${percent}%`;
|
||||
document.getElementById("goal-current-value").textContent =
|
||||
goal.current_value || 0;
|
||||
document.getElementById("goal-target-value").textContent =
|
||||
goal.target_value || 0;
|
||||
document.getElementById("goal-percent").textContent = percent;
|
||||
document.getElementById("goal-last-action").textContent = goal.last_action
|
||||
? `Last action: ${goal.last_action}`
|
||||
: "No actions yet";
|
||||
})
|
||||
.catch((err) => console.error("Failed to load goal:", err));
|
||||
};
|
||||
|
||||
// Select a pending info item
|
||||
window.selectPendingInfo = function (pendingId) {
|
||||
TasksState.selectedItemType = "pending";
|
||||
window.selectedTaskId = pendingId;
|
||||
|
||||
document.querySelectorAll(".task-item, .task-card").forEach((el) => {
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
const selectedEl = document.querySelector(`[data-pending-id="${pendingId}"]`);
|
||||
if (selectedEl) {
|
||||
selectedEl.classList.add("selected");
|
||||
}
|
||||
|
||||
document.getElementById("task-detail-empty").style.display = "none";
|
||||
document.getElementById("task-detail-content").style.display = "block";
|
||||
|
||||
hideAllDetailSections();
|
||||
document.getElementById("pending-fill-section").style.display = "block";
|
||||
|
||||
fetch(`/api/pending-info/${pendingId}`)
|
||||
.then((response) => response.json())
|
||||
.then((pending) => {
|
||||
document.getElementById("detail-title").textContent =
|
||||
pending.field_label || "Pending Info";
|
||||
document.getElementById("detail-status-text").textContent = "Pending";
|
||||
document.getElementById("detail-priority-text").textContent =
|
||||
pending.app_name || "";
|
||||
document.getElementById("detail-description").textContent =
|
||||
pending.reason || "";
|
||||
|
||||
document.getElementById("pending-reason").textContent =
|
||||
pending.reason || "Required for app functionality";
|
||||
document.getElementById("pending-fill-id").value = pending.id;
|
||||
document.getElementById("pending-fill-label").textContent =
|
||||
pending.field_label;
|
||||
document.getElementById("pending-fill-value").type =
|
||||
pending.field_type === "secret" ? "password" : "text";
|
||||
})
|
||||
.catch((err) => console.error("Failed to load pending info:", err));
|
||||
};
|
||||
|
||||
// Select a scheduler
|
||||
window.selectScheduler = function (schedulerName) {
|
||||
TasksState.selectedItemType = "scheduler";
|
||||
window.selectedTaskId = schedulerName;
|
||||
|
||||
document.querySelectorAll(".task-item, .task-card").forEach((el) => {
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
const selectedEl = document.querySelector(
|
||||
`[data-scheduler-name="${schedulerName}"]`,
|
||||
);
|
||||
if (selectedEl) {
|
||||
selectedEl.classList.add("selected");
|
||||
}
|
||||
|
||||
document.getElementById("task-detail-empty").style.display = "none";
|
||||
document.getElementById("task-detail-content").style.display = "block";
|
||||
|
||||
hideAllDetailSections();
|
||||
document.getElementById("scheduler-info-section").style.display = "block";
|
||||
|
||||
fetch(`/api/schedulers/${encodeURIComponent(schedulerName)}`)
|
||||
.then((response) => response.json())
|
||||
.then((scheduler) => {
|
||||
document.getElementById("detail-title").textContent =
|
||||
scheduler.name || schedulerName;
|
||||
document.getElementById("detail-status-text").textContent =
|
||||
scheduler.status || "active";
|
||||
document.getElementById("detail-priority-text").textContent = "Scheduler";
|
||||
document.getElementById("detail-description").textContent =
|
||||
scheduler.description || "";
|
||||
|
||||
document.getElementById("scheduler-cron").textContent =
|
||||
scheduler.cron || "-";
|
||||
document.getElementById("scheduler-next").textContent = scheduler.next_run
|
||||
? `Next run: ${new Date(scheduler.next_run).toLocaleString()}`
|
||||
: "Next run: -";
|
||||
document.getElementById("scheduler-file").textContent = scheduler.file
|
||||
? `File: ${scheduler.file}`
|
||||
: "File: -";
|
||||
})
|
||||
.catch((err) => console.error("Failed to load scheduler:", err));
|
||||
};
|
||||
|
||||
// Select a monitor
|
||||
window.selectMonitor = function (monitorName) {
|
||||
TasksState.selectedItemType = "monitor";
|
||||
window.selectedTaskId = monitorName;
|
||||
|
||||
document.querySelectorAll(".task-item, .task-card").forEach((el) => {
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
const selectedEl = document.querySelector(
|
||||
`[data-monitor-name="${monitorName}"]`,
|
||||
);
|
||||
if (selectedEl) {
|
||||
selectedEl.classList.add("selected");
|
||||
}
|
||||
|
||||
document.getElementById("task-detail-empty").style.display = "none";
|
||||
document.getElementById("task-detail-content").style.display = "block";
|
||||
|
||||
hideAllDetailSections();
|
||||
document.getElementById("monitor-info-section").style.display = "block";
|
||||
|
||||
fetch(`/api/monitors/${encodeURIComponent(monitorName)}`)
|
||||
.then((response) => response.json())
|
||||
.then((monitor) => {
|
||||
document.getElementById("detail-title").textContent =
|
||||
monitor.name || monitorName;
|
||||
document.getElementById("detail-status-text").textContent =
|
||||
monitor.status || "active";
|
||||
document.getElementById("detail-priority-text").textContent = "Monitor";
|
||||
document.getElementById("detail-description").textContent =
|
||||
monitor.description || "";
|
||||
|
||||
document.getElementById("monitor-target").textContent = monitor.target
|
||||
? `Target: ${monitor.target}`
|
||||
: "Target: -";
|
||||
document.getElementById("monitor-interval").textContent = monitor.interval
|
||||
? `Interval: ${monitor.interval}`
|
||||
: "Interval: -";
|
||||
document.getElementById("monitor-last-check").textContent =
|
||||
monitor.last_check
|
||||
? `Last check: ${new Date(monitor.last_check).toLocaleString()}`
|
||||
: "Last check: -";
|
||||
document.getElementById("monitor-last-value").textContent =
|
||||
monitor.last_value
|
||||
? `Last value: ${monitor.last_value}`
|
||||
: "Last value: -";
|
||||
})
|
||||
.catch((err) => console.error("Failed to load monitor:", err));
|
||||
};
|
||||
|
||||
// Hide all detail sections
|
||||
function hideAllDetailSections() {
|
||||
document.getElementById("goal-progress-section").style.display = "none";
|
||||
document.getElementById("pending-fill-section").style.display = "none";
|
||||
document.getElementById("scheduler-info-section").style.display = "none";
|
||||
document.getElementById("monitor-info-section").style.display = "none";
|
||||
}
|
||||
|
||||
// Fill pending info form submission
|
||||
document.addEventListener("htmx:afterRequest", function (event) {
|
||||
if (event.detail.elt.id === "pending-fill-form" && event.detail.successful) {
|
||||
htmx.trigger(document.body, "taskCreated");
|
||||
document.getElementById("pending-fill-value").value = "";
|
||||
addAgentLog("success", "[OK] Pending info filled successfully");
|
||||
}
|
||||
});
|
||||
|
||||
// Update counts for new filters
|
||||
function updateFilterCounts() {
|
||||
fetch("/api/tasks/stats")
|
||||
.then((response) => response.json())
|
||||
.then((stats) => {
|
||||
if (stats.pending_count !== undefined) {
|
||||
document.getElementById("count-pending").textContent =
|
||||
stats.pending_count;
|
||||
}
|
||||
if (stats.goals_count !== undefined) {
|
||||
document.getElementById("count-goals").textContent = stats.goals_count;
|
||||
}
|
||||
if (stats.schedulers_count !== undefined) {
|
||||
document.getElementById("count-schedulers").textContent =
|
||||
stats.schedulers_count;
|
||||
}
|
||||
if (stats.monitors_count !== undefined) {
|
||||
document.getElementById("count-monitors").textContent =
|
||||
stats.monitors_count;
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
// Call updateFilterCounts on load
|
||||
document.addEventListener("DOMContentLoaded", updateFilterCounts);
|
||||
document.body.addEventListener("taskCreated", updateFilterCounts);
|
||||
|
||||
// =============================================================================
|
||||
// DEMO: Simulate real-time activity
|
||||
// =============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue