opencode-agent-modes 0.2.0 → 0.3.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 +6 -2
- package/dist/config/guards.d.ts +14 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/types.d.ts +36 -8
- package/dist/index.js +121 -91
- package/dist/modes/manager.d.ts +14 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Add the plugin to your `opencode.json`:
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
The following command files are automatically copied to
|
|
44
|
-
`~/.config/opencode/
|
|
44
|
+
`~/.config/opencode/commands/` when the plugin initializes:
|
|
45
45
|
|
|
46
46
|
- `mode-performance.md`
|
|
47
47
|
- `mode-economy.md`
|
|
@@ -135,7 +135,7 @@ To add a custom preset (e.g., "premium"):
|
|
|
135
135
|
}
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
2. Create a command file at `~/.config/opencode/
|
|
138
|
+
2. Create a command file at `~/.config/opencode/commands/mode-premium.md`:
|
|
139
139
|
|
|
140
140
|
```md
|
|
141
141
|
---
|
|
@@ -150,6 +150,10 @@ To add a custom preset (e.g., "premium"):
|
|
|
150
150
|
> [!INFO]
|
|
151
151
|
> - Changes require an opencode restart to take effect
|
|
152
152
|
> - Custom mode presets can be added by editing the configuration file
|
|
153
|
+
> - Built-in command files (`mode-performance.md`, `mode-economy.md`, etc.)
|
|
154
|
+
> are overwritten on every plugin startup. Do not modify them directly.
|
|
155
|
+
> - Custom command files (e.g., `mode-premium.md`) are not affected by
|
|
156
|
+
> this overwrite and will persist across restarts.
|
|
153
157
|
|
|
154
158
|
## Development
|
|
155
159
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type guard utilities for configuration processing.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Checks if a value is a plain object (not null, not array).
|
|
6
|
+
*
|
|
7
|
+
* This is used throughout the codebase to distinguish between
|
|
8
|
+
* hierarchical structures and leaf values when processing
|
|
9
|
+
* configurations.
|
|
10
|
+
*
|
|
11
|
+
* @param obj - Value to check
|
|
12
|
+
* @returns True if the value is a plain object
|
|
13
|
+
*/
|
|
14
|
+
export declare function isObject(obj: unknown): obj is Record<string, unknown>;
|
package/dist/config/index.d.ts
CHANGED
package/dist/config/types.d.ts
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Generic model configuration for any agent.
|
|
3
|
+
*
|
|
4
|
+
* This interface is intentionally flexible to support arbitrary
|
|
5
|
+
* properties beyond just `model` and `variant`.
|
|
3
6
|
*/
|
|
4
|
-
export interface
|
|
5
|
-
model
|
|
7
|
+
export interface ModelConfig {
|
|
8
|
+
model?: string;
|
|
9
|
+
variant?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
6
11
|
}
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
13
|
+
* Hierarchical preset structure supporting arbitrary nesting.
|
|
14
|
+
*
|
|
15
|
+
* This type recursively represents the configuration structure for
|
|
16
|
+
* both opencode and oh-my-opencode, supporting any level of nesting
|
|
17
|
+
* (e.g., agents/categories, future sections).
|
|
18
|
+
*
|
|
19
|
+
* Note: This type alias has a circular reference by design to support
|
|
20
|
+
* recursive structures. The TypeScript compiler warning about this
|
|
21
|
+
* can be safely ignored.
|
|
22
|
+
*/
|
|
23
|
+
export type HierarchicalPreset = Record<string, ModelConfig | HierarchicalPreset>;
|
|
24
|
+
/**
|
|
25
|
+
* Mode preset containing configurations for both opencode and oh-my-opencode agents.
|
|
26
|
+
*
|
|
27
|
+
* Both opencode and oh-my-opencode use the same HierarchicalPreset type,
|
|
28
|
+
* allowing them to have arbitrary nested structures that are handled
|
|
29
|
+
* uniformly by recursive merge functions.
|
|
9
30
|
*/
|
|
10
31
|
export interface ModePreset {
|
|
11
32
|
description: string;
|
|
12
33
|
model?: string;
|
|
13
|
-
opencode:
|
|
14
|
-
'oh-my-opencode':
|
|
34
|
+
opencode: HierarchicalPreset;
|
|
35
|
+
'oh-my-opencode': HierarchicalPreset;
|
|
15
36
|
}
|
|
16
37
|
/**
|
|
17
38
|
* Main configuration for the mode switcher plugin
|
|
@@ -23,6 +44,9 @@ export interface ModeSwitcherConfig {
|
|
|
23
44
|
}
|
|
24
45
|
/**
|
|
25
46
|
* OpenCode agent configuration structure in opencode.json
|
|
47
|
+
*
|
|
48
|
+
* @deprecated This type is kept for backward compatibility but may not
|
|
49
|
+
* accurately represent the actual structure. Use ModelConfig directly.
|
|
26
50
|
*/
|
|
27
51
|
export interface OpencodeAgentConfig {
|
|
28
52
|
model?: string;
|
|
@@ -31,17 +55,21 @@ export interface OpencodeAgentConfig {
|
|
|
31
55
|
}
|
|
32
56
|
/**
|
|
33
57
|
* OpenCode configuration file structure
|
|
58
|
+
*
|
|
59
|
+
* Supports arbitrary properties beyond the documented ones.
|
|
34
60
|
*/
|
|
35
61
|
export interface OpencodeConfig {
|
|
36
62
|
model?: string;
|
|
37
|
-
agent?:
|
|
63
|
+
agent?: HierarchicalPreset;
|
|
38
64
|
[key: string]: unknown;
|
|
39
65
|
}
|
|
40
66
|
/**
|
|
41
67
|
* Oh-my-opencode configuration file structure
|
|
68
|
+
*
|
|
69
|
+
* Supports arbitrary properties and nested structures like
|
|
70
|
+
* agents, categories, and any future sections.
|
|
42
71
|
*/
|
|
43
72
|
export interface OhMyOpencodeConfig {
|
|
44
|
-
agents?: Record<string, AgentPreset>;
|
|
45
73
|
[key: string]: unknown;
|
|
46
74
|
}
|
|
47
75
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
3
7
|
var __export = (target, all) => {
|
|
4
8
|
for (var name in all)
|
|
5
9
|
__defProp(target, name, {
|
|
6
10
|
get: all[name],
|
|
7
11
|
enumerable: true,
|
|
8
12
|
configurable: true,
|
|
9
|
-
set: (
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
10
14
|
});
|
|
11
15
|
};
|
|
12
16
|
|
|
@@ -12332,6 +12336,10 @@ function tool(input) {
|
|
|
12332
12336
|
tool.schema = exports_external;
|
|
12333
12337
|
// src/config/types.ts
|
|
12334
12338
|
var DEFAULT_ECONOMY_MODEL = "opencode/glm-4.7-free";
|
|
12339
|
+
// src/config/guards.ts
|
|
12340
|
+
function isObject2(obj) {
|
|
12341
|
+
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
12342
|
+
}
|
|
12335
12343
|
// src/config/loader.ts
|
|
12336
12344
|
import { homedir } from "os";
|
|
12337
12345
|
import { join } from "path";
|
|
@@ -13795,35 +13803,29 @@ async function pluginConfigExists() {
|
|
|
13795
13803
|
return Bun.file(getPluginConfigPath()).exists();
|
|
13796
13804
|
}
|
|
13797
13805
|
// src/config/initializer.ts
|
|
13798
|
-
|
|
13799
|
-
|
|
13800
|
-
|
|
13801
|
-
|
|
13802
|
-
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13809
|
-
const ohMyOpencodeConfig = await loadOhMyOpencodeConfig();
|
|
13810
|
-
const opencodePreset = {};
|
|
13811
|
-
const ohMyOpencodePreset = {};
|
|
13812
|
-
if (opencodeConfig?.agent) {
|
|
13813
|
-
for (const agentName of OPENCODE_AGENTS) {
|
|
13814
|
-
const agentConfig = opencodeConfig.agent[agentName];
|
|
13815
|
-
if (agentConfig?.model) {
|
|
13816
|
-
opencodePreset[agentName] = { model: agentConfig.model };
|
|
13817
|
-
}
|
|
13818
|
-
}
|
|
13819
|
-
}
|
|
13820
|
-
if (ohMyOpencodeConfig?.agents) {
|
|
13821
|
-
for (const [agentName, agentConfig] of Object.entries(ohMyOpencodeConfig.agents)) {
|
|
13822
|
-
if (agentConfig?.model) {
|
|
13823
|
-
ohMyOpencodePreset[agentName] = { model: agentConfig.model };
|
|
13806
|
+
function applyEconomyModel(config2, economyModel) {
|
|
13807
|
+
const result = {};
|
|
13808
|
+
for (const [key, value] of Object.entries(config2)) {
|
|
13809
|
+
if (isObject2(value)) {
|
|
13810
|
+
if ("model" in value) {
|
|
13811
|
+
result[key] = {
|
|
13812
|
+
...value,
|
|
13813
|
+
model: economyModel
|
|
13814
|
+
};
|
|
13815
|
+
} else {
|
|
13816
|
+
result[key] = applyEconomyModel(value, economyModel);
|
|
13824
13817
|
}
|
|
13818
|
+
} else {
|
|
13819
|
+
result[key] = value;
|
|
13825
13820
|
}
|
|
13826
13821
|
}
|
|
13822
|
+
return result;
|
|
13823
|
+
}
|
|
13824
|
+
async function buildPerformancePreset() {
|
|
13825
|
+
const opencodeConfig = await loadOpencodeConfig();
|
|
13826
|
+
const ohMyOpencodeConfig = await loadOhMyOpencodeConfig();
|
|
13827
|
+
const opencodePreset = opencodeConfig?.agent || {};
|
|
13828
|
+
const ohMyOpencodePreset = ohMyOpencodeConfig || {};
|
|
13827
13829
|
const globalModel = opencodeConfig?.model;
|
|
13828
13830
|
return {
|
|
13829
13831
|
description: "High-performance models for complex tasks",
|
|
@@ -13835,22 +13837,8 @@ async function buildPerformancePreset() {
|
|
|
13835
13837
|
async function buildEconomyPreset() {
|
|
13836
13838
|
const opencodeConfig = await loadOpencodeConfig();
|
|
13837
13839
|
const ohMyOpencodeConfig = await loadOhMyOpencodeConfig();
|
|
13838
|
-
const opencodePreset = {};
|
|
13839
|
-
const ohMyOpencodePreset = {};
|
|
13840
|
-
if (opencodeConfig?.agent) {
|
|
13841
|
-
for (const agentName of Object.keys(opencodeConfig.agent)) {
|
|
13842
|
-
opencodePreset[agentName] = { model: DEFAULT_ECONOMY_MODEL };
|
|
13843
|
-
}
|
|
13844
|
-
} else {
|
|
13845
|
-
for (const agentName of OPENCODE_AGENTS) {
|
|
13846
|
-
opencodePreset[agentName] = { model: DEFAULT_ECONOMY_MODEL };
|
|
13847
|
-
}
|
|
13848
|
-
}
|
|
13849
|
-
if (ohMyOpencodeConfig?.agents) {
|
|
13850
|
-
for (const agentName of Object.keys(ohMyOpencodeConfig.agents)) {
|
|
13851
|
-
ohMyOpencodePreset[agentName] = { model: DEFAULT_ECONOMY_MODEL };
|
|
13852
|
-
}
|
|
13853
|
-
}
|
|
13840
|
+
const opencodePreset = applyEconomyModel(opencodeConfig?.agent || {}, DEFAULT_ECONOMY_MODEL);
|
|
13841
|
+
const ohMyOpencodePreset = applyEconomyModel(ohMyOpencodeConfig || {}, DEFAULT_ECONOMY_MODEL);
|
|
13854
13842
|
return {
|
|
13855
13843
|
description: "Cost-efficient free model for routine tasks",
|
|
13856
13844
|
model: DEFAULT_ECONOMY_MODEL,
|
|
@@ -13884,7 +13872,7 @@ import { copyFileSync, existsSync, mkdirSync, readdirSync } from "fs";
|
|
|
13884
13872
|
import { homedir as homedir2 } from "os";
|
|
13885
13873
|
import { dirname, join as join2 } from "path";
|
|
13886
13874
|
import { fileURLToPath } from "url";
|
|
13887
|
-
var COMMANDS_DEST = join2(homedir2(), ".config", "opencode", "
|
|
13875
|
+
var COMMANDS_DEST = join2(homedir2(), ".config", "opencode", "commands");
|
|
13888
13876
|
function findCommandsDir() {
|
|
13889
13877
|
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
13890
13878
|
const candidates = [
|
|
@@ -13911,6 +13899,69 @@ function copyCommandFiles() {
|
|
|
13911
13899
|
}
|
|
13912
13900
|
}
|
|
13913
13901
|
// src/modes/manager.ts
|
|
13902
|
+
function isLeafNode(value) {
|
|
13903
|
+
return "model" in value && typeof value.model === "string";
|
|
13904
|
+
}
|
|
13905
|
+
function deepMergeModel(target, preset) {
|
|
13906
|
+
for (const [key, value] of Object.entries(preset)) {
|
|
13907
|
+
if (!isObject2(value))
|
|
13908
|
+
continue;
|
|
13909
|
+
const actualValue = target[key];
|
|
13910
|
+
if (isLeafNode(value)) {
|
|
13911
|
+
const valueRecord = value;
|
|
13912
|
+
const existing = actualValue ?? {};
|
|
13913
|
+
const merged = {
|
|
13914
|
+
...existing,
|
|
13915
|
+
...valueRecord
|
|
13916
|
+
};
|
|
13917
|
+
target[key] = merged;
|
|
13918
|
+
} else {
|
|
13919
|
+
const childTarget = actualValue ?? {};
|
|
13920
|
+
target[key] = childTarget;
|
|
13921
|
+
deepMergeModel(childTarget, value);
|
|
13922
|
+
}
|
|
13923
|
+
}
|
|
13924
|
+
}
|
|
13925
|
+
function hasDriftRecursive(actual, expected) {
|
|
13926
|
+
for (const [key, expectedValue] of Object.entries(expected)) {
|
|
13927
|
+
if (!isObject2(expectedValue))
|
|
13928
|
+
continue;
|
|
13929
|
+
const actualValue = actual[key];
|
|
13930
|
+
if (isLeafNode(expectedValue)) {
|
|
13931
|
+
const actualObj = actualValue;
|
|
13932
|
+
if (!actualObj) {
|
|
13933
|
+
return true;
|
|
13934
|
+
}
|
|
13935
|
+
for (const [propKey, expectedPropValue] of Object.entries(expectedValue)) {
|
|
13936
|
+
if (actualObj[propKey] !== expectedPropValue) {
|
|
13937
|
+
return true;
|
|
13938
|
+
}
|
|
13939
|
+
}
|
|
13940
|
+
} else if (hasDriftRecursive(actualValue || {}, expectedValue)) {
|
|
13941
|
+
return true;
|
|
13942
|
+
}
|
|
13943
|
+
}
|
|
13944
|
+
return false;
|
|
13945
|
+
}
|
|
13946
|
+
function formatHierarchicalTree(preset, indent = " ") {
|
|
13947
|
+
const lines = [];
|
|
13948
|
+
for (const [key, value] of Object.entries(preset)) {
|
|
13949
|
+
if (!isObject2(value))
|
|
13950
|
+
continue;
|
|
13951
|
+
if (isLeafNode(value)) {
|
|
13952
|
+
const variant = value.variant ? ` (${value.variant})` : "";
|
|
13953
|
+
const otherProps = Object.keys(value).filter((k) => k !== "model" && k !== "variant").map((k) => `${k}: ${JSON.stringify(value[k])}`).join(", ");
|
|
13954
|
+
const extra = otherProps ? ` [${otherProps}]` : "";
|
|
13955
|
+
lines.push(`${indent}${key}: ${value.model}${variant}${extra}`);
|
|
13956
|
+
} else {
|
|
13957
|
+
lines.push(`${indent}${key}:`);
|
|
13958
|
+
lines.push(formatHierarchicalTree(value, `${indent} `));
|
|
13959
|
+
}
|
|
13960
|
+
}
|
|
13961
|
+
return lines.join(`
|
|
13962
|
+
`);
|
|
13963
|
+
}
|
|
13964
|
+
|
|
13914
13965
|
class ModeManager {
|
|
13915
13966
|
client;
|
|
13916
13967
|
config = null;
|
|
@@ -13953,26 +14004,17 @@ class ModeManager {
|
|
|
13953
14004
|
async hasConfigDrift(preset) {
|
|
13954
14005
|
const opencodeConfig = await loadOpencodeConfig();
|
|
13955
14006
|
const ohMyConfig = await loadOhMyOpencodeConfig();
|
|
13956
|
-
if (
|
|
13957
|
-
|
|
13958
|
-
return true;
|
|
13959
|
-
}
|
|
14007
|
+
if (!opencodeConfig && !ohMyConfig) {
|
|
14008
|
+
return false;
|
|
13960
14009
|
}
|
|
13961
|
-
if (opencodeConfig?.
|
|
13962
|
-
|
|
13963
|
-
const actual = opencodeConfig.agent[agentName];
|
|
13964
|
-
if (actual?.model !== agentPreset.model) {
|
|
13965
|
-
return true;
|
|
13966
|
-
}
|
|
13967
|
-
}
|
|
14010
|
+
if (preset.model && opencodeConfig?.model !== preset.model) {
|
|
14011
|
+
return true;
|
|
13968
14012
|
}
|
|
13969
|
-
if (
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
}
|
|
13975
|
-
}
|
|
14013
|
+
if (opencodeConfig?.agent && hasDriftRecursive(opencodeConfig.agent, preset.opencode)) {
|
|
14014
|
+
return true;
|
|
14015
|
+
}
|
|
14016
|
+
if (ohMyConfig && hasDriftRecursive(ohMyConfig, preset["oh-my-opencode"])) {
|
|
14017
|
+
return true;
|
|
13976
14018
|
}
|
|
13977
14019
|
return false;
|
|
13978
14020
|
}
|
|
@@ -14003,20 +14045,18 @@ ${modes}`;
|
|
|
14003
14045
|
return `Current mode: ${currentMode} (preset not found)`;
|
|
14004
14046
|
}
|
|
14005
14047
|
const globalModel = preset.model ? `Global model: ${preset.model}` : "Global model: (not set)";
|
|
14006
|
-
const
|
|
14007
|
-
|
|
14008
|
-
const ohMyOpencodeAgents = Object.entries(preset["oh-my-opencode"]).map(([name, cfg]) => ` - ${name}: ${cfg.model}`).join(`
|
|
14009
|
-
`);
|
|
14048
|
+
const opencodeTree = formatHierarchicalTree(preset.opencode);
|
|
14049
|
+
const ohMyOpencodeTree = formatHierarchicalTree(preset["oh-my-opencode"]);
|
|
14010
14050
|
return [
|
|
14011
14051
|
`Current mode: ${currentMode}`,
|
|
14012
14052
|
`Description: ${preset.description}`,
|
|
14013
14053
|
globalModel,
|
|
14014
14054
|
"",
|
|
14015
|
-
"OpenCode
|
|
14016
|
-
|
|
14055
|
+
"OpenCode config:",
|
|
14056
|
+
opencodeTree || " (none configured)",
|
|
14017
14057
|
"",
|
|
14018
|
-
"Oh-my-opencode
|
|
14019
|
-
|
|
14058
|
+
"Oh-my-opencode config:",
|
|
14059
|
+
ohMyOpencodeTree || " (none configured)"
|
|
14020
14060
|
].join(`
|
|
14021
14061
|
`);
|
|
14022
14062
|
}
|
|
@@ -14036,16 +14076,14 @@ ${modes}`;
|
|
|
14036
14076
|
this.config = config2;
|
|
14037
14077
|
await savePluginConfig(config2);
|
|
14038
14078
|
results.push("agent-mode-switcher.json: updated");
|
|
14039
|
-
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
});
|
|
14048
|
-
} catch {}
|
|
14079
|
+
this.client.tui.showToast({
|
|
14080
|
+
body: {
|
|
14081
|
+
title: "Mode Switched",
|
|
14082
|
+
message: `Switched to "${modeName}". Restart opencode to apply.`,
|
|
14083
|
+
variant: "warning",
|
|
14084
|
+
duration: 5000
|
|
14085
|
+
}
|
|
14086
|
+
}).catch(() => {});
|
|
14049
14087
|
return [
|
|
14050
14088
|
`Switched to ${modeName} mode`,
|
|
14051
14089
|
preset.description,
|
|
@@ -14067,12 +14105,7 @@ ${modes}`;
|
|
|
14067
14105
|
opencodeConfig.model = globalModel;
|
|
14068
14106
|
}
|
|
14069
14107
|
opencodeConfig.agent = opencodeConfig.agent || {};
|
|
14070
|
-
|
|
14071
|
-
opencodeConfig.agent[agentName] = {
|
|
14072
|
-
...opencodeConfig.agent[agentName],
|
|
14073
|
-
model: preset.model
|
|
14074
|
-
};
|
|
14075
|
-
}
|
|
14108
|
+
deepMergeModel(opencodeConfig.agent, agentPresets);
|
|
14076
14109
|
await saveOpencodeConfig(opencodeConfig);
|
|
14077
14110
|
return "updated";
|
|
14078
14111
|
} catch (error45) {
|
|
@@ -14080,16 +14113,13 @@ ${modes}`;
|
|
|
14080
14113
|
return `error: ${message}`;
|
|
14081
14114
|
}
|
|
14082
14115
|
}
|
|
14083
|
-
async updateOhMyOpencodeConfig(
|
|
14116
|
+
async updateOhMyOpencodeConfig(preset) {
|
|
14084
14117
|
try {
|
|
14085
14118
|
const ohMyConfig = await loadOhMyOpencodeConfig();
|
|
14086
14119
|
if (!ohMyConfig) {
|
|
14087
14120
|
return "skipped (not found)";
|
|
14088
14121
|
}
|
|
14089
|
-
ohMyConfig
|
|
14090
|
-
for (const [agentName, preset] of Object.entries(agentPresets)) {
|
|
14091
|
-
ohMyConfig.agents[agentName] = { model: preset.model };
|
|
14092
|
-
}
|
|
14122
|
+
deepMergeModel(ohMyConfig, preset);
|
|
14093
14123
|
await saveOhMyOpencodeConfig(ohMyConfig);
|
|
14094
14124
|
return "updated";
|
|
14095
14125
|
} catch (error45) {
|
package/dist/modes/manager.d.ts
CHANGED
|
@@ -76,7 +76,7 @@ export declare class ModeManager {
|
|
|
76
76
|
* Compares a mode preset against the actual opencode.json and
|
|
77
77
|
* oh-my-opencode.json files to detect configuration drift.
|
|
78
78
|
*
|
|
79
|
-
* Checks global model and per-agent model values. Returns true
|
|
79
|
+
* Checks global model and per-agent model values recursively. Returns true
|
|
80
80
|
* if any expected value differs from the actual file content.
|
|
81
81
|
*
|
|
82
82
|
* @param preset - The mode preset to compare against
|
|
@@ -134,8 +134,8 @@ export declare class ModeManager {
|
|
|
134
134
|
* Returns a formatted multi-line string showing:
|
|
135
135
|
* - Current mode name and description
|
|
136
136
|
* - Global model setting (if configured)
|
|
137
|
-
* -
|
|
138
|
-
* -
|
|
137
|
+
* - Hierarchical tree of OpenCode configuration
|
|
138
|
+
* - Hierarchical tree of oh-my-opencode configuration
|
|
139
139
|
*
|
|
140
140
|
* @returns Promise resolving to formatted status string
|
|
141
141
|
* @example
|
|
@@ -147,9 +147,10 @@ export declare class ModeManager {
|
|
|
147
147
|
* // Description: High-performance models for complex tasks
|
|
148
148
|
* // Global model: (not set)
|
|
149
149
|
* //
|
|
150
|
-
* // OpenCode
|
|
151
|
-
* //
|
|
152
|
-
* //
|
|
150
|
+
* // OpenCode config:
|
|
151
|
+
* // agent:
|
|
152
|
+
* // build: anthropic/claude-sonnet-4
|
|
153
|
+
* // plan: anthropic/claude-sonnet-4
|
|
153
154
|
* // ...
|
|
154
155
|
* ```
|
|
155
156
|
*/
|
|
@@ -191,22 +192,23 @@ export declare class ModeManager {
|
|
|
191
192
|
*
|
|
192
193
|
* This internal method modifies the OpenCode configuration file to apply
|
|
193
194
|
* the new preset's settings. It preserves other configuration properties
|
|
194
|
-
* and only updates model-related fields.
|
|
195
|
+
* and only updates model-related fields using recursive merge.
|
|
195
196
|
*
|
|
196
197
|
* @param globalModel - Global model setting (optional). If provided, sets the top-level "model" field
|
|
197
|
-
* @param agentPresets -
|
|
198
|
+
* @param agentPresets - Hierarchical preset structure for agent configuration
|
|
198
199
|
* @returns Promise resolving to result status: "updated", "skipped (not found)", or "error: ..."
|
|
199
200
|
* @private
|
|
200
201
|
*/
|
|
201
202
|
private updateOpencodeConfig;
|
|
202
203
|
/**
|
|
203
|
-
* Updates oh-my-opencode.json
|
|
204
|
+
* Updates oh-my-opencode.json with preset values.
|
|
204
205
|
*
|
|
205
206
|
* This internal method modifies the oh-my-opencode configuration file
|
|
206
|
-
* to apply the new preset's
|
|
207
|
-
*
|
|
207
|
+
* to apply the new preset's settings using recursive merge. The entire
|
|
208
|
+
* structure (agents, categories, etc.) is updated while preserving
|
|
209
|
+
* other properties.
|
|
208
210
|
*
|
|
209
|
-
* @param
|
|
211
|
+
* @param preset - Hierarchical preset structure for oh-my-opencode configuration
|
|
210
212
|
* @returns Promise resolving to result status: "updated", "skipped (not found)", or "error: ..."
|
|
211
213
|
* @private
|
|
212
214
|
*/
|