@cat-factory/orchestration 0.6.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/dist/container.d.ts +460 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +657 -0
- package/dist/container.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/board/BoardService.d.ts +125 -0
- package/dist/modules/board/BoardService.d.ts.map +1 -0
- package/dist/modules/board/BoardService.js +496 -0
- package/dist/modules/board/BoardService.js.map +1 -0
- package/dist/modules/board/board.logic.d.ts +17 -0
- package/dist/modules/board/board.logic.d.ts.map +1 -0
- package/dist/modules/board/board.logic.js +51 -0
- package/dist/modules/board/board.logic.js.map +1 -0
- package/dist/modules/boardScan/BoardScanService.d.ts +35 -0
- package/dist/modules/boardScan/BoardScanService.d.ts.map +1 -0
- package/dist/modules/boardScan/BoardScanService.js +91 -0
- package/dist/modules/boardScan/BoardScanService.js.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts +10 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.js +26 -0
- package/dist/modules/boardScan/board-scan.logic.js.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts +114 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.js +516 -0
- package/dist/modules/bootstrap/BootstrapService.js.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts +48 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.js +63 -0
- package/dist/modules/clarity/ClarityReviewService.js.map +1 -0
- package/dist/modules/clarity/clarity.logic.d.ts +36 -0
- package/dist/modules/clarity/clarity.logic.d.ts.map +1 -0
- package/dist/modules/clarity/clarity.logic.js +98 -0
- package/dist/modules/clarity/clarity.logic.js.map +1 -0
- package/dist/modules/estimation/estimate.logic.d.ts +11 -0
- package/dist/modules/estimation/estimate.logic.d.ts.map +1 -0
- package/dist/modules/estimation/estimate.logic.js +37 -0
- package/dist/modules/estimation/estimate.logic.js.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts +114 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.js +316 -0
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -0
- package/dist/modules/execution/CompanionController.d.ts +60 -0
- package/dist/modules/execution/CompanionController.d.ts.map +1 -0
- package/dist/modules/execution/CompanionController.js +216 -0
- package/dist/modules/execution/CompanionController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +874 -0
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -0
- package/dist/modules/execution/ExecutionService.js +2921 -0
- package/dist/modules/execution/ExecutionService.js.map +1 -0
- package/dist/modules/execution/MergeResolver.d.ts +34 -0
- package/dist/modules/execution/MergeResolver.d.ts.map +1 -0
- package/dist/modules/execution/MergeResolver.js +81 -0
- package/dist/modules/execution/MergeResolver.js.map +1 -0
- package/dist/modules/execution/ReviewGateController.d.ts +163 -0
- package/dist/modules/execution/ReviewGateController.d.ts.map +1 -0
- package/dist/modules/execution/ReviewGateController.js +251 -0
- package/dist/modules/execution/ReviewGateController.js.map +1 -0
- package/dist/modules/execution/TesterController.d.ts +61 -0
- package/dist/modules/execution/TesterController.d.ts.map +1 -0
- package/dist/modules/execution/TesterController.js +215 -0
- package/dist/modules/execution/TesterController.js.map +1 -0
- package/dist/modules/execution/advance.d.ts +84 -0
- package/dist/modules/execution/advance.d.ts.map +1 -0
- package/dist/modules/execution/advance.js +2 -0
- package/dist/modules/execution/advance.js.map +1 -0
- package/dist/modules/execution/artifact-review.logic.d.ts +25 -0
- package/dist/modules/execution/artifact-review.logic.d.ts.map +1 -0
- package/dist/modules/execution/artifact-review.logic.js +39 -0
- package/dist/modules/execution/artifact-review.logic.js.map +1 -0
- package/dist/modules/execution/ci.logic.d.ts +101 -0
- package/dist/modules/execution/ci.logic.d.ts.map +1 -0
- package/dist/modules/execution/ci.logic.js +117 -0
- package/dist/modules/execution/ci.logic.js.map +1 -0
- package/dist/modules/execution/drive.d.ts +47 -0
- package/dist/modules/execution/drive.d.ts.map +1 -0
- package/dist/modules/execution/drive.js +112 -0
- package/dist/modules/execution/drive.js.map +1 -0
- package/dist/modules/execution/gates.d.ts +97 -0
- package/dist/modules/execution/gates.d.ts.map +1 -0
- package/dist/modules/execution/gates.js +2 -0
- package/dist/modules/execution/gates.js.map +1 -0
- package/dist/modules/execution/individualVendors.logic.d.ts +22 -0
- package/dist/modules/execution/individualVendors.logic.d.ts.map +1 -0
- package/dist/modules/execution/individualVendors.logic.js +33 -0
- package/dist/modules/execution/individualVendors.logic.js.map +1 -0
- package/dist/modules/execution/job.logic.d.ts +52 -0
- package/dist/modules/execution/job.logic.d.ts.map +1 -0
- package/dist/modules/execution/job.logic.js +56 -0
- package/dist/modules/execution/job.logic.js.map +1 -0
- package/dist/modules/execution/release.logic.d.ts +43 -0
- package/dist/modules/execution/release.logic.d.ts.map +1 -0
- package/dist/modules/execution/release.logic.js +49 -0
- package/dist/modules/execution/release.logic.js.map +1 -0
- package/dist/modules/execution/retry.logic.d.ts +40 -0
- package/dist/modules/execution/retry.logic.d.ts.map +1 -0
- package/dist/modules/execution/retry.logic.js +83 -0
- package/dist/modules/execution/retry.logic.js.map +1 -0
- package/dist/modules/execution/stepGating.logic.d.ts +15 -0
- package/dist/modules/execution/stepGating.logic.d.ts.map +1 -0
- package/dist/modules/execution/stepGating.logic.js +29 -0
- package/dist/modules/execution/stepGating.logic.js.map +1 -0
- package/dist/modules/execution/stepResolvers.d.ts +41 -0
- package/dist/modules/execution/stepResolvers.d.ts.map +1 -0
- package/dist/modules/execution/stepResolvers.js +2 -0
- package/dist/modules/execution/stepResolvers.js.map +1 -0
- package/dist/modules/execution/tester-infra.logic.d.ts +42 -0
- package/dist/modules/execution/tester-infra.logic.d.ts.map +1 -0
- package/dist/modules/execution/tester-infra.logic.js +46 -0
- package/dist/modules/execution/tester-infra.logic.js.map +1 -0
- package/dist/modules/merge/MergePresetService.d.ts +32 -0
- package/dist/modules/merge/MergePresetService.d.ts.map +1 -0
- package/dist/modules/merge/MergePresetService.js +109 -0
- package/dist/modules/merge/MergePresetService.js.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts +22 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js +28 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js.map +1 -0
- package/dist/modules/notifications/NotificationService.d.ts +74 -0
- package/dist/modules/notifications/NotificationService.d.ts.map +1 -0
- package/dist/modules/notifications/NotificationService.js +131 -0
- package/dist/modules/notifications/NotificationService.js.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts +121 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.js +140 -0
- package/dist/modules/observability/LlmObservabilityService.js.map +1 -0
- package/dist/modules/observability/observability.logic.d.ts +57 -0
- package/dist/modules/observability/observability.logic.d.ts.map +1 -0
- package/dist/modules/observability/observability.logic.js +186 -0
- package/dist/modules/observability/observability.logic.js.map +1 -0
- package/dist/modules/pipelines/PipelineService.d.ts +54 -0
- package/dist/modules/pipelines/PipelineService.d.ts.map +1 -0
- package/dist/modules/pipelines/PipelineService.js +226 -0
- package/dist/modules/pipelines/PipelineService.js.map +1 -0
- package/dist/modules/pipelines/pipelineShape.d.ts +53 -0
- package/dist/modules/pipelines/pipelineShape.d.ts.map +1 -0
- package/dist/modules/pipelines/pipelineShape.js +74 -0
- package/dist/modules/pipelines/pipelineShape.js.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts +76 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.js +295 -0
- package/dist/modules/recurring/RecurringPipelineService.js.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts +16 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.js +30 -0
- package/dist/modules/recurring/TrackerSettingsService.js.map +1 -0
- package/dist/modules/recurring/schedule.logic.d.ts +14 -0
- package/dist/modules/recurring/schedule.logic.d.ts.map +1 -0
- package/dist/modules/recurring/schedule.logic.js +85 -0
- package/dist/modules/recurring/schedule.logic.js.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts +38 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js +96 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts +48 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.js +83 -0
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -0
- package/dist/modules/requirements/requirements.logic.d.ts +93 -0
- package/dist/modules/requirements/requirements.logic.d.ts.map +1 -0
- package/dist/modules/requirements/requirements.logic.js +203 -0
- package/dist/modules/requirements/requirements.logic.js.map +1 -0
- package/dist/modules/review/IterativeReviewService.d.ts +175 -0
- package/dist/modules/review/IterativeReviewService.d.ts.map +1 -0
- package/dist/modules/review/IterativeReviewService.js +327 -0
- package/dist/modules/review/IterativeReviewService.js.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts +20 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js +26 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js.map +1 -0
- package/dist/modules/services/ServiceMountService.d.ts +48 -0
- package/dist/modules/services/ServiceMountService.d.ts.map +1 -0
- package/dist/modules/services/ServiceMountService.js +90 -0
- package/dist/modules/services/ServiceMountService.js.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts +22 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.js +50 -0
- package/dist/modules/settings/WorkspaceSettingsService.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { CODE_AWARE_TRAIT, hasTrait } from '@cat-factory/agents';
|
|
2
|
+
import { getFragment } from '@cat-factory/prompt-fragments';
|
|
3
|
+
/**
|
|
4
|
+
* The `revision` slice of an agent context when a step is being re-run with feedback
|
|
5
|
+
* — either a human's "request changes" on its approval gate, or a downstream
|
|
6
|
+
* companion's automatic rework (`step.rework`). The companion path wins when both are
|
|
7
|
+
* present. Empty object when neither applies (no revision context).
|
|
8
|
+
*/
|
|
9
|
+
export function buildRevisionContext(step) {
|
|
10
|
+
const source = step.rework
|
|
11
|
+
? {
|
|
12
|
+
previousProposal: step.rework.previousProposal,
|
|
13
|
+
feedback: step.rework.feedback,
|
|
14
|
+
comments: step.rework.comments,
|
|
15
|
+
}
|
|
16
|
+
: step.approval?.status === 'changes_requested'
|
|
17
|
+
? {
|
|
18
|
+
previousProposal: step.approval.proposal,
|
|
19
|
+
feedback: step.approval.feedback ?? '',
|
|
20
|
+
comments: step.approval.comments,
|
|
21
|
+
}
|
|
22
|
+
: undefined;
|
|
23
|
+
if (!source)
|
|
24
|
+
return {};
|
|
25
|
+
return {
|
|
26
|
+
revision: {
|
|
27
|
+
previousProposal: source.previousProposal,
|
|
28
|
+
feedback: source.feedback,
|
|
29
|
+
...(source.comments?.length
|
|
30
|
+
? {
|
|
31
|
+
comments: source.comments.map((c) => ({
|
|
32
|
+
...(c.quotedSource ? { quotedSource: c.quotedSource } : {}),
|
|
33
|
+
body: c.body,
|
|
34
|
+
})),
|
|
35
|
+
}
|
|
36
|
+
: {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Assembles the {@link AgentRunContext} for a pipeline step from the run + block state:
|
|
42
|
+
* the (possibly reworked) requirements, linked docs/tracker issues, the live environment,
|
|
43
|
+
* the service-frame config, the best-practice fragments, prior step outputs, recorded
|
|
44
|
+
* decisions and any revision feedback. Pure inputs → output (it only reads repositories),
|
|
45
|
+
* extracted out of `ExecutionService` so the engine stays a thin state machine. Also the
|
|
46
|
+
* single home for service-frame resolution (`resolveServiceFrameId`/`resolveServiceConfig`),
|
|
47
|
+
* which a few other engine paths reuse.
|
|
48
|
+
*/
|
|
49
|
+
export class AgentContextBuilder {
|
|
50
|
+
deps;
|
|
51
|
+
constructor(deps) {
|
|
52
|
+
this.deps = deps;
|
|
53
|
+
}
|
|
54
|
+
/** Assemble the {@link AgentRunContext} for a step from the run + block state. */
|
|
55
|
+
async buildContext(workspaceId, instance, step, isFinalStep, block) {
|
|
56
|
+
// When a block's requirements have been reworked, that standardized document is
|
|
57
|
+
// the single source of truth for every agent step: it already folds in the
|
|
58
|
+
// description plus the linked docs / tracker issues, so it REPLACES the
|
|
59
|
+
// description and the (now-redundant) doc/task context. Reviews are only ever run
|
|
60
|
+
// on task blocks, so skip the lookup entirely for frames/modules — that keeps the
|
|
61
|
+
// extra read off every container/frame step rather than on the whole hot path.
|
|
62
|
+
// A converged clarity (bug-report triage) report substitutes downstream exactly like a
|
|
63
|
+
// reworked requirements doc. When both exist on one task the requirements doc — which
|
|
64
|
+
// runs after clarity and is the more refined artifact — takes precedence.
|
|
65
|
+
const reworked = block.level === 'task'
|
|
66
|
+
? ((await this.resolveReworkedRequirements(workspaceId, block.id)) ??
|
|
67
|
+
(await this.resolveClarifiedBrief(workspaceId, block.id)))
|
|
68
|
+
: null;
|
|
69
|
+
const description = reworked ?? block.description;
|
|
70
|
+
const contextDocs = reworked ? [] : await this.resolveContextDocs(workspaceId, block.id);
|
|
71
|
+
const contextTasks = reworked ? [] : await this.resolveContextTasks(workspaceId, block.id);
|
|
72
|
+
const environment = await this.resolveEnvironment(workspaceId, block.id);
|
|
73
|
+
const service = await this.resolveServiceConfig(workspaceId, block);
|
|
74
|
+
const priorOutputs = instance.steps
|
|
75
|
+
.slice(0, instance.currentStep)
|
|
76
|
+
.filter((s) => s.output)
|
|
77
|
+
.map((s) => ({ agentKind: s.agentKind, output: s.output }));
|
|
78
|
+
// Resolve the best-practice fragments to inject for this step. `code-aware` kinds
|
|
79
|
+
// get the running service's selected fragments unioned with the block's own pins;
|
|
80
|
+
// other kinds keep only their block pins. Recorded on the step for observability.
|
|
81
|
+
const resolved = await this.resolveFragments(workspaceId, step, block);
|
|
82
|
+
return {
|
|
83
|
+
agentKind: step.agentKind,
|
|
84
|
+
pipelineName: instance.pipelineName,
|
|
85
|
+
workspaceId,
|
|
86
|
+
executionId: instance.id,
|
|
87
|
+
// Carry the run initiator so the container executor can lease their OWN personal
|
|
88
|
+
// (individual-usage) subscription for the step. Null on system/dev runs.
|
|
89
|
+
...(instance.initiatedBy != null ? { initiatedByUserId: instance.initiatedBy } : {}),
|
|
90
|
+
stepIndex: instance.currentStep,
|
|
91
|
+
isFinalStep,
|
|
92
|
+
// Consensus config for this step (copied onto the step at run start). Read only
|
|
93
|
+
// by the optional consensus executor, which decides — possibly gated on the
|
|
94
|
+
// block estimate below — whether to run the multi-model process. Absent ⇒ standard.
|
|
95
|
+
...(step.consensus ? { consensus: step.consensus } : {}),
|
|
96
|
+
block: {
|
|
97
|
+
id: block.id,
|
|
98
|
+
title: block.title,
|
|
99
|
+
type: block.type,
|
|
100
|
+
description,
|
|
101
|
+
fragmentIds: block.fragmentIds,
|
|
102
|
+
...(resolved ? { resolvedFragments: resolved.fragments } : {}),
|
|
103
|
+
modelId: block.modelId,
|
|
104
|
+
...(block.agentConfig ? { agentConfig: block.agentConfig } : {}),
|
|
105
|
+
...(block.pullRequest ? { pullRequest: block.pullRequest } : {}),
|
|
106
|
+
...(contextDocs.length ? { contextDocs } : {}),
|
|
107
|
+
...(contextTasks.length ? { contextTasks } : {}),
|
|
108
|
+
// The task-estimator's triage, when produced earlier in this run — the
|
|
109
|
+
// consensus executor's gating input.
|
|
110
|
+
...(block.estimate ? { estimate: block.estimate } : {}),
|
|
111
|
+
},
|
|
112
|
+
...(environment ? { environment } : {}),
|
|
113
|
+
...(service ? { service } : {}),
|
|
114
|
+
priorOutputs,
|
|
115
|
+
decisions: instance.steps
|
|
116
|
+
.filter((s, i) => i < instance.currentStep && s.decision?.chosen)
|
|
117
|
+
.map((s) => ({ question: s.decision.question, chosen: s.decision.chosen })),
|
|
118
|
+
resolvedDecision: step.decision?.chosen
|
|
119
|
+
? { question: step.decision.question, chosen: step.decision.chosen }
|
|
120
|
+
: null,
|
|
121
|
+
// A re-run triggered either by a human "Request changes" on this step's
|
|
122
|
+
// approval gate OR by a downstream companion looping it back for rework: hand
|
|
123
|
+
// the agent its previous proposal plus the feedback so it revises rather than
|
|
124
|
+
// starting over. The companion's automatic rework (`step.rework`) and the
|
|
125
|
+
// human's gate feedback share one revision shape; the companion path takes
|
|
126
|
+
// precedence when both are present.
|
|
127
|
+
...buildRevisionContext(step),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** The service-frame id for a block (walks up frame → module → task; cycle-guarded). */
|
|
131
|
+
async resolveServiceFrameId(workspaceId, blockId) {
|
|
132
|
+
let current = await this.deps.blockRepository.get(workspaceId, blockId);
|
|
133
|
+
// Bounded walk (the tree is at most frame → module → task) guarded against cycles.
|
|
134
|
+
for (let i = 0; current && i < 8; i++) {
|
|
135
|
+
if (current.level === 'frame' || !current.parentId)
|
|
136
|
+
return current.id;
|
|
137
|
+
current = await this.deps.blockRepository.get(workspaceId, current.parentId);
|
|
138
|
+
}
|
|
139
|
+
return current?.id ?? null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolve the service-level (frame) configuration for a run's block — the
|
|
143
|
+
* Tester's local-infra docker-compose path / "no infra" flag and the provisioning
|
|
144
|
+
* provider + instance size — by walking up to the service frame. When the frame
|
|
145
|
+
* pins no cloud provider it inherits the owning account's `defaultCloudProvider`
|
|
146
|
+
* (so the account-level default actually reaches dispatch, not just the UI).
|
|
147
|
+
* Returns undefined when no frame carries any of these settings, so callers can
|
|
148
|
+
* spread it conditionally onto the agent context.
|
|
149
|
+
*/
|
|
150
|
+
async resolveServiceConfig(workspaceId, block) {
|
|
151
|
+
const frame = block.level === 'frame'
|
|
152
|
+
? block
|
|
153
|
+
: await this.resolveServiceFrameId(workspaceId, block.id).then((id) => id ? this.deps.blockRepository.get(workspaceId, id) : null);
|
|
154
|
+
if (!frame)
|
|
155
|
+
return undefined;
|
|
156
|
+
const service = {};
|
|
157
|
+
if (frame.testComposePath)
|
|
158
|
+
service.testComposePath = frame.testComposePath;
|
|
159
|
+
if (frame.noInfraDependencies)
|
|
160
|
+
service.noInfraDependencies = frame.noInfraDependencies;
|
|
161
|
+
if (frame.cloudProvider)
|
|
162
|
+
service.cloudProvider = frame.cloudProvider;
|
|
163
|
+
else {
|
|
164
|
+
// No per-service override: fall back to the owning account's default provider
|
|
165
|
+
// so a pool/local deployment honours the account-level choice at dispatch.
|
|
166
|
+
const accountDefault = await this.resolveAccountDefaultProvider(workspaceId);
|
|
167
|
+
if (accountDefault)
|
|
168
|
+
service.cloudProvider = accountDefault;
|
|
169
|
+
}
|
|
170
|
+
if (frame.instanceSize)
|
|
171
|
+
service.instanceSize = frame.instanceSize;
|
|
172
|
+
return Object.keys(service).length ? service : undefined;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The owning account's `defaultCloudProvider`, or undefined when the workspace
|
|
176
|
+
* has no account or the account pins no default (so the transport keeps its own).
|
|
177
|
+
*/
|
|
178
|
+
async resolveAccountDefaultProvider(workspaceId) {
|
|
179
|
+
const workspace = await this.deps.workspaceRepository.get(workspaceId);
|
|
180
|
+
if (!workspace?.accountId)
|
|
181
|
+
return undefined;
|
|
182
|
+
const account = await this.deps.accountRepository.get(workspace.accountId);
|
|
183
|
+
return account?.defaultCloudProvider;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The reworked ("incorporated") requirements for a block — the standard-format
|
|
187
|
+
* document the requirements-rework step produced — or `null` when the feature is
|
|
188
|
+
* unwired or the block has no incorporated review yet. Used both to substitute the
|
|
189
|
+
* agent context for every step and to feed the spec-writer.
|
|
190
|
+
*/
|
|
191
|
+
async resolveReworkedRequirements(workspaceId, blockId) {
|
|
192
|
+
if (!this.deps.requirementReviews)
|
|
193
|
+
return null;
|
|
194
|
+
const review = await this.deps.requirementReviews.getByBlock(workspaceId, blockId);
|
|
195
|
+
if (review?.status === 'incorporated' && review.incorporatedRequirements) {
|
|
196
|
+
return review.incorporatedRequirements;
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The clarified bug report for a block — the standard-format document the clarity-rework
|
|
202
|
+
* step produced — or `null` when the feature is unwired or the block has no incorporated
|
|
203
|
+
* clarity review yet. The clarity mirror of {@link resolveReworkedRequirements}.
|
|
204
|
+
*/
|
|
205
|
+
async resolveClarifiedBrief(workspaceId, blockId) {
|
|
206
|
+
if (!this.deps.clarityReviews)
|
|
207
|
+
return null;
|
|
208
|
+
const review = await this.deps.clarityReviews.getByBlock(workspaceId, blockId);
|
|
209
|
+
if (review?.status === 'incorporated' && review.clarifiedReport) {
|
|
210
|
+
return review.clarifiedReport;
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Resolve the best-practice fragments to fold into a step's system prompt. Service
|
|
216
|
+
* fragments reach an agent ONLY when its kind carries the `code-aware` trait: those
|
|
217
|
+
* kinds get the running SERVICE's selected fragments (the frame's
|
|
218
|
+
* `serviceFragmentIds`, seeded from the workspace default and editable per service)
|
|
219
|
+
* unioned with the block's own manual pins, resolved against the universal pool. A
|
|
220
|
+
* non-code-aware kind returns null so `composeBlockSystemPrompt` falls back to the
|
|
221
|
+
* block's own `fragmentIds` unchanged. Records the selected ids on the step for
|
|
222
|
+
* observability; never throws (a lookup failure degrades to the block pins).
|
|
223
|
+
*/
|
|
224
|
+
async resolveFragments(workspaceId, step, block) {
|
|
225
|
+
if (!hasTrait(step.agentKind, CODE_AWARE_TRAIT))
|
|
226
|
+
return null;
|
|
227
|
+
try {
|
|
228
|
+
const serviceIds = await this.resolveServiceFragmentIds(workspaceId, block);
|
|
229
|
+
// Service standards first, then the block's own pins; deduped, stable order.
|
|
230
|
+
const ids = [];
|
|
231
|
+
const seen = new Set();
|
|
232
|
+
for (const id of [...serviceIds, ...(block.fragmentIds ?? [])]) {
|
|
233
|
+
if (seen.has(id))
|
|
234
|
+
continue;
|
|
235
|
+
seen.add(id);
|
|
236
|
+
ids.push(id);
|
|
237
|
+
}
|
|
238
|
+
const fragments = ids
|
|
239
|
+
.map((id) => {
|
|
240
|
+
const fragment = getFragment(id);
|
|
241
|
+
return fragment ? { id, body: fragment.body } : null;
|
|
242
|
+
})
|
|
243
|
+
.filter((f) => f !== null);
|
|
244
|
+
if (fragments.length === 0)
|
|
245
|
+
return null;
|
|
246
|
+
step.selectedFragmentIds = fragments.map((f) => f.id);
|
|
247
|
+
return { fragments };
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// Resolution must never wedge a run; fall back to the block's own pins.
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* The selected best-practice fragment ids of the block's owning service frame. Walks
|
|
256
|
+
* up from the block we already hold (bounded: frame → module → task, cycle-guarded),
|
|
257
|
+
* reading the frame's `serviceFragmentIds` — without re-fetching the block in hand or
|
|
258
|
+
* fetching the frame twice.
|
|
259
|
+
*/
|
|
260
|
+
async resolveServiceFragmentIds(workspaceId, block) {
|
|
261
|
+
let current = block;
|
|
262
|
+
for (let i = 0; current && i < 8; i++) {
|
|
263
|
+
if (current.level === 'frame' || !current.parentId)
|
|
264
|
+
return current.serviceFragmentIds ?? [];
|
|
265
|
+
current = await this.deps.blockRepository.get(workspaceId, current.parentId);
|
|
266
|
+
}
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Resolve documents (from any source) linked to the running block into compact
|
|
271
|
+
* agent context. A no-op unless the document-source integration is wired (the
|
|
272
|
+
* repository is an optional dependency), so the engine stays unchanged when it
|
|
273
|
+
* is off.
|
|
274
|
+
*/
|
|
275
|
+
async resolveContextDocs(workspaceId, blockId) {
|
|
276
|
+
if (!this.deps.documents)
|
|
277
|
+
return [];
|
|
278
|
+
const docs = await this.deps.documents.listByBlock(workspaceId, blockId);
|
|
279
|
+
return docs.map((d) => ({ title: d.title, url: d.url, excerpt: d.excerpt }));
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Resolve tracker issues (from any source) linked to the running block into
|
|
283
|
+
* structured agent context. A no-op unless the task-source integration is
|
|
284
|
+
* wired (the repository is an optional dependency), so the engine stays
|
|
285
|
+
* unchanged when it is off.
|
|
286
|
+
*/
|
|
287
|
+
async resolveContextTasks(workspaceId, blockId) {
|
|
288
|
+
if (!this.deps.tasks)
|
|
289
|
+
return [];
|
|
290
|
+
const tasks = await this.deps.tasks.listByBlock(workspaceId, blockId);
|
|
291
|
+
return tasks.map((t) => ({
|
|
292
|
+
key: t.externalId,
|
|
293
|
+
url: t.url,
|
|
294
|
+
title: t.title,
|
|
295
|
+
status: t.status,
|
|
296
|
+
type: t.type,
|
|
297
|
+
assignee: t.assignee,
|
|
298
|
+
priority: t.priority,
|
|
299
|
+
labels: t.labels,
|
|
300
|
+
description: t.description,
|
|
301
|
+
comments: t.comments,
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Resolve the live ephemeral environment provisioned for the running block
|
|
306
|
+
* into compact agent context. A no-op unless the environment integration is
|
|
307
|
+
* wired (the provisioning service is an optional dependency), so the engine
|
|
308
|
+
* stays unchanged when it is off.
|
|
309
|
+
*/
|
|
310
|
+
async resolveEnvironment(workspaceId, blockId) {
|
|
311
|
+
if (!this.deps.environmentProvisioning)
|
|
312
|
+
return null;
|
|
313
|
+
return this.deps.environmentProvisioning.resolveForBlock(workspaceId, blockId);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=AgentContextBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentContextBuilder.js","sourceRoot":"","sources":["../../../src/modules/execution/AgentContextBuilder.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAG3D;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IAOrD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;QACxB,CAAC,CAAC;YACE,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;YAC9C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;SAC/B;QACH,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,KAAK,mBAAmB;YAC7C,CAAC,CAAC;gBACE,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;gBACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE;gBACtC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;aACjC;YACH,CAAC,CAAC,SAAS,CAAA;IACf,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,OAAO;QACL,QAAQ,EAAE;YACR,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM;gBACzB,CAAC,CAAC;oBACE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACpC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC3D,IAAI,EAAE,CAAC,CAAC,IAAI;qBACb,CAAC,CAAC;iBACJ;gBACH,CAAC,CAAC,EAAE,CAAC;SACR;KACF,CAAA;AACH,CAAC;AAcD;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAmB;IACD,IAAI;IAAjC,YAA6B,IAA6B;oBAA7B,IAAI;IAA4B,CAAC;IAE9D,kFAAkF;IAClF,KAAK,CAAC,YAAY,CAChB,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,WAAoB,EACpB,KAAY;QAEZ,gFAAgF;QAChF,2EAA2E;QAC3E,wEAAwE;QACxE,kFAAkF;QAClF,kFAAkF;QAClF,+EAA+E;QAC/E,uFAAuF;QACvF,sFAAsF;QACtF,0EAA0E;QAC1E,MAAM,QAAQ,GACZ,KAAK,CAAC,KAAK,KAAK,MAAM;YACpB,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,2BAA2B,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBAChE,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5D,CAAC,CAAC,IAAI,CAAA;QACV,MAAM,WAAW,GAAG,QAAQ,IAAI,KAAK,CAAC,WAAW,CAAA;QACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QACxF,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QAC1F,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QACxE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACnE,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK;aAChC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC;aAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;aACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,MAAO,EAAE,CAAC,CAAC,CAAA;QAC9D,kFAAkF;QAClF,kFAAkF;QAClF,kFAAkF;QAClF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QACtE,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,WAAW;YACX,WAAW,EAAE,QAAQ,CAAC,EAAE;YACxB,iFAAiF;YACjF,yEAAyE;YACzE,GAAG,CAAC,QAAQ,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpF,SAAS,EAAE,QAAQ,CAAC,WAAW;YAC/B,WAAW;YACX,gFAAgF;YAChF,4EAA4E;YAC5E,oFAAoF;YACpF,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,KAAK,EAAE;gBACL,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW;gBACX,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChD,uEAAuE;gBACvE,qCAAqC;gBACrC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxD;YACD,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,YAAY;YACZ,SAAS,EAAE,QAAQ,CAAC,KAAK;iBACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC;iBAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,QAAS,CAAC,MAAO,EAAE,CAAC,CAAC;YAChF,gBAAgB,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM;gBACrC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;gBACpE,CAAC,CAAC,IAAI;YACR,wEAAwE;YACxE,8EAA8E;YAC9E,8EAA8E;YAC9E,0EAA0E;YAC1E,2EAA2E;YAC3E,oCAAoC;YACpC,GAAG,oBAAoB,CAAC,IAAI,CAAC;SAC9B,CAAA;IACH,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,qBAAqB,CAAC,WAAmB,EAAE,OAAe;QAC9D,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACvE,mFAAmF;QACnF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ;gBAAE,OAAO,OAAO,CAAC,EAAE,CAAA;YACrE,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9E,CAAC;QACD,OAAO,OAAO,EAAE,EAAE,IAAI,IAAI,CAAA;IAC5B,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,oBAAoB,CACxB,WAAmB,EACnB,KAAY;QAEZ,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,KAAK,OAAO;YACrB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAClE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3D,CAAA;QACP,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC5B,MAAM,OAAO,GAA4C,EAAE,CAAA;QAC3D,IAAI,KAAK,CAAC,eAAe;YAAE,OAAO,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAA;QAC1E,IAAI,KAAK,CAAC,mBAAmB;YAAE,OAAO,CAAC,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAA;QACtF,IAAI,KAAK,CAAC,aAAa;YAAE,OAAO,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAA;aAC/D,CAAC;YACJ,8EAA8E;YAC9E,2EAA2E;YAC3E,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,WAAW,CAAC,CAAA;YAC5E,IAAI,cAAc;gBAAE,OAAO,CAAC,aAAa,GAAG,cAAc,CAAA;QAC5D,CAAC;QACD,IAAI,KAAK,CAAC,YAAY;YAAE,OAAO,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAA;QACjE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1D,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,6BAA6B,CACzC,WAAmB;QAEnB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACtE,IAAI,CAAC,SAAS,EAAE,SAAS;YAAE,OAAO,SAAS,CAAA;QAC3C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC1E,OAAO,OAAO,EAAE,oBAAoB,CAAA;IACtC,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,2BAA2B,CACvC,WAAmB,EACnB,OAAe;QAEf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB;YAAE,OAAO,IAAI,CAAA;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAClF,IAAI,MAAM,EAAE,MAAM,KAAK,cAAc,IAAI,MAAM,CAAC,wBAAwB,EAAE,CAAC;YACzE,OAAO,MAAM,CAAC,wBAAwB,CAAA;QACxC,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,qBAAqB,CACjC,WAAmB,EACnB,OAAe;QAEf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAA;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAC9E,IAAI,MAAM,EAAE,MAAM,KAAK,cAAc,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAChE,OAAO,MAAM,CAAC,eAAe,CAAA;QAC/B,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,gBAAgB,CAC5B,WAAmB,EACnB,IAAkB,EAClB,KAAY;QAEZ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;YAAE,OAAO,IAAI,CAAA;QAC5D,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YAC3E,6EAA6E;YAC7E,MAAM,GAAG,GAAa,EAAE,CAAA;YACxB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;YAC9B,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC/D,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBAAE,SAAQ;gBAC1B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACZ,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACd,CAAC;YACD,MAAM,SAAS,GAAG,GAAG;iBAClB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;gBACV,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;gBAChC,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;YACtD,CAAC,CAAC;iBACD,MAAM,CAAC,CAAC,CAAC,EAAqC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;YAC/D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAA;YACvC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YACrD,OAAO,EAAE,SAAS,EAAE,CAAA;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,yBAAyB,CAAC,WAAmB,EAAE,KAAY;QACvE,IAAI,OAAO,GAAiB,KAAK,CAAA;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ;gBAAE,OAAO,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAA;YAC3F,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9E,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,kBAAkB,CAC9B,WAAmB,EACnB,OAAe;QAEf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,CAAA;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACxE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;IAC9E,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,mBAAmB,CAAC,WAAmB,EAAE,OAAe;QACpE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAA;QAC/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACrE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,GAAG,EAAE,CAAC,CAAC,UAAU;YACjB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC,CAAA;IACL,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,OAAe;QACnE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB;YAAE,OAAO,IAAI,CAAA;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,eAAe,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAChF,CAAC;CACF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AgentRunContext, AgentRunResult, Block, ExecutionInstance, IdGenerator, PipelineStep } from '@cat-factory/kernel';
|
|
2
|
+
import type { SpendService } from '@cat-factory/spend';
|
|
3
|
+
import type { AdvanceOptions, AdvanceResult } from './advance.js';
|
|
4
|
+
import type { AgentContextBuilder } from './AgentContextBuilder.js';
|
|
5
|
+
/**
|
|
6
|
+
* The engine flow-control operations the companion loop drives. These stay on
|
|
7
|
+
* `ExecutionService` (they are the shared state-machine primitives, reused by the human
|
|
8
|
+
* "request changes" path and the iteration-cap resolution) and are injected here so the
|
|
9
|
+
* companion evaluation can live in its own unit without duplicating them.
|
|
10
|
+
*/
|
|
11
|
+
export interface CompanionControllerDeps {
|
|
12
|
+
contextBuilder: AgentContextBuilder;
|
|
13
|
+
spend: SpendService;
|
|
14
|
+
idGenerator: IdGenerator;
|
|
15
|
+
previewStepModel: (context: AgentRunContext) => Promise<string | undefined>;
|
|
16
|
+
runAgent: (context: AgentRunContext, options: AdvanceOptions) => Promise<AgentRunResult>;
|
|
17
|
+
finishStep: (step: PipelineStep) => void;
|
|
18
|
+
startStep: (step: PipelineStep) => void;
|
|
19
|
+
pauseStepForInput: (step: PipelineStep) => void;
|
|
20
|
+
updateBlockProgress: (workspaceId: string, instance: ExecutionInstance, status: 'in_progress' | 'blocked') => Promise<void>;
|
|
21
|
+
persistInstance: (workspaceId: string, instance: ExecutionInstance) => Promise<void>;
|
|
22
|
+
emitInstance: (workspaceId: string, instance: ExecutionInstance) => Promise<void>;
|
|
23
|
+
stopRunContainer: (workspaceId: string, instance: ExecutionInstance) => Promise<void>;
|
|
24
|
+
finalizeBlock: (workspaceId: string, instance: ExecutionInstance, confidence: number | undefined) => Promise<void>;
|
|
25
|
+
parkStepOnDecision: (workspaceId: string, instance: ExecutionInstance, step: PipelineStep, proposal?: string) => Promise<AdvanceResult>;
|
|
26
|
+
raiseDecisionRequired: (workspaceId: string, instance: ExecutionInstance) => Promise<void>;
|
|
27
|
+
loopCompanionProducer: (instance: ExecutionInstance, companionIndex: number, rework: NonNullable<PipelineStep['rework']>) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Drives a companion (reviewer / spec-companion / architect-companion) step: it runs the
|
|
31
|
+
* companion as a normal inline LLM step, parses its rating JSON (with one repair retry), and
|
|
32
|
+
* acts on the verdict —
|
|
33
|
+
* - at/above threshold → finish; a gated companion raises the human approval gate on the
|
|
34
|
+
* producer's output, else the run advances.
|
|
35
|
+
* - below, budget left → loop the producer back with the feedback folded in (the automatic
|
|
36
|
+
* analogue of "request changes").
|
|
37
|
+
* - below, budget spent → park on the iteration-cap gate for a human (one more round /
|
|
38
|
+
* proceed / stop & reset), NOT a failure.
|
|
39
|
+
* An unparseable verdict (even after the repair retry) fails the run (`companion_rejected`)
|
|
40
|
+
* rather than silently passing. Extracted out of `ExecutionService`; the shared step-graph
|
|
41
|
+
* primitives it calls (`loopCompanionProducer`, the parking gate, the block/instance writes)
|
|
42
|
+
* stay on the engine and are injected via {@link CompanionControllerDeps}.
|
|
43
|
+
*/
|
|
44
|
+
export declare class CompanionController {
|
|
45
|
+
private readonly deps;
|
|
46
|
+
constructor(deps: CompanionControllerDeps);
|
|
47
|
+
evaluate(workspaceId: string, instance: ExecutionInstance, step: PipelineStep, block: Block, isFinalStep: boolean, options: AdvanceOptions): Promise<AdvanceResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Run a companion step and parse its JSON verdict, with ONE repair retry when the
|
|
50
|
+
* first reply doesn't parse (truncated, or wrapped in prose `extractJson` can't
|
|
51
|
+
* recover). The retry runs only when there is a producer to grade (`gradable`) — with
|
|
52
|
+
* none there is nothing to assess, so a malformed reply is irrelevant. Returns the
|
|
53
|
+
* parsed assessment (or `undefined` if even the repair failed) and the LAST call's
|
|
54
|
+
* result, with usage summed across both calls so the caller's single `spend.record`
|
|
55
|
+
* prices the whole thing. A still-unparseable verdict is handled by the caller (it
|
|
56
|
+
* surfaces to a human rather than passing), so this never wedges the run.
|
|
57
|
+
*/
|
|
58
|
+
private runWithRepair;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=CompanionController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompanionController.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/CompanionController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAEd,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,YAAY,EACb,MAAM,qBAAqB,CAAA;AAO5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAwBnE;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,mBAAmB,CAAA;IACnC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,WAAW,CAAA;IACxB,gBAAgB,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC3E,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IACxF,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACvC,iBAAiB,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IAC/C,mBAAmB,EAAE,CACnB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,aAAa,GAAG,SAAS,KAC9B,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpF,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjF,gBAAgB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrF,aAAa,EAAE,CACb,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,KAC3B,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,kBAAkB,EAAE,CAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,EAClB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,aAAa,CAAC,CAAA;IAC3B,qBAAqB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1F,qBAAqB,EAAE,CACrB,QAAQ,EAAE,iBAAiB,EAC3B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,KACxC,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,uBAAuB,EAAI;IAExD,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA6JxB;IAED;;;;;;;;;OASG;YACW,aAAa;CAiB5B"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { DEFAULT_COMPANION_MAX_ATTEMPTS, parseCompanionAssessment, } from '@cat-factory/contracts';
|
|
2
|
+
import { companionFor, companionTargets } from '@cat-factory/agents';
|
|
3
|
+
import { extractJson } from '../requirements/requirements.logic.js';
|
|
4
|
+
/** Parse a companion's JSON verdict from a model reply, or `undefined` if it won't parse. */
|
|
5
|
+
function parseCompanionOrUndefined(output) {
|
|
6
|
+
try {
|
|
7
|
+
return parseCompanionAssessment(extractJson(output ?? ''));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Sum the token usage of two model calls (for the companion's repair retry). */
|
|
14
|
+
function sumUsage(a, b) {
|
|
15
|
+
if (!a)
|
|
16
|
+
return b;
|
|
17
|
+
if (!b)
|
|
18
|
+
return a;
|
|
19
|
+
return {
|
|
20
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
21
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Drives a companion (reviewer / spec-companion / architect-companion) step: it runs the
|
|
26
|
+
* companion as a normal inline LLM step, parses its rating JSON (with one repair retry), and
|
|
27
|
+
* acts on the verdict —
|
|
28
|
+
* - at/above threshold → finish; a gated companion raises the human approval gate on the
|
|
29
|
+
* producer's output, else the run advances.
|
|
30
|
+
* - below, budget left → loop the producer back with the feedback folded in (the automatic
|
|
31
|
+
* analogue of "request changes").
|
|
32
|
+
* - below, budget spent → park on the iteration-cap gate for a human (one more round /
|
|
33
|
+
* proceed / stop & reset), NOT a failure.
|
|
34
|
+
* An unparseable verdict (even after the repair retry) fails the run (`companion_rejected`)
|
|
35
|
+
* rather than silently passing. Extracted out of `ExecutionService`; the shared step-graph
|
|
36
|
+
* primitives it calls (`loopCompanionProducer`, the parking gate, the block/instance writes)
|
|
37
|
+
* stay on the engine and are injected via {@link CompanionControllerDeps}.
|
|
38
|
+
*/
|
|
39
|
+
export class CompanionController {
|
|
40
|
+
deps;
|
|
41
|
+
constructor(deps) {
|
|
42
|
+
this.deps = deps;
|
|
43
|
+
}
|
|
44
|
+
async evaluate(workspaceId, instance, step, block, isFinalStep, options) {
|
|
45
|
+
const targets = companionTargets(step.agentKind);
|
|
46
|
+
// The nearest earlier step whose kind this companion reviews (the producer).
|
|
47
|
+
let producerIndex = -1;
|
|
48
|
+
for (let i = instance.currentStep - 1; i >= 0; i--) {
|
|
49
|
+
if (targets.includes(instance.steps[i].agentKind)) {
|
|
50
|
+
producerIndex = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Run the companion as a normal inline LLM step: its prompt asks for the rating
|
|
55
|
+
// JSON and `priorOutputs` already carries the producer's output for it to grade.
|
|
56
|
+
const context = await this.deps.contextBuilder.buildContext(workspaceId, instance, step, isFinalStep, block);
|
|
57
|
+
const previewModel = await this.deps.previewStepModel(context);
|
|
58
|
+
if (previewModel && previewModel !== step.model)
|
|
59
|
+
step.model = previewModel;
|
|
60
|
+
// Run the companion, parsing its JSON verdict with ONE repair retry when the first
|
|
61
|
+
// reply doesn't parse (truncated / wrapped in prose). Only retried when there is a
|
|
62
|
+
// producer to grade. `result` carries the LAST call's output + the summed usage.
|
|
63
|
+
const { assessment, result } = await this.runWithRepair(context, options, producerIndex >= 0);
|
|
64
|
+
if (result.usage) {
|
|
65
|
+
await this.deps.spend.record({
|
|
66
|
+
workspaceId,
|
|
67
|
+
executionId: instance.id,
|
|
68
|
+
agentKind: step.agentKind,
|
|
69
|
+
model: result.model ?? 'unknown',
|
|
70
|
+
usage: result.usage,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (result.model)
|
|
74
|
+
step.model = result.model;
|
|
75
|
+
const companion = step.companion ?? {
|
|
76
|
+
threshold: companionFor(step.agentKind)?.defaultThreshold ?? 0.8,
|
|
77
|
+
maxAttempts: DEFAULT_COMPANION_MAX_ATTEMPTS,
|
|
78
|
+
attempts: 0,
|
|
79
|
+
verdicts: [],
|
|
80
|
+
};
|
|
81
|
+
const feedback = assessment?.summary ?? '';
|
|
82
|
+
// There IS a producer to grade but the companion's own verdict never parsed (even
|
|
83
|
+
// after the repair retry): do NOT silently treat that as a perfect pass. That is the
|
|
84
|
+
// bug where a truncated reviewer reply surfaced as "100% ≥ 80%" and dropped a real
|
|
85
|
+
// review. Surface it for a human instead, recording the raw reply as the detail.
|
|
86
|
+
if (producerIndex >= 0 && !assessment) {
|
|
87
|
+
step.output = result.output || '';
|
|
88
|
+
step.companion = companion;
|
|
89
|
+
await this.deps.persistInstance(workspaceId, instance);
|
|
90
|
+
// Hand the precise classification + the raw reply (the whole point of the failure,
|
|
91
|
+
// for triage) to the driver's single `failRun` funnel. Do NOT fail the run here as
|
|
92
|
+
// well: a second `failRun` from the driver would clobber this rich record with a
|
|
93
|
+
// generic `job_failed` ("the implementation container reported a failure", no
|
|
94
|
+
// detail), which is exactly the misleading surface this path is meant to avoid.
|
|
95
|
+
return {
|
|
96
|
+
kind: 'job_failed',
|
|
97
|
+
failureKind: 'companion_rejected',
|
|
98
|
+
error: `Companion "${step.agentKind}" did not return a parseable assessment (its reply ` +
|
|
99
|
+
`was truncated or malformed) after a repair retry.`,
|
|
100
|
+
detail: (result.output ?? '').slice(0, 2000) || undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// The score to judge: the parsed rating when there is a producer to grade, else a
|
|
104
|
+
// perfect score (no producer of this companion's target kind precedes it, so there
|
|
105
|
+
// is genuinely nothing to grade and the run advances).
|
|
106
|
+
const rating = assessment && producerIndex >= 0 ? assessment.rating : 1;
|
|
107
|
+
// The FIRST review batch ALWAYS loops the producer back when it raised any comments,
|
|
108
|
+
// regardless of rating; the configured threshold only governs the SECOND pass onward.
|
|
109
|
+
// `attempts` counts automatic reworks, so it is 0 on the first batch. Applies to every
|
|
110
|
+
// companion (reviewer / spec-companion / architect-companion). Gated on a real producer
|
|
111
|
+
// so the loop-back below always has a step to re-run.
|
|
112
|
+
const firstBatch = companion.attempts === 0;
|
|
113
|
+
const hasComments = producerIndex >= 0 && (assessment?.comments?.length ?? 0) > 0;
|
|
114
|
+
const passed = firstBatch && hasComments ? false : rating >= companion.threshold;
|
|
115
|
+
// Append this cycle's standardized verdict (the same shape the requirements-rework
|
|
116
|
+
// gate stores) so the whole correction sequence is visible, not just the latest.
|
|
117
|
+
companion.verdicts.push({
|
|
118
|
+
rating,
|
|
119
|
+
threshold: companion.threshold,
|
|
120
|
+
passed,
|
|
121
|
+
feedback,
|
|
122
|
+
});
|
|
123
|
+
step.companion = companion;
|
|
124
|
+
step.output = feedback || result.output || '';
|
|
125
|
+
// PASS: the producer cleared the bar (and was not force-looped on its first batch).
|
|
126
|
+
if (passed) {
|
|
127
|
+
this.deps.finishStep(step);
|
|
128
|
+
step.progress = 1;
|
|
129
|
+
// A gated companion now raises the HUMAN approval gate on the producer's output
|
|
130
|
+
// (the human reviews what the companion just cleared). Never on the final step.
|
|
131
|
+
if (step.requiresApproval && !isFinalStep && step.approval?.status !== 'approved') {
|
|
132
|
+
const producer = producerIndex >= 0 ? instance.steps[producerIndex] : undefined;
|
|
133
|
+
step.approval = {
|
|
134
|
+
id: this.deps.idGenerator.next('appr'),
|
|
135
|
+
status: 'pending',
|
|
136
|
+
proposal: producer?.output ?? step.output,
|
|
137
|
+
};
|
|
138
|
+
this.deps.pauseStepForInput(step);
|
|
139
|
+
instance.status = 'blocked';
|
|
140
|
+
await this.deps.updateBlockProgress(workspaceId, instance, 'blocked');
|
|
141
|
+
await this.deps.persistInstance(workspaceId, instance);
|
|
142
|
+
await this.deps.emitInstance(workspaceId, instance);
|
|
143
|
+
return { kind: 'awaiting_decision', decisionId: step.approval.id };
|
|
144
|
+
}
|
|
145
|
+
if (isFinalStep) {
|
|
146
|
+
instance.status = 'done';
|
|
147
|
+
await this.deps.finalizeBlock(workspaceId, instance, undefined);
|
|
148
|
+
await this.deps.persistInstance(workspaceId, instance);
|
|
149
|
+
await this.deps.emitInstance(workspaceId, instance);
|
|
150
|
+
await this.deps.stopRunContainer(workspaceId, instance);
|
|
151
|
+
return { kind: 'done' };
|
|
152
|
+
}
|
|
153
|
+
instance.currentStep += 1;
|
|
154
|
+
const next = instance.steps[instance.currentStep];
|
|
155
|
+
if (next)
|
|
156
|
+
this.deps.startStep(next);
|
|
157
|
+
await this.deps.updateBlockProgress(workspaceId, instance, 'in_progress');
|
|
158
|
+
await this.deps.persistInstance(workspaceId, instance);
|
|
159
|
+
await this.deps.emitInstance(workspaceId, instance);
|
|
160
|
+
return { kind: 'continue' };
|
|
161
|
+
}
|
|
162
|
+
// BELOW THRESHOLD, automatic budget spent → DON'T get stuck. Park on a human
|
|
163
|
+
// decision (one more round / proceed anyway / stop & reset) — the same iteration-cap
|
|
164
|
+
// surface the requirements reviewer uses at its cap. Only AUTOMATIC reworks count
|
|
165
|
+
// against the budget (`attempts`); human "request changes" cycles on a gated
|
|
166
|
+
// companion re-run the producer without consuming it. `step.output` already holds the
|
|
167
|
+
// companion's latest feedback; the `exceeded` flag + the parked approval gate let the
|
|
168
|
+
// SPA render the three choices (resolved via `resolveCompanionExceeded`).
|
|
169
|
+
if (companion.attempts >= companion.maxAttempts) {
|
|
170
|
+
companion.exceeded = true;
|
|
171
|
+
step.companion = companion;
|
|
172
|
+
await this.deps.raiseDecisionRequired(workspaceId, instance);
|
|
173
|
+
return this.deps.parkStepOnDecision(workspaceId, instance, step, step.output ?? '');
|
|
174
|
+
}
|
|
175
|
+
// NOT PASSED, budget left → loop the producer back with the feedback folded in (the
|
|
176
|
+
// automatic analogue of a human "request changes"). Reached either below threshold or
|
|
177
|
+
// on the forced first-batch loop. `producerIndex` is guaranteed >= 0 here: a forced
|
|
178
|
+
// loop requires comments on a real producer, and a below-threshold rating requires a
|
|
179
|
+
// parsed verdict against a producer (otherwise rating defaulted to 1 and we passed).
|
|
180
|
+
const producer = instance.steps[producerIndex];
|
|
181
|
+
this.deps.loopCompanionProducer(instance, instance.currentStep, {
|
|
182
|
+
previousProposal: producer.output ?? '',
|
|
183
|
+
feedback: assessment?.summary ?? '',
|
|
184
|
+
...(assessment?.comments?.length ? { comments: assessment.comments } : {}),
|
|
185
|
+
});
|
|
186
|
+
await this.deps.updateBlockProgress(workspaceId, instance, 'in_progress');
|
|
187
|
+
await this.deps.persistInstance(workspaceId, instance);
|
|
188
|
+
await this.deps.emitInstance(workspaceId, instance);
|
|
189
|
+
return { kind: 'continue' };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Run a companion step and parse its JSON verdict, with ONE repair retry when the
|
|
193
|
+
* first reply doesn't parse (truncated, or wrapped in prose `extractJson` can't
|
|
194
|
+
* recover). The retry runs only when there is a producer to grade (`gradable`) — with
|
|
195
|
+
* none there is nothing to assess, so a malformed reply is irrelevant. Returns the
|
|
196
|
+
* parsed assessment (or `undefined` if even the repair failed) and the LAST call's
|
|
197
|
+
* result, with usage summed across both calls so the caller's single `spend.record`
|
|
198
|
+
* prices the whole thing. A still-unparseable verdict is handled by the caller (it
|
|
199
|
+
* surfaces to a human rather than passing), so this never wedges the run.
|
|
200
|
+
*/
|
|
201
|
+
async runWithRepair(context, options, gradable) {
|
|
202
|
+
const first = await this.deps.runAgent(context, options);
|
|
203
|
+
const parsed = parseCompanionOrUndefined(first.output);
|
|
204
|
+
if (parsed || !gradable)
|
|
205
|
+
return { assessment: parsed, result: first };
|
|
206
|
+
// The first reply didn't parse. Re-run the same grading step once more; with the
|
|
207
|
+
// companion's raised output budget this almost always clears a one-off truncation.
|
|
208
|
+
const second = await this.deps.runAgent(context, options);
|
|
209
|
+
const repaired = parseCompanionOrUndefined(second.output);
|
|
210
|
+
return {
|
|
211
|
+
assessment: repaired,
|
|
212
|
+
result: { ...second, usage: sumUsage(first.usage, second.usage) },
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=CompanionController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompanionController.js","sourceRoot":"","sources":["../../../src/modules/execution/CompanionController.ts"],"names":[],"mappings":"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"}
|