@cat-factory/orchestration 0.192.0 → 0.194.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/dist/container/dependencies.d.ts +5 -1
- package/dist/container/dependencies.d.ts.map +1 -1
- package/dist/container/engine-collaborators.d.ts.map +1 -1
- package/dist/container/engine-collaborators.js +4 -7
- package/dist/container/engine-collaborators.js.map +1 -1
- package/dist/container/execution-service.d.ts.map +1 -1
- package/dist/container/execution-service.js +3 -0
- package/dist/container/execution-service.js.map +1 -1
- package/dist/container/inline-model-deps.d.ts +20 -0
- package/dist/container/inline-model-deps.d.ts.map +1 -0
- package/dist/container/inline-model-deps.js +38 -0
- package/dist/container/inline-model-deps.js.map +1 -0
- package/dist/container/modules.d.ts.map +1 -1
- package/dist/container/modules.js +23 -39
- package/dist/container/modules.js.map +1 -1
- package/dist/container/review-modules.d.ts.map +1 -1
- package/dist/container/review-modules.js +10 -28
- package/dist/container/review-modules.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inlineBlockModel.d.ts +51 -0
- package/dist/inlineBlockModel.d.ts.map +1 -0
- package/dist/inlineBlockModel.js +31 -0
- package/dist/inlineBlockModel.js.map +1 -0
- package/dist/modules/board/BoardService.d.ts +2 -0
- package/dist/modules/board/BoardService.d.ts.map +1 -1
- package/dist/modules/board/BoardService.js +4 -0
- package/dist/modules/board/BoardService.js.map +1 -1
- package/dist/modules/board/publicBoardReads.d.ts +12 -0
- package/dist/modules/board/publicBoardReads.d.ts.map +1 -1
- package/dist/modules/board/publicBoardReads.js +19 -4
- package/dist/modules/board/publicBoardReads.js.map +1 -1
- package/dist/modules/bugHunt/BugHuntAssessorService.d.ts +8 -4
- package/dist/modules/bugHunt/BugHuntAssessorService.d.ts.map +1 -1
- package/dist/modules/bugHunt/BugHuntAssessorService.js +6 -10
- package/dist/modules/bugHunt/BugHuntAssessorService.js.map +1 -1
- package/dist/modules/docInterview/DocInterviewService.d.ts +8 -4
- package/dist/modules/docInterview/DocInterviewService.d.ts.map +1 -1
- package/dist/modules/docInterview/DocInterviewService.js +4 -13
- package/dist/modules/docInterview/DocInterviewService.js.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.d.ts +14 -12
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.js +8 -28
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
- package/dist/modules/execution/AgentDispatchController.d.ts +115 -0
- package/dist/modules/execution/AgentDispatchController.d.ts.map +1 -0
- package/dist/modules/execution/AgentDispatchController.js +307 -0
- package/dist/modules/execution/AgentDispatchController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +18 -105
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +70 -589
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/ExecutionServiceDependencies.d.ts +19 -3
- package/dist/modules/execution/ExecutionServiceDependencies.d.ts.map +1 -1
- package/dist/modules/execution/ForkChatService.d.ts +8 -4
- package/dist/modules/execution/ForkChatService.d.ts.map +1 -1
- package/dist/modules/execution/ForkChatService.js +4 -13
- package/dist/modules/execution/ForkChatService.js.map +1 -1
- package/dist/modules/execution/IterationCapController.d.ts +57 -0
- package/dist/modules/execution/IterationCapController.d.ts.map +1 -0
- package/dist/modules/execution/IterationCapController.js +141 -0
- package/dist/modules/execution/IterationCapController.js.map +1 -0
- package/dist/modules/execution/JudgeService.d.ts +8 -4
- package/dist/modules/execution/JudgeService.d.ts.map +1 -1
- package/dist/modules/execution/JudgeService.js +4 -13
- package/dist/modules/execution/JudgeService.js.map +1 -1
- package/dist/modules/execution/RunAdmission.d.ts +1 -1
- package/dist/modules/execution/RunAdmission.d.ts.map +1 -1
- package/dist/modules/execution/RunAdmission.js +5 -2
- package/dist/modules/execution/RunAdmission.js.map +1 -1
- package/dist/modules/execution/RunDispatcher.d.ts +31 -195
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +47 -313
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/RunDispatcherDependencies.d.ts +142 -0
- package/dist/modules/execution/RunDispatcherDependencies.d.ts.map +1 -0
- package/dist/modules/execution/RunDispatcherDependencies.js +27 -0
- package/dist/modules/execution/RunDispatcherDependencies.js.map +1 -0
- package/dist/modules/execution/RunLifecycleController.d.ts +141 -0
- package/dist/modules/execution/RunLifecycleController.d.ts.map +1 -0
- package/dist/modules/execution/RunLifecycleController.js +489 -0
- package/dist/modules/execution/RunLifecycleController.js.map +1 -0
- package/dist/modules/execution/TesterQualityReviewService.d.ts +8 -4
- package/dist/modules/execution/TesterQualityReviewService.d.ts.map +1 -1
- package/dist/modules/execution/TesterQualityReviewService.js +4 -13
- package/dist/modules/execution/TesterQualityReviewService.js.map +1 -1
- package/dist/modules/execution/dispatchPromptSettings.d.ts +42 -2
- package/dist/modules/execution/dispatchPromptSettings.d.ts.map +1 -1
- package/dist/modules/execution/dispatchPromptSettings.js +37 -0
- package/dist/modules/execution/dispatchPromptSettings.js.map +1 -1
- package/dist/modules/execution/run-action-controllers.d.ts +18 -0
- package/dist/modules/execution/run-action-controllers.d.ts.map +1 -0
- package/dist/modules/execution/run-action-controllers.js +19 -0
- package/dist/modules/execution/run-action-controllers.js.map +1 -0
- package/dist/modules/execution/run-context-admission.d.ts +1 -1
- package/dist/modules/execution/run-context-admission.d.ts.map +1 -1
- package/dist/modules/execution/run-context-admission.js +2 -0
- package/dist/modules/execution/run-context-admission.js.map +1 -1
- package/dist/modules/initiative/InitiativeInterviewService.d.ts +8 -4
- package/dist/modules/initiative/InitiativeInterviewService.d.ts.map +1 -1
- package/dist/modules/initiative/InitiativeInterviewService.js +4 -13
- package/dist/modules/initiative/InitiativeInterviewService.js.map +1 -1
- package/dist/modules/kaizen/KaizenService.d.ts +14 -9
- package/dist/modules/kaizen/KaizenService.d.ts.map +1 -1
- package/dist/modules/kaizen/KaizenService.js +11 -16
- package/dist/modules/kaizen/KaizenService.js.map +1 -1
- package/dist/modules/modelPresets/ModelPresetService.d.ts +54 -2
- package/dist/modules/modelPresets/ModelPresetService.d.ts.map +1 -1
- package/dist/modules/modelPresets/ModelPresetService.js +103 -4
- package/dist/modules/modelPresets/ModelPresetService.js.map +1 -1
- package/dist/modules/review/IterativeReviewService.d.ts +8 -4
- package/dist/modules/review/IterativeReviewService.d.ts.map +1 -1
- package/dist/modules/review/IterativeReviewService.js +4 -13
- package/dist/modules/review/IterativeReviewService.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { assertFound, ConflictError, DEFAULT_RISK_POLICY, ValidationError, } from '@cat-factory/kernel';
|
|
2
|
+
import { companionFor } from '@cat-factory/agents';
|
|
3
|
+
import { DEFAULT_COMPANION_MAX_ATTEMPTS, pipelineHasVisualStep } from '@cat-factory/contracts';
|
|
4
|
+
import { assertPipelineLaunchable } from '../pipelines/pipelineShape.js';
|
|
5
|
+
import { isTesterKind } from './ci.logic.js';
|
|
6
|
+
import { DEFAULT_FOLLOW_UP_MAX_LOOPS, FOLLOW_UP_PRODUCER_KIND } from './followUp.logic.js';
|
|
7
|
+
import { isRalphKind, resolveRalphConfig, seedRalphState } from './ralph.logic.js';
|
|
8
|
+
import { buildResumedInstance, planResumedSteps, planRestartFromStep } from './retry.logic.js';
|
|
9
|
+
import { claimLiveRunOrConflict, handOffLiveRun } from './runStart.js';
|
|
10
|
+
import { descendantIds } from '../board/board.logic.js';
|
|
11
|
+
/**
|
|
12
|
+
* A run's LIFECYCLE surface: every entry point that launches one (`start`), re-launches one
|
|
13
|
+
* (`retry` / `restartFromStep`), lifts a spend pause (`resumePaused`), or ends one (`cancel` /
|
|
14
|
+
* `stopRun` / `teardownForBlockTree`).
|
|
15
|
+
*
|
|
16
|
+
* They belong together because all three launch paths write the SAME two things in the SAME order:
|
|
17
|
+
* the atomic live-run claim, then the durable/SPA/outbound hand-off (both owned by `runStart.ts`,
|
|
18
|
+
* reached through the one `runStartDeps` getter below). They differ only in the block patch written
|
|
19
|
+
* between the two and in what each tears down first. Keeping that order in one place is what stops
|
|
20
|
+
* a new entry point from claiming without handing off (a run nothing drives) or announcing before
|
|
21
|
+
* the claim commits.
|
|
22
|
+
*
|
|
23
|
+
* `ExecutionService` keeps thin delegates, so no HTTP call site changed. The per-step machine
|
|
24
|
+
* (`advanceInstance` / `stepInstance`) and the human decision surface (`StepDecisionController`)
|
|
25
|
+
* deliberately stay where they are: those act on a run that is already live.
|
|
26
|
+
*/
|
|
27
|
+
export class RunLifecycleController {
|
|
28
|
+
deps;
|
|
29
|
+
constructor(deps) {
|
|
30
|
+
this.deps = deps;
|
|
31
|
+
}
|
|
32
|
+
/** Start a pipeline against a block, replacing any prior run on it. */
|
|
33
|
+
async start(workspaceId, blockId, pipelineId, options = {}) {
|
|
34
|
+
const { initiatedBy, activate, origin = 'manual', intakeOrigin, gatesOverride } = options;
|
|
35
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
36
|
+
const block = await this.deps.requireBlock(workspaceId, blockId);
|
|
37
|
+
const pipeline = assertFound(await this.deps.pipelineRepository.get(workspaceId, pipelineId), 'Pipeline', pipelineId);
|
|
38
|
+
// Launch-constraint gate (start-only, NOT part of the shared retry re-validation): reject a
|
|
39
|
+
// manual start of a recurring-only pipeline (or a scheduled fire of a one-off-only one), and
|
|
40
|
+
// a bug-intake pipeline that isn't recurring. Before any side effects.
|
|
41
|
+
assertPipelineLaunchable(pipeline.agentKinds, pipeline.availability, origin, pipeline.enabled);
|
|
42
|
+
// Per-run gate override must be parallel to the pipeline's steps (one boolean per step,
|
|
43
|
+
// original-index-aligned like `pipeline.gates`). A mismatch means a preset's review mapping
|
|
44
|
+
// is out of step with the pipeline it targets — reject up front, before any side effects.
|
|
45
|
+
if (gatesOverride && gatesOverride.length !== pipeline.agentKinds.length) {
|
|
46
|
+
throw new ValidationError(`Gate override has ${gatesOverride.length} entr${gatesOverride.length === 1 ? 'y' : 'ies'} but pipeline '${pipeline.id}' has ${pipeline.agentKinds.length} step(s).`);
|
|
47
|
+
}
|
|
48
|
+
// Shared config/resource preconditions (pipeline shape, frame type, tester infra, binary
|
|
49
|
+
// storage, agent backend, provider/preset satisfiability, budget) — the SAME gate a retry
|
|
50
|
+
// runs, so the two can't drift. See assertRunnable.
|
|
51
|
+
await this.deps.admission.assertRunnable(workspaceId, block, pipeline, initiatedBy);
|
|
52
|
+
// A Ralph-loop step needs a programmatic completion command (its exit condition); refuse to
|
|
53
|
+
// start a misconfigured run rather than dispatch a validation-less coding pass that never
|
|
54
|
+
// gates. The command is a per-task agent-config value (the SPA also requires it at creation).
|
|
55
|
+
if (pipeline.agentKinds.some(isRalphKind) &&
|
|
56
|
+
!resolveRalphConfig(block.agentConfig).validationCommand) {
|
|
57
|
+
throw new ValidationError('A Ralph loop task needs a validation command (its completion criterion) before it can ' +
|
|
58
|
+
'start. Set one in the task configuration.');
|
|
59
|
+
}
|
|
60
|
+
// START-ONLY gates below: a retry REPLACES the failed run rather than adding a new one, so
|
|
61
|
+
// the concurrency limit doesn't apply to it, and a re-drive of an already-started task isn't
|
|
62
|
+
// re-gated on its dependencies.
|
|
63
|
+
// Enforce the workspace's per-service running-task limit (off by default) — a clear,
|
|
64
|
+
// actionable error before any side effects, so the human knows why the start was refused.
|
|
65
|
+
await this.deps.admission.assertWithinTaskLimit(workspaceId, block);
|
|
66
|
+
// Hard dependency gate: a task cannot start while any block it `dependsOn` is unfinished
|
|
67
|
+
// (not yet `done`/merged). Enforced server-side so it holds for manual starts, recurring
|
|
68
|
+
// fires, auto-start propagation and direct API calls alike — the frontend's runnable
|
|
69
|
+
// check is only a hint. Before any side effects so nothing is torn down on a refusal.
|
|
70
|
+
await this.deps.admission.assertDependenciesMet(workspaceId, block);
|
|
71
|
+
// Mint the activation next: if the credential can't be unlocked, fail before
|
|
72
|
+
// tearing down the block's prior run or creating a new one.
|
|
73
|
+
const executionId = this.deps.idGenerator.next('exec');
|
|
74
|
+
await activate?.(executionId);
|
|
75
|
+
// Read the block's prior run once: a manual re-start of an already-running block REPLACES
|
|
76
|
+
// it (the board offers "start" on a live block), so we pass its id to `insertLive` as the
|
|
77
|
+
// `replaceId` it supersedes atomically. A genuinely-CONCURRENT second start reads the SAME
|
|
78
|
+
// prior (or none), so only one insert wins and the other is rejected 409 — the loser's
|
|
79
|
+
// `replaceId` deletes only what it read, never the winner's fresh row (see insertLive).
|
|
80
|
+
const prior = await this.deps.executionRepository.getByBlock(workspaceId, blockId);
|
|
81
|
+
// Replacing the block's prior run: clear its per-run activation now (it never reaches
|
|
82
|
+
// the terminal cleanup in emitInstance when it's still running), so a replaced run's
|
|
83
|
+
// system-encrypted token copy doesn't linger to its TTL. Keyed by the OLD run id, so
|
|
84
|
+
// the activation just minted for the new run is untouched.
|
|
85
|
+
if (this.deps.subscriptionActivations && prior && prior.id !== executionId) {
|
|
86
|
+
// Best-effort + idempotent, mirroring the terminal cleanup in RunStateMachine.emit: a
|
|
87
|
+
// failure here must never derail the start. In mothership mode this repo is remote and
|
|
88
|
+
// `deleteByExecution` is not yet allow-listed (it throws `unknown_method`), so an
|
|
89
|
+
// unguarded call would otherwise break re-running any block; the TTL sweep reclaims the
|
|
90
|
+
// stale activation row as the backstop.
|
|
91
|
+
try {
|
|
92
|
+
await this.deps.subscriptionActivations.deleteByExecution(prior.id);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Swallow — see above.
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// NB: do NOT `deleteByBlock` here — `claimLiveRunOrConflict` (below) atomically clears the
|
|
99
|
+
// block's terminal rows AND the `prior` run it replaces, then inserts the new live run, so a
|
|
100
|
+
// concurrent double-start is rejected by the live-run index instead of both wiping each
|
|
101
|
+
// other's row (see insertLive).
|
|
102
|
+
// Build the run only from the ENABLED steps. A step the pipeline marked
|
|
103
|
+
// `enabled[i] === false` is kept in the saved pipeline (so it can be toggled back
|
|
104
|
+
// on later) but skipped here entirely. Gates/thresholds are read by the kind's
|
|
105
|
+
// ORIGINAL index `i`, so they stay aligned to the kind even when earlier steps are
|
|
106
|
+
// skipped; the first SURVIVING step is the one that starts working.
|
|
107
|
+
const steps = pipeline.agentKinds
|
|
108
|
+
.map((kind, i) => ({ kind, i }))
|
|
109
|
+
.filter(({ i }) => pipeline.enabled?.[i] !== false)
|
|
110
|
+
.map(({ kind, i }, position) => {
|
|
111
|
+
const companionDef = companionFor(kind);
|
|
112
|
+
return {
|
|
113
|
+
agentKind: kind,
|
|
114
|
+
state: position === 0 ? 'working' : 'pending',
|
|
115
|
+
progress: 0,
|
|
116
|
+
decision: null,
|
|
117
|
+
// A gated step pauses for human approval once its proposal is ready (see
|
|
118
|
+
// recordStepResult). A per-run override (the initiative-preset seam) wins over the
|
|
119
|
+
// pipeline's own gate for this step; else the pipeline definition at run start. Both
|
|
120
|
+
// read by the step's ORIGINAL index `i`, so they stay aligned to the kind even when
|
|
121
|
+
// earlier steps are disabled.
|
|
122
|
+
requiresApproval: gatesOverride?.[i] ?? pipeline.gates?.[i] ?? false,
|
|
123
|
+
approval: null,
|
|
124
|
+
// A consensus-enabled step runs through the multi-model mechanism (the consensus
|
|
125
|
+
// executor reads this off the context). Copied from the pipeline at run start.
|
|
126
|
+
...(pipeline.consensus?.[i] ? { consensus: pipeline.consensus[i] } : {}),
|
|
127
|
+
// Estimate gating: when set+enabled the step is skipped at runtime unless the
|
|
128
|
+
// block estimate (written by an earlier task-estimator step) meets the threshold.
|
|
129
|
+
...(pipeline.gating?.[i] ? { gating: pipeline.gating[i] } : {}),
|
|
130
|
+
// The extensible per-step options bag (the new home for per-step parameters — see
|
|
131
|
+
// stepOptionsSchema). Copied from the pipeline at run start, keyed by the step's
|
|
132
|
+
// ORIGINAL index `i`, so it stays aligned to the kind even when earlier steps are
|
|
133
|
+
// disabled. Today it carries the requirements-review `autoRecommend` toggle.
|
|
134
|
+
...(pipeline.stepOptions?.[i] ? { stepOptions: pipeline.stepOptions[i] } : {}),
|
|
135
|
+
// A companion step carries its quality bar + rework budget, seeded from the
|
|
136
|
+
// pipeline's per-step threshold (else the companion's default).
|
|
137
|
+
...(companionDef
|
|
138
|
+
? {
|
|
139
|
+
companion: {
|
|
140
|
+
threshold: pipeline.thresholds?.[i] ?? companionDef.defaultThreshold,
|
|
141
|
+
maxAttempts: DEFAULT_COMPANION_MAX_ATTEMPTS,
|
|
142
|
+
attempts: 0,
|
|
143
|
+
verdicts: [],
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
: {}),
|
|
147
|
+
// The Follow-up companion is on by default for a `coder` step; the pipeline's
|
|
148
|
+
// per-step `followUps[i] === false` toggle disables it. Seeded empty here; the
|
|
149
|
+
// harness streams items in as the Coder surfaces them (see pollAgentJob).
|
|
150
|
+
...(kind === FOLLOW_UP_PRODUCER_KIND && pipeline.followUps?.[i] !== false
|
|
151
|
+
? {
|
|
152
|
+
followUps: {
|
|
153
|
+
enabled: true,
|
|
154
|
+
items: [],
|
|
155
|
+
loops: 0,
|
|
156
|
+
maxLoops: DEFAULT_FOLLOW_UP_MAX_LOOPS,
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
: {}),
|
|
160
|
+
// The test quality-control companion is on by default for a Tester step; the
|
|
161
|
+
// pipeline's per-step `testerQuality[i].enabled === false` disables it. `maxAttempts`
|
|
162
|
+
// is seeded with the default ceiling here and refreshed from the task's resolved
|
|
163
|
+
// merge preset on the first report (TesterController). Optional estimate gating is
|
|
164
|
+
// carried through so it can be evaluated against the block estimate at gate time.
|
|
165
|
+
...(isTesterKind(kind) && pipeline.testerQuality?.[i]?.enabled !== false
|
|
166
|
+
? {
|
|
167
|
+
testerQuality: {
|
|
168
|
+
enabled: true,
|
|
169
|
+
attempts: 0,
|
|
170
|
+
maxAttempts: DEFAULT_RISK_POLICY.maxTesterQualityIterations,
|
|
171
|
+
verdicts: [],
|
|
172
|
+
...(pipeline.testerQuality?.[i]?.gating
|
|
173
|
+
? { gating: pipeline.testerQuality[i].gating }
|
|
174
|
+
: {}),
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
: {}),
|
|
178
|
+
// A `ralph` step carries its persistent-loop state — the iteration count, the budget,
|
|
179
|
+
// and the programmatic completion command — seeded from the block's per-task agent
|
|
180
|
+
// config. Riding the persisted step is what lets a mid-loop run survive a restart
|
|
181
|
+
// (both durable drivers + sweepers re-drive from it). See ralph.logic.ts.
|
|
182
|
+
...(isRalphKind(kind)
|
|
183
|
+
? { ralph: seedRalphState(resolveRalphConfig(block.agentConfig)) }
|
|
184
|
+
: {}),
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
if (steps.length === 0) {
|
|
188
|
+
throw new ValidationError('Pipeline has no enabled steps to run.');
|
|
189
|
+
}
|
|
190
|
+
// For a visual (UI-test) pipeline on a frontend frame, resolve its backend bindings ONCE at
|
|
191
|
+
// start and stamp both the resolved bindings and the non-fatal advisories (duplicate env vars,
|
|
192
|
+
// or a partial-live set of bound services) on the run. The bindings are a frozen snapshot so
|
|
193
|
+
// the SPA's run/step detail projects what the run ACTUALLY drove against (truthful after the
|
|
194
|
+
// envs are torn down). Only paid for a visual pipeline — the same condition the tester infra
|
|
195
|
+
// gate keys off — so a plain backend run does no extra env read. Absent → no notes/bindings.
|
|
196
|
+
const frontendRun = pipelineHasVisualStep({ agentKinds: pipeline.agentKinds })
|
|
197
|
+
? await this.deps.contextBuilder.resolveFrontendRunInfo(workspaceId, block)
|
|
198
|
+
: undefined;
|
|
199
|
+
const instance = {
|
|
200
|
+
id: executionId,
|
|
201
|
+
blockId,
|
|
202
|
+
pipelineId: pipeline.id,
|
|
203
|
+
pipelineName: pipeline.name,
|
|
204
|
+
steps,
|
|
205
|
+
currentStep: 0,
|
|
206
|
+
status: 'running',
|
|
207
|
+
initiatedBy: initiatedBy ?? null,
|
|
208
|
+
// Only a headless start carries an explicit intake origin; `ui` is the read-time
|
|
209
|
+
// default, so an ordinary board/schedule start stores nothing extra.
|
|
210
|
+
...(intakeOrigin != null ? { intakeOrigin } : {}),
|
|
211
|
+
createdAt: this.deps.clock.now(),
|
|
212
|
+
...(frontendRun?.notes.length ? { notes: frontendRun.notes } : {}),
|
|
213
|
+
...(frontendRun?.bindings.length ? { frontendBindings: frontendRun.bindings } : {}),
|
|
214
|
+
};
|
|
215
|
+
await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, prior?.id);
|
|
216
|
+
await this.deps.blockRepository.update(workspaceId, blockId, {
|
|
217
|
+
status: 'in_progress',
|
|
218
|
+
progress: 0,
|
|
219
|
+
executionId: instance.id,
|
|
220
|
+
});
|
|
221
|
+
await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
|
|
222
|
+
return instance;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Retry a failed run: re-drive the same pipeline on the same block, **resuming
|
|
226
|
+
* from the step that actually failed** rather than restarting from step 0. The
|
|
227
|
+
* steps that already completed are preserved (so a `coder` failure in `pl_full`
|
|
228
|
+
* doesn't re-run the human-gated `requirements`/`architect` steps before it);
|
|
229
|
+
* the failed step and everything after it are reset to a clean, re-runnable
|
|
230
|
+
* state. Only a `failed` run can be retried.
|
|
231
|
+
*
|
|
232
|
+
* A fresh instance id is minted because the durable runner addresses one
|
|
233
|
+
* Workflows instance per execution id and the failed one is terminal — the new
|
|
234
|
+
* instance simply starts with `currentStep` pointed at the failed step, so the
|
|
235
|
+
* driver advances forward from there and never re-issues the completed steps'
|
|
236
|
+
* work. Mirrors {@link BootstrapService.retry}; both are reached via the unified
|
|
237
|
+
* `POST /agent-runs/:id/retry` endpoint.
|
|
238
|
+
*/
|
|
239
|
+
async retry(workspaceId, executionId,
|
|
240
|
+
/** The retrying user (their personal subscription is used for individual-usage
|
|
241
|
+
* models). Falls back to the original initiator when omitted. */
|
|
242
|
+
initiatedBy,
|
|
243
|
+
/** Mint the per-run personal-credential activation (see {@link start}). */
|
|
244
|
+
activate) {
|
|
245
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
246
|
+
const previous = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
|
|
247
|
+
if (previous.status !== 'failed') {
|
|
248
|
+
throw new ConflictError(`Only a failed run can be retried (run is '${previous.status}').`, 'run_not_retryable', { status: previous.status });
|
|
249
|
+
}
|
|
250
|
+
const block = await this.deps.requireBlock(workspaceId, previous.blockId);
|
|
251
|
+
// Run the SAME config/resource preconditions start() does (shape, frame type, tester infra,
|
|
252
|
+
// binary storage, agent backend, provider/preset satisfiability, budget), so a retry can't
|
|
253
|
+
// silently proceed on a config a fresh start would refuse — the drift that let a
|
|
254
|
+
// subscription-only preset fail mid-run against the routing default. Validated over the
|
|
255
|
+
// STORED steps (what the retry actually re-drives), not the current pipeline definition, so
|
|
256
|
+
// an out-of-band pipeline edit can't skew the gate and a deleted pipeline needs no special
|
|
257
|
+
// case. Before any side effects.
|
|
258
|
+
await this.deps.admission.assertRunnable(workspaceId, block, this.deps.admission.runnableShapeOf(previous.steps), initiatedBy ?? previous.initiatedBy);
|
|
259
|
+
const { steps, currentStep } = planResumedSteps(previous);
|
|
260
|
+
// Mint the activation before replacing the failed run, so a bad password aborts
|
|
261
|
+
// the retry without losing the retryable terminal run.
|
|
262
|
+
const newId = this.deps.idGenerator.next('exec');
|
|
263
|
+
const replaceId = previous.id;
|
|
264
|
+
await activate?.(newId);
|
|
265
|
+
// Replace the terminal failed run for this block with the resumed one (single run per
|
|
266
|
+
// block, matching the board's by-block projection). This mints a FRESH run id; the
|
|
267
|
+
// atomic `claimLiveRunOrConflict` below replaces `previous` (via `replaceId`) and clears
|
|
268
|
+
// any terminal rows in the SAME transaction, so a concurrent double-retry is serialised by
|
|
269
|
+
// the live-run index (the loser gets a 409) instead of both deleting-then-inserting.
|
|
270
|
+
const instance = buildResumedInstance({
|
|
271
|
+
previous,
|
|
272
|
+
id: newId,
|
|
273
|
+
plan: { steps, currentStep },
|
|
274
|
+
initiatedBy,
|
|
275
|
+
now: this.deps.clock.now(),
|
|
276
|
+
});
|
|
277
|
+
await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, replaceId);
|
|
278
|
+
const done = steps.filter((s) => s.state === 'done').length;
|
|
279
|
+
await this.deps.blockRepository.update(workspaceId, previous.blockId, {
|
|
280
|
+
status: 'in_progress',
|
|
281
|
+
progress: steps.length > 0 ? done / steps.length : 0,
|
|
282
|
+
executionId: instance.id,
|
|
283
|
+
});
|
|
284
|
+
await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
|
|
285
|
+
return instance;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Restart a run from a human-chosen step: re-run from `fromStepIndex` onward,
|
|
289
|
+
* regardless of how far the run had progressed (a `done`, `failed`, `blocked`,
|
|
290
|
+
* `paused` or still-`running` run are all valid sources). Unlike {@link retry}
|
|
291
|
+
* (which resumes at the first FAILURE) this rewinds to an arbitrary step the user
|
|
292
|
+
* picked — so it can re-run steps that already completed.
|
|
293
|
+
*
|
|
294
|
+
* What is preserved vs reset:
|
|
295
|
+
* - Steps BEFORE `fromStepIndex` keep their `output`/approval/timing untouched, so
|
|
296
|
+
* the engine still hands the restarted step its predecessors' work as
|
|
297
|
+
* `priorOutputs` (and their resolved `decisions`) — a useful handoff.
|
|
298
|
+
* - The chosen step and every later one are reset to a clean, re-runnable state,
|
|
299
|
+
* dropping each step's iteration counters (companion attempts, gate/test attempts,
|
|
300
|
+
* eviction recoveries) so the restart starts those loops from zero.
|
|
301
|
+
* - A block's incorporated requirements are NOT touched: they live on the
|
|
302
|
+
* requirement-review record, so a restarted spec-writer/coder still receives the
|
|
303
|
+
* incorporated document (or the base description when none was generated). When the
|
|
304
|
+
* chosen step is the `requirements-review` gate ITSELF, re-running it mints a fresh
|
|
305
|
+
* iteration-1 review (the reviewer's `review()` replaces the prior one), which is
|
|
306
|
+
* exactly the "reset the iterations counter from this step" semantics.
|
|
307
|
+
*
|
|
308
|
+
* Like {@link retry} a fresh instance id is minted (the durable runner addresses one
|
|
309
|
+
* driver per execution id). Any still-live driver/container for the run being
|
|
310
|
+
* replaced is torn down first, so restarting a RUNNING run never orphans a container
|
|
311
|
+
* or a parked Workflows instance.
|
|
312
|
+
*/
|
|
313
|
+
async restartFromStep(workspaceId, executionId, fromStepIndex,
|
|
314
|
+
/** The restarting user (their personal subscription is used for individual-usage
|
|
315
|
+
* models). Falls back to the original initiator when omitted. */
|
|
316
|
+
initiatedBy,
|
|
317
|
+
/** Mint the per-run personal-credential activation (see {@link start}). */
|
|
318
|
+
activate) {
|
|
319
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
320
|
+
const previous = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
|
|
321
|
+
const block = await this.deps.requireBlock(workspaceId, previous.blockId);
|
|
322
|
+
if (!Number.isInteger(fromStepIndex) ||
|
|
323
|
+
fromStepIndex < 0 ||
|
|
324
|
+
fromStepIndex >= previous.steps.length) {
|
|
325
|
+
throw new ValidationError(`Step ${fromStepIndex} is out of range for this run (it has ${previous.steps.length} step(s)).`);
|
|
326
|
+
}
|
|
327
|
+
// Run the SAME config/resource preconditions start()/retry() do, over the STORED steps this
|
|
328
|
+
// restart re-drives (frame type, tester infra, binary storage, agent backend, provider/preset
|
|
329
|
+
// satisfiability, budget). A restart re-dispatches provider-bearing steps just like a retry,
|
|
330
|
+
// so it must be gated identically — otherwise a run whose preset can't run every step (e.g. a
|
|
331
|
+
// subscription-only model an inline reviewer can't drive) strands mid-run instead of being
|
|
332
|
+
// refused up front. Before any teardown/side effects.
|
|
333
|
+
await this.deps.admission.assertRunnable(workspaceId, block, this.deps.admission.runnableShapeOf(previous.steps), initiatedBy ?? previous.initiatedBy);
|
|
334
|
+
// Tear down whatever was driving the run we're about to replace — its per-run
|
|
335
|
+
// container AND its durable driver — before minting the restart. A `done`/`failed`
|
|
336
|
+
// run is already terminal (a no-op teardown), but a still-`running` run would
|
|
337
|
+
// otherwise leak a container and a live Workflows/pg-boss driver.
|
|
338
|
+
await this.deps.runStateMachine.stopRunContainer(workspaceId, previous);
|
|
339
|
+
await this.deps.workRunner.cancelRun(workspaceId, executionId);
|
|
340
|
+
const { steps, currentStep } = planRestartFromStep(previous, fromStepIndex);
|
|
341
|
+
// Mint the activation before replacing the prior run, so a bad password aborts the
|
|
342
|
+
// restart without losing the source run.
|
|
343
|
+
const newId = this.deps.idGenerator.next('exec');
|
|
344
|
+
const replaceId = previous.id;
|
|
345
|
+
await activate?.(newId);
|
|
346
|
+
// Like retry(), this mints a FRESH run id. `claimLiveRunOrConflict` atomically supersedes
|
|
347
|
+
// the torn-down source run (`replaceId`, which here may still be LIVE — running/paused/
|
|
348
|
+
// blocked) and clears terminal rows in one transaction, so a concurrent start that already
|
|
349
|
+
// created a NEW live run for the block loses (409) instead of being silently clobbered.
|
|
350
|
+
const instance = buildResumedInstance({
|
|
351
|
+
previous,
|
|
352
|
+
id: newId,
|
|
353
|
+
plan: { steps, currentStep },
|
|
354
|
+
initiatedBy,
|
|
355
|
+
now: this.deps.clock.now(),
|
|
356
|
+
});
|
|
357
|
+
await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, replaceId);
|
|
358
|
+
const done = steps.filter((s) => s.state === 'done').length;
|
|
359
|
+
await this.deps.blockRepository.update(workspaceId, previous.blockId, {
|
|
360
|
+
status: 'in_progress',
|
|
361
|
+
progress: steps.length > 0 ? done / steps.length : 0,
|
|
362
|
+
executionId: instance.id,
|
|
363
|
+
});
|
|
364
|
+
await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
|
|
365
|
+
return instance;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* The bound callbacks the two run-start funnels (`runStart.ts`) need, so they depend on no
|
|
369
|
+
* concrete repository or service. Those funnels own the ORDER between a run's atomic claim and
|
|
370
|
+
* its hand-off and are documented there; every start path calls both, writing the block state
|
|
371
|
+
* that path owns in between.
|
|
372
|
+
*/
|
|
373
|
+
get runStartDeps() {
|
|
374
|
+
return {
|
|
375
|
+
insertLive: (ws, instance, options) => this.deps.executionRepository.insertLive(ws, instance, options),
|
|
376
|
+
startRun: (ws, id) => this.deps.workRunner.startRun(ws, id),
|
|
377
|
+
emitInstance: (ws, instance) => this.deps.runStateMachine.emitInstance(ws, instance),
|
|
378
|
+
publishRunStarted: (ws, instance, block) => this.deps.runStateMachine.publishRunStarted(ws, instance, block),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Resume every run paused by the spend safeguard in this workspace. Flips them
|
|
383
|
+
* back to `running` and re-drives the durable runner. If the budget is still
|
|
384
|
+
* exhausted the spend gate will simply pause them again on their next step.
|
|
385
|
+
*/
|
|
386
|
+
async resumePaused(workspaceId) {
|
|
387
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
388
|
+
// Lean projection: only the paused runs' ids are needed to re-drive them — no `detail` decode.
|
|
389
|
+
const live = await this.deps.executionRepository.listLive(workspaceId);
|
|
390
|
+
const paused = live.filter((e) => e.status === 'paused');
|
|
391
|
+
for (const p of paused) {
|
|
392
|
+
// Optimistic-concurrency write: only flip + re-drive a run that is STILL paused at
|
|
393
|
+
// write time, so a resume racing the driver (or a concurrent resume) can't clobber a
|
|
394
|
+
// run another writer already advanced. A vanished/contended run is skipped (the next
|
|
395
|
+
// sweep retries) rather than failing the whole batch.
|
|
396
|
+
let flipped = false;
|
|
397
|
+
const resumed = await this.deps.runStateMachine
|
|
398
|
+
.mutateInstance(workspaceId, p.id, (inst) => {
|
|
399
|
+
flipped = inst.status === 'paused';
|
|
400
|
+
if (flipped)
|
|
401
|
+
inst.status = 'running';
|
|
402
|
+
})
|
|
403
|
+
.catch(() => null);
|
|
404
|
+
if (resumed && flipped) {
|
|
405
|
+
// `startRun` re-drives runners that re-create the run from scratch (pg-boss re-enqueues
|
|
406
|
+
// the same id). On Cloudflare the paused run's Workflows instance is still ALIVE parked
|
|
407
|
+
// on a `waitForEvent`, so `startRun`'s `create` no-ops there; `signalResume` delivers the
|
|
408
|
+
// event that wakes it immediately instead of waiting out the periodic budget re-check.
|
|
409
|
+
await this.deps.workRunner.startRun(workspaceId, resumed.id);
|
|
410
|
+
await this.deps.workRunner.signalResume?.(workspaceId, resumed.id);
|
|
411
|
+
await this.deps.runStateMachine.emitInstance(workspaceId, resumed);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Clear the workspace-scoped `budget_paused` card now the pause is being lifted (F3). If the
|
|
415
|
+
// budget is still exhausted a resumed run re-pauses and re-raises it on its next step.
|
|
416
|
+
await this.deps.runStateMachine.clearBudgetPaused(workspaceId);
|
|
417
|
+
return this.deps.executionRepository.listByWorkspace(workspaceId);
|
|
418
|
+
}
|
|
419
|
+
/** Cancel the run on a block, returning it to `planned`. */
|
|
420
|
+
async cancel(workspaceId, blockId) {
|
|
421
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
422
|
+
await this.deps.requireBlock(workspaceId, blockId);
|
|
423
|
+
// Tear down the durable run (if any) AND its per-run container before removing
|
|
424
|
+
// the record, so a cancel never leaves a container running until its watchdog.
|
|
425
|
+
const existing = await this.deps.executionRepository.getByBlock(workspaceId, blockId);
|
|
426
|
+
if (existing) {
|
|
427
|
+
await this.deps.runStateMachine.stopRunContainer(workspaceId, existing);
|
|
428
|
+
await this.deps.workRunner.cancelRun(workspaceId, existing.id);
|
|
429
|
+
}
|
|
430
|
+
await this.deps.executionRepository.deleteByBlock(workspaceId, blockId);
|
|
431
|
+
await this.deps.blockRepository.update(workspaceId, blockId, {
|
|
432
|
+
status: 'planned',
|
|
433
|
+
progress: 0,
|
|
434
|
+
executionId: null,
|
|
435
|
+
});
|
|
436
|
+
// The run record is gone and the block is back to planned; the client can't
|
|
437
|
+
// reconstruct that from a per-instance event, so signal a coarse refresh. Name the block
|
|
438
|
+
// so the refresh fans out to every board mounting its shared service.
|
|
439
|
+
await this.deps.events.boardChanged(workspaceId, 'cancel', blockId);
|
|
440
|
+
return this.deps.requireBlock(workspaceId, blockId);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Explicitly stop a *running* run by id (the unified `POST /agent-runs/:id/stop`
|
|
444
|
+
* surface): kill its per-run container, tear down the durable driver, then record
|
|
445
|
+
* a terminal `cancelled` failure so the board shows the run stopped (with retry)
|
|
446
|
+
* rather than spinning forever. Idempotent — a run already terminal is returned
|
|
447
|
+
* as-is. `opts.reason`/`opts.kind` let the orphan sweep reuse this with its own
|
|
448
|
+
* wording instead of the user-facing default.
|
|
449
|
+
*/
|
|
450
|
+
async stopRun(workspaceId, executionId, opts = {}) {
|
|
451
|
+
await this.deps.requireWorkspace(workspaceId);
|
|
452
|
+
const instance = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
|
|
453
|
+
if (instance.status === 'failed' || instance.status === 'done')
|
|
454
|
+
return instance;
|
|
455
|
+
await this.deps.runStateMachine.stopRunContainer(workspaceId, instance);
|
|
456
|
+
await this.deps.workRunner.cancelRun(workspaceId, executionId);
|
|
457
|
+
await this.deps.failRun(workspaceId, executionId, opts.reason ?? 'Stopped by the user.', opts.kind ?? 'cancelled');
|
|
458
|
+
return assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Tear down every run under a block subtree — kill each container, terminate each
|
|
462
|
+
* durable driver, and delete the run record — so deleting a service/module never
|
|
463
|
+
* orphans a container or a Workflows instance. Best-effort and silent: the board
|
|
464
|
+
* delete that follows emits the coarse refresh, so no per-run event is needed.
|
|
465
|
+
*
|
|
466
|
+
* Returns the workspace block list it loaded so the immediately-following `removeBlock`
|
|
467
|
+
* can reuse it instead of re-listing the whole board (this teardown deletes only run
|
|
468
|
+
* records, never blocks, so the list is still current) — see {@link PreloadedBlocks}.
|
|
469
|
+
*/
|
|
470
|
+
async teardownForBlockTree(workspaceId, rootId) {
|
|
471
|
+
const blocks = await this.deps.blockRepository.listByWorkspace(workspaceId);
|
|
472
|
+
// Resolve every run in one query and index by block id, rather than a per-block
|
|
473
|
+
// getByBlock (N+1) over the whole subtree.
|
|
474
|
+
const runsByBlock = new Map((await this.deps.executionRepository.listByWorkspace(workspaceId)).map((run) => [
|
|
475
|
+
run.blockId,
|
|
476
|
+
run,
|
|
477
|
+
]));
|
|
478
|
+
for (const blockId of descendantIds(blocks, rootId)) {
|
|
479
|
+
const run = runsByBlock.get(blockId);
|
|
480
|
+
if (!run)
|
|
481
|
+
continue;
|
|
482
|
+
await this.deps.runStateMachine.stopRunContainer(workspaceId, run);
|
|
483
|
+
await this.deps.workRunner.cancelRun(workspaceId, run.id);
|
|
484
|
+
await this.deps.executionRepository.deleteByBlock(workspaceId, blockId);
|
|
485
|
+
}
|
|
486
|
+
return { workspaceId, blocks };
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
//# sourceMappingURL=RunLifecycleController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunLifecycleController.js","sourceRoot":"","sources":["../../../src/modules/execution/RunLifecycleController.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Block, ModelProvider, ModelProviderResolver, ModelRef } from '@cat-factory/kernel';
|
|
2
2
|
import { type ResolveBlockRunContext } from '../../inlineScope.js';
|
|
3
|
+
import { type InlineBlockModelDeps } from '../../inlineBlockModel.js';
|
|
3
4
|
import type { TestReport } from '@cat-factory/contracts';
|
|
4
5
|
import { type TesterQualityOutcome } from './testerQuality.logic.js';
|
|
5
6
|
/**
|
|
@@ -26,12 +27,15 @@ export interface TesterQualityReviewDeps {
|
|
|
26
27
|
modelProvider?: ModelProvider;
|
|
27
28
|
/** Default model ref when the block pins none — the agents' routing default. */
|
|
28
29
|
modelRef?: ModelRef;
|
|
29
|
-
/** Resolve a block's selected model id to a ref
|
|
30
|
-
resolveBlockModel?:
|
|
30
|
+
/** Resolve a block's selected model id to a ref, under the preset's route order. */
|
|
31
|
+
resolveBlockModel?: InlineBlockModelDeps['resolveBlockModel'];
|
|
31
32
|
/** Keep an ambient-eligible harness ref inline (local mode) instead of degrading it. */
|
|
32
33
|
runsInline?: (ref: ModelRef) => boolean;
|
|
33
|
-
/**
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The workspace's per-kind default MODEL and the ROUTE order the preset in force states, from
|
|
36
|
+
* ONE read. Absent ⇒ block pin plus the routing default, on the deployment's default order.
|
|
37
|
+
*/
|
|
38
|
+
resolvePresetRouting?: InlineBlockModelDeps['resolvePresetRouting'];
|
|
35
39
|
/** Resolve the block's run/execution + initiator, folded into the inline model scope. */
|
|
36
40
|
resolveRunContext?: ResolveBlockRunContext;
|
|
37
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TesterQualityReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEhG,OAAO,EAAE,KAAK,sBAAsB,EAAoB,MAAM,sBAAsB,CAAA;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAIxD,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CACN,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC3E;AAED,6FAA6F;AAC7F,MAAM,WAAW,uBAAuB;IACtC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"TesterQualityReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEhG,OAAO,EAAE,KAAK,sBAAsB,EAAoB,MAAM,sBAAsB,CAAA;AACpF,OAAO,EAAE,KAAK,oBAAoB,EAA8B,MAAM,2BAA2B,CAAA;AACjG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAIxD,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CACN,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC3E;AAED,6FAA6F;AAC7F,MAAM,WAAW,uBAAuB;IACtC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,oBAAoB,CAAC,mBAAmB,CAAC,CAAA;IAC7D,wFAAwF;IACxF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IACvC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;IACnE,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,sBAAsB,CAAA;CAC3C;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,uBAAuB,EAAI;IAE9D,OAAO,CAAC,QAAQ;IAIV,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAyCzE;CACF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveScopedModelProvider } from '@cat-factory/kernel';
|
|
2
2
|
import { scopeForBlockRun } from '../../inlineScope.js';
|
|
3
|
+
import { resolveInlineBlockModelRef } from '../../inlineBlockModel.js';
|
|
3
4
|
import { TESTER_QC_AGENT_KIND } from '@cat-factory/contracts';
|
|
4
5
|
import { generateText } from 'ai';
|
|
5
6
|
import { catFactoryObservability, TESTER_QC_SYSTEM_PROMPT } from '@cat-factory/agents';
|
|
@@ -16,18 +17,8 @@ export class TesterQualityReviewService {
|
|
|
16
17
|
constructor(deps) {
|
|
17
18
|
this.deps = deps;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const runsInline = this.deps.runsInline;
|
|
22
|
-
const resolve = (ref) => inlineModelRef(ref, fallback ?? ref, runsInline ? { runsInline } : {});
|
|
23
|
-
const fromBlock = this.deps.resolveBlockModel?.(block.modelId);
|
|
24
|
-
if (fromBlock)
|
|
25
|
-
return resolve(fromBlock);
|
|
26
|
-
const defaultId = await this.deps.resolveWorkspaceModelDefault?.(workspaceId, TESTER_QC_AGENT_KIND, block.modelPresetId);
|
|
27
|
-
const fromDefault = this.deps.resolveBlockModel?.(defaultId);
|
|
28
|
-
if (fromDefault)
|
|
29
|
-
return resolve(fromDefault);
|
|
30
|
-
return fallback;
|
|
20
|
+
modelFor(workspaceId, block) {
|
|
21
|
+
return resolveInlineBlockModelRef(this.deps, workspaceId, TESTER_QC_AGENT_KIND, block);
|
|
31
22
|
}
|
|
32
23
|
async evaluate(workspaceId, block, report) {
|
|
33
24
|
const scope = await scopeForBlockRun(workspaceId, block, this.deps.resolveRunContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TesterQualityReviewService.js","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"TesterQualityReviewService.js","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAA+B,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,EAA6B,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AAEjG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,EAEL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA;AAyCjC;;;;;;GAMG;AACH,MAAM,OAAO,0BAA0B;IACR,IAAI;IAAjC,YAA6B,IAA6B;oBAA7B,IAAI;IAA4B,CAAC;IAEtD,QAAQ,CAAC,WAAmB,EAAE,KAAY;QAChD,OAAO,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAA;IACxF,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,WAAmB,EACnB,KAAY,EACZ,MAAkB;QAElB,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACrF,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACxE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACnD,0FAA0F;QAC1F,IAAI,CAAC,aAAa,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QACvC,IAAI,KAA2C,CAAA;QAC/C,IAAI,CAAC;YACH,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;YACtF,sFAAsF;YACtF,wFAAwF;YACxF,sFAAsF;YACtF,6DAA6D;YAC7D,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;gBAChC,KAAK;gBACL,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,wBAAwB,CAAC;oBAC/B,SAAS,EAAE,KAAK,CAAC,KAAK;oBACtB,eAAe,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;oBACxC,MAAM;iBACP,CAAC;gBACF,WAAW,EAAE,GAAG;gBAChB,eAAe,EAAE,IAAI;gBACrB,eAAe,EAAE,uBAAuB,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;aAC3F,CAAC,CAAA;YACF,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;YACtF,6EAA6E;YAC7E,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO;YACL,OAAO,EAAE,0BAA0B,CAAC,IAAI,CAAC;YACzC,KAAK,EAAE,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,EAAE;SACtC,CAAA;IACH,CAAC;CACF"}
|