bosun 0.42.2 → 0.42.5
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 +9 -0
- package/agent/agent-custom-tools.mjs +10 -12
- package/agent/agent-event-bus.mjs +10 -0
- package/agent/agent-pool.mjs +15 -0
- package/agent/agent-prompt-catalog.mjs +4 -4
- package/agent/agent-prompts.mjs +20 -0
- package/agent/agent-supervisor.mjs +20 -0
- package/agent/bosun-skills.mjs +162 -832
- package/agent/fleet-coordinator.mjs +3 -16
- package/bosun-tui.mjs +107 -105
- package/cli.mjs +11 -0
- package/config/config.mjs +25 -0
- package/config/executor-config.mjs +124 -1
- package/infra/container-runner.mjs +565 -1
- package/infra/monitor.mjs +21 -0
- package/infra/tracing.mjs +775 -280
- package/infra/tui-bridge.mjs +13 -1
- package/kanban/kanban-adapter.mjs +131 -19
- package/kanban/vibe-kanban-wrapper.mjs +0 -0
- package/lib/repo-map.mjs +114 -3
- package/package.json +13 -5
- package/server/ui-server.mjs +151 -48
- package/shell/codex-config.mjs +33 -8
- package/shell/opencode-providers.mjs +41 -3
- package/task/task-archiver.mjs +18 -6
- package/task/task-attachments.mjs +14 -10
- package/task/task-cli.mjs +24 -4
- package/task/task-executor.mjs +110 -61
- package/task/task-store.mjs +194 -37
- package/telegram/get-telegram-chat-id.mjs +0 -0
- package/telegram/telegram-bot.mjs +4 -1
- package/telegram/telegram-sentinel.mjs +0 -0
- package/tools/import-check.mjs +234 -0
- package/tools/prompt-lint.mjs +161 -0
- package/tools/syntax-check.mjs +29 -0
- package/tools/test-shared-state-integration.mjs +2 -9
- package/tui/app.mjs +158 -182
- package/tui/components/status-header.mjs +178 -75
- package/tui/lib/fuzzy-score.mjs +61 -0
- package/tui/lib/header-config.mjs +68 -0
- package/tui/lib/navigation.mjs +15 -0
- package/tui/lib/sparkline.mjs +38 -0
- package/tui/lib/ws-bridge.mjs +152 -29
- package/tui/screens/agents-screen-helpers.mjs +1 -1
- package/tui/screens/agents.mjs +153 -8
- package/tui/screens/tasks-screen-helpers.mjs +78 -0
- package/tui/screens/tasks.mjs +1 -48
- package/ui/app.js +8 -5
- package/ui/components/chat-view.js.bak +1 -0
- package/ui/components/kanban-board.js +65 -3
- package/ui/components/session-list.js +18 -32
- package/ui/demo-defaults.js +200 -75
- package/ui/demo.html +10 -0
- package/ui/modules/api.js +109 -34
- package/ui/modules/session-api.js +100 -0
- package/ui/modules/state.js +160 -53
- package/ui/tabs/infra.js.bak +1 -0
- package/ui/tabs/workflow-canvas-utils.mjs +555 -13
- package/ui/tabs/workflows.js +810 -87
- package/ui/tui/App.js +298 -0
- package/ui/tui/TasksScreen.js +564 -0
- package/ui/tui/constants.js +55 -0
- package/ui/tui/tasks-screen-helpers.js +301 -0
- package/ui/tui/useTasks.js +61 -0
- package/ui/tui/useWebSocket.js +166 -0
- package/ui/tui/useWorkflows.js +30 -0
- package/voice/vision-session-state.mjs +317 -2
- package/voice/voice-action-dispatcher.mjs +184 -9
- package/voice/voice-relay.mjs +33 -0
- package/workflow/execution-ledger.mjs +534 -3
- package/workflow/workflow-cli.mjs +45 -1
- package/workflow/workflow-engine.mjs +859 -90
- package/workflow/workflow-nodes/custom-loader.mjs +259 -56
- package/workflow/workflow-nodes.mjs +1061 -159
- package/workflow-templates/agents.mjs +3 -0
- package/workflow-templates/github.mjs +70 -47
- package/workflow-templates/planning.mjs +7 -0
- package/workflow-templates/sub-workflows.mjs +5 -0
- package/workflow-templates/task-execution.mjs +3 -0
- package/workspace/command-diagnostics.mjs +1 -1
- package/workspace/context-cache.mjs +182 -9
- package/workspace/shared-workspace-cli.mjs +0 -0
package/.env.example
CHANGED
|
@@ -802,6 +802,11 @@ VK_RECOVERY_PORT=54089
|
|
|
802
802
|
# BOSUN_HOOKS_DISABLE_TASK_COMPLETE=false
|
|
803
803
|
# BOSUN_HOOKS_DISABLE_HEALTH_CHECK=false
|
|
804
804
|
|
|
805
|
+
# ── OpenTelemetry Tracing & Metrics ───────────────────────────────────────────
|
|
806
|
+
# External orchestration-layer observability only; never affects agent context.
|
|
807
|
+
# BOSUN_OTEL_ENDPOINT=http://localhost:4318/v1/traces
|
|
808
|
+
# Configure tracing.sampleRate in bosun.config.json to tune sampling.
|
|
809
|
+
|
|
805
810
|
# Force hooks to fire even for non-managed sessions (debug only):
|
|
806
811
|
# BOSUN_HOOKS_FORCE=false
|
|
807
812
|
|
|
@@ -1175,3 +1180,7 @@ COPILOT_CLOUD_DISABLED=true
|
|
|
1175
1180
|
# AGENT_STUCK_THRESHOLD_MS=300000
|
|
1176
1181
|
# Alert if session costs more than $N (default: 1.0)
|
|
1177
1182
|
# AGENT_COST_ANOMALY_THRESHOLD=1.0
|
|
1183
|
+
|
|
1184
|
+
# OpenTelemetry tracing (optional)
|
|
1185
|
+
# BOSUN_OTEL_ENDPOINT=http://localhost:4318/v1/traces
|
|
1186
|
+
|
|
@@ -746,12 +746,12 @@ export function getToolsPromptBlock(rootDir, opts = {}) {
|
|
|
746
746
|
"## Custom Tools Library",
|
|
747
747
|
"",
|
|
748
748
|
discoveryMode
|
|
749
|
-
? "
|
|
750
|
-
: "
|
|
749
|
+
? "- Eager tools only below. Discover the rest at runtime."
|
|
750
|
+
: "- Run tools via `node <tool>.mjs`, `bash <tool>.sh`, or `python3 <tool>.py`.",
|
|
751
751
|
discoveryMode
|
|
752
|
-
? "Use `search`, then `get_schema`, then `execute` for tools not listed here.
|
|
753
|
-
: "
|
|
754
|
-
"Built-in tools
|
|
752
|
+
? "- Use `search`, then `get_schema`, then `execute` for tools not listed here."
|
|
753
|
+
: "- Check this library before writing new helper code.",
|
|
754
|
+
"- Built-in tools: `bosun/tools/`; workspace tools: `.bosun/tools/`.",
|
|
755
755
|
"",
|
|
756
756
|
];
|
|
757
757
|
|
|
@@ -791,16 +791,13 @@ export function getToolsPromptBlock(rootDir, opts = {}) {
|
|
|
791
791
|
lines.push(
|
|
792
792
|
"---",
|
|
793
793
|
"",
|
|
794
|
-
"
|
|
795
|
-
"
|
|
796
|
-
"
|
|
797
|
-
"
|
|
798
|
-
"team benefits. Good candidates: analysis helpers, test generators, codemods,",
|
|
799
|
-
"build/lint wrappers that differ from what `npm run *` provides.",
|
|
794
|
+
"Reflect:",
|
|
795
|
+
"- Check existing tools before writing new helpers.",
|
|
796
|
+
"- Promote repeated analysis, test, build, transform, or search logic into `.bosun/tools/`.",
|
|
797
|
+
"- Skip one-off scripts.",
|
|
800
798
|
"",
|
|
801
799
|
);
|
|
802
800
|
}
|
|
803
|
-
|
|
804
801
|
return lines.join("\n");
|
|
805
802
|
}
|
|
806
803
|
|
|
@@ -931,3 +928,4 @@ export function getAffinityTools(rootDir, opts = {}) {
|
|
|
931
928
|
.slice(0, limit)
|
|
932
929
|
.map((s) => s.tool);
|
|
933
930
|
}
|
|
931
|
+
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
reduceRetryQueue,
|
|
26
26
|
snapshotRetryQueue,
|
|
27
27
|
} from "./retry-queue.mjs";
|
|
28
|
+
import { addSpanEvent, recordAgentError, recordIntervention } from "../infra/tracing.mjs";
|
|
28
29
|
|
|
29
30
|
const TAG = "[agent-event-bus]";
|
|
30
31
|
|
|
@@ -232,6 +233,14 @@ export class AgentEventBus {
|
|
|
232
233
|
emit(type, taskId, payload = {}, opts = {}) {
|
|
233
234
|
const ts = Date.now();
|
|
234
235
|
const event = { type, taskId, payload, ts };
|
|
236
|
+
addSpanEvent(type, { "bosun.task.id": taskId, ...payload });
|
|
237
|
+
if (type === AGENT_EVENT.AGENT_ERROR) {
|
|
238
|
+
recordAgentError(payload?.errorType || payload?.classification || "agent_error", {
|
|
239
|
+
"bosun.task.id": taskId,
|
|
240
|
+
"bosun.executor": payload?.executor,
|
|
241
|
+
"bosun.agent.sdk": payload?.sdk,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
235
244
|
|
|
236
245
|
// ── Dedup
|
|
237
246
|
const key = `${type}:${taskId}`;
|
|
@@ -1092,3 +1101,4 @@ export function createAgentEventBus(options) {
|
|
|
1092
1101
|
return new AgentEventBus(options);
|
|
1093
1102
|
}
|
|
1094
1103
|
|
|
1104
|
+
|
package/agent/agent-pool.mjs
CHANGED
|
@@ -791,6 +791,9 @@ function buildCodexSdkOptions(envInput = process.env) {
|
|
|
791
791
|
wire_api: "responses",
|
|
792
792
|
},
|
|
793
793
|
},
|
|
794
|
+
features: {
|
|
795
|
+
remote_models: false,
|
|
796
|
+
},
|
|
794
797
|
...(azureModel ? { model: azureModel } : {}),
|
|
795
798
|
},
|
|
796
799
|
};
|
|
@@ -1222,6 +1225,7 @@ async function launchCodexThread(prompt, cwd, timeoutMs, extra = {}) {
|
|
|
1222
1225
|
codexOpts.config = {
|
|
1223
1226
|
...(codexOpts.config || {}),
|
|
1224
1227
|
features: {
|
|
1228
|
+
...(codexOpts.config?.features || {}),
|
|
1225
1229
|
child_agents_md: true,
|
|
1226
1230
|
multi_agent: true,
|
|
1227
1231
|
memories: true,
|
|
@@ -3158,6 +3162,17 @@ async function resumeCodexThread(threadId, prompt, cwd, timeoutMs, extra = {}) {
|
|
|
3158
3162
|
codexOpts.env = { ...(codexOpts.env || {}), CODEX_MODEL: modelOverride };
|
|
3159
3163
|
codexOpts.config = { ...(codexOpts.config || {}), model: modelOverride };
|
|
3160
3164
|
}
|
|
3165
|
+
codexOpts.config = {
|
|
3166
|
+
...(codexOpts.config || {}),
|
|
3167
|
+
features: {
|
|
3168
|
+
...(codexOpts.config?.features || {}),
|
|
3169
|
+
child_agents_md: true,
|
|
3170
|
+
multi_agent: true,
|
|
3171
|
+
memories: true,
|
|
3172
|
+
undo: true,
|
|
3173
|
+
steer: true,
|
|
3174
|
+
},
|
|
3175
|
+
};
|
|
3161
3176
|
const codex = new CodexClass(codexOpts);
|
|
3162
3177
|
|
|
3163
3178
|
let thread;
|
|
@@ -909,7 +909,7 @@ Examples:
|
|
|
909
909
|
- For numbers, say them naturally: "You have 12 tasks in the backlog."
|
|
910
910
|
- When tasks or agents are busy, keep the user informed.
|
|
911
911
|
- For long outputs (code, logs), summarize the key points vocally.
|
|
912
|
-
- When delegating to an agent,
|
|
912
|
+
- When delegating to an agent, say: "Sending that to Codex now."
|
|
913
913
|
|
|
914
914
|
## Error Handling
|
|
915
915
|
|
|
@@ -938,7 +938,7 @@ Be concise. Lead with answers. Summarize long outputs.
|
|
|
938
938
|
|
|
939
939
|
customToolReflect: `## Reflect: Custom Tool Extraction
|
|
940
940
|
|
|
941
|
-
Before closing
|
|
941
|
+
Before closing the task, check for reusable tooling:
|
|
942
942
|
|
|
943
943
|
1. **Did you write any utility code (≥ 10 lines) that you'd write again?**
|
|
944
944
|
If yes — extract it into a persistent custom tool in \`.bosun/tools/\`.
|
|
@@ -948,7 +948,7 @@ Before closing this task, reflect on the work you just completed:
|
|
|
948
948
|
If yes — package it as a custom tool so future agents skip the re-derivation.
|
|
949
949
|
|
|
950
950
|
3. **Did an existing custom tool help you?**
|
|
951
|
-
Consider
|
|
951
|
+
Consider promoting it to global scope (\`promoteToGlobal\`).
|
|
952
952
|
|
|
953
953
|
4. **What category does the extracted logic fall into?**
|
|
954
954
|
analysis | testing | git | build | transform | search | validation | utility
|
|
@@ -962,7 +962,7 @@ registerCustomTool(rootDir, {
|
|
|
962
962
|
});
|
|
963
963
|
\`\`\`
|
|
964
964
|
|
|
965
|
-
|
|
965
|
+
Extract only when reuse is clear. Skip one-off logic.
|
|
966
966
|
`,
|
|
967
967
|
|
|
968
968
|
customToolsContext: `{{CUSTOM_TOOLS_BLOCK}}
|
package/agent/agent-prompts.mjs
CHANGED
|
@@ -174,6 +174,26 @@ export function resolvePromptTemplate(template, values, fallback) {
|
|
|
174
174
|
return rendered && rendered.trim() ? rendered : base;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
export async function buildCustomToolsContextPrompt(rootDir, opts = {}) {
|
|
178
|
+
const { getToolsPromptBlock, listCustomTools } = await import("./agent-custom-tools.mjs");
|
|
179
|
+
const registeredTools = listCustomTools(rootDir, {
|
|
180
|
+
includeBuiltins: false,
|
|
181
|
+
});
|
|
182
|
+
if (registeredTools.length === 0) return "";
|
|
183
|
+
|
|
184
|
+
const promptTemplate = DEFAULT_PROMPTS.customToolsContext || "{{CUSTOM_TOOLS_BLOCK}}";
|
|
185
|
+
const toolsBlock = getToolsPromptBlock(rootDir, opts);
|
|
186
|
+
if (!toolsBlock.trim()) return "";
|
|
187
|
+
|
|
188
|
+
return renderPromptTemplate(
|
|
189
|
+
promptTemplate,
|
|
190
|
+
{
|
|
191
|
+
CUSTOM_TOOLS_BLOCK: toolsBlock,
|
|
192
|
+
},
|
|
193
|
+
rootDir,
|
|
194
|
+
).trim();
|
|
195
|
+
}
|
|
196
|
+
|
|
177
197
|
export function ensureAgentPromptWorkspace(repoRoot) {
|
|
178
198
|
const root = resolve(repoRoot || process.cwd());
|
|
179
199
|
let workspaceDir = getDefaultPromptWorkspace(root);
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
* @module agent-supervisor
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
+
import { addSpanEvent, recordIntervention } from "../infra/tracing.mjs";
|
|
33
|
+
|
|
32
34
|
const TAG = "[agent-supervisor]";
|
|
33
35
|
const API_ERROR_CONTINUE_COOLDOWNS_MS = Object.freeze([
|
|
34
36
|
3 * 60_000,
|
|
@@ -473,6 +475,12 @@ export class AgentSupervisor {
|
|
|
473
475
|
}
|
|
474
476
|
|
|
475
477
|
this._lastDecision.set(taskId, { situation, intervention, ts: Date.now() });
|
|
478
|
+
addSpanEvent("bosun.supervisor.assess", {
|
|
479
|
+
"bosun.task.id": taskId,
|
|
480
|
+
"bosun.health.score": healthScore,
|
|
481
|
+
"bosun.situation": situation,
|
|
482
|
+
"bosun.intervention.type": intervention,
|
|
483
|
+
});
|
|
476
484
|
|
|
477
485
|
return { situation, healthScore, intervention, prompt, reason };
|
|
478
486
|
}
|
|
@@ -489,6 +497,18 @@ export class AgentSupervisor {
|
|
|
489
497
|
);
|
|
490
498
|
|
|
491
499
|
try {
|
|
500
|
+
if (intervention !== INTERVENTION.NONE) {
|
|
501
|
+
recordIntervention(intervention, {
|
|
502
|
+
"bosun.task.id": taskId,
|
|
503
|
+
"bosun.situation": situation,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
addSpanEvent("bosun.supervisor.intervention", {
|
|
507
|
+
"bosun.task.id": taskId,
|
|
508
|
+
"bosun.intervention.type": intervention,
|
|
509
|
+
"bosun.situation": situation,
|
|
510
|
+
"bosun.reason": reason,
|
|
511
|
+
});
|
|
492
512
|
switch (intervention) {
|
|
493
513
|
case INTERVENTION.NONE:
|
|
494
514
|
break;
|