opencode-swarm 7.99.7 → 7.100.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/{config-doctor-1j77p1jy.js → config-doctor-g29kxhek.js} +2 -2
- package/dist/cli/{evidence-summary-service-ch74hb16.js → evidence-summary-service-vgw9vw3n.js} +1 -1
- package/dist/cli/{guardrail-explain-dkh5f7nf.js → guardrail-explain-z37rtfz4.js} +6 -6
- package/dist/cli/{guardrail-log-ya49kpwn.js → guardrail-log-ywajkn46.js} +3 -3
- package/dist/cli/{index-y3x3gvy6.js → index-3emh7rny.js} +3 -2
- package/dist/cli/{index-zyhd4mnn.js → index-4xqnktvr.js} +2 -2
- package/dist/cli/{index-h9ptj4b1.js → index-5bstvpct.js} +1 -1
- package/dist/cli/{index-sz3kw59p.js → index-bcr2a549.js} +7 -7
- package/dist/cli/{index-7hnwnw5g.js → index-m0qshbr6.js} +41 -1
- package/dist/cli/{index-xsswhy6k.js → index-pj3a5fbt.js} +1 -1
- package/dist/cli/{index-wpnam1jh.js → index-qvdxzjqt.js} +1069 -316
- package/dist/cli/{index-0d3pmjf9.js → index-rpb763g8.js} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/{schema-nz638xc3.js → schema-n7pd65qq.js} +1 -1
- package/dist/config/schema.d.ts +40 -0
- package/dist/git/branch.d.ts +16 -0
- package/dist/index.js +2253 -1440
- package/dist/lang/runtime.d.ts +3 -0
- package/dist/memory/config.d.ts +38 -0
- package/dist/memory/embeddings/cache.d.ts +25 -0
- package/dist/memory/embeddings/fusion.d.ts +56 -0
- package/dist/memory/embeddings/local-provider.d.ts +57 -0
- package/dist/memory/embeddings/reranker.d.ts +42 -0
- package/dist/memory/embeddings/types.d.ts +27 -0
- package/dist/memory/scoring.d.ts +1 -0
- package/dist/memory/sqlite-provider.d.ts +19 -0
- package/package.json +1 -1
- package/tests/fixtures/memory-recall/paraphrase-auth.json +64 -0
- package/tests/fixtures/memory-recall/paraphrase-concurrency.json +64 -0
- package/tests/fixtures/memory-recall/paraphrase-deployment.json +64 -0
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
readDoctorArtifact,
|
|
58
58
|
removeStraySwarmDir,
|
|
59
59
|
runConfigDoctor
|
|
60
|
-
} from "./index-
|
|
60
|
+
} from "./index-rpb763g8.js";
|
|
61
61
|
import {
|
|
62
62
|
AGENT_TOOL_MAP,
|
|
63
63
|
ALL_SUBAGENT_NAMES,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
TOOL_NAME_SET,
|
|
71
71
|
resolveExternalSkillsConfig,
|
|
72
72
|
stripKnownSwarmPrefix
|
|
73
|
-
} from "./index-
|
|
73
|
+
} from "./index-m0qshbr6.js";
|
|
74
74
|
import {
|
|
75
75
|
MAX_TRANSIENT_RETRIES,
|
|
76
76
|
PlanSchema,
|
|
@@ -114,7 +114,7 @@ import {
|
|
|
114
114
|
transientBackoff,
|
|
115
115
|
validateProjectRoot,
|
|
116
116
|
writeProjectedSpecSync
|
|
117
|
-
} from "./index-
|
|
117
|
+
} from "./index-3emh7rny.js";
|
|
118
118
|
import {
|
|
119
119
|
_internals as _internals2,
|
|
120
120
|
_internals1 as _internals3,
|
|
@@ -909,7 +909,7 @@ var init_executor = __esm(() => {
|
|
|
909
909
|
// package.json
|
|
910
910
|
var package_default = {
|
|
911
911
|
name: "opencode-swarm",
|
|
912
|
-
version: "7.
|
|
912
|
+
version: "7.100.1",
|
|
913
913
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
914
914
|
main: "dist/index.js",
|
|
915
915
|
types: "dist/index.d.ts",
|
|
@@ -13089,6 +13089,7 @@ var ACTIVE_STATE_TO_CLEAN = [
|
|
|
13089
13089
|
"swarm.db-shm",
|
|
13090
13090
|
"swarm.db-wal"
|
|
13091
13091
|
];
|
|
13092
|
+
var TERMINAL_STATE_FILES = ["plan.json", "plan-ledger.jsonl"];
|
|
13092
13093
|
var KNOWLEDGE_FAMILY_ARTIFACTS = new Set([
|
|
13093
13094
|
"knowledge.jsonl",
|
|
13094
13095
|
"knowledge-rejected.jsonl"
|
|
@@ -13362,7 +13363,7 @@ async function runFinalizeStage(ctx) {
|
|
|
13362
13363
|
}
|
|
13363
13364
|
}
|
|
13364
13365
|
try {
|
|
13365
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
13366
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-n7pd65qq.js");
|
|
13366
13367
|
const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
|
|
13367
13368
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
13368
13369
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -13579,6 +13580,10 @@ async function runCleanStage(ctx) {
|
|
|
13579
13580
|
}
|
|
13580
13581
|
if (!ctx.archivedActiveStateFiles.has(artifact)) {
|
|
13581
13582
|
const reason = ctx.archiveFailureReasons?.get(artifact);
|
|
13583
|
+
if (TERMINAL_STATE_FILES.includes(artifact)) {
|
|
13584
|
+
ctx.warnings.push(reason ? `${artifact} was not archived (${reason}); removing it anyway to prevent CLOSED-plan resurrection next session \u2014 no archive copy retained.` : `${artifact} was not archived; removing it anyway to prevent CLOSED-plan resurrection next session \u2014 no archive copy retained.`);
|
|
13585
|
+
continue;
|
|
13586
|
+
}
|
|
13582
13587
|
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
13583
13588
|
continue;
|
|
13584
13589
|
}
|
|
@@ -13686,6 +13691,20 @@ async function runCleanStage(ctx) {
|
|
|
13686
13691
|
if (tmpFilesRemoved > 0) {
|
|
13687
13692
|
cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
|
|
13688
13693
|
}
|
|
13694
|
+
for (const terminalFile of TERMINAL_STATE_FILES) {
|
|
13695
|
+
try {
|
|
13696
|
+
await fs13.unlink(path26.join(ctx.swarmDir, terminalFile));
|
|
13697
|
+
if (!cleanedFiles.includes(terminalFile)) {
|
|
13698
|
+
cleanedFiles.push(terminalFile);
|
|
13699
|
+
}
|
|
13700
|
+
} catch (err) {
|
|
13701
|
+
const errno = err?.code;
|
|
13702
|
+
if (errno === "ENOENT") {} else {
|
|
13703
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
13704
|
+
ctx.warnings.push(`Failed to remove terminal-state file ${terminalFile} [${errno ?? "unknown"}]: ${reason}`);
|
|
13705
|
+
}
|
|
13706
|
+
}
|
|
13707
|
+
}
|
|
13689
13708
|
clearAllScopes(ctx.directory);
|
|
13690
13709
|
const contextPath = path26.join(ctx.swarmDir, "context.md");
|
|
13691
13710
|
const contextContent = [
|
|
@@ -16153,6 +16172,15 @@ async function checkKnowledgeHealth(directory) {
|
|
|
16153
16172
|
// src/services/diagnose-service.ts
|
|
16154
16173
|
var { version: version2 } = package_default;
|
|
16155
16174
|
var sandboxCapabilityProbe = new SandboxCapabilityProbe;
|
|
16175
|
+
var REQUIRED_CACHE_GRAMMAR_ASSETS = [
|
|
16176
|
+
"tree-sitter.wasm",
|
|
16177
|
+
"tree-sitter-javascript.wasm",
|
|
16178
|
+
"tree-sitter-typescript.wasm"
|
|
16179
|
+
];
|
|
16180
|
+
function resolveCachePackageRoot(cachePath) {
|
|
16181
|
+
const nestedPackageRoot = path33.join(cachePath, "node_modules", "opencode-swarm");
|
|
16182
|
+
return existsSync18(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
16183
|
+
}
|
|
16156
16184
|
var _internals24 = {
|
|
16157
16185
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
16158
16186
|
getSandboxExecutor: getExecutor
|
|
@@ -16933,14 +16961,21 @@ async function getDiagnoseData(directory) {
|
|
|
16933
16961
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
16934
16962
|
continue;
|
|
16935
16963
|
}
|
|
16936
|
-
const
|
|
16964
|
+
const packageRoot = resolveCachePackageRoot(cachePath);
|
|
16965
|
+
const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
|
|
16966
|
+
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync18(path33.join(packageRoot, "dist", "lang", "grammars", file)));
|
|
16967
|
+
const pkgJsonPath = path33.join(packageRoot, "package.json");
|
|
16937
16968
|
try {
|
|
16938
16969
|
const raw = readFileSync10(pkgJsonPath, "utf-8");
|
|
16939
16970
|
const parsed = JSON.parse(raw);
|
|
16940
16971
|
const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
|
|
16941
|
-
|
|
16972
|
+
if (missingGrammarAssets.length > 0) {
|
|
16973
|
+
cacheRows.push(`\u26A0\uFE0F ${cacheLabel} \u2014 v${installedVersion}, missing grammar assets: ${missingGrammarAssets.join(", ")}; run \`bunx opencode-swarm update\` and restart OpenCode`);
|
|
16974
|
+
continue;
|
|
16975
|
+
}
|
|
16976
|
+
cacheRows.push(`\u2705 ${cacheLabel} \u2014 v${installedVersion}`);
|
|
16942
16977
|
} catch {
|
|
16943
|
-
cacheRows.push(`\u26A0\uFE0F ${
|
|
16978
|
+
cacheRows.push(`\u26A0\uFE0F ${cacheLabel} \u2014 present (package.json unreadable)`);
|
|
16944
16979
|
}
|
|
16945
16980
|
} catch {
|
|
16946
16981
|
cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 status unknown (read error)`);
|
|
@@ -17154,7 +17189,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
17154
17189
|
const result = runConfigDoctor(config, directory);
|
|
17155
17190
|
let output;
|
|
17156
17191
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
17157
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
17192
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-g29kxhek.js");
|
|
17158
17193
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true);
|
|
17159
17194
|
output = formatDoctorMarkdown(fixResult.result);
|
|
17160
17195
|
} else {
|
|
@@ -17967,7 +18002,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
17967
18002
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
17968
18003
|
}
|
|
17969
18004
|
async function handleEvidenceSummaryCommand(directory) {
|
|
17970
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
18005
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-vgw9vw3n.js");
|
|
17971
18006
|
const artifact = await buildEvidenceSummary(directory);
|
|
17972
18007
|
if (!artifact) {
|
|
17973
18008
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -20521,7 +20556,7 @@ ${USAGE7}`;
|
|
|
20521
20556
|
|
|
20522
20557
|
// src/commands/memory.ts
|
|
20523
20558
|
import { existsSync as existsSync27 } from "fs";
|
|
20524
|
-
import * as
|
|
20559
|
+
import * as path50 from "path";
|
|
20525
20560
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20526
20561
|
|
|
20527
20562
|
// src/memory/config.ts
|
|
@@ -20556,6 +20591,24 @@ var DEFAULT_CONSOLIDATION_CONFIG = {
|
|
|
20556
20591
|
autoApplyMinConfidence: 0.6,
|
|
20557
20592
|
decayHalfLifeDays: { ...DEFAULT_DECAY_HALF_LIFE_DAYS }
|
|
20558
20593
|
};
|
|
20594
|
+
var DEFAULT_EMBEDDINGS_CONFIG = {
|
|
20595
|
+
enabled: false,
|
|
20596
|
+
model: "Xenova/all-MiniLM-L6-v2",
|
|
20597
|
+
dimension: 384,
|
|
20598
|
+
cacheSize: 256
|
|
20599
|
+
};
|
|
20600
|
+
var DEFAULT_RETRIEVAL_CONFIG = {
|
|
20601
|
+
rrfK: 60,
|
|
20602
|
+
weights: {
|
|
20603
|
+
lexical: 0.5,
|
|
20604
|
+
dense: 0.4,
|
|
20605
|
+
metadata: 0.1
|
|
20606
|
+
},
|
|
20607
|
+
rerank: {
|
|
20608
|
+
enabled: false
|
|
20609
|
+
},
|
|
20610
|
+
latencyBudgetMs: 250
|
|
20611
|
+
};
|
|
20559
20612
|
var DEFAULT_MEMORY_CONFIG = {
|
|
20560
20613
|
enabled: false,
|
|
20561
20614
|
provider: "sqlite",
|
|
@@ -20592,6 +20645,8 @@ var DEFAULT_MEMORY_CONFIG = {
|
|
|
20592
20645
|
...DEFAULT_CONSOLIDATION_CONFIG,
|
|
20593
20646
|
decayHalfLifeDays: { ...DEFAULT_DECAY_HALF_LIFE_DAYS }
|
|
20594
20647
|
},
|
|
20648
|
+
embeddings: { ...DEFAULT_EMBEDDINGS_CONFIG },
|
|
20649
|
+
retrieval: { ...DEFAULT_RETRIEVAL_CONFIG },
|
|
20595
20650
|
hardDelete: false
|
|
20596
20651
|
};
|
|
20597
20652
|
var DURABLE_MEMORY_KINDS = new Set([
|
|
@@ -20648,6 +20703,22 @@ function resolveMemoryConfig(input) {
|
|
|
20648
20703
|
...DEFAULT_MEMORY_CONFIG.consolidation.decayHalfLifeDays,
|
|
20649
20704
|
...input?.consolidation?.decayHalfLifeDays ?? {}
|
|
20650
20705
|
}
|
|
20706
|
+
},
|
|
20707
|
+
embeddings: {
|
|
20708
|
+
...DEFAULT_MEMORY_CONFIG.embeddings,
|
|
20709
|
+
...input?.embeddings ?? {}
|
|
20710
|
+
},
|
|
20711
|
+
retrieval: {
|
|
20712
|
+
...DEFAULT_MEMORY_CONFIG.retrieval,
|
|
20713
|
+
...input?.retrieval ?? {},
|
|
20714
|
+
weights: {
|
|
20715
|
+
...DEFAULT_MEMORY_CONFIG.retrieval.weights,
|
|
20716
|
+
...input?.retrieval?.weights ?? {}
|
|
20717
|
+
},
|
|
20718
|
+
rerank: {
|
|
20719
|
+
...DEFAULT_MEMORY_CONFIG.retrieval.rerank,
|
|
20720
|
+
...input?.retrieval?.rerank ?? {}
|
|
20721
|
+
}
|
|
20651
20722
|
}
|
|
20652
20723
|
};
|
|
20653
20724
|
}
|
|
@@ -20662,8 +20733,8 @@ class MemoryValidationError extends Error {
|
|
|
20662
20733
|
}
|
|
20663
20734
|
// src/memory/evaluation.ts
|
|
20664
20735
|
import * as fs19 from "fs/promises";
|
|
20665
|
-
import * as
|
|
20666
|
-
import * as
|
|
20736
|
+
import * as os12 from "os";
|
|
20737
|
+
import * as path48 from "path";
|
|
20667
20738
|
|
|
20668
20739
|
// src/memory/local-jsonl-provider.ts
|
|
20669
20740
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -21935,18 +22006,372 @@ async function writeJsonlAtomic(filePath, values) {
|
|
|
21935
22006
|
|
|
21936
22007
|
// src/memory/provider-pool.ts
|
|
21937
22008
|
import { realpathSync as realpathSync2 } from "fs";
|
|
21938
|
-
import * as
|
|
22009
|
+
import * as path47 from "path";
|
|
21939
22010
|
|
|
21940
22011
|
// src/memory/sqlite-provider.ts
|
|
21941
22012
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
22013
|
+
import { mkdirSync as mkdirSync17 } from "fs";
|
|
22014
|
+
import { createRequire as createRequire4 } from "module";
|
|
22015
|
+
import * as path46 from "path";
|
|
22016
|
+
|
|
22017
|
+
// src/memory/embeddings/cache.ts
|
|
22018
|
+
var DEFAULT_CACHE_SIZE = 256;
|
|
22019
|
+
function normalizeQuery(query) {
|
|
22020
|
+
return query.toLowerCase().trim();
|
|
22021
|
+
}
|
|
22022
|
+
function compositeKey(modelVersion, normalizedQuery) {
|
|
22023
|
+
return `${modelVersion}\x00${normalizedQuery}`;
|
|
22024
|
+
}
|
|
22025
|
+
|
|
22026
|
+
class EmbeddingCache {
|
|
22027
|
+
cache;
|
|
22028
|
+
maxSize;
|
|
22029
|
+
constructor(maxSize = DEFAULT_CACHE_SIZE) {
|
|
22030
|
+
this.maxSize = maxSize;
|
|
22031
|
+
this.cache = new Map;
|
|
22032
|
+
}
|
|
22033
|
+
get size() {
|
|
22034
|
+
return this.cache.size;
|
|
22035
|
+
}
|
|
22036
|
+
get(modelVersion, query) {
|
|
22037
|
+
const key = compositeKey(modelVersion, normalizeQuery(query));
|
|
22038
|
+
const entry = this.cache.get(key);
|
|
22039
|
+
if (entry !== undefined) {
|
|
22040
|
+
this.cache.delete(key);
|
|
22041
|
+
this.cache.set(key, entry);
|
|
22042
|
+
}
|
|
22043
|
+
return entry;
|
|
22044
|
+
}
|
|
22045
|
+
set(modelVersion, query, entry) {
|
|
22046
|
+
const key = compositeKey(modelVersion, normalizeQuery(query));
|
|
22047
|
+
if (this.cache.has(key)) {
|
|
22048
|
+
this.cache.delete(key);
|
|
22049
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
22050
|
+
const oldestKey = this.cache.keys().next().value;
|
|
22051
|
+
if (oldestKey !== undefined) {
|
|
22052
|
+
this.cache.delete(oldestKey);
|
|
22053
|
+
}
|
|
22054
|
+
}
|
|
22055
|
+
if (this.cache.size < this.maxSize) {
|
|
22056
|
+
this.cache.set(key, entry);
|
|
22057
|
+
}
|
|
22058
|
+
}
|
|
22059
|
+
has(modelVersion, query) {
|
|
22060
|
+
const key = compositeKey(modelVersion, normalizeQuery(query));
|
|
22061
|
+
return this.cache.has(key);
|
|
22062
|
+
}
|
|
22063
|
+
clear() {
|
|
22064
|
+
this.cache.clear();
|
|
22065
|
+
}
|
|
22066
|
+
}
|
|
22067
|
+
|
|
22068
|
+
// src/memory/embeddings/fusion.ts
|
|
22069
|
+
function fuseRankings(lexicalRankedIds, denseRankedIds, metadataRankedIds, weights, rrfK) {
|
|
22070
|
+
const lexicalRanks = buildRankMap(lexicalRankedIds);
|
|
22071
|
+
const denseRanks = buildRankMap(denseRankedIds);
|
|
22072
|
+
const metadataRanks = buildRankMap(metadataRankedIds);
|
|
22073
|
+
const allIds = new Set;
|
|
22074
|
+
for (const id of lexicalRankedIds)
|
|
22075
|
+
allIds.add(id);
|
|
22076
|
+
for (const id of denseRankedIds)
|
|
22077
|
+
allIds.add(id);
|
|
22078
|
+
for (const id of metadataRankedIds)
|
|
22079
|
+
allIds.add(id);
|
|
22080
|
+
const candidates = [];
|
|
22081
|
+
for (const id of allIds) {
|
|
22082
|
+
const lexicalRank = lexicalRanks.get(id) ?? null;
|
|
22083
|
+
const denseRank = denseRanks.get(id) ?? null;
|
|
22084
|
+
const metadataRank = metadataRanks.get(id) ?? null;
|
|
22085
|
+
const rawScore = (lexicalRank !== null ? weights.lexical * rrfTerm(lexicalRank, rrfK) : 0) + (denseRank !== null ? weights.dense * rrfTerm(denseRank, rrfK) : 0) + (metadataRank !== null ? weights.metadata * rrfTerm(metadataRank, rrfK) : 0);
|
|
22086
|
+
candidates.push({
|
|
22087
|
+
id,
|
|
22088
|
+
fusedScore: rawScore,
|
|
22089
|
+
lexicalRank,
|
|
22090
|
+
denseRank,
|
|
22091
|
+
metadataRank
|
|
22092
|
+
});
|
|
22093
|
+
}
|
|
22094
|
+
return minMaxNormalise(candidates);
|
|
22095
|
+
}
|
|
22096
|
+
function buildRankMap(rankedIds) {
|
|
22097
|
+
const map = new Map;
|
|
22098
|
+
for (let i = 0;i < rankedIds.length; i++) {
|
|
22099
|
+
map.set(rankedIds[i], i + 1);
|
|
22100
|
+
}
|
|
22101
|
+
return map;
|
|
22102
|
+
}
|
|
22103
|
+
function rrfTerm(rank, rrfK) {
|
|
22104
|
+
return 1 / (rrfK + rank);
|
|
22105
|
+
}
|
|
22106
|
+
function minMaxNormalise(candidates) {
|
|
22107
|
+
if (candidates.length === 0)
|
|
22108
|
+
return candidates;
|
|
22109
|
+
let min = Infinity;
|
|
22110
|
+
let max = -Infinity;
|
|
22111
|
+
for (const c of candidates) {
|
|
22112
|
+
if (c.fusedScore < min)
|
|
22113
|
+
min = c.fusedScore;
|
|
22114
|
+
if (c.fusedScore > max)
|
|
22115
|
+
max = c.fusedScore;
|
|
22116
|
+
}
|
|
22117
|
+
const range = max - min;
|
|
22118
|
+
const normalised = [];
|
|
22119
|
+
for (const c of candidates) {
|
|
22120
|
+
const normalisedScore = range === 0 ? 1 : (c.fusedScore - min) / range;
|
|
22121
|
+
normalised.push({
|
|
22122
|
+
...c,
|
|
22123
|
+
fusedScore: normalisedScore
|
|
22124
|
+
});
|
|
22125
|
+
}
|
|
22126
|
+
normalised.sort((a, b) => b.fusedScore - a.fusedScore || a.id.localeCompare(b.id));
|
|
22127
|
+
return normalised;
|
|
22128
|
+
}
|
|
22129
|
+
|
|
22130
|
+
// src/memory/embeddings/local-provider.ts
|
|
21942
22131
|
import { mkdirSync as mkdirSync15 } from "fs";
|
|
21943
22132
|
import { createRequire as createRequire2 } from "module";
|
|
22133
|
+
import * as os10 from "os";
|
|
22134
|
+
import * as path43 from "path";
|
|
22135
|
+
|
|
22136
|
+
// src/memory/embeddings/types.ts
|
|
22137
|
+
class EmbeddingUnavailableError extends Error {
|
|
22138
|
+
constructor(message) {
|
|
22139
|
+
super(message ?? "Embedding provider is unavailable (dependency not installed or model failed to load)");
|
|
22140
|
+
this.name = "EmbeddingUnavailableError";
|
|
22141
|
+
}
|
|
22142
|
+
}
|
|
22143
|
+
|
|
22144
|
+
class EmbeddingVersionMismatchError extends Error {
|
|
22145
|
+
queryVersion;
|
|
22146
|
+
storedVersion;
|
|
22147
|
+
constructor(queryVersion, storedVersion) {
|
|
22148
|
+
super(`Embedding version mismatch: query uses ${queryVersion} but stored vectors are ${storedVersion}. Rebuild the index or pin the model version.`);
|
|
22149
|
+
this.name = "EmbeddingVersionMismatchError";
|
|
22150
|
+
this.queryVersion = queryVersion;
|
|
22151
|
+
this.storedVersion = storedVersion;
|
|
22152
|
+
}
|
|
22153
|
+
}
|
|
22154
|
+
|
|
22155
|
+
// src/memory/embeddings/local-provider.ts
|
|
22156
|
+
var _internals33 = {
|
|
22157
|
+
resolveEmbeddingCacheDir() {
|
|
22158
|
+
let base;
|
|
22159
|
+
if (process.platform === "win32") {
|
|
22160
|
+
base = process.env.LOCALAPPDATA || path43.join(os10.homedir(), "AppData", "Local");
|
|
22161
|
+
} else if (process.platform === "darwin") {
|
|
22162
|
+
base = path43.join(os10.homedir(), "Library", "Caches");
|
|
22163
|
+
} else {
|
|
22164
|
+
base = process.env.XDG_CACHE_HOME || path43.join(os10.homedir(), ".cache");
|
|
22165
|
+
}
|
|
22166
|
+
const resolved = path43.join(base, "opencode", "embeddings");
|
|
22167
|
+
const segments = resolved.split(path43.sep);
|
|
22168
|
+
if (segments.includes(".swarm")) {
|
|
22169
|
+
const safeDefault = process.platform === "win32" ? path43.join(os10.homedir(), "AppData", "Local", "opencode", "embeddings") : process.platform === "darwin" ? path43.join(os10.homedir(), "Library", "Caches", "opencode", "embeddings") : path43.join(os10.homedir(), ".cache", "opencode", "embeddings");
|
|
22170
|
+
warn("Embedding cache dir resolved under .swarm/ \u2014 falling back to safe default");
|
|
22171
|
+
return safeDefault;
|
|
22172
|
+
}
|
|
22173
|
+
return resolved;
|
|
22174
|
+
}
|
|
22175
|
+
};
|
|
22176
|
+
function resolveEmbeddingCacheDir() {
|
|
22177
|
+
return _internals33.resolveEmbeddingCacheDir();
|
|
22178
|
+
}
|
|
22179
|
+
|
|
22180
|
+
class LocalEmbeddingProvider {
|
|
22181
|
+
modelName;
|
|
22182
|
+
dimension;
|
|
22183
|
+
modelVersion;
|
|
22184
|
+
_available = false;
|
|
22185
|
+
loadFailed = false;
|
|
22186
|
+
pipeline = null;
|
|
22187
|
+
static downloadNoticePrinted = false;
|
|
22188
|
+
constructor(config) {
|
|
22189
|
+
this.modelName = config.model;
|
|
22190
|
+
this.dimension = config.dimension;
|
|
22191
|
+
this.modelVersion = config.version ?? `${config.model}:${config.dimension}`;
|
|
22192
|
+
}
|
|
22193
|
+
get available() {
|
|
22194
|
+
return this._available;
|
|
22195
|
+
}
|
|
22196
|
+
async ensurePipeline() {
|
|
22197
|
+
if (this.loadFailed) {
|
|
22198
|
+
return null;
|
|
22199
|
+
}
|
|
22200
|
+
if (this.pipeline)
|
|
22201
|
+
return this.pipeline;
|
|
22202
|
+
try {
|
|
22203
|
+
const req = createRequire2(import.meta.url);
|
|
22204
|
+
const transformers = req("@xenova/transformers");
|
|
22205
|
+
if (!LocalEmbeddingProvider.downloadNoticePrinted) {
|
|
22206
|
+
LocalEmbeddingProvider.downloadNoticePrinted = true;
|
|
22207
|
+
console.log(`[opencode-swarm] Downloading embedding model "${this.modelName}" (~25 MB) \u2014 this happens once per process.`);
|
|
22208
|
+
}
|
|
22209
|
+
const cacheDir2 = resolveEmbeddingCacheDir();
|
|
22210
|
+
mkdirSync15(cacheDir2, { recursive: true });
|
|
22211
|
+
this.pipeline = await transformers.pipeline("feature-extraction", this.modelName, { cache_dir: cacheDir2 });
|
|
22212
|
+
this._available = true;
|
|
22213
|
+
return this.pipeline;
|
|
22214
|
+
} catch (err) {
|
|
22215
|
+
this.loadFailed = true;
|
|
22216
|
+
this._available = false;
|
|
22217
|
+
warn("Local embedding provider unavailable \u2014 falling back to lexical-only", {
|
|
22218
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22219
|
+
});
|
|
22220
|
+
return null;
|
|
22221
|
+
}
|
|
22222
|
+
}
|
|
22223
|
+
async embed(text) {
|
|
22224
|
+
const pipeline = await this.ensurePipeline();
|
|
22225
|
+
if (!pipeline) {
|
|
22226
|
+
throw new EmbeddingUnavailableError("Embedding provider is unavailable (dependency not installed or model failed to load)");
|
|
22227
|
+
}
|
|
22228
|
+
const result = await pipeline(text, {
|
|
22229
|
+
pooling: "mean",
|
|
22230
|
+
normalize: true
|
|
22231
|
+
});
|
|
22232
|
+
return this.tensorToFloat32Array(result);
|
|
22233
|
+
}
|
|
22234
|
+
async embedBatch(texts) {
|
|
22235
|
+
if (texts.length === 0)
|
|
22236
|
+
return [];
|
|
22237
|
+
const pipeline = await this.ensurePipeline();
|
|
22238
|
+
if (!pipeline) {
|
|
22239
|
+
throw new EmbeddingUnavailableError("Embedding provider is unavailable (dependency not installed or model failed to load)");
|
|
22240
|
+
}
|
|
22241
|
+
const result = await pipeline(texts, {
|
|
22242
|
+
pooling: "mean",
|
|
22243
|
+
normalize: true
|
|
22244
|
+
});
|
|
22245
|
+
if (Array.isArray(result)) {
|
|
22246
|
+
return result.map((t) => this.tensorToFloat32Array(t));
|
|
22247
|
+
}
|
|
22248
|
+
return this.tensorToFloat32ArrayBatch(result);
|
|
22249
|
+
}
|
|
22250
|
+
tensorToFloat32Array(tensor) {
|
|
22251
|
+
if (tensor instanceof Float32Array)
|
|
22252
|
+
return tensor;
|
|
22253
|
+
const obj = tensor;
|
|
22254
|
+
if (obj?.data && obj.data instanceof Float32Array) {
|
|
22255
|
+
return obj.data;
|
|
22256
|
+
}
|
|
22257
|
+
const entries = Object.entries(tensor);
|
|
22258
|
+
for (const [, value] of entries) {
|
|
22259
|
+
if (value instanceof Float32Array)
|
|
22260
|
+
return value;
|
|
22261
|
+
}
|
|
22262
|
+
throw new Error(`Unexpected embedding tensor shape: ${JSON.stringify(tensor)}`);
|
|
22263
|
+
}
|
|
22264
|
+
tensorToFloat32ArrayBatch(tensor) {
|
|
22265
|
+
const obj = tensor;
|
|
22266
|
+
if (obj?.data && obj.data instanceof Float32Array && obj.dims && obj.dims.length >= 2) {
|
|
22267
|
+
const batchSize = obj.dims[0];
|
|
22268
|
+
const dim = obj.dims[1];
|
|
22269
|
+
const result = [];
|
|
22270
|
+
for (let i = 0;i < batchSize; i++) {
|
|
22271
|
+
const offset = i * dim;
|
|
22272
|
+
result.push(obj.data.slice(offset, offset + dim));
|
|
22273
|
+
}
|
|
22274
|
+
return result;
|
|
22275
|
+
}
|
|
22276
|
+
if (Array.isArray(tensor)) {
|
|
22277
|
+
return tensor.map((t) => this.tensorToFloat32Array(t));
|
|
22278
|
+
}
|
|
22279
|
+
throw new Error(`Unexpected batch embedding tensor shape: ${JSON.stringify(tensor)}`);
|
|
22280
|
+
}
|
|
22281
|
+
}
|
|
22282
|
+
|
|
22283
|
+
// src/memory/embeddings/reranker.ts
|
|
22284
|
+
import { mkdirSync as mkdirSync16 } from "fs";
|
|
22285
|
+
import { createRequire as createRequire3 } from "module";
|
|
22286
|
+
import * as os11 from "os";
|
|
21944
22287
|
import * as path44 from "path";
|
|
22288
|
+
function shouldRerank(previousRecallElapsedMs, latencyBudgetMs) {
|
|
22289
|
+
return previousRecallElapsedMs <= latencyBudgetMs;
|
|
22290
|
+
}
|
|
22291
|
+
|
|
22292
|
+
class CrossEncoderReranker {
|
|
22293
|
+
options;
|
|
22294
|
+
loadFailed = false;
|
|
22295
|
+
_available = false;
|
|
22296
|
+
pipeline = null;
|
|
22297
|
+
constructor(options) {
|
|
22298
|
+
this.options = options;
|
|
22299
|
+
}
|
|
22300
|
+
get available() {
|
|
22301
|
+
return this._available;
|
|
22302
|
+
}
|
|
22303
|
+
async ensurePipeline() {
|
|
22304
|
+
if (this.loadFailed)
|
|
22305
|
+
return null;
|
|
22306
|
+
if (this.pipeline)
|
|
22307
|
+
return this.pipeline;
|
|
22308
|
+
try {
|
|
22309
|
+
const req = createRequire3(import.meta.url);
|
|
22310
|
+
const transformers = req("@xenova/transformers");
|
|
22311
|
+
const modelName = this.options.model ?? "Xenova/ms-marco-MiniLM-L-6-v2";
|
|
22312
|
+
const cacheDir2 = resolveRerankerCacheDir();
|
|
22313
|
+
mkdirSync16(cacheDir2, { recursive: true });
|
|
22314
|
+
this.pipeline = await transformers.pipeline("text-classification", modelName, { cache_dir: cacheDir2 });
|
|
22315
|
+
this._available = true;
|
|
22316
|
+
return this.pipeline;
|
|
22317
|
+
} catch (err) {
|
|
22318
|
+
this.loadFailed = true;
|
|
22319
|
+
this._available = false;
|
|
22320
|
+
warn("Cross-encoder reranker unavailable \u2014 skipping rerank", {
|
|
22321
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22322
|
+
});
|
|
22323
|
+
return null;
|
|
22324
|
+
}
|
|
22325
|
+
}
|
|
22326
|
+
async rerank(candidates, query, topN) {
|
|
22327
|
+
if (candidates.length === 0)
|
|
22328
|
+
return candidates;
|
|
22329
|
+
const pipeline = await this.ensurePipeline();
|
|
22330
|
+
if (!pipeline)
|
|
22331
|
+
return candidates;
|
|
22332
|
+
try {
|
|
22333
|
+
const inputs = candidates.map((c) => [query, c.text]);
|
|
22334
|
+
const results = await pipeline(inputs, { truncation: true });
|
|
22335
|
+
const scored = candidates.map((c, idx) => ({
|
|
22336
|
+
...c,
|
|
22337
|
+
score: results[idx]?.score ?? 0
|
|
22338
|
+
}));
|
|
22339
|
+
scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
22340
|
+
if (typeof topN === "number" && topN > 0) {
|
|
22341
|
+
return scored.slice(0, topN);
|
|
22342
|
+
}
|
|
22343
|
+
return scored;
|
|
22344
|
+
} catch (err) {
|
|
22345
|
+
warn("Rerank scoring failed \u2014 returning original order", {
|
|
22346
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22347
|
+
});
|
|
22348
|
+
return candidates;
|
|
22349
|
+
}
|
|
22350
|
+
}
|
|
22351
|
+
}
|
|
22352
|
+
function resolveRerankerCacheDir() {
|
|
22353
|
+
let base;
|
|
22354
|
+
if (process.platform === "win32") {
|
|
22355
|
+
base = process.env.LOCALAPPDATA || path44.join(os11.homedir(), "AppData", "Local");
|
|
22356
|
+
} else if (process.platform === "darwin") {
|
|
22357
|
+
base = path44.join(os11.homedir(), "Library", "Caches");
|
|
22358
|
+
} else {
|
|
22359
|
+
base = process.env.XDG_CACHE_HOME || path44.join(os11.homedir(), ".cache");
|
|
22360
|
+
}
|
|
22361
|
+
const resolved = path44.join(base, "opencode", "embeddings");
|
|
22362
|
+
const segments = resolved.split(path44.sep);
|
|
22363
|
+
if (segments.includes(".swarm")) {
|
|
22364
|
+
const safeDefault = process.platform === "win32" ? path44.join(os11.homedir(), "AppData", "Local", "opencode", "embeddings") : process.platform === "darwin" ? path44.join(os11.homedir(), "Library", "Caches", "opencode", "embeddings") : path44.join(os11.homedir(), ".cache", "opencode", "embeddings");
|
|
22365
|
+
warn("Reranker cache dir resolved under .swarm/ \u2014 falling back to safe default");
|
|
22366
|
+
return safeDefault;
|
|
22367
|
+
}
|
|
22368
|
+
return resolved;
|
|
22369
|
+
}
|
|
21945
22370
|
|
|
21946
22371
|
// src/memory/jsonl-migration.ts
|
|
21947
22372
|
import { existsSync as existsSync26, renameSync as renameSync10, unlinkSync as unlinkSync7 } from "fs";
|
|
21948
22373
|
import { copyFile as copyFile2, mkdir as mkdir11, readFile as readFile13, stat as stat5, writeFile as writeFile11 } from "fs/promises";
|
|
21949
|
-
import * as
|
|
22374
|
+
import * as path45 from "path";
|
|
21950
22375
|
var LEGACY_JSONL_MIGRATION_VERSION = 2;
|
|
21951
22376
|
var LEGACY_JSONL_MIGRATION_NAME = "legacy_jsonl_import_complete";
|
|
21952
22377
|
function resolveMemoryStorageDir(rootDirectory, config = {}) {
|
|
@@ -21962,8 +22387,8 @@ function resolveSqliteDatabasePath(rootDirectory, config = {}) {
|
|
|
21962
22387
|
async function readLegacyJsonl(rootDirectory, config = {}) {
|
|
21963
22388
|
const resolved = resolveConfig(config);
|
|
21964
22389
|
const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
|
|
21965
|
-
const memoryLoad = await readMemoryJsonl(
|
|
21966
|
-
const proposalLoad = await readProposalJsonl(
|
|
22390
|
+
const memoryLoad = await readMemoryJsonl(path45.join(storageDir, "memories.jsonl"), resolved);
|
|
22391
|
+
const proposalLoad = await readProposalJsonl(path45.join(storageDir, "proposals.jsonl"), resolved);
|
|
21967
22392
|
return {
|
|
21968
22393
|
memories: memoryLoad.records,
|
|
21969
22394
|
proposals: proposalLoad.records,
|
|
@@ -21973,14 +22398,14 @@ async function readLegacyJsonl(rootDirectory, config = {}) {
|
|
|
21973
22398
|
}
|
|
21974
22399
|
async function backupLegacyJsonl(rootDirectory, config = {}) {
|
|
21975
22400
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config);
|
|
21976
|
-
const backupDir =
|
|
22401
|
+
const backupDir = path45.join(storageDir, "backups");
|
|
21977
22402
|
await mkdir11(backupDir, { recursive: true });
|
|
21978
22403
|
const results = [];
|
|
21979
22404
|
for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
|
|
21980
|
-
const source =
|
|
22405
|
+
const source = path45.join(storageDir, filename);
|
|
21981
22406
|
if (!existsSync26(source))
|
|
21982
22407
|
continue;
|
|
21983
|
-
const backup =
|
|
22408
|
+
const backup = path45.join(backupDir, `${filename}.pre-sqlite-migration`);
|
|
21984
22409
|
if (existsSync26(backup)) {
|
|
21985
22410
|
results.push({ source, backup, created: false });
|
|
21986
22411
|
continue;
|
|
@@ -21991,11 +22416,11 @@ async function backupLegacyJsonl(rootDirectory, config = {}) {
|
|
|
21991
22416
|
return results;
|
|
21992
22417
|
}
|
|
21993
22418
|
async function writeJsonlExport(rootDirectory, config, memories, proposals) {
|
|
21994
|
-
const exportDir =
|
|
22419
|
+
const exportDir = path45.join(resolveMemoryStorageDir(rootDirectory, config), "export");
|
|
21995
22420
|
await mkdir11(exportDir, { recursive: true });
|
|
21996
|
-
const memoriesPath =
|
|
21997
|
-
const proposalsPath =
|
|
21998
|
-
const memoriesTempPath =
|
|
22421
|
+
const memoriesPath = path45.join(exportDir, "memories.jsonl");
|
|
22422
|
+
const proposalsPath = path45.join(exportDir, "proposals.jsonl");
|
|
22423
|
+
const memoriesTempPath = path45.join(path45.dirname(memoriesPath), `${path45.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
21999
22424
|
try {
|
|
22000
22425
|
await writeFile11(memoriesTempPath, toJsonl(memories), "utf-8");
|
|
22001
22426
|
renameSync10(memoriesTempPath, memoriesPath);
|
|
@@ -22005,7 +22430,7 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
|
|
|
22005
22430
|
} catch {}
|
|
22006
22431
|
throw err;
|
|
22007
22432
|
}
|
|
22008
|
-
const proposalsTempPath =
|
|
22433
|
+
const proposalsTempPath = path45.join(path45.dirname(proposalsPath), `${path45.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
22009
22434
|
try {
|
|
22010
22435
|
await writeFile11(proposalsTempPath, toJsonl(proposals), "utf-8");
|
|
22011
22436
|
renameSync10(proposalsTempPath, proposalsPath);
|
|
@@ -22018,9 +22443,9 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
|
|
|
22018
22443
|
return { directory: exportDir, memoriesPath, proposalsPath };
|
|
22019
22444
|
}
|
|
22020
22445
|
async function writeMigrationReport(rootDirectory, report, config = {}) {
|
|
22021
|
-
const reportPath =
|
|
22022
|
-
await mkdir11(
|
|
22023
|
-
const reportTempPath =
|
|
22446
|
+
const reportPath = path45.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
22447
|
+
await mkdir11(path45.dirname(reportPath), { recursive: true });
|
|
22448
|
+
const reportTempPath = path45.join(path45.dirname(reportPath), `${path45.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
22024
22449
|
try {
|
|
22025
22450
|
await writeFile11(reportTempPath, `${JSON.stringify(report, null, 2)}
|
|
22026
22451
|
`, "utf-8");
|
|
@@ -22034,7 +22459,7 @@ async function writeMigrationReport(rootDirectory, report, config = {}) {
|
|
|
22034
22459
|
return reportPath;
|
|
22035
22460
|
}
|
|
22036
22461
|
async function readMigrationReport(rootDirectory, config = {}) {
|
|
22037
|
-
const reportPath =
|
|
22462
|
+
const reportPath = path45.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
22038
22463
|
if (!existsSync26(reportPath))
|
|
22039
22464
|
return null;
|
|
22040
22465
|
try {
|
|
@@ -22047,7 +22472,7 @@ async function getLegacyJsonlFileStatus(rootDirectory, config = {}) {
|
|
|
22047
22472
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config);
|
|
22048
22473
|
const statuses = [];
|
|
22049
22474
|
for (const file of ["memories.jsonl", "proposals.jsonl"]) {
|
|
22050
|
-
const filePath =
|
|
22475
|
+
const filePath = path45.join(storageDir, file);
|
|
22051
22476
|
let sizeBytes = 0;
|
|
22052
22477
|
if (existsSync26(filePath)) {
|
|
22053
22478
|
sizeBytes = (await stat5(filePath)).size;
|
|
@@ -22171,7 +22596,7 @@ var _DatabaseCtor2 = null;
|
|
|
22171
22596
|
function loadDatabaseCtor2() {
|
|
22172
22597
|
if (_DatabaseCtor2)
|
|
22173
22598
|
return _DatabaseCtor2;
|
|
22174
|
-
const req =
|
|
22599
|
+
const req = createRequire4(import.meta.url);
|
|
22175
22600
|
_DatabaseCtor2 = req("bun:sqlite").Database;
|
|
22176
22601
|
return _DatabaseCtor2;
|
|
22177
22602
|
}
|
|
@@ -22291,6 +22716,16 @@ var MIGRATIONS2 = [
|
|
|
22291
22716
|
CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_timestamp
|
|
22292
22717
|
ON memory_recall_usage(timestamp DESC);
|
|
22293
22718
|
`
|
|
22719
|
+
},
|
|
22720
|
+
{
|
|
22721
|
+
version: 6,
|
|
22722
|
+
name: "create_embedding_config_table",
|
|
22723
|
+
sql: `
|
|
22724
|
+
CREATE TABLE IF NOT EXISTS embedding_config (
|
|
22725
|
+
key TEXT PRIMARY KEY,
|
|
22726
|
+
value TEXT
|
|
22727
|
+
);
|
|
22728
|
+
`
|
|
22294
22729
|
}
|
|
22295
22730
|
];
|
|
22296
22731
|
|
|
@@ -22302,6 +22737,10 @@ class SQLiteMemoryProvider {
|
|
|
22302
22737
|
initPromise = null;
|
|
22303
22738
|
db = null;
|
|
22304
22739
|
ftsAvailable = false;
|
|
22740
|
+
vecAvailable = false;
|
|
22741
|
+
embeddingProvider = null;
|
|
22742
|
+
embeddingCache = null;
|
|
22743
|
+
reranker = null;
|
|
22305
22744
|
memories = new Map;
|
|
22306
22745
|
proposals = new Map;
|
|
22307
22746
|
lastAutomaticJsonlMigration = null;
|
|
@@ -22355,7 +22794,7 @@ class SQLiteMemoryProvider {
|
|
|
22355
22794
|
}
|
|
22356
22795
|
async doInitialize() {
|
|
22357
22796
|
const dbPath = this.databasePath();
|
|
22358
|
-
|
|
22797
|
+
mkdirSync17(path46.dirname(dbPath), { recursive: true });
|
|
22359
22798
|
const Db = loadDatabaseCtor2();
|
|
22360
22799
|
this.db = new Db(dbPath);
|
|
22361
22800
|
this.db.run("PRAGMA journal_mode = WAL;");
|
|
@@ -22366,6 +22805,29 @@ class SQLiteMemoryProvider {
|
|
|
22366
22805
|
this.runMigrations();
|
|
22367
22806
|
this.backfillScopeKeys();
|
|
22368
22807
|
this.ftsAvailable = this.initializeFtsIndex();
|
|
22808
|
+
this.initializeVecExtension();
|
|
22809
|
+
if (this.config.embeddings.enabled && !this.embeddingProvider) {
|
|
22810
|
+
try {
|
|
22811
|
+
this.embeddingProvider = new LocalEmbeddingProvider({
|
|
22812
|
+
model: this.config.embeddings.model,
|
|
22813
|
+
dimension: this.config.embeddings.dimension,
|
|
22814
|
+
version: this.config.embeddings.version
|
|
22815
|
+
});
|
|
22816
|
+
} catch (err) {
|
|
22817
|
+
this.embeddingProvider = null;
|
|
22818
|
+
warn("Failed to construct embedding provider \u2014 dense retrieval disabled", {
|
|
22819
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22820
|
+
});
|
|
22821
|
+
}
|
|
22822
|
+
try {
|
|
22823
|
+
this.embeddingCache = new EmbeddingCache(this.config.embeddings.cacheSize);
|
|
22824
|
+
} catch (err) {
|
|
22825
|
+
this.embeddingCache = null;
|
|
22826
|
+
warn("Failed to construct embedding cache \u2014 recall works without cache", {
|
|
22827
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22828
|
+
});
|
|
22829
|
+
}
|
|
22830
|
+
}
|
|
22369
22831
|
this.lastAutomaticJsonlMigration = null;
|
|
22370
22832
|
await this.migrateLegacyJsonlIfNeeded();
|
|
22371
22833
|
const memoryLoad = this.loadMemories();
|
|
@@ -22392,6 +22854,7 @@ class SQLiteMemoryProvider {
|
|
|
22392
22854
|
}, { rejectDurableSecrets: this.config.redaction.rejectDurableSecrets });
|
|
22393
22855
|
this.memories.set(next.id, next);
|
|
22394
22856
|
this.writeMemory(next);
|
|
22857
|
+
await this.writeMemoryVec(next);
|
|
22395
22858
|
await this.event("upsert", next.id);
|
|
22396
22859
|
return next;
|
|
22397
22860
|
}
|
|
@@ -22408,6 +22871,7 @@ class SQLiteMemoryProvider {
|
|
|
22408
22871
|
this.memories.delete(id);
|
|
22409
22872
|
this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
22410
22873
|
this.deleteMemoryFts(id);
|
|
22874
|
+
this.deleteMemoryVec(id);
|
|
22411
22875
|
} else {
|
|
22412
22876
|
const tombstone = {
|
|
22413
22877
|
...existing,
|
|
@@ -22424,20 +22888,139 @@ class SQLiteMemoryProvider {
|
|
|
22424
22888
|
}
|
|
22425
22889
|
async recallWithDiagnostics(request) {
|
|
22426
22890
|
await this.initialize();
|
|
22891
|
+
if (!this.config.embeddings.enabled || !this.vecAvailable || !this.embeddingProvider) {
|
|
22892
|
+
const scopedRecords2 = await this.list({
|
|
22893
|
+
scopes: request.scopes,
|
|
22894
|
+
kinds: request.kinds,
|
|
22895
|
+
includeExpired: request.includeExpired,
|
|
22896
|
+
limit: RECALL_CANDIDATE_LIMIT
|
|
22897
|
+
});
|
|
22898
|
+
const candidates = this.selectRecallCandidates(request, scopedRecords2);
|
|
22899
|
+
const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
|
|
22900
|
+
const reranked = candidates.ftsOrder ? rerankWithFts(result.items, candidates.ftsOrder) : result.items;
|
|
22901
|
+
return {
|
|
22902
|
+
items: reranked.slice(0, request.maxItems),
|
|
22903
|
+
diagnostics: {
|
|
22904
|
+
...result.diagnostics,
|
|
22905
|
+
returnedCount: Math.min(reranked.length, request.maxItems)
|
|
22906
|
+
}
|
|
22907
|
+
};
|
|
22908
|
+
}
|
|
22909
|
+
const recallElapsedStart = Date.now();
|
|
22427
22910
|
const scopedRecords = await this.list({
|
|
22428
22911
|
scopes: request.scopes,
|
|
22429
22912
|
kinds: request.kinds,
|
|
22430
22913
|
includeExpired: request.includeExpired,
|
|
22431
22914
|
limit: RECALL_CANDIDATE_LIMIT
|
|
22432
22915
|
});
|
|
22433
|
-
const
|
|
22434
|
-
const
|
|
22435
|
-
const
|
|
22916
|
+
const lexicalCandidates = this.selectRecallCandidates(request, scopedRecords);
|
|
22917
|
+
const lexicalResult = scoreMemoryRecordsWithDiagnostics(lexicalCandidates.records, request);
|
|
22918
|
+
const lexicalReranked = lexicalCandidates.ftsOrder ? rerankWithFts(lexicalResult.items, lexicalCandidates.ftsOrder) : lexicalResult.items;
|
|
22919
|
+
const lexicalIds = lexicalReranked.map((item) => item.record.id);
|
|
22920
|
+
let denseIds = [];
|
|
22921
|
+
try {
|
|
22922
|
+
const modelVersion = this.embeddingProvider.modelVersion;
|
|
22923
|
+
const normalizedQuery = normalizeMemoryText(request.query).toLowerCase();
|
|
22924
|
+
let queryEmbedding = this.embeddingCache?.get(modelVersion, normalizedQuery)?.vector ?? null;
|
|
22925
|
+
if (queryEmbedding === null) {
|
|
22926
|
+
queryEmbedding = await this.embeddingProvider.embed(normalizedQuery);
|
|
22927
|
+
this.embeddingCache?.set(modelVersion, normalizedQuery, {
|
|
22928
|
+
vector: queryEmbedding,
|
|
22929
|
+
modelVersion,
|
|
22930
|
+
queryHash: normalizedQuery
|
|
22931
|
+
});
|
|
22932
|
+
}
|
|
22933
|
+
const denseRecords = await this.selectDenseCandidates(request, queryEmbedding);
|
|
22934
|
+
denseIds = denseRecords.map((record) => record.id);
|
|
22935
|
+
} catch (err) {
|
|
22936
|
+
if (err instanceof EmbeddingVersionMismatchError || err instanceof EmbeddingUnavailableError) {
|
|
22937
|
+
warn("Dense retrieval failed \u2014 falling back to lexical-only", {
|
|
22938
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22939
|
+
});
|
|
22940
|
+
} else {
|
|
22941
|
+
warn("Dense retrieval failed \u2014 falling back to lexical-only", {
|
|
22942
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
22943
|
+
});
|
|
22944
|
+
}
|
|
22945
|
+
return {
|
|
22946
|
+
items: lexicalReranked.slice(0, request.maxItems),
|
|
22947
|
+
diagnostics: {
|
|
22948
|
+
...lexicalResult.diagnostics,
|
|
22949
|
+
returnedCount: Math.min(lexicalReranked.length, request.maxItems)
|
|
22950
|
+
}
|
|
22951
|
+
};
|
|
22952
|
+
}
|
|
22953
|
+
const metadataIds = buildMetadataRankedIds(lexicalReranked, request);
|
|
22954
|
+
const weights = this.config.retrieval.weights;
|
|
22955
|
+
const rrfK = this.config.retrieval.rrfK;
|
|
22956
|
+
const fused = fuseRankings(lexicalIds, denseIds, metadataIds, weights, rrfK);
|
|
22957
|
+
const lexicalItemMap = new Map(lexicalReranked.map((item) => [item.record.id, item]));
|
|
22958
|
+
const minScore = request.minScore ?? this.config.recall.minScore;
|
|
22959
|
+
const fusedItems = [];
|
|
22960
|
+
for (const candidate of fused) {
|
|
22961
|
+
if (candidate.fusedScore < minScore)
|
|
22962
|
+
continue;
|
|
22963
|
+
const lexicalItem = lexicalItemMap.get(candidate.id);
|
|
22964
|
+
if (lexicalItem) {
|
|
22965
|
+
fusedItems.push({
|
|
22966
|
+
record: lexicalItem.record,
|
|
22967
|
+
score: candidate.fusedScore,
|
|
22968
|
+
reason: `${lexicalItem.reason}, rrf_fused=${candidate.fusedScore.toFixed(4)}`,
|
|
22969
|
+
signals: lexicalItem.signals
|
|
22970
|
+
});
|
|
22971
|
+
} else {
|
|
22972
|
+
const record = this.memories.get(candidate.id);
|
|
22973
|
+
if (record) {
|
|
22974
|
+
fusedItems.push({
|
|
22975
|
+
record,
|
|
22976
|
+
score: candidate.fusedScore,
|
|
22977
|
+
reason: `rrf_fused=${candidate.fusedScore.toFixed(4)}`,
|
|
22978
|
+
signals: {
|
|
22979
|
+
textOverlap: 0,
|
|
22980
|
+
tagOverlap: 0,
|
|
22981
|
+
fileOverlap: 0,
|
|
22982
|
+
symbolOverlap: 0,
|
|
22983
|
+
kindMatch: false,
|
|
22984
|
+
scopeMatch: false
|
|
22985
|
+
}
|
|
22986
|
+
});
|
|
22987
|
+
}
|
|
22988
|
+
}
|
|
22989
|
+
}
|
|
22990
|
+
const previousRecallElapsedMs = Date.now() - recallElapsedStart;
|
|
22991
|
+
let rerankedItems = fusedItems;
|
|
22992
|
+
if (this.config.retrieval.rerank.enabled && shouldRerank(previousRecallElapsedMs, this.config.retrieval.latencyBudgetMs)) {
|
|
22993
|
+
try {
|
|
22994
|
+
if (!this.reranker) {
|
|
22995
|
+
this.reranker = new CrossEncoderReranker({
|
|
22996
|
+
model: this.config.retrieval.rerank.model
|
|
22997
|
+
});
|
|
22998
|
+
}
|
|
22999
|
+
const topN = Math.min(20, fusedItems.length);
|
|
23000
|
+
const rerankCandidates = fusedItems.slice(0, topN).map((item) => ({
|
|
23001
|
+
id: item.record.id,
|
|
23002
|
+
text: item.record.text,
|
|
23003
|
+
score: item.score
|
|
23004
|
+
}));
|
|
23005
|
+
const rerankResult = await this.reranker.rerank(rerankCandidates, request.query, topN);
|
|
23006
|
+
const topNPrefix = fusedItems.slice(0, topN);
|
|
23007
|
+
const tail = fusedItems.slice(topN);
|
|
23008
|
+
const rerankOrder = new Map(rerankResult.map((c, idx) => [c.id, idx]));
|
|
23009
|
+
const reorderedTopN = [...topNPrefix].sort((a, b) => (rerankOrder.get(a.record.id) ?? 0) - (rerankOrder.get(b.record.id) ?? 0));
|
|
23010
|
+
rerankedItems = [...reorderedTopN, ...tail];
|
|
23011
|
+
} catch (err) {
|
|
23012
|
+
warn("Rerank failed \u2014 returning fused order", {
|
|
23013
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
23014
|
+
});
|
|
23015
|
+
rerankedItems = fusedItems;
|
|
23016
|
+
}
|
|
23017
|
+
}
|
|
22436
23018
|
return {
|
|
22437
|
-
items:
|
|
23019
|
+
items: rerankedItems.slice(0, request.maxItems),
|
|
22438
23020
|
diagnostics: {
|
|
22439
|
-
...
|
|
22440
|
-
returnedCount: Math.min(
|
|
23021
|
+
...lexicalResult.diagnostics,
|
|
23022
|
+
returnedCount: Math.min(rerankedItems.length, request.maxItems),
|
|
23023
|
+
fusionActive: true
|
|
22441
23024
|
}
|
|
22442
23025
|
};
|
|
22443
23026
|
}
|
|
@@ -22594,6 +23177,11 @@ class SQLiteMemoryProvider {
|
|
|
22594
23177
|
for (const memory of result.memories) {
|
|
22595
23178
|
this.memories.set(memory.id, memory);
|
|
22596
23179
|
}
|
|
23180
|
+
for (const memory of result.memories) {
|
|
23181
|
+
if (memory.metadata.deleted !== true) {
|
|
23182
|
+
await this.writeMemoryVec(memory);
|
|
23183
|
+
}
|
|
23184
|
+
}
|
|
22597
23185
|
return result.change;
|
|
22598
23186
|
}
|
|
22599
23187
|
close() {
|
|
@@ -22606,6 +23194,46 @@ class SQLiteMemoryProvider {
|
|
|
22606
23194
|
this.initPromise = null;
|
|
22607
23195
|
this.lastAutomaticJsonlMigration = null;
|
|
22608
23196
|
}
|
|
23197
|
+
async rebuildEmbeddingIndex() {
|
|
23198
|
+
await this.initialize();
|
|
23199
|
+
if (!this.vecAvailable || !this.embeddingProvider) {
|
|
23200
|
+
warn("rebuildEmbeddingIndex skipped \u2014 sqlite-vec or embedding provider not available");
|
|
23201
|
+
return;
|
|
23202
|
+
}
|
|
23203
|
+
const currentVersion = this.embeddingProvider.modelVersion;
|
|
23204
|
+
const durableRecords = Array.from(this.memories.values()).filter((record) => DURABLE_MEMORY_KINDS.has(record.kind) && record.metadata.deleted !== true && record.supersededBy === undefined && record.stability !== "ephemeral");
|
|
23205
|
+
let successCount = 0;
|
|
23206
|
+
let failureCount = 0;
|
|
23207
|
+
const db = this.requireDb();
|
|
23208
|
+
for (const record of durableRecords) {
|
|
23209
|
+
try {
|
|
23210
|
+
const normalizedText = normalizeMemoryText(record.text).toLowerCase();
|
|
23211
|
+
if (normalizedText.length === 0)
|
|
23212
|
+
continue;
|
|
23213
|
+
const vector = await this.embeddingProvider.embed(normalizedText);
|
|
23214
|
+
db.run("INSERT OR REPLACE INTO memory_items_vec (id, embedding) VALUES (?, ?)", [record.id, vector]);
|
|
23215
|
+
successCount++;
|
|
23216
|
+
} catch (err) {
|
|
23217
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
23218
|
+
warn("rebuildEmbeddingIndex: failed to embed record", {
|
|
23219
|
+
id: record.id,
|
|
23220
|
+
reason
|
|
23221
|
+
});
|
|
23222
|
+
failureCount++;
|
|
23223
|
+
}
|
|
23224
|
+
}
|
|
23225
|
+
if (failureCount === 0) {
|
|
23226
|
+
db.run("INSERT OR REPLACE INTO embedding_config (key, value) VALUES (?, ?)", ["model_version", currentVersion]);
|
|
23227
|
+
}
|
|
23228
|
+
this.embeddingCache?.clear();
|
|
23229
|
+
if (failureCount > 0) {
|
|
23230
|
+
warn("rebuildEmbeddingIndex completed with failures", {
|
|
23231
|
+
successCount,
|
|
23232
|
+
failureCount,
|
|
23233
|
+
total: durableRecords.length
|
|
23234
|
+
});
|
|
23235
|
+
}
|
|
23236
|
+
}
|
|
22609
23237
|
async importJsonl() {
|
|
22610
23238
|
const wasInitialized = this.initialized;
|
|
22611
23239
|
await this.initialize();
|
|
@@ -22664,6 +23292,7 @@ class SQLiteMemoryProvider {
|
|
|
22664
23292
|
for (const id of removeIds) {
|
|
22665
23293
|
db.run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
22666
23294
|
this.deleteMemoryFts(id);
|
|
23295
|
+
this.deleteMemoryVec(id);
|
|
22667
23296
|
}
|
|
22668
23297
|
this.insertEvent("compact", "memory_items", "removed deleted, superseded, and expired scratch memories", JSON.stringify(result));
|
|
22669
23298
|
});
|
|
@@ -22710,6 +23339,52 @@ class SQLiteMemoryProvider {
|
|
|
22710
23339
|
return { records: scopedRecords, usedFts: false };
|
|
22711
23340
|
}
|
|
22712
23341
|
}
|
|
23342
|
+
getStoredModelVersion() {
|
|
23343
|
+
const row = this.requireDb().query(`SELECT value FROM embedding_config WHERE key = 'model_version' LIMIT 1`).get("model_version");
|
|
23344
|
+
return row?.value ?? null;
|
|
23345
|
+
}
|
|
23346
|
+
async selectDenseCandidates(request, queryEmbedding) {
|
|
23347
|
+
if (!this.config.embeddings.enabled || !this.vecAvailable || !this.embeddingProvider) {
|
|
23348
|
+
return [];
|
|
23349
|
+
}
|
|
23350
|
+
const storedVersion = this.getStoredModelVersion();
|
|
23351
|
+
const queryVersion = this.embeddingProvider.modelVersion;
|
|
23352
|
+
if (storedVersion !== null && storedVersion !== queryVersion) {
|
|
23353
|
+
throw new EmbeddingVersionMismatchError(queryVersion, storedVersion);
|
|
23354
|
+
}
|
|
23355
|
+
const k = Math.max(100, request.maxItems * 20);
|
|
23356
|
+
const rows = this.requireDb().query(`SELECT id, distance FROM memory_items_vec WHERE embedding MATCH ? ORDER BY distance LIMIT ?`).all(queryEmbedding, k);
|
|
23357
|
+
const scopeKeys = request.scopes?.map((s) => stableScopeKey(s)) ?? [];
|
|
23358
|
+
const kinds = request.kinds ?? [];
|
|
23359
|
+
const includeInactive = false;
|
|
23360
|
+
const includeExpired = request.includeExpired ?? false;
|
|
23361
|
+
const allowedIds = new Set;
|
|
23362
|
+
for (const record of this.memories.values()) {
|
|
23363
|
+
if (scopeKeys.length > 0 && !scopeKeys.includes(stableScopeKey(record.scope)))
|
|
23364
|
+
continue;
|
|
23365
|
+
if (kinds.length > 0 && !kinds.includes(record.kind))
|
|
23366
|
+
continue;
|
|
23367
|
+
if (!includeInactive && record.supersededBy)
|
|
23368
|
+
continue;
|
|
23369
|
+
if (!includeInactive && record.metadata.deleted === true)
|
|
23370
|
+
continue;
|
|
23371
|
+
if (!includeExpired && record.expiresAt) {
|
|
23372
|
+
const expires = Date.parse(record.expiresAt);
|
|
23373
|
+
if (Number.isFinite(expires) && expires <= Date.now())
|
|
23374
|
+
continue;
|
|
23375
|
+
}
|
|
23376
|
+
allowedIds.add(record.id);
|
|
23377
|
+
}
|
|
23378
|
+
const results = [];
|
|
23379
|
+
for (const row of rows) {
|
|
23380
|
+
if (!allowedIds.has(row.id))
|
|
23381
|
+
continue;
|
|
23382
|
+
const record = this.memories.get(row.id);
|
|
23383
|
+
if (record)
|
|
23384
|
+
results.push(record);
|
|
23385
|
+
}
|
|
23386
|
+
return results;
|
|
23387
|
+
}
|
|
22713
23388
|
runMigrations() {
|
|
22714
23389
|
const db = this.requireDb();
|
|
22715
23390
|
db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
@@ -22782,6 +23457,26 @@ class SQLiteMemoryProvider {
|
|
|
22782
23457
|
return false;
|
|
22783
23458
|
}
|
|
22784
23459
|
}
|
|
23460
|
+
initializeVecExtension() {
|
|
23461
|
+
const db = this.requireDb();
|
|
23462
|
+
try {
|
|
23463
|
+
const dimension = Math.max(1, Math.trunc(this.config.embeddings.dimension ?? 384));
|
|
23464
|
+
const req = createRequire4(import.meta.url);
|
|
23465
|
+
const pkgDir = path46.dirname(req.resolve("@sqlite/sqlite-vec/package.json"));
|
|
23466
|
+
const ext = process.platform === "win32" ? ".dll" : process.platform === "darwin" ? ".dylib" : ".so";
|
|
23467
|
+
const vec0Path = path46.join(pkgDir, `vec0${ext}`);
|
|
23468
|
+
db.loadExtension(vec0Path);
|
|
23469
|
+
db.run(`CREATE VIRTUAL TABLE IF NOT EXISTS memory_items_vec USING vec0(
|
|
23470
|
+
id TEXT PRIMARY KEY, embedding FLOAT[${dimension}]
|
|
23471
|
+
)`);
|
|
23472
|
+
const modelVersion = this.config.embeddings.version ?? `${this.config.embeddings.model}:${dimension}`;
|
|
23473
|
+
db.run("INSERT OR IGNORE INTO embedding_config (key, value) VALUES (?, ?)", ["model_version", modelVersion]);
|
|
23474
|
+
this.vecAvailable = true;
|
|
23475
|
+
} catch (err) {
|
|
23476
|
+
this.vecAvailable = false;
|
|
23477
|
+
warn("sqlite-vec extension not available \u2014 dense retrieval disabled", err);
|
|
23478
|
+
}
|
|
23479
|
+
}
|
|
22785
23480
|
recreateFtsIndex() {
|
|
22786
23481
|
const db = this.requireDb();
|
|
22787
23482
|
const recreate = db.transaction(() => {
|
|
@@ -22893,6 +23588,34 @@ class SQLiteMemoryProvider {
|
|
|
22893
23588
|
this.ftsAvailable = false;
|
|
22894
23589
|
}
|
|
22895
23590
|
}
|
|
23591
|
+
async writeMemoryVec(record) {
|
|
23592
|
+
if (!this.config.embeddings.enabled)
|
|
23593
|
+
return;
|
|
23594
|
+
if (!this.vecAvailable)
|
|
23595
|
+
return;
|
|
23596
|
+
if (!this.embeddingProvider)
|
|
23597
|
+
return;
|
|
23598
|
+
if (!DURABLE_MEMORY_KINDS.has(record.kind))
|
|
23599
|
+
return;
|
|
23600
|
+
if (record.stability === "ephemeral")
|
|
23601
|
+
return;
|
|
23602
|
+
const normalizedText = normalizeMemoryText(record.text).toLowerCase();
|
|
23603
|
+
if (normalizedText.length === 0)
|
|
23604
|
+
return;
|
|
23605
|
+
try {
|
|
23606
|
+
const vector = await this.embeddingProvider.embed(normalizedText);
|
|
23607
|
+
this.requireDb().run("INSERT OR REPLACE INTO memory_items_vec (id, embedding) VALUES (?, ?)", [record.id, vector]);
|
|
23608
|
+
} catch (err) {
|
|
23609
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
23610
|
+
if (err instanceof EmbeddingUnavailableError) {
|
|
23611
|
+
warn("Embedding provider unavailable during write \u2014 skipping vector", {
|
|
23612
|
+
reason
|
|
23613
|
+
});
|
|
23614
|
+
} else {
|
|
23615
|
+
warn("Embedding computation failed \u2014 skipping vector", { reason });
|
|
23616
|
+
}
|
|
23617
|
+
}
|
|
23618
|
+
}
|
|
22896
23619
|
deleteMemoryFts(id) {
|
|
22897
23620
|
if (!this.ftsAvailable)
|
|
22898
23621
|
return;
|
|
@@ -22902,6 +23625,13 @@ class SQLiteMemoryProvider {
|
|
|
22902
23625
|
this.ftsAvailable = false;
|
|
22903
23626
|
}
|
|
22904
23627
|
}
|
|
23628
|
+
deleteMemoryVec(id) {
|
|
23629
|
+
if (!this.vecAvailable)
|
|
23630
|
+
return;
|
|
23631
|
+
try {
|
|
23632
|
+
this.requireDb().run("DELETE FROM memory_items_vec WHERE id = ?", [id]);
|
|
23633
|
+
} catch {}
|
|
23634
|
+
}
|
|
22905
23635
|
writeProposal(proposal) {
|
|
22906
23636
|
this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
|
|
22907
23637
|
id,
|
|
@@ -23245,6 +23975,29 @@ function rerankWithFts(items, ftsOrder) {
|
|
|
23245
23975
|
};
|
|
23246
23976
|
}).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
|
|
23247
23977
|
}
|
|
23978
|
+
function buildMetadataRankedIds(lexicalItems, request) {
|
|
23979
|
+
const scopeKeys = request.scopes?.map((s) => stableScopeKey(s)) ?? [];
|
|
23980
|
+
const kinds = new Set(request.kinds ?? []);
|
|
23981
|
+
const hasScopeFilter = scopeKeys.length > 0;
|
|
23982
|
+
const hasKindFilter = kinds.size > 0;
|
|
23983
|
+
const both = [];
|
|
23984
|
+
const scopeOnly = [];
|
|
23985
|
+
const kindOnly = [];
|
|
23986
|
+
const neither = [];
|
|
23987
|
+
for (const item of lexicalItems) {
|
|
23988
|
+
const scopeMatch = !hasScopeFilter || scopeKeys.includes(stableScopeKey(item.record.scope));
|
|
23989
|
+
const kindMatch = !hasKindFilter || kinds.has(item.record.kind);
|
|
23990
|
+
if (scopeMatch && kindMatch)
|
|
23991
|
+
both.push(item.record.id);
|
|
23992
|
+
else if (scopeMatch)
|
|
23993
|
+
scopeOnly.push(item.record.id);
|
|
23994
|
+
else if (kindMatch)
|
|
23995
|
+
kindOnly.push(item.record.id);
|
|
23996
|
+
else
|
|
23997
|
+
neither.push(item.record.id);
|
|
23998
|
+
}
|
|
23999
|
+
return [...both, ...scopeOnly, ...kindOnly, ...neither];
|
|
24000
|
+
}
|
|
23248
24001
|
|
|
23249
24002
|
// src/memory/provider-pool.ts
|
|
23250
24003
|
var MAX_POOL_SIZE = 16;
|
|
@@ -23384,7 +24137,7 @@ function resolvePoolKey(directory) {
|
|
|
23384
24137
|
try {
|
|
23385
24138
|
return realpathSync2(directory);
|
|
23386
24139
|
} catch {
|
|
23387
|
-
return
|
|
24140
|
+
return path47.resolve(directory);
|
|
23388
24141
|
}
|
|
23389
24142
|
}
|
|
23390
24143
|
|
|
@@ -23456,7 +24209,7 @@ var DEFAULT_MODES = [
|
|
|
23456
24209
|
];
|
|
23457
24210
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
23458
24211
|
async function evaluateMemoryRecallFixtures(options) {
|
|
23459
|
-
const fixtureDirectory =
|
|
24212
|
+
const fixtureDirectory = path48.resolve(options.fixtureDirectory);
|
|
23460
24213
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
23461
24214
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
23462
24215
|
const generatedAt = new Date().toISOString();
|
|
@@ -23465,7 +24218,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
23465
24218
|
for (const fixture of fixtures) {
|
|
23466
24219
|
const materialized = materializeFixture(fixture);
|
|
23467
24220
|
for (const providerName of providers) {
|
|
23468
|
-
const tempRoot = await fs19.realpath(await fs19.mkdtemp(
|
|
24221
|
+
const tempRoot = await fs19.realpath(await fs19.mkdtemp(path48.join(os12.tmpdir(), "swarm-memory-eval-")));
|
|
23469
24222
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
23470
24223
|
try {
|
|
23471
24224
|
await provider.initialize?.();
|
|
@@ -23509,7 +24262,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
|
23509
24262
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
23510
24263
|
const fixtures = [];
|
|
23511
24264
|
for (const file of files) {
|
|
23512
|
-
const raw = await fs19.readFile(
|
|
24265
|
+
const raw = await fs19.readFile(path48.join(fixtureDirectory, file), "utf-8");
|
|
23513
24266
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
23514
24267
|
}
|
|
23515
24268
|
return fixtures;
|
|
@@ -23786,8 +24539,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
23786
24539
|
}).passthrough();
|
|
23787
24540
|
// src/memory/consolidation-log.ts
|
|
23788
24541
|
import { appendFile as appendFile4, mkdir as mkdir12, readFile as readFile15 } from "fs/promises";
|
|
23789
|
-
import * as
|
|
23790
|
-
var LOG_RELATIVE_PATH =
|
|
24542
|
+
import * as path49 from "path";
|
|
24543
|
+
var LOG_RELATIVE_PATH = path49.join("memory", "consolidation-log.jsonl");
|
|
23791
24544
|
async function readConsolidationLog(directory) {
|
|
23792
24545
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
23793
24546
|
let raw;
|
|
@@ -23810,7 +24563,7 @@ async function readConsolidationLog(directory) {
|
|
|
23810
24563
|
}
|
|
23811
24564
|
|
|
23812
24565
|
// src/commands/memory.ts
|
|
23813
|
-
var PACKAGE_ROOT =
|
|
24566
|
+
var PACKAGE_ROOT = path50.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
23814
24567
|
async function handleMemoryCommand(_directory, _args) {
|
|
23815
24568
|
return [
|
|
23816
24569
|
"## Swarm Memory",
|
|
@@ -24108,7 +24861,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
24108
24861
|
}
|
|
24109
24862
|
function parseEvaluateArgs(directory, args) {
|
|
24110
24863
|
let json = false;
|
|
24111
|
-
let fixtureDirectory =
|
|
24864
|
+
let fixtureDirectory = path50.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
24112
24865
|
for (let i = 0;i < args.length; i++) {
|
|
24113
24866
|
const arg = args[i];
|
|
24114
24867
|
if (arg === "--json") {
|
|
@@ -24122,10 +24875,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
24122
24875
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
24123
24876
|
};
|
|
24124
24877
|
}
|
|
24125
|
-
const resolvedFixtures =
|
|
24126
|
-
const canonical =
|
|
24127
|
-
const allowedRootA =
|
|
24128
|
-
const allowedRootB =
|
|
24878
|
+
const resolvedFixtures = path50.resolve(directory, next);
|
|
24879
|
+
const canonical = path50.normalize(resolvedFixtures) + path50.sep;
|
|
24880
|
+
const allowedRootA = path50.normalize(directory) + path50.sep;
|
|
24881
|
+
const allowedRootB = path50.normalize(path50.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path50.sep;
|
|
24129
24882
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
24130
24883
|
return {
|
|
24131
24884
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -24164,15 +24917,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
24164
24917
|
return { limit, confirm };
|
|
24165
24918
|
}
|
|
24166
24919
|
function resolvePackageRootFromModule(modulePath) {
|
|
24167
|
-
const moduleDir =
|
|
24168
|
-
const leaf =
|
|
24920
|
+
const moduleDir = path50.dirname(modulePath);
|
|
24921
|
+
const leaf = path50.basename(moduleDir);
|
|
24169
24922
|
if (leaf === "commands" || leaf === "cli") {
|
|
24170
|
-
return
|
|
24923
|
+
return path50.resolve(moduleDir, "..", "..");
|
|
24171
24924
|
}
|
|
24172
24925
|
if (leaf === "dist") {
|
|
24173
|
-
return
|
|
24926
|
+
return path50.resolve(moduleDir, "..");
|
|
24174
24927
|
}
|
|
24175
|
-
return
|
|
24928
|
+
return path50.resolve(moduleDir, "..");
|
|
24176
24929
|
}
|
|
24177
24930
|
function formatMigrationResult(label, report) {
|
|
24178
24931
|
if (!report) {
|
|
@@ -24289,15 +25042,15 @@ function truncate(value, maxLength) {
|
|
|
24289
25042
|
}
|
|
24290
25043
|
|
|
24291
25044
|
// src/services/plan-service.ts
|
|
24292
|
-
var
|
|
25045
|
+
var _internals34 = {
|
|
24293
25046
|
loadPlanJsonOnly,
|
|
24294
25047
|
derivePlanMarkdown,
|
|
24295
25048
|
readSwarmFileAsync
|
|
24296
25049
|
};
|
|
24297
25050
|
async function getPlanData(directory, phaseArg) {
|
|
24298
|
-
const plan = await
|
|
25051
|
+
const plan = await _internals34.loadPlanJsonOnly(directory);
|
|
24299
25052
|
if (plan) {
|
|
24300
|
-
const fullMarkdown =
|
|
25053
|
+
const fullMarkdown = _internals34.derivePlanMarkdown(plan);
|
|
24301
25054
|
if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
|
|
24302
25055
|
return {
|
|
24303
25056
|
hasPlan: true,
|
|
@@ -24340,7 +25093,7 @@ async function getPlanData(directory, phaseArg) {
|
|
|
24340
25093
|
isLegacy: false
|
|
24341
25094
|
};
|
|
24342
25095
|
}
|
|
24343
|
-
const planContent = await
|
|
25096
|
+
const planContent = await _internals34.readSwarmFileAsync(directory, "plan.md");
|
|
24344
25097
|
if (!planContent) {
|
|
24345
25098
|
return {
|
|
24346
25099
|
hasPlan: false,
|
|
@@ -24437,7 +25190,7 @@ async function handlePlanCommand(directory, args) {
|
|
|
24437
25190
|
return formatPlanMarkdown(planData);
|
|
24438
25191
|
}
|
|
24439
25192
|
// src/commands/post-mortem.ts
|
|
24440
|
-
var
|
|
25193
|
+
var _internals35 = {
|
|
24441
25194
|
createCuratorLLMDelegate,
|
|
24442
25195
|
runCuratorPostMortem
|
|
24443
25196
|
};
|
|
@@ -24449,10 +25202,10 @@ async function handlePostMortemCommand(directory, args, options) {
|
|
|
24449
25202
|
};
|
|
24450
25203
|
if (options?.sessionID) {
|
|
24451
25204
|
try {
|
|
24452
|
-
pmOptions.llmDelegate =
|
|
25205
|
+
pmOptions.llmDelegate = _internals35.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
|
|
24453
25206
|
} catch {}
|
|
24454
25207
|
}
|
|
24455
|
-
const result = await
|
|
25208
|
+
const result = await _internals35.runCuratorPostMortem(directory, pmOptions);
|
|
24456
25209
|
const lines = [];
|
|
24457
25210
|
if (result.success) {
|
|
24458
25211
|
lines.push("## Post-Mortem Report Generated");
|
|
@@ -24607,12 +25360,12 @@ function formatRelativeTime(epochMs) {
|
|
|
24607
25360
|
const diffDays = Math.floor(diffHours / 24);
|
|
24608
25361
|
return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
24609
25362
|
}
|
|
24610
|
-
var
|
|
25363
|
+
var _internals36 = {
|
|
24611
25364
|
formatRelativeTime,
|
|
24612
25365
|
listActive
|
|
24613
25366
|
};
|
|
24614
25367
|
async function handlePrMonitorStatusCommand(directory, _args, sessionID, source) {
|
|
24615
|
-
const allActive = await
|
|
25368
|
+
const allActive = await _internals36.listActive(directory);
|
|
24616
25369
|
const allSessions = source === "cli";
|
|
24617
25370
|
const subs = allSessions ? allActive : allActive.filter((record) => record.sessionID === sessionID);
|
|
24618
25371
|
if (subs.length === 0) {
|
|
@@ -24750,7 +25503,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
24750
25503
|
const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
|
|
24751
25504
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
24752
25505
|
try {
|
|
24753
|
-
const config =
|
|
25506
|
+
const config = _internals37.loadPluginConfig(directory);
|
|
24754
25507
|
const prMonitorConfig = config.pr_monitor;
|
|
24755
25508
|
if (!prMonitorConfig?.enabled) {
|
|
24756
25509
|
return [
|
|
@@ -24760,7 +25513,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
24760
25513
|
].join(`
|
|
24761
25514
|
`);
|
|
24762
25515
|
}
|
|
24763
|
-
await
|
|
25516
|
+
await _internals37.subscribe(directory, {
|
|
24764
25517
|
sessionID,
|
|
24765
25518
|
prNumber: prInfo.number,
|
|
24766
25519
|
repoFullName,
|
|
@@ -24784,7 +25537,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
24784
25537
|
`);
|
|
24785
25538
|
}
|
|
24786
25539
|
}
|
|
24787
|
-
var
|
|
25540
|
+
var _internals37 = {
|
|
24788
25541
|
loadPluginConfig,
|
|
24789
25542
|
subscribe
|
|
24790
25543
|
};
|
|
@@ -24807,9 +25560,9 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
24807
25560
|
`);
|
|
24808
25561
|
}
|
|
24809
25562
|
const refToken = rest[0];
|
|
24810
|
-
const prInfo =
|
|
25563
|
+
const prInfo = _internals38.parsePrRef(refToken, directory);
|
|
24811
25564
|
if (!prInfo) {
|
|
24812
|
-
if (
|
|
25565
|
+
if (_internals38.looksLikePrRef(refToken)) {
|
|
24813
25566
|
return [
|
|
24814
25567
|
`Error: Could not resolve PR reference from "${refToken}".`,
|
|
24815
25568
|
"",
|
|
@@ -24830,8 +25583,8 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
24830
25583
|
const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
|
|
24831
25584
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
24832
25585
|
try {
|
|
24833
|
-
const correlationId =
|
|
24834
|
-
const result = await
|
|
25586
|
+
const correlationId = _internals38.buildCorrelationId(sessionID, repoFullName, prInfo.number);
|
|
25587
|
+
const result = await _internals38.unsubscribe(directory, correlationId);
|
|
24835
25588
|
if (!result) {
|
|
24836
25589
|
return [
|
|
24837
25590
|
`Not subscribed to ${prUrl}`,
|
|
@@ -24858,7 +25611,7 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
24858
25611
|
`);
|
|
24859
25612
|
}
|
|
24860
25613
|
}
|
|
24861
|
-
var
|
|
25614
|
+
var _internals38 = {
|
|
24862
25615
|
unsubscribe,
|
|
24863
25616
|
buildCorrelationId,
|
|
24864
25617
|
parsePrRef,
|
|
@@ -24867,11 +25620,11 @@ var _internals37 = {
|
|
|
24867
25620
|
|
|
24868
25621
|
// src/services/preflight-service.ts
|
|
24869
25622
|
import * as fs26 from "fs";
|
|
24870
|
-
import * as
|
|
25623
|
+
import * as path57 from "path";
|
|
24871
25624
|
|
|
24872
25625
|
// src/tools/lint.ts
|
|
24873
25626
|
import * as fs20 from "fs";
|
|
24874
|
-
import * as
|
|
25627
|
+
import * as path51 from "path";
|
|
24875
25628
|
|
|
24876
25629
|
// src/utils/path-security.ts
|
|
24877
25630
|
function containsPathTraversal(str) {
|
|
@@ -24927,9 +25680,9 @@ function validateArgs(args) {
|
|
|
24927
25680
|
}
|
|
24928
25681
|
function getLinterCommand(linter, mode, projectDir) {
|
|
24929
25682
|
const isWindows = process.platform === "win32";
|
|
24930
|
-
const binDir =
|
|
24931
|
-
const biomeBin = isWindows ?
|
|
24932
|
-
const eslintBin = isWindows ?
|
|
25683
|
+
const binDir = path51.join(projectDir, "node_modules", ".bin");
|
|
25684
|
+
const biomeBin = isWindows ? path51.join(binDir, "biome.EXE") : path51.join(binDir, "biome");
|
|
25685
|
+
const eslintBin = isWindows ? path51.join(binDir, "eslint.cmd") : path51.join(binDir, "eslint");
|
|
24933
25686
|
switch (linter) {
|
|
24934
25687
|
case "biome":
|
|
24935
25688
|
if (mode === "fix") {
|
|
@@ -24945,7 +25698,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
24945
25698
|
}
|
|
24946
25699
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
24947
25700
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
24948
|
-
const gradlew = fs20.existsSync(
|
|
25701
|
+
const gradlew = fs20.existsSync(path51.join(cwd, gradlewName)) ? path51.join(cwd, gradlewName) : null;
|
|
24949
25702
|
switch (linter) {
|
|
24950
25703
|
case "ruff":
|
|
24951
25704
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -24979,10 +25732,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
24979
25732
|
}
|
|
24980
25733
|
}
|
|
24981
25734
|
function detectRuff(cwd) {
|
|
24982
|
-
if (fs20.existsSync(
|
|
25735
|
+
if (fs20.existsSync(path51.join(cwd, "ruff.toml")))
|
|
24983
25736
|
return isCommandAvailable("ruff");
|
|
24984
25737
|
try {
|
|
24985
|
-
const pyproject =
|
|
25738
|
+
const pyproject = path51.join(cwd, "pyproject.toml");
|
|
24986
25739
|
if (fs20.existsSync(pyproject)) {
|
|
24987
25740
|
const content = fs20.readFileSync(pyproject, "utf-8");
|
|
24988
25741
|
if (content.includes("[tool.ruff]"))
|
|
@@ -24992,19 +25745,19 @@ function detectRuff(cwd) {
|
|
|
24992
25745
|
return false;
|
|
24993
25746
|
}
|
|
24994
25747
|
function detectClippy(cwd) {
|
|
24995
|
-
return fs20.existsSync(
|
|
25748
|
+
return fs20.existsSync(path51.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
24996
25749
|
}
|
|
24997
25750
|
function detectGolangciLint(cwd) {
|
|
24998
|
-
return fs20.existsSync(
|
|
25751
|
+
return fs20.existsSync(path51.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
24999
25752
|
}
|
|
25000
25753
|
function detectCheckstyle(cwd) {
|
|
25001
|
-
const hasMaven = fs20.existsSync(
|
|
25002
|
-
const hasGradle = fs20.existsSync(
|
|
25003
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs20.existsSync(
|
|
25754
|
+
const hasMaven = fs20.existsSync(path51.join(cwd, "pom.xml"));
|
|
25755
|
+
const hasGradle = fs20.existsSync(path51.join(cwd, "build.gradle")) || fs20.existsSync(path51.join(cwd, "build.gradle.kts"));
|
|
25756
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs20.existsSync(path51.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
25004
25757
|
return (hasMaven || hasGradle) && hasBinary;
|
|
25005
25758
|
}
|
|
25006
25759
|
function detectKtlint(cwd) {
|
|
25007
|
-
const hasKotlin = fs20.existsSync(
|
|
25760
|
+
const hasKotlin = fs20.existsSync(path51.join(cwd, "build.gradle.kts")) || fs20.existsSync(path51.join(cwd, "build.gradle")) || (() => {
|
|
25008
25761
|
try {
|
|
25009
25762
|
return fs20.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
25010
25763
|
} catch {
|
|
@@ -25023,11 +25776,11 @@ function detectDotnetFormat(cwd) {
|
|
|
25023
25776
|
}
|
|
25024
25777
|
}
|
|
25025
25778
|
function detectCppcheck(cwd) {
|
|
25026
|
-
if (fs20.existsSync(
|
|
25779
|
+
if (fs20.existsSync(path51.join(cwd, "CMakeLists.txt"))) {
|
|
25027
25780
|
return isCommandAvailable("cppcheck");
|
|
25028
25781
|
}
|
|
25029
25782
|
try {
|
|
25030
|
-
const dirsToCheck = [cwd,
|
|
25783
|
+
const dirsToCheck = [cwd, path51.join(cwd, "src")];
|
|
25031
25784
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
25032
25785
|
try {
|
|
25033
25786
|
return fs20.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -25041,13 +25794,13 @@ function detectCppcheck(cwd) {
|
|
|
25041
25794
|
}
|
|
25042
25795
|
}
|
|
25043
25796
|
function detectSwiftlint(cwd) {
|
|
25044
|
-
return fs20.existsSync(
|
|
25797
|
+
return fs20.existsSync(path51.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
25045
25798
|
}
|
|
25046
25799
|
function detectDartAnalyze(cwd) {
|
|
25047
|
-
return fs20.existsSync(
|
|
25800
|
+
return fs20.existsSync(path51.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
25048
25801
|
}
|
|
25049
25802
|
function detectRubocop(cwd) {
|
|
25050
|
-
return (fs20.existsSync(
|
|
25803
|
+
return (fs20.existsSync(path51.join(cwd, "Gemfile")) || fs20.existsSync(path51.join(cwd, "gems.rb")) || fs20.existsSync(path51.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
25051
25804
|
}
|
|
25052
25805
|
function detectAdditionalLinter(cwd) {
|
|
25053
25806
|
if (detectRuff(cwd))
|
|
@@ -25075,10 +25828,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
25075
25828
|
function findBinInAncestors(startDir, binName) {
|
|
25076
25829
|
let dir = startDir;
|
|
25077
25830
|
while (true) {
|
|
25078
|
-
const candidate =
|
|
25831
|
+
const candidate = path51.join(dir, "node_modules", ".bin", binName);
|
|
25079
25832
|
if (fs20.existsSync(candidate))
|
|
25080
25833
|
return candidate;
|
|
25081
|
-
const parent =
|
|
25834
|
+
const parent = path51.dirname(dir);
|
|
25082
25835
|
if (parent === dir)
|
|
25083
25836
|
break;
|
|
25084
25837
|
dir = parent;
|
|
@@ -25087,10 +25840,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
25087
25840
|
}
|
|
25088
25841
|
function findBinInEnvPath(binName) {
|
|
25089
25842
|
const searchPath = process.env.PATH ?? "";
|
|
25090
|
-
for (const dir of searchPath.split(
|
|
25843
|
+
for (const dir of searchPath.split(path51.delimiter)) {
|
|
25091
25844
|
if (!dir)
|
|
25092
25845
|
continue;
|
|
25093
|
-
const candidate =
|
|
25846
|
+
const candidate = path51.join(dir, binName);
|
|
25094
25847
|
if (fs20.existsSync(candidate))
|
|
25095
25848
|
return candidate;
|
|
25096
25849
|
}
|
|
@@ -25103,13 +25856,13 @@ async function detectAvailableLinter(directory) {
|
|
|
25103
25856
|
return null;
|
|
25104
25857
|
const projectDir = directory;
|
|
25105
25858
|
const isWindows = process.platform === "win32";
|
|
25106
|
-
const biomeBin = isWindows ?
|
|
25107
|
-
const eslintBin = isWindows ?
|
|
25859
|
+
const biomeBin = isWindows ? path51.join(projectDir, "node_modules", ".bin", "biome.EXE") : path51.join(projectDir, "node_modules", ".bin", "biome");
|
|
25860
|
+
const eslintBin = isWindows ? path51.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path51.join(projectDir, "node_modules", ".bin", "eslint");
|
|
25108
25861
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
25109
25862
|
if (localResult)
|
|
25110
25863
|
return localResult;
|
|
25111
|
-
const biomeAncestor = findBinInAncestors(
|
|
25112
|
-
const eslintAncestor = findBinInAncestors(
|
|
25864
|
+
const biomeAncestor = findBinInAncestors(path51.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
25865
|
+
const eslintAncestor = findBinInAncestors(path51.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
25113
25866
|
if (biomeAncestor || eslintAncestor) {
|
|
25114
25867
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
25115
25868
|
}
|
|
@@ -25292,15 +26045,15 @@ var lint = createSwarmTool({
|
|
|
25292
26045
|
}
|
|
25293
26046
|
const { mode } = args;
|
|
25294
26047
|
const cwd = directory;
|
|
25295
|
-
const linter = await
|
|
26048
|
+
const linter = await _internals39.detectAvailableLinter(directory);
|
|
25296
26049
|
if (linter) {
|
|
25297
|
-
const result = await
|
|
26050
|
+
const result = await _internals39.runLint(linter, mode, directory);
|
|
25298
26051
|
return JSON.stringify(result, null, 2);
|
|
25299
26052
|
}
|
|
25300
|
-
const additionalLinter =
|
|
26053
|
+
const additionalLinter = _internals39.detectAdditionalLinter(cwd);
|
|
25301
26054
|
if (additionalLinter) {
|
|
25302
26055
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
25303
|
-
const result = await
|
|
26056
|
+
const result = await _internals39.runAdditionalLint(additionalLinter, mode, cwd);
|
|
25304
26057
|
return JSON.stringify(result, null, 2);
|
|
25305
26058
|
}
|
|
25306
26059
|
const errorResult = {
|
|
@@ -25314,7 +26067,7 @@ For Rust: rustup component add clippy`
|
|
|
25314
26067
|
return JSON.stringify(errorResult, null, 2);
|
|
25315
26068
|
}
|
|
25316
26069
|
});
|
|
25317
|
-
var
|
|
26070
|
+
var _internals39 = {
|
|
25318
26071
|
detectAvailableLinter,
|
|
25319
26072
|
runLint,
|
|
25320
26073
|
detectAdditionalLinter,
|
|
@@ -25323,7 +26076,7 @@ var _internals38 = {
|
|
|
25323
26076
|
|
|
25324
26077
|
// src/tools/secretscan.ts
|
|
25325
26078
|
import * as fs21 from "fs";
|
|
25326
|
-
import * as
|
|
26079
|
+
import * as path52 from "path";
|
|
25327
26080
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
25328
26081
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
25329
26082
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -25550,7 +26303,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
25550
26303
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
25551
26304
|
}
|
|
25552
26305
|
function loadSecretScanIgnore(scanDir) {
|
|
25553
|
-
const ignorePath =
|
|
26306
|
+
const ignorePath = path52.join(scanDir, ".secretscanignore");
|
|
25554
26307
|
try {
|
|
25555
26308
|
if (!fs21.existsSync(ignorePath))
|
|
25556
26309
|
return [];
|
|
@@ -25573,7 +26326,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
25573
26326
|
if (exactNames.has(entry))
|
|
25574
26327
|
return true;
|
|
25575
26328
|
for (const pattern of globPatterns) {
|
|
25576
|
-
if (
|
|
26329
|
+
if (path52.matchesGlob(relPath, pattern))
|
|
25577
26330
|
return true;
|
|
25578
26331
|
}
|
|
25579
26332
|
return false;
|
|
@@ -25594,7 +26347,7 @@ function validateDirectoryInput(dir) {
|
|
|
25594
26347
|
return null;
|
|
25595
26348
|
}
|
|
25596
26349
|
function isBinaryFile(filePath, buffer) {
|
|
25597
|
-
const ext =
|
|
26350
|
+
const ext = path52.extname(filePath).toLowerCase();
|
|
25598
26351
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
25599
26352
|
return true;
|
|
25600
26353
|
}
|
|
@@ -25731,9 +26484,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
25731
26484
|
return false;
|
|
25732
26485
|
}
|
|
25733
26486
|
function isPathWithinScope(realPath, scanDir) {
|
|
25734
|
-
const resolvedScanDir =
|
|
25735
|
-
const resolvedRealPath =
|
|
25736
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
26487
|
+
const resolvedScanDir = path52.resolve(scanDir);
|
|
26488
|
+
const resolvedRealPath = path52.resolve(realPath);
|
|
26489
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path52.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
25737
26490
|
}
|
|
25738
26491
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
25739
26492
|
skippedDirs: 0,
|
|
@@ -25759,8 +26512,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25759
26512
|
return a.localeCompare(b);
|
|
25760
26513
|
});
|
|
25761
26514
|
for (const entry of entries) {
|
|
25762
|
-
const fullPath =
|
|
25763
|
-
const relPath =
|
|
26515
|
+
const fullPath = path52.join(dir, entry);
|
|
26516
|
+
const relPath = path52.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
25764
26517
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
25765
26518
|
stats.skippedDirs++;
|
|
25766
26519
|
continue;
|
|
@@ -25795,7 +26548,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25795
26548
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
25796
26549
|
files.push(...subFiles);
|
|
25797
26550
|
} else if (lstat2.isFile()) {
|
|
25798
|
-
const ext =
|
|
26551
|
+
const ext = path52.extname(fullPath).toLowerCase();
|
|
25799
26552
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
25800
26553
|
files.push(fullPath);
|
|
25801
26554
|
} else {
|
|
@@ -25861,7 +26614,7 @@ var secretscan = createSwarmTool({
|
|
|
25861
26614
|
}
|
|
25862
26615
|
}
|
|
25863
26616
|
try {
|
|
25864
|
-
const _scanDirRaw =
|
|
26617
|
+
const _scanDirRaw = path52.resolve(directory);
|
|
25865
26618
|
const scanDir = (() => {
|
|
25866
26619
|
try {
|
|
25867
26620
|
return fs21.realpathSync(_scanDirRaw);
|
|
@@ -26002,7 +26755,7 @@ var secretscan = createSwarmTool({
|
|
|
26002
26755
|
});
|
|
26003
26756
|
async function runSecretscan(directory) {
|
|
26004
26757
|
try {
|
|
26005
|
-
const result = await
|
|
26758
|
+
const result = await _internals40.secretscan.execute({ directory }, {});
|
|
26006
26759
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
26007
26760
|
return JSON.parse(jsonStr);
|
|
26008
26761
|
} catch (e) {
|
|
@@ -26017,18 +26770,18 @@ async function runSecretscan(directory) {
|
|
|
26017
26770
|
return errorResult;
|
|
26018
26771
|
}
|
|
26019
26772
|
}
|
|
26020
|
-
var
|
|
26773
|
+
var _internals40 = {
|
|
26021
26774
|
secretscan,
|
|
26022
26775
|
runSecretscan
|
|
26023
26776
|
};
|
|
26024
26777
|
|
|
26025
26778
|
// src/tools/test-runner.ts
|
|
26026
26779
|
import * as fs25 from "fs";
|
|
26027
|
-
import * as
|
|
26780
|
+
import * as path56 from "path";
|
|
26028
26781
|
|
|
26029
26782
|
// src/test-impact/analyzer.ts
|
|
26030
26783
|
import fs22 from "fs";
|
|
26031
|
-
import
|
|
26784
|
+
import path53 from "path";
|
|
26032
26785
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
26033
26786
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
26034
26787
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -26069,8 +26822,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
26069
26822
|
if (!importPath.startsWith(".")) {
|
|
26070
26823
|
return null;
|
|
26071
26824
|
}
|
|
26072
|
-
const resolved =
|
|
26073
|
-
if (
|
|
26825
|
+
const resolved = path53.resolve(fromDir, importPath);
|
|
26826
|
+
if (path53.extname(resolved)) {
|
|
26074
26827
|
if (fs22.existsSync(resolved) && fs22.statSync(resolved).isFile()) {
|
|
26075
26828
|
return normalizePath2(resolved);
|
|
26076
26829
|
}
|
|
@@ -26090,20 +26843,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
26090
26843
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
26091
26844
|
let baseDir = fromDir;
|
|
26092
26845
|
for (let i = 1;i < leadingDots; i++) {
|
|
26093
|
-
baseDir =
|
|
26846
|
+
baseDir = path53.dirname(baseDir);
|
|
26094
26847
|
}
|
|
26095
26848
|
const rest = module.slice(leadingDots);
|
|
26096
26849
|
if (rest.length === 0) {
|
|
26097
|
-
const initPath =
|
|
26850
|
+
const initPath = path53.join(baseDir, "__init__.py");
|
|
26098
26851
|
if (fs22.existsSync(initPath) && fs22.statSync(initPath).isFile()) {
|
|
26099
26852
|
return normalizePath2(initPath);
|
|
26100
26853
|
}
|
|
26101
26854
|
return null;
|
|
26102
26855
|
}
|
|
26103
|
-
const subpath = rest.replace(/\./g,
|
|
26856
|
+
const subpath = rest.replace(/\./g, path53.sep);
|
|
26104
26857
|
const candidates = [
|
|
26105
|
-
`${
|
|
26106
|
-
|
|
26858
|
+
`${path53.join(baseDir, subpath)}.py`,
|
|
26859
|
+
path53.join(baseDir, subpath, "__init__.py")
|
|
26107
26860
|
];
|
|
26108
26861
|
for (const c of candidates) {
|
|
26109
26862
|
if (fs22.existsSync(c) && fs22.statSync(c).isFile())
|
|
@@ -26113,7 +26866,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
26113
26866
|
}
|
|
26114
26867
|
var goModuleCache = new Map;
|
|
26115
26868
|
function findGoModule(fromDir) {
|
|
26116
|
-
const resolved =
|
|
26869
|
+
const resolved = path53.resolve(fromDir);
|
|
26117
26870
|
let cur = resolved;
|
|
26118
26871
|
const walked = [];
|
|
26119
26872
|
for (let i = 0;i < 16; i++) {
|
|
@@ -26125,7 +26878,7 @@ function findGoModule(fromDir) {
|
|
|
26125
26878
|
}
|
|
26126
26879
|
walked.push(cur);
|
|
26127
26880
|
try {
|
|
26128
|
-
const goMod =
|
|
26881
|
+
const goMod = path53.join(cur, "go.mod");
|
|
26129
26882
|
const content = fs22.readFileSync(goMod, "utf-8");
|
|
26130
26883
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
26131
26884
|
if (moduleMatch) {
|
|
@@ -26136,10 +26889,10 @@ function findGoModule(fromDir) {
|
|
|
26136
26889
|
}
|
|
26137
26890
|
} catch {}
|
|
26138
26891
|
try {
|
|
26139
|
-
fs22.accessSync(
|
|
26892
|
+
fs22.accessSync(path53.join(cur, ".git"));
|
|
26140
26893
|
break;
|
|
26141
26894
|
} catch {}
|
|
26142
|
-
const parent =
|
|
26895
|
+
const parent = path53.dirname(cur);
|
|
26143
26896
|
if (parent === cur)
|
|
26144
26897
|
break;
|
|
26145
26898
|
cur = parent;
|
|
@@ -26151,12 +26904,12 @@ function findGoModule(fromDir) {
|
|
|
26151
26904
|
function resolveGoImport(fromDir, importPath) {
|
|
26152
26905
|
let dir = null;
|
|
26153
26906
|
if (importPath.startsWith(".")) {
|
|
26154
|
-
dir =
|
|
26907
|
+
dir = path53.resolve(fromDir, importPath);
|
|
26155
26908
|
} else {
|
|
26156
26909
|
const mod = findGoModule(fromDir);
|
|
26157
26910
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
26158
26911
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
26159
|
-
dir =
|
|
26912
|
+
dir = path53.join(mod.moduleRoot, subpath);
|
|
26160
26913
|
}
|
|
26161
26914
|
}
|
|
26162
26915
|
if (dir === null)
|
|
@@ -26164,7 +26917,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
26164
26917
|
if (!fs22.existsSync(dir) || !fs22.statSync(dir).isDirectory())
|
|
26165
26918
|
return [];
|
|
26166
26919
|
try {
|
|
26167
|
-
return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(
|
|
26920
|
+
return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path53.join(dir, f)));
|
|
26168
26921
|
} catch {
|
|
26169
26922
|
return [];
|
|
26170
26923
|
}
|
|
@@ -26203,15 +26956,15 @@ function findTestFilesSync(cwd) {
|
|
|
26203
26956
|
for (const entry of entries) {
|
|
26204
26957
|
if (entry.isDirectory()) {
|
|
26205
26958
|
if (!skipDirs.has(entry.name)) {
|
|
26206
|
-
walk(
|
|
26959
|
+
walk(path53.join(dir, entry.name), visitedInodes);
|
|
26207
26960
|
}
|
|
26208
26961
|
} else if (entry.isFile()) {
|
|
26209
26962
|
const name = entry.name;
|
|
26210
26963
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
26211
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
26964
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path53.sep}tests${path53.sep}`) && name.endsWith(".py");
|
|
26212
26965
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
26213
26966
|
if (isTsTest || isPyTest || isGoTest) {
|
|
26214
|
-
testFiles.push(normalizePath2(
|
|
26967
|
+
testFiles.push(normalizePath2(path53.join(dir, entry.name)));
|
|
26215
26968
|
}
|
|
26216
26969
|
}
|
|
26217
26970
|
}
|
|
@@ -26236,8 +26989,8 @@ function extractImports(content) {
|
|
|
26236
26989
|
];
|
|
26237
26990
|
}
|
|
26238
26991
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
26239
|
-
const ext =
|
|
26240
|
-
const testDir =
|
|
26992
|
+
const ext = path53.extname(testFile).toLowerCase();
|
|
26993
|
+
const testDir = path53.dirname(testFile);
|
|
26241
26994
|
function addEdge(source) {
|
|
26242
26995
|
if (!impactMap[source])
|
|
26243
26996
|
impactMap[source] = [];
|
|
@@ -26290,7 +27043,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
26290
27043
|
}
|
|
26291
27044
|
return impactMap;
|
|
26292
27045
|
}
|
|
26293
|
-
var
|
|
27046
|
+
var _internals41 = {
|
|
26294
27047
|
validateProjectRoot,
|
|
26295
27048
|
normalizePath: normalizePath2,
|
|
26296
27049
|
isCacheStale,
|
|
@@ -26305,12 +27058,12 @@ var _internals40 = {
|
|
|
26305
27058
|
_clearGoModuleCache
|
|
26306
27059
|
};
|
|
26307
27060
|
async function buildImpactMap(cwd) {
|
|
26308
|
-
const impactMap = await
|
|
26309
|
-
await
|
|
27061
|
+
const impactMap = await _internals41.buildImpactMapInternal(cwd);
|
|
27062
|
+
await _internals41.saveImpactMap(cwd, impactMap);
|
|
26310
27063
|
return impactMap;
|
|
26311
27064
|
}
|
|
26312
27065
|
async function loadImpactMap(cwd, options) {
|
|
26313
|
-
const cachePath =
|
|
27066
|
+
const cachePath = path53.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
26314
27067
|
if (fs22.existsSync(cachePath)) {
|
|
26315
27068
|
try {
|
|
26316
27069
|
const content = fs22.readFileSync(cachePath, "utf-8");
|
|
@@ -26320,7 +27073,7 @@ async function loadImpactMap(cwd, options) {
|
|
|
26320
27073
|
const hasValidValues = Object.values(map).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
|
|
26321
27074
|
if (hasValidValues) {
|
|
26322
27075
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
26323
|
-
if (!
|
|
27076
|
+
if (!_internals41.isCacheStale(map, generatedAt)) {
|
|
26324
27077
|
return map;
|
|
26325
27078
|
}
|
|
26326
27079
|
if (options?.skipRebuild) {
|
|
@@ -26340,15 +27093,15 @@ async function loadImpactMap(cwd, options) {
|
|
|
26340
27093
|
if (options?.skipRebuild) {
|
|
26341
27094
|
return {};
|
|
26342
27095
|
}
|
|
26343
|
-
return
|
|
27096
|
+
return _internals41.buildImpactMap(cwd);
|
|
26344
27097
|
}
|
|
26345
27098
|
async function saveImpactMap(cwd, impactMap) {
|
|
26346
|
-
if (!
|
|
27099
|
+
if (!path53.isAbsolute(cwd)) {
|
|
26347
27100
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
26348
27101
|
}
|
|
26349
|
-
|
|
26350
|
-
const cacheDir2 =
|
|
26351
|
-
const cachePath =
|
|
27102
|
+
_internals41.validateProjectRoot(cwd);
|
|
27103
|
+
const cacheDir2 = path53.join(cwd, ".swarm", "cache");
|
|
27104
|
+
const cachePath = path53.join(cacheDir2, "impact-map.json");
|
|
26352
27105
|
if (!fs22.existsSync(cacheDir2)) {
|
|
26353
27106
|
fs22.mkdirSync(cacheDir2, { recursive: true });
|
|
26354
27107
|
}
|
|
@@ -26370,7 +27123,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
26370
27123
|
};
|
|
26371
27124
|
}
|
|
26372
27125
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
|
|
26373
|
-
const impactMap = await
|
|
27126
|
+
const impactMap = await _internals41.loadImpactMap(cwd);
|
|
26374
27127
|
const impactedTestsSet = new Set;
|
|
26375
27128
|
const untestedFiles = [];
|
|
26376
27129
|
let visitedCount = 0;
|
|
@@ -26380,7 +27133,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
26380
27133
|
budgetExceeded = true;
|
|
26381
27134
|
break;
|
|
26382
27135
|
}
|
|
26383
|
-
const normalizedChanged = normalizePath2(
|
|
27136
|
+
const normalizedChanged = normalizePath2(path53.resolve(changedFile));
|
|
26384
27137
|
const tests = impactMap[normalizedChanged];
|
|
26385
27138
|
if (tests && tests.length > 0) {
|
|
26386
27139
|
for (const test of tests) {
|
|
@@ -26394,13 +27147,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
26394
27147
|
if (budgetExceeded)
|
|
26395
27148
|
break;
|
|
26396
27149
|
} else {
|
|
26397
|
-
const changedDir = normalizePath2(
|
|
26398
|
-
const changedInputDir = normalizePath2(
|
|
27150
|
+
const changedDir = normalizePath2(path53.dirname(normalizedChanged));
|
|
27151
|
+
const changedInputDir = normalizePath2(path53.dirname(changedFile));
|
|
26399
27152
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
26400
27153
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
26401
27154
|
}).sort(([sourceA], [sourceB]) => {
|
|
26402
|
-
const sourceDirA = normalizePath2(
|
|
26403
|
-
const sourceDirB = normalizePath2(
|
|
27155
|
+
const sourceDirA = normalizePath2(path53.dirname(sourceA));
|
|
27156
|
+
const sourceDirB = normalizePath2(path53.dirname(sourceB));
|
|
26404
27157
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
26405
27158
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
26406
27159
|
if (exactA !== exactB)
|
|
@@ -26727,7 +27480,7 @@ function detectFlakyTests(allHistory) {
|
|
|
26727
27480
|
|
|
26728
27481
|
// src/test-impact/history-store.ts
|
|
26729
27482
|
import fs23 from "fs";
|
|
26730
|
-
import
|
|
27483
|
+
import path54 from "path";
|
|
26731
27484
|
var MAX_HISTORY_PER_TEST = 20;
|
|
26732
27485
|
var MAX_ERROR_LENGTH = 500;
|
|
26733
27486
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -26739,10 +27492,10 @@ function getHistoryPath(workingDir) {
|
|
|
26739
27492
|
if (!workingDir) {
|
|
26740
27493
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
26741
27494
|
}
|
|
26742
|
-
if (!
|
|
27495
|
+
if (!path54.isAbsolute(workingDir)) {
|
|
26743
27496
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
26744
27497
|
}
|
|
26745
|
-
return
|
|
27498
|
+
return path54.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
26746
27499
|
}
|
|
26747
27500
|
function sanitizeErrorMessage(errorMessage) {
|
|
26748
27501
|
if (errorMessage === undefined) {
|
|
@@ -26834,8 +27587,8 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
26834
27587
|
}
|
|
26835
27588
|
}
|
|
26836
27589
|
const historyPath = getHistoryPath(workingDir);
|
|
26837
|
-
const historyDir =
|
|
26838
|
-
|
|
27590
|
+
const historyDir = path54.dirname(historyPath);
|
|
27591
|
+
_internals42.validateProjectRoot(workingDir);
|
|
26839
27592
|
if (!fs23.existsSync(historyDir)) {
|
|
26840
27593
|
fs23.mkdirSync(historyDir, { recursive: true });
|
|
26841
27594
|
}
|
|
@@ -26958,13 +27711,13 @@ function getAllHistory(workingDir) {
|
|
|
26958
27711
|
records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
26959
27712
|
return records;
|
|
26960
27713
|
}
|
|
26961
|
-
var
|
|
27714
|
+
var _internals42 = {
|
|
26962
27715
|
validateProjectRoot
|
|
26963
27716
|
};
|
|
26964
27717
|
|
|
26965
27718
|
// src/tools/resolve-working-directory.ts
|
|
26966
27719
|
import * as fs24 from "fs";
|
|
26967
|
-
import * as
|
|
27720
|
+
import * as path55 from "path";
|
|
26968
27721
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
26969
27722
|
if (workingDirectory == null || workingDirectory === "") {
|
|
26970
27723
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -27003,8 +27756,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
27003
27756
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
27004
27757
|
};
|
|
27005
27758
|
}
|
|
27006
|
-
const normalizedDir =
|
|
27007
|
-
const resolvedDir =
|
|
27759
|
+
const normalizedDir = path55.normalize(workingDirectory);
|
|
27760
|
+
const resolvedDir = path55.resolve(normalizedDir);
|
|
27008
27761
|
let statResult;
|
|
27009
27762
|
try {
|
|
27010
27763
|
statResult = fs24.statSync(resolvedDir);
|
|
@@ -27023,7 +27776,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
27023
27776
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
27024
27777
|
return { success: true, directory: resolvedDir };
|
|
27025
27778
|
}
|
|
27026
|
-
const resolvedFallback =
|
|
27779
|
+
const resolvedFallback = path55.resolve(fallbackDirectory);
|
|
27027
27780
|
let fallbackExists = false;
|
|
27028
27781
|
try {
|
|
27029
27782
|
fs24.statSync(resolvedFallback);
|
|
@@ -27032,7 +27785,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
27032
27785
|
fallbackExists = false;
|
|
27033
27786
|
}
|
|
27034
27787
|
if (fallbackExists) {
|
|
27035
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
27788
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path55.sep);
|
|
27036
27789
|
if (isSubdirectory) {
|
|
27037
27790
|
return {
|
|
27038
27791
|
success: false,
|
|
@@ -27055,7 +27808,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
27055
27808
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
27056
27809
|
const uniqueTestFiles = new Set;
|
|
27057
27810
|
for (const sourceFile of sourceFiles) {
|
|
27058
|
-
const resolvedPath =
|
|
27811
|
+
const resolvedPath = path56.resolve(cwd, sourceFile);
|
|
27059
27812
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
27060
27813
|
const testFiles = impactMap[normalizedPath];
|
|
27061
27814
|
if (testFiles) {
|
|
@@ -27140,14 +27893,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
27140
27893
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
27141
27894
|
}
|
|
27142
27895
|
function detectGoTest(cwd) {
|
|
27143
|
-
return fs25.existsSync(
|
|
27896
|
+
return fs25.existsSync(path56.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
27144
27897
|
}
|
|
27145
27898
|
function detectJavaMaven(cwd) {
|
|
27146
|
-
return fs25.existsSync(
|
|
27899
|
+
return fs25.existsSync(path56.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
27147
27900
|
}
|
|
27148
27901
|
function detectGradle(cwd) {
|
|
27149
|
-
const hasBuildFile = fs25.existsSync(
|
|
27150
|
-
const hasGradlew = fs25.existsSync(
|
|
27902
|
+
const hasBuildFile = fs25.existsSync(path56.join(cwd, "build.gradle")) || fs25.existsSync(path56.join(cwd, "build.gradle.kts"));
|
|
27903
|
+
const hasGradlew = fs25.existsSync(path56.join(cwd, "gradlew")) || fs25.existsSync(path56.join(cwd, "gradlew.bat"));
|
|
27151
27904
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
27152
27905
|
}
|
|
27153
27906
|
function detectDotnetTest(cwd) {
|
|
@@ -27160,25 +27913,25 @@ function detectDotnetTest(cwd) {
|
|
|
27160
27913
|
}
|
|
27161
27914
|
}
|
|
27162
27915
|
function detectCTest(cwd) {
|
|
27163
|
-
const hasSource = fs25.existsSync(
|
|
27164
|
-
const hasBuildCache = fs25.existsSync(
|
|
27916
|
+
const hasSource = fs25.existsSync(path56.join(cwd, "CMakeLists.txt"));
|
|
27917
|
+
const hasBuildCache = fs25.existsSync(path56.join(cwd, "CMakeCache.txt")) || fs25.existsSync(path56.join(cwd, "build", "CMakeCache.txt"));
|
|
27165
27918
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
27166
27919
|
}
|
|
27167
27920
|
function detectSwiftTest(cwd) {
|
|
27168
|
-
return fs25.existsSync(
|
|
27921
|
+
return fs25.existsSync(path56.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
27169
27922
|
}
|
|
27170
27923
|
function detectDartTest(cwd) {
|
|
27171
|
-
return fs25.existsSync(
|
|
27924
|
+
return fs25.existsSync(path56.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
27172
27925
|
}
|
|
27173
27926
|
function detectRSpec(cwd) {
|
|
27174
|
-
const hasRSpecFile = fs25.existsSync(
|
|
27175
|
-
const hasGemfile = fs25.existsSync(
|
|
27176
|
-
const hasSpecDir = fs25.existsSync(
|
|
27927
|
+
const hasRSpecFile = fs25.existsSync(path56.join(cwd, ".rspec"));
|
|
27928
|
+
const hasGemfile = fs25.existsSync(path56.join(cwd, "Gemfile"));
|
|
27929
|
+
const hasSpecDir = fs25.existsSync(path56.join(cwd, "spec"));
|
|
27177
27930
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
27178
27931
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
27179
27932
|
}
|
|
27180
27933
|
function detectMinitest(cwd) {
|
|
27181
|
-
return fs25.existsSync(
|
|
27934
|
+
return fs25.existsSync(path56.join(cwd, "test")) && (fs25.existsSync(path56.join(cwd, "Gemfile")) || fs25.existsSync(path56.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
27182
27935
|
}
|
|
27183
27936
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
27184
27937
|
bun: "bun",
|
|
@@ -27263,7 +28016,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
27263
28016
|
async function detectTestFramework(cwd) {
|
|
27264
28017
|
const baseDir = cwd;
|
|
27265
28018
|
try {
|
|
27266
|
-
const packageJsonPath =
|
|
28019
|
+
const packageJsonPath = path56.join(baseDir, "package.json");
|
|
27267
28020
|
if (fs25.existsSync(packageJsonPath)) {
|
|
27268
28021
|
const content = fs25.readFileSync(packageJsonPath, "utf-8");
|
|
27269
28022
|
const pkg = JSON.parse(content);
|
|
@@ -27284,16 +28037,16 @@ async function detectTestFramework(cwd) {
|
|
|
27284
28037
|
return "jest";
|
|
27285
28038
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
27286
28039
|
return "mocha";
|
|
27287
|
-
if (fs25.existsSync(
|
|
28040
|
+
if (fs25.existsSync(path56.join(baseDir, "bun.lockb")) || fs25.existsSync(path56.join(baseDir, "bun.lock"))) {
|
|
27288
28041
|
if (scripts.test?.includes("bun"))
|
|
27289
28042
|
return "bun";
|
|
27290
28043
|
}
|
|
27291
28044
|
}
|
|
27292
28045
|
} catch {}
|
|
27293
28046
|
try {
|
|
27294
|
-
const pyprojectTomlPath =
|
|
27295
|
-
const setupCfgPath =
|
|
27296
|
-
const requirementsTxtPath =
|
|
28047
|
+
const pyprojectTomlPath = path56.join(baseDir, "pyproject.toml");
|
|
28048
|
+
const setupCfgPath = path56.join(baseDir, "setup.cfg");
|
|
28049
|
+
const requirementsTxtPath = path56.join(baseDir, "requirements.txt");
|
|
27297
28050
|
if (fs25.existsSync(pyprojectTomlPath)) {
|
|
27298
28051
|
const content = fs25.readFileSync(pyprojectTomlPath, "utf-8");
|
|
27299
28052
|
if (content.includes("[tool.pytest"))
|
|
@@ -27313,7 +28066,7 @@ async function detectTestFramework(cwd) {
|
|
|
27313
28066
|
}
|
|
27314
28067
|
} catch {}
|
|
27315
28068
|
try {
|
|
27316
|
-
const cargoTomlPath =
|
|
28069
|
+
const cargoTomlPath = path56.join(baseDir, "Cargo.toml");
|
|
27317
28070
|
if (fs25.existsSync(cargoTomlPath)) {
|
|
27318
28071
|
const content = fs25.readFileSync(cargoTomlPath, "utf-8");
|
|
27319
28072
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -27324,9 +28077,9 @@ async function detectTestFramework(cwd) {
|
|
|
27324
28077
|
}
|
|
27325
28078
|
} catch {}
|
|
27326
28079
|
try {
|
|
27327
|
-
const pesterConfigPath =
|
|
27328
|
-
const pesterConfigJsonPath =
|
|
27329
|
-
const pesterPs1Path =
|
|
28080
|
+
const pesterConfigPath = path56.join(baseDir, "pester.config.ps1");
|
|
28081
|
+
const pesterConfigJsonPath = path56.join(baseDir, "pester.config.ps1.json");
|
|
28082
|
+
const pesterPs1Path = path56.join(baseDir, "tests.ps1");
|
|
27330
28083
|
if (fs25.existsSync(pesterConfigPath) || fs25.existsSync(pesterConfigJsonPath) || fs25.existsSync(pesterPs1Path)) {
|
|
27331
28084
|
return "pester";
|
|
27332
28085
|
}
|
|
@@ -27369,12 +28122,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
27369
28122
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
27370
28123
|
}
|
|
27371
28124
|
function resolveWorkspacePath(file, workingDir) {
|
|
27372
|
-
return
|
|
28125
|
+
return path56.isAbsolute(file) ? path56.resolve(file) : path56.resolve(workingDir, file);
|
|
27373
28126
|
}
|
|
27374
28127
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
27375
28128
|
if (!preferRelative)
|
|
27376
28129
|
return absolutePath;
|
|
27377
|
-
return
|
|
28130
|
+
return path56.relative(workingDir, absolutePath);
|
|
27378
28131
|
}
|
|
27379
28132
|
function dedupePush(target, value) {
|
|
27380
28133
|
if (!target.includes(value)) {
|
|
@@ -27411,18 +28164,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
27411
28164
|
}
|
|
27412
28165
|
}
|
|
27413
28166
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
27414
|
-
const relativeDir =
|
|
28167
|
+
const relativeDir = path56.dirname(relativePath);
|
|
27415
28168
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
27416
28169
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
27417
|
-
const rootDir =
|
|
27418
|
-
return nestedRelativeDir ? [rootDir,
|
|
28170
|
+
const rootDir = path56.join(workingDir, dirName);
|
|
28171
|
+
return nestedRelativeDir ? [rootDir, path56.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
27419
28172
|
});
|
|
27420
28173
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
27421
28174
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
27422
|
-
directories.push(
|
|
28175
|
+
directories.push(path56.join(workingDir, "src/test/java", path56.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
27423
28176
|
}
|
|
27424
28177
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
27425
|
-
directories.push(
|
|
28178
|
+
directories.push(path56.join(workingDir, "src/test/kotlin", path56.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
27426
28179
|
}
|
|
27427
28180
|
return [...new Set(directories)];
|
|
27428
28181
|
}
|
|
@@ -27450,23 +28203,23 @@ function isLanguageSpecificTestFile(basename10) {
|
|
|
27450
28203
|
}
|
|
27451
28204
|
function isConventionTestFilePath(filePath) {
|
|
27452
28205
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
27453
|
-
const basename10 =
|
|
28206
|
+
const basename10 = path56.basename(filePath);
|
|
27454
28207
|
return hasCompoundTestExtension(basename10) || basename10.includes(".spec.") || basename10.includes(".test.") || isLanguageSpecificTestFile(basename10) || isTestDirectoryPath(normalizedPath);
|
|
27455
28208
|
}
|
|
27456
28209
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
27457
28210
|
const testFiles = [];
|
|
27458
28211
|
for (const file of sourceFiles) {
|
|
27459
28212
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
27460
|
-
const relativeFile =
|
|
27461
|
-
const basename10 =
|
|
27462
|
-
const dirname25 =
|
|
27463
|
-
const preferRelativeOutput = !
|
|
28213
|
+
const relativeFile = path56.relative(workingDir, absoluteFile);
|
|
28214
|
+
const basename10 = path56.basename(absoluteFile);
|
|
28215
|
+
const dirname25 = path56.dirname(absoluteFile);
|
|
28216
|
+
const preferRelativeOutput = !path56.isAbsolute(file);
|
|
27464
28217
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
27465
28218
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
27466
28219
|
continue;
|
|
27467
28220
|
}
|
|
27468
28221
|
const nameWithoutExt = basename10.replace(/\.[^.]+$/, "");
|
|
27469
|
-
const ext =
|
|
28222
|
+
const ext = path56.extname(basename10);
|
|
27470
28223
|
const genericTestNames = [
|
|
27471
28224
|
`${nameWithoutExt}.spec${ext}`,
|
|
27472
28225
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -27475,7 +28228,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
27475
28228
|
const colocatedCandidates = [
|
|
27476
28229
|
...genericTestNames,
|
|
27477
28230
|
...languageSpecificTestNames
|
|
27478
|
-
].map((candidateName) =>
|
|
28231
|
+
].map((candidateName) => path56.join(dirname25, candidateName));
|
|
27479
28232
|
const testDirectoryNames = [
|
|
27480
28233
|
basename10,
|
|
27481
28234
|
...genericTestNames,
|
|
@@ -27484,8 +28237,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
27484
28237
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
27485
28238
|
const possibleTestFiles = [
|
|
27486
28239
|
...colocatedCandidates,
|
|
27487
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
27488
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
28240
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path56.join(dirname25, dirName, candidateName))),
|
|
28241
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path56.join(candidateDir, candidateName)))
|
|
27489
28242
|
];
|
|
27490
28243
|
for (const testFile of possibleTestFiles) {
|
|
27491
28244
|
if (fs25.existsSync(testFile)) {
|
|
@@ -27506,7 +28259,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27506
28259
|
try {
|
|
27507
28260
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
27508
28261
|
const content = fs25.readFileSync(absoluteTestFile, "utf-8");
|
|
27509
|
-
const testDir =
|
|
28262
|
+
const testDir = path56.dirname(absoluteTestFile);
|
|
27510
28263
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
27511
28264
|
let match;
|
|
27512
28265
|
match = importRegex.exec(content);
|
|
@@ -27514,8 +28267,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27514
28267
|
const importPath = match[1];
|
|
27515
28268
|
let resolvedImport;
|
|
27516
28269
|
if (importPath.startsWith(".")) {
|
|
27517
|
-
resolvedImport =
|
|
27518
|
-
const existingExt =
|
|
28270
|
+
resolvedImport = path56.resolve(testDir, importPath);
|
|
28271
|
+
const existingExt = path56.extname(resolvedImport);
|
|
27519
28272
|
if (!existingExt) {
|
|
27520
28273
|
for (const extToTry of [
|
|
27521
28274
|
".ts",
|
|
@@ -27535,12 +28288,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27535
28288
|
} else {
|
|
27536
28289
|
continue;
|
|
27537
28290
|
}
|
|
27538
|
-
const importBasename =
|
|
27539
|
-
const importDir =
|
|
28291
|
+
const importBasename = path56.basename(resolvedImport, path56.extname(resolvedImport));
|
|
28292
|
+
const importDir = path56.dirname(resolvedImport);
|
|
27540
28293
|
for (const sourceFile of absoluteSourceFiles) {
|
|
27541
|
-
const sourceDir =
|
|
27542
|
-
const sourceBasename =
|
|
27543
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
28294
|
+
const sourceDir = path56.dirname(sourceFile);
|
|
28295
|
+
const sourceBasename = path56.basename(sourceFile, path56.extname(sourceFile));
|
|
28296
|
+
const isRelatedDir = importDir === sourceDir || importDir === path56.join(sourceDir, "__tests__") || importDir === path56.join(sourceDir, "tests") || importDir === path56.join(sourceDir, "test") || importDir === path56.join(sourceDir, "spec");
|
|
27544
28297
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
27545
28298
|
dedupePush(testFiles, testFile);
|
|
27546
28299
|
break;
|
|
@@ -27553,8 +28306,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27553
28306
|
while (match !== null) {
|
|
27554
28307
|
const importPath = match[1];
|
|
27555
28308
|
if (importPath.startsWith(".")) {
|
|
27556
|
-
let resolvedImport =
|
|
27557
|
-
const existingExt =
|
|
28309
|
+
let resolvedImport = path56.resolve(testDir, importPath);
|
|
28310
|
+
const existingExt = path56.extname(resolvedImport);
|
|
27558
28311
|
if (!existingExt) {
|
|
27559
28312
|
for (const extToTry of [
|
|
27560
28313
|
".ts",
|
|
@@ -27571,12 +28324,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27571
28324
|
}
|
|
27572
28325
|
}
|
|
27573
28326
|
}
|
|
27574
|
-
const importDir =
|
|
27575
|
-
const importBasename =
|
|
28327
|
+
const importDir = path56.dirname(resolvedImport);
|
|
28328
|
+
const importBasename = path56.basename(resolvedImport, path56.extname(resolvedImport));
|
|
27576
28329
|
for (const sourceFile of absoluteSourceFiles) {
|
|
27577
|
-
const sourceDir =
|
|
27578
|
-
const sourceBasename =
|
|
27579
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
28330
|
+
const sourceDir = path56.dirname(sourceFile);
|
|
28331
|
+
const sourceBasename = path56.basename(sourceFile, path56.extname(sourceFile));
|
|
28332
|
+
const isRelatedDir = importDir === sourceDir || importDir === path56.join(sourceDir, "__tests__") || importDir === path56.join(sourceDir, "tests") || importDir === path56.join(sourceDir, "test") || importDir === path56.join(sourceDir, "spec");
|
|
27580
28333
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
27581
28334
|
dedupePush(testFiles, testFile);
|
|
27582
28335
|
break;
|
|
@@ -27696,8 +28449,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
27696
28449
|
return ["mvn", "test"];
|
|
27697
28450
|
case "gradle": {
|
|
27698
28451
|
const isWindows = process.platform === "win32";
|
|
27699
|
-
const hasGradlewBat = fs25.existsSync(
|
|
27700
|
-
const hasGradlew = fs25.existsSync(
|
|
28452
|
+
const hasGradlewBat = fs25.existsSync(path56.join(baseDir, "gradlew.bat"));
|
|
28453
|
+
const hasGradlew = fs25.existsSync(path56.join(baseDir, "gradlew"));
|
|
27701
28454
|
if (hasGradlewBat && isWindows)
|
|
27702
28455
|
return ["gradlew.bat", "test"];
|
|
27703
28456
|
if (hasGradlew)
|
|
@@ -27714,7 +28467,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
27714
28467
|
"cmake-build-release",
|
|
27715
28468
|
"out"
|
|
27716
28469
|
];
|
|
27717
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs25.existsSync(
|
|
28470
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs25.existsSync(path56.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
27718
28471
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
27719
28472
|
}
|
|
27720
28473
|
case "swift-test":
|
|
@@ -28148,11 +28901,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
28148
28901
|
};
|
|
28149
28902
|
}
|
|
28150
28903
|
const startTime = Date.now();
|
|
28151
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
28904
|
+
const vitestJsonOutputPath = framework === "vitest" ? path56.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
28152
28905
|
try {
|
|
28153
28906
|
if (vitestJsonOutputPath) {
|
|
28154
28907
|
try {
|
|
28155
|
-
fs25.mkdirSync(
|
|
28908
|
+
fs25.mkdirSync(path56.dirname(vitestJsonOutputPath), { recursive: true });
|
|
28156
28909
|
if (fs25.existsSync(vitestJsonOutputPath)) {
|
|
28157
28910
|
fs25.unlinkSync(vitestJsonOutputPath);
|
|
28158
28911
|
}
|
|
@@ -28320,10 +29073,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
28320
29073
|
]);
|
|
28321
29074
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
28322
29075
|
const normalized = testFile.replace(/\\/g, "/");
|
|
28323
|
-
if (!
|
|
29076
|
+
if (!path56.isAbsolute(testFile))
|
|
28324
29077
|
return normalized;
|
|
28325
|
-
const relative8 =
|
|
28326
|
-
if (relative8.startsWith("..") ||
|
|
29078
|
+
const relative8 = path56.relative(workingDir, testFile);
|
|
29079
|
+
if (relative8.startsWith("..") || path56.isAbsolute(relative8)) {
|
|
28327
29080
|
return normalized;
|
|
28328
29081
|
}
|
|
28329
29082
|
return relative8.replace(/\\/g, "/");
|
|
@@ -28562,7 +29315,7 @@ var test_runner = createSwarmTool({
|
|
|
28562
29315
|
const sourceFiles = args.files.filter((file) => {
|
|
28563
29316
|
if (directTestFiles.includes(file))
|
|
28564
29317
|
return false;
|
|
28565
|
-
const ext =
|
|
29318
|
+
const ext = path56.extname(file).toLowerCase();
|
|
28566
29319
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28567
29320
|
});
|
|
28568
29321
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -28608,7 +29361,7 @@ var test_runner = createSwarmTool({
|
|
|
28608
29361
|
if (isConventionTestFilePath(f)) {
|
|
28609
29362
|
return false;
|
|
28610
29363
|
}
|
|
28611
|
-
const ext =
|
|
29364
|
+
const ext = path56.extname(f).toLowerCase();
|
|
28612
29365
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28613
29366
|
});
|
|
28614
29367
|
if (sourceFiles.length === 0) {
|
|
@@ -28658,7 +29411,7 @@ var test_runner = createSwarmTool({
|
|
|
28658
29411
|
if (isConventionTestFilePath(f)) {
|
|
28659
29412
|
return false;
|
|
28660
29413
|
}
|
|
28661
|
-
const ext =
|
|
29414
|
+
const ext = path56.extname(f).toLowerCase();
|
|
28662
29415
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28663
29416
|
});
|
|
28664
29417
|
if (sourceFiles.length === 0) {
|
|
@@ -28710,8 +29463,8 @@ var test_runner = createSwarmTool({
|
|
|
28710
29463
|
}
|
|
28711
29464
|
if (impactResult.impactedTests.length > 0) {
|
|
28712
29465
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
28713
|
-
const relativePath =
|
|
28714
|
-
return
|
|
29466
|
+
const relativePath = path56.relative(workingDir, absPath);
|
|
29467
|
+
return path56.isAbsolute(relativePath) ? absPath : relativePath;
|
|
28715
29468
|
});
|
|
28716
29469
|
} else {
|
|
28717
29470
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -28806,8 +29559,8 @@ function validateDirectoryPath(dir) {
|
|
|
28806
29559
|
if (dir.includes("..")) {
|
|
28807
29560
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
28808
29561
|
}
|
|
28809
|
-
const normalized =
|
|
28810
|
-
const absolutePath =
|
|
29562
|
+
const normalized = path57.normalize(dir);
|
|
29563
|
+
const absolutePath = path57.isAbsolute(normalized) ? normalized : path57.resolve(normalized);
|
|
28811
29564
|
return absolutePath;
|
|
28812
29565
|
}
|
|
28813
29566
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -28830,7 +29583,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
28830
29583
|
}
|
|
28831
29584
|
function getPackageVersion(dir) {
|
|
28832
29585
|
try {
|
|
28833
|
-
const packagePath =
|
|
29586
|
+
const packagePath = path57.join(dir, "package.json");
|
|
28834
29587
|
if (fs26.existsSync(packagePath)) {
|
|
28835
29588
|
const content = fs26.readFileSync(packagePath, "utf-8");
|
|
28836
29589
|
const pkg = JSON.parse(content);
|
|
@@ -28841,7 +29594,7 @@ function getPackageVersion(dir) {
|
|
|
28841
29594
|
}
|
|
28842
29595
|
function getChangelogVersion(dir) {
|
|
28843
29596
|
try {
|
|
28844
|
-
const changelogPath =
|
|
29597
|
+
const changelogPath = path57.join(dir, "CHANGELOG.md");
|
|
28845
29598
|
if (fs26.existsSync(changelogPath)) {
|
|
28846
29599
|
const content = fs26.readFileSync(changelogPath, "utf-8");
|
|
28847
29600
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -28855,7 +29608,7 @@ function getChangelogVersion(dir) {
|
|
|
28855
29608
|
function getVersionFileVersion(dir) {
|
|
28856
29609
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
28857
29610
|
for (const file of possibleFiles) {
|
|
28858
|
-
const filePath =
|
|
29611
|
+
const filePath = path57.join(dir, file);
|
|
28859
29612
|
if (fs26.existsSync(filePath)) {
|
|
28860
29613
|
try {
|
|
28861
29614
|
const content = fs26.readFileSync(filePath, "utf-8").trim();
|
|
@@ -28871,9 +29624,9 @@ function getVersionFileVersion(dir) {
|
|
|
28871
29624
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
28872
29625
|
const startTime = Date.now();
|
|
28873
29626
|
try {
|
|
28874
|
-
const packageVersion =
|
|
28875
|
-
const changelogVersion =
|
|
28876
|
-
const versionFileVersion =
|
|
29627
|
+
const packageVersion = _internals43.getPackageVersion(dir);
|
|
29628
|
+
const changelogVersion = _internals43.getChangelogVersion(dir);
|
|
29629
|
+
const versionFileVersion = _internals43.getVersionFileVersion(dir);
|
|
28877
29630
|
const versions = [];
|
|
28878
29631
|
if (packageVersion)
|
|
28879
29632
|
versions.push(`package.json: ${packageVersion}`);
|
|
@@ -29237,7 +29990,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
29237
29990
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
29238
29991
|
let validatedDir;
|
|
29239
29992
|
try {
|
|
29240
|
-
validatedDir =
|
|
29993
|
+
validatedDir = _internals43.validateDirectoryPath(dir);
|
|
29241
29994
|
} catch (error2) {
|
|
29242
29995
|
return {
|
|
29243
29996
|
id: reportId,
|
|
@@ -29257,7 +30010,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
29257
30010
|
}
|
|
29258
30011
|
let validatedTimeout;
|
|
29259
30012
|
try {
|
|
29260
|
-
validatedTimeout =
|
|
30013
|
+
validatedTimeout = _internals43.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
29261
30014
|
} catch (error2) {
|
|
29262
30015
|
return {
|
|
29263
30016
|
id: reportId,
|
|
@@ -29298,12 +30051,12 @@ async function runPreflight(dir, phase, config) {
|
|
|
29298
30051
|
});
|
|
29299
30052
|
const checks = [];
|
|
29300
30053
|
log("[Preflight] Running lint check...");
|
|
29301
|
-
const lintResult = await
|
|
30054
|
+
const lintResult = await _internals43.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
29302
30055
|
checks.push(lintResult);
|
|
29303
30056
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
29304
30057
|
if (!cfg.skipTests) {
|
|
29305
30058
|
log("[Preflight] Running tests check...");
|
|
29306
|
-
const testsResult = await
|
|
30059
|
+
const testsResult = await _internals43.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
29307
30060
|
checks.push(testsResult);
|
|
29308
30061
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
29309
30062
|
} else {
|
|
@@ -29315,7 +30068,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
29315
30068
|
}
|
|
29316
30069
|
if (!cfg.skipSecrets) {
|
|
29317
30070
|
log("[Preflight] Running secrets check...");
|
|
29318
|
-
const secretsResult = await
|
|
30071
|
+
const secretsResult = await _internals43.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
29319
30072
|
checks.push(secretsResult);
|
|
29320
30073
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
29321
30074
|
} else {
|
|
@@ -29327,7 +30080,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
29327
30080
|
}
|
|
29328
30081
|
if (!cfg.skipEvidence) {
|
|
29329
30082
|
log("[Preflight] Running evidence check...");
|
|
29330
|
-
const evidenceResult = await
|
|
30083
|
+
const evidenceResult = await _internals43.runEvidenceCheck(validatedDir);
|
|
29331
30084
|
checks.push(evidenceResult);
|
|
29332
30085
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
29333
30086
|
} else {
|
|
@@ -29338,12 +30091,12 @@ async function runPreflight(dir, phase, config) {
|
|
|
29338
30091
|
});
|
|
29339
30092
|
}
|
|
29340
30093
|
log("[Preflight] Running requirement coverage check...");
|
|
29341
|
-
const reqCoverageResult = await
|
|
30094
|
+
const reqCoverageResult = await _internals43.runRequirementCoverageCheck(validatedDir, phase);
|
|
29342
30095
|
checks.push(reqCoverageResult);
|
|
29343
30096
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
29344
30097
|
if (!cfg.skipVersion) {
|
|
29345
30098
|
log("[Preflight] Running version check...");
|
|
29346
|
-
const versionResult = await
|
|
30099
|
+
const versionResult = await _internals43.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
29347
30100
|
checks.push(versionResult);
|
|
29348
30101
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
29349
30102
|
} else {
|
|
@@ -29406,10 +30159,10 @@ function formatPreflightMarkdown(report) {
|
|
|
29406
30159
|
async function handlePreflightCommand(directory, _args) {
|
|
29407
30160
|
const plan = await loadPlan(directory);
|
|
29408
30161
|
const phase = plan?.current_phase ?? 1;
|
|
29409
|
-
const report = await
|
|
29410
|
-
return
|
|
30162
|
+
const report = await _internals43.runPreflight(directory, phase);
|
|
30163
|
+
return _internals43.formatPreflightMarkdown(report);
|
|
29411
30164
|
}
|
|
29412
|
-
var
|
|
30165
|
+
var _internals43 = {
|
|
29413
30166
|
runPreflight,
|
|
29414
30167
|
formatPreflightMarkdown,
|
|
29415
30168
|
handlePreflightCommand,
|
|
@@ -29593,7 +30346,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
29593
30346
|
|
|
29594
30347
|
// src/commands/reset.ts
|
|
29595
30348
|
import * as fs27 from "fs";
|
|
29596
|
-
import * as
|
|
30349
|
+
import * as path58 from "path";
|
|
29597
30350
|
|
|
29598
30351
|
// src/background/circuit-breaker.ts
|
|
29599
30352
|
class CircuitBreaker {
|
|
@@ -30312,7 +31065,7 @@ async function handleResetCommand(directory, args) {
|
|
|
30312
31065
|
}
|
|
30313
31066
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
30314
31067
|
try {
|
|
30315
|
-
const rootPath =
|
|
31068
|
+
const rootPath = path58.join(directory, filename);
|
|
30316
31069
|
if (fs27.existsSync(rootPath)) {
|
|
30317
31070
|
fs27.unlinkSync(rootPath);
|
|
30318
31071
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -30350,7 +31103,7 @@ async function handleResetCommand(directory, args) {
|
|
|
30350
31103
|
|
|
30351
31104
|
// src/commands/reset-session.ts
|
|
30352
31105
|
import * as fs29 from "fs";
|
|
30353
|
-
import * as
|
|
31106
|
+
import * as path60 from "path";
|
|
30354
31107
|
|
|
30355
31108
|
// src/hooks/trajectory-logger.ts
|
|
30356
31109
|
var callStartTimes = new Map;
|
|
@@ -30757,16 +31510,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
30757
31510
|
}
|
|
30758
31511
|
// src/prm/replay.ts
|
|
30759
31512
|
import { promises as fs28 } from "fs";
|
|
30760
|
-
import
|
|
31513
|
+
import path59 from "path";
|
|
30761
31514
|
function isPathSafe(targetPath, basePath) {
|
|
30762
|
-
const resolvedTarget =
|
|
30763
|
-
const resolvedBase =
|
|
30764
|
-
const rel =
|
|
30765
|
-
return !rel.startsWith("..") && !
|
|
31515
|
+
const resolvedTarget = path59.resolve(targetPath);
|
|
31516
|
+
const resolvedBase = path59.resolve(basePath);
|
|
31517
|
+
const rel = path59.relative(resolvedBase, resolvedTarget);
|
|
31518
|
+
return !rel.startsWith("..") && !path59.isAbsolute(rel);
|
|
30766
31519
|
}
|
|
30767
31520
|
function isWithinReplaysDir(targetPath) {
|
|
30768
|
-
const resolved =
|
|
30769
|
-
const parts = resolved.split(
|
|
31521
|
+
const resolved = path59.resolve(targetPath);
|
|
31522
|
+
const parts = resolved.split(path59.sep);
|
|
30770
31523
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
30771
31524
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
30772
31525
|
return true;
|
|
@@ -30779,10 +31532,10 @@ function sanitizeFilename(input) {
|
|
|
30779
31532
|
}
|
|
30780
31533
|
async function startReplayRecording(sessionID, directory) {
|
|
30781
31534
|
try {
|
|
30782
|
-
const replayDir =
|
|
31535
|
+
const replayDir = path59.join(directory, ".swarm", "replays");
|
|
30783
31536
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
30784
31537
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
30785
|
-
const filepath =
|
|
31538
|
+
const filepath = path59.join(replayDir, filename);
|
|
30786
31539
|
if (!isPathSafe(filepath, replayDir)) {
|
|
30787
31540
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
30788
31541
|
return null;
|
|
@@ -30814,7 +31567,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
|
|
|
30814
31567
|
}
|
|
30815
31568
|
|
|
30816
31569
|
// src/prm/index.ts
|
|
30817
|
-
var
|
|
31570
|
+
var _internals44 = {
|
|
30818
31571
|
getAgentSession,
|
|
30819
31572
|
readTrajectory,
|
|
30820
31573
|
getInMemoryTrajectory,
|
|
@@ -30837,7 +31590,7 @@ function resetPrmSessionState(session, sessionId) {
|
|
|
30837
31590
|
session.prmTrajectoryStep = 0;
|
|
30838
31591
|
session.replayArtifactPath = null;
|
|
30839
31592
|
if (sessionId) {
|
|
30840
|
-
|
|
31593
|
+
_internals44.clearTrajectoryCache(sessionId);
|
|
30841
31594
|
}
|
|
30842
31595
|
}
|
|
30843
31596
|
|
|
@@ -30860,7 +31613,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30860
31613
|
} catch {
|
|
30861
31614
|
results.push("\u274C Failed to delete state.json");
|
|
30862
31615
|
}
|
|
30863
|
-
const sessionDir =
|
|
31616
|
+
const sessionDir = path60.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
30864
31617
|
let sessionFiles = [];
|
|
30865
31618
|
if (fs29.existsSync(sessionDir)) {
|
|
30866
31619
|
try {
|
|
@@ -30872,7 +31625,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30872
31625
|
for (const file of sessionFiles) {
|
|
30873
31626
|
if (file === "state.json")
|
|
30874
31627
|
continue;
|
|
30875
|
-
const filePath =
|
|
31628
|
+
const filePath = path60.join(sessionDir, file);
|
|
30876
31629
|
try {
|
|
30877
31630
|
if (!fs29.existsSync(filePath))
|
|
30878
31631
|
continue;
|
|
@@ -30907,7 +31660,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30907
31660
|
}
|
|
30908
31661
|
|
|
30909
31662
|
// src/summaries/manager.ts
|
|
30910
|
-
import * as
|
|
31663
|
+
import * as path61 from "path";
|
|
30911
31664
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
30912
31665
|
function sanitizeSummaryId(id) {
|
|
30913
31666
|
if (!id || id.length === 0) {
|
|
@@ -30931,7 +31684,7 @@ function sanitizeSummaryId(id) {
|
|
|
30931
31684
|
}
|
|
30932
31685
|
async function loadFullOutput(directory, id) {
|
|
30933
31686
|
const sanitizedId = sanitizeSummaryId(id);
|
|
30934
|
-
const relativePath =
|
|
31687
|
+
const relativePath = path61.join("summaries", `${sanitizedId}.json`);
|
|
30935
31688
|
validateSwarmPath(directory, relativePath);
|
|
30936
31689
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
30937
31690
|
if (content === null) {
|
|
@@ -30984,7 +31737,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
30984
31737
|
|
|
30985
31738
|
// src/commands/rollback.ts
|
|
30986
31739
|
import * as fs30 from "fs";
|
|
30987
|
-
import * as
|
|
31740
|
+
import * as path62 from "path";
|
|
30988
31741
|
async function handleRollbackCommand(directory, args) {
|
|
30989
31742
|
const phaseArg = args[0];
|
|
30990
31743
|
if (!phaseArg) {
|
|
@@ -31050,8 +31803,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
31050
31803
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
31051
31804
|
continue;
|
|
31052
31805
|
}
|
|
31053
|
-
const src =
|
|
31054
|
-
const dest =
|
|
31806
|
+
const src = path62.join(checkpointDir, file);
|
|
31807
|
+
const dest = path62.join(swarmDir, file);
|
|
31055
31808
|
try {
|
|
31056
31809
|
fs30.cpSync(src, dest, { recursive: true, force: true });
|
|
31057
31810
|
successes.push(file);
|
|
@@ -31070,7 +31823,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
31070
31823
|
].join(`
|
|
31071
31824
|
`);
|
|
31072
31825
|
}
|
|
31073
|
-
const existingLedgerPath =
|
|
31826
|
+
const existingLedgerPath = path62.join(swarmDir, "plan-ledger.jsonl");
|
|
31074
31827
|
let ledgerDeletionFailed = false;
|
|
31075
31828
|
if (fs30.existsSync(existingLedgerPath)) {
|
|
31076
31829
|
try {
|
|
@@ -31083,7 +31836,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
31083
31836
|
}
|
|
31084
31837
|
if (!ledgerDeletionFailed) {
|
|
31085
31838
|
try {
|
|
31086
|
-
const planJsonPath =
|
|
31839
|
+
const planJsonPath = path62.join(swarmDir, "plan.json");
|
|
31087
31840
|
if (fs30.existsSync(planJsonPath)) {
|
|
31088
31841
|
const planRaw = fs30.readFileSync(planJsonPath, "utf-8");
|
|
31089
31842
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -31344,10 +32097,10 @@ Ensure this is a git repository with commit history.`;
|
|
|
31344
32097
|
`);
|
|
31345
32098
|
try {
|
|
31346
32099
|
const fs31 = await import("fs/promises");
|
|
31347
|
-
const
|
|
31348
|
-
const reportPath =
|
|
31349
|
-
await fs31.mkdir(
|
|
31350
|
-
const reportTempPath =
|
|
32100
|
+
const path63 = await import("path");
|
|
32101
|
+
const reportPath = path63.join(directory, ".swarm", "simulate-report.md");
|
|
32102
|
+
await fs31.mkdir(path63.dirname(reportPath), { recursive: true });
|
|
32103
|
+
const reportTempPath = path63.join(path63.dirname(reportPath), `${path63.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
31351
32104
|
try {
|
|
31352
32105
|
await fs31.writeFile(reportTempPath, report, "utf-8");
|
|
31353
32106
|
renameSync11(reportTempPath, reportPath);
|
|
@@ -31376,18 +32129,18 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
31376
32129
|
// src/services/status-service.ts
|
|
31377
32130
|
import * as fsSync3 from "fs";
|
|
31378
32131
|
import { readFile as readFile16 } from "fs/promises";
|
|
31379
|
-
import * as
|
|
32132
|
+
import * as path64 from "path";
|
|
31380
32133
|
|
|
31381
32134
|
// src/turbo/lean/state.ts
|
|
31382
32135
|
init_logger();
|
|
31383
32136
|
import * as fs31 from "fs";
|
|
31384
|
-
import * as
|
|
32137
|
+
import * as path63 from "path";
|
|
31385
32138
|
var STATE_FILE3 = "turbo-state.json";
|
|
31386
32139
|
function nowISO3() {
|
|
31387
32140
|
return new Date().toISOString();
|
|
31388
32141
|
}
|
|
31389
32142
|
function ensureSwarmDir2(directory) {
|
|
31390
|
-
const swarmDir =
|
|
32143
|
+
const swarmDir = path63.resolve(directory, ".swarm");
|
|
31391
32144
|
if (!fs31.existsSync(swarmDir)) {
|
|
31392
32145
|
fs31.mkdirSync(swarmDir, { recursive: true });
|
|
31393
32146
|
}
|
|
@@ -31432,7 +32185,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
31432
32185
|
}
|
|
31433
32186
|
function readPersisted2(directory) {
|
|
31434
32187
|
try {
|
|
31435
|
-
const filePath =
|
|
32188
|
+
const filePath = path63.join(directory, ".swarm", STATE_FILE3);
|
|
31436
32189
|
if (!fs31.existsSync(filePath)) {
|
|
31437
32190
|
const seed = emptyPersisted2();
|
|
31438
32191
|
try {
|
|
@@ -31468,7 +32221,7 @@ function writePersisted2(directory, persisted) {
|
|
|
31468
32221
|
let payload;
|
|
31469
32222
|
try {
|
|
31470
32223
|
ensureSwarmDir2(directory);
|
|
31471
|
-
filePath =
|
|
32224
|
+
filePath = path63.join(directory, ".swarm", STATE_FILE3);
|
|
31472
32225
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
31473
32226
|
persisted.updatedAt = nowISO3();
|
|
31474
32227
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -31579,14 +32332,14 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
|
|
|
31579
32332
|
};
|
|
31580
32333
|
|
|
31581
32334
|
// src/services/status-service.ts
|
|
31582
|
-
var
|
|
32335
|
+
var _internals45 = {
|
|
31583
32336
|
loadLeanTurboRunState,
|
|
31584
32337
|
hasActiveLeanTurbo,
|
|
31585
32338
|
hasActiveFullAuto
|
|
31586
32339
|
};
|
|
31587
32340
|
function readSpecStalenessSnapshot(directory) {
|
|
31588
32341
|
try {
|
|
31589
|
-
const p =
|
|
32342
|
+
const p = path64.join(directory, ".swarm", "spec-staleness.json");
|
|
31590
32343
|
if (!fsSync3.existsSync(p))
|
|
31591
32344
|
return { stale: false };
|
|
31592
32345
|
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
@@ -31684,7 +32437,7 @@ async function getStatusData(directory, agents) {
|
|
|
31684
32437
|
}
|
|
31685
32438
|
function enrichWithLeanTurbo(status, directory) {
|
|
31686
32439
|
const turboMode = hasActiveTurboMode();
|
|
31687
|
-
const leanActive =
|
|
32440
|
+
const leanActive = _internals45.hasActiveLeanTurbo();
|
|
31688
32441
|
let turboStrategy = "off";
|
|
31689
32442
|
if (leanActive) {
|
|
31690
32443
|
turboStrategy = "lean";
|
|
@@ -31703,7 +32456,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
31703
32456
|
}
|
|
31704
32457
|
}
|
|
31705
32458
|
if (leanSessionID) {
|
|
31706
|
-
const runState =
|
|
32459
|
+
const runState = _internals45.loadLeanTurboRunState(directory, leanSessionID);
|
|
31707
32460
|
if (runState) {
|
|
31708
32461
|
status.leanTurboPhase = runState.phase;
|
|
31709
32462
|
status.leanMaxParallelCoders = runState.maxParallelCoders;
|
|
@@ -31735,7 +32488,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
31735
32488
|
}
|
|
31736
32489
|
}
|
|
31737
32490
|
}
|
|
31738
|
-
status.fullAutoActive =
|
|
32491
|
+
status.fullAutoActive = _internals45.hasActiveFullAuto();
|
|
31739
32492
|
return status;
|
|
31740
32493
|
}
|
|
31741
32494
|
function formatStatusMarkdown(status) {
|
|
@@ -31889,7 +32642,7 @@ No active swarm plan found. Nothing to sync.`;
|
|
|
31889
32642
|
|
|
31890
32643
|
// src/commands/turbo.ts
|
|
31891
32644
|
init_logger();
|
|
31892
|
-
var
|
|
32645
|
+
var _internals46 = {
|
|
31893
32646
|
loadPluginConfigWithMeta
|
|
31894
32647
|
};
|
|
31895
32648
|
async function handleTurboCommand(directory, args, sessionID) {
|
|
@@ -31949,7 +32702,7 @@ async function handleTurboCommand(directory, args, sessionID) {
|
|
|
31949
32702
|
if (arg0 === "on") {
|
|
31950
32703
|
let strategy = "standard";
|
|
31951
32704
|
try {
|
|
31952
|
-
const { config } =
|
|
32705
|
+
const { config } = _internals46.loadPluginConfigWithMeta(directory);
|
|
31953
32706
|
if (config.turbo?.strategy === "lean") {
|
|
31954
32707
|
strategy = "lean";
|
|
31955
32708
|
}
|
|
@@ -32046,7 +32799,7 @@ function enableLeanTurbo(session, directory, sessionID) {
|
|
|
32046
32799
|
let maxParallelCoders = 4;
|
|
32047
32800
|
let conflictPolicy = "serialize";
|
|
32048
32801
|
try {
|
|
32049
|
-
const { config } =
|
|
32802
|
+
const { config } = _internals46.loadPluginConfigWithMeta(directory);
|
|
32050
32803
|
const leanConfig = config.turbo?.lean;
|
|
32051
32804
|
if (leanConfig) {
|
|
32052
32805
|
maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
|
|
@@ -32119,11 +32872,11 @@ function buildStatusMessage2(session, directory, sessionID) {
|
|
|
32119
32872
|
|
|
32120
32873
|
// src/commands/unlink.ts
|
|
32121
32874
|
import { existsSync as existsSync37 } from "fs";
|
|
32122
|
-
import * as
|
|
32875
|
+
import * as path65 from "path";
|
|
32123
32876
|
var DEDUP_THRESHOLD2 = 0.6;
|
|
32124
32877
|
async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
|
|
32125
|
-
const sharedPath =
|
|
32126
|
-
const localPath =
|
|
32878
|
+
const sharedPath = path65.join(linkDir, "knowledge.jsonl");
|
|
32879
|
+
const localPath = path65.join(localSwarmDir, "knowledge.jsonl");
|
|
32127
32880
|
if (!existsSync37(sharedPath))
|
|
32128
32881
|
return 0;
|
|
32129
32882
|
const sharedEntries = await readKnowledge(sharedPath);
|
|
@@ -32158,7 +32911,7 @@ async function handleUnlinkCommand(directory, args) {
|
|
|
32158
32911
|
let copied = 0;
|
|
32159
32912
|
if (copyBack) {
|
|
32160
32913
|
try {
|
|
32161
|
-
copied = await copySharedKnowledgeToLocal(linkDir,
|
|
32914
|
+
copied = await copySharedKnowledgeToLocal(linkDir, path65.join(directory, ".swarm"));
|
|
32162
32915
|
} catch (error2) {
|
|
32163
32916
|
return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
32164
32917
|
}
|
|
@@ -32262,7 +33015,7 @@ function findSimilarCommands(query) {
|
|
|
32262
33015
|
}
|
|
32263
33016
|
const scored = VALID_COMMANDS.map((cmd) => {
|
|
32264
33017
|
const cmdLower = cmd.toLowerCase();
|
|
32265
|
-
const fullScore =
|
|
33018
|
+
const fullScore = _internals47.levenshteinDistance(q, cmdLower);
|
|
32266
33019
|
let tokenScore = Infinity;
|
|
32267
33020
|
if (cmd.includes(" ") || cmd.includes("-")) {
|
|
32268
33021
|
const qTokens = q.split(/[\s-]+/);
|
|
@@ -32275,7 +33028,7 @@ function findSimilarCommands(query) {
|
|
|
32275
33028
|
for (const ct of cmdTokens) {
|
|
32276
33029
|
if (ct.length === 0)
|
|
32277
33030
|
continue;
|
|
32278
|
-
const dist =
|
|
33031
|
+
const dist = _internals47.levenshteinDistance(qt, ct);
|
|
32279
33032
|
if (dist < minDist)
|
|
32280
33033
|
minDist = dist;
|
|
32281
33034
|
}
|
|
@@ -32285,7 +33038,7 @@ function findSimilarCommands(query) {
|
|
|
32285
33038
|
}
|
|
32286
33039
|
const dashStrippedQ = q.replace(/-/g, "");
|
|
32287
33040
|
const dashStrippedCmd = cmdLower.replace(/-/g, "");
|
|
32288
|
-
const dashScore =
|
|
33041
|
+
const dashScore = _internals47.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
|
|
32289
33042
|
const score = Math.min(fullScore, tokenScore, dashScore);
|
|
32290
33043
|
return { cmd, score };
|
|
32291
33044
|
});
|
|
@@ -32320,16 +33073,16 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
32320
33073
|
async function handleHelpCommand(ctx) {
|
|
32321
33074
|
const targetCommand = ctx.args.join(" ");
|
|
32322
33075
|
if (!targetCommand) {
|
|
32323
|
-
const { buildHelpText } = await import("./index-
|
|
33076
|
+
const { buildHelpText } = await import("./index-bcr2a549.js");
|
|
32324
33077
|
return buildHelpText();
|
|
32325
33078
|
}
|
|
32326
33079
|
const tokens = targetCommand.split(/\s+/);
|
|
32327
|
-
const resolved =
|
|
33080
|
+
const resolved = _internals47.resolveCommand(tokens);
|
|
32328
33081
|
if (resolved) {
|
|
32329
|
-
return
|
|
33082
|
+
return _internals47.buildDetailedHelp(resolved.key, resolved.entry);
|
|
32330
33083
|
}
|
|
32331
|
-
const similar =
|
|
32332
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
33084
|
+
const similar = _internals47.findSimilarCommands(targetCommand);
|
|
33085
|
+
const { buildHelpText: fullHelp } = await import("./index-bcr2a549.js");
|
|
32333
33086
|
if (similar.length > 0) {
|
|
32334
33087
|
return `Command '/swarm ${targetCommand}' not found.
|
|
32335
33088
|
|
|
@@ -32393,7 +33146,7 @@ var COMMAND_REGISTRY = {
|
|
|
32393
33146
|
toolNoArgs: true
|
|
32394
33147
|
},
|
|
32395
33148
|
help: {
|
|
32396
|
-
handler: (ctx) =>
|
|
33149
|
+
handler: (ctx) => _internals47.handleHelpCommand(ctx),
|
|
32397
33150
|
description: "Show help for swarm commands",
|
|
32398
33151
|
category: "core",
|
|
32399
33152
|
args: "[command]",
|
|
@@ -32462,7 +33215,7 @@ var COMMAND_REGISTRY = {
|
|
|
32462
33215
|
},
|
|
32463
33216
|
"guardrail explain": {
|
|
32464
33217
|
handler: async (ctx) => {
|
|
32465
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
33218
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-z37rtfz4.js");
|
|
32466
33219
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32467
33220
|
},
|
|
32468
33221
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -32472,7 +33225,7 @@ var COMMAND_REGISTRY = {
|
|
|
32472
33225
|
},
|
|
32473
33226
|
"guardrail-log": {
|
|
32474
33227
|
handler: async (ctx) => {
|
|
32475
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
33228
|
+
const { handleGuardrailLog } = await import("./guardrail-log-ywajkn46.js");
|
|
32476
33229
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
32477
33230
|
},
|
|
32478
33231
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -33235,24 +33988,24 @@ function validateAliases() {
|
|
|
33235
33988
|
continue;
|
|
33236
33989
|
}
|
|
33237
33990
|
const visited = new Set;
|
|
33238
|
-
const
|
|
33991
|
+
const path66 = [];
|
|
33239
33992
|
let current = target;
|
|
33240
33993
|
while (current) {
|
|
33241
33994
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
33242
33995
|
if (!currentEntry)
|
|
33243
33996
|
break;
|
|
33244
33997
|
if (visited.has(current)) {
|
|
33245
|
-
const cycleStart =
|
|
33998
|
+
const cycleStart = path66.indexOf(current);
|
|
33246
33999
|
const fullChain = [
|
|
33247
34000
|
name,
|
|
33248
|
-
...
|
|
34001
|
+
...path66.slice(0, cycleStart > 0 ? cycleStart : path66.length),
|
|
33249
34002
|
current
|
|
33250
34003
|
].join(" \u2192 ");
|
|
33251
34004
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
33252
34005
|
break;
|
|
33253
34006
|
}
|
|
33254
34007
|
visited.add(current);
|
|
33255
|
-
|
|
34008
|
+
path66.push(current);
|
|
33256
34009
|
current = currentEntry.aliasOf || "";
|
|
33257
34010
|
}
|
|
33258
34011
|
}
|
|
@@ -33271,7 +34024,7 @@ function validateToolPolicy() {
|
|
|
33271
34024
|
}
|
|
33272
34025
|
return { valid: warnings.length === 0, warnings };
|
|
33273
34026
|
}
|
|
33274
|
-
var
|
|
34027
|
+
var _internals47 = {
|
|
33275
34028
|
handleHelpCommand,
|
|
33276
34029
|
validateAliases,
|
|
33277
34030
|
validateToolPolicy,
|
|
@@ -33281,16 +34034,16 @@ var _internals46 = {
|
|
|
33281
34034
|
findSimilarCommands,
|
|
33282
34035
|
buildDetailedHelp
|
|
33283
34036
|
};
|
|
33284
|
-
var validation =
|
|
34037
|
+
var validation = _internals47.validateAliases();
|
|
33285
34038
|
if (!validation.valid) {
|
|
33286
34039
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
33287
34040
|
${validation.errors.join(`
|
|
33288
34041
|
`)}`);
|
|
33289
34042
|
}
|
|
33290
|
-
|
|
34043
|
+
_internals47.emitValidationWarnings("COMMAND_REGISTRY alias warnings", validation.warnings);
|
|
33291
34044
|
try {
|
|
33292
|
-
const toolPolicyValidation =
|
|
33293
|
-
|
|
34045
|
+
const toolPolicyValidation = _internals47.validateToolPolicy();
|
|
34046
|
+
_internals47.emitValidationWarnings("COMMAND_REGISTRY toolPolicy warnings", toolPolicyValidation.warnings);
|
|
33294
34047
|
} catch (e) {
|
|
33295
34048
|
warn(`COMMAND_REGISTRY toolPolicy validation failed (non-fatal): ${e.message}`);
|
|
33296
34049
|
}
|
|
@@ -33349,7 +34102,7 @@ function formatCommandNotFound(tokens) {
|
|
|
33349
34102
|
const attemptedCommand = tokens[0] || "";
|
|
33350
34103
|
const MAX_DISPLAY = 100;
|
|
33351
34104
|
const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
|
|
33352
|
-
const similar =
|
|
34105
|
+
const similar = _internals47.findSimilarCommands(attemptedCommand);
|
|
33353
34106
|
const header = `Command \`/swarm ${displayCommand}\` not found.`;
|
|
33354
34107
|
const suggestions = similar.length > 0 ? `Did you mean:
|
|
33355
34108
|
${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
@@ -33406,4 +34159,4 @@ ${text}`;
|
|
|
33406
34159
|
};
|
|
33407
34160
|
}
|
|
33408
34161
|
|
|
33409
|
-
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS,
|
|
34162
|
+
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals47 as _internals, resolveCommand };
|