aimeat 1.7.0 → 1.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/dist/bin/aimeat.js +0 -0
- package/dist/locales/en.json +46 -3
- package/dist/locales/fi.json +46 -3
- package/dist/public/css/views/agents-detail.css +150 -0
- package/dist/public/css/views/profile.css +22 -2
- package/dist/public/js/services/generator-spec-validate.js +23 -0
- package/dist/public/js/services/memory.js +39 -0
- package/dist/public/views/admin/federation-tab.js +5 -5
- package/dist/public/views/admin/prompts-tab.js +9 -10
- package/dist/public/views/profile/access-tab.js +18 -0
- package/dist/public/views/profile/agents-messages-subtab.js +3 -2
- package/dist/public/views/profile/agents-tab.js +10 -6
- package/dist/public/views/profile/agents-tasks-subtab.js +123 -64
- package/dist/public/views/profile/generator-detail.js +8 -1
- package/dist/public/views/profile/memory-tab.js +371 -7
- package/dist/public/views/profile/wallet-tab.js +14 -0
- package/dist/src/models/agent-capabilities-schemas.d.ts +3 -0
- package/dist/src/models/agent-capabilities-schemas.d.ts.map +1 -1
- package/dist/src/models/agent-capabilities-schemas.js +3 -0
- package/dist/src/models/agent-capabilities-schemas.js.map +1 -1
- package/dist/src/routes/admin-monitoring.js +12 -7
- package/dist/src/routes/admin-monitoring.js.map +1 -1
- package/dist/src/routes/agent-capabilities.d.ts +1 -0
- package/dist/src/routes/agent-capabilities.d.ts.map +1 -1
- package/dist/src/routes/agent-capabilities.js +9 -0
- package/dist/src/routes/agent-capabilities.js.map +1 -1
- package/dist/src/routes/agent-tasks.d.ts +1 -0
- package/dist/src/routes/agent-tasks.d.ts.map +1 -1
- package/dist/src/routes/agent-tasks.js +9 -7
- package/dist/src/routes/agent-tasks.js.map +1 -1
- package/dist/src/routes/federation-auth.d.ts.map +1 -1
- package/dist/src/routes/federation-auth.js +3 -1
- package/dist/src/routes/federation-auth.js.map +1 -1
- package/dist/src/routes/federation-peer.d.ts.map +1 -1
- package/dist/src/routes/federation-peer.js +11 -2
- package/dist/src/routes/federation-peer.js.map +1 -1
- package/dist/src/routes/federation-sync.d.ts +1 -0
- package/dist/src/routes/federation-sync.d.ts.map +1 -1
- package/dist/src/routes/federation-sync.js +29 -0
- package/dist/src/routes/federation-sync.js.map +1 -1
- package/dist/src/routes/memory.d.ts +9 -0
- package/dist/src/routes/memory.d.ts.map +1 -1
- package/dist/src/routes/memory.js +304 -9
- package/dist/src/routes/memory.js.map +1 -1
- package/dist/src/routes/prompts.d.ts +1 -0
- package/dist/src/routes/prompts.d.ts.map +1 -1
- package/dist/src/routes/prompts.js +40 -1
- package/dist/src/routes/prompts.js.map +1 -1
- package/dist/src/routes/sharing-groups.d.ts.map +1 -1
- package/dist/src/routes/sharing-groups.js +8 -2
- package/dist/src/routes/sharing-groups.js.map +1 -1
- package/dist/src/routes/wallet.d.ts.map +1 -1
- package/dist/src/routes/wallet.js +2 -0
- package/dist/src/routes/wallet.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +31 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/services/federation-helpers.d.ts +1 -0
- package/dist/src/services/federation-helpers.d.ts.map +1 -1
- package/dist/src/services/federation-helpers.js +1 -1
- package/dist/src/services/federation-helpers.js.map +1 -1
- package/dist/src/services/generator-autopilot.d.ts.map +1 -1
- package/dist/src/services/generator-autopilot.js +125 -26
- package/dist/src/services/generator-autopilot.js.map +1 -1
- package/dist/src/services/generator-prompts/index.d.ts +1 -1
- package/dist/src/services/generator-prompts/index.d.ts.map +1 -1
- package/dist/src/services/generator-prompts/index.js +1 -1
- package/dist/src/services/generator-prompts/index.js.map +1 -1
- package/dist/src/services/generator-prompts/spec-validate.d.ts +1 -0
- package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -1
- package/dist/src/services/generator-prompts/spec-validate.js +20 -0
- package/dist/src/services/generator-prompts/spec-validate.js.map +1 -1
- package/dist/src/services/generator-prompts/validate.d.ts +7 -1
- package/dist/src/services/generator-prompts/validate.d.ts.map +1 -1
- package/dist/src/services/generator-prompts/validate.js +70 -0
- package/dist/src/services/generator-prompts/validate.js.map +1 -1
- package/dist/src/services/prompt-defaults.d.ts +1 -0
- package/dist/src/services/prompt-defaults.d.ts.map +1 -1
- package/dist/src/services/prompt-defaults.js +830 -8
- package/dist/src/services/prompt-defaults.js.map +1 -1
- package/dist/src/services/prompt-seeder.js +1 -1
- package/dist/src/services/prompt-seeder.js.map +1 -1
- package/dist/src/storage/interface.d.ts +2 -0
- package/dist/src/storage/interface.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.js +5 -2
- package/dist/src/storage/providers/mongodb/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +7 -2
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +2 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/package.json +77 -97
- package/prisma/schema.prisma +2 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file agents-tasks-subtab.js
|
|
3
3
|
* @description Task queue sub-tab for agent detail view.
|
|
4
|
-
* Shows queued, active, and completed tasks with
|
|
5
|
-
*
|
|
4
|
+
* Shows queued, active, and completed tasks with todo plans,
|
|
5
|
+
* "Start this task" approval button, and progress tracking.
|
|
6
6
|
* @structure
|
|
7
7
|
* - AgentTasksSubtab (default export) -- main component
|
|
8
|
-
* - TaskItem --
|
|
8
|
+
* - TaskItem -- task row with expand/collapse, todo list, start button
|
|
9
9
|
* - TaskCreateForm -- inline task creation form
|
|
10
10
|
* @version-history
|
|
11
|
+
* v2.0.0 -- 2026-05-22 -- Add todo rendering, Start button, progress tracking
|
|
11
12
|
* v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
|
|
12
13
|
*/
|
|
13
14
|
import { h } from 'preact';
|
|
@@ -16,54 +17,89 @@ import htm from 'htm';
|
|
|
16
17
|
const html = htm.bind(h);
|
|
17
18
|
import { t } from '/js/i18n.js';
|
|
18
19
|
import { timeAgo } from '/js/utils.js';
|
|
19
|
-
import { listTasks, createTask, deleteTask, listEvents } from '/js/services/agent-tasks.js';
|
|
20
|
+
import { listTasks, createTask, deleteTask, startTask, listEvents } from '/js/services/agent-tasks.js';
|
|
20
21
|
|
|
21
22
|
function statusLabel(status) {
|
|
22
23
|
const key = `profile.agents.tasks.status.${status}`;
|
|
23
24
|
const val = t(key);
|
|
24
|
-
// Fallback to capitalized status if translation key not found
|
|
25
25
|
return val !== key ? val : status.charAt(0).toUpperCase() + status.slice(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function
|
|
28
|
+
function todoStatusIcon(status) {
|
|
29
|
+
if (status === 'done') return '✅';
|
|
30
|
+
if (status === 'failed') return '❌';
|
|
31
|
+
if (status === 'skipped') return '⏭';
|
|
32
|
+
if (status === 'active') return '▶';
|
|
33
|
+
return '⬜';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function todoProgress(todos) {
|
|
37
|
+
if (!todos || todos.length === 0) return null;
|
|
38
|
+
const done = todos.filter(td => td.status === 'done').length;
|
|
39
|
+
return `${done}/${todos.length}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function TaskItem({ task, agentName, showToast, onRefresh }) {
|
|
29
43
|
const [expanded, setExpanded] = useState(false);
|
|
30
44
|
const [events, setEvents] = useState(null);
|
|
31
45
|
const [loadingEvents, setLoadingEvents] = useState(false);
|
|
46
|
+
const [starting, setStarting] = useState(false);
|
|
32
47
|
|
|
33
48
|
async function handleExpand(e) {
|
|
34
49
|
e.stopPropagation();
|
|
35
|
-
if (expanded) {
|
|
36
|
-
setExpanded(false);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
50
|
+
if (expanded) { setExpanded(false); return; }
|
|
39
51
|
setExpanded(true);
|
|
40
52
|
if (!events) {
|
|
41
53
|
setLoadingEvents(true);
|
|
42
54
|
try {
|
|
43
55
|
const resp = await listEvents(agentName, task.id);
|
|
44
56
|
setEvents(resp?.data?.events || []);
|
|
45
|
-
} catch {
|
|
46
|
-
setEvents([]);
|
|
47
|
-
}
|
|
57
|
+
} catch { setEvents([]); }
|
|
48
58
|
setLoadingEvents(false);
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
61
|
|
|
62
|
+
async function handleStart(e) {
|
|
63
|
+
e.stopPropagation();
|
|
64
|
+
setStarting(true);
|
|
65
|
+
try {
|
|
66
|
+
await startTask(agentName, task.id);
|
|
67
|
+
showToast('Task started');
|
|
68
|
+
onRefresh();
|
|
69
|
+
} catch (err) {
|
|
70
|
+
showToast(err.message || 'Failed to start task', true);
|
|
71
|
+
}
|
|
72
|
+
setStarting(false);
|
|
73
|
+
}
|
|
74
|
+
|
|
52
75
|
async function handleDelete(e) {
|
|
53
76
|
e.stopPropagation();
|
|
54
77
|
try {
|
|
55
78
|
await deleteTask(agentName, task.id);
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
showToast('Task deleted');
|
|
80
|
+
onRefresh();
|
|
58
81
|
} catch (err) {
|
|
59
82
|
showToast(err.message || 'Failed to delete task', true);
|
|
60
83
|
}
|
|
61
84
|
}
|
|
62
85
|
|
|
86
|
+
const todos = task.todos || [];
|
|
87
|
+
const hasTodos = todos.length > 0;
|
|
88
|
+
const progress = todoProgress(todos);
|
|
89
|
+
const isQueued = task.status === 'queued' || task.status === 'draft';
|
|
90
|
+
const isActive = task.status === 'active';
|
|
91
|
+
const canStart = isQueued && hasTodos;
|
|
92
|
+
const totalMinutes = todos.reduce((sum, td) => sum + (td.estimateMinutes || td.estimate_minutes || 0), 0);
|
|
93
|
+
const aimeatSteps = todos.filter(td => td.environment === 'aimeat').length;
|
|
94
|
+
const agentSteps = todos.filter(td => td.environment === 'agent').length;
|
|
95
|
+
|
|
63
96
|
return html`
|
|
64
97
|
<div>
|
|
65
98
|
<div class="agd-task-item" onClick=${handleExpand}>
|
|
66
|
-
<
|
|
99
|
+
<div style="flex:1;display:flex;align-items:center;gap:0.5rem">
|
|
100
|
+
<span class="agd-task-title">${task.title || task.id}</span>
|
|
101
|
+
${progress && html`<span class="agd-todo-progress">${progress}</span>`}
|
|
102
|
+
</div>
|
|
67
103
|
<div class="agd-task-meta">
|
|
68
104
|
${task.created_at && html`<span class="agd-task-time">${timeAgo(task.created_at)}</span>`}
|
|
69
105
|
<span class="agd-status agd-status-${task.status || 'draft'}">${statusLabel(task.status || 'draft')}</span>
|
|
@@ -72,30 +108,72 @@ function TaskItem({ task, agentName, showToast }) {
|
|
|
72
108
|
${expanded && html`
|
|
73
109
|
<div class="agd-task-expanded">
|
|
74
110
|
${task.description && html`<div class="agd-task-desc">${task.description}</div>`}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
111
|
+
|
|
112
|
+
${hasTodos && html`
|
|
113
|
+
<div class="agd-todo-section">
|
|
114
|
+
<div class="agd-todo-header">
|
|
115
|
+
<strong>TODO</strong>
|
|
116
|
+
<span class="agd-todo-summary">
|
|
117
|
+
${aimeatSteps > 0 && html`<span class="agd-env-badge agd-env-aimeat">AIMEAT: ${aimeatSteps}</span>`}
|
|
118
|
+
${agentSteps > 0 && html`<span class="agd-env-badge agd-env-agent">Agent: ${agentSteps}</span>`}
|
|
119
|
+
${totalMinutes > 0 && html`<span class="agd-todo-time">~${totalMinutes} min</span>`}
|
|
120
|
+
</span>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="agd-todo-list">
|
|
123
|
+
${todos.map((td, i) => html`
|
|
124
|
+
<div class="agd-todo-item agd-todo-${td.status || 'pending'}" key=${td.id || i}>
|
|
125
|
+
<span class="agd-todo-icon">${todoStatusIcon(td.status || 'pending')}</span>
|
|
126
|
+
<div class="agd-todo-content">
|
|
127
|
+
<div class="agd-todo-title">
|
|
128
|
+
${td.title}
|
|
129
|
+
<span class="agd-env-badge agd-env-${td.environment || 'agent'}">${(td.environment || 'agent').toUpperCase()}</span>
|
|
130
|
+
${(td.estimateMinutes || td.estimate_minutes) && html`
|
|
131
|
+
<span class="agd-todo-est">${td.estimateMinutes || td.estimate_minutes} min</span>
|
|
132
|
+
`}
|
|
133
|
+
</div>
|
|
134
|
+
${td.description && html`<div class="agd-todo-desc">${td.description}</div>`}
|
|
135
|
+
${(td.environmentReason || td.environment_reason) && html`
|
|
136
|
+
<div class="agd-todo-reason">${td.environmentReason || td.environment_reason}</div>
|
|
137
|
+
`}
|
|
138
|
+
${td.verification && html`<div class="agd-todo-verify">${td.verification}</div>`}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
`)}
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
`}
|
|
145
|
+
|
|
146
|
+
${!hasTodos && isQueued && html`
|
|
147
|
+
<div class="agd-todo-waiting">
|
|
148
|
+
Waiting for agent to propose a plan...
|
|
78
149
|
</div>
|
|
79
150
|
`}
|
|
151
|
+
|
|
80
152
|
${loadingEvents && html`<div class="agd-empty">${t('profile.loading')}</div>`}
|
|
81
153
|
${events && events.length > 0 && html`
|
|
82
154
|
<div class="agd-event-log">
|
|
83
155
|
${events.map(ev => html`
|
|
84
156
|
<div class="agd-event-item" key=${ev.id || ev.timestamp}>
|
|
85
157
|
<span class="agd-event-time">${ev.timestamp ? timeAgo(ev.timestamp) : ''}</span>
|
|
86
|
-
<span class="agd-event-type">${ev.type ||
|
|
87
|
-
<span>${ev.message ||
|
|
158
|
+
<span class="agd-event-type">${ev.type || ''}</span>
|
|
159
|
+
<span>${ev.message || ''}</span>
|
|
88
160
|
</div>
|
|
89
161
|
`)}
|
|
90
162
|
</div>
|
|
91
163
|
`}
|
|
92
|
-
${events && events.length === 0 && html`
|
|
93
|
-
<div class="agd-empty"
|
|
164
|
+
${events && events.length === 0 && !isQueued && html`
|
|
165
|
+
<div class="agd-empty">No events recorded</div>
|
|
94
166
|
`}
|
|
167
|
+
|
|
95
168
|
<div class="agd-task-actions">
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
169
|
+
${canStart && html`
|
|
170
|
+
<button class="btn-primary btn-sm" onClick=${handleStart} disabled=${starting}>
|
|
171
|
+
${starting ? 'Starting...' : 'Start this task'}
|
|
172
|
+
</button>
|
|
173
|
+
`}
|
|
174
|
+
${(isQueued || task.status === 'draft') && html`
|
|
175
|
+
<button class="btn-danger btn-sm" onClick=${handleDelete}>Delete</button>
|
|
176
|
+
`}
|
|
99
177
|
</div>
|
|
100
178
|
</div>
|
|
101
179
|
`}
|
|
@@ -119,8 +197,7 @@ function TaskCreateForm({ agentName, showToast, onCreated, onCancel }) {
|
|
|
119
197
|
description: description.trim() || undefined,
|
|
120
198
|
status,
|
|
121
199
|
});
|
|
122
|
-
|
|
123
|
-
showToast(msg !== 'profile.agents.tasks.created' ? msg : 'Task created');
|
|
200
|
+
showToast('Task created');
|
|
124
201
|
onCreated();
|
|
125
202
|
} catch (err) {
|
|
126
203
|
showToast(err.message || 'Failed to create task', true);
|
|
@@ -131,18 +208,17 @@ function TaskCreateForm({ agentName, showToast, onCreated, onCancel }) {
|
|
|
131
208
|
return html`
|
|
132
209
|
<form class="agd-create-form" onSubmit=${handleSubmit}>
|
|
133
210
|
<div class="agd-form-field">
|
|
134
|
-
<label
|
|
211
|
+
<label>Title</label>
|
|
135
212
|
<input type="text" value=${title} onInput=${(e) => setTitle(e.target.value)}
|
|
136
|
-
placeholder
|
|
137
|
-
required />
|
|
213
|
+
placeholder="What should the agent do?" required />
|
|
138
214
|
</div>
|
|
139
215
|
<div class="agd-form-field">
|
|
140
|
-
<label
|
|
216
|
+
<label>Description</label>
|
|
141
217
|
<textarea value=${description} onInput=${(e) => setDescription(e.target.value)}
|
|
142
|
-
placeholder
|
|
218
|
+
placeholder="Detailed instructions (optional)"></textarea>
|
|
143
219
|
</div>
|
|
144
220
|
<div class="agd-form-field">
|
|
145
|
-
<label
|
|
221
|
+
<label>Initial status</label>
|
|
146
222
|
<select value=${status} onChange=${(e) => setStatus(e.target.value)}>
|
|
147
223
|
<option value="draft">${statusLabel('draft')}</option>
|
|
148
224
|
<option value="queued">${statusLabel('queued')}</option>
|
|
@@ -150,13 +226,9 @@ function TaskCreateForm({ agentName, showToast, onCreated, onCancel }) {
|
|
|
150
226
|
</div>
|
|
151
227
|
<div class="agd-form-actions">
|
|
152
228
|
<button type="submit" class="btn-primary btn-sm" disabled=${saving || !title.trim()}>
|
|
153
|
-
${saving
|
|
154
|
-
? (t('profile.agents.tasks.creating') !== 'profile.agents.tasks.creating' ? t('profile.agents.tasks.creating') : 'Creating...')
|
|
155
|
-
: (t('profile.agents.tasks.createBtn') !== 'profile.agents.tasks.createBtn' ? t('profile.agents.tasks.createBtn') : 'Create Task')}
|
|
156
|
-
</button>
|
|
157
|
-
<button type="button" class="btn-outline btn-sm" onClick=${onCancel}>
|
|
158
|
-
${t('profile.agents.scopeUi.cancel')}
|
|
229
|
+
${saving ? 'Creating...' : 'Create Task'}
|
|
159
230
|
</button>
|
|
231
|
+
<button type="button" class="btn-outline btn-sm" onClick=${onCancel}>Cancel</button>
|
|
160
232
|
</div>
|
|
161
233
|
</form>
|
|
162
234
|
`;
|
|
@@ -178,11 +250,8 @@ export default function AgentTasksSubtab({ agentName, session, showToast }) {
|
|
|
178
250
|
}
|
|
179
251
|
}
|
|
180
252
|
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
loadTasks();
|
|
183
|
-
}, [agentName]);
|
|
253
|
+
useEffect(() => { loadTasks(); }, [agentName]);
|
|
184
254
|
|
|
185
|
-
// Live update listener
|
|
186
255
|
const loadRef = useRef(loadTasks);
|
|
187
256
|
loadRef.current = loadTasks;
|
|
188
257
|
useEffect(() => {
|
|
@@ -200,7 +269,6 @@ export default function AgentTasksSubtab({ agentName, session, showToast }) {
|
|
|
200
269
|
return html`<div class="agd-empty">${t('profile.loading')}</div>`;
|
|
201
270
|
}
|
|
202
271
|
|
|
203
|
-
// Group tasks by status category
|
|
204
272
|
const active = tasks.filter(t => t.status === 'active');
|
|
205
273
|
const queued = tasks.filter(t => t.status === 'queued' || t.status === 'draft');
|
|
206
274
|
const completed = tasks.filter(t => t.status === 'done' || t.status === 'failed' || t.status === 'stalled');
|
|
@@ -209,11 +277,10 @@ export default function AgentTasksSubtab({ agentName, session, showToast }) {
|
|
|
209
277
|
<div>
|
|
210
278
|
<div class="agd-section-header">
|
|
211
279
|
<span class="agd-section-title">
|
|
212
|
-
${
|
|
213
|
-
${tasks.length > 0 && html` (${tasks.length})`}
|
|
280
|
+
TASK QUEUE${tasks.length > 0 ? ` (${tasks.length})` : ''}
|
|
214
281
|
</span>
|
|
215
|
-
<button class="btn-outline btn-sm" onClick=${(
|
|
216
|
-
${showCreate ? '-' : '+'}
|
|
282
|
+
<button class="btn-outline btn-sm" onClick=${() => setShowCreate(!showCreate)}>
|
|
283
|
+
${showCreate ? '-' : '+'} New Task
|
|
217
284
|
</button>
|
|
218
285
|
</div>
|
|
219
286
|
|
|
@@ -224,30 +291,22 @@ export default function AgentTasksSubtab({ agentName, session, showToast }) {
|
|
|
224
291
|
${error && html`<div class="agd-empty">${error}</div>`}
|
|
225
292
|
|
|
226
293
|
${active.length > 0 && html`
|
|
227
|
-
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">
|
|
228
|
-
|
|
229
|
-
</div>
|
|
230
|
-
${active.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} />`)}
|
|
294
|
+
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">ACTIVE</div>
|
|
295
|
+
${active.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} onRefresh=${loadTasks} />`)}
|
|
231
296
|
`}
|
|
232
297
|
|
|
233
298
|
${queued.length > 0 && html`
|
|
234
|
-
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">
|
|
235
|
-
|
|
236
|
-
</div>
|
|
237
|
-
${queued.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} />`)}
|
|
299
|
+
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">QUEUED</div>
|
|
300
|
+
${queued.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} onRefresh=${loadTasks} />`)}
|
|
238
301
|
`}
|
|
239
302
|
|
|
240
303
|
${completed.length > 0 && html`
|
|
241
|
-
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">
|
|
242
|
-
|
|
243
|
-
</div>
|
|
244
|
-
${completed.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} />`)}
|
|
304
|
+
<div class="agd-section-title" style="margin-top:0.5rem;margin-bottom:0.25rem">COMPLETED</div>
|
|
305
|
+
${completed.map(task => html`<${TaskItem} key=${task.id} task=${task} agentName=${agentName} showToast=${showToast} onRefresh=${loadTasks} />`)}
|
|
245
306
|
`}
|
|
246
307
|
|
|
247
308
|
${tasks.length === 0 && !showCreate && html`
|
|
248
|
-
<div class="agd-empty">
|
|
249
|
-
${t('profile.agents.tasks.empty') !== 'profile.agents.tasks.empty' ? t('profile.agents.tasks.empty') : 'No tasks yet. Create one to get started.'}
|
|
250
|
-
</div>
|
|
309
|
+
<div class="agd-empty">No tasks yet. Create one to get started.</div>
|
|
251
310
|
`}
|
|
252
311
|
</div>
|
|
253
312
|
`;
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
// DEPRECATED: browser-side prompt builders no longer used. Prompts loaded from database via API.
|
|
33
33
|
// import { buildComponentPrompt, buildFixPrompt, buildReflectionPrompt, buildTestPrompt } from '/js/services/generator-prompts.js';
|
|
34
34
|
import { validateComponent } from '/js/services/generator-validate.js';
|
|
35
|
-
import { validateExtensionSpec, validateDataApiSpec, validateComponentSpec, validateAppDomainSpec } from '/js/services/generator-spec-validate.js';
|
|
35
|
+
import { validateExtensionSpec, validateDataApiSpec, validateComponentSpec, validateAppDomainSpec, validateAppSpec } from '/js/services/generator-spec-validate.js';
|
|
36
36
|
import { verifyContract } from '/js/services/generator-contract.js';
|
|
37
37
|
import { smokeTest } from '/js/services/generator-smoke.js';
|
|
38
38
|
import { createBundle } from '/js/services/generator-context-bundle.js';
|
|
@@ -672,6 +672,7 @@ export function ComponentDetail({ component, project, components, projectId, int
|
|
|
672
672
|
// Validate spec structure
|
|
673
673
|
let sv;
|
|
674
674
|
if (component.type === 'extension') sv = validateExtensionSpec(parsed);
|
|
675
|
+
else if (component.type === 'app') sv = validateAppSpec(parsed);
|
|
675
676
|
else if (component.subtype === 'data') sv = validateDataApiSpec(parsed);
|
|
676
677
|
else if (component.subtype === 'component') sv = validateComponentSpec(parsed);
|
|
677
678
|
else if (component.subtype === 'app-domain') sv = validateAppDomainSpec(parsed);
|
|
@@ -705,6 +706,12 @@ export function ComponentDetail({ component, project, components, projectId, int
|
|
|
705
706
|
try {
|
|
706
707
|
const parsed = JSON.parse(specResult);
|
|
707
708
|
await saveSpec(projectId, component.id, parsed);
|
|
709
|
+
// Rebuild code prompt now that the spec is saved
|
|
710
|
+
const freshPrompt = await loadPromptFromBackend(projectId, component.id, 'code');
|
|
711
|
+
setGeneratedPrompt(freshPrompt);
|
|
712
|
+
if (component.prompt) {
|
|
713
|
+
await saveComponent(projectId, { ...component, prompt: freshPrompt, spec: parsed });
|
|
714
|
+
}
|
|
708
715
|
showToast?.('Spec saved');
|
|
709
716
|
onUpdate();
|
|
710
717
|
} catch (e) {
|