@yemi33/minions 0.1.1052 → 0.1.1054
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/CHANGELOG.md +3 -1
- package/engine/meeting.js +95 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1054 (2026-04-17)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- seed realActivityMap at spawn time, stamp pid in live-output (#1200)
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- improve fallback meeting conclusion
|
|
9
10
|
- remove command center chevron
|
|
10
11
|
- stamp live-output.log stub before spawn (#1198)
|
|
11
12
|
- harden settings save and migrate pr poll config
|
|
12
13
|
|
|
13
14
|
### Other
|
|
15
|
+
- Fix publish workflow merge
|
|
14
16
|
- chore: raise default meeting round timeout
|
|
15
17
|
- Harden prompt context handling
|
|
16
18
|
- Harden loop watch conversion
|
package/engine/meeting.js
CHANGED
|
@@ -32,6 +32,100 @@ function formatMeetingContributions(entries, agents, emptyText, label, maxBytes)
|
|
|
32
32
|
return truncateMeetingContext(combined, maxBytes, label);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function cleanMeetingSummaryText(text) {
|
|
36
|
+
return String(text || '')
|
|
37
|
+
.replace(/\r/g, '')
|
|
38
|
+
.replace(/```[\s\S]*?```/g, ' ')
|
|
39
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
40
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
|
41
|
+
.replace(/^[#>*-]+\s*/gm, '')
|
|
42
|
+
.replace(/\s+/g, ' ')
|
|
43
|
+
.trim();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function splitMeetingSummaryFragments(text) {
|
|
47
|
+
return cleanMeetingSummaryText(text)
|
|
48
|
+
.split(/\n+|(?:[.!?])\s+|;\s+/)
|
|
49
|
+
.map(s => s.trim())
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function truncateMeetingSummary(text, maxLen) {
|
|
54
|
+
if (text.length <= maxLen) return text;
|
|
55
|
+
return text.slice(0, Math.max(0, maxLen - 1)).trimEnd() + '…';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function formatMeetingSummaryBullets(entries, agents, emptyText, maxLen) {
|
|
59
|
+
const pairs = Object.entries(typeof entries === 'object' && entries ? entries : {});
|
|
60
|
+
if (pairs.length === 0) return [`- ${emptyText}`];
|
|
61
|
+
return pairs.map(([agent, value]) => {
|
|
62
|
+
const fragments = splitMeetingSummaryFragments(value?.content || '');
|
|
63
|
+
const summary = truncateMeetingSummary(fragments[0] || cleanMeetingSummaryText(value?.content || '') || emptyText, maxLen);
|
|
64
|
+
return `- **${agents[agent]?.name || agent}**: ${summary}`;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function scoreMeetingTakeaway(fragment) {
|
|
69
|
+
const lower = fragment.toLowerCase();
|
|
70
|
+
let score = 0;
|
|
71
|
+
if (/(should|must|need to|needs to|recommend|recommended|action|next step|follow up|fix|mitigat|investigat|verify|test|block)/.test(lower)) score += 4;
|
|
72
|
+
if (/(agree|aligned|consensus|support|prefer)/.test(lower)) score += 3;
|
|
73
|
+
if (/(disagree|however|but|risk|risky|concern|trade-off|question|uncertain|worry)/.test(lower)) score += 3;
|
|
74
|
+
if (fragment.length >= 40 && fragment.length <= 180) score += 2;
|
|
75
|
+
if (fragment.length > 220) score -= 1;
|
|
76
|
+
return score;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function collectMeetingTakeaways(entries, agents, maxItems) {
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
const candidates = [];
|
|
82
|
+
for (const [agent, value] of Object.entries(typeof entries === 'object' && entries ? entries : {})) {
|
|
83
|
+
for (const fragment of splitMeetingSummaryFragments(value?.content || '')) {
|
|
84
|
+
if (fragment.length < 20) continue;
|
|
85
|
+
const normalized = fragment.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
|
|
86
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
87
|
+
seen.add(normalized);
|
|
88
|
+
candidates.push({
|
|
89
|
+
text: `- **${agents[agent]?.name || agent}**: ${truncateMeetingSummary(fragment, 180)}`,
|
|
90
|
+
score: scoreMeetingTakeaway(fragment),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return candidates
|
|
95
|
+
.sort((a, b) => b.score - a.score || a.text.length - b.text.length)
|
|
96
|
+
.slice(0, maxItems)
|
|
97
|
+
.map(item => item.text);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function collectMeetingNextSteps(meeting) {
|
|
101
|
+
const actionPattern = /\b(should|must|need to|needs to|recommend|recommended|follow up|fix|mitigate|investigate|verify|test|document|ship|patch|review)\b/i;
|
|
102
|
+
const seen = new Set();
|
|
103
|
+
const steps = [];
|
|
104
|
+
for (const entries of [meeting.debate, meeting.findings]) {
|
|
105
|
+
for (const value of Object.values(typeof entries === 'object' && entries ? entries : {})) {
|
|
106
|
+
for (const fragment of splitMeetingSummaryFragments(value?.content || '')) {
|
|
107
|
+
if (!actionPattern.test(fragment)) continue;
|
|
108
|
+
const normalized = fragment.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
|
|
109
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
110
|
+
seen.add(normalized);
|
|
111
|
+
steps.push(`- ${truncateMeetingSummary(fragment, 180)}`);
|
|
112
|
+
if (steps.length >= 3) return steps;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return ['- Review the findings and debate, then add a human-written conclusion if more nuance is needed.'];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function buildTimedOutMeetingConclusion(meeting, agents) {
|
|
120
|
+
const findingsCount = Object.keys(meeting.findings || {}).length;
|
|
121
|
+
const debateCount = Object.keys(meeting.debate || {}).length;
|
|
122
|
+
const findingsHighlights = formatMeetingSummaryBullets(meeting.findings, agents, '(none)', 180);
|
|
123
|
+
const debateTakeaways = collectMeetingTakeaways(meeting.debate, agents, 4);
|
|
124
|
+
const fallbackDebate = formatMeetingSummaryBullets(meeting.debate, agents, '(none)', 180);
|
|
125
|
+
const nextSteps = collectMeetingNextSteps(meeting);
|
|
126
|
+
return `*Auto-generated — conclusion round timed out.*\n\nThis summary is based on ${findingsCount} finding${findingsCount === 1 ? '' : 's'} and ${debateCount} debate response${debateCount === 1 ? '' : 's'}.\n\n## Findings Highlights\n${findingsHighlights.join('\n')}\n\n## Debate Takeaways\n${(debateTakeaways.length ? debateTakeaways : fallbackDebate).join('\n')}\n\n## Recommended Next Steps\n${nextSteps.join('\n')}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
35
129
|
function getMeetings() {
|
|
36
130
|
if (!fs.existsSync(MEETINGS_DIR)) return [];
|
|
37
131
|
return fs.readdirSync(MEETINGS_DIR)
|
|
@@ -417,14 +511,7 @@ function checkMeetingTimeouts(config) {
|
|
|
417
511
|
saveMeeting(meeting);
|
|
418
512
|
} else if (meeting.status === 'concluding') {
|
|
419
513
|
log('warn', `Meeting ${meeting.id}: conclusion round timed out after ${Math.round(elapsed / 60000)}min — auto-summarizing`);
|
|
420
|
-
|
|
421
|
-
const findingsSummary = Object.entries(meeting.findings || {}).map(([agent, f]) =>
|
|
422
|
-
`**${(config.agents || {})[agent]?.name || agent}**: ${(f.content || '').slice(0, 200)}`
|
|
423
|
-
).join('\n');
|
|
424
|
-
const debateSummary = Object.entries(meeting.debate || {}).map(([agent, d]) =>
|
|
425
|
-
`**${(config.agents || {})[agent]?.name || agent}**: ${(d.content || '').slice(0, 200)}`
|
|
426
|
-
).join('\n');
|
|
427
|
-
const autoConclusion = `*Auto-generated — conclusion round timed out.*\n\n## Key Findings\n${findingsSummary || '(none)'}\n\n## Debate Summary\n${debateSummary || '(none)'}`;
|
|
514
|
+
const autoConclusion = buildTimedOutMeetingConclusion(meeting, config.agents || {});
|
|
428
515
|
meeting.conclusion = { content: autoConclusion, agent: 'system', submittedAt: ts() };
|
|
429
516
|
meeting.transcript.push({ round: meeting.round, agent: 'system', type: 'conclusion', content: autoConclusion, at: ts() });
|
|
430
517
|
meeting.status = 'completed';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1054",
|
|
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"
|