oh-my-opencode 1.1.3 → 1.1.5

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.
@@ -0,0 +1 @@
1
+ export declare const BUILD_AGENT_PROMPT_EXTENSION = "\n# Agent Orchestration & Task Management\n\nYou are not just a coder - you are an **ORCHESTRATOR**. Your primary job is to delegate work to specialized agents and track progress obsessively.\n\n## Think Before Acting\n\nWhen you receive a user request, STOP and think deeply:\n\n1. **What specialized agents can handle this better than me?**\n - explore: File search, codebase navigation, pattern matching\n - librarian: Documentation lookup, API references, implementation examples\n - oracle: Architecture decisions, code review, complex logic analysis\n - frontend-ui-ux-engineer: UI/UX implementation, component design\n - document-writer: Documentation, README, technical writing\n\n2. **Can I parallelize this work?**\n - Fire multiple background_task calls simultaneously\n - Continue working on other parts while agents investigate\n - Aggregate results when notified\n\n3. **Have I planned this in my TODO list?**\n - Break down the task into atomic steps FIRST\n - Track every investigation, every delegation\n\n## PARALLEL TOOL CALLS - MANDATORY\n\n**ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.** This is non-negotiable.\n\nThis parallel approach allows you to:\n- Gather comprehensive context faster\n- Cross-reference information simultaneously\n- Reduce total execution time dramatically\n- Maintain high accuracy through concurrent validation\n- Complete multi-file modifications in a single turn\n\n**ALWAYS prefer parallel tool calls over sequential ones when the operations are independent.**\n\n## TODO Tool Obsession\n\n**USE TODO TOOLS AGGRESSIVELY.** This is non-negotiable.\n\n### When to Use TodoWrite:\n- IMMEDIATELY after receiving a user request\n- Before ANY multi-step task (even if it seems \"simple\")\n- When delegating to agents (track what you delegated)\n- After completing each step (mark it done)\n\n### TODO Workflow:\n```\nUser Request \u2192 TodoWrite (plan) \u2192 Mark in_progress \u2192 Execute/Delegate \u2192 Mark complete \u2192 Next\n```\n\n### Rules:\n- Only ONE task in_progress at a time\n- Mark complete IMMEDIATELY after finishing (never batch)\n- Never proceed without updating TODO status\n\n## Delegation Pattern\n\n```typescript\n// 1. PLAN with TODO first\ntodowrite([\n { id: \"research\", content: \"Research X implementation\", status: \"in_progress\", priority: \"high\" },\n { id: \"impl\", content: \"Implement X feature\", status: \"pending\", priority: \"high\" },\n { id: \"test\", content: \"Test X feature\", status: \"pending\", priority: \"medium\" }\n])\n\n// 2. DELEGATE research in parallel - FIRE MULTIPLE AT ONCE\nbackground_task(agent=\"explore\", prompt=\"Find all files related to X\")\nbackground_task(agent=\"librarian\", prompt=\"Look up X documentation\")\n\n// 3. CONTINUE working on implementation skeleton while agents research\n// 4. When notified, INTEGRATE findings and mark TODO complete\n```\n\n## Subagent Prompt Structure - MANDATORY 7 SECTIONS\n\nWhen invoking Task() or background_task() with any subagent, ALWAYS structure your prompt with these 7 sections to prevent AI slop:\n\n1. **TASK**: What exactly needs to be done (be obsessively specific)\n2. **EXPECTED OUTCOME**: Concrete deliverables when complete (files, behaviors, states)\n3. **REQUIRED SKILLS**: Which skills the agent MUST invoke\n4. **REQUIRED TOOLS**: Which tools the agent MUST use (context7 MCP, ast-grep, Grep, etc.)\n5. **MUST DO**: Exhaustive list of requirements (leave NOTHING implicit)\n6. **MUST NOT DO**: Forbidden actions (anticipate every way agent could go rogue)\n7. **CONTEXT**: Additional info agent needs (file paths, patterns, dependencies)\n\nExample:\n```\nbackground_task(agent=\"explore\", prompt=\"\"\"\nTASK: Find all authentication-related files in the codebase\n\nEXPECTED OUTCOME:\n- List of all auth files with their purposes\n- Identified patterns for token handling\n\nREQUIRED TOOLS:\n- ast-grep: Find function definitions with `sg --pattern 'def $FUNC($$$):' --lang python`\n- Grep: Search for 'auth', 'token', 'jwt' patterns\n\nMUST DO:\n- Search in src/, lib/, and utils/ directories\n- Include test files for context\n\nMUST NOT DO:\n- Do NOT modify any files\n- Do NOT make assumptions about implementation\n\nCONTEXT:\n- Project uses Python/Django\n- Auth system is custom-built\n\"\"\")\n```\n\n**Vague prompts = agent goes rogue. Lock them down.**\n\n## Anti-Patterns (AVOID):\n- Doing everything yourself when agents can help\n- Skipping TODO planning for \"quick\" tasks\n- Forgetting to mark tasks complete\n- Sequential execution when parallel is possible\n- Direct tool calls without considering delegation\n- Vague subagent prompts without the 7 sections\n\n## Remember:\n- You are the **team lead**, not the grunt worker\n- Your context window is precious - delegate to preserve it\n- Agents have specialized expertise - USE THEM\n- TODO tracking gives users visibility into your progress\n- Parallel execution = faster results\n- **ALWAYS fire multiple independent operations simultaneously**\n";
@@ -2,3 +2,4 @@ import type { AgentConfig } from "@opencode-ai/sdk";
2
2
  export declare const builtinAgents: Record<string, AgentConfig>;
3
3
  export * from "./types";
4
4
  export { createBuiltinAgents } from "./utils";
5
+ export { BUILD_AGENT_PROMPT_EXTENSION } from "./build";
@@ -1,4 +1,6 @@
1
1
  import type { AgentConfig } from "@opencode-ai/sdk";
2
- export type AgentName = "oracle" | "librarian" | "explore" | "frontend-ui-ux-engineer" | "document-writer" | "multimodal-looker";
2
+ export type BuiltinAgentName = "oracle" | "librarian" | "explore" | "frontend-ui-ux-engineer" | "document-writer" | "multimodal-looker";
3
+ export type OverridableAgentName = "build" | BuiltinAgentName;
4
+ export type AgentName = BuiltinAgentName;
3
5
  export type AgentOverrideConfig = Partial<AgentConfig>;
4
- export type AgentOverrides = Partial<Record<AgentName, AgentOverrideConfig>>;
6
+ export type AgentOverrides = Partial<Record<OverridableAgentName, AgentOverrideConfig>>;
@@ -1,3 +1,3 @@
1
1
  import type { AgentConfig } from "@opencode-ai/sdk";
2
- import type { AgentName, AgentOverrides } from "./types";
3
- export declare function createBuiltinAgents(disabledAgents?: AgentName[], agentOverrides?: AgentOverrides): Record<string, AgentConfig>;
2
+ import type { BuiltinAgentName, AgentOverrides } from "./types";
3
+ export declare function createBuiltinAgents(disabledAgents?: BuiltinAgentName[], agentOverrides?: AgentOverrides): Record<string, AgentConfig>;
@@ -1,4 +1,21 @@
1
1
  import { z } from "zod";
