opencode-swarm 7.38.0 → 7.40.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/cli/index.js +750 -20
- package/dist/commands/concurrency.d.ts +10 -0
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/memory.d.ts +4 -0
- package/dist/commands/registry.d.ts +35 -0
- package/dist/commands/tool-policy.d.ts +1 -1
- package/dist/config/schema.d.ts +8 -0
- package/dist/hooks/delegation-gate.d.ts +4 -1
- package/dist/index.js +763 -30
- package/dist/memory/config.d.ts +4 -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/session/snapshot-writer.d.ts +2 -0
- package/dist/state.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.40.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({
|
|
@@ -38860,6 +38867,110 @@ var init_close = __esm(() => {
|
|
|
38860
38867
|
];
|
|
38861
38868
|
});
|
|
38862
38869
|
|
|
38870
|
+
// src/commands/concurrency.ts
|
|
38871
|
+
async function handleConcurrencyCommand(directory, args, sessionID) {
|
|
38872
|
+
if (!sessionID || sessionID.trim() === "") {
|
|
38873
|
+
return "Error: No active session context. Concurrency requires an active session. Use /swarm concurrency from within an OpenCode session, or start a session first.";
|
|
38874
|
+
}
|
|
38875
|
+
const session = getAgentSession(sessionID);
|
|
38876
|
+
if (!session) {
|
|
38877
|
+
return "Error: No active session. Concurrency requires an active session to operate.";
|
|
38878
|
+
}
|
|
38879
|
+
const arg0 = args[0]?.toLowerCase();
|
|
38880
|
+
const arg1 = args[1];
|
|
38881
|
+
const plan = await loadPlanJsonOnly(directory).catch(() => null);
|
|
38882
|
+
const hasPlan = plan !== null && plan !== undefined;
|
|
38883
|
+
if (arg0 === undefined) {
|
|
38884
|
+
return [
|
|
38885
|
+
"Concurrency commands:",
|
|
38886
|
+
" /swarm concurrency set <N|preset> \u2014 Set session concurrency override (1-64 or min/medium/max)",
|
|
38887
|
+
" /swarm concurrency status \u2014 Show effective concurrency",
|
|
38888
|
+
" /swarm concurrency reset \u2014 Clear the override"
|
|
38889
|
+
].join(`
|
|
38890
|
+
`);
|
|
38891
|
+
}
|
|
38892
|
+
if (arg0 === "status") {
|
|
38893
|
+
return buildStatusMessage(session, plan);
|
|
38894
|
+
}
|
|
38895
|
+
if (!hasPlan) {
|
|
38896
|
+
if (arg0 === "set") {
|
|
38897
|
+
return "No active plan. Concurrency override requires an active plan.";
|
|
38898
|
+
}
|
|
38899
|
+
}
|
|
38900
|
+
if (arg0 === "reset") {
|
|
38901
|
+
session.maxConcurrencyOverride = undefined;
|
|
38902
|
+
return "Concurrency override cleared";
|
|
38903
|
+
}
|
|
38904
|
+
if (arg0 === "set") {
|
|
38905
|
+
if (arg1 === undefined) {
|
|
38906
|
+
return "Error: /swarm concurrency set requires a value. Usage: /swarm concurrency set <N|preset>";
|
|
38907
|
+
}
|
|
38908
|
+
return handleSetCommand(session, arg1);
|
|
38909
|
+
}
|
|
38910
|
+
return [
|
|
38911
|
+
`Unknown concurrency subcommand: ${arg0}`,
|
|
38912
|
+
"Usage: /swarm concurrency <set|status|reset>"
|
|
38913
|
+
].join(`
|
|
38914
|
+
`);
|
|
38915
|
+
}
|
|
38916
|
+
function handleSetCommand(session, value) {
|
|
38917
|
+
const normalizedValue = value.toLowerCase();
|
|
38918
|
+
if (normalizedValue in PRESETS) {
|
|
38919
|
+
const presetConcurrency = PRESETS[normalizedValue];
|
|
38920
|
+
session.maxConcurrencyOverride = presetConcurrency;
|
|
38921
|
+
return `Concurrency override set to ${presetConcurrency} (${normalizedValue})`;
|
|
38922
|
+
}
|
|
38923
|
+
const numericValue = Number(value);
|
|
38924
|
+
if (Number.isNaN(numericValue)) {
|
|
38925
|
+
return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
|
|
38926
|
+
}
|
|
38927
|
+
if (!Number.isInteger(numericValue)) {
|
|
38928
|
+
return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
|
|
38929
|
+
}
|
|
38930
|
+
if (numericValue < MIN_CONCURRENCY || numericValue > MAX_CONCURRENCY) {
|
|
38931
|
+
return `Concurrency value ${value} is out of range. Must be between ${MIN_CONCURRENCY} and ${MAX_CONCURRENCY}.`;
|
|
38932
|
+
}
|
|
38933
|
+
session.maxConcurrencyOverride = numericValue;
|
|
38934
|
+
return `Concurrency override set to ${numericValue}`;
|
|
38935
|
+
}
|
|
38936
|
+
function buildStatusMessage(session, plan) {
|
|
38937
|
+
const overrideActive = session.maxConcurrencyOverride !== undefined;
|
|
38938
|
+
const configuredOverride = session.maxConcurrencyOverride ?? "absent";
|
|
38939
|
+
const hasPlan = plan !== null && plan !== undefined;
|
|
38940
|
+
const planBaseline = hasPlan ? plan.execution_profile?.max_concurrent_tasks ?? 1 : 1;
|
|
38941
|
+
const parallelizationEnabled = hasPlan ? plan.execution_profile?.parallelization_enabled ?? false : false;
|
|
38942
|
+
const operationalEffective = !parallelizationEnabled ? 1 : session.maxConcurrencyOverride ?? planBaseline;
|
|
38943
|
+
let description;
|
|
38944
|
+
if (!hasPlan) {
|
|
38945
|
+
description = "No active plan";
|
|
38946
|
+
} else if (!parallelizationEnabled) {
|
|
38947
|
+
description = "Parallelization disabled (always 1)";
|
|
38948
|
+
} else if (overrideActive) {
|
|
38949
|
+
description = `Override active (${session.maxConcurrencyOverride})`;
|
|
38950
|
+
} else {
|
|
38951
|
+
description = `Plan baseline (${planBaseline})`;
|
|
38952
|
+
}
|
|
38953
|
+
return [
|
|
38954
|
+
`Concurrency: ${description}`,
|
|
38955
|
+
` override_active: ${overrideActive}`,
|
|
38956
|
+
` configured_override: ${configuredOverride}`,
|
|
38957
|
+
` plan_baseline: ${planBaseline}`,
|
|
38958
|
+
` operational_effective: ${operationalEffective}`,
|
|
38959
|
+
` parallelization_enabled: ${parallelizationEnabled}`
|
|
38960
|
+
].join(`
|
|
38961
|
+
`);
|
|
38962
|
+
}
|
|
38963
|
+
var PRESETS, MIN_CONCURRENCY = 1, MAX_CONCURRENCY = 64;
|
|
38964
|
+
var init_concurrency = __esm(() => {
|
|
38965
|
+
init_manager();
|
|
38966
|
+
init_state();
|
|
38967
|
+
PRESETS = {
|
|
38968
|
+
min: 1,
|
|
38969
|
+
medium: 3,
|
|
38970
|
+
max: 8
|
|
38971
|
+
};
|
|
38972
|
+
});
|
|
38973
|
+
|
|
38863
38974
|
// src/commands/config.ts
|
|
38864
38975
|
import * as os4 from "os";
|
|
38865
38976
|
import * as path17 from "path";
|
|
@@ -44428,7 +44539,10 @@ function serializeAgentSession(s) {
|
|
|
44428
44539
|
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
44429
44540
|
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
44430
44541
|
sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
|
|
44431
|
-
...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
|
|
44542
|
+
...Object.keys(stageBCompletion).length > 0 && { stageBCompletion },
|
|
44543
|
+
...s.maxConcurrencyOverride !== undefined && {
|
|
44544
|
+
maxConcurrencyOverride: s.maxConcurrencyOverride
|
|
44545
|
+
}
|
|
44432
44546
|
};
|
|
44433
44547
|
}
|
|
44434
44548
|
async function writeSnapshot(directory, state) {
|
|
@@ -45301,6 +45415,10 @@ function resolveMemoryConfig(input) {
|
|
|
45301
45415
|
redaction: {
|
|
45302
45416
|
...DEFAULT_MEMORY_CONFIG.redaction,
|
|
45303
45417
|
...input?.redaction ?? {}
|
|
45418
|
+
},
|
|
45419
|
+
maintenance: {
|
|
45420
|
+
...DEFAULT_MEMORY_CONFIG.maintenance,
|
|
45421
|
+
...input?.maintenance ?? {}
|
|
45304
45422
|
}
|
|
45305
45423
|
};
|
|
45306
45424
|
}
|
|
@@ -45332,6 +45450,10 @@ var init_config3 = __esm(() => {
|
|
|
45332
45450
|
redaction: {
|
|
45333
45451
|
rejectDurableSecrets: true
|
|
45334
45452
|
},
|
|
45453
|
+
maintenance: {
|
|
45454
|
+
lowUtilityMaxConfidence: 0.45,
|
|
45455
|
+
lowUtilityMinAgeDays: 30
|
|
45456
|
+
},
|
|
45335
45457
|
hardDelete: false
|
|
45336
45458
|
};
|
|
45337
45459
|
DURABLE_MEMORY_KINDS = new Set([
|
|
@@ -45715,6 +45837,167 @@ var init_curator_decision_helpers = __esm(() => {
|
|
|
45715
45837
|
init_schema2();
|
|
45716
45838
|
});
|
|
45717
45839
|
|
|
45840
|
+
// src/memory/maintenance.ts
|
|
45841
|
+
async function buildMemoryMaintenanceReport(provider, options = {}) {
|
|
45842
|
+
const now = options.now ?? new Date;
|
|
45843
|
+
const limit = Math.max(1, Math.trunc(options.limit ?? 20));
|
|
45844
|
+
const memories = await provider.list({
|
|
45845
|
+
includeExpired: true,
|
|
45846
|
+
includeInactive: true
|
|
45847
|
+
});
|
|
45848
|
+
const proposals = await loadMaintenanceProposals(provider, limit);
|
|
45849
|
+
const recallUsage = provider.listRecallUsage ? await provider.listRecallUsage() : [];
|
|
45850
|
+
const usageByMemory = summarizeRecallByMemory(recallUsage);
|
|
45851
|
+
const usageByRole = summarizeRecallByRole(recallUsage);
|
|
45852
|
+
const activeMemories = memories.filter((memory) => isActiveMemory(memory, now));
|
|
45853
|
+
const deletedMemories = memories.filter((memory) => memory.metadata.deleted === true);
|
|
45854
|
+
const expiredScratchMemories = memories.filter((memory) => memory.kind === "scratch" && isExpired(memory, now));
|
|
45855
|
+
const supersededMemories = memories.filter((memory) => Boolean(memory.supersededBy));
|
|
45856
|
+
const lowUtilityMemories = activeMemories.filter((memory) => isLowUtility(memory, usageByMemory, now, {
|
|
45857
|
+
maxConfidence: options.lowUtilityMaxConfidence ?? DEFAULT_LOW_UTILITY_MAX_CONFIDENCE,
|
|
45858
|
+
minAgeDays: options.lowUtilityMinAgeDays ?? DEFAULT_LOW_UTILITY_MIN_AGE_DAYS
|
|
45859
|
+
})).sort(memorySort);
|
|
45860
|
+
const neverRecalledMemories = activeMemories.filter((memory) => !usageByMemory.has(memory.id)).sort(memorySort);
|
|
45861
|
+
const rejectedProposalReasons = proposals.filter((proposal) => proposal.status === "rejected").sort(proposalSort);
|
|
45862
|
+
const pendingProposals = proposals.filter((proposal) => proposal.status === "pending").sort(proposalSort);
|
|
45863
|
+
return {
|
|
45864
|
+
generatedAt: now.toISOString(),
|
|
45865
|
+
totalMemories: memories.length,
|
|
45866
|
+
activeMemories: activeMemories.length,
|
|
45867
|
+
deletedMemories: deletedMemories.slice(0, limit),
|
|
45868
|
+
expiredScratchMemories: expiredScratchMemories.slice(0, limit),
|
|
45869
|
+
supersededMemories: supersededMemories.slice(0, limit),
|
|
45870
|
+
supersededChains: buildSupersededChains(memories).slice(0, limit),
|
|
45871
|
+
lowUtilityMemories: lowUtilityMemories.slice(0, limit),
|
|
45872
|
+
neverRecalledMemories: neverRecalledMemories.slice(0, limit),
|
|
45873
|
+
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),
|
|
45874
|
+
recallByAgentRole: Array.from(usageByRole.values()).sort((a, b) => b.count - a.count || a.agentRole.localeCompare(b.agentRole)).slice(0, limit),
|
|
45875
|
+
rejectedProposalReasons: rejectedProposalReasons.slice(0, limit),
|
|
45876
|
+
pendingProposals: pendingProposals.slice(0, limit),
|
|
45877
|
+
recallEventCount: recallUsage.length
|
|
45878
|
+
};
|
|
45879
|
+
}
|
|
45880
|
+
function shouldCompactMemory(memory, now = new Date) {
|
|
45881
|
+
if (memory.metadata.deleted === true)
|
|
45882
|
+
return "deleted";
|
|
45883
|
+
if (memory.supersededBy)
|
|
45884
|
+
return "superseded";
|
|
45885
|
+
if (memory.kind === "scratch" && isExpired(memory, now)) {
|
|
45886
|
+
return "expired_scratch";
|
|
45887
|
+
}
|
|
45888
|
+
return null;
|
|
45889
|
+
}
|
|
45890
|
+
function isActiveMemory(memory, now) {
|
|
45891
|
+
return memory.metadata.deleted !== true && !memory.supersededBy && !isExpired(memory, now);
|
|
45892
|
+
}
|
|
45893
|
+
function isLowUtility(memory, usageByMemory, now, options) {
|
|
45894
|
+
if (usageByMemory.has(memory.id))
|
|
45895
|
+
return false;
|
|
45896
|
+
const updated = Date.parse(memory.updatedAt);
|
|
45897
|
+
const ageDays = Number.isFinite(updated) ? (now.getTime() - updated) / (24 * 60 * 60 * 1000) : 0;
|
|
45898
|
+
return memory.confidence <= options.maxConfidence || ageDays >= options.minAgeDays;
|
|
45899
|
+
}
|
|
45900
|
+
function summarizeRecallByMemory(usageEvents) {
|
|
45901
|
+
const byMemory = new Map;
|
|
45902
|
+
for (const event of usageEvents) {
|
|
45903
|
+
event.memoryIds.forEach((memoryId, index) => {
|
|
45904
|
+
const role = event.agentRole ?? "unknown";
|
|
45905
|
+
const existing = byMemory.get(memoryId) ?? {
|
|
45906
|
+
memoryId,
|
|
45907
|
+
count: 0,
|
|
45908
|
+
lastRecalledAt: event.timestamp,
|
|
45909
|
+
agentRoles: {},
|
|
45910
|
+
averageScore: 0,
|
|
45911
|
+
scoreTotal: 0,
|
|
45912
|
+
scoreCount: 0
|
|
45913
|
+
};
|
|
45914
|
+
existing.count++;
|
|
45915
|
+
existing.lastRecalledAt = event.timestamp > existing.lastRecalledAt ? event.timestamp : existing.lastRecalledAt;
|
|
45916
|
+
existing.agentRoles[role] = (existing.agentRoles[role] ?? 0) + 1;
|
|
45917
|
+
const score = event.scores[index];
|
|
45918
|
+
if (typeof score === "number" && Number.isFinite(score)) {
|
|
45919
|
+
existing.scoreTotal += score;
|
|
45920
|
+
existing.scoreCount++;
|
|
45921
|
+
existing.averageScore = existing.scoreTotal / existing.scoreCount;
|
|
45922
|
+
}
|
|
45923
|
+
byMemory.set(memoryId, existing);
|
|
45924
|
+
});
|
|
45925
|
+
}
|
|
45926
|
+
return new Map(Array.from(byMemory, ([memoryId, value]) => [
|
|
45927
|
+
memoryId,
|
|
45928
|
+
{
|
|
45929
|
+
memoryId,
|
|
45930
|
+
count: value.count,
|
|
45931
|
+
lastRecalledAt: value.lastRecalledAt,
|
|
45932
|
+
agentRoles: value.agentRoles,
|
|
45933
|
+
averageScore: value.averageScore
|
|
45934
|
+
}
|
|
45935
|
+
]));
|
|
45936
|
+
}
|
|
45937
|
+
async function loadMaintenanceProposals(provider, limit) {
|
|
45938
|
+
if (!provider.listProposals)
|
|
45939
|
+
return [];
|
|
45940
|
+
const [pending, rejected, recent] = await Promise.all([
|
|
45941
|
+
provider.listProposals({ status: "pending", limit }),
|
|
45942
|
+
provider.listProposals({ status: "rejected", limit }),
|
|
45943
|
+
provider.listProposals({ limit: Math.max(limit * 4, 100) })
|
|
45944
|
+
]);
|
|
45945
|
+
const byId = new Map;
|
|
45946
|
+
for (const proposal of [...pending, ...rejected, ...recent]) {
|
|
45947
|
+
byId.set(proposal.id, proposal);
|
|
45948
|
+
}
|
|
45949
|
+
return Array.from(byId.values());
|
|
45950
|
+
}
|
|
45951
|
+
function summarizeRecallByRole(usageEvents) {
|
|
45952
|
+
const byRole = new Map;
|
|
45953
|
+
for (const event of usageEvents) {
|
|
45954
|
+
const role = event.agentRole ?? "unknown";
|
|
45955
|
+
const existing = byRole.get(role) ?? {
|
|
45956
|
+
agentRole: role,
|
|
45957
|
+
count: 0,
|
|
45958
|
+
memoryIds: {}
|
|
45959
|
+
};
|
|
45960
|
+
existing.count++;
|
|
45961
|
+
for (const memoryId of event.memoryIds) {
|
|
45962
|
+
existing.memoryIds[memoryId] = (existing.memoryIds[memoryId] ?? 0) + 1;
|
|
45963
|
+
}
|
|
45964
|
+
byRole.set(role, existing);
|
|
45965
|
+
}
|
|
45966
|
+
return byRole;
|
|
45967
|
+
}
|
|
45968
|
+
function buildSupersededChains(memories) {
|
|
45969
|
+
const byId = new Map(memories.map((memory) => [memory.id, memory]));
|
|
45970
|
+
const supersededIds = new Set(memories.filter((memory) => memory.supersededBy).map((memory) => memory.id));
|
|
45971
|
+
const roots = memories.filter((memory) => memory.supersededBy && !(memory.supersedes ?? []).some((id) => supersededIds.has(id)));
|
|
45972
|
+
return roots.map((root) => {
|
|
45973
|
+
const chain = [root.id];
|
|
45974
|
+
const seen = new Set(chain);
|
|
45975
|
+
let cursor = root;
|
|
45976
|
+
while (cursor?.supersededBy && !seen.has(cursor.supersededBy)) {
|
|
45977
|
+
chain.push(cursor.supersededBy);
|
|
45978
|
+
seen.add(cursor.supersededBy);
|
|
45979
|
+
cursor = byId.get(cursor.supersededBy);
|
|
45980
|
+
}
|
|
45981
|
+
return {
|
|
45982
|
+
rootId: root.id,
|
|
45983
|
+
chain,
|
|
45984
|
+
reason: typeof root.metadata.supersedeReason === "string" ? root.metadata.supersedeReason : undefined
|
|
45985
|
+
};
|
|
45986
|
+
});
|
|
45987
|
+
}
|
|
45988
|
+
function memorySort(a, b) {
|
|
45989
|
+
return b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id);
|
|
45990
|
+
}
|
|
45991
|
+
function proposalSort(a, b) {
|
|
45992
|
+
const aTime = a.reviewedAt ?? a.createdAt;
|
|
45993
|
+
const bTime = b.reviewedAt ?? b.createdAt;
|
|
45994
|
+
return bTime.localeCompare(aTime) || a.id.localeCompare(b.id);
|
|
45995
|
+
}
|
|
45996
|
+
var DEFAULT_LOW_UTILITY_MAX_CONFIDENCE = 0.45, DEFAULT_LOW_UTILITY_MIN_AGE_DAYS = 30;
|
|
45997
|
+
var init_maintenance = __esm(() => {
|
|
45998
|
+
init_schema2();
|
|
45999
|
+
});
|
|
46000
|
+
|
|
45718
46001
|
// src/memory/role-profiles.ts
|
|
45719
46002
|
function resolveMemoryRecallProfile(agentRole) {
|
|
45720
46003
|
const role = normalizeMemoryAgentRole(agentRole);
|
|
@@ -46102,16 +46385,21 @@ class LocalJsonlMemoryProvider {
|
|
|
46102
46385
|
}
|
|
46103
46386
|
async recordRecallUsage(event) {
|
|
46104
46387
|
await this.initialize();
|
|
46105
|
-
await this.audit("recall", event.bundleId,
|
|
46106
|
-
|
|
46107
|
-
|
|
46108
|
-
|
|
46109
|
-
|
|
46110
|
-
|
|
46111
|
-
|
|
46112
|
-
|
|
46113
|
-
|
|
46114
|
-
|
|
46388
|
+
await this.audit("recall", event.bundleId, undefined, event);
|
|
46389
|
+
}
|
|
46390
|
+
async listRecallUsage(filter = {}) {
|
|
46391
|
+
await this.initialize();
|
|
46392
|
+
const events = await readAuditEvents(this.pathFor("audit"));
|
|
46393
|
+
const usage = [];
|
|
46394
|
+
for (const event of events) {
|
|
46395
|
+
if (event.operation !== "recall")
|
|
46396
|
+
continue;
|
|
46397
|
+
const parsed = parseRecallUsageEvent(event);
|
|
46398
|
+
if (parsed)
|
|
46399
|
+
usage.push(parsed);
|
|
46400
|
+
}
|
|
46401
|
+
usage.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
46402
|
+
return usage.slice(0, filter.limit ?? usage.length);
|
|
46115
46403
|
}
|
|
46116
46404
|
async list(filter = {}) {
|
|
46117
46405
|
await this.initialize();
|
|
@@ -46131,7 +46419,9 @@ class LocalJsonlMemoryProvider {
|
|
|
46131
46419
|
return !Number.isFinite(expires) || expires > now;
|
|
46132
46420
|
});
|
|
46133
46421
|
}
|
|
46134
|
-
|
|
46422
|
+
if (!filter.includeInactive) {
|
|
46423
|
+
records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
|
|
46424
|
+
}
|
|
46135
46425
|
records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
46136
46426
|
return records.slice(0, filter.limit ?? records.length);
|
|
46137
46427
|
}
|
|
@@ -46243,6 +46533,41 @@ class LocalJsonlMemoryProvider {
|
|
|
46243
46533
|
await writeJsonlAtomic(this.pathFor("memories"), Array.from(this.memories.values()));
|
|
46244
46534
|
await this.audit("compact", "memories");
|
|
46245
46535
|
}
|
|
46536
|
+
async compactMaintenance(options = {}) {
|
|
46537
|
+
await this.initialize();
|
|
46538
|
+
const now = options.now ? new Date(options.now) : new Date;
|
|
46539
|
+
const kept = [];
|
|
46540
|
+
const result = {
|
|
46541
|
+
dryRun: options.dryRun !== false,
|
|
46542
|
+
removedDeleted: 0,
|
|
46543
|
+
removedSuperseded: 0,
|
|
46544
|
+
removedExpiredScratch: 0,
|
|
46545
|
+
remaining: 0
|
|
46546
|
+
};
|
|
46547
|
+
for (const memory of this.memories.values()) {
|
|
46548
|
+
const compactReason = shouldCompactMemory(memory, now);
|
|
46549
|
+
if (compactReason === "deleted") {
|
|
46550
|
+
result.removedDeleted++;
|
|
46551
|
+
continue;
|
|
46552
|
+
}
|
|
46553
|
+
if (compactReason === "superseded") {
|
|
46554
|
+
result.removedSuperseded++;
|
|
46555
|
+
continue;
|
|
46556
|
+
}
|
|
46557
|
+
if (compactReason === "expired_scratch") {
|
|
46558
|
+
result.removedExpiredScratch++;
|
|
46559
|
+
continue;
|
|
46560
|
+
}
|
|
46561
|
+
kept.push(memory);
|
|
46562
|
+
}
|
|
46563
|
+
result.remaining = kept.length;
|
|
46564
|
+
if (result.dryRun)
|
|
46565
|
+
return result;
|
|
46566
|
+
this.memories = new Map(kept.map((memory) => [memory.id, memory]));
|
|
46567
|
+
await writeJsonlAtomic(this.pathFor("memories"), kept);
|
|
46568
|
+
await this.audit("compact", "memories", "removed deleted, superseded, and expired scratch memories", result);
|
|
46569
|
+
return result;
|
|
46570
|
+
}
|
|
46246
46571
|
async audit(operation, targetId, reason, eventJson) {
|
|
46247
46572
|
const event = {
|
|
46248
46573
|
id: randomUUID3(),
|
|
@@ -46321,6 +46646,46 @@ async function readJsonl(filePath) {
|
|
|
46321
46646
|
}
|
|
46322
46647
|
return records;
|
|
46323
46648
|
}
|
|
46649
|
+
async function readAuditEvents(filePath) {
|
|
46650
|
+
const values = await readJsonl(filePath);
|
|
46651
|
+
const events = [];
|
|
46652
|
+
for (const value of values) {
|
|
46653
|
+
if (!value || typeof value !== "object")
|
|
46654
|
+
continue;
|
|
46655
|
+
const candidate = value;
|
|
46656
|
+
if (typeof candidate.id !== "string" || typeof candidate.operation !== "string" || typeof candidate.targetId !== "string" || typeof candidate.timestamp !== "string") {
|
|
46657
|
+
continue;
|
|
46658
|
+
}
|
|
46659
|
+
events.push(candidate);
|
|
46660
|
+
}
|
|
46661
|
+
return events;
|
|
46662
|
+
}
|
|
46663
|
+
function parseRecallUsageEvent(event) {
|
|
46664
|
+
const raw = event.eventJson ?? event.reason;
|
|
46665
|
+
if (typeof raw !== "string" && (!raw || typeof raw !== "object")) {
|
|
46666
|
+
return null;
|
|
46667
|
+
}
|
|
46668
|
+
try {
|
|
46669
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
46670
|
+
if (!Array.isArray(parsed.memoryIds) || typeof parsed.query !== "string") {
|
|
46671
|
+
return null;
|
|
46672
|
+
}
|
|
46673
|
+
return {
|
|
46674
|
+
bundleId: typeof parsed.bundleId === "string" ? parsed.bundleId : event.targetId,
|
|
46675
|
+
query: parsed.query,
|
|
46676
|
+
scopes: Array.isArray(parsed.scopes) ? parsed.scopes : [],
|
|
46677
|
+
kinds: Array.isArray(parsed.kinds) ? parsed.kinds : undefined,
|
|
46678
|
+
memoryIds: parsed.memoryIds.filter((memoryId) => typeof memoryId === "string"),
|
|
46679
|
+
scores: Array.isArray(parsed.scores) ? parsed.scores.filter((score) => typeof score === "number" && Number.isFinite(score)) : [],
|
|
46680
|
+
tokenEstimate: typeof parsed.tokenEstimate === "number" ? parsed.tokenEstimate : 0,
|
|
46681
|
+
agentRole: typeof parsed.agentRole === "string" ? parsed.agentRole : undefined,
|
|
46682
|
+
runId: typeof parsed.runId === "string" ? parsed.runId : undefined,
|
|
46683
|
+
timestamp: typeof parsed.timestamp === "string" ? parsed.timestamp : event.timestamp
|
|
46684
|
+
};
|
|
46685
|
+
} catch {
|
|
46686
|
+
return null;
|
|
46687
|
+
}
|
|
46688
|
+
}
|
|
46324
46689
|
async function appendJsonl(filePath, value) {
|
|
46325
46690
|
await mkdir8(path29.dirname(filePath), { recursive: true });
|
|
46326
46691
|
await appendFile4(filePath, `${JSON.stringify(value)}
|
|
@@ -46340,6 +46705,7 @@ var init_local_jsonl_provider = __esm(() => {
|
|
|
46340
46705
|
init_config3();
|
|
46341
46706
|
init_curator_decision_helpers();
|
|
46342
46707
|
init_errors6();
|
|
46708
|
+
init_maintenance();
|
|
46343
46709
|
init_schema2();
|
|
46344
46710
|
init_scoring();
|
|
46345
46711
|
});
|
|
@@ -46597,6 +46963,10 @@ class SQLiteMemoryProvider {
|
|
|
46597
46963
|
redaction: {
|
|
46598
46964
|
...DEFAULT_MEMORY_CONFIG.redaction,
|
|
46599
46965
|
...config3.redaction ?? {}
|
|
46966
|
+
},
|
|
46967
|
+
maintenance: {
|
|
46968
|
+
...DEFAULT_MEMORY_CONFIG.maintenance,
|
|
46969
|
+
...config3.maintenance ?? {}
|
|
46600
46970
|
}
|
|
46601
46971
|
};
|
|
46602
46972
|
}
|
|
@@ -46702,6 +47072,26 @@ class SQLiteMemoryProvider {
|
|
|
46702
47072
|
) VALUES (?, ?, ?, ?)`, [randomUUID4(), event.bundleId, event.timestamp, JSON.stringify(event)]);
|
|
46703
47073
|
await this.event("recall", event.bundleId, JSON.stringify(event));
|
|
46704
47074
|
}
|
|
47075
|
+
async listRecallUsage(filter = {}) {
|
|
47076
|
+
await this.initialize();
|
|
47077
|
+
const rows = typeof filter.limit === "number" ? this.requireDb().query(`SELECT usage_json
|
|
47078
|
+
FROM memory_recall_usage
|
|
47079
|
+
ORDER BY timestamp DESC
|
|
47080
|
+
LIMIT ?`).all(Math.max(1, Math.trunc(filter.limit))) : this.requireDb().query(`SELECT usage_json
|
|
47081
|
+
FROM memory_recall_usage
|
|
47082
|
+
ORDER BY timestamp DESC
|
|
47083
|
+
`).all();
|
|
47084
|
+
const events = [];
|
|
47085
|
+
for (const row of rows) {
|
|
47086
|
+
try {
|
|
47087
|
+
const parsed = JSON.parse(row.usage_json);
|
|
47088
|
+
if (Array.isArray(parsed.memoryIds) && typeof parsed.query === "string") {
|
|
47089
|
+
events.push(parsed);
|
|
47090
|
+
}
|
|
47091
|
+
} catch {}
|
|
47092
|
+
}
|
|
47093
|
+
return events;
|
|
47094
|
+
}
|
|
46705
47095
|
async list(filter = {}) {
|
|
46706
47096
|
await this.initialize();
|
|
46707
47097
|
let records = Array.from(this.memories.values());
|
|
@@ -46720,7 +47110,9 @@ class SQLiteMemoryProvider {
|
|
|
46720
47110
|
return !Number.isFinite(expires) || expires > now;
|
|
46721
47111
|
});
|
|
46722
47112
|
}
|
|
46723
|
-
|
|
47113
|
+
if (!filter.includeInactive) {
|
|
47114
|
+
records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
|
|
47115
|
+
}
|
|
46724
47116
|
records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
46725
47117
|
return records.slice(0, filter.limit ?? records.length);
|
|
46726
47118
|
}
|
|
@@ -46801,6 +47193,52 @@ class SQLiteMemoryProvider {
|
|
|
46801
47193
|
proposals: proposals.length
|
|
46802
47194
|
};
|
|
46803
47195
|
}
|
|
47196
|
+
async compactMaintenance(options = {}) {
|
|
47197
|
+
await this.initialize();
|
|
47198
|
+
const now = options.now ? new Date(options.now) : new Date;
|
|
47199
|
+
const kept = [];
|
|
47200
|
+
const removeIds = [];
|
|
47201
|
+
const result = {
|
|
47202
|
+
dryRun: options.dryRun !== false,
|
|
47203
|
+
removedDeleted: 0,
|
|
47204
|
+
removedSuperseded: 0,
|
|
47205
|
+
removedExpiredScratch: 0,
|
|
47206
|
+
remaining: 0
|
|
47207
|
+
};
|
|
47208
|
+
for (const memory of this.memories.values()) {
|
|
47209
|
+
const compactReason = shouldCompactMemory(memory, now);
|
|
47210
|
+
if (compactReason === "deleted") {
|
|
47211
|
+
result.removedDeleted++;
|
|
47212
|
+
removeIds.push(memory.id);
|
|
47213
|
+
continue;
|
|
47214
|
+
}
|
|
47215
|
+
if (compactReason === "superseded") {
|
|
47216
|
+
result.removedSuperseded++;
|
|
47217
|
+
removeIds.push(memory.id);
|
|
47218
|
+
continue;
|
|
47219
|
+
}
|
|
47220
|
+
if (compactReason === "expired_scratch") {
|
|
47221
|
+
result.removedExpiredScratch++;
|
|
47222
|
+
removeIds.push(memory.id);
|
|
47223
|
+
continue;
|
|
47224
|
+
}
|
|
47225
|
+
kept.push(memory);
|
|
47226
|
+
}
|
|
47227
|
+
result.remaining = kept.length;
|
|
47228
|
+
if (result.dryRun)
|
|
47229
|
+
return result;
|
|
47230
|
+
const db = this.requireDb();
|
|
47231
|
+
const compact = db.transaction(() => {
|
|
47232
|
+
for (const id of removeIds) {
|
|
47233
|
+
db.run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
47234
|
+
this.deleteMemoryFts(id);
|
|
47235
|
+
}
|
|
47236
|
+
this.insertEvent("compact", "memory_items", "removed deleted, superseded, and expired scratch memories", JSON.stringify(result));
|
|
47237
|
+
});
|
|
47238
|
+
compact();
|
|
47239
|
+
this.memories = new Map(kept.map((memory) => [memory.id, memory]));
|
|
47240
|
+
return result;
|
|
47241
|
+
}
|
|
46804
47242
|
hasMigration(name) {
|
|
46805
47243
|
const row = this.requireDb().query("SELECT version, name FROM schema_migrations WHERE name = ? LIMIT 1").get(name);
|
|
46806
47244
|
return Boolean(row);
|
|
@@ -47277,6 +47715,7 @@ var init_sqlite_provider = __esm(() => {
|
|
|
47277
47715
|
init_curator_decision_helpers();
|
|
47278
47716
|
init_errors6();
|
|
47279
47717
|
init_jsonl_migration();
|
|
47718
|
+
init_maintenance();
|
|
47280
47719
|
init_schema2();
|
|
47281
47720
|
init_scoring();
|
|
47282
47721
|
FTS_INDEX_COLUMNS = [
|
|
@@ -47804,6 +48243,7 @@ var init_memory = __esm(() => {
|
|
|
47804
48243
|
init_injector();
|
|
47805
48244
|
init_jsonl_migration();
|
|
47806
48245
|
init_local_jsonl_provider();
|
|
48246
|
+
init_maintenance();
|
|
47807
48247
|
init_prompt_block();
|
|
47808
48248
|
init_recall_planner();
|
|
47809
48249
|
init_redaction();
|
|
@@ -47822,6 +48262,10 @@ async function handleMemoryCommand(_directory, _args) {
|
|
|
47822
48262
|
"## Swarm Memory",
|
|
47823
48263
|
"",
|
|
47824
48264
|
"- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
|
|
48265
|
+
"- `/swarm memory pending` - show pending proposals and recent rejection reasons",
|
|
48266
|
+
"- `/swarm memory recall-log` - summarize recall usage by agent role and memory ID",
|
|
48267
|
+
"- `/swarm memory stale` - list expired scratch, superseded, deleted, and low-utility memories",
|
|
48268
|
+
"- `/swarm memory compact` - dry-run compaction; pass `--confirm` to remove deleted, superseded, and expired scratch records",
|
|
47825
48269
|
"- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
|
|
47826
48270
|
"- `/swarm memory import` - import `.swarm/memory/{memories,proposals}.jsonl` into SQLite",
|
|
47827
48271
|
"- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration",
|
|
@@ -47843,6 +48287,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
47843
48287
|
`- Storage: \`${storageDir}\``,
|
|
47844
48288
|
`- SQLite path: \`${sqlitePath}\``,
|
|
47845
48289
|
`- SQLite database exists: \`${existsSync20(sqlitePath)}\``,
|
|
48290
|
+
`- Automatic destructive cleanup: \`disabled\``,
|
|
47846
48291
|
"",
|
|
47847
48292
|
"### Legacy JSONL"
|
|
47848
48293
|
];
|
|
@@ -47867,6 +48312,119 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
47867
48312
|
return lines.join(`
|
|
47868
48313
|
`);
|
|
47869
48314
|
}
|
|
48315
|
+
async function handleMemoryPendingCommand(directory, args) {
|
|
48316
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48317
|
+
usage: "Usage: /swarm memory pending [--limit <n>]",
|
|
48318
|
+
allowConfirm: false
|
|
48319
|
+
});
|
|
48320
|
+
if ("error" in parsed)
|
|
48321
|
+
return parsed.error;
|
|
48322
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48323
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48324
|
+
try {
|
|
48325
|
+
await provider.initialize?.();
|
|
48326
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48327
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48328
|
+
});
|
|
48329
|
+
const lines = [
|
|
48330
|
+
"## Swarm Memory Pending",
|
|
48331
|
+
"",
|
|
48332
|
+
`- Pending proposals shown: \`${report.pendingProposals.length}\``,
|
|
48333
|
+
`- Rejected proposal reasons shown: \`${report.rejectedProposalReasons.length}\``
|
|
48334
|
+
];
|
|
48335
|
+
appendProposalLines(lines, "Pending proposals", report.pendingProposals);
|
|
48336
|
+
appendProposalLines(lines, "Rejected proposal reasons", report.rejectedProposalReasons);
|
|
48337
|
+
return lines.join(`
|
|
48338
|
+
`);
|
|
48339
|
+
} finally {
|
|
48340
|
+
await provider.close?.();
|
|
48341
|
+
}
|
|
48342
|
+
}
|
|
48343
|
+
async function handleMemoryRecallLogCommand(directory, args) {
|
|
48344
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48345
|
+
usage: "Usage: /swarm memory recall-log [--limit <n>]",
|
|
48346
|
+
allowConfirm: false
|
|
48347
|
+
});
|
|
48348
|
+
if ("error" in parsed)
|
|
48349
|
+
return parsed.error;
|
|
48350
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48351
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48352
|
+
try {
|
|
48353
|
+
await provider.initialize?.();
|
|
48354
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48355
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48356
|
+
});
|
|
48357
|
+
const lines = [
|
|
48358
|
+
"## Swarm Memory Recall Log",
|
|
48359
|
+
"",
|
|
48360
|
+
`- Recall events scanned: \`${report.recallEventCount}\``,
|
|
48361
|
+
`- Most-recalled memories shown: \`${report.mostRecalledMemories.length}\``,
|
|
48362
|
+
`- Never-recalled memories shown: \`${report.neverRecalledMemories.length}\``
|
|
48363
|
+
];
|
|
48364
|
+
appendRecallRoleLines(lines, report.recallByAgentRole);
|
|
48365
|
+
appendRecallMemoryLines(lines, report.mostRecalledMemories);
|
|
48366
|
+
appendMemoryLines(lines, "Never-recalled memories", report.neverRecalledMemories);
|
|
48367
|
+
return lines.join(`
|
|
48368
|
+
`);
|
|
48369
|
+
} finally {
|
|
48370
|
+
await provider.close?.();
|
|
48371
|
+
}
|
|
48372
|
+
}
|
|
48373
|
+
async function handleMemoryStaleCommand(directory, args) {
|
|
48374
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48375
|
+
usage: "Usage: /swarm memory stale [--limit <n>]",
|
|
48376
|
+
allowConfirm: false
|
|
48377
|
+
});
|
|
48378
|
+
if ("error" in parsed)
|
|
48379
|
+
return parsed.error;
|
|
48380
|
+
const config3 = resolveCommandMemoryConfig(directory);
|
|
48381
|
+
const provider = createMaintenanceProvider(directory, config3);
|
|
48382
|
+
try {
|
|
48383
|
+
await provider.initialize?.();
|
|
48384
|
+
const report = await buildMemoryMaintenanceReport(provider, {
|
|
48385
|
+
...maintenanceReportOptions(config3, parsed.limit)
|
|
48386
|
+
});
|
|
48387
|
+
const lines = [
|
|
48388
|
+
"## Swarm Memory Stale",
|
|
48389
|
+
"",
|
|
48390
|
+
`- Active memories: \`${report.activeMemories}\``,
|
|
48391
|
+
`- Expired scratch memories shown: \`${report.expiredScratchMemories.length}\``,
|
|
48392
|
+
`- Deleted tombstones shown: \`${report.deletedMemories.length}\``,
|
|
48393
|
+
`- Superseded memories shown: \`${report.supersededMemories.length}\``,
|
|
48394
|
+
`- Low-utility memories shown: \`${report.lowUtilityMemories.length}\``
|
|
48395
|
+
];
|
|
48396
|
+
appendMemoryLines(lines, "Expired scratch memories", report.expiredScratchMemories);
|
|
48397
|
+
appendMemoryLines(lines, "Deleted tombstones", report.deletedMemories);
|
|
48398
|
+
appendSupersededChains(lines, report);
|
|
48399
|
+
appendMemoryLines(lines, "Low-utility memories", report.lowUtilityMemories);
|
|
48400
|
+
return lines.join(`
|
|
48401
|
+
`);
|
|
48402
|
+
} finally {
|
|
48403
|
+
await provider.close?.();
|
|
48404
|
+
}
|
|
48405
|
+
}
|
|
48406
|
+
async function handleMemoryCompactCommand(directory, args) {
|
|
48407
|
+
const parsed = parseMaintenanceArgs(args, {
|
|
48408
|
+
usage: "Usage: /swarm memory compact [--confirm]",
|
|
48409
|
+
allowConfirm: true,
|
|
48410
|
+
allowLimit: false
|
|
48411
|
+
});
|
|
48412
|
+
if ("error" in parsed)
|
|
48413
|
+
return parsed.error;
|
|
48414
|
+
const provider = createMaintenanceProvider(directory, resolveCommandMemoryConfig(directory));
|
|
48415
|
+
try {
|
|
48416
|
+
await provider.initialize?.();
|
|
48417
|
+
if (!provider.compactMaintenance) {
|
|
48418
|
+
return "Memory provider does not support compaction.";
|
|
48419
|
+
}
|
|
48420
|
+
const result = await provider.compactMaintenance({
|
|
48421
|
+
dryRun: !parsed.confirm
|
|
48422
|
+
});
|
|
48423
|
+
return formatCompactResult(result, parsed.confirm);
|
|
48424
|
+
} finally {
|
|
48425
|
+
await provider.close?.();
|
|
48426
|
+
}
|
|
48427
|
+
}
|
|
47870
48428
|
async function handleMemoryMigrateCommand(directory, _args) {
|
|
47871
48429
|
const config3 = {
|
|
47872
48430
|
...resolveCommandMemoryConfig(directory),
|
|
@@ -47923,6 +48481,16 @@ async function handleMemoryExportCommand(directory, _args) {
|
|
|
47923
48481
|
await provider.close?.();
|
|
47924
48482
|
}
|
|
47925
48483
|
}
|
|
48484
|
+
function createMaintenanceProvider(directory, config3) {
|
|
48485
|
+
return createConfiguredMemoryProvider(directory, config3);
|
|
48486
|
+
}
|
|
48487
|
+
function maintenanceReportOptions(config3, limit) {
|
|
48488
|
+
return {
|
|
48489
|
+
limit,
|
|
48490
|
+
lowUtilityMaxConfidence: config3.maintenance.lowUtilityMaxConfidence,
|
|
48491
|
+
lowUtilityMinAgeDays: config3.maintenance.lowUtilityMinAgeDays
|
|
48492
|
+
};
|
|
48493
|
+
}
|
|
47926
48494
|
async function handleMemoryEvaluateCommand(directory, args) {
|
|
47927
48495
|
const parsed = parseEvaluateArgs(directory, args);
|
|
47928
48496
|
if ("error" in parsed)
|
|
@@ -47981,6 +48549,28 @@ function parseEvaluateArgs(directory, args) {
|
|
|
47981
48549
|
}
|
|
47982
48550
|
return { json: json3, fixtureDirectory };
|
|
47983
48551
|
}
|
|
48552
|
+
function parseMaintenanceArgs(args, options) {
|
|
48553
|
+
let limit = 20;
|
|
48554
|
+
let confirm = false;
|
|
48555
|
+
const allowLimit = options.allowLimit ?? true;
|
|
48556
|
+
for (let i = 0;i < args.length; i++) {
|
|
48557
|
+
const arg = args[i];
|
|
48558
|
+
if (arg === "--confirm" && options.allowConfirm) {
|
|
48559
|
+
confirm = true;
|
|
48560
|
+
continue;
|
|
48561
|
+
}
|
|
48562
|
+
if (arg === "--limit" && allowLimit) {
|
|
48563
|
+
const next = args[i + 1];
|
|
48564
|
+
if (!next || !/^\d+$/.test(next))
|
|
48565
|
+
return { error: options.usage };
|
|
48566
|
+
limit = Math.min(100, Math.max(1, Number(next)));
|
|
48567
|
+
i++;
|
|
48568
|
+
continue;
|
|
48569
|
+
}
|
|
48570
|
+
return { error: options.usage };
|
|
48571
|
+
}
|
|
48572
|
+
return { limit, confirm };
|
|
48573
|
+
}
|
|
47984
48574
|
function resolvePackageRootFromModule(modulePath) {
|
|
47985
48575
|
const moduleDir = path33.dirname(modulePath);
|
|
47986
48576
|
const leaf = path33.basename(moduleDir);
|
|
@@ -48031,6 +48621,80 @@ function appendInvalidRows(lines, invalidRows) {
|
|
|
48031
48621
|
lines.push(`- ... ${invalidRows.length - 20} more`);
|
|
48032
48622
|
}
|
|
48033
48623
|
}
|
|
48624
|
+
function appendProposalLines(lines, title, proposals) {
|
|
48625
|
+
lines.push("", `### ${title}`);
|
|
48626
|
+
if (proposals.length === 0) {
|
|
48627
|
+
lines.push("- none");
|
|
48628
|
+
return;
|
|
48629
|
+
}
|
|
48630
|
+
for (const proposal of proposals) {
|
|
48631
|
+
const reason = proposal.status === "rejected" ? ` - ${proposal.rejectionReason ?? "no reason recorded"}` : "";
|
|
48632
|
+
lines.push(`- \`${proposal.id}\` ${proposal.operation} ${proposal.targetMemoryId ?? proposal.proposedRecord?.id ?? "new"} (${proposal.status})${reason}`);
|
|
48633
|
+
}
|
|
48634
|
+
}
|
|
48635
|
+
function appendMemoryLines(lines, title, memories) {
|
|
48636
|
+
lines.push("", `### ${title}`);
|
|
48637
|
+
if (memories.length === 0) {
|
|
48638
|
+
lines.push("- none");
|
|
48639
|
+
return;
|
|
48640
|
+
}
|
|
48641
|
+
for (const memory of memories) {
|
|
48642
|
+
lines.push(`- \`${memory.id}\` ${memory.kind} confidence=${memory.confidence.toFixed(2)} updated=${memory.updatedAt} - ${truncate(memory.text, 100)}`);
|
|
48643
|
+
}
|
|
48644
|
+
}
|
|
48645
|
+
function appendRecallRoleLines(lines, roles) {
|
|
48646
|
+
lines.push("", "### Recall by agent role");
|
|
48647
|
+
if (roles.length === 0) {
|
|
48648
|
+
lines.push("- none");
|
|
48649
|
+
return;
|
|
48650
|
+
}
|
|
48651
|
+
for (const role of roles) {
|
|
48652
|
+
const memoryCount = Object.keys(role.memoryIds).length;
|
|
48653
|
+
lines.push(`- \`${role.agentRole}\`: ${role.count} recall event(s), ${memoryCount} memory ID(s)`);
|
|
48654
|
+
}
|
|
48655
|
+
}
|
|
48656
|
+
function appendRecallMemoryLines(lines, memories) {
|
|
48657
|
+
lines.push("", "### Most-recalled memories");
|
|
48658
|
+
if (memories.length === 0) {
|
|
48659
|
+
lines.push("- none");
|
|
48660
|
+
return;
|
|
48661
|
+
}
|
|
48662
|
+
for (const memory of memories) {
|
|
48663
|
+
lines.push(`- \`${memory.memoryId}\`: ${memory.count} hit(s), last=${memory.lastRecalledAt}, avgScore=${memory.averageScore.toFixed(3)}`);
|
|
48664
|
+
}
|
|
48665
|
+
}
|
|
48666
|
+
function appendSupersededChains(lines, report) {
|
|
48667
|
+
lines.push("", "### Superseded chains");
|
|
48668
|
+
if (report.supersededChains.length === 0) {
|
|
48669
|
+
lines.push("- none");
|
|
48670
|
+
return;
|
|
48671
|
+
}
|
|
48672
|
+
for (const chain of report.supersededChains) {
|
|
48673
|
+
const reason = chain.reason ? ` - ${chain.reason}` : "";
|
|
48674
|
+
lines.push(`- ${chain.chain.map((id) => `\`${id}\``).join(" -> ")}${reason}`);
|
|
48675
|
+
}
|
|
48676
|
+
}
|
|
48677
|
+
function formatCompactResult(result, confirmed) {
|
|
48678
|
+
const lines = [
|
|
48679
|
+
"## Swarm Memory Compact",
|
|
48680
|
+
"",
|
|
48681
|
+
`- Mode: \`${confirmed ? "confirmed" : "dry-run"}\``,
|
|
48682
|
+
`- Deleted tombstones: \`${result.removedDeleted}\``,
|
|
48683
|
+
`- Superseded records: \`${result.removedSuperseded}\``,
|
|
48684
|
+
`- Expired scratch records: \`${result.removedExpiredScratch}\``,
|
|
48685
|
+
`- Remaining memories: \`${result.remaining}\``
|
|
48686
|
+
];
|
|
48687
|
+
if (!confirmed) {
|
|
48688
|
+
lines.push("", "No records were removed. Re-run `/swarm memory compact --confirm` to apply this compaction.");
|
|
48689
|
+
}
|
|
48690
|
+
return lines.join(`
|
|
48691
|
+
`);
|
|
48692
|
+
}
|
|
48693
|
+
function truncate(value, maxLength) {
|
|
48694
|
+
if (value.length <= maxLength)
|
|
48695
|
+
return value;
|
|
48696
|
+
return `${value.slice(0, maxLength - 3)}...`;
|
|
48697
|
+
}
|
|
48034
48698
|
var PACKAGE_ROOT;
|
|
48035
48699
|
var init_memory2 = __esm(() => {
|
|
48036
48700
|
init_loader();
|
|
@@ -55699,7 +56363,7 @@ async function handleTurboCommand(directory, args, sessionID) {
|
|
|
55699
56363
|
const arg0 = args[0]?.toLowerCase();
|
|
55700
56364
|
const arg1 = args[1]?.toLowerCase();
|
|
55701
56365
|
if (arg0 === "status") {
|
|
55702
|
-
return
|
|
56366
|
+
return buildStatusMessage2(session, directory, sessionID);
|
|
55703
56367
|
}
|
|
55704
56368
|
const isTurboOn = session.turboMode;
|
|
55705
56369
|
const isLeanActive = session.leanTurboActive === true;
|
|
@@ -55830,7 +56494,7 @@ function enableLeanTurbo(session, directory, sessionID) {
|
|
|
55830
56494
|
`Full-Auto: ${fullAutoActive ? "active" : "inactive"})`
|
|
55831
56495
|
].join(" ");
|
|
55832
56496
|
}
|
|
55833
|
-
function
|
|
56497
|
+
function buildStatusMessage2(session, directory, sessionID) {
|
|
55834
56498
|
if (!session.turboMode) {
|
|
55835
56499
|
return "Turbo: off";
|
|
55836
56500
|
}
|
|
@@ -56090,7 +56754,7 @@ function classifySwarmCommandToolUse(resolved) {
|
|
|
56090
56754
|
return { allowed: true };
|
|
56091
56755
|
return {
|
|
56092
56756
|
allowed: false,
|
|
56093
|
-
message: "Use `/swarm memory status`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import and
|
|
56757
|
+
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."
|
|
56094
56758
|
};
|
|
56095
56759
|
}
|
|
56096
56760
|
if (canonicalKey === "memory evaluate") {
|
|
@@ -56103,6 +56767,17 @@ function classifySwarmCommandToolUse(resolved) {
|
|
|
56103
56767
|
message: "Usage through swarm_command: `/swarm memory evaluate --json`. Custom fixture directories are only available through direct user command execution."
|
|
56104
56768
|
};
|
|
56105
56769
|
}
|
|
56770
|
+
if (canonicalKey === "memory pending" || canonicalKey === "memory recall-log" || canonicalKey === "memory stale") {
|
|
56771
|
+
if (args.length === 0)
|
|
56772
|
+
return { allowed: true };
|
|
56773
|
+
if (args.length === 2 && args[0] === "--limit" && /^\d+$/.test(args[1])) {
|
|
56774
|
+
return { allowed: true };
|
|
56775
|
+
}
|
|
56776
|
+
return {
|
|
56777
|
+
allowed: false,
|
|
56778
|
+
message: `Usage through swarm_command: \`/swarm ${canonicalKey}\` or ` + `\`/swarm ${canonicalKey} --limit <n>\`.`
|
|
56779
|
+
};
|
|
56780
|
+
}
|
|
56106
56781
|
if (canonicalKey === "retrieve") {
|
|
56107
56782
|
if (args.length !== 1 || !SUMMARY_ID_PATTERN.test(args[0])) {
|
|
56108
56783
|
return {
|
|
@@ -56154,7 +56829,7 @@ function classifySwarmCommandChatFallbackUse(resolved) {
|
|
|
56154
56829
|
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."
|
|
56155
56830
|
};
|
|
56156
56831
|
}
|
|
56157
|
-
if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore" || canonicalKey === "memory import" || canonicalKey === "memory migrate") {
|
|
56832
|
+
if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore" || canonicalKey === "memory import" || canonicalKey === "memory migrate" || canonicalKey === "memory compact") {
|
|
56158
56833
|
return {
|
|
56159
56834
|
allowed: false,
|
|
56160
56835
|
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."
|
|
@@ -56187,6 +56862,10 @@ var init_tool_policy = __esm(() => {
|
|
|
56187
56862
|
"knowledge",
|
|
56188
56863
|
"memory",
|
|
56189
56864
|
"memory status",
|
|
56865
|
+
"memory pending",
|
|
56866
|
+
"memory recall-log",
|
|
56867
|
+
"memory compact",
|
|
56868
|
+
"memory stale",
|
|
56190
56869
|
"memory export",
|
|
56191
56870
|
"memory evaluate",
|
|
56192
56871
|
"memory import",
|
|
@@ -56213,6 +56892,9 @@ var init_tool_policy = __esm(() => {
|
|
|
56213
56892
|
"knowledge",
|
|
56214
56893
|
"memory",
|
|
56215
56894
|
"memory status",
|
|
56895
|
+
"memory pending",
|
|
56896
|
+
"memory recall-log",
|
|
56897
|
+
"memory stale",
|
|
56216
56898
|
"memory export",
|
|
56217
56899
|
"memory evaluate",
|
|
56218
56900
|
"sync-plan",
|
|
@@ -56225,7 +56907,8 @@ var init_tool_policy = __esm(() => {
|
|
|
56225
56907
|
"rollback",
|
|
56226
56908
|
"checkpoint",
|
|
56227
56909
|
"memory import",
|
|
56228
|
-
"memory migrate"
|
|
56910
|
+
"memory migrate",
|
|
56911
|
+
"memory compact"
|
|
56229
56912
|
]);
|
|
56230
56913
|
NO_ARGS = new Set([
|
|
56231
56914
|
"agents",
|
|
@@ -56278,7 +56961,6 @@ __export(exports_commands, {
|
|
|
56278
56961
|
handleMemoryMigrateCommand: () => handleMemoryMigrateCommand,
|
|
56279
56962
|
handleMemoryImportCommand: () => handleMemoryImportCommand,
|
|
56280
56963
|
handleMemoryExportCommand: () => handleMemoryExportCommand,
|
|
56281
|
-
handleMemoryEvaluateCommand: () => handleMemoryEvaluateCommand,
|
|
56282
56964
|
handleMemoryCommand: () => handleMemoryCommand,
|
|
56283
56965
|
handleKnowledgeRestoreCommand: () => handleKnowledgeRestoreCommand,
|
|
56284
56966
|
handleKnowledgeQuarantineCommand: () => handleKnowledgeQuarantineCommand,
|
|
@@ -56298,6 +56980,7 @@ __export(exports_commands, {
|
|
|
56298
56980
|
handleCurateCommand: () => handleCurateCommand,
|
|
56299
56981
|
handleCouncilCommand: () => handleCouncilCommand,
|
|
56300
56982
|
handleConfigCommand: () => handleConfigCommand,
|
|
56983
|
+
handleConcurrencyCommand: () => handleConcurrencyCommand,
|
|
56301
56984
|
handleCloseCommand: () => handleCloseCommand,
|
|
56302
56985
|
handleClarifyCommand: () => handleClarifyCommand,
|
|
56303
56986
|
handleCheckpointCommand: () => handleCheckpointCommand,
|
|
@@ -56544,6 +57227,7 @@ var init_commands = __esm(() => {
|
|
|
56544
57227
|
init_close();
|
|
56545
57228
|
init_command_dispatch();
|
|
56546
57229
|
init_command_names();
|
|
57230
|
+
init_concurrency();
|
|
56547
57231
|
init_config2();
|
|
56548
57232
|
init_council();
|
|
56549
57233
|
init_curate();
|
|
@@ -56764,6 +57448,7 @@ var init_registry = __esm(() => {
|
|
|
56764
57448
|
init_benchmark();
|
|
56765
57449
|
init_checkpoint2();
|
|
56766
57450
|
init_close();
|
|
57451
|
+
init_concurrency();
|
|
56767
57452
|
init_config2();
|
|
56768
57453
|
init_council();
|
|
56769
57454
|
init_curate();
|
|
@@ -57008,6 +57693,23 @@ var init_registry = __esm(() => {
|
|
|
57008
57693
|
aliasOf: "finalize",
|
|
57009
57694
|
deprecated: true
|
|
57010
57695
|
},
|
|
57696
|
+
concurrency: {
|
|
57697
|
+
handler: (ctx) => handleConcurrencyCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
57698
|
+
description: "Manage runtime concurrency override for plan execution [set|status|reset]",
|
|
57699
|
+
args: "set <N|preset>, status, reset",
|
|
57700
|
+
details: `Sets, queries, or clears a session-scoped concurrency override for max_concurrent_tasks during plan execution.
|
|
57701
|
+
When set, the override takes precedence over the plan's locked execution_profile.max_concurrent_tasks.
|
|
57702
|
+
` + `The override is session-scoped \u2014 it does not modify the plan and is cleared on session reset.
|
|
57703
|
+
` + `
|
|
57704
|
+
Subcommands:
|
|
57705
|
+
` + ` concurrency set <N> \u2014 Set session concurrency to N (1-64)
|
|
57706
|
+
` + ` concurrency set <preset> \u2014 Set to preset: min (1), medium (3), max (8)
|
|
57707
|
+
` + ` concurrency status \u2014 Show effective concurrency (override, plan baseline, operational effective)
|
|
57708
|
+
` + ` concurrency reset \u2014 Clear the session concurrency override
|
|
57709
|
+
` + `
|
|
57710
|
+
` + "Session-scoped \u2014 resets on new session.",
|
|
57711
|
+
category: "utility"
|
|
57712
|
+
},
|
|
57011
57713
|
simulate: {
|
|
57012
57714
|
handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
|
|
57013
57715
|
description: "Dry-run hidden coupling analysis with configurable thresholds",
|
|
@@ -57201,6 +57903,34 @@ Subcommands:
|
|
|
57201
57903
|
args: "",
|
|
57202
57904
|
category: "diagnostics"
|
|
57203
57905
|
},
|
|
57906
|
+
"memory pending": {
|
|
57907
|
+
handler: (ctx) => handleMemoryPendingCommand(ctx.directory, ctx.args),
|
|
57908
|
+
description: "Show pending Swarm memory proposals and rejection reasons",
|
|
57909
|
+
subcommandOf: "memory",
|
|
57910
|
+
args: "--limit <n>",
|
|
57911
|
+
category: "diagnostics"
|
|
57912
|
+
},
|
|
57913
|
+
"memory recall-log": {
|
|
57914
|
+
handler: (ctx) => handleMemoryRecallLogCommand(ctx.directory, ctx.args),
|
|
57915
|
+
description: "Summarize Swarm memory recall usage",
|
|
57916
|
+
subcommandOf: "memory",
|
|
57917
|
+
args: "--limit <n>",
|
|
57918
|
+
category: "diagnostics"
|
|
57919
|
+
},
|
|
57920
|
+
"memory compact": {
|
|
57921
|
+
handler: (ctx) => handleMemoryCompactCommand(ctx.directory, ctx.args),
|
|
57922
|
+
description: "Compact deleted, superseded, and expired scratch memories",
|
|
57923
|
+
subcommandOf: "memory",
|
|
57924
|
+
args: "--confirm",
|
|
57925
|
+
category: "utility"
|
|
57926
|
+
},
|
|
57927
|
+
"memory stale": {
|
|
57928
|
+
handler: (ctx) => handleMemoryStaleCommand(ctx.directory, ctx.args),
|
|
57929
|
+
description: "List stale and low-utility Swarm memories",
|
|
57930
|
+
subcommandOf: "memory",
|
|
57931
|
+
args: "--limit <n>",
|
|
57932
|
+
category: "diagnostics"
|
|
57933
|
+
},
|
|
57204
57934
|
"memory export": {
|
|
57205
57935
|
handler: (ctx) => handleMemoryExportCommand(ctx.directory, ctx.args),
|
|
57206
57936
|
description: "Export current Swarm memory to JSONL files",
|