oh-my-opencode-slim 0.8.6 → 0.9.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.
@@ -1,6 +1,8 @@
1
+ import type { WebsearchConfig } from '../config';
1
2
  import type { McpConfig } from './types';
2
3
  export type { LocalMcpConfig, McpConfig, RemoteMcpConfig } from './types';
3
4
  /**
4
- * Creates MCP configurations, excluding disabled ones
5
+ * Creates MCP configurations, excluding disabled ones.
6
+ * Accepts an optional websearchConfig to override the default Exa provider.
5
7
  */
6
- export declare function createBuiltinMcps(disabledMcps?: readonly string[]): Record<string, McpConfig>;
8
+ export declare function createBuiltinMcps(disabledMcps?: readonly string[], websearchConfig?: WebsearchConfig): Record<string, McpConfig>;
@@ -1,6 +1,9 @@
1
+ import type { WebsearchConfig } from '../config';
1
2
  import type { RemoteMcpConfig } from './types';
2
3
  /**
3
- * Exa AI web search - real-time web search
4
- * @see https://exa.ai
4
+ * Creates a websearch MCP config based on the provided configuration.
5
+ * Supports Exa (default) and Tavily providers.
6
+ * @see https://exa.ai @see https://tavily.com
5
7
  */
8
+ export declare function createWebsearchConfig(config?: WebsearchConfig): RemoteMcpConfig;
6
9
  export declare const websearch: RemoteMcpConfig;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Multiplexer factory - creates the appropriate multiplexer instance
