mio-agent-runtime 0.3.13 → 0.3.15

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/adapters/codex.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
5
  const os = require('os')
6
+ const { restartWarning } = require('./host-utils')
6
7
 
7
8
  const SERVER_SECTION = '[mcp_servers.mio-intelligence]'
8
9
  const ENV_SECTION = '[mcp_servers.mio-intelligence.env]'
@@ -34,6 +35,23 @@ function configNeedsRepair(serverScript) {
34
35
  }
35
36
  }
36
37
 
38
+ function installMessage(installed, restartHint) {
39
+ let message = installed
40
+ ? 'Codex Mio MCP repaired (server path updated). Restart Codex to load it.'
41
+ : 'Codex Mio MCP installed. Restart Codex to load it.'
42
+ if (restartHint) message += ' ' + restartHint
43
+ return message
44
+ }
45
+
46
+ function restartWarningMessage() {
47
+ return restartWarning({
48
+ hostLabel: 'Codex',
49
+ exeName: 'codex.exe',
50
+ exePathFragment: 'OpenAI.Codex',
51
+ configPath: configPath(),
52
+ })
53
+ }
54
+
37
55
  function stripMioSection(toml) {
38
56
  const lines = toml.replace(/\r\n/g, '\n').split('\n')
39
57
  const out = []
@@ -97,10 +115,8 @@ function install({ node, serverScript, home, workspace }) {
97
115
  changed: true,
98
116
  configPath: target,
99
117
  backup,
100
- message: installed
101
- ? 'Codex Mio MCP repaired (server path updated). Restart Codex to load it.'
102
- : 'Codex Mio MCP installed. Restart Codex to load it.',
118
+ message: installMessage(installed, restartWarningMessage()),
103
119
  }
104
120
  }
105
121
 
106
- module.exports = { configPath, isInstalled, install }
122
+ module.exports = { configPath, isInstalled, install, restartWarningMessage }
@@ -0,0 +1,62 @@
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const { spawnSync } = require('child_process')
5
+
6
+ // Windows only: returns the earliest creation time (epoch ms) of a running
7
+ // process whose ExecutablePath contains `exePathFragment`, or null when the
8
+ // host app is not running / detection is unavailable.
9
+ function earliestRunningSince(exePathFragment) {
10
+ if (process.platform !== 'win32') return null
11
+ try {
12
+ const escaped = String(exePathFragment).replace(/'/g, "''")
13
+ const script =
14
+ "Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -like '*" +
15
+ escaped +
16
+ "*' } | ForEach-Object { [long]($_.CreationDate.ToUniversalTime() - [datetime]'1970-01-01').TotalMilliseconds }"
17
+ const res = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], {
18
+ encoding: 'utf8',
19
+ timeout: 10000,
20
+ windowsHide: true,
21
+ })
22
+ if (res.error || res.status !== 0) return null
23
+ const times = (res.stdout || '')
24
+ .split(/\r?\n/)
25
+ .map((line) => line.trim())
26
+ .filter(Boolean)
27
+ .map(Number)
28
+ .filter((value) => Number.isFinite(value) && value > 0)
29
+ if (times.length === 0) return null
30
+ return Math.min(...times)
31
+ } catch (_) {
32
+ return null
33
+ }
34
+ }
35
+
36
+ // Returns a human-readable warning when the host app is currently running from
37
+ // a config that predates its process start (i.e. a restart is required to load
38
+ // the updated Mio MCP config). Returns null when no restart is needed.
39
+ function restartWarning({ hostLabel, exeName, exePathFragment, configPath }) {
40
+ const since = earliestRunningSince(exePathFragment)
41
+ if (since === null) return null
42
+ let mtime = null
43
+ try {
44
+ mtime = fs.statSync(configPath).mtimeMs
45
+ } catch (_) {
46
+ return null
47
+ }
48
+ if (!(mtime > since)) return null
49
+ const started = new Date(since).toISOString().replace('T', ' ').slice(0, 19) + ' UTC'
50
+ return (
51
+ hostLabel +
52
+ ' is running with an older Mio config (app started ' +
53
+ started +
54
+ ', config updated after). Fully quit ' +
55
+ hostLabel +
56
+ ' (end all ' +
57
+ exeName +
58
+ ' processes) and relaunch to load the updated Mio MCP config.'
59
+ )
60
+ }
61
+
62
+ module.exports = { earliestRunningSince, restartWarning }
@@ -3,6 +3,7 @@
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
5
  const os = require('os')
6
+ const { restartWarning } = require('./host-utils')
6
7
 
7
8
  const INSTRUCTIONS_BEGIN = '<!-- MIO_INTELLIGENCE_BEGIN -->'
8
9
  const INSTRUCTIONS_END = '<!-- MIO_INTELLIGENCE_END -->'
@@ -74,6 +75,26 @@ function ensureGlobalInstructions() {
74
75
  return { changed: true, target, backup }
75
76
  }
76
77
 
