mio-agent-runtime 0.3.4 → 0.3.6
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 +102 -79
- package/adapters/hermes.js +90 -0
- package/bin/mio.js +255 -247
- package/observe/observer.js +576 -1
- package/package.json +2 -2
package/bin/mio.js
CHANGED
|
@@ -1,247 +1,255 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
const fs = require('fs')
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const os = require('os')
|
|
7
|
-
|
|
8
|
-
const SERVER_SCRIPT = path.resolve(__dirname, '..', 'server', 'mio-intelligence-mcp', 'index.js')
|
|
9
|
-
const MIO_HOME = process.env.MIO_HOME || path.join(os.homedir(), '.mio-intelligence')
|
|
10
|
-
const CONFIG_FILE = path.join(MIO_HOME, 'config.json')
|
|
11
|
-
|
|
12
|
-
const adapters = {
|
|
13
|
-
codex: require('../adapters/codex.js'),
|
|
14
|
-
opencode: require('../adapters/opencode.js'),
|
|
15
|
-
workbuddy: require('../adapters/workbuddy.js'),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
fs.mkdirSync(
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
console.log(`
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
mio
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
case '
|
|
234
|
-
return
|
|
235
|
-
case '
|
|
236
|
-
return
|
|
237
|
-
case '
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const fs = require('fs')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const os = require('os')
|
|
7
|
+
|
|
8
|
+
const SERVER_SCRIPT = path.resolve(__dirname, '..', 'server', 'mio-intelligence-mcp', 'index.js')
|
|
9
|
+
const MIO_HOME = process.env.MIO_HOME || path.join(os.homedir(), '.mio-intelligence')
|
|
10
|
+
const CONFIG_FILE = path.join(MIO_HOME, 'config.json')
|
|
11
|
+
|
|
12
|
+
const adapters = {
|
|
13
|
+
codex: require('../adapters/codex.js'),
|
|
14
|
+
opencode: require('../adapters/opencode.js'),
|
|
15
|
+
workbuddy: require('../adapters/workbuddy.js'),
|
|
16
|
+
hermes: require('../adapters/hermes.js'),
|
|
17
|
+
}
|
|
18
|
+
const observer = require('../observe/observer.js')
|
|
19
|
+
|
|
20
|
+
function ensureHome() {
|
|
21
|
+
fs.mkdirSync(MIO_HOME, { recursive: true })
|
|
22
|
+
fs.mkdirSync(path.join(MIO_HOME, 'logs'), { recursive: true })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function readConfig() {
|
|
26
|
+
const fallback = { version: 1, home: MIO_HOME, agents: {} }
|
|
27
|
+
if (!fs.existsSync(CONFIG_FILE)) return fallback
|
|
28
|
+
try {
|
|
29
|
+
return { ...fallback, ...JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) }
|
|
30
|
+
} catch (_) {
|
|
31
|
+
return fallback
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writeConfig(config) {
|
|
36
|
+
ensureHome()
|
|
37
|
+
fs.writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\n`, 'utf8')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function jsonOrText(payload, useJson) {
|
|
41
|
+
if (useJson) {
|
|
42
|
+
console.log(JSON.stringify(payload, null, 2))
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
return payload
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function initCommand() {
|
|
49
|
+
ensureHome()
|
|
50
|
+
const config = readConfig()
|
|
51
|
+
if (!config.createdAt) config.createdAt = new Date().toISOString()
|
|
52
|
+
writeConfig(config)
|
|
53
|
+
console.log(`MIO_HOME ready: ${MIO_HOME}`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function statusCommand(useJson) {
|
|
57
|
+
const config = readConfig()
|
|
58
|
+
const installed = {
|
|
59
|
+
codex: adapters.codex.isInstalled(),
|
|
60
|
+
opencode: adapters.opencode.isInstalled(),
|
|
61
|
+
workbuddy: adapters.workbuddy.isInstalled(),
|
|
62
|
+
hermes: adapters.hermes.isInstalled(),
|
|
63
|
+
}
|
|
64
|
+
const payload = {
|
|
65
|
+
version: config.version,
|
|
66
|
+
home: MIO_HOME,
|
|
67
|
+
serverScript: SERVER_SCRIPT,
|
|
68
|
+
serverScriptExists: fs.existsSync(SERVER_SCRIPT),
|
|
69
|
+
agents: config.agents || {},
|
|
70
|
+
codexInstalled: installed.codex,
|
|
71
|
+
opencodeInstalled: installed.opencode,
|
|
72
|
+
workbuddyInstalled: installed.workbuddy,
|
|
73
|
+
hermesInstalled: installed.hermes,
|
|
74
|
+
hermesObserverReady: fs.existsSync(observer.hermesDbPath()),
|
|
75
|
+
opencodeObserverReady: fs.existsSync(observer.opencodeDbPath()),
|
|
76
|
+
observerRunning: observer.isRunning(MIO_HOME),
|
|
77
|
+
observerPid: observer.isRunning(MIO_HOME) ? observer.readPid(MIO_HOME) : null,
|
|
78
|
+
}
|
|
79
|
+
if (useJson) {
|
|
80
|
+
jsonOrText(payload, true)
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
console.log(`MIO_HOME: ${MIO_HOME}`)
|
|
84
|
+
console.log(`MCP Server: ${SERVER_SCRIPT}`)
|
|
85
|
+
console.log(`Codex MCP: ${installed.codex ? 'installed' : 'not installed'}`)
|
|
86
|
+
console.log(`OpenCode MCP: ${installed.opencode ? 'installed' : 'not installed'}`)
|
|
87
|
+
console.log(`OpenCode observer: ${fs.existsSync(observer.opencodeDbPath()) ? 'ready' : 'no database'}`)
|
|
88
|
+
console.log(`WorkBuddy MCP: ${installed.workbuddy ? 'installed' : 'not installed'}`)
|
|
89
|
+
console.log(`Hermes MCP: ${installed.hermes ? 'installed' : 'not installed'}`)
|
|
90
|
+
console.log(`Hermes observer: ${fs.existsSync(observer.hermesDbPath()) ? 'ready' : 'no database'}`)
|
|
91
|
+
console.log(`Observer: ${observer.isRunning(MIO_HOME) ? 'running (pid ' + observer.readPid(MIO_HOME) + ')' : 'not running'}`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function agentsCommand(useJson) {
|
|
95
|
+
const config = readConfig()
|
|
96
|
+
const agents = config.agents || {}
|
|
97
|
+
if (useJson) {
|
|
98
|
+
jsonOrText(agents, true)
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
const names = Object.keys(agents)
|
|
102
|
+
if (names.length === 0) {
|
|
103
|
+
console.log('No agents installed.')
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
for (const name of names) {
|
|
107
|
+
console.log(`${name}\t${agents[name].installedAt || ''}`)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function installCommand(host, useJson) {
|
|
112
|
+
if (!host) {
|
|
113
|
+
console.error('Usage: mio install <codex|opencode|workbuddy|hermes>')
|
|
114
|
+
process.exitCode = 1
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
const adapter = adapters[host]
|
|
118
|
+
if (!adapter) {
|
|
119
|
+
console.error(`Unknown host: ${host}`)
|
|
120
|
+
process.exitCode = 1
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
ensureHome()
|
|
124
|
+
const config = readConfig()
|
|
125
|
+
let result
|
|
126
|
+
try {
|
|
127
|
+
result = adapter.install({
|
|
128
|
+
node: process.execPath,
|
|
129
|
+
serverScript: SERVER_SCRIPT,
|
|
130
|
+
home: MIO_HOME,
|
|
131
|
+
workspace: process.cwd(),
|
|
132
|
+
})
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(`Failed to install ${host}: ${error.message || error}`)
|
|
135
|
+
process.exitCode = 1
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
if (result.changed) {
|
|
139
|
+
config.agents = config.agents || {}
|
|
140
|
+
config.agents[host] = {
|
|
141
|
+
installedAt: new Date().toISOString(),
|
|
142
|
+
configPath: result.configPath || null,
|
|
143
|
+
}
|
|
144
|
+
writeConfig(config)
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
observer.runCycle(MIO_HOME, observer.loadState(MIO_HOME), observer.createSinks(MIO_HOME))
|
|
148
|
+
} catch (_) {}
|
|
149
|
+
let observerStarted = false
|
|
150
|
+
try {
|
|
151
|
+
observerStarted = observer.startBackground(MIO_HOME).started
|
|
152
|
+
} catch (_) {}
|
|
153
|
+
if (useJson) {
|
|
154
|
+
result.observer = {
|
|
155
|
+
running: observer.isRunning(MIO_HOME),
|
|
156
|
+
started: observerStarted,
|
|
157
|
+
}
|
|
158
|
+
jsonOrText(result, true)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
console.log(result.message || `${host} adapter completed.`)
|
|
162
|
+
console.log(
|
|
163
|
+
observer.isRunning(MIO_HOME)
|
|
164
|
+
? 'Observer daemon running.'
|
|
165
|
+
: 'Observer daemon not running. Run `mio observe --start`.'
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function mcpCommand() {
|
|
170
|
+
require(SERVER_SCRIPT)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function observeCommand(args) {
|
|
174
|
+
const flags = args.slice(1)
|
|
175
|
+
const useJson = flags.includes('--json')
|
|
176
|
+
if (flags.includes('--start')) {
|
|
177
|
+
const result = observer.startBackground(MIO_HOME)
|
|
178
|
+
if (useJson) return jsonOrText(result, true)
|
|
179
|
+
console.log(result.started ? 'Observer started.' : 'Observer already running.')
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
if (flags.includes('--stop')) {
|
|
183
|
+
const result = observer.stopBackground(MIO_HOME)
|
|
184
|
+
if (useJson) return jsonOrText(result, true)
|
|
185
|
+
console.log(result.stopped ? 'Observer stopped.' : 'Observer was not running.')
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
if (flags.includes('--status')) {
|
|
189
|
+
const running = observer.isRunning(MIO_HOME)
|
|
190
|
+
const pid = observer.readPid(MIO_HOME)
|
|
191
|
+
if (useJson) return jsonOrText({ running, pid }, true)
|
|
192
|
+
console.log(running ? 'Observer: running (pid ' + pid + ')' : 'Observer: not running')
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
if (flags.includes('--once')) {
|
|
196
|
+
const res = observer.runCycle(
|
|
197
|
+
MIO_HOME,
|
|
198
|
+
observer.loadState(MIO_HOME),
|
|
199
|
+
observer.createSinks(MIO_HOME)
|
|
200
|
+
)
|
|
201
|
+
if (useJson) return jsonOrText(res, true)
|
|
202
|
+
console.log('Observed files=' + res.files + ' lines=' + res.lines + ' outcomes=' + res.outcomes)
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
console.log('Observing WorkBuddy transcripts into ' + MIO_HOME + ' (Ctrl+C to stop)...')
|
|
206
|
+
observer.startForeground(MIO_HOME)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function help() {
|
|
210
|
+
console.log(`Mio Agent Runtime CLI
|
|
211
|
+
|
|
212
|
+
Usage:
|
|
213
|
+
mio init Initialize MIO_HOME
|
|
214
|
+
mio mcp Start Mio MCP server (stdio)
|
|
215
|
+
mio install <host> Install Mio into a host (codex|opencode|workbuddy|hermes)
|
|
216
|
+
mio status Show runtime and adapter status
|
|
217
|
+
mio agents List installed agents
|
|
218
|
+
mio observe Watch WorkBuddy transcripts and auto-ingest task outcomes
|
|
219
|
+
mio observe --start|--stop|--status|--once Manage the background observer daemon
|
|
220
|
+
mio --json status Machine-readable status
|
|
221
|
+
mio --json agents Machine-readable agents
|
|
222
|
+
`)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function main() {
|
|
226
|
+
const args = process.argv.slice(2)
|
|
227
|
+
const jsonIndex = args.indexOf('--json')
|
|
228
|
+
const useJson = jsonIndex !== -1
|
|
229
|
+
if (useJson) args.splice(jsonIndex, 1)
|
|
230
|
+
const command = args[0] || 'help'
|
|
231
|
+
|
|
232
|
+
switch (command) {
|
|
233
|
+
case 'init':
|
|
234
|
+
return initCommand()
|
|
235
|
+
case 'mcp':
|
|
236
|
+
return mcpCommand()
|
|
237
|
+
case 'install':
|
|
238
|
+
return installCommand(args[1], useJson)
|
|
239
|
+
case 'status':
|
|
240
|
+
return statusCommand(useJson)
|
|
241
|
+
case 'agents':
|
|
242
|
+
return agentsCommand(useJson)
|
|
243
|
+
case 'observe':
|
|
244
|
+
return observeCommand(args)
|
|
245
|
+
case 'help':
|
|
246
|
+
case '--help':
|
|
247
|
+
return help()
|
|
248
|
+
default:
|
|
249
|
+
console.error(`Unknown command: ${command}`)
|
|
250
|
+
help()
|
|
251
|
+
process.exitCode = 1
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
main()
|