3
+ */
4
+ import type { MultiplexerConfig } from '../config/schema';
5
+ import type { Multiplexer } from './types';
6
+ /**
7
+ * Create or retrieve a multiplexer instance based on config
8
+ */
9
+ export declare function getMultiplexer(config: MultiplexerConfig): Multiplexer | null;
10
+ /**
11
+ * Clear the multiplexer cache (useful for testing)
12
+ */
13
+ export declare function clearMultiplexerCache(): void;
14
+ /**
15
+ * Get the effective multiplexer type for auto mode
16
+ * Returns the actual type that would be used (tmux/zellij/none)
17
+ */
18
+ export declare function getAutoMultiplexerType(): 'tmux' | 'zellij' | 'none';
19
+ /**
20
+ * Start background availability check for a multiplexer
21
+ */
22
+ export declare function startAvailabilityCheck(config: MultiplexerConfig): void;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Multiplexer module exports
3
+ */
4
+ export { clearMultiplexerCache, getMultiplexer, startAvailabilityCheck, } from './factory';
5
+ export { TmuxMultiplexer } from './tmux';
6
+ export type { Multiplexer, PaneResult } from './types';
7
+ export { isServerRunning } from './types';
8
+ export { ZellijMultiplexer } from './zellij';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Tmux multiplexer implementation
3
+ */
4
+ import type { MultiplexerLayout } from '../../config/schema';
5
+ import type { Multiplexer, PaneResult } from '../types';
6
+ export declare class TmuxMultiplexer implements Multiplexer {
7
+ readonly type: "tmux";
8
+ private binaryPath;
9
+ private hasChecked;
10
+ private storedLayout;
11
+ private storedMainPaneSize;
12
+ constructor(layout?: MultiplexerLayout, mainPaneSize?: number);
13
+ isAvailable(): Promise<boolean>;
14
+ isInsideSession(): boolean;
15
+ spawnPane(sessionId: string, description: string, serverUrl: string): Promise<PaneResult>;
16
+ closePane(paneId: string): Promise<boolean>;
17
+ applyLayout(layout: MultiplexerLayout, mainPaneSize: number): Promise<void>;
18
+ private getBinary;
19
+ private findBinary;
20
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Multiplexer abstraction layer
3
+ *
4
+ * Provides a unified interface for terminal multiplexers (tmux, zellij, etc.)
5
+ * to spawn and manage panes for background task visualization.
6
+ */
7
+ import type { MultiplexerConfig, MultiplexerLayout } from '../config/schema';
8
+ export interface PaneResult {
9
+ success: boolean;
10
+ paneId?: string;
11
+ }
12
+ /**
13
+ * Core multiplexer interface
14
+ * Implementations: TmuxMultiplexer, ZellijMultiplexer
15
+ */
16
+ export interface Multiplexer {
17
+ readonly type: 'tmux' | 'zellij';
18
+ /**
19
+ * Check if the multiplexer binary is available on the system
20
+ */
21
+ isAvailable(): Promise<boolean>;
22
+ /**
23
+ * Check if currently running inside a multiplexer session
24
+ */
25
+ isInsideSession(): boolean;
26
+ /**
27
+ * Spawn a new pane running the given command
28
+ * @param sessionId - The OpenCode session ID to attach to
29
+ * @param description - Human-readable description for the pane
30
+ * @param serverUrl - The OpenCode server URL to attach to
31
+ * @returns PaneResult with pane ID for later cleanup
32
+ */
33
+ spawnPane(sessionId: string, description: string, serverUrl: string): Promise<PaneResult>;
34
+ /**
35
+ * Close a pane by its ID
36
+ * @param paneId - The pane ID returned by spawnPane
37
+ * @returns true if successfully closed
38
+ */
39
+ closePane(paneId: string): Promise<boolean>;
40
+ /**
41
+ * Apply layout to rebalance panes
42
+ * @param layout - The layout type to apply
43
+ * @param mainPaneSize - Percentage for main pane (for main-* layouts)
44
+ */
45
+ applyLayout(layout: MultiplexerLayout, mainPaneSize: number): Promise<void>;
46
+ }
47
+ /**
48
+ * Factory function type for creating multiplexer instances
49
+ */
50
+ export type MultiplexerFactory = (config: MultiplexerConfig) => Multiplexer;
51
+ /**
52
+ * Server health check utility (shared across implementations)
53
+ */
54
+ export declare function isServerRunning(serverUrl: string, timeoutMs?: number, maxAttempts?: number): Promise<boolean>;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Zellij multiplexer implementation
3
+ *
4
+ * Creates a dedicated "opencode-agents" tab for all sub-agent panes.
5
+ * - First sub-agent uses the default pane from new-tab
6
+ * - Subsequent sub-agents create new panes
7
+ * - User stays in their original tab
8
+ */
9
+ import type { MultiplexerLayout } from '../../config/schema';
10
+ import type { Multiplexer, PaneResult } from '../types';
11
+ export declare class ZellijMultiplexer implements Multiplexer {
12
+ readonly type: "zellij";
13
+ private binaryPath;
14
+ private hasChecked;
15
+ private storedLayout;
16
+ private storedMainPaneSize;
17
+ private agentTabId;
18
+ private firstPaneId;
19
+ private firstPaneUsed;
20
+ constructor(layout?: MultiplexerLayout, mainPaneSize?: number);
21
+ isAvailable(): Promise<boolean>;
22
+ isInsideSession(): boolean;
23
+ spawnPane(sessionId: string, description: string, serverUrl: string): Promise<PaneResult>;
24
+ private createPaneInAgentTab;
25
+ private runInPane;
26
+ private ensureAgentTab;
27
+ private getFirstPaneInTab;
28
+ private findTabByName;
29
+ private findTabByNameText;
30
+ private getCurrentTabId;
31
+ private listPanes;
32
+ closePane(paneId: string): Promise<boolean>;
33
+ applyLayout(_layout: MultiplexerLayout, _mainPaneSize: number): Promise<void>;
34
+ private getBinary;
35
+ private findBinary;
36
+ }
@@ -1,13 +1,13 @@
1
1
  import { type PluginInput, type ToolDefinition } from '@opencode-ai/plugin';
2
2
  import type { BackgroundTaskManager } from '../background';
3
3
  import type { PluginConfig } from '../config';
4
- import type { TmuxConfig } from '../config/schema';
4
+ import type { MultiplexerConfig } from '../config/schema';
5
5
  /**
6
6
  * Creates background task management tools for the plugin.
7
7
  * @param _ctx - Plugin input context
8
8
  * @param manager - Background task manager for launching and tracking tasks
9
- * @param _tmuxConfig - Optional tmux configuration for session management
9
+ * @param _multiplexerConfig - Optional multiplexer configuration for session management
10
10
  * @param _pluginConfig - Optional plugin configuration for agent variants
11
11
  * @returns Object containing background_task, background_output, and background_cancel tools
12
12
  */
13
- export declare function createBackgroundTools(_ctx: PluginInput, manager: BackgroundTaskManager, _tmuxConfig?: TmuxConfig, _pluginConfig?: PluginConfig): Record<string, ToolDefinition>;
13
+ export declare function createBackgroundTools(_ctx: PluginInput, manager: BackgroundTaskManager, _multiplexerConfig?: MultiplexerConfig, _pluginConfig?: PluginConfig): Record<string, ToolDefinition>;
@@ -1,4 +1,34 @@
1
1
  import type { Diagnostic, ResolvedServer } from './types';
2
+ export declare const LSP_TIMEOUTS: {
3
+ start: number;
4
+ request: number;
5
+ openFileDelay: number;
6
+ initializeDelay: number;
7
+ diagnosticSettleDelay: number;
8
+ };
9
+ interface DiagnosticProviderCapabilities {
10
+ identifier?: string;
11
+ interFileDependencies?: boolean;
12
+ workspaceDiagnostics?: boolean;
13
+ }
14
+ export declare function getDiagnosticsCapabilitySummary({ diagnosticProvider, publishDiagnosticsObserved, workspaceConfigurationRequested, }: {
15
+ diagnosticProvider?: DiagnosticProviderCapabilities | null;
16
+ publishDiagnosticsObserved?: boolean;
17
+ workspaceConfigurationRequested?: boolean;
18
+ }): {
19
+ availableModes: string[];
20
+ preferredMode: 'push' | 'pull';
21
+ inferredTransport: 'push' | 'pull' | 'hybrid';
22
+ pull: boolean;
23
+ pushObserved: boolean;
24
+ pullResultTracking: boolean;
25
+ workspaceDiagnostics: boolean;
26
+ interFileDependencies: boolean;
27
+ workspaceConfiguration: boolean;
28
+ };
29
+ export declare function getWorkspaceConfiguration(items: Array<{
30
+ section?: string;
31
+ } | undefined>): Array<unknown>;
2
32
  declare class LSPServerManager {
3
33
  private static instance;
4
34
  private clients;
@@ -25,11 +55,19 @@ export declare class LSPClient {
25
55
  private stderrBuffer;
26
56
  private processExited;
27
57
  private diagnosticsStore;
58
+ private diagnosticResultIds;
59
+ private documents;
60
+ private diagnosticProvider;
61
+ private publishDiagnosticsObserved;
62
+ private supportsPullDiagnostics;
63
+ private workspaceConfigurationRequested;
28
64
  constructor(root: string, server: ResolvedServer);
29
65
  start(): Promise<void>;
30
66
  private startStderrReading;
31
67
  initialize(): Promise<void>;
68
+ private waitForPublishedDiagnostics;
32
69
  openFile(filePath: string): Promise<void>;
70
+ private ensureDocumentSynced;
33
71
  definition(filePath: string, line: number, character: number): Promise<unknown>;
34
72
  references(filePath: string, line: number, character: number, includeDeclaration?: boolean): Promise<unknown>;
35
73
  diagnostics(filePath: string): Promise<{
@@ -1,4 +1,5 @@
1
1
  import type { ServerLookupResult } from './types';
2
- export declare function findServerForExtension(ext: string): ServerLookupResult;
2
+ export declare function findServerForExtension(ext: string, filePath?: string): ServerLookupResult;
3
3
  export declare function getLanguageId(ext: string): string;
4
+ export declare function resolveServerCommand(command: string[], cwd?: string): string[] | null;
4
5
  export declare function isServerInstalled(command: string[]): boolean;
@@ -33,3 +33,13 @@ export type ServerLookupResult = {
33
33
  installHint: string;
34
34
  };
35
35
  export type { Position, Range, Location, LocationLink, Diagnostic, TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextEdit, TextDocumentEdit, CreateFile, RenameFile, DeleteFile, WorkspaceEdit, SymbolInfo, DocumentSymbol, };
36
+ export interface DocumentDiagnosticReportFull {
37
+ kind: 'full';
38
+ items: Diagnostic[];
39
+ resultId?: string;
40
+ }
41
+ export interface DocumentDiagnosticReportUnchanged {
42
+ kind: 'unchanged';
43
+ resultId?: string;
44
+ }
45
+ export type DocumentDiagnosticReport = DocumentDiagnosticReportFull | DocumentDiagnosticReportUnchanged;
@@ -4,5 +4,4 @@ export * from './internal-initiator';
4
4
  export { log } from './logger';
5
5
  export * from './polling';
6
6
  export * from './session';
7
- export * from './tmux';
8
7
  export { extractZip } from './zip-extractor';
@@ -44,6 +44,15 @@ export declare function parseModelReference(model: string): {
44
44
  * @throws Error if timeout is exceeded
45
45
  */
46
46
  export declare function promptWithTimeout(client: OpencodeClient, args: Parameters<OpencodeClient['session']['prompt']>[0], timeoutMs: number): Promise<void>;
47
+ /**
48
+ * Result of extracting session content.
49
+ * `empty` is true when the assistant produced zero text content —
50
+ * the provider returned an empty response (e.g. rate-limited silently).
51
+ */
52
+ export interface SessionExtractionResult {
53
+ text: string;
54
+ empty: boolean;
55
+ }
47
56
  /**
48
57
  * Extract the result text from a session.
49
58
  * Collects all assistant messages and concatenates their text parts.
@@ -51,9 +60,9 @@ export declare function promptWithTimeout(client: OpencodeClient, args: Paramete
51
60
  * @param sessionId - Session ID to extract from
52
61
  * @param options - Optional: `includeReasoning` (default true) controls whether
53
62
  * reasoning/chain-of-thought parts are included.
54
- * @returns Concatenated text from all assistant messages
63
+ * @returns Object with extracted text and an `empty` flag for zero-content detection
55
64
  */
56
65
  export declare function extractSessionResult(client: OpencodeClient, sessionId: string, options?: {
57
66
  includeReasoning?: boolean;
58
- }): Promise<string>;
67
+ }): Promise<SessionExtractionResult>;
59
68
  export {};
@@ -331,6 +331,38 @@
331
331
  "type": "string"
332
332
  }
333
333
  },
334
+ "multiplexer": {
335
+ "type": "object",
336
+ "properties": {
337
+ "type": {
338
+ "default": "none",
339
+ "type": "string",
340
+ "enum": [
341
+ "auto",
342
+ "tmux",
343
+ "zellij",
344
+ "none"
345
+ ]
346
+ },
347
+ "layout": {
348
+ "default": "main-vertical",
349
+ "type": "string",
350
+ "enum": [
351
+ "main-horizontal",
352
+ "main-vertical",
353
+ "tiled",
354
+ "even-horizontal",
355
+ "even-vertical"
356
+ ]
357
+ },
358
+ "main_pane_size": {
359
+ "default": 60,
360
+ "type": "number",
361
+ "minimum": 20,
362
+ "maximum": 80
363
+ }
364
+ }
365
+ },
334
366
  "tmux": {
335
367
  "type": "object",
336
368
  "properties": {
@@ -357,6 +389,19 @@
357
389
  }
358
390
  }
359
391
  },
