Skip to content

Commit cc9fed6

Browse files
committed
Command Center
1 parent d364c14 commit cc9fed6

4 files changed

Lines changed: 33 additions & 8 deletions

File tree

config.default.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
]
1313
},
1414
"agent": {
15-
"paused": false
15+
"paused": false,
16+
"requireApprovalForFacts": false
1617
},
1718
"heartbeat": [],
1819
"skills": { "enabledIds": [] },

lib/agentRunner.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,12 +554,28 @@ async function learnFromTask(task) {
554554
addLog(task, 'learn', `Added ${learnings.strategyNotes.length} strategy note(s) to memory`);
555555
}
556556

557-
// Facts require approval
557+
// Facts are relatively low-risk, but can be noisy. By default we require approval,
558+
// except for Command Center missions where we auto-store to avoid constant prompts.
558559
const facts = Array.isArray(learnings.factsToStore)
559560
? learnings.factsToStore.filter(f => f && f.key)
560561
: [];
561562

562563
if (facts.length > 0) {
564+
const cfg = getConfig();
565+
const isCommandCenterMission = !!(task && task.parentMissionId);
566+
const requireApprovalForFacts = cfg.agent?.requireApprovalForFacts;
567+
const mustApprove = (requireApprovalForFacts === true) || (!isCommandCenterMission && requireApprovalForFacts !== false);
568+
569+
if (!mustApprove) {
570+
for (const { key, value } of facts) {
571+
if (key) structuredMemory.setMemory(String(key), String(value || ''));
572+
}
573+
addLog(task, 'result', `Stored ${facts.length} memory fact(s)`);
574+
addLog(task, 'learn', 'Learning phase complete');
575+
agentStore.updateTask(task.id, { status: 'complete', log: task.log });
576+
return;
577+
}
578+
563579
addLog(task, 'approval_request',
564580
`Learning: needs approval to store ${facts.length} memory fact(s): ${facts.map(f => f.key).join(', ')}`
565581
);

lib/commandCenter/missionReporter.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ async function summarizeMissionCompletion(payload) {
9595
const model = cfg.ollama?.mainModel || 'llama3.2';
9696
const system = [
9797
'You are the Shadow Command Center mission reporter.',
98-
'Summarize a finished multi-agent mission into a concise final report grounded in task evidence.',
99-
'Return ONLY strict JSON with keys:',
100-
'{ "headline": string, "summary": string, "outcome": "complete"|"partial"|"failed" }',
101-
'Keep the summary to 3-6 short sentences.',
98+
'Summarize a finished multi-agent mission into a clear, human-readable report grounded in task evidence.',
99+
'Return ONLY strict JSON with keys (no extra keys):',
100+
'{ "headline": string, "summary": string, "outcome": "complete"|"partial"|"failed", "finalReport": string }',
101+
'"summary" must be a 3-6 sentence high-level overview.',
102+
'"finalReport" must be a merged, well-structured narrative (2-8 short paragraphs) suitable for the user to read as-is.',
102103
'Base the outcome on task statuses and evidence quality.',
103104
'If statuses are complete but concrete outputs are missing/empty, set outcome to "partial" and say that explicitly.',
104-
'Never claim data was retrieved unless evidence contains that data.'
105+
'Never claim data was retrieved unless evidence contains that data.',
106+
'In "finalReport", do NOT mention internal agent steps or tool names; focus only on user-facing facts and conclusions.'
105107
].join('\n');
106108
const data = await ollamaChatJson(baseUrl, model, [
107109
{ role: 'system', content: system },
@@ -113,7 +115,8 @@ async function summarizeMissionCompletion(payload) {
113115
return {
114116
headline: safeText(parsed && parsed.headline ? parsed.headline : payload.title, 200),
115117
summary: safeText(parsed && parsed.summary ? parsed.summary : '', 2000),
116-
outcome: ['complete', 'partial', 'failed'].includes(parsed && parsed.outcome) ? parsed.outcome : 'partial'
118+
outcome: ['complete', 'partial', 'failed'].includes(parsed && parsed.outcome) ? parsed.outcome : 'partial',
119+
finalReport: safeText(parsed && parsed.finalReport ? parsed.finalReport : (parsed && parsed.summary ? parsed.summary : ''), 16000)
117120
};
118121
}
119122

public/command-center.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];
145145
const statusCounts = payload.statusCounts || {};
146146
const summary = report.summary || mission.summary || '';
147+
const finalReport = report.finalReport || summary || '';
147148
const headline = report.headline || mission.title || mission.id || 'Mission Report';
148149

149150
if (reportTitleEl) reportTitleEl.textContent = String(headline);
@@ -177,6 +178,10 @@
177178
<div class="cc-report-title">SUMMARY</div>
178179
<div>${escapeHtml(summary || '(none)')}</div>
179180
</div>
181+
<div class="cc-report-section">
182+
<div class="cc-report-title">FINAL REPORT</div>
183+
<div>${escapeHtml(finalReport || '(none)')}</div>
184+
</div>
180185
<div class="cc-report-section">
181186
<div class="cc-report-title">OUTCOME</div>
182187
<div>${escapeHtml(report.outcome || 'unknown')}</div>

0 commit comments

Comments
 (0)