mio-agent-runtime 0.5.2 → 0.5.4
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/package.json +1 -1
- package/server/mio-intelligence-mcp/index.js +106 -52
package/package.json
CHANGED
|
@@ -19,7 +19,9 @@ const experienceReusePath = path.join(dataDir, 'experience_reuse.jsonl')
|
|
|
19
19
|
const queryPath = path.join(dataDir, 'queries.jsonl')
|
|
20
20
|
const agentsPath = path.join(dataDir, 'agents.jsonl')
|
|
21
21
|
const subscriptionPath = path.join(dataDir, 'subscriptions.jsonl')
|
|
22
|
-
const digestStatePath = path.join(dataDir, 'digest_state.json')
|
|
22
|
+
const digestStatePath = path.join(dataDir, 'digest_state.json')
|
|
23
|
+
const ideasPath = path.join(dataDir, 'ideas.jsonl')
|
|
24
|
+
const suggestionsPath = path.join(dataDir, 'suggestions.jsonl')
|
|
23
25
|
fs.mkdirSync(dataDir, { recursive: true })
|
|
24
26
|
|
|
25
27
|
const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
|
|
@@ -1635,8 +1637,52 @@ const TOOLS = [
|
|
|
1635
1637
|
additionalProperties: false
|
|
1636
1638
|
},
|
|
1637
1639
|
},
|
|
1640
|
+
{
|
|
1641
|
+
name: 'mio.idea.list',
|
|
1642
|
+
description: 'List previously generated ideas, optionally filtered by keyword, strategy, or time window.',
|
|
1643
|
+
inputSchema: {
|
|
1644
|
+
type: 'object',
|
|
1645
|
+
properties: {
|
|
1646
|
+
goal: { type: 'string', description: '(Optional) Filter ideas whose goal contains this keyword.' },
|
|
1647
|
+
strategy: { type: 'string', description: '(Optional) Filter by generation strategy (e.g. SCAMPER, Analogy).' },
|
|
1648
|
+
limit: { type: 'integer', description: '(Optional) Max results, default 10.', default: 10, minimum: 1 },
|
|
1649
|
+
period: { type: 'string', description: '(Optional) Time window: 24h, 7d, 30d, or all (default).' }
|
|
1650
|
+
}
|
|
1651
|
+
},
|
|
1652
|
+
},
|
|
1653
|
+
{
|
|
1654
|
+
name: 'mio.evolution.suggest',
|
|
1655
|
+
description: 'Analyze ecosystem data and produce prioritized improvement suggestions with next actions and expected impact.',
|
|
1656
|
+
inputSchema: {
|
|
1657
|
+
type: 'object',
|
|
1658
|
+
properties: {
|
|
1659
|
+
project: { type: 'string', description: 'Project name filter. Defaults to current repository.' }
|
|
1660
|
+
}
|
|
1661
|
+
},
|
|
1662
|
+
},
|
|
1638
1663
|
]
|
|
1639
1664
|
|
|
1665
|
+
function listIdeas(args = {}) {
|
|
1666
|
+
if (!fs.existsSync(ideasPath)) return { ideas: [], count: 0, total: 0 }
|
|
1667
|
+
const now = Date.now()
|
|
1668
|
+
const period = String(args.period || 'all').trim()
|
|
1669
|
+
const periodMs = period === '24h' ? 86400000 : period === '7d' ? 604800000 : period === '30d' ? 2592000000 : Infinity
|
|
1670
|
+
const cutoff = periodMs === Infinity ? 0 : now - periodMs
|
|
1671
|
+
const goalFilter = args.goal ? String(args.goal).toLowerCase() : null
|
|
1672
|
+
const strategyFilter = args.strategy ? String(args.strategy).trim().toLowerCase() : null
|
|
1673
|
+
const limit = Math.min(Math.max(Number(args.limit) || 10, 1), 50)
|
|
1674
|
+
const all = fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(line => {
|
|
1675
|
+
try { return JSON.parse(line) } catch (_) { return null }
|
|
1676
|
+
}).filter(Boolean)
|
|
1677
|
+
const filtered = all.filter(idea => {
|
|
1678
|
+
if (cutoff && new Date(idea.generatedAt).getTime() < cutoff) return false
|
|
1679
|
+
if (goalFilter && !String(idea.goal || '').toLowerCase().includes(goalFilter)) return false
|
|
1680
|
+
if (strategyFilter && String(idea.provenance?.strategy || '').toLowerCase() !== strategyFilter) return false
|
|
1681
|
+
return true
|
|
1682
|
+
})
|
|
1683
|
+
return { ideas: filtered.slice(-limit), count: filtered.length, total: all.length }
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1640
1686
|
async function callTool(name, args = {}) {
|
|
1641
1687
|
switch (name) {
|
|
1642
1688
|
case 'mio.memory.query':
|
|
@@ -1679,6 +1725,10 @@ async function callTool(name, args = {}) {
|
|
|
1679
1725
|
return recordTaskOutcome(args)
|
|
1680
1726
|
case 'mio.idea.generate':
|
|
1681
1727
|
return handleIdeaGenerate(args)
|
|
1728
|
+
case 'mio.idea.list':
|
|
1729
|
+
return listIdeas(args)
|
|
1730
|
+
case 'mio.evolution.suggest':
|
|
1731
|
+
return evolutionSuggest(args)
|
|
1682
1732
|
default:
|
|
1683
1733
|
throw new Error(`Unknown tool: ${name}`)
|
|
1684
1734
|
}
|
|
@@ -1999,60 +2049,64 @@ function recordTaskOutcome(args = {}) {
|
|
|
1999
2049
|
}
|
|
2000
2050
|
|
|
2001
2051
|
|
|
2002
|
-
|
|
2003
|
-
const
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
}
|
|
2013
|
-
const
|
|
2014
|
-
const
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
'First-Principles',
|
|
2024
|
-
'Random-Stimulus',
|
|
2025
|
-
'Constraint-Inversion'
|
|
2026
|
-
]
|
|
2052
|
+
function evolutionSuggest(args = {}) {
|
|
2053
|
+
const project = args.project || projectName()
|
|
2054
|
+
const now = Date.now()
|
|
2055
|
+
const memories = readJsonl(memoryPath)
|
|
2056
|
+
const traces = readJsonl(tracePath)
|
|
2057
|
+
const reuses = readJsonl(experienceReusePath)
|
|
2058
|
+
const ideas = fs.existsSync(ideasPath)
|
|
2059
|
+
? fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(l => { try { return JSON.parse(l) } catch (_) { return null } }).filter(Boolean)
|
|
2060
|
+
: []
|
|
2061
|
+
const agentIds = new Set()
|
|
2062
|
+
traces.forEach((t) => { if (t.agent) agentIds.add(t.agent) })
|
|
2063
|
+
const outcomes = traces.filter((t) => t.event_type === 'task_outcome')
|
|
2064
|
+
const successes = outcomes.filter((t) => t.outcome === 'success').length
|
|
2065
|
+
const successRate = outcomes.length > 0 ? Math.round((successes / outcomes.length) * 100) : 0
|
|
2066
|
+
const verifiedReuses = reuses.filter((r) => r.confirmed && r.reuse && r.behaviorChanged && r.outcomeImproved)
|
|
2067
|
+
const pendingReuses = reuses.filter((r) => r.source === 'auto_claim' && !r.confirmed)
|
|
2068
|
+
const decisions = memories.filter((m) => m.kind === 'decision')
|
|
2069
|
+
const problems = memories.filter((m) => m.kind === 'problem')
|
|
2070
|
+
const shortMemories = memories.filter((m) => String(m.content || '').trim().length < 20)
|
|
2071
|
+
const ideasWithoutMemory = ideas.filter((i) => !i.provenance?.relatedMemoryIds?.length)
|
|
2072
|
+
const suggestions = []
|
|
2027
2073
|
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
const
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
})
|
|
2074
|
+
if (agentIds.size >= 2) {
|
|
2075
|
+
const agentStats = []
|
|
2076
|
+
for (const id of agentIds) {
|
|
2077
|
+
const ao = outcomes.filter((t) => t.agent === id)
|
|
2078
|
+
const as = ao.filter((t) => t.outcome === 'success').length
|
|
2079
|
+
agentStats.push({ id, total: ao.length, success: as, rate: ao.length > 0 ? Math.round(as / ao.length * 100) : 0 })
|
|
2080
|
+
}
|
|
2081
|
+
agentStats.sort((a, b) => b.rate - a.rate)
|
|
2082
|
+
const best = agentStats[0], worst = agentStats[agentStats.length - 1]
|
|
2083
|
+
if (best.total >= 5 && worst.total >= 5 && best.rate - worst.rate >= 15) {
|
|
2084
|
+
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' })
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
if (shortMemories.length > 5 && memories.length > 10) {
|
|
2088
|
+
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' })
|
|
2089
|
+
}
|
|
2090
|
+
if (pendingReuses.length >= 5) {
|
|
2091
|
+
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' })
|
|
2092
|
+
}
|
|
2093
|
+
const crossAgent = verifiedReuses.filter((r) => r.sourceAgent !== r.targetAgent)
|
|
2094
|
+
if (agentIds.size >= 2 && crossAgent.length === 0) {
|
|
2095
|
+
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' })
|
|
2096
|
+
}
|
|
2097
|
+
if (ideas.length > 0 && ideasWithoutMemory.length > ideas.length * 0.5) {
|
|
2098
|
+
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' })
|
|
2050
2099
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2100
|
+
if (problems.length >= 3) {
|
|
2101
|
+
const recent = problems.filter((p) => (now - new Date(p.timestamp).getTime()) < 7 * 86400000)
|
|
2102
|
+
if (recent.length >= 2) {
|
|
2103
|
+
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' })
|
|
2104
|
+
}
|
|
2055
2105
|
}
|
|
2106
|
+
suggestions.sort((a, b) => ({ high: 0, medium: 1, low: 2 }[a.priority] || 2) - ({ high: 0, medium: 1, low: 2 }[b.priority] || 2))
|
|
2107
|
+
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 }
|
|
2108
|
+
try { fs.appendFileSync(suggestionsPath, JSON.stringify(record) + '\n') } catch (_) {}
|
|
2109
|
+
return record
|
|
2056
2110
|
}
|
|
2057
2111
|
|
|
2058
2112
|
module.exports = { TOOLS, callTool, handleMessage, readJsonl, appendJsonl, rl }
|