78
+ function configNeedsRepair(serverScript) {
79
+ const config = readConfig()
80
+ const mcp = config && config.mcp && config.mcp['mio-intelligence']
81
+ if (!mcp) return false
82
+ const command = mcp.command
83
+ if (!Array.isArray(command) || command.length < 2) return true
84
+ const configured = String(command[1]).replace(/\\/g, '/').toLowerCase()
85
+ const needle = String(serverScript).replace(/\\/g, '/').toLowerCase()
86
+ return configured !== needle
87
+ }
88
+
89
+ function restartWarningMessage() {
90
+ return restartWarning({
91
+ hostLabel: 'OpenCode Desktop',
92
+ exeName: 'OpenCode.exe',
93
+ exePathFragment: '@opencode-aidesktop',
94
+ configPath: configPath(),
95
+ })
96
+ }
97
+
77
98
  function isInstalled() {
78
99
  const config = readConfig()
79
100
  if (!config || !config.mcp || !config.mcp['mio-intelligence']) return false
@@ -85,11 +106,12 @@ function install({ node, serverScript, home, workspace, project }) {
85
106
  const target = configPath()
86
107
  const config = readConfig() || {}
87
108
  const configInstalled = Boolean(config.mcp && config.mcp['mio-intelligence'])
109
+ const needsRepair = configInstalled && configNeedsRepair(serverScript)
88
110
 
89
111
  let configChanged = false
90
112
  let backup = null
91
113
 
92
- if (!configInstalled) {
114
+ if (!configInstalled || needsRepair) {
93
115
  backup = `${target}.bak-mio-${Date.now()}`
94
116
  if (fs.existsSync(target)) {
95
117
  fs.copyFileSync(target, backup)
@@ -129,11 +151,15 @@ function install({ node, serverScript, home, workspace, project }) {
129
151
  let message
130
152
  if (configChanged && instructionsResult.changed) {
131
153
  message = 'OpenCode Mio MCP installed and global Mio rules injected into AGENTS.md. Restart OpenCode to load them.'
154
+ } else if (needsRepair && !instructionsResult.changed) {
155
+ message = 'OpenCode Mio MCP repaired (server path updated). Restart OpenCode to load it.'
132
156
  } else if (instructionsResult.changed) {
133
157
  message = 'OpenCode Mio MCP already installed. Injected global Mio rules into AGENTS.md. Restart OpenCode to load them.'
134
158
  } else {
135
159
  message = 'OpenCode Mio MCP already installed.'
136
160
  }
161
+ const restartHint = restartWarningMessage()
162
+ if (restartHint) message += ' ' + restartHint
137
163
 
138
164
  return {
139
165
  changed,
@@ -147,4 +173,4 @@ function install({ node, serverScript, home, workspace, project }) {
147
173
  }
148
174
  }
149
175
 
150
- module.exports = { configPath, globalInstructionsPath, isInstalled, install }
176
+ module.exports = { configPath, globalInstructionsPath, isInstalled, install, configNeedsRepair, restartWarningMessage }
package/bin/mio.js CHANGED
@@ -55,6 +55,8 @@ function initCommand() {
55
55
 
56
56
  function statusCommand(useJson) {
57
57
  const config = readConfig()
58
+ const codexRestart = adapters.codex.restartWarningMessage()
59
+ const opencodeRestart = adapters.opencode.restartWarningMessage()
58
60
  const installed = {
59
61
  codex: adapters.codex.isInstalled(),
60
62
  opencode: adapters.opencode.isInstalled(),
@@ -71,6 +73,10 @@ function statusCommand(useJson) {
71
73
  opencodeInstalled: installed.opencode,
72
74
  workbuddyInstalled: installed.workbuddy,
73
75
  hermesInstalled: installed.hermes,
76
+ codexNeedsRestart: Boolean(codexRestart),
77
+ opencodeNeedsRestart: Boolean(opencodeRestart),
78
+ codexRestartHint: codexRestart,
79
+ opencodeRestartHint: opencodeRestart,
74
80
  hermesObserverReady: fs.existsSync(observer.hermesDbPath()),
75
81
  opencodeObserverReady: fs.existsSync(observer.opencodeDbPath()),
76
82
  observerRunning: observer.isRunning(MIO_HOME),
@@ -83,7 +89,9 @@ function statusCommand(useJson) {
83
89
  console.log(`MIO_HOME: ${MIO_HOME}`)
84
90
  console.log(`MCP Server: ${SERVER_SCRIPT}`)
85
91
  console.log(`Codex MCP: ${installed.codex ? 'installed' : 'not installed'}`)
92
+ if (codexRestart) console.log(`Codex app: running with an older Mio config - fully restart Codex to load it`)
86
93
  console.log(`OpenCode MCP: ${installed.opencode ? 'installed' : 'not installed'}`)
94
+ if (opencodeRestart) console.log(`OpenCode Desktop: running with an older Mio config - restart it to load it`)
87
95
  console.log(`OpenCode observer: ${fs.existsSync(observer.opencodeDbPath()) ? 'ready' : 'no database'}`)
88
96
  console.log(`WorkBuddy MCP: ${installed.workbuddy ? 'installed' : 'not installed'}`)
89
97
  console.log(`Hermes MCP: ${installed.hermes ? 'installed' : 'not installed'}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mio-agent-runtime",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "description": "Mio Agent Runtime installer and MCP intelligence layer",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -16,7 +16,7 @@
16
16
  "!server/mio-intelligence-mcp/__tests__"
17
17
  ],
18
18
  "scripts": {
19
- "check": "node --check bin/mio.js && node --check adapters/codex.js && node --check adapters/opencode.js && node --check adapters/workbuddy.js && node --check adapters/hermes.js && node --check server/mio-intelligence-mcp/index.js && node --check server/mio-intelligence-mcp/phase0.js && node --check observe/observer.js",
19
+ "check": "node --check bin/mio.js && node --check adapters/host-utils.js && node --check adapters/codex.js && node --check adapters/opencode.js && node --check adapters/workbuddy.js && node --check adapters/hermes.js && node --check server/mio-intelligence-mcp/index.js && node --check server/mio-intelligence-mcp/phase0.js && node --check observe/observer.js",
20
20
  "prepack": "npm run check"
21
21
  },
22
22
  "engines": {