oh-my-opencode-slim 2.0.5 → 2.1.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.
Files changed (67) hide show
  1. package/README.ja-JP.md +64 -38
  2. package/README.ko-KR.md +62 -36
  3. package/README.md +82 -47
  4. package/README.zh-CN.md +63 -39
  5. package/dist/agents/council.d.ts +1 -1
  6. package/dist/agents/index.d.ts +7 -2
  7. package/dist/agents/orchestrator.d.ts +1 -1
  8. package/dist/cli/custom-skills-registry.d.ts +18 -0
  9. package/dist/cli/custom-skills.d.ts +3 -19
  10. package/dist/cli/index.js +1130 -195
  11. package/dist/cli/providers.d.ts +12 -16
  12. package/dist/cli/skills.d.ts +2 -2
  13. package/dist/companion/manager.d.ts +10 -0
  14. package/dist/config/constants.d.ts +2 -1
  15. package/dist/config/council-schema.d.ts +37 -12
  16. package/dist/config/loader.d.ts +5 -2
  17. package/dist/config/schema.d.ts +17 -6
  18. package/dist/council/council-manager.d.ts +7 -3
  19. package/dist/hooks/auto-update-checker/skill-sync.d.ts +59 -1
  20. package/dist/hooks/filter-available-skills/index.d.ts +1 -2
  21. package/dist/hooks/foreground-fallback/index.d.ts +40 -2
  22. package/dist/hooks/image-hook.d.ts +1 -1
  23. package/dist/hooks/index.d.ts +2 -0
  24. package/dist/hooks/loop-command/index.d.ts +13 -0
  25. package/dist/hooks/phase-reminder/index.d.ts +4 -3
  26. package/dist/hooks/post-file-tool-nudge/index.d.ts +15 -9
  27. package/dist/hooks/session-lifecycle.d.ts +11 -0
  28. package/dist/hooks/task-session-manager/index.d.ts +15 -4
  29. package/dist/hooks/task-session-manager/pending-call-tracker.d.ts +13 -0
  30. package/dist/hooks/task-session-manager/task-context-tracker.d.ts +14 -0
  31. package/dist/hooks/types.d.ts +3 -1
  32. package/dist/index.js +2890 -986
  33. package/dist/interview/dashboard-manager.d.ts +21 -0
  34. package/dist/interview/manager.d.ts +0 -14
  35. package/dist/interview/service.d.ts +9 -0
  36. package/dist/interview/session-server.d.ts +21 -0
  37. package/dist/interview/types.d.ts +3 -1
  38. package/dist/loop/loop-session.d.ts +64 -0
  39. package/dist/multiplexer/factory.d.ts +5 -5
  40. package/dist/multiplexer/herdr/index.d.ts +33 -0
  41. package/dist/multiplexer/index.d.ts +1 -0
  42. package/dist/multiplexer/session-manager.d.ts +6 -5
  43. package/dist/multiplexer/shared.d.ts +24 -0
  44. package/dist/multiplexer/tmux/index.d.ts +0 -1
  45. package/dist/multiplexer/types.d.ts +4 -4
  46. package/dist/multiplexer/zellij/index.d.ts +0 -1
  47. package/dist/tools/cancel-task.d.ts +2 -2
  48. package/dist/tui.d.ts +1 -0
  49. package/dist/tui.js +123 -45
  50. package/dist/utils/background-job-board.d.ts +22 -2
  51. package/dist/utils/background-job-coordinator.d.ts +72 -0
  52. package/dist/utils/background-job-store.d.ts +46 -0
  53. package/dist/utils/councillor-models.d.ts +20 -0
  54. package/dist/utils/index.d.ts +2 -0
  55. package/dist/utils/internal-initiator.d.ts +6 -1
  56. package/dist/utils/session.d.ts +2 -2
  57. package/oh-my-opencode-slim.schema.json +18 -1
  58. package/package.json +1 -1
  59. package/src/skills/clonedeps/SKILL.md +2 -2
  60. package/src/skills/clonedeps/codemap.md +23 -32
  61. package/src/skills/codemap/SKILL.md +2 -2
  62. package/src/skills/codemap.md +63 -36
  63. package/src/skills/loop-engineering/SKILL.md +30 -0
  64. package/src/skills/oh-my-opencode-slim/SKILL.md +3 -3
  65. package/src/skills/reflect/SKILL.md +133 -0
  66. package/src/skills/release-smoke-test/SKILL.md +159 -0
  67. package/src/skills/simplify/SKILL.md +6 -6
