bosun 0.37.0 → 0.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +4 -1
- package/agent-tool-config.mjs +338 -0
- package/bosun-skills.mjs +59 -4
- package/bosun.schema.json +1 -1
- package/desktop/launch.mjs +18 -0
- package/desktop/main.mjs +52 -13
- package/fleet-coordinator.mjs +34 -1
- package/kanban-adapter.mjs +30 -3
- package/library-manager.mjs +66 -0
- package/maintenance.mjs +30 -5
- package/monitor.mjs +56 -0
- package/package.json +4 -1
- package/setup-web-server.mjs +73 -12
- package/setup.mjs +3 -3
- package/ui/app.js +40 -3
- package/ui/components/session-list.js +25 -7
- package/ui/components/workspace-switcher.js +48 -1
- package/ui/demo.html +176 -0
- package/ui/modules/mic-track-registry.js +83 -0
- package/ui/modules/settings-schema.js +4 -1
- package/ui/modules/state.js +25 -0
- package/ui/modules/streaming.js +1 -1
- package/ui/modules/voice-barge-in.js +27 -0
- package/ui/modules/voice-client-sdk.js +268 -42
- package/ui/modules/voice-client.js +665 -61
- package/ui/modules/voice-overlay.js +829 -47
- package/ui/setup.html +151 -9
- package/ui/styles.css +258 -0
- package/ui/tabs/chat.js +11 -0
- package/ui/tabs/library.js +890 -15
- package/ui/tabs/settings.js +51 -11
- package/ui/tabs/telemetry.js +327 -105
- package/ui/tabs/workflows.js +86 -0
- package/ui-server.mjs +1201 -107
- package/voice-action-dispatcher.mjs +81 -0
- package/voice-agents-sdk.mjs +2 -2
- package/voice-relay.mjs +131 -14
- package/voice-tools.mjs +475 -9
- package/workflow-engine.mjs +54 -0
- package/workflow-nodes.mjs +177 -28
- package/workflow-templates/github.mjs +205 -94
- package/workflow-templates/task-batch.mjs +247 -0
- package/workflow-templates.mjs +15 -0
package/ui/tabs/workflows.js
CHANGED
|
@@ -1102,6 +1102,72 @@ const EXPRESSION_PRESETS = [
|
|
|
1102
1102
|
{ label: "Branch Match", expr: "/^(feat|fix)\\//.test($data?.branch || '')" },
|
|
1103
1103
|
];
|
|
1104
1104
|
|
|
1105
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
1106
|
+
* Workflow Agent Library Picker
|
|
1107
|
+
* — Lets users select an agent profile from the Library
|
|
1108
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
1109
|
+
|
|
1110
|
+
function WorkflowAgentLibraryPicker({ config, onUpdate }) {
|
|
1111
|
+
const [agents, setAgents] = useState([]);
|
|
1112
|
+
const [loading, setLoading] = useState(false);
|
|
1113
|
+
const [expanded, setExpanded] = useState(false);
|
|
1114
|
+
|
|
1115
|
+
const loadAgents = useCallback(async () => {
|
|
1116
|
+
if (agents.length > 0) { setExpanded(e => !e); return; }
|
|
1117
|
+
setLoading(true);
|
|
1118
|
+
try {
|
|
1119
|
+
const res = await apiFetch("/api/library?type=agent&agentType=task");
|
|
1120
|
+
const data = Array.isArray(res?.data) ? res.data : [];
|
|
1121
|
+
setAgents(data);
|
|
1122
|
+
} catch { /* ignore */ }
|
|
1123
|
+
setLoading(false);
|
|
1124
|
+
setExpanded(true);
|
|
1125
|
+
}, [agents.length]);
|
|
1126
|
+
|
|
1127
|
+
const selectAgent = useCallback((agent) => {
|
|
1128
|
+
onUpdate("agentProfileId", agent.id);
|
|
1129
|
+
if (agent.content?.prompt) onUpdate("prompt", agent.content?.prompt);
|
|
1130
|
+
if (agent.content?.model) onUpdate("model", agent.content.model);
|
|
1131
|
+
haptic?.("light");
|
|
1132
|
+
showToast(`Agent "${agent.name || agent.id}" applied`);
|
|
1133
|
+
}, [onUpdate]);
|
|
1134
|
+
|
|
1135
|
+
const selected = config?.agentProfileId;
|
|
1136
|
+
|
|
1137
|
+
return html`
|
|
1138
|
+
<div style="margin-top: 10px; margin-bottom: 6px;">
|
|
1139
|
+
<button
|
|
1140
|
+
onClick=${loadAgents}
|
|
1141
|
+
style="width: 100%; padding: 7px 10px; font-size: 11px; border: 1px solid #2a3040; border-radius: 6px; background: #1a1f2e; color: #c9d1d9; cursor: pointer; display: flex; align-items: center; gap: 8px;"
|
|
1142
|
+
>
|
|
1143
|
+
<span class="btn-icon" style="color: #60a5fa;">${resolveIcon("users")}</span>
|
|
1144
|
+
<span style="flex: 1; text-align: left; font-weight: 500;">Library Agent Profiles</span>
|
|
1145
|
+
${selected && html`<span style="font-size: 10px; background: #1e3a5f; color: #60a5fa; padding: 1px 6px; border-radius: 4px;">${selected}</span>`}
|
|
1146
|
+
<span style="font-size: 10px; color: #6b7280;">${loading ? "…" : (expanded ? ICONS.chevronDown : ICONS.arrowRight)}</span>
|
|
1147
|
+
</button>
|
|
1148
|
+
${expanded && html`
|
|
1149
|
+
<div style="margin-top: 6px; display: flex; flex-direction: column; gap: 4px; max-height: 220px; overflow-y: auto; padding-right: 4px;">
|
|
1150
|
+
${agents.length === 0 && html`<div style="font-size: 11px; color: #6b7280; padding: 6px;">No agent profiles in library.</div>`}
|
|
1151
|
+
${agents.map(a => html`
|
|
1152
|
+
<button
|
|
1153
|
+
key=${a.id}
|
|
1154
|
+
onClick=${() => selectAgent(a)}
|
|
1155
|
+
style="padding: 6px 10px; font-size: 11px; border: 1px solid ${selected === a.id ? '#2563eb' : '#2a3040'}; border-radius: 6px; background: ${selected === a.id ? '#1e3a5f' : '#161b22'}; color: #c9d1d9; cursor: pointer; text-align: left; transition: all 0.15s;"
|
|
1156
|
+
>
|
|
1157
|
+
<div style="font-weight: 500; display: flex; align-items: center; gap: 6px;">
|
|
1158
|
+
<span class="btn-icon" style="color: ${selected === a.id ? '#60a5fa' : '#6b7280'};">${resolveIcon("user")}</span>
|
|
1159
|
+
<span>${a.name || a.id}</span>
|
|
1160
|
+
${selected === a.id && html`<span style="margin-left: auto; font-size: 9px; color: #60a5fa;">● active</span>`}
|
|
1161
|
+
</div>
|
|
1162
|
+
${a.description && html`<div style="font-size: 10px; color: #6b7280; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${a.description}</div>`}
|
|
1163
|
+
</button>
|
|
1164
|
+
`)}
|
|
1165
|
+
</div>
|
|
1166
|
+
`}
|
|
1167
|
+
</div>
|
|
1168
|
+
`;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1105
1171
|
/* ═══════════════════════════════════════════════════════════════
|
|
1106
1172
|
* Node Config Editor (right side panel)
|
|
1107
1173
|
* ═══════════════════════════════════════════════════════════════ */
|
|
@@ -1218,6 +1284,7 @@ function NodeConfigEditor({ node, nodeTypes: types, onUpdate, onUpdateLabel, onC
|
|
|
1218
1284
|
</div>
|
|
1219
1285
|
`}
|
|
1220
1286
|
${(node.type === "action.run_agent") && html`
|
|
1287
|
+
<${WorkflowAgentLibraryPicker} config=${config} onUpdate=${onFieldChange} />
|
|
1221
1288
|
<div style="margin-top: 8px; padding: 6px 8px; background: #1a1f2e; border-radius: 6px; border-left: 3px solid #a78bfa;">
|
|
1222
1289
|
<div style="font-size: 10px; color: #a78bfa; font-weight: 600; margin-bottom: 2px; display: flex; align-items: center; gap: 6px;">
|
|
1223
1290
|
<span class="btn-icon">${resolveIcon("lightbulb")}</span>
|
|
@@ -2252,6 +2319,25 @@ export function WorkflowsTab() {
|
|
|
2252
2319
|
loadNodeTypes();
|
|
2253
2320
|
}, []);
|
|
2254
2321
|
|
|
2322
|
+
useEffect(() => {
|
|
2323
|
+
const onWorkspaceSwitched = () => {
|
|
2324
|
+
activeWorkflow.value = null;
|
|
2325
|
+
selectedRunId.value = null;
|
|
2326
|
+
selectedRunDetail.value = null;
|
|
2327
|
+
workflowRuns.value = [];
|
|
2328
|
+
workflowRunsLimit.value = WORKFLOW_RUN_PAGE_SIZE;
|
|
2329
|
+
viewMode.value = "list";
|
|
2330
|
+
setRouteParams({}, { replace: true, skipGuard: true });
|
|
2331
|
+
loadWorkflows();
|
|
2332
|
+
loadTemplates();
|
|
2333
|
+
loadNodeTypes();
|
|
2334
|
+
};
|
|
2335
|
+
window.addEventListener("ve:workspace-switched", onWorkspaceSwitched);
|
|
2336
|
+
return () => {
|
|
2337
|
+
window.removeEventListener("ve:workspace-switched", onWorkspaceSwitched);
|
|
2338
|
+
};
|
|
2339
|
+
}, []);
|
|
2340
|
+
|
|
2255
2341
|
useEffect(() => {
|
|
2256
2342
|
const route = routeParams.value || {};
|
|
2257
2343
|
const workflowId = String(route.workflowId || "").trim();
|