@backburner/cli 0.1.0
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/LICENSE +21 -0
- package/README.md +329 -0
- package/dist/src/agents/antigravity-launch.js +162 -0
- package/dist/src/agents/antigravity.js +251 -0
- package/dist/src/agents/claude-launch.js +117 -0
- package/dist/src/agents/claude.js +271 -0
- package/dist/src/agents/codex-launch.js +82 -0
- package/dist/src/agents/codex.js +261 -0
- package/dist/src/agents/composite-runner.js +13 -0
- package/dist/src/agents/extraction.js +442 -0
- package/dist/src/agents/failure-feedback.js +132 -0
- package/dist/src/agents/gemini-launch.js +96 -0
- package/dist/src/agents/gemini.js +392 -0
- package/dist/src/agents/job-agent-assignments.js +180 -0
- package/dist/src/agents/lifecycle-feedback.js +147 -0
- package/dist/src/agents/limit-detector.js +83 -0
- package/dist/src/agents/opencode-launch.js +138 -0
- package/dist/src/agents/opencode.js +156 -0
- package/dist/src/agents/plan-breakdown-feedback.js +97 -0
- package/dist/src/agents/pool.js +168 -0
- package/dist/src/agents/prompt.js +462 -0
- package/dist/src/agents/provider-sessions.js +105 -0
- package/dist/src/agents/review-feedback.js +255 -0
- package/dist/src/agents/selection.js +113 -0
- package/dist/src/agents/service.js +1087 -0
- package/dist/src/agents/types.js +1 -0
- package/dist/src/agents/wave-assessment-feedback.js +69 -0
- package/dist/src/attention/derive.js +337 -0
- package/dist/src/capabilities/index.js +2 -0
- package/dist/src/capabilities/projection.js +183 -0
- package/dist/src/capabilities/types.js +1 -0
- package/dist/src/capabilities/validator.js +87 -0
- package/dist/src/cli/commands/broker-smoke.js +96 -0
- package/dist/src/cli/commands/broker.js +56 -0
- package/dist/src/cli/commands/init.js +4 -0
- package/dist/src/cli/commands/journal.js +43 -0
- package/dist/src/cli/commands/run-loop.js +56 -0
- package/dist/src/cli/commands/run.js +1241 -0
- package/dist/src/cli/commands/tui.js +187 -0
- package/dist/src/cli/dispatcher.js +51 -0
- package/dist/src/cli/errors.js +2 -0
- package/dist/src/cli/init.js +92 -0
- package/dist/src/cli/options.js +86 -0
- package/dist/src/cli/output.js +231 -0
- package/dist/src/cli/run-journal.js +342 -0
- package/dist/src/cli/run-types.js +1 -0
- package/dist/src/cli/run.js +32 -0
- package/dist/src/cli/runtime/dispatch-lifecycle.js +772 -0
- package/dist/src/cli/runtime/provider-runtime-types.js +1 -0
- package/dist/src/cli/runtime/provider-runtime.js +152 -0
- package/dist/src/cli/runtime/provider-tools.js +73 -0
- package/dist/src/cli/runtime/providers/antigravity.js +26 -0
- package/dist/src/cli/runtime/providers/claude.js +20 -0
- package/dist/src/cli/runtime/providers/codex.js +20 -0
- package/dist/src/cli/runtime/providers/gemini.js +20 -0
- package/dist/src/cli/runtime/providers/opencode.js +20 -0
- package/dist/src/cli/runtime/run-context.js +131 -0
- package/dist/src/cli/tui/index.js +3 -0
- package/dist/src/cli/tui/screen.js +388 -0
- package/dist/src/cli/tui/tracker.js +558 -0
- package/dist/src/cli/tui/types.js +1 -0
- package/dist/src/cli/tui/views.js +1006 -0
- package/dist/src/config/loader.js +136 -0
- package/dist/src/config/schemas.js +403 -0
- package/dist/src/config/types.js +1 -0
- package/dist/src/context/types.js +331 -0
- package/dist/src/domain/entities.js +1 -0
- package/dist/src/git/backburner-git-tool-service.js +680 -0
- package/dist/src/git/gitops-lifecycle.js +56 -0
- package/dist/src/git/merge-prep-workspace.js +357 -0
- package/dist/src/git/types.js +484 -0
- package/dist/src/github/broker-model-content.js +215 -0
- package/dist/src/github/broker-server.js +237 -0
- package/dist/src/github/broker.js +638 -0
- package/dist/src/github/composed.js +53 -0
- package/dist/src/github/gateway.js +478 -0
- package/dist/src/github/normalize.js +222 -0
- package/dist/src/github/pr-classification.js +73 -0
- package/dist/src/github/scoped-broker.js +35 -0
- package/dist/src/github/security.js +126 -0
- package/dist/src/github/service.js +332 -0
- package/dist/src/github/types.js +1 -0
- package/dist/src/github/utils.js +16 -0
- package/dist/src/journal/index.js +4 -0
- package/dist/src/journal/reader.js +62 -0
- package/dist/src/journal/renderer.js +50 -0
- package/dist/src/journal/service.js +72 -0
- package/dist/src/journal/types.js +1 -0
- package/dist/src/journal/writer.js +19 -0
- package/dist/src/mcps/bridge.js +166 -0
- package/dist/src/mcps/index.js +5 -0
- package/dist/src/mcps/reconcile.js +113 -0
- package/dist/src/mcps/smithery-client.js +186 -0
- package/dist/src/mcps/smithery.js +164 -0
- package/dist/src/mcps/types.js +1 -0
- package/dist/src/memory/json-store.js +71 -0
- package/dist/src/memory/prompt.js +16 -0
- package/dist/src/memory/scope.js +31 -0
- package/dist/src/memory/store.js +1 -0
- package/dist/src/memory/tool-service.js +142 -0
- package/dist/src/memory/types.js +12 -0
- package/dist/src/onboarding/config-writer.js +96 -0
- package/dist/src/onboarding/engine.js +86 -0
- package/dist/src/onboarding/prompt.js +102 -0
- package/dist/src/onboarding/services/provider-discovery.js +58 -0
- package/dist/src/onboarding/services/repo-discovery.js +246 -0
- package/dist/src/onboarding/steps/check-github-auth.js +32 -0
- package/dist/src/onboarding/steps/check-requirements.js +34 -0
- package/dist/src/onboarding/steps/configure-models.js +105 -0
- package/dist/src/onboarding/steps/configure-paths.js +33 -0
- package/dist/src/onboarding/steps/discover-providers.js +38 -0
- package/dist/src/onboarding/steps/discover-repos.js +39 -0
- package/dist/src/onboarding/steps/generate-config.js +106 -0
- package/dist/src/onboarding/steps/readiness-validation.js +158 -0
- package/dist/src/onboarding/steps/select-repos.js +76 -0
- package/dist/src/onboarding/steps/show-summary.js +97 -0
- package/dist/src/onboarding/steps/welcome.js +27 -0
- package/dist/src/onboarding/types.js +1 -0
- package/dist/src/onboarding/validators/git-access.js +63 -0
- package/dist/src/onboarding/validators/github-auth.js +85 -0
- package/dist/src/onboarding/validators/tool-checker.js +153 -0
- package/dist/src/onboarding/validators/workspace.js +83 -0
- package/dist/src/prompts/resolver.js +106 -0
- package/dist/src/retrospectives/candidates.js +224 -0
- package/dist/src/retrospectives/derive.js +169 -0
- package/dist/src/retrospectives/ingest.js +321 -0
- package/dist/src/retrospectives/management-prs.js +380 -0
- package/dist/src/retrospectives/proposals.js +199 -0
- package/dist/src/retrospectives/scopes.js +272 -0
- package/dist/src/retrospectives/scoring.js +171 -0
- package/dist/src/retrospectives/types.js +1 -0
- package/dist/src/state/loader.js +473 -0
- package/dist/src/state/types.js +15 -0
- package/dist/src/tasks/derivation/builders.js +70 -0
- package/dist/src/tasks/derivation/handlers/comment-response.js +169 -0
- package/dist/src/tasks/derivation/handlers/implement-plan.js +103 -0
- package/dist/src/tasks/derivation/handlers/index.js +54 -0
- package/dist/src/tasks/derivation/handlers/packet-pr-control.js +92 -0
- package/dist/src/tasks/derivation/handlers/packet-worktree.js +29 -0
- package/dist/src/tasks/derivation/handlers/plan-breakdown.js +45 -0
- package/dist/src/tasks/derivation/handlers/prepare-for-merge.js +91 -0
- package/dist/src/tasks/derivation/handlers/product-discovery.js +36 -0
- package/dist/src/tasks/derivation/handlers/retry-failed-task.js +125 -0
- package/dist/src/tasks/derivation/handlers/review-pr.js +28 -0
- package/dist/src/tasks/derivation/handlers/shared.js +24 -0
- package/dist/src/tasks/derivation/handlers/sync-parent-branch.js +100 -0
- package/dist/src/tasks/derivation/handlers/wave-assessment.js +223 -0
- package/dist/src/tasks/derivation/handlers/write-plan.js +101 -0
- package/dist/src/tasks/derivation/handlers/write-product-spec.js +49 -0
- package/dist/src/tasks/derivation/runner.js +18 -0
- package/dist/src/tasks/derivation/types.js +1 -0
- package/dist/src/tasks/derive.js +810 -0
- package/dist/src/tasks/mcp-skip.js +10 -0
- package/dist/src/tasks/retry.js +10 -0
- package/dist/src/tasks/task.js +184 -0
- package/dist/src/tasks/types.js +1 -0
- package/dist/src/utils/command-runner.js +192 -0
- package/dist/src/utils/json.js +38 -0
- package/dist/src/utils/logger.js +43 -0
- package/dist/src/utils/paths.js +38 -0
- package/dist/src/utils/slug.js +10 -0
- package/dist/src/workflows/registry.js +174 -0
- package/dist/src/workflows/triage.js +90 -0
- package/dist/src/workflows/workstream-machine/derive-events.js +121 -0
- package/dist/src/workflows/workstream-machine/evaluate.js +24 -0
- package/dist/src/workflows/workstream-machine/events.js +1 -0
- package/dist/src/workflows/workstream-machine/machine.js +355 -0
- package/dist/src/workflows/workstream-machine/selectors.js +19 -0
- package/dist/src/workflows/workstream-machine/types.js +1 -0
- package/dist/src/workstreams/branch-sync.js +87 -0
- package/dist/src/workstreams/derive.js +629 -0
- package/dist/src/workstreams/mcp-blockers.js +420 -0
- package/dist/src/workstreams/packet-candidates.js +42 -0
- package/dist/src/workstreams/packet-lifecycle-feedback.js +60 -0
- package/dist/src/workstreams/packet-lifecycle-report.js +199 -0
- package/dist/src/workstreams/packet-plan.js +597 -0
- package/dist/src/workstreams/packet-projections.js +190 -0
- package/dist/src/workstreams/parent-branch-sync-action.js +312 -0
- package/dist/src/workstreams/parent-branch-sync.js +148 -0
- package/dist/src/workstreams/phases.js +4 -0
- package/dist/src/workstreams/plan-breakdown-generator/export.js +19 -0
- package/dist/src/workstreams/plan-breakdown-generator/index.js +6 -0
- package/dist/src/workstreams/plan-breakdown-generator/inspect.js +50 -0
- package/dist/src/workstreams/plan-breakdown-generator/patch.js +139 -0
- package/dist/src/workstreams/plan-breakdown-generator/session.js +19 -0
- package/dist/src/workstreams/plan-breakdown-generator/store.js +27 -0
- package/dist/src/workstreams/plan-breakdown-generator/tools.js +407 -0
- package/dist/src/workstreams/plan-breakdown-generator/types.js +6 -0
- package/dist/src/workstreams/plan-breakdown-generator/validate.js +212 -0
- package/dist/src/workstreams/plan-breakdown-schema.js +175 -0
- package/dist/src/workstreams/utils.js +15 -0
- package/dist/src/workstreams/wave-assessment/checkpoint.js +172 -0
- package/dist/src/workstreams/wave-assessment/index.js +3 -0
- package/dist/src/workstreams/wave-assessment/session.js +84 -0
- package/dist/src/workstreams/wave-assessment/store.js +51 -0
- package/dist/src/workstreams/wave-assessment/tools.js +419 -0
- package/dist/src/workstreams/wave-assessment/types.js +1 -0
- package/dist/src/workstreams/wave-assessment/validate.js +78 -0
- package/dist/src/worktrees/service.js +839 -0
- package/dist/src/worktrees/workspace-ownership.js +34 -0
- package/dist/src/worktrees/workspace-recovery.js +177 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { CodexCliAgent } from "../../agents/codex.js";
|
|
3
|
+
import { CompositeAgentRunner } from "../../agents/composite-runner.js";
|
|
4
|
+
import { GitHubBrokerService } from "../../github/broker.js";
|
|
5
|
+
import { ComposedBrokerService } from "../../github/composed.js";
|
|
6
|
+
import { ScopedBrokerToolService } from "../../github/scoped-broker.js";
|
|
7
|
+
import { createSmitheryMcpBridgeServicesFromStatuses } from "../../mcps/index.js";
|
|
8
|
+
import { createTeeFileLogger } from "../../utils/logger.js";
|
|
9
|
+
import { PlanBreakdownSessionStore } from "../../workstreams/plan-breakdown-generator/store.js";
|
|
10
|
+
import { PlanBreakdownToolService } from "../../workstreams/plan-breakdown-generator/tools.js";
|
|
11
|
+
import { WaveAssessmentSessionStore } from "../../workstreams/wave-assessment/store.js";
|
|
12
|
+
import { WaveAssessmentToolService } from "../../workstreams/wave-assessment/tools.js";
|
|
13
|
+
import { antigravityRuntimeProvider } from "./providers/antigravity.js";
|
|
14
|
+
import { claudeRuntimeProvider } from "./providers/claude.js";
|
|
15
|
+
import { codexRuntimeProvider } from "./providers/codex.js";
|
|
16
|
+
import { geminiRuntimeProvider } from "./providers/gemini.js";
|
|
17
|
+
import { openCodeRuntimeProvider } from "./providers/opencode.js";
|
|
18
|
+
import { buildCapabilitiesByProvider, buildEffectiveProviderBrokerToolAllowLists } from "./provider-tools.js";
|
|
19
|
+
const providerRuntimeDescriptors = [
|
|
20
|
+
codexRuntimeProvider,
|
|
21
|
+
geminiRuntimeProvider,
|
|
22
|
+
claudeRuntimeProvider,
|
|
23
|
+
openCodeRuntimeProvider,
|
|
24
|
+
antigravityRuntimeProvider
|
|
25
|
+
];
|
|
26
|
+
export async function setupProviderRuntime(input) {
|
|
27
|
+
let brokerServer;
|
|
28
|
+
let brokerLogger;
|
|
29
|
+
try {
|
|
30
|
+
let agentRunner = input.agentRunner;
|
|
31
|
+
let capabilitiesByProvider;
|
|
32
|
+
let providerBrokerToolAllowLists;
|
|
33
|
+
let brokerToolScope;
|
|
34
|
+
const enabledProviderDescriptors = providerRuntimeDescriptors.filter((descriptor) => descriptor.isEnabled(input.config));
|
|
35
|
+
if (!agentRunner && enabledProviderDescriptors.length > 0) {
|
|
36
|
+
const brokerToolUnion = new Set();
|
|
37
|
+
for (const descriptor of enabledProviderDescriptors) {
|
|
38
|
+
descriptor.toolAllowList(input.config).forEach((toolName) => brokerToolUnion.add(toolName));
|
|
39
|
+
}
|
|
40
|
+
brokerLogger = createTeeFileLogger(input.logger, path.join(input.logDir, "github-broker.log"));
|
|
41
|
+
const githubBrokerService = new GitHubBrokerService(input.gitHubGateway, input.config.repos, brokerLogger, Array.from(brokerToolUnion));
|
|
42
|
+
const planBreakdownSessionStore = new PlanBreakdownSessionStore(input.logDir);
|
|
43
|
+
const planBreakdownToolService = new PlanBreakdownToolService(planBreakdownSessionStore, input.logger);
|
|
44
|
+
const waveAssessmentSessionStore = new WaveAssessmentSessionStore(input.logDir);
|
|
45
|
+
const waveAssessmentToolService = new WaveAssessmentToolService(waveAssessmentSessionStore, input.logger);
|
|
46
|
+
let smitheryBridgeServices = [];
|
|
47
|
+
try {
|
|
48
|
+
smitheryBridgeServices = await createSmitheryMcpBridgeServicesFromStatuses(input.currentMcpStatuses, { apiKey: process.env.SMITHERY_API_KEY }, undefined, Array.from(brokerToolUnion));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
input.logger.warn(`Failed to initialize Smithery MCP bridge tools: ${err instanceof Error ? err.message : String(err)}`);
|
|
52
|
+
}
|
|
53
|
+
const brokerService = new ComposedBrokerService([
|
|
54
|
+
githubBrokerService,
|
|
55
|
+
...smitheryBridgeServices,
|
|
56
|
+
planBreakdownToolService,
|
|
57
|
+
waveAssessmentToolService,
|
|
58
|
+
input.memoryToolService,
|
|
59
|
+
input.backburnerGitToolService
|
|
60
|
+
]);
|
|
61
|
+
brokerToolScope = new ScopedBrokerToolService(brokerService);
|
|
62
|
+
brokerServer = await input.startBrokerServer({
|
|
63
|
+
brokerService: brokerToolScope,
|
|
64
|
+
host: "127.0.0.1",
|
|
65
|
+
port: input.brokerPort,
|
|
66
|
+
logger: brokerLogger
|
|
67
|
+
});
|
|
68
|
+
const composite = new CompositeAgentRunner();
|
|
69
|
+
const planBreakdownTools = [
|
|
70
|
+
"plan_breakdown.start_session",
|
|
71
|
+
"plan_breakdown.apply_patch",
|
|
72
|
+
"plan_breakdown.inspect_session",
|
|
73
|
+
"plan_breakdown.validate_session",
|
|
74
|
+
"plan_breakdown.export_session"
|
|
75
|
+
];
|
|
76
|
+
const memoryTools = ["memory_search", "memory_add"];
|
|
77
|
+
const waveAssessmentTools = [
|
|
78
|
+
"wave_assessment.start_session",
|
|
79
|
+
"wave_assessment.add_finding",
|
|
80
|
+
"wave_assessment.complete_session",
|
|
81
|
+
"wave_assessment.export_session"
|
|
82
|
+
];
|
|
83
|
+
const backburnerGitTools = input.backburnerGitToolService.listTools().map((tool) => tool.name);
|
|
84
|
+
const extraTools = [...planBreakdownTools, ...waveAssessmentTools, ...memoryTools, ...backburnerGitTools];
|
|
85
|
+
const providerBrokerToolAllowListsForRun = new Map();
|
|
86
|
+
for (const descriptor of enabledProviderDescriptors) {
|
|
87
|
+
providerBrokerToolAllowListsForRun.set(descriptor.provider, [
|
|
88
|
+
...descriptor.toolAllowList(input.config),
|
|
89
|
+
...extraTools
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
const registeredPublicBrokerToolNames = brokerService.listTools().map((tool) => tool.name);
|
|
93
|
+
capabilitiesByProvider = buildCapabilitiesByProvider({
|
|
94
|
+
capabilities: input.config.capabilities,
|
|
95
|
+
mcps: input.config.mcps,
|
|
96
|
+
mcpStatuses: input.currentMcpStatuses,
|
|
97
|
+
enabledAgents: input.config.agents.filter((agent) => agent.enabled),
|
|
98
|
+
providerBrokerToolAllowLists: providerBrokerToolAllowListsForRun,
|
|
99
|
+
registeredPublicBrokerToolNames
|
|
100
|
+
});
|
|
101
|
+
const effectiveProviderBrokerToolAllowListsForRun = buildEffectiveProviderBrokerToolAllowLists({
|
|
102
|
+
declaredMcps: input.config.mcps,
|
|
103
|
+
enabledAgents: input.config.agents.filter((agent) => agent.enabled),
|
|
104
|
+
providerBrokerToolAllowLists: providerBrokerToolAllowListsForRun,
|
|
105
|
+
capabilitiesByProvider,
|
|
106
|
+
registeredPublicBrokerToolNames,
|
|
107
|
+
internalAlwaysAllowedTools: extraTools
|
|
108
|
+
});
|
|
109
|
+
providerBrokerToolAllowLists = effectiveProviderBrokerToolAllowListsForRun;
|
|
110
|
+
for (const descriptor of enabledProviderDescriptors) {
|
|
111
|
+
descriptor.register({
|
|
112
|
+
composite,
|
|
113
|
+
commandRunner: input.commandRunner,
|
|
114
|
+
config: input.config,
|
|
115
|
+
logDir: input.logDir,
|
|
116
|
+
logger: input.logger,
|
|
117
|
+
serverUrl: brokerServer.url,
|
|
118
|
+
toolAllowList: effectiveProviderBrokerToolAllowListsForRun.get(descriptor.provider) ?? [],
|
|
119
|
+
planBreakdownSessionStore,
|
|
120
|
+
waveAssessmentSessionStore
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
agentRunner = composite;
|
|
124
|
+
}
|
|
125
|
+
if (!agentRunner) {
|
|
126
|
+
agentRunner = new CodexCliAgent({
|
|
127
|
+
commandRunner: input.commandRunner,
|
|
128
|
+
logDir: input.logDir,
|
|
129
|
+
logger: input.logger,
|
|
130
|
+
planBreakdownSessionStore: new PlanBreakdownSessionStore(input.logDir),
|
|
131
|
+
waveAssessmentSessionStore: new WaveAssessmentSessionStore(input.logDir)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
agentRunner,
|
|
136
|
+
...(capabilitiesByProvider ? { capabilitiesByProvider } : {}),
|
|
137
|
+
...(providerBrokerToolAllowLists ? { providerBrokerToolAllowLists } : {}),
|
|
138
|
+
...(brokerToolScope ? { brokerToolScope } : {}),
|
|
139
|
+
...(brokerServer ? { brokerServer } : {}),
|
|
140
|
+
...(brokerLogger ? { brokerLogger } : {})
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (brokerServer) {
|
|
145
|
+
await brokerServer.close();
|
|
146
|
+
}
|
|
147
|
+
if (brokerLogger) {
|
|
148
|
+
await brokerLogger.close();
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { deriveProjectedCapabilityToolNames, projectCapabilities } from "../../capabilities/projection.js";
|
|
2
|
+
export function buildCapabilitiesByProvider(input) {
|
|
3
|
+
const projections = new Map();
|
|
4
|
+
if (input.capabilities.sensors.length === 0 && input.capabilities.controllers.length === 0) {
|
|
5
|
+
return projections;
|
|
6
|
+
}
|
|
7
|
+
for (const agent of input.enabledAgents) {
|
|
8
|
+
const providerAllowList = input.providerBrokerToolAllowLists.get(agent.provider);
|
|
9
|
+
if (!providerAllowList) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
projections.set(agent.provider, projectCapabilities({
|
|
13
|
+
capabilities: input.capabilities,
|
|
14
|
+
declaredMcps: input.mcps,
|
|
15
|
+
mcpStatuses: input.mcpStatuses,
|
|
16
|
+
registeredPublicBrokerToolNames: input.registeredPublicBrokerToolNames,
|
|
17
|
+
providerRunAllowList: providerAllowList
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
return projections;
|
|
21
|
+
}
|
|
22
|
+
export function buildEffectiveProviderBrokerToolAllowLists(input) {
|
|
23
|
+
const projectedToolsByProvider = new Map();
|
|
24
|
+
for (const [provider, capabilities] of input.capabilitiesByProvider.entries()) {
|
|
25
|
+
projectedToolsByProvider.set(provider, new Set(deriveProjectedCapabilityToolNames(capabilities)));
|
|
26
|
+
}
|
|
27
|
+
const registeredTools = new Set(input.registeredPublicBrokerToolNames);
|
|
28
|
+
const internalTools = new Set(input.internalAlwaysAllowedTools);
|
|
29
|
+
const hostedMcpHandles = new Set(input.declaredMcps.map((mcp) => mcp.handle));
|
|
30
|
+
const effective = new Map();
|
|
31
|
+
for (const agent of input.enabledAgents) {
|
|
32
|
+
if (effective.has(agent.provider)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const providerAllowList = input.providerBrokerToolAllowLists.get(agent.provider) ?? [];
|
|
36
|
+
const providerAllowedRegisteredTools = input.registeredPublicBrokerToolNames.filter((toolName) => providerAllowListAllowsTool(providerAllowList, toolName, hostedMcpHandles));
|
|
37
|
+
const projectedTools = projectedToolsByProvider.get(agent.provider) ?? new Set();
|
|
38
|
+
const effectiveTools = new Set();
|
|
39
|
+
for (const toolName of input.internalAlwaysAllowedTools) {
|
|
40
|
+
effectiveTools.add(toolName);
|
|
41
|
+
}
|
|
42
|
+
for (const toolName of providerAllowedRegisteredTools) {
|
|
43
|
+
if (internalTools.has(toolName)) {
|
|
44
|
+
effectiveTools.add(toolName);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (!isDeclaredHostedMcpTool(toolName, hostedMcpHandles)) {
|
|
48
|
+
effectiveTools.add(toolName);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (projectedTools.has(toolName)) {
|
|
52
|
+
effectiveTools.add(toolName);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
effective.set(agent.provider, [...effectiveTools].filter((toolName) => internalTools.has(toolName) || registeredTools.has(toolName)));
|
|
56
|
+
}
|
|
57
|
+
return effective;
|
|
58
|
+
}
|
|
59
|
+
function providerAllowListAllowsTool(providerAllowList, publicToolName, hostedMcpHandles) {
|
|
60
|
+
if (isDeclaredHostedMcpTool(publicToolName, hostedMcpHandles)) {
|
|
61
|
+
return providerAllowList.includes(publicToolName);
|
|
62
|
+
}
|
|
63
|
+
return providerAllowList.some((allowedToolName) => {
|
|
64
|
+
if (allowedToolName === publicToolName || allowedToolName === "*") {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return allowedToolName.endsWith(".*") && publicToolName.startsWith(allowedToolName.slice(0, -1));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function isDeclaredHostedMcpTool(publicToolName, hostedMcpHandles) {
|
|
71
|
+
const dotIndex = publicToolName.indexOf(".");
|
|
72
|
+
return dotIndex > 0 && hostedMcpHandles.has(publicToolName.slice(0, dotIndex));
|
|
73
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AntigravityCliAgent } from "../../../agents/antigravity.js";
|
|
2
|
+
export const antigravityRuntimeProvider = {
|
|
3
|
+
provider: "antigravity",
|
|
4
|
+
isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "antigravity"),
|
|
5
|
+
toolAllowList: (config) => config.antigravity.githubBroker.toolAllowList,
|
|
6
|
+
register: (input) => {
|
|
7
|
+
input.composite.register("antigravity", new AntigravityCliAgent({
|
|
8
|
+
commandRunner: input.commandRunner,
|
|
9
|
+
logDir: input.logDir,
|
|
10
|
+
logger: input.logger,
|
|
11
|
+
...(process.env.BACKBURNER_ANTIGRAVITY_CONFIG_HOME
|
|
12
|
+
? { configHome: process.env.BACKBURNER_ANTIGRAVITY_CONFIG_HOME }
|
|
13
|
+
: {}),
|
|
14
|
+
...(process.env.BACKBURNER_GEMINI_CONFIG_HOME
|
|
15
|
+
? { legacyGeminiConfigHome: process.env.BACKBURNER_GEMINI_CONFIG_HOME }
|
|
16
|
+
: {}),
|
|
17
|
+
githubBroker: {
|
|
18
|
+
serverName: input.config.antigravity.githubBroker.serverName,
|
|
19
|
+
serverUrl: input.serverUrl,
|
|
20
|
+
toolAllowList: [...input.toolAllowList]
|
|
21
|
+
},
|
|
22
|
+
planBreakdownSessionStore: input.planBreakdownSessionStore,
|
|
23
|
+
waveAssessmentSessionStore: input.waveAssessmentSessionStore
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ClaudeCodeCliAgent } from "../../../agents/claude.js";
|
|
2
|
+
export const claudeRuntimeProvider = {
|
|
3
|
+
provider: "claude",
|
|
4
|
+
isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "claude"),
|
|
5
|
+
toolAllowList: (config) => config.claude.githubBroker.toolAllowList,
|
|
6
|
+
register: (input) => {
|
|
7
|
+
input.composite.register("claude", new ClaudeCodeCliAgent({
|
|
8
|
+
commandRunner: input.commandRunner,
|
|
9
|
+
logDir: input.logDir,
|
|
10
|
+
logger: input.logger,
|
|
11
|
+
githubBroker: {
|
|
12
|
+
serverName: input.config.claude.githubBroker.serverName,
|
|
13
|
+
serverUrl: input.serverUrl,
|
|
14
|
+
toolAllowList: [...input.toolAllowList]
|
|
15
|
+
},
|
|
16
|
+
planBreakdownSessionStore: input.planBreakdownSessionStore,
|
|
17
|
+
waveAssessmentSessionStore: input.waveAssessmentSessionStore
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CodexCliAgent } from "../../../agents/codex.js";
|
|
2
|
+
export const codexRuntimeProvider = {
|
|
3
|
+
provider: "codex",
|
|
4
|
+
isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "codex"),
|
|
5
|
+
toolAllowList: (config) => config.codex.githubBroker.toolAllowList,
|
|
6
|
+
register: (input) => {
|
|
7
|
+
input.composite.register("codex", new CodexCliAgent({
|
|
8
|
+
commandRunner: input.commandRunner,
|
|
9
|
+
logDir: input.logDir,
|
|
10
|
+
logger: input.logger,
|
|
11
|
+
githubBroker: {
|
|
12
|
+
serverName: input.config.codex.githubBroker.serverName,
|
|
13
|
+
serverUrl: input.serverUrl,
|
|
14
|
+
toolAllowList: [...input.toolAllowList]
|
|
15
|
+
},
|
|
16
|
+
planBreakdownSessionStore: input.planBreakdownSessionStore,
|
|
17
|
+
waveAssessmentSessionStore: input.waveAssessmentSessionStore
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GeminiCliAgent } from "../../../agents/gemini.js";
|
|
2
|
+
export const geminiRuntimeProvider = {
|
|
3
|
+
provider: "gemini",
|
|
4
|
+
isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "gemini"),
|
|
5
|
+
toolAllowList: (config) => config.gemini.githubBroker.toolAllowList,
|
|
6
|
+
register: (input) => {
|
|
7
|
+
input.composite.register("gemini", new GeminiCliAgent({
|
|
8
|
+
commandRunner: input.commandRunner,
|
|
9
|
+
logDir: input.logDir,
|
|
10
|
+
logger: input.logger,
|
|
11
|
+
githubBroker: {
|
|
12
|
+
serverName: input.config.gemini.githubBroker.serverName,
|
|
13
|
+
serverUrl: input.serverUrl,
|
|
14
|
+
toolAllowList: [...input.toolAllowList]
|
|
15
|
+
},
|
|
16
|
+
planBreakdownSessionStore: input.planBreakdownSessionStore,
|
|
17
|
+
waveAssessmentSessionStore: input.waveAssessmentSessionStore
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OpenCodeCliAgent } from "../../../agents/opencode.js";
|
|
2
|
+
export const openCodeRuntimeProvider = {
|
|
3
|
+
provider: "opencode",
|
|
4
|
+
isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "opencode"),
|
|
5
|
+
toolAllowList: (config) => config.opencode.githubBroker.toolAllowList,
|
|
6
|
+
register: (input) => {
|
|
7
|
+
input.composite.register("opencode", new OpenCodeCliAgent({
|
|
8
|
+
commandRunner: input.commandRunner,
|
|
9
|
+
logDir: input.logDir,
|
|
10
|
+
logger: input.logger,
|
|
11
|
+
githubBroker: {
|
|
12
|
+
serverName: input.config.opencode.githubBroker.serverName,
|
|
13
|
+
serverUrl: input.serverUrl,
|
|
14
|
+
toolAllowList: [...input.toolAllowList]
|
|
15
|
+
},
|
|
16
|
+
planBreakdownSessionStore: input.planBreakdownSessionStore,
|
|
17
|
+
waveAssessmentSessionStore: input.waveAssessmentSessionStore
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { AgentPool } from "../../agents/pool.js";
|
|
3
|
+
import { loadConfig } from "../../config/loader.js";
|
|
4
|
+
import { GitCliGateway, LocalRepoSyncService } from "../../git/types.js";
|
|
5
|
+
import { GitOpsLifecycleService } from "../../git/gitops-lifecycle.js";
|
|
6
|
+
import { MergePrepWorkspaceService } from "../../git/merge-prep-workspace.js";
|
|
7
|
+
import { BackburnerGitToolService } from "../../git/backburner-git-tool-service.js";
|
|
8
|
+
import { GhCliGitHubGateway } from "../../github/gateway.js";
|
|
9
|
+
import { GitHubScanService } from "../../github/service.js";
|
|
10
|
+
import { parseGitHubRemoteUrl } from "../../github/utils.js";
|
|
11
|
+
import { JournalService } from "../../journal/index.js";
|
|
12
|
+
import { JsonJobMemoryStore } from "../../memory/json-store.js";
|
|
13
|
+
import { JobMemoryToolService } from "../../memory/tool-service.js";
|
|
14
|
+
import { createSmitheryMcpResolverFromEnv, reconcileMcpStatus } from "../../mcps/index.js";
|
|
15
|
+
import { StateStore } from "../../state/loader.js";
|
|
16
|
+
import { ExecFileCommandRunner } from "../../utils/command-runner.js";
|
|
17
|
+
import { defaultStderrLogger } from "../../utils/logger.js";
|
|
18
|
+
import { defaultBackburnerCodeRoot, defaultBackburnerManagementRoot, defaultBackburnerOutputsRoot, resolveOutputsStateRoot, resolveOutputsLogsRoot, resolveOutputsJournalRoot } from "../../utils/paths.js";
|
|
19
|
+
import { TriageFollowUpService } from "../../workflows/triage.js";
|
|
20
|
+
import { ImplementationWorkflowService } from "../../worktrees/service.js";
|
|
21
|
+
import { WorkspaceRecoveryService } from "../../worktrees/workspace-recovery.js";
|
|
22
|
+
import { DEFAULT_GITHUB_BROKER_PORT as CLI_DEFAULT_GITHUB_BROKER_PORT, readNumberFlag, readOptionalStringFlag, readStringFlag } from "../options.js";
|
|
23
|
+
export async function createRunContext(input) {
|
|
24
|
+
const { rest, options } = input;
|
|
25
|
+
const managementDir = path.resolve(options.managementDir ?? readStringFlag(rest, "--management-dir", defaultBackburnerManagementRoot()));
|
|
26
|
+
const configuredOutputsDir = options.outputsDir ?? readOptionalStringFlag(rest, "--outputs-dir");
|
|
27
|
+
const outputsDir = path.resolve(configuredOutputsDir ?? defaultBackburnerOutputsRoot());
|
|
28
|
+
const useLegacyStateDirWithoutOutputs = options.stateDir !== undefined && configuredOutputsDir === undefined;
|
|
29
|
+
const logger = options.logger ?? defaultStderrLogger;
|
|
30
|
+
const codeRoot = path.resolve(readOptionalStringFlag(rest, "--code-root") ?? defaultBackburnerCodeRoot());
|
|
31
|
+
const brokerPort = readNumberFlag(rest, "--broker-port", CLI_DEFAULT_GITHUB_BROKER_PORT);
|
|
32
|
+
const commandRunner = options.commandRunner ?? new ExecFileCommandRunner();
|
|
33
|
+
const gitGateway = options.gitGateway ?? new GitCliGateway(commandRunner);
|
|
34
|
+
const gitOpsLifecycle = options.gitOpsLifecycleService ?? new GitOpsLifecycleService(gitGateway);
|
|
35
|
+
const workspaceRecoveryService = options.workspaceRecoveryService ?? new WorkspaceRecoveryService();
|
|
36
|
+
logger.info(`Preparing management root ${managementDir}`);
|
|
37
|
+
const managementGitOps = await gitOpsLifecycle.prepareManagementRoot(managementDir);
|
|
38
|
+
logger.info(`Loading orchestrator config from ${managementDir}`);
|
|
39
|
+
const config = await loadConfig(managementDir);
|
|
40
|
+
const agentPool = new AgentPool(config.maxConcurrentAgents);
|
|
41
|
+
logger.info(`Agent pool: maxConcurrentAgents=${agentPool.maxConcurrent}`);
|
|
42
|
+
let outputsGitOpsPrepared;
|
|
43
|
+
if (useLegacyStateDirWithoutOutputs) {
|
|
44
|
+
logger.info(`Skipping outputs root GitOps because explicit state is stored at ${options.stateDir}`);
|
|
45
|
+
outputsGitOpsPrepared = { status: "skipped_not_git" };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
logger.info(`Preparing outputs root ${outputsDir}`);
|
|
49
|
+
outputsGitOpsPrepared = await gitOpsLifecycle.prepareOutputsRoot(outputsDir);
|
|
50
|
+
}
|
|
51
|
+
const stateDir = path.resolve(options.stateDir ?? resolveOutputsStateRoot(outputsDir));
|
|
52
|
+
const defaultLogDir = options.stateDir !== undefined ? stateDir : resolveOutputsLogsRoot(outputsDir);
|
|
53
|
+
const logDir = path.resolve(options.logDir ?? readStringFlag(rest, "--log-dir", defaultLogDir));
|
|
54
|
+
let managementRepo;
|
|
55
|
+
try {
|
|
56
|
+
const remoteResult = await commandRunner.run("git", ["remote", "get-url", "origin"], { cwd: managementDir });
|
|
57
|
+
const remoteUrl = remoteResult.stdout.trim();
|
|
58
|
+
const identity = parseGitHubRemoteUrl(remoteUrl);
|
|
59
|
+
if (identity) {
|
|
60
|
+
managementRepo = { repoSlug: `${identity.owner}/${identity.name}` };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Management repo identity resolve failed, classifyPullRequest will handle missing managementRepo
|
|
65
|
+
}
|
|
66
|
+
const stateStore = new StateStore({ stateDir, executionDir: logDir });
|
|
67
|
+
const journal = options.journalService ?? new JournalService(resolveOutputsJournalRoot(outputsDir));
|
|
68
|
+
const memoryStore = new JsonJobMemoryStore({ filePath: path.join(stateDir, "job-memory.json") });
|
|
69
|
+
const memoryToolService = new JobMemoryToolService(memoryStore, logger);
|
|
70
|
+
const backburnerGitToolService = new BackburnerGitToolService(commandRunner, logger);
|
|
71
|
+
logger.info(`Loading persisted state from ${stateDir}`);
|
|
72
|
+
if (logDir !== stateDir) {
|
|
73
|
+
logger.info(`Loading execution log from ${logDir}`);
|
|
74
|
+
}
|
|
75
|
+
const previousState = await stateStore.load();
|
|
76
|
+
let currentMcpStatuses = previousState.mcpStatuses ?? [];
|
|
77
|
+
if (config.mcps.length > 0) {
|
|
78
|
+
try {
|
|
79
|
+
const resolvedMcps = await createSmitheryMcpResolverFromEnv().resolveDependencies(config.mcps, currentMcpStatuses);
|
|
80
|
+
const reconciliation = reconcileMcpStatus(config.mcps, currentMcpStatuses, resolvedMcps, new Date().toISOString());
|
|
81
|
+
currentMcpStatuses = reconciliation.records;
|
|
82
|
+
await stateStore.writeMcpStatusState(currentMcpStatuses);
|
|
83
|
+
logger.info(`MCP readiness reconciled: added=${reconciliation.added.length}, updated=${reconciliation.updated.length}, unchanged=${reconciliation.unchanged.length}, removed=${reconciliation.removed.length}`);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
logger.warn(`Failed to reconcile MCP readiness: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const gitHubGateway = options.gitHubGateway ?? new GhCliGitHubGateway(commandRunner, config.allowedUsers);
|
|
90
|
+
const syncService = options.syncService ??
|
|
91
|
+
new LocalRepoSyncService(gitGateway, gitHubGateway);
|
|
92
|
+
const scanService = options.scanService ?? new GitHubScanService(gitHubGateway);
|
|
93
|
+
const implementationWorkflowService = new ImplementationWorkflowService(gitGateway, gitHubGateway);
|
|
94
|
+
const triageFollowUpService = new TriageFollowUpService(gitGateway, gitHubGateway);
|
|
95
|
+
const mergePrepService = options.mergePrepService ?? new MergePrepWorkspaceService(gitGateway);
|
|
96
|
+
const enabledRepos = config.repos.filter((repo) => repo.enabled);
|
|
97
|
+
const results = [];
|
|
98
|
+
return {
|
|
99
|
+
managementDir,
|
|
100
|
+
outputsDir,
|
|
101
|
+
stateDir,
|
|
102
|
+
logDir,
|
|
103
|
+
logger,
|
|
104
|
+
codeRoot,
|
|
105
|
+
brokerPort,
|
|
106
|
+
commandRunner,
|
|
107
|
+
gitGateway,
|
|
108
|
+
gitOpsLifecycle,
|
|
109
|
+
workspaceRecoveryService,
|
|
110
|
+
managementGitOps,
|
|
111
|
+
config,
|
|
112
|
+
agentPool,
|
|
113
|
+
outputsGitOpsPrepared,
|
|
114
|
+
...(managementRepo ? { managementRepo } : {}),
|
|
115
|
+
stateStore,
|
|
116
|
+
journal,
|
|
117
|
+
memoryStore,
|
|
118
|
+
memoryToolService,
|
|
119
|
+
backburnerGitToolService,
|
|
120
|
+
previousState,
|
|
121
|
+
currentMcpStatuses,
|
|
122
|
+
gitHubGateway,
|
|
123
|
+
syncService,
|
|
124
|
+
scanService,
|
|
125
|
+
implementationWorkflowService,
|
|
126
|
+
triageFollowUpService,
|
|
127
|
+
mergePrepService,
|
|
128
|
+
enabledRepos,
|
|
129
|
+
results
|
|
130
|
+
};
|
|
131
|
+
}
|