opencode-agent-modes 0.1.1 → 0.2.0
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 +34 -3
- package/dist/config/command-installer.d.ts +26 -1
- package/dist/config/initializer.d.ts +39 -3
- package/dist/config/loader.d.ts +1 -1
- package/dist/index.d.ts +29 -4
- package/dist/index.js +90 -40
- package/dist/modes/manager.d.ts +194 -15
- package/package.json +7 -13
package/README.md
CHANGED
|
@@ -147,7 +147,38 @@ To add a custom preset (e.g., "premium"):
|
|
|
147
147
|
|
|
148
148
|
3. Restart opencode to apply changes.
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
> [!INFO]
|
|
151
|
+
> - Changes require an opencode restart to take effect
|
|
152
|
+
> - Custom mode presets can be added by editing the configuration file
|
|
151
153
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
This project uses [Bun](https://bun.sh/) as the runtime and package manager.
|
|
157
|
+
|
|
158
|
+
### Prerequisites
|
|
159
|
+
|
|
160
|
+
- [Bun](https://bun.sh/) v1.0 or later
|
|
161
|
+
|
|
162
|
+
### Setup
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Clone the repository
|
|
166
|
+
git clone https://github.com/j4rviscmd/opencode-agent-modes.git
|
|
167
|
+
cd opencode-agent-modes
|
|
168
|
+
|
|
169
|
+
# Install dependencies
|
|
170
|
+
bun install
|
|
171
|
+
|
|
172
|
+
# Run tests
|
|
173
|
+
bun test
|
|
174
|
+
|
|
175
|
+
# Type check
|
|
176
|
+
bun run typecheck
|
|
177
|
+
|
|
178
|
+
# Lint & format
|
|
179
|
+
bun run lint
|
|
180
|
+
bun run format
|
|
181
|
+
|
|
182
|
+
# Build
|
|
183
|
+
bun run build
|
|
184
|
+
```
|
|
@@ -1,9 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Command file installer for OpenCode slash commands.
|
|
3
|
+
*
|
|
4
|
+
* This module handles copying slash command markdown files from the plugin's
|
|
5
|
+
* commands directory to OpenCode's configuration directory during plugin
|
|
6
|
+
* initialization. This ensures command files are available without requiring
|
|
7
|
+
* manual postinstall script execution.
|
|
8
|
+
*
|
|
9
|
+
* @module config/command-installer
|
|
10
|
+
*/
|
|
1
11
|
/**
|
|
2
12
|
* Copies slash command markdown files to OpenCode's command directory.
|
|
3
13
|
*
|
|
4
14
|
* This function is called during plugin initialization to ensure
|
|
5
15
|
* command files are available without manual postinstall execution.
|
|
16
|
+
* It creates the destination directory if it doesn't exist and copies
|
|
17
|
+
* all `.md` files from the source commands directory.
|
|
18
|
+
*
|
|
19
|
+
* The function is designed to be non-fatal: if copying fails (e.g., due to
|
|
20
|
+
* permission issues), it logs a warning but doesn't throw an error,
|
|
21
|
+
* allowing the plugin to continue initializing.
|
|
22
|
+
*
|
|
23
|
+
* @returns Number of files successfully copied, or -1 if source directory
|
|
24
|
+
* not found or an error occurred during copying
|
|
6
25
|
*
|
|
7
|
-
* @
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const copied = copyCommandFiles();
|
|
29
|
+
* if (copied > 0) {
|
|
30
|
+
* console.log(`Copied ${copied} command files`);
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
8
33
|
*/
|
|
9
34
|
export declare function copyCommandFiles(): number;
|
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
import type { ModeSwitcherConfig } from './types.ts';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Initializes the plugin configuration if it doesn't exist.
|
|
4
|
+
*
|
|
5
|
+
* This function performs the following steps:
|
|
6
|
+
* 1. Checks if a configuration file already exists
|
|
7
|
+
* 2. If exists, loads and returns it
|
|
8
|
+
* 3. If not, creates a new configuration by:
|
|
9
|
+
* - Building a performance preset from current settings
|
|
10
|
+
* - Building an economy preset with free models
|
|
11
|
+
* - Setting default mode to "performance"
|
|
12
|
+
* - Saving the configuration to disk
|
|
13
|
+
*
|
|
14
|
+
* This is called on plugin startup to ensure a valid configuration
|
|
15
|
+
* is always available.
|
|
16
|
+
*
|
|
17
|
+
* @returns Promise resolving to the configuration (existing or newly created)
|
|
18
|
+
* @throws {Error} If configuration creation or file I/O fails
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const config = await initializeConfig();
|
|
22
|
+
* console.log(config.currentMode); // "performance"
|
|
23
|
+
* ```
|
|
5
24
|
*/
|
|
6
25
|
export declare function initializeConfig(): Promise<ModeSwitcherConfig>;
|
|
7
26
|
/**
|
|
8
|
-
*
|
|
27
|
+
* Validates that a configuration object is well-formed and has required presets.
|
|
28
|
+
*
|
|
29
|
+
* This function performs the following checks:
|
|
30
|
+
* - `currentMode` field is present and non-empty
|
|
31
|
+
* - `presets` object exists and contains at least one preset
|
|
32
|
+
* - A preset exists for the current mode
|
|
33
|
+
*
|
|
34
|
+
* @param config - The configuration object to validate
|
|
35
|
+
* @returns True if configuration is valid, false otherwise
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const config = await loadPluginConfig();
|
|
39
|
+
* if (validateConfig(config)) {
|
|
40
|
+
* console.log('Configuration is valid');
|
|
41
|
+
* } else {
|
|
42
|
+
* console.error('Invalid configuration detected');
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
9
45
|
*/
|
|
10
46
|
export declare function validateConfig(config: ModeSwitcherConfig): boolean;
|
package/dist/config/loader.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
|
-
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
1
|
/**
|
|
3
|
-
* OpenCode Agent Mode Switcher Plugin
|
|
2
|
+
* @fileoverview OpenCode Agent Mode Switcher Plugin.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* This plugin provides tools for managing agent mode presets in OpenCode.
|
|
5
|
+
* It allows users to switch between different configurations (e.g., performance
|
|
6
|
+
* vs economy modes) that determine which AI models are used for each agent type.
|
|
7
|
+
*
|
|
8
|
+
* @module index
|
|
9
|
+
*/
|
|
10
|
+
import type { Plugin } from '@opencode-ai/plugin';
|
|
11
|
+
/**
|
|
12
|
+
* OpenCode Agent Mode Switcher Plugin.
|
|
13
|
+
*
|
|
14
|
+
* Provides tools for switching between agent mode presets (e.g., performance
|
|
15
|
+
* vs economy) that configure which AI models are used for each agent type.
|
|
16
|
+
* The plugin initializes on startup by loading configurations and copying
|
|
17
|
+
* slash command files to the OpenCode command directory.
|
|
18
|
+
*
|
|
19
|
+
* @param params - Plugin initialization parameters
|
|
20
|
+
* @param params.client - OpenCode client for SDK interactions
|
|
21
|
+
* @returns Plugin object containing mode management tools
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Plugin is automatically loaded by OpenCode
|
|
26
|
+
* // Users can then use slash commands:
|
|
27
|
+
* // /mode-performance
|
|
28
|
+
* // /mode-economy
|
|
29
|
+
* // /mode-status
|
|
30
|
+
* // /mode-list
|
|
31
|
+
* ```
|
|
7
32
|
*/
|
|
8
33
|
declare const modeSwitcherPlugin: Plugin;
|
|
9
34
|
export default modeSwitcherPlugin;
|
package/dist/index.js
CHANGED
|
@@ -12330,6 +12330,8 @@ function tool(input) {
|
|
|
12330
12330
|
return input;
|
|
12331
12331
|
}
|
|
12332
12332
|
tool.schema = exports_external;
|
|
12333
|
+
// src/config/types.ts
|
|
12334
|
+
var DEFAULT_ECONOMY_MODEL = "opencode/glm-4.7-free";
|
|
12333
12335
|
// src/config/loader.ts
|
|
12334
12336
|
import { homedir } from "os";
|
|
12335
12337
|
import { join } from "path";
|
|
@@ -13790,13 +13792,8 @@ async function saveOhMyOpencodeConfig(config2) {
|
|
|
13790
13792
|
await saveJsonFile(getOhMyOpencodeConfigPath(), config2);
|
|
13791
13793
|
}
|
|
13792
13794
|
async function pluginConfigExists() {
|
|
13793
|
-
|
|
13794
|
-
return await file2.exists();
|
|
13795
|
+
return Bun.file(getPluginConfigPath()).exists();
|
|
13795
13796
|
}
|
|
13796
|
-
|
|
13797
|
-
// src/config/types.ts
|
|
13798
|
-
var DEFAULT_ECONOMY_MODEL = "opencode/glm-4.7-free";
|
|
13799
|
-
|
|
13800
13797
|
// src/config/initializer.ts
|
|
13801
13798
|
var OPENCODE_AGENTS = [
|
|
13802
13799
|
"build",
|
|
@@ -13882,7 +13879,37 @@ async function initializeConfig() {
|
|
|
13882
13879
|
await savePluginConfig(config2);
|
|
13883
13880
|
return config2;
|
|
13884
13881
|
}
|
|
13885
|
-
|
|
13882
|
+
// src/config/command-installer.ts
|
|
13883
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync } from "fs";
|
|
13884
|
+
import { homedir as homedir2 } from "os";
|
|
13885
|
+
import { dirname, join as join2 } from "path";
|
|
13886
|
+
import { fileURLToPath } from "url";
|
|
13887
|
+
var COMMANDS_DEST = join2(homedir2(), ".config", "opencode", "command");
|
|
13888
|
+
function findCommandsDir() {
|
|
13889
|
+
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
13890
|
+
const candidates = [
|
|
13891
|
+
join2(__dirname2, "..", "commands"),
|
|
13892
|
+
join2(__dirname2, "..", "..", "commands")
|
|
13893
|
+
];
|
|
13894
|
+
return candidates.find(existsSync) ?? null;
|
|
13895
|
+
}
|
|
13896
|
+
function copyCommandFiles() {
|
|
13897
|
+
const commandsSrc = findCommandsDir();
|
|
13898
|
+
if (!commandsSrc) {
|
|
13899
|
+
return -1;
|
|
13900
|
+
}
|
|
13901
|
+
try {
|
|
13902
|
+
mkdirSync(COMMANDS_DEST, { recursive: true });
|
|
13903
|
+
const files = readdirSync(commandsSrc).filter((f) => f.endsWith(".md"));
|
|
13904
|
+
for (const file2 of files) {
|
|
13905
|
+
copyFileSync(join2(commandsSrc, file2), join2(COMMANDS_DEST, file2));
|
|
13906
|
+
}
|
|
13907
|
+
return files.length;
|
|
13908
|
+
} catch (error45) {
|
|
13909
|
+
console.warn("[agent-mode-switcher] Warning: Could not copy command files:", error45 instanceof Error ? error45.message : String(error45));
|
|
13910
|
+
return -1;
|
|
13911
|
+
}
|
|
13912
|
+
}
|
|
13886
13913
|
// src/modes/manager.ts
|
|
13887
13914
|
class ModeManager {
|
|
13888
13915
|
client;
|
|
@@ -13892,6 +13919,7 @@ class ModeManager {
|
|
|
13892
13919
|
}
|
|
13893
13920
|
async initialize() {
|
|
13894
13921
|
this.config = await initializeConfig();
|
|
13922
|
+
await this.applyCurrentModeIfNeeded();
|
|
13895
13923
|
}
|
|
13896
13924
|
async ensureConfig() {
|
|
13897
13925
|
if (!this.config) {
|
|
@@ -13899,6 +13927,55 @@ class ModeManager {
|
|
|
13899
13927
|
}
|
|
13900
13928
|
return this.config;
|
|
13901
13929
|
}
|
|
13930
|
+
async applyCurrentModeIfNeeded() {
|
|
13931
|
+
if (!this.config) {
|
|
13932
|
+
return;
|
|
13933
|
+
}
|
|
13934
|
+
const preset = this.config.presets[this.config.currentMode];
|
|
13935
|
+
if (!preset) {
|
|
13936
|
+
return;
|
|
13937
|
+
}
|
|
13938
|
+
const drifted = await this.hasConfigDrift(preset);
|
|
13939
|
+
if (!drifted) {
|
|
13940
|
+
return;
|
|
13941
|
+
}
|
|
13942
|
+
await this.updateOpencodeConfig(preset.model, preset.opencode);
|
|
13943
|
+
await this.updateOhMyOpencodeConfig(preset["oh-my-opencode"]);
|
|
13944
|
+
this.client.tui.showToast({
|
|
13945
|
+
body: {
|
|
13946
|
+
title: "Mode Applied",
|
|
13947
|
+
message: `Applied "${this.config.currentMode}" mode. Restart opencode to take effect.`,
|
|
13948
|
+
variant: "warning",
|
|
13949
|
+
duration: 5000
|
|
13950
|
+
}
|
|
13951
|
+
}).catch(() => {});
|
|
13952
|
+
}
|
|
13953
|
+
async hasConfigDrift(preset) {
|
|
13954
|
+
const opencodeConfig = await loadOpencodeConfig();
|
|
13955
|
+
const ohMyConfig = await loadOhMyOpencodeConfig();
|
|
13956
|
+
if (preset.model && opencodeConfig) {
|
|
13957
|
+
if (opencodeConfig.model !== preset.model) {
|
|
13958
|
+
return true;
|
|
13959
|
+
}
|
|
13960
|
+
}
|
|
13961
|
+
if (opencodeConfig?.agent) {
|
|
13962
|
+
for (const [agentName, agentPreset] of Object.entries(preset.opencode)) {
|
|
13963
|
+
const actual = opencodeConfig.agent[agentName];
|
|
13964
|
+
if (actual?.model !== agentPreset.model) {
|
|
13965
|
+
return true;
|
|
13966
|
+
}
|
|
13967
|
+
}
|
|
13968
|
+
}
|
|
13969
|
+
if (ohMyConfig?.agents) {
|
|
13970
|
+
for (const [agentName, agentPreset] of Object.entries(preset["oh-my-opencode"])) {
|
|
13971
|
+
const actual = ohMyConfig.agents[agentName];
|
|
13972
|
+
if (actual?.model !== agentPreset.model) {
|
|
13973
|
+
return true;
|
|
13974
|
+
}
|
|
13975
|
+
}
|
|
13976
|
+
}
|
|
13977
|
+
return false;
|
|
13978
|
+
}
|
|
13902
13979
|
async getCurrentMode() {
|
|
13903
13980
|
const config2 = await this.ensureConfig();
|
|
13904
13981
|
return config2.currentMode;
|
|
@@ -13989,14 +14066,12 @@ ${modes}`;
|
|
|
13989
14066
|
if (globalModel) {
|
|
13990
14067
|
opencodeConfig.model = globalModel;
|
|
13991
14068
|
}
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
opencodeConfig.agent[agentName]
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
};
|
|
13999
|
-
}
|
|
14069
|
+
opencodeConfig.agent = opencodeConfig.agent || {};
|
|
14070
|
+
for (const [agentName, preset] of Object.entries(agentPresets)) {
|
|
14071
|
+
opencodeConfig.agent[agentName] = {
|
|
14072
|
+
...opencodeConfig.agent[agentName],
|
|
14073
|
+
model: preset.model
|
|
14074
|
+
};
|
|
14000
14075
|
}
|
|
14001
14076
|
await saveOpencodeConfig(opencodeConfig);
|
|
14002
14077
|
return "updated";
|
|
@@ -14027,31 +14102,6 @@ ${modes}`;
|
|
|
14027
14102
|
return config2.showToastOnStartup;
|
|
14028
14103
|
}
|
|
14029
14104
|
}
|
|
14030
|
-
// src/config/command-installer.ts
|
|
14031
|
-
import { copyFileSync, mkdirSync, readdirSync, existsSync } from "fs";
|
|
14032
|
-
import { homedir as homedir2 } from "os";
|
|
14033
|
-
import { dirname, join as join2 } from "path";
|
|
14034
|
-
import { fileURLToPath } from "url";
|
|
14035
|
-
var COMMANDS_DEST = join2(homedir2(), ".config", "opencode", "command");
|
|
14036
|
-
function copyCommandFiles() {
|
|
14037
|
-
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
14038
|
-
const commandsSrc = join2(__dirname2, "..", "..", "commands");
|
|
14039
|
-
if (!existsSync(commandsSrc)) {
|
|
14040
|
-
console.warn("[agent-mode-switcher] Commands directory not found:", commandsSrc);
|
|
14041
|
-
return -1;
|
|
14042
|
-
}
|
|
14043
|
-
try {
|
|
14044
|
-
mkdirSync(COMMANDS_DEST, { recursive: true });
|
|
14045
|
-
const files = readdirSync(commandsSrc).filter((f) => f.endsWith(".md"));
|
|
14046
|
-
for (const file2 of files) {
|
|
14047
|
-
copyFileSync(join2(commandsSrc, file2), join2(COMMANDS_DEST, file2));
|
|
14048
|
-
}
|
|
14049
|
-
return files.length;
|
|
14050
|
-
} catch (error45) {
|
|
14051
|
-
console.warn("[agent-mode-switcher] Warning: Could not copy command files:", error45 instanceof Error ? error45.message : String(error45));
|
|
14052
|
-
return -1;
|
|
14053
|
-
}
|
|
14054
|
-
}
|
|
14055
14105
|
// src/index.ts
|
|
14056
14106
|
var modeSwitcherPlugin = async ({ client }) => {
|
|
14057
14107
|
const modeManager = new ModeManager(client);
|
package/dist/modes/manager.d.ts
CHANGED
|
@@ -1,54 +1,233 @@
|
|
|
1
1
|
import type { OpencodeClient } from '@opencode-ai/sdk';
|
|
2
2
|
import type { ModePreset } from '../config/types.ts';
|
|
3
3
|
/**
|
|
4
|
-
* Manages agent mode switching between different presets
|
|
4
|
+
* Manages agent mode switching between different presets.
|
|
5
|
+
*
|
|
6
|
+
* This class provides the core functionality for switching between
|
|
7
|
+
* performance and economy modes (or custom presets). It handles:
|
|
8
|
+
* - Loading and managing plugin configuration
|
|
9
|
+
* - Switching between different model presets
|
|
10
|
+
* - Updating OpenCode configuration files
|
|
11
|
+
* - Providing status and listing available modes
|
|
12
|
+
*
|
|
13
|
+
* The manager updates three configuration files when switching modes:
|
|
14
|
+
* - `~/.config/opencode/agent-mode-switcher.json` (plugin state)
|
|
15
|
+
* - `~/.config/opencode/opencode.json` (OpenCode agents)
|
|
16
|
+
* - `~/.config/opencode/oh-my-opencode.json` (oh-my-opencode agents)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const manager = new ModeManager(client);
|
|
21
|
+
* await manager.initialize();
|
|
22
|
+
*
|
|
23
|
+
* // Switch to economy mode
|
|
24
|
+
* const result = await manager.switchMode('economy');
|
|
25
|
+
* console.log(result);
|
|
26
|
+
*
|
|
27
|
+
* // Get current status
|
|
28
|
+
* const status = await manager.getStatus();
|
|
29
|
+
* console.log(status);
|
|
30
|
+
* ```
|
|
5
31
|
*/
|
|
6
32
|
export declare class ModeManager {
|
|
7
33
|
private readonly client;
|
|
8
34
|
private config;
|
|
9
35
|
constructor(client: OpencodeClient);
|
|
10
36
|
/**
|
|
11
|
-
*
|
|
37
|
+
* Initializes the mode manager and loads configuration.
|
|
38
|
+
*
|
|
39
|
+
* This method should be called before using any other manager methods.
|
|
40
|
+
* It loads or creates the plugin configuration file, ensuring all
|
|
41
|
+
* required presets are available.
|
|
42
|
+
*
|
|
43
|
+
* @throws {Error} If configuration initialization fails
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const manager = new ModeManager(client);
|
|
47
|
+
* await manager.initialize();
|
|
48
|
+
* ```
|
|
12
49
|
*/
|
|
13
50
|
initialize(): Promise<void>;
|
|
14
51
|
/**
|
|
15
|
-
*
|
|
52
|
+
* Ensures configuration is loaded before any operation.
|
|
53
|
+
*
|
|
54
|
+
* This internal method is called by all public methods to lazily
|
|
55
|
+
* initialize the configuration if it hasn't been loaded yet.
|
|
56
|
+
*
|
|
57
|
+
* @returns Promise resolving to the loaded configuration
|
|
58
|
+
* @throws {Error} If configuration loading fails
|
|
59
|
+
* @private
|
|
16
60
|
*/
|
|
17
61
|
private ensureConfig;
|
|
18
62
|
/**
|
|
19
|
-
*
|
|
63
|
+
* Checks if actual config files have drifted from the current
|
|
64
|
+
* mode preset and applies the preset if needed.
|
|
65
|
+
*
|
|
66
|
+
* This handles the case where a user manually edits
|
|
67
|
+
* `agent-mode-switcher.json` to change `currentMode` while
|
|
68
|
+
* OpenCode is not running. On next startup, the actual config
|
|
69
|
+
* files are updated to match the expected preset values,
|
|
70
|
+
* and a toast notification prompts the user to restart.
|
|
71
|
+
*
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
private applyCurrentModeIfNeeded;
|
|
75
|
+
/**
|
|
76
|
+
* Compares a mode preset against the actual opencode.json and
|
|
77
|
+
* oh-my-opencode.json files to detect configuration drift.
|
|
78
|
+
*
|
|
79
|
+
* Checks global model and per-agent model values. Returns true
|
|
80
|
+
* if any expected value differs from the actual file content.
|
|
81
|
+
*
|
|
82
|
+
* @param preset - The mode preset to compare against
|
|
83
|
+
* @returns True if actual configs differ from the preset
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
86
|
+
private hasConfigDrift;
|
|
87
|
+
/**
|
|
88
|
+
* Gets the name of the currently active mode.
|
|
89
|
+
*
|
|
90
|
+
* @returns Promise resolving to the current mode name (e.g., "performance", "economy")
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const currentMode = await manager.getCurrentMode();
|
|
94
|
+
* console.log(`Current mode: ${currentMode}`);
|
|
95
|
+
* ```
|
|
20
96
|
*/
|
|
21
97
|
getCurrentMode(): Promise<string>;
|
|
22
98
|
/**
|
|
23
|
-
*
|
|
99
|
+
* Gets a specific mode preset by name.
|
|
100
|
+
*
|
|
101
|
+
* @param modeName - The name of the mode to retrieve (e.g., "performance", "economy")
|
|
102
|
+
* @returns Promise resolving to the preset configuration, or undefined if not found
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const preset = await manager.getPreset('economy');
|
|
106
|
+
* if (preset) {
|
|
107
|
+
* console.log(preset.description);
|
|
108
|
+
* console.log(preset.model);
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
24
111
|
*/
|
|
25
112
|
getPreset(modeName: string): Promise<ModePreset | undefined>;
|
|
26
113
|
/**
|
|
27
|
-
*
|
|
114
|
+
* Gets a formatted list of all available modes.
|
|
115
|
+
*
|
|
116
|
+
* Returns a multi-line string listing each mode with its description,
|
|
117
|
+
* marking the currently active mode with "(current)".
|
|
118
|
+
*
|
|
119
|
+
* @returns Promise resolving to formatted string listing all available modes
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const list = await manager.listModes();
|
|
123
|
+
* console.log(list);
|
|
124
|
+
* // Output:
|
|
125
|
+
* // Available modes:
|
|
126
|
+
* // - performance (current): High-performance models for complex tasks
|
|
127
|
+
* // - economy: Cost-efficient free model for routine tasks
|
|
128
|
+
* ```
|
|
28
129
|
*/
|
|
29
130
|
listModes(): Promise<string>;
|
|
30
131
|
/**
|
|
31
|
-
*
|
|
132
|
+
* Gets detailed status information for the current mode.
|
|
133
|
+
*
|
|
134
|
+
* Returns a formatted multi-line string showing:
|
|
135
|
+
* - Current mode name and description
|
|
136
|
+
* - Global model setting (if configured)
|
|
137
|
+
* - All OpenCode agents and their assigned models
|
|
138
|
+
* - All oh-my-opencode agents and their assigned models
|
|
139
|
+
*
|
|
140
|
+
* @returns Promise resolving to formatted status string
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const status = await manager.getStatus();
|
|
144
|
+
* console.log(status);
|
|
145
|
+
* // Output:
|
|
146
|
+
* // Current mode: performance
|
|
147
|
+
* // Description: High-performance models for complex tasks
|
|
148
|
+
* // Global model: (not set)
|
|
149
|
+
* //
|
|
150
|
+
* // OpenCode agents:
|
|
151
|
+
* // - build: anthropic/claude-sonnet-4
|
|
152
|
+
* // - plan: anthropic/claude-sonnet-4
|
|
153
|
+
* // ...
|
|
154
|
+
* ```
|
|
32
155
|
*/
|
|
33
156
|
getStatus(): Promise<string>;
|
|
34
157
|
/**
|
|
35
|
-
*
|
|
158
|
+
* Switches to a different mode by updating all configuration files.
|
|
159
|
+
*
|
|
160
|
+
* This method performs the following operations:
|
|
161
|
+
* 1. Validates that the requested mode exists
|
|
162
|
+
* 2. Updates `opencode.json` with new global model and agent settings
|
|
163
|
+
* 3. Updates `oh-my-opencode.json` with new agent settings
|
|
164
|
+
* 4. Updates `agent-mode-switcher.json` with the new current mode
|
|
165
|
+
* 5. Shows a toast notification (if available)
|
|
166
|
+
*
|
|
167
|
+
* Configuration files that don't exist are skipped with a warning.
|
|
168
|
+
* Changes take effect after restarting OpenCode.
|
|
169
|
+
*
|
|
170
|
+
* @param modeName - The name of the mode to switch to
|
|
171
|
+
* @returns Promise resolving to a formatted result message with status of each config update
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const result = await manager.switchMode('economy');
|
|
175
|
+
* console.log(result);
|
|
176
|
+
* // Output:
|
|
177
|
+
* // Switched to economy mode
|
|
178
|
+
* // Cost-efficient free model for routine tasks
|
|
179
|
+
* //
|
|
180
|
+
* // Results:
|
|
181
|
+
* // - opencode.json: updated
|
|
182
|
+
* // - oh-my-opencode.json: updated
|
|
183
|
+
* // - agent-mode-switcher.json: updated
|
|
184
|
+
* //
|
|
185
|
+
* // Note: Restart opencode to apply changes.
|
|
186
|
+
* ```
|
|
36
187
|
*/
|
|
37
188
|
switchMode(modeName: string): Promise<string>;
|
|
38
189
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
190
|
+
* Updates opencode.json with global model and agent section.
|
|
191
|
+
*
|
|
192
|
+
* This internal method modifies the OpenCode configuration file to apply
|
|
193
|
+
* the new preset's settings. It preserves other configuration properties
|
|
194
|
+
* and only updates model-related fields.
|
|
195
|
+
*
|
|
196
|
+
* @param globalModel - Global model setting (optional). If provided, sets the top-level "model" field
|
|
197
|
+
* @param agentPresets - Agent-specific model settings. Keys are agent names, values contain model strings
|
|
198
|
+
* @returns Promise resolving to result status: "updated", "skipped (not found)", or "error: ..."
|
|
199
|
+
* @private
|
|
43
200
|
*/
|
|
44
201
|
private updateOpencodeConfig;
|
|
45
202
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
203
|
+
* Updates oh-my-opencode.json agents section with preset values.
|
|
204
|
+
*
|
|
205
|
+
* This internal method modifies the oh-my-opencode configuration file
|
|
206
|
+
* to apply the new preset's agent settings. Unlike opencode.json, this
|
|
207
|
+
* only updates the agents section and doesn't set a global model.
|
|
208
|
+
*
|
|
209
|
+
* @param agentPresets - Agent-specific model settings. Keys are agent names, values contain model strings
|
|
210
|
+
* @returns Promise resolving to result status: "updated", "skipped (not found)", or "error: ..."
|
|
211
|
+
* @private
|
|
48
212
|
*/
|
|
49
213
|
private updateOhMyOpencodeConfig;
|
|
50
214
|
/**
|
|
51
|
-
*
|
|
215
|
+
* Checks if a toast notification should be shown on plugin startup.
|
|
216
|
+
*
|
|
217
|
+
* This is controlled by the `showToastOnStartup` configuration flag,
|
|
218
|
+
* which can be useful for reminding users of the current mode when
|
|
219
|
+
* OpenCode starts.
|
|
220
|
+
*
|
|
221
|
+
* @returns Promise resolving to true if toast should be shown, false otherwise
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* if (await manager.shouldShowToastOnStartup()) {
|
|
225
|
+
* const mode = await manager.getCurrentMode();
|
|
226
|
+
* await client.tui.showToast({
|
|
227
|
+
* body: { message: `Current mode: ${mode}` }
|
|
228
|
+
* });
|
|
229
|
+
* }
|
|
230
|
+
* ```
|
|
52
231
|
*/
|
|
53
232
|
shouldShowToastOnStartup(): Promise<boolean>;
|
|
54
233
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-agent-modes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "OpenCode plugin to switch agent modes between performance and economy presets",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,29 +25,23 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"typecheck": "tsc --noEmit",
|
|
27
27
|
"build": "bun build src/index.ts --outdir dist --format esm --target bun && tsc -p tsconfig.build.json",
|
|
28
|
-
"lint": "bunx biome check
|
|
29
|
-
"format": "
|
|
30
|
-
"format:check": "
|
|
28
|
+
"lint": "bunx biome check .",
|
|
29
|
+
"format": "bunx biome format --write .",
|
|
30
|
+
"format:check": "bunx biome format .",
|
|
31
31
|
"test": "bun test",
|
|
32
32
|
"test:watch": "bun test --watch",
|
|
33
33
|
"test:coverage": "bun test --coverage",
|
|
34
34
|
"prepublishOnly": "bun run build"
|
|
35
35
|
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
"opencode",
|
|
38
|
-
"plugin",
|
|
39
|
-
"agent",
|
|
40
|
-
"mode",
|
|
41
|
-
"switcher"
|
|
42
|
-
],
|
|
36
|
+
"keywords": ["opencode", "plugin", "agent", "mode", "switcher"],
|
|
43
37
|
"author": "j4rviscmd",
|
|
44
38
|
"license": "MIT",
|
|
45
39
|
"engines": {
|
|
46
40
|
"node": ">=18"
|
|
47
41
|
},
|
|
48
42
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
43
|
+
"@biomejs/biome": "^1.9.4",
|
|
44
|
+
"@types/bun": "latest"
|
|
51
45
|
},
|
|
52
46
|
"peerDependencies": {
|
|
53
47
|
"typescript": "^5"
|