opencode-swarm 7.39.0 → 7.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/explorer.d.ts +2 -2
- package/dist/cli/index.js +639 -16
- package/dist/commands/memory.d.ts +4 -0
- package/dist/commands/registry.d.ts +28 -0
- package/dist/commands/tool-policy.d.ts +1 -1
- package/dist/config/schema.d.ts +8 -0
- package/dist/evidence/documents.d.ts +31 -0
- package/dist/evidence/index.d.ts +1 -0
- package/dist/index.js +792 -47
- package/dist/memory/config.d.ts +4 -0
- package/dist/memory/curator-decision-helpers.d.ts +2 -0
- package/dist/memory/index.d.ts +2 -1
- package/dist/memory/local-jsonl-provider.d.ts +3 -1
- package/dist/memory/maintenance.d.ts +47 -0
- package/dist/memory/provider.d.ts +16 -0
- package/dist/memory/sqlite-provider.d.ts +3 -1
- package/dist/memory/types.d.ts +1 -0
- package/dist/tools/web-search.d.ts +4 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.
|
|
37
|
+
version: "7.41.0",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -17643,6 +17643,13 @@ var init_schema = __esm(() => {
|
|
|
17643
17643
|
redaction: exports_external.object({
|
|
17644
17644
|
rejectDurableSecrets: exports_external.boolean().default(true)
|
|
17645
17645
|
}).default({ rejectDurableSecrets: true }),
|
|
17646
|
+
maintenance: exports_external.object({
|
|
17647
|
+
lowUtilityMaxConfidence: exports_external.number().min(0).max(1).default(0.45),
|
|
17648
|
+
lowUtilityMinAgeDays: exports_external.number().int().min(1).max(3650).default(30)
|
|
17649
|
+
}).default({
|
|
17650
|
+
lowUtilityMaxConfidence: 0.45,
|
|
17651
|
+
lowUtilityMinAgeDays: 30
|
|
17652
|
+
}),
|
|
17646
17653
|
hardDelete: exports_external.boolean().default(false)
|
|
17647
17654
|
});
|
|
17648
17655
|
CuratorConfigSchema = exports_external.object({
|
|
@@ -45408,6 +45415,10 @@ function resolveMemoryConfig(input) {
|
|
|
45408
45415
|
redaction: {
|
|
45409
45416
|
...DEFAULT_MEMORY_CONFIG.redaction,
|
|
45410
45417
|
...input?.redaction ?? {}
|
|
45418
|
+
},
|
|
45419
|
+
maintenance: {
|
|
45420
|
+
...DEFAULT_MEMORY_CONFIG.maintenance,
|
|
45421
|
+
...input?.maintenance ?? {}
|
|
45411
45422
|
}
|
|
45412
45423
|
};
|
|
45413
45424
|
}
|
|
@@ -45439,6 +45450,10 @@ var init_config3 = __esm(() => {
|
|
|
45439
45450
|
redaction: {
|
|
45440
45451
|
rejectDurableSecrets: true
|
|
45441
45452
|
},
|
|
45453
|
+
maintenance: {
|
|
45454
|
+
lowUtilityMaxConfidence: 0.45,
|
|
45455
|
+
lowUtilityMinAgeDays: 30
|
|
45456
|
+
},
|
|
45442
45457
|
hardDelete: false
|
|
45443
45458
|
};
|
|
45444
45459
|
DURABLE_MEMORY_KINDS = new Set([
|
|
@@ -45760,6 +45775,17 @@ function validateDecisionMatchesProposal(decision, proposal) {
|
|
|
45760
45775
|
throw new MemoryValidationError("curator supersede decision target does not match proposal target");
|
|
45761
45776
|
}
|
|
45762
45777
|
}
|
|
45778
|
+
function validateCuratorPromotableMemory(record3) {
|
|
45779
|
+
if (record3.stability !== "durable") {
|
|
45780
|
+
throw new MemoryValidationError("curator memory promotions must be durable facts");
|
|
45781
|
+
}
|
|
45782
|
+
if (!DURABLE_MEMORY_KINDS.has(record3.kind)) {
|
|
45783
|
+
throw new MemoryValidationError("curator memory promotions must use durable fact kinds; store raw docs, search results, and other bulky source material as evidence records instead");
|
|
45784
|
+
}
|
|
45785
|
+
if (normalizeMemoryText(record3.text).length > CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH) {
|
|
45786
|
+
throw new MemoryValidationError(`curator memory promotions must be concise durable facts under ${CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH} characters`);
|
|
45787
|
+
}
|
|
45788
|
+
}
|
|
45763
45789
|
function applyPatchToMemory(existing, patch, updatedAt) {
|
|
45764
45790
|
const base = {
|
|
45765
45791
|
scope: patch.scope ?? existing.scope,
|
|
@@ -45817,11 +45843,174 @@ function buildCuratorDecisionEvent(change, proposal) {
|
|
|
45817
45843
|
function normalizeTags(tags) {
|
|
45818
45844
|
return Array.from(new Set(tags.map((tag) => tag.toLowerCase().replace(/[^\w-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")).filter(Boolean))).slice(0, 32);
|
|
45819
45845
|
}
|
|
45846
|
+
var CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH = 500;
|
|
45820
45847
|
var init_curator_decision_helpers = __esm(() => {
|
|
45848
|
+
init_config3();
|
|
45821
45849
|
init_errors6();
|
|
45822
45850
|
init_schema2();
|
|
45823
45851
|
});
|
|
45824
45852
|
|
|
45853
|
+
// src/memory/maintenance.ts
|
|
45854
|
+
async function buildMemoryMaintenanceReport(provider, options = {}) {
|
|
45855
|
+
const now = options.now ?? new Date;
|
|
45856
|
+
const limit = Math.max(1, Math.trunc(options.limit ?? 20));
|
|
45857
|
+
const memories = await provider.list({
|
|
45858
|
+
includeExpired: true,
|
|
45859
|
+
includeInactive: true
|
|
45860
|
+
});
|
|
45861
|
+
const proposals = await loadMaintenanceProposals(provider, limit);
|
|
45862
|
+
const recallUsage = provider.listRecallUsage ? await provider.listRecallUsage() : [];
|
|
45863
|
+
const usageByMemory = summarizeRecallByMemory(recallUsage);
|
|
45864
|
+
const usageByRole = summarizeRecallByRole(recallUsage);
|
|
45865
|
+
const activeMemories = memories.filter((memory) => isActiveMemory(memory, now));
|
|
45866
|
+
const deletedMemories = memories.filter((memory) => memory.metadata.deleted === true);
|
|
45867
|
+
const expiredScratchMemories = memories.filter((memory) => memory.kind === "scratch" && isExpired(memory, now));
|
|
45868
|
+
const supersededMemories = memories.filter((memory) => Boolean(memory.supersededBy));
|
|
45869
|
+
const lowUtilityMemories = activeMemories.filter((memory) => isLowUtility(memory, usageByMemory, now, {
|
|
45870
|
+
maxConfidence: options.lowUtilityMaxConfidence ?? DEFAULT_LOW_UTILITY_MAX_CONFIDENCE,
|
|
45871
|
+
minAgeDays: options.lowUtilityMinAgeDays ?? DEFAULT_LOW_UTILITY_MIN_AGE_DAYS
|
|
45872
|
+
})).sort(memorySort);
|
|
45873
|
+
const neverRecalledMemories = activeMemories.filter((memory) => !usageByMemory.has(memory.id)).sort(memorySort);
|
|
45874
|
+
const rejectedProposalReasons = proposals.filter((proposal) => proposal.status === "rejected").sort(proposalSort);
|
|
45875
|
+
const pendingProposals = proposals.filter((proposal) => proposal.status === "pending").sort(proposalSort);
|
|
45876
|
+
return {
|
|
45877
|
+
generatedAt: now.toISOString(),
|
|
45878
|
+
totalMemories: memories.length,
|
|
45879
|
+
activeMemories: activeMemories.length,
|
|
45880
|
+
deletedMemories: deletedMemories.slice(0, limit),
|
|
45881
|
+
expiredScratchMemories: expiredScratchMemories.slice(0, limit),
|
|
45882
|
+
supersededMemories: supersededMemories.slice(0, limit),
|
|
45883
|
+
supersededChains: buildSupersededChains(memories).slice(0, limit),
|
|
45884
|
+
lowUtilityMemories: lowUtilityMemories.slice(0, limit),
|
|
45885
|
+
neverRecalledMemories: neverRecalledMemories.slice(0, limit),
|
|
45886
|
+
mostRecalledMemories: Array.from(usageByMemory.values()).sort((a, b) => b.count - a.count || b.lastRecalledAt.localeCompare(a.lastRecalledAt) || a.memoryId.localeCompare(b.memoryId)).slice(0, limit),
|
|
45887
|
+
recallByAgentRole: Array.from(usageByRole.values()).sort((a, b) => b.count - a.count || a.agentRole.localeCompare(b.agentRole)).slice(0, limit),
|
|
45888
|
+
rejectedProposalReasons: rejectedProposalReasons.slice(0, limit),
|
|
45889
|
+
pendingProposals: pendingProposals.slice(0, limit),
|
|
45890
|
+
recallEventCount: recallUsage.length
|
|
45891
|
+
};
|
|
45892
|
+
}
|
|
45893
|
+
function shouldCompactMemory(memory, now = new Date) {
|
|
45894
|
+
if (memory.metadata.deleted === true)
|
|
45895
|
+
return "deleted";
|
|
45896
|
+
if (memory.supersededBy)
|
|
45897
|
+
return "superseded";
|
|
45898
|
+
if (memory.kind === "scratch" && isExpired(memory, now)) {
|
|
45899
|
+
return "expired_scratch";
|
|
45900
|
+
}
|
|
45901
|
+
return null;
|
|
45902
|
+
}
|
|
45903
|
+
function isActiveMemory(memory, now) {
|
|
45904
|
+
return memory.metadata.deleted !== true && !memory.supersededBy && !isExpired(memory, now);
|
|
45905
|
+
}
|
|
45906
|
+
function isLowUtility(memory, usageByMemory, now, options) {
|
|
45907
|
+
if (usageByMemory.has(memory.id))
|
|
45908
|
+
return false;
|
|
45909
|
+
const updated = Date.parse(memory.updatedAt);
|
|
45910
|
+
const ageDays = Number.isFinite(updated) ? (now.getTime() - updated) / (24 * 60 * 60 * 1000) : 0;
|
|
45911
|
+
return memory.confidence <= options.maxConfidence || ageDays >= options.minAgeDays;
|
|
45912
|
+
}
|
|
45913
|
+
function summarizeRecallByMemory(usageEvents) {
|
|
45914
|
+
const byMemory = new Map;
|
|
45915
|
+
for (const event of usageEvents) {
|
|
45916
|
+
event.memoryIds.forEach((memoryId, index) => {
|
|
45917
|
+
const role = event.agentRole ?? "unknown";
|
|
45918
|
+
const existing = byMemory.get(memoryId) ?? {
|
|
45919
|
+
memoryId,
|
|
45920
|
+
count: 0,
|
|
45921
|
+
lastRecalledAt: event.timestamp,
|
|
45922
|
+
agentRoles: {},
|
|
45923
|
+
averageScore: 0,
|
|
45924
|
+
scoreTotal: 0,
|
|
45925
|
+
scoreCount: 0
|
|
45926
|
+
};
|
|
45927
|
+
existing.count++;
|
|
45928
|
+
existing.lastRecalledAt = event.timestamp > existing.lastRecalledAt ? event.timestamp : existing.lastRecalledAt;
|
|
45929
|
+
existing.agentRoles[role] = (existing.agentRoles[role] ?? 0) + 1;
|
|
45930
|
+
const score = event.scores[index];
|
|
45931
|
+
if (typeof score === "number" && Number.isFinite(score)) {
|
|
45932
|
+
existing.scoreTotal += score;
|
|
45933
|
+
existing.scoreCount++;
|
|
45934
|
+
existing.averageScore = existing.scoreTotal / existing.scoreCount;
|
|
45935
|
+
}
|
|
45936
|
+
byMemory.set(memoryId, existing);
|
|
45937
|
+
});
|
|
45938
|
+
}
|
|
45939
|
+
return new Map(Array.from(byMemory, ([memoryId, value]) => [
|
|
45940
|
+
memoryId,
|
|
45941
|
+
{
|
|
45942
|
+
memoryId,
|
|
45943
|
+
count: value.count,
|
|
45944
|
+
lastRecalledAt: value.lastRecalledAt,
|
|
45945
|
+
agentRoles: value.agentRoles,
|
|
45946
|
+
averageScore: value.averageScore
|
|
45947
|
+
}
|
|
45948
|
+
]));
|
|
45949
|
+
}
|
|
45950
|
+
async function loadMaintenanceProposals(provider, limit) {
|
|
45951
|
+
if (!provider.listProposals)
|
|
45952
|
+
return [];
|
|
45953
|
+
const [pending, rejected, recent] = await Promise.all([
|
|
45954
|
+
provider.listProposals({ status: "pending", limit }),
|
|
45955
|
+
provider.listProposals({ status: "rejected", limit }),
|
|
45956
|
+
provider.listProposals({ limit: Math.max(limit * 4, 100) })
|
|
45957
|
+
]);
|
|
45958
|
+
const byId = new Map;
|
|
45959
|
+
for (const proposal of [...pending, ...rejected, ...recent]) {
|
|
45960
|
+
byId.set(proposal.id, proposal);
|
|
45961
|
+
}
|
|
45962
|
+
return Array.from(byId.values());
|
|
45963
|
+
}
|
|
45964
|
+
function summarizeRecallByRole(usageEvents) {
|
|
45965
|
+
const byRole = new Map;
|
|
45966
|
+
for (const event of usageEvents) {
|
|
45967
|
+
const role = event.agentRole ?? "unknown";
|
|
45968
|
+
const existing = byRole.get(role) ?? {
|
|
45969
|
+
agentRole: role,
|
|
45970
|
+
count: 0,
|
|
45971
|
+
memoryIds: {}
|
|
45972
|
+
};
|
|
45973
|
+
existing.count++;
|
|
45974
|
+
for (const memoryId of event.memoryIds) {
|
|
45975
|
+
existing.memoryIds[memoryId] = (existing.memoryIds[memoryId] ?? 0) + 1;
|
|
45976
|
+
}
|
|
45977
|
+
byRole.set(role, existing);
|
|
45978
|
+
}
|
|
45979
|
+
return byRole;
|
|
45980
|
+
}
|
|
45981
|
+
function buildSupersededChains(memories) {
|
|
45982
|
+
const byId = new Map(memories.map((memory) => [memory.id, memory]));
|
|
45983
|
+
const supersededIds = new Set(memories.filter((memory) => memory.supersededBy).map((memory) => memory.id));
|
|
45984
|
+
const roots = memories.filter((memory) => memory.supersededBy && !(memory.supersedes ?? []).some((id) => supersededIds.has(id)));
|
|
45985
|
+
return roots.map((root) => {
|
|
45986
|
+
const chain = [root.id];
|
|
45987
|
+
const seen = new Set(chain);
|
|
45988
|
+
let cursor = root;
|
|
45989
|
+
while (cursor?.supersededBy && !seen.has(cursor.supersededBy)) {
|
|
45990
|
+
chain.push(cursor.supersededBy);
|
|
45991
|
+
seen.add(cursor.supersededBy);
|
|
45992
|
+
cursor = byId.get(cursor.supersededBy);
|
|
45993
|
+
}
|
|
45994
|
+
return {
|
|
45995
|
+
rootId: root.id,
|
|
45996
|
+
chain,
|
|
45997
|
+
reason: typeof root.metadata.supersedeReason === "string" ? root.metadata.supersedeReason : undefined
|
|
45998
|
+
};
|
|
45999
|
+
});
|
|
46000
|
+
}
|
|
46001
|
+
function memorySort(a, b) {
|
|
46002
|
+
return b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id);
|
|
46003
|
+
}
|
|
46004
|
+
function proposalSort(a, b) {
|
|
46005
|
+
const aTime = a.reviewedAt ?? a.createdAt;
|
|
46006
|
+
const bTime = b.reviewedAt ?? b.createdAt;
|
|
46007
|
+
return bTime.localeCompare(aTime) || a.id.localeCompare(b.id);
|
|
46008
|
+
}
|
|
46009
|
+
var DEFAULT_LOW_UTILITY_MAX_CONFIDENCE = 0.45, DEFAULT_LOW_UTILITY_MIN_AGE_DAYS = 30;
|
|
46010
|
+
var init_maintenance = __esm(() => {
|
|
46011
|
+
init_schema2();
|
|
46012
|
+
});
|
|
46013
|
+
|
|
45825
46014
|
// src/memory/role-profiles.ts
|
|
45826
46015
|
function resolveMemoryRecallProfile(agentRole) {
|
|
45827
46016
|
const role = normalizeMemoryAgentRole(agentRole);
|
|
@@ -46209,16 +46398,21 @@ class LocalJsonlMemoryProvider {
|
|
|
46209
46398
|
}
|
|
46210
46399
|
async recordRecallUsage(event) {
|
|
46211
46400
|
await this.initialize();
|
|
46212
|
-
await this.audit("recall", event.bundleId,
|
|
46213
|
-
|
|
46214
|
-
|
|
46215
|
-
|
|
46216
|
-
|
|
46217
|
-
|
|
46218
|
-
|
|
46219
|
-
|
|
46220
|
-
|
|
46221
|
-
|
|
46401
|
+
await this.audit("recall", event.bundleId, undefined, event);
|
|
46402
|
+
}
|
|
46403
|
+
async listRecallUsage(filter = {}) {
|
|
46404
|
+
await this.initialize();
|
|
46405
|
+
const events = await readAuditEvents(this.pathFor("audit"));
|
|
46406
|
+
const usage = [];
|
|
46407
|
+
for (const event of events) {
|
|
46408
|
+
if (event.operation !== "recall")
|
|
46409
|
+
continue;
|
|
46410
|
+
const parsed = parseRecallUsageEvent(event);
|
|
46411
|
+
if (parsed)
|
|
46412
|
+
usage.push(parsed);
|
|
46413
|
+
}
|
|
46414
|
+
usage.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
46415
|
+
return usage.slice(0, filter.limit ?? usage.length);
|
|
46222
46416
|
}
|
|
46223
46417
|
async list(filter = {}) {
|
|
46224
46418
|
await this.initialize();
|
|
@@ -46238,7 +46432,9 @@ class LocalJsonlMemoryProvider {
|
|
|
46238
46432
|
return !Number.isFinite(expires) || expires > now;
|
|
46239
46433
|
});
|
|
46240
46434
|
}
|
|
46241
|
-
|
|
46435
|
+
if (!filter.includeInactive) {
|
|
46436
|
+
records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
|
|
46437
|
+
}
|
|
46242
46438
|
records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
46243
46439
|
return records.slice(0, filter.limit ?? records.length);
|
|
46244
46440
|
}
|
|
@@ -46279,12 +46475,14 @@ class LocalJsonlMemoryProvider {
|
|
|
46279
46475
|
...decision.memory,
|
|
46280
46476
|
updatedAt: appliedAt
|
|
46281
46477
|
});
|
|
46478
|
+
validateCuratorPromotableMemory(memory);
|
|
46282
46479
|
this.memories.set(memory.id, memory);
|
|
46283
46480
|
await appendJsonl(this.pathFor("memories"), memory);
|
|
46284
46481
|
memoryId = memory.id;
|
|
46285
46482
|
} else if (decision.action === "update") {
|
|
46286
46483
|
const existing = this.activeMemory(decision.targetMemoryId);
|
|
46287
46484
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
46485
|
+
validateCuratorPromotableMemory(updated);
|
|
46288
46486
|
if (updated.id !== existing.id) {
|
|
46289
46487
|
const tombstone = this.validateDecisionMemory({
|
|
46290
46488
|
...existing,
|
|
@@ -46310,6 +46508,7 @@ class LocalJsonlMemoryProvider {
|
|
|
46310
46508
|
updatedAt: appliedAt,
|
|
46311
46509
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
46312
46510
|
});
|
|
46511
|
+
validateCuratorPromotableMemory(replacement);
|
|
46313
46512
|
const superseded = this.validateDecisionMemory({
|
|
46314
46513
|
...oldMemory,
|
|
46315
46514
|
updatedAt: appliedAt,
|
|
@@ -46350,6 +46549,41 @@ class LocalJsonlMemoryProvider {
|
|
|
46350
46549
|
await writeJsonlAtomic(this.pathFor("memories"), Array.from(this.memories.values()));
|
|
46351
46550
|
await this.audit("compact", "memories");
|
|
46352
46551
|
}
|
|
46552
|
+
async compactMaintenance(options = {}) {
|
|
46553
|
+
await this.initialize();
|
|
46554
|
+
const now = options.now ? new Date(options.now) : new Date;
|
|
46555
|
+
const kept = [];
|
|
46556
|
+
const result = {
|
|
46557
|
+
dryRun: options.dryRun !== false,
|
|
46558
|
+
removedDeleted: 0,
|
|
46559
|
+
removedSuperseded: 0,
|
|
46560
|
+
removedExpiredScratch: 0,
|
|
46561
|
+
remaining: 0
|
|
46562
|
+
};
|
|
46563
|
+
for (const memory of this.memories.values()) {
|
|
46564
|
+
const compactReason = shouldCompactMemory(memory, now);
|
|
46565
|
+
if (compactReason === "deleted") {
|
|
46566
|
+
result.removedDeleted++;
|
|
46567
|
+
continue;
|
|
46568
|
+
}
|
|
46569
|
+
if (compactReason === "superseded") {
|
|
46570
|
+
result.removedSuperseded++;
|
|
46571
|
+
continue;
|
|
46572
|
+
}
|
|
46573
|
+
if (compactReason === "expired_scratch") {
|
|
46574
|
+
result.removedExpiredScratch++;
|
|
46575
|
+
continue;
|
|
46576
|
+
}
|
|
46577
|
+
kept.push(memory);
|
|
46578
|
+
}
|
|
46579
|
+
result.remaining = kept.length;
|
|
46580
|
+
if (result.dryRun)
|
|
46581
|
+
return result;
|
|
46582
|
+
this.memories = new Map(kept.map((memory) => [memory.id, memory]));
|
|
46583
|
+
await writeJsonlAtomic(this.pathFor("memories"), kept);
|
|
46584
|
+
await this.audit("compact", "memories", "removed deleted, superseded, and expired scratch memories", result);
|
|
46585
|
+
return result;
|
|
46586
|
+
}
|
|
46353
46587
|
async audit(operation, targetId, reason, eventJson) {
|
|
46354
46588
|
const event = {
|
|
46355
46589
|
id: randomUUID3(),
|
|
@@ -46428,6 +46662,46 @@ async function readJsonl(filePath) {
|
|
|
46428
46662
|
}
|
|
46429
46663
|
return records;
|
|
46430
46664
|
}
|
|
46665
|
+
async function readAuditEvents(filePath) {
|
|
46666
|
+
const values = await readJsonl(filePath);
|
|
46667
|
+
const events = [];
|
|
46668
|
+
for (const value of values) {
|
|
46669
|
+
if (!value || typeof value !== "object")
|
|
46670
|
+
continue;
|
|
46671
|
+
const candidate = value;
|
|
46672
|
+
if (typeof candidate.id !== "string" || typeof candidate.operation !== "string" || typeof candidate.targetId !== "string" || typeof candidate.timestamp !== "string") {
|
|
46673
|
+
continue;
|
|
46674
|
+
}
|
|
46675
|
+
events.push(candidate);
|
|
46676
|
+
}
|
|
46677
|
+
return events;
|
|
46678
|
+
}
|
|
46679
|
+
function parseRecallUsageEvent(event) {
|
|
46680
|
+
const raw = event.eventJson ?? event.reason;
|
|
46681
|
+
if (typeof raw !== "string" && (!raw || typeof raw !== "object")) {
|
|
46682
|
+
return null;
|
|
46683
|
+
}
|
|
46684
|
+
try {
|
|
46685
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
46686
|
+
if (!Array.isArray(parsed.memoryIds) || typeof parsed.query !== "string") {
|
|
46687
|
+
return null;
|
|
46688
|
+
}
|
|
46689
|
+
return {
|
|
46690
|
+
bundleId: typeof parsed.bundleId === "string" ? parsed.bundleId : event.targetId,
|
|
46691
|
+
query: parsed.query,
|
|
46692
|
+
scopes: Array.isArray(parsed.scopes) ? parsed.scopes : [],
|
|
46693
|
+
kinds: Array.isArray(parsed.kinds) ? parsed.kinds : undefined,
|
|
46694
|
+
memoryIds: parsed.memoryIds.filter((memoryId) => typeof memoryId === "string"),
|
|
46695
|
+
scores: Array.isArray(parsed.scores) ? parsed.scores.filter((score) => typeof score === "number" && Number.isFinite(score)) : [],
|
|
46696
|
+
tokenEstimate: typeof parsed.tokenEstimate === "number" ? parsed.tokenEstimate : 0,
|
|
46697
|
+
agentRole: typeof parsed.agentRole === "string" ? parsed.agentRole : undefined,
|
|
46698
|
+
runId: typeof parsed.runId === "string" ? parsed.runId : undefined,
|
|
46699
|
+
timestamp: typeof parsed.timestamp === "string" ? parsed.timestamp : event.timestamp
|
|
46700
|
+
};
|
|
46701
|
+
} catch {
|
|
46702
|
+
return null;
|
|
46703
|
+
}
|
|
46704
|
+
}
|
|
46431
46705
|
async function appendJsonl(filePath, value) {
|
|
46432
46706
|
await mkdir8(path29.dirname(filePath), { recursive: true });
|
|
46433
46707
|
await appendFile4(filePath, `${JSON.stringify(value)}
|
|
@@ -46447,6 +46721,7 @@ var init_local_jsonl_provider = __esm(() => {
|
|
|
46447
46721
|
init_config3();
|
|
46448
46722
|
init_curator_decision_helpers();
|
|
46449
46723
|
init_errors6();
|
|
46724
|
+
init_maintenance();
|
|
46450
46725
|
init_schema2();
|
|
46451
46726
|
init_scoring();
|
|
46452
46727
|
});
|
|
@@ -46704,6 +46979,10 @@ class SQLiteMemoryProvider {
|
|
|
46704
46979
|
redaction: {
|
|
46705
46980
|
...DEFAULT_MEMORY_CONFIG.redaction,
|
|
46706
46981
|
...config3.redaction ?? {}
|
|
46982
|
+
},
|
|
46983
|
+
maintenance: {
|
|
46984
|
+
...DEFAULT_MEMORY_CONFIG.maintenance,
|
|
46985
|
+
...config3.maintenance ?? {}
|
|
46707
46986
|
}
|
|
46708
46987
|
};
|
|
46709
46988
|
}
|
|
@@ -46809,6 +47088,26 @@ class SQLiteMemoryProvider {
|
|
|
46809
47088
|
) VALUES (?, ?, ?, ?)`, [randomUUID4(), event.bundleId, event.timestamp, JSON.stringify(event)]);
|
|
46810
47089
|
await this.event("recall", event.bundleId, JSON.stringify(event));
|
|
46811
47090
|
}
|
|
47091
|
+
async listRecallUsage(filter = {}) {
|
|
47092
|
+
await this.initialize();
|
|
47093
|
+
const rows = typeof filter.limit === "number" ? this.requireDb().query(`SELECT usage_json
|
|
47094
|
+
FROM memory_recall_usage
|
|
47095
|
+
ORDER BY timestamp DESC
|
|
47096
|
+
LIMIT ?`).all(Math.max(1, Math.trunc(filter.limit))) : this.requireDb().query(`SELECT usage_json
|
|
47097
|
+
FROM memory_recall_usage
|
|
47098
|
+
ORDER BY timestamp DESC
|
|
47099
|
+
`).all();
|
|
47100
|
+
const events = [];
|
|
47101
|
+
for (const row of rows) {
|
|
47102
|
+
try {
|
|
47103
|
+
const parsed = JSON.parse(row.usage_json);
|
|
47104
|
+
if (Array.isArray(parsed.memoryIds) && typeof parsed.query === "string") {
|
|
47105
|
+
events.push(parsed);
|
|
47106
|
+
}
|
|
47107
|
+
} catch {}
|
|
47108
|
+
}
|
|
47109
|
+
return events;
|
|
47110
|
+
}
|
|
46812
47111
|
async list(filter = {}) {
|
|
46813
47112
|
await this.initialize();
|
|
46814
47113
|
let records = Array.from(this.memories.values());
|
|
@@ -46827,7 +47126,9 @@ class SQLiteMemoryProvider {
|
|
|
46827
47126
|
return !Number.isFinite(expires) || expires > now;
|
|
46828
47127
|
});
|
|
46829
47128
|
}
|
|
46830
|
-
|
|
47129
|
+
if (!filter.includeInactive) {
|
|
47130
|
+
records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
|
|
47131
|
+
}
|
|
46831
47132
|
records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
46832
47133
|
return records.slice(0, filter.limit ?? records.length);
|
|
46833
47134
|
}
|
|
@@ -46908,6 +47209,52 @@ class SQLiteMemoryProvider {
|
|
|
46908
47209
|
proposals: proposals.length
|
|
46909
47210
|
};
|
|
46910
47211
|
}
|
|
47212
|
+
async compactMaintenance(options = {}) {
|
|
47213
|
+
await this.initialize();
|
|
47214
|
+
const now = options.now ? new Date(options.now) : new Date;
|
|
47215
|
+
const kept = [];
|
|
47216
|
+
const removeIds = [];
|
|
47217
|
+
const result = {
|
|
47218
|
+
dryRun: options.dryRun !== false,
|
|
47219
|
+
removedDeleted: 0,
|
|
47220
|
+
removedSuperseded: 0,
|
|
47221
|
+
removedExpiredScratch: 0,
|
|
47222
|
+
remaining: 0
|
|
47223
|
+
};
|
|
47224
|
+
for (const memory of this.memories.values()) {
|
|
47225
|
+
const compactReason = shouldCompactMemory(memory, now);
|
|
47226
|
+
if (compactReason === "deleted") {
|
|
47227
|
+
result.removedDeleted++;
|
|
47228
|
+
removeIds.push(memory.id);
|
|
47229
|
+
continue;
|
|
47230
|
+
}
|
|
47231
|
+
if (compactReason === "superseded") {
|
|
47232
|
+
result.removedSuperseded++;
|
|
47233
|
+
removeIds.push(memory.id);
|
|
47234
|
+
continue;
|
|
47235
|
+
}
|
|
47236
|
+
if (compactReason === "expired_scratch") {
|
|
47237
|
+
result.removedExpiredScratch++;
|
|
47238
|
+
removeIds.push(memory.id);
|
|
47239
|
+
continue;
|
|
47240
|
+
}
|
|
47241
|
+
kept.push(memory);
|
|
47242
|
+
}
|
|
47243
|
+
result.remaining = kept.length;
|
|
47244
|
+
if (result.dryRun)
|
|
47245
|
+
return result;
|
|
47246
|
+
const db = this.requireDb();
|
|
47247
|
+
const compact = db.transaction(() => {
|
|
47248
|
+
for (const id of removeIds) {
|
|
47249
|
+
db.run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
47250
|
+
this.deleteMemoryFts(id);
|
|
47251
|
+
}
|
|
47252
|
+
this.insertEvent("compact", "memory_items", "removed deleted, superseded, and expired scratch memories", JSON.stringify(result));
|
|
47253
|
+
});
|
|
47254
|
+
compact();
|
|
47255
|
+
this.memories = new Map(kept.map((memory) => [memory.id, memory]));
|
|
47256
|
+
return result;
|
|
47257
|
+
}
|
|
46911
47258
|
hasMigration(name) {
|
|
46912
47259
|
const row = this.requireDb().query("SELECT version, name FROM schema_migrations WHERE name = ? LIMIT 1").get(name);
|
|
46913
47260
|
return Boolean(row);
|
|
@@ -47141,12 +47488,14 @@ class SQLiteMemoryProvider {
|
|
|
47141
47488
|
...decision.memory,
|
|
47142
47489
|
updatedAt: appliedAt
|
|
47143
47490
|
});
|
|
47491
|
+
validateCuratorPromotableMemory(memory);
|
|
47144
47492
|
this.writeMemory(memory);
|
|
47145
47493
|
memories.push(memory);
|
|
47146
47494
|
memoryId = memory.id;
|
|
47147
47495
|
} else if (decision.action === "update") {
|
|
47148
47496
|
const existing = this.readActiveMemory(decision.targetMemoryId);
|
|
47149
47497
|
const updated = this.validateDecisionMemory(applyPatchToMemory(existing, decision.patch, appliedAt));
|
|
47498
|
+
validateCuratorPromotableMemory(updated);
|
|
47150
47499
|
if (updated.id !== existing.id) {
|
|
47151
47500
|
const tombstone = this.validateDecisionMemory({
|
|
47152
47501
|
...existing,
|
|
@@ -47172,6 +47521,7 @@ class SQLiteMemoryProvider {
|
|
|
47172
47521
|
updatedAt: appliedAt,
|
|
47173
47522
|
supersedes: Array.from(new Set([...decision.replacement.supersedes ?? [], oldMemory.id]))
|
|
47174
47523
|
});
|
|
47524
|
+
validateCuratorPromotableMemory(replacement);
|
|
47175
47525
|
const superseded = this.validateDecisionMemory({
|
|
47176
47526
|
...oldMemory,
|
|
47177
47527
|
updatedAt: appliedAt,
|
|
@@ -47384,6 +47734,7 @@ var init_sqlite_provider = __esm(() => {
|
|
|
47384
47734
|
init_curator_decision_helpers();
|
|
47385
47735
|
init_errors6();
|
|
47386
47736
|
init_jsonl_migration();
|
|
47737
|
+
init_maintenance();
|
|
47387
47738
|
init_schema2();
|
|
47388
47739
|
init_scoring();
|
|
47389
47740
|
FTS_INDEX_COLUMNS = [
|
|
@@ -47911,6 +48262,7 @@ var init_memory = __esm(() => {
|
|
|
47911
48262
|
init_injector();
|
|
47912
48263
|
init_jsonl_migration();
|
|
47913
48264
|
init_local_jsonl_provider();
|
|
48265
|
+
init_maintenance();
|
|
47914
48266
|
init_prompt_block();
|
|
47915
48267
|
init_recall_planner();
|
|
47916
48268
|
init_redaction();
|
|
@@ -47929,6 +48281,10 @@ async function handleMemoryCommand(_directory, _args) {
|
|
|
47929
48281
|
"## Swarm Memory",
|
|
47930
48282
|
"",
|
|
47931
48283
|
"- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
|
|
48284
|
+
"- `/swarm memory pending` - show pending proposals and recent rejection reasons",
|
|
48285
|
+
"- `/swarm memory recall-log` - summarize recall usage by agent role and memory ID",
|
|
48286
|
+
"- `/swarm memory stale` - list expired scratch, superseded, deleted, and low-utility memories",
|
|
48287
|
+
"- `/swarm memory compact` - dry-run compaction; pass `--confirm` to remove deleted, superseded, and expired scratch records",
|
|
47932
48288
|
"- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
|
|
47933
48289
|
"- `/swarm memory import` - import `.swarm/memory/{memories,proposals}.jsonl` into SQLite",
|
|
47934
48290
|
"- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration",
|
|
@@ -47950,6 +48306,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
47950
48306
|
`- Storage: \`${storageDir}\``,
|
|
47951
48307
|
`- SQLite path: \`${sqlitePath}\``,
|
|
47952
48308
|
`- SQLite database exists: \`${existsSync20(sqlitePath)}\``,
|
|
48309
|
+
`- Automatic destructive cleanup: \`disabled\``,
|
|
47953
48310
|
"",
|
|
47954
48311
|
"### Legacy JSONL"
|
|
47955
48312
|
];
|
|
@@ -47974,6 +48331,119 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
47974
48331
|
return lines.join(`
|
|
47975
48332
|
`);
|
|
47976
48333
|
}
|
|
48334
|
+
async function handleMemoryPendingCommand(directory, args) {
|
|
48335
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48336
|
+
usage: "Usage: /swarm memory pending [--limit <n>]",
|
|
48337
|
+
allowConfirm: false
|
|
48338
|
+
});
|
|
48339
|
+
if ("error" in parsed)
|
|
48340
|
+
return parsed.error;
|
|
48341
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48342
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48343
|
+
try {
|
|
48344
|
+
await provider.initialize?.();
|
|
48345
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48346
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48347
|
+
});
|
|
48348
|
+
const lines = [
|
|
48349
|
+
"## Swarm Memory Pending",
|
|
48350
|
+
"",
|
|
48351
|
+
`- Pending proposals shown: \`${report.pendingProposals.length}\``,
|
|
48352
|
+
`- Rejected proposal reasons shown: \`${report.rejectedProposalReasons.length}\``
|
|
48353
|
+
];
|
|
48354
|
+
appendProposalLines(lines, "Pending proposals", report.pendingProposals);
|
|
48355
|
+
appendProposalLines(lines, "Rejected proposal reasons", report.rejectedProposalReasons);
|
|
48356
|
+
return lines.join(`
|
|
48357
|
+
`);
|
|
48358
|
+
} finally {
|
|
48359
|
+
await provider.close?.();
|
|
48360
|
+
}
|
|
48361
|
+
}
|
|
48362
|
+
async function handleMemoryRecallLogCommand(directory, args) {
|
|
48363
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48364
|
+
usage: "Usage: /swarm memory recall-log [--limit <n>]",
|
|
48365
|
+
allowConfirm: false
|
|
48366
|
+
});
|
|
48367
|
+
if ("error" in parsed)
|
|
48368
|
+
return parsed.error;
|
|
48369
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48370
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48371
|
+
try {
|
|
48372
|
+
await provider.initialize?.();
|
|
48373
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48374
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48375
|
+
});
|
|
48376
|
+
const lines = [
|
|
48377
|
+
"## Swarm Memory Recall Log",
|
|
48378
|
+
"",
|
|
48379
|
+
`- Recall events scanned: \`${report.recallEventCount}\``,
|
|
48380
|
+
`- Most-recalled memories shown: \`${report.mostRecalledMemories.length}\``,
|
|
48381
|
+
`- Never-recalled memories shown: \`${report.neverRecalledMemories.length}\``
|
|
48382
|
+
];
|
|
48383
|
+
appendRecallRoleLines(lines, report.recallByAgentRole);
|
|
48384
|
+
appendRecallMemoryLines(lines, report.mostRecalledMemories);
|
|
48385
|
+
appendMemoryLines(lines, "Never-recalled memories", report.neverRecalledMemories);
|
|
48386
|
+
return lines.join(`
|
|
48387
|
+
`);
|
|
48388
|
+
} finally {
|
|
48389
|
+
await provider.close?.();
|
|
48390
|
+
}
|
|
48391
|
+
}
|
|
48392
|
+
async function handleMemoryStaleCommand(directory, args) {
|
|
48393
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48394
|
+
usage: "Usage: /swarm memory stale [--limit <n>]",
|
|
48395
|
+
allowConfirm: false
|
|
48396
|
+
});
|
|
48397
|
+
if ("error" in parsed)
|
|
48398
|
+
return parsed.error;
|
|
48399
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48400
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48401
|
+
try {
|
|
48402
|
+
await provider.initialize?.();
|
|
48403
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48404
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48405
|
+
});
|
|
48406
|
+
const lines = [
|
|
48407
|
+
"## Swarm Memory Stale",
|
|
48408
|
+
"",
|
|
48409
|
+
`- Active memories: \`${report.activeMemories}\``,
|
|
48410
|
+
`- Expired scratch memories shown: \`${report.expiredScratchMemories.length}\``,
|
|
48411
|
+
`- Deleted tombstones shown: \`${report.deletedMemories.length}\``,
|
|
48412
|
+
`- Superseded memories shown: \`${report.supersededMemories.length}\``,
|
|
48413
|
+
`- Low-utility memories shown: \`${report.lowUtilityMemories.length}\``
|
|
48414
|
+
];
|
|
48415
|
+
appendMemoryLines(lines, "Expired scratch memories", report.expiredScratchMemories);
|
|
48416
|
+
appendMemoryLines(lines, "Deleted tombstones", report.deletedMemories);
|
|
48417
|
+
appendSupersededChains(lines, report);
|
|
48418
|
+
appendMemoryLines(lines, "Low-utility memories", report.lowUtilityMemories);
|
|
48419
|
+
return lines.join(`
|
|
48420
|
+
`);
|
|
48421
|
+
} finally {
|
|
48422
|
+
await provider.close?.();
|
|
48423
|
+
}
|
|
48424
|
+
}
|
|
48425
|
+
async function handleMemoryCompactCommand(directory, args) {
|
|
48426
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48427
|
+
usage: "Usage: /swarm memory compact [--confirm]",
|
|
48428
|
+
allowConfirm: true,
|
|
48429
|
+
allowLimit: false
|
|
48430
|
+
});
|
|
48431
|
+
if ("error" in parsed)
|
|
48432
|
+
return parsed.error;
|
|
48433
|
+
const provider = createMaintenanceProvider(directory, resolveCommandMemoryConfig(directory));
|
|
48434
|
+
try {
|
|
48435
|
+
await provider.initialize?.();
|
|
48436
|
+
if (!provider.compactMaintenance) {
|
|
48437
|
+
return "Memory provider does not support compaction.";
|
|
48438
|
+
}
|
|
48439
|
+
const result = await provider.compactMaintenance({
|
|
48440
|
+
dryRun: !parsed.confirm
|
|
48441
|
+
});
|
|
48442
|
+
return formatCompactResult(result, parsed.confirm);
|
|
48443
|
+
} finally {
|
|
48444
|
+
await provider.close?.();
|
|
48445
|
+
}
|
|
48446
|
+
}
|
|
47977
48447
|
async function handleMemoryMigrateCommand(directory, _args) {
|
|
47978
48448
|
const config3 = {
|
|
47979
48449
|
...resolveCommandMemoryConfig(directory),
|
|
@@ -48030,6 +48500,16 @@ async function handleMemoryExportCommand(directory, _args) {
|
|
|
48030
48500
|
await provider.close?.();
|
|
48031
48501
|
}
|
|
48032
48502
|
}
|
|
48503
|
+
function createMaintenanceProvider(directory, config3) {
|
|
48504
|
+
return createConfiguredMemoryProvider(directory, config3);
|
|
48505
|
+
}
|
|
48506
|
+
function maintenanceReportOptions(config3, limit) {
|
|
48507
|
+
return {
|
|
48508
|
+
limit,
|
|
48509
|
+
lowUtilityMaxConfidence: config3.maintenance.lowUtilityMaxConfidence,
|
|
48510
|
+
lowUtilityMinAgeDays: config3.maintenance.lowUtilityMinAgeDays
|
|
48511
|
+
};
|
|
48512
|
+
}
|
|
48033
48513
|
async function handleMemoryEvaluateCommand(directory, args) {
|
|
48034
48514
|
const parsed = parseEvaluateArgs(directory, args);
|
|
48035
48515
|
if ("error" in parsed)
|
|
@@ -48088,6 +48568,28 @@ function parseEvaluateArgs(directory, args) {
|
|
|
48088
48568
|
}
|
|
48089
48569
|
return { json: json3, fixtureDirectory };
|
|
48090
48570
|
}
|
|
48571
|
+
function parseMaintenanceArgs(args, options) {
|
|
48572
|
+
let limit = 20;
|
|
48573
|
+
let confirm = false;
|
|
48574
|
+
const allowLimit = options.allowLimit ?? true;
|
|
48575
|
+
for (let i = 0;i < args.length; i++) {
|
|
48576
|
+
const arg = args[i];
|
|
48577
|
+
if (arg === "--confirm" && options.allowConfirm) {
|
|
48578
|
+
confirm = true;
|
|
48579
|
+
continue;
|
|
48580
|
+
}
|
|
48581
|
+
if (arg === "--limit" && allowLimit) {
|
|
48582
|
+
const next = args[i + 1];
|
|
48583
|
+
if (!next || !/^\d+$/.test(next))
|
|
48584
|
+
return { error: options.usage };
|
|
48585
|
+
limit = Math.min(100, Math.max(1, Number(next)));
|
|
48586
|
+
i++;
|
|
48587
|
+
continue;
|
|
48588
|
+
}
|
|
48589
|
+
return { error: options.usage };
|
|
48590
|
+
}
|
|
48591
|
+
return { limit, confirm };
|
|
48592
|
+
}
|
|
48091
48593
|
function resolvePackageRootFromModule(modulePath) {
|
|
48092
48594
|
const moduleDir = path33.dirname(modulePath);
|
|
48093
48595
|
const leaf = path33.basename(moduleDir);
|
|
@@ -48138,6 +48640,80 @@ function appendInvalidRows(lines, invalidRows) {
|
|
|
48138
48640
|
lines.push(`- ... ${invalidRows.length - 20} more`);
|
|
48139
48641
|
}
|
|
48140
48642
|
}
|
|
48643
|
+
function appendProposalLines(lines, title, proposals) {
|
|
48644
|
+
lines.push("", `### ${title}`);
|
|
48645
|
+
if (proposals.length === 0) {
|
|
48646
|
+
lines.push("- none");
|
|
48647
|
+
return;
|
|
48648
|
+
}
|
|
48649
|
+
for (const proposal of proposals) {
|
|
48650
|
+
const reason = proposal.status === "rejected" ? ` - ${proposal.rejectionReason ?? "no reason recorded"}` : "";
|
|
48651
|
+
lines.push(`- \`${proposal.id}\` ${proposal.operation} ${proposal.targetMemoryId ?? proposal.proposedRecord?.id ?? "new"} (${proposal.status})${reason}`);
|
|
48652
|
+
}
|
|
48653
|
+
}
|
|
48654
|
+
function appendMemoryLines(lines, title, memories) {
|
|
48655
|
+
lines.push("", `### ${title}`);
|
|
48656
|
+
if (memories.length === 0) {
|
|
48657
|
+
lines.push("- none");
|
|
48658
|
+
return;
|
|
48659
|
+
}
|
|
48660
|
+
for (const memory of memories) {
|
|
48661
|
+
lines.push(`- \`${memory.id}\` ${memory.kind} confidence=${memory.confidence.toFixed(2)} updated=${memory.updatedAt} - ${truncate(memory.text, 100)}`);
|
|
48662
|
+
}
|
|
48663
|
+
}
|
|
48664
|
+
function appendRecallRoleLines(lines, roles) {
|
|
48665
|
+
lines.push("", "### Recall by agent role");
|
|
48666
|
+
if (roles.length === 0) {
|
|
48667
|
+
lines.push("- none");
|
|
48668
|
+
return;
|
|
48669
|
+
}
|
|
48670
|
+
for (const role of roles) {
|
|
48671
|
+
const memoryCount = Object.keys(role.memoryIds).length;
|
|
48672
|
+
lines.push(`- \`${role.agentRole}\`: ${role.count} recall event(s), ${memoryCount} memory ID(s)`);
|
|
48673
|
+
}
|
|
48674
|
+
}
|
|
48675
|
+
function appendRecallMemoryLines(lines, memories) {
|
|
48676
|
+
lines.push("", "### Most-recalled memories");
|
|
48677
|
+
if (memories.length === 0) {
|
|
48678
|
+
lines.push("- none");
|
|
48679
|
+
return;
|
|
48680
|
+
}
|
|
48681
|
+
for (const memory of memories) {
|
|
48682
|
+
lines.push(`- \`${memory.memoryId}\`: ${memory.count} hit(s), last=${memory.lastRecalledAt}, avgScore=${memory.averageScore.toFixed(3)}`);
|
|
48683
|
+
}
|
|
48684
|
+
}
|
|
48685
|
+
function appendSupersededChains(lines, report) {
|
|
48686
|
+
lines.push("", "### Superseded chains");
|
|
48687
|
+
if (report.supersededChains.length === 0) {
|
|
48688
|
+
lines.push("- none");
|
|
48689
|
+
return;
|
|
48690
|
+
}
|
|
48691
|
+
for (const chain of report.supersededChains) {
|
|
48692
|
+
const reason = chain.reason ? ` - ${chain.reason}` : "";
|
|
48693
|
+
lines.push(`- ${chain.chain.map((id) => `\`${id}\``).join(" -> ")}${reason}`);
|
|
48694
|
+
}
|
|
48695
|
+
}
|
|
48696
|
+
function formatCompactResult(result, confirmed) {
|
|
48697
|
+
const lines = [
|
|
48698
|
+
"## Swarm Memory Compact",
|
|
48699
|
+
"",
|
|
48700
|
+
`- Mode: \`${confirmed ? "confirmed" : "dry-run"}\``,
|
|
48701
|
+
`- Deleted tombstones: \`${result.removedDeleted}\``,
|
|
48702
|
+
`- Superseded records: \`${result.removedSuperseded}\``,
|
|
48703
|
+
`- Expired scratch records: \`${result.removedExpiredScratch}\``,
|
|
48704
|
+
`- Remaining memories: \`${result.remaining}\``
|
|
48705
|
+
];
|
|
48706
|
+
if (!confirmed) {
|
|
48707
|
+
lines.push("", "No records were removed. Re-run `/swarm memory compact --confirm` to apply this compaction.");
|
|
48708
|
+
}
|
|
48709
|
+
return lines.join(`
|
|
48710
|
+
`);
|
|
48711
|
+
}
|
|
48712
|
+
function truncate(value, maxLength) {
|
|
48713
|
+
if (value.length <= maxLength)
|
|
48714
|
+
return value;
|
|
48715
|
+
return `${value.slice(0, maxLength - 3)}...`;
|
|
48716
|
+
}
|
|
48141
48717
|
var PACKAGE_ROOT;
|
|
48142
48718
|
var init_memory2 = __esm(() => {
|
|
48143
48719
|
init_loader();
|
|
@@ -56197,7 +56773,7 @@ function classifySwarmCommandToolUse(resolved) {
|
|
|
56197
56773
|
return { allowed: true };
|
|
56198
56774
|
return {
|
|
56199
56775
|
allowed: false,
|
|
56200
|
-
message: "Use `/swarm memory status`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import and
|
|
56776
|
+
message: "Use `/swarm memory status`, `/swarm memory pending`, `/swarm memory recall-log`, `/swarm memory stale`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import, migrate, and compact are intentionally excluded from chat-tool execution."
|
|
56201
56777
|
};
|
|
56202
56778
|
}
|
|
56203
56779
|
if (canonicalKey === "memory evaluate") {
|
|
@@ -56210,6 +56786,17 @@ function classifySwarmCommandToolUse(resolved) {
|
|
|
56210
56786
|
message: "Usage through swarm_command: `/swarm memory evaluate --json`. Custom fixture directories are only available through direct user command execution."
|
|
56211
56787
|
};
|
|
56212
56788
|
}
|
|
56789
|
+
if (canonicalKey === "memory pending" || canonicalKey === "memory recall-log" || canonicalKey === "memory stale") {
|
|
56790
|
+
if (args.length === 0)
|
|
56791
|
+
return { allowed: true };
|
|
56792
|
+
if (args.length === 2 && args[0] === "--limit" && /^\d+$/.test(args[1])) {
|
|
56793
|
+
return { allowed: true };
|
|
56794
|
+
}
|
|
56795
|
+
return {
|
|
56796
|
+
allowed: false,
|
|
56797
|
+
message: `Usage through swarm_command: \`/swarm ${canonicalKey}\` or ` + `\`/swarm ${canonicalKey} --limit <n>\`.`
|
|
56798
|
+
};
|
|
56799
|
+
}
|
|
56213
56800
|
if (canonicalKey === "retrieve") {
|
|
56214
56801
|
if (args.length !== 1 || !SUMMARY_ID_PATTERN.test(args[0])) {
|
|
56215
56802
|
return {
|
|
@@ -56261,7 +56848,7 @@ function classifySwarmCommandChatFallbackUse(resolved) {
|
|
|
56261
56848
|
message: "/swarm config doctor --fix is not available through chat fallback because it can modify configuration files. Run the CLI command directly when you intend to apply fixes."
|
|
56262
56849
|
};
|
|
56263
56850
|
}
|
|
56264
|
-
if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore" || canonicalKey === "memory import" || canonicalKey === "memory migrate") {
|
|
56851
|
+
if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore" || canonicalKey === "memory import" || canonicalKey === "memory migrate" || canonicalKey === "memory compact") {
|
|
56265
56852
|
return {
|
|
56266
56853
|
allowed: false,
|
|
56267
56854
|
message: `/swarm ${canonicalKey} is not available through chat fallback because it mutates .swarm state. ` + "Run the CLI command directly after confirming the intended state change."
|
|
@@ -56294,6 +56881,10 @@ var init_tool_policy = __esm(() => {
|
|
|
56294
56881
|
"knowledge",
|
|
56295
56882
|
"memory",
|
|
56296
56883
|
"memory status",
|
|
56884
|
+
"memory pending",
|
|
56885
|
+
"memory recall-log",
|
|
56886
|
+
"memory compact",
|
|
56887
|
+
"memory stale",
|
|
56297
56888
|
"memory export",
|
|
56298
56889
|
"memory evaluate",
|
|
56299
56890
|
"memory import",
|
|
@@ -56320,6 +56911,9 @@ var init_tool_policy = __esm(() => {
|
|
|
56320
56911
|
"knowledge",
|
|
56321
56912
|
"memory",
|
|
56322
56913
|
"memory status",
|
|
56914
|
+
"memory pending",
|
|
56915
|
+
"memory recall-log",
|
|
56916
|
+
"memory stale",
|
|
56323
56917
|
"memory export",
|
|
56324
56918
|
"memory evaluate",
|
|
56325
56919
|
"sync-plan",
|
|
@@ -56332,7 +56926,8 @@ var init_tool_policy = __esm(() => {
|
|
|
56332
56926
|
"rollback",
|
|
56333
56927
|
"checkpoint",
|
|
56334
56928
|
"memory import",
|
|
56335
|
-
"memory migrate"
|
|
56929
|
+
"memory migrate",
|
|
56930
|
+
"memory compact"
|
|
56336
56931
|
]);
|
|
56337
56932
|
NO_ARGS = new Set([
|
|
56338
56933
|
"agents",
|
|
@@ -57327,6 +57922,34 @@ Subcommands:
|
|
|
57327
57922
|
args: "",
|
|
57328
57923
|
category: "diagnostics"
|
|
57329
57924
|
},
|
|
57925
|
+
"memory pending": {
|
|
57926
|
+
handler: (ctx) => handleMemoryPendingCommand(ctx.directory, ctx.args),
|
|
57927
|
+
description: "Show pending Swarm memory proposals and rejection reasons",
|
|
57928
|
+
subcommandOf: "memory",
|
|
57929
|
+
args: "--limit <n>",
|
|
57930
|
+
category: "diagnostics"
|
|
57931
|
+
},
|
|
57932
|
+
"memory recall-log": {
|
|
57933
|
+
handler: (ctx) => handleMemoryRecallLogCommand(ctx.directory, ctx.args),
|
|
57934
|
+
description: "Summarize Swarm memory recall usage",
|
|
57935
|
+
subcommandOf: "memory",
|
|
57936
|
+
args: "--limit <n>",
|
|
57937
|
+
category: "diagnostics"
|
|
57938
|
+
},
|
|
57939
|
+
"memory compact": {
|
|
57940
|
+
handler: (ctx) => handleMemoryCompactCommand(ctx.directory, ctx.args),
|
|
57941
|
+
description: "Compact deleted, superseded, and expired scratch memories",
|
|
57942
|
+
subcommandOf: "memory",
|
|
57943
|
+
args: "--confirm",
|
|
57944
|
+
category: "utility"
|
|
57945
|
+
},
|
|
57946
|
+
"memory stale": {
|
|
57947
|
+
handler: (ctx) => handleMemoryStaleCommand(ctx.directory, ctx.args),
|
|
57948
|
+
description: "List stale and low-utility Swarm memories",
|
|
57949
|
+
subcommandOf: "memory",
|
|
57950
|
+
args: "--limit <n>",
|
|
57951
|
+
category: "diagnostics"
|
|
57952
|
+
},
|
|
57330
57953
|
"memory export": {
|
|
57331
57954
|
handler: (ctx) => handleMemoryExportCommand(ctx.directory, ctx.args),
|
|
57332
57955
|
description: "Export current Swarm memory to JSONL files",
|