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