opencode-swarm 7.82.2 → 7.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cli/capability-probe-jevmgwmf.js +18 -0
- package/dist/cli/config-doctor-4tcdd9vt.js +35 -0
- package/dist/cli/dispatch-k86d928w.js +477 -0
- package/dist/cli/evidence-summary-service-g2znnd33.js +320 -0
- package/dist/cli/explorer-gz70sm9b.js +16 -0
- package/dist/cli/gate-evidence-y8zn7fe2.js +29 -0
- package/dist/cli/guardrail-explain-tcamcdfy.js +30 -0
- package/dist/cli/guardrail-log-fd14n96q.js +15 -0
- package/dist/cli/index-293f68mj.js +13538 -0
- package/dist/cli/index-8ra2qpk8.js +29027 -0
- package/dist/cli/index-a76rekgs.js +67 -0
- package/dist/cli/index-a82d6d87.js +1241 -0
- package/dist/cli/index-b9v501fr.js +371 -0
- package/dist/cli/index-bcp79s17.js +1673 -0
- package/dist/cli/index-ckntc5gf.js +91 -0
- package/dist/cli/index-d9fbxaqd.js +2314 -0
- package/dist/cli/index-e7h9bb6v.js +233 -0
- package/dist/cli/index-e8pk68cc.js +540 -0
- package/dist/cli/index-eb85wtx9.js +242 -0
- package/dist/cli/index-f8r50m3h.js +14505 -0
- package/dist/cli/index-fjwwrwr5.js +37 -0
- package/dist/cli/index-hz59hg4h.js +452 -0
- package/dist/cli/index-j710h2ge.js +412 -0
- package/dist/cli/index-jfgr5gye.js +110 -0
- package/dist/cli/index-jtqkh8jf.js +119 -0
- package/dist/cli/index-p0arc26j.js +28 -0
- package/dist/cli/index-p0ye10nd.js +222 -0
- package/dist/cli/index-pv2xmc9k.js +2391 -0
- package/dist/cli/index-red8fm8p.js +2914 -0
- package/dist/cli/index-wg3r6acj.js +2042 -0
- package/dist/cli/index-xw0bcy0v.js +583 -0
- package/dist/cli/index-yhsmmv2z.js +339 -0
- package/dist/cli/index-yx44zd0p.js +40 -0
- package/dist/cli/index-zfsbaaqh.js +29 -0
- package/dist/cli/index.js +73 -69703
- package/dist/cli/knowledge-store-n4x6zyk7.js +73 -0
- package/dist/cli/pending-delegations-pz61mrsz.js +255 -0
- package/dist/cli/pr-subscriptions-y1nn36e5.js +33 -0
- package/dist/cli/schema-c2dbzhm8.js +168 -0
- package/dist/cli/skill-generator-a5ehggyg.js +55 -0
- package/dist/cli/task-envelope-qn0qtnh0.js +90 -0
- package/dist/cli/telemetry-9bbyxrvn.js +20 -0
- package/dist/cli/workspace-snapshot-w58jr2ga.js +90 -0
- package/dist/commands/guardrail-explain.d.ts +1 -0
- package/dist/commands/guardrail-log.d.ts +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +7 -0
- package/dist/hooks/guardrails/audit-log.d.ts +114 -0
- package/dist/hooks/repo-graph-builder.d.ts +4 -1
- package/dist/index.js +3615 -2378
- package/dist/services/diagnose-service.d.ts +5 -0
- package/dist/services/guardrail-explain-service.d.ts +42 -0
- package/dist/services/guardrail-log-service.d.ts +10 -0
- package/dist/tools/repo-graph/types.d.ts +6 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1080,7 +1080,9 @@ Control how tool outputs are summarized for LLM context.
|
|
|
1080
1080
|
| `/swarm agents` | Registered agents with models and permissions |
|
|
1081
1081
|
| `/swarm history` | Completed phases with status |
|
|
1082
1082
|
| `/swarm config` | Current resolved configuration |
|
|
1083
|
-
| `/swarm diagnose` | Health check for `.swarm/` files and
|
|
1083
|
+
| `/swarm diagnose` | Health check for `.swarm/` files, config, and sandbox executor status |
|
|
1084
|
+
| `/swarm guardrail explain [--agent <role>] [--scope <path>] [--write <path>...] [--] <command>` | Dry-run guardrail decisions — report what would be allowed/blocked without executing anything |
|
|
1085
|
+
| `/swarm guardrail-log [--blocks-only]` | Read and print the guardrail decision log most-recent-first; `--blocks-only` shows only block decisions |
|
|
1084
1086
|
| `/swarm export` | Export plan and context as portable JSON |
|
|
1085
1087
|
| `/swarm evidence [task]` | Evidence bundles for a task or all tasks |
|
|
1086
1088
|
| `/swarm archive [--dry-run]` | Archive old evidence with retention policy |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
SandboxCapabilityProbe,
|
|
4
|
+
init_capability_probe,
|
|
5
|
+
isBubblewrapAvailable,
|
|
6
|
+
isSandboxExecAvailable,
|
|
7
|
+
isWindowsSandboxAvailable
|
|
8
|
+
} from "./index-hz59hg4h.js";
|
|
9
|
+
import"./index-yx44zd0p.js";
|
|
10
|
+
import"./index-a76rekgs.js";
|
|
11
|
+
init_capability_probe();
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
isWindowsSandboxAvailable,
|
|
15
|
+
isSandboxExecAvailable,
|
|
16
|
+
isBubblewrapAvailable,
|
|
17
|
+
SandboxCapabilityProbe
|
|
18
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
applySafeAutoFixes,
|
|
4
|
+
createConfigBackup,
|
|
5
|
+
detectStraySwarmDirs,
|
|
6
|
+
getConfigPaths,
|
|
7
|
+
readDoctorArtifact,
|
|
8
|
+
removeStraySwarmDir,
|
|
9
|
+
restoreFromBackup,
|
|
10
|
+
runConfigDoctor,
|
|
11
|
+
runConfigDoctorWithFixes,
|
|
12
|
+
shouldRunOnStartup,
|
|
13
|
+
writeBackupArtifact,
|
|
14
|
+
writeDoctorArtifact
|
|
15
|
+
} from "./index-a82d6d87.js";
|
|
16
|
+
import"./index-wg3r6acj.js";
|
|
17
|
+
import"./index-zfsbaaqh.js";
|
|
18
|
+
import"./index-p0arc26j.js";
|
|
19
|
+
import"./index-yx44zd0p.js";
|
|
20
|
+
import"./index-293f68mj.js";
|
|
21
|
+
import"./index-a76rekgs.js";
|
|
22
|
+
export {
|
|
23
|
+
writeDoctorArtifact,
|
|
24
|
+
writeBackupArtifact,
|
|
25
|
+
shouldRunOnStartup,
|
|
26
|
+
runConfigDoctorWithFixes,
|
|
27
|
+
runConfigDoctor,
|
|
28
|
+
restoreFromBackup,
|
|
29
|
+
removeStraySwarmDir,
|
|
30
|
+
readDoctorArtifact,
|
|
31
|
+
getConfigPaths,
|
|
32
|
+
detectStraySwarmDirs,
|
|
33
|
+
createConfigBackup,
|
|
34
|
+
applySafeAutoFixes
|
|
35
|
+
};
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
LANGUAGE_REGISTRY,
|
|
4
|
+
buildGoBackend,
|
|
5
|
+
buildPythonBackend,
|
|
6
|
+
defaultBackendFor,
|
|
7
|
+
defaultBuildTestCommand,
|
|
8
|
+
defaultParseTestOutput,
|
|
9
|
+
defaultSelectBuildCommand,
|
|
10
|
+
defaultSelectTestFramework,
|
|
11
|
+
defaultTestFilesFor,
|
|
12
|
+
detectProjectLanguages,
|
|
13
|
+
tokenizeCommand
|
|
14
|
+
} from "./index-f8r50m3h.js";
|
|
15
|
+
import"./index-zfsbaaqh.js";
|
|
16
|
+
import"./index-p0arc26j.js";
|
|
17
|
+
import"./index-yx44zd0p.js";
|
|
18
|
+
import"./index-b9v501fr.js";
|
|
19
|
+
import"./index-a76rekgs.js";
|
|
20
|
+
|
|
21
|
+
// src/lang/dispatch.ts
|
|
22
|
+
import * as fs3 from "fs";
|
|
23
|
+
import * as path3 from "path";
|
|
24
|
+
|
|
25
|
+
// src/lang/registry-backend.ts
|
|
26
|
+
class LanguageBackendRegistry {
|
|
27
|
+
backends = new Map;
|
|
28
|
+
register(backend) {
|
|
29
|
+
const existing = this.backends.get(backend.id);
|
|
30
|
+
if (existing && existing !== backend) {
|
|
31
|
+
throw new Error(`LanguageBackendRegistry: backend id "${backend.id}" registered twice. ` + `Each LanguageBackend.id must be unique.`);
|
|
32
|
+
}
|
|
33
|
+
this.backends.set(backend.id, backend);
|
|
34
|
+
}
|
|
35
|
+
get(id) {
|
|
36
|
+
return this.backends.get(id);
|
|
37
|
+
}
|
|
38
|
+
getOrDefault(id) {
|
|
39
|
+
const registered = this.backends.get(id);
|
|
40
|
+
if (registered)
|
|
41
|
+
return registered;
|
|
42
|
+
const profile = LANGUAGE_REGISTRY.get(id);
|
|
43
|
+
if (!profile)
|
|
44
|
+
return;
|
|
45
|
+
return defaultBackendFor(profile);
|
|
46
|
+
}
|
|
47
|
+
unregister(id) {
|
|
48
|
+
this.backends.delete(id);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var LANGUAGE_BACKEND_REGISTRY = new LanguageBackendRegistry;
|
|
52
|
+
|
|
53
|
+
// src/lang/framework-detector.ts
|
|
54
|
+
import * as fs from "fs";
|
|
55
|
+
import * as path from "path";
|
|
56
|
+
function detectLaravelProject(directory) {
|
|
57
|
+
const signals = getLaravelSignals(directory);
|
|
58
|
+
const signalCount = [
|
|
59
|
+
signals.hasArtisanFile,
|
|
60
|
+
signals.hasLaravelFrameworkDep,
|
|
61
|
+
signals.hasConfigApp
|
|
62
|
+
].filter(Boolean).length;
|
|
63
|
+
return signalCount >= 2;
|
|
64
|
+
}
|
|
65
|
+
function getLaravelSignals(directory) {
|
|
66
|
+
const hasArtisanFile = checkArtisanFile(directory);
|
|
67
|
+
const hasLaravelFrameworkDep = checkLaravelFrameworkDep(directory);
|
|
68
|
+
const hasConfigApp = checkConfigApp(directory);
|
|
69
|
+
return { hasArtisanFile, hasLaravelFrameworkDep, hasConfigApp };
|
|
70
|
+
}
|
|
71
|
+
function checkArtisanFile(directory) {
|
|
72
|
+
const artisanPath = path.join(directory, "artisan");
|
|
73
|
+
if (!fs.existsSync(artisanPath))
|
|
74
|
+
return false;
|
|
75
|
+
try {
|
|
76
|
+
return fs.statSync(artisanPath).isFile();
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function checkLaravelFrameworkDep(directory) {
|
|
82
|
+
const composerPath = path.join(directory, "composer.json");
|
|
83
|
+
if (!fs.existsSync(composerPath))
|
|
84
|
+
return false;
|
|
85
|
+
try {
|
|
86
|
+
const content = fs.readFileSync(composerPath, "utf-8");
|
|
87
|
+
const parsed = JSON.parse(content);
|
|
88
|
+
const require2 = parsed?.require ?? {};
|
|
89
|
+
return typeof require2["laravel/framework"] === "string";
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function checkConfigApp(directory) {
|
|
95
|
+
return fs.existsSync(path.join(directory, "config", "app.php"));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/lang/backends/php.ts
|
|
99
|
+
var PROFILE_ID = "php";
|
|
100
|
+
async function selectFramework(dir) {
|
|
101
|
+
if (detectLaravelProject(dir)) {
|
|
102
|
+
return {
|
|
103
|
+
name: "laravel",
|
|
104
|
+
detectedVia: "Laravel signals (artisan / composer.json / config/app.php)"
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function buildPhpBackend() {
|
|
110
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID);
|
|
111
|
+
if (!profile) {
|
|
112
|
+
throw new Error("buildPhpBackend: php profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
...defaultBackendFor(profile),
|
|
116
|
+
selectFramework
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/lang/backends/typescript.ts
|
|
121
|
+
import * as fs2 from "fs";
|
|
122
|
+
import * as path2 from "path";
|
|
123
|
+
var PROFILE_ID2 = "typescript";
|
|
124
|
+
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
125
|
+
var IMPORT_REGEX_BARE = /import\s+['"]([^'"]+)['"]/g;
|
|
126
|
+
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
127
|
+
var IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
128
|
+
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
129
|
+
function readPackageJsonRaw(dir) {
|
|
130
|
+
try {
|
|
131
|
+
const content = fs2.readFileSync(path2.join(dir, "package.json"), "utf-8");
|
|
132
|
+
return JSON.parse(content);
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function readPackageJson(dir) {
|
|
138
|
+
return _internals.readPackageJsonRaw(dir);
|
|
139
|
+
}
|
|
140
|
+
function readPackageJsonTestScript(dir) {
|
|
141
|
+
return readPackageJson(dir)?.scripts?.test ?? null;
|
|
142
|
+
}
|
|
143
|
+
function frameworkFromScriptsTest(script) {
|
|
144
|
+
if (script.includes("vitest"))
|
|
145
|
+
return "vitest";
|
|
146
|
+
if (script.includes("jest"))
|
|
147
|
+
return "jest";
|
|
148
|
+
if (script.includes("mocha"))
|
|
149
|
+
return "mocha";
|
|
150
|
+
if (script.includes("bun test"))
|
|
151
|
+
return "bun:test";
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
function frameworkFromDevDeps(devDeps) {
|
|
155
|
+
if (!devDeps)
|
|
156
|
+
return null;
|
|
157
|
+
if (devDeps.vitest || devDeps["@vitest/ui"])
|
|
158
|
+
return "vitest";
|
|
159
|
+
if (devDeps.jest || devDeps["@types/jest"])
|
|
160
|
+
return "jest";
|
|
161
|
+
if (devDeps.mocha || devDeps["@types/mocha"])
|
|
162
|
+
return "mocha";
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function selectionFromFramework(profile, fwName, dir, detectedVia) {
|
|
166
|
+
const fw = profile.test.frameworks.find((f) => f.name === fwName);
|
|
167
|
+
if (!fw)
|
|
168
|
+
return null;
|
|
169
|
+
const argv = tokenizeCommand(fw.cmd);
|
|
170
|
+
if (argv.length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
return {
|
|
173
|
+
name: fw.name,
|
|
174
|
+
cmd: argv,
|
|
175
|
+
cwd: dir,
|
|
176
|
+
detectedVia,
|
|
177
|
+
filesIgnored: false
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function selectTestFramework(dir) {
|
|
181
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
|
|
182
|
+
if (!profile)
|
|
183
|
+
return null;
|
|
184
|
+
const pkg = readPackageJson(dir);
|
|
185
|
+
const script = pkg?.scripts?.test;
|
|
186
|
+
if (script) {
|
|
187
|
+
const fwName = frameworkFromScriptsTest(script);
|
|
188
|
+
if (fwName) {
|
|
189
|
+
const sel = selectionFromFramework(profile, fwName, dir, "package.json#scripts.test");
|
|
190
|
+
if (sel)
|
|
191
|
+
return sel;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const devDepsFw = frameworkFromDevDeps(pkg?.devDependencies);
|
|
195
|
+
if (devDepsFw) {
|
|
196
|
+
const sel = selectionFromFramework(profile, devDepsFw, dir, "package.json#devDependencies");
|
|
197
|
+
if (sel)
|
|
198
|
+
return sel;
|
|
199
|
+
}
|
|
200
|
+
return defaultSelectTestFramework(profile, dir);
|
|
201
|
+
}
|
|
202
|
+
function buildTestCommand(framework, files, dir, opts) {
|
|
203
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
|
|
204
|
+
if (!profile)
|
|
205
|
+
return null;
|
|
206
|
+
return defaultBuildTestCommand(profile, framework, files, dir, opts);
|
|
207
|
+
}
|
|
208
|
+
function parseTestOutput(framework, stdout, stderr, exitCode) {
|
|
209
|
+
return defaultParseTestOutput(framework, stdout, stderr, exitCode);
|
|
210
|
+
}
|
|
211
|
+
async function selectFramework2(dir) {
|
|
212
|
+
const pkg = readPackageJson(dir);
|
|
213
|
+
if (!pkg)
|
|
214
|
+
return null;
|
|
215
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
216
|
+
const order = [
|
|
217
|
+
["next", "next"],
|
|
218
|
+
["nuxt", "nuxt"],
|
|
219
|
+
["@angular/core", "angular"],
|
|
220
|
+
["svelte", "svelte"],
|
|
221
|
+
["react", "react"],
|
|
222
|
+
["vue", "vue"],
|
|
223
|
+
["express", "express"],
|
|
224
|
+
["fastify", "fastify"],
|
|
225
|
+
["@nestjs/core", "nestjs"]
|
|
226
|
+
];
|
|
227
|
+
for (const [pkgName, displayName] of order) {
|
|
228
|
+
if (deps[pkgName]) {
|
|
229
|
+
return {
|
|
230
|
+
name: displayName,
|
|
231
|
+
detectedVia: `package.json#dependencies.${pkgName}`
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
async function selectEntryPoints(dir) {
|
|
238
|
+
const pkg = readPackageJson(dir);
|
|
239
|
+
if (!pkg)
|
|
240
|
+
return [];
|
|
241
|
+
const points = [];
|
|
242
|
+
const obj = pkg;
|
|
243
|
+
if (obj.bin) {
|
|
244
|
+
if (typeof obj.bin === "string")
|
|
245
|
+
points.push(obj.bin);
|
|
246
|
+
else
|
|
247
|
+
for (const v of Object.values(obj.bin))
|
|
248
|
+
points.push(v);
|
|
249
|
+
}
|
|
250
|
+
if (obj.main)
|
|
251
|
+
points.push(obj.main);
|
|
252
|
+
if (obj.module && obj.module !== obj.main)
|
|
253
|
+
points.push(obj.module);
|
|
254
|
+
if (obj.exports && typeof obj.exports === "object") {
|
|
255
|
+
const root = obj.exports["."];
|
|
256
|
+
if (typeof root === "string" && !points.includes(root))
|
|
257
|
+
points.push(root);
|
|
258
|
+
}
|
|
259
|
+
return [...new Set(points.filter((p) => p.length > 0))];
|
|
260
|
+
}
|
|
261
|
+
function extractImports(_sourceFile, source) {
|
|
262
|
+
const out = new Set;
|
|
263
|
+
for (const re of [
|
|
264
|
+
IMPORT_REGEX_ES,
|
|
265
|
+
IMPORT_REGEX_BARE,
|
|
266
|
+
IMPORT_REGEX_REQUIRE,
|
|
267
|
+
IMPORT_REGEX_DYNAMIC,
|
|
268
|
+
IMPORT_REGEX_REEXPORT
|
|
269
|
+
]) {
|
|
270
|
+
re.lastIndex = 0;
|
|
271
|
+
let m = re.exec(source);
|
|
272
|
+
while (m !== null) {
|
|
273
|
+
out.add(m[1]);
|
|
274
|
+
m = re.exec(source);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return [...out];
|
|
278
|
+
}
|
|
279
|
+
async function selectBuildCommand(dir) {
|
|
280
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
|
|
281
|
+
if (!profile)
|
|
282
|
+
return null;
|
|
283
|
+
return defaultSelectBuildCommand(profile, dir);
|
|
284
|
+
}
|
|
285
|
+
async function testFilesFor(sourceFile, dir) {
|
|
286
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
|
|
287
|
+
if (!profile)
|
|
288
|
+
return [];
|
|
289
|
+
return defaultTestFilesFor(profile, sourceFile, dir);
|
|
290
|
+
}
|
|
291
|
+
function buildTypescriptBackend() {
|
|
292
|
+
const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
|
|
293
|
+
if (!profile) {
|
|
294
|
+
throw new Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
...profile,
|
|
298
|
+
selectTestFramework,
|
|
299
|
+
buildTestCommand,
|
|
300
|
+
parseTestOutput,
|
|
301
|
+
extractImports,
|
|
302
|
+
selectBuildCommand,
|
|
303
|
+
testFilesFor,
|
|
304
|
+
selectFramework: selectFramework2,
|
|
305
|
+
selectEntryPoints
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
var _internals = {
|
|
309
|
+
readPackageJsonRaw,
|
|
310
|
+
readPackageJsonTestScript,
|
|
311
|
+
frameworkFromScriptsTest
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/lang/backends/index.ts
|
|
315
|
+
var registered = false;
|
|
316
|
+
function registerAllBackends() {
|
|
317
|
+
if (registered)
|
|
318
|
+
return;
|
|
319
|
+
LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend());
|
|
320
|
+
LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend());
|
|
321
|
+
LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend());
|
|
322
|
+
LANGUAGE_BACKEND_REGISTRY.register(buildPhpBackend());
|
|
323
|
+
registered = true;
|
|
324
|
+
}
|
|
325
|
+
registerAllBackends();
|
|
326
|
+
|
|
327
|
+
// src/lang/dispatch.ts
|
|
328
|
+
var _internals2 = {
|
|
329
|
+
detectProjectLanguages,
|
|
330
|
+
cacheCapacity: 64
|
|
331
|
+
};
|
|
332
|
+
var cache = new Map;
|
|
333
|
+
var insertCounter = 0;
|
|
334
|
+
var MANIFEST_FILES = [
|
|
335
|
+
"package.json",
|
|
336
|
+
"tsconfig.json",
|
|
337
|
+
"pyproject.toml",
|
|
338
|
+
"setup.py",
|
|
339
|
+
"setup.cfg",
|
|
340
|
+
"requirements.txt",
|
|
341
|
+
"Pipfile",
|
|
342
|
+
"Cargo.toml",
|
|
343
|
+
"go.mod",
|
|
344
|
+
"pom.xml",
|
|
345
|
+
"build.gradle",
|
|
346
|
+
"build.gradle.kts",
|
|
347
|
+
"build.zig",
|
|
348
|
+
"CMakeLists.txt",
|
|
349
|
+
"Makefile",
|
|
350
|
+
"meson.build",
|
|
351
|
+
"Package.swift",
|
|
352
|
+
"pubspec.yaml",
|
|
353
|
+
"Gemfile",
|
|
354
|
+
"composer.json"
|
|
355
|
+
];
|
|
356
|
+
var _MANIFEST_SET = new Set(MANIFEST_FILES);
|
|
357
|
+
function safeReaddirSet(dir) {
|
|
358
|
+
try {
|
|
359
|
+
return new Set(fs3.readdirSync(dir));
|
|
360
|
+
} catch {
|
|
361
|
+
return new Set;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function manifestHash(dir) {
|
|
365
|
+
const entries = safeReaddirSet(dir);
|
|
366
|
+
if (entries.size === 0)
|
|
367
|
+
return "";
|
|
368
|
+
const parts = [];
|
|
369
|
+
for (const name of MANIFEST_FILES) {
|
|
370
|
+
if (!entries.has(name))
|
|
371
|
+
continue;
|
|
372
|
+
try {
|
|
373
|
+
const stat = fs3.statSync(path3.join(dir, name));
|
|
374
|
+
parts.push(`${name}:${stat.size}:${stat.mtimeMs}:${stat.ino}`);
|
|
375
|
+
} catch {}
|
|
376
|
+
}
|
|
377
|
+
return parts.join("|");
|
|
378
|
+
}
|
|
379
|
+
var manifestRootCache = new Map;
|
|
380
|
+
function findManifestRoot(start) {
|
|
381
|
+
const resolved = path3.resolve(start);
|
|
382
|
+
const cached = manifestRootCache.get(resolved);
|
|
383
|
+
if (cached !== undefined)
|
|
384
|
+
return cached;
|
|
385
|
+
let cur = resolved;
|
|
386
|
+
for (let i = 0;i < 32; i++) {
|
|
387
|
+
const entries = safeReaddirSet(cur);
|
|
388
|
+
if (entries.size > 0) {
|
|
389
|
+
for (const name of MANIFEST_FILES) {
|
|
390
|
+
if (entries.has(name)) {
|
|
391
|
+
manifestRootCache.set(resolved, cur);
|
|
392
|
+
return cur;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (entries.has(".git")) {
|
|
396
|
+
manifestRootCache.set(resolved, cur);
|
|
397
|
+
return cur;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
const parent = path3.dirname(cur);
|
|
401
|
+
if (parent === cur)
|
|
402
|
+
break;
|
|
403
|
+
cur = parent;
|
|
404
|
+
}
|
|
405
|
+
manifestRootCache.set(resolved, start);
|
|
406
|
+
return start;
|
|
407
|
+
}
|
|
408
|
+
function evictIfNeeded() {
|
|
409
|
+
if (cache.size <= _internals2.cacheCapacity)
|
|
410
|
+
return;
|
|
411
|
+
let oldestKey;
|
|
412
|
+
let oldestOrder = Infinity;
|
|
413
|
+
for (const [k, v] of cache.entries()) {
|
|
414
|
+
if (v.insertOrder < oldestOrder) {
|
|
415
|
+
oldestOrder = v.insertOrder;
|
|
416
|
+
oldestKey = k;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
if (oldestKey !== undefined)
|
|
420
|
+
cache.delete(oldestKey);
|
|
421
|
+
}
|
|
422
|
+
async function pickBackend(dir) {
|
|
423
|
+
const root = findManifestRoot(dir);
|
|
424
|
+
const hash = manifestHash(root);
|
|
425
|
+
const cacheKey = root;
|
|
426
|
+
const cached = cache.get(cacheKey);
|
|
427
|
+
if (cached && cached.hash === hash) {
|
|
428
|
+
return cached.backend;
|
|
429
|
+
}
|
|
430
|
+
if (hash === "") {
|
|
431
|
+
cache.set(cacheKey, {
|
|
432
|
+
hash,
|
|
433
|
+
backend: null,
|
|
434
|
+
profiles: [],
|
|
435
|
+
insertOrder: insertCounter++
|
|
436
|
+
});
|
|
437
|
+
evictIfNeeded();
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
const profiles = await _internals2.detectProjectLanguages(root);
|
|
441
|
+
if (profiles.length === 0) {
|
|
442
|
+
cache.set(cacheKey, {
|
|
443
|
+
hash,
|
|
444
|
+
backend: null,
|
|
445
|
+
profiles: [],
|
|
446
|
+
insertOrder: insertCounter++
|
|
447
|
+
});
|
|
448
|
+
evictIfNeeded();
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
const winner = profiles[0];
|
|
452
|
+
const backend = LANGUAGE_BACKEND_REGISTRY.getOrDefault(winner.id) ?? null;
|
|
453
|
+
cache.set(cacheKey, {
|
|
454
|
+
hash,
|
|
455
|
+
backend,
|
|
456
|
+
profiles: profiles.map((p) => ({ id: p.id })),
|
|
457
|
+
insertOrder: insertCounter++
|
|
458
|
+
});
|
|
459
|
+
evictIfNeeded();
|
|
460
|
+
return backend;
|
|
461
|
+
}
|
|
462
|
+
function pickedProfiles(dir) {
|
|
463
|
+
const root = findManifestRoot(dir);
|
|
464
|
+
const cached = cache.get(root);
|
|
465
|
+
return cached?.profiles ?? [];
|
|
466
|
+
}
|
|
467
|
+
function clearDispatchCache() {
|
|
468
|
+
cache.clear();
|
|
469
|
+
manifestRootCache.clear();
|
|
470
|
+
insertCounter = 0;
|
|
471
|
+
}
|
|
472
|
+
export {
|
|
473
|
+
pickedProfiles,
|
|
474
|
+
pickBackend,
|
|
475
|
+
clearDispatchCache,
|
|
476
|
+
_internals2 as _internals
|
|
477
|
+
};
|