@openscout/scout 0.2.37 → 0.2.39

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.
@@ -0,0 +1 @@
1
+ :root{--bg: #F9F9F8;--surface: #FFFFFF;--ink: #1C1C1A;--muted: #8A8A86;--dim: #C4C4C0;--border: #E4E4E2;--accent: #0066FF;--accent-soft: rgba(0, 102, 255, .08);--green: #22c55e;--red: #dc2626;--pill-updated-bg: rgba(138, 138, 134, .12);--pill-working-bg: var(--accent-soft);--pill-completed-bg: rgba(34, 197, 94, .14);--pill-failed-bg: rgba(220, 38, 38, .14);--radius: 8px;--shadow-soft: rgba(24, 24, 22, .06);--sidebar-w: 280px;--font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--font-serif: "Spectral", Georgia, serif;font-family:var(--font-sans);font-size:13px;line-height:1.5;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased}*{box-sizing:border-box;margin:0}body{margin:0}.s-app{display:flex;height:100vh;overflow:hidden}.s-sidebar{width:var(--sidebar-w);flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border);background:var(--surface);height:100vh;overflow:hidden}.s-content{flex:1;min-width:0;height:100vh;overflow-y:auto;background:var(--bg)}.s-sidebar-header{padding:16px 16px 12px;flex-shrink:0}.s-logo{font-family:var(--font-serif);font-size:18px;font-weight:600;letter-spacing:-.02em;cursor:pointer;-webkit-user-select:none;user-select:none}.s-sidebar-footer{flex-shrink:0;padding:8px;border-top:1px solid var(--border)}.s-nav-item{display:flex;align-items:center;gap:8px;width:100%;border:none;background:none;padding:6px 8px;border-radius:6px;font-family:var(--font-sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:background .12s ease,color .12s ease}.s-nav-item:hover{background:var(--bg);color:var(--ink)}.s-nav-item-active{background:var(--accent-soft);color:var(--accent)}.s-sidebar-label{padding:4px 16px 6px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);flex-shrink:0}.s-sidebar-list{flex:1;overflow-y:auto;padding-bottom:12px}.s-sidebar-empty{padding:24px 16px;text-align:center;font-size:11px;color:var(--dim)}.s-sidebar-row{display:flex;align-items:center;gap:8px;padding:8px 12px;margin:0 6px;border-radius:6px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .1s ease}.s-sidebar-row:hover{background:var(--bg)}.s-sidebar-row-active,.s-sidebar-row-active:hover{background:var(--accent-soft)}.s-sidebar-row-body{flex:1;min-width:0}.s-sidebar-row-header{display:flex;align-items:center;gap:5px}.s-sidebar-row-name{font-size:12px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-sidebar-row-preview{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px;line-height:1.3}.s-sidebar-row-preview-empty{font-style:italic;color:var(--dim)}.s-sidebar-row-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;align-self:flex-start;margin-top:2px}.s-welcome{display:flex;align-items:center;justify-content:center;height:100%;color:var(--dim)}.s-welcome-inner{text-align:center}.s-welcome h2{font-family:var(--font-serif);font-size:24px;font-weight:600;color:var(--dim);margin-bottom:4px}.s-welcome p{font-size:12px}.s-home{padding:32px;height:100vh;overflow-y:auto}.s-home-header{margin-bottom:32px}.s-home-header h2{font-family:var(--font-serif);font-size:22px;font-weight:600;color:var(--ink);margin-bottom:4px}.s-home-header p{font-size:12px;color:var(--muted)}.s-home-section{margin-bottom:28px}.s-home-section-title{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);margin-bottom:10px}.s-home-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;max-width:480px}.s-home-card-row{display:flex;align-items:center;gap:10px;padding:10px 14px;font-size:12px}.s-home-card-row+.s-home-card-row{border-top:1px solid var(--border)}.s-home-card-row-label{color:var(--muted);font-size:11px;min-width:80px;flex-shrink:0}.s-home-card-row-value{color:var(--ink);font-family:var(--font-mono);font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-home-steps{list-style:none;padding:0;max-width:480px}.s-home-steps li{display:flex;align-items:baseline;gap:10px;padding:6px 0;font-size:12px;color:var(--ink);line-height:1.5}.s-home-steps li:before{content:attr(data-step);font-size:10px;font-weight:700;font-family:var(--font-mono);color:var(--muted);flex-shrink:0;width:18px;height:18px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--bg);border:1px solid var(--border)}.s-home-steps code{font-family:var(--font-mono);font-size:11px;background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:1px 5px}.s-home-card-row-clickable{cursor:pointer;transition:background .1s ease}.s-home-card-row-clickable:hover{background:var(--bg)}.s-activity-stream{max-width:560px}.s-activity-row{display:flex;align-items:baseline;gap:8px;padding:4px 0;font-size:12px;line-height:1.5}.s-activity-row-clickable{cursor:pointer;border-radius:4px;padding:4px 6px;margin:0 -6px;transition:background .1s ease}.s-activity-row-clickable:hover{background:var(--surface)}.s-activity-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;min-width:36px}.s-activity-actor{font-weight:600;color:var(--ink);flex-shrink:0}.s-activity-kind{color:var(--muted)}.s-activity-title{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-activity-list{max-width:560px}.s-activity-list-row{display:flex;align-items:flex-start;gap:10px;padding:8px 0}.s-activity-list-item+.s-activity-list-item{border-top:1px solid var(--border)}.s-activity-list-row-clickable{cursor:pointer;border-radius:6px;padding:8px;margin:0 -8px;transition:background .1s ease}.s-activity-list-row-clickable:hover{background:var(--surface)}.s-activity-list-body{flex:1;min-width:0}.s-activity-list-header{display:flex;align-items:baseline;gap:6px}.s-activity-list-actor{font-size:12px;font-weight:600;color:var(--ink)}.s-activity-list-kind{font-size:11px;color:var(--muted)}.s-activity-list-title{font-size:12px;color:var(--ink);margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.s-activity-list-summary{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-activity-expanded{padding:4px 8px 12px 38px}.s-activity-expanded-summary{font-size:12px;color:var(--ink);margin-bottom:8px;line-height:1.4}.s-activity-expanded-meta{display:flex;gap:8px;font-size:11px;padding:2px 0}.s-activity-meta-label{color:var(--muted);min-width:56px}.s-activity-meta-value{color:var(--ink);word-break:break-all}.s-activity-expanded-actions{margin-top:8px}.s-btn-sm{font-size:11px;padding:4px 10px}.s-error{color:var(--red);font-size:12px;padding:8px 12px;background:#fef2f2;border:1px solid #fecaca;border-radius:var(--radius);margin:12px}.s-empty{padding:32px 0;color:var(--muted);font-size:12px}.s-empty p:first-child{font-size:13px;font-weight:500;color:var(--ink);margin-bottom:4px}.s-meta{font-size:11px;color:var(--muted);font-family:var(--font-mono)}.s-spacer{flex:1}.s-dot{display:inline-block;width:6px;height:6px;border-radius:50%;flex-shrink:0}.s-dot-sm{width:5px;height:5px}.s-badge{font-size:10px;font-family:var(--font-mono);color:var(--muted);background:var(--bg);border-radius:4px;padding:1px 6px;flex-shrink:0;text-transform:uppercase;letter-spacing:.04em}.s-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;letter-spacing:.01em}.s-back{border:none;background:none;padding:0;font-family:var(--font-sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:color .12s ease}.s-back:hover{color:var(--ink)}.s-chevron{width:12px;height:12px;flex-shrink:0;position:relative;opacity:.3;transition:opacity .14s ease}.s-chevron:before{content:"";position:absolute;top:3px;left:2px;width:6px;height:6px;border-right:1.5px solid var(--ink);border-bottom:1.5px solid var(--ink);transform:rotate(-45deg)}.s-avatar{width:32px;height:32px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:#fff}.s-avatar-sm{width:28px;height:28px;font-size:11px}.s-avatar-lg{width:56px;height:56px;font-size:20px}.s-conversation{display:flex;flex-direction:column;height:100vh}.s-conv-header{display:flex;align-items:center;gap:10px;padding:10px 20px;border-bottom:1px solid var(--border);background:var(--bg);flex-shrink:0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .12s ease}.s-conv-header:hover{background:#f6f6f5}.s-conv-header .s-back{margin-right:2px;font-size:16px;line-height:1}.s-conv-header-info{flex:1;min-width:0}.s-conv-header-name{font-size:13px;font-weight:600;color:var(--ink)}.s-conv-header-state{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--muted);margin-top:1px}.s-conv-status{display:flex;align-items:center;gap:10px;padding:10px 20px;border-bottom:1px solid var(--border);flex-shrink:0}.s-conv-status-pending{background:#0066ff0f;border-bottom-color:#0066ff1f}.s-conv-status-working{background:#22c55e0f;border-bottom-color:#22c55e24}.s-conv-status-offline{background:#1118270a;border-bottom-color:#11182714}.s-conv-status-dot{width:8px;height:8px;border-radius:50%;background:currentColor;color:var(--accent);flex-shrink:0}.s-conv-status-working .s-conv-status-dot{color:var(--green);animation:s-pulse 1.4s ease-in-out infinite}.s-conv-status-offline .s-conv-status-dot{color:var(--dim)}.s-conv-status-copy{display:flex;flex-direction:column;min-width:0;gap:2px}.s-conv-status-label{font-size:11px;font-weight:700;color:var(--ink)}.s-conv-status-detail{font-size:11px;color:var(--muted);line-height:1.4}.s-messages{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:6px}.s-msg{max-width:85%;align-self:flex-start}.s-msg-you{align-self:flex-end}.s-msg-header{display:flex;align-items:baseline;gap:6px;margin-bottom:2px;padding:0 2px}.s-msg-actor{font-size:11px;font-weight:600;color:var(--ink)}.s-msg-time{font-size:10px;color:var(--dim);font-family:var(--font-mono)}.s-msg-body{font-size:12px;line-height:1.5;color:var(--ink);white-space:pre-wrap;word-break:break-word;padding:8px 12px;border-radius:14px 14px 14px 4px;background:var(--surface);border:1px solid var(--border)}.s-msg-you .s-msg-body{border-radius:14px 14px 4px;background:var(--accent-soft);border-color:#0066ff1f}.s-msg-you .s-msg-header{justify-content:flex-end}.s-msg-working{max-width:85%;align-self:flex-start}.s-msg-working-body{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:14px 14px 14px 4px;background:linear-gradient(135deg,#22c55e14,#22c55e0a);border:1px solid rgba(34,197,94,.14)}.s-msg-working-copy{font-size:12px;line-height:1.45;color:var(--ink)}.s-typing-indicator{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.s-typing-dot{width:6px;height:6px;border-radius:50%;background:var(--green);opacity:.35;animation:s-typing-bounce 1.1s ease-in-out infinite}.s-typing-dot:nth-child(2){animation-delay:.14s}.s-typing-dot:nth-child(3){animation-delay:.28s}@keyframes s-typing-bounce{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.s-compose{display:flex;align-items:flex-end;gap:8px;padding:10px 20px;border-top:1px solid var(--border);background:var(--bg);flex-shrink:0}.s-compose-input{flex:1;border:1px solid var(--border);background:var(--surface);border-radius:20px;min-height:40px;max-height:160px;padding:10px 14px;font-family:var(--font-sans);font-size:12px;line-height:1.45;color:var(--ink);outline:none;transition:border-color .12s ease;resize:none;overflow-y:hidden;white-space:pre-wrap}.s-compose-input:focus{border-color:var(--accent)}.s-compose-input:disabled{opacity:.5;cursor:not-allowed}.s-compose-send{width:32px;height:32px;border-radius:50%;border:none;background:var(--ink);color:#fff;font-size:14px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:opacity .12s ease}.s-compose-send svg{display:block}.s-compose-send:disabled{opacity:.3;cursor:not-allowed}.s-agent-profile{display:flex;flex-direction:column;align-items:flex-start;padding:8px 0 16px;gap:4px}.s-agent-profile-name{font-size:18px;font-weight:600;color:var(--ink);margin-top:8px}.s-agent-profile-handle{font-size:12px;font-family:var(--font-mono);color:var(--muted)}.s-agent-profile-state{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);margin-top:4px}.s-agent-details{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-top:16px;max-width:480px}.s-detail-row{display:flex;align-items:baseline;justify-content:space-between;padding:7px 14px;font-size:12px;gap:12px}.s-detail-row+.s-detail-row{border-top:1px solid var(--border)}.s-detail-label{color:var(--muted);flex-shrink:0;font-size:11px}.s-detail-value{color:var(--ink);font-family:var(--font-mono);font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-section-title{font-size:15px;font-weight:600;color:var(--ink);margin-bottom:16px}.s-actions{display:flex;gap:8px;margin-bottom:16px}.s-btn{border:1px solid var(--border);background:var(--surface);padding:6px 14px;border-radius:var(--radius);font-family:var(--font-sans);font-size:12px;font-weight:500;cursor:pointer;transition:all .14s cubic-bezier(.16,1,.3,1)}.s-btn:hover{border-color:var(--dim);box-shadow:0 1px 2px var(--shadow-soft)}.s-btn:disabled{opacity:.4;cursor:not-allowed}.s-btn-primary{background:var(--ink);color:var(--bg);border-color:var(--ink)}.s-btn-primary:hover{background:#2a2a28;box-shadow:0 2px 6px var(--shadow-soft)}.s-qr{max-width:240px;margin:20px 0;padding:16px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:0 2px 6px var(--shadow-soft)}.s-qr svg{display:block;width:100%;height:auto}.s-pair-meta{max-width:360px;margin:0;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.s-pair-row{display:flex;align-items:center;justify-content:space-between;padding:7px 14px;font-size:12px}.s-pair-row+.s-pair-row{border-top:1px solid var(--border)}.s-pair-label{color:var(--muted);flex-shrink:0}.s-pair-value{display:flex;align-items:center;color:var(--ink);text-align:right;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-pair-mono{font-family:var(--font-mono);font-size:11px}.s-sidebar-nav{padding:0 8px 4px;flex-shrink:0}.s-nav-badge{font-size:10px;font-weight:600;font-family:var(--font-mono);color:#fff;background:var(--green);border-radius:10px;padding:0 6px;min-width:18px;text-align:center;line-height:16px;margin-left:auto}.s-sidebar-avatar-wrap{position:relative;flex-shrink:0}.s-task-indicator{position:absolute;bottom:-1px;right:-1px;width:8px;height:8px;border-radius:50%;background:var(--green);border:2px solid var(--surface)}.s-sidebar-row-active .s-task-indicator{border-color:#0066ff14}.s-flight-banner{display:flex;align-items:center;gap:6px;padding:6px 20px;background:#22c55e0f;border-bottom:1px solid rgba(34,197,94,.12);font-size:11px;flex-shrink:0}.s-flight-banner-dot{width:6px;height:6px;border-radius:50%;background:var(--green);flex-shrink:0;animation:s-pulse 2s ease-in-out infinite}@keyframes s-pulse{0%,to{opacity:1}50%{opacity:.4}}.s-flight-banner-label{font-weight:600;color:var(--ink)}.s-flight-banner-summary{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-flights{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.s-flight-row{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--surface);cursor:pointer;transition:background .12s ease}.s-flight-row:hover{background:#f6f6f5}.s-flight-row+.s-flight-row{border-top:1px solid var(--border)}.s-flight-body{flex:1;min-width:0}.s-flight-header{display:flex;align-items:center;gap:6px}.s-flight-name{font-size:12px;font-weight:600;color:var(--ink)}.s-flight-state{font-size:11px;font-family:var(--font-mono);font-weight:500}.s-flight-summary{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-content>div:not(.s-conversation):not(.s-welcome):not(.s-home):not(.s-agents-layout){padding:24px 32px;max-width:640px}.s-agents-layout{display:flex;height:100vh;overflow:hidden}.s-agents-list-panel{width:100%;height:100vh;overflow-y:auto;padding:24px 16px;transition:width .15s ease}.s-agents-layout-split .s-agents-list-panel{width:280px;flex-shrink:0;border-right:1px solid var(--border);padding:16px 8px}.s-agents-detail-panel{flex:1;min-width:0;height:100vh;overflow-y:auto;padding:24px 32px}.s-agent-list-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:6px;cursor:pointer;transition:background .1s ease}.s-agent-list-row:hover{background:var(--bg)}.s-agent-list-row-active,.s-agent-list-row-active:hover{background:var(--accent-soft)}.s-agent-list-body{flex:1;min-width:0}.s-agent-list-header{display:flex;align-items:center;gap:5px}.s-agent-list-name{font-size:12px;font-weight:600;color:var(--ink)}.s-agent-list-qualifier{font-size:10px;font-family:var(--font-mono);color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-agent-list-meta{display:flex;align-items:center;gap:8px;margin-top:1px;font-size:11px;color:var(--muted)}.s-agent-list-meta span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-agent-detail-header{display:flex;align-items:center;gap:16px;margin-bottom:20px}.s-agent-detail-name{font-size:18px;font-weight:600;color:var(--ink);display:flex;align-items:baseline;gap:8px}.s-agent-detail-qualifier{font-size:12px;font-family:var(--font-mono);color:var(--dim);font-weight:400}.s-agent-detail-state{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);margin-top:2px}.s-agent-detail-meta{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;max-width:480px}.s-agent-detail-section{margin-top:20px}.s-agent-detail-messages{max-width:480px}.s-agent-detail-msg{display:flex;align-items:baseline;gap:6px;padding:4px 0;font-size:12px}.s-agent-detail-msg-clickable{cursor:pointer;border-radius:4px;margin:0 -4px;padding:4px}.s-agent-detail-msg-clickable:hover{background:var(--hover)}.s-agent-detail-msg+.s-agent-detail-msg{border-top:1px solid var(--border)}.s-agent-detail-msg-actor{font-weight:600;color:var(--ink);flex-shrink:0}.s-agent-detail-msg-body{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:767px){.s-sidebar{width:100%;position:absolute;inset:0;z-index:20;transition:transform .2s cubic-bezier(.16,1,.3,1)}.s-content{position:absolute;inset:0;z-index:10;transform:translate(100%);transition:transform .2s cubic-bezier(.16,1,.3,1)}.s-app{position:relative}.s-app-content-open .s-sidebar{transform:translate(-100%)}.s-app-content-open .s-content{transform:translate(0)}.s-conv-header .s-back{display:block}}@media(min-width:768px){.s-conv-header .s-back{display:none}}.s-sessions-screen,.s-mesh-screen{padding:20px 24px}.s-sessions-header{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.s-page-title{font-size:18px;font-weight:600;letter-spacing:-.01em}.s-session-participants{font-size:10px;font-family:var(--font-mono);color:var(--dim);margin-top:2px}.s-filter-bar{display:flex;gap:6px;margin-bottom:16px;overflow-x:auto}.s-filter-chip{font-size:11px;font-weight:500;padding:4px 12px;border-radius:20px;border:1px solid var(--border);background:var(--surface);color:var(--muted);cursor:pointer;flex-shrink:0;transition:background .15s,color .15s}.s-filter-chip:hover{background:var(--bg)}.s-filter-chip-active{background:var(--accent);color:#fff;border-color:var(--accent)}.s-filter-chip-active:hover{background:var(--accent)}.s-mesh-status-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:4px 0;margin-bottom:16px}.s-mesh-warnings{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}.s-mesh-warning{font-size:12px;line-height:1.55;padding:10px 14px;border-radius:var(--radius);background:#f59e0b14;color:#92400e;border:1px solid rgba(245,158,11,.2)}.s-mesh-section{margin-bottom:20px}.s-mesh-section-title{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:10px;display:flex;align-items:center}.s-mesh-nodes{display:flex;flex-direction:column;gap:6px}.s-mesh-node{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px 14px}.s-mesh-node-local{border-color:var(--accent);border-width:1.5px}.s-mesh-node-header{display:flex;align-items:center;gap:8px}.s-mesh-node-name{font-size:13px;font-weight:500}.s-mesh-node-detail{font-size:11px;color:var(--muted);margin-top:3px;padding-left:14px}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--muted)}.s-mention{display:inline-flex;align-items:center;padding:0 6px;margin:0 1px;border-radius:4px;font-family:var(--font-mono);font-size:11px;font-weight:500;color:var(--mention-color, var(--accent));background:color-mix(in srgb,var(--mention-color, var(--accent)) 10%,transparent);border:1px solid color-mix(in srgb,var(--mention-color, var(--accent)) 22%,transparent);line-height:1.6}.s-pill{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;font-family:var(--font-mono);font-size:10px;font-weight:500;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);background:var(--pill-updated-bg);white-space:nowrap}.s-pill-updated{background:var(--pill-updated-bg);color:var(--muted)}.s-pill-working{background:var(--pill-working-bg);color:var(--accent)}.s-pill-completed{background:var(--pill-completed-bg);color:var(--green)}.s-pill-failed{background:var(--pill-failed-bg);color:var(--red)}.s-row-event{display:flex;align-items:center;gap:10px;padding:6px 14px;font-size:12px;color:var(--muted)}.s-row-event .s-pill{margin-left:auto}.s-row-message{display:flex;flex-direction:column;gap:4px}.s-scout-dispatch{display:flex;flex-direction:column;gap:8px;margin-top:8px}.s-scout-tile{display:grid;grid-template-columns:1fr auto;gap:4px 12px;padding:8px 12px;border-radius:8px;border:1px solid var(--border);background:var(--surface);cursor:pointer;font-size:12px;text-align:left;transition:border-color .12s,background .12s}.s-scout-tile:hover{border-color:var(--accent);background:var(--accent-soft)}.s-scout-tile-id{font-family:var(--font-mono);font-weight:500;color:var(--ink)}.s-scout-tile-state{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.s-scout-tile-meta{grid-column:1 / -1;font-size:11px;color:var(--muted)}.s-messages{gap:14px}.s-activity-list{gap:8px}.s-row-message[data-class="scout.dispatch"]{margin-block:22px}.s-conv-header-name{font-weight:600;font-size:15px}.s-conv-status{margin-top:6px}
@@ -7,8 +7,8 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&family=Spectral:wght@500;600&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="/assets/index-RH3faelc.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-BA2r5hxl.css">
10
+ <script type="module" crossorigin src="/assets/index-CafSuiif.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-X47yO2a-.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
package/dist/main.mjs CHANGED
@@ -726,27 +726,38 @@ function agentIdentityMatches(identity, candidate) {
726
726
  return true;
727
727
  }
728
728
  function resolveAgentIdentity(identity, candidates) {
729
+ const diagnosis = diagnoseAgentIdentity(identity, candidates);
730
+ return diagnosis.kind === "resolved" ? diagnosis.match : null;
731
+ }
732
+ function diagnoseAgentIdentity(identity, candidates) {
729
733
  const aliasKeys = identityAliasKeys(identity);
730
734
  const exactAliasMatches = candidates.filter((candidate) => {
731
735
  const candidateAliasKeys = explicitCandidateAliases(candidate).map(canonicalizeAliasValue);
732
736
  return aliasKeys.some((key) => candidateAliasKeys.includes(key));
733
737
  });
734
738
  if (exactAliasMatches.length === 1) {
735
- return exactAliasMatches[0];
739
+ return { kind: "resolved", match: exactAliasMatches[0] };
736
740
  }
737
741
  if (exactAliasMatches.length > 1) {
738
- return null;
742
+ return { kind: "ambiguous", candidates: exactAliasMatches };
739
743
  }
740
744
  const matches = candidates.filter((candidate) => agentIdentityMatches(identity, candidate));
741
745
  if (matches.length === 1) {
742
- return matches[0];
746
+ return { kind: "resolved", match: matches[0] };
747
+ }
748
+ if (matches.length === 0) {
749
+ return { kind: "unknown" };
743
750
  }
744
751
  if (!identity.nodeQualifier && !identity.workspaceQualifier && !identity.profile && !identity.harness) {
745
- return matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId) ?? matches[0] ?? null;
752
+ const exactIdMatch = matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId);
753
+ if (exactIdMatch) {
754
+ return { kind: "resolved", match: exactIdMatch };
755
+ }
756
+ return { kind: "ambiguous", candidates: matches };
746
757
  }