@@ -0,0 +1,21 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { PluginConfig } from '../config';
3
+ export declare function createDashboardManager(ctx: PluginInput, config: PluginConfig, dashboardPort: number, outputFolder: string): {
4
+ registerCommand: (config: Record<string, unknown>) => void;
5
+ handleCommandExecuteBefore: (input: {
6
+ command: string;
7
+ sessionID: string;
8
+ arguments: string;
9
+ }, output: {
10
+ parts: Array<{
11
+ type: string;
12
+ text?: string;
13
+ }>;
14
+ }) => Promise<void>;
15
+ handleEvent: (input: {
16
+ event: {
17
+ type: string;
18
+ properties?: Record<string, unknown>;
19
+ };
20
+ }) => Promise<void>;
21
+ };
@@ -1,19 +1,5 @@
1
1
  import type { PluginInput } from '@opencode-ai/plugin';
2
2
  import type { PluginConfig } from '../config';
3
- /**
4
- * Interview Manager — Composition root.
5
- *
6
- * Two modes:
7
- *
8
- * 1. **Dashboard mode** (dashboard:true or port>0):
9
- * First process to bind the port becomes the dashboard (dumb aggregator).
10
- * Other processes register as sessions and push state to it.
11
- * Sessions drive LLM interaction locally, dashboard just serves the web UI.
12
- *
13
- * 2. **Per-session mode** (default, port=0, dashboard:false):
14
- * Upstream behavior. Each process runs its own interview server on a random
15
- * port. Lazy startup on first /interview command.
16
- */
17
3
  export declare function createInterviewManager(ctx: PluginInput, config: PluginConfig): {
18
4
  registerCommand: (config: Record<string, unknown>) => void;
19
5
  handleCommandExecuteBefore: (input: {
@@ -1,6 +1,13 @@
1
1
  import type { PluginInput } from '@opencode-ai/plugin';
2
2
  import type { InterviewConfig } from '../config';
3
3
  import type { InterviewAnswer, InterviewFileItem, InterviewListItem, InterviewRecord, InterviewState } from './types';
4
+ /**
5
+ * Cap on retained abandoned interview records. Abandoned interviews are kept
6
+ * briefly so a still-open browser tab can render their final state, but
7
+ * without a bound the `interviewsById` and `browserOpened` collections grow
8
+ * for the life of a long-running session/dashboard process.
9
+ */
10
+ export declare const MAX_RETAINED_ABANDONED = 50;
4
11
  export declare function createInterviewService(ctx: PluginInput, config?: InterviewConfig, deps?: {
5
12
  openBrowser?: (url: string) => void;
6
13
  env?: NodeJS.ProcessEnv;
@@ -18,6 +25,8 @@ export declare function createInterviewService(ctx: PluginInput, config?: Interv
18
25
  parts: Array<{
19
26
  type: string;
20
27
  text?: string;
28
+ synthetic?: boolean;
29
+ metadata?: Record<string, unknown>;
21
30
  }>;
22
31
  }) => Promise<void>;
23
32
  handleEvent: (input: {
@@ -0,0 +1,21 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { InterviewConfig } from '../config';
3
+ export declare function createPerSessionInterviewServer(ctx: PluginInput, interviewConfig: InterviewConfig | undefined, outputFolder: string): {
4
+ registerCommand: (config: Record<string, unknown>) => void;
5
+ handleCommandExecuteBefore: (input: {
6
+ command: string;
7
+ sessionID: string;
8
+ arguments: string;
9
+ }, output: {
10
+ parts: Array<{
11
+ type: string;
12
+ text?: string;
13
+ }>;
14
+ }) => Promise<void>;
15
+ handleEvent: (input: {
16
+ event: {
17
+ type: string;
18
+ properties?: Record<string, unknown>;
19
+ };
20
+ }) => Promise<void>;
21
+ };
@@ -14,7 +14,7 @@ export interface InterviewAssistantState {
14
14
  title?: string;
15
15
  questions: InterviewQuestion[];
16
16
  }
17
- /** Raw question object from LLM output loose, everything optional. */
17
+ /** Raw question object from LLM output - loose, everything optional. */
18
18
  export declare const RawQuestionSchema: z.ZodObject<{
19
19
  id: z.ZodOptional<z.ZodString>;
20
20
  question: z.ZodOptional<z.ZodString>;
@@ -33,6 +33,8 @@ export interface InterviewRecord {
33
33
  idea: string;
34
34
  markdownPath: string;
35
35
  createdAt: string;
36
+ abandonedAt?: string;
37
+ abandonedOrder?: number;
36
38
  status: 'active' | 'abandoned';
37
39
  baseMessageCount: number;
38
40
  }
@@ -0,0 +1,64 @@
1
+ export declare function loopDirname(loopID: string, goal: string): string;
2
+ export type LoopPhase = 'executing' | 'verifying' | 'done' | 'escalated' | 'cancelled';
3
+ export type ExecuteAgent = 'fixer' | 'designer' | 'explorer' | 'librarian';
4
+ export type VerifyAgent = 'oracle' | 'observer' | 'test';
5
+ export type SuccessCriterion = {
6
+ type: 'test';
7
+ command: string;
8
+ } | {
9
+ type: 'build';
10
+ command: string;
11
+ } | {
12
+ type: 'lint';
13
+ command: string;
14
+ } | {
15
+ type: 'fileExists';
16
+ path: string;
17
+ } | {
18
+ type: 'command';
19
+ command: string;
20
+ expectExitCode?: number;
21
+ } | {
22
+ type: 'oracle';
23
+ } | {
24
+ type: 'observer';
25
+ } | {
26
+ type: 'manual';
27
+ };
28
+ export interface LoopDefinition {
29
+ goal: string;
30
+ successCriteria: string;
31
+ success: SuccessCriterion;
32
+ maxAttempts: number;
33
+ executeAgent: ExecuteAgent;
34
+ verifyAgent: VerifyAgent;
35
+ contextFiles?: string[];
36
+ parentSessionID?: string;
37
+ }
38
+ export type VerificationResult = {
39
+ passed: true;
40
+ reason: string;
41
+ } | {
42
+ passed: false;
43
+ reason: string;
44
+ suggestedFix?: string;
45
+ };
46
+ export interface AttemptRecord {
47
+ attemptNumber: number;
48
+ executionResult: string;
49
+ verificationResult: VerificationResult;
50
+ artifactPaths?: string[];
51
+ }
52
+ export interface LoopSession {
53
+ loopID: string;
54
+ definition: LoopDefinition;
55
+ currentPhase: LoopPhase;
56
+ attempts: number;
57
+ activeJobID?: string;
58
+ history: AttemptRecord[];
59
+ historyDir: string;
60
+ manualReviewPending: boolean;
61
+ }
62
+ export declare function createLoopSession(definition: LoopDefinition, loopID: string): LoopSession;
63
+ export declare function compactAttempt(attempt: AttemptRecord): string;
64
+ export declare function writeHistoryFile(session: LoopSession): void;
@@ -6,9 +6,9 @@ import type { Multiplexer } from './types';
6
6
  /**
7
7
  * Create a multiplexer instance based on config.
8
8
  *
9
- * Do not cache instances: tmux/zellij integrations may depend on
10
- * per-process environment like TMUX_PANE/ZELLIJ, which should be captured
11
- * fresh for each plugin context.
9
+ * Do not cache instances: tmux/zellij/herdr integrations may depend on
10
+ * per-process environment like TMUX_PANE/ZELLIJ/HERDR_PANE_ID, which should
11
+ * be captured fresh for each plugin context.
12
12
  */
13
13
  export declare function getMultiplexer(config: MultiplexerConfig): Multiplexer | null;
14
14
  /**
@@ -17,9 +17,9 @@ export declare function getMultiplexer(config: MultiplexerConfig): Multiplexer |
17
17
  export declare function clearMultiplexerCache(): void;
18
18
  /**
19
19
  * Get the effective multiplexer type for auto mode
20
- * Returns the actual type that would be used (tmux/zellij/none)
20
+ * Returns the actual type that would be used (tmux/zellij/herdr/none)
21
21
  */
22
- export declare function getAutoMultiplexerType(): 'tmux' | 'zellij' | 'none';
22
+ export declare function getAutoMultiplexerType(): 'tmux' | 'zellij' | 'herdr' | 'none';
23
23
  /**
24
24
  * Start background availability check for a multiplexer
25
25
  */
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Herdr multiplexer implementation
3
+ *
4
+ * Splits panes for sub-agent sessions in Herdr.
5
+ *
6
+ * Herdr is an agent-aware terminal multiplexer (workspaces → tabs → panes).
7
+ * Pane IDs use the format `w<workspace>:p<pane>`. The CLI outputs
8
+ * newline-delimited JSON; `pane split` returns a `pane_info` result whose
9
+ * `pane.pane_id` field is the new pane's ID.
10
+ *
11
+ * Environment detection: Herdr injects `HERDR_ENV=1` and `HERDR_PANE_ID`
12
+ * into every pane it manages.
13
+ */
14
+ import type { MultiplexerLayout } from '../../config/schema';
15
+ import type { Multiplexer, PaneResult } from '../types';
16
+ export declare class HerdrMultiplexer implements Multiplexer {
17
+ readonly type: "herdr";
18
+ private binaryPath;
19
+ private hasChecked;
20
+ private readonly parentPaneId;
21
+ private layout;
22
+ private paneDirection;
23
+ private agentAreaPaneId;
24
+ constructor(layout?: MultiplexerLayout, mainPaneSize?: number);
25
+ isAvailable(): Promise<boolean>;
26
+ isInsideSession(): boolean;
27
+ spawnPane(sessionId: string, description: string, serverUrl: string, directory: string): Promise<PaneResult>;
28
+ closePane(paneId: string): Promise<boolean>;
29
+ applyLayout(layout: MultiplexerLayout, _mainPaneSize: number): Promise<void>;
30
+ private runSplit;
31
+ private targetPaneArg;
32
+ private getBinary;
33
+ }
@@ -2,6 +2,7 @@
2
2
  * Multiplexer module exports
3
3
  */
4
4
  export { clearMultiplexerCache, getMultiplexer, startAvailabilityCheck, } from './factory';
5
+ export { HerdrMultiplexer } from './herdr';
5
6
  export { MultiplexerSessionManager, TmuxSessionManager, } from './session-manager';
6
7
  export { TmuxMultiplexer } from './tmux';
7
8
  export type { Multiplexer, PaneResult } from './types';
@@ -1,6 +1,7 @@
1
1
  import type { PluginInput } from '@opencode-ai/plugin';
2
2
  import type { MultiplexerConfig } from '../config/schema';
3
- import type { BackgroundJobBoard } from '../utils/background-job-board';
3
+ import type { BackgroundJobStore } from '../utils/background-job-store';
4
+ type BackgroundJobReader = Pick<BackgroundJobStore, 'getState' | 'deferIfRunning' | 'clearDeferredClose'>;
4
5
  interface SessionEvent {
5
6
  type: string;
6
7
  properties?: {
@@ -33,10 +34,9 @@ export declare class MultiplexerSessionManager {
33
34
  private knownSessions;
34
35
  private spawningSessions;
35
36
  private closingSessions;
36
- private deferredIdleCloses;
37
37
  private pollInterval?;
38
38
  private enabled;
39
- constructor(ctx: PluginInput, config: MultiplexerConfig, backgroundJobBoard?: BackgroundJobBoard | undefined);
39
+ constructor(ctx: PluginInput, config: MultiplexerConfig, backgroundJobBoard?: BackgroundJobReader | undefined);
40
40
  onSessionCreated(event: SessionEvent): Promise<void>;
41
41
  onSessionStatus(event: SessionEvent): Promise<void>;
42
42
  onSessionDeleted(event: SessionEvent): Promise<void>;
@@ -49,8 +49,9 @@ export declare class MultiplexerSessionManager {
49
49
  private isTrackedOrSpawning;
50
50
  private updatePolling;
51
51
  private getSessionId;
52
- private isRunningBackgroundJob;
53
- retryDeferredIdleClose(sessionId: string): Promise<void>;
52
+ private backgroundJobState;
53
+ private shouldCloseNow;
54
+ closeSessionFromCoordinator(sessionId: string): Promise<void>;
54
55
  cleanup(): Promise<void>;
55
56
  }
56
57
  /**
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared multiplexer infrastructure
3
+ *
4
+ * Functions used across tmux, zellij, and herdr backend adapters.
5
+ * Extracted to eliminate copy-paste duplication and prevent drift.
6
+ */
7
+ export declare function quoteShellArg(value: string): string;
8
+ /** Normalize Windows backslashes to / so sh -lc (MSYS2/Git Bash) doesn't treat them as escape chars. */
9
+ export declare function normalizePathForShell(directory: string): string;
10
+ export declare function buildOpencodeAttachCommand(sessionId: string, serverUrl: string, directory: string): string;
11
+ export declare function findBinary(binaryName: string, options?: {
12
+ verify?: boolean;
13
+ }): Promise<string | null>;
14
+ export interface GracefulClosePaneOptions {
15
+ /** Backend-specific Ctrl+C command args (binary prepended by caller). */
16
+ ctrlC: string[];
17
+ /** Backend-specific close/kill command args (binary prepended by caller). */
18
+ close: string[];
19
+ /** Accept exit code 1 as success (zellij/herdr treat "already closed" as 1). */
20
+ acceptExitCode1?: boolean;
21
+ /** Return true for empty/unknown paneId instead of false (zellij/herdr behavior). */
22
+ emptyPaneReturnsTrue?: boolean;
23
+ }
24
+ export declare function gracefulClosePane(binary: string | null, paneId: string, options: GracefulClosePaneOptions): Promise<boolean>;
@@ -23,5 +23,4 @@ export declare class TmuxMultiplexer implements Multiplexer {
23
23
  private runTmux;
24
24
  private getBinary;
25
25
  private targetArgs;
26
- private findBinary;
27
26
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Multiplexer abstraction layer
3
3
  *
4
- * Provides a unified interface for terminal multiplexers (tmux, zellij, etc.)
5
- * to spawn and manage panes for child agent sessions.
4
+ * Provides a unified interface for terminal multiplexers (tmux, zellij,
5
+ * herdr, etc.) to spawn and manage panes for child agent sessions.
6
6
  */
7
7
  import type { MultiplexerConfig, MultiplexerLayout } from '../config/schema';
8
8
  export interface PaneResult {
@@ -11,10 +11,10 @@ export interface PaneResult {
11
11
  }
12
12
  /**
13
13
  * Core multiplexer interface
14
- * Implementations: TmuxMultiplexer, ZellijMultiplexer
14
+ * Implementations: TmuxMultiplexer, ZellijMultiplexer, HerdrMultiplexer
15
15
  */
16
16
  export interface Multiplexer {
17
- readonly type: 'tmux' | 'zellij';
17
+ readonly type: 'tmux' | 'zellij' | 'herdr';
18
18
  /**
19
19
  * Check if the multiplexer binary is available on the system
20
20
  */
@@ -44,5 +44,4 @@ export declare class ZellijMultiplexer implements Multiplexer {
44
44
  private getParentTabId;
45
45
  private findTabIdForPane;
46
46
  private getBinary;
47
- private findBinary;
48
47
  }
@@ -1,8 +1,8 @@
1
1
  import { type PluginInput, type ToolDefinition } from '@opencode-ai/plugin';
2
- import type { BackgroundJobBoard } from '../utils/background-job-board';
2
+ import type { BackgroundJobStore } from '../utils/background-job-store';
3
3
  interface CancelTaskToolOptions {
4
4
  client: PluginInput['client'];
5
- backgroundJobBoard: BackgroundJobBoard;
5
+ backgroundJobBoard: BackgroundJobStore;
6
6
  shouldManageSession: (sessionID: string) => boolean;
7
7
  abortTimeoutMs?: number;
8
8
  verifyAbortMs?: number;
package/dist/tui.d.ts CHANGED
@@ -6,6 +6,7 @@ export declare function splitSidebarModelId(model: string): {
6
6
  };
7
7
  export declare function getSidebarAgentNames(snapshot: TuiSnapshot): string[];
8
8
  export declare function readConfigInvalid(directory: string): boolean;
9
+ export declare function readCompactSidebar(directory: string): boolean;
9
10
  declare const plugin: TuiPluginModule & {
10
11
  id: string;
11
12
  };