mio-agent-runtime 0.3.12 → 0.3.14

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
@@ -1,62 +1,106 @@
1
- 'use strict'
2
-
3
- const fs = require('fs')
4
- const path = require('path')
5
- const os = require('os')
6
-
7
- function configPath() {
8
- return path.join(os.homedir(), '.codex', 'config.toml')
9
- }
10
-
11
- function isInstalled() {
12
- const target = configPath()
13
- if (!fs.existsSync(target)) return false
14
- return fs.readFileSync(target, 'utf8').includes('[mcp_servers.mio-intelligence]')
15
- }
16
-
17
- function install({ node, serverScript, home, workspace }) {
18
- const target = configPath()
19
- const backup = `${target}.bak-mio-${Date.now()}`
20
- if (isInstalled()) {
21
- return {
22
- changed: false,
23
- configPath: target,
24
- message: 'Codex Mio MCP already installed.',
25
- }
26
- }
27
-
28
- if (fs.existsSync(target)) {
29
- fs.copyFileSync(target, backup)
30
- }
31
-
32
- const context = JSON.stringify({
33
- agentId: 'codex',
34
- workspace: workspace || process.cwd(),
35
- sessionId: 'codex-session',
36
- })
37
-
38
- fs.mkdirSync(path.dirname(target), { recursive: true })
39
- let toml = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : ''
40
- if (!toml.endsWith('\n')) toml += '\n'
41
- const section = [
42
- '[mcp_servers.mio-intelligence]',
43
- `command = '${node}'`,
44
- `args = ['${serverScript}']`,
45
- 'startup_timeout_sec = 30',
46
- '',
47
- '[mcp_servers.mio-intelligence.env]',
48
- `MIO_DATA_DIR = '${home}'`,
49
- `MIO_CONTEXT = '${context}'`,
50
- '',
51
- ].join('\n')
52
- fs.writeFileSync(target, `${toml}${section}\n`, 'utf8')
53
-
54
- return {
55
- changed: true,
56
- configPath: target,
57
- backup,
58
- message: 'Codex Mio MCP installed. Restart Codex to load it.',
59
- }
60
- }
61
-
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const os = require('os')
6
+
7
+ const SERVER_SECTION = '[mcp_servers.mio-intelligence]'
8
+ const ENV_SECTION = '[mcp_servers.mio-intelligence.env]'
9
+
10
+ function configPath() {
11
+ return path.join(os.homedir(), '.codex', 'config.toml')
12
+ }
13
+
14
+ function isInstalled() {
15
+ const target = configPath()
16
+ if (!fs.existsSync(target)) return false
17
+ return fs.readFileSync(target, 'utf8').includes(SERVER_SECTION)
18
+ }
19
+
20
+ // Legacy installs pointed args at the worktree copy of the server
21
+ // (server/mio-intelligence-mcp/index.js) instead of this package's copy
22
+ // (server/mio-intelligence-mcp/index.js). Detect staleness by comparing the
23
+ // configured args path with the server path this package ships.
24
+ function configNeedsRepair(serverScript) {
25
+ const target = configPath()
26
+ if (!fs.existsSync(target)) return false
27
+ try {
28
+ const src = fs.readFileSync(target, 'utf8')
29
+ if (!src.includes(SERVER_SECTION)) return false
30
+ const needle = serverScript.replace(/\\/g, '/').toLowerCase()
31
+ return !src.replace(/\\/g, '/').toLowerCase().includes(needle)
32
+ } catch (_) {
33
+ return false
34
+ }
35
+ }
36
+
37
+ function stripMioSection(toml) {
38
+ const lines = toml.replace(/\r\n/g, '\n').split('\n')
39
+ const out = []
40
+ let skipping = false
41
+ for (const line of lines) {
42
+ const trimmed = line.trim()
43
+ if (trimmed === SERVER_SECTION || trimmed === ENV_SECTION) {
44
+ skipping = true
45
+ continue
46
+ }
47
+ if (skipping && /^\[.*\]$/.test(trimmed)) {
48
+ skipping = false
49
+ }
50
+ if (!skipping) out.push(line)
51
+ }
52
+ return out.join('\n').replace(/\n{3,}/g, '\n\n').trimEnd() + '\n'
53
+ }
54
+
55
+ function install({ node, serverScript, home, workspace }) {
56
+ const target = configPath()
57
+ const backup = `${target}.bak-mio-${Date.now()}`
58
+ const installed = isInstalled()
59
+ if (installed && !configNeedsRepair(serverScript)) {
60
+ return {
61
+ changed: false,
62
+ configPath: target,
63
+ message: 'Codex Mio MCP already installed.',
64
+ }
65
+ }
66
+
67
+ if (fs.existsSync(target)) {
68
+ fs.copyFileSync(target, backup)
69
+ }
70
+
71
+ const context = JSON.stringify({
72
+ agentId: 'codex',
73
+ workspace: workspace || process.cwd(),
74
+ sessionId: 'codex-session',
75
+ })
76
+
77
+ fs.mkdirSync(path.dirname(target), { recursive: true })
78
+ let toml = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : ''
79
+ toml = stripMioSection(toml)
80
+ toml = toml.replace(/\n{3,}/g, '\n\n')
81
+ if (!toml.endsWith('\n')) toml += '\n'
82
+ const section = [
83
+ '',
84
+ SERVER_SECTION,
85
+ `command = '${node}'`,
86
+ `args = ['${serverScript}']`,
87
+ 'startup_timeout_sec = 30',
88
+ '',
89
+ ENV_SECTION,
90
+ `MIO_DATA_DIR = '${home}'`,
91
+ `MIO_CONTEXT = '${context}'`,
92
+ '',
93
+ ].join('\n')
94
+ fs.writeFileSync(target, `${toml}${section}\n`, 'utf8')
95
+
96
+ return {
97
+ changed: true,
98
+ configPath: target,
99
+ 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.',
103
+ }
104
+ }
105
+
62
106
  module.exports = { configPath, isInstalled, install }