392
+ "websearch": {
393
+ "type": "object",
394
+ "properties": {
395
+ "provider": {
396
+ "default": "exa",
397
+ "type": "string",
398
+ "enum": [
399
+ "exa",
400
+ "tavily"
401
+ ]
402
+ }
403
+ }
404
+ },
360
405
  "background": {
361
406
  "type": "object",
362
407
  "properties": {
@@ -439,6 +484,11 @@
439
484
  "type": "string"
440
485
  }
441
486
  }
487
+ },
488
+ "retry_on_empty": {
489
+ "default": true,
490
+ "description": "When true (default), empty provider responses are treated as failures, triggering fallback/retry. Set to false to treat them as successes.",
491
+ "type": "boolean"
442
492
  }
443
493
  }
444
494
  },
@@ -505,6 +555,22 @@
505
555
  "type": "string",
506
556
  "pattern": "^[^/\\s]+\\/[^\\s]+$"
507
557
  }
558
+ },
559
+ "councillor_execution_mode": {
560
+ "default": "parallel",
561
+ "description": "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).",
562
+ "type": "string",
563
+ "enum": [
564
+ "parallel",
565
+ "serial"
566
+ ]
567
+ },
568
+ "councillor_retries": {
569
+ "default": 3,
570
+ "description": "Number of retry attempts for councillors and master that return empty responses (e.g. due to provider rate limiting). Default: 3 retries.",
571
+ "type": "integer",
572
+ "minimum": 0,
573
+ "maximum": 5
508
574
  }
509
575
  },
510
576
  "required": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-slim",
3
- "version": "0.8.6",
3
+ "version": "0.9.1",
4
4
  "description": "Lightweight agent orchestration plugin for OpenCode - a slimmed-down fork of oh-my-opencode",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,6 +37,9 @@
37
37
  ],
38
38
  "scripts": {
39
39
  "build": "bun build src/index.ts --outdir dist --target bun --format esm && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm && tsc --emitDeclarationOnly && bun run generate-schema",
40
+ "contributors:add": "all-contributors add",
41
+ "contributors:check": "all-contributors check",
42
+ "contributors:generate": "all-contributors generate",
40
43
  "generate-schema": "bun run scripts/generate-schema.ts",
41
44
  "typecheck": "tsc --noEmit",
42
45
  "test": "bun test",
@@ -63,6 +66,7 @@
63
66
  "devDependencies": {
64
67
  "@biomejs/biome": "2.4.2",
65
68
  "@types/which": "^3.0.4",
69
+ "all-contributors-cli": "^6.26.1",
66
70
  "bun-types": "1.3.9",
67
71
  "typescript": "^5.9.3"
68
72
  },