2
+ export declare const BuiltinAgentNameSchema: z.ZodEnum<{
3
+ oracle: "oracle";
4
+ librarian: "librarian";
5
+ explore: "explore";
6
+ "frontend-ui-ux-engineer": "frontend-ui-ux-engineer";
7
+ "document-writer": "document-writer";
8
+ "multimodal-looker": "multimodal-looker";
9
+ }>;
10
+ export declare const OverridableAgentNameSchema: z.ZodEnum<{
11
+ oracle: "oracle";
12
+ librarian: "librarian";
13
+ explore: "explore";
14
+ "frontend-ui-ux-engineer": "frontend-ui-ux-engineer";
15
+ "document-writer": "document-writer";
16
+ "multimodal-looker": "multimodal-looker";
17
+ build: "build";
18
+ }>;
2
19
  export declare const AgentNameSchema: z.ZodEnum<{
3
20
  oracle: "oracle";
4
21
  librarian: "librarian";
@@ -10,6 +27,7 @@ export declare const AgentNameSchema: z.ZodEnum<{
10
27
  export declare const HookNameSchema: z.ZodEnum<{
11
28
  "comment-checker": "comment-checker";
12
29
  "rules-injector": "rules-injector";
30
+ "agent-usage-reminder": "agent-usage-reminder";
13
31
  "todo-continuation-enforcer": "todo-continuation-enforcer";
14
32
  "context-window-monitor": "context-window-monitor";
15
33
  "session-recovery": "session-recovery";
@@ -71,6 +89,52 @@ export declare const AgentOverrideConfigSchema: z.ZodObject<{
71
89
  }, z.core.$strip>>;
72
90
  }, z.core.$strip>;
73
91
  export declare const AgentOverridesSchema: z.ZodObject<{
92
+ build: z.ZodOptional<z.ZodOptional<z.ZodObject<{
93
+ model: z.ZodOptional<z.ZodString>;
94
+ temperature: z.ZodOptional<z.ZodNumber>;
95
+ top_p: z.ZodOptional<z.ZodNumber>;
96
+ prompt: z.ZodOptional<z.ZodString>;
97
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
98
+ disable: z.ZodOptional<z.ZodBoolean>;
99
+ description: z.ZodOptional<z.ZodString>;
100
+ mode: z.ZodOptional<z.ZodEnum<{
101
+ subagent: "subagent";
102
+ primary: "primary";
103
+ all: "all";
104
+ }>>;
105
+ color: z.ZodOptional<z.ZodString>;
106
+ permission: z.ZodOptional<z.ZodObject<{
107
+ edit: z.ZodOptional<z.ZodEnum<{
108
+ allow: "allow";
109
+ deny: "deny";
110
+ ask: "ask";
111
+ }>>;
112
+ bash: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
113
+ allow: "allow";
114
+ deny: "deny";
115
+ ask: "ask";
116
+ }>, z.ZodRecord<z.ZodString, z.ZodEnum<{
117
+ allow: "allow";
118
+ deny: "deny";
119
+ ask: "ask";
120
+ }>>]>>;
121
+ webfetch: z.ZodOptional<z.ZodEnum<{
122
+ allow: "allow";
123
+ deny: "deny";
124
+ ask: "ask";
125
+ }>>;
126
+ doom_loop: z.ZodOptional<z.ZodEnum<{
127
+ allow: "allow";
128
+ deny: "deny";
129
+ ask: "ask";
130
+ }>>;
131
+ external_directory: z.ZodOptional<z.ZodEnum<{
132
+ allow: "allow";
133
+ deny: "deny";
134
+ ask: "ask";
135
+ }>>;
136
+ }, z.core.$strip>>;
137
+ }, z.core.$strip>>>;
74
138
  oracle: z.ZodOptional<z.ZodOptional<z.ZodObject<{
75
139
  model: z.ZodOptional<z.ZodString>;
76
140
  temperature: z.ZodOptional<z.ZodNumber>;
@@ -373,6 +437,7 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
373
437
  disabled_hooks: z.ZodOptional<z.ZodArray<z.ZodEnum<{
374
438
  "comment-checker": "comment-checker";
375
439
  "rules-injector": "rules-injector";
440
+ "agent-usage-reminder": "agent-usage-reminder";
376
441
  "todo-continuation-enforcer": "todo-continuation-enforcer";
377
442
  "context-window-monitor": "context-window-monitor";
378
443
  "session-recovery": "session-recovery";
@@ -388,6 +453,52 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
388
453
  "ultrawork-mode": "ultrawork-mode";
389
454
  }>>>;
390
455
  agents: z.ZodOptional<z.ZodObject<{
456
+ build: z.ZodOptional<z.ZodOptional<z.ZodObject<{
457
+ model: z.ZodOptional<z.ZodString>;
458
+ temperature: z.ZodOptional<z.ZodNumber>;
459
+ top_p: z.ZodOptional<z.ZodNumber>;
460
+ prompt: z.ZodOptional<z.ZodString>;
461
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
462
+ disable: z.ZodOptional<z.ZodBoolean>;
463
+ description: z.ZodOptional<z.ZodString>;
464
+ mode: z.ZodOptional<z.ZodEnum<{
465
+ subagent: "subagent";
466
+ primary: "primary";
467
+ all: "all";
468
+ }>>;
469
+ color: z.ZodOptional<z.ZodString>;
470
+ permission: z.ZodOptional<z.ZodObject<{
471
+ edit: z.ZodOptional<z.ZodEnum<{
472
+ allow: "allow";
473
+ deny: "deny";
474
+ ask: "ask";
475
+ }>>;
476
+ bash: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
477
+ allow: "allow";
478
+ deny: "deny";
479
+ ask: "ask";
480
+ }>, z.ZodRecord<z.ZodString, z.ZodEnum<{
481
+ allow: "allow";
482
+ deny: "deny";
483
+ ask: "ask";
484
+ }>>]>>;
485
+ webfetch: z.ZodOptional<z.ZodEnum<{
486
+ allow: "allow";
487
+ deny: "deny";
488
+ ask: "ask";
489
+ }>>;
490
+ doom_loop: z.ZodOptional<z.ZodEnum<{
491
+ allow: "allow";
492
+ deny: "deny";
493
+ ask: "ask";
494
+ }>>;
495
+ external_directory: z.ZodOptional<z.ZodEnum<{
496
+ allow: "allow";
497
+ deny: "deny";
498
+ ask: "ask";
499
+ }>>;
500
+ }, z.core.$strip>>;
501
+ }, z.core.$strip>>>;
391
502
  oracle: z.ZodOptional<z.ZodOptional<z.ZodObject<{
392
503
  model: z.ZodOptional<z.ZodString>;
393
504
  temperature: z.ZodOptional<z.ZodNumber>;
@@ -0,0 +1,5 @@
1
+ export declare const OPENCODE_STORAGE: string;
2
+ export declare const AGENT_USAGE_REMINDER_STORAGE: string;
3
+ export declare const TARGET_TOOLS: Set<string>;
4
+ export declare const AGENT_TOOLS: Set<string>;
5
+ export declare const REMINDER_MESSAGE = "\n[Agent Usage Reminder]\n\nYou called a search/fetch tool directly without leveraging specialized agents.\n\nRECOMMENDED: Use background_task with explore/librarian agents for better results:\n\n```\n// Parallel exploration - fire multiple agents simultaneously\nbackground_task(agent=\"explore\", prompt=\"Find all files matching pattern X\")\nbackground_task(agent=\"explore\", prompt=\"Search for implementation of Y\") \nbackground_task(agent=\"librarian\", prompt=\"Lookup documentation for Z\")\n\n// Then continue your work while they run in background\n// System will notify you when each completes\n```\n\nWHY:\n- Agents can perform deeper, more thorough searches\n- Background tasks run in parallel, saving time\n- Specialized agents have domain expertise\n- Reduces context window usage in main session\n\nALWAYS prefer: Multiple parallel background_task calls > Direct tool calls\n";
@@ -0,0 +1,22 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ interface ToolExecuteInput {
3
+ tool: string;
4
+ sessionID: string;
5
+ callID: string;
6
+ }
7
+ interface ToolExecuteOutput {
8
+ title: string;
9
+ output: string;
10
+ metadata: unknown;
11
+ }
12
+ interface EventInput {
13
+ event: {
14
+ type: string;
15
+ properties?: unknown;
16
+ };
17
+ }
18
+ export declare function createAgentUsageReminderHook(_ctx: PluginInput): {
19
+ "tool.execute.after": (input: ToolExecuteInput, output: ToolExecuteOutput) => Promise<void>;
20
+ event: ({ event }: EventInput) => Promise<void>;
21
+ };
22
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { AgentUsageState } from "./types";
2
+ export declare function loadAgentUsageState(sessionID: string): AgentUsageState | null;
3
+ export declare function saveAgentUsageState(state: AgentUsageState): void;
4
+ export declare function clearAgentUsageState(sessionID: string): void;
@@ -0,0 +1,6 @@
1
+ export interface AgentUsageState {
2
+ sessionID: string;
3
+ agentUsed: boolean;
4
+ reminderCount: number;
5
+ updatedAt: number;
6
+ }
@@ -14,3 +14,4 @@ export { createRulesInjectorHook } from "./rules-injector";
14
14
  export { createBackgroundNotificationHook } from "./background-notification";
15
15
  export { createAutoUpdateCheckerHook } from "./auto-update-checker";
16
16
  export { createUltraworkModeHook } from "./ultrawork-mode";
17
+ export { createAgentUsageReminderHook } from "./agent-usage-reminder";
package/dist/index.js CHANGED
@@ -2826,6 +2826,140 @@ function createBuiltinAgents(disabledAgents = [], agentOverrides = {}) {
2826
2826
  }
2827
2827
  return result;
2828
2828
  }
2829
+ // src/agents/build.ts
2830
+ var BUILD_AGENT_PROMPT_EXTENSION = `
2831
+ # Agent Orchestration & Task Management
2832
+
2833
+ You are not just a coder - you are an **ORCHESTRATOR**. Your primary job is to delegate work to specialized agents and track progress obsessively.
2834
+
2835
+ ## Think Before Acting
2836
+
2837
+ When you receive a user request, STOP and think deeply:
2838
+
2839
+ 1. **What specialized agents can handle this better than me?**
2840
+ - explore: File search, codebase navigation, pattern matching
2841
+ - librarian: Documentation lookup, API references, implementation examples
2842
+ - oracle: Architecture decisions, code review, complex logic analysis
2843
+ - frontend-ui-ux-engineer: UI/UX implementation, component design
2844
+ - document-writer: Documentation, README, technical writing
2845
+
2846
+ 2. **Can I parallelize this work?**
2847
+ - Fire multiple background_task calls simultaneously
2848
+ - Continue working on other parts while agents investigate
2849
+ - Aggregate results when notified
2850
+
2851
+ 3. **Have I planned this in my TODO list?**
2852
+ - Break down the task into atomic steps FIRST
2853
+ - Track every investigation, every delegation
2854
+
2855
+ ## PARALLEL TOOL CALLS - MANDATORY
2856
+
2857
+ **ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.** This is non-negotiable.
2858
+
2859
+ This parallel approach allows you to:
2860
+ - Gather comprehensive context faster
2861
+ - Cross-reference information simultaneously
2862
+ - Reduce total execution time dramatically
2863
+ - Maintain high accuracy through concurrent validation
2864
+ - Complete multi-file modifications in a single turn
2865
+
2866
+ **ALWAYS prefer parallel tool calls over sequential ones when the operations are independent.**
2867
+
2868
+ ## TODO Tool Obsession
2869
+
2870
+ **USE TODO TOOLS AGGRESSIVELY.** This is non-negotiable.
2871
+
2872
+ ### When to Use TodoWrite:
2873
+ - IMMEDIATELY after receiving a user request
2874
+ - Before ANY multi-step task (even if it seems "simple")
2875
+ - When delegating to agents (track what you delegated)
2876
+ - After completing each step (mark it done)
2877
+
2878
+ ### TODO Workflow:
2879
+ \`\`\`
2880
+ User Request \u2192 TodoWrite (plan) \u2192 Mark in_progress \u2192 Execute/Delegate \u2192 Mark complete \u2192 Next
2881
+ \`\`\`
2882
+
2883
+ ### Rules:
2884
+ - Only ONE task in_progress at a time
2885
+ - Mark complete IMMEDIATELY after finishing (never batch)
2886
+ - Never proceed without updating TODO status
2887
+
2888
+ ## Delegation Pattern
2889
+
2890
+ \`\`\`typescript
2891
+ // 1. PLAN with TODO first
2892
+ todowrite([
2893
+ { id: "research", content: "Research X implementation", status: "in_progress", priority: "high" },
2894
+ { id: "impl", content: "Implement X feature", status: "pending", priority: "high" },
2895
+ { id: "test", content: "Test X feature", status: "pending", priority: "medium" }
2896
+ ])
2897
+
2898
+ // 2. DELEGATE research in parallel - FIRE MULTIPLE AT ONCE
2899
+ background_task(agent="explore", prompt="Find all files related to X")
2900
+ background_task(agent="librarian", prompt="Look up X documentation")
2901
+
2902
+ // 3. CONTINUE working on implementation skeleton while agents research
2903
+ // 4. When notified, INTEGRATE findings and mark TODO complete
2904
+ \`\`\`
2905
+
2906
+ ## Subagent Prompt Structure - MANDATORY 7 SECTIONS
2907
+
2908
+ When invoking Task() or background_task() with any subagent, ALWAYS structure your prompt with these 7 sections to prevent AI slop:
2909
+
2910
+ 1. **TASK**: What exactly needs to be done (be obsessively specific)
2911
+ 2. **EXPECTED OUTCOME**: Concrete deliverables when complete (files, behaviors, states)
2912
+ 3. **REQUIRED SKILLS**: Which skills the agent MUST invoke
2913
+ 4. **REQUIRED TOOLS**: Which tools the agent MUST use (context7 MCP, ast-grep, Grep, etc.)
2914
+ 5. **MUST DO**: Exhaustive list of requirements (leave NOTHING implicit)
2915
+ 6. **MUST NOT DO**: Forbidden actions (anticipate every way agent could go rogue)
2916
+ 7. **CONTEXT**: Additional info agent needs (file paths, patterns, dependencies)
2917
+
2918
+ Example:
2919
+ \`\`\`
2920
+ background_task(agent="explore", prompt="""
2921
+ TASK: Find all authentication-related files in the codebase
2922
+
2923
+ EXPECTED OUTCOME:
2924
+ - List of all auth files with their purposes
2925
+ - Identified patterns for token handling
2926
+
2927
+ REQUIRED TOOLS:
2928
+ - ast-grep: Find function definitions with \`sg --pattern 'def $FUNC($$$):' --lang python\`
2929
+ - Grep: Search for 'auth', 'token', 'jwt' patterns
2930
+
2931
+ MUST DO:
2932
+ - Search in src/, lib/, and utils/ directories
2933
+ - Include test files for context
2934
+
2935
+ MUST NOT DO:
2936
+ - Do NOT modify any files
2937
+ - Do NOT make assumptions about implementation
2938
+
2939
+ CONTEXT:
2940
+ - Project uses Python/Django
2941
+ - Auth system is custom-built
2942
+ """)
2943
+ \`\`\`
2944
+
2945
+ **Vague prompts = agent goes rogue. Lock them down.**
2946
+
2947
+ ## Anti-Patterns (AVOID):
2948
+ - Doing everything yourself when agents can help
2949
+ - Skipping TODO planning for "quick" tasks
2950
+ - Forgetting to mark tasks complete
2951
+ - Sequential execution when parallel is possible
2952
+ - Direct tool calls without considering delegation
2953
+ - Vague subagent prompts without the 7 sections
2954
+
2955
+ ## Remember:
2956
+ - You are the **team lead**, not the grunt worker
2957
+ - Your context window is precious - delegate to preserve it
2958
+ - Agents have specialized expertise - USE THEM
2959
+ - TODO tracking gives users visibility into your progress
2960
+ - Parallel execution = faster results
2961
+ - **ALWAYS fire multiple independent operations simultaneously**
2962
+ `;
2829
2963
  // src/hooks/todo-continuation-enforcer.ts
2830
2964
  var CONTINUATION_PROMPT = `[SYSTEM REMINDER - TODO CONTINUATION]
2831
2965
 
@@ -6783,6 +6917,156 @@ function createUltraworkModeHook() {
6783
6917
  }
6784
6918
  };
6785
6919
  }
6920
+ // src/hooks/agent-usage-reminder/storage.ts
6921
+ import {
6922
+ existsSync as existsSync19,
6923
+ mkdirSync as mkdirSync8,
6924
+ readFileSync as readFileSync11,
6925
+ writeFileSync as writeFileSync7,
6926
+ unlinkSync as unlinkSync8
6927
+ } from "fs";
6928
+ import { join as join25 } from "path";
6929
+
6930
+ // src/hooks/agent-usage-reminder/constants.ts
6931
+ import { join as join24 } from "path";
6932
+ var OPENCODE_STORAGE6 = join24(xdgData ?? "", "opencode", "storage");
6933
+ var AGENT_USAGE_REMINDER_STORAGE = join24(OPENCODE_STORAGE6, "agent-usage-reminder");
6934
+ var TARGET_TOOLS = new Set([
6935
+ "grep",
6936
+ "safe_grep",
6937
+ "glob",
6938
+ "safe_glob",
6939
+ "webfetch",
6940
+ "context7_resolve-library-id",
6941
+ "context7_get-library-docs",
6942
+ "websearch_exa_web_search_exa",
6943
+ "grep_app_searchgithub"
6944
+ ]);
6945
+ var AGENT_TOOLS = new Set([
6946
+ "task",
6947
+ "call_omo_agent",
6948
+ "background_task"
6949
+ ]);
6950
+ var REMINDER_MESSAGE = `
6951
+ [Agent Usage Reminder]
6952
+
6953
+ You called a search/fetch tool directly without leveraging specialized agents.
6954
+
6955
+ RECOMMENDED: Use background_task with explore/librarian agents for better results:
6956
+
6957
+ \`\`\`
6958
+ // Parallel exploration - fire multiple agents simultaneously
6959
+ background_task(agent="explore", prompt="Find all files matching pattern X")
6960
+ background_task(agent="explore", prompt="Search for implementation of Y")
6961
+ background_task(agent="librarian", prompt="Lookup documentation for Z")
6962
+
6963
+ // Then continue your work while they run in background
6964
+ // System will notify you when each completes
6965
+ \`\`\`
6966
+
6967
+ WHY:
6968
+ - Agents can perform deeper, more thorough searches
6969
+ - Background tasks run in parallel, saving time
6970
+ - Specialized agents have domain expertise
6971
+ - Reduces context window usage in main session
6972
+
6973
+ ALWAYS prefer: Multiple parallel background_task calls > Direct tool calls
6974
+ `;
6975
+
6976
+ // src/hooks/agent-usage-reminder/storage.ts
6977
+ function getStoragePath4(sessionID) {
6978
+ return join25(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
6979
+ }
6980
+ function loadAgentUsageState(sessionID) {
6981
+ const filePath = getStoragePath4(sessionID);
6982
+ if (!existsSync19(filePath))
6983
+ return null;
6984
+ try {
6985
+ const content = readFileSync11(filePath, "utf-8");
6986
+ return JSON.parse(content);
6987
+ } catch {
6988
+ return null;
6989
+ }
6990
+ }
6991
+ function saveAgentUsageState(state) {
6992
+ if (!existsSync19(AGENT_USAGE_REMINDER_STORAGE)) {
6993
+ mkdirSync8(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
6994
+ }
6995
+ const filePath = getStoragePath4(state.sessionID);
6996
+ writeFileSync7(filePath, JSON.stringify(state, null, 2));
6997
+ }
6998
+ function clearAgentUsageState(sessionID) {
6999
+ const filePath = getStoragePath4(sessionID);
7000
+ if (existsSync19(filePath)) {
7001
+ unlinkSync8(filePath);
7002
+ }
7003
+ }
7004
+
7005
+ // src/hooks/agent-usage-reminder/index.ts
7006
+ function createAgentUsageReminderHook(_ctx) {
7007
+ const sessionStates = new Map;
7008
+ function getOrCreateState(sessionID) {
7009
+ if (!sessionStates.has(sessionID)) {
7010
+ const persisted = loadAgentUsageState(sessionID);
7011
+ const state = persisted ?? {
7012
+ sessionID,
7013
+ agentUsed: false,
7014
+ reminderCount: 0,
7015
+ updatedAt: Date.now()
7016
+ };
7017
+ sessionStates.set(sessionID, state);
7018
+ }
7019
+ return sessionStates.get(sessionID);
7020
+ }
7021
+ function markAgentUsed(sessionID) {
7022
+ const state = getOrCreateState(sessionID);
7023
+ state.agentUsed = true;
7024
+ state.updatedAt = Date.now();
7025
+ saveAgentUsageState(state);
7026
+ }
7027
+ function resetState(sessionID) {
7028
+ sessionStates.delete(sessionID);
7029
+ clearAgentUsageState(sessionID);
7030
+ }
7031
+ const toolExecuteAfter = async (input, output) => {
7032
+ const { tool, sessionID } = input;
7033
+ const toolLower = tool.toLowerCase();
7034
+ if (AGENT_TOOLS.has(toolLower)) {
7035
+ markAgentUsed(sessionID);
7036
+ return;
7037
+ }
7038
+ if (!TARGET_TOOLS.has(toolLower)) {
7039
+ return;
7040
+ }
7041
+ const state = getOrCreateState(sessionID);
7042
+ if (state.agentUsed) {
7043
+ return;
7044
+ }
7045
+ output.output += REMINDER_MESSAGE;
7046
+ state.reminderCount++;
7047
+ state.updatedAt = Date.now();
7048
+ saveAgentUsageState(state);
7049
+ };
7050
+ const eventHandler = async ({ event }) => {
7051
+ const props = event.properties;
7052
+ if (event.type === "session.deleted") {
7053
+ const sessionInfo = props?.info;
7054
+ if (sessionInfo?.id) {
7055
+ resetState(sessionInfo.id);
7056
+ }
7057
+ }
7058
+ if (event.type === "session.compacted") {
7059
+ const sessionID = props?.sessionID ?? props?.info?.id;
7060
+ if (sessionID) {
7061
+ resetState(sessionID);
7062
+ }
7063
+ }
7064
+ };
7065
+ return {
7066
+ "tool.execute.after": toolExecuteAfter,
7067
+ event: eventHandler
7068
+ };
7069
+ }
6786
7070
  // src/auth/antigravity/constants.ts
6787
7071
  var ANTIGRAVITY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
6788
7072
  var ANTIGRAVITY_CLIENT_SECRET = "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";
@@ -8289,11 +8573,11 @@ async function createGoogleAntigravityAuthPlugin({
8289
8573
  };
8290
8574
  }
8291
8575
  // src/features/claude-code-command-loader/loader.ts
8292
- import { existsSync as existsSync19, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "fs";
8576
+ import { existsSync as existsSync20, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs";
8293
8577
  import { homedir as homedir9 } from "os";
8294
- import { join as join24, basename } from "path";
8578
+ import { join as join26, basename } from "path";
8295
8579
  function loadCommandsFromDir(commandsDir, scope) {
8296
- if (!existsSync19(commandsDir)) {
8580
+ if (!existsSync20(commandsDir)) {
8297
8581
  return [];
8298
8582
  }
8299
8583
  const entries = readdirSync4(commandsDir, { withFileTypes: true });
@@ -8301,10 +8585,10 @@ function loadCommandsFromDir(commandsDir, scope) {
8301
8585
  for (const entry of entries) {
8302
8586
  if (!isMarkdownFile(entry))
8303
8587
  continue;
8304
- const commandPath = join24(commandsDir, entry.name);
8588
+ const commandPath = join26(commandsDir, entry.name);
8305
8589
  const commandName = basename(entry.name, ".md");
8306
8590
  try {
8307
- const content = readFileSync11(commandPath, "utf-8");
8591
+ const content = readFileSync12(commandPath, "utf-8");
8308
8592
  const { data, body } = parseFrontmatter(content);
8309
8593
  const wrappedTemplate = `<command-instruction>
8310
8594
  ${body.trim()}
@@ -8343,31 +8627,31 @@ function commandsToRecord(commands) {
8343
8627
  return result;
8344
8628
  }
8345
8629
  function loadUserCommands() {
8346
- const userCommandsDir = join24(homedir9(), ".claude", "commands");
8630
+ const userCommandsDir = join26(homedir9(), ".claude", "commands");
8347
8631
  const commands = loadCommandsFromDir(userCommandsDir, "user");
8348
8632
  return commandsToRecord(commands);
8349
8633
  }
8350
8634
  function loadProjectCommands() {
8351
- const projectCommandsDir = join24(process.cwd(), ".claude", "commands");
8635
+ const projectCommandsDir = join26(process.cwd(), ".claude", "commands");
8352
8636
  const commands = loadCommandsFromDir(projectCommandsDir, "project");
8353
8637
  return commandsToRecord(commands);
8354
8638
  }
8355
8639
  function loadOpencodeGlobalCommands() {
8356
- const opencodeCommandsDir = join24(homedir9(), ".config", "opencode", "command");
8640
+ const opencodeCommandsDir = join26(homedir9(), ".config", "opencode", "command");
8357
8641
  const commands = loadCommandsFromDir(opencodeCommandsDir, "opencode");
8358
8642
  return commandsToRecord(commands);
8359
8643
  }
8360
8644
  function loadOpencodeProjectCommands() {
8361
- const opencodeProjectDir = join24(process.cwd(), ".opencode", "command");
8645
+ const opencodeProjectDir = join26(process.cwd(), ".opencode", "command");
8362
8646
  const commands = loadCommandsFromDir(opencodeProjectDir, "opencode-project");
8363
8647
  return commandsToRecord(commands);
8364
8648
  }
8365
8649
  // src/features/claude-code-skill-loader/loader.ts
8366
- import { existsSync as existsSync20, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "fs";
8650
+ import { existsSync as existsSync21, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "fs";
8367
8651
  import { homedir as homedir10 } from "os";
8368
- import { join as join25 } from "path";
8652
+ import { join as join27 } from "path";
8369
8653
  function loadSkillsFromDir(skillsDir, scope) {
8370
- if (!existsSync20(skillsDir)) {
8654
+ if (!existsSync21(skillsDir)) {
8371
8655
  return [];
8372
8656
  }
8373
8657
  const entries = readdirSync5(skillsDir, { withFileTypes: true });
@@ -8375,15 +8659,15 @@ function loadSkillsFromDir(skillsDir, scope) {
8375
8659
  for (const entry of entries) {
8376
8660
  if (entry.name.startsWith("."))
8377
8661
  continue;
8378
- const skillPath = join25(skillsDir, entry.name);
8662
+ const skillPath = join27(skillsDir, entry.name);
8379
8663
  if (!entry.isDirectory() && !entry.isSymbolicLink())
8380
8664
  continue;
8381
8665
  const resolvedPath = resolveSymlink(skillPath);
8382
- const skillMdPath = join25(resolvedPath, "SKILL.md");
8383
- if (!existsSync20(skillMdPath))
8666
+ const skillMdPath = join27(resolvedPath, "SKILL.md");
8667
+ if (!existsSync21(skillMdPath))
8384
8668
  continue;
8385
8669
  try {
8386
- const content = readFileSync12(skillMdPath, "utf-8");
8670
+ const content = readFileSync13(skillMdPath, "utf-8");
8387
8671
  const { data, body } = parseFrontmatter(content);
8388
8672
  const skillName = data.name || entry.name;
8389
8673
  const originalDescription = data.description || "";
@@ -8414,7 +8698,7 @@ $ARGUMENTS
8414
8698
  return skills;
8415
8699
  }
8416
8700
  function loadUserSkillsAsCommands() {
8417
- const userSkillsDir = join25(homedir10(), ".claude", "skills");
8701
+ const userSkillsDir = join27(homedir10(), ".claude", "skills");
8418
8702
  const skills = loadSkillsFromDir(userSkillsDir, "user");
8419
8703
  return skills.reduce((acc, skill) => {
8420
8704
  acc[skill.name] = skill.definition;
@@ -8422,7 +8706,7 @@ function loadUserSkillsAsCommands() {
8422
8706
  }, {});
8423
8707
  }
8424
8708
  function loadProjectSkillsAsCommands() {
8425
- const projectSkillsDir = join25(process.cwd(), ".claude", "skills");
8709
+ const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
8426
8710
  const skills = loadSkillsFromDir(projectSkillsDir, "project");
8427
8711
  return skills.reduce((acc, skill) => {
8428
8712
  acc[skill.name] = skill.definition;
@@ -8430,9 +8714,9 @@ function loadProjectSkillsAsCommands() {
8430
8714
  }, {});
8431
8715
  }
8432
8716
  // src/features/claude-code-agent-loader/loader.ts
8433
- import { existsSync as existsSync21, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
8717
+ import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync14 } from "fs";
8434
8718
  import { homedir as homedir11 } from "os";
8435
- import { join as join26, basename as basename2 } from "path";
8719
+ import { join as join28, basename as basename2 } from "path";
8436
8720
  function parseToolsConfig(toolsStr) {
8437
8721
  if (!toolsStr)
8438
8722
  return;
@@ -8446,7 +8730,7 @@ function parseToolsConfig(toolsStr) {
8446
8730
  return result;
8447
8731
  }
8448
8732
  function loadAgentsFromDir(agentsDir, scope) {
8449
- if (!existsSync21(agentsDir)) {
8733
+ if (!existsSync22(agentsDir)) {
8450
8734
  return [];
8451
8735
  }
8452
8736
  const entries = readdirSync6(agentsDir, { withFileTypes: true });
@@ -8454,10 +8738,10 @@ function loadAgentsFromDir(agentsDir, scope) {
8454
8738
  for (const entry of entries) {
8455
8739
  if (!isMarkdownFile(entry))
8456
8740
  continue;
8457
- const agentPath = join26(agentsDir, entry.name);
8741
+ const agentPath = join28(agentsDir, entry.name);
8458
8742
  const agentName = basename2(entry.name, ".md");
8459
8743
  try {
8460
- const content = readFileSync13(agentPath, "utf-8");
8744
+ const content = readFileSync14(agentPath, "utf-8");
8461
8745
  const { data, body } = parseFrontmatter(content);
8462
8746
  const name = data.name || agentName;
8463
8747
  const originalDescription = data.description || "";
@@ -8484,7 +8768,7 @@ function loadAgentsFromDir(agentsDir, scope) {
8484
8768
  return agents;
8485
8769
  }
8486
8770
  function loadUserAgents() {
8487
- const userAgentsDir = join26(homedir11(), ".claude", "agents");
8771
+ const userAgentsDir = join28(homedir11(), ".claude", "agents");
8488
8772
  const agents = loadAgentsFromDir(userAgentsDir, "user");
8489
8773
  const result = {};
8490
8774
  for (const agent of agents) {
@@ -8493,7 +8777,7 @@ function loadUserAgents() {
8493
8777
  return result;
8494
8778
  }
8495
8779
  function loadProjectAgents() {
8496
- const projectAgentsDir = join26(process.cwd(), ".claude", "agents");
8780
+ const projectAgentsDir = join28(process.cwd(), ".claude", "agents");
8497
8781
  const agents = loadAgentsFromDir(projectAgentsDir, "project");
8498
8782
  const result = {};
8499
8783
  for (const agent of agents) {
@@ -8502,9 +8786,9 @@ function loadProjectAgents() {
8502
8786
  return result;
8503
8787
  }
8504
8788
  // src/features/claude-code-mcp-loader/loader.ts
8505
- import { existsSync as existsSync22 } from "fs";
8789
+ import { existsSync as existsSync23 } from "fs";
8506
8790
  import { homedir as homedir12 } from "os";
8507
- import { join as join27 } from "path";
8791
+ import { join as join29 } from "path";
8508
8792
 
8509
8793
  // src/features/claude-code-mcp-loader/env-expander.ts
8510
8794
  function expandEnvVars(value) {
@@ -8573,13 +8857,13 @@ function getMcpConfigPaths() {
8573
8857
  const home = homedir12();
8574
8858
  const cwd = process.cwd();
8575
8859
  return [
8576
- { path: join27(home, ".claude", ".mcp.json"), scope: "user" },
8577
- { path: join27(cwd, ".mcp.json"), scope: "project" },
8578
- { path: join27(cwd, ".claude", ".mcp.json"), scope: "local" }
8860
+ { path: join29(home, ".claude", ".mcp.json"), scope: "user" },
8861
+ { path: join29(cwd, ".mcp.json"), scope: "project" },
8862
+ { path: join29(cwd, ".claude", ".mcp.json"), scope: "local" }
8579
8863
  ];
8580
8864
  }
8581
8865
  async function loadMcpConfigFile(filePath) {
8582
- if (!existsSync22(filePath)) {
8866
+ if (!existsSync23(filePath)) {
8583
8867
  return null;
8584
8868
  }
8585
8869
  try {
@@ -8865,14 +9149,14 @@ var EXT_TO_LANG = {
8865
9149
  ".tfvars": "terraform"
8866
9150
  };
8867
9151
  // src/tools/lsp/config.ts
8868
- import { existsSync as existsSync23, readFileSync as readFileSync14 } from "fs";
8869
- import { join as join28 } from "path";
9152
+ import { existsSync as existsSync24, readFileSync as readFileSync15 } from "fs";
9153
+ import { join as join30 } from "path";
8870
9154
  import { homedir as homedir13 } from "os";
8871
9155
  function loadJsonFile(path5) {
8872
- if (!existsSync23(path5))
9156
+ if (!existsSync24(path5))
8873
9157
  return null;
8874
9158
  try {
8875
- return JSON.parse(readFileSync14(path5, "utf-8"));
9159
+ return JSON.parse(readFileSync15(path5, "utf-8"));
8876
9160
  } catch {
8877
9161
  return null;
8878
9162
  }
@@ -8880,9 +9164,9 @@ function loadJsonFile(path5) {
8880
9164
  function getConfigPaths() {
8881
9165
  const cwd = process.cwd();
8882
9166
  return {
8883
- project: join28(cwd, ".opencode", "oh-my-opencode.json"),
8884
- user: join28(homedir13(), ".config", "opencode", "oh-my-opencode.json"),
8885
- opencode: join28(homedir13(), ".config", "opencode", "opencode.json")
9167
+ project: join30(cwd, ".opencode", "oh-my-opencode.json"),
9168
+ user: join30(homedir13(), ".config", "opencode", "oh-my-opencode.json"),
9169
+ opencode: join30(homedir13(), ".config", "opencode", "opencode.json")
8886
9170
  };
8887
9171
  }
8888
9172
  function loadAllConfigs() {
@@ -8975,7 +9259,7 @@ function isServerInstalled(command) {
8975
9259
  const pathEnv = process.env.PATH || "";
8976
9260
  const paths = pathEnv.split(":");
8977
9261
  for (const p of paths) {
8978
- if (existsSync23(join28(p, cmd))) {
9262
+ if (existsSync24(join30(p, cmd))) {
8979
9263
  return true;
8980
9264
  }
8981
9265
  }
@@ -9025,7 +9309,7 @@ function getAllServers() {
9025
9309
  }
9026
9310
  // src/tools/lsp/client.ts
9027
9311
  var {spawn: spawn4 } = globalThis.Bun;
9028
- import { readFileSync as readFileSync15 } from "fs";
9312
+ import { readFileSync as readFileSync16 } from "fs";
9029
9313
  import { extname, resolve as resolve5 } from "path";
9030
9314
  class LSPServerManager {
9031
9315
  static instance;
@@ -9425,7 +9709,7 @@ ${msg}`);
9425
9709
  const absPath = resolve5(filePath);
9426
9710
  if (this.openedFiles.has(absPath))
9427
9711
  return;
9428
- const text = readFileSync15(absPath, "utf-8");
9712
+ const text = readFileSync16(absPath, "utf-8");
9429
9713
  const ext = extname(absPath);
9430
9714
  const languageId = getLanguageId(ext);
9431
9715
  this.notify("textDocument/didOpen", {
@@ -9540,16 +9824,16 @@ ${msg}`);
9540
9824
  }
9541
9825
  // src/tools/lsp/utils.ts
9542
9826
  import { extname as extname2, resolve as resolve6 } from "path";
9543
- import { existsSync as existsSync24, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "fs";
9827
+ import { existsSync as existsSync25, readFileSync as readFileSync17, writeFileSync as writeFileSync8 } from "fs";
9544
9828
  function findWorkspaceRoot(filePath) {
9545
9829
  let dir = resolve6(filePath);
9546
- if (!existsSync24(dir) || !__require("fs").statSync(dir).isDirectory()) {
9830
+ if (!existsSync25(dir) || !__require("fs").statSync(dir).isDirectory()) {
9547
9831
  dir = __require("path").dirname(dir);
9548
9832
  }
9549
9833
  const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
9550
9834
  while (dir !== "/") {
9551
9835
  for (const marker of markers) {
9552
- if (existsSync24(__require("path").join(dir, marker))) {
9836
+ if (existsSync25(__require("path").join(dir, marker))) {
9553
9837
  return dir;
9554
9838
  }
9555
9839
  }
@@ -9707,7 +9991,7 @@ function formatCodeActions(actions) {
9707
9991
  }
9708
9992
  function applyTextEditsToFile(filePath, edits) {
9709
9993
  try {
9710
- let content = readFileSync16(filePath, "utf-8");
9994
+ let content = readFileSync17(filePath, "utf-8");
9711
9995
  const lines = content.split(`
9712
9996
  `);
9713
9997
  const sortedEdits = [...edits].sort((a, b) => {
@@ -9732,7 +10016,7 @@ function applyTextEditsToFile(filePath, edits) {
9732
10016
  `));
9733
10017
  }
9734
10018
  }
9735
- writeFileSync7(filePath, lines.join(`
10019
+ writeFileSync8(filePath, lines.join(`
9736
10020
  `), "utf-8");
9737
10021
  return { success: true, editCount: edits.length };
9738
10022
  } catch (err) {
@@ -9763,7 +10047,7 @@ function applyWorkspaceEdit(edit) {
9763
10047
  if (change.kind === "create") {
9764
10048
  try {
9765
10049
  const filePath = change.uri.replace("file://", "");
9766
- writeFileSync7(filePath, "", "utf-8");
10050
+ writeFileSync8(filePath, "", "utf-8");
9767
10051
  result.filesModified.push(filePath);
9768
10052
  } catch (err) {
9769
10053
  result.success = false;
@@ -9773,8 +10057,8 @@ function applyWorkspaceEdit(edit) {
9773
10057
  try {
9774
10058
  const oldPath = change.oldUri.replace("file://", "");
9775
10059
  const newPath = change.newUri.replace("file://", "");
9776
- const content = readFileSync16(oldPath, "utf-8");
9777
- writeFileSync7(newPath, content, "utf-8");
10060
+ const content = readFileSync17(oldPath, "utf-8");
10061
+ writeFileSync8(newPath, content, "utf-8");
9778
10062
  __require("fs").unlinkSync(oldPath);
9779
10063
  result.filesModified.push(newPath);
9780
10064
  } catch (err) {
@@ -22474,13 +22758,13 @@ var lsp_code_action_resolve = tool({
22474
22758
  });
22475
22759
  // src/tools/ast-grep/constants.ts
22476
22760
  import { createRequire as createRequire4 } from "module";
22477
- import { dirname as dirname5, join as join30 } from "path";
22478
- import { existsSync as existsSync26, statSync as statSync3 } from "fs";
22761
+ import { dirname as dirname5, join as join32 } from "path";
22762
+ import { existsSync as existsSync27, statSync as statSync3 } from "fs";
22479
22763
 
22480
22764
  // src/tools/ast-grep/downloader.ts
22481
22765
  var {spawn: spawn5 } = globalThis.Bun;
22482
- import { existsSync as existsSync25, mkdirSync as mkdirSync8, chmodSync as chmodSync2, unlinkSync as unlinkSync8 } from "fs";
22483
- import { join as join29 } from "path";
22766
+ import { existsSync as existsSync26, mkdirSync as mkdirSync9, chmodSync as chmodSync2, unlinkSync as unlinkSync9 } from "fs";
22767
+ import { join as join31 } from "path";
22484
22768
  import { homedir as homedir14 } from "os";
22485
22769
  import { createRequire as createRequire3 } from "module";
22486
22770
  var REPO2 = "ast-grep/ast-grep";
@@ -22506,19 +22790,19 @@ var PLATFORM_MAP2 = {
22506
22790
  function getCacheDir3() {
22507
22791
  if (process.platform === "win32") {
22508
22792
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
22509
- const base2 = localAppData || join29(homedir14(), "AppData", "Local");
22510
- return join29(base2, "oh-my-opencode", "bin");
22793
+ const base2 = localAppData || join31(homedir14(), "AppData", "Local");
22794
+ return join31(base2, "oh-my-opencode", "bin");
22511
22795
  }
22512
22796
  const xdgCache2 = process.env.XDG_CACHE_HOME;
22513
- const base = xdgCache2 || join29(homedir14(), ".cache");
22514
- return join29(base, "oh-my-opencode", "bin");
22797
+ const base = xdgCache2 || join31(homedir14(), ".cache");
22798
+ return join31(base, "oh-my-opencode", "bin");
22515
22799
  }
22516
22800
  function getBinaryName3() {
22517
22801
  return process.platform === "win32" ? "sg.exe" : "sg";
22518
22802
  }
22519
22803
  function getCachedBinaryPath2() {
22520
- const binaryPath = join29(getCacheDir3(), getBinaryName3());
22521
- return existsSync25(binaryPath) ? binaryPath : null;
22804
+ const binaryPath = join31(getCacheDir3(), getBinaryName3());
22805
+ return existsSync26(binaryPath) ? binaryPath : null;
22522
22806
  }
22523
22807
  async function extractZip2(archivePath, destDir) {
22524
22808
  const proc = process.platform === "win32" ? spawn5([
@@ -22544,8 +22828,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
22544
22828
  }
22545
22829
  const cacheDir = getCacheDir3();
22546
22830
  const binaryName = getBinaryName3();
22547
- const binaryPath = join29(cacheDir, binaryName);
22548
- if (existsSync25(binaryPath)) {
22831
+ const binaryPath = join31(cacheDir, binaryName);
22832
+ if (existsSync26(binaryPath)) {
22549
22833
  return binaryPath;
22550
22834
  }
22551
22835
  const { arch, os: os4 } = platformInfo;
@@ -22553,21 +22837,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
22553
22837
  const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
22554
22838
  console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
22555
22839
  try {
22556
- if (!existsSync25(cacheDir)) {
22557
- mkdirSync8(cacheDir, { recursive: true });
22840
+ if (!existsSync26(cacheDir)) {
22841
+ mkdirSync9(cacheDir, { recursive: true });
22558
22842
  }
22559
22843
  const response2 = await fetch(downloadUrl, { redirect: "follow" });
22560
22844
  if (!response2.ok) {
22561
22845
  throw new Error(`HTTP ${response2.status}: ${response2.statusText}`);
22562
22846
  }
22563
- const archivePath = join29(cacheDir, assetName);
22847
+ const archivePath = join31(cacheDir, assetName);
22564
22848
  const arrayBuffer = await response2.arrayBuffer();
22565
22849
  await Bun.write(archivePath, arrayBuffer);
22566
22850
  await extractZip2(archivePath, cacheDir);
22567
- if (existsSync25(archivePath)) {
22568
- unlinkSync8(archivePath);
22851
+ if (existsSync26(archivePath)) {
22852
+ unlinkSync9(archivePath);
22569
22853
  }
22570
- if (process.platform !== "win32" && existsSync25(binaryPath)) {
22854
+ if (process.platform !== "win32" && existsSync26(binaryPath)) {
22571
22855
  chmodSync2(binaryPath, 493);
22572
22856
  }
22573
22857
  console.log(`[oh-my-opencode] ast-grep binary ready.`);
@@ -22618,8 +22902,8 @@ function findSgCliPathSync() {
22618
22902
  const require2 = createRequire4(import.meta.url);
22619
22903
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
22620
22904
  const cliDir = dirname5(cliPkgPath);
22621
- const sgPath = join30(cliDir, binaryName);
22622
- if (existsSync26(sgPath) && isValidBinary(sgPath)) {
22905
+ const sgPath = join32(cliDir, binaryName);
22906
+ if (existsSync27(sgPath) && isValidBinary(sgPath)) {
22623
22907
  return sgPath;
22624
22908
  }
22625
22909
  } catch {}
@@ -22630,8 +22914,8 @@ function findSgCliPathSync() {
22630
22914
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
22631
22915
  const pkgDir = dirname5(pkgPath);
22632
22916
  const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
22633
- const binaryPath = join30(pkgDir, astGrepName);
22634
- if (existsSync26(binaryPath) && isValidBinary(binaryPath)) {
22917
+ const binaryPath = join32(pkgDir, astGrepName);
22918
+ if (existsSync27(binaryPath) && isValidBinary(binaryPath)) {
22635
22919
  return binaryPath;
22636
22920
  }
22637
22921
  } catch {}
@@ -22639,7 +22923,7 @@ function findSgCliPathSync() {
22639
22923
  if (process.platform === "darwin") {
22640
22924
  const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
22641
22925
  for (const path5 of homebrewPaths) {
22642
- if (existsSync26(path5) && isValidBinary(path5)) {
22926
+ if (existsSync27(path5) && isValidBinary(path5)) {
22643
22927
  return path5;
22644
22928
  }
22645
22929
  }
@@ -22695,11 +22979,11 @@ var DEFAULT_MAX_MATCHES = 500;
22695
22979
 
22696
22980
  // src/tools/ast-grep/cli.ts
22697
22981
  var {spawn: spawn6 } = globalThis.Bun;
22698
- import { existsSync as existsSync27 } from "fs";
22982
+ import { existsSync as existsSync28 } from "fs";
22699
22983
  var resolvedCliPath3 = null;
22700
22984
  var initPromise2 = null;
22701
22985
  async function getAstGrepPath() {
22702
- if (resolvedCliPath3 !== null && existsSync27(resolvedCliPath3)) {
22986
+ if (resolvedCliPath3 !== null && existsSync28(resolvedCliPath3)) {
22703
22987
  return resolvedCliPath3;
22704
22988
  }
22705
22989
  if (initPromise2) {
@@ -22707,7 +22991,7 @@ async function getAstGrepPath() {
22707
22991
  }
22708
22992
  initPromise2 = (async () => {
22709
22993
  const syncPath = findSgCliPathSync();
22710
- if (syncPath && existsSync27(syncPath)) {
22994
+ if (syncPath && existsSync28(syncPath)) {
22711
22995
  resolvedCliPath3 = syncPath;
22712
22996
  setSgCliPath(syncPath);
22713
22997
  return syncPath;
@@ -22741,7 +23025,7 @@ async function runSg(options) {
22741
23025
  const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
22742
23026
  args.push(...paths);
22743
23027
  let cliPath = getSgCliPath();
22744
- if (!existsSync27(cliPath) && cliPath !== "sg") {
23028
+ if (!existsSync28(cliPath) && cliPath !== "sg") {
22745
23029
  const downloadedPath = await getAstGrepPath();
22746
23030
  if (downloadedPath) {
22747
23031
  cliPath = downloadedPath;
@@ -23005,8 +23289,8 @@ var ast_grep_replace = tool({
23005
23289
  var {spawn: spawn7 } = globalThis.Bun;
23006
23290
 
23007
23291
  // src/tools/grep/constants.ts
23008
- import { existsSync as existsSync28 } from "fs";
23009
- import { join as join31, dirname as dirname6 } from "path";
23292
+ import { existsSync as existsSync29 } from "fs";
23293
+ import { join as join33, dirname as dirname6 } from "path";
23010
23294
  import { spawnSync } from "child_process";
23011
23295
  var cachedCli = null;
23012
23296
  function findExecutable(name) {
@@ -23027,13 +23311,13 @@ function getOpenCodeBundledRg() {
23027
23311
  const isWindows = process.platform === "win32";
23028
23312
  const rgName = isWindows ? "rg.exe" : "rg";
23029
23313
  const candidates = [
23030
- join31(execDir, rgName),
23031
- join31(execDir, "bin", rgName),
23032
- join31(execDir, "..", "bin", rgName),
23033
- join31(execDir, "..", "libexec", rgName)
23314
+ join33(execDir, rgName),
23315
+ join33(execDir, "bin", rgName),
23316
+ join33(execDir, "..", "bin", rgName),
23317
+ join33(execDir, "..", "libexec", rgName)
23034
23318
  ];
23035
23319
  for (const candidate of candidates) {
23036
- if (existsSync28(candidate)) {
23320
+ if (existsSync29(candidate)) {
23037
23321
  return candidate;
23038
23322
  }
23039
23323
  }
@@ -23431,11 +23715,11 @@ var glob = tool({
23431
23715
  }
23432
23716
  });
23433
23717
  // src/tools/slashcommand/tools.ts
23434
- import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as readFileSync17 } from "fs";
23718
+ import { existsSync as existsSync30, readdirSync as readdirSync7, readFileSync as readFileSync18 } from "fs";
23435
23719
  import { homedir as homedir15 } from "os";
23436
- import { join as join32, basename as basename3, dirname as dirname7 } from "path";
23720
+ import { join as join34, basename as basename3, dirname as dirname7 } from "path";
23437
23721
  function discoverCommandsFromDir(commandsDir, scope) {
23438
- if (!existsSync29(commandsDir)) {
23722
+ if (!existsSync30(commandsDir)) {
23439
23723
  return [];
23440
23724
  }
23441
23725
  const entries = readdirSync7(commandsDir, { withFileTypes: true });
@@ -23443,10 +23727,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
23443
23727
  for (const entry of entries) {
23444
23728
  if (!isMarkdownFile(entry))
23445
23729
  continue;
23446
- const commandPath = join32(commandsDir, entry.name);
23730
+ const commandPath = join34(commandsDir, entry.name);
23447
23731
  const commandName = basename3(entry.name, ".md");
23448
23732
  try {
23449
- const content = readFileSync17(commandPath, "utf-8");
23733
+ const content = readFileSync18(commandPath, "utf-8");
23450
23734
  const { data, body } = parseFrontmatter(content);
23451
23735
  const metadata = {
23452
23736
  name: commandName,
@@ -23470,10 +23754,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
23470
23754
  return commands;
23471
23755
  }
23472
23756
  function discoverCommandsSync() {
23473
- const userCommandsDir = join32(homedir15(), ".claude", "commands");
23474
- const projectCommandsDir = join32(process.cwd(), ".claude", "commands");
23475
- const opencodeGlobalDir = join32(homedir15(), ".config", "opencode", "command");
23476
- const opencodeProjectDir = join32(process.cwd(), ".opencode", "command");
23757
+ const userCommandsDir = join34(homedir15(), ".claude", "commands");
23758
+ const projectCommandsDir = join34(process.cwd(), ".claude", "commands");
23759
+ const opencodeGlobalDir = join34(homedir15(), ".config", "opencode", "command");
23760
+ const opencodeProjectDir = join34(process.cwd(), ".opencode", "command");
23477
23761
  const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
23478
23762
  const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
23479
23763
  const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
@@ -23605,9 +23889,9 @@ var SkillFrontmatterSchema = exports_external.object({
23605
23889
  metadata: exports_external.record(exports_external.string(), exports_external.string()).optional()
23606
23890
  });
23607
23891
  // src/tools/skill/tools.ts
23608
- import { existsSync as existsSync30, readdirSync as readdirSync8, readFileSync as readFileSync18 } from "fs";
23892
+ import { existsSync as existsSync31, readdirSync as readdirSync8, readFileSync as readFileSync19 } from "fs";
23609
23893
  import { homedir as homedir16 } from "os";
23610
- import { join as join33, basename as basename4 } from "path";
23894
+ import { join as join35, basename as basename4 } from "path";
23611
23895
  function parseSkillFrontmatter(data) {
23612
23896
  return {
23613
23897
  name: typeof data.name === "string" ? data.name : "",
@@ -23618,7 +23902,7 @@ function parseSkillFrontmatter(data) {
23618
23902
  };
23619
23903
  }
23620
23904
  function discoverSkillsFromDir(skillsDir, scope) {
23621
- if (!existsSync30(skillsDir)) {
23905
+ if (!existsSync31(skillsDir)) {
23622
23906
  return [];
23623
23907
  }
23624
23908
  const entries = readdirSync8(skillsDir, { withFileTypes: true });
@@ -23626,14 +23910,14 @@ function discoverSkillsFromDir(skillsDir, scope) {
23626
23910
  for (const entry of entries) {
23627
23911
  if (entry.name.startsWith("."))
23628
23912
  continue;
23629
- const skillPath = join33(skillsDir, entry.name);
23913
+ const skillPath = join35(skillsDir, entry.name);
23630
23914
  if (entry.isDirectory() || entry.isSymbolicLink()) {
23631
23915
  const resolvedPath = resolveSymlink(skillPath);
23632
- const skillMdPath = join33(resolvedPath, "SKILL.md");
23633
- if (!existsSync30(skillMdPath))
23916
+ const skillMdPath = join35(resolvedPath, "SKILL.md");
23917
+ if (!existsSync31(skillMdPath))
23634
23918
  continue;
23635
23919
  try {
23636
- const content = readFileSync18(skillMdPath, "utf-8");
23920
+ const content = readFileSync19(skillMdPath, "utf-8");
23637
23921
  const { data } = parseFrontmatter(content);
23638
23922
  skills.push({
23639
23923
  name: data.name || entry.name,
@@ -23648,8 +23932,8 @@ function discoverSkillsFromDir(skillsDir, scope) {
23648
23932
  return skills;
23649
23933
  }
23650
23934
  function discoverSkillsSync() {
23651
- const userSkillsDir = join33(homedir16(), ".claude", "skills");
23652
- const projectSkillsDir = join33(process.cwd(), ".claude", "skills");
23935
+ const userSkillsDir = join35(homedir16(), ".claude", "skills");
23936
+ const projectSkillsDir = join35(process.cwd(), ".claude", "skills");
23653
23937
  const userSkills = discoverSkillsFromDir(userSkillsDir, "user");
23654
23938
  const projectSkills = discoverSkillsFromDir(projectSkillsDir, "project");
23655
23939
  return [...projectSkills, ...userSkills];
@@ -23659,12 +23943,12 @@ var skillListForDescription = availableSkills.map((s) => `- ${s.name}: ${s.descr
23659
23943
  `);
23660
23944
  async function parseSkillMd(skillPath) {
23661
23945
  const resolvedPath = resolveSymlink(skillPath);
23662
- const skillMdPath = join33(resolvedPath, "SKILL.md");
23663
- if (!existsSync30(skillMdPath)) {
23946
+ const skillMdPath = join35(resolvedPath, "SKILL.md");
23947
+ if (!existsSync31(skillMdPath)) {
23664
23948
  return null;
23665
23949
  }
23666
23950
  try {
23667
- let content = readFileSync18(skillMdPath, "utf-8");
23951
+ let content = readFileSync19(skillMdPath, "utf-8");
23668
23952
  content = await resolveCommandsInText(content);
23669
23953
  const { data, body } = parseFrontmatter(content);
23670
23954
  const frontmatter2 = parseSkillFrontmatter(data);
@@ -23675,12 +23959,12 @@ async function parseSkillMd(skillPath) {
23675
23959
  allowedTools: frontmatter2["allowed-tools"],
23676
23960
  metadata: frontmatter2.metadata
23677
23961
  };
23678
- const referencesDir = join33(resolvedPath, "references");
23679
- const scriptsDir = join33(resolvedPath, "scripts");
23680
- const assetsDir = join33(resolvedPath, "assets");
23681
- const references = existsSync30(referencesDir) ? readdirSync8(referencesDir).filter((f) => !f.startsWith(".")) : [];
23682
- const scripts = existsSync30(scriptsDir) ? readdirSync8(scriptsDir).filter((f) => !f.startsWith(".") && !f.startsWith("__")) : [];
23683
- const assets = existsSync30(assetsDir) ? readdirSync8(assetsDir).filter((f) => !f.startsWith(".")) : [];
23962
+ const referencesDir = join35(resolvedPath, "references");
23963
+ const scriptsDir = join35(resolvedPath, "scripts");
23964
+ const assetsDir = join35(resolvedPath, "assets");
23965
+ const references = existsSync31(referencesDir) ? readdirSync8(referencesDir).filter((f) => !f.startsWith(".")) : [];
23966
+ const scripts = existsSync31(scriptsDir) ? readdirSync8(scriptsDir).filter((f) => !f.startsWith(".") && !f.startsWith("__")) : [];
23967
+ const assets = existsSync31(assetsDir) ? readdirSync8(assetsDir).filter((f) => !f.startsWith(".")) : [];
23684
23968
  return {
23685
23969
  name: metadata.name,
23686
23970
  path: resolvedPath,
@@ -23696,7 +23980,7 @@ async function parseSkillMd(skillPath) {
23696
23980
  }
23697
23981
  }
23698
23982
  async function discoverSkillsFromDirAsync(skillsDir) {
23699
- if (!existsSync30(skillsDir)) {
23983
+ if (!existsSync31(skillsDir)) {
23700
23984
  return [];
23701
23985
  }
23702
23986
  const entries = readdirSync8(skillsDir, { withFileTypes: true });
@@ -23704,7 +23988,7 @@ async function discoverSkillsFromDirAsync(skillsDir) {
23704
23988
  for (const entry of entries) {
23705
23989
  if (entry.name.startsWith("."))
23706
23990
  continue;
23707
- const skillPath = join33(skillsDir, entry.name);
23991
+ const skillPath = join35(skillsDir, entry.name);
23708
23992
  if (entry.isDirectory() || entry.isSymbolicLink()) {
23709
23993
  const skillInfo = await parseSkillMd(skillPath);
23710
23994
  if (skillInfo) {
@@ -23715,8 +23999,8 @@ async function discoverSkillsFromDirAsync(skillsDir) {
23715
23999
  return skills;
23716
24000
  }
23717
24001
  async function discoverSkills() {
23718
- const userSkillsDir = join33(homedir16(), ".claude", "skills");
23719
- const projectSkillsDir = join33(process.cwd(), ".claude", "skills");
24002
+ const userSkillsDir = join35(homedir16(), ".claude", "skills");
24003
+ const projectSkillsDir = join35(process.cwd(), ".claude", "skills");
23720
24004
  const userSkills = await discoverSkillsFromDirAsync(userSkillsDir);
23721
24005
  const projectSkills = await discoverSkillsFromDirAsync(projectSkillsDir);
23722
24006
  return [...projectSkills, ...userSkills];
@@ -23745,9 +24029,9 @@ async function loadSkillWithReferences(skill, includeRefs) {
23745
24029
  const referencesLoaded = [];
23746
24030
  if (includeRefs && skill.references.length > 0) {
23747
24031
  for (const ref of skill.references) {
23748
- const refPath = join33(skill.path, "references", ref);
24032
+ const refPath = join35(skill.path, "references", ref);
23749
24033
  try {
23750
- let content = readFileSync18(refPath, "utf-8");
24034
+ let content = readFileSync19(refPath, "utf-8");
23751
24035
  content = await resolveCommandsInText(content);
23752
24036
  referencesLoaded.push({ path: ref, content });
23753
24037
  } catch {}
@@ -23939,10 +24223,9 @@ function formatTaskStatus(task) {
23939
24223
  const duration3 = formatDuration(task.startedAt, task.completedAt);
23940
24224
  const promptPreview = truncateText(task.prompt, 500);
23941
24225
  let progressSection = "";
23942
- if (task.progress) {
24226
+ if (task.progress?.lastTool) {
23943
24227
  progressSection = `
23944
- Tool calls: ${task.progress.toolCalls}
23945
- Last tool: ${task.progress.lastTool ?? "N/A"}`;
24228
+ | Last tool | ${task.progress.lastTool} |`;
23946
24229
  }
23947
24230
  let lastMessageSection = "";
23948
24231
  if (task.progress?.lastMessage) {
@@ -23955,6 +24238,16 @@ Last tool: ${task.progress.lastTool ?? "N/A"}`;
23955
24238
  \`\`\`
23956
24239
  ${truncated}
23957
24240
  \`\`\``;
24241
+ }
24242
+ let statusNote = "";
24243
+ if (task.status === "running") {
24244
+ statusNote = `
24245
+
24246
+ > **Note**: No need to wait explicitly - the system will notify you when this task completes.`;
24247
+ } else if (task.status === "error") {
24248
+ statusNote = `
24249
+
24250
+ > **Failed**: The task encountered an error. Check the last message for details.`;
23958
24251
  }
23959
24252
  return `# Task Status
23960
24253
 
@@ -23966,7 +24259,7 @@ ${truncated}
23966
24259
  | Status | **${task.status}** |
23967
24260
  | Duration | ${duration3} |
23968
24261
  | Session ID | \`${task.sessionID}\` |${progressSection}
23969
-
24262
+ ${statusNote}
23970
24263
  ## Original Prompt
23971
24264
 
23972
24265
  \`\`\`
@@ -24712,7 +25005,16 @@ var AgentPermissionSchema = exports_external.object({
24712
25005
  doom_loop: PermissionValue.optional(),
24713
25006
  external_directory: PermissionValue.optional()
24714
25007
  });
24715
- var AgentNameSchema = exports_external.enum([
25008
+ var BuiltinAgentNameSchema = exports_external.enum([
25009
+ "oracle",
25010
+ "librarian",
25011
+ "explore",
25012
+ "frontend-ui-ux-engineer",
25013
+ "document-writer",
25014
+ "multimodal-looker"
25015
+ ]);
25016
+ var OverridableAgentNameSchema = exports_external.enum([
25017
+ "build",
24716
25018
  "oracle",
24717
25019
  "librarian",
24718
25020
  "explore",
@@ -24735,7 +25037,8 @@ var HookNameSchema = exports_external.enum([
24735
25037
  "rules-injector",
24736
25038
  "background-notification",
24737
25039
  "auto-update-checker",
24738
- "ultrawork-mode"
25040
+ "ultrawork-mode",
25041
+ "agent-usage-reminder"
24739
25042
  ]);
24740
25043
  var AgentOverrideConfigSchema = exports_external.object({
24741
25044
  model: exports_external.string().optional(),
@@ -24750,6 +25053,7 @@ var AgentOverrideConfigSchema = exports_external.object({
24750
25053
  permission: AgentPermissionSchema.optional()
24751
25054
  });
24752
25055
  var AgentOverridesSchema = exports_external.object({
25056
+ build: AgentOverrideConfigSchema.optional(),
24753
25057
  oracle: AgentOverrideConfigSchema.optional(),
24754
25058
  librarian: AgentOverrideConfigSchema.optional(),
24755
25059
  explore: AgentOverrideConfigSchema.optional(),
@@ -24767,7 +25071,7 @@ var ClaudeCodeConfigSchema = exports_external.object({
24767
25071
  var OhMyOpenCodeConfigSchema = exports_external.object({
24768
25072
  $schema: exports_external.string().optional(),
24769
25073
  disabled_mcps: exports_external.array(McpNameSchema).optional(),
24770
- disabled_agents: exports_external.array(AgentNameSchema).optional(),
25074
+ disabled_agents: exports_external.array(BuiltinAgentNameSchema).optional(),
24771
25075
  disabled_hooks: exports_external.array(HookNameSchema).optional(),
24772
25076
  agents: AgentOverridesSchema.optional(),
24773
25077
  claude_code: ClaudeCodeConfigSchema.optional(),
@@ -24869,6 +25173,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
24869
25173
  const rulesInjector = isHookEnabled("rules-injector") ? createRulesInjectorHook(ctx) : null;
24870
25174
  const autoUpdateChecker = isHookEnabled("auto-update-checker") ? createAutoUpdateCheckerHook(ctx) : null;
24871
25175
  const ultraworkMode = isHookEnabled("ultrawork-mode") ? createUltraworkModeHook() : null;
25176
+ const agentUsageReminder = isHookEnabled("agent-usage-reminder") ? createAgentUsageReminderHook(ctx) : null;
24872
25177
  updateTerminalTitle({ sessionId: "main" });
24873
25178
  const backgroundManager = new BackgroundManager(ctx);
24874
25179
  const backgroundNotificationHook = isHookEnabled("background-notification") ? createBackgroundNotificationHook(backgroundManager) : null;
@@ -24898,6 +25203,16 @@ var OhMyOpenCodePlugin = async (ctx) => {
24898
25203
  ...projectAgents,
24899
25204
  ...config3.agent
24900
25205
  };
25206
+ for (const [agentName, agentConfig] of Object.entries(config3.agent ?? {})) {
25207
+ if (agentConfig && agentConfig.mode !== "subagent") {
25208
+ const existingPrompt = agentConfig.prompt || "";
25209
+ const userOverride = pluginConfig.agents?.[agentName]?.prompt || "";
25210
+ config3.agent[agentName] = {
25211
+ ...agentConfig,
25212
+ prompt: existingPrompt + BUILD_AGENT_PROMPT_EXTENSION + userOverride
25213
+ };
25214
+ }
25215
+ }
24901
25216
  config3.tools = {
24902
25217
  ...config3.tools
24903
25218
  };
@@ -24957,6 +25272,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
24957
25272
  await thinkMode?.event(input);
24958
25273
  await anthropicAutoCompact?.event(input);
24959
25274
  await ultraworkMode?.event(input);
25275
+ await agentUsageReminder?.event(input);
24960
25276
  const { event } = input;
24961
25277
  const props = event.properties;
24962
25278
  if (event.type === "session.created") {
@@ -25057,6 +25373,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
25057
25373
  await directoryReadmeInjector?.["tool.execute.after"](input, output);
25058
25374
  await rulesInjector?.["tool.execute.after"](input, output);
25059
25375
  await emptyTaskResponseDetector?.["tool.execute.after"](input, output);
25376
+ await agentUsageReminder?.["tool.execute.after"](input, output);
25060
25377
  if (input.sessionID === getMainSessionID()) {
25061
25378
  updateTerminalTitle({
25062
25379
  sessionId: input.sessionID,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",