@yemi33/minions 0.1.2369 → 0.1.2370
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/dashboard/js/memory-search.js +112 -0
- package/dashboard/js/render-kb.js +15 -0
- package/dashboard/js/settings.js +15 -0
- package/dashboard/pages/inbox.html +1 -1
- package/dashboard.js +68 -1
- package/docs/team-memory.md +18 -4
- package/engine/consolidation.js +72 -1
- package/engine/db/migrations/017-agent-memory.js +208 -0
- package/engine/features.js +6 -0
- package/engine/lifecycle.js +83 -0
- package/engine/memory-retrieval.js +165 -0
- package/engine/memory-store.js +365 -0
- package/engine/playbook.js +56 -2
- package/engine/shared.js +5 -0
- package/package.json +1 -1
package/engine/playbook.js
CHANGED
|
@@ -11,6 +11,9 @@ const shared = require('./shared');
|
|
|
11
11
|
const queries = require('./queries');
|
|
12
12
|
const { wrapUntrusted, buildSource } = require('./untrusted-fence');
|
|
13
13
|
const { MINIONS_BRAND_URL } = require('./comment-format');
|
|
14
|
+
const features = require('./features');
|
|
15
|
+
const memoryRetrieval = require('./memory-retrieval');
|
|
16
|
+
const memoryStore = require('./memory-store');
|
|
14
17
|
|
|
15
18
|
const { safeJsonArr, safeRead, getProjects, log, ts, dateStamp, truncateTextBytes, ENGINE_DEFAULTS, WI_STATUS, WORK_TYPE, PR_STATUS, DISPATCH_RESULT, getProjectOrg } = shared;
|
|
16
19
|
const { getConfig, getDispatch, getNotes, getPrs, getKnowledgeBaseIndex, AGENTS_DIR } = queries;
|
|
@@ -716,10 +719,61 @@ function renderPlaybook(type, vars) {
|
|
|
716
719
|
inertAppendices.push('\n\n---\n\n## Pinned Context (CRITICAL — READ FIRST)\n\n' + (fenced || pinnedContent));
|
|
717
720
|
}
|
|
718
721
|
|
|
722
|
+
// Structured memory rollout is deliberately two-stage. The feature flag
|
|
723
|
+
// turns retrieval on; shadow mode (default) records selection telemetry but
|
|
724
|
+
// leaves the legacy notes/personal-memory prompt unchanged. Once shadow mode
|
|
725
|
+
// is disabled, a non-empty bounded retrieval pack replaces those broad
|
|
726
|
+
// appendices. Pinned operator context always remains fully visible.
|
|
727
|
+
let relevantMemoryInjected = false;
|
|
728
|
+
if (features.isFeatureOn('memoryRetrieval', configEarly)) {
|
|
729
|
+
const engineConfig = configEarly.engine || {};
|
|
730
|
+
const shadow = engineConfig.memoryRetrievalShadowMode ?? ENGINE_DEFAULTS.memoryRetrievalShadowMode;
|
|
731
|
+
try {
|
|
732
|
+
const retrieved = memoryRetrieval.retrieveRelevantMemory({
|
|
733
|
+
workItemId: vars.item_id || vars.task_id || '',
|
|
734
|
+
title: vars.item_name || vars.pr_title || '',
|
|
735
|
+
description: vars.item_description || vars.task_description || vars.pr_description || '',
|
|
736
|
+
type: vars.work_type || type,
|
|
737
|
+
project: projectName || '',
|
|
738
|
+
agent: vars.agent_id || '',
|
|
739
|
+
failureClass: vars.failure_class || '',
|
|
740
|
+
sourcePlan: vars.source_plan || '',
|
|
741
|
+
references: vars.references || '',
|
|
742
|
+
prTitle: vars.pr_title || '',
|
|
743
|
+
prBranch: vars.pr_branch || '',
|
|
744
|
+
}, {
|
|
745
|
+
topK: engineConfig.memoryRetrievalTopK ?? ENGINE_DEFAULTS.memoryRetrievalTopK,
|
|
746
|
+
maxBytes: engineConfig.memoryRetrievalMaxBytes ?? ENGINE_DEFAULTS.memoryRetrievalMaxBytes,
|
|
747
|
+
candidateLimit: engineConfig.memoryRetrievalCandidateLimit ?? ENGINE_DEFAULTS.memoryRetrievalCandidateLimit,
|
|
748
|
+
});
|
|
749
|
+
memoryStore.recordRetrievalRun({
|
|
750
|
+
workItemId: vars.item_id || vars.task_id || null,
|
|
751
|
+
project: projectName,
|
|
752
|
+
agent: vars.agent_id || null,
|
|
753
|
+
query: retrieved.query,
|
|
754
|
+
candidateCount: retrieved.candidates.length,
|
|
755
|
+
selectedCount: retrieved.selected.length,
|
|
756
|
+
selectedBytes: retrieved.bytes,
|
|
757
|
+
durationMs: retrieved.durationMs,
|
|
758
|
+
shadow,
|
|
759
|
+
});
|
|
760
|
+
if (!shadow && retrieved.text) {
|
|
761
|
+
const fenced = wrapUntrusted(
|
|
762
|
+
retrieved.text,
|
|
763
|
+
buildSource('memory-retrieval', { item: vars.item_id || vars.task_id || 'unknown' })
|
|
764
|
+
);
|
|
765
|
+
inertAppendices.push('\n\n---\n\n## Relevant Memory (task-selected; verify against live code)\n\n' + (fenced || retrieved.text));
|
|
766
|
+
relevantMemoryInjected = true;
|
|
767
|
+
}
|
|
768
|
+
} catch (e) {
|
|
769
|
+
log('warn', `Memory retrieval failed for ${vars.item_id || vars.task_id || type}; using legacy memory: ${e.message}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
719
773
|
// Inject team notes (single injection point — not in buildAgentContext) — capped via ENGINE_DEFAULTS.
|
|
720
774
|
// F5: wrap in <UNTRUSTED-INPUT> fence — notes.md is an LLM-consolidated mix
|
|
721
775
|
// of agent inbox notes (semi-trusted) and human edits.
|
|
722
|
-
let notes = getNotes();
|
|
776
|
+
let notes = relevantMemoryInjected ? '' : getNotes();
|
|
723
777
|
if (notes) {
|
|
724
778
|
if (Buffer.byteLength(notes, 'utf8') > ENGINE_DEFAULTS.maxNotesPromptBytes) {
|
|
725
779
|
const sections = notes.split(/(?=^### )/m);
|
|
@@ -738,7 +792,7 @@ function renderPlaybook(type, vars) {
|
|
|
738
792
|
// notes budget; missing file degrades gracefully (silent skip).
|
|
739
793
|
// F5: fence — agent-authored inbox notes routed into this file; any agent
|
|
740
794
|
// could include attacker-controlled quoted material.
|
|
741
|
-
const agentIdForMemory = vars.agent_id;
|
|
795
|
+
const agentIdForMemory = relevantMemoryInjected ? '' : vars.agent_id;
|
|
742
796
|
if (agentIdForMemory && /^[a-z][a-z0-9-]{0,40}$/i.test(agentIdForMemory) && !String(agentIdForMemory).toLowerCase().startsWith('temp-')) {
|
|
743
797
|
const agentMemRel = `knowledge/agents/${String(agentIdForMemory).toLowerCase()}.md`;
|
|
744
798
|
const agentMemPath = path.join(MINIONS_DIR, agentMemRel);
|
package/engine/shared.js
CHANGED
|
@@ -3683,6 +3683,11 @@ const ENGINE_DEFAULTS = {
|
|
|
3683
3683
|
agentMemorySummaryEnabled: false, // opt-in: when true, eviction batches go through an LLM-compressed summary before being dropped. Default off to mirror the conservative gating on the existing reconcile pass (LLM cost + test stability). Operators flip via engine.agentMemorySummaryEnabled.
|
|
3684
3684
|
agentMemorySummaryThreshold: 30, // batch window: when summary is enabled and a prune evicts entries, fold at least this many oldest sections into one summary. Means "summary every ~30 entries" in steady state (the original PRD intent).
|
|
3685
3685
|
agentMemorySummaryDays: 30, // age trigger: when the oldest section is older than this and >= agentMemorySummaryThreshold entries exist, summarize the oldest window even if the file is under the entry cap.
|
|
3686
|
+
memoryRetrievalShadowMode: true, // compute + measure FTS5 retrieval but preserve legacy prompt injection until explicitly disabled
|
|
3687
|
+
memoryRetrievalTopK: 8, // maximum structured memory records injected into one dispatch
|
|
3688
|
+
memoryRetrievalMaxBytes: 8 * 1024, // hard byte budget for the Relevant Memory prompt appendix
|
|
3689
|
+
memoryRetrievalCandidateLimit: 50, // bounded FTS5 candidate pool before deterministic re-ranking
|
|
3690
|
+
memoryEpisodicCapture: false, // opt-in capture of compact task outcomes; never stores transcripts or chain-of-thought
|
|
3686
3691
|
untrustedFenceMaxBytes: 64 * 1024, // F5 (W-mpeklod3000we69c): per-block cap for `<UNTRUSTED-INPUT>` fences in engine/untrusted-fence.js. 64KB is long enough for realistic PR comments / pinned notes / agent memory sections, short enough that a megabyte-bomb comment cannot blow up the prompt. Content above the cap is truncated INSIDE the fence with a `[truncated N more bytes]` marker so the agent still sees the provenance attribute.
|
|
3687
3692
|
maxMeetingPromptBytes: 16 * 1024, // cap meeting findings/debate context injected into prompts
|
|
3688
3693
|
maxMeetingHumanNotesBytes: 2 * 1024, // cap human note bullet lists injected into meeting prompts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2370",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|