oh-my-opencode-slim 1.0.3 → 1.0.5
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 +9 -3
- package/dist/cli/config-io.d.ts +2 -0
- package/dist/cli/index.js +213 -9
- package/dist/cli/install.d.ts +1 -1
- package/dist/cli/paths.d.ts +4 -0
- package/dist/cli/providers.d.ts +36 -2
- package/dist/cli/types.d.ts +3 -0
- package/dist/config/constants.d.ts +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/loader.d.ts +9 -0
- package/dist/config/runtime-preset.d.ts +12 -0
- package/dist/hooks/apply-patch/matching.d.ts +9 -1
- package/dist/hooks/apply-patch/rewrite.d.ts +0 -3
- package/dist/hooks/phase-reminder/index.d.ts +1 -1
- package/dist/hooks/post-file-tool-nudge/index.d.ts +3 -19
- package/dist/hooks/task-session-manager/index.d.ts +16 -4
- package/dist/hooks/todo-continuation/index.d.ts +2 -5
- package/dist/hooks/todo-continuation/todo-hygiene.d.ts +2 -8
- package/dist/index.js +589 -277
- package/dist/multiplexer/session-manager.d.ts +3 -0
- package/dist/tui.d.ts +5 -0
- package/dist/tui.js +86 -0
- package/package.json +15 -2
package/README.md
CHANGED
|
@@ -37,9 +37,15 @@ Install and configure oh-my-opencode-slim: https://raw.githubusercontent.com/alv
|
|
|
37
37
|
bunx oh-my-opencode-slim@latest install
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
The installer also registers the companion TUI plugin in OpenCode's
|
|
41
|
+
`tui.json`, which adds an `OMOS <version>` badge beside the prompt without
|
|
42
|
+
replacing OpenCode's built-in TUI footer. For manual setups, add
|
|
43
|
+
`oh-my-opencode-slim` to the `plugin` array in both `opencode.json` and
|
|
44
|
+
`tui.json`.
|
|
45
|
+
|
|
40
46
|
### Getting Started
|
|
41
47
|
|
|
42
|
-
The installer generates
|
|
48
|
+
The installer generates both OpenAI and OpenCode Go presets, with OpenAI active by default. OpenAI uses `openai/gpt-5.5` for the higher-judgment agents and `openai/gpt-5.4-mini` for the faster scoped agents. To make OpenCode Go active during install, run `bunx oh-my-opencode-slim@latest install --preset=opencode-go`.
|
|
43
49
|
|
|
44
50
|
Then:
|
|
45
51
|
|
|
@@ -60,7 +66,7 @@ Then:
|
|
|
60
66
|
> [!TIP]
|
|
61
67
|
> Want to understand how automatic delegation works in practice? Review the **[Orchestrator prompt](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** — it contains the delegation rules, specialist routing logic, and the thresholds for when the main agent should hand work off to subagents.
|
|
62
68
|
|
|
63
|
-
The default generated configuration
|
|
69
|
+
The default generated configuration includes both `openai` and `opencode-go` presets. Abbreviated:
|
|
64
70
|
|
|
65
71
|
```jsonc
|
|
66
72
|
{
|
|
@@ -85,7 +91,7 @@ want to customize how many resumable child-agent sessions are remembered.
|
|
|
85
91
|
|
|
86
92
|
### For Alternative Providers
|
|
87
93
|
|
|
88
|
-
To use Kimi, GitHub Copilot, ZAI Coding Plan, or a mixed-provider setup, use **[Configuration](docs/configuration.md)** for the full reference. If you want a ready-made starting point, check the **[Author's Preset](docs/authors-preset.md)** and **[$30 Preset](docs/thirty-dollars-preset.md)** - the `$30` preset is the best cheap setup.
|
|
94
|
+
To use OpenCode Go, Kimi, GitHub Copilot, ZAI Coding Plan, or a mixed-provider setup, use **[Configuration](docs/configuration.md)** for the full reference. If you want a ready-made starting point, check the **[Author's Preset](docs/authors-preset.md)** and **[$30 Preset](docs/thirty-dollars-preset.md)** - the `$30` preset is the best cheap setup.
|
|
89
95
|
|
|
90
96
|
The configuration guide also covers custom subagents via `agents.<name>`, where
|
|
91
97
|
you can define both a normal `prompt` and an `orchestratorPrompt` block for
|
package/dist/cli/config-io.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ export declare function parseConfig(path: string): {
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function writeConfig(configPath: string, config: OpenCodeConfig): void;
|
|
18
18
|
export declare function addPluginToOpenCodeConfig(): Promise<ConfigMergeResult>;
|
|
19
|
+
export declare function addPluginToOpenCodeTuiConfig(): Promise<ConfigMergeResult>;
|
|
19
20
|
export declare function writeLiteConfig(installConfig: InstallConfig, targetPath?: string): ConfigMergeResult;
|
|
20
21
|
export declare function disableDefaultAgents(): ConfigMergeResult;
|
|
22
|
+
export declare function enableLspByDefault(): ConfigMergeResult;
|
|
21
23
|
export declare function canModifyOpenCodeConfig(): boolean;
|
|
22
24
|
export declare function detectCurrentConfig(): DetectedConfig;
|
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
5
|
|
|
4
6
|
// src/cli/install.ts
|
|
5
7
|
import { existsSync as existsSync4 } from "node:fs";
|
|
8
|
+
import { createInterface } from "node:readline/promises";
|
|
6
9
|
|
|
7
10
|
// src/cli/config-io.ts
|
|
8
11
|
import {
|
|
@@ -27,6 +30,10 @@ function getCustomOpenCodeConfigDir() {
|
|
|
27
30
|
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
28
31
|
return configDir || undefined;
|
|
29
32
|
}
|
|
33
|
+
function getCustomTuiConfigPath() {
|
|
34
|
+
const configPath = process.env.OPENCODE_TUI_CONFIG?.trim();
|
|
35
|
+
return configPath || undefined;
|
|
36
|
+
}
|
|
30
37
|
function getConfigDir() {
|
|
31
38
|
const customConfigDir = getCustomOpenCodeConfigDir();
|
|
32
39
|
if (customConfigDir) {
|
|
@@ -50,6 +57,15 @@ function getLiteConfig() {
|
|
|
50
57
|
function getLiteConfigJsonc() {
|
|
51
58
|
return join(getConfigDir(), "oh-my-opencode-slim.jsonc");
|
|
52
59
|
}
|
|
60
|
+
function getTuiConfig() {
|
|
61
|
+
const customConfigPath = getCustomTuiConfigPath();
|
|
62
|
+
if (customConfigPath)
|
|
63
|
+
return customConfigPath;
|
|
64
|
+
return join(getConfigDir(), "tui.json");
|
|
65
|
+
}
|
|
66
|
+
function getTuiConfigJsonc() {
|
|
67
|
+
return join(getConfigDir(), "tui.jsonc");
|
|
68
|
+
}
|
|
53
69
|
function getExistingLiteConfigPath() {
|
|
54
70
|
const jsonPath = getLiteConfig();
|
|
55
71
|
if (existsSync(jsonPath))
|
|
@@ -59,6 +75,18 @@ function getExistingLiteConfigPath() {
|
|
|
59
75
|
return jsoncPath;
|
|
60
76
|
return jsonPath;
|
|
61
77
|
}
|
|
78
|
+
function getExistingTuiConfigPath() {
|
|
79
|
+
const customConfigPath = getCustomTuiConfigPath();
|
|
80
|
+
if (customConfigPath)
|
|
81
|
+
return customConfigPath;
|
|
82
|
+
const jsonPath = join(getConfigDir(), "tui.json");
|
|
83
|
+
if (existsSync(jsonPath))
|
|
84
|
+
return jsonPath;
|
|
85
|
+
const jsoncPath = getTuiConfigJsonc();
|
|
86
|
+
if (existsSync(jsoncPath))
|
|
87
|
+
return jsoncPath;
|
|
88
|
+
return jsonPath;
|
|
89
|
+
}
|
|
62
90
|
function getExistingConfigPath() {
|
|
63
91
|
const jsonPath = getConfigJson();
|
|
64
92
|
if (existsSync(jsonPath))
|
|
@@ -74,6 +102,12 @@ function ensureConfigDir() {
|
|
|
74
102
|
mkdirSync(configDir, { recursive: true });
|
|
75
103
|
}
|
|
76
104
|
}
|
|
105
|
+
function ensureTuiConfigDir() {
|
|
106
|
+
const configDir = dirname(getTuiConfig());
|
|
107
|
+
if (!existsSync(configDir)) {
|
|
108
|
+
mkdirSync(configDir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
77
111
|
function ensureOpenCodeConfigDir() {
|
|
78
112
|
const configDir = dirname(getConfigJson());
|
|
79
113
|
if (!existsSync(configDir)) {
|
|
@@ -458,6 +492,7 @@ function installSkill(skill) {
|
|
|
458
492
|
|
|
459
493
|
// src/cli/providers.ts
|
|
460
494
|
var SCHEMA_URL = "https://unpkg.com/oh-my-opencode-slim@latest/oh-my-opencode-slim.schema.json";
|
|
495
|
+
var GENERATED_PRESETS = ["openai", "opencode-go"];
|
|
461
496
|
var MODEL_MAPPINGS = {
|
|
462
497
|
openai: {
|
|
463
498
|
orchestrator: { model: "openai/gpt-5.5" },
|
|
@@ -493,12 +528,31 @@ var MODEL_MAPPINGS = {
|
|
|
493
528
|
explorer: { model: "zai-coding-plan/glm-5", variant: "low" },
|
|
494
529
|
designer: { model: "zai-coding-plan/glm-5", variant: "medium" },
|
|
495
530
|
fixer: { model: "zai-coding-plan/glm-5", variant: "low" }
|
|
531
|
+
},
|
|
532
|
+
"opencode-go": {
|
|
533
|
+
orchestrator: { model: "opencode-go/glm-5.1" },
|
|
534
|
+
oracle: { model: "opencode-go/deepseek-v4-pro", variant: "max" },
|
|
535
|
+
council: { model: "opencode-go/deepseek-v4-pro", variant: "high" },
|
|
536
|
+
librarian: { model: "opencode-go/minimax-m2.7" },
|
|
537
|
+
explorer: { model: "opencode-go/minimax-m2.7" },
|
|
538
|
+
designer: { model: "opencode-go/kimi-k2.6", variant: "medium" },
|
|
539
|
+
fixer: { model: "opencode-go/deepseek-v4-flash", variant: "high" }
|
|
496
540
|
}
|
|
497
541
|
};
|
|
542
|
+
function isGeneratedPresetName(value) {
|
|
543
|
+
return GENERATED_PRESETS.includes(value);
|
|
544
|
+
}
|
|
545
|
+
function getGeneratedPresetNames() {
|
|
546
|
+
return [...GENERATED_PRESETS];
|
|
547
|
+
}
|
|
498
548
|
function generateLiteConfig(installConfig) {
|
|
549
|
+
const preset = installConfig.preset ?? "openai";
|
|
550
|
+
if (!isGeneratedPresetName(preset)) {
|
|
551
|
+
throw new Error(`Unsupported preset "${preset}". Available generated presets: ${getGeneratedPresetNames().join(", ")}`);
|
|
552
|
+
}
|
|
499
553
|
const config = {
|
|
500
554
|
$schema: SCHEMA_URL,
|
|
501
|
-
preset
|
|
555
|
+
preset,
|
|
502
556
|
presets: {}
|
|
503
557
|
};
|
|
504
558
|
const createAgentConfig = (agentName, modelInfo) => {
|
|
@@ -524,7 +578,10 @@ function generateLiteConfig(installConfig) {
|
|
|
524
578
|
createAgentConfig(agentName, modelInfo)
|
|
525
579
|
]));
|
|
526
580
|
};
|
|
527
|
-
|
|
581
|
+
const presets = config.presets;
|
|
582
|
+
for (const presetName of GENERATED_PRESETS) {
|
|
583
|
+
presets[presetName] = buildPreset(presetName);
|
|
584
|
+
}
|
|
528
585
|
if (installConfig.hasTmux) {
|
|
529
586
|
config.tmux = {
|
|
530
587
|
enabled: true,
|
|
@@ -546,6 +603,14 @@ function getPlugins(config) {
|
|
|
546
603
|
function getPluginEntries(config) {
|
|
547
604
|
return getPlugins(config).filter(isString);
|
|
548
605
|
}
|
|
606
|
+
function getPluginSpec(entry) {
|
|
607
|
+
if (isString(entry))
|
|
608
|
+
return entry;
|
|
609
|
+
if (!Array.isArray(entry))
|
|
610
|
+
return;
|
|
611
|
+
const spec = entry[0];
|
|
612
|
+
return isString(spec) ? spec : undefined;
|
|
613
|
+
}
|
|
549
614
|
function normalizePathForMatch(path) {
|
|
550
615
|
return path.replaceAll("\\", "/");
|
|
551
616
|
}
|
|
@@ -590,6 +655,10 @@ function isLocalPackageRootEntry(entry) {
|
|
|
590
655
|
function isPluginEntry(entry) {
|
|
591
656
|
return entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`) || entry.startsWith("file://") && entry.includes(PACKAGE_NAME) || isLocalPackageRootEntry(entry);
|
|
592
657
|
}
|
|
658
|
+
function isMatchingPluginEntry(entry) {
|
|
659
|
+
const spec = getPluginSpec(entry);
|
|
660
|
+
return spec ? isPluginEntry(spec) : false;
|
|
661
|
+
}
|
|
593
662
|
function getPluginEntry() {
|
|
594
663
|
const cliEntryPath = process.argv[1];
|
|
595
664
|
if (!cliEntryPath) {
|
|
@@ -672,7 +741,7 @@ async function addPluginToOpenCodeConfig() {
|
|
|
672
741
|
const config = parsedConfig ?? {};
|
|
673
742
|
const plugins = getPlugins(config);
|
|
674
743
|
const pluginEntry = getPluginEntry();
|
|
675
|
-
const filteredPlugins = plugins.filter((plugin) => !
|
|
744
|
+
const filteredPlugins = plugins.filter((plugin) => !isMatchingPluginEntry(plugin));
|
|
676
745
|
filteredPlugins.push(pluginEntry);
|
|
677
746
|
config.plugin = filteredPlugins;
|
|
678
747
|
writeConfig(configPath, config);
|
|
@@ -685,6 +754,42 @@ async function addPluginToOpenCodeConfig() {
|
|
|
685
754
|
};
|
|
686
755
|
}
|
|
687
756
|
}
|
|
757
|
+
async function addPluginToOpenCodeTuiConfig() {
|
|
758
|
+
const configPath = getExistingTuiConfigPath();
|
|
759
|
+
try {
|
|
760
|
+
ensureTuiConfigDir();
|
|
761
|
+
} catch (err) {
|
|
762
|
+
return {
|
|
763
|
+
success: false,
|
|
764
|
+
configPath,
|
|
765
|
+
error: `Failed to create config directory: ${err}`
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
try {
|
|
769
|
+
const { config: parsedConfig, error } = parseConfig(configPath);
|
|
770
|
+
if (error) {
|
|
771
|
+
return {
|
|
772
|
+
success: false,
|
|
773
|
+
configPath,
|
|
774
|
+
error: `Failed to parse TUI config: ${error}`
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
const config = parsedConfig ?? {};
|
|
778
|
+
const plugins = getPlugins(config);
|
|
779
|
+
const pluginEntry = getPluginEntry();
|
|
780
|
+
const filteredPlugins = plugins.filter((plugin) => !isMatchingPluginEntry(plugin));
|
|
781
|
+
filteredPlugins.push(pluginEntry);
|
|
782
|
+
config.plugin = filteredPlugins;
|
|
783
|
+
writeConfig(configPath, config);
|
|
784
|
+
return { success: true, configPath };
|
|
785
|
+
} catch (err) {
|
|
786
|
+
return {
|
|
787
|
+
success: false,
|
|
788
|
+
configPath,
|
|
789
|
+
error: `Failed to update opencode TUI config: ${err}`
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
}
|
|
688
793
|
function writeLiteConfig(installConfig, targetPath) {
|
|
689
794
|
const configPath = targetPath ?? getLiteConfig();
|
|
690
795
|
try {
|
|
@@ -735,6 +840,32 @@ function disableDefaultAgents() {
|
|
|
735
840
|
};
|
|
736
841
|
}
|
|
737
842
|
}
|
|
843
|
+
function enableLspByDefault() {
|
|
844
|
+
const configPath = getExistingConfigPath();
|
|
845
|
+
try {
|
|
846
|
+
ensureOpenCodeConfigDir();
|
|
847
|
+
const { config: parsedConfig, error } = parseConfig(configPath);
|
|
848
|
+
if (error) {
|
|
849
|
+
return {
|
|
850
|
+
success: false,
|
|
851
|
+
configPath,
|
|
852
|
+
error: `Failed to parse config: ${error}`
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const config = parsedConfig ?? {};
|
|
856
|
+
if (config.lsp === undefined) {
|
|
857
|
+
config.lsp = true;
|
|
858
|
+
writeConfig(configPath, config);
|
|
859
|
+
}
|
|
860
|
+
return { success: true, configPath };
|
|
861
|
+
} catch (err) {
|
|
862
|
+
return {
|
|
863
|
+
success: false,
|
|
864
|
+
configPath,
|
|
865
|
+
error: `Failed to enable LSP: ${err}`
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
738
869
|
function detectCurrentConfig() {
|
|
739
870
|
const result = {
|
|
740
871
|
isInstalled: false,
|
|
@@ -979,8 +1110,10 @@ var SYMBOLS = {
|
|
|
979
1110
|
bullet: `${DIM}-${RESET}`,
|
|
980
1111
|
info: `${BLUE}[i]${RESET}`,
|
|
981
1112
|
warn: `${YELLOW}[!]${RESET}`,
|
|
982
|
-
star: `${YELLOW}
|
|
1113
|
+
star: `${YELLOW}★${RESET}`
|
|
983
1114
|
};
|
|
1115
|
+
var GITHUB_REPO = "alvinunreal/oh-my-opencode-slim";
|
|
1116
|
+
var GITHUB_URL = `https://github.com/${GITHUB_REPO}`;
|
|
984
1117
|
function printHeader(isUpdate) {
|
|
985
1118
|
console.log();
|
|
986
1119
|
console.log(`${BOLD}oh-my-opencode-slim ${isUpdate ? "Update" : "Install"}${RESET}`);
|
|
@@ -999,6 +1132,34 @@ function printError(message) {
|
|
|
999
1132
|
function printInfo(message) {
|
|
1000
1133
|
console.log(`${SYMBOLS.info} ${message}`);
|
|
1001
1134
|
}
|
|
1135
|
+
async function confirm(message, defaultYes = true) {
|
|
1136
|
+
const suffix = defaultYes ? " (Y/n) " : " (y/N) ";
|
|
1137
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1138
|
+
try {
|
|
1139
|
+
const answer = (await rl.question(`${message}${suffix}`)).trim().toLowerCase();
|
|
1140
|
+
if (!answer)
|
|
1141
|
+
return defaultYes;
|
|
1142
|
+
return answer === "y" || answer === "yes";
|
|
1143
|
+
} finally {
|
|
1144
|
+
rl.close();
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
async function askToStarRepo(config) {
|
|
1148
|
+
if (!config.promptForStar || config.dryRun || !process.stdin.isTTY)
|
|
1149
|
+
return;
|
|
1150
|
+
console.log();
|
|
1151
|
+
const shouldStar = await confirm(`${SYMBOLS.star} Star the repo on GitHub?`, true);
|
|
1152
|
+
if (!shouldStar)
|
|
1153
|
+
return;
|
|
1154
|
+
try {
|
|
1155
|
+
const { execFileSync } = await import("node:child_process");
|
|
1156
|
+
execFileSync("gh", ["api", "--silent", "--method", "PUT", `/user/starred/${GITHUB_REPO}`], { stdio: "ignore", timeout: 1e4 });
|
|
1157
|
+
printSuccess("Thanks for starring! ★");
|
|
1158
|
+
} catch {
|
|
1159
|
+
printInfo(`Couldn't star automatically. You can star manually:
|
|
1160
|
+
${BLUE}${GITHUB_URL}${RESET}`);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1002
1163
|
async function checkOpenCodeInstalled() {
|
|
1003
1164
|
const installed = await isOpenCodeInstalled();
|
|
1004
1165
|
if (!installed) {
|
|
@@ -1030,7 +1191,7 @@ async function runInstall(config) {
|
|
|
1030
1191
|
const detected = detectCurrentConfig();
|
|
1031
1192
|
const isUpdate = detected.isInstalled;
|
|
1032
1193
|
printHeader(isUpdate);
|
|
1033
|
-
let totalSteps =
|
|
1194
|
+
let totalSteps = 6;
|
|
1034
1195
|
if (config.installSkills)
|
|
1035
1196
|
totalSteps += 1;
|
|
1036
1197
|
if (config.installCustomSkills)
|
|
@@ -1052,6 +1213,17 @@ async function runInstall(config) {
|
|
|
1052
1213
|
if (!handleStepResult(pluginResult, "Plugin added"))
|
|
1053
1214
|
return 1;
|
|
1054
1215
|
}
|
|
1216
|
+
printStep(step++, totalSteps, "Adding TUI version badge...");
|
|
1217
|
+
if (config.dryRun) {
|
|
1218
|
+
printInfo("Dry run mode - skipping TUI plugin installation");
|
|
1219
|
+
} else {
|
|
1220
|
+
const tuiResult = await addPluginToOpenCodeTuiConfig();
|
|
1221
|
+
if (!tuiResult.success) {
|
|
1222
|
+
printInfo(`Skipped TUI badge: ${tuiResult.error}`);
|
|
1223
|
+
} else {
|
|
1224
|
+
handleStepResult(tuiResult, "TUI badge added");
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1055
1227
|
printStep(step++, totalSteps, "Disabling OpenCode default agents...");
|
|
1056
1228
|
if (config.dryRun) {
|
|
1057
1229
|
printInfo("Dry run mode - skipping agent disabling");
|
|
@@ -1060,6 +1232,14 @@ async function runInstall(config) {
|
|
|
1060
1232
|
if (!handleStepResult(agentResult, "Default agents disabled"))
|
|
1061
1233
|
return 1;
|
|
1062
1234
|
}
|
|
1235
|
+
printStep(step++, totalSteps, "Enabling OpenCode LSP integration...");
|
|
1236
|
+
if (config.dryRun) {
|
|
1237
|
+
printInfo("Dry run mode - skipping LSP configuration");
|
|
1238
|
+
} else {
|
|
1239
|
+
const lspResult = enableLspByDefault();
|
|
1240
|
+
if (!handleStepResult(lspResult, "LSP enabled"))
|
|
1241
|
+
return 1;
|
|
1242
|
+
}
|
|
1063
1243
|
printStep(step++, totalSteps, "Writing oh-my-opencode-slim configuration...");
|
|
1064
1244
|
if (config.dryRun) {
|
|
1065
1245
|
const liteConfig = generateLiteConfig(config);
|
|
@@ -1071,7 +1251,7 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1071
1251
|
const configPath2 = getExistingLiteConfigPath();
|
|
1072
1252
|
const configExists = existsSync4(configPath2);
|
|
1073
1253
|
if (configExists && !config.reset) {
|
|
1074
|
-
printInfo(`Configuration already exists at ${configPath2}.
|
|
1254
|
+
printInfo(`Configuration already exists at ${configPath2}. Use --reset to overwrite.`);
|
|
1075
1255
|
} else {
|
|
1076
1256
|
const liteResult = writeLiteConfig(config, configExists ? configPath2 : undefined);
|
|
1077
1257
|
if (!handleStepResult(liteResult, configExists ? "Config reset" : "Config written"))
|
|
@@ -1142,13 +1322,14 @@ ${JSON.stringify(liteConfig, null, 2)}
|
|
|
1142
1322
|
console.log(" 5. Verify the agents are responding:");
|
|
1143
1323
|
console.log(` ${BLUE}> ping all agents${RESET}`);
|
|
1144
1324
|
console.log();
|
|
1145
|
-
const modelsInfo = "
|
|
1325
|
+
const modelsInfo = config.preset && config.preset !== "openai" ? `Generated OpenAI and OpenCode Go presets; ${config.preset} is active.` : "Generated OpenAI and OpenCode Go presets; OpenAI is active by default.";
|
|
1146
1326
|
console.log(`${modelsInfo}`);
|
|
1147
1327
|
const altProviders = "For the full configuration reference, see:";
|
|
1148
1328
|
console.log(altProviders);
|
|
1149
|
-
const docsUrl = "https://github.com/alvinunreal/oh-my-opencode-slim/
|
|
1329
|
+
const docsUrl = "https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/docs/configuration.md";
|
|
1150
1330
|
console.log(` ${BLUE}${docsUrl}${RESET}`);
|
|
1151
1331
|
console.log();
|
|
1332
|
+
await askToStarRepo(config);
|
|
1152
1333
|
return 0;
|
|
1153
1334
|
}
|
|
1154
1335
|
async function install(args) {
|
|
@@ -1156,12 +1337,23 @@ async function install(args) {
|
|
|
1156
1337
|
hasTmux: false,
|
|
1157
1338
|
installSkills: args.skills === "yes",
|
|
1158
1339
|
installCustomSkills: args.skills === "yes",
|
|
1340
|
+
preset: args.preset,
|
|
1341
|
+
promptForStar: args.tui,
|
|
1159
1342
|
dryRun: args.dryRun,
|
|
1160
1343
|
reset: args.reset ?? false
|
|
1161
1344
|
};
|
|
1162
1345
|
return runInstall(config);
|
|
1163
1346
|
}
|
|
1164
1347
|
|
|
1348
|
+
// src/cli/providers.ts
|
|
1349
|
+
var GENERATED_PRESETS2 = ["openai", "opencode-go"];
|
|
1350
|
+
function isGeneratedPresetName2(value) {
|
|
1351
|
+
return GENERATED_PRESETS2.includes(value);
|
|
1352
|
+
}
|
|
1353
|
+
function getGeneratedPresetNames2() {
|
|
1354
|
+
return [...GENERATED_PRESETS2];
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1165
1357
|
// src/cli/index.ts
|
|
1166
1358
|
function parseArgs(args) {
|
|
1167
1359
|
const result = {
|
|
@@ -1173,6 +1365,13 @@ function parseArgs(args) {
|
|
|
1173
1365
|
result.tui = false;
|
|
1174
1366
|
} else if (arg.startsWith("--skills=")) {
|
|
1175
1367
|
result.skills = arg.split("=")[1];
|
|
1368
|
+
} else if (arg.startsWith("--preset=")) {
|
|
1369
|
+
const preset = arg.split("=")[1];
|
|
1370
|
+
if (!isGeneratedPresetName2(preset)) {
|
|
1371
|
+
console.error(`Unsupported preset: ${preset}. Available presets: ${getGeneratedPresetNames2().join(", ")}`);
|
|
1372
|
+
process.exit(1);
|
|
1373
|
+
}
|
|
1374
|
+
result.preset = preset;
|
|
1176
1375
|
} else if (arg === "--dry-run") {
|
|
1177
1376
|
result.dryRun = true;
|
|
1178
1377
|
} else if (arg === "--reset") {
|
|
@@ -1192,17 +1391,22 @@ Usage: bunx oh-my-opencode-slim install [OPTIONS]
|
|
|
1192
1391
|
|
|
1193
1392
|
Options:
|
|
1194
1393
|
--skills=yes|no Install recommended and bundled skills (default: yes)
|
|
1394
|
+
--preset=<name> Active generated config preset (default: openai)
|
|
1195
1395
|
--no-tui Non-interactive mode
|
|
1196
1396
|
--dry-run Simulate install without writing files
|
|
1197
1397
|
--reset Force overwrite of existing configuration
|
|
1198
1398
|
-h, --help Show this help message
|
|
1199
1399
|
|
|
1200
|
-
|
|
1400
|
+
Available presets: ${getGeneratedPresetNames2().join(", ")}
|
|
1401
|
+
|
|
1402
|
+
The installer generates OpenAI and OpenCode Go presets by default.
|
|
1403
|
+
OpenAI is active unless --preset selects another generated preset.
|
|
1201
1404
|
For the full config reference, see docs/configuration.md.
|
|
1202
1405
|
|
|
1203
1406
|
Examples:
|
|
1204
1407
|
bunx oh-my-opencode-slim install
|
|
1205
1408
|
bunx oh-my-opencode-slim install --no-tui --skills=yes
|
|
1409
|
+
bunx oh-my-opencode-slim install --preset=opencode-go
|
|
1206
1410
|
bunx oh-my-opencode-slim install --reset
|
|
1207
1411
|
`);
|
|
1208
1412
|
}
|
package/dist/cli/install.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { InstallArgs } from
|
|
1
|
+
import type { InstallArgs } from './types';
|
|
2
2
|
export declare function install(args: InstallArgs): Promise<number>;
|
package/dist/cli/paths.d.ts
CHANGED
|
@@ -22,9 +22,13 @@ export declare function getConfigJson(): string;
|
|
|
22
22
|
export declare function getConfigJsonc(): string;
|
|
23
23
|
export declare function getLiteConfig(): string;
|
|
24
24
|
export declare function getLiteConfigJsonc(): string;
|
|
25
|
+
export declare function getTuiConfig(): string;
|
|
26
|
+
export declare function getTuiConfigJsonc(): string;
|
|
25
27
|
export declare function getExistingLiteConfigPath(): string;
|
|
28
|
+
export declare function getExistingTuiConfigPath(): string;
|
|
26
29
|
export declare function getExistingConfigPath(): string;
|
|
27
30
|
export declare function ensureConfigDir(): void;
|
|
31
|
+
export declare function ensureTuiConfigDir(): void;
|
|
28
32
|
/**
|
|
29
33
|
* Ensure the directory for OpenCode's main config file exists.
|
|
30
34
|
*/
|
package/dist/cli/providers.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { InstallConfig } from
|
|
1
|
+
import type { InstallConfig } from './types';
|
|
2
|
+
export declare const GENERATED_PRESETS: readonly ["openai", "opencode-go"];
|
|
2
3
|
export declare const MODEL_MAPPINGS: {
|
|
3
4
|
readonly openai: {
|
|
4
5
|
readonly orchestrator: {
|
|
@@ -75,7 +76,7 @@ export declare const MODEL_MAPPINGS: {
|
|
|
75
76
|
readonly variant: "low";
|
|
76
77
|
};
|
|
77
78
|
};
|
|
78
|
-
readonly
|
|
79
|
+
readonly 'zai-plan': {
|
|
79
80
|
readonly orchestrator: {
|
|
80
81
|
readonly model: "zai-coding-plan/glm-5";
|
|
81
82
|
};
|
|
@@ -100,5 +101,38 @@ export declare const MODEL_MAPPINGS: {
|
|
|
100
101
|
readonly variant: "low";
|
|
101
102
|
};
|
|
102
103
|
};
|
|
104
|
+
readonly 'opencode-go': {
|
|
105
|
+
readonly orchestrator: {
|
|
106
|
+
readonly model: "opencode-go/glm-5.1";
|
|
107
|
+
};
|
|
108
|
+
readonly oracle: {
|
|
109
|
+
readonly model: "opencode-go/deepseek-v4-pro";
|
|
110
|
+
readonly variant: "max";
|
|
111
|
+
};
|
|
112
|
+
readonly council: {
|
|
113
|
+
readonly model: "opencode-go/deepseek-v4-pro";
|
|
114
|
+
readonly variant: "high";
|
|
115
|
+
};
|
|
116
|
+
readonly librarian: {
|
|
117
|
+
readonly model: "opencode-go/minimax-m2.7";
|
|
118
|
+
};
|
|
119
|
+
readonly explorer: {
|
|
120
|
+
readonly model: "opencode-go/minimax-m2.7";
|
|
121
|
+
};
|
|
122
|
+
readonly designer: {
|
|
123
|
+
readonly model: "opencode-go/kimi-k2.6";
|
|
124
|
+
readonly variant: "medium";
|
|
125
|
+
};
|
|
126
|
+
readonly fixer: {
|
|
127
|
+
readonly model: "opencode-go/deepseek-v4-flash";
|
|
128
|
+
readonly variant: "high";
|
|
129
|
+
};
|
|
130
|
+
};
|
|
103
131
|
};
|
|
132
|
+
export type PresetName = keyof typeof MODEL_MAPPINGS;
|
|
133
|
+
export type GeneratedPresetName = (typeof GENERATED_PRESETS)[number];
|
|
134
|
+
export declare function isPresetName(value: string): value is PresetName;
|
|
135
|
+
export declare function getPresetNames(): PresetName[];
|
|
136
|
+
export declare function isGeneratedPresetName(value: string): value is GeneratedPresetName;
|
|
137
|
+
export declare function getGeneratedPresetNames(): GeneratedPresetName[];
|
|
104
138
|
export declare function generateLiteConfig(installConfig: InstallConfig): Record<string, unknown>;
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type BooleanArg = 'yes' | 'no';
|
|
|
2
2
|
export interface InstallArgs {
|
|
3
3
|
tui: boolean;
|
|
4
4
|
skills?: BooleanArg;
|
|
5
|
+
preset?: string;
|
|
5
6
|
dryRun?: boolean;
|
|
6
7
|
reset?: boolean;
|
|
7
8
|
}
|
|
@@ -15,6 +16,8 @@ export interface InstallConfig {
|
|
|
15
16
|
hasTmux: boolean;
|
|
16
17
|
installSkills: boolean;
|
|
17
18
|
installCustomSkills: boolean;
|
|
19
|
+
preset?: string;
|
|
20
|
+
promptForStar?: boolean;
|
|
18
21
|
dryRun?: boolean;
|
|
19
22
|
reset: boolean;
|
|
20
23
|
}
|
|
@@ -20,7 +20,7 @@ export declare const DEFAULT_TIMEOUT_MS: number;
|
|
|
20
20
|
export declare const MAX_POLL_TIME_MS: number;
|
|
21
21
|
export declare const FALLBACK_FAILOVER_TIMEOUT_MS = 15000;
|
|
22
22
|
export declare const DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
23
|
-
export declare const PHASE_REMINDER_TEXT = "!IMPORTANT! Recall the workflow rules:\nUnderstand \u2192 choose the best parallelized path based on your capabilities and agents delegation rules \u2192 execute \u2192 verify.\nIf delegating, launch the specialist in the same turn you mention it !END!";
|
|
23
|
+
export declare const PHASE_REMINDER_TEXT = "!IMPORTANT! Recall the workflow rules:\nUnderstand \u2192 choose the best parallelized path based on your capabilities and agents delegation rules \u2192 recall session reuse rules \u2192 execute \u2192 verify.\nIf delegating, launch the specialist in the same turn you mention it !END!";
|
|
24
24
|
export declare const TMUX_SPAWN_DELAY_MS = 500;
|
|
25
25
|
export declare const COUNCILLOR_STAGGER_MS = 250;
|
|
26
26
|
export declare const STABLE_POLLS_THRESHOLD = 3;
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './constants';
|
|
2
2
|
export * from './council-schema';
|
|
3
|
-
export { loadAgentPrompt, loadPluginConfig } from './loader';
|
|
3
|
+
export { deepMerge, loadAgentPrompt, loadPluginConfig } from './loader';
|
|
4
4
|
export * from './schema';
|
|
5
5
|
export { getAgentOverride, getCustomAgentNames } from './utils';
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { type PluginConfig } from './schema';
|
|
2
|
+
/**
|
|
3
|
+
* Recursively merge two objects, with override values taking precedence.
|
|
4
|
+
* For nested objects, merges recursively. For arrays and primitives, override replaces base.
|
|
5
|
+
*
|
|
6
|
+
* @param base - Base object to merge into
|
|
7
|
+
* @param override - Override object whose values take precedence
|
|
8
|
+
* @returns Merged object, or undefined if both inputs are undefined
|
|
9
|
+
*/
|
|
10
|
+
export declare function deepMerge<T extends Record<string, unknown>>(base?: T, override?: T): T | undefined;
|
|
2
11
|
/**
|
|
3
12
|
* Load plugin configuration from user and project config files, merging them appropriately.
|
|
4
13
|
*
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-level runtime preset state.
|
|
3
|
+
*
|
|
4
|
+
* Survives plugin re-inits triggered by client.config.update() →
|
|
5
|
+
* Instance.dispose(). The plugin function re-runs but this module-level
|
|
6
|
+
* variable persists within the same Node.js process.
|
|
7
|
+
*/
|
|
8
|
+
export declare function setActiveRuntimePreset(name: string | null): void;
|
|
9
|
+
export declare function getActiveRuntimePreset(): string | null;
|
|
10
|
+
export declare function getPreviousRuntimePreset(): string | null;
|
|
11
|
+
export declare function setActiveRuntimePresetWithPrevious(name: string | null): void;
|
|
12
|
+
export declare function rollbackRuntimePreset(previous: string | null): void;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type { LineComparator, RescueResult, SeekHit } from './types';
|
|
1
|
+
import type { LineComparator, MatchComparatorName, RescueResult, SeekHit } from './types';
|
|
2
|
+
export type PreparedAutoRescueTarget = {
|
|
3
|
+
exact: string;
|
|
4
|
+
unicode: string;
|
|
5
|
+
trimEnd: string;
|
|
6
|
+
unicodeTrimEnd: string;
|
|
7
|
+
};
|
|
2
8
|
export declare function equalExact(a: string, b: string): boolean;
|
|
3
9
|
export declare function equalUnicodeExact(a: string, b: string): boolean;
|
|
4
10
|
export declare function equalTrimEnd(a: string, b: string): boolean;
|
|
@@ -6,6 +12,8 @@ export declare function equalUnicodeTrimEnd(a: string, b: string): boolean;
|
|
|
6
12
|
export declare function equalTrim(a: string, b: string): boolean;
|
|
7
13
|
export declare function equalUnicodeTrim(a: string, b: string): boolean;
|
|
8
14
|
export declare const autoRescueComparators: LineComparator[];
|
|
15
|
+
export declare function prepareAutoRescueTarget(target: string): PreparedAutoRescueTarget;
|
|
16
|
+
export declare function matchPreparedAutoRescueComparator(candidate: string, target: PreparedAutoRescueTarget): MatchComparatorName | undefined;
|
|
9
17
|
export declare const permissiveComparators: LineComparator[];
|
|
10
18
|
export declare function seekMatch(lines: string[], pattern: string[], start: number, eof?: boolean): SeekHit | undefined;
|
|
11
19
|
export declare function seek(lines: string[], pattern: string[], start: number, eof?: boolean): number;
|
|
@@ -2,9 +2,6 @@ import type { ApplyPatchRuntimeOptions } from './types';
|
|
|
2
2
|
export type RewritePatchResult = {
|
|
3
3
|
patchText: string;
|
|
4
4
|
changed: boolean;
|
|
5
|
-
rewrittenChunks: number;
|
|
6
|
-
totalChunks: number;
|
|
7
|
-
rewriteModes: string[];
|
|
8
5
|
};
|
|
9
6
|
export declare function rewritePatch(root: string, patchText: string, cfg: ApplyPatchRuntimeOptions, worktree?: string): Promise<RewritePatchResult>;
|
|
10
7
|
export declare function rewritePatchText(root: string, patchText: string, cfg: ApplyPatchRuntimeOptions, worktree?: string): Promise<string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const PHASE_REMINDER = "<
|
|
1
|
+
export declare const PHASE_REMINDER = "<internal_reminder>!IMPORTANT! Recall the workflow rules:\nUnderstand \u2192 choose the best parallelized path based on your capabilities and agents delegation rules \u2192 recall session reuse rules \u2192 execute \u2192 verify.\nIf delegating, launch the specialist in the same turn you mention it !END!</internal_reminder>";
|
|
2
2
|
interface MessageInfo {
|
|
3
3
|
role: string;
|
|
4
4
|
agent?: string;
|
|
@@ -7,29 +7,13 @@ interface ToolExecuteAfterInput {
|
|
|
7
7
|
sessionID?: string;
|
|
8
8
|
callID?: string;
|
|
9
9
|
}
|
|
10
|
-
interface
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
interface ChatSystemTransformOutput {
|
|
14
|
-
system: string[];
|
|
15
|
-
}
|
|
16
|
-
interface EventInput {
|
|
17
|
-
event: {
|
|
18
|
-
type: string;
|
|
19
|
-
properties?: {
|
|
20
|
-
info?: {
|
|
21
|
-
id?: string;
|
|
22
|
-
};
|
|
23
|
-
sessionID?: string;
|
|
24
|
-
};
|
|
25
|
-
};
|
|
10
|
+
interface ToolExecuteAfterOutput {
|
|
11
|
+
output?: unknown;
|
|
26
12
|
}
|
|
27
13
|
interface PostFileToolNudgeOptions {
|
|
28
14
|
shouldInject?: (sessionID: string) => boolean;
|
|
29
15
|
}
|
|
30
16
|
export declare function createPostFileToolNudgeHook(options?: PostFileToolNudgeOptions): {
|
|
31
|
-
'tool.execute.after': (input: ToolExecuteAfterInput,
|
|
32
|
-
'experimental.chat.system.transform': (input: ChatSystemTransformInput, output: ChatSystemTransformOutput) => Promise<void>;
|
|
33
|
-
event: (input: EventInput) => Promise<void>;
|
|
17
|
+
'tool.execute.after': (input: ToolExecuteAfterInput, output: ToolExecuteAfterOutput) => Promise<void>;
|
|
34
18
|
};
|
|
35
19
|
export {};
|