oh-my-opencode-slim 0.9.0 → 0.9.2

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 CHANGED
@@ -3,6 +3,12 @@
3
3
  <p><i>Seven divine beings emerged from the dawn of code, each an immortal master of their craft await your command to forge order from chaos and build what was once thought impossible.</i></p>
4
4
  <p><b>Open Multi Agent Suite</b> · Mix any models · Auto delegate tasks</p>
5
5
  <p><a href="https://moltfounders.com/jobs/09d1c6e7-9e0e-4683-8d78-e2376aaa2333"><img src="https://moltfounders.com/badges/4.png" alt="MoltFounders" height="30"></a></p>
6
+ <p><sub>by <b>Boring Dystopia Development</b></sub></p>
7
+ <p>
8
+ <a href="https://boringdystopia.ai/"><img src="https://img.shields.io/badge/boringdystopia.ai-111111?style=for-the-badge&logo=vercel&logoColor=white" alt="boringdystopia.ai"></a>&nbsp;
9
+ <a href="https://x.com/alvinunreal"><img src="https://img.shields.io/badge/X-@alvinunreal-000000?style=for-the-badge&logo=x&logoColor=white" alt="X @alvinunreal"></a>&nbsp;
10
+ <a href="https://t.me/boringdystopiadevelopment"><img src="https://img.shields.io/badge/Telegram-Join%20channel-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white" alt="Telegram Join channel"></a>
11
+ </p>
6
12
  </div>
7
13
 
8
14
  ---
