mio-agent-runtime 0.5.14 → 0.5.16
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/README.md +144 -236
- package/adapters/codex.js +122 -134
- package/adapters/hermes.js +122 -140
- package/adapters/host-utils.js +61 -61
- package/adapters/opencode.js +176 -215
- package/adapters/workbuddy.js +196 -242
- package/bin/mio.js +423 -424
- package/observe/observer.js +1326 -1335
- package/package.json +24 -13
- package/scripts/verify-packed-runtime.js +371 -0
- package/server/evolution-cutover.js +119 -0
- package/server/host-capabilities.js +50 -0
- package/server/mio-intelligence-mcp/README.md +184 -173
- package/server/mio-intelligence-mcp/index.js +123 -284
- package/server/mio-intelligence-mcp/package.json +17 -17
- package/server/mio-intelligence-mcp/phase0.js +381 -381
- package/server/runtime-modules.js +111 -0
- package/server/mio-intelligence-mcp/dashboard-server.js +0 -171
|
@@ -5,7 +5,10 @@ const fs = require('fs')
|
|
|
5
5
|
const path = require('path')
|
|
6
6
|
const crypto = require('crypto')
|
|
7
7
|
const readline = require('readline')
|
|
8
|
-
const { execFileSync } = require('child_process')
|
|
8
|
+
const { execFileSync } = require('child_process')
|
|
9
|
+
const { getEvolutionStatus } = require('../runtime-modules.js')
|
|
10
|
+
const { listHostCapabilities } = require('../host-capabilities.js')
|
|
11
|
+
const { createEvolutionCutoverTools } = require('../evolution-cutover.js')
|
|
9
12
|
|
|
10
13
|
const SERVER_INFO = { name: 'mio-intelligence-mcp', version: '0.1.0' }
|
|
11
14
|
const PROTOCOL_VERSION = '2024-11-05'
|
|
@@ -20,11 +23,10 @@ const queryPath = path.join(dataDir, 'queries.jsonl')
|
|
|
20
23
|
const agentsPath = path.join(dataDir, 'agents.jsonl')
|
|
21
24
|
const subscriptionPath = path.join(dataDir, 'subscriptions.jsonl')
|
|
22
25
|
const digestStatePath = path.join(dataDir, 'digest_state.json')
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
|
|
26
|
+
fs.mkdirSync(dataDir, { recursive: true })
|
|
27
|
+
|
|
28
|
+
const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
|
|
29
|
+
const evolutionCutover = createEvolutionCutoverTools({ dataDir, appendJsonl, readJsonl, projectName })
|
|
28
30
|
|
|
29
31
|
let runtimeContext = {}
|
|
30
32
|
try {
|
|
@@ -1594,188 +1596,132 @@ const TOOLS = [
|
|
|
1594
1596
|
},
|
|
1595
1597
|
},
|
|
1596
1598
|
},
|
|
1597
|
-
{
|
|
1598
|
-
name: 'mio.evolution.report',
|
|
1599
|
-
description: 'Generate cross-agent evolution report: ecosystem summary, agent performance comparison, cross-agent patterns, memory health, and optimization suggestions (ADR-017 Evolution plane).',
|
|
1599
|
+
{
|
|
1600
|
+
name: 'mio.evolution.report',
|
|
1601
|
+
description: 'Generate cross-agent evolution report: ecosystem summary, agent performance comparison, cross-agent patterns, memory health, and optimization suggestions (ADR-017 Evolution plane).',
|
|
1600
1602
|
inputSchema: {
|
|
1601
1603
|
type: 'object',
|
|
1602
1604
|
properties: {
|
|
1603
1605
|
project: { type: 'string', description: 'Project name filter. Defaults to current repository.' },
|
|
1604
1606
|
period: { type: 'string', description: 'Time window: 24h, 7d, 30d, or all (default).' },
|
|
1605
1607
|
},
|
|
1606
|
-
},
|
|
1607
|
-
},
|
|
1608
|
-
{
|
|
1609
|
-
name: 'mio.task.record_outcome',
|
|
1610
|
-
description: 'Record task outcome with agent registry update and auto-claim experience reuse in one atomic call. Combines observer.ingest + agent stats + auto-claim for a complete task lifecycle closure.',
|
|
1611
|
-
inputSchema: {
|
|
1612
|
-
type: 'object',
|
|
1613
|
-
properties: {
|
|
1614
|
-
outcome: { type: 'string', description: 'Task outcome: success, failure, or aborted.' },
|
|
1615
|
-
task: { type: 'string', description: 'Brief task description.' },
|
|
1616
|
-
summary: { type: 'string', description: 'Optional task summary.' },
|
|
1617
|
-
verification: { type: 'string', description: 'Optional verification details.' },
|
|
1618
|
-
agentId: { type: 'string', description: 'Agent identifier. Defaults to MIO_CONTEXT agentId.' },
|
|
1619
|
-
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1620
|
-
traceId: { type: 'string', description: 'Optional custom trace ID. Auto-generated if omitted.' },
|
|
1621
|
-
},
|
|
1622
|
-
required: ['outcome'],
|
|
1623
|
-
},
|
|
1608
|
+
},
|
|
1624
1609
|
},
|
|
1625
1610
|
{
|
|
1626
|
-
name: 'mio.
|
|
1627
|
-
description: '
|
|
1611
|
+
name: 'mio.evolution.status',
|
|
1612
|
+
description: 'Report composed mio-agent-runtime module health from the canonical runtime module registry.',
|
|
1613
|
+
inputSchema: {
|
|
1614
|
+
type: 'object',
|
|
1615
|
+
properties: {},
|
|
1616
|
+
},
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
name: 'mio.host.capabilities',
|
|
1620
|
+
description: 'List installed desktop host adapters and the safe capability surface they expose to runtime modules.',
|
|
1621
|
+
inputSchema: {
|
|
1622
|
+
type: 'object',
|
|
1623
|
+
properties: {},
|
|
1624
|
+
},
|
|
1625
|
+
},
|
|
1626
|
+
{
|
|
1627
|
+
name: 'mio.evolution.shadow.record',
|
|
1628
|
+
description: 'Record a shadow comparison between legacy and modular runtime outputs without changing authority.',
|
|
1628
1629
|
inputSchema: {
|
|
1629
1630
|
type: 'object',
|
|
1630
|
-
required: ['goal'],
|
|
1631
1631
|
properties: {
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1632
|
+
label: { type: 'string', description: 'Human-readable comparison label.' },
|
|
1633
|
+
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1634
|
+
legacy: { type: 'object', description: 'Legacy path output snapshot.' },
|
|
1635
|
+
modular: { type: 'object', description: 'Modular path output snapshot.' },
|
|
1636
|
+
input: { type: 'object', description: 'Optional sanitized input snapshot.' },
|
|
1636
1637
|
},
|
|
1637
|
-
|
|
1638
|
+
required: ['legacy', 'modular'],
|
|
1638
1639
|
},
|
|
1639
1640
|
},
|
|
1640
1641
|
{
|
|
1641
|
-
name: 'mio.
|
|
1642
|
-
description: '
|
|
1642
|
+
name: 'mio.evolution.dual_write.record',
|
|
1643
|
+
description: 'Record a dual-write sample result for legacy and modular state paths without switching authority.',
|
|
1643
1644
|
inputSchema: {
|
|
1644
1645
|
type: 'object',
|
|
1645
1646
|
properties: {
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1647
|
+
label: { type: 'string', description: 'Human-readable dual-write label.' },
|
|
1648
|
+
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1649
|
+
authoritative: { type: 'string', description: 'Authoritative path: legacy or modular. Defaults to legacy.' },
|
|
1650
|
+
legacyResult: { type: 'object', description: 'Legacy write result snapshot.' },
|
|
1651
|
+
modularResult: { type: 'object', description: 'Modular write result snapshot.' },
|
|
1652
|
+
record: { type: 'object', description: 'Optional sanitized record metadata.' },
|
|
1653
|
+
},
|
|
1654
|
+
required: ['legacyResult', 'modularResult'],
|
|
1651
1655
|
},
|
|
1652
1656
|
},
|
|
1653
1657
|
{
|
|
1654
|
-
name: 'mio.evolution.
|
|
1655
|
-
description: '
|
|
1658
|
+
name: 'mio.evolution.cutover.readiness',
|
|
1659
|
+
description: 'Assess whether shadow and dual-write samples are sufficient to consider modular runtime cutover.',
|
|
1656
1660
|
inputSchema: {
|
|
1657
1661
|
type: 'object',
|
|
1658
1662
|
properties: {
|
|
1659
|
-
project: { type: 'string', description: 'Project name
|
|
1660
|
-
|
|
1663
|
+
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1664
|
+
minShadowRuns: { type: 'number', description: 'Minimum shadow comparison samples required. Defaults to 5.' },
|
|
1665
|
+
maxMismatchRate: { type: 'number', description: 'Allowed shadow mismatch rate. Defaults to 0.' },
|
|
1666
|
+
},
|
|
1661
1667
|
},
|
|
1662
1668
|
},
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
// Query Mio memory for related context
|
|
1673
|
-
const relatedRecords = readJsonl(memoryPath)
|
|
1674
|
-
.filter(r => r.archived !== true)
|
|
1675
|
-
.filter(r => {
|
|
1676
|
-
const text = (r.content || '').toLowerCase()
|
|
1677
|
-
const goalLower = goal.toLowerCase()
|
|
1678
|
-
// Support both space-separated (English) and continuous (Chinese) matching
|
|
1679
|
-
const goalWords = goalLower.split(/\s+/).filter(w => w.length > 2)
|
|
1680
|
-
// For Chinese: extract 2-char n-grams as search tokens
|
|
1681
|
-
const ngrams = []
|
|
1682
|
-
for (let i = 0; i < goalLower.length - 1; i++) {
|
|
1683
|
-
const ng = goalLower.slice(i, i + 2)
|
|
1684
|
-
if (ng.trim().length === 2) ngrams.push(ng)
|
|
1685
|
-
}
|
|
1686
|
-
const allTokens = [...new Set([...goalWords, ...ngrams])]
|
|
1687
|
-
return allTokens.some(t => text.includes(t))
|
|
1688
|
-
})
|
|
1689
|
-
.slice(0, 8)
|
|
1690
|
-
|
|
1691
|
-
const relatedMemoryText = relatedRecords.length > 0
|
|
1692
|
-
? relatedRecords.map(r => '- [' + r.kind + '] ' + (r.content || '').slice(0, 200)).join('\n')
|
|
1693
|
-
: '(no related memories found)'
|
|
1694
|
-
|
|
1695
|
-
const strategies = [
|
|
1696
|
-
{
|
|
1697
|
-
name: 'SCAMPER',
|
|
1698
|
-
prompt: 'Apply SCAMPER: Substitute, Combine, Adapt, Modify, Put to another use, Eliminate, Reverse. ' +
|
|
1699
|
-
'For goal: ' + goal + '. What novel combination or modification of existing elements could work?'
|
|
1700
|
-
},
|
|
1701
|
-
{
|
|
1702
|
-
name: 'Analogy',
|
|
1703
|
-
prompt: 'By analogy: What similar problem has been solved in a completely different domain? ' +
|
|
1704
|
-
'For goal: ' + goal + '. What approach from another field (biology, economics, gaming, logistics) transfers here?'
|
|
1705
|
-
},
|
|
1706
|
-
{
|
|
1707
|
-
name: 'First-Principles',
|
|
1708
|
-
prompt: 'First principles: Strip away all assumptions. What are the absolute basics of ' + goal + '? ' +
|
|
1709
|
-
'What would you build if you had no prior art, no constraints, no legacy?'
|
|
1669
|
+
{
|
|
1670
|
+
name: 'mio.evolution.migration.plan',
|
|
1671
|
+
description: 'Preview a state migration plan between legacy and modular records without writing state.',
|
|
1672
|
+
inputSchema: {
|
|
1673
|
+
type: 'object',
|
|
1674
|
+
properties: {
|
|
1675
|
+
legacyRecords: { type: 'array', items: { type: 'object' }, description: 'Legacy state records.' },
|
|
1676
|
+
modularRecords: { type: 'array', items: { type: 'object' }, description: 'Existing modular state records.' },
|
|
1677
|
+
},
|
|
1710
1678
|
},
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1679
|
+
},
|
|
1680
|
+
{
|
|
1681
|
+
name: 'mio.evolution.authority.plan',
|
|
1682
|
+
description: 'Create a gated authority switch plan from legacy to modular runtime without applying it.',
|
|
1683
|
+
inputSchema: {
|
|
1684
|
+
type: 'object',
|
|
1685
|
+
properties: {
|
|
1686
|
+
readiness: { type: 'object', description: 'Result from mio.evolution.cutover.readiness.' },
|
|
1687
|
+
from: { type: 'string', description: 'Current authoritative path. Defaults to legacy.' },
|
|
1688
|
+
to: { type: 'string', description: 'Target authoritative path. Defaults to modular.' },
|
|
1689
|
+
},
|
|
1690
|
+
required: ['readiness'],
|
|
1715
1691
|
},
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
for (let i = 0; i < selectedStrategies.length; i++) {
|
|
1727
|
-
const s = selectedStrategies[i]
|
|
1728
|
-
const idea = {
|
|
1729
|
-
id: createId('idea'),
|
|
1730
|
-
title: 'Idea #' + (i + 1) + ' (' + s.name + '): ' + goal,
|
|
1731
|
-
description: 'Goal: ' + goal + '\n\n' +
|
|
1732
|
-
'Strategy: ' + s.name + '\n\n' +
|
|
1733
|
-
'Related Mio memory:\n' + relatedMemoryText + '\n\n' +
|
|
1734
|
-
(context ? 'Context: ' + context + '\n\n' : '') +
|
|
1735
|
-
(constraints.length > 0 ? 'Constraints:\n' + constraints.map(c => '- ' + c).join('\n') + '\n\n' : '') +
|
|
1736
|
-
'Strategy prompt: ' + s.prompt + '\n\n' +
|
|
1737
|
-
'Suggestion: Consider prototyping the idea and measuring its impact against prior decisions.',
|
|
1738
|
-
provenance: {
|
|
1739
|
-
strategy: s.name,
|
|
1740
|
-
relatedMemoryIds: relatedRecords.map(r => r.id).slice(0, 5),
|
|
1692
|
+
},
|
|
1693
|
+
{
|
|
1694
|
+
name: 'mio.evolution.cutover.apply',
|
|
1695
|
+
description: 'Dry-run an authority switch plan. This stage refuses real cutover and never mutates authority state.',
|
|
1696
|
+
inputSchema: {
|
|
1697
|
+
type: 'object',
|
|
1698
|
+
properties: {
|
|
1699
|
+
dryRun: { type: 'boolean', description: 'Must be true. Real cutover is intentionally gated.' },
|
|
1700
|
+
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1701
|
+
plan: { type: 'object', description: 'Authority switch plan from mio.evolution.authority.plan.' },
|
|
1741
1702
|
},
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
const goalFilter = args.goal ? String(args.goal).toLowerCase() : null
|
|
1765
|
-
const strategyFilter = args.strategy ? String(args.strategy).trim().toLowerCase() : null
|
|
1766
|
-
const limit = Math.min(Math.max(Number(args.limit) || 10, 1), 50)
|
|
1767
|
-
const all = fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(line => {
|
|
1768
|
-
try { return JSON.parse(line) } catch (_) { return null }
|
|
1769
|
-
}).filter(Boolean)
|
|
1770
|
-
const filtered = all.filter(idea => {
|
|
1771
|
-
if (cutoff && new Date(idea.generatedAt).getTime() < cutoff) return false
|
|
1772
|
-
if (goalFilter && !String(idea.goal || '').toLowerCase().includes(goalFilter)) return false
|
|
1773
|
-
if (strategyFilter && String(idea.provenance?.strategy || '').toLowerCase() !== strategyFilter) return false
|
|
1774
|
-
return true
|
|
1775
|
-
})
|
|
1776
|
-
return { ideas: filtered.slice(-limit), count: filtered.length, total: all.length }
|
|
1777
|
-
}
|
|
1778
|
-
|
|
1703
|
+
required: ['dryRun', 'plan'],
|
|
1704
|
+
},
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
name: 'mio.task.record_outcome',
|
|
1708
|
+
description: 'Record task outcome with agent registry update and auto-claim experience reuse in one atomic call. Combines observer.ingest + agent stats + auto-claim for a complete task lifecycle closure.',
|
|
1709
|
+
inputSchema: {
|
|
1710
|
+
type: 'object',
|
|
1711
|
+
properties: {
|
|
1712
|
+
outcome: { type: 'string', description: 'Task outcome: success, failure, or aborted.' },
|
|
1713
|
+
task: { type: 'string', description: 'Brief task description.' },
|
|
1714
|
+
summary: { type: 'string', description: 'Optional task summary.' },
|
|
1715
|
+
verification: { type: 'string', description: 'Optional verification details.' },
|
|
1716
|
+
agentId: { type: 'string', description: 'Agent identifier. Defaults to MIO_CONTEXT agentId.' },
|
|
1717
|
+
project: { type: 'string', description: 'Project name. Defaults to current repository.' },
|
|
1718
|
+
traceId: { type: 'string', description: 'Optional custom trace ID. Auto-generated if omitted.' },
|
|
1719
|
+
},
|
|
1720
|
+
required: ['outcome'],
|
|
1721
|
+
},
|
|
1722
|
+
},
|
|
1723
|
+
]
|
|
1724
|
+
|
|
1779
1725
|
async function callTool(name, args = {}) {
|
|
1780
1726
|
switch (name) {
|
|
1781
1727
|
case 'mio.memory.query':
|
|
@@ -1812,77 +1758,31 @@ async function callTool(name, args = {}) {
|
|
|
1812
1758
|
return listAgents(args)
|
|
1813
1759
|
case 'mio.agent.report':
|
|
1814
1760
|
return reportAgent(args)
|
|
1815
|
-
case 'mio.evolution.report':
|
|
1816
|
-
return evolutionReport(args)
|
|
1761
|
+
case 'mio.evolution.report':
|
|
1762
|
+
return evolutionReport(args)
|
|
1763
|
+
case 'mio.evolution.status':
|
|
1764
|
+
return getEvolutionStatus()
|
|
1765
|
+
case 'mio.host.capabilities':
|
|
1766
|
+
return listHostCapabilities()
|
|
1767
|
+
case 'mio.evolution.shadow.record':
|
|
1768
|
+
return evolutionCutover.recordShadowComparison(args)
|
|
1769
|
+
case 'mio.evolution.dual_write.record':
|
|
1770
|
+
return evolutionCutover.recordDualWrite(args)
|
|
1771
|
+
case 'mio.evolution.cutover.readiness':
|
|
1772
|
+
return evolutionCutover.cutoverReadiness(args)
|
|
1773
|
+
case 'mio.evolution.migration.plan':
|
|
1774
|
+
return evolutionCutover.migrationPlan(args)
|
|
1775
|
+
case 'mio.evolution.authority.plan':
|
|
1776
|
+
return evolutionCutover.authorityPlan(args)
|
|
1777
|
+
case 'mio.evolution.cutover.apply':
|
|
1778
|
+
return evolutionCutover.applyCutover(args)
|
|
1817
1779
|
case 'mio.task.record_outcome':
|
|
1818
1780
|
return recordTaskOutcome(args)
|
|
1819
|
-
case 'mio.idea.generate':
|
|
1820
|
-
return handleIdeaGenerate(args)
|
|
1821
|
-
case 'mio.idea.list':
|
|
1822
|
-
return listIdeas(args)
|
|
1823
|
-
case 'mio.evolution.suggest':
|
|
1824
|
-
return evolutionSuggest(args)
|
|
1825
|
-
case 'mio.dashboard.start':
|
|
1826
|
-
return handleDashboardStart(args)
|
|
1827
|
-
case 'mio.dashboard.stop':
|
|
1828
|
-
return handleDashboardStop()
|
|
1829
|
-
case 'mio.dashboard.status':
|
|
1830
|
-
return handleDashboardStatus()
|
|
1831
1781
|
default:
|
|
1832
1782
|
throw new Error(`Unknown tool: ${name}`)
|
|
1833
1783
|
}
|
|
1834
1784
|
}
|
|
1835
1785
|
|
|
1836
|
-
const DASHBOARD_PORT = 8787
|
|
1837
|
-
const dashboardPidPath = () => path.join(dataDir, 'dashboard.pid')
|
|
1838
|
-
|
|
1839
|
-
function isDashboardRunning() {
|
|
1840
|
-
const pidFile = dashboardPidPath()
|
|
1841
|
-
if (!fs.existsSync(pidFile)) return false
|
|
1842
|
-
try {
|
|
1843
|
-
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10)
|
|
1844
|
-
process.kill(pid, 0)
|
|
1845
|
-
return true
|
|
1846
|
-
} catch (_) {
|
|
1847
|
-
return false
|
|
1848
|
-
}
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
function handleDashboardStart(args = {}) {
|
|
1852
|
-
const port = parseInt(args.port || process.env.MIO_DASHBOARD_PORT || DASHBOARD_PORT, 10)
|
|
1853
|
-
const url = 'http://localhost:' + port
|
|
1854
|
-
if (isDashboardRunning()) {
|
|
1855
|
-
if (args.open) { try { require('child_process').exec('start ' + url) } catch (_) {} }
|
|
1856
|
-
return { url: url, running: true, message: 'Dashboard already running at ' + url }
|
|
1857
|
-
}
|
|
1858
|
-
const serverScript = path.join(__dirname, 'dashboard-server.js')
|
|
1859
|
-
const child = require('child_process').spawn(process.execPath, [serverScript, String(port)], {
|
|
1860
|
-
env: Object.assign({}, process.env, { MIO_DATA_DIR: dataDir }),
|
|
1861
|
-
detached: true,
|
|
1862
|
-
stdio: 'ignore',
|
|
1863
|
-
})
|
|
1864
|
-
child.unref()
|
|
1865
|
-
fs.writeFileSync(dashboardPidPath(), String(child.pid))
|
|
1866
|
-
if (args.open) { try { require('child_process').exec('start ' + url) } catch (_) {} }
|
|
1867
|
-
return { url: url, running: true, pid: child.pid, message: 'Dashboard started at ' + url }
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
function handleDashboardStop() {
|
|
1871
|
-
const pidFile = dashboardPidPath()
|
|
1872
|
-
if (!fs.existsSync(pidFile)) return { running: false, message: 'Dashboard not running.' }
|
|
1873
|
-
try {
|
|
1874
|
-
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10)
|
|
1875
|
-
process.kill(pid, 'SIGTERM')
|
|
1876
|
-
} catch (_) {}
|
|
1877
|
-
try { fs.unlinkSync(pidFile) } catch (_) {}
|
|
1878
|
-
return { running: false, message: 'Dashboard stopped.' }
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
function handleDashboardStatus() {
|
|
1882
|
-
const running = isDashboardRunning()
|
|
1883
|
-
return { running: running, url: running ? 'http://localhost:' + DASHBOARD_PORT : null }
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
1786
|
function jsonRpcResult(id, result) {
|
|
1887
1787
|
return { jsonrpc: '2.0', id, result }
|
|
1888
1788
|
}
|
|
@@ -2197,65 +2097,4 @@ function recordTaskOutcome(args = {}) {
|
|
|
2197
2097
|
}
|
|
2198
2098
|
}
|
|
2199
2099
|
|
|
2200
|
-
|
|
2201
|
-
function evolutionSuggest(args = {}) {
|
|
2202
|
-
const project = args.project || projectName()
|
|
2203
|
-
const now = Date.now()
|
|
2204
|
-
const memories = readJsonl(memoryPath)
|
|
2205
|
-
const traces = readJsonl(tracePath)
|
|
2206
|
-
const reuses = readJsonl(experienceReusePath)
|
|
2207
|
-
const ideas = fs.existsSync(ideasPath)
|
|
2208
|
-
? fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(l => { try { return JSON.parse(l) } catch (_) { return null } }).filter(Boolean)
|
|
2209
|
-
: []
|
|
2210
|
-
const agentIds = new Set()
|
|
2211
|
-
traces.forEach((t) => { if (t.agent) agentIds.add(t.agent) })
|
|
2212
|
-
const outcomes = traces.filter((t) => t.event_type === 'task_outcome')
|
|
2213
|
-
const successes = outcomes.filter((t) => t.outcome === 'success').length
|
|
2214
|
-
const successRate = outcomes.length > 0 ? Math.round((successes / outcomes.length) * 100) : 0
|
|
2215
|
-
const verifiedReuses = reuses.filter((r) => r.confirmed && r.reuse && r.behaviorChanged && r.outcomeImproved)
|
|
2216
|
-
const pendingReuses = reuses.filter((r) => r.source === 'auto_claim' && !r.confirmed)
|
|
2217
|
-
const decisions = memories.filter((m) => m.kind === 'decision')
|
|
2218
|
-
const problems = memories.filter((m) => m.kind === 'problem')
|
|
2219
|
-
const shortMemories = memories.filter((m) => String(m.content || '').trim().length < 20)
|
|
2220
|
-
const ideasWithoutMemory = ideas.filter((i) => !i.provenance?.relatedMemoryIds?.length)
|
|
2221
|
-
const suggestions = []
|
|
2222
|
-
|
|
2223
|
-
if (agentIds.size >= 2) {
|
|
2224
|
-
const agentStats = []
|
|
2225
|
-
for (const id of agentIds) {
|
|
2226
|
-
const ao = outcomes.filter((t) => t.agent === id)
|
|
2227
|
-
const as = ao.filter((t) => t.outcome === 'success').length
|
|
2228
|
-
agentStats.push({ id, total: ao.length, success: as, rate: ao.length > 0 ? Math.round(as / ao.length * 100) : 0 })
|
|
2229
|
-
}
|
|
2230
|
-
agentStats.sort((a, b) => b.rate - a.rate)
|
|
2231
|
-
const best = agentStats[0], worst = agentStats[agentStats.length - 1]
|
|
2232
|
-
if (best.total >= 5 && worst.total >= 5 && best.rate - worst.rate >= 15) {
|
|
2233
|
-
suggestions.push({ category: 'routing', priority: 'high', title: 'Route tasks to ' + best.id, description: best.id + ' has ' + best.rate + '% success rate vs ' + worst.id + ' at ' + worst.rate + '%.', nextAction: 'Update task routing rules to prefer ' + best.id, impact: 'Could improve overall success rate by ~' + Math.round((best.rate - worst.rate) * 0.3) + '%', basedOn: 'task_outcome comparison' })
|
|
2234
|
-
}
|
|
2235
|
-
}
|
|
2236
|
-
if (shortMemories.length > 5 && memories.length > 10) {
|
|
2237
|
-
suggestions.push({ category: 'memory', priority: 'medium', title: 'Enrich ' + shortMemories.length + ' short memory records', description: Math.round(shortMemories.length / memories.length * 100) + '% of memories have content < 20 chars.', nextAction: 'Review and expand short memory records, or archive irrelevant ones.', impact: 'Improves memory.query recall precision', basedOn: 'memory.jsonl analysis' })
|
|
2238
|
-
}
|
|
2239
|
-
if (pendingReuses.length >= 5) {
|
|
2240
|
-
suggestions.push({ category: 'evidence', priority: 'medium', title: 'Confirm ' + pendingReuses.length + ' pending auto-claims', description: pendingReuses.length + ' auto-claimed reuses await confirmation.', nextAction: 'Call mio.experience.confirm on each auto_claim id.', impact: 'Increases verified reuse count toward Phase 0 threshold', basedOn: 'experience_reuse.jsonl' })
|
|
2241
|
-
}
|
|
2242
|
-
const crossAgent = verifiedReuses.filter((r) => r.sourceAgent !== r.targetAgent)
|
|
2243
|
-
if (agentIds.size >= 2 && crossAgent.length === 0) {
|
|
2244
|
-
suggestions.push({ category: 'interop', priority: 'high', title: 'Enable cross-agent experience sharing', description: 'Multiple agents exist but no cross-agent reuse detected.', nextAction: 'Ensure all agents query shared memory before designing solutions.', impact: 'Unlocks core Agent Control Plane value', basedOn: 'experience_reuse.jsonl' })
|
|
2245
|
-
}
|
|
2246
|
-
if (ideas.length > 0 && ideasWithoutMemory.length > ideas.length * 0.5) {
|
|
2247
|
-
suggestions.push({ category: 'creativity', priority: 'low', title: 'Improve idea grounding (' + ideasWithoutMemory.length + ' ungrounded)', description: Math.round(ideasWithoutMemory.length / ideas.length * 100) + '% of ideas lack related memory context.', nextAction: 'Record more decision/problem memories to enrich the idea pipeline.', impact: 'Higher-quality, more context-aware ideas', basedOn: 'ideas.jsonl provenance' })
|
|
2248
|
-
}
|
|
2249
|
-
if (problems.length >= 3) {
|
|
2250
|
-
const recent = problems.filter((p) => (now - new Date(p.timestamp).getTime()) < 7 * 86400000)
|
|
2251
|
-
if (recent.length >= 2) {
|
|
2252
|
-
suggestions.push({ category: 'health', priority: 'high', title: recent.length + ' problems in last 7 days', description: 'Recurring problems may indicate systemic issues.', nextAction: 'Review recent problems, identify root causes, create decision records.', impact: 'Prevents problem accumulation', basedOn: 'memory.jsonl recent problems' })
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
suggestions.sort((a, b) => ({ high: 0, medium: 1, low: 2 }[a.priority] || 2) - ({ high: 0, medium: 1, low: 2 }[b.priority] || 2))
|
|
2256
|
-
const record = { id: 'evo_' + Date.now(), timestamp: new Date().toISOString(), project, metrics: { agents: agentIds.size, tasks: outcomes.length, successRate, memories: memories.length, decisions: decisions.length, problems: problems.length, verifiedReuses: verifiedReuses.length, pendingReuses: pendingReuses.length, ideas: ideas.length }, suggestions }
|
|
2257
|
-
try { fs.appendFileSync(suggestionsPath, JSON.stringify(record) + '\n') } catch (_) {}
|
|
2258
|
-
return record
|
|
2259
|
-
}
|
|
2260
|
-
|
|
2261
2100
|
module.exports = { TOOLS, callTool, handleMessage, readJsonl, appendJsonl, rl }
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@mio/mio-intelligence-mcp",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"description": "Mio Agent Enhancement Layer - MCP-first intelligence core",
|
|
6
|
-
"type": "commonjs",
|
|
7
|
-
"main": "index.js",
|
|
8
|
-
"bin": {
|
|
9
|
-
"mio-intelligence-mcp": "index.js"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"start": "node index.js",
|
|
13
|
-
"check": "node --check index.js"
|
|
14
|
-
},
|
|
15
|
-
"engines": {
|
|
16
|
-
"node": ">=18"
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@akemi-mio/mio-intelligence-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Mio Agent Enhancement Layer - MCP-first intelligence core",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mio-intelligence-mcp": "index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node index.js",
|
|
13
|
+
"check": "node --check index.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
}
|
|
18
18
|
}
|