bosun 0.40.21 → 0.41.1
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/.env.example +8 -0
- package/README.md +20 -0
- package/agent/agent-custom-tools.mjs +23 -5
- package/agent/agent-event-bus.mjs +248 -6
- package/agent/agent-pool.mjs +131 -30
- package/agent/agent-work-analyzer.mjs +8 -16
- package/agent/primary-agent.mjs +81 -7
- package/agent/retry-queue.mjs +164 -0
- package/bench/swebench/bosun-swebench.mjs +5 -0
- package/bosun.config.example.json +25 -0
- package/bosun.schema.json +825 -183
- package/cli.mjs +267 -8
- package/config/config-doctor.mjs +51 -2
- package/config/config.mjs +232 -5
- package/github/github-auth-manager.mjs +70 -19
- package/infra/library-manager.mjs +894 -60
- package/infra/monitor.mjs +701 -69
- package/infra/runtime-accumulator.mjs +376 -84
- package/infra/session-tracker.mjs +95 -28
- package/infra/test-runtime.mjs +267 -0
- package/lib/codebase-audit.mjs +133 -18
- package/package.json +30 -8
- package/server/setup-web-server.mjs +29 -1
- package/server/ui-server.mjs +1571 -49
- package/setup.mjs +27 -24
- package/shell/codex-shell.mjs +34 -3
- package/shell/copilot-shell.mjs +50 -8
- package/task/msg-hub.mjs +193 -0
- package/task/pipeline.mjs +544 -0
- package/task/task-claims.mjs +6 -10
- package/task/task-cli.mjs +38 -2
- package/task/task-executor-pipeline.mjs +143 -0
- package/task/task-executor.mjs +36 -27
- package/telegram/get-telegram-chat-id.mjs +57 -47
- package/ui/components/chat-view.js +18 -1
- package/ui/components/workspace-switcher.js +321 -9
- package/ui/demo-defaults.js +17830 -10433
- package/ui/demo.html +9 -1
- package/ui/modules/router.js +1 -1
- package/ui/modules/settings-schema.js +2 -0
- package/ui/modules/state.js +54 -57
- package/ui/modules/voice-client-sdk.js +376 -37
- package/ui/modules/voice-client.js +173 -33
- package/ui/setup.html +68 -2
- package/ui/styles/components.css +571 -1
- package/ui/styles.css +201 -1
- package/ui/tabs/dashboard.js +74 -0
- package/ui/tabs/library.js +410 -55
- package/ui/tabs/logs.js +10 -0
- package/ui/tabs/settings.js +178 -99
- package/ui/tabs/tasks.js +1083 -507
- package/ui/tabs/telemetry.js +34 -0
- package/ui/tabs/workflow-canvas-utils.mjs +38 -1
- package/ui/tabs/workflows.js +1275 -402
- package/voice/voice-agents-sdk.mjs +2 -2
- package/voice/voice-relay.mjs +28 -20
- package/workflow/declarative-workflows.mjs +145 -0
- package/workflow/msg-hub.mjs +237 -0
- package/workflow/pipeline-workflows.mjs +287 -0
- package/workflow/pipeline.mjs +828 -315
- package/workflow/project-detection.mjs +559 -0
- package/workflow/workflow-cli.mjs +128 -0
- package/workflow/workflow-contract.mjs +433 -232
- package/workflow/workflow-engine.mjs +510 -47
- package/workflow/workflow-nodes/custom-loader.mjs +251 -0
- package/workflow/workflow-nodes.mjs +2024 -184
- package/workflow/workflow-templates.mjs +118 -24
- package/workflow-templates/agents.mjs +20 -20
- package/workflow-templates/bosun-native.mjs +212 -2
- package/workflow-templates/code-quality.mjs +20 -14
- package/workflow-templates/continuation-loop.mjs +339 -0
- package/workflow-templates/github.mjs +516 -40
- package/workflow-templates/planning.mjs +446 -17
- package/workflow-templates/reliability.mjs +65 -12
- package/workflow-templates/task-batch.mjs +27 -10
- package/workflow-templates/task-execution.mjs +752 -0
- package/workflow-templates/task-lifecycle.mjs +117 -14
- package/workspace/context-cache.mjs +66 -18
- package/workspace/workspace-manager.mjs +153 -1
- package/workflow-templates/issue-continuation.mjs +0 -243
package/ui/styles.css
CHANGED
|
@@ -199,6 +199,207 @@
|
|
|
199
199
|
padding: 0 12px;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
.wf-palette-backdrop {
|
|
203
|
+
position: absolute;
|
|
204
|
+
inset: 0;
|
|
205
|
+
z-index: 32;
|
|
206
|
+
background: rgba(3, 7, 18, 0.55);
|
|
207
|
+
backdrop-filter: blur(3px);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.wf-palette {
|
|
211
|
+
position: absolute;
|
|
212
|
+
top: 72px;
|
|
213
|
+
left: 50%;
|
|
214
|
+
transform: translateX(-50%);
|
|
215
|
+
width: min(760px, calc(100% - 32px));
|
|
216
|
+
max-height: min(70vh, 720px);
|
|
217
|
+
overflow: hidden;
|
|
218
|
+
background: var(--color-bg, #0d1117);
|
|
219
|
+
border: 1px solid var(--color-border, #2a3040);
|
|
220
|
+
border-radius: 16px;
|
|
221
|
+
padding: 14px;
|
|
222
|
+
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
|
|
223
|
+
display: flex;
|
|
224
|
+
flex-direction: column;
|
|
225
|
+
gap: 12px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.wf-palette-header {
|
|
229
|
+
display: flex;
|
|
230
|
+
align-items: center;
|
|
231
|
+
gap: 10px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.wf-palette-title-group {
|
|
235
|
+
flex: 1;
|
|
236
|
+
min-width: 0;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.wf-palette-title {
|
|
240
|
+
font-size: 14px;
|
|
241
|
+
font-weight: 700;
|
|
242
|
+
color: var(--color-text, #fff);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.wf-palette-subtitle {
|
|
246
|
+
font-size: 11px;
|
|
247
|
+
color: var(--color-text-secondary, #9ca3af);
|
|
248
|
+
opacity: 0.85;
|
|
249
|
+
margin-top: 3px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.wf-palette-hints {
|
|
253
|
+
display: flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
gap: 8px;
|
|
256
|
+
font-size: 11px;
|
|
257
|
+
opacity: 0.7;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.wf-palette-results {
|
|
261
|
+
display: flex;
|
|
262
|
+
flex-direction: column;
|
|
263
|
+
gap: 8px;
|
|
264
|
+
overflow-y: auto;
|
|
265
|
+
padding-right: 2px;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.wf-node-search-item {
|
|
269
|
+
display: flex;
|
|
270
|
+
flex-direction: column;
|
|
271
|
+
gap: 8px;
|
|
272
|
+
width: 100%;
|
|
273
|
+
text-align: left;
|
|
274
|
+
border: 1px solid var(--color-border, #2a3040);
|
|
275
|
+
border-radius: 12px;
|
|
276
|
+
padding: 12px 14px;
|
|
277
|
+
color: var(--color-text, #fff);
|
|
278
|
+
cursor: pointer;
|
|
279
|
+
background: var(--color-bg-secondary, #131722);
|
|
280
|
+
transition: border 0.15s, background 0.15s;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.wf-node-search-item.active {
|
|
284
|
+
background: rgba(59, 130, 246, 0.12);
|
|
285
|
+
border-color: rgba(59, 130, 246, 0.66);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.wf-node-search-item-top {
|
|
289
|
+
display: flex;
|
|
290
|
+
align-items: center;
|
|
291
|
+
gap: 8px;
|
|
292
|
+
flex-wrap: wrap;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.wf-node-search-label {
|
|
296
|
+
font-weight: 700;
|
|
297
|
+
font-size: 13px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.wf-node-category-badge {
|
|
301
|
+
display: inline-flex;
|
|
302
|
+
align-items: center;
|
|
303
|
+
padding: 2px 8px;
|
|
304
|
+
border-radius: 999px;
|
|
305
|
+
font-size: 10px;
|
|
306
|
+
letter-spacing: 0.04em;
|
|
307
|
+
text-transform: uppercase;
|
|
308
|
+
border: 1px solid rgba(148, 163, 184, 0.2);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.wf-node-search-type {
|
|
312
|
+
font-size: 11px;
|
|
313
|
+
opacity: 0.55;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.wf-node-search-description {
|
|
317
|
+
font-size: 12px;
|
|
318
|
+
opacity: 0.78;
|
|
319
|
+
line-height: 1.4;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.wf-node-chip-row {
|
|
323
|
+
display: flex;
|
|
324
|
+
gap: 12px;
|
|
325
|
+
flex-wrap: wrap;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.wf-node-chip-group {
|
|
329
|
+
display: flex;
|
|
330
|
+
flex-direction: column;
|
|
331
|
+
gap: 4px;
|
|
332
|
+
min-width: 0;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.wf-node-chip-label {
|
|
336
|
+
font-size: 11px;
|
|
337
|
+
color: var(--color-text-secondary, #9ca3af);
|
|
338
|
+
text-transform: uppercase;
|
|
339
|
+
letter-spacing: 0.08em;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.wf-node-chip-list {
|
|
343
|
+
display: flex;
|
|
344
|
+
flex-wrap: wrap;
|
|
345
|
+
gap: 4px;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.wf-node-chip {
|
|
349
|
+
display: inline-flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
padding: 2px 8px;
|
|
352
|
+
border-radius: 999px;
|
|
353
|
+
border: 1px solid rgba(148, 163, 184, 0.4);
|
|
354
|
+
font-size: 11px;
|
|
355
|
+
background: var(--color-bg-secondary, #1e293b);
|
|
356
|
+
color: var(--color-text-secondary, #94a3b8);
|
|
357
|
+
letter-spacing: 0.04em;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.wf-node-chip-more {
|
|
361
|
+
background: rgba(59, 130, 246, 0.15);
|
|
362
|
+
border-color: rgba(59, 130, 246, 0.3);
|
|
363
|
+
color: #93c5fd;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.wf-node-chip-fallback {
|
|
367
|
+
opacity: 0.6;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.wf-node-search-empty {
|
|
371
|
+
text-align: center;
|
|
372
|
+
padding: 20px;
|
|
373
|
+
opacity: 0.6;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.wf-shortcuts-grid {
|
|
377
|
+
display: flex;
|
|
378
|
+
flex-direction: column;
|
|
379
|
+
gap: 10px;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.wf-shortcut-row {
|
|
383
|
+
display: flex;
|
|
384
|
+
align-items: flex-start;
|
|
385
|
+
justify-content: space-between;
|
|
386
|
+
gap: 16px;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.wf-shortcut-key {
|
|
390
|
+
font-size: 12px;
|
|
391
|
+
padding: 4px 10px;
|
|
392
|
+
border-radius: 8px;
|
|
393
|
+
background: rgba(148, 163, 184, 0.14);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.wf-shortcut-desc {
|
|
397
|
+
font-size: 13px;
|
|
398
|
+
opacity: 0.82;
|
|
399
|
+
text-align: right;
|
|
400
|
+
flex: 1;
|
|
401
|
+
}
|
|
402
|
+
|
|
202
403
|
.stream-item-details.expanded .stream-item-details-inner {
|
|
203
404
|
padding: 10px 12px 12px;
|
|
204
405
|
}
|
|
@@ -649,4 +850,3 @@
|
|
|
649
850
|
color: var(--text-primary);
|
|
650
851
|
font-size: 12px;
|
|
651
852
|
}
|
|
652
|
-
|
package/ui/tabs/dashboard.js
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
projectSummary,
|
|
23
23
|
loadStatus,
|
|
24
24
|
loadProjectSummary,
|
|
25
|
+
loadRetryQueue,
|
|
25
26
|
showToast,
|
|
26
27
|
refreshTab,
|
|
27
28
|
runOptimistic,
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
getDashboardHistory,
|
|
31
32
|
setPendingChange,
|
|
32
33
|
clearPendingChange,
|
|
34
|
+
retryQueueData,
|
|
33
35
|
} from "../modules/state.js";
|
|
34
36
|
import { navigateTo } from "../modules/router.js";
|
|
35
37
|
import { ICONS } from "../modules/icons.js";
|
|
@@ -322,6 +324,7 @@ export function DashboardTab() {
|
|
|
322
324
|
const prevCounts = useRef(null);
|
|
323
325
|
const status = statusData.value;
|
|
324
326
|
const executor = executorData.value;
|
|
327
|
+
const retryQueue = retryQueueData.value || { count: 0, items: [], stats: {} };
|
|
325
328
|
const project = projectSummary.value;
|
|
326
329
|
const counts = status?.counts || {};
|
|
327
330
|
const summary = status?.success_metrics || {};
|
|
@@ -448,6 +451,10 @@ export function DashboardTab() {
|
|
|
448
451
|
.catch(() => {});
|
|
449
452
|
}, []);
|
|
450
453
|
|
|
454
|
+
useEffect(() => {
|
|
455
|
+
loadRetryQueue().catch(() => {});
|
|
456
|
+
}, []);
|
|
457
|
+
|
|
451
458
|
// ── Flash metrics on counts change ──
|
|
452
459
|
useEffect(() => {
|
|
453
460
|
const current = JSON.stringify(counts);
|
|
@@ -657,6 +664,34 @@ export function DashboardTab() {
|
|
|
657
664
|
|
|
658
665
|
/* ── Recent activity (last 5 tasks from global tasks signal) ── */
|
|
659
666
|
const recentTasks = (tasksData.value || []).slice(0, 5);
|
|
667
|
+
const retryItems = Array.isArray(retryQueue.items) ? retryQueue.items : [];
|
|
668
|
+
|
|
669
|
+
const formatRetryCountdown = useCallback((nextAttemptAt) => {
|
|
670
|
+
const target = Number(nextAttemptAt || 0);
|
|
671
|
+
if (!Number.isFinite(target) || target <= 0) return "Now";
|
|
672
|
+
const remainingMs = target - now.getTime();
|
|
673
|
+
if (remainingMs <= 0) return "Now";
|
|
674
|
+
const totalSec = Math.ceil(remainingMs / 1000);
|
|
675
|
+
const min = Math.floor(totalSec / 60);
|
|
676
|
+
const sec = totalSec % 60;
|
|
677
|
+
if (min > 0) return `${min}m ${String(sec).padStart(2, "0")}s`;
|
|
678
|
+
return `${sec}s`;
|
|
679
|
+
}, [now]);
|
|
680
|
+
|
|
681
|
+
const handleRetryNow = useCallback(async (taskId) => {
|
|
682
|
+
const id = String(taskId || "").trim();
|
|
683
|
+
if (!id) return;
|
|
684
|
+
try {
|
|
685
|
+
await apiFetch("/api/tasks/retry", {
|
|
686
|
+
method: "POST",
|
|
687
|
+
body: JSON.stringify({ taskId: id }),
|
|
688
|
+
});
|
|
689
|
+
showToast(`Retry requested for ${id}`, "success");
|
|
690
|
+
scheduleRefresh(100);
|
|
691
|
+
} catch {
|
|
692
|
+
/* toast shown by apiFetch */
|
|
693
|
+
}
|
|
694
|
+
}, []);
|
|
660
695
|
|
|
661
696
|
/* ── Loading skeleton ── */
|
|
662
697
|
if (!status && !executor)
|
|
@@ -981,6 +1016,45 @@ export function DashboardTab() {
|
|
|
981
1016
|
</div>
|
|
982
1017
|
<//>
|
|
983
1018
|
|
|
1019
|
+
<${Card}
|
|
1020
|
+
title=${html`<span class="dashboard-card-title"
|
|
1021
|
+
><span class="dashboard-title-icon">${ICONS.refresh || resolveIcon("refresh")}</span>Retry Queue</span
|
|
1022
|
+
>`}
|
|
1023
|
+
className="dashboard-card dashboard-retry-queue"
|
|
1024
|
+
>
|
|
1025
|
+
${retryItems.length
|
|
1026
|
+
? html`
|
|
1027
|
+
<div class="dashboard-retry-list">
|
|
1028
|
+
${retryItems.map((item) => html`
|
|
1029
|
+
<div key=${item.taskId} class="dashboard-retry-item">
|
|
1030
|
+
<div class="dashboard-retry-main">
|
|
1031
|
+
<div class="dashboard-retry-task">${item.taskId}</div>
|
|
1032
|
+
${item.taskTitle
|
|
1033
|
+
? html`<div class="dashboard-retry-task-title">${truncate(item.taskTitle, 72)}</div>`
|
|
1034
|
+
: null}
|
|
1035
|
+
<div class="dashboard-retry-error">${truncate(item.lastError || item.reason || "Unknown retry reason", 120)}</div>
|
|
1036
|
+
</div>
|
|
1037
|
+
<div class="dashboard-retry-meta">
|
|
1038
|
+
<span class="dashboard-retry-pill">Attempt ${item.retryCount || 0}</span>
|
|
1039
|
+
<span class="dashboard-retry-pill">Next ${formatRetryCountdown(item.nextAttemptAt)}</span>
|
|
1040
|
+
<${Button}
|
|
1041
|
+
variant="outlined"
|
|
1042
|
+
size="small"
|
|
1043
|
+
onClick=${() => {
|
|
1044
|
+
haptic("medium");
|
|
1045
|
+
void handleRetryNow(item.taskId);
|
|
1046
|
+
}}
|
|
1047
|
+
>
|
|
1048
|
+
Retry Now
|
|
1049
|
+
<//>
|
|
1050
|
+
</div>
|
|
1051
|
+
</div>
|
|
1052
|
+
`)}
|
|
1053
|
+
</div>
|
|
1054
|
+
`
|
|
1055
|
+
: html`<${EmptyState} title="No queued retries" description="Failed tasks waiting to retry appear here automatically." />`}
|
|
1056
|
+
<//>
|
|
1057
|
+
|
|
984
1058
|
<${Card}
|
|
985
1059
|
title=${html`<span class="dashboard-card-title"
|
|
986
1060
|
><span class="dashboard-title-icon">${ICONS.clock}</span>Recent
|