@mcoda/core 0.1.8 → 0.1.11
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/CHANGELOG.md +3 -0
- package/README.md +2 -2
- package/dist/api/AgentsApi.d.ts +9 -1
- package/dist/api/AgentsApi.d.ts.map +1 -1
- package/dist/api/AgentsApi.js +201 -6
- package/dist/api/QaTasksApi.d.ts.map +1 -1
- package/dist/api/QaTasksApi.js +6 -0
- package/dist/api/TasksApi.d.ts.map +1 -1
- package/dist/api/TasksApi.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/prompts/PdrPrompts.d.ts.map +1 -1
- package/dist/prompts/PdrPrompts.js +9 -1
- package/dist/prompts/SdsPrompts.d.ts.map +1 -1
- package/dist/prompts/SdsPrompts.js +9 -0
- package/dist/services/agents/AgentRatingFormula.d.ts +27 -0
- package/dist/services/agents/AgentRatingFormula.d.ts.map +1 -0
- package/dist/services/agents/AgentRatingFormula.js +45 -0
- package/dist/services/agents/AgentRatingService.d.ts +60 -0
- package/dist/services/agents/AgentRatingService.d.ts.map +1 -0
- package/dist/services/agents/AgentRatingService.js +363 -0
- package/dist/services/agents/GatewayAgentService.d.ts +11 -0
- package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
- package/dist/services/agents/GatewayAgentService.js +525 -84
- package/dist/services/agents/GatewayHandoff.d.ts +11 -0
- package/dist/services/agents/GatewayHandoff.d.ts.map +1 -0
- package/dist/services/agents/GatewayHandoff.js +141 -0
- package/dist/services/agents/RoutingService.d.ts +1 -0
- package/dist/services/agents/RoutingService.d.ts.map +1 -1
- package/dist/services/agents/RoutingService.js +4 -4
- package/dist/services/backlog/BacklogService.d.ts +23 -0
- package/dist/services/backlog/BacklogService.d.ts.map +1 -1
- package/dist/services/backlog/BacklogService.js +62 -7
- package/dist/services/backlog/TaskOrderingHeuristics.d.ts +12 -0
- package/dist/services/backlog/TaskOrderingHeuristics.d.ts.map +1 -0
- package/dist/services/backlog/TaskOrderingHeuristics.js +56 -0
- package/dist/services/backlog/TaskOrderingService.d.ts +17 -4
- package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
- package/dist/services/backlog/TaskOrderingService.js +538 -79
- package/dist/services/docs/DocInventory.d.ts +11 -0
- package/dist/services/docs/DocInventory.d.ts.map +1 -0
- package/dist/services/docs/DocInventory.js +230 -0
- package/dist/services/docs/DocgenRunContext.d.ts +59 -0
- package/dist/services/docs/DocgenRunContext.d.ts.map +1 -0
- package/dist/services/docs/DocgenRunContext.js +4 -0
- package/dist/services/docs/DocsService.d.ts +70 -3
- package/dist/services/docs/DocsService.d.ts.map +1 -1
- package/dist/services/docs/DocsService.js +1930 -89
- package/dist/services/docs/alignment/DocAlignmentGraph.d.ts +23 -0
- package/dist/services/docs/alignment/DocAlignmentGraph.d.ts.map +1 -0
- package/dist/services/docs/alignment/DocAlignmentGraph.js +78 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts +19 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts.map +1 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.js +222 -0
- package/dist/services/docs/patch/DocPatchEngine.d.ts +57 -0
- package/dist/services/docs/patch/DocPatchEngine.d.ts.map +1 -0
- package/dist/services/docs/patch/DocPatchEngine.js +331 -0
- package/dist/services/docs/review/Glossary.d.ts +16 -0
- package/dist/services/docs/review/Glossary.d.ts.map +1 -0
- package/dist/services/docs/review/Glossary.js +47 -0
- package/dist/services/docs/review/ReviewReportRenderer.d.ts +3 -0
- package/dist/services/docs/review/ReviewReportRenderer.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewReportRenderer.js +133 -0
- package/dist/services/docs/review/ReviewReportSchema.d.ts +39 -0
- package/dist/services/docs/review/ReviewReportSchema.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewReportSchema.js +47 -0
- package/dist/services/docs/review/ReviewTypes.d.ts +76 -0
- package/dist/services/docs/review/ReviewTypes.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewTypes.js +94 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts +7 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.js +93 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts +7 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.js +308 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts +8 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.js +278 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts +8 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.js +487 -0
- package/dist/services/docs/review/gates/NoMaybesGate.d.ts +8 -0
- package/dist/services/docs/review/gates/NoMaybesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/NoMaybesGate.js +145 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.js +266 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.js +59 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.js +200 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts +7 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.js +159 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts +8 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.js +129 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts +7 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.js +169 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts +10 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.js +261 -0
- package/dist/services/docs/review/gates/RfpConsentGate.d.ts +6 -0
- package/dist/services/docs/review/gates/RfpConsentGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/RfpConsentGate.js +127 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts +7 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.js +173 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.js +196 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.js +89 -0
- package/dist/services/docs/review/gates/SdsOpsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsOpsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsOpsGate.js +162 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.js +166 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.js +273 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.js +203 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts +9 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.js +217 -0
- package/dist/services/docs/review/glossary.json +47 -0
- package/dist/services/estimate/EstimateService.d.ts +2 -0
- package/dist/services/estimate/EstimateService.d.ts.map +1 -1
- package/dist/services/estimate/EstimateService.js +66 -18
- package/dist/services/estimate/VelocityService.d.ts +4 -0
- package/dist/services/estimate/VelocityService.d.ts.map +1 -1
- package/dist/services/estimate/VelocityService.js +179 -36
- package/dist/services/estimate/types.d.ts +1 -0
- package/dist/services/estimate/types.d.ts.map +1 -1
- package/dist/services/execution/GatewayTrioService.d.ts +200 -0
- package/dist/services/execution/GatewayTrioService.d.ts.map +1 -0
- package/dist/services/execution/GatewayTrioService.js +2492 -0
- package/dist/services/execution/QaApiRunner.d.ts +30 -0
- package/dist/services/execution/QaApiRunner.d.ts.map +1 -0
- package/dist/services/execution/QaApiRunner.js +881 -0
- package/dist/services/execution/QaFollowupService.d.ts +2 -0
- package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
- package/dist/services/execution/QaFollowupService.js +9 -2
- package/dist/services/execution/QaPlanValidator.d.ts +10 -0
- package/dist/services/execution/QaPlanValidator.d.ts.map +1 -0
- package/dist/services/execution/QaPlanValidator.js +128 -0
- package/dist/services/execution/QaProfileService.d.ts +27 -1
- package/dist/services/execution/QaProfileService.d.ts.map +1 -1
- package/dist/services/execution/QaProfileService.js +354 -7
- package/dist/services/execution/QaTasksService.d.ts +59 -1
- package/dist/services/execution/QaTasksService.d.ts.map +1 -1
- package/dist/services/execution/QaTasksService.js +3347 -318
- package/dist/services/execution/QaTestCommandBuilder.d.ts +51 -0
- package/dist/services/execution/QaTestCommandBuilder.d.ts.map +1 -0
- package/dist/services/execution/QaTestCommandBuilder.js +495 -0
- package/dist/services/execution/TaskSelectionService.d.ts +4 -2
- package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
- package/dist/services/execution/TaskSelectionService.js +144 -28
- package/dist/services/execution/TaskStateService.d.ts +19 -6
- package/dist/services/execution/TaskStateService.d.ts.map +1 -1
- package/dist/services/execution/TaskStateService.js +128 -13
- package/dist/services/execution/WorkOnTasksService.d.ts +32 -1
- package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
- package/dist/services/execution/WorkOnTasksService.js +4667 -722
- package/dist/services/jobs/JobInsightsService.d.ts +4 -0
- package/dist/services/jobs/JobInsightsService.d.ts.map +1 -1
- package/dist/services/jobs/JobInsightsService.js +51 -5
- package/dist/services/jobs/JobResumeService.d.ts.map +1 -1
- package/dist/services/jobs/JobResumeService.js +23 -10
- package/dist/services/jobs/JobService.d.ts +56 -4
- package/dist/services/jobs/JobService.d.ts.map +1 -1
- package/dist/services/jobs/JobService.js +232 -1
- package/dist/services/openapi/OpenApiService.d.ts +51 -0
- package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
- package/dist/services/openapi/OpenApiService.js +953 -106
- package/dist/services/planning/CreateTasksService.d.ts +21 -0
- package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
- package/dist/services/planning/CreateTasksService.js +569 -31
- package/dist/services/planning/RefineTasksService.d.ts +9 -0
- package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
- package/dist/services/planning/RefineTasksService.js +409 -59
- package/dist/services/review/CodeReviewService.d.ts +18 -0
- package/dist/services/review/CodeReviewService.d.ts.map +1 -1
- package/dist/services/review/CodeReviewService.js +1309 -167
- package/dist/services/review/ReviewNormalizer.d.ts +9 -0
- package/dist/services/review/ReviewNormalizer.d.ts.map +1 -0
- package/dist/services/review/ReviewNormalizer.js +147 -0
- package/dist/services/shared/AuthErrors.d.ts +3 -0
- package/dist/services/shared/AuthErrors.d.ts.map +1 -0
- package/dist/services/shared/AuthErrors.js +17 -0
- package/dist/services/shared/DocdexGuidance.d.ts +7 -0
- package/dist/services/shared/DocdexGuidance.d.ts.map +1 -0
- package/dist/services/shared/DocdexGuidance.js +12 -0
- package/dist/services/shared/ProjectGuidance.d.ts +17 -0
- package/dist/services/shared/ProjectGuidance.d.ts.map +1 -0
- package/dist/services/shared/ProjectGuidance.js +78 -0
- package/dist/services/system/ToolDenylist.d.ts +13 -0
- package/dist/services/system/ToolDenylist.d.ts.map +1 -0
- package/dist/services/system/ToolDenylist.js +85 -0
- package/dist/services/tasks/TaskCommentFormatter.d.ts +20 -0
- package/dist/services/tasks/TaskCommentFormatter.d.ts.map +1 -0
- package/dist/services/tasks/TaskCommentFormatter.js +54 -0
- package/dist/services/telemetry/TelemetryService.d.ts.map +1 -1
- package/dist/services/telemetry/TelemetryService.js +39 -7
- package/dist/workspace/WorkspaceManager.d.ts +26 -0
- package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
- package/dist/workspace/WorkspaceManager.js +206 -32
- package/package.json +6 -5
|
@@ -4,7 +4,41 @@ import { promises as fs } from "node:fs";
|
|
|
4
4
|
import { PathHelper } from "@mcoda/shared";
|
|
5
5
|
import { WorkspaceRepository, } from "@mcoda/db";
|
|
6
6
|
const nowIso = () => new Date().toISOString();
|
|
7
|
+
const TERMINAL_JOB_STATES = new Set(["completed", "failed", "cancelled", "partial"]);
|
|
7
8
|
export class JobService {
|
|
9
|
+
static ensureSignalHandlers() {
|
|
10
|
+
if (JobService.signalHandlersRegistered)
|
|
11
|
+
return;
|
|
12
|
+
if (process.env.MCODA_DISABLE_JOB_SIGNAL_HANDLERS === "1")
|
|
13
|
+
return;
|
|
14
|
+
JobService.signalHandlersRegistered = true;
|
|
15
|
+
const handler = (signal) => {
|
|
16
|
+
void JobService.handleProcessSignal(signal);
|
|
17
|
+
};
|
|
18
|
+
process.once("SIGINT", handler);
|
|
19
|
+
process.once("SIGTERM", handler);
|
|
20
|
+
process.once("SIGTSTP", handler);
|
|
21
|
+
}
|
|
22
|
+
static registerActiveJob(jobId, service, commandRunId) {
|
|
23
|
+
JobService.activeJobs.set(jobId, { service, commandRunId });
|
|
24
|
+
JobService.ensureSignalHandlers();
|
|
25
|
+
}
|
|
26
|
+
static unregisterActiveJob(jobId) {
|
|
27
|
+
JobService.activeJobs.delete(jobId);
|
|
28
|
+
}
|
|
29
|
+
static async cancelActiveJobs(signal) {
|
|
30
|
+
const active = Array.from(JobService.activeJobs.entries());
|
|
31
|
+
await Promise.all(active.map(async ([jobId, entry]) => entry.service.cancelJobOnSignal(jobId, entry.commandRunId, signal)));
|
|
32
|
+
}
|
|
33
|
+
static async handleProcessSignal(signal) {
|
|
34
|
+
if (JobService.handlingSignal)
|
|
35
|
+
return;
|
|
36
|
+
JobService.handlingSignal = true;
|
|
37
|
+
await JobService.cancelActiveJobs(signal);
|
|
38
|
+
const exitCode = signal === "SIGTERM" ? 143 : 130;
|
|
39
|
+
process.exitCode = exitCode;
|
|
40
|
+
process.exit(exitCode);
|
|
41
|
+
}
|
|
8
42
|
constructor(workspace, workspaceRepo, options = {}) {
|
|
9
43
|
this.workspaceRepo = workspaceRepo;
|
|
10
44
|
this.checkpointCounters = new Map();
|
|
@@ -14,12 +48,13 @@ export class JobService {
|
|
|
14
48
|
const resolvedRoot = typeof workspace === "string" ? workspace : workspace.workspaceRoot;
|
|
15
49
|
this.workspaceRoot = resolvedRoot;
|
|
16
50
|
this.workspaceId = typeof workspace === "string" ? resolvedRoot : workspace.workspaceId ?? resolvedRoot;
|
|
51
|
+
this.mcodaDirOverride = typeof workspace === "string" ? undefined : workspace.mcodaDir;
|
|
17
52
|
this.perRunTelemetryDisabled = options.noTelemetry ?? false;
|
|
18
53
|
this.envTelemetryDisabled = (process.env.MCODA_TELEMETRY ?? "").toLowerCase() === "off";
|
|
19
54
|
this.requireRepo = options.requireRepo ?? false;
|
|
20
55
|
}
|
|
21
56
|
get mcodaDir() {
|
|
22
|
-
return
|
|
57
|
+
return this.mcodaDirOverride ?? PathHelper.getWorkspaceDir(this.workspaceRoot);
|
|
23
58
|
}
|
|
24
59
|
get commandRunsPath() {
|
|
25
60
|
return path.join(this.mcodaDir, "command_runs.json");
|
|
@@ -67,6 +102,37 @@ export class JobService {
|
|
|
67
102
|
this.workspaceRepo = undefined;
|
|
68
103
|
}
|
|
69
104
|
}
|
|
105
|
+
async cancelJobOnSignal(jobId, commandRunId, signal) {
|
|
106
|
+
const reason = `Cancelled by ${signal}`;
|
|
107
|
+
try {
|
|
108
|
+
await this.ensureMcoda();
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// ignore workspace bootstrap failures during shutdown
|
|
112
|
+
}
|
|
113
|
+
if (this.workspaceRepo && "releaseTaskLocksByJob" in this.workspaceRepo) {
|
|
114
|
+
try {
|
|
115
|
+
await this.workspaceRepo.releaseTaskLocksByJob(jobId);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// ignore lock cleanup failures during shutdown
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
await this.updateJobStatus(jobId, "cancelled", { errorSummary: reason });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// ignore job status failures during shutdown
|
|
126
|
+
}
|
|
127
|
+
if (commandRunId) {
|
|
128
|
+
try {
|
|
129
|
+
await this.finishCommandRun(commandRunId, "cancelled", reason);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// ignore command run failures during shutdown
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
70
136
|
async readJsonArray(filePath) {
|
|
71
137
|
try {
|
|
72
138
|
const raw = await fs.readFile(filePath, "utf8");
|
|
@@ -104,6 +170,16 @@ export class JobService {
|
|
|
104
170
|
const jobs = await this.readJsonArray(this.jobsStorePath);
|
|
105
171
|
return jobs.find((j) => j.id === jobId);
|
|
106
172
|
}
|
|
173
|
+
async readManifest(jobId) {
|
|
174
|
+
const manifestPath = this.manifestPath(jobId);
|
|
175
|
+
try {
|
|
176
|
+
const raw = await fs.readFile(manifestPath, "utf8");
|
|
177
|
+
return JSON.parse(raw);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
107
183
|
async readCheckpoints(jobId) {
|
|
108
184
|
const dir = this.checkpointDir(jobId);
|
|
109
185
|
try {
|
|
@@ -207,6 +283,7 @@ export class JobService {
|
|
|
207
283
|
workspaceId: this.workspaceId,
|
|
208
284
|
projectKey,
|
|
209
285
|
jobId: options?.jobId,
|
|
286
|
+
agentId: options?.agentId,
|
|
210
287
|
taskIds: options?.taskIds,
|
|
211
288
|
gitBranch: options?.gitBranch,
|
|
212
289
|
gitBaseBranch: options?.gitBaseBranch,
|
|
@@ -219,6 +296,7 @@ export class JobService {
|
|
|
219
296
|
workspaceId: this.workspaceId,
|
|
220
297
|
commandName,
|
|
221
298
|
jobId: record.jobId,
|
|
299
|
+
agentId: record.agentId ?? null,
|
|
222
300
|
taskIds: record.taskIds,
|
|
223
301
|
gitBranch: record.gitBranch,
|
|
224
302
|
gitBaseBranch: record.gitBaseBranch,
|
|
@@ -261,6 +339,8 @@ export class JobService {
|
|
|
261
339
|
workspaceId: this.workspaceId,
|
|
262
340
|
projectKey,
|
|
263
341
|
payload: options.payload,
|
|
342
|
+
agentId: options.agentId,
|
|
343
|
+
agentIds: options.agentIds ?? (options.agentId ? [options.agentId] : undefined),
|
|
264
344
|
totalItems: options.totalItems,
|
|
265
345
|
processedItems: options.processedItems,
|
|
266
346
|
totalUnits: options.totalItems,
|
|
@@ -275,6 +355,8 @@ export class JobService {
|
|
|
275
355
|
state: "running",
|
|
276
356
|
commandName: record.commandName,
|
|
277
357
|
payload: options.payload,
|
|
358
|
+
agentId: record.agentId ?? null,
|
|
359
|
+
agentIds: record.agentIds ?? null,
|
|
278
360
|
totalItems: record.totalItems,
|
|
279
361
|
processedItems: record.processedItems,
|
|
280
362
|
});
|
|
@@ -287,6 +369,7 @@ export class JobService {
|
|
|
287
369
|
if (commandRunId) {
|
|
288
370
|
await this.attachCommandRunToJob(commandRunId, record.id);
|
|
289
371
|
}
|
|
372
|
+
JobService.registerActiveJob(record.id, this, commandRunId);
|
|
290
373
|
return record;
|
|
291
374
|
}
|
|
292
375
|
async attachCommandRunToJob(commandRunId, jobId) {
|
|
@@ -348,6 +431,110 @@ export class JobService {
|
|
|
348
431
|
payload: updated.payload,
|
|
349
432
|
});
|
|
350
433
|
}
|
|
434
|
+
if (state === "cancelled" && this.workspaceRepo && "releaseTaskLocksByJob" in this.workspaceRepo) {
|
|
435
|
+
try {
|
|
436
|
+
await this.workspaceRepo.releaseTaskLocksByJob(jobId);
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
// ignore lock cleanup failures during cancellation
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (TERMINAL_JOB_STATES.has(state)) {
|
|
443
|
+
JobService.unregisterActiveJob(jobId);
|
|
444
|
+
}
|
|
445
|
+
else if (state === "running") {
|
|
446
|
+
JobService.registerActiveJob(jobId, this, updated.commandRunId);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async computeElapsed(jobId) {
|
|
450
|
+
const job = await this.getJob(jobId);
|
|
451
|
+
if (!job?.createdAt)
|
|
452
|
+
return {};
|
|
453
|
+
const startedAt = Date.parse(job.createdAt);
|
|
454
|
+
if (Number.isNaN(startedAt))
|
|
455
|
+
return {};
|
|
456
|
+
const elapsedMs = Math.max(0, Date.now() - startedAt);
|
|
457
|
+
return { elapsedMs, elapsedSeconds: Math.round(elapsedMs / 1000) };
|
|
458
|
+
}
|
|
459
|
+
async recordJobProgress(jobId, input) {
|
|
460
|
+
const elapsed = await this.computeElapsed(jobId);
|
|
461
|
+
const payload = {
|
|
462
|
+
docgen_stage: input.stage,
|
|
463
|
+
docgen_status_message: input.message,
|
|
464
|
+
};
|
|
465
|
+
if (elapsed.elapsedMs !== undefined) {
|
|
466
|
+
payload.docgen_elapsed_ms = elapsed.elapsedMs;
|
|
467
|
+
payload.docgen_elapsed_seconds = elapsed.elapsedSeconds;
|
|
468
|
+
}
|
|
469
|
+
if (input.iteration) {
|
|
470
|
+
payload.docgen_iteration_current = input.iteration.current;
|
|
471
|
+
payload.docgen_iteration_max = input.iteration.max;
|
|
472
|
+
if (input.iteration.phase) {
|
|
473
|
+
payload.docgen_iteration_phase = input.iteration.phase;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (input.payload && Object.keys(input.payload).length > 0) {
|
|
477
|
+
Object.assign(payload, input.payload);
|
|
478
|
+
}
|
|
479
|
+
await this.updateJobStatus(jobId, "running", {
|
|
480
|
+
totalItems: input.totalItems,
|
|
481
|
+
processedItems: input.processedItems,
|
|
482
|
+
lastCheckpoint: input.stage,
|
|
483
|
+
jobStateDetail: input.message,
|
|
484
|
+
payload,
|
|
485
|
+
});
|
|
486
|
+
const checkpointDetails = { message: input.message };
|
|
487
|
+
if (elapsed.elapsedMs !== undefined) {
|
|
488
|
+
checkpointDetails.elapsedMs = elapsed.elapsedMs;
|
|
489
|
+
checkpointDetails.elapsedSeconds = elapsed.elapsedSeconds;
|
|
490
|
+
}
|
|
491
|
+
if (input.iteration) {
|
|
492
|
+
checkpointDetails.iteration = input.iteration;
|
|
493
|
+
}
|
|
494
|
+
if (input.details && Object.keys(input.details).length > 0) {
|
|
495
|
+
Object.assign(checkpointDetails, input.details);
|
|
496
|
+
}
|
|
497
|
+
await this.writeCheckpoint(jobId, {
|
|
498
|
+
stage: input.stage,
|
|
499
|
+
timestamp: nowIso(),
|
|
500
|
+
details: checkpointDetails,
|
|
501
|
+
});
|
|
502
|
+
if (input.heartbeat) {
|
|
503
|
+
const parts = [`[docgen heartbeat] ${input.message}`];
|
|
504
|
+
if (input.iteration) {
|
|
505
|
+
const phase = input.iteration.phase ? `:${input.iteration.phase}` : "";
|
|
506
|
+
parts.push(`iter=${input.iteration.current}/${input.iteration.max}${phase}`);
|
|
507
|
+
}
|
|
508
|
+
if (elapsed.elapsedSeconds !== undefined) {
|
|
509
|
+
parts.push(`elapsed=${elapsed.elapsedSeconds}s`);
|
|
510
|
+
}
|
|
511
|
+
await this.appendLog(jobId, `${parts.join(" ")}\n`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
async recordIterationProgress(jobId, input) {
|
|
515
|
+
const stage = `iteration_${input.current}_${input.phase}`;
|
|
516
|
+
const phaseLabel = input.phase === "recheck"
|
|
517
|
+
? "Re-check"
|
|
518
|
+
: input.phase === "review"
|
|
519
|
+
? "Review"
|
|
520
|
+
: input.phase === "patch"
|
|
521
|
+
? "Patch"
|
|
522
|
+
: input.phase;
|
|
523
|
+
const payload = {
|
|
524
|
+
iteration: { current: input.current, max: input.max, phase: input.phase },
|
|
525
|
+
};
|
|
526
|
+
if (input.details && Object.keys(input.details).length > 0) {
|
|
527
|
+
payload.iterationDetails = input.details;
|
|
528
|
+
}
|
|
529
|
+
await this.recordJobProgress(jobId, {
|
|
530
|
+
stage,
|
|
531
|
+
message: `${phaseLabel} iteration ${input.current}/${input.max}`,
|
|
532
|
+
iteration: { current: input.current, max: input.max, phase: input.phase },
|
|
533
|
+
details: input.details,
|
|
534
|
+
totalItems: input.max,
|
|
535
|
+
processedItems: input.current,
|
|
536
|
+
payload,
|
|
537
|
+
});
|
|
351
538
|
}
|
|
352
539
|
async writeCheckpoint(jobId, checkpoint) {
|
|
353
540
|
const dir = this.checkpointDir(jobId);
|
|
@@ -446,26 +633,67 @@ export class JobService {
|
|
|
446
633
|
projectId: entry.projectId ?? null,
|
|
447
634
|
epicId: entry.epicId ?? null,
|
|
448
635
|
userStoryId: entry.userStoryId ?? null,
|
|
636
|
+
commandName: entry.commandName ?? null,
|
|
637
|
+
action: entry.action ?? null,
|
|
638
|
+
invocationKind: entry.invocationKind ?? null,
|
|
639
|
+
provider: entry.provider ?? null,
|
|
640
|
+
currency: entry.currency ?? null,
|
|
449
641
|
tokensPrompt: entry.tokensPrompt ?? entry.promptTokens ?? null,
|
|
450
642
|
tokensCompletion: entry.tokensCompletion ?? entry.completionTokens ?? null,
|
|
451
643
|
tokensTotal: entry.tokensTotal ?? null,
|
|
644
|
+
tokensCached: entry.tokensCached ?? null,
|
|
645
|
+
tokensCacheRead: entry.tokensCacheRead ?? null,
|
|
646
|
+
tokensCacheWrite: entry.tokensCacheWrite ?? null,
|
|
452
647
|
costEstimate: entry.costEstimate ?? entry.costUsd ?? null,
|
|
453
648
|
durationSeconds: entry.durationSeconds ?? null,
|
|
649
|
+
durationMs: entry.durationMs ?? null,
|
|
650
|
+
startedAt: entry.startedAt ?? null,
|
|
651
|
+
finishedAt: entry.finishedAt ?? null,
|
|
454
652
|
timestamp: entry.timestamp,
|
|
455
653
|
metadata: {
|
|
456
654
|
...(entry.metadata ?? {}),
|
|
457
655
|
...(entry.commandName ? { commandName: entry.commandName } : {}),
|
|
458
656
|
...(entry.action ? { action: entry.action } : {}),
|
|
657
|
+
...(entry.invocationKind ? { invocationKind: entry.invocationKind } : {}),
|
|
658
|
+
...(entry.provider ? { provider: entry.provider } : {}),
|
|
659
|
+
...(entry.currency ? { currency: entry.currency } : {}),
|
|
459
660
|
},
|
|
460
661
|
};
|
|
461
662
|
const fileRecord = {
|
|
462
663
|
...normalized,
|
|
463
664
|
...(entry.commandName ? { commandName: entry.commandName } : {}),
|
|
464
665
|
...(entry.action ? { action: entry.action } : {}),
|
|
666
|
+
...(entry.invocationKind ? { invocationKind: entry.invocationKind } : {}),
|
|
667
|
+
...(entry.provider ? { provider: entry.provider } : {}),
|
|
668
|
+
...(entry.currency ? { currency: entry.currency } : {}),
|
|
669
|
+
...(entry.tokensCached !== undefined && entry.tokensCached !== null ? { tokensCached: entry.tokensCached } : {}),
|
|
670
|
+
...(entry.tokensCacheRead !== undefined && entry.tokensCacheRead !== null ? { tokensCacheRead: entry.tokensCacheRead } : {}),
|
|
671
|
+
...(entry.tokensCacheWrite !== undefined && entry.tokensCacheWrite !== null ? { tokensCacheWrite: entry.tokensCacheWrite } : {}),
|
|
672
|
+
...(entry.durationMs !== undefined && entry.durationMs !== null ? { durationMs: entry.durationMs } : {}),
|
|
673
|
+
...(entry.startedAt ? { startedAt: entry.startedAt } : {}),
|
|
674
|
+
...(entry.finishedAt ? { finishedAt: entry.finishedAt } : {}),
|
|
465
675
|
};
|
|
466
676
|
await this.appendJsonArray(this.tokenUsagePath, fileRecord);
|
|
467
677
|
if (this.workspaceRepo) {
|
|
468
678
|
await this.workspaceRepo.recordTokenUsage(normalized);
|
|
679
|
+
if (entry.agentId) {
|
|
680
|
+
if (entry.commandRunId) {
|
|
681
|
+
try {
|
|
682
|
+
await this.workspaceRepo.setCommandRunAgentId(entry.commandRunId, entry.agentId);
|
|
683
|
+
}
|
|
684
|
+
catch {
|
|
685
|
+
// ignore attribution failures
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (entry.jobId) {
|
|
689
|
+
try {
|
|
690
|
+
await this.workspaceRepo.setJobAgentIds(entry.jobId, entry.agentId);
|
|
691
|
+
}
|
|
692
|
+
catch {
|
|
693
|
+
// ignore attribution failures
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
469
697
|
}
|
|
470
698
|
}
|
|
471
699
|
async writeManifest(job, extras = {}) {
|
|
@@ -488,3 +716,6 @@ export class JobService {
|
|
|
488
716
|
}
|
|
489
717
|
}
|
|
490
718
|
}
|
|
719
|
+
JobService.activeJobs = new Map();
|
|
720
|
+
JobService.signalHandlersRegistered = false;
|
|
721
|
+
JobService.handlingSignal = false;
|
|
@@ -1,38 +1,79 @@
|
|
|
1
1
|
import { AgentService } from "@mcoda/agents";
|
|
2
2
|
import { DocdexClient } from "@mcoda/integrations";
|
|
3
|
+
import { GlobalRepository, WorkspaceRepository } from "@mcoda/db";
|
|
3
4
|
import { WorkspaceResolution } from "../../workspace/WorkspaceManager.js";
|
|
4
5
|
import { JobService } from "../jobs/JobService.js";
|
|
5
6
|
import { RoutingService } from "../agents/RoutingService.js";
|
|
7
|
+
import { AgentRatingService } from "../agents/AgentRatingService.js";
|
|
6
8
|
export interface GenerateOpenapiOptions {
|
|
7
9
|
workspace: WorkspaceResolution;
|
|
8
10
|
agentName?: string;
|
|
9
11
|
agentStream?: boolean;
|
|
12
|
+
rateAgents?: boolean;
|
|
10
13
|
force?: boolean;
|
|
11
14
|
dryRun?: boolean;
|
|
12
15
|
validateOnly?: boolean;
|
|
13
16
|
cliVersion: string;
|
|
14
17
|
onToken?: (token: string) => void;
|
|
15
18
|
projectKey?: string;
|
|
19
|
+
resumeJobId?: string;
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
iteration?: {
|
|
22
|
+
current: number;
|
|
23
|
+
max?: number;
|
|
24
|
+
};
|
|
16
25
|
}
|
|
17
26
|
export interface GenerateOpenapiResult {
|
|
18
27
|
jobId: string;
|
|
19
28
|
commandRunId: string;
|
|
20
29
|
outputPath?: string;
|
|
21
30
|
spec: string;
|
|
31
|
+
adminOutputPath?: string;
|
|
32
|
+
adminSpec?: string;
|
|
22
33
|
docdexId?: string;
|
|
34
|
+
adminDocdexId?: string;
|
|
23
35
|
warnings: string[];
|
|
24
36
|
}
|
|
37
|
+
export declare class OpenApiJobError extends Error {
|
|
38
|
+
code: string;
|
|
39
|
+
jobId?: string;
|
|
40
|
+
constructor(code: string, message: string, jobId?: string);
|
|
41
|
+
}
|
|
42
|
+
export declare const normalizeOpenApiPath: (value: string) => string;
|
|
43
|
+
export declare const extractOpenApiPaths: (raw: string) => {
|
|
44
|
+
paths: string[];
|
|
45
|
+
errors: string[];
|
|
46
|
+
};
|
|
47
|
+
export declare const findOpenApiPathLine: (raw: string, target: string) => number | undefined;
|
|
48
|
+
export interface AdminSurfaceMention {
|
|
49
|
+
line: number;
|
|
50
|
+
excerpt: string;
|
|
51
|
+
heading?: string;
|
|
52
|
+
}
|
|
53
|
+
export declare const findAdminSurfaceMentions: (raw: string) => AdminSurfaceMention[];
|
|
54
|
+
export interface OpenApiSchemaValidationResult {
|
|
55
|
+
doc?: any;
|
|
56
|
+
errors: string[];
|
|
57
|
+
}
|
|
58
|
+
export declare const validateOpenApiSchema: (doc: any) => string[];
|
|
59
|
+
export declare const validateOpenApiSchemaContent: (raw: string) => OpenApiSchemaValidationResult;
|
|
25
60
|
export declare class OpenApiService {
|
|
26
61
|
private docdex;
|
|
27
62
|
private jobService;
|
|
28
63
|
private agentService;
|
|
29
64
|
private routingService;
|
|
30
65
|
private workspace;
|
|
66
|
+
private repo?;
|
|
67
|
+
private ratingService?;
|
|
68
|
+
private workspaceRepo?;
|
|
31
69
|
constructor(workspace: WorkspaceResolution, deps: {
|
|
32
70
|
docdex?: DocdexClient;
|
|
33
71
|
jobService?: JobService;
|
|
34
72
|
agentService: AgentService;
|
|
35
73
|
routingService: RoutingService;
|
|
74
|
+
repo?: GlobalRepository;
|
|
75
|
+
workspaceRepo?: WorkspaceRepository;
|
|
76
|
+
ratingService?: AgentRatingService;
|
|
36
77
|
noTelemetry?: boolean;
|
|
37
78
|
});
|
|
38
79
|
static create(workspace: WorkspaceResolution, options?: {
|
|
@@ -40,6 +81,7 @@ export declare class OpenApiService {
|
|
|
40
81
|
}): Promise<OpenApiService>;
|
|
41
82
|
close(): Promise<void>;
|
|
42
83
|
private resolveAgent;
|
|
84
|
+
private ensureRatingService;
|
|
43
85
|
private invokeAgent;
|
|
44
86
|
private sanitizeOutput;
|
|
45
87
|
private validateSpec;
|
|
@@ -49,6 +91,15 @@ export declare class OpenApiService {
|
|
|
49
91
|
private backupIfNeeded;
|
|
50
92
|
private registerOpenapi;
|
|
51
93
|
private validateExistingSpec;
|
|
94
|
+
private collectAdminMentions;
|
|
95
|
+
private openapiDraftPath;
|
|
96
|
+
private readOpenapiDraft;
|
|
97
|
+
private writeOpenapiDraft;
|
|
98
|
+
private isJobCancelled;
|
|
99
|
+
private updateOpenapiJobStatus;
|
|
100
|
+
private writeOpenapiCheckpoint;
|
|
101
|
+
private startOpenapiHeartbeat;
|
|
102
|
+
private tryResumeOpenapi;
|
|
52
103
|
generateFromDocs(options: GenerateOpenapiOptions): Promise<GenerateOpenapiResult>;
|
|
53
104
|
}
|
|
54
105
|
//# sourceMappingURL=OpenApiService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenApiService.d.ts","sourceRoot":"","sources":["../../../src/services/openapi/OpenApiService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAkB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenApiService.d.ts","sourceRoot":"","sources":["../../../src/services/openapi/OpenApiService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAkB,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAiC,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAIrE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA6CD,qBAAa,eAAgB,SAAQ,KAAK;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEH,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAK1D;AAgBD,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,KAAG,MAapD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAmBpF,CAAC;AAIF,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,EAAE,QAAQ,MAAM,KAAG,MAAM,GAAG,SAS1E,CAAC;AAMF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,mBAAmB,EAwCzE,CAAC;AAEF,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA4BD,eAAO,MAAM,qBAAqB,GAAI,KAAK,GAAG,KAAG,MAAM,EA6EtD,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,KAAK,MAAM,KAAG,6BAoB1D,CAAC;AAuLF,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,IAAI,CAAC,CAAmB;IAChC,OAAO,CAAC,aAAa,CAAC,CAAqB;IAC3C,OAAO,CAAC,aAAa,CAAC,CAAsB;gBAG1C,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE;QACJ,MAAM,CAAC,EAAE,YAAY,CAAC;QACtB,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,YAAY,EAAE,YAAY,CAAC;QAC3B,cAAc,EAAE,cAAc,CAAC;QAC/B,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACxB,aAAa,CAAC,EAAE,mBAAmB,CAAC;QACpC,aAAa,CAAC,EAAE,kBAAkB,CAAC;QACnC,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB;WAcU,MAAM,CAAC,SAAS,EAAE,mBAAmB,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAe/G,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAcd,YAAY;YASZ,mBAAmB;YAoBnB,WAAW;IA8BzB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,YAAY;YAIN,mBAAmB;IAajC,OAAO,CAAC,WAAW;YAsCL,gBAAgB;YAMhB,cAAc;YAOd,eAAe;YAoBf,oBAAoB;YAWpB,oBAAoB;IAmClC,OAAO,CAAC,gBAAgB;YAKV,gBAAgB;YAahB,iBAAiB;YAMjB,cAAc;YAMd,sBAAsB;YA6CtB,sBAAsB;IAYpC,OAAO,CAAC,qBAAqB;YA2Cf,gBAAgB;IAoGxB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAyiBxF"}
|