oh-my-opencode-slim 0.8.2 → 0.8.4

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.
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Get the OpenCode plugin config directory.
3
+ *
4
+ * Resolution order:
5
+ * 1. OPENCODE_CONFIG_DIR (custom OpenCode directory)
6
+ * 2. XDG_CONFIG_HOME/opencode
7
+ * 3. ~/.config/opencode
8
+ */
1
9
  export declare function getConfigDir(): string;
2
10
  export declare function getOpenCodeConfigPaths(): string[];
3
11
  export declare function getConfigJson(): string;
@@ -7,3 +15,7 @@ export declare function getLiteConfigJsonc(): string;
7
15
  export declare function getExistingLiteConfigPath(): string;
8
16
  export declare function getExistingConfigPath(): string;
9
17
  export declare function ensureConfigDir(): void;
18
+ /**
19
+ * Ensure the directory for OpenCode's main config file exists.
20
+ */
21
+ export declare function ensureOpenCodeConfigDir(): void;
@@ -1,86 +1,61 @@
1
1
  import type { InstallConfig } from './types';
2
2
  export declare const MODEL_MAPPINGS: {
3
- readonly kimi: {
4
- readonly orchestrator: {
5
- readonly model: "kimi-for-coding/k2p5";
6
- };
7
- readonly oracle: {
8
- readonly model: "kimi-for-coding/k2p5";
9
- readonly variant: "high";
10
- };
11
- readonly librarian: {
12
- readonly model: "kimi-for-coding/k2p5";
13
- readonly variant: "low";
14
- };
15
- readonly explorer: {
16
- readonly model: "kimi-for-coding/k2p5";
17
- readonly variant: "low";
18
- };
19
- readonly designer: {
20
- readonly model: "kimi-for-coding/k2p5";
21
- readonly variant: "medium";
22
- };
23
- readonly fixer: {
24
- readonly model: "kimi-for-coding/k2p5";
25
- readonly variant: "low";
26
- };
27
- };
28
3
  readonly openai: {
29
4
  readonly orchestrator: {
30
- readonly model: "openai/gpt-5.3-codex";
5
+ readonly model: "openai/gpt-5.4";
31
6
  };
32
7
  readonly oracle: {
33
- readonly model: "openai/gpt-5.3-codex";
8
+ readonly model: "openai/gpt-5.4";
34
9
  readonly variant: "high";
35
10
  };
36
11
  readonly librarian: {
37
- readonly model: "openai/gpt-5.1-codex-mini";
12
+ readonly model: "openai/gpt-5.4-mini";
38
13
  readonly variant: "low";
39
14
  };
40
15
  readonly explorer: {
41
- readonly model: "openai/gpt-5.1-codex-mini";
16
+ readonly model: "openai/gpt-5.4-mini";
42
17
  readonly variant: "low";
43
18
  };
44
19
  readonly designer: {
45
- readonly model: "openai/gpt-5.1-codex-mini";
20
+ readonly model: "openai/gpt-5.4-mini";
46
21
  readonly variant: "medium";
47
22
  };
48
23
  readonly fixer: {
49
- readonly model: "openai/gpt-5.1-codex-mini";
24
+ readonly model: "openai/gpt-5.4-mini";
50
25
  readonly variant: "low";
51
26
  };
52
27
  };
53
- readonly anthropic: {
28
+ readonly kimi: {
54
29
  readonly orchestrator: {
55
- readonly model: "anthropic/claude-opus-4-6";
30
+ readonly model: "kimi-for-coding/k2p5";
56
31
  };
57
32
  readonly oracle: {
58
- readonly model: "anthropic/claude-opus-4-6";
33
+ readonly model: "kimi-for-coding/k2p5";
59
34
  readonly variant: "high";
60
35
  };
61
36
  readonly librarian: {
62
- readonly model: "anthropic/claude-sonnet-4-5";
37
+ readonly model: "kimi-for-coding/k2p5";
63
38
  readonly variant: "low";
64
39
  };
65
40
  readonly explorer: {
66
- readonly model: "anthropic/claude-haiku-4-5";
41
+ readonly model: "kimi-for-coding/k2p5";
67
42
  readonly variant: "low";
68
43
  };
69
44
  readonly designer: {
70
- readonly model: "anthropic/claude-sonnet-4-5";
45
+ readonly model: "kimi-for-coding/k2p5";
71
46
  readonly variant: "medium";
72
47
  };
73
48
  readonly fixer: {
74
- readonly model: "anthropic/claude-sonnet-4-5";
49
+ readonly model: "kimi-for-coding/k2p5";
75
50
  readonly variant: "low";
76
51
  };
77
52
  };
78
53
  readonly copilot: {
79
54
  readonly orchestrator: {
80
- readonly model: "github-copilot/grok-code-fast-1";
55
+ readonly model: "github-copilot/claude-opus-4.6";
81
56
  };
82
57
  readonly oracle: {
83
- readonly model: "github-copilot/grok-code-fast-1";
58
+ readonly model: "github-copilot/claude-opus-4.6";
84
59
  readonly variant: "high";
85
60
  };
86
61
  readonly librarian: {
@@ -92,113 +67,38 @@ export declare const MODEL_MAPPINGS: {
92
67
  readonly variant: "low";
93
68
  };
94
69
  readonly designer: {
95
- readonly model: "github-copilot/grok-code-fast-1";
70
+ readonly model: "github-copilot/gemini-3.1-pro-preview";
96
71
  readonly variant: "medium";
97
72
  };
98
73
  readonly fixer: {
99
- readonly model: "github-copilot/grok-code-fast-1";
74
+ readonly model: "github-copilot/claude-sonnet-4.6";
100
75
  readonly variant: "low";
101
76
  };
102
77
  };
103
78
  readonly 'zai-plan': {
104
79
  readonly orchestrator: {
105
- readonly model: "zai-coding-plan/glm-4.7";
106
- };
107
- readonly oracle: {
108
- readonly model: "zai-coding-plan/glm-4.7";
109
- readonly variant: "high";
110
- };
111
- readonly librarian: {
112
- readonly model: "zai-coding-plan/glm-4.7";
113
- readonly variant: "low";
114
- };
115
- readonly explorer: {
116
- readonly model: "zai-coding-plan/glm-4.7";
117
- readonly variant: "low";
118
- };
119
- readonly designer: {
120
- readonly model: "zai-coding-plan/glm-4.7";
121
- readonly variant: "medium";
122
- };
123
- readonly fixer: {
124
- readonly model: "zai-coding-plan/glm-4.7";
125
- readonly variant: "low";
126
- };
127
- };
128
- readonly antigravity: {
129
- readonly orchestrator: {
130
- readonly model: "google/antigravity-gemini-3-flash";
131
- };
132
- readonly oracle: {
133
- readonly model: "google/antigravity-gemini-3.1-pro";
134
- };
135
- readonly librarian: {
136
- readonly model: "google/antigravity-gemini-3-flash";
137
- readonly variant: "low";
138
- };
139
- readonly explorer: {
140
- readonly model: "google/antigravity-gemini-3-flash";
141
- readonly variant: "low";
142
- };
143
- readonly designer: {
144
- readonly model: "google/antigravity-gemini-3-flash";
145
- readonly variant: "medium";
146
- };
147
- readonly fixer: {
148
- readonly model: "google/antigravity-gemini-3-flash";
149
- readonly variant: "low";
150
- };
151
- };
152
- readonly chutes: {
153
- readonly orchestrator: {
154
- readonly model: "chutes/kimi-k2.5";
155
- };
156
- readonly oracle: {
157
- readonly model: "chutes/kimi-k2.5";
158
- readonly variant: "high";
159
- };
160
- readonly librarian: {
161
- readonly model: "chutes/minimax-m2.1";
162
- readonly variant: "low";
163
- };
164
- readonly explorer: {
165
- readonly model: "chutes/minimax-m2.1";
166
- readonly variant: "low";
167
- };
168
- readonly designer: {
169
- readonly model: "chutes/kimi-k2.5";
170
- readonly variant: "medium";
171
- };
172
- readonly fixer: {
173
- readonly model: "chutes/minimax-m2.1";
174
- readonly variant: "low";
175
- };
176
- };
177
- readonly 'zen-free': {
178
- readonly orchestrator: {
179
- readonly model: "opencode/big-pickle";
80
+ readonly model: "zai-coding-plan/glm-5";
180
81
  };
181
82
  readonly oracle: {
182
- readonly model: "opencode/big-pickle";
83
+ readonly model: "zai-coding-plan/glm-5";
183
84
  readonly variant: "high";
184
85
  };
185
86
  readonly librarian: {
186
- readonly model: "opencode/big-pickle";
87
+ readonly model: "zai-coding-plan/glm-5";
187
88
  readonly variant: "low";
188
89
  };
189
90
  readonly explorer: {
190
- readonly model: "opencode/big-pickle";
91
+ readonly model: "zai-coding-plan/glm-5";
191
92
  readonly variant: "low";
192
93
  };
193
94
  readonly designer: {
194
- readonly model: "opencode/big-pickle";
95
+ readonly model: "zai-coding-plan/glm-5";
195
96
  readonly variant: "medium";
196
97
  };
197
98
  readonly fixer: {
198
- readonly model: "opencode/big-pickle";
99
+ readonly model: "zai-coding-plan/glm-5";
199
100
  readonly variant: "low";
200
101
  };
201
102
  };
202
103
  };
203
- export declare function generateAntigravityMixedPreset(config: InstallConfig, existingPreset?: Record<string, unknown>): Record<string, unknown>;
204
104
  export declare function generateLiteConfig(installConfig: InstallConfig): Record<string, unknown>;
@@ -1,88 +1,11 @@
1
1
  export type BooleanArg = 'yes' | 'no';
2
2
  export interface InstallArgs {
3
3
  tui: boolean;
4
- kimi?: BooleanArg;
5
- openai?: BooleanArg;
6
- anthropic?: BooleanArg;
7
- copilot?: BooleanArg;
8
- zaiPlan?: BooleanArg;
9
- antigravity?: BooleanArg;
10
- chutes?: BooleanArg;
11
4
  tmux?: BooleanArg;
12
5
  skills?: BooleanArg;
13
- opencodeFree?: BooleanArg;
14
- balancedSpend?: BooleanArg;
15
- opencodeFreeModel?: string;
16
- aaKey?: string;
17
- openrouterKey?: string;
18
6
  dryRun?: boolean;
19
- modelsOnly?: boolean;
7
+ reset?: boolean;
20
8
  }
21
- export interface OpenCodeFreeModel {
22
- providerID: string;
23
- model: string;
24
- name: string;
25
- status: 'alpha' | 'beta' | 'deprecated' | 'active';
26
- contextLimit: number;
27
- outputLimit: number;
28
- reasoning: boolean;
29
- toolcall: boolean;
30
- attachment: boolean;
31
- dailyRequestLimit?: number;
32
- }
33
- export interface DiscoveredModel {
34
- providerID: string;
35
- model: string;
36
- name: string;
37
- status: 'alpha' | 'beta' | 'deprecated' | 'active';
38
- contextLimit: number;
39
- outputLimit: number;
40
- reasoning: boolean;
41
- toolcall: boolean;
42
- attachment: boolean;
43
- dailyRequestLimit?: number;
44
- costInput?: number;
45
- costOutput?: number;
46
- }
47
- export interface DynamicAgentAssignment {
48
- model: string;
49
- variant?: string;
50
- }
51
- export type ScoringEngineVersion = 'v1' | 'v2-shadow' | 'v2';
52
- export type ResolutionLayerName = 'opencode-direct-override' | 'manual-user-plan' | 'pinned-model' | 'dynamic-recommendation' | 'provider-fallback-policy' | 'system-default';
53
- export interface AgentResolutionProvenance {
54
- winnerLayer: ResolutionLayerName;
55
- winnerModel: string;
56
- }
57
- export interface DynamicPlanScoringMeta {
58
- engineVersionApplied: 'v1' | 'v2';
59
- shadowCompared: boolean;
60
- diffs?: Record<string, {
61
- v1TopModel?: string;
62
- v2TopModel?: string;
63
- }>;
64
- }
65
- export interface DynamicModelPlan {
66
- agents: Record<string, DynamicAgentAssignment>;
67
- chains: Record<string, string[]>;
68
- provenance?: Record<string, AgentResolutionProvenance>;
69
- scoring?: DynamicPlanScoringMeta;
70
- }
71
- export interface ExternalModelSignal {
72
- qualityScore?: number;
73
- codingScore?: number;
74
- latencySeconds?: number;
75
- inputPricePer1M?: number;
76
- outputPricePer1M?: number;
77
- source: 'artificial-analysis' | 'openrouter' | 'merged';
78
- }
79
- export type ExternalSignalMap = Record<string, ExternalModelSignal>;
80
- export type ManualAgentConfig = {
81
- primary: string;
82
- fallback1: string;
83
- fallback2: string;
84
- fallback3: string;
85
- };
86
9
  export interface OpenCodeConfig {
87
10
  plugin?: string[];
88
11
  provider?: Record<string, unknown>;
@@ -90,34 +13,11 @@ export interface OpenCodeConfig {
90
13
  [key: string]: unknown;
91
14
  }
92
15
  export interface InstallConfig {
93
- hasKimi: boolean;
94
- hasOpenAI: boolean;
95
- hasAnthropic?: boolean;
96
- hasCopilot?: boolean;
97
- hasZaiPlan?: boolean;
98
- hasAntigravity: boolean;
99
- hasChutes?: boolean;
100
- hasOpencodeZen: boolean;
101
- useOpenCodeFreeModels?: boolean;
102
- preferredOpenCodeModel?: string;
103
- selectedOpenCodePrimaryModel?: string;
104
- selectedOpenCodeSecondaryModel?: string;
105
- availableOpenCodeFreeModels?: OpenCodeFreeModel[];
106
- selectedChutesPrimaryModel?: string;
107
- selectedChutesSecondaryModel?: string;
108
- availableChutesModels?: DiscoveredModel[];
109
- dynamicModelPlan?: DynamicModelPlan;
110
- scoringEngineVersion?: ScoringEngineVersion;
111
- artificialAnalysisApiKey?: string;
112
- openRouterApiKey?: string;
113
- balanceProviderUsage?: boolean;
114
16
  hasTmux: boolean;
115
17
  installSkills: boolean;
116
18
  installCustomSkills: boolean;
117
- setupMode: 'quick' | 'manual';
118
- manualAgentConfigs?: Record<string, ManualAgentConfig>;
119
19
  dryRun?: boolean;
120
- modelsOnly?: boolean;
20
+ reset: boolean;
121
21
  }
122
22
  export interface ConfigMergeResult {
123
23
  success: boolean;
@@ -3,7 +3,8 @@ import { type PluginConfig } from './schema';
3
3
  * Load plugin configuration from user and project config files, merging them appropriately.
4
4
  *
5
5
  * Configuration is loaded from two locations:
6
- * 1. User config: ~/.config/opencode/oh-my-opencode-slim.jsonc or .json (or $XDG_CONFIG_HOME)
6
+ * 1. User config: $OPENCODE_CONFIG_DIR/oh-my-opencode-slim.jsonc or .json,
7
+ * or ~/.config/opencode/oh-my-opencode-slim.jsonc or .json (or $XDG_CONFIG_HOME)
7
8
  * 2. Project config: <directory>/.opencode/oh-my-opencode-slim.jsonc or .json
8
9
  *
9
10
  * JSONC format is preferred over JSON (allows comments and trailing commas).
@@ -109,6 +109,7 @@ export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>;
109
109
  export declare const FailoverConfigSchema: z.ZodObject<{
110
110
  enabled: z.ZodDefault<z.ZodBoolean>;
111
111
  timeoutMs: z.ZodDefault<z.ZodNumber>;
112
+ retryDelayMs: z.ZodDefault<z.ZodNumber>;
112
113
  chains: z.ZodDefault<z.ZodObject<{
113
114
  orchestrator: z.ZodOptional<z.ZodArray<z.ZodString>>;
114
115
  oracle: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -121,6 +122,7 @@ export declare const FailoverConfigSchema: z.ZodObject<{
121
122
  export type FailoverConfig = z.infer<typeof FailoverConfigSchema>;
122
123
  export declare const PluginConfigSchema: z.ZodObject<{
123
124
  preset: z.ZodOptional<z.ZodString>;
125
+ setDefaultAgent: z.ZodOptional<z.ZodBoolean>;
124
126
  scoringEngineVersion: z.ZodOptional<z.ZodEnum<{
125
127
  v1: "v1";
126
128
  "v2-shadow": "v2-shadow";
@@ -203,6 +205,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
203
205
  fallback: z.ZodOptional<z.ZodObject<{
204
206
  enabled: z.ZodDefault<z.ZodBoolean>;
205
207
  timeoutMs: z.ZodDefault<z.ZodNumber>;
208
+ retryDelayMs: z.ZodDefault<z.ZodNumber>;
206
209
  chains: z.ZodDefault<z.ZodObject<{
207
210
  orchestrator: z.ZodOptional<z.ZodArray<z.ZodString>>;
208
211
  oracle: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Runtime model fallback for foreground (interactive) agent sessions.
3
+ *
4
+ * When OpenCode fires a session.error, message.updated, or session.status
5
+ * event containing a rate-limit signal, this manager:
6
+ * 1. Looks up the next untried model in the agent's configured chain
7
+ * 2. Aborts the rate-limited prompt via client.session.abort()
8
+ * 3. Re-queues the last user message via client.session.promptAsync()
9
+ * with the new model — promptAsync returns immediately so we never
10
+ * block the event handler waiting for a full LLM response.
11
+ *
12
+ * This mirrors the BackgroundTaskManager's fallback loop but operates
13
+ * reactively through the event system instead of wrapping prompt() in a
14
+ * try/catch, which is not possible for interactive (foreground) sessions.
15
+ */
16
+ import type { PluginInput } from '@opencode-ai/plugin';
17
+ type OpencodeClient = PluginInput['client'];
18
+ export declare function isRateLimitError(error: unknown): boolean;
19
+ /**
20
+ * Manages runtime model fallback for foreground agent sessions.
21
+ *
22
+ * Constructed at plugin init with the ordered fallback chains for each agent
23
+ * (built from _modelArray entries merged with fallback.chains config).
24
+ */
25
+ export declare class ForegroundFallbackManager {
26
+ private readonly client;
27
+ /**
28
+ * Ordered fallback chains per agent.
29
+ * e.g. { orchestrator: ['anthropic/claude-opus-4-5', 'openai/gpt-4o'] }
30
+ * The first model that hasn't been tried yet is selected on each fallback.
31
+ */
32
+ private readonly chains;
33
+ private readonly enabled;
34
+ /** sessionID → last observed model string ("providerID/modelID") */
35
+ private readonly sessionModel;
36
+ /** sessionID → agent name (populated from message.updated info.agent field) */
37
+ private readonly sessionAgent;
38
+ /** sessionID → set of models already attempted this session */
39
+ private readonly sessionTried;
40
+ /** Sessions with an active fallback switch in flight */
41
+ private readonly inProgress;
42
+ /** sessionID → timestamp of last trigger (for deduplication) */
43
+ private readonly lastTrigger;
44
+ constructor(client: OpencodeClient,
45
+ /**
46
+ * Ordered fallback chains per agent.
47
+ * e.g. { orchestrator: ['anthropic/claude-opus-4-5', 'openai/gpt-4o'] }
48
+ * The first model that hasn't been tried yet is selected on each fallback.
49
+ */
50
+ chains: Record<string, string[]>, enabled: boolean);
51
+ /**
52
+ * Process an OpenCode plugin event.
53
+ * Call this from the plugin's `event` hook for every event received.
54
+ */
55
+ handleEvent(rawEvent: unknown): Promise<void>;
56
+ private tryFallback;
57
+ /**
58
+ * Determine the fallback chain to use for a session.
59
+ *
60
+ * Priority:
61
+ * 1. Agent name known AND has a configured chain → return it directly
62
+ * 2. Agent name known but NO chain configured → return [] (no fallback;
63
+ * do NOT bleed into other agents' chains which would re-prompt the
64
+ * session with a model belonging to a completely different agent)
65
+ * 3. Agent name unknown, current model known → search all chains for
66
+ * the model to infer which chain to use
67
+ * 4. Nothing matches → flatten all chains as a last resort (only
68
+ * reached when both agent name and current model are unavailable)
69
+ */
70
+ private resolveChain;
71
+ }
72
+ export {};
@@ -2,6 +2,7 @@ export type { AutoUpdateCheckerOptions } from './auto-update-checker';
2
2
  export { createAutoUpdateCheckerHook } from './auto-update-checker';
3
3
  export { createChatHeadersHook } from './chat-headers';
4
4
  export { createDelegateTaskRetryHook } from './delegate-task-retry';
5
+ export { ForegroundFallbackManager, isRateLimitError } from './foreground-fallback';
5
6
  export { createJsonErrorRecoveryHook } from './json-error-recovery';
6
7
  export { createPhaseReminderHook } from './phase-reminder';
7
8
  export { createPostReadNudgeHook } from './post-read-nudge';