@@ -74,6 +74,17 @@ function ensureGlobalInstructions() {
74
74
  return { changed: true, target, backup }
75
75
  }
76
76
 
77
+ function configNeedsRepair(serverScript) {
78
+ const config = readConfig()
79
+ const mcp = config && config.mcp && config.mcp['mio-intelligence']
80
+ if (!mcp) return false
81
+ const command = mcp.command
82
+ if (!Array.isArray(command) || command.length < 2) return true
83
+ const configured = String(command[1]).replace(/\\/g, '/').toLowerCase()
84
+ const needle = String(serverScript).replace(/\\/g, '/').toLowerCase()
85
+ return configured !== needle
86
+ }
87
+
77
88
  function isInstalled() {
78
89
  const config = readConfig()
79
90
  if (!config || !config.mcp || !config.mcp['mio-intelligence']) return false
@@ -85,11 +96,12 @@ function install({ node, serverScript, home, workspace, project }) {
85
96
  const target = configPath()
86
97
  const config = readConfig() || {}
87
98
  const configInstalled = Boolean(config.mcp && config.mcp['mio-intelligence'])
99
+ const needsRepair = configInstalled && configNeedsRepair(serverScript)
88
100
 
89
101
  let configChanged = false
90
102
  let backup = null
91
103
 
92
- if (!configInstalled) {
104
+ if (!configInstalled || needsRepair) {
93
105
  backup = `${target}.bak-mio-${Date.now()}`
94
106
  if (fs.existsSync(target)) {
95
107
  fs.copyFileSync(target, backup)
@@ -129,6 +141,8 @@ function install({ node, serverScript, home, workspace, project }) {
129
141
  let message
130
142
  if (configChanged && instructionsResult.changed) {
131
143
  message = 'OpenCode Mio MCP installed and global Mio rules injected into AGENTS.md. Restart OpenCode to load them.'
144
+ } else if (needsRepair && !instructionsResult.changed) {
145
+ message = 'OpenCode Mio MCP repaired (server path updated). Restart OpenCode to load it.'
132
146
  } else if (instructionsResult.changed) {
133
147
  message = 'OpenCode Mio MCP already installed. Injected global Mio rules into AGENTS.md. Restart OpenCode to load them.'
134
148
  } else {
@@ -147,4 +161,4 @@ function install({ node, serverScript, home, workspace, project }) {
147
161
  }
148
162
  }
149
163
 
150
- module.exports = { configPath, globalInstructionsPath, isInstalled, install }
164
+ module.exports = { configPath, globalInstructionsPath, isInstalled, install, configNeedsRepair }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mio-agent-runtime",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Mio Agent Runtime installer and MCP intelligence layer",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",