@monoes/monomindcli 1.14.1 → 1.14.3
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.
|
@@ -112,3 +112,20 @@ Follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
Invoke `Skill("mastermind:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call — do not skip it.
|
|
115
|
+
|
|
116
|
+
After the REPEAT POSTAMBLE completes, if a loop was started or continued (LOOP_ID is set), write the org name into the loop state file so the dashboard can detect running status:
|
|
117
|
+
```bash
|
|
118
|
+
if [ -n "${LOOP_ID:-}" ]; then
|
|
119
|
+
LOOP_FILE=".monomind/loops/${LOOP_ID}.json"
|
|
120
|
+
if [ -f "$LOOP_FILE" ]; then
|
|
121
|
+
python3 -c "
|
|
122
|
+
import json, sys
|
|
123
|
+
f = sys.argv[1]; org = sys.argv[2]
|
|
124
|
+
d = json.load(open(f))
|
|
125
|
+
if 'orgName' not in d:
|
|
126
|
+
d['orgName'] = org
|
|
127
|
+
open(f, 'w').write(json.dumps(d, indent=2))
|
|
128
|
+
" "$LOOP_FILE" "${org_name}" 2>/dev/null || true
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
131
|
+
```
|
|
@@ -449,8 +449,8 @@ html, body { height: 100%; background: var(--bg); color: var(--text-hi); font-fa
|
|
|
449
449
|
.hv2-val.red { color: var(--red); }
|
|
450
450
|
|
|
451
451
|
/* ── alerts rail ─────────────────────────────────────────── */
|
|
452
|
-
#alerts-rail { display: none
|
|
453
|
-
#alerts-rail.has-alerts { display:
|
|
452
|
+
#alerts-rail { display: none !important; }
|
|
453
|
+
#alerts-rail.has-alerts { display: none !important; }
|
|
454
454
|
.alert-item { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 4px 10px; border-radius: 10px; cursor: default; white-space: nowrap; user-select: none; }
|
|
455
455
|
.alert-item:hover .al-x { opacity: 1; }
|
|
456
456
|
.alert-warn { background: oklch(72% 0.18 75 / 0.1); color: oklch(78% 0.18 75); border: 1px solid oklch(72% 0.18 75 / 0.25); }
|
|
@@ -4044,7 +4044,7 @@ async function loadChatViewSessions() {
|
|
|
4044
4044
|
// include events that arrived via SSE right before the fetch, so we preserve their
|
|
4045
4045
|
// buffered events and merge them back after (same pattern as _odtLoadChatSessions).
|
|
4046
4046
|
const _prevChatSessions = { ...chatVSessions };
|
|
4047
|
-
const data = await apiFetch('/api/mastermind/sessions');
|
|
4047
|
+
const data = await apiFetch('/api/mastermind/sessions' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
4048
4048
|
chatVSessions = {};
|
|
4049
4049
|
chatVGroupMap = {};
|
|
4050
4050
|
chatVSessionGroupMap = {};
|
|
@@ -4453,7 +4453,7 @@ function connectChatViewSSE() {
|
|
|
4453
4453
|
if (chatVSseSource) return;
|
|
4454
4454
|
const dot = document.getElementById('chat-v-live-dot');
|
|
4455
4455
|
const lbl = document.getElementById('chat-v-live-lbl');
|
|
4456
|
-
chatVSseSource = new EventSource('/api/mastermind-stream');
|
|
4456
|
+
chatVSseSource = new EventSource('/api/mastermind-stream' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
4457
4457
|
chatVSseSource.onopen = () => { dot && dot.classList.add('on'); lbl && (lbl.textContent = 'LIVE'); };
|
|
4458
4458
|
chatVSseSource.onmessage = e => {
|
|
4459
4459
|
try { handleChatViewEvent(JSON.parse(e.data)); } catch(_) {}
|
|
@@ -4478,6 +4478,7 @@ function handleChatViewEvent(ev) {
|
|
|
4478
4478
|
// Org events (org:comms, org:agent:online, org:checkpoint, etc.) may carry a session field
|
|
4479
4479
|
// from the org run's session ID — route them directly to the feed if the session matches,
|
|
4480
4480
|
// or append them unconditionally when the chat view is showing the "live" placeholder.
|
|
4481
|
+
if (ev.project && DIR && ev.project !== DIR) return;
|
|
4481
4482
|
const isOrgEvent = ev.type && (ev.type.startsWith('org:') || ev.type.startsWith('run:') || ev.type.startsWith('loop:'));
|
|
4482
4483
|
if (!ev.session && !isOrgEvent) return;
|
|
4483
4484
|
if (ev.session) {
|
|
@@ -6926,7 +6927,7 @@ function _odtOrgSessionMatch(s) {
|
|
|
6926
6927
|
const after = str[idx + prefix.length];
|
|
6927
6928
|
return after === undefined || !/[a-z0-9_-]/.test(after);
|
|
6928
6929
|
};
|
|
6929
|
-
if (_orgBound(prompt, 'running org: ' + orgLc) || _orgBound(prompt, 'org: ' + orgLc)) return true;
|
|
6930
|
+
if (_orgBound(prompt, 'running org: ' + orgLc) || _orgBound(prompt, 'org: ' + orgLc) || _orgBound(prompt, 'running ' + orgLc + ' org:')) return true;
|
|
6930
6931
|
return (s.events || []).some(ev => (ev.org || '').toLowerCase() === orgLc);
|
|
6931
6932
|
}
|
|
6932
6933
|
|
|
@@ -7105,7 +7106,7 @@ async function _odtLoadChatSessions() {
|
|
|
7105
7106
|
// Orgs running via _repeat loops emit session:start/complete events to the mastermind
|
|
7106
7107
|
// event store; these never appear in the run list and are otherwise invisible.
|
|
7107
7108
|
try {
|
|
7108
|
-
const _mmSessR = await apiFetch('/api/mastermind/sessions');
|
|
7109
|
+
const _mmSessR = await apiFetch('/api/mastermind/sessions' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
7109
7110
|
if (_v2SelOrg === _loadedForOrg) {
|
|
7110
7111
|
const _mmAll = Array.isArray(_mmSessR) ? _mmSessR : Object.values(_mmSessR.sessions || {});
|
|
7111
7112
|
const _mmMatch = _mmAll.filter(_odtOrgSessionMatch).filter(s => !_odtChatSessions.find(x => x.id === s.id));
|
|
@@ -7135,7 +7136,7 @@ async function _odtLoadChatSessions() {
|
|
|
7135
7136
|
if (_v2SelOrg !== _loadedForOrg) return;
|
|
7136
7137
|
// Fallback: mastermind lifecycle events (pre-run-file era sessions)
|
|
7137
7138
|
try {
|
|
7138
|
-
const r = await apiFetch('/api/mastermind/sessions');
|
|
7139
|
+
const r = await apiFetch('/api/mastermind/sessions' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
7139
7140
|
if (_v2SelOrg !== _loadedForOrg) return;
|
|
7140
7141
|
const all = Array.isArray(r) ? r : Object.values(r.sessions || {});
|
|
7141
7142
|
_odtChatSessions = all.filter(_odtOrgSessionMatch).map(s => {
|
|
@@ -7743,7 +7744,7 @@ function _odtConnectChatSSE() {
|
|
|
7743
7744
|
if (_odtChatSseSource) return;
|
|
7744
7745
|
const dot = document.getElementById('odt-chat-live-dot');
|
|
7745
7746
|
const lbl = document.getElementById('odt-chat-live-lbl');
|
|
7746
|
-
_odtChatSseSource = new EventSource('/api/mastermind-stream');
|
|
7747
|
+
_odtChatSseSource = new EventSource('/api/mastermind-stream' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
7747
7748
|
_odtChatSseSource.onopen = () => { dot?.classList.add('on'); if (lbl) lbl.textContent = 'LIVE'; };
|
|
7748
7749
|
_odtChatSseSource.onmessage = e => {
|
|
7749
7750
|
try { _odtHandleLiveEvent(JSON.parse(e.data)); } catch(_) {}
|
|
@@ -7762,6 +7763,7 @@ function _odtConnectChatSSE() {
|
|
|
7762
7763
|
}
|
|
7763
7764
|
|
|
7764
7765
|
function _odtHandleLiveEvent(ev) {
|
|
7766
|
+
if (ev?.project && DIR && ev.project !== DIR) return;
|
|
7765
7767
|
// Deduplicate SSE reconnect replays (server replays last 50 events on every reconnect)
|
|
7766
7768
|
const _odtDedupKey = (ev?.ts||'') + '|' + (ev?.type||'') + '|' + (ev?.runId||ev?.session||'') + '|' + (ev?.from||ev?.role||ev?.agent||'') + '|' + (ev?.result||ev?.msg||ev?.message||ev?.summary||'').slice(0,20);
|
|
7767
7769
|
if (_odtChatSeenKeys.has(_odtDedupKey)) return;
|
|
@@ -8435,7 +8437,7 @@ function filterOrgList(q) {
|
|
|
8435
8437
|
if (src) src.close();
|
|
8436
8438
|
// Do NOT reset seenKeys here — the server replays ~50 events on every reconnect and
|
|
8437
8439
|
// clearing the set lets all replays through, duplicating _v2OrgEventLog and _activity entries.
|
|
8438
|
-
src = new EventSource('/api/mastermind-stream');
|
|
8440
|
+
src = new EventSource('/api/mastermind-stream' + (DIR ? '?project=' + encodeURIComponent(DIR) : ''));
|
|
8439
8441
|
src.onmessage = e => {
|
|
8440
8442
|
try {
|
|
8441
8443
|
const ev = JSON.parse(e.data);
|
package/dist/src/ui/server.mjs
CHANGED
|
@@ -3525,16 +3525,39 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
3525
3525
|
const _loopRunning = (() => {
|
|
3526
3526
|
try {
|
|
3527
3527
|
if (!fs.existsSync(_loopsDir)) return false;
|
|
3528
|
+
// Get the org's state file mtime to correlate with loop activity
|
|
3529
|
+
const orgStateMtime = (() => {
|
|
3530
|
+
try { return fs.statSync(path.join(orgsDir, `${orgName}-state.json`)).mtimeMs; } catch { return 0; }
|
|
3531
|
+
})();
|
|
3532
|
+
// Also check org's most recent run file mtime
|
|
3533
|
+
const orgRunsDir = path.join(d, '.monomind', 'orgs', orgName, 'runs');
|
|
3534
|
+
const orgLastRunMtime = (() => {
|
|
3535
|
+
try {
|
|
3536
|
+
if (!fs.existsSync(orgRunsDir)) return 0;
|
|
3537
|
+
const runFiles = fs.readdirSync(orgRunsDir).filter(f => f.endsWith('.jsonl'));
|
|
3538
|
+
if (!runFiles.length) return 0;
|
|
3539
|
+
return Math.max(...runFiles.map(f => { try { return fs.statSync(path.join(orgRunsDir, f)).mtimeMs; } catch { return 0; } }));
|
|
3540
|
+
} catch { return 0; }
|
|
3541
|
+
})();
|
|
3542
|
+
const orgLastActivity = Math.max(orgStateMtime, orgLastRunMtime);
|
|
3528
3543
|
return fs.readdirSync(_loopsDir).some(f => {
|
|
3529
3544
|
if (!f.endsWith('.json') || f.endsWith('.stop')) return false;
|
|
3530
3545
|
try {
|
|
3531
3546
|
const lp = JSON.parse(fs.readFileSync(path.join(_loopsDir, f), 'utf8'));
|
|
3532
|
-
|
|
3547
|
+
if (!lp.command || !lp.command.includes('runorg')) return false;
|
|
3548
|
+
if (!['running', 'paused'].includes(lp.status)) return false;
|
|
3549
|
+
// Primary match: explicit orgName field (written by runorg command since v1.14.2)
|
|
3550
|
+
if (lp.orgName === orgName) return true;
|
|
3551
|
+
// Fallback: org name in prompt (early loop files that preserved --org flag)
|
|
3552
|
+
if ((lp.prompt || '').includes(orgName)) return true;
|
|
3553
|
+
// Heuristic: if loop's lastRunAt is within 3x wait interval of org's last activity
|
|
3554
|
+
const waitMs = (lp.wait || 60) * 3 * 1000;
|
|
3555
|
+
return orgLastActivity > 0 && Math.abs(orgLastActivity - (lp.lastRunAt || 0)) < waitMs;
|
|
3533
3556
|
} catch { return false; }
|
|
3534
3557
|
});
|
|
3535
3558
|
} catch { return false; }
|
|
3536
3559
|
})();
|
|
3537
|
-
const running = !fs.existsSync(stopFile) && (activeOrgRuns.has(orgName) || Object.values(state.agents || {}).some(a => a.status === 'running') || _loopRunning);
|
|
3560
|
+
const running = !fs.existsSync(stopFile) && (activeOrgRuns.has(orgName) || ['running','active'].includes(state.status) || Object.values(state.agents || {}).some(a => a.status === 'running') || _loopRunning);
|
|
3538
3561
|
|
|
3539
3562
|
// Read real tasks from the task store and group by status column
|
|
3540
3563
|
const taskStoreData = readJsonSafe(path.join(d, '.monomind', 'tasks', 'store.json'));
|
|
@@ -4755,9 +4778,11 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
4755
4778
|
});
|
|
4756
4779
|
res.write(': connected\n\n');
|
|
4757
4780
|
mmSseClients.add(res);
|
|
4758
|
-
// Replay last 50 events from disk
|
|
4781
|
+
// Replay last 50 events from disk (use ?project= param if provided)
|
|
4759
4782
|
try {
|
|
4760
|
-
const
|
|
4783
|
+
const _sseQp = new URL('http://x' + req.url).searchParams;
|
|
4784
|
+
const _sseProj = _sseQp.get('project');
|
|
4785
|
+
const root2 = _sseProj || projectDir || process.cwd();
|
|
4761
4786
|
const evFile = path.join(root2, 'data', 'mastermind-events.jsonl');
|
|
4762
4787
|
const lines = fs.readFileSync(evFile, 'utf8').trim().split('\n').filter(Boolean).slice(-50);
|
|
4763
4788
|
for (const l of lines) res.write(`data: ${l}\n\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|