747
- return null;
758
+ return { kind: "ambiguous", candidates: matches };
748
759
  }
749
- var DIMENSION_ALIASES, normalizeAgentSelectorSegment, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
760
+ var DIMENSION_ALIASES, normalizeAgentSelectorSegment, SCOUT_DISPATCHER_AGENT_ID = "scout", RESERVED_AGENT_DEFINITION_IDS, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
750
761
  var init_agent_identity = __esm(() => {
751
762
  DIMENSION_ALIASES = {
752
763
  workspace: "workspace",
@@ -760,6 +771,9 @@ var init_agent_identity = __esm(() => {
760
771
  host: "node"
761
772
  };
762
773
  normalizeAgentSelectorSegment = normalizeAgentIdentitySegment;
774
+ RESERVED_AGENT_DEFINITION_IDS = new Set([
775
+ SCOUT_DISPATCHER_AGENT_ID
776
+ ]);
763
777
  parseAgentSelector = parseAgentIdentity;
764
778
  formatAgentSelector = formatAgentIdentity;
765
779
  extractAgentSelectors = extractAgentIdentities;
@@ -5522,6 +5536,24 @@ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as rea
5522
5536
  import { homedir as homedir4 } from "os";
5523
5537
  import { basename as basename2, dirname as dirname4, join as join7, resolve as resolve5 } from "path";
5524
5538
  import { fileURLToPath as fileURLToPath3 } from "url";
5539
+ function isTmpPath(p) {
5540
+ return /^\/(?:private\/)?tmp\//.test(p);
5541
+ }
5542
+ function resolveAdvertiseScope() {
5543
+ const raw = (process.env.OPENSCOUT_ADVERTISE_SCOPE ?? "").trim().toLowerCase();
5544
+ if (raw === "mesh")
5545
+ return "mesh";
5546
+ if (raw === "local")
5547
+ return "local";
5548
+ return DEFAULT_ADVERTISE_SCOPE;
5549
+ }
5550
+ function resolveBrokerHost(scope = resolveAdvertiseScope()) {
5551
+ const explicit = process.env.OPENSCOUT_BROKER_HOST;
5552
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
5553
+ return explicit;
5554
+ }
5555
+ return scope === "mesh" ? DEFAULT_BROKER_HOST_MESH : DEFAULT_BROKER_HOST;
5556
+ }
5525
5557
  function buildDefaultBrokerUrl(host = DEFAULT_BROKER_HOST, port = DEFAULT_BROKER_PORT) {
5526
5558
  return `http://${host}:${port}`;
5527
5559
  }
@@ -5542,15 +5574,28 @@ function isInstalledRuntimePackageDir(candidate) {
5542
5574
  return existsSync4(join7(candidate, "package.json")) && existsSync4(join7(candidate, "bin", "openscout-runtime.mjs"));
5543
5575
  }
5544
5576
  function findGlobalRuntimeDir() {
5545
- const bunCandidate = join7(homedir4(), ".bun", "node_modules", "@openscout", "runtime");
5546
- if (isInstalledRuntimePackageDir(bunCandidate))
5547
- return bunCandidate;
5548
- const bunGlobalCandidate = join7(homedir4(), ".bun", "install", "global", "node_modules", "@openscout", "runtime");
5549
- if (isInstalledRuntimePackageDir(bunGlobalCandidate))
5550
- return bunGlobalCandidate;
5551
- const bunScoutNested = join7(homedir4(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime");
5552
- if (isInstalledRuntimePackageDir(bunScoutNested))
5553
- return bunScoutNested;
5577
+ const candidates = [
5578
+ join7(homedir4(), ".bun", "node_modules", "@openscout", "runtime"),
5579
+ join7(homedir4(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
5580
+ join7(homedir4(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
5581
+ ];
5582
+ for (const c of candidates) {
5583
+ if (isInstalledRuntimePackageDir(c))
5584
+ return c;
5585
+ }
5586
+ try {
5587
+ const result = spawnSync("which", ["scout"], { encoding: "utf8", timeout: 3000 });
5588
+ const scoutBin = result.stdout?.trim();
5589
+ if (scoutBin) {
5590
+ const scoutPkg = resolve5(scoutBin, "..", "..");
5591
+ const nested = join7(scoutPkg, "node_modules", "@openscout", "runtime");
5592
+ if (isInstalledRuntimePackageDir(nested))
5593
+ return nested;
5594
+ const sibling = resolve5(scoutPkg, "..", "runtime");
5595
+ if (isInstalledRuntimePackageDir(sibling))
5596
+ return sibling;
5597
+ }
5598
+ } catch {}
5554
5599
  return null;
5555
5600
  }
5556
5601
  function findWorkspaceRuntimeDir(startDir) {
@@ -5624,11 +5669,12 @@ function resolveBrokerServiceConfig() {
5624
5669
  const label = resolveBrokerServiceLabel(mode);
5625
5670
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
5626
5671
  const supportPaths = resolveOpenScoutSupportPaths();
5627
- const supportDirectory = supportPaths.supportDirectory;
5628
- const logsDirectory = supportPaths.brokerLogsDirectory;
5629
- const rawControlHome = supportPaths.controlHome;
5630
- const controlHome = /^\/(?:private\/)?tmp\//.test(rawControlHome) ? join7(homedir4(), ".openscout", "control-plane") : rawControlHome;
5631
- const brokerHost = process.env.OPENSCOUT_BROKER_HOST ?? DEFAULT_BROKER_HOST;
5672
+ const defaultSupportDir = join7(homedir4(), "Library", "Application Support", "OpenScout");
5673
+ const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
5674
+ const logsDirectory = join7(supportDirectory, "logs", "broker");
5675
+ const controlHome = isTmpPath(supportPaths.controlHome) ? join7(homedir4(), ".openscout", "control-plane") : supportPaths.controlHome;
5676
+ const advertiseScope = resolveAdvertiseScope();
5677
+ const brokerHost = resolveBrokerHost(advertiseScope);
5632
5678
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
5633
5679
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
5634
5680
  const launchAgentPath = join7(homedir4(), "Library", "LaunchAgents", `${label}.plist`);
@@ -5648,7 +5694,8 @@ function resolveBrokerServiceConfig() {
5648
5694
  bunExecutable: resolveBunExecutable(),
5649
5695
  brokerHost,
5650
5696
  brokerPort,
5651
- brokerUrl
5697
+ brokerUrl,
5698
+ advertiseScope
5652
5699
  };
5653
5700
  }
5654
5701
  function renderLaunchAgentPlist(config) {
@@ -5660,6 +5707,7 @@ function renderLaunchAgentPlist(config) {
5660
5707
  OPENSCOUT_CONTROL_HOME: config.controlHome,
5661
5708
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
5662
5709
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
5710
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
5663
5711
  HOME: homedir4(),
5664
5712
  PATH: launchPath,
5665
5713
  ...collectOptionalEnvVars([
@@ -5730,7 +5778,7 @@ function resolveLaunchAgentPATH() {
5730
5778
  "/usr/sbin",
5731
5779
  "/sbin"
5732
5780
  ];
5733
- return Array.from(new Set(entries)).join(":");
5781
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
5734
5782
  }
5735
5783
  function xmlEscape(value) {
5736
5784
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -5989,7 +6037,7 @@ function formatBrokerServiceStatus(status) {
5989
6037
  return lines.join(`
5990
6038
  `);
5991
6039
  }
5992
- var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_PORT = 65535, BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
6040
+ var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_HOST_MESH = "0.0.0.0", DEFAULT_BROKER_PORT = 65535, DEFAULT_ADVERTISE_SCOPE = "local", BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
5993
6041
  var init_broker_service = __esm(async () => {
5994
6042
  init_support_paths();
5995
6043
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();
@@ -10000,6 +10048,14 @@ var init_tailscale = __esm(() => {
10000
10048
  });
10001
10049
 
10002
10050
  // ../../apps/desktop/src/core/mesh/service.ts
10051
+ function isLoopbackBrokerUrl(url) {
10052
+ try {
10053
+ const hostname3 = new URL(url).hostname;
10054
+ return hostname3 === "127.0.0.1" || hostname3 === "::1" || hostname3 === "localhost";
10055
+ } catch {
10056
+ return false;
10057
+ }
10058
+ }
10003
10059
  function readMeshEnvVars() {
10004
10060
  return {
10005
10061
  meshId: process.env.OPENSCOUT_MESH_ID ?? null,
@@ -10007,6 +10063,7 @@ function readMeshEnvVars() {
10007
10063
  brokerHost: process.env.OPENSCOUT_BROKER_HOST ?? null,
10008
10064
  brokerPort: process.env.OPENSCOUT_BROKER_PORT ?? null,
10009
10065
  brokerUrl: process.env.OPENSCOUT_BROKER_URL ?? null,
10066
+ advertiseScope: process.env.OPENSCOUT_ADVERTISE_SCOPE ?? null,
10010
10067
  nodeId: process.env.OPENSCOUT_NODE_ID ?? null,
10011
10068
  nodeName: process.env.OPENSCOUT_NODE_NAME ?? null,
10012
10069
  discoveryIntervalMs: process.env.OPENSCOUT_MESH_DISCOVERY_INTERVAL_MS ?? null
@@ -10027,7 +10084,9 @@ function computeWarnings(health, localNode, nodes, tailscale) {
10027
10084
  return warnings;
10028
10085
  }
10029
10086
  if (localNode?.advertiseScope === "local") {
10030
- warnings.push("Broker is bound to 127.0.0.1 \u2014 mesh peers cannot reach it. " + "Set OPENSCOUT_BROKER_HOST=0.0.0.0 or use your Tailscale IP.");
10087
+ warnings.push("Node advertise scope is `local` \u2014 peers will not discover this broker. " + "Set OPENSCOUT_ADVERTISE_SCOPE=mesh and restart the broker.");
10088
+ } else if (localNode?.advertiseScope === "mesh" && localNode.brokerUrl && isLoopbackBrokerUrl(localNode.brokerUrl)) {
10089
+ warnings.push("Broker advertises mesh scope but is bound to loopback \u2014 peers cannot reach it. " + "Unset OPENSCOUT_BROKER_HOST (mesh default is 0.0.0.0) or use your Tailscale IP.");
10031
10090
  }
10032
10091
  const remoteNodes = Object.values(nodes).filter((n) => n.id !== localNode?.id);
10033
10092
  if (remoteNodes.length === 0 && tailscale.onlineCount > 0) {
@@ -2272,27 +2272,38 @@ function agentIdentityMatches(identity, candidate) {
2272
2272
  return true;
2273
2273
  }
2274
2274
  function resolveAgentIdentity(identity, candidates) {
2275
+ const diagnosis = diagnoseAgentIdentity(identity, candidates);
2276
+ return diagnosis.kind === "resolved" ? diagnosis.match : null;
2277
+ }
2278
+ function diagnoseAgentIdentity(identity, candidates) {
2275
2279
  const aliasKeys = identityAliasKeys(identity);
2276
2280
  const exactAliasMatches = candidates.filter((candidate) => {
2277
2281
  const candidateAliasKeys = explicitCandidateAliases(candidate).map(canonicalizeAliasValue);
2278
2282
  return aliasKeys.some((key) => candidateAliasKeys.includes(key));
2279
2283
  });
2280
2284
  if (exactAliasMatches.length === 1) {
2281
- return exactAliasMatches[0];
2285
+ return { kind: "resolved", match: exactAliasMatches[0] };
2282
2286
  }
2283
2287
  if (exactAliasMatches.length > 1) {
2284
- return null;
2288
+ return { kind: "ambiguous", candidates: exactAliasMatches };
2285
2289
  }
2286
2290
  const matches = candidates.filter((candidate) => agentIdentityMatches(identity, candidate));
2287
2291
  if (matches.length === 1) {
2288
- return matches[0];
2292
+ return { kind: "resolved", match: matches[0] };
2293
+ }
2294
+ if (matches.length === 0) {
2295
+ return { kind: "unknown" };
2289
2296
  }
2290
2297
  if (!identity.nodeQualifier && !identity.workspaceQualifier && !identity.profile && !identity.harness) {
2291
- return matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId) ?? matches[0] ?? null;
2298
+ const exactIdMatch = matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId);
2299
+ if (exactIdMatch) {
2300
+ return { kind: "resolved", match: exactIdMatch };
2301
+ }
2302
+ return { kind: "ambiguous", candidates: matches };
2292
2303
  }
2293
- return null;
2304
+ return { kind: "ambiguous", candidates: matches };
2294
2305
  }
2295
- var DIMENSION_ALIASES, normalizeAgentSelectorSegment, parseAgentSelector, formatAgentSelector, resolveAgentSelector;
2306
+ var DIMENSION_ALIASES, normalizeAgentSelectorSegment, SCOUT_DISPATCHER_AGENT_ID = "scout", RESERVED_AGENT_DEFINITION_IDS, parseAgentSelector, formatAgentSelector, resolveAgentSelector;
2296
2307
  var init_agent_identity = __esm(() => {
2297
2308
  DIMENSION_ALIASES = {
2298
2309
  workspace: "workspace",
@@ -2306,6 +2317,9 @@ var init_agent_identity = __esm(() => {
2306
2317
  host: "node"
2307
2318
  };
2308
2319
  normalizeAgentSelectorSegment = normalizeAgentIdentitySegment;
2320
+ RESERVED_AGENT_DEFINITION_IDS = new Set([
2321
+ SCOUT_DISPATCHER_AGENT_ID
2322
+ ]);
2309
2323
  parseAgentSelector = parseAgentIdentity;
2310
2324
  formatAgentSelector = formatAgentIdentity;
2311
2325
  resolveAgentSelector = resolveAgentIdentity;
@@ -4751,6 +4765,24 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as rea
4751
4765
  import { homedir as homedir11 } from "os";
4752
4766
  import { basename as basename2, dirname as dirname4, join as join12, resolve as resolve3 } from "path";
4753
4767
  import { fileURLToPath as fileURLToPath3 } from "url";
4768
+ function isTmpPath(p) {
4769
+ return /^\/(?:private\/)?tmp\//.test(p);
4770
+ }
4771
+ function resolveAdvertiseScope() {
4772
+ const raw = (process.env.OPENSCOUT_ADVERTISE_SCOPE ?? "").trim().toLowerCase();
4773
+ if (raw === "mesh")
4774
+ return "mesh";
4775
+ if (raw === "local")
4776
+ return "local";
4777
+ return DEFAULT_ADVERTISE_SCOPE;
4778
+ }
4779
+ function resolveBrokerHost(scope = resolveAdvertiseScope()) {
4780
+ const explicit = process.env.OPENSCOUT_BROKER_HOST;
4781
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
4782
+ return explicit;
4783
+ }
4784
+ return scope === "mesh" ? DEFAULT_BROKER_HOST_MESH : DEFAULT_BROKER_HOST;
4785
+ }
4754
4786
  function buildDefaultBrokerUrl(host = DEFAULT_BROKER_HOST, port = DEFAULT_BROKER_PORT) {
4755
4787
  return `http://${host}:${port}`;
4756
4788
  }
@@ -4771,15 +4803,28 @@ function isInstalledRuntimePackageDir(candidate) {
4771
4803
  return existsSync9(join12(candidate, "package.json")) && existsSync9(join12(candidate, "bin", "openscout-runtime.mjs"));
4772
4804
  }
4773
4805
  function findGlobalRuntimeDir() {
4774
- const bunCandidate = join12(homedir11(), ".bun", "node_modules", "@openscout", "runtime");
4775
- if (isInstalledRuntimePackageDir(bunCandidate))
4776
- return bunCandidate;
4777
- const bunGlobalCandidate = join12(homedir11(), ".bun", "install", "global", "node_modules", "@openscout", "runtime");
4778
- if (isInstalledRuntimePackageDir(bunGlobalCandidate))
4779
- return bunGlobalCandidate;
4780
- const bunScoutNested = join12(homedir11(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime");
4781
- if (isInstalledRuntimePackageDir(bunScoutNested))
4782
- return bunScoutNested;
4806
+ const candidates = [
4807
+ join12(homedir11(), ".bun", "node_modules", "@openscout", "runtime"),
4808
+ join12(homedir11(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
4809
+ join12(homedir11(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
4810
+ ];
4811
+ for (const c of candidates) {
4812
+ if (isInstalledRuntimePackageDir(c))
4813
+ return c;
4814
+ }
4815
+ try {
4816
+ const result = spawnSync("which", ["scout"], { encoding: "utf8", timeout: 3000 });
4817
+ const scoutBin = result.stdout?.trim();
4818
+ if (scoutBin) {
4819
+ const scoutPkg = resolve3(scoutBin, "..", "..");
4820
+ const nested = join12(scoutPkg, "node_modules", "@openscout", "runtime");
4821
+ if (isInstalledRuntimePackageDir(nested))
4822
+ return nested;
4823
+ const sibling = resolve3(scoutPkg, "..", "runtime");
4824
+ if (isInstalledRuntimePackageDir(sibling))
4825
+ return sibling;
4826
+ }
4827
+ } catch {}
4783
4828
  return null;
4784
4829
  }
4785
4830
  function findWorkspaceRuntimeDir(startDir) {
@@ -4853,11 +4898,12 @@ function resolveBrokerServiceConfig() {
4853
4898
  const label = resolveBrokerServiceLabel(mode);
4854
4899
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
4855
4900
  const supportPaths = resolveOpenScoutSupportPaths();
4856
- const supportDirectory = supportPaths.supportDirectory;
4857
- const logsDirectory = supportPaths.brokerLogsDirectory;
4858
- const rawControlHome = supportPaths.controlHome;
4859
- const controlHome = /^\/(?:private\/)?tmp\//.test(rawControlHome) ? join12(homedir11(), ".openscout", "control-plane") : rawControlHome;
4860
- const brokerHost = process.env.OPENSCOUT_BROKER_HOST ?? DEFAULT_BROKER_HOST;
4901
+ const defaultSupportDir = join12(homedir11(), "Library", "Application Support", "OpenScout");
4902
+ const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
4903
+ const logsDirectory = join12(supportDirectory, "logs", "broker");
4904
+ const controlHome = isTmpPath(supportPaths.controlHome) ? join12(homedir11(), ".openscout", "control-plane") : supportPaths.controlHome;
4905
+ const advertiseScope = resolveAdvertiseScope();
4906
+ const brokerHost = resolveBrokerHost(advertiseScope);
4861
4907
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
4862
4908
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
4863
4909
  const launchAgentPath = join12(homedir11(), "Library", "LaunchAgents", `${label}.plist`);
@@ -4877,7 +4923,8 @@ function resolveBrokerServiceConfig() {
4877
4923
  bunExecutable: resolveBunExecutable(),
4878
4924
  brokerHost,
4879
4925
  brokerPort,
4880
- brokerUrl
4926
+ brokerUrl,
4927
+ advertiseScope
4881
4928
  };
4882
4929
  }
4883
4930
  function renderLaunchAgentPlist(config) {
@@ -4889,6 +4936,7 @@ function renderLaunchAgentPlist(config) {
4889
4936
  OPENSCOUT_CONTROL_HOME: config.controlHome,
4890
4937
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
4891
4938
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
4939
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
4892
4940
  HOME: homedir11(),
4893
4941
  PATH: launchPath,
4894
4942
  ...collectOptionalEnvVars([
@@ -4959,7 +5007,7 @@ function resolveLaunchAgentPATH() {
4959
5007
  "/usr/sbin",
4960
5008
  "/sbin"
4961
5009
  ];
4962
- return Array.from(new Set(entries)).join(":");
5010
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
4963
5011
  }
4964
5012
  function xmlEscape(value) {
4965
5013
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -5218,7 +5266,7 @@ function formatBrokerServiceStatus(status) {
5218
5266
  return lines.join(`
5219
5267
  `);
5220
5268
  }
5221
- var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_PORT = 65535, BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
5269
+ var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_HOST_MESH = "0.0.0.0", DEFAULT_BROKER_PORT = 65535, DEFAULT_ADVERTISE_SCOPE = "local", BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
5222
5270
  var init_broker_service = __esm(async () => {
5223
5271
  init_support_paths();
5224
5272
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();
@@ -1201,27 +1201,38 @@ function agentIdentityMatches(identity, candidate) {
1201
1201
  return true;
1202
1202
  }
1203
1203
  function resolveAgentIdentity(identity, candidates) {
1204
+ const diagnosis = diagnoseAgentIdentity(identity, candidates);
1205
+ return diagnosis.kind === "resolved" ? diagnosis.match : null;
1206
+ }
1207
+ function diagnoseAgentIdentity(identity, candidates) {
1204
1208
  const aliasKeys = identityAliasKeys(identity);
1205
1209
  const exactAliasMatches = candidates.filter((candidate) => {
1206
1210
  const candidateAliasKeys = explicitCandidateAliases(candidate).map(canonicalizeAliasValue);
1207
1211
  return aliasKeys.some((key) => candidateAliasKeys.includes(key));
1208
1212
  });
1209
1213
  if (exactAliasMatches.length === 1) {
1210
- return exactAliasMatches[0];
1214
+ return { kind: "resolved", match: exactAliasMatches[0] };
1211
1215
  }
1212
1216
  if (exactAliasMatches.length > 1) {
1213
- return null;
1217
+ return { kind: "ambiguous", candidates: exactAliasMatches };
1214
1218
  }
1215
1219
  const matches = candidates.filter((candidate) => agentIdentityMatches(identity, candidate));
1216
1220
  if (matches.length === 1) {
1217
- return matches[0];
1221
+ return { kind: "resolved", match: matches[0] };
1222
+ }
1223
+ if (matches.length === 0) {
1224
+ return { kind: "unknown" };
1218
1225
  }
1219
1226
  if (!identity.nodeQualifier && !identity.workspaceQualifier && !identity.profile && !identity.harness) {
1220
- return matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId) ?? matches[0] ?? null;
1227
+ const exactIdMatch = matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId);
1228
+ if (exactIdMatch) {
1229
+ return { kind: "resolved", match: exactIdMatch };
1230
+ }
1231
+ return { kind: "ambiguous", candidates: matches };
1221
1232
  }
1222
- return null;
1233
+ return { kind: "ambiguous", candidates: matches };
1223
1234
  }
1224
- var DIMENSION_ALIASES, normalizeAgentSelectorSegment, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
1235
+ var DIMENSION_ALIASES, normalizeAgentSelectorSegment, SCOUT_DISPATCHER_AGENT_ID = "scout", RESERVED_AGENT_DEFINITION_IDS, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
1225
1236
  var init_agent_identity = __esm(() => {
1226
1237
  DIMENSION_ALIASES = {
1227
1238
  workspace: "workspace",
@@ -1235,6 +1246,9 @@ var init_agent_identity = __esm(() => {
1235
1246
  host: "node"
1236
1247
  };
1237
1248
  normalizeAgentSelectorSegment = normalizeAgentIdentitySegment;
1249
+ RESERVED_AGENT_DEFINITION_IDS = new Set([
1250
+ SCOUT_DISPATCHER_AGENT_ID
1251
+ ]);
1238
1252
  parseAgentSelector = parseAgentIdentity;
1239
1253
  formatAgentSelector = formatAgentIdentity;
1240
1254
  extractAgentSelectors = extractAgentIdentities;
@@ -4163,6 +4177,24 @@ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as rea
4163
4177
  import { homedir as homedir5 } from "os";
4164
4178
  import { basename as basename2, dirname as dirname5, join as join8, resolve as resolve4 } from "path";
4165
4179
  import { fileURLToPath as fileURLToPath4 } from "url";
4180
+ function isTmpPath(p) {
4181
+ return /^\/(?:private\/)?tmp\//.test(p);
4182
+ }
4183
+ function resolveAdvertiseScope() {
4184
+ const raw2 = (process.env.OPENSCOUT_ADVERTISE_SCOPE ?? "").trim().toLowerCase();
4185
+ if (raw2 === "mesh")
4186
+ return "mesh";
4187
+ if (raw2 === "local")
4188
+ return "local";
4189
+ return DEFAULT_ADVERTISE_SCOPE;
4190
+ }
4191
+ function resolveBrokerHost(scope = resolveAdvertiseScope()) {
4192
+ const explicit = process.env.OPENSCOUT_BROKER_HOST;
4193
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
4194
+ return explicit;
4195
+ }
4196
+ return scope === "mesh" ? DEFAULT_BROKER_HOST_MESH : DEFAULT_BROKER_HOST;
4197
+ }
4166
4198
  function buildDefaultBrokerUrl(host = DEFAULT_BROKER_HOST, port = DEFAULT_BROKER_PORT) {
4167
4199
  return `http://${host}:${port}`;
4168
4200
  }
@@ -4183,15 +4215,28 @@ function isInstalledRuntimePackageDir(candidate) {
4183
4215
  return existsSync6(join8(candidate, "package.json")) && existsSync6(join8(candidate, "bin", "openscout-runtime.mjs"));
4184
4216
  }
4185
4217
  function findGlobalRuntimeDir() {
4186
- const bunCandidate = join8(homedir5(), ".bun", "node_modules", "@openscout", "runtime");
4187
- if (isInstalledRuntimePackageDir(bunCandidate))
4188
- return bunCandidate;
4189
- const bunGlobalCandidate = join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "runtime");
4190
- if (isInstalledRuntimePackageDir(bunGlobalCandidate))
4191
- return bunGlobalCandidate;
4192
- const bunScoutNested = join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime");
4193
- if (isInstalledRuntimePackageDir(bunScoutNested))
4194
- return bunScoutNested;
4218
+ const candidates = [
4219
+ join8(homedir5(), ".bun", "node_modules", "@openscout", "runtime"),
4220
+ join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
4221
+ join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
4222
+ ];
4223
+ for (const c of candidates) {
4224
+ if (isInstalledRuntimePackageDir(c))
4225
+ return c;
4226
+ }
4227
+ try {
4228
+ const result = spawnSync("which", ["scout"], { encoding: "utf8", timeout: 3000 });
4229
+ const scoutBin = result.stdout?.trim();
4230
+ if (scoutBin) {
4231
+ const scoutPkg = resolve4(scoutBin, "..", "..");
4232
+ const nested = join8(scoutPkg, "node_modules", "@openscout", "runtime");
4233
+ if (isInstalledRuntimePackageDir(nested))
4234
+ return nested;
4235
+ const sibling = resolve4(scoutPkg, "..", "runtime");
4236
+ if (isInstalledRuntimePackageDir(sibling))
4237
+ return sibling;
4238
+ }
4239
+ } catch {}
4195
4240
  return null;
4196
4241
  }
4197
4242
  function findWorkspaceRuntimeDir(startDir) {
@@ -4265,11 +4310,12 @@ function resolveBrokerServiceConfig() {
4265
4310
  const label = resolveBrokerServiceLabel(mode);
4266
4311
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
4267
4312
  const supportPaths = resolveOpenScoutSupportPaths();
4268
- const supportDirectory = supportPaths.supportDirectory;
4269
- const logsDirectory = supportPaths.brokerLogsDirectory;
4270
- const rawControlHome = supportPaths.controlHome;
4271
- const controlHome = /^\/(?:private\/)?tmp\//.test(rawControlHome) ? join8(homedir5(), ".openscout", "control-plane") : rawControlHome;
4272
- const brokerHost = process.env.OPENSCOUT_BROKER_HOST ?? DEFAULT_BROKER_HOST;
4313
+ const defaultSupportDir = join8(homedir5(), "Library", "Application Support", "OpenScout");
4314
+ const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
4315
+ const logsDirectory = join8(supportDirectory, "logs", "broker");
4316
+ const controlHome = isTmpPath(supportPaths.controlHome) ? join8(homedir5(), ".openscout", "control-plane") : supportPaths.controlHome;
4317
+ const advertiseScope = resolveAdvertiseScope();
4318
+ const brokerHost = resolveBrokerHost(advertiseScope);
4273
4319
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
4274
4320
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
4275
4321
  const launchAgentPath = join8(homedir5(), "Library", "LaunchAgents", `${label}.plist`);
@@ -4289,7 +4335,8 @@ function resolveBrokerServiceConfig() {
4289
4335
  bunExecutable: resolveBunExecutable(),
4290
4336
  brokerHost,
4291
4337
  brokerPort,
4292
- brokerUrl
4338
+ brokerUrl,
4339
+ advertiseScope
4293
4340
  };
4294
4341
  }
4295
4342
  function renderLaunchAgentPlist(config) {
@@ -4301,6 +4348,7 @@ function renderLaunchAgentPlist(config) {
4301
4348
  OPENSCOUT_CONTROL_HOME: config.controlHome,
4302
4349
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
4303
4350
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
4351
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
4304
4352
  HOME: homedir5(),
4305
4353
  PATH: launchPath,
4306
4354
  ...collectOptionalEnvVars([
@@ -4371,7 +4419,7 @@ function resolveLaunchAgentPATH() {
4371
4419
  "/usr/sbin",
4372
4420
  "/sbin"
4373
4421
  ];
4374
- return Array.from(new Set(entries)).join(":");
4422
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
4375
4423
  }
4376
4424
  function xmlEscape(value) {
4377
4425
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -4630,7 +4678,7 @@ function formatBrokerServiceStatus(status) {
4630
4678
  return lines.join(`
4631
4679
  `);
4632
4680
  }
4633
- var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_PORT = 65535, BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
4681
+ var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_HOST_MESH = "0.0.0.0", DEFAULT_BROKER_PORT = 65535, DEFAULT_ADVERTISE_SCOPE = "local", BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
4634
4682
  var init_broker_service = __esm(async () => {
4635
4683
  init_support_paths();
4636
4684
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();