opencode-swarm 7.88.0 → 7.88.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/.opencode/skills/brainstorm/SKILL.md +2 -1
- package/.opencode/skills/clarify/SKILL.md +7 -1
- package/.opencode/skills/clarify-spec/SKILL.md +1 -1
- package/.opencode/skills/issue-ingest/SKILL.md +3 -2
- package/.opencode/skills/plan/SKILL.md +7 -1
- package/.opencode/skills/specify/SKILL.md +3 -2
- package/dist/cli/{guardrail-explain-sw5bjxtk.js → guardrail-explain-995zavv8.js} +2 -2
- package/dist/cli/{index-jch711dq.js → index-4td9ef53.js} +518 -224
- package/dist/cli/{index-dkytd370.js → index-sr7g2msm.js} +2 -2
- package/dist/cli/{index-fwb5f2gr.js → index-tt5aehrb.js} +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/index.js +1346 -994
- package/dist/memory/config.d.ts +1 -0
- package/dist/memory/gateway.d.ts +1 -0
- package/dist/memory/provider-pool.d.ts +50 -0
- package/dist/memory/sqlite-provider.d.ts +3 -0
- package/package.json +1 -1
|
@@ -899,7 +899,7 @@ var init_executor = __esm(() => {
|
|
|
899
899
|
// package.json
|
|
900
900
|
var package_default = {
|
|
901
901
|
name: "opencode-swarm",
|
|
902
|
-
version: "7.88.
|
|
902
|
+
version: "7.88.1",
|
|
903
903
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
904
904
|
main: "dist/index.js",
|
|
905
905
|
types: "dist/index.d.ts",
|
|
@@ -18335,7 +18335,7 @@ ${USAGE7}`;
|
|
|
18335
18335
|
|
|
18336
18336
|
// src/commands/memory.ts
|
|
18337
18337
|
import { existsSync as existsSync25 } from "fs";
|
|
18338
|
-
import * as
|
|
18338
|
+
import * as path43 from "path";
|
|
18339
18339
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
18340
18340
|
|
|
18341
18341
|
// src/memory/config.ts
|
|
@@ -18367,7 +18367,8 @@ var DEFAULT_MEMORY_CONFIG = {
|
|
|
18367
18367
|
},
|
|
18368
18368
|
maintenance: {
|
|
18369
18369
|
lowUtilityMaxConfidence: 0.45,
|
|
18370
|
-
lowUtilityMinAgeDays: 30
|
|
18370
|
+
lowUtilityMinAgeDays: 30,
|
|
18371
|
+
autoCompactEveryNRecalls: 50
|
|
18371
18372
|
},
|
|
18372
18373
|
hardDelete: false
|
|
18373
18374
|
};
|
|
@@ -18428,7 +18429,7 @@ class MemoryValidationError extends Error {
|
|
|
18428
18429
|
// src/memory/evaluation.ts
|
|
18429
18430
|
import * as fs17 from "fs/promises";
|
|
18430
18431
|
import * as os9 from "os";
|
|
18431
|
-
import * as
|
|
18432
|
+
import * as path42 from "path";
|
|
18432
18433
|
|
|
18433
18434
|
// src/memory/local-jsonl-provider.ts
|
|
18434
18435
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -19669,6 +19670,10 @@ async function writeJsonlAtomic(filePath, values) {
|
|
|
19669
19670
|
await rename5(tmp, filePath);
|
|
19670
19671
|
}
|
|
19671
19672
|
|
|
19673
|
+
// src/memory/provider-pool.ts
|
|
19674
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
19675
|
+
import * as path41 from "path";
|
|
19676
|
+
|
|
19672
19677
|
// src/memory/sqlite-provider.ts
|
|
19673
19678
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
19674
19679
|
import { mkdirSync as mkdirSync15 } from "fs";
|
|
@@ -19907,6 +19912,7 @@ function loadDatabaseCtor2() {
|
|
|
19907
19912
|
_DatabaseCtor2 = req("bun:sqlite").Database;
|
|
19908
19913
|
return _DatabaseCtor2;
|
|
19909
19914
|
}
|
|
19915
|
+
var RECALL_CANDIDATE_LIMIT = 1000;
|
|
19910
19916
|
var FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index";
|
|
19911
19917
|
var FTS_TABLE_NAME = "memory_items_fts";
|
|
19912
19918
|
var FTS_INDEX_COLUMNS = [
|
|
@@ -20004,6 +20010,24 @@ var MIGRATIONS2 = [
|
|
|
20004
20010
|
${ftsCreateColumnsSql()}
|
|
20005
20011
|
);
|
|
20006
20012
|
`
|
|
20013
|
+
},
|
|
20014
|
+
{
|
|
20015
|
+
version: 4,
|
|
20016
|
+
name: "create_meta_table",
|
|
20017
|
+
sql: `
|
|
20018
|
+
CREATE TABLE IF NOT EXISTS _meta (
|
|
20019
|
+
key TEXT PRIMARY KEY,
|
|
20020
|
+
value TEXT NOT NULL
|
|
20021
|
+
);
|
|
20022
|
+
`
|
|
20023
|
+
},
|
|
20024
|
+
{
|
|
20025
|
+
version: 5,
|
|
20026
|
+
name: "create_recall_usage_timestamp_index",
|
|
20027
|
+
sql: `
|
|
20028
|
+
CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_timestamp
|
|
20029
|
+
ON memory_recall_usage(timestamp DESC);
|
|
20030
|
+
`
|
|
20007
20031
|
}
|
|
20008
20032
|
];
|
|
20009
20033
|
|
|
@@ -20018,6 +20042,8 @@ class SQLiteMemoryProvider {
|
|
|
20018
20042
|
memories = new Map;
|
|
20019
20043
|
proposals = new Map;
|
|
20020
20044
|
lastAutomaticJsonlMigration = null;
|
|
20045
|
+
recallCountSinceLastCompaction = 0;
|
|
20046
|
+
isCompacting = false;
|
|
20021
20047
|
constructor(rootDirectory, config = {}) {
|
|
20022
20048
|
this.rootDirectory = rootDirectory;
|
|
20023
20049
|
this.config = {
|
|
@@ -20075,6 +20101,7 @@ class SQLiteMemoryProvider {
|
|
|
20075
20101
|
this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
|
|
20076
20102
|
this.db.run("PRAGMA foreign_keys = ON;");
|
|
20077
20103
|
this.runMigrations();
|
|
20104
|
+
this.backfillScopeKeys();
|
|
20078
20105
|
this.ftsAvailable = this.initializeFtsIndex();
|
|
20079
20106
|
this.lastAutomaticJsonlMigration = null;
|
|
20080
20107
|
await this.migrateLegacyJsonlIfNeeded();
|
|
@@ -20137,7 +20164,8 @@ class SQLiteMemoryProvider {
|
|
|
20137
20164
|
const scopedRecords = await this.list({
|
|
20138
20165
|
scopes: request.scopes,
|
|
20139
20166
|
kinds: request.kinds,
|
|
20140
|
-
includeExpired: request.includeExpired
|
|
20167
|
+
includeExpired: request.includeExpired,
|
|
20168
|
+
limit: RECALL_CANDIDATE_LIMIT
|
|
20141
20169
|
});
|
|
20142
20170
|
const candidates = this.selectRecallCandidates(request, scopedRecords);
|
|
20143
20171
|
const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
|
|
@@ -20158,7 +20186,29 @@ class SQLiteMemoryProvider {
|
|
|
20158
20186
|
timestamp,
|
|
20159
20187
|
usage_json
|
|
20160
20188
|
) VALUES (?, ?, ?, ?)`, [randomUUID6(), event.bundleId, event.timestamp, JSON.stringify(event)]);
|
|
20161
|
-
|
|
20189
|
+
this.recallCountSinceLastCompaction++;
|
|
20190
|
+
const threshold = this.config.maintenance?.autoCompactEveryNRecalls ?? 50;
|
|
20191
|
+
if (threshold > 0 && this.recallCountSinceLastCompaction >= threshold && !this.isCompacting) {
|
|
20192
|
+
this.recallCountSinceLastCompaction = 0;
|
|
20193
|
+
this.isCompacting = true;
|
|
20194
|
+
this.compactMaintenance({ dryRun: false }).then((result) => {
|
|
20195
|
+
const rowsInspected = result.remaining + result.removedDeleted + result.removedSuperseded + result.removedExpiredScratch;
|
|
20196
|
+
const rowsPurged = result.removedDeleted + result.removedSuperseded + result.removedExpiredScratch;
|
|
20197
|
+
return this.insertEvent("compact_triggered", "memory_items", "auto compaction triggered", JSON.stringify({
|
|
20198
|
+
trigger: "auto",
|
|
20199
|
+
threshold,
|
|
20200
|
+
rowsInspected,
|
|
20201
|
+
rowsPurged,
|
|
20202
|
+
timestamp: new Date().toISOString()
|
|
20203
|
+
}));
|
|
20204
|
+
}).catch((err) => {
|
|
20205
|
+
if (process.env.OPENCODE_SWARM_DEBUG === "1") {
|
|
20206
|
+
console.debug(`[memory] auto-compaction failed: ${err}`);
|
|
20207
|
+
}
|
|
20208
|
+
}).finally(() => {
|
|
20209
|
+
this.isCompacting = false;
|
|
20210
|
+
});
|
|
20211
|
+
}
|
|
20162
20212
|
}
|
|
20163
20213
|
async listRecallUsage(filter = {}) {
|
|
20164
20214
|
await this.initialize();
|
|
@@ -20182,12 +20232,46 @@ class SQLiteMemoryProvider {
|
|
|
20182
20232
|
}
|
|
20183
20233
|
async list(filter = {}) {
|
|
20184
20234
|
await this.initialize();
|
|
20185
|
-
|
|
20235
|
+
const db = this.requireDb();
|
|
20236
|
+
const conditions = [];
|
|
20237
|
+
const params = [];
|
|
20186
20238
|
if (filter.scopes && filter.scopes.length > 0) {
|
|
20187
|
-
|
|
20239
|
+
const scopeKeys = filter.scopes.map((scope) => stableScopeKey(scope));
|
|
20240
|
+
const placeholders = scopeKeys.map(() => "?").join(", ");
|
|
20241
|
+
conditions.push(`scope_key IN (${placeholders})`);
|
|
20242
|
+
params.push(...scopeKeys);
|
|
20188
20243
|
}
|
|
20189
20244
|
if (filter.kinds && filter.kinds.length > 0) {
|
|
20190
|
-
|
|
20245
|
+
if (filter.kinds.length === 1) {
|
|
20246
|
+
conditions.push("kind = ?");
|
|
20247
|
+
params.push(filter.kinds[0]);
|
|
20248
|
+
} else {
|
|
20249
|
+
const placeholders = filter.kinds.map(() => "?").join(", ");
|
|
20250
|
+
conditions.push(`kind IN (${placeholders})`);
|
|
20251
|
+
params.push(...filter.kinds);
|
|
20252
|
+
}
|
|
20253
|
+
}
|
|
20254
|
+
if (!filter.includeInactive) {
|
|
20255
|
+
conditions.push("superseded_by IS NULL");
|
|
20256
|
+
conditions.push("deleted = 0");
|
|
20257
|
+
}
|
|
20258
|
+
if (!filter.includeExpired) {
|
|
20259
|
+
const nowIso = new Date().toISOString();
|
|
20260
|
+
conditions.push("(expires_at IS NULL OR expires_at > ?)");
|
|
20261
|
+
params.push(nowIso);
|
|
20262
|
+
}
|
|
20263
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
20264
|
+
let sql = `SELECT id, record_json FROM memory_items ${whereClause} ORDER BY updated_at DESC`;
|
|
20265
|
+
if (typeof filter.limit === "number") {
|
|
20266
|
+
sql += " LIMIT ?";
|
|
20267
|
+
params.push(Math.trunc(filter.limit));
|
|
20268
|
+
}
|
|
20269
|
+
const rows = db.query(sql).all(...params);
|
|
20270
|
+
let records = [];
|
|
20271
|
+
for (const row of rows) {
|
|
20272
|
+
const parsed = this.parseMemoryRow(row);
|
|
20273
|
+
if (parsed)
|
|
20274
|
+
records.push(parsed);
|
|
20191
20275
|
}
|
|
20192
20276
|
if (!filter.includeExpired) {
|
|
20193
20277
|
const now = Date.now();
|
|
@@ -20198,11 +20282,7 @@ class SQLiteMemoryProvider {
|
|
|
20198
20282
|
return !Number.isFinite(expires) || expires > now;
|
|
20199
20283
|
});
|
|
20200
20284
|
}
|
|
20201
|
-
|
|
20202
|
-
records = records.filter((record) => !record.supersededBy && record.metadata.deleted !== true);
|
|
20203
|
-
}
|
|
20204
|
-
records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
20205
|
-
return records.slice(0, filter.limit ?? records.length);
|
|
20285
|
+
return records;
|
|
20206
20286
|
}
|
|
20207
20287
|
async createProposal(proposal) {
|
|
20208
20288
|
await this.initialize();
|
|
@@ -20392,6 +20472,31 @@ class SQLiteMemoryProvider {
|
|
|
20392
20472
|
apply();
|
|
20393
20473
|
}
|
|
20394
20474
|
}
|
|
20475
|
+
backfillScopeKeys() {
|
|
20476
|
+
const db = this.requireDb();
|
|
20477
|
+
const metaRow = db.query("SELECT value FROM _meta WHERE key = 'scope_key_backfilled'").get("scope_key_backfilled");
|
|
20478
|
+
if (metaRow?.value === "1")
|
|
20479
|
+
return;
|
|
20480
|
+
const rows = db.query("SELECT id, record_json, scope_key FROM memory_items").all();
|
|
20481
|
+
let backfillCount = 0;
|
|
20482
|
+
for (const row of rows) {
|
|
20483
|
+
try {
|
|
20484
|
+
const record = JSON.parse(row.record_json);
|
|
20485
|
+
const canonicalKey = stableScopeKey(record.scope);
|
|
20486
|
+
if (row.scope_key !== canonicalKey) {
|
|
20487
|
+
db.run("UPDATE memory_items SET scope_key = ? WHERE id = ?", [
|
|
20488
|
+
canonicalKey,
|
|
20489
|
+
row.id
|
|
20490
|
+
]);
|
|
20491
|
+
backfillCount++;
|
|
20492
|
+
}
|
|
20493
|
+
} catch {}
|
|
20494
|
+
}
|
|
20495
|
+
if (backfillCount > 0) {
|
|
20496
|
+
this.insertEvent("migration", "backfill_scope_keys", `${backfillCount} memory item(s) scope_key backfilled to canonical form`);
|
|
20497
|
+
}
|
|
20498
|
+
db.run("INSERT OR REPLACE INTO _meta (key, value) VALUES ('scope_key_backfilled', '1')");
|
|
20499
|
+
}
|
|
20395
20500
|
initializeFtsIndex() {
|
|
20396
20501
|
const db = this.requireDb();
|
|
20397
20502
|
try {
|
|
@@ -20502,7 +20607,7 @@ class SQLiteMemoryProvider {
|
|
|
20502
20607
|
record_json
|
|
20503
20608
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
20504
20609
|
record.id,
|
|
20505
|
-
|
|
20610
|
+
stableScopeKey(record.scope),
|
|
20506
20611
|
record.kind,
|
|
20507
20612
|
record.updatedAt,
|
|
20508
20613
|
record.expiresAt ?? null,
|
|
@@ -20878,14 +20983,203 @@ function rerankWithFts(items, ftsOrder) {
|
|
|
20878
20983
|
}).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
|
|
20879
20984
|
}
|
|
20880
20985
|
|
|
20986
|
+
// src/memory/provider-pool.ts
|
|
20987
|
+
var MAX_POOL_SIZE = 16;
|
|
20988
|
+
var POOLED_MARKER = Symbol("opencode-swarm-pooled-provider");
|
|
20989
|
+
var REAL_CLOSE = Symbol("opencode-swarm-real-close");
|
|
20990
|
+
var head = null;
|
|
20991
|
+
var tail = null;
|
|
20992
|
+
var entriesByKey = new Map;
|
|
20993
|
+
var deferredEntries = new Set;
|
|
20994
|
+
function markAsPooled(provider) {
|
|
20995
|
+
const originalClose = provider.close;
|
|
20996
|
+
provider.close = () => {
|
|
20997
|
+
releaseProvider(provider);
|
|
20998
|
+
return Promise.resolve();
|
|
20999
|
+
};
|
|
21000
|
+
provider[POOLED_MARKER] = true;
|
|
21001
|
+
if (originalClose) {
|
|
21002
|
+
provider[REAL_CLOSE] = originalClose;
|
|
21003
|
+
}
|
|
21004
|
+
}
|
|
21005
|
+
function callRealClose(provider) {
|
|
21006
|
+
const realClose = provider[REAL_CLOSE];
|
|
21007
|
+
try {
|
|
21008
|
+
realClose?.call(provider);
|
|
21009
|
+
} catch (err) {
|
|
21010
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
21011
|
+
if (process.env.OPENCODE_SWARM_DEBUG === "1") {
|
|
21012
|
+
console.debug(`[provider-pool] real close failed: ${msg}`);
|
|
21013
|
+
}
|
|
21014
|
+
}
|
|
21015
|
+
}
|
|
21016
|
+
function isPooledProvider(provider) {
|
|
21017
|
+
return POOLED_MARKER in provider;
|
|
21018
|
+
}
|
|
21019
|
+
function getOrCreateProvider(directory, config) {
|
|
21020
|
+
const key = resolvePoolKey(directory);
|
|
21021
|
+
const existing = entriesByKey.get(key);
|
|
21022
|
+
if (existing) {
|
|
21023
|
+
moveToHead(existing);
|
|
21024
|
+
existing.refCount++;
|
|
21025
|
+
return existing.provider;
|
|
21026
|
+
}
|
|
21027
|
+
for (const deferred of deferredEntries) {
|
|
21028
|
+
if (deferred.key === key) {
|
|
21029
|
+
deferredEntries.delete(deferred);
|
|
21030
|
+
if (entriesByKey.size >= MAX_POOL_SIZE) {
|
|
21031
|
+
evictLru();
|
|
21032
|
+
}
|
|
21033
|
+
deferred.prev = null;
|
|
21034
|
+
deferred.next = head;
|
|
21035
|
+
if (head)
|
|
21036
|
+
head.prev = deferred;
|
|
21037
|
+
head = deferred;
|
|
21038
|
+
if (!tail)
|
|
21039
|
+
tail = deferred;
|
|
21040
|
+
entriesByKey.set(key, deferred);
|
|
21041
|
+
deferred.refCount++;
|
|
21042
|
+
return deferred.provider;
|
|
21043
|
+
}
|
|
21044
|
+
}
|
|
21045
|
+
const provider = new SQLiteMemoryProvider(directory, config);
|
|
21046
|
+
markAsPooled(provider);
|
|
21047
|
+
if (entriesByKey.size >= MAX_POOL_SIZE) {
|
|
21048
|
+
evictLru();
|
|
21049
|
+
}
|
|
21050
|
+
const entry = {
|
|
21051
|
+
key,
|
|
21052
|
+
provider,
|
|
21053
|
+
refCount: 1,
|
|
21054
|
+
prev: null,
|
|
21055
|
+
next: head
|
|
21056
|
+
};
|
|
21057
|
+
if (head)
|
|
21058
|
+
head.prev = entry;
|
|
21059
|
+
head = entry;
|
|
21060
|
+
if (!tail)
|
|
21061
|
+
tail = entry;
|
|
21062
|
+
entriesByKey.set(key, entry);
|
|
21063
|
+
return provider;
|
|
21064
|
+
}
|
|
21065
|
+
function releaseProvider(provider) {
|
|
21066
|
+
for (const [_key, entry] of entriesByKey) {
|
|
21067
|
+
if (entry.provider === provider) {
|
|
21068
|
+
entry.refCount = Math.max(0, entry.refCount - 1);
|
|
21069
|
+
return;
|
|
21070
|
+
}
|
|
21071
|
+
}
|
|
21072
|
+
for (const entry of deferredEntries) {
|
|
21073
|
+
if (entry.provider === provider) {
|
|
21074
|
+
entry.refCount--;
|
|
21075
|
+
if (entry.refCount <= 0) {
|
|
21076
|
+
deferredEntries.delete(entry);
|
|
21077
|
+
callRealClose(provider);
|
|
21078
|
+
}
|
|
21079
|
+
return;
|
|
21080
|
+
}
|
|
21081
|
+
}
|
|
21082
|
+
if (isPooledProvider(provider)) {
|
|
21083
|
+
callRealClose(provider);
|
|
21084
|
+
}
|
|
21085
|
+
}
|
|
21086
|
+
function evictLru() {
|
|
21087
|
+
if (!tail)
|
|
21088
|
+
return;
|
|
21089
|
+
const evicted = tail;
|
|
21090
|
+
entriesByKey.delete(evicted.key);
|
|
21091
|
+
unlinkEntry(evicted);
|
|
21092
|
+
if (evicted.refCount > 0) {
|
|
21093
|
+
deferredEntries.add(evicted);
|
|
21094
|
+
} else {
|
|
21095
|
+
callRealClose(evicted.provider);
|
|
21096
|
+
}
|
|
21097
|
+
}
|
|
21098
|
+
function moveToHead(entry) {
|
|
21099
|
+
if (head === entry)
|
|
21100
|
+
return;
|
|
21101
|
+
unlinkEntry(entry);
|
|
21102
|
+
entry.prev = null;
|
|
21103
|
+
entry.next = head;
|
|
21104
|
+
if (head)
|
|
21105
|
+
head.prev = entry;
|
|
21106
|
+
head = entry;
|
|
21107
|
+
if (!tail)
|
|
21108
|
+
tail = entry;
|
|
21109
|
+
}
|
|
21110
|
+
function unlinkEntry(entry) {
|
|
21111
|
+
if (entry.prev)
|
|
21112
|
+
entry.prev.next = entry.next;
|
|
21113
|
+
if (entry.next)
|
|
21114
|
+
entry.next.prev = entry.prev;
|
|
21115
|
+
if (head === entry)
|
|
21116
|
+
head = entry.next;
|
|
21117
|
+
if (tail === entry)
|
|
21118
|
+
tail = entry.prev;
|
|
21119
|
+
}
|
|
21120
|
+
function resolvePoolKey(directory) {
|
|
21121
|
+
try {
|
|
21122
|
+
return realpathSync2(directory);
|
|
21123
|
+
} catch {
|
|
21124
|
+
return path41.resolve(directory);
|
|
21125
|
+
}
|
|
21126
|
+
}
|
|
21127
|
+
|
|
20881
21128
|
// src/memory/gateway.ts
|
|
20882
21129
|
function createConfiguredMemoryProvider(directory, config) {
|
|
20883
21130
|
if (config.provider === "sqlite") {
|
|
20884
|
-
return
|
|
21131
|
+
return getOrCreateProvider(directory, config);
|
|
20885
21132
|
}
|
|
20886
21133
|
return new LocalJsonlMemoryProvider(directory, config);
|
|
20887
21134
|
}
|
|
20888
21135
|
var gitRemoteUrlCache = new Map;
|
|
21136
|
+
var RESERVED_IDENTIFIERS = new Set([
|
|
21137
|
+
"const",
|
|
21138
|
+
"let",
|
|
21139
|
+
"var",
|
|
21140
|
+
"function",
|
|
21141
|
+
"class",
|
|
21142
|
+
"interface",
|
|
21143
|
+
"type",
|
|
21144
|
+
"async",
|
|
21145
|
+
"await",
|
|
21146
|
+
"return",
|
|
21147
|
+
"if",
|
|
21148
|
+
"else",
|
|
21149
|
+
"for",
|
|
21150
|
+
"while",
|
|
21151
|
+
"do",
|
|
21152
|
+
"switch",
|
|
21153
|
+
"case",
|
|
21154
|
+
"break",
|
|
21155
|
+
"continue",
|
|
21156
|
+
"new",
|
|
21157
|
+
"this",
|
|
21158
|
+
"super",
|
|
21159
|
+
"extends",
|
|
21160
|
+
"implements",
|
|
21161
|
+
"import",
|
|
21162
|
+
"export",
|
|
21163
|
+
"from",
|
|
21164
|
+
"default",
|
|
21165
|
+
"try",
|
|
21166
|
+
"catch",
|
|
21167
|
+
"finally",
|
|
21168
|
+
"throw",
|
|
21169
|
+
"typeof",
|
|
21170
|
+
"instanceof",
|
|
21171
|
+
"in",
|
|
21172
|
+
"of",
|
|
21173
|
+
"as",
|
|
21174
|
+
"yield",
|
|
21175
|
+
"static",
|
|
21176
|
+
"get",
|
|
21177
|
+
"set",
|
|
21178
|
+
"readonly",
|
|
21179
|
+
"public",
|
|
21180
|
+
"private",
|
|
21181
|
+
"protected"
|
|
21182
|
+
]);
|
|
20889
21183
|
|
|
20890
21184
|
// src/memory/evaluation.ts
|
|
20891
21185
|
var DEFAULT_PROVIDERS = [
|
|
@@ -20899,7 +21193,7 @@ var DEFAULT_MODES = [
|
|
|
20899
21193
|
];
|
|
20900
21194
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
20901
21195
|
async function evaluateMemoryRecallFixtures(options) {
|
|
20902
|
-
const fixtureDirectory =
|
|
21196
|
+
const fixtureDirectory = path42.resolve(options.fixtureDirectory);
|
|
20903
21197
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
20904
21198
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
20905
21199
|
const generatedAt = new Date().toISOString();
|
|
@@ -20908,7 +21202,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
20908
21202
|
for (const fixture of fixtures) {
|
|
20909
21203
|
const materialized = materializeFixture(fixture);
|
|
20910
21204
|
for (const providerName of providers) {
|
|
20911
|
-
const tempRoot = await fs17.realpath(await fs17.mkdtemp(
|
|
21205
|
+
const tempRoot = await fs17.realpath(await fs17.mkdtemp(path42.join(os9.tmpdir(), "swarm-memory-eval-")));
|
|
20912
21206
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
20913
21207
|
try {
|
|
20914
21208
|
await provider.initialize?.();
|
|
@@ -20952,7 +21246,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
|
20952
21246
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
20953
21247
|
const fixtures = [];
|
|
20954
21248
|
for (const file of files) {
|
|
20955
|
-
const raw = await fs17.readFile(
|
|
21249
|
+
const raw = await fs17.readFile(path42.join(fixtureDirectory, file), "utf-8");
|
|
20956
21250
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
20957
21251
|
}
|
|
20958
21252
|
return fixtures;
|
|
@@ -21228,7 +21522,7 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
21228
21522
|
curatorMemoryDecisions: exports_external.array(CuratorMemoryDecisionSchema).max(20).optional()
|
|
21229
21523
|
}).passthrough();
|
|
21230
21524
|
// src/commands/memory.ts
|
|
21231
|
-
var PACKAGE_ROOT =
|
|
21525
|
+
var PACKAGE_ROOT = path43.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
21232
21526
|
async function handleMemoryCommand(_directory, _args) {
|
|
21233
21527
|
return [
|
|
21234
21528
|
"## Swarm Memory",
|
|
@@ -21497,7 +21791,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
21497
21791
|
}
|
|
21498
21792
|
function parseEvaluateArgs(directory, args) {
|
|
21499
21793
|
let json = false;
|
|
21500
|
-
let fixtureDirectory =
|
|
21794
|
+
let fixtureDirectory = path43.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
21501
21795
|
for (let i = 0;i < args.length; i++) {
|
|
21502
21796
|
const arg = args[i];
|
|
21503
21797
|
if (arg === "--json") {
|
|
@@ -21511,10 +21805,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
21511
21805
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
21512
21806
|
};
|
|
21513
21807
|
}
|
|
21514
|
-
const resolvedFixtures =
|
|
21515
|
-
const canonical =
|
|
21516
|
-
const allowedRootA =
|
|
21517
|
-
const allowedRootB =
|
|
21808
|
+
const resolvedFixtures = path43.resolve(directory, next);
|
|
21809
|
+
const canonical = path43.normalize(resolvedFixtures) + path43.sep;
|
|
21810
|
+
const allowedRootA = path43.normalize(directory) + path43.sep;
|
|
21811
|
+
const allowedRootB = path43.normalize(path43.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path43.sep;
|
|
21518
21812
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
21519
21813
|
return {
|
|
21520
21814
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -21553,15 +21847,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
21553
21847
|
return { limit, confirm };
|
|
21554
21848
|
}
|
|
21555
21849
|
function resolvePackageRootFromModule(modulePath) {
|
|
21556
|
-
const moduleDir =
|
|
21557
|
-
const leaf =
|
|
21850
|
+
const moduleDir = path43.dirname(modulePath);
|
|
21851
|
+
const leaf = path43.basename(moduleDir);
|
|
21558
21852
|
if (leaf === "commands" || leaf === "cli") {
|
|
21559
|
-
return
|
|
21853
|
+
return path43.resolve(moduleDir, "..", "..");
|
|
21560
21854
|
}
|
|
21561
21855
|
if (leaf === "dist") {
|
|
21562
|
-
return
|
|
21856
|
+
return path43.resolve(moduleDir, "..");
|
|
21563
21857
|
}
|
|
21564
|
-
return
|
|
21858
|
+
return path43.resolve(moduleDir, "..");
|
|
21565
21859
|
}
|
|
21566
21860
|
function formatMigrationResult(label, report) {
|
|
21567
21861
|
if (!report) {
|
|
@@ -22243,11 +22537,11 @@ var _internals36 = {
|
|
|
22243
22537
|
|
|
22244
22538
|
// src/services/preflight-service.ts
|
|
22245
22539
|
import * as fs24 from "fs";
|
|
22246
|
-
import * as
|
|
22540
|
+
import * as path50 from "path";
|
|
22247
22541
|
|
|
22248
22542
|
// src/tools/lint.ts
|
|
22249
22543
|
import * as fs18 from "fs";
|
|
22250
|
-
import * as
|
|
22544
|
+
import * as path44 from "path";
|
|
22251
22545
|
|
|
22252
22546
|
// src/utils/path-security.ts
|
|
22253
22547
|
function containsPathTraversal(str) {
|
|
@@ -22303,9 +22597,9 @@ function validateArgs(args) {
|
|
|
22303
22597
|
}
|
|
22304
22598
|
function getLinterCommand(linter, mode, projectDir) {
|
|
22305
22599
|
const isWindows = process.platform === "win32";
|
|
22306
|
-
const binDir =
|
|
22307
|
-
const biomeBin = isWindows ?
|
|
22308
|
-
const eslintBin = isWindows ?
|
|
22600
|
+
const binDir = path44.join(projectDir, "node_modules", ".bin");
|
|
22601
|
+
const biomeBin = isWindows ? path44.join(binDir, "biome.EXE") : path44.join(binDir, "biome");
|
|
22602
|
+
const eslintBin = isWindows ? path44.join(binDir, "eslint.cmd") : path44.join(binDir, "eslint");
|
|
22309
22603
|
switch (linter) {
|
|
22310
22604
|
case "biome":
|
|
22311
22605
|
if (mode === "fix") {
|
|
@@ -22321,7 +22615,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
22321
22615
|
}
|
|
22322
22616
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
22323
22617
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
22324
|
-
const gradlew = fs18.existsSync(
|
|
22618
|
+
const gradlew = fs18.existsSync(path44.join(cwd, gradlewName)) ? path44.join(cwd, gradlewName) : null;
|
|
22325
22619
|
switch (linter) {
|
|
22326
22620
|
case "ruff":
|
|
22327
22621
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -22355,10 +22649,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
22355
22649
|
}
|
|
22356
22650
|
}
|
|
22357
22651
|
function detectRuff(cwd) {
|
|
22358
|
-
if (fs18.existsSync(
|
|
22652
|
+
if (fs18.existsSync(path44.join(cwd, "ruff.toml")))
|
|
22359
22653
|
return isCommandAvailable("ruff");
|
|
22360
22654
|
try {
|
|
22361
|
-
const pyproject =
|
|
22655
|
+
const pyproject = path44.join(cwd, "pyproject.toml");
|
|
22362
22656
|
if (fs18.existsSync(pyproject)) {
|
|
22363
22657
|
const content = fs18.readFileSync(pyproject, "utf-8");
|
|
22364
22658
|
if (content.includes("[tool.ruff]"))
|
|
@@ -22368,19 +22662,19 @@ function detectRuff(cwd) {
|
|
|
22368
22662
|
return false;
|
|
22369
22663
|
}
|
|
22370
22664
|
function detectClippy(cwd) {
|
|
22371
|
-
return fs18.existsSync(
|
|
22665
|
+
return fs18.existsSync(path44.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
22372
22666
|
}
|
|
22373
22667
|
function detectGolangciLint(cwd) {
|
|
22374
|
-
return fs18.existsSync(
|
|
22668
|
+
return fs18.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
22375
22669
|
}
|
|
22376
22670
|
function detectCheckstyle(cwd) {
|
|
22377
|
-
const hasMaven = fs18.existsSync(
|
|
22378
|
-
const hasGradle = fs18.existsSync(
|
|
22379
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(
|
|
22671
|
+
const hasMaven = fs18.existsSync(path44.join(cwd, "pom.xml"));
|
|
22672
|
+
const hasGradle = fs18.existsSync(path44.join(cwd, "build.gradle")) || fs18.existsSync(path44.join(cwd, "build.gradle.kts"));
|
|
22673
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path44.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
22380
22674
|
return (hasMaven || hasGradle) && hasBinary;
|
|
22381
22675
|
}
|
|
22382
22676
|
function detectKtlint(cwd) {
|
|
22383
|
-
const hasKotlin = fs18.existsSync(
|
|
22677
|
+
const hasKotlin = fs18.existsSync(path44.join(cwd, "build.gradle.kts")) || fs18.existsSync(path44.join(cwd, "build.gradle")) || (() => {
|
|
22384
22678
|
try {
|
|
22385
22679
|
return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
22386
22680
|
} catch {
|
|
@@ -22399,11 +22693,11 @@ function detectDotnetFormat(cwd) {
|
|
|
22399
22693
|
}
|
|
22400
22694
|
}
|
|
22401
22695
|
function detectCppcheck(cwd) {
|
|
22402
|
-
if (fs18.existsSync(
|
|
22696
|
+
if (fs18.existsSync(path44.join(cwd, "CMakeLists.txt"))) {
|
|
22403
22697
|
return isCommandAvailable("cppcheck");
|
|
22404
22698
|
}
|
|
22405
22699
|
try {
|
|
22406
|
-
const dirsToCheck = [cwd,
|
|
22700
|
+
const dirsToCheck = [cwd, path44.join(cwd, "src")];
|
|
22407
22701
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
22408
22702
|
try {
|
|
22409
22703
|
return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -22417,13 +22711,13 @@ function detectCppcheck(cwd) {
|
|
|
22417
22711
|
}
|
|
22418
22712
|
}
|
|
22419
22713
|
function detectSwiftlint(cwd) {
|
|
22420
|
-
return fs18.existsSync(
|
|
22714
|
+
return fs18.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
22421
22715
|
}
|
|
22422
22716
|
function detectDartAnalyze(cwd) {
|
|
22423
|
-
return fs18.existsSync(
|
|
22717
|
+
return fs18.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
22424
22718
|
}
|
|
22425
22719
|
function detectRubocop(cwd) {
|
|
22426
|
-
return (fs18.existsSync(
|
|
22720
|
+
return (fs18.existsSync(path44.join(cwd, "Gemfile")) || fs18.existsSync(path44.join(cwd, "gems.rb")) || fs18.existsSync(path44.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
22427
22721
|
}
|
|
22428
22722
|
function detectAdditionalLinter(cwd) {
|
|
22429
22723
|
if (detectRuff(cwd))
|
|
@@ -22451,10 +22745,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
22451
22745
|
function findBinInAncestors(startDir, binName) {
|
|
22452
22746
|
let dir = startDir;
|
|
22453
22747
|
while (true) {
|
|
22454
|
-
const candidate =
|
|
22748
|
+
const candidate = path44.join(dir, "node_modules", ".bin", binName);
|
|
22455
22749
|
if (fs18.existsSync(candidate))
|
|
22456
22750
|
return candidate;
|
|
22457
|
-
const parent =
|
|
22751
|
+
const parent = path44.dirname(dir);
|
|
22458
22752
|
if (parent === dir)
|
|
22459
22753
|
break;
|
|
22460
22754
|
dir = parent;
|
|
@@ -22463,10 +22757,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
22463
22757
|
}
|
|
22464
22758
|
function findBinInEnvPath(binName) {
|
|
22465
22759
|
const searchPath = process.env.PATH ?? "";
|
|
22466
|
-
for (const dir of searchPath.split(
|
|
22760
|
+
for (const dir of searchPath.split(path44.delimiter)) {
|
|
22467
22761
|
if (!dir)
|
|
22468
22762
|
continue;
|
|
22469
|
-
const candidate =
|
|
22763
|
+
const candidate = path44.join(dir, binName);
|
|
22470
22764
|
if (fs18.existsSync(candidate))
|
|
22471
22765
|
return candidate;
|
|
22472
22766
|
}
|
|
@@ -22479,13 +22773,13 @@ async function detectAvailableLinter(directory) {
|
|
|
22479
22773
|
return null;
|
|
22480
22774
|
const projectDir = directory;
|
|
22481
22775
|
const isWindows = process.platform === "win32";
|
|
22482
|
-
const biomeBin = isWindows ?
|
|
22483
|
-
const eslintBin = isWindows ?
|
|
22776
|
+
const biomeBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "biome.EXE") : path44.join(projectDir, "node_modules", ".bin", "biome");
|
|
22777
|
+
const eslintBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path44.join(projectDir, "node_modules", ".bin", "eslint");
|
|
22484
22778
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
22485
22779
|
if (localResult)
|
|
22486
22780
|
return localResult;
|
|
22487
|
-
const biomeAncestor = findBinInAncestors(
|
|
22488
|
-
const eslintAncestor = findBinInAncestors(
|
|
22781
|
+
const biomeAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
22782
|
+
const eslintAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
22489
22783
|
if (biomeAncestor || eslintAncestor) {
|
|
22490
22784
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
22491
22785
|
}
|
|
@@ -22504,7 +22798,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
22504
22798
|
stderr: "pipe"
|
|
22505
22799
|
});
|
|
22506
22800
|
const biomeExit = biomeProc.exited;
|
|
22507
|
-
const timeout = new Promise((
|
|
22801
|
+
const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
|
|
22508
22802
|
const result = await Promise.race([biomeExit, timeout]);
|
|
22509
22803
|
if (result === "timeout") {
|
|
22510
22804
|
biomeProc.kill();
|
|
@@ -22518,7 +22812,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
22518
22812
|
stderr: "pipe"
|
|
22519
22813
|
});
|
|
22520
22814
|
const eslintExit = eslintProc.exited;
|
|
22521
|
-
const timeout = new Promise((
|
|
22815
|
+
const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
|
|
22522
22816
|
const result = await Promise.race([eslintExit, timeout]);
|
|
22523
22817
|
if (result === "timeout") {
|
|
22524
22818
|
eslintProc.kill();
|
|
@@ -22699,7 +22993,7 @@ var _internals37 = {
|
|
|
22699
22993
|
|
|
22700
22994
|
// src/tools/secretscan.ts
|
|
22701
22995
|
import * as fs19 from "fs";
|
|
22702
|
-
import * as
|
|
22996
|
+
import * as path45 from "path";
|
|
22703
22997
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
22704
22998
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
22705
22999
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -22926,7 +23220,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
22926
23220
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
22927
23221
|
}
|
|
22928
23222
|
function loadSecretScanIgnore(scanDir) {
|
|
22929
|
-
const ignorePath =
|
|
23223
|
+
const ignorePath = path45.join(scanDir, ".secretscanignore");
|
|
22930
23224
|
try {
|
|
22931
23225
|
if (!fs19.existsSync(ignorePath))
|
|
22932
23226
|
return [];
|
|
@@ -22949,7 +23243,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
22949
23243
|
if (exactNames.has(entry))
|
|
22950
23244
|
return true;
|
|
22951
23245
|
for (const pattern of globPatterns) {
|
|
22952
|
-
if (
|
|
23246
|
+
if (path45.matchesGlob(relPath, pattern))
|
|
22953
23247
|
return true;
|
|
22954
23248
|
}
|
|
22955
23249
|
return false;
|
|
@@ -22970,7 +23264,7 @@ function validateDirectoryInput(dir) {
|
|
|
22970
23264
|
return null;
|
|
22971
23265
|
}
|
|
22972
23266
|
function isBinaryFile(filePath, buffer) {
|
|
22973
|
-
const ext =
|
|
23267
|
+
const ext = path45.extname(filePath).toLowerCase();
|
|
22974
23268
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
22975
23269
|
return true;
|
|
22976
23270
|
}
|
|
@@ -23107,9 +23401,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
23107
23401
|
return false;
|
|
23108
23402
|
}
|
|
23109
23403
|
function isPathWithinScope(realPath, scanDir) {
|
|
23110
|
-
const resolvedScanDir =
|
|
23111
|
-
const resolvedRealPath =
|
|
23112
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
23404
|
+
const resolvedScanDir = path45.resolve(scanDir);
|
|
23405
|
+
const resolvedRealPath = path45.resolve(realPath);
|
|
23406
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path45.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
23113
23407
|
}
|
|
23114
23408
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
23115
23409
|
skippedDirs: 0,
|
|
@@ -23135,8 +23429,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
23135
23429
|
return a.localeCompare(b);
|
|
23136
23430
|
});
|
|
23137
23431
|
for (const entry of entries) {
|
|
23138
|
-
const fullPath =
|
|
23139
|
-
const relPath =
|
|
23432
|
+
const fullPath = path45.join(dir, entry);
|
|
23433
|
+
const relPath = path45.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
23140
23434
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
23141
23435
|
stats.skippedDirs++;
|
|
23142
23436
|
continue;
|
|
@@ -23171,7 +23465,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
23171
23465
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
23172
23466
|
files.push(...subFiles);
|
|
23173
23467
|
} else if (lstat2.isFile()) {
|
|
23174
|
-
const ext =
|
|
23468
|
+
const ext = path45.extname(fullPath).toLowerCase();
|
|
23175
23469
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
23176
23470
|
files.push(fullPath);
|
|
23177
23471
|
} else {
|
|
@@ -23237,7 +23531,7 @@ var secretscan = createSwarmTool({
|
|
|
23237
23531
|
}
|
|
23238
23532
|
}
|
|
23239
23533
|
try {
|
|
23240
|
-
const _scanDirRaw =
|
|
23534
|
+
const _scanDirRaw = path45.resolve(directory);
|
|
23241
23535
|
const scanDir = (() => {
|
|
23242
23536
|
try {
|
|
23243
23537
|
return fs19.realpathSync(_scanDirRaw);
|
|
@@ -23400,11 +23694,11 @@ var _internals38 = {
|
|
|
23400
23694
|
|
|
23401
23695
|
// src/tools/test-runner.ts
|
|
23402
23696
|
import * as fs23 from "fs";
|
|
23403
|
-
import * as
|
|
23697
|
+
import * as path49 from "path";
|
|
23404
23698
|
|
|
23405
23699
|
// src/test-impact/analyzer.ts
|
|
23406
23700
|
import fs20 from "fs";
|
|
23407
|
-
import
|
|
23701
|
+
import path46 from "path";
|
|
23408
23702
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
23409
23703
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
23410
23704
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -23445,8 +23739,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
23445
23739
|
if (!importPath.startsWith(".")) {
|
|
23446
23740
|
return null;
|
|
23447
23741
|
}
|
|
23448
|
-
const resolved =
|
|
23449
|
-
if (
|
|
23742
|
+
const resolved = path46.resolve(fromDir, importPath);
|
|
23743
|
+
if (path46.extname(resolved)) {
|
|
23450
23744
|
if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
|
|
23451
23745
|
return normalizePath2(resolved);
|
|
23452
23746
|
}
|
|
@@ -23466,20 +23760,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
23466
23760
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
23467
23761
|
let baseDir = fromDir;
|
|
23468
23762
|
for (let i = 1;i < leadingDots; i++) {
|
|
23469
|
-
baseDir =
|
|
23763
|
+
baseDir = path46.dirname(baseDir);
|
|
23470
23764
|
}
|
|
23471
23765
|
const rest = module.slice(leadingDots);
|
|
23472
23766
|
if (rest.length === 0) {
|
|
23473
|
-
const initPath =
|
|
23767
|
+
const initPath = path46.join(baseDir, "__init__.py");
|
|
23474
23768
|
if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
|
|
23475
23769
|
return normalizePath2(initPath);
|
|
23476
23770
|
}
|
|
23477
23771
|
return null;
|
|
23478
23772
|
}
|
|
23479
|
-
const subpath = rest.replace(/\./g,
|
|
23773
|
+
const subpath = rest.replace(/\./g, path46.sep);
|
|
23480
23774
|
const candidates = [
|
|
23481
|
-
`${
|
|
23482
|
-
|
|
23775
|
+
`${path46.join(baseDir, subpath)}.py`,
|
|
23776
|
+
path46.join(baseDir, subpath, "__init__.py")
|
|
23483
23777
|
];
|
|
23484
23778
|
for (const c of candidates) {
|
|
23485
23779
|
if (fs20.existsSync(c) && fs20.statSync(c).isFile())
|
|
@@ -23489,7 +23783,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
23489
23783
|
}
|
|
23490
23784
|
var goModuleCache = new Map;
|
|
23491
23785
|
function findGoModule(fromDir) {
|
|
23492
|
-
const resolved =
|
|
23786
|
+
const resolved = path46.resolve(fromDir);
|
|
23493
23787
|
let cur = resolved;
|
|
23494
23788
|
const walked = [];
|
|
23495
23789
|
for (let i = 0;i < 16; i++) {
|
|
@@ -23501,7 +23795,7 @@ function findGoModule(fromDir) {
|
|
|
23501
23795
|
}
|
|
23502
23796
|
walked.push(cur);
|
|
23503
23797
|
try {
|
|
23504
|
-
const goMod =
|
|
23798
|
+
const goMod = path46.join(cur, "go.mod");
|
|
23505
23799
|
const content = fs20.readFileSync(goMod, "utf-8");
|
|
23506
23800
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
23507
23801
|
if (moduleMatch) {
|
|
@@ -23512,10 +23806,10 @@ function findGoModule(fromDir) {
|
|
|
23512
23806
|
}
|
|
23513
23807
|
} catch {}
|
|
23514
23808
|
try {
|
|
23515
|
-
fs20.accessSync(
|
|
23809
|
+
fs20.accessSync(path46.join(cur, ".git"));
|
|
23516
23810
|
break;
|
|
23517
23811
|
} catch {}
|
|
23518
|
-
const parent =
|
|
23812
|
+
const parent = path46.dirname(cur);
|
|
23519
23813
|
if (parent === cur)
|
|
23520
23814
|
break;
|
|
23521
23815
|
cur = parent;
|
|
@@ -23527,12 +23821,12 @@ function findGoModule(fromDir) {
|
|
|
23527
23821
|
function resolveGoImport(fromDir, importPath) {
|
|
23528
23822
|
let dir = null;
|
|
23529
23823
|
if (importPath.startsWith(".")) {
|
|
23530
|
-
dir =
|
|
23824
|
+
dir = path46.resolve(fromDir, importPath);
|
|
23531
23825
|
} else {
|
|
23532
23826
|
const mod = findGoModule(fromDir);
|
|
23533
23827
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
23534
23828
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
23535
|
-
dir =
|
|
23829
|
+
dir = path46.join(mod.moduleRoot, subpath);
|
|
23536
23830
|
}
|
|
23537
23831
|
}
|
|
23538
23832
|
if (dir === null)
|
|
@@ -23540,7 +23834,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
23540
23834
|
if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
|
|
23541
23835
|
return [];
|
|
23542
23836
|
try {
|
|
23543
|
-
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(
|
|
23837
|
+
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path46.join(dir, f)));
|
|
23544
23838
|
} catch {
|
|
23545
23839
|
return [];
|
|
23546
23840
|
}
|
|
@@ -23579,15 +23873,15 @@ function findTestFilesSync(cwd) {
|
|
|
23579
23873
|
for (const entry of entries) {
|
|
23580
23874
|
if (entry.isDirectory()) {
|
|
23581
23875
|
if (!skipDirs.has(entry.name)) {
|
|
23582
|
-
walk(
|
|
23876
|
+
walk(path46.join(dir, entry.name), visitedInodes);
|
|
23583
23877
|
}
|
|
23584
23878
|
} else if (entry.isFile()) {
|
|
23585
23879
|
const name = entry.name;
|
|
23586
23880
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
23587
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
23881
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path46.sep}tests${path46.sep}`) && name.endsWith(".py");
|
|
23588
23882
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
23589
23883
|
if (isTsTest || isPyTest || isGoTest) {
|
|
23590
|
-
testFiles.push(normalizePath2(
|
|
23884
|
+
testFiles.push(normalizePath2(path46.join(dir, entry.name)));
|
|
23591
23885
|
}
|
|
23592
23886
|
}
|
|
23593
23887
|
}
|
|
@@ -23612,8 +23906,8 @@ function extractImports(content) {
|
|
|
23612
23906
|
];
|
|
23613
23907
|
}
|
|
23614
23908
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
23615
|
-
const ext =
|
|
23616
|
-
const testDir =
|
|
23909
|
+
const ext = path46.extname(testFile).toLowerCase();
|
|
23910
|
+
const testDir = path46.dirname(testFile);
|
|
23617
23911
|
function addEdge(source) {
|
|
23618
23912
|
if (!impactMap[source])
|
|
23619
23913
|
impactMap[source] = [];
|
|
@@ -23686,7 +23980,7 @@ async function buildImpactMap(cwd) {
|
|
|
23686
23980
|
return impactMap;
|
|
23687
23981
|
}
|
|
23688
23982
|
async function loadImpactMap(cwd, options) {
|
|
23689
|
-
const cachePath =
|
|
23983
|
+
const cachePath = path46.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
23690
23984
|
if (fs20.existsSync(cachePath)) {
|
|
23691
23985
|
try {
|
|
23692
23986
|
const content = fs20.readFileSync(cachePath, "utf-8");
|
|
@@ -23719,12 +24013,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
23719
24013
|
return _internals39.buildImpactMap(cwd);
|
|
23720
24014
|
}
|
|
23721
24015
|
async function saveImpactMap(cwd, impactMap) {
|
|
23722
|
-
if (!
|
|
24016
|
+
if (!path46.isAbsolute(cwd)) {
|
|
23723
24017
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
23724
24018
|
}
|
|
23725
24019
|
_internals39.validateProjectRoot(cwd);
|
|
23726
|
-
const cacheDir2 =
|
|
23727
|
-
const cachePath =
|
|
24020
|
+
const cacheDir2 = path46.join(cwd, ".swarm", "cache");
|
|
24021
|
+
const cachePath = path46.join(cacheDir2, "impact-map.json");
|
|
23728
24022
|
if (!fs20.existsSync(cacheDir2)) {
|
|
23729
24023
|
fs20.mkdirSync(cacheDir2, { recursive: true });
|
|
23730
24024
|
}
|
|
@@ -23756,7 +24050,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
23756
24050
|
budgetExceeded = true;
|
|
23757
24051
|
break;
|
|
23758
24052
|
}
|
|
23759
|
-
const normalizedChanged = normalizePath2(
|
|
24053
|
+
const normalizedChanged = normalizePath2(path46.resolve(changedFile));
|
|
23760
24054
|
const tests = impactMap[normalizedChanged];
|
|
23761
24055
|
if (tests && tests.length > 0) {
|
|
23762
24056
|
for (const test of tests) {
|
|
@@ -23770,13 +24064,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
23770
24064
|
if (budgetExceeded)
|
|
23771
24065
|
break;
|
|
23772
24066
|
} else {
|
|
23773
|
-
const changedDir = normalizePath2(
|
|
23774
|
-
const changedInputDir = normalizePath2(
|
|
24067
|
+
const changedDir = normalizePath2(path46.dirname(normalizedChanged));
|
|
24068
|
+
const changedInputDir = normalizePath2(path46.dirname(changedFile));
|
|
23775
24069
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
23776
24070
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
23777
24071
|
}).sort(([sourceA], [sourceB]) => {
|
|
23778
|
-
const sourceDirA = normalizePath2(
|
|
23779
|
-
const sourceDirB = normalizePath2(
|
|
24072
|
+
const sourceDirA = normalizePath2(path46.dirname(sourceA));
|
|
24073
|
+
const sourceDirB = normalizePath2(path46.dirname(sourceB));
|
|
23780
24074
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
23781
24075
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
23782
24076
|
if (exactA !== exactB)
|
|
@@ -24103,7 +24397,7 @@ function detectFlakyTests(allHistory) {
|
|
|
24103
24397
|
|
|
24104
24398
|
// src/test-impact/history-store.ts
|
|
24105
24399
|
import fs21 from "fs";
|
|
24106
|
-
import
|
|
24400
|
+
import path47 from "path";
|
|
24107
24401
|
var MAX_HISTORY_PER_TEST = 20;
|
|
24108
24402
|
var MAX_ERROR_LENGTH = 500;
|
|
24109
24403
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -24115,10 +24409,10 @@ function getHistoryPath(workingDir) {
|
|
|
24115
24409
|
if (!workingDir) {
|
|
24116
24410
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
24117
24411
|
}
|
|
24118
|
-
if (!
|
|
24412
|
+
if (!path47.isAbsolute(workingDir)) {
|
|
24119
24413
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
24120
24414
|
}
|
|
24121
|
-
return
|
|
24415
|
+
return path47.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
24122
24416
|
}
|
|
24123
24417
|
function sanitizeErrorMessage(errorMessage) {
|
|
24124
24418
|
if (errorMessage === undefined) {
|
|
@@ -24210,7 +24504,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
24210
24504
|
}
|
|
24211
24505
|
}
|
|
24212
24506
|
const historyPath = getHistoryPath(workingDir);
|
|
24213
|
-
const historyDir =
|
|
24507
|
+
const historyDir = path47.dirname(historyPath);
|
|
24214
24508
|
_internals40.validateProjectRoot(workingDir);
|
|
24215
24509
|
if (!fs21.existsSync(historyDir)) {
|
|
24216
24510
|
fs21.mkdirSync(historyDir, { recursive: true });
|
|
@@ -24340,7 +24634,7 @@ var _internals40 = {
|
|
|
24340
24634
|
|
|
24341
24635
|
// src/tools/resolve-working-directory.ts
|
|
24342
24636
|
import * as fs22 from "fs";
|
|
24343
|
-
import * as
|
|
24637
|
+
import * as path48 from "path";
|
|
24344
24638
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
24345
24639
|
if (workingDirectory == null || workingDirectory === "") {
|
|
24346
24640
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -24372,15 +24666,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
24372
24666
|
};
|
|
24373
24667
|
}
|
|
24374
24668
|
}
|
|
24375
|
-
const rawPathParts = workingDirectory.split(
|
|
24669
|
+
const rawPathParts = workingDirectory.split(path48.sep);
|
|
24376
24670
|
if (rawPathParts.includes("..")) {
|
|
24377
24671
|
return {
|
|
24378
24672
|
success: false,
|
|
24379
24673
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
24380
24674
|
};
|
|
24381
24675
|
}
|
|
24382
|
-
const normalizedDir =
|
|
24383
|
-
const resolvedDir =
|
|
24676
|
+
const normalizedDir = path48.normalize(workingDirectory);
|
|
24677
|
+
const resolvedDir = path48.resolve(normalizedDir);
|
|
24384
24678
|
let statResult;
|
|
24385
24679
|
try {
|
|
24386
24680
|
statResult = fs22.statSync(resolvedDir);
|
|
@@ -24399,7 +24693,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
24399
24693
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
24400
24694
|
return { success: true, directory: resolvedDir };
|
|
24401
24695
|
}
|
|
24402
|
-
const resolvedFallback =
|
|
24696
|
+
const resolvedFallback = path48.resolve(fallbackDirectory);
|
|
24403
24697
|
let fallbackExists = false;
|
|
24404
24698
|
try {
|
|
24405
24699
|
fs22.statSync(resolvedFallback);
|
|
@@ -24408,7 +24702,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
24408
24702
|
fallbackExists = false;
|
|
24409
24703
|
}
|
|
24410
24704
|
if (fallbackExists) {
|
|
24411
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
24705
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path48.sep);
|
|
24412
24706
|
if (isSubdirectory) {
|
|
24413
24707
|
return {
|
|
24414
24708
|
success: false,
|
|
@@ -24431,7 +24725,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
24431
24725
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
24432
24726
|
const uniqueTestFiles = new Set;
|
|
24433
24727
|
for (const sourceFile of sourceFiles) {
|
|
24434
|
-
const resolvedPath =
|
|
24728
|
+
const resolvedPath = path49.resolve(cwd, sourceFile);
|
|
24435
24729
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
24436
24730
|
const testFiles = impactMap[normalizedPath];
|
|
24437
24731
|
if (testFiles) {
|
|
@@ -24516,14 +24810,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
24516
24810
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
24517
24811
|
}
|
|
24518
24812
|
function detectGoTest(cwd) {
|
|
24519
|
-
return fs23.existsSync(
|
|
24813
|
+
return fs23.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
24520
24814
|
}
|
|
24521
24815
|
function detectJavaMaven(cwd) {
|
|
24522
|
-
return fs23.existsSync(
|
|
24816
|
+
return fs23.existsSync(path49.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
24523
24817
|
}
|
|
24524
24818
|
function detectGradle(cwd) {
|
|
24525
|
-
const hasBuildFile = fs23.existsSync(
|
|
24526
|
-
const hasGradlew = fs23.existsSync(
|
|
24819
|
+
const hasBuildFile = fs23.existsSync(path49.join(cwd, "build.gradle")) || fs23.existsSync(path49.join(cwd, "build.gradle.kts"));
|
|
24820
|
+
const hasGradlew = fs23.existsSync(path49.join(cwd, "gradlew")) || fs23.existsSync(path49.join(cwd, "gradlew.bat"));
|
|
24527
24821
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
24528
24822
|
}
|
|
24529
24823
|
function detectDotnetTest(cwd) {
|
|
@@ -24536,25 +24830,25 @@ function detectDotnetTest(cwd) {
|
|
|
24536
24830
|
}
|
|
24537
24831
|
}
|
|
24538
24832
|
function detectCTest(cwd) {
|
|
24539
|
-
const hasSource = fs23.existsSync(
|
|
24540
|
-
const hasBuildCache = fs23.existsSync(
|
|
24833
|
+
const hasSource = fs23.existsSync(path49.join(cwd, "CMakeLists.txt"));
|
|
24834
|
+
const hasBuildCache = fs23.existsSync(path49.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path49.join(cwd, "build", "CMakeCache.txt"));
|
|
24541
24835
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
24542
24836
|
}
|
|
24543
24837
|
function detectSwiftTest(cwd) {
|
|
24544
|
-
return fs23.existsSync(
|
|
24838
|
+
return fs23.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
24545
24839
|
}
|
|
24546
24840
|
function detectDartTest(cwd) {
|
|
24547
|
-
return fs23.existsSync(
|
|
24841
|
+
return fs23.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
24548
24842
|
}
|
|
24549
24843
|
function detectRSpec(cwd) {
|
|
24550
|
-
const hasRSpecFile = fs23.existsSync(
|
|
24551
|
-
const hasGemfile = fs23.existsSync(
|
|
24552
|
-
const hasSpecDir = fs23.existsSync(
|
|
24844
|
+
const hasRSpecFile = fs23.existsSync(path49.join(cwd, ".rspec"));
|
|
24845
|
+
const hasGemfile = fs23.existsSync(path49.join(cwd, "Gemfile"));
|
|
24846
|
+
const hasSpecDir = fs23.existsSync(path49.join(cwd, "spec"));
|
|
24553
24847
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
24554
24848
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
24555
24849
|
}
|
|
24556
24850
|
function detectMinitest(cwd) {
|
|
24557
|
-
return fs23.existsSync(
|
|
24851
|
+
return fs23.existsSync(path49.join(cwd, "test")) && (fs23.existsSync(path49.join(cwd, "Gemfile")) || fs23.existsSync(path49.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
24558
24852
|
}
|
|
24559
24853
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
24560
24854
|
bun: "bun",
|
|
@@ -24639,7 +24933,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
24639
24933
|
async function detectTestFramework(cwd) {
|
|
24640
24934
|
const baseDir = cwd;
|
|
24641
24935
|
try {
|
|
24642
|
-
const packageJsonPath =
|
|
24936
|
+
const packageJsonPath = path49.join(baseDir, "package.json");
|
|
24643
24937
|
if (fs23.existsSync(packageJsonPath)) {
|
|
24644
24938
|
const content = fs23.readFileSync(packageJsonPath, "utf-8");
|
|
24645
24939
|
const pkg = JSON.parse(content);
|
|
@@ -24660,16 +24954,16 @@ async function detectTestFramework(cwd) {
|
|
|
24660
24954
|
return "jest";
|
|
24661
24955
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
24662
24956
|
return "mocha";
|
|
24663
|
-
if (fs23.existsSync(
|
|
24957
|
+
if (fs23.existsSync(path49.join(baseDir, "bun.lockb")) || fs23.existsSync(path49.join(baseDir, "bun.lock"))) {
|
|
24664
24958
|
if (scripts.test?.includes("bun"))
|
|
24665
24959
|
return "bun";
|
|
24666
24960
|
}
|
|
24667
24961
|
}
|
|
24668
24962
|
} catch {}
|
|
24669
24963
|
try {
|
|
24670
|
-
const pyprojectTomlPath =
|
|
24671
|
-
const setupCfgPath =
|
|
24672
|
-
const requirementsTxtPath =
|
|
24964
|
+
const pyprojectTomlPath = path49.join(baseDir, "pyproject.toml");
|
|
24965
|
+
const setupCfgPath = path49.join(baseDir, "setup.cfg");
|
|
24966
|
+
const requirementsTxtPath = path49.join(baseDir, "requirements.txt");
|
|
24673
24967
|
if (fs23.existsSync(pyprojectTomlPath)) {
|
|
24674
24968
|
const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
|
|
24675
24969
|
if (content.includes("[tool.pytest"))
|
|
@@ -24689,7 +24983,7 @@ async function detectTestFramework(cwd) {
|
|
|
24689
24983
|
}
|
|
24690
24984
|
} catch {}
|
|
24691
24985
|
try {
|
|
24692
|
-
const cargoTomlPath =
|
|
24986
|
+
const cargoTomlPath = path49.join(baseDir, "Cargo.toml");
|
|
24693
24987
|
if (fs23.existsSync(cargoTomlPath)) {
|
|
24694
24988
|
const content = fs23.readFileSync(cargoTomlPath, "utf-8");
|
|
24695
24989
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -24700,9 +24994,9 @@ async function detectTestFramework(cwd) {
|
|
|
24700
24994
|
}
|
|
24701
24995
|
} catch {}
|
|
24702
24996
|
try {
|
|
24703
|
-
const pesterConfigPath =
|
|
24704
|
-
const pesterConfigJsonPath =
|
|
24705
|
-
const pesterPs1Path =
|
|
24997
|
+
const pesterConfigPath = path49.join(baseDir, "pester.config.ps1");
|
|
24998
|
+
const pesterConfigJsonPath = path49.join(baseDir, "pester.config.ps1.json");
|
|
24999
|
+
const pesterPs1Path = path49.join(baseDir, "tests.ps1");
|
|
24706
25000
|
if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
|
|
24707
25001
|
return "pester";
|
|
24708
25002
|
}
|
|
@@ -24745,12 +25039,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
24745
25039
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
24746
25040
|
}
|
|
24747
25041
|
function resolveWorkspacePath(file, workingDir) {
|
|
24748
|
-
return
|
|
25042
|
+
return path49.isAbsolute(file) ? path49.resolve(file) : path49.resolve(workingDir, file);
|
|
24749
25043
|
}
|
|
24750
25044
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
24751
25045
|
if (!preferRelative)
|
|
24752
25046
|
return absolutePath;
|
|
24753
|
-
return
|
|
25047
|
+
return path49.relative(workingDir, absolutePath);
|
|
24754
25048
|
}
|
|
24755
25049
|
function dedupePush(target, value) {
|
|
24756
25050
|
if (!target.includes(value)) {
|
|
@@ -24787,18 +25081,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
24787
25081
|
}
|
|
24788
25082
|
}
|
|
24789
25083
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
24790
|
-
const relativeDir =
|
|
25084
|
+
const relativeDir = path49.dirname(relativePath);
|
|
24791
25085
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
24792
25086
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
24793
|
-
const rootDir =
|
|
24794
|
-
return nestedRelativeDir ? [rootDir,
|
|
25087
|
+
const rootDir = path49.join(workingDir, dirName);
|
|
25088
|
+
return nestedRelativeDir ? [rootDir, path49.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
24795
25089
|
});
|
|
24796
25090
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
24797
25091
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
24798
|
-
directories.push(
|
|
25092
|
+
directories.push(path49.join(workingDir, "src/test/java", path49.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
24799
25093
|
}
|
|
24800
25094
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
24801
|
-
directories.push(
|
|
25095
|
+
directories.push(path49.join(workingDir, "src/test/kotlin", path49.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
24802
25096
|
}
|
|
24803
25097
|
return [...new Set(directories)];
|
|
24804
25098
|
}
|
|
@@ -24826,23 +25120,23 @@ function isLanguageSpecificTestFile(basename9) {
|
|
|
24826
25120
|
}
|
|
24827
25121
|
function isConventionTestFilePath(filePath) {
|
|
24828
25122
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
24829
|
-
const basename9 =
|
|
25123
|
+
const basename9 = path49.basename(filePath);
|
|
24830
25124
|
return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
|
|
24831
25125
|
}
|
|
24832
25126
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
24833
25127
|
const testFiles = [];
|
|
24834
25128
|
for (const file of sourceFiles) {
|
|
24835
25129
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
24836
|
-
const relativeFile =
|
|
24837
|
-
const basename9 =
|
|
24838
|
-
const dirname23 =
|
|
24839
|
-
const preferRelativeOutput = !
|
|
25130
|
+
const relativeFile = path49.relative(workingDir, absoluteFile);
|
|
25131
|
+
const basename9 = path49.basename(absoluteFile);
|
|
25132
|
+
const dirname23 = path49.dirname(absoluteFile);
|
|
25133
|
+
const preferRelativeOutput = !path49.isAbsolute(file);
|
|
24840
25134
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
24841
25135
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
24842
25136
|
continue;
|
|
24843
25137
|
}
|
|
24844
25138
|
const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
|
|
24845
|
-
const ext =
|
|
25139
|
+
const ext = path49.extname(basename9);
|
|
24846
25140
|
const genericTestNames = [
|
|
24847
25141
|
`${nameWithoutExt}.spec${ext}`,
|
|
24848
25142
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -24851,7 +25145,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
24851
25145
|
const colocatedCandidates = [
|
|
24852
25146
|
...genericTestNames,
|
|
24853
25147
|
...languageSpecificTestNames
|
|
24854
|
-
].map((candidateName) =>
|
|
25148
|
+
].map((candidateName) => path49.join(dirname23, candidateName));
|
|
24855
25149
|
const testDirectoryNames = [
|
|
24856
25150
|
basename9,
|
|
24857
25151
|
...genericTestNames,
|
|
@@ -24860,8 +25154,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
24860
25154
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
24861
25155
|
const possibleTestFiles = [
|
|
24862
25156
|
...colocatedCandidates,
|
|
24863
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
24864
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
25157
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path49.join(dirname23, dirName, candidateName))),
|
|
25158
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path49.join(candidateDir, candidateName)))
|
|
24865
25159
|
];
|
|
24866
25160
|
for (const testFile of possibleTestFiles) {
|
|
24867
25161
|
if (fs23.existsSync(testFile)) {
|
|
@@ -24882,7 +25176,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
24882
25176
|
try {
|
|
24883
25177
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
24884
25178
|
const content = fs23.readFileSync(absoluteTestFile, "utf-8");
|
|
24885
|
-
const testDir =
|
|
25179
|
+
const testDir = path49.dirname(absoluteTestFile);
|
|
24886
25180
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
24887
25181
|
let match;
|
|
24888
25182
|
match = importRegex.exec(content);
|
|
@@ -24890,8 +25184,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
24890
25184
|
const importPath = match[1];
|
|
24891
25185
|
let resolvedImport;
|
|
24892
25186
|
if (importPath.startsWith(".")) {
|
|
24893
|
-
resolvedImport =
|
|
24894
|
-
const existingExt =
|
|
25187
|
+
resolvedImport = path49.resolve(testDir, importPath);
|
|
25188
|
+
const existingExt = path49.extname(resolvedImport);
|
|
24895
25189
|
if (!existingExt) {
|
|
24896
25190
|
for (const extToTry of [
|
|
24897
25191
|
".ts",
|
|
@@ -24911,12 +25205,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
24911
25205
|
} else {
|
|
24912
25206
|
continue;
|
|
24913
25207
|
}
|
|
24914
|
-
const importBasename =
|
|
24915
|
-
const importDir =
|
|
25208
|
+
const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
|
|
25209
|
+
const importDir = path49.dirname(resolvedImport);
|
|
24916
25210
|
for (const sourceFile of absoluteSourceFiles) {
|
|
24917
|
-
const sourceDir =
|
|
24918
|
-
const sourceBasename =
|
|
24919
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
25211
|
+
const sourceDir = path49.dirname(sourceFile);
|
|
25212
|
+
const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
|
|
25213
|
+
const isRelatedDir = importDir === sourceDir || importDir === path49.join(sourceDir, "__tests__") || importDir === path49.join(sourceDir, "tests") || importDir === path49.join(sourceDir, "test") || importDir === path49.join(sourceDir, "spec");
|
|
24920
25214
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
24921
25215
|
dedupePush(testFiles, testFile);
|
|
24922
25216
|
break;
|
|
@@ -24929,8 +25223,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
24929
25223
|
while (match !== null) {
|
|
24930
25224
|
const importPath = match[1];
|
|
24931
25225
|
if (importPath.startsWith(".")) {
|
|
24932
|
-
let resolvedImport =
|
|
24933
|
-
const existingExt =
|
|
25226
|
+
let resolvedImport = path49.resolve(testDir, importPath);
|
|
25227
|
+
const existingExt = path49.extname(resolvedImport);
|
|
24934
25228
|
if (!existingExt) {
|
|
24935
25229
|
for (const extToTry of [
|
|
24936
25230
|
".ts",
|
|
@@ -24947,12 +25241,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
24947
25241
|
}
|
|
24948
25242
|
}
|
|
24949
25243
|
}
|
|
24950
|
-
const importDir =
|
|
24951
|
-
const importBasename =
|
|
25244
|
+
const importDir = path49.dirname(resolvedImport);
|
|
25245
|
+
const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
|
|
24952
25246
|
for (const sourceFile of absoluteSourceFiles) {
|
|
24953
|
-
const sourceDir =
|
|
24954
|
-
const sourceBasename =
|
|
24955
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
25247
|
+
const sourceDir = path49.dirname(sourceFile);
|
|
25248
|
+
const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
|
|
25249
|
+
const isRelatedDir = importDir === sourceDir || importDir === path49.join(sourceDir, "__tests__") || importDir === path49.join(sourceDir, "tests") || importDir === path49.join(sourceDir, "test") || importDir === path49.join(sourceDir, "spec");
|
|
24956
25250
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
24957
25251
|
dedupePush(testFiles, testFile);
|
|
24958
25252
|
break;
|
|
@@ -25072,8 +25366,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
25072
25366
|
return ["mvn", "test"];
|
|
25073
25367
|
case "gradle": {
|
|
25074
25368
|
const isWindows = process.platform === "win32";
|
|
25075
|
-
const hasGradlewBat = fs23.existsSync(
|
|
25076
|
-
const hasGradlew = fs23.existsSync(
|
|
25369
|
+
const hasGradlewBat = fs23.existsSync(path49.join(baseDir, "gradlew.bat"));
|
|
25370
|
+
const hasGradlew = fs23.existsSync(path49.join(baseDir, "gradlew"));
|
|
25077
25371
|
if (hasGradlewBat && isWindows)
|
|
25078
25372
|
return ["gradlew.bat", "test"];
|
|
25079
25373
|
if (hasGradlew)
|
|
@@ -25090,7 +25384,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
25090
25384
|
"cmake-build-release",
|
|
25091
25385
|
"out"
|
|
25092
25386
|
];
|
|
25093
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(
|
|
25387
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path49.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
25094
25388
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
25095
25389
|
}
|
|
25096
25390
|
case "swift-test":
|
|
@@ -25524,11 +25818,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
25524
25818
|
};
|
|
25525
25819
|
}
|
|
25526
25820
|
const startTime = Date.now();
|
|
25527
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
25821
|
+
const vitestJsonOutputPath = framework === "vitest" ? path49.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
25528
25822
|
try {
|
|
25529
25823
|
if (vitestJsonOutputPath) {
|
|
25530
25824
|
try {
|
|
25531
|
-
fs23.mkdirSync(
|
|
25825
|
+
fs23.mkdirSync(path49.dirname(vitestJsonOutputPath), { recursive: true });
|
|
25532
25826
|
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
25533
25827
|
fs23.unlinkSync(vitestJsonOutputPath);
|
|
25534
25828
|
}
|
|
@@ -25539,9 +25833,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
25539
25833
|
stderr: "pipe",
|
|
25540
25834
|
cwd
|
|
25541
25835
|
});
|
|
25542
|
-
const timeoutPromise = new Promise((
|
|
25836
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
|
|
25543
25837
|
proc.kill();
|
|
25544
|
-
|
|
25838
|
+
resolve16(-1);
|
|
25545
25839
|
}, timeout_ms));
|
|
25546
25840
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
25547
25841
|
Promise.race([proc.exited, timeoutPromise]),
|
|
@@ -25696,10 +25990,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
25696
25990
|
]);
|
|
25697
25991
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
25698
25992
|
const normalized = testFile.replace(/\\/g, "/");
|
|
25699
|
-
if (!
|
|
25993
|
+
if (!path49.isAbsolute(testFile))
|
|
25700
25994
|
return normalized;
|
|
25701
|
-
const relative8 =
|
|
25702
|
-
if (relative8.startsWith("..") ||
|
|
25995
|
+
const relative8 = path49.relative(workingDir, testFile);
|
|
25996
|
+
if (relative8.startsWith("..") || path49.isAbsolute(relative8)) {
|
|
25703
25997
|
return normalized;
|
|
25704
25998
|
}
|
|
25705
25999
|
return relative8.replace(/\\/g, "/");
|
|
@@ -25938,7 +26232,7 @@ var test_runner = createSwarmTool({
|
|
|
25938
26232
|
const sourceFiles = args.files.filter((file) => {
|
|
25939
26233
|
if (directTestFiles.includes(file))
|
|
25940
26234
|
return false;
|
|
25941
|
-
const ext =
|
|
26235
|
+
const ext = path49.extname(file).toLowerCase();
|
|
25942
26236
|
return SOURCE_EXTENSIONS.has(ext);
|
|
25943
26237
|
});
|
|
25944
26238
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -25984,7 +26278,7 @@ var test_runner = createSwarmTool({
|
|
|
25984
26278
|
if (isConventionTestFilePath(f)) {
|
|
25985
26279
|
return false;
|
|
25986
26280
|
}
|
|
25987
|
-
const ext =
|
|
26281
|
+
const ext = path49.extname(f).toLowerCase();
|
|
25988
26282
|
return SOURCE_EXTENSIONS.has(ext);
|
|
25989
26283
|
});
|
|
25990
26284
|
if (sourceFiles.length === 0) {
|
|
@@ -26034,7 +26328,7 @@ var test_runner = createSwarmTool({
|
|
|
26034
26328
|
if (isConventionTestFilePath(f)) {
|
|
26035
26329
|
return false;
|
|
26036
26330
|
}
|
|
26037
|
-
const ext =
|
|
26331
|
+
const ext = path49.extname(f).toLowerCase();
|
|
26038
26332
|
return SOURCE_EXTENSIONS.has(ext);
|
|
26039
26333
|
});
|
|
26040
26334
|
if (sourceFiles.length === 0) {
|
|
@@ -26086,8 +26380,8 @@ var test_runner = createSwarmTool({
|
|
|
26086
26380
|
}
|
|
26087
26381
|
if (impactResult.impactedTests.length > 0) {
|
|
26088
26382
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
26089
|
-
const relativePath =
|
|
26090
|
-
return
|
|
26383
|
+
const relativePath = path49.relative(workingDir, absPath);
|
|
26384
|
+
return path49.isAbsolute(relativePath) ? absPath : relativePath;
|
|
26091
26385
|
});
|
|
26092
26386
|
} else {
|
|
26093
26387
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -26182,8 +26476,8 @@ function validateDirectoryPath(dir) {
|
|
|
26182
26476
|
if (dir.includes("..")) {
|
|
26183
26477
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
26184
26478
|
}
|
|
26185
|
-
const normalized =
|
|
26186
|
-
const absolutePath =
|
|
26479
|
+
const normalized = path50.normalize(dir);
|
|
26480
|
+
const absolutePath = path50.isAbsolute(normalized) ? normalized : path50.resolve(normalized);
|
|
26187
26481
|
return absolutePath;
|
|
26188
26482
|
}
|
|
26189
26483
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -26206,7 +26500,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
26206
26500
|
}
|
|
26207
26501
|
function getPackageVersion(dir) {
|
|
26208
26502
|
try {
|
|
26209
|
-
const packagePath =
|
|
26503
|
+
const packagePath = path50.join(dir, "package.json");
|
|
26210
26504
|
if (fs24.existsSync(packagePath)) {
|
|
26211
26505
|
const content = fs24.readFileSync(packagePath, "utf-8");
|
|
26212
26506
|
const pkg = JSON.parse(content);
|
|
@@ -26217,7 +26511,7 @@ function getPackageVersion(dir) {
|
|
|
26217
26511
|
}
|
|
26218
26512
|
function getChangelogVersion(dir) {
|
|
26219
26513
|
try {
|
|
26220
|
-
const changelogPath =
|
|
26514
|
+
const changelogPath = path50.join(dir, "CHANGELOG.md");
|
|
26221
26515
|
if (fs24.existsSync(changelogPath)) {
|
|
26222
26516
|
const content = fs24.readFileSync(changelogPath, "utf-8");
|
|
26223
26517
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -26231,7 +26525,7 @@ function getChangelogVersion(dir) {
|
|
|
26231
26525
|
function getVersionFileVersion(dir) {
|
|
26232
26526
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
26233
26527
|
for (const file of possibleFiles) {
|
|
26234
|
-
const filePath =
|
|
26528
|
+
const filePath = path50.join(dir, file);
|
|
26235
26529
|
if (fs24.existsSync(filePath)) {
|
|
26236
26530
|
try {
|
|
26237
26531
|
const content = fs24.readFileSync(filePath, "utf-8").trim();
|
|
@@ -26969,7 +27263,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
26969
27263
|
|
|
26970
27264
|
// src/commands/reset.ts
|
|
26971
27265
|
import * as fs25 from "fs";
|
|
26972
|
-
import * as
|
|
27266
|
+
import * as path51 from "path";
|
|
26973
27267
|
|
|
26974
27268
|
// src/background/circuit-breaker.ts
|
|
26975
27269
|
class CircuitBreaker {
|
|
@@ -27021,13 +27315,13 @@ class CircuitBreaker {
|
|
|
27021
27315
|
if (this.config.callTimeoutMs <= 0) {
|
|
27022
27316
|
return fn();
|
|
27023
27317
|
}
|
|
27024
|
-
return new Promise((
|
|
27318
|
+
return new Promise((resolve17, reject) => {
|
|
27025
27319
|
const timeout = setTimeout(() => {
|
|
27026
27320
|
reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
|
|
27027
27321
|
}, this.config.callTimeoutMs);
|
|
27028
27322
|
fn().then((result) => {
|
|
27029
27323
|
clearTimeout(timeout);
|
|
27030
|
-
|
|
27324
|
+
resolve17(result);
|
|
27031
27325
|
}).catch((error2) => {
|
|
27032
27326
|
clearTimeout(timeout);
|
|
27033
27327
|
reject(error2);
|
|
@@ -27311,7 +27605,7 @@ class AutomationQueue {
|
|
|
27311
27605
|
|
|
27312
27606
|
// src/background/worker.ts
|
|
27313
27607
|
function sleep(ms) {
|
|
27314
|
-
return new Promise((
|
|
27608
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
27315
27609
|
}
|
|
27316
27610
|
|
|
27317
27611
|
class WorkerManager {
|
|
@@ -27686,7 +27980,7 @@ async function handleResetCommand(directory, args) {
|
|
|
27686
27980
|
}
|
|
27687
27981
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
27688
27982
|
try {
|
|
27689
|
-
const rootPath =
|
|
27983
|
+
const rootPath = path51.join(directory, filename);
|
|
27690
27984
|
if (fs25.existsSync(rootPath)) {
|
|
27691
27985
|
fs25.unlinkSync(rootPath);
|
|
27692
27986
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -27724,7 +28018,7 @@ async function handleResetCommand(directory, args) {
|
|
|
27724
28018
|
|
|
27725
28019
|
// src/commands/reset-session.ts
|
|
27726
28020
|
import * as fs27 from "fs";
|
|
27727
|
-
import * as
|
|
28021
|
+
import * as path53 from "path";
|
|
27728
28022
|
|
|
27729
28023
|
// src/hooks/trajectory-logger.ts
|
|
27730
28024
|
var callStartTimes = new Map;
|
|
@@ -28131,16 +28425,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
28131
28425
|
}
|
|
28132
28426
|
// src/prm/replay.ts
|
|
28133
28427
|
import { promises as fs26 } from "fs";
|
|
28134
|
-
import
|
|
28428
|
+
import path52 from "path";
|
|
28135
28429
|
function isPathSafe(targetPath, basePath) {
|
|
28136
|
-
const resolvedTarget =
|
|
28137
|
-
const resolvedBase =
|
|
28138
|
-
const rel =
|
|
28139
|
-
return !rel.startsWith("..") && !
|
|
28430
|
+
const resolvedTarget = path52.resolve(targetPath);
|
|
28431
|
+
const resolvedBase = path52.resolve(basePath);
|
|
28432
|
+
const rel = path52.relative(resolvedBase, resolvedTarget);
|
|
28433
|
+
return !rel.startsWith("..") && !path52.isAbsolute(rel);
|
|
28140
28434
|
}
|
|
28141
28435
|
function isWithinReplaysDir(targetPath) {
|
|
28142
|
-
const resolved =
|
|
28143
|
-
const parts = resolved.split(
|
|
28436
|
+
const resolved = path52.resolve(targetPath);
|
|
28437
|
+
const parts = resolved.split(path52.sep);
|
|
28144
28438
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
28145
28439
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
28146
28440
|
return true;
|
|
@@ -28153,10 +28447,10 @@ function sanitizeFilename(input) {
|
|
|
28153
28447
|
}
|
|
28154
28448
|
async function startReplayRecording(sessionID, directory) {
|
|
28155
28449
|
try {
|
|
28156
|
-
const replayDir =
|
|
28450
|
+
const replayDir = path52.join(directory, ".swarm", "replays");
|
|
28157
28451
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
28158
28452
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
28159
|
-
const filepath =
|
|
28453
|
+
const filepath = path52.join(replayDir, filename);
|
|
28160
28454
|
if (!isPathSafe(filepath, replayDir)) {
|
|
28161
28455
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
28162
28456
|
return null;
|
|
@@ -28234,7 +28528,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
28234
28528
|
} catch {
|
|
28235
28529
|
results.push("\u274C Failed to delete state.json");
|
|
28236
28530
|
}
|
|
28237
|
-
const sessionDir =
|
|
28531
|
+
const sessionDir = path53.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
28238
28532
|
let sessionFiles = [];
|
|
28239
28533
|
if (fs27.existsSync(sessionDir)) {
|
|
28240
28534
|
try {
|
|
@@ -28246,7 +28540,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
28246
28540
|
for (const file of sessionFiles) {
|
|
28247
28541
|
if (file === "state.json")
|
|
28248
28542
|
continue;
|
|
28249
|
-
const filePath =
|
|
28543
|
+
const filePath = path53.join(sessionDir, file);
|
|
28250
28544
|
try {
|
|
28251
28545
|
if (!fs27.existsSync(filePath))
|
|
28252
28546
|
continue;
|
|
@@ -28281,7 +28575,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
28281
28575
|
}
|
|
28282
28576
|
|
|
28283
28577
|
// src/summaries/manager.ts
|
|
28284
|
-
import * as
|
|
28578
|
+
import * as path54 from "path";
|
|
28285
28579
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
28286
28580
|
function sanitizeSummaryId(id) {
|
|
28287
28581
|
if (!id || id.length === 0) {
|
|
@@ -28305,7 +28599,7 @@ function sanitizeSummaryId(id) {
|
|
|
28305
28599
|
}
|
|
28306
28600
|
async function loadFullOutput(directory, id) {
|
|
28307
28601
|
const sanitizedId = sanitizeSummaryId(id);
|
|
28308
|
-
const relativePath =
|
|
28602
|
+
const relativePath = path54.join("summaries", `${sanitizedId}.json`);
|
|
28309
28603
|
validateSwarmPath(directory, relativePath);
|
|
28310
28604
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
28311
28605
|
if (content === null) {
|
|
@@ -28358,7 +28652,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
28358
28652
|
|
|
28359
28653
|
// src/commands/rollback.ts
|
|
28360
28654
|
import * as fs28 from "fs";
|
|
28361
|
-
import * as
|
|
28655
|
+
import * as path55 from "path";
|
|
28362
28656
|
async function handleRollbackCommand(directory, args) {
|
|
28363
28657
|
const phaseArg = args[0];
|
|
28364
28658
|
if (!phaseArg) {
|
|
@@ -28424,8 +28718,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28424
28718
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
28425
28719
|
continue;
|
|
28426
28720
|
}
|
|
28427
|
-
const src =
|
|
28428
|
-
const dest =
|
|
28721
|
+
const src = path55.join(checkpointDir, file);
|
|
28722
|
+
const dest = path55.join(swarmDir, file);
|
|
28429
28723
|
try {
|
|
28430
28724
|
fs28.cpSync(src, dest, { recursive: true, force: true });
|
|
28431
28725
|
successes.push(file);
|
|
@@ -28444,7 +28738,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28444
28738
|
].join(`
|
|
28445
28739
|
`);
|
|
28446
28740
|
}
|
|
28447
|
-
const existingLedgerPath =
|
|
28741
|
+
const existingLedgerPath = path55.join(swarmDir, "plan-ledger.jsonl");
|
|
28448
28742
|
let ledgerDeletionFailed = false;
|
|
28449
28743
|
if (fs28.existsSync(existingLedgerPath)) {
|
|
28450
28744
|
try {
|
|
@@ -28457,7 +28751,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28457
28751
|
}
|
|
28458
28752
|
if (!ledgerDeletionFailed) {
|
|
28459
28753
|
try {
|
|
28460
|
-
const planJsonPath =
|
|
28754
|
+
const planJsonPath = path55.join(swarmDir, "plan.json");
|
|
28461
28755
|
if (fs28.existsSync(planJsonPath)) {
|
|
28462
28756
|
const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
|
|
28463
28757
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -28718,10 +29012,10 @@ Ensure this is a git repository with commit history.`;
|
|
|
28718
29012
|
`);
|
|
28719
29013
|
try {
|
|
28720
29014
|
const fs29 = await import("fs/promises");
|
|
28721
|
-
const
|
|
28722
|
-
const reportPath =
|
|
28723
|
-
await fs29.mkdir(
|
|
28724
|
-
const reportTempPath =
|
|
29015
|
+
const path56 = await import("path");
|
|
29016
|
+
const reportPath = path56.join(directory, ".swarm", "simulate-report.md");
|
|
29017
|
+
await fs29.mkdir(path56.dirname(reportPath), { recursive: true });
|
|
29018
|
+
const reportTempPath = path56.join(path56.dirname(reportPath), `${path56.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
28725
29019
|
try {
|
|
28726
29020
|
await fs29.writeFile(reportTempPath, report, "utf-8");
|
|
28727
29021
|
renameSync11(reportTempPath, reportPath);
|
|
@@ -28750,18 +29044,18 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
28750
29044
|
// src/services/status-service.ts
|
|
28751
29045
|
import * as fsSync3 from "fs";
|
|
28752
29046
|
import { readFile as readFile15 } from "fs/promises";
|
|
28753
|
-
import * as
|
|
29047
|
+
import * as path57 from "path";
|
|
28754
29048
|
|
|
28755
29049
|
// src/turbo/lean/state.ts
|
|
28756
29050
|
init_logger();
|
|
28757
29051
|
import * as fs29 from "fs";
|
|
28758
|
-
import * as
|
|
29052
|
+
import * as path56 from "path";
|
|
28759
29053
|
var STATE_FILE3 = "turbo-state.json";
|
|
28760
29054
|
function nowISO3() {
|
|
28761
29055
|
return new Date().toISOString();
|
|
28762
29056
|
}
|
|
28763
29057
|
function ensureSwarmDir2(directory) {
|
|
28764
|
-
const swarmDir =
|
|
29058
|
+
const swarmDir = path56.resolve(directory, ".swarm");
|
|
28765
29059
|
if (!fs29.existsSync(swarmDir)) {
|
|
28766
29060
|
fs29.mkdirSync(swarmDir, { recursive: true });
|
|
28767
29061
|
}
|
|
@@ -28806,7 +29100,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
28806
29100
|
}
|
|
28807
29101
|
function readPersisted2(directory) {
|
|
28808
29102
|
try {
|
|
28809
|
-
const filePath =
|
|
29103
|
+
const filePath = path56.join(directory, ".swarm", STATE_FILE3);
|
|
28810
29104
|
if (!fs29.existsSync(filePath)) {
|
|
28811
29105
|
const seed = emptyPersisted2();
|
|
28812
29106
|
try {
|
|
@@ -28842,7 +29136,7 @@ function writePersisted2(directory, persisted) {
|
|
|
28842
29136
|
let payload;
|
|
28843
29137
|
try {
|
|
28844
29138
|
ensureSwarmDir2(directory);
|
|
28845
|
-
filePath =
|
|
29139
|
+
filePath = path56.join(directory, ".swarm", STATE_FILE3);
|
|
28846
29140
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
28847
29141
|
persisted.updatedAt = nowISO3();
|
|
28848
29142
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -28960,7 +29254,7 @@ var _internals43 = {
|
|
|
28960
29254
|
};
|
|
28961
29255
|
function readSpecStalenessSnapshot(directory) {
|
|
28962
29256
|
try {
|
|
28963
|
-
const p =
|
|
29257
|
+
const p = path57.join(directory, ".swarm", "spec-staleness.json");
|
|
28964
29258
|
if (!fsSync3.existsSync(p))
|
|
28965
29259
|
return { stale: false };
|
|
28966
29260
|
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
@@ -29627,7 +29921,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
29627
29921
|
async function handleHelpCommand(ctx) {
|
|
29628
29922
|
const targetCommand = ctx.args.join(" ");
|
|
29629
29923
|
if (!targetCommand) {
|
|
29630
|
-
const { buildHelpText } = await import("./index-
|
|
29924
|
+
const { buildHelpText } = await import("./index-sr7g2msm.js");
|
|
29631
29925
|
return buildHelpText();
|
|
29632
29926
|
}
|
|
29633
29927
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -29636,7 +29930,7 @@ async function handleHelpCommand(ctx) {
|
|
|
29636
29930
|
return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
|
|
29637
29931
|
}
|
|
29638
29932
|
const similar = _internals45.findSimilarCommands(targetCommand);
|
|
29639
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
29933
|
+
const { buildHelpText: fullHelp } = await import("./index-sr7g2msm.js");
|
|
29640
29934
|
if (similar.length > 0) {
|
|
29641
29935
|
return `Command '/swarm ${targetCommand}' not found.
|
|
29642
29936
|
|
|
@@ -29769,7 +30063,7 @@ var COMMAND_REGISTRY = {
|
|
|
29769
30063
|
},
|
|
29770
30064
|
"guardrail explain": {
|
|
29771
30065
|
handler: async (ctx) => {
|
|
29772
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
30066
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-995zavv8.js");
|
|
29773
30067
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
29774
30068
|
},
|
|
29775
30069
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -30509,24 +30803,24 @@ function validateAliases() {
|
|
|
30509
30803
|
}
|
|
30510
30804
|
aliasTargets.get(target).push(name);
|
|
30511
30805
|
const visited = new Set;
|
|
30512
|
-
const
|
|
30806
|
+
const path58 = [];
|
|
30513
30807
|
let current = target;
|
|
30514
30808
|
while (current) {
|
|
30515
30809
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
30516
30810
|
if (!currentEntry)
|
|
30517
30811
|
break;
|
|
30518
30812
|
if (visited.has(current)) {
|
|
30519
|
-
const cycleStart =
|
|
30813
|
+
const cycleStart = path58.indexOf(current);
|
|
30520
30814
|
const fullChain = [
|
|
30521
30815
|
name,
|
|
30522
|
-
...
|
|
30816
|
+
...path58.slice(0, cycleStart > 0 ? cycleStart : path58.length),
|
|
30523
30817
|
current
|
|
30524
30818
|
].join(" \u2192 ");
|
|
30525
30819
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
30526
30820
|
break;
|
|
30527
30821
|
}
|
|
30528
30822
|
visited.add(current);
|
|
30529
|
-
|
|
30823
|
+
path58.push(current);
|
|
30530
30824
|
current = currentEntry.aliasOf || "";
|
|
30531
30825
|
}
|
|
30532
30826
|
}
|