oh-my-opencode-slim 2.0.0-beta.9 → 2.0.0

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 (49) hide show
  1. package/README.ja-JP.md +86 -32
  2. package/README.ko-KR.md +690 -0
  3. package/README.md +118 -45
  4. package/README.zh-CN.md +97 -37
  5. package/dist/cli/background-subagents.d.ts +13 -0
  6. package/dist/cli/companion.d.ts +4 -0
  7. package/dist/cli/index.d.ts +2 -1
  8. package/dist/cli/index.js +626 -82
  9. package/dist/cli/install.d.ts +6 -1
  10. package/dist/cli/providers.d.ts +2 -1
  11. package/dist/cli/types.d.ts +8 -0
  12. package/dist/companion/manager.d.ts +38 -0
  13. package/dist/config/constants.d.ts +4 -1
  14. package/dist/config/fallback-chains.d.ts +1 -0
  15. package/dist/config/schema.d.ts +46 -40
  16. package/dist/hooks/auto-update-checker/checker.d.ts +7 -1
  17. package/dist/hooks/auto-update-checker/constants.d.ts +1 -0
  18. package/dist/hooks/auto-update-checker/types.d.ts +10 -0
  19. package/dist/hooks/index.d.ts +0 -2
  20. package/dist/hooks/json-error-recovery/hook.d.ts +1 -1
  21. package/dist/hooks/phase-reminder/index.d.ts +1 -1
  22. package/dist/index.js +1861 -2149
  23. package/dist/mcp/grep-app.d.ts +1 -1
  24. package/dist/multiplexer/zellij/index.d.ts +17 -3
  25. package/dist/tools/cancel-task.d.ts +6 -0
  26. package/dist/tools/preset-manager.d.ts +6 -7
  27. package/dist/tui.js +56 -31
  28. package/dist/utils/background-job-board.d.ts +39 -1
  29. package/dist/utils/index.d.ts +0 -1
  30. package/dist/utils/task.d.ts +2 -0
  31. package/oh-my-opencode-slim.schema.json +34 -91
  32. package/package.json +4 -3
  33. package/src/skills/codemap.md +3 -1
  34. package/src/skills/deepwork/SKILL.md +25 -3
  35. package/src/skills/oh-my-opencode-slim/SKILL.md +326 -0
  36. package/dist/divoom/council.gif +0 -0
  37. package/dist/divoom/designer.gif +0 -0
  38. package/dist/divoom/explorer.gif +0 -0
  39. package/dist/divoom/fixer.gif +0 -0
  40. package/dist/divoom/input.gif +0 -0
  41. package/dist/divoom/intro.gif +0 -0
  42. package/dist/divoom/librarian.gif +0 -0
  43. package/dist/divoom/manager.d.ts +0 -57
  44. package/dist/divoom/oracle.gif +0 -0
  45. package/dist/divoom/orchestrator.gif +0 -0
  46. package/dist/hooks/goal/index.d.ts +0 -38
  47. package/dist/hooks/todo-continuation/index.d.ts +0 -55
  48. package/dist/hooks/todo-continuation/todo-hygiene.d.ts +0 -35
  49. package/dist/utils/session-manager.d.ts +0 -55
@@ -3,4 +3,4 @@ import type { RemoteMcpConfig } from './types';
3
3
  * grep.app - ultra-fast code search across GitHub repositories
4
4
  * @see https://grep.app
5
5
  */
6
- export declare const grep_app: RemoteMcpConfig;
6
+ export declare const gh_grep: RemoteMcpConfig;
@@ -1,24 +1,34 @@
1
1
  /**
2
2
  * Zellij multiplexer implementation
3
3
  *
4
- * Creates a dedicated "opencode-agents" tab for all sub-agent panes.
4
+ * Creates panes for sub-agent sessions in Zellij.
5
+ *
6
+ * The default mode creates a dedicated "opencode-agents" tab:
5
7
  * - First sub-agent uses the default pane from new-tab
6
8
  * - Subsequent sub-agents create new panes
7
9
  * - User stays in their original tab
10
+ *
11
+ * The optional "current-tab" mode creates panes in the tab containing the
12
+ * parent OpenCode pane instead.
8
13
  */
