@mcoda/core 0.1.9 → 0.1.12
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/README.md +2 -2
- package/dist/api/AgentsApi.d.ts +1 -0
- package/dist/api/AgentsApi.d.ts.map +1 -1
- package/dist/api/AgentsApi.js +136 -11
- package/dist/api/QaTasksApi.d.ts.map +1 -1
- package/dist/api/QaTasksApi.js +4 -0
- package/dist/prompts/PdrPrompts.d.ts.map +1 -1
- package/dist/prompts/PdrPrompts.js +6 -0
- package/dist/prompts/SdsPrompts.d.ts.map +1 -1
- package/dist/prompts/SdsPrompts.js +7 -0
- package/dist/services/agents/AgentRatingService.d.ts +19 -0
- package/dist/services/agents/AgentRatingService.d.ts.map +1 -1
- package/dist/services/agents/AgentRatingService.js +66 -2
- package/dist/services/agents/GatewayAgentService.d.ts +8 -0
- package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
- package/dist/services/agents/GatewayAgentService.js +462 -65
- package/dist/services/agents/GatewayHandoff.d.ts +5 -1
- package/dist/services/agents/GatewayHandoff.d.ts.map +1 -1
- package/dist/services/agents/GatewayHandoff.js +65 -32
- 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 +16 -4
- package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
- package/dist/services/backlog/TaskOrderingService.js +529 -73
- 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 +59 -2
- package/dist/services/docs/DocsService.d.ts.map +1 -1
- package/dist/services/docs/DocsService.js +1701 -48
- 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 +71 -4
- package/dist/services/execution/GatewayTrioService.d.ts.map +1 -1
- package/dist/services/execution/GatewayTrioService.js +1695 -328
- 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 +1 -0
- package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
- package/dist/services/execution/QaFollowupService.js +8 -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 +21 -1
- package/dist/services/execution/QaProfileService.d.ts.map +1 -1
- package/dist/services/execution/QaProfileService.js +214 -29
- package/dist/services/execution/QaTasksService.d.ts +41 -1
- package/dist/services/execution/QaTasksService.d.ts.map +1 -1
- package/dist/services/execution/QaTasksService.js +2851 -500
- 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 +19 -2
- package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
- package/dist/services/execution/WorkOnTasksService.js +3913 -1225
- 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 +41 -0
- package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
- package/dist/services/openapi/OpenApiService.js +889 -98
- package/dist/services/planning/CreateTasksService.d.ts +15 -0
- package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
- package/dist/services/planning/CreateTasksService.js +311 -6
- package/dist/services/planning/RefineTasksService.d.ts +4 -0
- package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
- package/dist/services/planning/RefineTasksService.js +225 -24
- package/dist/services/review/CodeReviewService.d.ts +4 -0
- package/dist/services/review/CodeReviewService.d.ts.map +1 -1
- package/dist/services/review/CodeReviewService.js +778 -232
- 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 +12 -1
- package/dist/services/shared/ProjectGuidance.d.ts.map +1 -1
- package/dist/services/shared/ProjectGuidance.js +64 -7
- 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/telemetry/TelemetryService.d.ts.map +1 -1
- package/dist/services/telemetry/TelemetryService.js +39 -7
- package/dist/workspace/WorkspaceManager.d.ts +22 -0
- package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
- package/dist/workspace/WorkspaceManager.js +203 -32
- package/package.json +6 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os from "node:os";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { promises as fs } from "node:fs";
|
|
3
4
|
import { randomUUID } from "node:crypto";
|
|
@@ -11,6 +12,138 @@ const fileExists = async (candidate) => {
|
|
|
11
12
|
return false;
|
|
12
13
|
}
|
|
13
14
|
};
|
|
15
|
+
const dirHasEntries = async (candidate) => {
|
|
16
|
+
try {
|
|
17
|
+
const entries = await fs.readdir(candidate);
|
|
18
|
+
return entries.length > 0;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const STATE_DIR_NAMES = [".mcoda", ".mcoda-state", ".mcoda_state"];
|
|
25
|
+
const resolveUniqueTarget = async (base) => {
|
|
26
|
+
if (!(await fileExists(base)))
|
|
27
|
+
return base;
|
|
28
|
+
const parent = path.dirname(base);
|
|
29
|
+
const stem = path.basename(base);
|
|
30
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
31
|
+
const candidate = path.join(parent, `${stem}-${randomUUID().slice(0, 8)}`);
|
|
32
|
+
if (!(await fileExists(candidate)))
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
35
|
+
return path.join(parent, `${stem}-${Date.now()}`);
|
|
36
|
+
};
|
|
37
|
+
const copyLegacyConfigIfMissing = async (sourceDir, targetDir, warnings) => {
|
|
38
|
+
const sourceConfig = path.join(sourceDir, "config.json");
|
|
39
|
+
const targetConfig = path.join(targetDir, "config.json");
|
|
40
|
+
if (!(await fileExists(sourceConfig)))
|
|
41
|
+
return;
|
|
42
|
+
if (await fileExists(targetConfig))
|
|
43
|
+
return;
|
|
44
|
+
try {
|
|
45
|
+
await PathHelper.ensureDir(targetDir);
|
|
46
|
+
await fs.copyFile(sourceConfig, targetConfig);
|
|
47
|
+
warnings.push(`Copied legacy workspace config from ${sourceConfig} to ${targetConfig}.`);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
warnings.push(`Unable to copy legacy workspace config from ${sourceConfig}: ${error.message ?? String(error)}`);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
export const cleanupWorkspaceStateDirs = async (input) => {
|
|
54
|
+
const warnings = [];
|
|
55
|
+
const workspaceRoot = path.resolve(input.workspaceRoot);
|
|
56
|
+
const mcodaDir = path.resolve(input.mcodaDir);
|
|
57
|
+
for (const name of STATE_DIR_NAMES) {
|
|
58
|
+
const source = path.join(workspaceRoot, name);
|
|
59
|
+
if (!(await fileExists(source)))
|
|
60
|
+
continue;
|
|
61
|
+
if (PathHelper.normalizePathCase(source) === PathHelper.normalizePathCase(mcodaDir)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
let stat;
|
|
65
|
+
try {
|
|
66
|
+
stat = await fs.lstat(source);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (stat.isSymbolicLink()) {
|
|
72
|
+
warnings.push(`Skipped legacy state directory symlink at ${source}.`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!stat.isDirectory()) {
|
|
76
|
+
warnings.push(`Skipped legacy state path ${source} because it is not a directory.`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (!(await dirHasEntries(source))) {
|
|
80
|
+
try {
|
|
81
|
+
await fs.rm(source, { recursive: true, force: true });
|
|
82
|
+
warnings.push(`Removed empty legacy state directory at ${source}.`);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
warnings.push(`Unable to remove empty legacy state directory at ${source}: ${error.message ?? String(error)}`);
|
|
86
|
+
}
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (name === ".mcoda") {
|
|
90
|
+
await copyLegacyConfigIfMissing(source, mcodaDir, warnings);
|
|
91
|
+
}
|
|
92
|
+
const targetName = name.startsWith(".") ? name.slice(1) : name;
|
|
93
|
+
const targetBase = path.join(mcodaDir, "legacy", targetName);
|
|
94
|
+
const target = await resolveUniqueTarget(targetBase);
|
|
95
|
+
await PathHelper.ensureDir(path.dirname(target));
|
|
96
|
+
try {
|
|
97
|
+
await fs.rename(source, target);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const code = error.code;
|
|
101
|
+
if (code === "EXDEV") {
|
|
102
|
+
try {
|
|
103
|
+
await fs.cp(source, target, { recursive: true });
|
|
104
|
+
await fs.rm(source, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
catch (copyError) {
|
|
107
|
+
warnings.push(`Unable to relocate legacy state directory from ${source}: ${copyError.message ?? String(copyError)}`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
warnings.push(`Unable to relocate legacy state directory from ${source}: ${error.message ?? String(error)}`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
warnings.push(`Relocated legacy state directory from ${source} to ${target}.`);
|
|
117
|
+
}
|
|
118
|
+
return warnings;
|
|
119
|
+
};
|
|
120
|
+
export const resolveDocgenStatePath = (input) => {
|
|
121
|
+
const warnings = [];
|
|
122
|
+
const outputPath = path.resolve(input.outputPath);
|
|
123
|
+
const mcodaDir = path.resolve(input.mcodaDir);
|
|
124
|
+
const tempDir = path.resolve(os.tmpdir());
|
|
125
|
+
const allowedRoots = [mcodaDir, tempDir];
|
|
126
|
+
const isAllowed = allowedRoots.some((root) => PathHelper.isPathInside(root, outputPath));
|
|
127
|
+
if (isAllowed) {
|
|
128
|
+
return { statePath: outputPath, warnings };
|
|
129
|
+
}
|
|
130
|
+
const basename = path.basename(outputPath) || "docgen.md";
|
|
131
|
+
const statePath = path.join(mcodaDir, "state", "docgen", input.commandName, input.jobId, basename);
|
|
132
|
+
warnings.push(`Intermediate state redirected from ${outputPath} to ${statePath} to keep docgen state under .mcoda or OS temp directories.`);
|
|
133
|
+
return { statePath, warnings };
|
|
134
|
+
};
|
|
135
|
+
const maybeCopyLegacyWorkspace = async (sourceDir, targetDir) => {
|
|
136
|
+
if (!(await fileExists(sourceDir)))
|
|
137
|
+
return;
|
|
138
|
+
if (await dirHasEntries(targetDir))
|
|
139
|
+
return;
|
|
140
|
+
try {
|
|
141
|
+
await fs.cp(sourceDir, targetDir, { recursive: true });
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
/* best effort */
|
|
145
|
+
}
|
|
146
|
+
};
|
|
14
147
|
const findGitRoot = async (start) => {
|
|
15
148
|
// Only consider the provided directory; do not walk upward.
|
|
16
149
|
const current = path.resolve(start);
|
|
@@ -30,27 +163,34 @@ const findWorkspaceMarker = async (start) => {
|
|
|
30
163
|
return current;
|
|
31
164
|
return undefined;
|
|
32
165
|
};
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
166
|
+
const readWorkspaceConfig = async (mcodaDir, fallbackDir) => {
|
|
167
|
+
const readConfig = async (dir) => {
|
|
168
|
+
const configPath = path.join(dir, "config.json");
|
|
169
|
+
try {
|
|
170
|
+
const raw = await fs.readFile(configPath, "utf8");
|
|
171
|
+
return JSON.parse(raw);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const primary = await readConfig(mcodaDir);
|
|
178
|
+
if (primary)
|
|
179
|
+
return primary;
|
|
180
|
+
if (fallbackDir && fallbackDir !== mcodaDir) {
|
|
181
|
+
return readConfig(fallbackDir);
|
|
44
182
|
}
|
|
183
|
+
return undefined;
|
|
45
184
|
};
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
185
|
+
const applyWorkspaceEnvOverrides = (config) => {
|
|
186
|
+
if (!config)
|
|
187
|
+
return;
|
|
188
|
+
if (config.codexNoSandbox === true) {
|
|
189
|
+
process.env.MCODA_CODEX_NO_SANDBOX = "1";
|
|
190
|
+
return;
|
|
51
191
|
}
|
|
52
|
-
|
|
53
|
-
|
|
192
|
+
if (config.codexNoSandbox === false && process.env.MCODA_CODEX_NO_SANDBOX === undefined) {
|
|
193
|
+
process.env.MCODA_CODEX_NO_SANDBOX = "0";
|
|
54
194
|
}
|
|
55
195
|
};
|
|
56
196
|
const readWorkspaceIdentity = async (mcodaDir) => {
|
|
@@ -77,9 +217,10 @@ const migrateWorkspaceDbIds = async (workspace, legacyIds) => {
|
|
|
77
217
|
if (!(await fileExists(workspace.workspaceDbPath))) {
|
|
78
218
|
return;
|
|
79
219
|
}
|
|
220
|
+
let conn;
|
|
80
221
|
try {
|
|
81
222
|
const { Connection } = await import("@mcoda/db");
|
|
82
|
-
|
|
223
|
+
conn = await Connection.open(workspace.workspaceDbPath);
|
|
83
224
|
const db = conn.db;
|
|
84
225
|
const placeholders = legacyIds.map(() => "?").join(",");
|
|
85
226
|
const params = [workspace.workspaceId, ...legacyIds];
|
|
@@ -87,11 +228,20 @@ const migrateWorkspaceDbIds = async (workspace, legacyIds) => {
|
|
|
87
228
|
for (const table of tables) {
|
|
88
229
|
await db.run(`UPDATE ${table} SET workspace_id = ? WHERE workspace_id IN (${placeholders})`, params);
|
|
89
230
|
}
|
|
90
|
-
await conn.close();
|
|
91
231
|
}
|
|
92
232
|
catch {
|
|
93
233
|
/* best effort */
|
|
94
234
|
}
|
|
235
|
+
finally {
|
|
236
|
+
if (conn) {
|
|
237
|
+
try {
|
|
238
|
+
await conn.close();
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
/* best effort */
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
95
245
|
const updateJsonArray = async (filePath) => {
|
|
96
246
|
try {
|
|
97
247
|
const raw = await fs.readFile(filePath, "utf8");
|
|
@@ -114,12 +264,13 @@ const migrateWorkspaceDbIds = async (workspace, legacyIds) => {
|
|
|
114
264
|
/* ignore */
|
|
115
265
|
}
|
|
116
266
|
};
|
|
117
|
-
await updateJsonArray(path.join(workspace.
|
|
118
|
-
await updateJsonArray(path.join(workspace.
|
|
267
|
+
await updateJsonArray(path.join(workspace.mcodaDir, "command_runs.json"));
|
|
268
|
+
await updateJsonArray(path.join(workspace.mcodaDir, "token_usage.json"));
|
|
119
269
|
};
|
|
120
270
|
export class WorkspaceResolver {
|
|
121
271
|
static async resolveWorkspace(input) {
|
|
122
272
|
const cwd = path.resolve(input.cwd ?? process.cwd());
|
|
273
|
+
const noRepoWrites = Boolean(input.noRepoWrites);
|
|
123
274
|
let explicit = input.explicitWorkspace;
|
|
124
275
|
let explicitPath;
|
|
125
276
|
if (explicit) {
|
|
@@ -140,10 +291,13 @@ export class WorkspaceResolver {
|
|
|
140
291
|
const fromMarker = await findWorkspaceMarker(explicitPath ?? cwd);
|
|
141
292
|
const gitRoot = await findGitRoot(explicitPath ?? cwd);
|
|
142
293
|
const workspaceRoot = explicitPath ?? fromMarker ?? gitRoot ?? cwd;
|
|
143
|
-
const
|
|
294
|
+
const repoMcodaDir = path.join(workspaceRoot, ".mcoda");
|
|
295
|
+
const mcodaDir = PathHelper.getGlobalWorkspaceDir(workspaceRoot);
|
|
144
296
|
await PathHelper.ensureDir(mcodaDir);
|
|
145
|
-
await
|
|
146
|
-
const
|
|
297
|
+
await maybeCopyLegacyWorkspace(repoMcodaDir, mcodaDir);
|
|
298
|
+
const repoIdentity = await readWorkspaceIdentity(repoMcodaDir);
|
|
299
|
+
const globalIdentity = await readWorkspaceIdentity(mcodaDir);
|
|
300
|
+
const existingIdentity = globalIdentity ?? repoIdentity;
|
|
147
301
|
let identity;
|
|
148
302
|
let legacyIds = [];
|
|
149
303
|
if (existingIdentity) {
|
|
@@ -154,6 +308,19 @@ export class WorkspaceResolver {
|
|
|
154
308
|
legacyIds.push(workspaceRoot);
|
|
155
309
|
updatedIdentity = true;
|
|
156
310
|
}
|
|
311
|
+
if (repoIdentity) {
|
|
312
|
+
if (repoIdentity.id && repoIdentity.id !== existingIdentity.id) {
|
|
313
|
+
legacyIds.push(repoIdentity.id);
|
|
314
|
+
updatedIdentity = true;
|
|
315
|
+
}
|
|
316
|
+
if (repoIdentity.legacyIds?.length) {
|
|
317
|
+
legacyIds.push(...repoIdentity.legacyIds);
|
|
318
|
+
updatedIdentity = true;
|
|
319
|
+
}
|
|
320
|
+
if (!globalIdentity) {
|
|
321
|
+
updatedIdentity = true;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
157
324
|
if (!looksLikeWorkspaceId(existingIdentity.id)) {
|
|
158
325
|
legacyIds.push(existingIdentity.id);
|
|
159
326
|
identity = {
|
|
@@ -161,7 +328,7 @@ export class WorkspaceResolver {
|
|
|
161
328
|
id: randomUUID(),
|
|
162
329
|
legacyIds: Array.from(new Set(legacyIds)),
|
|
163
330
|
};
|
|
164
|
-
|
|
331
|
+
updatedIdentity = true;
|
|
165
332
|
}
|
|
166
333
|
else {
|
|
167
334
|
identity = {
|
|
@@ -171,9 +338,9 @@ export class WorkspaceResolver {
|
|
|
171
338
|
if ((identity.legacyIds?.length ?? 0) !== existingLegacy.size) {
|
|
172
339
|
updatedIdentity = true;
|
|
173
340
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
341
|
+
}
|
|
342
|
+
if (updatedIdentity) {
|
|
343
|
+
await writeWorkspaceIdentity(mcodaDir, identity);
|
|
177
344
|
}
|
|
178
345
|
}
|
|
179
346
|
else {
|
|
@@ -186,19 +353,23 @@ export class WorkspaceResolver {
|
|
|
186
353
|
await writeWorkspaceIdentity(mcodaDir, identity);
|
|
187
354
|
}
|
|
188
355
|
const legacyWorkspaceIds = Array.from(new Set([...(identity.legacyIds ?? []), workspaceRoot].filter(Boolean)));
|
|
189
|
-
const config = await readWorkspaceConfig(mcodaDir);
|
|
356
|
+
const config = await readWorkspaceConfig(mcodaDir, repoMcodaDir);
|
|
357
|
+
applyWorkspaceEnvOverrides(config);
|
|
190
358
|
const resolution = {
|
|
191
359
|
workspaceRoot,
|
|
192
360
|
workspaceId: identity.id,
|
|
193
361
|
id: identity.id,
|
|
194
362
|
legacyWorkspaceIds,
|
|
195
363
|
mcodaDir,
|
|
196
|
-
workspaceDbPath:
|
|
364
|
+
workspaceDbPath: path.join(mcodaDir, "mcoda.db"),
|
|
197
365
|
globalDbPath: PathHelper.getGlobalDbPath(),
|
|
366
|
+
noRepoWrites,
|
|
198
367
|
config,
|
|
199
368
|
};
|
|
200
369
|
// Best-effort migration of workspace_id columns and JSON logs from legacy IDs.
|
|
201
|
-
|
|
370
|
+
if (!noRepoWrites) {
|
|
371
|
+
await migrateWorkspaceDbIds(resolution, legacyWorkspaceIds.filter((id) => id !== identity.id));
|
|
372
|
+
}
|
|
202
373
|
return resolution;
|
|
203
374
|
}
|
|
204
375
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcoda/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Core services and APIs for the mcoda CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@apidevtools/swagger-parser": "^10.1.0",
|
|
34
34
|
"yaml": "^2.4.2",
|
|
35
|
-
"@mcoda/
|
|
36
|
-
"@mcoda/
|
|
37
|
-
"@mcoda/
|
|
38
|
-
"@mcoda/integrations": "0.1.
|
|
35
|
+
"@mcoda/shared": "0.1.12",
|
|
36
|
+
"@mcoda/agents": "0.1.12",
|
|
37
|
+
"@mcoda/generators": "0.1.12",
|
|
38
|
+
"@mcoda/integrations": "0.1.12",
|
|
39
|
+
"@mcoda/db": "0.1.12"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
42
|
"build": "tsc -p tsconfig.json",
|