@@ -20,7 +26,7 @@ The installer generates an OpenAI configuration by default (using `gpt-5.4` and
20
26
  For non-interactive mode:
21
27
 
22
28
  ```bash
23
- bunx oh-my-opencode-slim@latest install --no-tui --tmux=no --skills=yes
29
+ bunx oh-my-opencode-slim@latest install --no-tui --tmux=yes --skills=yes
24
30
  ```
25
31
 
26
32
  To force overwrite of an existing configuration:
@@ -352,7 +358,7 @@ If any agent fails to respond, check your provider authentication and config fil
352
358
  | Feature | Doc | What it does |
353
359
  |---------|-----|--------------|
354
360
  | **Council** | [council.md](docs/council.md) | Run N models in parallel, synthesize one answer (`@council`) |
355
- | **Tmux Integration** | [tmux-integration.md](docs/tmux-integration.md) | Watch agents work in real-time with auto-spawned panes |
361
+ | **Multiplexer Integration** | [multiplexer-integration.md](docs/multiplexer-integration.md) | Watch agents work in real-time with auto-spawned panes (Tmux/Zellij) |
356
362
  | **Cartography Skill** | [cartography.md](docs/cartography.md) | Auto-generate hierarchical codemaps for any codebase |
357
363
 
358
364
  ### ⚙️ Config & Reference
@@ -372,6 +378,74 @@ If any agent fails to respond, check your provider authentication and config fil
372
378
 
373
379
  ---
374
380
 
381
+ ## 🏛️ Contributors
382
+
383
+ <div align="center">
384
+ <p><i>The builders, debuggers, writers, and wanderers who have earned their place in the pantheon.</i></p>
385
+ <p><sub>Every merged contribution leaves a mark on the realm.</sub></p>
386
+
387
+ <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
388
+ [![All Contributors](https://img.shields.io/badge/all_contributors-30-orange.svg?style=flat-square)](#contributors-)
389
+ <!-- ALL-CONTRIBUTORS-BADGE:END -->
390
+ </div>
391
+
392
+ <br>
393
+
394
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
395
+ <!-- prettier-ignore-start -->
396
+ <!-- markdownlint-disable -->
397
+ <table>
398
+ <tbody>
399
+ <tr>
400
+ <td align="center" valign="top" width="16.66%"><a href="https://boringdystopia.ai/"><img src="https://avatars.githubusercontent.com/u/204474669?v=4?s=100" width="100px;" alt="Alvin"/><br /><sub><b>Alvin</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=alvinunreal" title="Code">💻</a></td>
401
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/alvinreal"><img src="https://avatars.githubusercontent.com/u/262747402?v=4?s=100" width="100px;" alt="alvinreal"/><br /><sub><b>alvinreal</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=alvinreal" title="Code">💻</a></td>
402
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/imarshallwidjaja"><img src="https://avatars.githubusercontent.com/u/60992624?v=4?s=100" width="100px;" alt="imw"/><br /><sub><b>imw</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=imarshallwidjaja" title="Code">💻</a></td>
403
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/adikpb"><img src="https://avatars.githubusercontent.com/u/67222969?v=4?s=100" width="100px;" alt="Adithya Kozham Burath Bijoy"/><br /><sub><b>Adithya Kozham Burath Bijoy</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=adikpb" title="Code">💻</a></td>
404
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/ReqX"><img src="https://avatars.githubusercontent.com/u/14987124?v=4?s=100" width="100px;" alt="ReqX"/><br /><sub><b>ReqX</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=ReqX" title="Code">💻</a></td>
405
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/abhideepm"><img src="https://avatars.githubusercontent.com/u/28213051?v=4?s=100" width="100px;" alt="Abhideep Maity"/><br /><sub><b>Abhideep Maity</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=abhideepm" title="Code">💻</a></td>
406
+ </tr>
407
+ <tr>
408
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Daltonganger"><img src="https://avatars.githubusercontent.com/u/17501732?v=4?s=100" width="100px;" alt="Ruben"/><br /><sub><b>Ruben</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=Daltonganger" title="Code">💻</a></td>
409
+ <td align="center" valign="top" width="16.66%"><a href="https://horizzon3507.vercel.app/"><img src="https://avatars.githubusercontent.com/u/148660626?v=4?s=100" width="100px;" alt="Gabriel Rodrigues"/><br /><sub><b>Gabriel Rodrigues</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=horizzon3507" title="Code">💻</a></td>
410
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/jmvbambico"><img src="https://avatars.githubusercontent.com/u/45126068?v=4?s=100" width="100px;" alt="John Michael Vincent Bambico"/><br /><sub><b>John Michael Vincent Bambico</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=jmvbambico" title="Code">💻</a></td>
411
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/mfold111"><img src="https://avatars.githubusercontent.com/u/261528848?v=4?s=100" width="100px;" alt="Molt Founders"/><br /><sub><b>Molt Founders</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=mfold111" title="Code">💻</a></td>
412
+ <td align="center" valign="top" width="16.66%"><a href="https://me.mashiro.best/"><img src="https://avatars.githubusercontent.com/u/22992947?v=4?s=100" width="100px;" alt="Muen Yu"/><br /><sub><b>Muen Yu</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=MuenYu" title="Code">💻</a></td>
413
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/NocturnesLK"><img src="https://avatars.githubusercontent.com/u/102891073?v=4?s=100" width="100px;" alt="NocturnesLK"/><br /><sub><b>NocturnesLK</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=NocturnesLK" title="Code">💻</a></td>
414
+ </tr>
415
+ <tr>
416
+ <td align="center" valign="top" width="16.66%"><a href="http://riccardosallusti.it/"><img src="https://avatars.githubusercontent.com/u/466102?v=4?s=100" width="100px;" alt="Riccardo Sallusti"/><br /><sub><b>Riccardo Sallusti</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=rizal72" title="Code">💻</a></td>
417
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Yusyuriv"><img src="https://avatars.githubusercontent.com/u/3993179?v=4?s=100" width="100px;" alt="Yan Li"/><br /><sub><b>Yan Li</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=Yusyuriv" title="Code">💻</a></td>
418
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/nghyane"><img src="https://avatars.githubusercontent.com/u/59473462?v=4?s=100" width="100px;" alt="Hoàng Văn Anh Nghĩa"/><br /><sub><b>Hoàng Văn Anh Nghĩa</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=nghyane" title="Code">💻</a></td>
419
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Jyers"><img src="https://avatars.githubusercontent.com/u/76993396?v=4?s=100" width="100px;" alt="Jacob Myers"/><br /><sub><b>Jacob Myers</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=Jyers" title="Code">💻</a></td>
420
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/kassieclaire"><img src="https://avatars.githubusercontent.com/u/59930829?v=4?s=100" width="100px;" alt="Kassie Povinelli"/><br /><sub><b>Kassie Povinelli</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=kassieclaire" title="Code">💻</a></td>
421
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/KyleHilliard"><img src="https://avatars.githubusercontent.com/u/178682772?v=4?s=100" width="100px;" alt="KyleHilliard"/><br /><sub><b>KyleHilliard</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=KyleHilliard" title="Code">💻</a></td>
422
+ </tr>
423
+ <tr>
424
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/j5hjun"><img src="https://avatars.githubusercontent.com/u/169322508?v=4?s=100" width="100px;" alt="j5hjun"/><br /><sub><b>j5hjun</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=j5hjun" title="Code">💻</a></td>
425
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/marcFernandez"><img src="https://avatars.githubusercontent.com/u/32362792?v=4?s=100" width="100px;" alt="marcFernandez"/><br /><sub><b>marcFernandez</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=marcFernandez" title="Code">💻</a></td>
426
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/mister-test"><img src="https://avatars.githubusercontent.com/u/212316706?v=4?s=100" width="100px;" alt="mister-test"/><br /><sub><b>mister-test</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=mister-test" title="Code">💻</a></td>
427
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/n24q02m"><img src="https://avatars.githubusercontent.com/u/135627235?v=4?s=100" width="100px;" alt="n24q02m"/><br /><sub><b>n24q02m</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=n24q02m" title="Code">💻</a></td>
428
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/oribarilan"><img src="https://avatars.githubusercontent.com/u/8760762?v=4?s=100" width="100px;" alt="oribi"/><br /><sub><b>oribi</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=oribarilan" title="Code">💻</a></td>
429
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/pelidan"><img src="https://avatars.githubusercontent.com/u/45832535?v=4?s=100" width="100px;" alt="pelidan"/><br /><sub><b>pelidan</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=pelidan" title="Code">💻</a></td>
430
+ </tr>
431
+ <tr>
432
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/xLillium"><img src="https://avatars.githubusercontent.com/u/16964936?v=4?s=100" width="100px;" alt="xLillium"/><br /><sub><b>xLillium</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=xLillium" title="Code">💻</a></td>
433
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/CoolZxp"><img src="https://avatars.githubusercontent.com/u/54017765?v=4?s=100" width="100px;" alt="⁢4.435km/s"/><br /><sub><b>⁢4.435km/s</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=CoolZxp" title="Code">💻</a></td>
434
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/drindr"><img src="https://avatars.githubusercontent.com/u/34709601?v=4?s=100" width="100px;" alt="Drin"/><br /><sub><b>Drin</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=drindr" title="Code">💻</a></td>
435
+ <td align="center" valign="top" width="16.66%"><a href="https://hzu.lol/"><img src="https://avatars.githubusercontent.com/u/42469039?v=4?s=100" width="100px;" alt="Hakim Zulkufli"/><br /><sub><b>Hakim Zulkufli</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=hakimzulkufli" title="Code">💻</a></td>
436
+ <td align="center" valign="top" width="16.66%"><a href="https://bit.ly/2N1ynXZ"><img src="https://avatars.githubusercontent.com/u/14874913?v=4?s=100" width="100px;" alt="Simon Klakegg"/><br /><sub><b>Simon Klakegg</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=sklakegg" title="Code">💻</a></td>
437
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/sudorest"><img src="https://avatars.githubusercontent.com/u/214225921?v=4?s=100" width="100px;" alt="Kiwi"/><br /><sub><b>Kiwi</b></sub></a><br /><a href="https://github.com/alvinunreal/oh-my-opencode-slim/commits?author=sudorest" title="Code">💻</a></td>
438
+ </tr>
439
+ </tbody>
440
+ </table>
441
+
442
+ <!-- markdownlint-restore -->
443
+ <!-- prettier-ignore-end -->
444
+
445
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
446
+
447
+ ---
448
+
375
449
  ## 📄 License
376
450
 
377
451
  MIT
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import type { PluginInput } from '@opencode-ai/plugin';
16
16
  import type { BackgroundTaskConfig, PluginConfig } from '../config';
17
- import type { TmuxConfig } from '../config/schema';
17
+ import type { MultiplexerConfig } from '../config/schema';
18
18
  import { SubagentDepthTracker } from './subagent-depth';
19
19
  /**
20
20
  * Represents a background task running in an isolated session.
@@ -57,7 +57,7 @@ export declare class BackgroundTaskManager {
57
57
  private activeStarts;
58
58
  private maxConcurrentStarts;
59
59
  private completionResolvers;
60
- constructor(ctx: PluginInput, tmuxConfig?: TmuxConfig, config?: PluginConfig);
60
+ constructor(ctx: PluginInput, multiplexerConfig?: MultiplexerConfig, config?: PluginConfig);
61
61
  /**
62
62
  * Look up the delegation rules for an agent type.
63
63
  * Unknown agent types default to explorer-only access, making it easy
@@ -137,6 +137,9 @@ export declare class BackgroundTaskManager {
137
137
  }): Promise<void>;
138
138
  /**
139
139
  * Extract task result and mark complete.
140
+ * When retry_on_empty is enabled (default), empty responses are
141
+ * treated as failures so the fallback chain can retry.
142
+ * When disabled, empty responses succeed with an empty string result.
140
143
  */
141
144
  private extractAndCompleteTask;
142
145
  /**
@@ -1,3 +1,3 @@
1
1
  export { type BackgroundTask, BackgroundTaskManager, type LaunchOptions, } from './background-manager';
2
+ export { MultiplexerSessionManager, TmuxSessionManager, } from './multiplexer-session-manager';
2
3
  export { SubagentDepthTracker } from './subagent-depth';
3
- export { TmuxSessionManager } from './tmux-session-manager';
@@ -0,0 +1,68 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { MultiplexerConfig } from '../config/schema';
3
+ /**
4
+ * Event shape for session events
5
+ */
6
+ interface SessionEvent {
7
+ type: string;
8
+ properties?: {
9
+ info?: {
10
+ id?: string;
11
+ parentID?: string;
12
+ title?: string;
13
+ };
14
+ sessionID?: string;
15
+ status?: {
16
+ type: string;
17
+ };
18
+ };
19
+ }
20
+ /**
21
+ * MultiplexerSessionManager tracks child sessions and spawns/closes multiplexer panes for them.
22
+ *
23
+ * Uses session.status events for completion detection instead of polling.
24
+ * Supports both tmux and zellij multiplexers.
25
+ */
26
+ export declare class MultiplexerSessionManager {
27
+ private client;
28
+ private serverUrl;
29
+ private multiplexer;
30
+ private sessions;
31
+ private pollInterval?;
32
+ private enabled;
33
+ constructor(ctx: PluginInput, config: MultiplexerConfig);
34
+ /**
35
+ * Handle session.created events.
36
+ * Spawns a multiplexer pane for child sessions (those with parentID).
37
+ */
38
+ onSessionCreated(event: SessionEvent): Promise<void>;
39
+ /**
40
+ * Handle session.status events for completion detection.
41
+ * Uses session.status instead of deprecated session.idle.
42
+ *
43
+ * When a session becomes idle (completed), close its pane.
44
+ */
45
+ onSessionStatus(event: SessionEvent): Promise<void>;
46
+ /**
47
+ * Handle session.deleted events.
48
+ * When a session is deleted, close its multiplexer pane immediately.
49
+ */
50
+ onSessionDeleted(event: SessionEvent): Promise<void>;
51
+ private startPolling;
52
+ private stopPolling;
53
+ /**
54
+ * Poll sessions for status updates (fallback for reliability).
55
+ * Also handles timeout and missing session detection.
56
+ */
57
+ private pollSessions;
58
+ private closeSession;
59
+ /**
60
+ * Clean up all tracked sessions.
61
+ */
62
+ cleanup(): Promise<void>;
63
+ }
64
+ /**
65
+ * @deprecated Use MultiplexerSessionManager instead
66
+ */
67
+ export declare const TmuxSessionManager: typeof MultiplexerSessionManager;
68
+ export {};
package/dist/cli/index.js CHANGED
@@ -90,6 +90,9 @@ function ensureOpenCodeConfigDir() {
90
90
  }
91
91
  }
92
92
 
93
+ // src/cli/config-io.ts
94
+ import { pathToFileURL } from "url";
95
+
93
96
  // src/config/constants.ts
94
97
  var SUBAGENT_NAMES = [
95
98
  "explorer",
@@ -13692,7 +13695,8 @@ var CouncilConfigSchema = exports_external.object({
13692
13695
  }
13693
13696
  return val;
13694
13697
  }).describe("Fallback models for the council master. Tried in order if the primary model fails. " + 'Example: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4"]'),
13695
- councillor_execution_mode: CouncillorExecutionModeSchema.describe('Execution mode for councillors. "serial" runs them one at a time (required for single-model systems). "parallel" runs them concurrently (default, faster for multi-model systems).')
13698
+ councillor_execution_mode: CouncillorExecutionModeSchema.describe('Execution mode for councillors. "serial" runs them one at a time (required for single-model systems). "parallel" runs them concurrently (default, faster for multi-model systems).'),
13699
+ councillor_retries: exports_external.number().int().min(0).max(5).default(3).describe("Number of retry attempts for councillors and master that return empty responses " + "(e.g. due to provider rate limiting). Default: 3 retries.")
13696
13700
  });
