toggle-oh-my 1.0.0 → 1.0.1
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 +5 -5
- package/index.js +46 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,10 +8,10 @@ The plugin reads your opencode config (`~/.config/opencode/opencode.jsonc` or pr
|
|
|
8
8
|
|
|
9
9
|
| State | plugin entry |
|
|
10
10
|
|-------|-------------|
|
|
11
|
-
| **ON** | `"oh-my-
|
|
12
|
-
| **OFF** | `"disabled_oh-my-
|
|
11
|
+
| **ON** | `"oh-my-openagent@latest"` (or `oh-my-opencode@latest`) |
|
|
12
|
+
| **OFF** | `"disabled_oh-my-openagent@latest"` (or `disabled_oh-my-opencode@latest`) |
|
|
13
13
|
|
|
14
|
-
The version string (`@latest`, `@1.2.3`, etc.) is preserved during the toggle, so you never lose the version pin.
|
|
14
|
+
Both `oh-my-openagent` and `oh-my-opencode` names are supported (they are the same npm package). The version string (`@latest`, `@1.2.3`, etc.) is preserved during the toggle, so you never lose the version pin.
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
@@ -31,10 +31,10 @@ Then add to your `opencode.json` / `opencode.jsonc`:
|
|
|
31
31
|
|
|
32
32
|
```json
|
|
33
33
|
{
|
|
34
|
-
"plugin": ["toggle-oh-my", "oh-my-
|
|
34
|
+
"plugin": ["toggle-oh-my", "oh-my-openagent@latest"]
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Compatibility
|
|
39
39
|
|
|
40
|
-
Works with any version
|
|
40
|
+
Works with any version (oh-my-openagent, oh-my-opencode). The version specifier (`@latest`, `@1.x`, etc.) is preserved through toggles.
|
package/index.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
2
2
|
import { homedir, platform } from 'os';
|
|
3
|
-
import { join
|
|
3
|
+
import { join } from 'path';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const PLUGIN_NAMES = ['oh-my-openagent', 'oh-my-opencode'];
|
|
6
6
|
const DISABLED_PREFIX = 'disabled_';
|
|
7
|
-
const PLUGIN_DISPLAY = 'oh-my-
|
|
7
|
+
const PLUGIN_DISPLAY = 'oh-my-openagent';
|
|
8
|
+
|
|
9
|
+
function escapeRegex(str) {
|
|
10
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
11
|
+
}
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
|
-
* Find and read the opencode config file that contains the plugin
|
|
14
|
+
* Find and read the opencode config file that contains any of the known plugin names.
|
|
11
15
|
* Checks project-level config first, then user-level config.
|
|
12
16
|
*/
|
|
13
17
|
function findConfig() {
|
|
18
|
+
const hasAnyPlugin = (raw) =>
|
|
19
|
+
PLUGIN_NAMES.some((n) => raw.includes(n) || raw.includes(DISABLED_PREFIX + n));
|
|
20
|
+
|
|
14
21
|
// project-level: <cwd>/.opencode/opencode.json
|
|
15
22
|
const projectCandidates = [
|
|
16
23
|
join(process.cwd(), '.opencode', 'opencode.json'),
|
|
@@ -19,7 +26,7 @@ function findConfig() {
|
|
|
19
26
|
for (const fp of projectCandidates) {
|
|
20
27
|
if (!existsSync(fp)) continue;
|
|
21
28
|
const raw = readFileSync(fp, 'utf-8');
|
|
22
|
-
if (
|
|
29
|
+
if (hasAnyPlugin(raw)) {
|
|
23
30
|
return { path: fp, raw, format: fp.endsWith('.jsonc') ? 'jsonc' : 'json' };
|
|
24
31
|
}
|
|
25
32
|
}
|
|
@@ -51,37 +58,51 @@ function findConfig() {
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
|
|
61
|
+
* Detect which plugin name is currently in the config (enabled or disabled).
|
|
62
|
+
* Returns the actual name found, or null.
|
|
63
|
+
*/
|
|
64
|
+
function detectActiveName(raw) {
|
|
65
|
+
for (const name of PLUGIN_NAMES) {
|
|
66
|
+
const enabledRE = new RegExp(`"(${escapeRegex(name)}(?:@[^"]*)?)"`);
|
|
67
|
+
const disabledRE = new RegExp(`"(${escapeRegex(DISABLED_PREFIX)}${escapeRegex(name)}(?:@[^"]*)?)"`);
|
|
68
|
+
if (enabledRE.test(raw) || disabledRE.test(raw)) {
|
|
69
|
+
return name;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Toggle the plugin in the raw config text.
|
|
77
|
+
* Preserves version and original formatting.
|
|
57
78
|
*/
|
|
58
79
|
function toggleInText(raw) {
|
|
59
|
-
|
|
60
|
-
|
|
80
|
+
const activeName = detectActiveName(raw);
|
|
81
|
+
if (!activeName) {
|
|
82
|
+
return { raw: null, newState: 'not-found', version: '' };
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
const enabledPattern = new RegExp(
|
|
62
|
-
`"(${escapeRegex(
|
|
86
|
+
`"(${escapeRegex(activeName)}(?:@[^"]*)?)"`,
|
|
63
87
|
'g'
|
|
64
88
|
);
|
|
65
89
|
const disabledPattern = new RegExp(
|
|
66
|
-
`"(${escapeRegex(DISABLED_PREFIX)}${escapeRegex(
|
|
90
|
+
`"(${escapeRegex(DISABLED_PREFIX)}${escapeRegex(activeName)}(?:@[^"]*)?)"`,
|
|
67
91
|
'g'
|
|
68
92
|
);
|
|
69
93
|
|
|
70
94
|
let isCurrentlyEnabled = false;
|
|
71
95
|
let version = '';
|
|
72
96
|
|
|
73
|
-
// Check if currently enabled
|
|
74
97
|
let match;
|
|
75
98
|
enabledPattern.lastIndex = 0;
|
|
76
99
|
while ((match = enabledPattern.exec(raw)) !== null) {
|
|
77
100
|
isCurrentlyEnabled = true;
|
|
78
|
-
// Extract version from the match
|
|
79
101
|
const atIdx = match[1].indexOf('@');
|
|
80
102
|
version = atIdx >= 0 ? match[1].slice(atIdx) : '';
|
|
81
103
|
break;
|
|
82
104
|
}
|
|
83
105
|
|
|
84
|
-
// Check if currently disabled
|
|
85
106
|
disabledPattern.lastIndex = 0;
|
|
86
107
|
let disabledVersion = '';
|
|
87
108
|
while ((match = disabledPattern.exec(raw)) !== null) {
|
|
@@ -91,31 +112,23 @@ function toggleInText(raw) {
|
|
|
91
112
|
break;
|
|
92
113
|
}
|
|
93
114
|
|
|
94
|
-
let toggledText;
|
|
95
115
|
if (isCurrentlyEnabled) {
|
|
96
|
-
|
|
97
|
-
toggledText = raw.replace(
|
|
116
|
+
const toggledText = raw.replace(
|
|
98
117
|
enabledPattern,
|
|
99
|
-
`"${DISABLED_PREFIX}${
|
|
118
|
+
`"${DISABLED_PREFIX}${activeName}${version}"`
|
|
100
119
|
);
|
|
101
|
-
return { raw: toggledText, newState: 'disabled', version };
|
|
120
|
+
return { raw: toggledText, newState: 'disabled', version, activeName };
|
|
102
121
|
} else if (disabledVersion !== '') {
|
|
103
|
-
|
|
104
|
-
toggledText = raw.replace(
|
|
122
|
+
const toggledText = raw.replace(
|
|
105
123
|
disabledPattern,
|
|
106
|
-
`"${
|
|
124
|
+
`"${activeName}${disabledVersion}"`
|
|
107
125
|
);
|
|
108
|
-
return { raw: toggledText, newState: 'enabled', version: disabledVersion };
|
|
126
|
+
return { raw: toggledText, newState: 'enabled', version: disabledVersion, activeName };
|
|
109
127
|
}
|
|
110
128
|
|
|
111
|
-
// Not found in any form
|
|
112
129
|
return { raw: null, newState: 'not-found', version: '' };
|
|
113
130
|
}
|
|
114
131
|
|
|
115
|
-
function escapeRegex(str) {
|
|
116
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
132
|
export const ToggleOhMyPlugin = async () => {
|
|
120
133
|
return {
|
|
121
134
|
config: async (opencodeConfig) => {
|
|
@@ -146,7 +159,7 @@ export const ToggleOhMyPlugin = async () => {
|
|
|
146
159
|
if (result.newState === 'not-found') {
|
|
147
160
|
output.parts = [{
|
|
148
161
|
type: 'text',
|
|
149
|
-
text: `⚠️
|
|
162
|
+
text: `⚠️ Plugin not found in ${configFile.path}. Nothing to toggle.`,
|
|
150
163
|
}];
|
|
151
164
|
return;
|
|
152
165
|
}
|
|
@@ -154,9 +167,10 @@ export const ToggleOhMyPlugin = async () => {
|
|
|
154
167
|
// Write the modified config back
|
|
155
168
|
writeFileSync(configFile.path, result.raw, 'utf-8');
|
|
156
169
|
|
|
170
|
+
const name = result.activeName || PLUGIN_DISPLAY;
|
|
157
171
|
const message = result.newState === 'enabled'
|
|
158
|
-
? `✅ **${
|
|
159
|
-
: `❌ **${
|
|
172
|
+
? `✅ **${name}${result.version}** is now **ENABLED**\n Restart opencode to apply.`
|
|
173
|
+
: `❌ **${name}${result.version}** is now **DISABLED**\n Restart opencode to apply.`;
|
|
160
174
|
|
|
161
175
|
output.parts = [{ type: 'text', text: message }];
|
|
162
176
|
},
|