@openscout/scout 0.2.36 → 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,10 +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 controlHome = supportPaths.controlHome;
5630
- 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);
5631
5678
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
5632
5679
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
5633
5680
  const launchAgentPath = join7(homedir4(), "Library", "LaunchAgents", `${label}.plist`);
@@ -5647,7 +5694,8 @@ function resolveBrokerServiceConfig() {
5647
5694
  bunExecutable: resolveBunExecutable(),
5648
5695
  brokerHost,
5649
5696
  brokerPort,
5650
- brokerUrl
5697
+ brokerUrl,
5698
+ advertiseScope
5651
5699
  };
5652
5700
  }
5653
5701
  function renderLaunchAgentPlist(config) {
@@ -5659,6 +5707,7 @@ function renderLaunchAgentPlist(config) {
5659
5707
  OPENSCOUT_CONTROL_HOME: config.controlHome,
5660
5708
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
5661
5709
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
5710
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
5662
5711
  HOME: homedir4(),
5663
5712
  PATH: launchPath,
5664
5713
  ...collectOptionalEnvVars([
@@ -5729,7 +5778,7 @@ function resolveLaunchAgentPATH() {
5729
5778
  "/usr/sbin",
5730
5779
  "/sbin"
5731
5780
  ];
5732
- return Array.from(new Set(entries)).join(":");
5781
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
5733
5782
  }
5734
5783
  function xmlEscape(value) {
5735
5784
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -5988,7 +6037,7 @@ function formatBrokerServiceStatus(status) {
5988
6037
  return lines.join(`
5989
6038
  `);
5990
6039
  }
5991
- 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;
5992
6041
  var init_broker_service = __esm(async () => {
5993
6042
  init_support_paths();
5994
6043
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();
@@ -9999,6 +10048,14 @@ var init_tailscale = __esm(() => {
9999
10048
  });
10000
10049
 
10001
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
+ }
10002
10059
  function readMeshEnvVars() {
10003
10060
  return {
10004
10061
  meshId: process.env.OPENSCOUT_MESH_ID ?? null,
@@ -10006,6 +10063,7 @@ function readMeshEnvVars() {
10006
10063
  brokerHost: process.env.OPENSCOUT_BROKER_HOST ?? null,
10007
10064
  brokerPort: process.env.OPENSCOUT_BROKER_PORT ?? null,
10008
10065
  brokerUrl: process.env.OPENSCOUT_BROKER_URL ?? null,
10066
+ advertiseScope: process.env.OPENSCOUT_ADVERTISE_SCOPE ?? null,
10009
10067
  nodeId: process.env.OPENSCOUT_NODE_ID ?? null,
10010
10068
  nodeName: process.env.OPENSCOUT_NODE_NAME ?? null,
10011
10069
  discoveryIntervalMs: process.env.OPENSCOUT_MESH_DISCOVERY_INTERVAL_MS ?? null
@@ -10026,7 +10084,9 @@ function computeWarnings(health, localNode, nodes, tailscale) {
10026
10084
  return warnings;
10027
10085
  }
10028
10086
  if (localNode?.advertiseScope === "local") {
10029
- 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.");
10030
10090
  }
10031
10091
  const remoteNodes = Object.values(nodes).filter((n) => n.id !== localNode?.id);
10032
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,10 +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 controlHome = supportPaths.controlHome;
4859
- 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);
4860
4907
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
4861
4908
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
4862
4909
  const launchAgentPath = join12(homedir11(), "Library", "LaunchAgents", `${label}.plist`);
@@ -4876,7 +4923,8 @@ function resolveBrokerServiceConfig() {
4876
4923
  bunExecutable: resolveBunExecutable(),
4877
4924
  brokerHost,
4878
4925
  brokerPort,
4879
- brokerUrl
4926
+ brokerUrl,
4927
+ advertiseScope
4880
4928
  };
4881
4929
  }
4882
4930
  function renderLaunchAgentPlist(config) {
@@ -4888,6 +4936,7 @@ function renderLaunchAgentPlist(config) {
4888
4936
  OPENSCOUT_CONTROL_HOME: config.controlHome,
4889
4937
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
4890
4938
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
4939
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
4891
4940
  HOME: homedir11(),
4892
4941
  PATH: launchPath,
4893
4942
  ...collectOptionalEnvVars([
@@ -4958,7 +5007,7 @@ function resolveLaunchAgentPATH() {
4958
5007
  "/usr/sbin",
4959
5008
  "/sbin"
4960
5009
  ];
4961
- return Array.from(new Set(entries)).join(":");
5010
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
4962
5011
  }
4963
5012
  function xmlEscape(value) {
4964
5013
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -5217,7 +5266,7 @@ function formatBrokerServiceStatus(status) {
5217
5266
  return lines.join(`
5218
5267
  `);
5219
5268
  }
5220
- 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;
5221
5270
  var init_broker_service = __esm(async () => {
5222
5271
  init_support_paths();
5223
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,10 +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 controlHome = supportPaths.controlHome;
4271
- 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);
4272
4319
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
4273
4320
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
4274
4321
  const launchAgentPath = join8(homedir5(), "Library", "LaunchAgents", `${label}.plist`);
@@ -4288,7 +4335,8 @@ function resolveBrokerServiceConfig() {
4288
4335
  bunExecutable: resolveBunExecutable(),
4289
4336
  brokerHost,
4290
4337
  brokerPort,
4291
- brokerUrl
4338
+ brokerUrl,
4339
+ advertiseScope
4292
4340
  };
4293
4341
  }
4294
4342
  function renderLaunchAgentPlist(config) {
@@ -4300,6 +4348,7 @@ function renderLaunchAgentPlist(config) {
4300
4348
  OPENSCOUT_CONTROL_HOME: config.controlHome,
4301
4349
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
4302
4350
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
4351
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
4303
4352
  HOME: homedir5(),
4304
4353
  PATH: launchPath,
4305
4354
  ...collectOptionalEnvVars([
@@ -4370,7 +4419,7 @@ function resolveLaunchAgentPATH() {
4370
4419
  "/usr/sbin",
4371
4420
  "/sbin"
4372
4421
  ];
4373
- return Array.from(new Set(entries)).join(":");
4422
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
4374
4423
  }
4375
4424
  function xmlEscape(value) {
4376
4425
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -4629,7 +4678,7 @@ function formatBrokerServiceStatus(status) {
4629
4678
  return lines.join(`
4630
4679
  `);
4631
4680
  }
4632
- 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;
4633
4682
  var init_broker_service = __esm(async () => {
4634
4683
  init_support_paths();
4635
4684
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();