opencode-swarm 7.55.0 → 7.56.1
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/cli/index.js +458 -262
- package/dist/index.js +1891 -1481
- package/dist/lang/backends/php.d.ts +29 -0
- package/dist/lang/index.d.ts +1 -1
- package/dist/lang/runtime.d.ts +9 -1
- package/dist/sast/semgrep.d.ts +19 -0
- package/dist/services/skill-generator.d.ts +2 -1
- package/dist/services/skill-improver.d.ts +6 -0
- package/dist/tools/repo-graph/builder.d.ts +1 -8
- package/dist/tools/test-runner.d.ts +16 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.
|
|
55
|
+
version: "7.56.1",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -36811,7 +36811,7 @@ function clusterEntries(entries) {
|
|
|
36811
36811
|
function uniqueStrings(arr) {
|
|
36812
36812
|
return [...new Set(arr.filter((s) => typeof s === "string" && s.length > 0))];
|
|
36813
36813
|
}
|
|
36814
|
-
function renderSkillMarkdown(cluster, mode = "active") {
|
|
36814
|
+
function renderSkillMarkdown(cluster, mode = "active", generatedAt = new Date().toISOString()) {
|
|
36815
36815
|
const description = cluster.title.length > 200 ? `${cluster.title.slice(0, 197)}\u2026` : cluster.title;
|
|
36816
36816
|
const ids = cluster.entries.map((e) => ` - ${e.id}`).join(`
|
|
36817
36817
|
`);
|
|
@@ -36821,6 +36821,9 @@ function renderSkillMarkdown(cluster, mode = "active") {
|
|
|
36821
36821
|
lines.push(`description: ${escapeYaml(description)}`);
|
|
36822
36822
|
lines.push("generated_from_knowledge:");
|
|
36823
36823
|
lines.push(ids);
|
|
36824
|
+
lines.push("source_knowledge_ids:");
|
|
36825
|
+
lines.push(ids);
|
|
36826
|
+
lines.push(`generated_at: ${generatedAt}`);
|
|
36824
36827
|
lines.push(`confidence: ${cluster.avgConfidence.toFixed(2)}`);
|
|
36825
36828
|
lines.push(`status: ${mode === "active" ? "active" : "draft"}`);
|
|
36826
36829
|
lines.push("---");
|
|
@@ -37009,6 +37012,62 @@ async function stampSourceEntries(directory, slug, ids) {
|
|
|
37009
37012
|
if (touchedHive)
|
|
37010
37013
|
await rewriteKnowledge(hivePath, hive);
|
|
37011
37014
|
}
|
|
37015
|
+
function parseDraftFrontmatter(content) {
|
|
37016
|
+
const stripped = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
37017
|
+
const openFence = stripped.match(/^---[ \t]*\r?\n/);
|
|
37018
|
+
if (!openFence)
|
|
37019
|
+
return null;
|
|
37020
|
+
const fenceLen = openFence[0].length;
|
|
37021
|
+
const closeFence = stripped.slice(fenceLen).match(/\n---[ \t]*(\r?\n|$)/);
|
|
37022
|
+
if (!closeFence)
|
|
37023
|
+
return null;
|
|
37024
|
+
const closeStart = fenceLen + (closeFence.index ?? 0);
|
|
37025
|
+
const body = stripped.slice(fenceLen, closeStart).replace(/\r\n/g, `
|
|
37026
|
+
`);
|
|
37027
|
+
const lines = body.split(`
|
|
37028
|
+
`);
|
|
37029
|
+
const out = {
|
|
37030
|
+
sourceKnowledgeIds: []
|
|
37031
|
+
};
|
|
37032
|
+
let inLegacyIdsList = false;
|
|
37033
|
+
let inSourceIdsList = false;
|
|
37034
|
+
for (const raw of lines) {
|
|
37035
|
+
const line = raw;
|
|
37036
|
+
if (inLegacyIdsList || inSourceIdsList) {
|
|
37037
|
+
const m = line.match(/^\s+-\s+(\S{1,64})\s*$/);
|
|
37038
|
+
if (m) {
|
|
37039
|
+
out.sourceKnowledgeIds.push(m[1]);
|
|
37040
|
+
continue;
|
|
37041
|
+
}
|
|
37042
|
+
inLegacyIdsList = false;
|
|
37043
|
+
inSourceIdsList = false;
|
|
37044
|
+
}
|
|
37045
|
+
const nm = line.match(/^name:\s*(\S+)\s*$/);
|
|
37046
|
+
if (nm) {
|
|
37047
|
+
out.name = nm[1];
|
|
37048
|
+
continue;
|
|
37049
|
+
}
|
|
37050
|
+
const st = line.match(/^status:\s*(\S+)\s*$/);
|
|
37051
|
+
if (st) {
|
|
37052
|
+
out.status = st[1];
|
|
37053
|
+
continue;
|
|
37054
|
+
}
|
|
37055
|
+
const ga = line.match(/^generated_at:\s*(\S+)\s*$/);
|
|
37056
|
+
if (ga) {
|
|
37057
|
+
out.generatedAt = ga[1];
|
|
37058
|
+
continue;
|
|
37059
|
+
}
|
|
37060
|
+
if (/^generated_from_knowledge:\s*$/.test(line)) {
|
|
37061
|
+
inLegacyIdsList = true;
|
|
37062
|
+
continue;
|
|
37063
|
+
}
|
|
37064
|
+
if (/^source_knowledge_ids:\s*$/.test(line)) {
|
|
37065
|
+
out.sourceKnowledgeIds = [];
|
|
37066
|
+
inSourceIdsList = true;
|
|
37067
|
+
}
|
|
37068
|
+
}
|
|
37069
|
+
return out;
|
|
37070
|
+
}
|
|
37012
37071
|
async function listSkills(directory) {
|
|
37013
37072
|
const result = {
|
|
37014
37073
|
proposals: [],
|
|
@@ -38338,7 +38397,7 @@ var init_skill_improver_quota = __esm(() => {
|
|
|
38338
38397
|
|
|
38339
38398
|
// src/services/skill-improver.ts
|
|
38340
38399
|
import { existsSync as existsSync12 } from "fs";
|
|
38341
|
-
import { mkdir as mkdir7, rename as rename5, writeFile as writeFile6 } from "fs/promises";
|
|
38400
|
+
import { mkdir as mkdir7, readFile as readFile7, rename as rename5, writeFile as writeFile6 } from "fs/promises";
|
|
38342
38401
|
import * as path18 from "path";
|
|
38343
38402
|
function timestampSlug(d) {
|
|
38344
38403
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
@@ -38355,15 +38414,63 @@ async function gatherInventory(directory) {
|
|
|
38355
38414
|
const hive = existsSync12(hivePath) ? await readKnowledge(hivePath) : [];
|
|
38356
38415
|
const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
|
|
38357
38416
|
const skills = await listSkills(directory);
|
|
38417
|
+
const knowledgeById = new Map([...swarm, ...hive].map((entry) => [entry.id, entry]));
|
|
38418
|
+
const staleActiveSkills = [];
|
|
38419
|
+
let metadataReadable = 0;
|
|
38420
|
+
for (const skill of skills.active) {
|
|
38421
|
+
let content;
|
|
38422
|
+
try {
|
|
38423
|
+
content = await readFile7(skill.path, "utf-8");
|
|
38424
|
+
} catch {
|
|
38425
|
+
continue;
|
|
38426
|
+
}
|
|
38427
|
+
const fm = parseDraftFrontmatter(content);
|
|
38428
|
+
if (!fm)
|
|
38429
|
+
continue;
|
|
38430
|
+
metadataReadable += 1;
|
|
38431
|
+
const reasons = [];
|
|
38432
|
+
if (fm.sourceKnowledgeIds.length === 0) {
|
|
38433
|
+
reasons.push("missing_source_knowledge_ids");
|
|
38434
|
+
}
|
|
38435
|
+
if (!fm.generatedAt) {
|
|
38436
|
+
reasons.push("missing_generated_at");
|
|
38437
|
+
} else {
|
|
38438
|
+
const generatedAtMs = Date.parse(fm.generatedAt);
|
|
38439
|
+
if (!Number.isFinite(generatedAtMs)) {
|
|
38440
|
+
reasons.push("invalid_generated_at");
|
|
38441
|
+
} else {
|
|
38442
|
+
for (const id of fm.sourceKnowledgeIds) {
|
|
38443
|
+
const source = knowledgeById.get(id);
|
|
38444
|
+
if (!source) {
|
|
38445
|
+
reasons.push(`missing_source:${id}`);
|
|
38446
|
+
continue;
|
|
38447
|
+
}
|
|
38448
|
+
const updatedAtMs = Date.parse(source.updated_at);
|
|
38449
|
+
if (Number.isFinite(updatedAtMs) && updatedAtMs > generatedAtMs) {
|
|
38450
|
+
reasons.push(`updated_after_generation:${id}`);
|
|
38451
|
+
}
|
|
38452
|
+
}
|
|
38453
|
+
}
|
|
38454
|
+
}
|
|
38455
|
+
if (reasons.length > 0) {
|
|
38456
|
+
staleActiveSkills.push({
|
|
38457
|
+
slug: skill.slug,
|
|
38458
|
+
reasons: reasons.slice(0, 6)
|
|
38459
|
+
});
|
|
38460
|
+
}
|
|
38461
|
+
}
|
|
38358
38462
|
const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
|
|
38359
38463
|
return {
|
|
38360
38464
|
knowledge: { swarm: swarm.length, hive: hive.length, archived },
|
|
38361
38465
|
skills: {
|
|
38362
38466
|
proposals: skills.proposals.length,
|
|
38363
|
-
active: skills.active.length
|
|
38467
|
+
active: skills.active.length,
|
|
38468
|
+
stale: staleActiveSkills.length,
|
|
38469
|
+
metadataReadable
|
|
38364
38470
|
},
|
|
38365
38471
|
highConfidenceClusters: matureCandidates.length,
|
|
38366
|
-
matureCandidates
|
|
38472
|
+
matureCandidates,
|
|
38473
|
+
staleActiveSkills
|
|
38367
38474
|
};
|
|
38368
38475
|
}
|
|
38369
38476
|
function buildSystemPrompt(targets, cfg) {
|
|
@@ -38387,10 +38494,16 @@ hive_entries: ${inv.knowledge.hive}
|
|
|
38387
38494
|
archived: ${inv.knowledge.archived}
|
|
38388
38495
|
draft_skills: ${inv.skills.proposals}
|
|
38389
38496
|
active_skills: ${inv.skills.active}
|
|
38497
|
+
active_skills_with_readable_metadata: ${inv.skills.metadataReadable}
|
|
38498
|
+
stale_active_skills: ${inv.skills.stale}
|
|
38390
38499
|
mature_uncompiled_clusters: ${inv.highConfidenceClusters}
|
|
38391
38500
|
|
|
38392
38501
|
TOP MATURE CANDIDATES (first 25):
|
|
38393
38502
|
${matureRows || "(none)"}
|
|
38503
|
+
|
|
38504
|
+
STALE ACTIVE SKILLS (first 10):
|
|
38505
|
+
${inv.staleActiveSkills.slice(0, 10).map((s) => `- ${s.slug} | ${s.reasons.join(", ")}`).join(`
|
|
38506
|
+
`) || "(none)"}
|
|
38394
38507
|
`;
|
|
38395
38508
|
}
|
|
38396
38509
|
function isAbortError(err) {
|
|
@@ -38419,7 +38532,11 @@ function buildDeterministicProposal(args) {
|
|
|
38419
38532
|
lines.push("## Inventory snapshot");
|
|
38420
38533
|
lines.push(`- Knowledge entries: swarm=${args.inventory.knowledge.swarm}, hive=${args.inventory.knowledge.hive}, archived=${args.inventory.knowledge.archived}`);
|
|
38421
38534
|
lines.push(`- Generated skills: proposals=${args.inventory.skills.proposals}, active=${args.inventory.skills.active}`);
|
|
38535
|
+
lines.push(`- Active skills with readable metadata: ${args.inventory.skills.metadataReadable} (stale=${args.inventory.skills.stale})`);
|
|
38422
38536
|
lines.push(`- High-confidence un-skill'd clusters: ${args.inventory.highConfidenceClusters}`);
|
|
38537
|
+
if (args.inventory.staleActiveSkills.length > 0) {
|
|
38538
|
+
lines.push(`- Stale active skills: ${args.inventory.staleActiveSkills.map((s) => s.slug).join(", ")}`);
|
|
38539
|
+
}
|
|
38423
38540
|
lines.push("");
|
|
38424
38541
|
lines.push("## Recommendations");
|
|
38425
38542
|
if (args.inventory.highConfidenceClusters > 0) {
|
|
@@ -39914,7 +40031,7 @@ var init_curate = __esm(() => {
|
|
|
39914
40031
|
// src/tools/co-change-analyzer.ts
|
|
39915
40032
|
import * as child_process3 from "child_process";
|
|
39916
40033
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
39917
|
-
import { readdir, readFile as
|
|
40034
|
+
import { readdir, readFile as readFile8, stat as stat2 } from "fs/promises";
|
|
39918
40035
|
import * as path21 from "path";
|
|
39919
40036
|
import { promisify } from "util";
|
|
39920
40037
|
function getExecFileAsync() {
|
|
@@ -40041,7 +40158,7 @@ async function getStaticEdges(directory) {
|
|
|
40041
40158
|
const sourceFiles = await scanSourceFiles(directory);
|
|
40042
40159
|
for (const sourceFile of sourceFiles) {
|
|
40043
40160
|
try {
|
|
40044
|
-
const content = await
|
|
40161
|
+
const content = await readFile8(sourceFile, "utf-8");
|
|
40045
40162
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
40046
40163
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
40047
40164
|
const importPath = match[1].trim();
|
|
@@ -40825,11 +40942,11 @@ var init_version_check = __esm(() => {
|
|
|
40825
40942
|
|
|
40826
40943
|
// src/services/knowledge-diagnostics.ts
|
|
40827
40944
|
import { existsSync as existsSync14 } from "fs";
|
|
40828
|
-
import { readFile as
|
|
40945
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
40829
40946
|
async function readRawLines(filePath) {
|
|
40830
40947
|
if (!existsSync14(filePath))
|
|
40831
40948
|
return { entries: [], corrupt: 0 };
|
|
40832
|
-
const content = await
|
|
40949
|
+
const content = await readFile9(filePath, "utf-8");
|
|
40833
40950
|
const entries = [];
|
|
40834
40951
|
let corrupt = 0;
|
|
40835
40952
|
for (const line of content.split(`
|
|
@@ -42803,7 +42920,7 @@ var init_profiles = __esm(() => {
|
|
|
42803
42920
|
detectFiles: ["Cargo.toml"],
|
|
42804
42921
|
frameworks: [
|
|
42805
42922
|
{
|
|
42806
|
-
name: "cargo
|
|
42923
|
+
name: "cargo",
|
|
42807
42924
|
detect: "Cargo.toml",
|
|
42808
42925
|
cmd: "cargo test",
|
|
42809
42926
|
priority: 10
|
|
@@ -42875,7 +42992,7 @@ var init_profiles = __esm(() => {
|
|
|
42875
42992
|
test: {
|
|
42876
42993
|
detectFiles: ["go.mod"],
|
|
42877
42994
|
frameworks: [
|
|
42878
|
-
{ name: "go
|
|
42995
|
+
{ name: "go-test", detect: "go.mod", cmd: "go test ./...", priority: 10 }
|
|
42879
42996
|
]
|
|
42880
42997
|
},
|
|
42881
42998
|
lint: {
|
|
@@ -42950,13 +43067,13 @@ var init_profiles = __esm(() => {
|
|
|
42950
43067
|
detectFiles: ["pom.xml", "build.gradle", "build.gradle.kts"],
|
|
42951
43068
|
frameworks: [
|
|
42952
43069
|
{
|
|
42953
|
-
name: "maven
|
|
43070
|
+
name: "maven",
|
|
42954
43071
|
detect: "pom.xml",
|
|
42955
43072
|
cmd: "mvn test -q",
|
|
42956
43073
|
priority: 10
|
|
42957
43074
|
},
|
|
42958
43075
|
{
|
|
42959
|
-
name: "gradle
|
|
43076
|
+
name: "gradle",
|
|
42960
43077
|
detect: "build.gradle",
|
|
42961
43078
|
cmd: "gradle test -q",
|
|
42962
43079
|
priority: 9
|
|
@@ -43034,13 +43151,13 @@ var init_profiles = __esm(() => {
|
|
|
43034
43151
|
detectFiles: ["build.gradle.kts", "build.gradle"],
|
|
43035
43152
|
frameworks: [
|
|
43036
43153
|
{
|
|
43037
|
-
name: "gradle
|
|
43154
|
+
name: "gradle",
|
|
43038
43155
|
detect: "build.gradle.kts",
|
|
43039
43156
|
cmd: "gradle test -q",
|
|
43040
43157
|
priority: 10
|
|
43041
43158
|
},
|
|
43042
43159
|
{
|
|
43043
|
-
name: "gradle
|
|
43160
|
+
name: "gradle",
|
|
43044
43161
|
detect: "build.gradle",
|
|
43045
43162
|
cmd: "gradle test -q",
|
|
43046
43163
|
priority: 9
|
|
@@ -43048,11 +43165,11 @@ var init_profiles = __esm(() => {
|
|
|
43048
43165
|
]
|
|
43049
43166
|
},
|
|
43050
43167
|
lint: {
|
|
43051
|
-
detectFiles: [".
|
|
43168
|
+
detectFiles: ["build.gradle.kts", "build.gradle"],
|
|
43052
43169
|
linters: [
|
|
43053
43170
|
{
|
|
43054
43171
|
name: "ktlint",
|
|
43055
|
-
detect: ".
|
|
43172
|
+
detect: "build.gradle.kts",
|
|
43056
43173
|
cmd: "ktlint --format",
|
|
43057
43174
|
priority: 10
|
|
43058
43175
|
}
|
|
@@ -43112,7 +43229,7 @@ var init_profiles = __esm(() => {
|
|
|
43112
43229
|
detectFiles: ["*.csproj", "*.sln"],
|
|
43113
43230
|
frameworks: [
|
|
43114
43231
|
{
|
|
43115
|
-
name: "dotnet
|
|
43232
|
+
name: "dotnet-test",
|
|
43116
43233
|
detect: "*.csproj",
|
|
43117
43234
|
cmd: "dotnet test",
|
|
43118
43235
|
priority: 10
|
|
@@ -43263,7 +43380,7 @@ var init_profiles = __esm(() => {
|
|
|
43263
43380
|
detectFiles: ["Package.swift", "*.xcodeproj"],
|
|
43264
43381
|
frameworks: [
|
|
43265
43382
|
{
|
|
43266
|
-
name: "swift
|
|
43383
|
+
name: "swift-test",
|
|
43267
43384
|
detect: "Package.swift",
|
|
43268
43385
|
cmd: "swift test",
|
|
43269
43386
|
priority: 10
|
|
@@ -43590,8 +43707,14 @@ async function detectProjectLanguages(projectDir) {
|
|
|
43590
43707
|
}
|
|
43591
43708
|
for (const profile of LANGUAGE_REGISTRY.getAll()) {
|
|
43592
43709
|
for (const detectFile of profile.build.detectFiles) {
|
|
43593
|
-
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
43710
|
+
if (detectFile.includes("*") || detectFile.includes("?")) {
|
|
43711
|
+
const regex = new RegExp(`^${detectFile.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
43712
|
+
if (entries.some((name) => regex.test(name))) {
|
|
43713
|
+
detected.add(profile.id);
|
|
43714
|
+
break;
|
|
43715
|
+
}
|
|
43594
43716
|
continue;
|
|
43717
|
+
}
|
|
43595
43718
|
try {
|
|
43596
43719
|
await access3(join24(dir, detectFile));
|
|
43597
43720
|
detected.add(profile.id);
|
|
@@ -46049,7 +46172,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
|
46049
46172
|
// src/hooks/knowledge-migrator.ts
|
|
46050
46173
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
46051
46174
|
import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
46052
|
-
import { mkdir as mkdir8, readFile as
|
|
46175
|
+
import { mkdir as mkdir8, readFile as readFile10, writeFile as writeFile7 } from "fs/promises";
|
|
46053
46176
|
import * as path29 from "path";
|
|
46054
46177
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
46055
46178
|
return {
|
|
@@ -46082,7 +46205,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
46082
46205
|
skippedReason: "no-context-file"
|
|
46083
46206
|
};
|
|
46084
46207
|
}
|
|
46085
|
-
const contextContent = await
|
|
46208
|
+
const contextContent = await readFile10(contextPath, "utf-8");
|
|
46086
46209
|
if (contextContent.trim().length === 0) {
|
|
46087
46210
|
return {
|
|
46088
46211
|
migrated: false,
|
|
@@ -47331,7 +47454,7 @@ import { existsSync as existsSync20 } from "fs";
|
|
|
47331
47454
|
import {
|
|
47332
47455
|
appendFile as appendFile5,
|
|
47333
47456
|
mkdir as mkdir9,
|
|
47334
|
-
readFile as
|
|
47457
|
+
readFile as readFile11,
|
|
47335
47458
|
rename as rename6,
|
|
47336
47459
|
writeFile as writeFile8
|
|
47337
47460
|
} from "fs/promises";
|
|
@@ -47680,7 +47803,7 @@ function validateLoadedProposals(values, config3) {
|
|
|
47680
47803
|
async function readJsonl(filePath) {
|
|
47681
47804
|
if (!existsSync20(filePath))
|
|
47682
47805
|
return [];
|
|
47683
|
-
const content = await
|
|
47806
|
+
const content = await readFile11(filePath, "utf-8");
|
|
47684
47807
|
const records = [];
|
|
47685
47808
|
for (const line of content.split(`
|
|
47686
47809
|
`)) {
|
|
@@ -47765,7 +47888,7 @@ var init_prompt_block = __esm(() => {
|
|
|
47765
47888
|
|
|
47766
47889
|
// src/memory/jsonl-migration.ts
|
|
47767
47890
|
import { existsSync as existsSync21 } from "fs";
|
|
47768
|
-
import { copyFile, mkdir as mkdir10, readFile as
|
|
47891
|
+
import { copyFile, mkdir as mkdir10, readFile as readFile12, stat as stat3, writeFile as writeFile9 } from "fs/promises";
|
|
47769
47892
|
import * as path31 from "path";
|
|
47770
47893
|
function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
|
|
47771
47894
|
const resolved = resolveConfig(config3);
|
|
@@ -47829,7 +47952,7 @@ async function readMigrationReport(rootDirectory, config3 = {}) {
|
|
|
47829
47952
|
if (!existsSync21(reportPath))
|
|
47830
47953
|
return null;
|
|
47831
47954
|
try {
|
|
47832
|
-
return JSON.parse(await
|
|
47955
|
+
return JSON.parse(await readFile12(reportPath, "utf-8"));
|
|
47833
47956
|
} catch {
|
|
47834
47957
|
return null;
|
|
47835
47958
|
}
|
|
@@ -47930,7 +48053,7 @@ async function readJsonlRows(filePath) {
|
|
|
47930
48053
|
if (!existsSync21(filePath)) {
|
|
47931
48054
|
return { rows: [], invalidRows: [], totalRows: 0 };
|
|
47932
48055
|
}
|
|
47933
|
-
const content = await
|
|
48056
|
+
const content = await readFile12(filePath, "utf-8");
|
|
47934
48057
|
const rows = [];
|
|
47935
48058
|
const invalidRows = [];
|
|
47936
48059
|
let totalRows = 0;
|
|
@@ -53044,12 +53167,85 @@ var init_registry_backend = __esm(() => {
|
|
|
53044
53167
|
LANGUAGE_BACKEND_REGISTRY = new LanguageBackendRegistry;
|
|
53045
53168
|
});
|
|
53046
53169
|
|
|
53047
|
-
// src/lang/
|
|
53170
|
+
// src/lang/framework-detector.ts
|
|
53048
53171
|
import * as fs21 from "fs";
|
|
53049
53172
|
import * as path43 from "path";
|
|
53173
|
+
function detectLaravelProject(directory) {
|
|
53174
|
+
const signals = getLaravelSignals(directory);
|
|
53175
|
+
const signalCount = [
|
|
53176
|
+
signals.hasArtisanFile,
|
|
53177
|
+
signals.hasLaravelFrameworkDep,
|
|
53178
|
+
signals.hasConfigApp
|
|
53179
|
+
].filter(Boolean).length;
|
|
53180
|
+
return signalCount >= 2;
|
|
53181
|
+
}
|
|
53182
|
+
function getLaravelSignals(directory) {
|
|
53183
|
+
const hasArtisanFile = checkArtisanFile(directory);
|
|
53184
|
+
const hasLaravelFrameworkDep = checkLaravelFrameworkDep(directory);
|
|
53185
|
+
const hasConfigApp = checkConfigApp(directory);
|
|
53186
|
+
return { hasArtisanFile, hasLaravelFrameworkDep, hasConfigApp };
|
|
53187
|
+
}
|
|
53188
|
+
function checkArtisanFile(directory) {
|
|
53189
|
+
const artisanPath = path43.join(directory, "artisan");
|
|
53190
|
+
if (!fs21.existsSync(artisanPath))
|
|
53191
|
+
return false;
|
|
53192
|
+
try {
|
|
53193
|
+
return fs21.statSync(artisanPath).isFile();
|
|
53194
|
+
} catch {
|
|
53195
|
+
return false;
|
|
53196
|
+
}
|
|
53197
|
+
}
|
|
53198
|
+
function checkLaravelFrameworkDep(directory) {
|
|
53199
|
+
const composerPath = path43.join(directory, "composer.json");
|
|
53200
|
+
if (!fs21.existsSync(composerPath))
|
|
53201
|
+
return false;
|
|
53202
|
+
try {
|
|
53203
|
+
const content = fs21.readFileSync(composerPath, "utf-8");
|
|
53204
|
+
const parsed = JSON.parse(content);
|
|
53205
|
+
const require2 = parsed?.require ?? {};
|
|
53206
|
+
return typeof require2["laravel/framework"] === "string";
|
|
53207
|
+
} catch {
|
|
53208
|
+
return false;
|
|
53209
|
+
}
|
|
53210
|
+
}
|
|
53211
|
+
function checkConfigApp(directory) {
|
|
53212
|
+
return fs21.existsSync(path43.join(directory, "config", "app.php"));
|
|
53213
|
+
}
|
|
53214
|
+
var init_framework_detector = () => {};
|
|
53215
|
+
|
|
53216
|
+
// src/lang/backends/php.ts
|
|
53217
|
+
async function selectFramework3(dir) {
|
|
53218
|
+
if (detectLaravelProject(dir)) {
|
|
53219
|
+
return {
|
|
53220
|
+
name: "laravel",
|
|
53221
|
+
detectedVia: "Laravel signals (artisan / composer.json / config/app.php)"
|
|
53222
|
+
};
|
|
53223
|
+
}
|
|
53224
|
+
return null;
|
|
53225
|
+
}
|
|
53226
|
+
function buildPhpBackend() {
|
|
53227
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
|
|
53228
|
+
if (!profile) {
|
|
53229
|
+
throw new Error("buildPhpBackend: php profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
|
|
53230
|
+
}
|
|
53231
|
+
return {
|
|
53232
|
+
...defaultBackendFor(profile),
|
|
53233
|
+
selectFramework: selectFramework3
|
|
53234
|
+
};
|
|
53235
|
+
}
|
|
53236
|
+
var PROFILE_ID3 = "php";
|
|
53237
|
+
var init_php = __esm(() => {
|
|
53238
|
+
init_default_backend();
|
|
53239
|
+
init_framework_detector();
|
|
53240
|
+
init_profiles();
|
|
53241
|
+
});
|
|
53242
|
+
|
|
53243
|
+
// src/lang/backends/typescript.ts
|
|
53244
|
+
import * as fs22 from "fs";
|
|
53245
|
+
import * as path44 from "path";
|
|
53050
53246
|
function readPackageJsonRaw(dir) {
|
|
53051
53247
|
try {
|
|
53052
|
-
const content =
|
|
53248
|
+
const content = fs22.readFileSync(path44.join(dir, "package.json"), "utf-8");
|
|
53053
53249
|
return JSON.parse(content);
|
|
53054
53250
|
} catch {
|
|
53055
53251
|
return null;
|
|
@@ -53099,7 +53295,7 @@ function selectionFromFramework(profile, fwName, dir, detectedVia) {
|
|
|
53099
53295
|
};
|
|
53100
53296
|
}
|
|
53101
53297
|
async function selectTestFramework(dir) {
|
|
53102
|
-
const profile = LANGUAGE_REGISTRY.get(
|
|
53298
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID4);
|
|
53103
53299
|
if (!profile)
|
|
53104
53300
|
return null;
|
|
53105
53301
|
const pkg = readPackageJson(dir);
|
|
@@ -53121,7 +53317,7 @@ async function selectTestFramework(dir) {
|
|
|
53121
53317
|
return defaultSelectTestFramework(profile, dir);
|
|
53122
53318
|
}
|
|
53123
53319
|
function buildTestCommand(framework, files, dir, opts) {
|
|
53124
|
-
const profile = LANGUAGE_REGISTRY.get(
|
|
53320
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID4);
|
|
53125
53321
|
if (!profile)
|
|
53126
53322
|
return null;
|
|
53127
53323
|
return defaultBuildTestCommand(profile, framework, files, dir, opts);
|
|
@@ -53129,7 +53325,7 @@ function buildTestCommand(framework, files, dir, opts) {
|
|
|
53129
53325
|
function parseTestOutput(framework, stdout, stderr, exitCode) {
|
|
53130
53326
|
return defaultParseTestOutput(framework, stdout, stderr, exitCode);
|
|
53131
53327
|
}
|
|
53132
|
-
async function
|
|
53328
|
+
async function selectFramework4(dir) {
|
|
53133
53329
|
const pkg = readPackageJson(dir);
|
|
53134
53330
|
if (!pkg)
|
|
53135
53331
|
return null;
|
|
@@ -53198,19 +53394,19 @@ function extractImports4(_sourceFile, source) {
|
|
|
53198
53394
|
return [...out];
|
|
53199
53395
|
}
|
|
53200
53396
|
async function selectBuildCommand(dir) {
|
|
53201
|
-
const profile = LANGUAGE_REGISTRY.get(
|
|
53397
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID4);
|
|
53202
53398
|
if (!profile)
|
|
53203
53399
|
return null;
|
|
53204
53400
|
return defaultSelectBuildCommand(profile, dir);
|
|
53205
53401
|
}
|
|
53206
53402
|
async function testFilesFor(sourceFile, dir) {
|
|
53207
|
-
const profile = LANGUAGE_REGISTRY.get(
|
|
53403
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID4);
|
|
53208
53404
|
if (!profile)
|
|
53209
53405
|
return [];
|
|
53210
53406
|
return defaultTestFilesFor(profile, sourceFile, dir);
|
|
53211
53407
|
}
|
|
53212
53408
|
function buildTypescriptBackend() {
|
|
53213
|
-
const profile = LANGUAGE_REGISTRY.get(
|
|
53409
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID4);
|
|
53214
53410
|
if (!profile) {
|
|
53215
53411
|
throw new Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
|
|
53216
53412
|
}
|
|
@@ -53222,11 +53418,11 @@ function buildTypescriptBackend() {
|
|
|
53222
53418
|
extractImports: extractImports4,
|
|
53223
53419
|
selectBuildCommand,
|
|
53224
53420
|
testFilesFor,
|
|
53225
|
-
selectFramework:
|
|
53421
|
+
selectFramework: selectFramework4,
|
|
53226
53422
|
selectEntryPoints: selectEntryPoints3
|
|
53227
53423
|
};
|
|
53228
53424
|
}
|
|
53229
|
-
var
|
|
53425
|
+
var PROFILE_ID4 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals28;
|
|
53230
53426
|
var init_typescript = __esm(() => {
|
|
53231
53427
|
init_default_backend();
|
|
53232
53428
|
init_profiles();
|
|
@@ -53249,12 +53445,14 @@ function registerAllBackends() {
|
|
|
53249
53445
|
LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend());
|
|
53250
53446
|
LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend());
|
|
53251
53447
|
LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend());
|
|
53448
|
+
LANGUAGE_BACKEND_REGISTRY.register(buildPhpBackend());
|
|
53252
53449
|
registered = true;
|
|
53253
53450
|
}
|
|
53254
53451
|
var registered = false;
|
|
53255
53452
|
var init_backends = __esm(() => {
|
|
53256
53453
|
init_registry_backend();
|
|
53257
53454
|
init_go();
|
|
53455
|
+
init_php();
|
|
53258
53456
|
init_python();
|
|
53259
53457
|
init_typescript();
|
|
53260
53458
|
registerAllBackends();
|
|
@@ -53268,11 +53466,11 @@ __export(exports_dispatch, {
|
|
|
53268
53466
|
clearDispatchCache: () => clearDispatchCache,
|
|
53269
53467
|
_internals: () => _internals29
|
|
53270
53468
|
});
|
|
53271
|
-
import * as
|
|
53272
|
-
import * as
|
|
53469
|
+
import * as fs23 from "fs";
|
|
53470
|
+
import * as path45 from "path";
|
|
53273
53471
|
function safeReaddirSet(dir) {
|
|
53274
53472
|
try {
|
|
53275
|
-
return new Set(
|
|
53473
|
+
return new Set(fs23.readdirSync(dir));
|
|
53276
53474
|
} catch {
|
|
53277
53475
|
return new Set;
|
|
53278
53476
|
}
|
|
@@ -53286,14 +53484,14 @@ function manifestHash(dir) {
|
|
|
53286
53484
|
if (!entries.has(name))
|
|
53287
53485
|
continue;
|
|
53288
53486
|
try {
|
|
53289
|
-
const stat4 =
|
|
53487
|
+
const stat4 = fs23.statSync(path45.join(dir, name));
|
|
53290
53488
|
parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
|
|
53291
53489
|
} catch {}
|
|
53292
53490
|
}
|
|
53293
53491
|
return parts.join("|");
|
|
53294
53492
|
}
|
|
53295
53493
|
function findManifestRoot(start) {
|
|
53296
|
-
const resolved =
|
|
53494
|
+
const resolved = path45.resolve(start);
|
|
53297
53495
|
const cached3 = manifestRootCache.get(resolved);
|
|
53298
53496
|
if (cached3 !== undefined)
|
|
53299
53497
|
return cached3;
|
|
@@ -53312,7 +53510,7 @@ function findManifestRoot(start) {
|
|
|
53312
53510
|
return cur;
|
|
53313
53511
|
}
|
|
53314
53512
|
}
|
|
53315
|
-
const parent =
|
|
53513
|
+
const parent = path45.dirname(cur);
|
|
53316
53514
|
if (parent === cur)
|
|
53317
53515
|
break;
|
|
53318
53516
|
cur = parent;
|
|
@@ -53421,14 +53619,14 @@ var init_dispatch = __esm(() => {
|
|
|
53421
53619
|
});
|
|
53422
53620
|
|
|
53423
53621
|
// src/tools/test-runner.ts
|
|
53424
|
-
import * as
|
|
53425
|
-
import * as
|
|
53622
|
+
import * as fs24 from "fs";
|
|
53623
|
+
import * as path46 from "path";
|
|
53426
53624
|
async function estimateFanOut(sourceFiles, cwd) {
|
|
53427
53625
|
try {
|
|
53428
53626
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
53429
53627
|
const uniqueTestFiles = new Set;
|
|
53430
53628
|
for (const sourceFile of sourceFiles) {
|
|
53431
|
-
const resolvedPath =
|
|
53629
|
+
const resolvedPath = path46.resolve(cwd, sourceFile);
|
|
53432
53630
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
53433
53631
|
const testFiles = impactMap[normalizedPath];
|
|
53434
53632
|
if (testFiles) {
|
|
@@ -53510,19 +53708,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
53510
53708
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
53511
53709
|
}
|
|
53512
53710
|
function detectGoTest(cwd) {
|
|
53513
|
-
return
|
|
53711
|
+
return fs24.existsSync(path46.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
53514
53712
|
}
|
|
53515
53713
|
function detectJavaMaven(cwd) {
|
|
53516
|
-
return
|
|
53714
|
+
return fs24.existsSync(path46.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
53517
53715
|
}
|
|
53518
53716
|
function detectGradle(cwd) {
|
|
53519
|
-
const hasBuildFile =
|
|
53520
|
-
const hasGradlew =
|
|
53717
|
+
const hasBuildFile = fs24.existsSync(path46.join(cwd, "build.gradle")) || fs24.existsSync(path46.join(cwd, "build.gradle.kts"));
|
|
53718
|
+
const hasGradlew = fs24.existsSync(path46.join(cwd, "gradlew")) || fs24.existsSync(path46.join(cwd, "gradlew.bat"));
|
|
53521
53719
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
53522
53720
|
}
|
|
53523
53721
|
function detectDotnetTest(cwd) {
|
|
53524
53722
|
try {
|
|
53525
|
-
const files =
|
|
53723
|
+
const files = fs24.readdirSync(cwd);
|
|
53526
53724
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
53527
53725
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
53528
53726
|
} catch {
|
|
@@ -53530,25 +53728,25 @@ function detectDotnetTest(cwd) {
|
|
|
53530
53728
|
}
|
|
53531
53729
|
}
|
|
53532
53730
|
function detectCTest(cwd) {
|
|
53533
|
-
const hasSource =
|
|
53534
|
-
const hasBuildCache =
|
|
53731
|
+
const hasSource = fs24.existsSync(path46.join(cwd, "CMakeLists.txt"));
|
|
53732
|
+
const hasBuildCache = fs24.existsSync(path46.join(cwd, "CMakeCache.txt")) || fs24.existsSync(path46.join(cwd, "build", "CMakeCache.txt"));
|
|
53535
53733
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
53536
53734
|
}
|
|
53537
53735
|
function detectSwiftTest(cwd) {
|
|
53538
|
-
return
|
|
53736
|
+
return fs24.existsSync(path46.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
53539
53737
|
}
|
|
53540
53738
|
function detectDartTest(cwd) {
|
|
53541
|
-
return
|
|
53739
|
+
return fs24.existsSync(path46.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
53542
53740
|
}
|
|
53543
53741
|
function detectRSpec(cwd) {
|
|
53544
|
-
const hasRSpecFile =
|
|
53545
|
-
const hasGemfile =
|
|
53546
|
-
const hasSpecDir =
|
|
53742
|
+
const hasRSpecFile = fs24.existsSync(path46.join(cwd, ".rspec"));
|
|
53743
|
+
const hasGemfile = fs24.existsSync(path46.join(cwd, "Gemfile"));
|
|
53744
|
+
const hasSpecDir = fs24.existsSync(path46.join(cwd, "spec"));
|
|
53547
53745
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
53548
53746
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
53549
53747
|
}
|
|
53550
53748
|
function detectMinitest(cwd) {
|
|
53551
|
-
return
|
|
53749
|
+
return fs24.existsSync(path46.join(cwd, "test")) && (fs24.existsSync(path46.join(cwd, "Gemfile")) || fs24.existsSync(path46.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
53552
53750
|
}
|
|
53553
53751
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
53554
53752
|
try {
|
|
@@ -53611,9 +53809,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
53611
53809
|
async function detectTestFramework(cwd) {
|
|
53612
53810
|
const baseDir = cwd;
|
|
53613
53811
|
try {
|
|
53614
|
-
const packageJsonPath =
|
|
53615
|
-
if (
|
|
53616
|
-
const content =
|
|
53812
|
+
const packageJsonPath = path46.join(baseDir, "package.json");
|
|
53813
|
+
if (fs24.existsSync(packageJsonPath)) {
|
|
53814
|
+
const content = fs24.readFileSync(packageJsonPath, "utf-8");
|
|
53617
53815
|
const pkg = JSON.parse(content);
|
|
53618
53816
|
const _deps = pkg.dependencies || {};
|
|
53619
53817
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -53632,38 +53830,38 @@ async function detectTestFramework(cwd) {
|
|
|
53632
53830
|
return "jest";
|
|
53633
53831
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
53634
53832
|
return "mocha";
|
|
53635
|
-
if (
|
|
53833
|
+
if (fs24.existsSync(path46.join(baseDir, "bun.lockb")) || fs24.existsSync(path46.join(baseDir, "bun.lock"))) {
|
|
53636
53834
|
if (scripts.test?.includes("bun"))
|
|
53637
53835
|
return "bun";
|
|
53638
53836
|
}
|
|
53639
53837
|
}
|
|
53640
53838
|
} catch {}
|
|
53641
53839
|
try {
|
|
53642
|
-
const pyprojectTomlPath =
|
|
53643
|
-
const setupCfgPath =
|
|
53644
|
-
const requirementsTxtPath =
|
|
53645
|
-
if (
|
|
53646
|
-
const content =
|
|
53840
|
+
const pyprojectTomlPath = path46.join(baseDir, "pyproject.toml");
|
|
53841
|
+
const setupCfgPath = path46.join(baseDir, "setup.cfg");
|
|
53842
|
+
const requirementsTxtPath = path46.join(baseDir, "requirements.txt");
|
|
53843
|
+
if (fs24.existsSync(pyprojectTomlPath)) {
|
|
53844
|
+
const content = fs24.readFileSync(pyprojectTomlPath, "utf-8");
|
|
53647
53845
|
if (content.includes("[tool.pytest"))
|
|
53648
53846
|
return "pytest";
|
|
53649
53847
|
if (content.includes("pytest"))
|
|
53650
53848
|
return "pytest";
|
|
53651
53849
|
}
|
|
53652
|
-
if (
|
|
53653
|
-
const content =
|
|
53850
|
+
if (fs24.existsSync(setupCfgPath)) {
|
|
53851
|
+
const content = fs24.readFileSync(setupCfgPath, "utf-8");
|
|
53654
53852
|
if (content.includes("[pytest]"))
|
|
53655
53853
|
return "pytest";
|
|
53656
53854
|
}
|
|
53657
|
-
if (
|
|
53658
|
-
const content =
|
|
53855
|
+
if (fs24.existsSync(requirementsTxtPath)) {
|
|
53856
|
+
const content = fs24.readFileSync(requirementsTxtPath, "utf-8");
|
|
53659
53857
|
if (content.includes("pytest"))
|
|
53660
53858
|
return "pytest";
|
|
53661
53859
|
}
|
|
53662
53860
|
} catch {}
|
|
53663
53861
|
try {
|
|
53664
|
-
const cargoTomlPath =
|
|
53665
|
-
if (
|
|
53666
|
-
const content =
|
|
53862
|
+
const cargoTomlPath = path46.join(baseDir, "Cargo.toml");
|
|
53863
|
+
if (fs24.existsSync(cargoTomlPath)) {
|
|
53864
|
+
const content = fs24.readFileSync(cargoTomlPath, "utf-8");
|
|
53667
53865
|
if (content.includes("[dev-dependencies]")) {
|
|
53668
53866
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
53669
53867
|
return "cargo";
|
|
@@ -53672,10 +53870,10 @@ async function detectTestFramework(cwd) {
|
|
|
53672
53870
|
}
|
|
53673
53871
|
} catch {}
|
|
53674
53872
|
try {
|
|
53675
|
-
const pesterConfigPath =
|
|
53676
|
-
const pesterConfigJsonPath =
|
|
53677
|
-
const pesterPs1Path =
|
|
53678
|
-
if (
|
|
53873
|
+
const pesterConfigPath = path46.join(baseDir, "pester.config.ps1");
|
|
53874
|
+
const pesterConfigJsonPath = path46.join(baseDir, "pester.config.ps1.json");
|
|
53875
|
+
const pesterPs1Path = path46.join(baseDir, "tests.ps1");
|
|
53876
|
+
if (fs24.existsSync(pesterConfigPath) || fs24.existsSync(pesterConfigJsonPath) || fs24.existsSync(pesterPs1Path)) {
|
|
53679
53877
|
return "pester";
|
|
53680
53878
|
}
|
|
53681
53879
|
} catch {}
|
|
@@ -53703,12 +53901,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
53703
53901
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
53704
53902
|
}
|
|
53705
53903
|
function resolveWorkspacePath(file3, workingDir) {
|
|
53706
|
-
return
|
|
53904
|
+
return path46.isAbsolute(file3) ? path46.resolve(file3) : path46.resolve(workingDir, file3);
|
|
53707
53905
|
}
|
|
53708
53906
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
53709
53907
|
if (!preferRelative)
|
|
53710
53908
|
return absolutePath;
|
|
53711
|
-
return
|
|
53909
|
+
return path46.relative(workingDir, absolutePath);
|
|
53712
53910
|
}
|
|
53713
53911
|
function dedupePush(target, value) {
|
|
53714
53912
|
if (!target.includes(value)) {
|
|
@@ -53745,18 +53943,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
53745
53943
|
}
|
|
53746
53944
|
}
|
|
53747
53945
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
53748
|
-
const relativeDir =
|
|
53946
|
+
const relativeDir = path46.dirname(relativePath);
|
|
53749
53947
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
53750
53948
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
53751
|
-
const rootDir =
|
|
53752
|
-
return nestedRelativeDir ? [rootDir,
|
|
53949
|
+
const rootDir = path46.join(workingDir, dirName);
|
|
53950
|
+
return nestedRelativeDir ? [rootDir, path46.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
53753
53951
|
});
|
|
53754
53952
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
53755
53953
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
53756
|
-
directories.push(
|
|
53954
|
+
directories.push(path46.join(workingDir, "src/test/java", path46.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
53757
53955
|
}
|
|
53758
53956
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
53759
|
-
directories.push(
|
|
53957
|
+
directories.push(path46.join(workingDir, "src/test/kotlin", path46.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
53760
53958
|
}
|
|
53761
53959
|
return [...new Set(directories)];
|
|
53762
53960
|
}
|
|
@@ -53784,23 +53982,23 @@ function isLanguageSpecificTestFile(basename7) {
|
|
|
53784
53982
|
}
|
|
53785
53983
|
function isConventionTestFilePath(filePath) {
|
|
53786
53984
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
53787
|
-
const basename7 =
|
|
53985
|
+
const basename7 = path46.basename(filePath);
|
|
53788
53986
|
return hasCompoundTestExtension(basename7) || basename7.includes(".spec.") || basename7.includes(".test.") || isLanguageSpecificTestFile(basename7) || isTestDirectoryPath(normalizedPath);
|
|
53789
53987
|
}
|
|
53790
53988
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
53791
53989
|
const testFiles = [];
|
|
53792
53990
|
for (const file3 of sourceFiles) {
|
|
53793
53991
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
53794
|
-
const relativeFile =
|
|
53795
|
-
const basename7 =
|
|
53796
|
-
const dirname23 =
|
|
53797
|
-
const preferRelativeOutput = !
|
|
53992
|
+
const relativeFile = path46.relative(workingDir, absoluteFile);
|
|
53993
|
+
const basename7 = path46.basename(absoluteFile);
|
|
53994
|
+
const dirname23 = path46.dirname(absoluteFile);
|
|
53995
|
+
const preferRelativeOutput = !path46.isAbsolute(file3);
|
|
53798
53996
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
53799
53997
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
53800
53998
|
continue;
|
|
53801
53999
|
}
|
|
53802
54000
|
const nameWithoutExt = basename7.replace(/\.[^.]+$/, "");
|
|
53803
|
-
const ext =
|
|
54001
|
+
const ext = path46.extname(basename7);
|
|
53804
54002
|
const genericTestNames = [
|
|
53805
54003
|
`${nameWithoutExt}.spec${ext}`,
|
|
53806
54004
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -53809,7 +54007,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
53809
54007
|
const colocatedCandidates = [
|
|
53810
54008
|
...genericTestNames,
|
|
53811
54009
|
...languageSpecificTestNames
|
|
53812
|
-
].map((candidateName) =>
|
|
54010
|
+
].map((candidateName) => path46.join(dirname23, candidateName));
|
|
53813
54011
|
const testDirectoryNames = [
|
|
53814
54012
|
basename7,
|
|
53815
54013
|
...genericTestNames,
|
|
@@ -53818,11 +54016,11 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
53818
54016
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
53819
54017
|
const possibleTestFiles = [
|
|
53820
54018
|
...colocatedCandidates,
|
|
53821
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
53822
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
54019
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path46.join(dirname23, dirName, candidateName))),
|
|
54020
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path46.join(candidateDir, candidateName)))
|
|
53823
54021
|
];
|
|
53824
54022
|
for (const testFile of possibleTestFiles) {
|
|
53825
|
-
if (
|
|
54023
|
+
if (fs24.existsSync(testFile)) {
|
|
53826
54024
|
dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
|
|
53827
54025
|
}
|
|
53828
54026
|
}
|
|
@@ -53839,8 +54037,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53839
54037
|
for (const testFile of candidateTestFiles) {
|
|
53840
54038
|
try {
|
|
53841
54039
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
53842
|
-
const content =
|
|
53843
|
-
const testDir =
|
|
54040
|
+
const content = fs24.readFileSync(absoluteTestFile, "utf-8");
|
|
54041
|
+
const testDir = path46.dirname(absoluteTestFile);
|
|
53844
54042
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
53845
54043
|
let match;
|
|
53846
54044
|
match = importRegex.exec(content);
|
|
@@ -53848,8 +54046,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53848
54046
|
const importPath = match[1];
|
|
53849
54047
|
let resolvedImport;
|
|
53850
54048
|
if (importPath.startsWith(".")) {
|
|
53851
|
-
resolvedImport =
|
|
53852
|
-
const existingExt =
|
|
54049
|
+
resolvedImport = path46.resolve(testDir, importPath);
|
|
54050
|
+
const existingExt = path46.extname(resolvedImport);
|
|
53853
54051
|
if (!existingExt) {
|
|
53854
54052
|
for (const extToTry of [
|
|
53855
54053
|
".ts",
|
|
@@ -53860,7 +54058,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53860
54058
|
".cjs"
|
|
53861
54059
|
]) {
|
|
53862
54060
|
const withExt = resolvedImport + extToTry;
|
|
53863
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
54061
|
+
if (absoluteSourceFiles.includes(withExt) || fs24.existsSync(withExt)) {
|
|
53864
54062
|
resolvedImport = withExt;
|
|
53865
54063
|
break;
|
|
53866
54064
|
}
|
|
@@ -53869,12 +54067,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53869
54067
|
} else {
|
|
53870
54068
|
continue;
|
|
53871
54069
|
}
|
|
53872
|
-
const importBasename =
|
|
53873
|
-
const importDir =
|
|
54070
|
+
const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
|
|
54071
|
+
const importDir = path46.dirname(resolvedImport);
|
|
53874
54072
|
for (const sourceFile of absoluteSourceFiles) {
|
|
53875
|
-
const sourceDir =
|
|
53876
|
-
const sourceBasename =
|
|
53877
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
54073
|
+
const sourceDir = path46.dirname(sourceFile);
|
|
54074
|
+
const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
|
|
54075
|
+
const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
|
|
53878
54076
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
53879
54077
|
dedupePush(testFiles, testFile);
|
|
53880
54078
|
break;
|
|
@@ -53887,8 +54085,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53887
54085
|
while (match !== null) {
|
|
53888
54086
|
const importPath = match[1];
|
|
53889
54087
|
if (importPath.startsWith(".")) {
|
|
53890
|
-
let resolvedImport =
|
|
53891
|
-
const existingExt =
|
|
54088
|
+
let resolvedImport = path46.resolve(testDir, importPath);
|
|
54089
|
+
const existingExt = path46.extname(resolvedImport);
|
|
53892
54090
|
if (!existingExt) {
|
|
53893
54091
|
for (const extToTry of [
|
|
53894
54092
|
".ts",
|
|
@@ -53899,18 +54097,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53899
54097
|
".cjs"
|
|
53900
54098
|
]) {
|
|
53901
54099
|
const withExt = resolvedImport + extToTry;
|
|
53902
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
54100
|
+
if (absoluteSourceFiles.includes(withExt) || fs24.existsSync(withExt)) {
|
|
53903
54101
|
resolvedImport = withExt;
|
|
53904
54102
|
break;
|
|
53905
54103
|
}
|
|
53906
54104
|
}
|
|
53907
54105
|
}
|
|
53908
|
-
const importDir =
|
|
53909
|
-
const importBasename =
|
|
54106
|
+
const importDir = path46.dirname(resolvedImport);
|
|
54107
|
+
const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
|
|
53910
54108
|
for (const sourceFile of absoluteSourceFiles) {
|
|
53911
|
-
const sourceDir =
|
|
53912
|
-
const sourceBasename =
|
|
53913
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
54109
|
+
const sourceDir = path46.dirname(sourceFile);
|
|
54110
|
+
const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
|
|
54111
|
+
const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
|
|
53914
54112
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
53915
54113
|
dedupePush(testFiles, testFile);
|
|
53916
54114
|
break;
|
|
@@ -54030,8 +54228,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
|
|
|
54030
54228
|
return ["mvn", "test"];
|
|
54031
54229
|
case "gradle": {
|
|
54032
54230
|
const isWindows = process.platform === "win32";
|
|
54033
|
-
const hasGradlewBat =
|
|
54034
|
-
const hasGradlew =
|
|
54231
|
+
const hasGradlewBat = fs24.existsSync(path46.join(baseDir, "gradlew.bat"));
|
|
54232
|
+
const hasGradlew = fs24.existsSync(path46.join(baseDir, "gradlew"));
|
|
54035
54233
|
if (hasGradlewBat && isWindows)
|
|
54036
54234
|
return ["gradlew.bat", "test"];
|
|
54037
54235
|
if (hasGradlew)
|
|
@@ -54048,7 +54246,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
|
|
|
54048
54246
|
"cmake-build-release",
|
|
54049
54247
|
"out"
|
|
54050
54248
|
];
|
|
54051
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
54249
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs24.existsSync(path46.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
54052
54250
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
54053
54251
|
}
|
|
54054
54252
|
case "swift-test":
|
|
@@ -54482,13 +54680,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
54482
54680
|
};
|
|
54483
54681
|
}
|
|
54484
54682
|
const startTime = Date.now();
|
|
54485
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
54683
|
+
const vitestJsonOutputPath = framework === "vitest" ? path46.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
54486
54684
|
try {
|
|
54487
54685
|
if (vitestJsonOutputPath) {
|
|
54488
54686
|
try {
|
|
54489
|
-
|
|
54490
|
-
if (
|
|
54491
|
-
|
|
54687
|
+
fs24.mkdirSync(path46.dirname(vitestJsonOutputPath), { recursive: true });
|
|
54688
|
+
if (fs24.existsSync(vitestJsonOutputPath)) {
|
|
54689
|
+
fs24.unlinkSync(vitestJsonOutputPath);
|
|
54492
54690
|
}
|
|
54493
54691
|
} catch {}
|
|
54494
54692
|
}
|
|
@@ -54514,8 +54712,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
54514
54712
|
}
|
|
54515
54713
|
if (vitestJsonOutputPath) {
|
|
54516
54714
|
try {
|
|
54517
|
-
if (
|
|
54518
|
-
const vitestJsonOutput =
|
|
54715
|
+
if (fs24.existsSync(vitestJsonOutputPath)) {
|
|
54716
|
+
const vitestJsonOutput = fs24.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
54519
54717
|
if (vitestJsonOutput.trim().length > 0) {
|
|
54520
54718
|
output += (output ? `
|
|
54521
54719
|
` : "") + vitestJsonOutput;
|
|
@@ -54602,10 +54800,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
54602
54800
|
}
|
|
54603
54801
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
54604
54802
|
const normalized = testFile.replace(/\\/g, "/");
|
|
54605
|
-
if (!
|
|
54803
|
+
if (!path46.isAbsolute(testFile))
|
|
54606
54804
|
return normalized;
|
|
54607
|
-
const relative9 =
|
|
54608
|
-
if (relative9.startsWith("..") ||
|
|
54805
|
+
const relative9 = path46.relative(workingDir, testFile);
|
|
54806
|
+
if (relative9.startsWith("..") || path46.isAbsolute(relative9)) {
|
|
54609
54807
|
return normalized;
|
|
54610
54808
|
}
|
|
54611
54809
|
return relative9.replace(/\\/g, "/");
|
|
@@ -54712,28 +54910,26 @@ var init_test_runner = __esm(() => {
|
|
|
54712
54910
|
init_resolve_working_directory();
|
|
54713
54911
|
POWERSHELL_METACHARACTERS = /[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;
|
|
54714
54912
|
DISPATCH_FRAMEWORK_MAP = {
|
|
54715
|
-
"bun:test": "bun",
|
|
54716
54913
|
bun: "bun",
|
|
54717
54914
|
vitest: "vitest",
|
|
54718
54915
|
jest: "jest",
|
|
54719
54916
|
mocha: "mocha",
|
|
54720
54917
|
pytest: "pytest",
|
|
54721
|
-
"cargo test": "cargo",
|
|
54722
54918
|
cargo: "cargo",
|
|
54723
54919
|
pester: "pester",
|
|
54724
|
-
"go
|
|
54725
|
-
|
|
54726
|
-
|
|
54727
|
-
"
|
|
54728
|
-
"gradle-kts": "gradle",
|
|
54729
|
-
"dotnet test": "dotnet-test",
|
|
54920
|
+
"go-test": "go-test",
|
|
54921
|
+
maven: "maven",
|
|
54922
|
+
gradle: "gradle",
|
|
54923
|
+
"dotnet-test": "dotnet-test",
|
|
54730
54924
|
ctest: "ctest",
|
|
54731
|
-
"swift
|
|
54925
|
+
"swift-test": "swift-test",
|
|
54926
|
+
"dart-test": "dart-test",
|
|
54927
|
+
rspec: "rspec",
|
|
54928
|
+
minitest: "minitest",
|
|
54929
|
+
"bun:test": "bun",
|
|
54732
54930
|
"xcodebuild-test": "swift-test",
|
|
54733
54931
|
"flutter test": "dart-test",
|
|
54734
|
-
"dart test": "dart-test"
|
|
54735
|
-
rspec: "rspec",
|
|
54736
|
-
minitest: "minitest"
|
|
54932
|
+
"dart test": "dart-test"
|
|
54737
54933
|
};
|
|
54738
54934
|
COMPOUND_TEST_EXTENSIONS = [
|
|
54739
54935
|
".test.ts",
|
|
@@ -54945,7 +55141,7 @@ var init_test_runner = __esm(() => {
|
|
|
54945
55141
|
const sourceFiles = args.files.filter((file3) => {
|
|
54946
55142
|
if (directTestFiles.includes(file3))
|
|
54947
55143
|
return false;
|
|
54948
|
-
const ext =
|
|
55144
|
+
const ext = path46.extname(file3).toLowerCase();
|
|
54949
55145
|
return SOURCE_EXTENSIONS.has(ext);
|
|
54950
55146
|
});
|
|
54951
55147
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -54991,7 +55187,7 @@ var init_test_runner = __esm(() => {
|
|
|
54991
55187
|
if (isConventionTestFilePath(f)) {
|
|
54992
55188
|
return false;
|
|
54993
55189
|
}
|
|
54994
|
-
const ext =
|
|
55190
|
+
const ext = path46.extname(f).toLowerCase();
|
|
54995
55191
|
return SOURCE_EXTENSIONS.has(ext);
|
|
54996
55192
|
});
|
|
54997
55193
|
if (sourceFiles.length === 0) {
|
|
@@ -55041,7 +55237,7 @@ var init_test_runner = __esm(() => {
|
|
|
55041
55237
|
if (isConventionTestFilePath(f)) {
|
|
55042
55238
|
return false;
|
|
55043
55239
|
}
|
|
55044
|
-
const ext =
|
|
55240
|
+
const ext = path46.extname(f).toLowerCase();
|
|
55045
55241
|
return SOURCE_EXTENSIONS.has(ext);
|
|
55046
55242
|
});
|
|
55047
55243
|
if (sourceFiles.length === 0) {
|
|
@@ -55093,8 +55289,8 @@ var init_test_runner = __esm(() => {
|
|
|
55093
55289
|
}
|
|
55094
55290
|
if (impactResult.impactedTests.length > 0) {
|
|
55095
55291
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
55096
|
-
const relativePath =
|
|
55097
|
-
return
|
|
55292
|
+
const relativePath = path46.relative(workingDir, absPath);
|
|
55293
|
+
return path46.isAbsolute(relativePath) ? absPath : relativePath;
|
|
55098
55294
|
});
|
|
55099
55295
|
} else {
|
|
55100
55296
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -55172,8 +55368,8 @@ var init_test_runner = __esm(() => {
|
|
|
55172
55368
|
});
|
|
55173
55369
|
|
|
55174
55370
|
// src/services/preflight-service.ts
|
|
55175
|
-
import * as
|
|
55176
|
-
import * as
|
|
55371
|
+
import * as fs25 from "fs";
|
|
55372
|
+
import * as path47 from "path";
|
|
55177
55373
|
function validateDirectoryPath(dir) {
|
|
55178
55374
|
if (!dir || typeof dir !== "string") {
|
|
55179
55375
|
throw new Error("Directory path is required");
|
|
@@ -55181,8 +55377,8 @@ function validateDirectoryPath(dir) {
|
|
|
55181
55377
|
if (dir.includes("..")) {
|
|
55182
55378
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
55183
55379
|
}
|
|
55184
|
-
const normalized =
|
|
55185
|
-
const absolutePath =
|
|
55380
|
+
const normalized = path47.normalize(dir);
|
|
55381
|
+
const absolutePath = path47.isAbsolute(normalized) ? normalized : path47.resolve(normalized);
|
|
55186
55382
|
return absolutePath;
|
|
55187
55383
|
}
|
|
55188
55384
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -55205,9 +55401,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
55205
55401
|
}
|
|
55206
55402
|
function getPackageVersion(dir) {
|
|
55207
55403
|
try {
|
|
55208
|
-
const packagePath =
|
|
55209
|
-
if (
|
|
55210
|
-
const content =
|
|
55404
|
+
const packagePath = path47.join(dir, "package.json");
|
|
55405
|
+
if (fs25.existsSync(packagePath)) {
|
|
55406
|
+
const content = fs25.readFileSync(packagePath, "utf-8");
|
|
55211
55407
|
const pkg = JSON.parse(content);
|
|
55212
55408
|
return pkg.version ?? null;
|
|
55213
55409
|
}
|
|
@@ -55216,9 +55412,9 @@ function getPackageVersion(dir) {
|
|
|
55216
55412
|
}
|
|
55217
55413
|
function getChangelogVersion(dir) {
|
|
55218
55414
|
try {
|
|
55219
|
-
const changelogPath =
|
|
55220
|
-
if (
|
|
55221
|
-
const content =
|
|
55415
|
+
const changelogPath = path47.join(dir, "CHANGELOG.md");
|
|
55416
|
+
if (fs25.existsSync(changelogPath)) {
|
|
55417
|
+
const content = fs25.readFileSync(changelogPath, "utf-8");
|
|
55222
55418
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
55223
55419
|
if (match) {
|
|
55224
55420
|
return match[1];
|
|
@@ -55230,10 +55426,10 @@ function getChangelogVersion(dir) {
|
|
|
55230
55426
|
function getVersionFileVersion(dir) {
|
|
55231
55427
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
55232
55428
|
for (const file3 of possibleFiles) {
|
|
55233
|
-
const filePath =
|
|
55234
|
-
if (
|
|
55429
|
+
const filePath = path47.join(dir, file3);
|
|
55430
|
+
if (fs25.existsSync(filePath)) {
|
|
55235
55431
|
try {
|
|
55236
|
-
const content =
|
|
55432
|
+
const content = fs25.readFileSync(filePath, "utf-8").trim();
|
|
55237
55433
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
55238
55434
|
if (match) {
|
|
55239
55435
|
return match[1];
|
|
@@ -55572,8 +55768,8 @@ async function runEvidenceCheck(dir) {
|
|
|
55572
55768
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
55573
55769
|
const startTime = Date.now();
|
|
55574
55770
|
try {
|
|
55575
|
-
const specPath =
|
|
55576
|
-
if (!
|
|
55771
|
+
const specPath = path47.join(dir, ".swarm", "spec.md");
|
|
55772
|
+
if (!fs25.existsSync(specPath)) {
|
|
55577
55773
|
return {
|
|
55578
55774
|
type: "req_coverage",
|
|
55579
55775
|
status: "skip",
|
|
@@ -56689,8 +56885,8 @@ var init_manager3 = __esm(() => {
|
|
|
56689
56885
|
});
|
|
56690
56886
|
|
|
56691
56887
|
// src/commands/reset.ts
|
|
56692
|
-
import * as
|
|
56693
|
-
import * as
|
|
56888
|
+
import * as fs26 from "fs";
|
|
56889
|
+
import * as path48 from "path";
|
|
56694
56890
|
async function handleResetCommand(directory, args) {
|
|
56695
56891
|
const hasConfirm = args.includes("--confirm");
|
|
56696
56892
|
if (!hasConfirm) {
|
|
@@ -56718,8 +56914,8 @@ async function handleResetCommand(directory, args) {
|
|
|
56718
56914
|
for (const filename of filesToReset) {
|
|
56719
56915
|
try {
|
|
56720
56916
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
56721
|
-
if (
|
|
56722
|
-
|
|
56917
|
+
if (fs26.existsSync(resolvedPath)) {
|
|
56918
|
+
fs26.unlinkSync(resolvedPath);
|
|
56723
56919
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
56724
56920
|
} else {
|
|
56725
56921
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -56730,9 +56926,9 @@ async function handleResetCommand(directory, args) {
|
|
|
56730
56926
|
}
|
|
56731
56927
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
56732
56928
|
try {
|
|
56733
|
-
const rootPath =
|
|
56734
|
-
if (
|
|
56735
|
-
|
|
56929
|
+
const rootPath = path48.join(directory, filename);
|
|
56930
|
+
if (fs26.existsSync(rootPath)) {
|
|
56931
|
+
fs26.unlinkSync(rootPath);
|
|
56736
56932
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
56737
56933
|
}
|
|
56738
56934
|
} catch {}
|
|
@@ -56745,8 +56941,8 @@ async function handleResetCommand(directory, args) {
|
|
|
56745
56941
|
}
|
|
56746
56942
|
try {
|
|
56747
56943
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
56748
|
-
if (
|
|
56749
|
-
|
|
56944
|
+
if (fs26.existsSync(summariesPath)) {
|
|
56945
|
+
fs26.rmSync(summariesPath, { recursive: true, force: true });
|
|
56750
56946
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
56751
56947
|
} else {
|
|
56752
56948
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -56769,14 +56965,14 @@ var init_reset = __esm(() => {
|
|
|
56769
56965
|
});
|
|
56770
56966
|
|
|
56771
56967
|
// src/commands/reset-session.ts
|
|
56772
|
-
import * as
|
|
56773
|
-
import * as
|
|
56968
|
+
import * as fs27 from "fs";
|
|
56969
|
+
import * as path49 from "path";
|
|
56774
56970
|
async function handleResetSessionCommand(directory, _args) {
|
|
56775
56971
|
const results = [];
|
|
56776
56972
|
try {
|
|
56777
56973
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
56778
|
-
if (
|
|
56779
|
-
|
|
56974
|
+
if (fs27.existsSync(statePath)) {
|
|
56975
|
+
fs27.unlinkSync(statePath);
|
|
56780
56976
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
56781
56977
|
} else {
|
|
56782
56978
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -56785,15 +56981,15 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
56785
56981
|
results.push("\u274C Failed to delete state.json");
|
|
56786
56982
|
}
|
|
56787
56983
|
try {
|
|
56788
|
-
const sessionDir =
|
|
56789
|
-
if (
|
|
56790
|
-
const files =
|
|
56984
|
+
const sessionDir = path49.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
56985
|
+
if (fs27.existsSync(sessionDir)) {
|
|
56986
|
+
const files = fs27.readdirSync(sessionDir);
|
|
56791
56987
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
56792
56988
|
let deletedCount = 0;
|
|
56793
56989
|
for (const file3 of otherFiles) {
|
|
56794
|
-
const filePath =
|
|
56795
|
-
if (
|
|
56796
|
-
|
|
56990
|
+
const filePath = path49.join(sessionDir, file3);
|
|
56991
|
+
if (fs27.lstatSync(filePath).isFile()) {
|
|
56992
|
+
fs27.unlinkSync(filePath);
|
|
56797
56993
|
deletedCount++;
|
|
56798
56994
|
}
|
|
56799
56995
|
}
|
|
@@ -56823,7 +57019,7 @@ var init_reset_session = __esm(() => {
|
|
|
56823
57019
|
});
|
|
56824
57020
|
|
|
56825
57021
|
// src/summaries/manager.ts
|
|
56826
|
-
import * as
|
|
57022
|
+
import * as path50 from "path";
|
|
56827
57023
|
function sanitizeSummaryId(id) {
|
|
56828
57024
|
if (!id || id.length === 0) {
|
|
56829
57025
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -56846,7 +57042,7 @@ function sanitizeSummaryId(id) {
|
|
|
56846
57042
|
}
|
|
56847
57043
|
async function loadFullOutput(directory, id) {
|
|
56848
57044
|
const sanitizedId = sanitizeSummaryId(id);
|
|
56849
|
-
const relativePath =
|
|
57045
|
+
const relativePath = path50.join("summaries", `${sanitizedId}.json`);
|
|
56850
57046
|
validateSwarmPath(directory, relativePath);
|
|
56851
57047
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
56852
57048
|
if (content === null) {
|
|
@@ -56908,18 +57104,18 @@ var init_retrieve = __esm(() => {
|
|
|
56908
57104
|
});
|
|
56909
57105
|
|
|
56910
57106
|
// src/commands/rollback.ts
|
|
56911
|
-
import * as
|
|
56912
|
-
import * as
|
|
57107
|
+
import * as fs28 from "fs";
|
|
57108
|
+
import * as path51 from "path";
|
|
56913
57109
|
async function handleRollbackCommand(directory, args) {
|
|
56914
57110
|
const phaseArg = args[0];
|
|
56915
57111
|
if (!phaseArg) {
|
|
56916
57112
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
56917
|
-
if (!
|
|
57113
|
+
if (!fs28.existsSync(manifestPath2)) {
|
|
56918
57114
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
56919
57115
|
}
|
|
56920
57116
|
let manifest2;
|
|
56921
57117
|
try {
|
|
56922
|
-
manifest2 = JSON.parse(
|
|
57118
|
+
manifest2 = JSON.parse(fs28.readFileSync(manifestPath2, "utf-8"));
|
|
56923
57119
|
} catch {
|
|
56924
57120
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
56925
57121
|
}
|
|
@@ -56941,12 +57137,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56941
57137
|
return "Error: Phase number must be a positive integer.";
|
|
56942
57138
|
}
|
|
56943
57139
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
56944
|
-
if (!
|
|
57140
|
+
if (!fs28.existsSync(manifestPath)) {
|
|
56945
57141
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
56946
57142
|
}
|
|
56947
57143
|
let manifest;
|
|
56948
57144
|
try {
|
|
56949
|
-
manifest = JSON.parse(
|
|
57145
|
+
manifest = JSON.parse(fs28.readFileSync(manifestPath, "utf-8"));
|
|
56950
57146
|
} catch {
|
|
56951
57147
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
56952
57148
|
}
|
|
@@ -56956,10 +57152,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56956
57152
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
56957
57153
|
}
|
|
56958
57154
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
56959
|
-
if (!
|
|
57155
|
+
if (!fs28.existsSync(checkpointDir)) {
|
|
56960
57156
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
56961
57157
|
}
|
|
56962
|
-
const checkpointFiles =
|
|
57158
|
+
const checkpointFiles = fs28.readdirSync(checkpointDir);
|
|
56963
57159
|
if (checkpointFiles.length === 0) {
|
|
56964
57160
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
56965
57161
|
}
|
|
@@ -56974,10 +57170,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56974
57170
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
56975
57171
|
continue;
|
|
56976
57172
|
}
|
|
56977
|
-
const src =
|
|
56978
|
-
const dest =
|
|
57173
|
+
const src = path51.join(checkpointDir, file3);
|
|
57174
|
+
const dest = path51.join(swarmDir, file3);
|
|
56979
57175
|
try {
|
|
56980
|
-
|
|
57176
|
+
fs28.cpSync(src, dest, { recursive: true, force: true });
|
|
56981
57177
|
successes.push(file3);
|
|
56982
57178
|
} catch (error93) {
|
|
56983
57179
|
failures.push({ file: file3, error: error93.message });
|
|
@@ -56994,14 +57190,14 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56994
57190
|
].join(`
|
|
56995
57191
|
`);
|
|
56996
57192
|
}
|
|
56997
|
-
const existingLedgerPath =
|
|
56998
|
-
if (
|
|
56999
|
-
|
|
57193
|
+
const existingLedgerPath = path51.join(swarmDir, "plan-ledger.jsonl");
|
|
57194
|
+
if (fs28.existsSync(existingLedgerPath)) {
|
|
57195
|
+
fs28.unlinkSync(existingLedgerPath);
|
|
57000
57196
|
}
|
|
57001
57197
|
try {
|
|
57002
|
-
const planJsonPath =
|
|
57003
|
-
if (
|
|
57004
|
-
const planRaw =
|
|
57198
|
+
const planJsonPath = path51.join(swarmDir, "plan.json");
|
|
57199
|
+
if (fs28.existsSync(planJsonPath)) {
|
|
57200
|
+
const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
|
|
57005
57201
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
57006
57202
|
const planId = derivePlanId(plan);
|
|
57007
57203
|
const planHash = computePlanHash(plan);
|
|
@@ -57028,7 +57224,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
57028
57224
|
timestamp: new Date().toISOString()
|
|
57029
57225
|
};
|
|
57030
57226
|
try {
|
|
57031
|
-
|
|
57227
|
+
fs28.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
57032
57228
|
`);
|
|
57033
57229
|
} catch (error93) {
|
|
57034
57230
|
console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -57089,11 +57285,11 @@ Ensure this is a git repository with commit history.`;
|
|
|
57089
57285
|
const report = reportLines.filter(Boolean).join(`
|
|
57090
57286
|
`);
|
|
57091
57287
|
try {
|
|
57092
|
-
const
|
|
57093
|
-
const
|
|
57094
|
-
const reportPath =
|
|
57095
|
-
await
|
|
57096
|
-
await
|
|
57288
|
+
const fs29 = await import("fs/promises");
|
|
57289
|
+
const path52 = await import("path");
|
|
57290
|
+
const reportPath = path52.join(directory, ".swarm", "simulate-report.md");
|
|
57291
|
+
await fs29.mkdir(path52.dirname(reportPath), { recursive: true });
|
|
57292
|
+
await fs29.writeFile(reportPath, report, "utf-8");
|
|
57097
57293
|
} catch (err) {
|
|
57098
57294
|
const writeErr = err instanceof Error ? err.message : String(err);
|
|
57099
57295
|
warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
|
|
@@ -57115,15 +57311,15 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
57115
57311
|
}
|
|
57116
57312
|
|
|
57117
57313
|
// src/turbo/lean/state.ts
|
|
57118
|
-
import * as
|
|
57119
|
-
import * as
|
|
57314
|
+
import * as fs29 from "fs";
|
|
57315
|
+
import * as path52 from "path";
|
|
57120
57316
|
function nowISO2() {
|
|
57121
57317
|
return new Date().toISOString();
|
|
57122
57318
|
}
|
|
57123
57319
|
function ensureSwarmDir2(directory) {
|
|
57124
|
-
const swarmDir =
|
|
57125
|
-
if (!
|
|
57126
|
-
|
|
57320
|
+
const swarmDir = path52.resolve(directory, ".swarm");
|
|
57321
|
+
if (!fs29.existsSync(swarmDir)) {
|
|
57322
|
+
fs29.mkdirSync(swarmDir, { recursive: true });
|
|
57127
57323
|
}
|
|
57128
57324
|
return swarmDir;
|
|
57129
57325
|
}
|
|
@@ -57165,17 +57361,17 @@ function markStateUnreadable2(directory, reason) {
|
|
|
57165
57361
|
}
|
|
57166
57362
|
function readPersisted2(directory) {
|
|
57167
57363
|
try {
|
|
57168
|
-
const filePath =
|
|
57169
|
-
if (!
|
|
57364
|
+
const filePath = path52.join(directory, ".swarm", STATE_FILE2);
|
|
57365
|
+
if (!fs29.existsSync(filePath)) {
|
|
57170
57366
|
const seed = emptyPersisted2();
|
|
57171
57367
|
try {
|
|
57172
57368
|
ensureSwarmDir2(directory);
|
|
57173
|
-
|
|
57369
|
+
fs29.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
57174
57370
|
`, "utf-8");
|
|
57175
57371
|
} catch {}
|
|
57176
57372
|
return seed;
|
|
57177
57373
|
}
|
|
57178
|
-
const raw =
|
|
57374
|
+
const raw = fs29.readFileSync(filePath, "utf-8");
|
|
57179
57375
|
const parsed = JSON.parse(raw);
|
|
57180
57376
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
57181
57377
|
markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -57201,7 +57397,7 @@ function writePersisted2(directory, persisted) {
|
|
|
57201
57397
|
let payload;
|
|
57202
57398
|
try {
|
|
57203
57399
|
ensureSwarmDir2(directory);
|
|
57204
|
-
filePath =
|
|
57400
|
+
filePath = path52.join(directory, ".swarm", STATE_FILE2);
|
|
57205
57401
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
57206
57402
|
persisted.updatedAt = nowISO2();
|
|
57207
57403
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -57212,14 +57408,14 @@ function writePersisted2(directory, persisted) {
|
|
|
57212
57408
|
throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
|
|
57213
57409
|
}
|
|
57214
57410
|
try {
|
|
57215
|
-
|
|
57216
|
-
|
|
57411
|
+
fs29.writeFileSync(tmpPath, payload, "utf-8");
|
|
57412
|
+
fs29.renameSync(tmpPath, filePath);
|
|
57217
57413
|
} catch (error93) {
|
|
57218
57414
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
57219
57415
|
error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
|
|
57220
57416
|
try {
|
|
57221
|
-
if (
|
|
57222
|
-
|
|
57417
|
+
if (fs29.existsSync(tmpPath)) {
|
|
57418
|
+
fs29.unlinkSync(tmpPath);
|
|
57223
57419
|
}
|
|
57224
57420
|
} catch {}
|
|
57225
57421
|
throw new Error(`Lean Turbo state persistence failed: ${msg}`);
|
|
@@ -57328,10 +57524,10 @@ var init_context_budget_service = __esm(() => {
|
|
|
57328
57524
|
|
|
57329
57525
|
// src/services/status-service.ts
|
|
57330
57526
|
import * as fsSync2 from "fs";
|
|
57331
|
-
import * as
|
|
57527
|
+
import * as path53 from "path";
|
|
57332
57528
|
function readSpecStalenessSnapshot(directory) {
|
|
57333
57529
|
try {
|
|
57334
|
-
const p =
|
|
57530
|
+
const p = path53.join(directory, ".swarm", "spec-staleness.json");
|
|
57335
57531
|
if (!fsSync2.existsSync(p))
|
|
57336
57532
|
return { stale: false };
|
|
57337
57533
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -57856,8 +58052,8 @@ var init_write_retro2 = __esm(() => {
|
|
|
57856
58052
|
});
|
|
57857
58053
|
|
|
57858
58054
|
// src/commands/command-dispatch.ts
|
|
57859
|
-
import
|
|
57860
|
-
import
|
|
58055
|
+
import fs30 from "fs";
|
|
58056
|
+
import path54 from "path";
|
|
57861
58057
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
57862
58058
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
57863
58059
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -57893,11 +58089,11 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
57893
58089
|
`);
|
|
57894
58090
|
}
|
|
57895
58091
|
function maybeMarkFirstRun(directory) {
|
|
57896
|
-
const sentinelPath =
|
|
58092
|
+
const sentinelPath = path54.join(directory, ".swarm", ".first-run-complete");
|
|
57897
58093
|
try {
|
|
57898
|
-
const swarmDir =
|
|
57899
|
-
|
|
57900
|
-
|
|
58094
|
+
const swarmDir = path54.join(directory, ".swarm");
|
|
58095
|
+
fs30.mkdirSync(swarmDir, { recursive: true });
|
|
58096
|
+
fs30.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
57901
58097
|
`, { flag: "wx" });
|
|
57902
58098
|
return true;
|
|
57903
58099
|
} catch {
|
|
@@ -58645,24 +58841,24 @@ function validateAliases() {
|
|
|
58645
58841
|
}
|
|
58646
58842
|
aliasTargets.get(target).push(name);
|
|
58647
58843
|
const visited = new Set;
|
|
58648
|
-
const
|
|
58844
|
+
const path55 = [];
|
|
58649
58845
|
let current = target;
|
|
58650
58846
|
while (current) {
|
|
58651
58847
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
58652
58848
|
if (!currentEntry)
|
|
58653
58849
|
break;
|
|
58654
58850
|
if (visited.has(current)) {
|
|
58655
|
-
const cycleStart =
|
|
58851
|
+
const cycleStart = path55.indexOf(current);
|
|
58656
58852
|
const fullChain = [
|
|
58657
58853
|
name,
|
|
58658
|
-
...
|
|
58854
|
+
...path55.slice(0, cycleStart > 0 ? cycleStart : path55.length),
|
|
58659
58855
|
current
|
|
58660
58856
|
].join(" \u2192 ");
|
|
58661
58857
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
58662
58858
|
break;
|
|
58663
58859
|
}
|
|
58664
58860
|
visited.add(current);
|
|
58665
|
-
|
|
58861
|
+
path55.push(current);
|
|
58666
58862
|
current = currentEntry.aliasOf || "";
|
|
58667
58863
|
}
|
|
58668
58864
|
}
|
|
@@ -59281,68 +59477,68 @@ init_package();
|
|
|
59281
59477
|
init_registry();
|
|
59282
59478
|
init_cache_paths();
|
|
59283
59479
|
init_constants();
|
|
59284
|
-
import * as
|
|
59480
|
+
import * as fs31 from "fs";
|
|
59285
59481
|
import * as os8 from "os";
|
|
59286
|
-
import * as
|
|
59482
|
+
import * as path55 from "path";
|
|
59287
59483
|
var { version: version5 } = package_default;
|
|
59288
59484
|
var CONFIG_DIR = getPluginConfigDir();
|
|
59289
|
-
var OPENCODE_CONFIG_PATH =
|
|
59290
|
-
var PLUGIN_CONFIG_PATH =
|
|
59291
|
-
var PROMPTS_DIR =
|
|
59485
|
+
var OPENCODE_CONFIG_PATH = path55.join(CONFIG_DIR, "opencode.json");
|
|
59486
|
+
var PLUGIN_CONFIG_PATH = path55.join(CONFIG_DIR, "opencode-swarm.json");
|
|
59487
|
+
var PROMPTS_DIR = path55.join(CONFIG_DIR, "opencode-swarm");
|
|
59292
59488
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
59293
59489
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
59294
59490
|
function isSafeCachePath(p) {
|
|
59295
|
-
const resolved =
|
|
59296
|
-
const home =
|
|
59491
|
+
const resolved = path55.resolve(p);
|
|
59492
|
+
const home = path55.resolve(os8.homedir());
|
|
59297
59493
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
59298
59494
|
return false;
|
|
59299
59495
|
}
|
|
59300
|
-
const segments = resolved.split(
|
|
59496
|
+
const segments = resolved.split(path55.sep).filter((s) => s.length > 0);
|
|
59301
59497
|
if (segments.length < 4) {
|
|
59302
59498
|
return false;
|
|
59303
59499
|
}
|
|
59304
|
-
const leaf =
|
|
59500
|
+
const leaf = path55.basename(resolved);
|
|
59305
59501
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
59306
59502
|
return false;
|
|
59307
59503
|
}
|
|
59308
|
-
const parent =
|
|
59504
|
+
const parent = path55.basename(path55.dirname(resolved));
|
|
59309
59505
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
59310
59506
|
return false;
|
|
59311
59507
|
}
|
|
59312
|
-
const grandparent =
|
|
59508
|
+
const grandparent = path55.basename(path55.dirname(path55.dirname(resolved)));
|
|
59313
59509
|
if (grandparent !== "opencode") {
|
|
59314
59510
|
return false;
|
|
59315
59511
|
}
|
|
59316
59512
|
return true;
|
|
59317
59513
|
}
|
|
59318
59514
|
function isSafeLockFilePath(p) {
|
|
59319
|
-
const resolved =
|
|
59320
|
-
const home =
|
|
59515
|
+
const resolved = path55.resolve(p);
|
|
59516
|
+
const home = path55.resolve(os8.homedir());
|
|
59321
59517
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
59322
59518
|
return false;
|
|
59323
59519
|
}
|
|
59324
|
-
const segments = resolved.split(
|
|
59520
|
+
const segments = resolved.split(path55.sep).filter((s) => s.length > 0);
|
|
59325
59521
|
if (segments.length < 4) {
|
|
59326
59522
|
return false;
|
|
59327
59523
|
}
|
|
59328
|
-
const leaf =
|
|
59524
|
+
const leaf = path55.basename(resolved);
|
|
59329
59525
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
59330
59526
|
return false;
|
|
59331
59527
|
}
|
|
59332
|
-
const parent =
|
|
59528
|
+
const parent = path55.basename(path55.dirname(resolved));
|
|
59333
59529
|
if (parent !== "opencode") {
|
|
59334
59530
|
return false;
|
|
59335
59531
|
}
|
|
59336
59532
|
return true;
|
|
59337
59533
|
}
|
|
59338
59534
|
function ensureDir(dir) {
|
|
59339
|
-
if (!
|
|
59340
|
-
|
|
59535
|
+
if (!fs31.existsSync(dir)) {
|
|
59536
|
+
fs31.mkdirSync(dir, { recursive: true });
|
|
59341
59537
|
}
|
|
59342
59538
|
}
|
|
59343
59539
|
function loadJson(filepath) {
|
|
59344
59540
|
try {
|
|
59345
|
-
const content =
|
|
59541
|
+
const content = fs31.readFileSync(filepath, "utf-8");
|
|
59346
59542
|
const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
|
|
59347
59543
|
return JSON.parse(stripped);
|
|
59348
59544
|
} catch {
|
|
@@ -59350,14 +59546,14 @@ function loadJson(filepath) {
|
|
|
59350
59546
|
}
|
|
59351
59547
|
}
|
|
59352
59548
|
function saveJson(filepath, data) {
|
|
59353
|
-
|
|
59549
|
+
fs31.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
|
|
59354
59550
|
`, "utf-8");
|
|
59355
59551
|
}
|
|
59356
59552
|
function writeProjectConfigIfMissing(cwd) {
|
|
59357
59553
|
try {
|
|
59358
|
-
const opencodeDir =
|
|
59359
|
-
const projectConfigPath =
|
|
59360
|
-
if (
|
|
59554
|
+
const opencodeDir = path55.join(cwd, ".opencode");
|
|
59555
|
+
const projectConfigPath = path55.join(opencodeDir, "opencode-swarm.json");
|
|
59556
|
+
if (fs31.existsSync(projectConfigPath)) {
|
|
59361
59557
|
return;
|
|
59362
59558
|
}
|
|
59363
59559
|
ensureDir(opencodeDir);
|
|
@@ -59373,7 +59569,7 @@ async function install() {
|
|
|
59373
59569
|
`);
|
|
59374
59570
|
ensureDir(CONFIG_DIR);
|
|
59375
59571
|
ensureDir(PROMPTS_DIR);
|
|
59376
|
-
const LEGACY_CONFIG_PATH =
|
|
59572
|
+
const LEGACY_CONFIG_PATH = path55.join(CONFIG_DIR, "config.json");
|
|
59377
59573
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
59378
59574
|
if (!opencodeConfig) {
|
|
59379
59575
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -59420,7 +59616,7 @@ async function install() {
|
|
|
59420
59616
|
console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
|
|
59421
59617
|
${failed}`);
|
|
59422
59618
|
}
|
|
59423
|
-
if (!
|
|
59619
|
+
if (!fs31.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
59424
59620
|
const defaultConfig = {
|
|
59425
59621
|
agents: { ...DEFAULT_AGENT_CONFIGS },
|
|
59426
59622
|
max_iterations: 5
|
|
@@ -59499,14 +59695,14 @@ function evictPluginCaches() {
|
|
|
59499
59695
|
const cleared = [];
|
|
59500
59696
|
const failed = [];
|
|
59501
59697
|
for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
59502
|
-
if (!
|
|
59698
|
+
if (!fs31.existsSync(cachePath))
|
|
59503
59699
|
continue;
|
|
59504
59700
|
if (!isSafeCachePath(cachePath)) {
|
|
59505
59701
|
failed.push(`${cachePath} (refused: failed safety check)`);
|
|
59506
59702
|
continue;
|
|
59507
59703
|
}
|
|
59508
59704
|
try {
|
|
59509
|
-
|
|
59705
|
+
fs31.rmSync(cachePath, { recursive: true, force: true });
|
|
59510
59706
|
cleared.push(cachePath);
|
|
59511
59707
|
} catch (err) {
|
|
59512
59708
|
failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -59518,14 +59714,14 @@ function evictLockFiles() {
|
|
|
59518
59714
|
const cleared = [];
|
|
59519
59715
|
const failed = [];
|
|
59520
59716
|
for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
|
|
59521
|
-
if (!
|
|
59717
|
+
if (!fs31.existsSync(lockPath))
|
|
59522
59718
|
continue;
|
|
59523
59719
|
if (!isSafeLockFilePath(lockPath)) {
|
|
59524
59720
|
failed.push(`${lockPath} (refused: failed safety check)`);
|
|
59525
59721
|
continue;
|
|
59526
59722
|
}
|
|
59527
59723
|
try {
|
|
59528
|
-
|
|
59724
|
+
fs31.unlinkSync(lockPath);
|
|
59529
59725
|
cleared.push(lockPath);
|
|
59530
59726
|
} catch (err) {
|
|
59531
59727
|
const code = err?.code;
|
|
@@ -59544,7 +59740,7 @@ async function uninstall() {
|
|
|
59544
59740
|
`);
|
|
59545
59741
|
const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
59546
59742
|
if (!opencodeConfig) {
|
|
59547
|
-
if (
|
|
59743
|
+
if (fs31.existsSync(OPENCODE_CONFIG_PATH)) {
|
|
59548
59744
|
console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
|
|
59549
59745
|
return 1;
|
|
59550
59746
|
} else {
|
|
@@ -59576,13 +59772,13 @@ async function uninstall() {
|
|
|
59576
59772
|
console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
|
|
59577
59773
|
if (process.argv.includes("--clean")) {
|
|
59578
59774
|
let cleaned = false;
|
|
59579
|
-
if (
|
|
59580
|
-
|
|
59775
|
+
if (fs31.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
59776
|
+
fs31.unlinkSync(PLUGIN_CONFIG_PATH);
|
|
59581
59777
|
console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
|
|
59582
59778
|
cleaned = true;
|
|
59583
59779
|
}
|
|
59584
|
-
if (
|
|
59585
|
-
|
|
59780
|
+
if (fs31.existsSync(PROMPTS_DIR)) {
|
|
59781
|
+
fs31.rmSync(PROMPTS_DIR, { recursive: true });
|
|
59586
59782
|
console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
|
|
59587
59783
|
cleaned = true;
|
|
59588
59784
|
}
|