bosun 0.36.2 → 0.36.4
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/agent-prompts.mjs +95 -0
- package/analyze-agent-work-helpers.mjs +308 -0
- package/analyze-agent-work.mjs +926 -0
- package/autofix.mjs +2 -0
- package/bosun.schema.json +101 -3
- package/codex-shell.mjs +85 -10
- package/desktop/main.mjs +871 -48
- package/desktop/preload.mjs +54 -1
- package/desktop-shortcut.mjs +90 -11
- package/git-editor-fix.mjs +273 -0
- package/mcp-registry.mjs +579 -0
- package/meeting-workflow-service.mjs +631 -0
- package/monitor.mjs +18 -103
- package/package.json +21 -2
- package/primary-agent.mjs +32 -12
- package/session-tracker.mjs +68 -0
- package/setup-web-server.mjs +20 -10
- package/setup.mjs +376 -83
- package/startup-service.mjs +51 -6
- package/stream-resilience.mjs +17 -7
- package/ui/app.js +164 -4
- package/ui/components/agent-selector.js +145 -1
- package/ui/components/chat-view.js +161 -15
- package/ui/components/session-list.js +2 -2
- package/ui/components/shared.js +188 -15
- package/ui/modules/icons.js +13 -0
- package/ui/modules/utils.js +44 -0
- package/ui/modules/voice-client-sdk.js +733 -0
- package/ui/modules/voice-overlay.js +128 -15
- package/ui/modules/voice.js +15 -6
- package/ui/setup.html +281 -81
- package/ui/styles/components.css +99 -3
- package/ui/styles/sessions.css +122 -14
- package/ui/styles.css +14 -0
- package/ui/tabs/agents.js +1 -1
- package/ui/tabs/chat.js +123 -14
- package/ui/tabs/control.js +16 -22
- package/ui/tabs/dashboard.js +85 -8
- package/ui/tabs/library.js +113 -17
- package/ui/tabs/settings.js +116 -2
- package/ui/tabs/tasks.js +388 -39
- package/ui/tabs/telemetry.js +0 -1
- package/ui/tabs/workflows.js +4 -0
- package/ui-server.mjs +400 -22
- package/update-check.mjs +41 -13
- package/voice-action-dispatcher.mjs +844 -0
- package/voice-agents-sdk.mjs +664 -0
- package/voice-auth-manager.mjs +164 -0
- package/voice-relay.mjs +1194 -0
- package/voice-tools.mjs +914 -0
- package/workflow-templates/agents.mjs +6 -2
- package/workflow-templates/github.mjs +154 -12
- package/workflow-templates.mjs +3 -0
- package/github-reconciler.mjs +0 -506
- package/merge-strategy.mjs +0 -1210
- package/pr-cleanup-daemon.mjs +0 -992
- package/workspace-reaper.mjs +0 -405
|
@@ -18,6 +18,12 @@ import {
|
|
|
18
18
|
voiceToolCalls, voiceDuration,
|
|
19
19
|
startVoiceSession, stopVoiceSession, interruptResponse,
|
|
20
20
|
} from "./voice-client.js";
|
|
21
|
+
import {
|
|
22
|
+
sdkVoiceState, sdkVoiceTranscript, sdkVoiceResponse, sdkVoiceError,
|
|
23
|
+
sdkVoiceToolCalls, sdkVoiceDuration, sdkVoiceSdkActive,
|
|
24
|
+
startSdkVoiceSession, stopSdkVoiceSession, interruptSdkResponse,
|
|
25
|
+
sendSdkTextMessage, onSdkVoiceEvent,
|
|
26
|
+
} from "./voice-client-sdk.js";
|
|
21
27
|
import {
|
|
22
28
|
fallbackState, fallbackTranscript, fallbackResponse,
|
|
23
29
|
fallbackError,
|
|
@@ -422,6 +428,53 @@ function injectOverlayStyles() {
|
|
|
422
428
|
width: 162px;
|
|
423
429
|
height: 162px;
|
|
424
430
|
}
|
|
431
|
+
}
|
|
432
|
+
.voice-overlay.compact {
|
|
433
|
+
background: rgba(0, 0, 0, 0.93);
|
|
434
|
+
}
|
|
435
|
+
.voice-overlay.compact .voice-overlay-header {
|
|
436
|
+
padding: 12px 14px;
|
|
437
|
+
}
|
|
438
|
+
.voice-overlay.compact .voice-overlay-main {
|
|
439
|
+
padding: 62px 10px 10px;
|
|
440
|
+
flex-direction: column;
|
|
441
|
+
gap: 10px;
|
|
442
|
+
}
|
|
443
|
+
.voice-overlay.compact .voice-overlay-stage {
|
|
444
|
+
gap: 12px;
|
|
445
|
+
}
|
|
446
|
+
.voice-overlay.compact .voice-overlay-center {
|
|
447
|
+
gap: 12px;
|
|
448
|
+
}
|
|
449
|
+
.voice-overlay.compact .voice-orb-container {
|
|
450
|
+
width: 138px;
|
|
451
|
+
height: 138px;
|
|
452
|
+
}
|
|
453
|
+
.voice-overlay.compact .voice-transcript-area {
|
|
454
|
+
max-width: none;
|
|
455
|
+
width: 100%;
|
|
456
|
+
min-height: 46px;
|
|
457
|
+
}
|
|
458
|
+
.voice-overlay.compact .voice-transcript-user {
|
|
459
|
+
font-size: 14px;
|
|
460
|
+
}
|
|
461
|
+
.voice-overlay.compact .voice-transcript-assistant {
|
|
462
|
+
font-size: 15px;
|
|
463
|
+
line-height: 1.4;
|
|
464
|
+
}
|
|
465
|
+
.voice-overlay.compact .voice-tool-cards {
|
|
466
|
+
max-width: none;
|
|
467
|
+
}
|
|
468
|
+
.voice-overlay.compact .voice-overlay-chat {
|
|
469
|
+
width: 100%;
|
|
470
|
+
min-width: 0;
|
|
471
|
+
max-width: none;
|
|
472
|
+
max-height: 44vh;
|
|
473
|
+
}
|
|
474
|
+
.voice-overlay.compact .voice-end-btn {
|
|
475
|
+
width: 56px;
|
|
476
|
+
height: 56px;
|
|
477
|
+
font-size: 20px;
|
|
425
478
|
}
|
|
426
479
|
`;
|
|
427
480
|
document.head.appendChild(style);
|
|
@@ -441,6 +494,8 @@ function formatDuration(seconds) {
|
|
|
441
494
|
* @param {{
|
|
442
495
|
* visible: boolean,
|
|
443
496
|
* onClose: () => void,
|
|
497
|
+
* onDismiss?: () => void,
|
|
498
|
+
* compact?: boolean,
|
|
444
499
|
* tier: number,
|
|
445
500
|
* sessionId?: string,
|
|
446
501
|
* executor?: string,
|
|
@@ -453,6 +508,8 @@ function formatDuration(seconds) {
|
|
|
453
508
|
export function VoiceOverlay({
|
|
454
509
|
visible,
|
|
455
510
|
onClose,
|
|
511
|
+
onDismiss,
|
|
512
|
+
compact = false,
|
|
456
513
|
tier = 1,
|
|
457
514
|
sessionId,
|
|
458
515
|
executor,
|
|
@@ -470,16 +527,33 @@ export function VoiceOverlay({
|
|
|
470
527
|
const [meetingChatError, setMeetingChatError] = useState(null);
|
|
471
528
|
const autoVisionAppliedRef = useRef(false);
|
|
472
529
|
const meetingScrollRef = useRef(null);
|
|
530
|
+
const [usingSdk, setUsingSdk] = useState(false);
|
|
531
|
+
const sdkFallbackCleanupRef = useRef(null);
|
|
473
532
|
|
|
474
533
|
useEffect(() => { injectOverlayStyles(); }, []);
|
|
475
534
|
|
|
476
|
-
//
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
535
|
+
// Determine effective tier: SDK takes over tier 1 when active
|
|
536
|
+
const effectiveSdk = usingSdk && sdkVoiceSdkActive.value;
|
|
537
|
+
|
|
538
|
+
// Use computed signals based on tier — SDK overrides tier 1 when active
|
|
539
|
+
const state = effectiveSdk
|
|
540
|
+
? sdkVoiceState.value
|
|
541
|
+
: tier === 1 ? voiceState.value : fallbackState.value;
|
|
542
|
+
const transcript = effectiveSdk
|
|
543
|
+
? sdkVoiceTranscript.value
|
|
544
|
+
: tier === 1 ? voiceTranscript.value : fallbackTranscript.value;
|
|
545
|
+
const response = effectiveSdk
|
|
546
|
+
? sdkVoiceResponse.value
|
|
547
|
+
: tier === 1 ? voiceResponse.value : fallbackResponse.value;
|
|
548
|
+
const error = effectiveSdk
|
|
549
|
+
? sdkVoiceError.value
|
|
550
|
+
: tier === 1 ? voiceError.value : fallbackError.value;
|
|
551
|
+
const toolCalls = effectiveSdk
|
|
552
|
+
? sdkVoiceToolCalls.value
|
|
553
|
+
: tier === 1 ? voiceToolCalls.value : [];
|
|
554
|
+
const duration = effectiveSdk
|
|
555
|
+
? sdkVoiceDuration.value
|
|
556
|
+
: tier === 1 ? voiceDuration.value : 0;
|
|
483
557
|
const visionState = visionShareState.value;
|
|
484
558
|
const visionSource = visionShareSource.value;
|
|
485
559
|
const visionErr = visionShareError.value;
|
|
@@ -495,12 +569,35 @@ export function VoiceOverlay({
|
|
|
495
569
|
return normalizedCallType === "video" ? "camera" : null;
|
|
496
570
|
})();
|
|
497
571
|
|
|
498
|
-
// Start session on mount
|
|
572
|
+
// Start session on mount — try Agents SDK first, fallback to legacy
|
|
499
573
|
useEffect(() => {
|
|
500
574
|
if (!visible || started) return;
|
|
501
575
|
setStarted(true);
|
|
576
|
+
|
|
502
577
|
if (tier === 1) {
|
|
503
|
-
|
|
578
|
+
// Try SDK-first for tier 1
|
|
579
|
+
startSdkVoiceSession({ sessionId, executor, mode, model })
|
|
580
|
+
.then((result) => {
|
|
581
|
+
if (result.sdk) {
|
|
582
|
+
setUsingSdk(true);
|
|
583
|
+
} else {
|
|
584
|
+
// SDK not available — fallback to legacy WebRTC
|
|
585
|
+
setUsingSdk(false);
|
|
586
|
+
startVoiceSession({ sessionId, executor, mode, model });
|
|
587
|
+
}
|
|
588
|
+
})
|
|
589
|
+
.catch(() => {
|
|
590
|
+
// SDK threw unexpectedly — fallback to legacy
|
|
591
|
+
setUsingSdk(false);
|
|
592
|
+
startVoiceSession({ sessionId, executor, mode, model });
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// Listen for SDK runtime failures to auto-fallback
|
|
596
|
+
const cleanup = onSdkVoiceEvent("sdk-unavailable", () => {
|
|
597
|
+
setUsingSdk(false);
|
|
598
|
+
startVoiceSession({ sessionId, executor, mode, model });
|
|
599
|
+
});
|
|
600
|
+
sdkFallbackCleanupRef.current = cleanup;
|
|
504
601
|
} else if (sessionId) {
|
|
505
602
|
startFallbackSession(sessionId, { executor, mode, model });
|
|
506
603
|
}
|
|
@@ -600,23 +697,39 @@ export function VoiceOverlay({
|
|
|
600
697
|
const handleClose = useCallback(() => {
|
|
601
698
|
haptic("medium");
|
|
602
699
|
stopVisionShare().catch(() => {});
|
|
603
|
-
|
|
700
|
+
// Clean up SDK fallback listener
|
|
701
|
+
if (typeof sdkFallbackCleanupRef.current === "function") {
|
|
702
|
+
sdkFallbackCleanupRef.current();
|
|
703
|
+
sdkFallbackCleanupRef.current = null;
|
|
704
|
+
}
|
|
705
|
+
if (usingSdk) {
|
|
706
|
+
stopSdkVoiceSession();
|
|
707
|
+
} else if (tier === 1) {
|
|
604
708
|
stopVoiceSession();
|
|
605
709
|
} else {
|
|
606
710
|
stopFallbackSession();
|
|
607
711
|
}
|
|
712
|
+
setUsingSdk(false);
|
|
608
713
|
setStarted(false);
|
|
609
714
|
onClose();
|
|
610
|
-
}, [tier, onClose]);
|
|
715
|
+
}, [tier, onClose, usingSdk]);
|
|
716
|
+
|
|
717
|
+
const handleDismiss = useCallback(() => {
|
|
718
|
+
haptic("light");
|
|
719
|
+
const fn = typeof onDismiss === "function" ? onDismiss : onClose;
|
|
720
|
+
fn();
|
|
721
|
+
}, [onDismiss, onClose]);
|
|
611
722
|
|
|
612
723
|
const handleInterrupt = useCallback(() => {
|
|
613
724
|
haptic("light");
|
|
614
|
-
if (
|
|
725
|
+
if (usingSdk) {
|
|
726
|
+
interruptSdkResponse();
|
|
727
|
+
} else if (tier === 1) {
|
|
615
728
|
interruptResponse();
|
|
616
729
|
} else {
|
|
617
730
|
interruptFallback();
|
|
618
731
|
}
|
|
619
|
-
}, [tier]);
|
|
732
|
+
}, [tier, usingSdk]);
|
|
620
733
|
|
|
621
734
|
const handleToggleScreenShare = useCallback(() => {
|
|
622
735
|
haptic("light");
|
|
@@ -689,10 +802,10 @@ export function VoiceOverlay({
|
|
|
689
802
|
: "live";
|
|
690
803
|
|
|
691
804
|
return html`
|
|
692
|
-
<div class
|
|
805
|
+
<div class=${`voice-overlay${compact ? " compact" : ""}`}>
|
|
693
806
|
<!-- Header -->
|
|
694
807
|
<div class="voice-overlay-header">
|
|
695
|
-
<button class="voice-overlay-close" onClick=${
|
|
808
|
+
<button class="voice-overlay-close" onClick=${handleDismiss} title="Hide voice window">
|
|
696
809
|
${resolveIcon("close")}
|
|
697
810
|
</button>
|
|
698
811
|
<div>
|
package/ui/modules/voice.js
CHANGED
|
@@ -38,8 +38,8 @@ function injectVoiceStyles() {
|
|
|
38
38
|
display: inline-flex;
|
|
39
39
|
align-items: center;
|
|
40
40
|
justify-content: center;
|
|
41
|
-
width:
|
|
42
|
-
height:
|
|
41
|
+
width: 34px;
|
|
42
|
+
height: 34px;
|
|
43
43
|
border-radius: 50%;
|
|
44
44
|
border: 1px solid rgba(255,255,255,0.10);
|
|
45
45
|
background: var(--tg-theme-secondary-bg-color, #1e1e2e);
|
|
@@ -49,10 +49,16 @@ function injectVoiceStyles() {
|
|
|
49
49
|
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
|
50
50
|
-webkit-tap-highlight-color: transparent;
|
|
51
51
|
padding: 0;
|
|
52
|
-
|
|
52
|
+
box-sizing: border-box;
|
|
53
|
+
font-size: 0;
|
|
53
54
|
line-height: 1;
|
|
54
55
|
user-select: none;
|
|
55
56
|
}
|
|
57
|
+
.mic-btn svg {
|
|
58
|
+
width: 16px;
|
|
59
|
+
height: 16px;
|
|
60
|
+
display: block;
|
|
61
|
+
}
|
|
56
62
|
.mic-btn:hover:not(:disabled) {
|
|
57
63
|
background: rgba(255,255,255,0.06);
|
|
58
64
|
color: var(--tg-theme-text-color, #fff);
|
|
@@ -74,9 +80,12 @@ function injectVoiceStyles() {
|
|
|
74
80
|
50% { box-shadow: 0 0 0 6px rgba(239,68,68,0.06); }
|
|
75
81
|
}
|
|
76
82
|
.mic-btn-sm {
|
|
77
|
-
width:
|
|
78
|
-
height:
|
|
79
|
-
|
|
83
|
+
width: 24px;
|
|
84
|
+
height: 24px;
|
|
85
|
+
}
|
|
86
|
+
.mic-btn-sm svg {
|
|
87
|
+
width: 12px;
|
|
88
|
+
height: 12px;
|
|
80
89
|
}
|
|
81
90
|
.mic-btn-inline {
|
|
82
91
|
position: absolute;
|