13697
13701
  // src/config/schema.ts
13698
13702
  var ProviderModelIdSchema = exports_external.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
@@ -13748,19 +13752,29 @@ var AgentOverrideConfigSchema = exports_external.object({
13748
13752
  skills: exports_external.array(exports_external.string()).optional(),
13749
13753
  mcps: exports_external.array(exports_external.string()).optional()
13750
13754
  });
13751
- var TmuxLayoutSchema = exports_external.enum([
13755
+ var MultiplexerTypeSchema = exports_external.enum(["auto", "tmux", "zellij", "none"]);
13756
+ var MultiplexerLayoutSchema = exports_external.enum([
13752
13757
  "main-horizontal",
13753
13758
  "main-vertical",
13754
13759
  "tiled",
13755
13760
  "even-horizontal",
13756
13761
  "even-vertical"
13757
13762
  ]);
13763
+ var TmuxLayoutSchema = MultiplexerLayoutSchema;
13764
+ var MultiplexerConfigSchema = exports_external.object({
13765
+ type: MultiplexerTypeSchema.default("none"),
13766
+ layout: MultiplexerLayoutSchema.default("main-vertical"),
13767
+ main_pane_size: exports_external.number().min(20).max(80).default(60)
13768
+ });
13758
13769
  var TmuxConfigSchema = exports_external.object({
13759
13770
  enabled: exports_external.boolean().default(false),
13760
13771
  layout: TmuxLayoutSchema.default("main-vertical"),
13761
13772
  main_pane_size: exports_external.number().min(20).max(80).default(60)
13762
13773
  });
13763
13774
  var PresetSchema = exports_external.record(exports_external.string(), AgentOverrideConfigSchema);
13775
+ var WebsearchConfigSchema = exports_external.object({
13776
+ provider: exports_external.enum(["exa", "tavily"]).default("exa")
13777
+ });
13764
13778
  var McpNameSchema = exports_external.enum(["websearch", "context7", "grep_app"]);
13765
13779
  var BackgroundTaskConfigSchema = exports_external.object({
13766
13780
  maxConcurrentStarts: exports_external.number().min(1).max(50).default(10)
@@ -13769,7 +13783,8 @@ var FailoverConfigSchema = exports_external.object({
13769
13783
  enabled: exports_external.boolean().default(true),
13770
13784
  timeoutMs: exports_external.number().min(0).default(15000),
13771
13785
  retryDelayMs: exports_external.number().min(0).default(500),
13772
- chains: FallbackChainsSchema.default({})
13786
+ chains: FallbackChainsSchema.default({}),
13787
+ retry_on_empty: exports_external.boolean().default(true).describe("When true (default), empty provider responses are treated as failures, " + "triggering fallback/retry. Set to false to treat them as successes.")
13773
13788
  });
13774
13789
  var PluginConfigSchema = exports_external.object({
13775
13790
  preset: exports_external.string().optional(),
@@ -13780,14 +13795,16 @@ var PluginConfigSchema = exports_external.object({
13780
13795
  presets: exports_external.record(exports_external.string(), PresetSchema).optional(),
13781
13796
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
13782
13797
  disabled_mcps: exports_external.array(exports_external.string()).optional(),
13798
+ multiplexer: MultiplexerConfigSchema.optional(),
13783
13799
  tmux: TmuxConfigSchema.optional(),
13800
+ websearch: WebsearchConfigSchema.optional(),
13784
13801
  background: BackgroundTaskConfigSchema.optional(),
13785
13802
  fallback: FailoverConfigSchema.optional(),
13786
13803
  council: CouncilConfigSchema.optional()
13787
13804
  });
13788
13805
  // src/config/agent-mcps.ts
13789
13806
  var DEFAULT_AGENT_MCPS = {
13790
- orchestrator: ["websearch"],
13807
+ orchestrator: ["*"],
13791
13808
  designer: [],
13792
13809
  oracle: [],
13793
13810
  librarian: ["websearch", "context7", "grep_app"],
@@ -13991,6 +14008,24 @@ function generateLiteConfig(installConfig) {
13991
14008
 
13992
14009
  // src/cli/config-io.ts
13993
14010
  var PACKAGE_NAME = "oh-my-opencode-slim";
14011
+ function isPluginEntry(entry) {
14012
+ return entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`) || entry.startsWith("file://") && entry.includes(PACKAGE_NAME);
14013
+ }
14014
+ function getPluginEntry() {
14015
+ const cliEntryPath = process.argv[1];
14016
+ if (!cliEntryPath) {
14017
+ return PACKAGE_NAME;
14018
+ }
14019
+ try {
14020
+ const pluginEntryPath = cliEntryPath.match(/[\\/]dist[\\/]cli[\\/]index\.js$/) ? cliEntryPath.replace(/[\\/]dist[\\/]cli[\\/]index\.js$/, "/dist/index.js") : null;
14021
+ if (!pluginEntryPath) {
14022
+ return PACKAGE_NAME;
14023
+ }
14024
+ return pathToFileURL(pluginEntryPath).href;
14025
+ } catch {
14026
+ return PACKAGE_NAME;
14027
+ }
14028
+ }
13994
14029
  function stripJsonComments(json2) {
13995
14030
  const commentPattern = /\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g;
13996
14031
  const trailingCommaPattern = /\\"|"(?:\\"|[^"])*"|(,)(\s*[}\]])/g;
@@ -14057,8 +14092,9 @@ async function addPluginToOpenCodeConfig() {
14057
14092
  }
14058
14093
  const config2 = parsedConfig ?? {};
14059
14094
  const plugins = config2.plugin ?? [];
14060
- const filteredPlugins = plugins.filter((p) => p !== PACKAGE_NAME && !p.startsWith(`${PACKAGE_NAME}@`));
14061
- filteredPlugins.push(PACKAGE_NAME);
14095
+ const pluginEntry = getPluginEntry();
14096
+ const filteredPlugins = plugins.filter((p) => !isPluginEntry(p));
14097
+ filteredPlugins.push(pluginEntry);
14062
14098
  config2.plugin = filteredPlugins;
14063
14099
  writeConfig(configPath, config2);
14064
14100
  return { success: true, configPath };
@@ -14137,7 +14173,7 @@ function detectCurrentConfig() {
14137
14173
  if (!config2)
14138
14174
  return result;
14139
14175
  const plugins = config2.plugin ?? [];
14140
- result.isInstalled = plugins.some((p) => p.startsWith(PACKAGE_NAME));
14176
+ result.isInstalled = plugins.some((p) => isPluginEntry(p));
14141
14177
  result.hasAntigravity = plugins.some((p) => p.startsWith("opencode-antigravity-auth"));
14142
14178
  const providers = config2.provider;
14143
14179
  result.hasKimi = !!providers?.kimi;
@@ -118,6 +118,7 @@ export declare const CouncilConfigSchema: z.ZodObject<{
118
118
  parallel: "parallel";
119
119
  serial: "serial";
120
120
  }>>;
121
+ councillor_retries: z.ZodDefault<z.ZodNumber>;
121
122
  }, z.core.$strip>;
122
123
  export type CouncilConfig = z.infer<typeof CouncilConfigSchema>;
123
124
  export type CouncillorExecutionMode = z.infer<typeof CouncillorExecutionModeSchema>;
@@ -60,6 +60,21 @@ export declare const AgentOverrideConfigSchema: z.ZodObject<{
60
60
  skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
61
  mcps: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
62
  }, z.core.$strip>;
63
+ export declare const MultiplexerTypeSchema: z.ZodEnum<{
64
+ auto: "auto";
65
+ tmux: "tmux";
66
+ zellij: "zellij";
67
+ none: "none";
68
+ }>;
69
+ export type MultiplexerType = z.infer<typeof MultiplexerTypeSchema>;
70
+ export declare const MultiplexerLayoutSchema: z.ZodEnum<{
71
+ "main-horizontal": "main-horizontal";
72
+ "main-vertical": "main-vertical";
73
+ tiled: "tiled";
74
+ "even-horizontal": "even-horizontal";
75
+ "even-vertical": "even-vertical";
76
+ }>;
77
+ export type MultiplexerLayout = z.infer<typeof MultiplexerLayoutSchema>;
63
78
  export declare const TmuxLayoutSchema: z.ZodEnum<{
64
79
  "main-horizontal": "main-horizontal";
65
80
  "main-vertical": "main-vertical";
@@ -67,7 +82,24 @@ export declare const TmuxLayoutSchema: z.ZodEnum<{
67
82
  "even-horizontal": "even-horizontal";
68
83
  "even-vertical": "even-vertical";
69
84
  }>;
70
- export type TmuxLayout = z.infer<typeof TmuxLayoutSchema>;
85
+ export type TmuxLayout = MultiplexerLayout;
86
+ export declare const MultiplexerConfigSchema: z.ZodObject<{
87
+ type: z.ZodDefault<z.ZodEnum<{
88
+ auto: "auto";
89
+ tmux: "tmux";
90
+ zellij: "zellij";
91
+ none: "none";
92
+ }>>;
93
+ layout: z.ZodDefault<z.ZodEnum<{
94
+ "main-horizontal": "main-horizontal";
95
+ "main-vertical": "main-vertical";
96
+ tiled: "tiled";
97
+ "even-horizontal": "even-horizontal";
98
+ "even-vertical": "even-vertical";
99
+ }>>;
100
+ main_pane_size: z.ZodDefault<z.ZodNumber>;
101
+ }, z.core.$strip>;
102
+ export type MultiplexerConfig = z.infer<typeof MultiplexerConfigSchema>;
71
103
  export declare const TmuxConfigSchema: z.ZodObject<{
72
104
  enabled: z.ZodDefault<z.ZodBoolean>;
73
105
  layout: z.ZodDefault<z.ZodEnum<{
@@ -97,6 +129,13 @@ export declare const PresetSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
97
129
  mcps: z.ZodOptional<z.ZodArray<z.ZodString>>;
98
130
  }, z.core.$strip>>;
99
131
  export type Preset = z.infer<typeof PresetSchema>;
132
+ export declare const WebsearchConfigSchema: z.ZodObject<{
133
+ provider: z.ZodDefault<z.ZodEnum<{
134
+ exa: "exa";
135
+ tavily: "tavily";
136
+ }>>;
137
+ }, z.core.$strip>;
138
+ export type WebsearchConfig = z.infer<typeof WebsearchConfigSchema>;
100
139
  export declare const McpNameSchema: z.ZodEnum<{
101
140
  websearch: "websearch";
102
141
  context7: "context7";
@@ -119,6 +158,7 @@ export declare const FailoverConfigSchema: z.ZodObject<{
119
158
  librarian: z.ZodOptional<z.ZodArray<z.ZodString>>;
120
159
  fixer: z.ZodOptional<z.ZodArray<z.ZodString>>;
121
160
  }, z.core.$catchall<z.ZodArray<z.ZodString>>>>;
161
+ retry_on_empty: z.ZodDefault<z.ZodBoolean>;
122
162
  }, z.core.$strip>;
123
163
  export type FailoverConfig = z.infer<typeof FailoverConfigSchema>;
124
164
  export declare const PluginConfigSchema: z.ZodObject<{
@@ -189,6 +229,22 @@ export declare const PluginConfigSchema: z.ZodObject<{
189
229
  mcps: z.ZodOptional<z.ZodArray<z.ZodString>>;
190
230
  }, z.core.$strip>>>;
191
231
  disabled_mcps: z.ZodOptional<z.ZodArray<z.ZodString>>;
232
+ multiplexer: z.ZodOptional<z.ZodObject<{
233
+ type: z.ZodDefault<z.ZodEnum<{
234
+ auto: "auto";
235
+ tmux: "tmux";
236
+ zellij: "zellij";
237
+ none: "none";
238
+ }>>;
239
+ layout: z.ZodDefault<z.ZodEnum<{
240
+ "main-horizontal": "main-horizontal";
241
+ "main-vertical": "main-vertical";
242
+ tiled: "tiled";
243
+ "even-horizontal": "even-horizontal";
244
+ "even-vertical": "even-vertical";
245
+ }>>;
246
+ main_pane_size: z.ZodDefault<z.ZodNumber>;
247
+ }, z.core.$strip>>;
192
248
  tmux: z.ZodOptional<z.ZodObject<{
193
249
  enabled: z.ZodDefault<z.ZodBoolean>;
194
250
  layout: z.ZodDefault<z.ZodEnum<{
@@ -200,6 +256,12 @@ export declare const PluginConfigSchema: z.ZodObject<{
200
256
  }>>;
201
257
  main_pane_size: z.ZodDefault<z.ZodNumber>;
202
258
  }, z.core.$strip>>;
259
+ websearch: z.ZodOptional<z.ZodObject<{
260
+ provider: z.ZodDefault<z.ZodEnum<{
261
+ exa: "exa";
262
+ tavily: "tavily";
263
+ }>>;
264
+ }, z.core.$strip>>;
203
265
  background: z.ZodOptional<z.ZodObject<{
204
266
  maxConcurrentStarts: z.ZodDefault<z.ZodNumber>;
205
267
  }, z.core.$strip>>;
@@ -215,6 +277,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
215
277
  librarian: z.ZodOptional<z.ZodArray<z.ZodString>>;
216
278
  fixer: z.ZodOptional<z.ZodArray<z.ZodString>>;
217
279
  }, z.core.$catchall<z.ZodArray<z.ZodString>>>>;
280
+ retry_on_empty: z.ZodDefault<z.ZodBoolean>;
218
281
  }, z.core.$strip>>;
219
282
  council: z.ZodOptional<z.ZodObject<{
220
283
  master: z.ZodObject<{
@@ -242,6 +305,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
242
305
  parallel: "parallel";
243
306
  serial: "serial";
244
307
  }>>;
308
+ councillor_retries: z.ZodDefault<z.ZodNumber>;
245
309
  }, z.core.$strip>>;
246
310
  }, z.core.$strip>;
247
311
  export type PluginConfig = z.infer<typeof PluginConfigSchema>;
@@ -36,5 +36,18 @@ export declare class CouncilManager {
36
36
  */
37
37
  private runAgentSession;
38
38
  private runCouncillors;
39
+ /**
40
+ * Run a single councillor with retry logic for empty responses.
41
+ * Only retries on "Empty response from provider" errors — timeouts
42
+ * and other failures are returned immediately.
43
+ */
44
+ private runCouncillorWithRetry;
45
+ /**
46
+ * Run a single master model with retry logic for empty responses.
47
+ * Only retries on "Empty response from provider" — timeouts and
48
+ * other failures throw immediately so runMaster can try the next
49
+ * fallback model.
50
+ */
51
+ private runMasterModelWithRetry;
39
52
  private runMaster;
40
53
  }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Filter available_skills block based on the current agent's permission.skill rules.
3
+ * OpenCode core injects `<available_skills>` globally, so this hook rewrites that
4
+ * block before the prompt is sent.
5
+ */
6
+ import type { PluginInput } from '@opencode-ai/plugin';
7
+ import { type PluginConfig } from '../../config';
8
+ interface MessageInfo {
9
+ role: string;
10
+ agent?: string;
11
+ }
12
+ interface MessagePart {
13
+ type: string;
14
+ text?: string;
15
+ [key: string]: unknown;
16
+ }
17
+ interface MessageWithParts {
18
+ info: MessageInfo;
19
+ parts: MessagePart[];
20
+ }
21
+ type SkillRule = 'allow' | 'ask' | 'deny';
22
+ declare function filterAvailableSkillsText(text: string, permissionRules: Record<string, SkillRule>): string;
23
+ /**
24
+ * Creates the experimental.chat.messages.transform hook for filtering available skills.
25
+ * This hook runs right before sending to API, so it doesn't affect UI display.
26
+ */
27
+ export declare function createFilterAvailableSkillsHook(_ctx: PluginInput, config: PluginConfig): {
28
+ 'experimental.chat.messages.transform': (_input: Record<string, never>, output: {
29
+ messages: MessageWithParts[];
30
+ }) => Promise<void>;
31
+ };
32
+ export { filterAvailableSkillsText };
@@ -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 { createFilterAvailableSkillsHook } from './filter-available-skills';
5
6
  export { ForegroundFallbackManager, isRateLimitError, } from './foreground-fallback';
6
7
  export { createJsonErrorRecoveryHook } from './json-error-recovery';
7
8
  export { createPhaseReminderHook } from './phase-reminder';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Plugin } from '@opencode-ai/plugin';
2
2
  declare const OhMyOpenCodeLite: Plugin;
3
3
  export default OhMyOpenCodeLite;
4
- export type { AgentName, AgentOverrideConfig, McpName, PluginConfig, TmuxConfig, TmuxLayout, } from './config';
4
+ export type { AgentName, AgentOverrideConfig, McpName, MultiplexerConfig, MultiplexerLayout, MultiplexerType, PluginConfig, TmuxConfig, TmuxLayout, } from './config';
5
5
  export type { RemoteMcpConfig } from './mcp';