9
- import type { MultiplexerLayout } from '../../config/schema';
14
+ import type { MultiplexerLayout, ZellijPaneMode } from '../../config/schema';
10
15
  import type { Multiplexer, PaneResult } from '../types';
11
16
  export declare class ZellijMultiplexer implements Multiplexer {
17
+ private readonly paneMode;
12
18
  readonly type: "zellij";
13
19
  private binaryPath;
14
20
  private hasChecked;
15
21
  private agentTabId;
16
22
  private firstPaneId;
17
23
  private firstPaneUsed;
18
- constructor(layout?: MultiplexerLayout, mainPaneSize?: number);
24
+ private parentTabId;
25
+ private readonly parentPaneId;
26
+ private readonly paneDirection;
27
+ constructor(layout?: MultiplexerLayout, mainPaneSize?: number, paneMode?: ZellijPaneMode);
19
28
  isAvailable(): Promise<boolean>;
20
29
  isInsideSession(): boolean;
21
30
  spawnPane(sessionId: string, description: string, serverUrl: string, directory: string): Promise<PaneResult>;
31
+ private createPaneInCurrentTab;
22
32
  private createPaneInAgentTab;
23
33
  private runInPane;
24
34
  private ensureAgentTab;
@@ -29,6 +39,10 @@ export declare class ZellijMultiplexer implements Multiplexer {
29
39
  private listPanes;
30
40
  closePane(paneId: string): Promise<boolean>;
31
41
  applyLayout(_layout: MultiplexerLayout, _mainPaneSize: number): Promise<void>;
42
+ private directionArgs;
43
+ private tabIdArgs;
44
+ private getParentTabId;
45
+ private findTabIdForPane;
32
46
  private getBinary;
33
47
  private findBinary;
34
48
  }
@@ -5,6 +5,12 @@ interface CancelTaskToolOptions {
5
5
  backgroundJobBoard: BackgroundJobBoard;
6
6
  shouldManageSession: (sessionID: string) => boolean;
7
7
  abortTimeoutMs?: number;
8
+ verifyAbortMs?: number;
9
+ abortRetryIntervalMs?: number;
10
+ stableStoppedMs?: number;
11
+ deleteTimeoutMs?: number;
12
+ deleteVerifyMs?: number;
13
+ deleteStableStoppedMs?: number;
8
14
  }
9
15
  export declare function createCancelTaskTool(options: CancelTaskToolOptions): Record<string, ToolDefinition>;
10
16
  export {};
@@ -3,13 +3,12 @@ import type { PluginConfig } from '../config';
3
3
  /**
4
4
  * Creates a preset manager for the /preset slash command.
5
5
  *
6
- * Uses the OpenCode SDK's client.config.update() to change agent models
7
- * and temperatures without restarting. The server invalidates its agent
8
- * cache and re-reads config on the next prompt.
9
- *
10
- * Note: activePreset is tracked in-memory only and resets on plugin reload.
11
- * If the user manually edits config or another mechanism changes agents,
12
- * this tracker may become stale until the next /preset call.
6
+ * Stores the requested runtime preset in plugin memory and updates the
7
+ * plugin-facing TUI snapshot. It deliberately does not call OpenCode's
8
+ * client.config.update() or instance.dispose() from command hooks because
9
+ * OpenCode continues the same command into the prompt loop after
10
+ * command.execute.before, which can break the active conversation while
11
+ * the agent registry is changing.
13
12
  */
14
13
  export declare function createPresetManager(ctx: PluginInput, config: PluginConfig): {
15
14
  handleCommandExecuteBefore: (input: {
package/dist/tui.js CHANGED
@@ -68,7 +68,22 @@ var POLL_INTERVAL_BACKGROUND_MS = 2000;
68
68
  var DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
69
69
  var MAX_POLL_TIME_MS = 5 * 60 * 1000;
70
70
  var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
71
- var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion or use task_status only when needed → reconcile terminal results → verify. Do not consume running-job output or advance dependent work. !END!`;
71
+ var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
72
+ var WRITABLE_FILE_OPERATIONS_RULES = `**File Operations Rules**:
73
+ - Prefer dedicated file tools for normal code work: glob/grep/ast_grep_search for discovery, read for file contents, and edit/write/apply_patch for targeted source changes.
74
+ - Use bash for execution and automation: git, package managers, tests, builds, scripts, diagnostics, and shell-native filesystem operations.
75
+ - Shell is acceptable for bulk or mechanical filesystem changes when it is clearer or safer than many individual edits (for example: truncate generated logs, remove build artifacts, batch rename/move files), especially when the user explicitly asks for that shell operation.
76
+ - Before destructive or broad shell operations, verify the target set and quote paths. Prefer a dry-run/listing first when practical.
77
+ - Do not use cat/head/tail/sed/awk only to read code into context; use read/grep unless a shell pipeline is genuinely the better diagnostic.`;
78
+ var READONLY_FILE_OPERATIONS_RULES = `**File Operations Rules**:
79
+ - READ-ONLY: inspect and report; do not modify files.
80
+ - Prefer dedicated file tools for codebase inspection: glob/grep/ast_grep_search for discovery and read for file contents.
81
+ - Bash is allowed for non-mutating diagnostics and shell-native inspection when it is the clearest tool, but not for modifying files.
82
+ - Do not use cat/head/tail/sed/awk only to read code into context; use read/grep unless a shell pipeline is genuinely the better diagnostic.`;
83
+ var NO_SHELL_READONLY_FILE_OPERATIONS_RULES = `**File Operations Rules**:
84
+ - READ-ONLY: inspect and report; do not modify files.
85
+ - Use glob/grep/ast_grep_search for discovery and read for file contents.
86
+ - Do not use bash or shell commands.`;
72
87
  var TMUX_SPAWN_DELAY_MS = 500;
73
88
  var COUNCILLOR_STAGGER_MS = 250;
74
89
  var DEFAULT_DISABLED_AGENTS = ["observer"];
@@ -138,6 +153,13 @@ function getCustomOpenCodeConfigDir() {
138
153
  const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
139
154
  return configDir || undefined;
140
155
  }
156
+ function getConfigDir() {
157
+ const customConfigDir = getCustomOpenCodeConfigDir();
158
+ if (customConfigDir) {
159
+ return customConfigDir;
160
+ }
161
+ return getDefaultOpenCodeConfigDir();
162
+ }
141
163
  function getConfigSearchDirs() {
142
164
  const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
143
165
  return dirs.filter((dir, index) => {
@@ -145,7 +167,7 @@ function getConfigSearchDirs() {
145
167
  });
146
168
  }
147
169
  function getOpenCodeConfigPaths() {
148
- const configDir = getDefaultOpenCodeConfigDir();
170
+ const configDir = getConfigDir();
149
171
  return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
150
172
  }
151
173
  // src/config/council-schema.ts
@@ -283,11 +305,13 @@ var MultiplexerLayoutSchema = z2.enum([
283
305
  "even-horizontal",
284
306
  "even-vertical"
285
307
  ]);
308
+ var ZellijPaneModeSchema = z2.enum(["agent-tab", "current-tab"]);
286
309
  var TmuxLayoutSchema = MultiplexerLayoutSchema;
287
310
  var MultiplexerConfigSchema = z2.object({
288
311
  type: MultiplexerTypeSchema.default("none"),
289
312
  layout: MultiplexerLayoutSchema.default("main-vertical"),
290
- main_pane_size: z2.number().min(20).max(80).default(60)
313
+ main_pane_size: z2.number().min(20).max(80).default(60),
314
+ zellij_pane_mode: ZellijPaneModeSchema.default("agent-tab")
291
315
  });
292
316
  var TmuxConfigSchema = z2.object({
293
317
  enabled: z2.boolean().default(false),
@@ -298,7 +322,7 @@ var PresetSchema = z2.record(z2.string(), AgentOverrideConfigSchema);
298
322
  var WebsearchConfigSchema = z2.object({
299
323
  provider: z2.enum(["exa", "tavily"]).default("exa")
300
324
  });
301
- var McpNameSchema = z2.enum(["websearch", "context7", "grep_app"]);
325
+ var McpNameSchema = z2.enum(["websearch", "context7", "gh_grep"]);
302
326
  var InterviewConfigSchema = z2.object({
303
327
  maxQuestions: z2.number().int().min(1).max(10).default(2),
304
328
  outputFolder: z2.string().min(1).default("interview"),
@@ -306,28 +330,11 @@ var InterviewConfigSchema = z2.object({
306
330
  port: z2.number().int().min(0).max(65535).default(0),
307
331
  dashboard: z2.boolean().default(false)
308
332
  });
309
- var SessionManagerConfigSchema = z2.object({
333
+ var BackgroundJobsConfigSchema = z2.object({
310
334
  maxSessionsPerAgent: z2.number().int().min(1).max(10).default(2),
311
335
  readContextMinLines: z2.number().int().min(0).max(1000).default(10),
312
336
  readContextMaxFiles: z2.number().int().min(0).max(50).default(8)
313
337
  });
314
- var DivoomConfigSchema = z2.object({
315
- enabled: z2.boolean().default(false),
316
- python: z2.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/.venv/bin/python"),
317
- script: z2.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/tools/divoom_send.py"),
318
- size: z2.number().int().min(1).max(1024).default(128),
319
- fps: z2.number().int().min(1).max(60).default(8),
320
- speed: z2.number().int().min(1).max(1e4).default(125),
321
- maxFrames: z2.number().int().min(1).max(500).default(24),
322
- posterizeBits: z2.number().int().min(1).max(8).default(3),
323
- gifs: z2.record(z2.string(), z2.string().min(1)).optional()
324
- });
325
- var TodoContinuationConfigSchema = z2.object({
326
- maxContinuations: z2.number().int().min(1).max(50).default(5).describe("Maximum consecutive auto-continuations before stopping to ask user"),
327
- cooldownMs: z2.number().int().min(0).max(30000).default(3000).describe("Delay in ms before auto-continuing (gives user time to abort)"),
328
- autoEnable: z2.boolean().default(false).describe("Automatically enable auto-continue when the orchestrator session has enough todos"),
329
- autoEnableThreshold: z2.number().int().min(1).max(50).default(4).describe("Number of todos that triggers auto-enable (only used when autoEnable is true)")
330
- });
331
338
  var FailoverConfigSchema = z2.object({
332
339
  enabled: z2.boolean().default(true),
333
340
  timeoutMs: z2.number().min(0).default(15000),
@@ -335,6 +342,11 @@ var FailoverConfigSchema = z2.object({
335
342
  chains: FallbackChainsSchema.default({}),
336
343
  retry_on_empty: z2.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.")
337
344
  });
345
+ var CompanionConfigSchema = z2.object({
346
+ enabled: z2.boolean().optional(),
347
+ position: z2.enum(["bottom-right", "bottom-left", "top-right", "top-left"]).optional(),
348
+ size: z2.enum(["small", "medium", "large"]).optional()
349
+ });
338
350
  function validateCustomOnlyPromptFields(overrides, ctx, pathPrefix) {
339
351
  for (const [name, override] of Object.entries(overrides)) {
340
352
  const isBuiltInOrAlias = ALL_AGENT_NAMES.includes(name) || AGENT_ALIASES[name] !== undefined;
@@ -372,11 +384,10 @@ var PluginConfigSchema = z2.object({
372
384
  tmux: TmuxConfigSchema.optional(),
373
385
  websearch: WebsearchConfigSchema.optional(),
374
386
  interview: InterviewConfigSchema.optional(),
375
- sessionManager: SessionManagerConfigSchema.optional(),
376
- divoom: DivoomConfigSchema.optional(),
377
- todoContinuation: TodoContinuationConfigSchema.optional(),
387
+ backgroundJobs: BackgroundJobsConfigSchema.optional(),
378
388
  fallback: FailoverConfigSchema.optional(),
379
- council: CouncilConfigSchema.optional()
389
+ council: CouncilConfigSchema.optional(),
390
+ companion: CompanionConfigSchema.optional()
380
391
  }).superRefine((value, ctx) => {
381
392
  if (value.agents) {
382
393
  validateCustomOnlyPromptFields(value.agents, ctx, ["agents"]);
@@ -406,7 +417,7 @@ var DEFAULT_AGENT_MCPS = {
406
417
  orchestrator: ["*", "!context7"],
407
418
  designer: [],
408
419
  oracle: [],
409
- librarian: ["websearch", "context7", "grep_app"],
420
+ librarian: ["websearch", "context7", "gh_grep"],
410
421
  explorer: [],
411
422
  fixer: [],
412
423
  observer: [],
@@ -461,6 +472,12 @@ var CUSTOM_SKILLS = [
461
472
  description: "Heavy/complex coding sessions and large modifications workflow",
462
473
  allowedAgents: ["orchestrator"],
463
474
  sourcePath: "src/skills/deepwork"
475
+ },
476
+ {
477
+ name: "oh-my-opencode-slim",
478
+ description: "Configure, customize, and safely improve oh-my-opencode-slim setups",
479
+ allowedAgents: ["orchestrator"],
480
+ sourcePath: "src/skills/oh-my-opencode-slim"
464
481
  }
465
482
  ];
466
483
 
@@ -556,10 +573,10 @@ function mergePluginConfigs(base, override) {
556
573
  tmux: deepMerge(base.tmux, override.tmux),
557
574
  multiplexer: deepMerge(base.multiplexer, override.multiplexer),
558
575
  interview: deepMerge(base.interview, override.interview),
559
- sessionManager: deepMerge(base.sessionManager, override.sessionManager),
560
- divoom: deepMerge(base.divoom, override.divoom),
576
+ backgroundJobs: deepMerge(base.backgroundJobs, override.backgroundJobs),
561
577
  fallback: deepMerge(base.fallback, override.fallback),
562
- council: deepMerge(base.council, override.council)
578
+ council: deepMerge(base.council, override.council),
579
+ companion: deepMerge(base.companion, override.companion)
563
580
  };
564
581
  }
565
582
  function deepMerge(base, override) {
@@ -609,6 +626,13 @@ function loadPluginConfig(directory, options) {
609
626
  }
610
627
  }
611
628
  }
629
+ if (config.companion) {
630
+ config.companion = {
631
+ enabled: config.companion.enabled ?? false,
632
+ position: config.companion.position ?? "bottom-right",
633
+ size: config.companion.size ?? "medium"
634
+ };
635
+ }
612
636
  return config;
613
637
  }
614
638
  function loadAgentPrompt(agentName, preset) {
@@ -646,7 +670,8 @@ function migrateTmuxToMultiplexer(config) {
646
670
  multiplexer: {
647
671
  type: "tmux",
648
672
  layout: config.tmux.layout ?? "main-vertical",
649
- main_pane_size: config.tmux.main_pane_size ?? 60
673
+ main_pane_size: config.tmux.main_pane_size ?? 60,
674
+ zellij_pane_mode: "agent-tab"
650
675
  }
651
676
  };
652
677
  }
@@ -1,4 +1,10 @@
1
1
  import { type TaskOutputState } from './task';
2
+ export interface ContextFile {
3
+ path: string;
4
+ lineCount: number;
5
+ lineNumbers?: number[];
6
+ lastReadAt: number;
7
+ }
2
8
  export type BackgroundJobState = TaskOutputState | 'reconciled';
3
9
  export interface BackgroundJobRecord {
4
10
  taskID: string;
@@ -8,13 +14,25 @@ export interface BackgroundJobRecord {
8
14
  objective?: string;
9
15
  state: BackgroundJobState;
10
16
  timedOut: boolean;
17
+ statusUncertain: boolean;
18
+ cancellationRequested: boolean;
11
19
  terminalUnreconciled: boolean;
12
20
  launchedAt: number;
13
21
  lastLaunchedAt: number;
14
22
  updatedAt: number;
23
+ lastLiveBusyAt?: number;
15
24
  completedAt?: number;
16
25
  resultSummary?: string;
26
+ lastStatusError?: string;
17
27
  alias: string;
28
+ lastUsedAt: number;
29
+ terminalState?: TaskOutputState;
30
+ contextFiles: ContextFile[];
31
+ }
32
+ export interface BackgroundJobBoardOptions {
33
+ maxReusablePerAgent?: number;
34
+ readContextMinLines?: number;
35
+ readContextMaxFiles?: number;
18
36
  }
19
37
  export interface BackgroundJobLaunchInput {
20
38
  taskID: string;
@@ -28,24 +46,44 @@ export interface BackgroundJobStatusInput {
28
46
  taskID: string;
29
47
  state: TaskOutputState;
30
48
  timedOut?: boolean;
49
+ statusUncertain?: boolean;
31
50
  resultSummary?: string;
51
+ lastStatusError?: string;
32
52
  now?: number;
33
53
  }
34
54
  export declare class BackgroundJobBoard {
35
55
  private readonly jobs;
36
56
  private readonly counters;
57
+ private readonly maxReusablePerAgent;
58
+ private readonly readContextMinLines;
59
+ private readonly readContextMaxFiles;
60
+ constructor(options?: BackgroundJobBoardOptions);
37
61
  registerLaunch(input: BackgroundJobLaunchInput): BackgroundJobRecord;
38
62
  updateStatus(input: BackgroundJobStatusInput): BackgroundJobRecord | undefined;
39
63
  updateFromStatusOutput(output: string): BackgroundJobRecord | undefined;
64
+ markRunningFromLiveSession(taskID: string, now?: number): BackgroundJobRecord | undefined;
40
65
  markReconciled(taskID: string, now?: number): BackgroundJobRecord | undefined;
41
- markCancelled(taskID: string, reason?: string, now?: number): BackgroundJobRecord | undefined;
66
+ markCancelled(taskID: string, reason?: string, now?: number, options?: {
67
+ force?: boolean;
68
+ }): BackgroundJobRecord | undefined;
42
69
  get(taskID: string): BackgroundJobRecord | undefined;
43
70
  resolve(parentSessionID: string, taskIDOrAlias: string): BackgroundJobRecord | undefined;
71
+ resolveReusable(parentSessionID: string, taskIDOrAlias: string, agent?: string): BackgroundJobRecord | undefined;
72
+ markUsed(parentSessionID: string, key: string, now?: number): void;
73
+ taskIDs(): Set<string>;
74
+ addContext(taskID: string, files: ContextFile[]): void;
44
75
  list(parentSessionID?: string): BackgroundJobRecord[];
45
76
  hasRunning(parentSessionID: string): boolean;
46
77
  hasTerminalUnreconciled(parentSessionID: string): boolean;
47
78
  formatForPrompt(parentSessionID: string, now?: number): string | undefined;
48
79
  clearParent(parentSessionID: string): void;
49
80
  drop(taskID: string): void;
81
+ private trimReusable;
82
+ private formatReusableJob;
50
83
  private nextAlias;
51
84
  }
85
+ export declare function deriveTaskSessionLabel(input: {
86
+ description?: string;
87
+ prompt?: string;
88
+ agentType: string;
89
+ }): string;
@@ -5,6 +5,5 @@ export * from './internal-initiator';
5
5
  export { getLogDir, initLogger, log, resetLogger } from './logger';
6
6
  export * from './polling';
7
7
  export * from './session';
8
- export * from './session-manager';
9
8
  export * from './task';
10
9
  export { extractZip } from './zip-extractor';
@@ -13,8 +13,10 @@ export interface TaskStatusOutput {
13
13
  timedOut: boolean;
14
14
  result?: string;
15
15
  }
16
+ export type TaskStatusClassification = 'running' | 'terminal' | 'timeout' | 'transient_process_error' | 'unknown_error';
16
17
  export declare function parseTaskIdFromTaskOutput(output: string): string | undefined;
17
18
  export declare function parseTaskLaunchOutput(output: string): TaskLaunchOutput | undefined;
18
19
  export declare function parseTaskStatusOutput(output: string): TaskStatusOutput | undefined;
20
+ export declare function classifyTaskStatusOutput(status: TaskStatusOutput): TaskStatusClassification;
19
21
  export declare function parseTaskStateFromOutput(output: string): TaskOutputState | undefined;
20
22
  export declare function parseTaskResultFromOutput(output: string): string | undefined;
@@ -413,6 +413,14 @@
413
413
  "type": "number",
414
414
  "minimum": 20,
415
415
  "maximum": 80
416
+ },
417
+ "zellij_pane_mode": {
418
+ "default": "agent-tab",
419
+ "type": "string",
420
+ "enum": [
421
+ "agent-tab",
422
+ "current-tab"
423
+ ]
416
424
  }
417
425
  }
418
426
  },
@@ -486,7 +494,7 @@
486
494
  }
487
495
  }
488
496
  },
489
- "sessionManager": {
497
+ "backgroundJobs": {
490
498
  "type": "object",
491
499
  "properties": {
492
500
  "maxSessionsPerAgent": {
@@ -509,96 +517,6 @@
509
517
  }
510
518
  }
511
519
  },
512
- "divoom": {
513
- "type": "object",
514
- "properties": {
515
- "enabled": {
516
- "default": false,
517
- "type": "boolean"
518
- },
519
- "python": {
520
- "default": "/Applications/Divoom MiniToo.app/Contents/Resources/.venv/bin/python",
521
- "type": "string",
522
- "minLength": 1
523
- },
524
- "script": {
525
- "default": "/Applications/Divoom MiniToo.app/Contents/Resources/tools/divoom_send.py",
526
- "type": "string",
527
- "minLength": 1
528
- },
529
- "size": {
530
- "default": 128,
531
- "type": "integer",
532
- "minimum": 1,
533
- "maximum": 1024
534
- },
535
- "fps": {
536
- "default": 8,
537
- "type": "integer",
538
- "minimum": 1,
539
- "maximum": 60
540
- },
541
- "speed": {
542
- "default": 125,
543
- "type": "integer",
544
- "minimum": 1,
545
- "maximum": 10000
546
- },
547
- "maxFrames": {
548
- "default": 24,
549
- "type": "integer",
550
- "minimum": 1,
551
- "maximum": 500
552
- },
553
- "posterizeBits": {
554
- "default": 3,
555
- "type": "integer",
556
- "minimum": 1,
557
- "maximum": 8
558
- },
559
- "gifs": {
560
- "type": "object",
561
- "propertyNames": {
562
- "type": "string"
563
- },
564
- "additionalProperties": {
565
- "type": "string",
566
- "minLength": 1
567
- }
568
- }
569
- }
570
- },
571
- "todoContinuation": {
572
- "type": "object",
573
- "properties": {
574
- "maxContinuations": {
575
- "default": 5,
576
- "description": "Maximum consecutive auto-continuations before stopping to ask user",
577
- "type": "integer",
578
- "minimum": 1,
579
- "maximum": 50
580
- },
581
- "cooldownMs": {
582
- "default": 3000,
583
- "description": "Delay in ms before auto-continuing (gives user time to abort)",
584
- "type": "integer",
585
- "minimum": 0,
586
- "maximum": 30000
587
- },
588
- "autoEnable": {
589
- "default": false,
590
- "description": "Automatically enable auto-continue when the orchestrator session has enough todos",
591
- "type": "boolean"
592
- },
593
- "autoEnableThreshold": {
594
- "default": 4,
595
- "description": "Number of todos that triggers auto-enable (only used when autoEnable is true)",
596
- "type": "integer",
597
- "minimum": 1,
598
- "maximum": 50
599
- }
600
- }
601
- },
602
520
  "fallback": {
603
521
  "type": "object",
604
522
  "properties": {
@@ -738,6 +656,31 @@
738
656
  "required": [
739
657
  "presets"
740
658
  ]
659
+ },
660
+ "companion": {
661
+ "type": "object",
662
+ "properties": {
663
+ "enabled": {
664
+ "type": "boolean"
665
+ },
666
+ "position": {
667
+ "type": "string",
668
+ "enum": [
669
+ "bottom-right",
670
+ "bottom-left",
671
+ "top-right",
672
+ "top-left"
673
+ ]
674
+ },
675
+ "size": {
676
+ "type": "string",
677
+ "enum": [
678
+ "small",
679
+ "medium",
680
+ "large"
681
+ ]
682
+ }
683
+ }
741
684
  }
742
685
  },
743
686
  "title": "oh-my-opencode-slim",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-slim",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.0.0",
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",
@@ -44,14 +44,15 @@
44
44
  "oh-my-opencode-slim.schema.json",
45
45
  "README.md",
46
46
  "README.zh-CN.md",
47
+ "README.ja-JP.md",
48
+ "README.ko-KR.md",
47
49
  "LICENSE"
48
50
  ],
49
51
  "scripts": {
50
52
  "clean:dist": "bun -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",
51
53
  "build:plugin": "bun build src/index.ts src/tui.ts --outdir dist --target node --format esm --external @ast-grep/napi --external @opencode-ai/plugin --external @opencode-ai/plugin/* --external @opencode-ai/sdk --external @opencode-ai/sdk/* --external @opentui/core --external @opentui/solid --external jsdom --external zod",
52
54
  "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm --external @ast-grep/napi --external @opencode-ai/plugin --external @opencode-ai/plugin/* --external @opencode-ai/sdk --external @opencode-ai/sdk/* --external jsdom --external zod",
53
- "copy:divoom-assets": "bun run scripts/copy-divoom-assets.ts",
54
- "build": "bun run clean:dist && bun run build:plugin && bun run build:cli && bun run copy:divoom-assets && tsc --emitDeclarationOnly && bun run generate-schema",
55
+ "build": "bun run clean:dist && bun run build:plugin && bun run build:cli && tsc --emitDeclarationOnly && bun run generate-schema",
55
56
  "prepare": "bun run build",
56
57
  "contributors:add": "all-contributors add",
57
58
  "contributors:check": "all-contributors check",
@@ -19,6 +19,7 @@
19
19
  - `src/skills/clonedeps/` (workflow skill for dependency source mirroring)
20
20
  - `src/skills/simplify/` (readability/refactor guidance skill)
21
21
  - `src/skills/deepwork/` (orchestrator-only workflow for heavy coding sessions)
22
+ - `src/skills/oh-my-opencode-slim/` (orchestrator-only plugin configuration and self-improvement guidance)
22
23
  - Files are considered static runtime payload. No plugin TS module in `src/` imports these files directly; they
23
24
  are loaded by OpenCode via filesystem installation.
24
25
 
@@ -40,5 +41,6 @@
40
41
  - `verify-release-artifact.ts` enforces artifact completeness by asserting key
41
42
  bundled skill payloads such as `src/skills/simplify/SKILL.md`,
42
43
  `src/skills/codemap/SKILL.md`, `src/skills/clonedeps/SKILL.md`, and
43
- `src/skills/deepwork/SKILL.md` are present in the tarball.
44
+ `src/skills/deepwork/SKILL.md`, plus `src/skills/oh-my-opencode-slim/SKILL.md`,
45
+ are present in the tarball.
44
46
  - `package.json` scripts (`verify:release`, `build`) rely on these assets to ensure install-time skill availability.
@@ -33,8 +33,30 @@ Required behavior:
33
33
  - after each phase, validate, update the deepwork file, prepare the plan file
34
34
  for oracle review and ask `@oracle` to review the phase result, fix
35
35
  actionable issues, then continue;
36
+ - when a phase includes `@designer`, preserve designer intent across later
37
+ phases. Use `@fixer` only for mechanical follow-up that does not alter the
38
+ UI/UX;
36
39
  - finish with final validation and a concise summary.
37
40
 
41
+ ## Designer Handoff Guardrail
42
+
43
+ When a deepwork phase includes `@designer`, treat the delivered UI/UX as
44
+ accepted design intent for later phases. Record any important design decisions in
45
+ the deepwork file before continuing.
46
+
47
+ After designer work:
48
+
49
+ - preserve layout, rhythm, hierarchy, motion, spacing, color, affordances,
50
+ responsiveness, and component feel;
51
+ - review and improve user-facing copy with grounded, normal wording, but do not
52
+ change visual structure or interaction intent;
53
+ - route follow-up visual, responsive, motion, hierarchy, polish, or
54
+ component-feel changes back to `@designer`;
55
+ - use `@fixer` only for bounded mechanical follow-up that preserves the design
56
+ exactly, such as wiring, tests, type fixes, or non-visual behavior changes;
57
+ - if design intent must change, record why in the deepwork file before changing
58
+ it.
59
+
38
60
  ## Deepwork File
39
61
 
40
62
  Create a task-specific file such as:
@@ -82,8 +104,8 @@ Use the scheduler model throughout:
82
104
 
83
105
  - follow Orchestrator delegations rules
84
106
  - record task/session IDs and ownership boundaries;
85
- - poll `task_status` before consuming background results;
86
- - avoid blocking Orchestrator lane too long; prefer shorter periodic task waits
87
- rather than one long wait;
107
+ - wait for hook-driven background completion before consuming background results;
108
+ - avoid blocking Orchestrator lane while background jobs run; if no independent
109
+ work remains, stop briefly and let the completion event resume the workflow;
88
110
  - do not advance to the next phase while relevant jobs are running or terminal
89
111
  results are unreconciled.